aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs99
-rw-r--r--crates/ra_ide_api/src/expand.rs59
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs60
-rw-r--r--crates/ra_ide_api/src/hover.rs4
-rw-r--r--crates/ra_ide_api/src/lib.rs1
-rw-r--r--crates/ra_ide_api/src/references.rs2
-rw-r--r--crates/ra_ide_api/src/references/classify.rs38
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs3
8 files changed, 142 insertions, 124 deletions
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index f7ad08515..b30ef8e05 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -1,16 +1,17 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource}; 3use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource, Source};
4use ra_db::{FileId, SourceDatabase}; 4use ra_db::{FileId, SourceDatabase};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, DocCommentsOwner, NameOwner}, 6 ast::{self, DocCommentsOwner, NameOwner},
7 match_ast, AstNode, SmolStr, 7 match_ast, AstNode, SmolStr,
8 SyntaxKind::{self, BIND_PAT}, 8 SyntaxKind::{self, BIND_PAT},
9 SyntaxNode, TextRange, 9 TextRange,
10}; 10};
11 11
12use crate::{db::RootDatabase, expand::original_range, FileSymbol};
13
12use super::short_label::ShortLabel; 14use super::short_label::ShortLabel;
13use crate::{db::RootDatabase, FileSymbol};
14 15
15/// `NavigationTarget` represents and element in the editor's UI which you can 16/// `NavigationTarget` represents and element in the editor's UI which you can
16/// click on to navigate to a particular piece of code. 17/// click on to navigate to a particular piece of code.
@@ -79,13 +80,13 @@ impl NavigationTarget {
79 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 80 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
80 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 81 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
81 if let Some(src) = module.declaration_source(db) { 82 if let Some(src) = module.declaration_source(db) {
82 let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax()); 83 let frange = original_range(db, src.as_ref().map(|it| it.syntax()));
83 return NavigationTarget::from_syntax( 84 return NavigationTarget::from_syntax(
84 file_id, 85 frange.file_id,
85 name, 86 name,
86 None, 87 None,
87 text_range, 88 frange.range,
88 src.ast.syntax(), 89 src.ast.syntax().kind(),
89 src.ast.doc_comment_text(), 90 src.ast.doc_comment_text(),
90 src.ast.short_label(), 91 src.ast.short_label(),
91 ); 92 );
@@ -140,22 +141,22 @@ impl NavigationTarget {
140 /// Allows `NavigationTarget` to be created from a `NameOwner` 141 /// Allows `NavigationTarget` to be created from a `NameOwner`
141 pub(crate) fn from_named( 142 pub(crate) fn from_named(
142 db: &RootDatabase, 143 db: &RootDatabase,
143 file_id: hir::HirFileId, 144 node: Source<&dyn ast::NameOwner>,
144 node: &impl ast::NameOwner,
145 docs: Option<String>, 145 docs: Option<String>,
146 description: Option<String>, 146 description: Option<String>,
147 ) -> NavigationTarget { 147 ) -> NavigationTarget {
148 //FIXME: use `_` instead of empty string 148 //FIXME: use `_` instead of empty string
149 let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); 149 let name = node.ast.name().map(|it| it.text().clone()).unwrap_or_default();
150 let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1); 150 let focus_range =
151 let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax()); 151 node.ast.name().map(|it| original_range(db, node.with_ast(it.syntax())).range);
152 let frange = original_range(db, node.map(|it| it.syntax()));
152 153
153 NavigationTarget::from_syntax( 154 NavigationTarget::from_syntax(
154 file_id, 155 frange.file_id,
155 name, 156 name,
156 focus_range, 157 focus_range,
157 full_range, 158 frange.range,
158 node.syntax(), 159 node.ast.syntax().kind(),
159 docs, 160 docs,
160 description, 161 description,
161 ) 162 )
@@ -166,14 +167,14 @@ impl NavigationTarget {
166 name: SmolStr, 167 name: SmolStr,
167 focus_range: Option<TextRange>, 168 focus_range: Option<TextRange>,
168 full_range: TextRange, 169 full_range: TextRange,
169 node: &SyntaxNode, 170 kind: SyntaxKind,
170 docs: Option<String>, 171 docs: Option<String>,
171 description: Option<String>, 172 description: Option<String>,
172 ) -> NavigationTarget { 173 ) -> NavigationTarget {
173 NavigationTarget { 174 NavigationTarget {
174 file_id, 175 file_id,
175 name, 176 name,
176 kind: node.kind(), 177 kind,
177 full_range, 178 full_range,
178 focus_range, 179 focus_range,
179 container_name: None, 180 container_name: None,
@@ -218,8 +219,7 @@ where
218 let src = self.source(db); 219 let src = self.source(db);
219 NavigationTarget::from_named( 220 NavigationTarget::from_named(
220 db, 221 db,
221 src.file_id, 222 src.as_ref().map(|it| it as &dyn ast::NameOwner),
222 &src.ast,
223 src.ast.doc_comment_text(), 223 src.ast.doc_comment_text(),
224 src.ast.short_label(), 224 src.ast.short_label(),
225 ) 225 )
@@ -230,29 +230,29 @@ impl ToNav for hir::Module {
230 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 230 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
231 let src = self.definition_source(db); 231 let src = self.definition_source(db);
232 let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 232 let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default();
233 match src.ast { 233 match &src.ast {
234 ModuleSource::SourceFile(node) => { 234 ModuleSource::SourceFile(node) => {
235 let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); 235 let frange = original_range(db, src.with_ast(node.syntax()));
236 236
237 NavigationTarget::from_syntax( 237 NavigationTarget::from_syntax(
238 file_id, 238 frange.file_id,
239 name, 239 name,
240 None, 240 None,
241 text_range, 241 frange.range,
242 node.syntax(), 242 node.syntax().kind(),
243 None, 243 None,
244 None, 244 None,
245 ) 245 )
246 } 246 }
247 ModuleSource::Module(node) => { 247 ModuleSource::Module(node) => {
248 let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); 248 let frange = original_range(db, src.with_ast(node.syntax()));
249 249
250 NavigationTarget::from_syntax( 250 NavigationTarget::from_syntax(
251 file_id, 251 frange.file_id,
252 name, 252 name,
253 None, 253 None,
254 text_range, 254 frange.range,
255 node.syntax(), 255 node.syntax().kind(),
256 node.doc_comment_text(), 256 node.doc_comment_text(),
257 node.short_label(), 257 node.short_label(),
258 ) 258 )
@@ -264,14 +264,14 @@ impl ToNav for hir::Module {
264impl ToNav for hir::ImplBlock { 264impl ToNav for hir::ImplBlock {
265 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 265 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
266 let src = self.source(db); 266 let src = self.source(db);
267 let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax()); 267 let frange = original_range(db, src.as_ref().map(|it| it.syntax()));
268 268
269 NavigationTarget::from_syntax( 269 NavigationTarget::from_syntax(
270 file_id, 270 frange.file_id,
271 "impl".into(), 271 "impl".into(),
272 None, 272 None,
273 text_range, 273 frange.range,
274 src.ast.syntax(), 274 src.ast.syntax().kind(),
275 None, 275 None,
276 None, 276 None,
277 ) 277 )
@@ -282,22 +282,21 @@ impl ToNav for hir::StructField {
282 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 282 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
283 let src = self.source(db); 283 let src = self.source(db);
284 284
285 match src.ast { 285 match &src.ast {
286 FieldSource::Named(it) => NavigationTarget::from_named( 286 FieldSource::Named(it) => NavigationTarget::from_named(
287 db, 287 db,
288 src.file_id, 288 src.with_ast(it),
289 &it,
290 it.doc_comment_text(), 289 it.doc_comment_text(),
291 it.short_label(), 290 it.short_label(),
292 ), 291 ),
293 FieldSource::Pos(it) => { 292 FieldSource::Pos(it) => {
294 let (file_id, text_range) = find_range_from_node(db, src.file_id, it.syntax()); 293 let frange = original_range(db, src.with_ast(it.syntax()));
295 NavigationTarget::from_syntax( 294 NavigationTarget::from_syntax(
296 file_id, 295 frange.file_id,
297 "".into(), 296 "".into(),
298 None, 297 None,
299 text_range, 298 frange.range,
300 it.syntax(), 299 it.syntax().kind(),
301 None, 300 None,
302 None, 301 None,
303 ) 302 )
@@ -310,7 +309,12 @@ impl ToNav for hir::MacroDef {
310 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 309 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
311 let src = self.source(db); 310 let src = self.source(db);
312 log::debug!("nav target {:#?}", src.ast.syntax()); 311 log::debug!("nav target {:#?}", src.ast.syntax());
313 NavigationTarget::from_named(db, src.file_id, &src.ast, src.ast.doc_comment_text(), None) 312 NavigationTarget::from_named(
313 db,
314 src.as_ref().map(|it| it as &dyn ast::NameOwner),
315 src.ast.doc_comment_text(),
316 None,
317 )
314 } 318 }
315} 319}
316 320
@@ -360,21 +364,6 @@ impl ToNav for hir::Local {
360 } 364 }
361} 365}
362 366
363fn find_range_from_node(
364 db: &RootDatabase,
365 src: hir::HirFileId,
366 node: &SyntaxNode,
367) -> (FileId, TextRange) {
368 let text_range = node.text_range();
369 let (file_id, text_range) = src
370 .expansion_info(db)
371 .and_then(|expansion_info| expansion_info.find_range(text_range))
372 .unwrap_or((src, text_range));
373
374 // FIXME: handle recursive macro generated macro
375 (file_id.original_file(db), text_range)
376}
377
378pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { 367pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
379 let parse = db.parse(symbol.file_id); 368 let parse = db.parse(symbol.file_id);
380 let node = symbol.ptr.to_node(parse.tree().syntax()); 369 let node = symbol.ptr.to_node(parse.tree().syntax());
diff --git a/crates/ra_ide_api/src/expand.rs b/crates/ra_ide_api/src/expand.rs
new file mode 100644
index 000000000..7f59e46d2
--- /dev/null
+++ b/crates/ra_ide_api/src/expand.rs
@@ -0,0 +1,59 @@
1//! Utilities to work with files, produced by macros.
2use std::iter::successors;
3
4use hir::Source;
5use ra_db::FileId;
6use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken};
7
8use crate::{db::RootDatabase, FileRange};
9
10pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> FileRange {
11 let expansion = match node.file_id.expansion_info(db) {
12 None => {
13 return FileRange {
14 file_id: node.file_id.original_file(db),
15 range: node.ast.text_range(),
16 }
17 }
18 Some(it) => it,
19 };
20 // FIXME: the following completely wrong.
21 //
22 // *First*, we should try to map first and last tokens of node, and, if that
23 // fails, return the range of the overall macro expansions.
24 //
25 // *Second*, we should handle recurside macro expansions
26
27 let token = node
28 .ast
29 .descendants_with_tokens()
30 .filter_map(|it| it.into_token())
31 .find_map(|it| expansion.map_token_up(node.with_ast(&it)));
32
33 match token {
34 Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.ast.text_range() },
35 None => FileRange { file_id: node.file_id.original_file(db), range: node.ast.text_range() },
36 }
37}
38
39pub(crate) fn descend_into_macros(
40 db: &RootDatabase,
41 file_id: FileId,
42 token: SyntaxToken,
43) -> Source<SyntaxToken> {
44 let src = Source::new(file_id.into(), token);
45
46 successors(Some(src), |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()
58 .unwrap()
59}
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index b693a4c31..3f16e9566 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -1,16 +1,15 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::iter::successors;
4
5use hir::{db::AstDatabase, Source}; 3use hir::{db::AstDatabase, Source};
6use ra_syntax::{ 4use ra_syntax::{
7 ast::{self, DocCommentsOwner}, 5 ast::{self, DocCommentsOwner},
8 match_ast, AstNode, SyntaxNode, SyntaxToken, 6 match_ast, AstNode, SyntaxNode,
9}; 7};
10 8
11use crate::{ 9use crate::{
12 db::RootDatabase, 10 db::RootDatabase,
13 display::{ShortLabel, ToNav}, 11 display::{ShortLabel, ToNav},
12 expand::descend_into_macros,
14 references::{classify_name_ref, NameKind::*}, 13 references::{classify_name_ref, NameKind::*},
15 FilePosition, NavigationTarget, RangeInfo, 14 FilePosition, NavigationTarget, RangeInfo,
16}; 15};
@@ -19,7 +18,9 @@ pub(crate) fn goto_definition(
19 db: &RootDatabase, 18 db: &RootDatabase,
20 position: FilePosition, 19 position: FilePosition,
21) -> Option<RangeInfo<Vec<NavigationTarget>>> { 20) -> Option<RangeInfo<Vec<NavigationTarget>>> {
22 let token = descend_into_macros(db, position)?; 21 let file = db.parse_or_expand(position.file_id.into())?;
22 let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?;
23 let token = descend_into_macros(db, position.file_id, token);
23 24
24 let res = match_ast! { 25 let res = match_ast! {
25 match (token.ast.parent()) { 26 match (token.ast.parent()) {
@@ -39,24 +40,6 @@ pub(crate) fn goto_definition(
39 Some(res) 40 Some(res)
40} 41}
41 42
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()
58}
59
60#[derive(Debug)] 43#[derive(Debug)]
61pub(crate) enum ReferenceResult { 44pub(crate) enum ReferenceResult {
62 Exact(NavigationTarget), 45 Exact(NavigationTarget),
@@ -137,8 +120,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
137 ast::StructDef(it) => { 120 ast::StructDef(it) => {
138 Some(NavigationTarget::from_named( 121 Some(NavigationTarget::from_named(
139 db, 122 db,
140 node.file_id, 123 node.with_ast(&it),
141 &it,
142 it.doc_comment_text(), 124 it.doc_comment_text(),
143 it.short_label(), 125 it.short_label(),
144 )) 126 ))
@@ -146,8 +128,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
146 ast::EnumDef(it) => { 128 ast::EnumDef(it) => {
147 Some(NavigationTarget::from_named( 129 Some(NavigationTarget::from_named(
148 db, 130 db,
149 node.file_id, 131 node.with_ast(&it),
150 &it,
151 it.doc_comment_text(), 132 it.doc_comment_text(),
152 it.short_label(), 133 it.short_label(),
153 )) 134 ))
@@ -155,8 +136,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
155 ast::EnumVariant(it) => { 136 ast::EnumVariant(it) => {
156 Some(NavigationTarget::from_named( 137 Some(NavigationTarget::from_named(
157 db, 138 db,
158 node.file_id, 139 node.with_ast(&it),
159 &it,
160 it.doc_comment_text(), 140 it.doc_comment_text(),
161 it.short_label(), 141 it.short_label(),
162 )) 142 ))
@@ -164,8 +144,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
164 ast::FnDef(it) => { 144 ast::FnDef(it) => {
165 Some(NavigationTarget::from_named( 145 Some(NavigationTarget::from_named(
166 db, 146 db,
167 node.file_id, 147 node.with_ast(&it),
168 &it,
169 it.doc_comment_text(), 148 it.doc_comment_text(),
170 it.short_label(), 149 it.short_label(),
171 )) 150 ))
@@ -173,8 +152,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
173 ast::TypeAliasDef(it) => { 152 ast::TypeAliasDef(it) => {
174 Some(NavigationTarget::from_named( 153 Some(NavigationTarget::from_named(
175 db, 154 db,
176 node.file_id, 155 node.with_ast(&it),
177 &it,
178 it.doc_comment_text(), 156 it.doc_comment_text(),
179 it.short_label(), 157 it.short_label(),
180 )) 158 ))
@@ -182,8 +160,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
182 ast::ConstDef(it) => { 160 ast::ConstDef(it) => {
183 Some(NavigationTarget::from_named( 161 Some(NavigationTarget::from_named(
184 db, 162 db,
185 node.file_id, 163 node.with_ast(&it),
186 &it,
187 it.doc_comment_text(), 164 it.doc_comment_text(),
188 it.short_label(), 165 it.short_label(),
189 )) 166 ))
@@ -191,8 +168,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
191 ast::StaticDef(it) => { 168 ast::StaticDef(it) => {
192 Some(NavigationTarget::from_named( 169 Some(NavigationTarget::from_named(
193 db, 170 db,
194 node.file_id, 171 node.with_ast(&it),
195 &it,
196 it.doc_comment_text(), 172 it.doc_comment_text(),
197 it.short_label(), 173 it.short_label(),
198 )) 174 ))
@@ -200,8 +176,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
200 ast::TraitDef(it) => { 176 ast::TraitDef(it) => {
201 Some(NavigationTarget::from_named( 177 Some(NavigationTarget::from_named(
202 db, 178 db,
203 node.file_id, 179 node.with_ast(&it),
204 &it,
205 it.doc_comment_text(), 180 it.doc_comment_text(),
206 it.short_label(), 181 it.short_label(),
207 )) 182 ))
@@ -209,8 +184,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
209 ast::RecordFieldDef(it) => { 184 ast::RecordFieldDef(it) => {
210 Some(NavigationTarget::from_named( 185 Some(NavigationTarget::from_named(
211 db, 186 db,
212 node.file_id, 187 node.with_ast(&it),
213 &it,
214 it.doc_comment_text(), 188 it.doc_comment_text(),
215 it.short_label(), 189 it.short_label(),
216 )) 190 ))
@@ -218,8 +192,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
218 ast::Module(it) => { 192 ast::Module(it) => {
219 Some(NavigationTarget::from_named( 193 Some(NavigationTarget::from_named(
220 db, 194 db,
221 node.file_id, 195 node.with_ast(&it),
222 &it,
223 it.doc_comment_text(), 196 it.doc_comment_text(),
224 it.short_label(), 197 it.short_label(),
225 )) 198 ))
@@ -227,8 +200,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
227 ast::MacroCall(it) => { 200 ast::MacroCall(it) => {
228 Some(NavigationTarget::from_named( 201 Some(NavigationTarget::from_named(
229 db, 202 db,
230 node.file_id, 203 node.with_ast(&it),
231 &it,
232 it.doc_comment_text(), 204 it.doc_comment_text(),
233 None, 205 None,
234 )) 206 ))
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index cc25f4c37..c6d678c0c 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -193,7 +193,9 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
193 None 193 None
194 } 194 }
195 } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { 195 } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
196 if let Some(name_kind) = classify_name(db, position.file_id, &name).map(|d| d.kind) { 196 if let Some(name_kind) =
197 classify_name(db, Source::new(position.file_id.into(), &name)).map(|d| d.kind)
198 {
197 let mut _b: bool = true; 199 let mut _b: bool = true;
198 res.extend(hover_text_from_name_kind(db, name_kind, &mut _b)); 200 res.extend(hover_text_from_name_kind(db, name_kind, &mut _b));
199 } 201 }
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 484fbcc82..110ddcd62 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -41,6 +41,7 @@ mod matching_brace;
41mod display; 41mod display;
42mod inlay_hints; 42mod inlay_hints;
43mod wasm_shims; 43mod wasm_shims;
44mod expand;
44 45
45#[cfg(test)] 46#[cfg(test)]
46mod marks; 47mod marks;
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index 1af7e8a9f..cb343e59a 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -110,7 +110,7 @@ fn find_name<'a>(
110 position: FilePosition, 110 position: FilePosition,
111) -> Option<RangeInfo<(String, NameDefinition)>> { 111) -> Option<RangeInfo<(String, NameDefinition)>> {
112 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) { 112 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) {
113 let def = classify_name(db, position.file_id, &name)?; 113 let def = classify_name(db, Source::new(position.file_id.into(), &name))?;
114 let range = name.syntax().text_range(); 114 let range = name.syntax().text_range();
115 return Some(RangeInfo::new(range, (name.text().to_string(), def))); 115 return Some(RangeInfo::new(range, (name.text().to_string(), def)));
116 } 116 }
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs
index 5ca9da15e..ea9d20e71 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide_api/src/references/classify.rs
@@ -1,7 +1,6 @@
1//! Functions that are used to classify an element from its definition or reference. 1//! Functions that are used to classify an element from its definition or reference.
2 2
3use hir::{FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; 3use hir::{FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer};
4use ra_db::FileId;
5use ra_prof::profile; 4use ra_prof::profile;
6use ra_syntax::{ast, match_ast, AstNode}; 5use ra_syntax::{ast, match_ast, AstNode};
7use test_utils::tested_by; 6use test_utils::tested_by;
@@ -12,19 +11,14 @@ use super::{
12}; 11};
13use crate::db::RootDatabase; 12use crate::db::RootDatabase;
14 13
15pub(crate) fn classify_name( 14pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option<NameDefinition> {
16 db: &RootDatabase,
17 file_id: FileId,
18 name: &ast::Name,
19) -> Option<NameDefinition> {
20 let _p = profile("classify_name"); 15 let _p = profile("classify_name");
21 let parent = name.syntax().parent()?; 16 let parent = name.ast.syntax().parent()?;
22 let file_id = file_id.into();
23 17
24 match_ast! { 18 match_ast! {
25 match parent { 19 match parent {
26 ast::BindPat(it) => { 20 ast::BindPat(it) => {
27 let src = hir::Source { file_id, ast: it }; 21 let src = name.with_ast(it);
28 let local = hir::Local::from_source(db, src)?; 22 let local = hir::Local::from_source(db, src)?;
29 Some(NameDefinition { 23 Some(NameDefinition {
30 visibility: None, 24 visibility: None,
@@ -34,7 +28,7 @@ pub(crate) fn classify_name(
34 }, 28 },
35 ast::RecordFieldDef(it) => { 29 ast::RecordFieldDef(it) => {
36 let ast = hir::FieldSource::Named(it); 30 let ast = hir::FieldSource::Named(it);
37 let src = hir::Source { file_id, ast }; 31 let src = name.with_ast(ast);
38 let field = hir::StructField::from_source(db, src)?; 32 let field = hir::StructField::from_source(db, src)?;
39 Some(from_struct_field(db, field)) 33 Some(from_struct_field(db, field))
40 }, 34 },
@@ -42,42 +36,42 @@ pub(crate) fn classify_name(
42 let def = { 36 let def = {
43 if !it.has_semi() { 37 if !it.has_semi() {
44 let ast = hir::ModuleSource::Module(it); 38 let ast = hir::ModuleSource::Module(it);
45 let src = hir::Source { file_id, ast }; 39 let src = name.with_ast(ast);
46 hir::Module::from_definition(db, src) 40 hir::Module::from_definition(db, src)
47 } else { 41 } else {
48 let src = hir::Source { file_id, ast: it }; 42 let src = name.with_ast(it);
49 hir::Module::from_declaration(db, src) 43 hir::Module::from_declaration(db, src)
50 } 44 }
51 }?; 45 }?;
52 Some(from_module_def(db, def.into(), None)) 46 Some(from_module_def(db, def.into(), None))
53 }, 47 },
54 ast::StructDef(it) => { 48 ast::StructDef(it) => {
55 let src = hir::Source { file_id, ast: it }; 49 let src = name.with_ast(it);
56 let def = hir::Struct::from_source(db, src)?; 50 let def = hir::Struct::from_source(db, src)?;
57 Some(from_module_def(db, def.into(), None)) 51 Some(from_module_def(db, def.into(), None))
58 }, 52 },
59 ast::EnumDef(it) => { 53 ast::EnumDef(it) => {
60 let src = hir::Source { file_id, ast: it }; 54 let src = name.with_ast(it);
61 let def = hir::Enum::from_source(db, src)?; 55 let def = hir::Enum::from_source(db, src)?;
62 Some(from_module_def(db, def.into(), None)) 56 Some(from_module_def(db, def.into(), None))
63 }, 57 },
64 ast::TraitDef(it) => { 58 ast::TraitDef(it) => {
65 let src = hir::Source { file_id, ast: it }; 59 let src = name.with_ast(it);
66 let def = hir::Trait::from_source(db, src)?; 60 let def = hir::Trait::from_source(db, src)?;
67 Some(from_module_def(db, def.into(), None)) 61 Some(from_module_def(db, def.into(), None))
68 }, 62 },
69 ast::StaticDef(it) => { 63 ast::StaticDef(it) => {
70 let src = hir::Source { file_id, ast: it }; 64 let src = name.with_ast(it);
71 let def = hir::Static::from_source(db, src)?; 65 let def = hir::Static::from_source(db, src)?;
72 Some(from_module_def(db, def.into(), None)) 66 Some(from_module_def(db, def.into(), None))
73 }, 67 },
74 ast::EnumVariant(it) => { 68 ast::EnumVariant(it) => {
75 let src = hir::Source { file_id, ast: it }; 69 let src = name.with_ast(it);
76 let def = hir::EnumVariant::from_source(db, src)?; 70 let def = hir::EnumVariant::from_source(db, src)?;
77 Some(from_module_def(db, def.into(), None)) 71 Some(from_module_def(db, def.into(), None))
78 }, 72 },
79 ast::FnDef(it) => { 73 ast::FnDef(it) => {
80 let src = hir::Source { file_id, ast: it }; 74 let src = name.with_ast(it);
81 let def = hir::Function::from_source(db, src)?; 75 let def = hir::Function::from_source(db, src)?;
82 if parent.parent().and_then(ast::ItemList::cast).is_some() { 76 if parent.parent().and_then(ast::ItemList::cast).is_some() {
83 Some(from_assoc_item(db, def.into())) 77 Some(from_assoc_item(db, def.into()))
@@ -86,7 +80,7 @@ pub(crate) fn classify_name(
86 } 80 }
87 }, 81 },
88 ast::ConstDef(it) => { 82 ast::ConstDef(it) => {
89 let src = hir::Source { file_id, ast: it }; 83 let src = name.with_ast(it);
90 let def = hir::Const::from_source(db, src)?; 84 let def = hir::Const::from_source(db, src)?;
91 if parent.parent().and_then(ast::ItemList::cast).is_some() { 85 if parent.parent().and_then(ast::ItemList::cast).is_some() {
92 Some(from_assoc_item(db, def.into())) 86 Some(from_assoc_item(db, def.into()))
@@ -95,7 +89,7 @@ pub(crate) fn classify_name(
95 } 89 }
96 }, 90 },
97 ast::TypeAliasDef(it) => { 91 ast::TypeAliasDef(it) => {
98 let src = hir::Source { file_id, ast: it }; 92 let src = name.with_ast(it);
99 let def = hir::TypeAlias::from_source(db, src)?; 93 let def = hir::TypeAlias::from_source(db, src)?;
100 if parent.parent().and_then(ast::ItemList::cast).is_some() { 94 if parent.parent().and_then(ast::ItemList::cast).is_some() {
101 Some(from_assoc_item(db, def.into())) 95 Some(from_assoc_item(db, def.into()))
@@ -104,11 +98,11 @@ pub(crate) fn classify_name(
104 } 98 }
105 }, 99 },
106 ast::MacroCall(it) => { 100 ast::MacroCall(it) => {
107 let src = hir::Source { file_id, ast: it}; 101 let src = name.with_ast(it);
108 let def = hir::MacroDef::from_source(db, src.clone())?; 102 let def = hir::MacroDef::from_source(db, src.clone())?;
109 103
110 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); 104 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))?; 105 let module = Module::from_definition(db, src.with_ast(module_src))?;
112 106
113 Some(NameDefinition { 107 Some(NameDefinition {
114 visibility: None, 108 visibility: None,
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 584657ca2..2b653fe8f 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -94,7 +94,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
94 } 94 }
95 NAME => { 95 NAME => {
96 let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); 96 let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap();
97 let name_kind = classify_name(db, file_id, &name).map(|d| d.kind); 97 let name_kind =
98 classify_name(db, Source::new(file_id.into(), &name)).map(|d| d.kind);
98 99
99 if let Some(Local(local)) = &name_kind { 100 if let Some(Local(local)) = &name_kind {
100 if let Some(name) = local.name(db) { 101 if let Some(name) = local.name(db) {