aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/expand_macro.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-02-18 17:35:10 +0000
committerAleksey Kladov <[email protected]>2020-02-26 11:55:50 +0000
commitc3a4c4429de83450654795534e64e878a774a088 (patch)
tree12d89798f61b276f8bd640db07276a7d4e92b1c2 /crates/ra_ide/src/expand_macro.rs
parent04deae3dba7c9b7054f7a1d64e4b93a05aecc132 (diff)
Refactor primary IDE API
This introduces the new type -- Semantics. Semantics maps SyntaxNodes to various semantic info, such as type, name resolution or macro expansions. To do so, Semantics maintains a HashMap which maps every node it saw to the file from which the node originated. This is enough to get all the necessary hir bits just from syntax.
Diffstat (limited to 'crates/ra_ide/src/expand_macro.rs')
-rw-r--r--crates/ra_ide/src/expand_macro.rs29
1 files changed, 12 insertions, 17 deletions
diff --git a/crates/ra_ide/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs
index af2783bef..f2814e684 100644
--- a/crates/ra_ide/src/expand_macro.rs
+++ b/crates/ra_ide/src/expand_macro.rs
@@ -1,7 +1,6 @@
1//! This modules implements "expand macro" functionality in the IDE 1//! This modules implements "expand macro" functionality in the IDE
2 2
3use hir::db::AstDatabase; 3use hir::Semantics;
4use ra_db::SourceDatabase;
5use ra_ide_db::RootDatabase; 4use ra_ide_db::RootDatabase;
6use ra_syntax::{ 5use ra_syntax::{
7 algo::{find_node_at_offset, replace_descendants}, 6 algo::{find_node_at_offset, replace_descendants},
@@ -17,13 +16,12 @@ pub struct ExpandedMacro {
17} 16}
18 17
19pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> { 18pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> {
20 let parse = db.parse(position.file_id); 19 let sema = Semantics::new(db);
21 let file = parse.tree(); 20 let file = sema.parse(position.file_id);
22 let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset)?; 21 let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset)?;
23 let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?; 22 let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?;
24 23
25 let source = hir::InFile::new(position.file_id.into(), mac.syntax()); 24 let expanded = expand_macro_recur(&sema, &mac)?;
26 let expanded = expand_macro_recur(db, source, source.with_value(&mac))?;
27 25
28 // FIXME: 26 // FIXME:
29 // macro expansion may lose all white space information 27 // macro expansion may lose all white space information
@@ -33,21 +31,16 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
33} 31}
34 32
35fn expand_macro_recur( 33fn expand_macro_recur(
36 db: &RootDatabase, 34 sema: &Semantics<RootDatabase>,
37 source: hir::InFile<&SyntaxNode>, 35 macro_call: &ast::MacroCall,
38 macro_call: hir::InFile<&ast::MacroCall>,
39) -> Option<SyntaxNode> { 36) -> Option<SyntaxNode> {
40 let analyzer = hir::SourceAnalyzer::new(db, source, None); 37 let mut expanded = sema.expand(macro_call)?;
41 let expansion = analyzer.expand(db, macro_call)?;
42 let macro_file_id = expansion.file_id();
43 let mut expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?;
44 38
45 let children = expanded.descendants().filter_map(ast::MacroCall::cast); 39 let children = expanded.descendants().filter_map(ast::MacroCall::cast);
46 let mut replaces: FxHashMap<SyntaxElement, SyntaxElement> = FxHashMap::default(); 40 let mut replaces: FxHashMap<SyntaxElement, SyntaxElement> = FxHashMap::default();
47 41
48 for child in children.into_iter() { 42 for child in children.into_iter() {
49 let node = hir::InFile::new(macro_file_id, &child); 43 if let Some(new_node) = expand_macro_recur(sema, &child) {
50 if let Some(new_node) = expand_macro_recur(db, source, node) {
51 // Replace the whole node if it is root 44 // Replace the whole node if it is root
52 // `replace_descendants` will not replace the parent node 45 // `replace_descendants` will not replace the parent node
53 // but `SyntaxNode::descendants include itself 46 // but `SyntaxNode::descendants include itself
@@ -120,10 +113,12 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
120 113
121#[cfg(test)] 114#[cfg(test)]
122mod tests { 115mod tests {
123 use super::*;
124 use crate::mock_analysis::analysis_and_position;
125 use insta::assert_snapshot; 116 use insta::assert_snapshot;
126 117
118 use crate::mock_analysis::analysis_and_position;
119
120 use super::*;
121
127 fn check_expand_macro(fixture: &str) -> ExpandedMacro { 122 fn check_expand_macro(fixture: &str) -> ExpandedMacro {
128 let (analysis, pos) = analysis_and_position(fixture); 123 let (analysis, pos) = analysis_and_position(fixture);
129 analysis.expand_macro(pos).unwrap().unwrap() 124 analysis.expand_macro(pos).unwrap().unwrap()