diff options
Diffstat (limited to 'crates/ra_ide_api/src/expand.rs')
-rw-r--r-- | crates/ra_ide_api/src/expand.rs | 42 |
1 files changed, 42 insertions, 0 deletions
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 | } | ||