diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/expand_macro.rs | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs index 7f39262dc..7dbf33a16 100644 --- a/crates/ra_ide_api/src/expand_macro.rs +++ b/crates/ra_ide_api/src/expand_macro.rs | |||
@@ -84,24 +84,19 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
84 | }; | 84 | }; |
85 | 85 | ||
86 | res += &match token.kind() { | 86 | res += &match token.kind() { |
87 | k @ _ | 87 | k @ _ if is_text(k) && is_next(|it| !it.is_punct(), true) => { |
88 | if (k.is_keyword() || k.is_literal() || k == IDENT) | ||
89 | && is_next(|it| !it.is_punct(), true) => | ||
90 | { | ||
91 | token.text().to_string() + " " | 88 | token.text().to_string() + " " |
92 | } | 89 | } |
93 | L_CURLY if is_next(|it| it != R_CURLY, true) => { | 90 | L_CURLY if is_next(|it| it != R_CURLY, true) => { |
94 | indent += 1; | 91 | indent += 1; |
95 | format!(" {{\n{}", " ".repeat(indent)) | 92 | let leading_space = if is_last(|it| is_text(it), false) { " " } else { "" }; |
93 | format!("{}{{\n{}", leading_space, " ".repeat(indent)) | ||
96 | } | 94 | } |
97 | R_CURLY if is_last(|it| it != L_CURLY, true) => { | 95 | R_CURLY if is_last(|it| it != L_CURLY, true) => { |
98 | indent = indent.checked_sub(1).unwrap_or(0); | 96 | indent = indent.checked_sub(1).unwrap_or(0); |
99 | format!("\n}}{}", " ".repeat(indent)) | 97 | format!("\n{}}}", " ".repeat(indent)) |
100 | } | ||
101 | R_CURLY => { | ||
102 | indent = indent.checked_sub(1).unwrap_or(0); | ||
103 | format!("}}\n{}", " ".repeat(indent)) | ||
104 | } | 98 | } |
99 | R_CURLY => format!("}}\n{}", " ".repeat(indent)), | ||
105 | T![;] => format!(";\n{}", " ".repeat(indent)), | 100 | T![;] => format!(";\n{}", " ".repeat(indent)), |
106 | T![->] => " -> ".to_string(), | 101 | T![->] => " -> ".to_string(), |
107 | T![=] => " = ".to_string(), | 102 | T![=] => " = ".to_string(), |
@@ -112,7 +107,11 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
112 | last = Some(token.kind()); | 107 | last = Some(token.kind()); |
113 | } | 108 | } |
114 | 109 | ||
115 | res | 110 | return res; |
111 | |||
112 | fn is_text(k: SyntaxKind) -> bool { | ||
113 | k.is_keyword() || k.is_literal() || k == IDENT | ||
114 | } | ||
116 | } | 115 | } |
117 | 116 | ||
118 | #[cfg(test)] | 117 | #[cfg(test)] |
@@ -175,4 +174,47 @@ fn some_thing() -> u32 { | |||
175 | } | 174 | } |
176 | "###); | 175 | "###); |
177 | } | 176 | } |
177 | |||
178 | #[test] | ||
179 | fn macro_expand_match_ast() { | ||
180 | let res = check_expand_macro( | ||
181 | r#" | ||
182 | //- /lib.rs | ||
183 | macro_rules! match_ast { | ||
184 | (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; | ||
185 | |||
186 | (match ($node:expr) { | ||
187 | $( ast::$ast:ident($it:ident) => $res:block, )* | ||
188 | _ => $catch_all:expr $(,)? | ||
189 | }) => {{ | ||
190 | $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* | ||
191 | { $catch_all } | ||
192 | }}; | ||
193 | } | ||
194 | |||
195 | fn main() { | ||
196 | mat<|>ch_ast! { | ||
197 | match container { | ||
198 | ast::TraitDef(it) => {}, | ||
199 | ast::ImplBlock(it) => {}, | ||
200 | _ => { continue }, | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | "#, | ||
205 | ); | ||
206 | |||
207 | assert_eq!(res.name, "match_ast"); | ||
208 | assert_snapshot!(res.expansion, @r###" | ||
209 | { | ||
210 | if let Some(it) = ast::TraitDef::cast(container.clone()){} | ||
211 | else if let Some(it) = ast::ImplBlock::cast(container.clone()){} | ||
212 | else { | ||
213 | { | ||
214 | continue | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | "###); | ||
219 | } | ||
178 | } | 220 | } |