aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLenard Pratt <[email protected]>2019-04-24 21:16:50 +0100
committerLenard Pratt <[email protected]>2019-05-04 17:39:51 +0100
commit8198e13c26fe985af5893af7bdac04041880b461 (patch)
treed38470089855571fed08974c6cf3d57b80f3084f
parent12629d5e4f2d949eedb707dedad4d75eff09e683 (diff)
Added local macro goto
-rw-r--r--crates/ra_hir/src/lib.rs4
-rw-r--r--crates/ra_hir/src/source_binder.rs43
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs1
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs10
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs40
-rw-r--r--crates/ra_ide_api/src/marks.rs1
-rw-r--r--crates/ra_lsp_server/src/conv.rs1
-rw-r--r--crates/ra_syntax/src/ast/generated.rs1
-rw-r--r--crates/ra_syntax/src/grammar.ron2
9 files changed, 97 insertions, 6 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 4411715de..03b1063b6 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -69,7 +69,7 @@ pub use self::{
69 expr::ExprScopes, 69 expr::ExprScopes,
70 resolve::Resolution, 70 resolve::Resolution,
71 generics::{GenericParams, GenericParam, HasGenericParams}, 71 generics::{GenericParams, GenericParam, HasGenericParams},
72 source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax}, 72 source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax,MacroByExampleDef},
73}; 73};
74 74
75pub use self::code_model_api::{ 75pub use self::code_model_api::{
@@ -80,5 +80,5 @@ pub use self::code_model_api::{
80 Function, FnSignature, 80 Function, FnSignature,
81 StructField, FieldSource, 81 StructField, FieldSource,
82 Static, Const, ConstSignature, 82 Static, Const, ConstSignature,
83 Trait, TypeAlias, Container, 83 Trait, TypeAlias, Container
84}; 84};
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 2959e3eca..06d99351e 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;
10use rustc_hash::{FxHashSet, FxHashMap}; 10use rustc_hash::{FxHashSet, FxHashMap};
11use ra_db::{FileId, FilePosition}; 11use ra_db::{FileId, FilePosition};
12use ra_syntax::{ 12use ra_syntax::{
13 SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, TextRange, 13 SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, TextRange,TreeArc,
14 ast::{self, AstNode, NameOwner}, 14 ast::{self, AstNode, NameOwner},
15 algo::find_node_at_offset, 15 algo::find_node_at_offset,
16 SyntaxKind::*, 16 SyntaxKind::*,
@@ -18,9 +18,10 @@ use ra_syntax::{
18 18
19use crate::{ 19use crate::{
20 HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, 20 HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name,
21 AsName, Module, HirFileId, Crate, Trait, Resolver, Ty, 21 AsName, Module, HirFileId, Crate, Trait, Resolver, Ty,Path,
22 expr::{BodySourceMap, scope::{ScopeId, ExprScopes}}, 22 expr::{BodySourceMap, scope::{ScopeId, ExprScopes}},
23 ids::LocationCtx, 23 ids::{LocationCtx,MacroCallId},
24 docs::{docs_from_ast,Documentation},
24 expr, AstId, 25 expr, AstId,
25}; 26};
26 27
@@ -184,9 +185,28 @@ pub enum PathResolution {
184 /// A generic parameter 185 /// A generic parameter
185 GenericParam(u32), 186 GenericParam(u32),
186 SelfType(crate::ImplBlock), 187 SelfType(crate::ImplBlock),
188 Macro(MacroByExampleDef),
187 AssocItem(crate::ImplItem), 189 AssocItem(crate::ImplItem),
188} 190}
189 191
192#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
193pub struct MacroByExampleDef {
194 pub(crate) id: MacroCallId,
195}
196
197impl MacroByExampleDef {
198 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::MacroCall>) {
199 let loc = self.id.loc(db);
200 (self.id.into(), loc.def.0.to_node(db))
201 }
202}
203
204impl crate::Docs for MacroByExampleDef {
205 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
206 docs_from_ast(&*self.source(db).1)
207 }
208}
209
190#[derive(Debug, Clone, PartialEq, Eq)] 210#[derive(Debug, Clone, PartialEq, Eq)]
191pub struct ScopeEntryWithSyntax { 211pub struct ScopeEntryWithSyntax {
192 pub(crate) name: Name, 212 pub(crate) name: Name,
@@ -264,6 +284,23 @@ impl SourceAnalyzer {
264 self.infer.as_ref()?.field_resolution(expr_id) 284 self.infer.as_ref()?.field_resolution(expr_id)
265 } 285 }
266 286
287 pub fn resolve_macro_call(
288 &self,
289 db: &impl HirDatabase,
290 file_id: FileId,
291 macro_call: &ast::MacroCall,
292 ) -> Option<MacroByExampleDef> {
293 let hir_id = file_id.into();
294 let ast_id = db.ast_id_map(hir_id).ast_id(macro_call).with_file_id(hir_id);
295 let call_id = self.resolver.resolve_macro_call(
296 db,
297 macro_call.path().and_then(Path::from_ast),
298 ast_id,
299 );
300
301 call_id.map(|id| MacroByExampleDef { id })
302 }
303
267 pub fn resolve_hir_path( 304 pub fn resolve_hir_path(
268 &self, 305 &self,
269 db: &impl HirDatabase, 306 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 f515fcc14..6f1392231 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 {
89 TypeAlias, 89 TypeAlias,
90 Method, 90 Method,
91 TypeParam, 91 TypeParam,
92 Macro,
92} 93}
93 94
94#[derive(Debug, PartialEq, Eq, Copy, Clone)] 95#[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 84645287d..765cf883b 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 {
213 } 213 }
214 } 214 }
215 215
216 pub(crate) fn from_macro_def(
217 db: &RootDatabase,
218 macro_call: hir::MacroByExampleDef,
219 ) -> NavigationTarget {
220 let (file_id, node) = macro_call.source(db);
221 log::debug!("nav target {}", node.syntax().debug_dump());
222 NavigationTarget::from_named(file_id.original_file(db), &*node)
223 }
224
216 #[cfg(test)] 225 #[cfg(test)]
217 pub(crate) fn assert_match(&self, expected: &str) { 226 pub(crate) fn assert_match(&self, expected: &str) {
218 let actual = self.debug_render(); 227 let actual = self.debug_render();
@@ -289,6 +298,7 @@ impl NavigationTarget {
289 .visit(doc_comments::<ast::StaticDef>) 298 .visit(doc_comments::<ast::StaticDef>)
290 .visit(doc_comments::<ast::NamedFieldDef>) 299 .visit(doc_comments::<ast::NamedFieldDef>)
291 .visit(doc_comments::<ast::EnumVariant>) 300 .visit(doc_comments::<ast::EnumVariant>)
301 .visit(doc_comments::<ast::MacroCall>)
292 .accept(&node)? 302 .accept(&node)?
293 } 303 }
294 304
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 163781f88..533c229fe 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(
59 return Exact(NavigationTarget::from_function(db, func)); 59 return Exact(NavigationTarget::from_function(db, func));
60 } 60 }
61 } 61 }
62
63 //it could be a macro call
64 if let Some(macro_call) = name_ref
65 .syntax()
66 .parent()
67 .and_then(|node| node.parent())
68 .and_then(|node| node.parent())
69 .and_then(ast::MacroCall::cast)
70 {
71 tested_by!(goto_definition_works_for_macros);
72 if let Some(macro_call) = analyzer.resolve_macro_call(db, file_id, macro_call) {
73 return Exact(NavigationTarget::from_macro_def(db, macro_call));
74 }
75 }
76
62 // It could also be a field access 77 // It could also be a field access
63 if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast) { 78 if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast) {
64 tested_by!(goto_definition_works_for_fields); 79 tested_by!(goto_definition_works_for_fields);
@@ -97,6 +112,10 @@ pub(crate) fn reference_definition(
97 hir::PathResolution::GenericParam(..) => { 112 hir::PathResolution::GenericParam(..) => {
98 // FIXME: go to the generic param def 113 // FIXME: go to the generic param def
99 } 114 }
115 hir::PathResolution::Macro(def) => {
116 let nav = NavigationTarget::from_macro_def(db, def);
117 return Exact(nav);
118 }
100 hir::PathResolution::SelfType(impl_block) => { 119 hir::PathResolution::SelfType(impl_block) => {
101 let ty = impl_block.target_ty(db); 120 let ty = impl_block.target_ty(db);
102 121
@@ -156,6 +175,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget>
156 .visit(|node: &ast::TraitDef| NavigationTarget::from_named(file_id, node)) 175 .visit(|node: &ast::TraitDef| NavigationTarget::from_named(file_id, node))
157 .visit(|node: &ast::NamedFieldDef| NavigationTarget::from_named(file_id, node)) 176 .visit(|node: &ast::NamedFieldDef| NavigationTarget::from_named(file_id, node))
158 .visit(|node: &ast::Module| NavigationTarget::from_named(file_id, node)) 177 .visit(|node: &ast::Module| NavigationTarget::from_named(file_id, node))
178 .visit(|node: &ast::MacroCall| NavigationTarget::from_named(file_id, node))
159 .accept(node) 179 .accept(node)
160} 180}
161 181
@@ -228,6 +248,26 @@ mod tests {
228 } 248 }
229 249
230 #[test] 250 #[test]
251 fn goto_definition_works_for_macros() {
252 covers!(goto_definition_works_for_macros);
253 check_goto(
254 "
255 //- /lib.rs
256 macro_rules! foo {
257 () => {
258 {}
259 };
260 }
261
262 fn bar() {
263 <|>foo!();
264 }
265 ",
266 "foo MACRO_CALL FileId(1) [0; 50) [13; 16)",
267 );
268 }
269
270 #[test]
231 fn goto_definition_works_for_methods() { 271 fn goto_definition_works_for_methods() {
232 covers!(goto_definition_works_for_methods); 272 covers!(goto_definition_works_for_methods);
233 check_goto( 273 check_goto(
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs
index bcbe0d21b..cc894a7df 100644
--- a/crates/ra_ide_api/src/marks.rs
+++ b/crates/ra_ide_api/src/marks.rs
@@ -1,5 +1,6 @@
1test_utils::marks!( 1test_utils::marks!(
2 inserts_parens_for_function_calls 2 inserts_parens_for_function_calls
3 goto_definition_works_for_macros
3 goto_definition_works_for_methods 4 goto_definition_works_for_methods
4 goto_definition_works_for_fields 5 goto_definition_works_for_fields
5 goto_definition_works_for_named_fields 6 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 4d6ede316..50a12ddbc 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 {
73 CompletionItemKind::Static => Value, 73 CompletionItemKind::Static => Value,
74 CompletionItemKind::Method => Method, 74 CompletionItemKind::Method => Method,
75 CompletionItemKind::TypeParam => TypeParameter, 75 CompletionItemKind::TypeParam => TypeParameter,
76 CompletionItemKind::Macro => Method,
76 } 77 }
77 } 78 }
78} 79}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index fae371509..e373b3fa4 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 {
1761 1761
1762impl ast::NameOwner for MacroCall {} 1762impl ast::NameOwner for MacroCall {}
1763impl ast::AttrsOwner for MacroCall {} 1763impl ast::AttrsOwner for MacroCall {}
1764impl ast::DocCommentsOwner for MacroCall {}
1764impl MacroCall { 1765impl MacroCall {
1765 pub fn token_tree(&self) -> Option<&TokenTree> { 1766 pub fn token_tree(&self) -> Option<&TokenTree> {
1766 super::child_opt(self) 1767 super::child_opt(self)
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 5bdcf9c84..01778ed46 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -552,7 +552,7 @@ Grammar(
552 "Name": (), 552 "Name": (),
553 "NameRef": (), 553 "NameRef": (),
554 "MacroCall": ( 554 "MacroCall": (
555 traits: [ "NameOwner", "AttrsOwner" ], 555 traits: [ "NameOwner", "AttrsOwner","DocCommentsOwner" ],
556 options: [ "TokenTree", "Path" ], 556 options: [ "TokenTree", "Path" ],
557 ), 557 ),
558 "Attr": ( options: [ ["value", "TokenTree"] ] ), 558 "Attr": ( options: [ ["value", "TokenTree"] ] ),