From 8198e13c26fe985af5893af7bdac04041880b461 Mon Sep 17 00:00:00 2001 From: Lenard Pratt Date: Wed, 24 Apr 2019 21:16:50 +0100 Subject: [PATCH] Added local macro goto --- crates/ra_hir/src/lib.rs | 4 +- crates/ra_hir/src/source_binder.rs | 43 +++++++++++++++++-- .../src/completion/completion_item.rs | 1 + .../src/display/navigation_target.rs | 10 +++++ crates/ra_ide_api/src/goto_definition.rs | 40 +++++++++++++++++ crates/ra_ide_api/src/marks.rs | 1 + crates/ra_lsp_server/src/conv.rs | 1 + crates/ra_syntax/src/ast/generated.rs | 1 + crates/ra_syntax/src/grammar.ron | 2 +- 9 files changed, 97 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 4411715dea..03b1063b69 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -69,7 +69,7 @@ pub use self::{ expr::ExprScopes, resolve::Resolution, generics::{GenericParams, GenericParam, HasGenericParams}, - source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax}, + source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax,MacroByExampleDef}, }; pub use self::code_model_api::{ @@ -80,5 +80,5 @@ pub use self::code_model_api::{ Function, FnSignature, StructField, FieldSource, Static, Const, ConstSignature, - Trait, TypeAlias, Container, + Trait, TypeAlias, Container }; diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 2959e3eca2..06d99351ed 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use rustc_hash::{FxHashSet, FxHashMap}; use ra_db::{FileId, FilePosition}; use ra_syntax::{ - SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, TextRange, + SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, TextRange,TreeArc, ast::{self, AstNode, NameOwner}, algo::find_node_at_offset, SyntaxKind::*, @@ -18,9 +18,10 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, - AsName, Module, HirFileId, Crate, Trait, Resolver, Ty, + AsName, Module, HirFileId, Crate, Trait, Resolver, Ty,Path, expr::{BodySourceMap, scope::{ScopeId, ExprScopes}}, - ids::LocationCtx, + ids::{LocationCtx,MacroCallId}, + docs::{docs_from_ast,Documentation}, expr, AstId, }; @@ -184,9 +185,28 @@ pub enum PathResolution { /// A generic parameter GenericParam(u32), SelfType(crate::ImplBlock), + Macro(MacroByExampleDef), AssocItem(crate::ImplItem), } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct MacroByExampleDef { + pub(crate) id: MacroCallId, +} + +impl MacroByExampleDef { + pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { + let loc = self.id.loc(db); + (self.id.into(), loc.def.0.to_node(db)) + } +} + +impl crate::Docs for MacroByExampleDef { + fn docs(&self, db: &impl HirDatabase) -> Option { + docs_from_ast(&*self.source(db).1) + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScopeEntryWithSyntax { pub(crate) name: Name, @@ -264,6 +284,23 @@ impl SourceAnalyzer { self.infer.as_ref()?.field_resolution(expr_id) } + pub fn resolve_macro_call( + &self, + db: &impl HirDatabase, + file_id: FileId, + macro_call: &ast::MacroCall, + ) -> Option { + let hir_id = file_id.into(); + let ast_id = db.ast_id_map(hir_id).ast_id(macro_call).with_file_id(hir_id); + let call_id = self.resolver.resolve_macro_call( + db, + macro_call.path().and_then(Path::from_ast), + ast_id, + ); + + call_id.map(|id| MacroByExampleDef { id }) + } + pub fn resolve_hir_path( &self, db: &impl HirDatabase, diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index f515fcc14f..6f1392231f 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -89,6 +89,7 @@ pub enum CompletionItemKind { TypeAlias, Method, TypeParam, + Macro, } #[derive(Debug, PartialEq, Eq, Copy, Clone)] diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index 84645287d7..765cf883be 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -213,6 +213,15 @@ impl NavigationTarget { } } + pub(crate) fn from_macro_def( + db: &RootDatabase, + macro_call: hir::MacroByExampleDef, + ) -> NavigationTarget { + let (file_id, node) = macro_call.source(db); + log::debug!("nav target {}", node.syntax().debug_dump()); + NavigationTarget::from_named(file_id.original_file(db), &*node) + } + #[cfg(test)] pub(crate) fn assert_match(&self, expected: &str) { let actual = self.debug_render(); @@ -289,6 +298,7 @@ impl NavigationTarget { .visit(doc_comments::) .visit(doc_comments::) .visit(doc_comments::) + .visit(doc_comments::) .accept(&node)? } diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 163781f88a..533c229fee 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -59,6 +59,21 @@ pub(crate) fn reference_definition( return Exact(NavigationTarget::from_function(db, func)); } } + + //it could be a macro call + if let Some(macro_call) = name_ref + .syntax() + .parent() + .and_then(|node| node.parent()) + .and_then(|node| node.parent()) + .and_then(ast::MacroCall::cast) + { + tested_by!(goto_definition_works_for_macros); + if let Some(macro_call) = analyzer.resolve_macro_call(db, file_id, macro_call) { + return Exact(NavigationTarget::from_macro_def(db, macro_call)); + } + } + // It could also be a field access if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast) { tested_by!(goto_definition_works_for_fields); @@ -97,6 +112,10 @@ pub(crate) fn reference_definition( hir::PathResolution::GenericParam(..) => { // FIXME: go to the generic param def } + hir::PathResolution::Macro(def) => { + let nav = NavigationTarget::from_macro_def(db, def); + return Exact(nav); + } hir::PathResolution::SelfType(impl_block) => { let ty = impl_block.target_ty(db); @@ -156,6 +175,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option .visit(|node: &ast::TraitDef| NavigationTarget::from_named(file_id, node)) .visit(|node: &ast::NamedFieldDef| NavigationTarget::from_named(file_id, node)) .visit(|node: &ast::Module| NavigationTarget::from_named(file_id, node)) + .visit(|node: &ast::MacroCall| NavigationTarget::from_named(file_id, node)) .accept(node) } @@ -227,6 +247,26 @@ mod tests { ); } + #[test] + fn goto_definition_works_for_macros() { + covers!(goto_definition_works_for_macros); + check_goto( + " + //- /lib.rs + macro_rules! foo { + () => { + {} + }; + } + + fn bar() { + <|>foo!(); + } + ", + "foo MACRO_CALL FileId(1) [0; 50) [13; 16)", + ); + } + #[test] fn goto_definition_works_for_methods() { covers!(goto_definition_works_for_methods); diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs index bcbe0d21b5..cc894a7df3 100644 --- a/crates/ra_ide_api/src/marks.rs +++ b/crates/ra_ide_api/src/marks.rs @@ -1,5 +1,6 @@ test_utils::marks!( inserts_parens_for_function_calls + goto_definition_works_for_macros goto_definition_works_for_methods goto_definition_works_for_fields goto_definition_works_for_named_fields diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 4d6ede316c..50a12ddbc2 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -73,6 +73,7 @@ impl Conv for CompletionItemKind { CompletionItemKind::Static => Value, CompletionItemKind::Method => Method, CompletionItemKind::TypeParam => TypeParameter, + CompletionItemKind::Macro => Method, } } } diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index fae371509f..e373b3fa42 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1761,6 +1761,7 @@ impl ToOwned for MacroCall { impl ast::NameOwner for MacroCall {} impl ast::AttrsOwner for MacroCall {} +impl ast::DocCommentsOwner for MacroCall {} impl MacroCall { pub fn token_tree(&self) -> Option<&TokenTree> { super::child_opt(self) diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 5bdcf9c84b..01778ed460 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -552,7 +552,7 @@ Grammar( "Name": (), "NameRef": (), "MacroCall": ( - traits: [ "NameOwner", "AttrsOwner" ], + traits: [ "NameOwner", "AttrsOwner","DocCommentsOwner" ], options: [ "TokenTree", "Path" ], ), "Attr": ( options: [ ["value", "TokenTree"] ] ),