diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/change.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_context.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 115 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_type_definition.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide_api/src/inlay_hints.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/classify.rs | 46 | ||||
-rw-r--r-- | crates/ra_ide_api/src/runnables.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/syntax_highlighting.rs | 5 |
11 files changed, 149 insertions, 78 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 3572825b5..41ee81511 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -19,7 +19,11 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
19 | let calling_node = FnCallNode::with_node(&syntax, position.offset)?; | 19 | let calling_node = FnCallNode::with_node(&syntax, position.offset)?; |
20 | let name_ref = calling_node.name_ref()?; | 20 | let name_ref = calling_node.name_ref()?; |
21 | 21 | ||
22 | let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None); | 22 | let analyzer = hir::SourceAnalyzer::new( |
23 | db, | ||
24 | hir::Source::new(position.file_id.into(), name_ref.syntax()), | ||
25 | None, | ||
26 | ); | ||
23 | let (mut call_info, has_self) = match &calling_node { | 27 | let (mut call_info, has_self) = match &calling_node { |
24 | FnCallNode::CallExpr(expr) => { | 28 | FnCallNode::CallExpr(expr) => { |
25 | //FIXME: apply subst | 29 | //FIXME: apply subst |
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs index 010b45141..5c9dec13e 100644 --- a/crates/ra_ide_api/src/change.rs +++ b/crates/ra_ide_api/src/change.rs | |||
@@ -271,7 +271,6 @@ impl RootDatabase { | |||
271 | self.query(hir::db::AstIdMapQuery).sweep(sweep); | 271 | self.query(hir::db::AstIdMapQuery).sweep(sweep); |
272 | 272 | ||
273 | self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); | 273 | self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); |
274 | self.query(hir::db::ImplsInModuleWithSourceMapQuery).sweep(sweep); | ||
275 | self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); | 274 | self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); |
276 | 275 | ||
277 | self.query(hir::db::ExprScopesQuery).sweep(sweep); | 276 | self.query(hir::db::ExprScopesQuery).sweep(sweep); |
@@ -314,8 +313,6 @@ impl RootDatabase { | |||
314 | hir::db::RawItemsWithSourceMapQuery | 313 | hir::db::RawItemsWithSourceMapQuery |
315 | hir::db::RawItemsQuery | 314 | hir::db::RawItemsQuery |
316 | hir::db::CrateDefMapQuery | 315 | hir::db::CrateDefMapQuery |
317 | hir::db::ImplsInModuleWithSourceMapQuery | ||
318 | hir::db::ImplsInModuleQuery | ||
319 | hir::db::GenericParamsQuery | 316 | hir::db::GenericParamsQuery |
320 | hir::db::FnDataQuery | 317 | hir::db::FnDataQuery |
321 | hir::db::TypeAliasDataQuery | 318 | hir::db::TypeAliasDataQuery |
@@ -340,6 +337,7 @@ impl RootDatabase { | |||
340 | hir::db::TraitDatumQuery | 337 | hir::db::TraitDatumQuery |
341 | hir::db::StructDatumQuery | 338 | hir::db::StructDatumQuery |
342 | hir::db::ImplDatumQuery | 339 | hir::db::ImplDatumQuery |
340 | hir::db::ImplDataQuery | ||
343 | hir::db::TraitSolveQuery | 341 | hir::db::TraitSolveQuery |
344 | ]; | 342 | ]; |
345 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); | 343 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); |
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 64cbc0f98..0906a4e1b 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs | |||
@@ -58,8 +58,11 @@ impl<'a> CompletionContext<'a> { | |||
58 | ); | 58 | ); |
59 | let token = | 59 | let token = |
60 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; | 60 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; |
61 | let analyzer = | 61 | let analyzer = hir::SourceAnalyzer::new( |
62 | hir::SourceAnalyzer::new(db, position.file_id, &token.parent(), Some(position.offset)); | 62 | db, |
63 | hir::Source::new(position.file_id.into(), &token.parent()), | ||
64 | Some(position.offset), | ||
65 | ); | ||
63 | let mut ctx = CompletionContext { | 66 | let mut ctx = CompletionContext { |
64 | db, | 67 | db, |
65 | analyzer, | 68 | analyzer, |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 6c8387f6c..b693a4c31 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_db::{FileId, SourceDatabase}; | 3 | use std::iter::successors; |
4 | |||
5 | use hir::{db::AstDatabase, Source}; | ||
4 | use ra_syntax::{ | 6 | use ra_syntax::{ |
5 | algo::find_node_at_offset, | ||
6 | ast::{self, DocCommentsOwner}, | 7 | ast::{self, DocCommentsOwner}, |
7 | match_ast, AstNode, SyntaxNode, | 8 | match_ast, AstNode, SyntaxNode, SyntaxToken, |
8 | }; | 9 | }; |
9 | 10 | ||
10 | use crate::{ | 11 | use crate::{ |
@@ -18,17 +19,42 @@ pub(crate) fn goto_definition( | |||
18 | db: &RootDatabase, | 19 | db: &RootDatabase, |
19 | position: FilePosition, | 20 | position: FilePosition, |
20 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { | 21 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
21 | let parse = db.parse(position.file_id); | 22 | let token = descend_into_macros(db, position)?; |
22 | let syntax = parse.tree().syntax().clone(); | 23 | |
23 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, position.offset) { | 24 | let res = match_ast! { |
24 | let navs = reference_definition(db, position.file_id, &name_ref).to_vec(); | 25 | match (token.ast.parent()) { |
25 | return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); | 26 | ast::NameRef(name_ref) => { |
26 | } | 27 | let navs = reference_definition(db, token.with_ast(&name_ref)).to_vec(); |
27 | if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) { | 28 | RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()) |
28 | let navs = name_definition(db, position.file_id, &name)?; | 29 | }, |
29 | return Some(RangeInfo::new(name.syntax().text_range(), navs)); | 30 | ast::Name(name) => { |
30 | } | 31 | let navs = name_definition(db, token.with_ast(&name))?; |
31 | None | 32 | RangeInfo::new(name.syntax().text_range(), navs) |
33 | |||
34 | }, | ||
35 | _ => return None, | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | Some(res) | ||
40 | } | ||
41 | |||
42 | fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Option<Source<SyntaxToken>> { | ||
43 | let file = db.parse_or_expand(position.file_id.into())?; | ||
44 | let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; | ||
45 | |||
46 | successors(Some(Source::new(position.file_id.into(), token)), |token| { | ||
47 | let macro_call = token.ast.ancestors().find_map(ast::MacroCall::cast)?; | ||
48 | let tt = macro_call.token_tree()?; | ||
49 | if !token.ast.text_range().is_subrange(&tt.syntax().text_range()) { | ||
50 | return None; | ||
51 | } | ||
52 | let source_analyzer = | ||
53 | hir::SourceAnalyzer::new(db, token.with_ast(token.ast.parent()).as_ref(), None); | ||
54 | let exp = source_analyzer.expand(db, ¯o_call)?; | ||
55 | exp.map_token_down(db, token.as_ref()) | ||
56 | }) | ||
57 | .last() | ||
32 | } | 58 | } |
33 | 59 | ||
34 | #[derive(Debug)] | 60 | #[derive(Debug)] |
@@ -49,12 +75,11 @@ impl ReferenceResult { | |||
49 | 75 | ||
50 | pub(crate) fn reference_definition( | 76 | pub(crate) fn reference_definition( |
51 | db: &RootDatabase, | 77 | db: &RootDatabase, |
52 | file_id: FileId, | 78 | name_ref: Source<&ast::NameRef>, |
53 | name_ref: &ast::NameRef, | ||
54 | ) -> ReferenceResult { | 79 | ) -> ReferenceResult { |
55 | use self::ReferenceResult::*; | 80 | use self::ReferenceResult::*; |
56 | 81 | ||
57 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); | 82 | let name_kind = classify_name_ref(db, name_ref).map(|d| d.kind); |
58 | match name_kind { | 83 | match name_kind { |
59 | Some(Macro(mac)) => return Exact(mac.to_nav(db)), | 84 | Some(Macro(mac)) => return Exact(mac.to_nav(db)), |
60 | Some(Field(field)) => return Exact(field.to_nav(db)), | 85 | Some(Field(field)) => return Exact(field.to_nav(db)), |
@@ -76,7 +101,7 @@ pub(crate) fn reference_definition( | |||
76 | }; | 101 | }; |
77 | 102 | ||
78 | // Fallback index based approach: | 103 | // Fallback index based approach: |
79 | let navs = crate::symbol_index::index_resolve(db, name_ref) | 104 | let navs = crate::symbol_index::index_resolve(db, name_ref.ast) |
80 | .into_iter() | 105 | .into_iter() |
81 | .map(|s| s.to_nav(db)) | 106 | .map(|s| s.to_nav(db)) |
82 | .collect(); | 107 | .collect(); |
@@ -85,14 +110,13 @@ pub(crate) fn reference_definition( | |||
85 | 110 | ||
86 | pub(crate) fn name_definition( | 111 | pub(crate) fn name_definition( |
87 | db: &RootDatabase, | 112 | db: &RootDatabase, |
88 | file_id: FileId, | 113 | name: Source<&ast::Name>, |
89 | name: &ast::Name, | ||
90 | ) -> Option<Vec<NavigationTarget>> { | 114 | ) -> Option<Vec<NavigationTarget>> { |
91 | let parent = name.syntax().parent()?; | 115 | let parent = name.ast.syntax().parent()?; |
92 | 116 | ||
93 | if let Some(module) = ast::Module::cast(parent.clone()) { | 117 | if let Some(module) = ast::Module::cast(parent.clone()) { |
94 | if module.has_semi() { | 118 | if module.has_semi() { |
95 | let src = hir::Source { file_id: file_id.into(), ast: module }; | 119 | let src = name.with_ast(module); |
96 | if let Some(child_module) = hir::Module::from_declaration(db, src) { | 120 | if let Some(child_module) = hir::Module::from_declaration(db, src) { |
97 | let nav = child_module.to_nav(db); | 121 | let nav = child_module.to_nav(db); |
98 | return Some(vec![nav]); | 122 | return Some(vec![nav]); |
@@ -100,20 +124,20 @@ pub(crate) fn name_definition( | |||
100 | } | 124 | } |
101 | } | 125 | } |
102 | 126 | ||
103 | if let Some(nav) = named_target(db, file_id, &parent) { | 127 | if let Some(nav) = named_target(db, name.with_ast(&parent)) { |
104 | return Some(vec![nav]); | 128 | return Some(vec![nav]); |
105 | } | 129 | } |
106 | 130 | ||
107 | None | 131 | None |
108 | } | 132 | } |
109 | 133 | ||
110 | fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget> { | 134 | fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<NavigationTarget> { |
111 | match_ast! { | 135 | match_ast! { |
112 | match node { | 136 | match (node.ast) { |
113 | ast::StructDef(it) => { | 137 | ast::StructDef(it) => { |
114 | Some(NavigationTarget::from_named( | 138 | Some(NavigationTarget::from_named( |
115 | db, | 139 | db, |
116 | file_id.into(), | 140 | node.file_id, |
117 | &it, | 141 | &it, |
118 | it.doc_comment_text(), | 142 | it.doc_comment_text(), |
119 | it.short_label(), | 143 | it.short_label(), |
@@ -122,7 +146,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
122 | ast::EnumDef(it) => { | 146 | ast::EnumDef(it) => { |
123 | Some(NavigationTarget::from_named( | 147 | Some(NavigationTarget::from_named( |
124 | db, | 148 | db, |
125 | file_id.into(), | 149 | node.file_id, |
126 | &it, | 150 | &it, |
127 | it.doc_comment_text(), | 151 | it.doc_comment_text(), |
128 | it.short_label(), | 152 | it.short_label(), |
@@ -131,7 +155,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
131 | ast::EnumVariant(it) => { | 155 | ast::EnumVariant(it) => { |
132 | Some(NavigationTarget::from_named( | 156 | Some(NavigationTarget::from_named( |
133 | db, | 157 | db, |
134 | file_id.into(), | 158 | node.file_id, |
135 | &it, | 159 | &it, |
136 | it.doc_comment_text(), | 160 | it.doc_comment_text(), |
137 | it.short_label(), | 161 | it.short_label(), |
@@ -140,7 +164,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
140 | ast::FnDef(it) => { | 164 | ast::FnDef(it) => { |
141 | Some(NavigationTarget::from_named( | 165 | Some(NavigationTarget::from_named( |
142 | db, | 166 | db, |
143 | file_id.into(), | 167 | node.file_id, |
144 | &it, | 168 | &it, |
145 | it.doc_comment_text(), | 169 | it.doc_comment_text(), |
146 | it.short_label(), | 170 | it.short_label(), |
@@ -149,7 +173,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
149 | ast::TypeAliasDef(it) => { | 173 | ast::TypeAliasDef(it) => { |
150 | Some(NavigationTarget::from_named( | 174 | Some(NavigationTarget::from_named( |
151 | db, | 175 | db, |
152 | file_id.into(), | 176 | node.file_id, |
153 | &it, | 177 | &it, |
154 | it.doc_comment_text(), | 178 | it.doc_comment_text(), |
155 | it.short_label(), | 179 | it.short_label(), |
@@ -158,7 +182,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
158 | ast::ConstDef(it) => { | 182 | ast::ConstDef(it) => { |
159 | Some(NavigationTarget::from_named( | 183 | Some(NavigationTarget::from_named( |
160 | db, | 184 | db, |
161 | file_id.into(), | 185 | node.file_id, |
162 | &it, | 186 | &it, |
163 | it.doc_comment_text(), | 187 | it.doc_comment_text(), |
164 | it.short_label(), | 188 | it.short_label(), |
@@ -167,7 +191,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
167 | ast::StaticDef(it) => { | 191 | ast::StaticDef(it) => { |
168 | Some(NavigationTarget::from_named( | 192 | Some(NavigationTarget::from_named( |
169 | db, | 193 | db, |
170 | file_id.into(), | 194 | node.file_id, |
171 | &it, | 195 | &it, |
172 | it.doc_comment_text(), | 196 | it.doc_comment_text(), |
173 | it.short_label(), | 197 | it.short_label(), |
@@ -176,7 +200,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
176 | ast::TraitDef(it) => { | 200 | ast::TraitDef(it) => { |
177 | Some(NavigationTarget::from_named( | 201 | Some(NavigationTarget::from_named( |
178 | db, | 202 | db, |
179 | file_id.into(), | 203 | node.file_id, |
180 | &it, | 204 | &it, |
181 | it.doc_comment_text(), | 205 | it.doc_comment_text(), |
182 | it.short_label(), | 206 | it.short_label(), |
@@ -185,7 +209,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
185 | ast::RecordFieldDef(it) => { | 209 | ast::RecordFieldDef(it) => { |
186 | Some(NavigationTarget::from_named( | 210 | Some(NavigationTarget::from_named( |
187 | db, | 211 | db, |
188 | file_id.into(), | 212 | node.file_id, |
189 | &it, | 213 | &it, |
190 | it.doc_comment_text(), | 214 | it.doc_comment_text(), |
191 | it.short_label(), | 215 | it.short_label(), |
@@ -194,7 +218,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
194 | ast::Module(it) => { | 218 | ast::Module(it) => { |
195 | Some(NavigationTarget::from_named( | 219 | Some(NavigationTarget::from_named( |
196 | db, | 220 | db, |
197 | file_id.into(), | 221 | node.file_id, |
198 | &it, | 222 | &it, |
199 | it.doc_comment_text(), | 223 | it.doc_comment_text(), |
200 | it.short_label(), | 224 | it.short_label(), |
@@ -203,7 +227,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option | |||
203 | ast::MacroCall(it) => { | 227 | ast::MacroCall(it) => { |
204 | Some(NavigationTarget::from_named( | 228 | Some(NavigationTarget::from_named( |
205 | db, | 229 | db, |
206 | file_id.into(), | 230 | node.file_id, |
207 | &it, | 231 | &it, |
208 | it.doc_comment_text(), | 232 | it.doc_comment_text(), |
209 | None, | 233 | None, |
@@ -677,4 +701,23 @@ mod tests { | |||
677 | "bar MODULE FileId(1) [0; 11) [4; 7)", | 701 | "bar MODULE FileId(1) [0; 11) [4; 7)", |
678 | ); | 702 | ); |
679 | } | 703 | } |
704 | |||
705 | #[test] | ||
706 | fn goto_from_macro() { | ||
707 | check_goto( | ||
708 | " | ||
709 | //- /lib.rs | ||
710 | macro_rules! id { | ||
711 | ($($tt:tt)*) => { $($tt)* } | ||
712 | } | ||
713 | fn foo() {} | ||
714 | id! { | ||
715 | fn bar() { | ||
716 | fo<|>o(); | ||
717 | } | ||
718 | } | ||
719 | ", | ||
720 | "foo FN_DEF FileId(1) [52; 63) [55; 58)", | ||
721 | ); | ||
722 | } | ||
680 | } | 723 | } |
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs index 71146591d..2327cb1e7 100644 --- a/crates/ra_ide_api/src/goto_type_definition.rs +++ b/crates/ra_ide_api/src/goto_type_definition.rs | |||
@@ -18,7 +18,8 @@ pub(crate) fn goto_type_definition( | |||
18 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) | 18 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) |
19 | })?; | 19 | })?; |
20 | 20 | ||
21 | let analyzer = hir::SourceAnalyzer::new(db, position.file_id, &node, None); | 21 | let analyzer = |
22 | hir::SourceAnalyzer::new(db, hir::Source::new(position.file_id.into(), &node), None); | ||
22 | 23 | ||
23 | let ty: hir::Ty = if let Some(ty) = | 24 | let ty: hir::Ty = if let Some(ty) = |
24 | ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) | 25 | ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 07d511fb3..cc25f4c37 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{Adt, HasSource, HirDisplay}; | 3 | use hir::{Adt, HasSource, HirDisplay, Source}; |
4 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | algo::{ancestors_at_offset, find_covering_element, find_node_at_offset}, | 6 | algo::{ancestors_at_offset, find_covering_element, find_node_at_offset}, |
@@ -171,7 +171,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
171 | find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) | 171 | find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) |
172 | { | 172 | { |
173 | let mut no_fallback = false; | 173 | let mut no_fallback = false; |
174 | if let Some(name_kind) = classify_name_ref(db, position.file_id, &name_ref).map(|d| d.kind) | 174 | if let Some(name_kind) = |
175 | classify_name_ref(db, Source::new(position.file_id.into(), &name_ref)).map(|d| d.kind) | ||
175 | { | 176 | { |
176 | res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) | 177 | res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) |
177 | } | 178 | } |
@@ -230,7 +231,8 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { | |||
230 | .ancestors() | 231 | .ancestors() |
231 | .take_while(|it| it.text_range() == leaf_node.text_range()) | 232 | .take_while(|it| it.text_range() == leaf_node.text_range()) |
232 | .find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?; | 233 | .find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?; |
233 | let analyzer = hir::SourceAnalyzer::new(db, frange.file_id, &node, None); | 234 | let analyzer = |
235 | hir::SourceAnalyzer::new(db, hir::Source::new(frange.file_id.into(), &node), None); | ||
234 | let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) | 236 | let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) |
235 | { | 237 | { |
236 | ty | 238 | ty |
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index 2ff10b89a..0cd959848 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs | |||
@@ -32,6 +32,7 @@ fn get_inlay_hints( | |||
32 | file_id: FileId, | 32 | file_id: FileId, |
33 | node: &SyntaxNode, | 33 | node: &SyntaxNode, |
34 | ) -> Option<Vec<InlayHint>> { | 34 | ) -> Option<Vec<InlayHint>> { |
35 | let analyzer = SourceAnalyzer::new(db, hir::Source::new(file_id.into(), node), None); | ||
35 | match_ast! { | 36 | match_ast! { |
36 | match node { | 37 | match node { |
37 | ast::LetStmt(it) => { | 38 | ast::LetStmt(it) => { |
@@ -39,11 +40,9 @@ fn get_inlay_hints( | |||
39 | return None; | 40 | return None; |
40 | } | 41 | } |
41 | let pat = it.pat()?; | 42 | let pat = it.pat()?; |
42 | let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); | ||
43 | Some(get_pat_type_hints(db, &analyzer, pat, false)) | 43 | Some(get_pat_type_hints(db, &analyzer, pat, false)) |
44 | }, | 44 | }, |
45 | ast::LambdaExpr(it) => { | 45 | ast::LambdaExpr(it) => { |
46 | let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); | ||
47 | it.param_list().map(|param_list| { | 46 | it.param_list().map(|param_list| { |
48 | param_list | 47 | param_list |
49 | .params() | 48 | .params() |
@@ -56,21 +55,17 @@ fn get_inlay_hints( | |||
56 | }, | 55 | }, |
57 | ast::ForExpr(it) => { | 56 | ast::ForExpr(it) => { |
58 | let pat = it.pat()?; | 57 | let pat = it.pat()?; |
59 | let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); | ||
60 | Some(get_pat_type_hints(db, &analyzer, pat, false)) | 58 | Some(get_pat_type_hints(db, &analyzer, pat, false)) |
61 | }, | 59 | }, |
62 | ast::IfExpr(it) => { | 60 | ast::IfExpr(it) => { |
63 | let pat = it.condition()?.pat()?; | 61 | let pat = it.condition()?.pat()?; |
64 | let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); | ||
65 | Some(get_pat_type_hints(db, &analyzer, pat, true)) | 62 | Some(get_pat_type_hints(db, &analyzer, pat, true)) |
66 | }, | 63 | }, |
67 | ast::WhileExpr(it) => { | 64 | ast::WhileExpr(it) => { |
68 | let pat = it.condition()?.pat()?; | 65 | let pat = it.condition()?.pat()?; |
69 | let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); | ||
70 | Some(get_pat_type_hints(db, &analyzer, pat, true)) | 66 | Some(get_pat_type_hints(db, &analyzer, pat, true)) |
71 | }, | 67 | }, |
72 | ast::MatchArmList(it) => { | 68 | ast::MatchArmList(it) => { |
73 | let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); | ||
74 | Some( | 69 | Some( |
75 | it | 70 | it |
76 | .arms() | 71 | .arms() |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 9cb9433e7..1af7e8a9f 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -14,6 +14,7 @@ mod name_definition; | |||
14 | mod rename; | 14 | mod rename; |
15 | mod search_scope; | 15 | mod search_scope; |
16 | 16 | ||
17 | use hir::Source; | ||
17 | use once_cell::unsync::Lazy; | 18 | use once_cell::unsync::Lazy; |
18 | use ra_db::{SourceDatabase, SourceDatabaseExt}; | 19 | use ra_db::{SourceDatabase, SourceDatabaseExt}; |
19 | use ra_prof::profile; | 20 | use ra_prof::profile; |
@@ -114,7 +115,7 @@ fn find_name<'a>( | |||
114 | return Some(RangeInfo::new(range, (name.text().to_string(), def))); | 115 | return Some(RangeInfo::new(range, (name.text().to_string(), def))); |
115 | } | 116 | } |
116 | let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; | 117 | let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; |
117 | let def = classify_name_ref(db, position.file_id, &name_ref)?; | 118 | let def = classify_name_ref(db, Source::new(position.file_id.into(), &name_ref))?; |
118 | let range = name_ref.syntax().text_range(); | 119 | let range = name_ref.syntax().text_range(); |
119 | Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) | 120 | Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) |
120 | } | 121 | } |
@@ -146,7 +147,7 @@ fn process_definition( | |||
146 | continue; | 147 | continue; |
147 | } | 148 | } |
148 | } | 149 | } |
149 | if let Some(d) = classify_name_ref(db, file_id, &name_ref) { | 150 | if let Some(d) = classify_name_ref(db, Source::new(file_id.into(), &name_ref)) { |
150 | if d == def { | 151 | if d == def { |
151 | refs.push(FileRange { file_id, range }); | 152 | refs.push(FileRange { file_id, range }); |
152 | } | 153 | } |
@@ -369,6 +370,21 @@ mod tests { | |||
369 | assert_eq!(refs.len(), 2); | 370 | assert_eq!(refs.len(), 2); |
370 | } | 371 | } |
371 | 372 | ||
373 | #[test] | ||
374 | fn test_find_all_refs_macro_def() { | ||
375 | let code = r#" | ||
376 | #[macro_export] | ||
377 | macro_rules! m1<|> { () => (()) } | ||
378 | |||
379 | fn foo() { | ||
380 | m1(); | ||
381 | m1(); | ||
382 | }"#; | ||
383 | |||
384 | let refs = get_all_refs(code); | ||
385 | assert_eq!(refs.len(), 3); | ||
386 | } | ||
387 | |||
372 | fn get_all_refs(text: &str) -> ReferenceSearchResult { | 388 | fn get_all_refs(text: &str) -> ReferenceSearchResult { |
373 | let (analysis, position) = single_file_with_position(text); | 389 | let (analysis, position) = single_file_with_position(text); |
374 | analysis.find_all_refs(position, None).unwrap().unwrap() | 390 | analysis.find_all_refs(position, None).unwrap().unwrap() |
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 217f9951e..5ca9da15e 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs | |||
@@ -21,7 +21,6 @@ pub(crate) fn classify_name( | |||
21 | let parent = name.syntax().parent()?; | 21 | let parent = name.syntax().parent()?; |
22 | let file_id = file_id.into(); | 22 | let file_id = file_id.into(); |
23 | 23 | ||
24 | // FIXME: add ast::MacroCall(it) | ||
25 | match_ast! { | 24 | match_ast! { |
26 | match parent { | 25 | match parent { |
27 | ast::BindPat(it) => { | 26 | ast::BindPat(it) => { |
@@ -104,6 +103,19 @@ pub(crate) fn classify_name( | |||
104 | Some(from_module_def(db, def.into(), None)) | 103 | Some(from_module_def(db, def.into(), None)) |
105 | } | 104 | } |
106 | }, | 105 | }, |
106 | ast::MacroCall(it) => { | ||
107 | let src = hir::Source { file_id, ast: it}; | ||
108 | let def = hir::MacroDef::from_source(db, src.clone())?; | ||
109 | |||
110 | let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); | ||
111 | let module = Module::from_definition(db, Source::new(file_id, module_src))?; | ||
112 | |||
113 | Some(NameDefinition { | ||
114 | visibility: None, | ||
115 | container: module, | ||
116 | kind: NameKind::Macro(def), | ||
117 | }) | ||
118 | }, | ||
107 | _ => None, | 119 | _ => None, |
108 | } | 120 | } |
109 | } | 121 | } |
@@ -111,15 +123,12 @@ pub(crate) fn classify_name( | |||
111 | 123 | ||
112 | pub(crate) fn classify_name_ref( | 124 | pub(crate) fn classify_name_ref( |
113 | db: &RootDatabase, | 125 | db: &RootDatabase, |
114 | file_id: FileId, | 126 | name_ref: Source<&ast::NameRef>, |
115 | name_ref: &ast::NameRef, | ||
116 | ) -> Option<NameDefinition> { | 127 | ) -> Option<NameDefinition> { |
117 | use PathResolution::*; | ||
118 | |||
119 | let _p = profile("classify_name_ref"); | 128 | let _p = profile("classify_name_ref"); |
120 | 129 | ||
121 | let parent = name_ref.syntax().parent()?; | 130 | let parent = name_ref.ast.syntax().parent()?; |
122 | let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); | 131 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); |
123 | 132 | ||
124 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 133 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
125 | tested_by!(goto_definition_works_for_methods); | 134 | tested_by!(goto_definition_works_for_methods); |
@@ -139,17 +148,16 @@ pub(crate) fn classify_name_ref( | |||
139 | tested_by!(goto_definition_works_for_record_fields); | 148 | tested_by!(goto_definition_works_for_record_fields); |
140 | if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { | 149 | if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { |
141 | let variant_def = analyzer.resolve_record_literal(&record_lit)?; | 150 | let variant_def = analyzer.resolve_record_literal(&record_lit)?; |
142 | let hir_path = Path::from_name_ref(name_ref); | 151 | let hir_path = Path::from_name_ref(name_ref.ast); |
143 | let hir_name = hir_path.as_ident()?; | 152 | let hir_name = hir_path.as_ident()?; |
144 | let field = variant_def.field(db, hir_name)?; | 153 | let field = variant_def.field(db, hir_name)?; |
145 | return Some(from_struct_field(db, field)); | 154 | return Some(from_struct_field(db, field)); |
146 | } | 155 | } |
147 | } | 156 | } |
148 | 157 | ||
149 | let ast = ModuleSource::from_child_node(db, file_id, &parent); | 158 | let ast = ModuleSource::from_child_node(db, name_ref.with_ast(&parent)); |
150 | let file_id = file_id.into(); | ||
151 | // FIXME: find correct container and visibility for each case | 159 | // FIXME: find correct container and visibility for each case |
152 | let container = Module::from_definition(db, Source { file_id, ast })?; | 160 | let container = Module::from_definition(db, name_ref.with_ast(ast))?; |
153 | let visibility = None; | 161 | let visibility = None; |
154 | 162 | ||
155 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 163 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
@@ -160,29 +168,29 @@ pub(crate) fn classify_name_ref( | |||
160 | } | 168 | } |
161 | } | 169 | } |
162 | 170 | ||
163 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 171 | let path = name_ref.ast.syntax().ancestors().find_map(ast::Path::cast)?; |
164 | let resolved = analyzer.resolve_path(db, &path)?; | 172 | let resolved = analyzer.resolve_path(db, &path)?; |
165 | match resolved { | 173 | match resolved { |
166 | Def(def) => Some(from_module_def(db, def, Some(container))), | 174 | PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))), |
167 | AssocItem(item) => Some(from_assoc_item(db, item)), | 175 | PathResolution::AssocItem(item) => Some(from_assoc_item(db, item)), |
168 | Local(local) => { | 176 | PathResolution::Local(local) => { |
169 | let container = local.module(db); | 177 | let container = local.module(db); |
170 | let kind = NameKind::Local(local); | 178 | let kind = NameKind::Local(local); |
171 | Some(NameDefinition { kind, container, visibility: None }) | 179 | Some(NameDefinition { kind, container, visibility: None }) |
172 | } | 180 | } |
173 | GenericParam(par) => { | 181 | PathResolution::GenericParam(par) => { |
174 | // FIXME: get generic param def | 182 | // FIXME: get generic param def |
175 | let kind = NameKind::GenericParam(par); | 183 | let kind = NameKind::GenericParam(par); |
176 | Some(NameDefinition { kind, container, visibility }) | 184 | Some(NameDefinition { kind, container, visibility }) |
177 | } | 185 | } |
178 | Macro(def) => { | 186 | PathResolution::Macro(def) => { |
179 | let kind = NameKind::Macro(def); | 187 | let kind = NameKind::Macro(def); |
180 | Some(NameDefinition { kind, container, visibility }) | 188 | Some(NameDefinition { kind, container, visibility }) |
181 | } | 189 | } |
182 | SelfType(impl_block) => { | 190 | PathResolution::SelfType(impl_block) => { |
183 | let ty = impl_block.target_ty(db); | 191 | let ty = impl_block.target_ty(db); |
184 | let kind = NameKind::SelfType(ty); | 192 | let kind = NameKind::SelfType(ty); |
185 | let container = impl_block.module(); | 193 | let container = impl_block.module(db); |
186 | Some(NameDefinition { kind, container, visibility }) | 194 | Some(NameDefinition { kind, container, visibility }) |
187 | } | 195 | } |
188 | } | 196 | } |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 366ac8048..8039a5164 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::Source; | ||
3 | use itertools::Itertools; | 4 | use itertools::Itertools; |
4 | use ra_db::SourceDatabase; | 5 | use ra_db::SourceDatabase; |
5 | use ra_syntax::{ | 6 | use ra_syntax::{ |
@@ -65,9 +66,8 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti | |||
65 | return None; | 66 | return None; |
66 | } | 67 | } |
67 | let range = module.syntax().text_range(); | 68 | let range = module.syntax().text_range(); |
68 | let src = hir::ModuleSource::from_child_node(db, file_id, &module.syntax()); | 69 | let src = hir::ModuleSource::from_child_node(db, Source::new(file_id.into(), &module.syntax())); |
69 | let module = | 70 | let module = hir::Module::from_definition(db, Source::new(file_id.into(), src))?; |
70 | hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src })?; | ||
71 | 71 | ||
72 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); | 72 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); |
73 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) | 73 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) |
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index d53a759ee..584657ca2 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use rustc_hash::{FxHashMap, FxHashSet}; | 3 | use rustc_hash::{FxHashMap, FxHashSet}; |
4 | 4 | ||
5 | use hir::{Mutability, Name}; | 5 | use hir::{Mutability, Name, Source}; |
6 | use ra_db::SourceDatabase; | 6 | use ra_db::SourceDatabase; |
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
8 | use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; | 8 | use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; |
@@ -80,7 +80,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
80 | } | 80 | } |
81 | 81 | ||
82 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); | 82 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); |
83 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); | 83 | let name_kind = |
84 | classify_name_ref(db, Source::new(file_id.into(), &name_ref)).map(|d| d.kind); | ||
84 | 85 | ||
85 | if let Some(Local(local)) = &name_kind { | 86 | if let Some(Local(local)) = &name_kind { |
86 | if let Some(name) = local.name(db) { | 87 | if let Some(name) = local.name(db) { |