aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-18 01:27:53 +0000
committerSeivan Heidari <[email protected]>2019-11-18 01:27:53 +0000
commit166636ba77adcf5bf2c4ef935e9aa75e20f25e10 (patch)
tree168be1ca55c73b016e20586c08417c608450c92c /crates/ra_ide_api
parentcb26df950699586b314731fb70786e0db8eaa049 (diff)
parent28c2d74b2150102a8756a5357a5a965d7610bd15 (diff)
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/Cargo.toml3
-rw-r--r--crates/ra_ide_api/src/call_info.rs6
-rw-r--r--crates/ra_ide_api/src/change.rs4
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs7
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs115
-rw-r--r--crates/ra_ide_api/src/goto_type_definition.rs3
-rw-r--r--crates/ra_ide_api/src/hover.rs8
-rw-r--r--crates/ra_ide_api/src/inlay_hints.rs7
-rw-r--r--crates/ra_ide_api/src/references.rs20
-rw-r--r--crates/ra_ide_api/src/references/classify.rs46
-rw-r--r--crates/ra_ide_api/src/runnables.rs6
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs5
12 files changed, 152 insertions, 78 deletions
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml
index fa353b5dd..15346f388 100644
--- a/crates/ra_ide_api/Cargo.toml
+++ b/crates/ra_ide_api/Cargo.toml
@@ -4,6 +4,9 @@ name = "ra_ide_api"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6 6
7[lib]
8doctest = false
9
7[features] 10[features]
8wasm = [] 11wasm = []
9 12
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
3use ra_db::{FileId, SourceDatabase}; 3use std::iter::successors;
4
5use hir::{db::AstDatabase, Source};
4use ra_syntax::{ 6use 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
10use crate::{ 11use 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
42fn 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, &macro_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
50pub(crate) fn reference_definition( 76pub(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
86pub(crate) fn name_definition( 111pub(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
110fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget> { 134fn 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
3use hir::{Adt, HasSource, HirDisplay}; 3use hir::{Adt, HasSource, HirDisplay, Source};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_syntax::{ 5use 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;
14mod rename; 14mod rename;
15mod search_scope; 15mod search_scope;
16 16
17use hir::Source;
17use once_cell::unsync::Lazy; 18use once_cell::unsync::Lazy;
18use ra_db::{SourceDatabase, SourceDatabaseExt}; 19use ra_db::{SourceDatabase, SourceDatabaseExt};
19use ra_prof::profile; 20use 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
112pub(crate) fn classify_name_ref( 124pub(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
3use hir::Source;
3use itertools::Itertools; 4use itertools::Itertools;
4use ra_db::SourceDatabase; 5use ra_db::SourceDatabase;
5use ra_syntax::{ 6use 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
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
4 4
5use hir::{Mutability, Name}; 5use hir::{Mutability, Name, Source};
6use ra_db::SourceDatabase; 6use ra_db::SourceDatabase;
7use ra_prof::profile; 7use ra_prof::profile;
8use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; 8use 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) {