diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/expand_macro.rs | 79 |
2 files changed, 40 insertions, 46 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 6d75296a5..5d3196c2a 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -140,12 +140,7 @@ impl Expansion { | |||
140 | exp_info.map_token_down(token) | 140 | exp_info.map_token_down(token) |
141 | } | 141 | } |
142 | 142 | ||
143 | pub fn source(&self, db: &impl HirDatabase) -> Source<AstId<ast::MacroCall>> { | 143 | pub fn file_id(&self) -> HirFileId { |
144 | let loc = db.lookup_intern_macro(self.macro_call_id); | ||
145 | Source::new(self.file_id(), loc.ast_id) | ||
146 | } | ||
147 | |||
148 | fn file_id(&self) -> HirFileId { | ||
149 | self.macro_call_id.as_file(MacroFileKind::Items) | 144 | self.macro_call_id.as_file(MacroFileKind::Items) |
150 | } | 145 | } |
151 | } | 146 | } |
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs index 49c096ed5..bd557d455 100644 --- a/crates/ra_ide_api/src/expand_macro.rs +++ b/crates/ra_ide_api/src/expand_macro.rs | |||
@@ -11,33 +11,20 @@ use ra_syntax::{ | |||
11 | AstNode, NodeOrToken, SyntaxKind, SyntaxNode, WalkEvent, | 11 | AstNode, NodeOrToken, SyntaxKind, SyntaxNode, WalkEvent, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | fn insert_whitespaces(syn: SyntaxNode) -> String { | 14 | pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<(String, String)> { |
15 | let mut res = String::new(); | 15 | let parse = db.parse(position.file_id); |
16 | 16 | let file = parse.tree(); | |
17 | let mut token_iter = syn | 17 | let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset)?; |
18 | .preorder_with_tokens() | 18 | let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?; |
19 | .filter_map(|event| { | ||
20 | if let WalkEvent::Enter(NodeOrToken::Token(token)) = event { | ||
21 | Some(token) | ||
22 | } else { | ||
23 | None | ||
24 | } | ||
25 | }) | ||
26 | .peekable(); | ||
27 | 19 | ||
28 | while let Some(token) = token_iter.next() { | 20 | let source = hir::Source::new(position.file_id.into(), mac.syntax()); |
29 | res += &token.text().to_string(); | 21 | let expanded = expand_macro_recur(db, source, &mac)?; |
30 | if token.kind().is_keyword() | ||
31 | || token.kind().is_literal() | ||
32 | || token.kind() == SyntaxKind::IDENT | ||
33 | { | ||
34 | if !token_iter.peek().map(|it| it.kind().is_punct()).unwrap_or(false) { | ||
35 | res += " "; | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | 22 | ||
40 | res | 23 | // FIXME: |
24 | // macro expansion may lose all white space information | ||
25 | // But we hope someday we can use ra_fmt for that | ||
26 | let res = insert_whitespaces(expanded); | ||
27 | Some((name_ref.text().to_string(), res)) | ||
41 | } | 28 | } |
42 | 29 | ||
43 | fn expand_macro_recur( | 30 | fn expand_macro_recur( |
@@ -47,14 +34,14 @@ fn expand_macro_recur( | |||
47 | ) -> Option<SyntaxNode> { | 34 | ) -> Option<SyntaxNode> { |
48 | let analyzer = hir::SourceAnalyzer::new(db, source, None); | 35 | let analyzer = hir::SourceAnalyzer::new(db, source, None); |
49 | let expansion = analyzer.expand(db, ¯o_call)?; | 36 | let expansion = analyzer.expand(db, ¯o_call)?; |
50 | let new_source = expansion.source(db); | 37 | let macro_file_id = expansion.file_id(); |
51 | let expanded: SyntaxNode = db.parse_or_expand(new_source.file_id)?; | 38 | let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?; |
52 | 39 | ||
53 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); | 40 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); |
54 | let mut replaces = FxHashMap::default(); | 41 | let mut replaces = FxHashMap::default(); |
55 | 42 | ||
56 | for child in children.into_iter() { | 43 | for child in children.into_iter() { |
57 | let source = new_source.with_ast(source.ast); | 44 | let source = hir::Source::new(macro_file_id, source.ast); |
58 | let new_node = expand_macro_recur(db, source, &child)?; | 45 | let new_node = expand_macro_recur(db, source, &child)?; |
59 | 46 | ||
60 | replaces.insert(child.syntax().clone().into(), new_node.into()); | 47 | replaces.insert(child.syntax().clone().into(), new_node.into()); |
@@ -63,21 +50,33 @@ fn expand_macro_recur( | |||
63 | Some(replace_descendants(&expanded, &replaces)) | 50 | Some(replace_descendants(&expanded, &replaces)) |
64 | } | 51 | } |
65 | 52 | ||
66 | pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<(String, String)> { | 53 | fn insert_whitespaces(syn: SyntaxNode) -> String { |
67 | let parse = db.parse(position.file_id); | 54 | let mut res = String::new(); |
68 | let file = parse.tree(); | ||
69 | let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset)?; | ||
70 | let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?; | ||
71 | 55 | ||
72 | let source = hir::Source::new(position.file_id.into(), mac.syntax()); | 56 | let mut token_iter = syn |
57 | .preorder_with_tokens() | ||
58 | .filter_map(|event| { | ||
59 | if let WalkEvent::Enter(NodeOrToken::Token(token)) = event { | ||
60 | Some(token) | ||
61 | } else { | ||
62 | None | ||
63 | } | ||
64 | }) | ||
65 | .peekable(); | ||
73 | 66 | ||
74 | let expanded = expand_macro_recur(db, source, &mac)?; | 67 | while let Some(token) = token_iter.next() { |
68 | res += &token.text().to_string(); | ||
69 | if token.kind().is_keyword() | ||
70 | || token.kind().is_literal() | ||
71 | || token.kind() == SyntaxKind::IDENT | ||
72 | { | ||
73 | if !token_iter.peek().map(|it| it.kind().is_punct()).unwrap_or(false) { | ||
74 | res += " "; | ||
75 | } | ||
76 | } | ||
77 | } | ||
75 | 78 | ||
76 | // FIXME: | 79 | res |
77 | // macro expansion may lose all white space information | ||
78 | // But we hope someday we can use ra_fmt for that | ||
79 | let res = insert_whitespaces(expanded); | ||
80 | Some((name_ref.text().to_string(), res)) | ||
81 | } | 80 | } |
82 | 81 | ||
83 | #[cfg(test)] | 82 | #[cfg(test)] |