diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs index cb60a3128288..f9a62b9facd5 100644 --- a/crates/assists/src/handlers/fill_match_arms.rs +++ b/crates/assists/src/handlers/fill_match_arms.rs @@ -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))?); // 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) => { let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count()); make::tuple_struct_pat(path, pats).into() diff --git a/crates/assists/src/handlers/fix_visibility.rs b/crates/assists/src/handlers/fix_visibility.rs index 8558a8ff01ce..de1e8f0bfa6e 100644 --- a/crates/assists/src/handlers/fix_visibility.rs +++ b/crates/assists/src/handlers/fix_visibility.rs @@ -97,7 +97,8 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> let parent_name = parent.name(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 { hir::FieldSource::Named(it) => { let s = it.syntax(); @@ -145,53 +146,53 @@ fn target_data_for_def( fn offset_target_and_file_id( db: &dyn HirDatabase, x: S, - ) -> (TextSize, Option, TextRange, FileId) + ) -> Option<(TextSize, Option, TextRange, FileId)> where S: HasSource, Ast: AstNode + ast::VisibilityOwner, { - let source = x.source(db); + let source = x.source(db)?; let in_file_syntax = source.syntax(); let file_id = in_file_syntax.file_id; let syntax = in_file_syntax.value; let current_visibility = source.value.visibility(); - ( + Some(( vis_offset(syntax), current_visibility, syntax.text_range(), file_id.original_file(db.upcast()), - ) + )) } let target_name; let (offset, current_visibility, target, target_file) = match def { hir::ModuleDef::Function(f) => { target_name = Some(f.name(db)); - offset_target_and_file_id(db, f) + offset_target_and_file_id(db, f)? } hir::ModuleDef::Adt(adt) => { target_name = Some(adt.name(db)); match adt { - hir::Adt::Struct(s) => offset_target_and_file_id(db, s), - hir::Adt::Union(u) => offset_target_and_file_id(db, u), - hir::Adt::Enum(e) => offset_target_and_file_id(db, e), + hir::Adt::Struct(s) => offset_target_and_file_id(db, s)?, + hir::Adt::Union(u) => offset_target_and_file_id(db, u)?, + hir::Adt::Enum(e) => offset_target_and_file_id(db, e)?, } } hir::ModuleDef::Const(c) => { target_name = c.name(db); - offset_target_and_file_id(db, c) + offset_target_and_file_id(db, c)? } hir::ModuleDef::Static(s) => { target_name = s.name(db); - offset_target_and_file_id(db, s) + offset_target_and_file_id(db, s)? } hir::ModuleDef::Trait(t) => { target_name = Some(t.name(db)); - offset_target_and_file_id(db, t) + offset_target_and_file_id(db, t)? } hir::ModuleDef::TypeAlias(t) => { target_name = Some(t.name(db)); - offset_target_and_file_id(db, t) + offset_target_and_file_id(db, t)? } hir::ModuleDef::Module(m) => { target_name = m.name(db); diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index d41084b59944..7c159b5ba041 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs @@ -98,10 +98,14 @@ pub fn filter_assoc_items( items .iter() - .map(|i| match i { - 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), + // Note: This throws away items with no source. + .filter_map(|i| { + let item = match i { + 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(|it| match it { diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs index d9fe1348552e..00c9e76f038e 100644 --- a/crates/completion/src/completions.rs +++ b/crates/completion/src/completions.rs @@ -106,8 +106,9 @@ impl Completions { func: hir::Function, local_name: Option, ) { - let item = render_fn(RenderContext::new(ctx), None, local_name, func); - self.add(item) + if let Some(item) = render_fn(RenderContext::new(ctx), None, local_name, func) { + self.add(item) + } } pub(crate) fn add_variant_pat( diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs index c4e0d06698f2..54bb897e9b78 100644 --- a/crates/completion/src/completions/trait_impl.rs +++ b/crates/completion/src/completions/trait_impl.rs @@ -156,19 +156,21 @@ fn add_function_impl( }; let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end()); - let function_decl = function_declaration(&func.source(ctx.db).value); - match ctx.config.snippet_cap { - Some(cap) => { - let snippet = format!("{} {{\n $0\n}}", function_decl); - builder.snippet_edit(cap, TextEdit::replace(range, snippet)) - } - None => { - let header = format!("{} {{", function_decl); - builder.text_edit(TextEdit::replace(range, header)) + if let Some(src) = func.source(ctx.db) { + let function_decl = function_declaration(&src.value); + match ctx.config.snippet_cap { + Some(cap) => { + let snippet = format!("{} {{\n $0\n}}", function_decl); + builder.snippet_edit(cap, TextEdit::replace(range, snippet)) + } + None => { + 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( @@ -200,16 +202,19 @@ fn add_const_impl( let const_name = const_.name(ctx.db).map(|n| n.to_string()); if let Some(const_name) = const_name { - let snippet = make_const_compl_syntax(&const_.source(ctx.db).value); - - let range = TextRange::new(const_def_node.text_range().start(), ctx.source_range().end()); - - CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) - .text_edit(TextEdit::replace(range, snippet)) - .lookup_by(const_name) - .kind(CompletionItemKind::Const) - .set_documentation(const_.docs(ctx.db)) - .add_to(acc); + 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()); + + CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) + .text_edit(TextEdit::replace(range, snippet)) + .lookup_by(const_name) + .kind(CompletionItemKind::Const) + .set_documentation(const_.docs(ctx.db)) + .add_to(acc); + } } } diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index 1ba7201a1385..ac0b2a5139ec 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs @@ -157,8 +157,7 @@ impl<'a> Render<'a> { let kind = match resolution { ScopeDef::ModuleDef(Function(func)) => { - let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); - return Some(item); + return render_fn(self.ctx, import_to_add, Some(local_name), *func); } ScopeDef::ModuleDef(Variant(_)) if self.ctx.completion.is_pat_binding_or_const diff --git a/crates/completion/src/render/const_.rs b/crates/completion/src/render/const_.rs index 039bdabc051a..ce924f309526 100644 --- a/crates/completion/src/render/const_.rs +++ b/crates/completion/src/render/const_.rs @@ -15,7 +15,7 @@ pub(crate) fn render_const<'a>( ctx: RenderContext<'a>, const_: hir::Const, ) -> Option { - ConstRender::new(ctx, const_).render() + ConstRender::new(ctx, const_)?.render() } #[derive(Debug)] @@ -26,9 +26,9 @@ struct ConstRender<'a> { } impl<'a> ConstRender<'a> { - fn new(ctx: RenderContext<'a>, const_: hir::Const) -> ConstRender<'a> { - let ast_node = const_.source(ctx.db()).value; - ConstRender { ctx, const_, ast_node } + fn new(ctx: RenderContext<'a>, const_: hir::Const) -> Option> { + let ast_node = const_.source(ctx.db())?.value; + Some(ConstRender { ctx, const_, ast_node }) } fn render(self) -> Option { diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs index 316e05b529cc..081be14f4eb3 100644 --- a/crates/completion/src/render/function.rs +++ b/crates/completion/src/render/function.rs @@ -14,9 +14,9 @@ pub(crate) fn render_fn<'a>( import_to_add: Option, local_name: Option, fn_: hir::Function, -) -> CompletionItem { +) -> Option { 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)] @@ -32,11 +32,11 @@ impl<'a> FunctionRender<'a> { ctx: RenderContext<'a>, local_name: Option, fn_: hir::Function, - ) -> FunctionRender<'a> { + ) -> Option> { 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) -> CompletionItem { diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs index dac79592f7f2..6f4f9945c198 100644 --- a/crates/completion/src/render/macro_.rs +++ b/crates/completion/src/render/macro_.rs @@ -39,20 +39,13 @@ impl<'a> MacroRender<'a> { } fn render(&self, import_to_add: Option) -> Option { - // 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 = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()) .kind(CompletionItemKind::Macro) .set_documentation(self.docs.clone()) .set_deprecated(self.ctx.is_deprecated(self.macro_)) .add_import(import_to_add) - .detail(self.detail()); + .set_detail(self.detail()); let needs_bang = self.needs_bang(); builder = match self.ctx.snippet_cap() { @@ -95,9 +88,9 @@ impl<'a> MacroRender<'a> { format!("{}!", self.name) } - fn detail(&self) -> String { - let ast_node = self.macro_.source(self.ctx.db()).value; - macro_label(&ast_node) + fn detail(&self) -> Option { + let ast_node = self.macro_.source(self.ctx.db())?.value; + Some(macro_label(&ast_node)) } } diff --git a/crates/completion/src/render/type_alias.rs b/crates/completion/src/render/type_alias.rs index 9605c7fa9424..69b445b9c69d 100644 --- a/crates/completion/src/render/type_alias.rs +++ b/crates/completion/src/render/type_alias.rs @@ -15,7 +15,7 @@ pub(crate) fn render_type_alias<'a>( ctx: RenderContext<'a>, type_alias: hir::TypeAlias, ) -> Option { - TypeAliasRender::new(ctx, type_alias).render() + TypeAliasRender::new(ctx, type_alias)?.render() } #[derive(Debug)] @@ -26,9 +26,9 @@ struct TypeAliasRender<'a> { } impl<'a> TypeAliasRender<'a> { - fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> TypeAliasRender<'a> { - let ast_node = type_alias.source(ctx.db()).value; - TypeAliasRender { ctx, type_alias, ast_node } + fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> Option> { + let ast_node = type_alias.source(ctx.db())?.value; + Some(TypeAliasRender { ctx, type_alias, ast_node }) } fn render(self) -> Option { diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 97b7a8b5f58a..3c83231cf1c3 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs @@ -983,13 +983,7 @@ impl MacroDef { /// XXX: this parses the file pub fn name(self, db: &dyn HirDatabase) -> Option { - // 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.is_proc_macro() { - return None; - } - self.source(db).value.name().map(|it| it.as_name()) + self.source(db)?.value.name().map(|it| it.as_name()) } /// Indicate it is a proc-macro @@ -1378,7 +1372,7 @@ impl Impl { } pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option> { - let src = self.source(db); + let src = self.source(db)?; let item = src.file_id.is_builtin_derive(db.upcast())?; let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index dd7c0c57067c..7c57d8378cca 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -16,7 +16,7 @@ use crate::{ pub trait HasSource { type Ast; - fn source(self, db: &dyn HirDatabase) -> InFile; + fn source(self, db: &dyn HirDatabase) -> Option>; } /// NB: Module is !HasSource, because it has two source nodes at the same time: @@ -46,105 +46,104 @@ impl Module { impl HasSource for Field { type Ast = FieldSource; - fn source(self, db: &dyn HirDatabase) -> InFile { + fn source(self, db: &dyn HirDatabase) -> Option> { let var = VariantId::from(self.parent); 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::Right(it) => FieldSource::Named(it), - }) + }); + Some(field_source) } } impl HasSource for Struct { type Ast = ast::Struct; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for Union { type Ast = ast::Union; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for Enum { type Ast = ast::Enum; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for Variant { type Ast = ast::Variant; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone())) } } impl HasSource for Function { type Ast = ast::Fn; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for Const { type Ast = ast::Const; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for Static { type Ast = ast::Static; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for Trait { type Ast = ast::Trait; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for TypeAlias { type Ast = ast::TypeAlias; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for MacroDef { type Ast = ast::Macro; - fn source(self, db: &dyn HirDatabase) -> InFile { - InFile { - file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, - value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), - } + fn source(self, db: &dyn HirDatabase) -> Option> { + let ast_id = self.id.ast_id?; + Some(InFile { file_id: ast_id.file_id, value: ast_id.to_node(db.upcast()) }) } } impl HasSource for Impl { type Ast = ast::Impl; - fn source(self, db: &dyn HirDatabase) -> InFile { - self.id.lookup(db.upcast()).source(db.upcast()) + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for TypeParam { type Ast = Either; - fn source(self, db: &dyn HirDatabase) -> InFile { + fn source(self, db: &dyn HirDatabase) -> Option> { 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 { type Ast = ast::LifetimeParam; - fn source(self, db: &dyn HirDatabase) -> InFile { + fn source(self, db: &dyn HirDatabase) -> Option> { 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 { type Ast = ast::ConstParam; - fn source(self, db: &dyn HirDatabase) -> InFile { + fn source(self, db: &dyn HirDatabase) -> Option> { 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())) } } diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs index 60e0cd4addfe..3c2d39f5dfb8 100644 --- a/crates/ide/src/call_hierarchy.rs +++ b/crates/ide/src/call_hierarchy.rs @@ -8,7 +8,7 @@ use ide_db::RootDatabase; use syntax::{ast, match_ast, AstNode, TextRange}; use crate::{ - display::ToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, + display::TryToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, }; #[derive(Debug, Clone)] @@ -61,7 +61,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio match node { ast::Fn(it) => { let def = sema.to_def(&it)?; - Some(def.to_nav(sema.db)) + def.try_to_nav(sema.db) }, _ => None, } @@ -99,7 +99,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio match callable.kind() { hir::CallableKind::Function(it) => { let fn_def: hir::Function = it.into(); - let nav = fn_def.to_nav(db); + let nav = fn_def.try_to_nav(db)?; Some(nav) } _ => None, @@ -107,7 +107,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio } FnCallNode::MethodCallExpr(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())) diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index d79f5c170064..ec0f840e9d72 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs @@ -156,20 +156,23 @@ fn missing_record_expr_field_fix( let record_fields = match VariantDef::from(def_id) { VariantDef::Struct(s) => { 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; let fields = source.value.field_list()?; record_field_list(fields)? } VariantDef::Union(u) => { 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; source.value.record_field_list()? } VariantDef::Variant(e) => { 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; let fields = source.value.field_list()?; record_field_list(fields)? diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index bcde2b6f125a..e24c78301767 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs @@ -210,41 +210,32 @@ impl ToNav for FileSymbol { impl TryToNav for Definition { fn try_to_nav(&self, db: &RootDatabase) -> Option { match self { - Definition::Macro(it) => { - // 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 it.is_proc_macro() { - return None; - } - Some(it.to_nav(db)) - } - Definition::Field(it) => Some(it.to_nav(db)), + Definition::Macro(it) => it.try_to_nav(db), + Definition::Field(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::TypeParam(it) => Some(it.to_nav(db)), - Definition::LifetimeParam(it) => Some(it.to_nav(db)), + Definition::TypeParam(it) => it.try_to_nav(db), + Definition::LifetimeParam(it) => it.try_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 { fn try_to_nav(&self, db: &RootDatabase) -> Option { - let res = match self { - hir::ModuleDef::Module(it) => it.to_nav(db), - hir::ModuleDef::Function(it) => it.to_nav(db), - hir::ModuleDef::Adt(it) => it.to_nav(db), - hir::ModuleDef::Variant(it) => it.to_nav(db), - hir::ModuleDef::Const(it) => it.to_nav(db), - hir::ModuleDef::Static(it) => it.to_nav(db), - hir::ModuleDef::Trait(it) => it.to_nav(db), - hir::ModuleDef::TypeAlias(it) => it.to_nav(db), - hir::ModuleDef::BuiltinType(_) => return None, - }; - Some(res) + match self { + hir::ModuleDef::Module(it) => Some(it.to_nav(db)), + hir::ModuleDef::Function(it) => it.try_to_nav(db), + hir::ModuleDef::Adt(it) => it.try_to_nav(db), + hir::ModuleDef::Variant(it) => it.try_to_nav(db), + hir::ModuleDef::Const(it) => it.try_to_nav(db), + hir::ModuleDef::Static(it) => it.try_to_nav(db), + hir::ModuleDef::Trait(it) => it.try_to_nav(db), + hir::ModuleDef::TypeAlias(it) => it.try_to_nav(db), + hir::ModuleDef::BuiltinType(_) => None, + } } } @@ -279,13 +270,13 @@ impl ToNavFromAst for hir::Trait { const KIND: SymbolKind = SymbolKind::Trait; } -impl ToNav for D +impl TryToNav for D where D: HasSource + ToNavFromAst + Copy + HasAttrs, D::Ast: ast::NameOwner + ShortLabel, { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { - let src = self.source(db); + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; let mut res = NavigationTarget::from_named( db, src.as_ref().map(|it| it as &dyn ast::NameOwner), @@ -293,7 +284,7 @@ where ); res.docs = self.docs(db); res.description = src.value.short_label(); - res + Some(res) } } @@ -312,9 +303,9 @@ impl ToNav for hir::Module { } } -impl ToNav for hir::Impl { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { - let src = self.source(db); +impl TryToNav for hir::Impl { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; let derive_attr = self.is_builtin_derive(db); let frange = if let Some(item) = &derive_attr { 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) }; - NavigationTarget::from_syntax( + Some(NavigationTarget::from_syntax( frange.file_id, "impl".into(), focus_range, frange.range, SymbolKind::Impl, - ) + )) } } -impl ToNav for hir::Field { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { - let src = self.source(db); +impl TryToNav for hir::Field { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; - match &src.value { + let field_source = match &src.value { FieldSource::Named(it) => { let mut res = NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); @@ -359,13 +350,14 @@ impl ToNav for hir::Field { SymbolKind::Field, ) } - } + }; + Some(field_source) } } -impl ToNav for hir::MacroDef { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { - let src = self.source(db); +impl TryToNav for hir::MacroDef { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; log::debug!("nav target {:#?}", src.value.syntax()); let mut res = NavigationTarget::from_named( db, @@ -373,26 +365,26 @@ impl ToNav for hir::MacroDef { SymbolKind::Macro, ); res.docs = self.docs(db); - res + Some(res) } } -impl ToNav for hir::Adt { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { +impl TryToNav for hir::Adt { + fn try_to_nav(&self, db: &RootDatabase) -> Option { match self { - hir::Adt::Struct(it) => it.to_nav(db), - hir::Adt::Union(it) => it.to_nav(db), - hir::Adt::Enum(it) => it.to_nav(db), + hir::Adt::Struct(it) => it.try_to_nav(db), + hir::Adt::Union(it) => it.try_to_nav(db), + hir::Adt::Enum(it) => it.try_to_nav(db), } } } -impl ToNav for hir::AssocItem { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { +impl TryToNav for hir::AssocItem { + fn try_to_nav(&self, db: &RootDatabase) -> Option { match self { - AssocItem::Function(it) => it.to_nav(db), - AssocItem::Const(it) => it.to_nav(db), - AssocItem::TypeAlias(it) => it.to_nav(db), + AssocItem::Function(it) => it.try_to_nav(db), + AssocItem::Const(it) => it.try_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 { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { - let src = self.source(db); +impl TryToNav for hir::TypeParam { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; let full_range = match &src.value { Either::Left(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::Right(it) => it.name().map(|it| it.syntax().text_range()), }; - NavigationTarget { + Some(NavigationTarget { file_id: src.file_id.original_file(db), name: self.name(db).to_string().into(), kind: Some(SymbolKind::TypeParam), @@ -466,15 +458,15 @@ impl ToNav for hir::TypeParam { container_name: None, description: None, docs: None, - } + }) } } -impl ToNav for hir::LifetimeParam { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { - let src = self.source(db); +impl TryToNav for hir::LifetimeParam { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; let full_range = src.value.syntax().text_range(); - NavigationTarget { + Some(NavigationTarget { file_id: src.file_id.original_file(db), name: self.name(db).to_string().into(), kind: Some(SymbolKind::LifetimeParam), @@ -483,15 +475,15 @@ impl ToNav for hir::LifetimeParam { container_name: None, description: None, docs: None, - } + }) } } -impl ToNav for hir::ConstParam { - fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { - let src = self.source(db); +impl TryToNav for hir::ConstParam { + fn try_to_nav(&self, db: &RootDatabase) -> Option { + let src = self.source(db)?; let full_range = src.value.syntax().text_range(); - NavigationTarget { + Some(NavigationTarget { file_id: src.file_id.original_file(db), name: self.name(db).to_string().into(), kind: Some(SymbolKind::ConstParam), @@ -500,7 +492,7 @@ impl ToNav for hir::ConstParam { container_name: None, description: None, docs: None, - } + }) } } diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index 6eac39639251..da9378a97e63 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs @@ -2,7 +2,7 @@ use hir::{Crate, Impl, Semantics}; use ide_db::RootDatabase; 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 // @@ -55,7 +55,7 @@ fn impls_for_def( impls .into_iter() .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(), ) } @@ -69,7 +69,7 @@ fn impls_for_trait( 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)] diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index aba6bf5dc262..7e84e06bea4d 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs @@ -1,7 +1,7 @@ use ide_db::RootDatabase; 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 // @@ -37,7 +37,7 @@ pub(crate) fn goto_type_definition( 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])) } diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 98c7bfbe51bc..2737c900f4c9 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -13,7 +13,7 @@ use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, use test_utils::mark; use crate::{ - display::{macro_label, ShortLabel, ToNav, TryToNav}, + display::{macro_label, ShortLabel, TryToNav}, doc_links::{remove_links, rewrite_links}, markdown_remove::remove_markdown, markup::Markup, @@ -183,10 +183,10 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option match it { - ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.to_nav(db))), - ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.to_nav(db))), - ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.to_nav(db))), - ModuleDef::Trait(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.try_to_nav(db)?)), + ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.try_to_nav(db)?)), + ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)), _ => None, }, _ => None, @@ -206,7 +206,8 @@ fn runnable_action( _ => None, }, ModuleDef::Function(it) => { - let src = it.source(sema.db); + #[allow(deprecated)] + let src = it.source(sema.db)?; if src.file_id != file_id.into() { mark::hit!(hover_macro_generated_struct_fn_doc_comment); mark::hit!(hover_macro_generated_struct_fn_doc_attr); @@ -326,17 +327,12 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option { let mod_path = definition_mod_path(db, &def); return match def { Definition::Macro(it) => { - // 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 it.is_proc_macro() { - return None; - } - let label = macro_label(&it.source(db).value); + let label = macro_label(&it.source(db)?.value); from_def_source_labeled(db, it, Some(label), mod_path) } Definition::Field(def) => { - let src = def.source(db).value; + #[allow(deprecated)] + let src = def.source(db)?.value; if let FieldSource::Named(it) = src { from_def_source_labeled(db, def, it.short_label(), mod_path) } else { @@ -385,7 +381,8 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option { D: HasSource + HasAttrs + Copy, 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) } diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index ff10f71c358a..436c59d2c7bf 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs @@ -121,31 +121,56 @@ impl Definition { if let Definition::Local(var) = self { let range = match var.parent(db) { - DefWithBody::Function(f) => f.source(db).value.syntax().text_range(), - DefWithBody::Const(c) => c.source(db).value.syntax().text_range(), - DefWithBody::Static(s) => s.source(db).value.syntax().text_range(), + DefWithBody::Function(f) => { + f.source(db).and_then(|src| Some(src.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(); - res.insert(file_id, Some(range)); + res.insert(file_id, range); return SearchScope::new(res); } if let Definition::LifetimeParam(param) = self { + #[allow(deprecated)] 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::Adt::Struct(it) => it.source(db).value.syntax().text_range(), - hir::Adt::Union(it) => it.source(db).value.syntax().text_range(), - hir::Adt::Enum(it) => it.source(db).value.syntax().text_range(), + hir::Adt::Struct(it) => { + it.source(db).and_then(|src| Some(src.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::TypeAlias(it) => it.source(db).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::Const(it) => it.source(db).value.syntax().text_range(), + hir::GenericDef::Trait(it) => { + it.source(db).and_then(|src| Some(src.value.syntax().text_range())) + } + hir::GenericDef::TypeAlias(it) => { + 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(); - res.insert(file_id, Some(range)); + res.insert(file_id, range); return SearchScope::new(res); } diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index a23fb7a33a41..9445aec074d4 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -161,11 +161,12 @@ impl AnalysisStatsCmd { } let mut msg = format!("processing: {}", full_name); if verbosity.is_verbose() { - let src = f.source(db); - let original_file = src.file_id.original_file(db); - let path = vfs.file_path(original_file); - let syntax_range = src.value.syntax().text_range(); - format_to!(msg, " ({} {:?})", path, syntax_range); + if let Some(src) = f.source(db) { + let original_file = src.file_id.original_file(db); + let path = vfs.file_path(original_file); + let syntax_range = src.value.syntax().text_range(); + format_to!(msg, " ({} {:?})", path, syntax_range); + } } if verbosity.is_spammy() { bar.println(msg.to_string());