diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-11-18 11:24:35 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-11-18 11:24:35 +0000 |
commit | 91509073c54a6f815a443f70fd8f9e505b750177 (patch) | |
tree | ffc9afa4bd6f436e51eaa3de9758916a1bdc7124 /crates/ra_ide_api | |
parent | 614c034ffc3a7120f125eede8323f01c8f4411d3 (diff) | |
parent | 9fcd98e956a46d90c708abb9739f067a88ae3c4a (diff) |
Merge #2298
2298: Add ra_ide_api::expand r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r-- | crates/ra_ide_api/src/display/navigation_target.rs | 65 | ||||
-rw-r--r-- | crates/ra_ide_api/src/expand.rs | 42 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 27 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 1 |
4 files changed, 74 insertions, 61 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..291b5ee40 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource}; | 3 | use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource, Source}; |
4 | use ra_db::{FileId, SourceDatabase}; | 4 | use ra_db::{FileId, SourceDatabase}; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | ast::{self, DocCommentsOwner, NameOwner}, | 6 | ast::{self, DocCommentsOwner, NameOwner}, |
@@ -9,8 +9,9 @@ use ra_syntax::{ | |||
9 | SyntaxNode, TextRange, | 9 | SyntaxNode, TextRange, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{db::RootDatabase, expand::original_range, FileSymbol}; | ||
13 | |||
12 | use super::short_label::ShortLabel; | 14 | use super::short_label::ShortLabel; |
13 | use 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,12 +80,12 @@ 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(), |
89 | src.ast.doc_comment_text(), | 90 | src.ast.doc_comment_text(), |
90 | src.ast.short_label(), | 91 | src.ast.short_label(), |
@@ -147,14 +148,15 @@ impl NavigationTarget { | |||
147 | ) -> NavigationTarget { | 148 | ) -> NavigationTarget { |
148 | //FIXME: use `_` instead of empty string | 149 | //FIXME: use `_` instead of empty string |
149 | let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); | 150 | let name = node.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); | 151 | let focus_range = |
151 | let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax()); | 152 | node.name().map(|it| original_range(db, Source::new(file_id, it.syntax())).range); |
153 | let frange = original_range(db, Source::new(file_id, node.syntax())); | ||
152 | 154 | ||
153 | NavigationTarget::from_syntax( | 155 | NavigationTarget::from_syntax( |
154 | file_id, | 156 | frange.file_id, |
155 | name, | 157 | name, |
156 | focus_range, | 158 | focus_range, |
157 | full_range, | 159 | frange.range, |
158 | node.syntax(), | 160 | node.syntax(), |
159 | docs, | 161 | docs, |
160 | description, | 162 | description, |
@@ -230,28 +232,28 @@ impl ToNav for hir::Module { | |||
230 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 232 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
231 | let src = self.definition_source(db); | 233 | let src = self.definition_source(db); |
232 | let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); | 234 | let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); |
233 | match src.ast { | 235 | match &src.ast { |
234 | ModuleSource::SourceFile(node) => { | 236 | ModuleSource::SourceFile(node) => { |
235 | let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); | 237 | let frange = original_range(db, src.with_ast(node.syntax())); |
236 | 238 | ||
237 | NavigationTarget::from_syntax( | 239 | NavigationTarget::from_syntax( |
238 | file_id, | 240 | frange.file_id, |
239 | name, | 241 | name, |
240 | None, | 242 | None, |
241 | text_range, | 243 | frange.range, |
242 | node.syntax(), | 244 | node.syntax(), |
243 | None, | 245 | None, |
244 | None, | 246 | None, |
245 | ) | 247 | ) |
246 | } | 248 | } |
247 | ModuleSource::Module(node) => { | 249 | ModuleSource::Module(node) => { |
248 | let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); | 250 | let frange = original_range(db, src.with_ast(node.syntax())); |
249 | 251 | ||
250 | NavigationTarget::from_syntax( | 252 | NavigationTarget::from_syntax( |
251 | file_id, | 253 | frange.file_id, |
252 | name, | 254 | name, |
253 | None, | 255 | None, |
254 | text_range, | 256 | frange.range, |
255 | node.syntax(), | 257 | node.syntax(), |
256 | node.doc_comment_text(), | 258 | node.doc_comment_text(), |
257 | node.short_label(), | 259 | node.short_label(), |
@@ -264,13 +266,13 @@ impl ToNav for hir::Module { | |||
264 | impl ToNav for hir::ImplBlock { | 266 | impl ToNav for hir::ImplBlock { |
265 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 267 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
266 | let src = self.source(db); | 268 | let src = self.source(db); |
267 | let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax()); | 269 | let frange = original_range(db, src.as_ref().map(|it| it.syntax())); |
268 | 270 | ||
269 | NavigationTarget::from_syntax( | 271 | NavigationTarget::from_syntax( |
270 | file_id, | 272 | frange.file_id, |
271 | "impl".into(), | 273 | "impl".into(), |
272 | None, | 274 | None, |
273 | text_range, | 275 | frange.range, |
274 | src.ast.syntax(), | 276 | src.ast.syntax(), |
275 | None, | 277 | None, |
276 | None, | 278 | None, |
@@ -282,21 +284,21 @@ impl ToNav for hir::StructField { | |||
282 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 284 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
283 | let src = self.source(db); | 285 | let src = self.source(db); |
284 | 286 | ||
285 | match src.ast { | 287 | match &src.ast { |
286 | FieldSource::Named(it) => NavigationTarget::from_named( | 288 | FieldSource::Named(it) => NavigationTarget::from_named( |
287 | db, | 289 | db, |
288 | src.file_id, | 290 | src.file_id, |
289 | &it, | 291 | it, |
290 | it.doc_comment_text(), | 292 | it.doc_comment_text(), |
291 | it.short_label(), | 293 | it.short_label(), |
292 | ), | 294 | ), |
293 | FieldSource::Pos(it) => { | 295 | FieldSource::Pos(it) => { |
294 | let (file_id, text_range) = find_range_from_node(db, src.file_id, it.syntax()); | 296 | let frange = original_range(db, src.with_ast(it.syntax())); |
295 | NavigationTarget::from_syntax( | 297 | NavigationTarget::from_syntax( |
296 | file_id, | 298 | frange.file_id, |
297 | "".into(), | 299 | "".into(), |
298 | None, | 300 | None, |
299 | text_range, | 301 | frange.range, |
300 | it.syntax(), | 302 | it.syntax(), |
301 | None, | 303 | None, |
302 | None, | 304 | None, |
@@ -360,21 +362,6 @@ impl ToNav for hir::Local { | |||
360 | } | 362 | } |
361 | } | 363 | } |
362 | 364 | ||
363 | fn 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 | |||
378 | pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { | 365 | pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { |
379 | let parse = db.parse(symbol.file_id); | 366 | let parse = db.parse(symbol.file_id); |
380 | let node = symbol.ptr.to_node(parse.tree().syntax()); | 367 | 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..5f1fb9a12 --- /dev/null +++ b/crates/ra_ide_api/src/expand.rs | |||
@@ -0,0 +1,42 @@ | |||
1 | //! Utilities to work with files, produced by macros. | ||
2 | use std::iter::successors; | ||
3 | |||
4 | use hir::Source; | ||
5 | use ra_db::FileId; | ||
6 | use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken}; | ||
7 | |||
8 | use crate::{db::RootDatabase, FileRange}; | ||
9 | |||
10 | pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> FileRange { | ||
11 | let text_range = node.ast.text_range(); | ||
12 | let (file_id, range) = node | ||
13 | .file_id | ||
14 | .expansion_info(db) | ||
15 | .and_then(|expansion_info| expansion_info.find_range(text_range)) | ||
16 | .unwrap_or((node.file_id, text_range)); | ||
17 | |||
18 | // FIXME: handle recursive macro generated macro | ||
19 | FileRange { file_id: file_id.original_file(db), range } | ||
20 | } | ||
21 | |||
22 | pub(crate) fn descend_into_macros( | ||
23 | db: &RootDatabase, | ||
24 | file_id: FileId, | ||
25 | token: SyntaxToken, | ||
26 | ) -> Source<SyntaxToken> { | ||
27 | let src = Source::new(file_id.into(), token); | ||
28 | |||
29 | successors(Some(src), |token| { | ||
30 | let macro_call = token.ast.ancestors().find_map(ast::MacroCall::cast)?; | ||
31 | let tt = macro_call.token_tree()?; | ||
32 | if !token.ast.text_range().is_subrange(&tt.syntax().text_range()) { | ||
33 | return None; | ||
34 | } | ||
35 | let source_analyzer = | ||
36 | hir::SourceAnalyzer::new(db, token.with_ast(token.ast.parent()).as_ref(), None); | ||
37 | let exp = source_analyzer.expand(db, ¯o_call)?; | ||
38 | exp.map_token_down(db, token.as_ref()) | ||
39 | }) | ||
40 | .last() | ||
41 | .unwrap() | ||
42 | } | ||
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index b693a4c31..1a8db0ea0 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 | ||
3 | use std::iter::successors; | ||
4 | |||
5 | use hir::{db::AstDatabase, Source}; | 3 | use hir::{db::AstDatabase, Source}; |
6 | use ra_syntax::{ | 4 | use 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 | ||
11 | use crate::{ | 9 | use 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 | ||
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() | ||
58 | } | ||
59 | |||
60 | #[derive(Debug)] | 43 | #[derive(Debug)] |
61 | pub(crate) enum ReferenceResult { | 44 | pub(crate) enum ReferenceResult { |
62 | Exact(NavigationTarget), | 45 | Exact(NavigationTarget), |
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; | |||
41 | mod display; | 41 | mod display; |
42 | mod inlay_hints; | 42 | mod inlay_hints; |
43 | mod wasm_shims; | 43 | mod wasm_shims; |
44 | mod expand; | ||
44 | 45 | ||
45 | #[cfg(test)] | 46 | #[cfg(test)] |
46 | mod marks; | 47 | mod marks; |