mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Merge #7115
7115: Migrate HasSource::source to return Option r=matklad a=nick96 I've made a start on fixing #6913 based on the provided work plan, migrating `HasSource::source` to return an `Option`. The simple cases are migrated but there are a few that I'm unsure exactly how they should be handled: - Logging the processing of functions in `AnalysisStatsCmd::run`: In verbose mode it includes the path to the module containing the function and the syntax range. I've handled this with an if-let but would it be better to blow up here with `expect`? I'm not 100% on the code paths but if we're processing a function definition then the source should exist. I've handled `source()` in all code paths as `None` being a valid return value but are there some cases where we should just blow up? Also, all I've done is bubble up the returned `None`s, there may be some places where we can recover and still provide something. Co-authored-by: Nick Spain <nicholas.spain@stileeducation.com> Co-authored-by: Nick Spain <nicholas.spain96@gmail.com>
This commit is contained in:
commit
520b8a5a4d
20 changed files with 237 additions and 223 deletions
|
@ -196,7 +196,7 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::Variant) -> Optio
|
||||||
let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?);
|
let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?);
|
||||||
|
|
||||||
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
|
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
|
||||||
let pat: ast::Pat = match var.source(db).value.kind() {
|
let pat: ast::Pat = match var.source(db)?.value.kind() {
|
||||||
ast::StructKind::Tuple(field_list) => {
|
ast::StructKind::Tuple(field_list) => {
|
||||||
let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count());
|
let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count());
|
||||||
make::tuple_struct_pat(path, pats).into()
|
make::tuple_struct_pat(path, pats).into()
|
||||||
|
|
|
@ -97,7 +97,8 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) ->
|
||||||
let parent_name = parent.name(ctx.db());
|
let parent_name = parent.name(ctx.db());
|
||||||
let target_module = parent.module(ctx.db());
|
let target_module = parent.module(ctx.db());
|
||||||
|
|
||||||
let in_file_source = record_field_def.source(ctx.db());
|
#[allow(deprecated)]
|
||||||
|
let in_file_source = record_field_def.source(ctx.db())?;
|
||||||
let (offset, current_visibility, target) = match in_file_source.value {
|
let (offset, current_visibility, target) = match in_file_source.value {
|
||||||
hir::FieldSource::Named(it) => {
|
hir::FieldSource::Named(it) => {
|
||||||
let s = it.syntax();
|
let s = it.syntax();
|
||||||
|
@ -145,53 +146,53 @@ fn target_data_for_def(
|
||||||
fn offset_target_and_file_id<S, Ast>(
|
fn offset_target_and_file_id<S, Ast>(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
x: S,
|
x: S,
|
||||||
) -> (TextSize, Option<ast::Visibility>, TextRange, FileId)
|
) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId)>
|
||||||
where
|
where
|
||||||
S: HasSource<Ast = Ast>,
|
S: HasSource<Ast = Ast>,
|
||||||
Ast: AstNode + ast::VisibilityOwner,
|
Ast: AstNode + ast::VisibilityOwner,
|
||||||
{
|
{
|
||||||
let source = x.source(db);
|
let source = x.source(db)?;
|
||||||
let in_file_syntax = source.syntax();
|
let in_file_syntax = source.syntax();
|
||||||
let file_id = in_file_syntax.file_id;
|
let file_id = in_file_syntax.file_id;
|
||||||
let syntax = in_file_syntax.value;
|
let syntax = in_file_syntax.value;
|
||||||
let current_visibility = source.value.visibility();
|
let current_visibility = source.value.visibility();
|
||||||
(
|
Some((
|
||||||
vis_offset(syntax),
|
vis_offset(syntax),
|
||||||
current_visibility,
|
current_visibility,
|
||||||
syntax.text_range(),
|
syntax.text_range(),
|
||||||
file_id.original_file(db.upcast()),
|
file_id.original_file(db.upcast()),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
let target_name;
|
let target_name;
|
||||||
let (offset, current_visibility, target, target_file) = match def {
|
let (offset, current_visibility, target, target_file) = match def {
|
||||||
hir::ModuleDef::Function(f) => {
|
hir::ModuleDef::Function(f) => {
|
||||||
target_name = Some(f.name(db));
|
target_name = Some(f.name(db));
|
||||||
offset_target_and_file_id(db, f)
|
offset_target_and_file_id(db, f)?
|
||||||
}
|
}
|
||||||
hir::ModuleDef::Adt(adt) => {
|
hir::ModuleDef::Adt(adt) => {
|
||||||
target_name = Some(adt.name(db));
|
target_name = Some(adt.name(db));
|
||||||
match adt {
|
match adt {
|
||||||
hir::Adt::Struct(s) => offset_target_and_file_id(db, s),
|
hir::Adt::Struct(s) => offset_target_and_file_id(db, s)?,
|
||||||
hir::Adt::Union(u) => offset_target_and_file_id(db, u),
|
hir::Adt::Union(u) => offset_target_and_file_id(db, u)?,
|
||||||
hir::Adt::Enum(e) => offset_target_and_file_id(db, e),
|
hir::Adt::Enum(e) => offset_target_and_file_id(db, e)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ModuleDef::Const(c) => {
|
hir::ModuleDef::Const(c) => {
|
||||||
target_name = c.name(db);
|
target_name = c.name(db);
|
||||||
offset_target_and_file_id(db, c)
|
offset_target_and_file_id(db, c)?
|
||||||
}
|
}
|
||||||
hir::ModuleDef::Static(s) => {
|
hir::ModuleDef::Static(s) => {
|
||||||
target_name = s.name(db);
|
target_name = s.name(db);
|
||||||
offset_target_and_file_id(db, s)
|
offset_target_and_file_id(db, s)?
|
||||||
}
|
}
|
||||||
hir::ModuleDef::Trait(t) => {
|
hir::ModuleDef::Trait(t) => {
|
||||||
target_name = Some(t.name(db));
|
target_name = Some(t.name(db));
|
||||||
offset_target_and_file_id(db, t)
|
offset_target_and_file_id(db, t)?
|
||||||
}
|
}
|
||||||
hir::ModuleDef::TypeAlias(t) => {
|
hir::ModuleDef::TypeAlias(t) => {
|
||||||
target_name = Some(t.name(db));
|
target_name = Some(t.name(db));
|
||||||
offset_target_and_file_id(db, t)
|
offset_target_and_file_id(db, t)?
|
||||||
}
|
}
|
||||||
hir::ModuleDef::Module(m) => {
|
hir::ModuleDef::Module(m) => {
|
||||||
target_name = m.name(db);
|
target_name = m.name(db);
|
||||||
|
|
|
@ -98,10 +98,14 @@ pub fn filter_assoc_items(
|
||||||
|
|
||||||
items
|
items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| match i {
|
// Note: This throws away items with no source.
|
||||||
hir::AssocItem::Function(i) => ast::AssocItem::Fn(i.source(db).value),
|
.filter_map(|i| {
|
||||||
hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAlias(i.source(db).value),
|
let item = match i {
|
||||||
hir::AssocItem::Const(i) => ast::AssocItem::Const(i.source(db).value),
|
hir::AssocItem::Function(i) => ast::AssocItem::Fn(i.source(db)?.value),
|
||||||
|
hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAlias(i.source(db)?.value),
|
||||||
|
hir::AssocItem::Const(i) => ast::AssocItem::Const(i.source(db)?.value),
|
||||||
|
};
|
||||||
|
Some(item)
|
||||||
})
|
})
|
||||||
.filter(has_def_name)
|
.filter(has_def_name)
|
||||||
.filter(|it| match it {
|
.filter(|it| match it {
|
||||||
|
|
|
@ -106,8 +106,9 @@ impl Completions {
|
||||||
func: hir::Function,
|
func: hir::Function,
|
||||||
local_name: Option<String>,
|
local_name: Option<String>,
|
||||||
) {
|
) {
|
||||||
let item = render_fn(RenderContext::new(ctx), None, local_name, func);
|
if let Some(item) = render_fn(RenderContext::new(ctx), None, local_name, func) {
|
||||||
self.add(item)
|
self.add(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_variant_pat(
|
pub(crate) fn add_variant_pat(
|
||||||
|
|
|
@ -156,19 +156,21 @@ fn add_function_impl(
|
||||||
};
|
};
|
||||||
let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());
|
let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());
|
||||||
|
|
||||||
let function_decl = function_declaration(&func.source(ctx.db).value);
|
if let Some(src) = func.source(ctx.db) {
|
||||||
match ctx.config.snippet_cap {
|
let function_decl = function_declaration(&src.value);
|
||||||
Some(cap) => {
|
match ctx.config.snippet_cap {
|
||||||
let snippet = format!("{} {{\n $0\n}}", function_decl);
|
Some(cap) => {
|
||||||
builder.snippet_edit(cap, TextEdit::replace(range, snippet))
|
let snippet = format!("{} {{\n $0\n}}", function_decl);
|
||||||
}
|
builder.snippet_edit(cap, TextEdit::replace(range, snippet))
|
||||||
None => {
|
}
|
||||||
let header = format!("{} {{", function_decl);
|
None => {
|
||||||
builder.text_edit(TextEdit::replace(range, header))
|
let header = format!("{} {{", function_decl);
|
||||||
|
builder.text_edit(TextEdit::replace(range, header))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.kind(completion_kind)
|
||||||
|
.add_to(acc);
|
||||||
}
|
}
|
||||||
.kind(completion_kind)
|
|
||||||
.add_to(acc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_type_alias_impl(
|
fn add_type_alias_impl(
|
||||||
|
@ -200,16 +202,19 @@ fn add_const_impl(
|
||||||
let const_name = const_.name(ctx.db).map(|n| n.to_string());
|
let const_name = const_.name(ctx.db).map(|n| n.to_string());
|
||||||
|
|
||||||
if let Some(const_name) = const_name {
|
if let Some(const_name) = const_name {
|
||||||
let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);
|
if let Some(source) = const_.source(ctx.db) {
|
||||||
|
let snippet = make_const_compl_syntax(&source.value);
|
||||||
|
|
||||||
let range = TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());
|
let range =
|
||||||
|
TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());
|
||||||
|
|
||||||
CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
|
CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
|
||||||
.text_edit(TextEdit::replace(range, snippet))
|
.text_edit(TextEdit::replace(range, snippet))
|
||||||
.lookup_by(const_name)
|
.lookup_by(const_name)
|
||||||
.kind(CompletionItemKind::Const)
|
.kind(CompletionItemKind::Const)
|
||||||
.set_documentation(const_.docs(ctx.db))
|
.set_documentation(const_.docs(ctx.db))
|
||||||
.add_to(acc);
|
.add_to(acc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,8 +157,7 @@ impl<'a> Render<'a> {
|
||||||
|
|
||||||
let kind = match resolution {
|
let kind = match resolution {
|
||||||
ScopeDef::ModuleDef(Function(func)) => {
|
ScopeDef::ModuleDef(Function(func)) => {
|
||||||
let item = render_fn(self.ctx, import_to_add, Some(local_name), *func);
|
return render_fn(self.ctx, import_to_add, Some(local_name), *func);
|
||||||
return Some(item);
|
|
||||||
}
|
}
|
||||||
ScopeDef::ModuleDef(Variant(_))
|
ScopeDef::ModuleDef(Variant(_))
|
||||||
if self.ctx.completion.is_pat_binding_or_const
|
if self.ctx.completion.is_pat_binding_or_const
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub(crate) fn render_const<'a>(
|
||||||
ctx: RenderContext<'a>,
|
ctx: RenderContext<'a>,
|
||||||
const_: hir::Const,
|
const_: hir::Const,
|
||||||
) -> Option<CompletionItem> {
|
) -> Option<CompletionItem> {
|
||||||
ConstRender::new(ctx, const_).render()
|
ConstRender::new(ctx, const_)?.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -26,9 +26,9 @@ struct ConstRender<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ConstRender<'a> {
|
impl<'a> ConstRender<'a> {
|
||||||
fn new(ctx: RenderContext<'a>, const_: hir::Const) -> ConstRender<'a> {
|
fn new(ctx: RenderContext<'a>, const_: hir::Const) -> Option<ConstRender<'a>> {
|
||||||
let ast_node = const_.source(ctx.db()).value;
|
let ast_node = const_.source(ctx.db())?.value;
|
||||||
ConstRender { ctx, const_, ast_node }
|
Some(ConstRender { ctx, const_, ast_node })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(self) -> Option<CompletionItem> {
|
fn render(self) -> Option<CompletionItem> {
|
||||||
|
|
|
@ -14,9 +14,9 @@ pub(crate) fn render_fn<'a>(
|
||||||
import_to_add: Option<ImportEdit>,
|
import_to_add: Option<ImportEdit>,
|
||||||
local_name: Option<String>,
|
local_name: Option<String>,
|
||||||
fn_: hir::Function,
|
fn_: hir::Function,
|
||||||
) -> CompletionItem {
|
) -> Option<CompletionItem> {
|
||||||
let _p = profile::span("render_fn");
|
let _p = profile::span("render_fn");
|
||||||
FunctionRender::new(ctx, local_name, fn_).render(import_to_add)
|
Some(FunctionRender::new(ctx, local_name, fn_)?.render(import_to_add))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -32,11 +32,11 @@ impl<'a> FunctionRender<'a> {
|
||||||
ctx: RenderContext<'a>,
|
ctx: RenderContext<'a>,
|
||||||
local_name: Option<String>,
|
local_name: Option<String>,
|
||||||
fn_: hir::Function,
|
fn_: hir::Function,
|
||||||
) -> FunctionRender<'a> {
|
) -> Option<FunctionRender<'a>> {
|
||||||
let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string());
|
let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string());
|
||||||
let ast_node = fn_.source(ctx.db()).value;
|
let ast_node = fn_.source(ctx.db())?.value;
|
||||||
|
|
||||||
FunctionRender { ctx, name, func: fn_, ast_node }
|
Some(FunctionRender { ctx, name, func: fn_, ast_node })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
|
fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
|
||||||
|
|
|
@ -39,20 +39,13 @@ impl<'a> MacroRender<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
|
fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
|
||||||
// FIXME: Currently proc-macro do not have ast-node,
|
|
||||||
// such that it does not have source
|
|
||||||
// more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
|
|
||||||
if self.macro_.is_proc_macro() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut builder =
|
let mut builder =
|
||||||
CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label())
|
CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label())
|
||||||
.kind(CompletionItemKind::Macro)
|
.kind(CompletionItemKind::Macro)
|
||||||
.set_documentation(self.docs.clone())
|
.set_documentation(self.docs.clone())
|
||||||
.set_deprecated(self.ctx.is_deprecated(self.macro_))
|
.set_deprecated(self.ctx.is_deprecated(self.macro_))
|
||||||
.add_import(import_to_add)
|
.add_import(import_to_add)
|
||||||
.detail(self.detail());
|
.set_detail(self.detail());
|
||||||
|
|
||||||
let needs_bang = self.needs_bang();
|
let needs_bang = self.needs_bang();
|
||||||
builder = match self.ctx.snippet_cap() {
|
builder = match self.ctx.snippet_cap() {
|
||||||
|
@ -95,9 +88,9 @@ impl<'a> MacroRender<'a> {
|
||||||
format!("{}!", self.name)
|
format!("{}!", self.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detail(&self) -> String {
|
fn detail(&self) -> Option<String> {
|
||||||
let ast_node = self.macro_.source(self.ctx.db()).value;
|
let ast_node = self.macro_.source(self.ctx.db())?.value;
|
||||||
macro_label(&ast_node)
|
Some(macro_label(&ast_node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub(crate) fn render_type_alias<'a>(
|
||||||
ctx: RenderContext<'a>,
|
ctx: RenderContext<'a>,
|
||||||
type_alias: hir::TypeAlias,
|
type_alias: hir::TypeAlias,
|
||||||
) -> Option<CompletionItem> {
|
) -> Option<CompletionItem> {
|
||||||
TypeAliasRender::new(ctx, type_alias).render()
|
TypeAliasRender::new(ctx, type_alias)?.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -26,9 +26,9 @@ struct TypeAliasRender<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TypeAliasRender<'a> {
|
impl<'a> TypeAliasRender<'a> {
|
||||||
fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> TypeAliasRender<'a> {
|
fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> Option<TypeAliasRender<'a>> {
|
||||||
let ast_node = type_alias.source(ctx.db()).value;
|
let ast_node = type_alias.source(ctx.db())?.value;
|
||||||
TypeAliasRender { ctx, type_alias, ast_node }
|
Some(TypeAliasRender { ctx, type_alias, ast_node })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(self) -> Option<CompletionItem> {
|
fn render(self) -> Option<CompletionItem> {
|
||||||
|
|
|
@ -983,13 +983,7 @@ impl MacroDef {
|
||||||
|
|
||||||
/// XXX: this parses the file
|
/// XXX: this parses the file
|
||||||
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
||||||
// FIXME: Currently proc-macro do not have ast-node,
|
self.source(db)?.value.name().map(|it| it.as_name())
|
||||||
// such that it does not have source
|
|
||||||
// more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
|
|
||||||
if self.is_proc_macro() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
self.source(db).value.name().map(|it| it.as_name())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicate it is a proc-macro
|
/// Indicate it is a proc-macro
|
||||||
|
@ -1378,7 +1372,7 @@ impl Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
|
pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
let item = src.file_id.is_builtin_derive(db.upcast())?;
|
let item = src.file_id.is_builtin_derive(db.upcast())?;
|
||||||
let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id);
|
let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
|
|
||||||
pub trait HasSource {
|
pub trait HasSource {
|
||||||
type Ast;
|
type Ast;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast>;
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NB: Module is !HasSource, because it has two source nodes at the same time:
|
/// NB: Module is !HasSource, because it has two source nodes at the same time:
|
||||||
|
@ -46,105 +46,104 @@ impl Module {
|
||||||
|
|
||||||
impl HasSource for Field {
|
impl HasSource for Field {
|
||||||
type Ast = FieldSource;
|
type Ast = FieldSource;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<FieldSource> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
let var = VariantId::from(self.parent);
|
let var = VariantId::from(self.parent);
|
||||||
let src = var.child_source(db.upcast());
|
let src = var.child_source(db.upcast());
|
||||||
src.map(|it| match it[self.id].clone() {
|
let field_source = src.map(|it| match it[self.id].clone() {
|
||||||
Either::Left(it) => FieldSource::Pos(it),
|
Either::Left(it) => FieldSource::Pos(it),
|
||||||
Either::Right(it) => FieldSource::Named(it),
|
Either::Right(it) => FieldSource::Named(it),
|
||||||
})
|
});
|
||||||
|
Some(field_source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Struct {
|
impl HasSource for Struct {
|
||||||
type Ast = ast::Struct;
|
type Ast = ast::Struct;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Struct> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Union {
|
impl HasSource for Union {
|
||||||
type Ast = ast::Union;
|
type Ast = ast::Union;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Union> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Enum {
|
impl HasSource for Enum {
|
||||||
type Ast = ast::Enum;
|
type Ast = ast::Enum;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Enum> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Variant {
|
impl HasSource for Variant {
|
||||||
type Ast = ast::Variant;
|
type Ast = ast::Variant;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Variant> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Variant>> {
|
||||||
self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone())
|
Some(self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Function {
|
impl HasSource for Function {
|
||||||
type Ast = ast::Fn;
|
type Ast = ast::Fn;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Fn> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Const {
|
impl HasSource for Const {
|
||||||
type Ast = ast::Const;
|
type Ast = ast::Const;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Const> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Static {
|
impl HasSource for Static {
|
||||||
type Ast = ast::Static;
|
type Ast = ast::Static;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Static> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Trait {
|
impl HasSource for Trait {
|
||||||
type Ast = ast::Trait;
|
type Ast = ast::Trait;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Trait> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for TypeAlias {
|
impl HasSource for TypeAlias {
|
||||||
type Ast = ast::TypeAlias;
|
type Ast = ast::TypeAlias;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::TypeAlias> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for MacroDef {
|
impl HasSource for MacroDef {
|
||||||
type Ast = ast::Macro;
|
type Ast = ast::Macro;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Macro> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
InFile {
|
let ast_id = self.id.ast_id?;
|
||||||
file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id,
|
Some(InFile { file_id: ast_id.file_id, value: ast_id.to_node(db.upcast()) })
|
||||||
value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Impl {
|
impl HasSource for Impl {
|
||||||
type Ast = ast::Impl;
|
type Ast = ast::Impl;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Impl> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
self.id.lookup(db.upcast()).source(db.upcast())
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasSource for TypeParam {
|
impl HasSource for TypeParam {
|
||||||
type Ast = Either<ast::Trait, ast::TypeParam>;
|
type Ast = Either<ast::Trait, ast::TypeParam>;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
let child_source = self.id.parent.child_source(db.upcast());
|
let child_source = self.id.parent.child_source(db.upcast());
|
||||||
child_source.map(|it| it[self.id.local_id].clone())
|
Some(child_source.map(|it| it[self.id.local_id].clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasSource for LifetimeParam {
|
impl HasSource for LifetimeParam {
|
||||||
type Ast = ast::LifetimeParam;
|
type Ast = ast::LifetimeParam;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
let child_source = self.id.parent.child_source(db.upcast());
|
let child_source = self.id.parent.child_source(db.upcast());
|
||||||
child_source.map(|it| it[self.id.local_id].clone())
|
Some(child_source.map(|it| it[self.id.local_id].clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasSource for ConstParam {
|
impl HasSource for ConstParam {
|
||||||
type Ast = ast::ConstParam;
|
type Ast = ast::ConstParam;
|
||||||
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
let child_source = self.id.parent.child_source(db.upcast());
|
let child_source = self.id.parent.child_source(db.upcast());
|
||||||
child_source.map(|it| it[self.id.local_id].clone())
|
Some(child_source.map(|it| it[self.id.local_id].clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ide_db::RootDatabase;
|
||||||
use syntax::{ast, match_ast, AstNode, TextRange};
|
use syntax::{ast, match_ast, AstNode, TextRange};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::ToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo,
|
display::TryToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -61,7 +61,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio
|
||||||
match node {
|
match node {
|
||||||
ast::Fn(it) => {
|
ast::Fn(it) => {
|
||||||
let def = sema.to_def(&it)?;
|
let def = sema.to_def(&it)?;
|
||||||
Some(def.to_nav(sema.db))
|
def.try_to_nav(sema.db)
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
|
||||||
match callable.kind() {
|
match callable.kind() {
|
||||||
hir::CallableKind::Function(it) => {
|
hir::CallableKind::Function(it) => {
|
||||||
let fn_def: hir::Function = it.into();
|
let fn_def: hir::Function = it.into();
|
||||||
let nav = fn_def.to_nav(db);
|
let nav = fn_def.try_to_nav(db)?;
|
||||||
Some(nav)
|
Some(nav)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -107,7 +107,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
|
||||||
}
|
}
|
||||||
FnCallNode::MethodCallExpr(expr) => {
|
FnCallNode::MethodCallExpr(expr) => {
|
||||||
let function = sema.resolve_method_call(&expr)?;
|
let function = sema.resolve_method_call(&expr)?;
|
||||||
Some(function.to_nav(db))
|
function.try_to_nav(db)
|
||||||
}
|
}
|
||||||
} {
|
} {
|
||||||
Some((func_target, name_ref.syntax().text_range()))
|
Some((func_target, name_ref.syntax().text_range()))
|
||||||
|
|
|
@ -156,20 +156,23 @@ fn missing_record_expr_field_fix(
|
||||||
let record_fields = match VariantDef::from(def_id) {
|
let record_fields = match VariantDef::from(def_id) {
|
||||||
VariantDef::Struct(s) => {
|
VariantDef::Struct(s) => {
|
||||||
module = s.module(sema.db);
|
module = s.module(sema.db);
|
||||||
let source = s.source(sema.db);
|
#[allow(deprecated)]
|
||||||
|
let source = s.source(sema.db)?;
|
||||||
def_file_id = source.file_id;
|
def_file_id = source.file_id;
|
||||||
let fields = source.value.field_list()?;
|
let fields = source.value.field_list()?;
|
||||||
record_field_list(fields)?
|
record_field_list(fields)?
|
||||||
}
|
}
|
||||||
VariantDef::Union(u) => {
|
VariantDef::Union(u) => {
|
||||||
module = u.module(sema.db);
|
module = u.module(sema.db);
|
||||||
let source = u.source(sema.db);
|
#[allow(deprecated)]
|
||||||
|
let source = u.source(sema.db)?;
|
||||||
def_file_id = source.file_id;
|
def_file_id = source.file_id;
|
||||||
source.value.record_field_list()?
|
source.value.record_field_list()?
|
||||||
}
|
}
|
||||||
VariantDef::Variant(e) => {
|
VariantDef::Variant(e) => {
|
||||||
module = e.module(sema.db);
|
module = e.module(sema.db);
|
||||||
let source = e.source(sema.db);
|
#[allow(deprecated)]
|
||||||
|
let source = e.source(sema.db)?;
|
||||||
def_file_id = source.file_id;
|
def_file_id = source.file_id;
|
||||||
let fields = source.value.field_list()?;
|
let fields = source.value.field_list()?;
|
||||||
record_field_list(fields)?
|
record_field_list(fields)?
|
||||||
|
|
|
@ -210,41 +210,32 @@ impl ToNav for FileSymbol {
|
||||||
impl TryToNav for Definition {
|
impl TryToNav for Definition {
|
||||||
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
match self {
|
match self {
|
||||||
Definition::Macro(it) => {
|
Definition::Macro(it) => it.try_to_nav(db),
|
||||||
// FIXME: Currently proc-macro do not have ast-node,
|
Definition::Field(it) => it.try_to_nav(db),
|
||||||
// such that it does not have source
|
|
||||||
// more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
|
|
||||||
if it.is_proc_macro() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(it.to_nav(db))
|
|
||||||
}
|
|
||||||
Definition::Field(it) => Some(it.to_nav(db)),
|
|
||||||
Definition::ModuleDef(it) => it.try_to_nav(db),
|
Definition::ModuleDef(it) => it.try_to_nav(db),
|
||||||
Definition::SelfType(it) => Some(it.to_nav(db)),
|
Definition::SelfType(it) => it.try_to_nav(db),
|
||||||
Definition::Local(it) => Some(it.to_nav(db)),
|
Definition::Local(it) => Some(it.to_nav(db)),
|
||||||
Definition::TypeParam(it) => Some(it.to_nav(db)),
|
Definition::TypeParam(it) => it.try_to_nav(db),
|
||||||
Definition::LifetimeParam(it) => Some(it.to_nav(db)),
|
Definition::LifetimeParam(it) => it.try_to_nav(db),
|
||||||
Definition::Label(it) => Some(it.to_nav(db)),
|
Definition::Label(it) => Some(it.to_nav(db)),
|
||||||
Definition::ConstParam(it) => Some(it.to_nav(db)),
|
Definition::ConstParam(it) => it.try_to_nav(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryToNav for hir::ModuleDef {
|
impl TryToNav for hir::ModuleDef {
|
||||||
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let res = match self {
|
match self {
|
||||||
hir::ModuleDef::Module(it) => it.to_nav(db),
|
hir::ModuleDef::Module(it) => Some(it.to_nav(db)),
|
||||||
hir::ModuleDef::Function(it) => it.to_nav(db),
|
hir::ModuleDef::Function(it) => it.try_to_nav(db),
|
||||||
hir::ModuleDef::Adt(it) => it.to_nav(db),
|
hir::ModuleDef::Adt(it) => it.try_to_nav(db),
|
||||||
hir::ModuleDef::Variant(it) => it.to_nav(db),
|
hir::ModuleDef::Variant(it) => it.try_to_nav(db),
|
||||||
hir::ModuleDef::Const(it) => it.to_nav(db),
|
hir::ModuleDef::Const(it) => it.try_to_nav(db),
|
||||||
hir::ModuleDef::Static(it) => it.to_nav(db),
|
hir::ModuleDef::Static(it) => it.try_to_nav(db),
|
||||||
hir::ModuleDef::Trait(it) => it.to_nav(db),
|
hir::ModuleDef::Trait(it) => it.try_to_nav(db),
|
||||||
hir::ModuleDef::TypeAlias(it) => it.to_nav(db),
|
hir::ModuleDef::TypeAlias(it) => it.try_to_nav(db),
|
||||||
hir::ModuleDef::BuiltinType(_) => return None,
|
hir::ModuleDef::BuiltinType(_) => None,
|
||||||
};
|
}
|
||||||
Some(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,13 +270,13 @@ impl ToNavFromAst for hir::Trait {
|
||||||
const KIND: SymbolKind = SymbolKind::Trait;
|
const KIND: SymbolKind = SymbolKind::Trait;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ToNav for D
|
impl<D> TryToNav for D
|
||||||
where
|
where
|
||||||
D: HasSource + ToNavFromAst + Copy + HasAttrs,
|
D: HasSource + ToNavFromAst + Copy + HasAttrs,
|
||||||
D::Ast: ast::NameOwner + ShortLabel,
|
D::Ast: ast::NameOwner + ShortLabel,
|
||||||
{
|
{
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
let mut res = NavigationTarget::from_named(
|
let mut res = NavigationTarget::from_named(
|
||||||
db,
|
db,
|
||||||
src.as_ref().map(|it| it as &dyn ast::NameOwner),
|
src.as_ref().map(|it| it as &dyn ast::NameOwner),
|
||||||
|
@ -293,7 +284,7 @@ where
|
||||||
);
|
);
|
||||||
res.docs = self.docs(db);
|
res.docs = self.docs(db);
|
||||||
res.description = src.value.short_label();
|
res.description = src.value.short_label();
|
||||||
res
|
Some(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,9 +303,9 @@ impl ToNav for hir::Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::Impl {
|
impl TryToNav for hir::Impl {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
let derive_attr = self.is_builtin_derive(db);
|
let derive_attr = self.is_builtin_derive(db);
|
||||||
let frange = if let Some(item) = &derive_attr {
|
let frange = if let Some(item) = &derive_attr {
|
||||||
item.syntax().original_file_range(db)
|
item.syntax().original_file_range(db)
|
||||||
|
@ -327,21 +318,21 @@ impl ToNav for hir::Impl {
|
||||||
src.value.self_ty().map(|ty| src.with_value(ty.syntax()).original_file_range(db).range)
|
src.value.self_ty().map(|ty| src.with_value(ty.syntax()).original_file_range(db).range)
|
||||||
};
|
};
|
||||||
|
|
||||||
NavigationTarget::from_syntax(
|
Some(NavigationTarget::from_syntax(
|
||||||
frange.file_id,
|
frange.file_id,
|
||||||
"impl".into(),
|
"impl".into(),
|
||||||
focus_range,
|
focus_range,
|
||||||
frange.range,
|
frange.range,
|
||||||
SymbolKind::Impl,
|
SymbolKind::Impl,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::Field {
|
impl TryToNav for hir::Field {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
|
|
||||||
match &src.value {
|
let field_source = match &src.value {
|
||||||
FieldSource::Named(it) => {
|
FieldSource::Named(it) => {
|
||||||
let mut res =
|
let mut res =
|
||||||
NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field);
|
NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field);
|
||||||
|
@ -359,13 +350,14 @@ impl ToNav for hir::Field {
|
||||||
SymbolKind::Field,
|
SymbolKind::Field,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
Some(field_source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::MacroDef {
|
impl TryToNav for hir::MacroDef {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
log::debug!("nav target {:#?}", src.value.syntax());
|
log::debug!("nav target {:#?}", src.value.syntax());
|
||||||
let mut res = NavigationTarget::from_named(
|
let mut res = NavigationTarget::from_named(
|
||||||
db,
|
db,
|
||||||
|
@ -373,26 +365,26 @@ impl ToNav for hir::MacroDef {
|
||||||
SymbolKind::Macro,
|
SymbolKind::Macro,
|
||||||
);
|
);
|
||||||
res.docs = self.docs(db);
|
res.docs = self.docs(db);
|
||||||
res
|
Some(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::Adt {
|
impl TryToNav for hir::Adt {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
match self {
|
match self {
|
||||||
hir::Adt::Struct(it) => it.to_nav(db),
|
hir::Adt::Struct(it) => it.try_to_nav(db),
|
||||||
hir::Adt::Union(it) => it.to_nav(db),
|
hir::Adt::Union(it) => it.try_to_nav(db),
|
||||||
hir::Adt::Enum(it) => it.to_nav(db),
|
hir::Adt::Enum(it) => it.try_to_nav(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::AssocItem {
|
impl TryToNav for hir::AssocItem {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
match self {
|
match self {
|
||||||
AssocItem::Function(it) => it.to_nav(db),
|
AssocItem::Function(it) => it.try_to_nav(db),
|
||||||
AssocItem::Const(it) => it.to_nav(db),
|
AssocItem::Const(it) => it.try_to_nav(db),
|
||||||
AssocItem::TypeAlias(it) => it.to_nav(db),
|
AssocItem::TypeAlias(it) => it.try_to_nav(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,9 +438,9 @@ impl ToNav for hir::Label {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::TypeParam {
|
impl TryToNav for hir::TypeParam {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
let full_range = match &src.value {
|
let full_range = match &src.value {
|
||||||
Either::Left(it) => it.syntax().text_range(),
|
Either::Left(it) => it.syntax().text_range(),
|
||||||
Either::Right(it) => it.syntax().text_range(),
|
Either::Right(it) => it.syntax().text_range(),
|
||||||
|
@ -457,7 +449,7 @@ impl ToNav for hir::TypeParam {
|
||||||
Either::Left(_) => None,
|
Either::Left(_) => None,
|
||||||
Either::Right(it) => it.name().map(|it| it.syntax().text_range()),
|
Either::Right(it) => it.name().map(|it| it.syntax().text_range()),
|
||||||
};
|
};
|
||||||
NavigationTarget {
|
Some(NavigationTarget {
|
||||||
file_id: src.file_id.original_file(db),
|
file_id: src.file_id.original_file(db),
|
||||||
name: self.name(db).to_string().into(),
|
name: self.name(db).to_string().into(),
|
||||||
kind: Some(SymbolKind::TypeParam),
|
kind: Some(SymbolKind::TypeParam),
|
||||||
|
@ -466,15 +458,15 @@ impl ToNav for hir::TypeParam {
|
||||||
container_name: None,
|
container_name: None,
|
||||||
description: None,
|
description: None,
|
||||||
docs: None,
|
docs: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::LifetimeParam {
|
impl TryToNav for hir::LifetimeParam {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
let full_range = src.value.syntax().text_range();
|
let full_range = src.value.syntax().text_range();
|
||||||
NavigationTarget {
|
Some(NavigationTarget {
|
||||||
file_id: src.file_id.original_file(db),
|
file_id: src.file_id.original_file(db),
|
||||||
name: self.name(db).to_string().into(),
|
name: self.name(db).to_string().into(),
|
||||||
kind: Some(SymbolKind::LifetimeParam),
|
kind: Some(SymbolKind::LifetimeParam),
|
||||||
|
@ -483,15 +475,15 @@ impl ToNav for hir::LifetimeParam {
|
||||||
container_name: None,
|
container_name: None,
|
||||||
description: None,
|
description: None,
|
||||||
docs: None,
|
docs: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNav for hir::ConstParam {
|
impl TryToNav for hir::ConstParam {
|
||||||
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db);
|
let src = self.source(db)?;
|
||||||
let full_range = src.value.syntax().text_range();
|
let full_range = src.value.syntax().text_range();
|
||||||
NavigationTarget {
|
Some(NavigationTarget {
|
||||||
file_id: src.file_id.original_file(db),
|
file_id: src.file_id.original_file(db),
|
||||||
name: self.name(db).to_string().into(),
|
name: self.name(db).to_string().into(),
|
||||||
kind: Some(SymbolKind::ConstParam),
|
kind: Some(SymbolKind::ConstParam),
|
||||||
|
@ -500,7 +492,7 @@ impl ToNav for hir::ConstParam {
|
||||||
container_name: None,
|
container_name: None,
|
||||||
description: None,
|
description: None,
|
||||||
docs: None,
|
docs: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use hir::{Crate, Impl, Semantics};
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
use syntax::{algo::find_node_at_offset, ast, AstNode};
|
use syntax::{algo::find_node_at_offset, ast, AstNode};
|
||||||
|
|
||||||
use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo};
|
use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
|
||||||
|
|
||||||
// Feature: Go to Implementation
|
// Feature: Go to Implementation
|
||||||
//
|
//
|
||||||
|
@ -55,7 +55,7 @@ fn impls_for_def(
|
||||||
impls
|
impls
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|impl_def| ty.is_equal_for_find_impls(&impl_def.target_ty(sema.db)))
|
.filter(|impl_def| ty.is_equal_for_find_impls(&impl_def.target_ty(sema.db)))
|
||||||
.map(|imp| imp.to_nav(sema.db))
|
.filter_map(|imp| imp.try_to_nav(sema.db))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ fn impls_for_trait(
|
||||||
|
|
||||||
let impls = Impl::for_trait(sema.db, krate, tr);
|
let impls = Impl::for_trait(sema.db, krate, tr);
|
||||||
|
|
||||||
Some(impls.into_iter().map(|imp| imp.to_nav(sema.db)).collect())
|
Some(impls.into_iter().filter_map(|imp| imp.try_to_nav(sema.db)).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
|
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
|
||||||
|
|
||||||
use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo};
|
use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
|
||||||
|
|
||||||
// Feature: Go to Type Definition
|
// Feature: Go to Type Definition
|
||||||
//
|
//
|
||||||
|
@ -37,7 +37,7 @@ pub(crate) fn goto_type_definition(
|
||||||
|
|
||||||
let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?;
|
let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?;
|
||||||
|
|
||||||
let nav = adt_def.to_nav(db);
|
let nav = adt_def.try_to_nav(db)?;
|
||||||
Some(RangeInfo::new(node.text_range(), vec![nav]))
|
Some(RangeInfo::new(node.text_range(), vec![nav]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset,
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::{macro_label, ShortLabel, ToNav, TryToNav},
|
display::{macro_label, ShortLabel, TryToNav},
|
||||||
doc_links::{remove_links, rewrite_links},
|
doc_links::{remove_links, rewrite_links},
|
||||||
markdown_remove::remove_markdown,
|
markdown_remove::remove_markdown,
|
||||||
markup::Markup,
|
markup::Markup,
|
||||||
|
@ -183,10 +183,10 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
Definition::ModuleDef(it) => match it {
|
Definition::ModuleDef(it) => match it {
|
||||||
ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.to_nav(db))),
|
ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.try_to_nav(db)?)),
|
||||||
ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.to_nav(db))),
|
ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.try_to_nav(db)?)),
|
||||||
ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.to_nav(db))),
|
ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.try_to_nav(db)?)),
|
||||||
ModuleDef::Trait(it) => Some(to_action(it.to_nav(db))),
|
ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -206,7 +206,8 @@ fn runnable_action(
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
ModuleDef::Function(it) => {
|
ModuleDef::Function(it) => {
|
||||||
let src = it.source(sema.db);
|
#[allow(deprecated)]
|
||||||
|
let src = it.source(sema.db)?;
|
||||||
if src.file_id != file_id.into() {
|
if src.file_id != file_id.into() {
|
||||||
mark::hit!(hover_macro_generated_struct_fn_doc_comment);
|
mark::hit!(hover_macro_generated_struct_fn_doc_comment);
|
||||||
mark::hit!(hover_macro_generated_struct_fn_doc_attr);
|
mark::hit!(hover_macro_generated_struct_fn_doc_attr);
|
||||||
|
@ -326,17 +327,12 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
|
||||||
let mod_path = definition_mod_path(db, &def);
|
let mod_path = definition_mod_path(db, &def);
|
||||||
return match def {
|
return match def {
|
||||||
Definition::Macro(it) => {
|
Definition::Macro(it) => {
|
||||||
// FIXME: Currently proc-macro do not have ast-node,
|
let label = macro_label(&it.source(db)?.value);
|
||||||
// such that it does not have source
|
|
||||||
// more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
|
|
||||||
if it.is_proc_macro() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let label = macro_label(&it.source(db).value);
|
|
||||||
from_def_source_labeled(db, it, Some(label), mod_path)
|
from_def_source_labeled(db, it, Some(label), mod_path)
|
||||||
}
|
}
|
||||||
Definition::Field(def) => {
|
Definition::Field(def) => {
|
||||||
let src = def.source(db).value;
|
#[allow(deprecated)]
|
||||||
|
let src = def.source(db)?.value;
|
||||||
if let FieldSource::Named(it) = src {
|
if let FieldSource::Named(it) = src {
|
||||||
from_def_source_labeled(db, def, it.short_label(), mod_path)
|
from_def_source_labeled(db, def, it.short_label(), mod_path)
|
||||||
} else {
|
} else {
|
||||||
|
@ -385,7 +381,8 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
|
||||||
D: HasSource<Ast = A> + HasAttrs + Copy,
|
D: HasSource<Ast = A> + HasAttrs + Copy,
|
||||||
A: ShortLabel,
|
A: ShortLabel,
|
||||||
{
|
{
|
||||||
let short_label = def.source(db).value.short_label();
|
#[allow(deprecated)]
|
||||||
|
let short_label = def.source(db)?.value.short_label();
|
||||||
from_def_source_labeled(db, def, short_label, mod_path)
|
from_def_source_labeled(db, def, short_label, mod_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,31 +121,56 @@ impl Definition {
|
||||||
|
|
||||||
if let Definition::Local(var) = self {
|
if let Definition::Local(var) = self {
|
||||||
let range = match var.parent(db) {
|
let range = match var.parent(db) {
|
||||||
DefWithBody::Function(f) => f.source(db).value.syntax().text_range(),
|
DefWithBody::Function(f) => {
|
||||||
DefWithBody::Const(c) => c.source(db).value.syntax().text_range(),
|
f.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
DefWithBody::Static(s) => s.source(db).value.syntax().text_range(),
|
}
|
||||||
|
DefWithBody::Const(c) => {
|
||||||
|
c.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
|
DefWithBody::Static(s) => {
|
||||||
|
s.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let mut res = FxHashMap::default();
|
let mut res = FxHashMap::default();
|
||||||
res.insert(file_id, Some(range));
|
res.insert(file_id, range);
|
||||||
return SearchScope::new(res);
|
return SearchScope::new(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Definition::LifetimeParam(param) = self {
|
if let Definition::LifetimeParam(param) = self {
|
||||||
|
#[allow(deprecated)]
|
||||||
let range = match param.parent(db) {
|
let range = match param.parent(db) {
|
||||||
hir::GenericDef::Function(it) => it.source(db).value.syntax().text_range(),
|
hir::GenericDef::Function(it) => {
|
||||||
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
hir::GenericDef::Adt(it) => match it {
|
hir::GenericDef::Adt(it) => match it {
|
||||||
hir::Adt::Struct(it) => it.source(db).value.syntax().text_range(),
|
hir::Adt::Struct(it) => {
|
||||||
hir::Adt::Union(it) => it.source(db).value.syntax().text_range(),
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
hir::Adt::Enum(it) => it.source(db).value.syntax().text_range(),
|
}
|
||||||
|
hir::Adt::Union(it) => {
|
||||||
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
|
hir::Adt::Enum(it) => {
|
||||||
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
hir::GenericDef::Trait(it) => it.source(db).value.syntax().text_range(),
|
hir::GenericDef::Trait(it) => {
|
||||||
hir::GenericDef::TypeAlias(it) => it.source(db).value.syntax().text_range(),
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
hir::GenericDef::Impl(it) => it.source(db).value.syntax().text_range(),
|
}
|
||||||
hir::GenericDef::Variant(it) => it.source(db).value.syntax().text_range(),
|
hir::GenericDef::TypeAlias(it) => {
|
||||||
hir::GenericDef::Const(it) => it.source(db).value.syntax().text_range(),
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
|
hir::GenericDef::Impl(it) => {
|
||||||
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
|
hir::GenericDef::Variant(it) => {
|
||||||
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
|
hir::GenericDef::Const(it) => {
|
||||||
|
it.source(db).and_then(|src| Some(src.value.syntax().text_range()))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let mut res = FxHashMap::default();
|
let mut res = FxHashMap::default();
|
||||||
res.insert(file_id, Some(range));
|
res.insert(file_id, range);
|
||||||
return SearchScope::new(res);
|
return SearchScope::new(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,11 +161,12 @@ impl AnalysisStatsCmd {
|
||||||
}
|
}
|
||||||
let mut msg = format!("processing: {}", full_name);
|
let mut msg = format!("processing: {}", full_name);
|
||||||
if verbosity.is_verbose() {
|
if verbosity.is_verbose() {
|
||||||
let src = f.source(db);
|
if let Some(src) = f.source(db) {
|
||||||
let original_file = src.file_id.original_file(db);
|
let original_file = src.file_id.original_file(db);
|
||||||
let path = vfs.file_path(original_file);
|
let path = vfs.file_path(original_file);
|
||||||
let syntax_range = src.value.syntax().text_range();
|
let syntax_range = src.value.syntax().text_range();
|
||||||
format_to!(msg, " ({} {:?})", path, syntax_range);
|
format_to!(msg, " ({} {:?})", path, syntax_range);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if verbosity.is_spammy() {
|
if verbosity.is_spammy() {
|
||||||
bar.println(msg.to_string());
|
bar.println(msg.to_string());
|
||||||
|
|
Loading…
Reference in a new issue