diff options
author | Aleksey Kladov <[email protected]> | 2019-01-31 15:51:17 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-31 20:23:30 +0000 |
commit | ad80a0c551458de7d27a98d182d7f559de04f291 (patch) | |
tree | 20a3e85a30a45365fe31360cb57b4f53a17b9a28 | |
parent | 59347388541388347e86de9718bd69994c113203 (diff) |
preserve token spacing
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/macros.rs | 44 | ||||
-rw-r--r-- | crates/ra_macros/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_macros/src/mbe.rs | 2 | ||||
-rw-r--r-- | crates/ra_macros/src/mbe_parser.rs | 8 | ||||
-rw-r--r-- | crates/ra_macros/src/tt.rs | 31 | ||||
-rw-r--r-- | crates/ra_macros/src/tt_cursor.rs | 2 |
7 files changed, 59 insertions, 30 deletions
diff --git a/Cargo.lock b/Cargo.lock index a9bc80c40..b48721622 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1022,7 +1022,6 @@ dependencies = [ | |||
1022 | name = "ra_macros" | 1022 | name = "ra_macros" |
1023 | version = "0.1.0" | 1023 | version = "0.1.0" |
1024 | dependencies = [ | 1024 | dependencies = [ |
1025 | "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||
1026 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1025 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1027 | "smol_str 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", | 1026 | "smol_str 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", |
1028 | ] | 1027 | ] |
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index 059543bf2..e6ba8c08f 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs | |||
@@ -218,14 +218,28 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { | |||
218 | continue; | 218 | continue; |
219 | } | 219 | } |
220 | if child.kind().is_punct() { | 220 | if child.kind().is_punct() { |
221 | let leaves = child | 221 | let mut prev = None; |
222 | .leaf_text() | 222 | for char in child.leaf_text().unwrap().chars() { |
223 | .unwrap() | 223 | if let Some(char) = prev { |
224 | .chars() | 224 | token_trees.push( |
225 | .map(|char| tt::Punct { char }) | 225 | tt::Leaf::from(tt::Punct { |
226 | .map(tt::Leaf::from) | 226 | char, |
227 | .map(tt::TokenTree::from); | 227 | spacing: tt::Spacing::Joint, |
228 | token_trees.extend(leaves); | 228 | }) |
229 | .into(), | ||
230 | ); | ||
231 | } | ||
232 | prev = Some(char) | ||
233 | } | ||
234 | if let Some(char) = prev { | ||
235 | token_trees.push( | ||
236 | tt::Leaf::from(tt::Punct { | ||
237 | char, | ||
238 | spacing: tt::Spacing::Alone, | ||
239 | }) | ||
240 | .into(), | ||
241 | ); | ||
242 | } | ||
229 | } else { | 243 | } else { |
230 | let child: tt::TokenTree = if child.kind() == TOKEN_TREE { | 244 | let child: tt::TokenTree = if child.kind() == TOKEN_TREE { |
231 | convert_tt(child)?.into() | 245 | convert_tt(child)?.into() |
@@ -254,7 +268,7 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { | |||
254 | 268 | ||
255 | #[test] | 269 | #[test] |
256 | fn test_convert_tt() { | 270 | fn test_convert_tt() { |
257 | let macro_defenition = r#" | 271 | let macro_definition = r#" |
258 | macro_rules! impl_froms { | 272 | macro_rules! impl_froms { |
259 | ($e:ident: $($v:ident),*) => { | 273 | ($e:ident: $($v:ident),*) => { |
260 | $( | 274 | $( |
@@ -272,8 +286,8 @@ macro_rules! impl_froms { | |||
272 | impl_froms!(TokenTree: Leaf, Subtree); | 286 | impl_froms!(TokenTree: Leaf, Subtree); |
273 | "#; | 287 | "#; |
274 | 288 | ||
275 | let source_file = ast::SourceFile::parse(macro_defenition); | 289 | let source_file = ast::SourceFile::parse(macro_definition); |
276 | let macro_defenition = source_file | 290 | let macro_definition = source_file |
277 | .syntax() | 291 | .syntax() |
278 | .descendants() | 292 | .descendants() |
279 | .find_map(ast::MacroCall::cast) | 293 | .find_map(ast::MacroCall::cast) |
@@ -286,13 +300,13 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
286 | .find_map(ast::MacroCall::cast) | 300 | .find_map(ast::MacroCall::cast) |
287 | .unwrap(); | 301 | .unwrap(); |
288 | 302 | ||
289 | let defenition_tt = macro_call_to_tt(macro_defenition).unwrap(); | 303 | let definition_tt = macro_call_to_tt(macro_definition).unwrap(); |
290 | let invocation_tt = macro_call_to_tt(macro_invocation).unwrap(); | 304 | let invocation_tt = macro_call_to_tt(macro_invocation).unwrap(); |
291 | let mbe = mbe::parse(&defenition_tt).unwrap(); | 305 | let mbe = mbe::parse(&definition_tt).unwrap(); |
292 | let expansion = mbe::exapnd(&mbe, &invocation_tt).unwrap(); | 306 | let expansion = mbe::exapnd(&mbe, &invocation_tt).unwrap(); |
293 | assert_eq!( | 307 | assert_eq!( |
294 | expansion.to_string(), | 308 | expansion.to_string(), |
295 | "{(impl From < Leaf > for TokenTree {fn from (it : Leaf) - > TokenTree {TokenTree : : Leaf (it)}}) \ | 309 | "{(impl From < Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree :: Leaf (it)}}) \ |
296 | (impl From < Subtree > for TokenTree {fn from (it : Subtree) - > TokenTree {TokenTree : : Subtree (it)}})}" | 310 | (impl From < Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree :: Subtree (it)}})}" |
297 | ) | 311 | ) |
298 | } | 312 | } |
diff --git a/crates/ra_macros/Cargo.toml b/crates/ra_macros/Cargo.toml index 1c9cc9e92..7d3cb055c 100644 --- a/crates/ra_macros/Cargo.toml +++ b/crates/ra_macros/Cargo.toml | |||
@@ -7,4 +7,3 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
7 | [dependencies] | 7 | [dependencies] |
8 | rustc-hash = "1.0.0" | 8 | rustc-hash = "1.0.0" |
9 | smol_str = "0.1.9" | 9 | smol_str = "0.1.9" |
10 | join_to_string = "0.1.3" | ||
diff --git a/crates/ra_macros/src/mbe.rs b/crates/ra_macros/src/mbe.rs index ac76d64e4..d4106a41c 100644 --- a/crates/ra_macros/src/mbe.rs +++ b/crates/ra_macros/src/mbe.rs | |||
@@ -45,7 +45,7 @@ pub(crate) struct Subtree { | |||
45 | pub(crate) struct Repeat { | 45 | pub(crate) struct Repeat { |
46 | pub(crate) subtree: Subtree, | 46 | pub(crate) subtree: Subtree, |
47 | pub(crate) kind: RepeatKind, | 47 | pub(crate) kind: RepeatKind, |
48 | pub(crate) separator: Option<Punct>, | 48 | pub(crate) separator: Option<char>, |
49 | } | 49 | } |
50 | 50 | ||
51 | #[derive(Debug)] | 51 | #[derive(Debug)] |
diff --git a/crates/ra_macros/src/mbe_parser.rs b/crates/ra_macros/src/mbe_parser.rs index 279ab2f25..483594590 100644 --- a/crates/ra_macros/src/mbe_parser.rs +++ b/crates/ra_macros/src/mbe_parser.rs | |||
@@ -28,16 +28,14 @@ fn parse_subtree(tt: &tt::Subtree) -> Option<mbe::Subtree> { | |||
28 | while let Some(tt) = p.eat() { | 28 | while let Some(tt) = p.eat() { |
29 | let child: mbe::TokenTree = match tt { | 29 | let child: mbe::TokenTree = match tt { |
30 | tt::TokenTree::Leaf(leaf) => match leaf { | 30 | tt::TokenTree::Leaf(leaf) => match leaf { |
31 | tt::Leaf::Punct(tt::Punct { char: '$' }) => { | 31 | tt::Leaf::Punct(tt::Punct { char: '$', .. }) => { |
32 | if p.at_ident().is_some() { | 32 | if p.at_ident().is_some() { |
33 | mbe::Leaf::from(parse_var(&mut p)?).into() | 33 | mbe::Leaf::from(parse_var(&mut p)?).into() |
34 | } else { | 34 | } else { |
35 | parse_repeat(&mut p)?.into() | 35 | parse_repeat(&mut p)?.into() |
36 | } | 36 | } |
37 | } | 37 | } |
38 | tt::Leaf::Punct(tt::Punct { char }) => { | 38 | tt::Leaf::Punct(punct) => mbe::Leaf::from(*punct).into(), |
39 | mbe::Leaf::from(mbe::Punct { char: *char }).into() | ||
40 | } | ||
41 | tt::Leaf::Ident(tt::Ident { text }) => { | 39 | tt::Leaf::Ident(tt::Ident { text }) => { |
42 | mbe::Leaf::from(mbe::Ident { text: text.clone() }).into() | 40 | mbe::Leaf::from(mbe::Ident { text: text.clone() }).into() |
43 | } | 41 | } |
@@ -78,7 +76,7 @@ fn parse_repeat(p: &mut TtCursor) -> Option<mbe::Repeat> { | |||
78 | let sep = p.eat_punct()?; | 76 | let sep = p.eat_punct()?; |
79 | let (separator, rep) = match sep.char { | 77 | let (separator, rep) = match sep.char { |
80 | '*' | '+' | '?' => (None, sep.char), | 78 | '*' | '+' | '?' => (None, sep.char), |
81 | char => (Some(mbe::Punct { char }), p.eat_punct()?.char), | 79 | char => (Some(char), p.eat_punct()?.char), |
82 | }; | 80 | }; |
83 | 81 | ||
84 | let kind = match rep { | 82 | let kind = match rep { |
diff --git a/crates/ra_macros/src/tt.rs b/crates/ra_macros/src/tt.rs index 56e930f00..2855bae51 100644 --- a/crates/ra_macros/src/tt.rs +++ b/crates/ra_macros/src/tt.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use std::fmt; | 1 | use std::fmt; |
2 | 2 | ||
3 | use smol_str::SmolStr; | 3 | use smol_str::SmolStr; |
4 | use join_to_string::join; | ||
5 | 4 | ||
6 | #[derive(Debug, Clone)] | 5 | #[derive(Debug, Clone)] |
7 | pub enum TokenTree { | 6 | pub enum TokenTree { |
@@ -37,9 +36,16 @@ pub struct Literal { | |||
37 | pub text: SmolStr, | 36 | pub text: SmolStr, |
38 | } | 37 | } |
39 | 38 | ||
40 | #[derive(Debug, Clone, PartialEq, Eq)] | 39 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
41 | pub struct Punct { | 40 | pub struct Punct { |
42 | pub char: char, | 41 | pub char: char, |
42 | pub spacing: Spacing, | ||
43 | } | ||
44 | |||
45 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
46 | pub enum Spacing { | ||
47 | Alone, | ||
48 | Joint, | ||
43 | } | 49 | } |
44 | 50 | ||
45 | #[derive(Debug, Clone)] | 51 | #[derive(Debug, Clone)] |
@@ -64,10 +70,23 @@ impl fmt::Display for Subtree { | |||
64 | Delimiter::Bracket => ("[", "]"), | 70 | Delimiter::Bracket => ("[", "]"), |
65 | Delimiter::None => ("", ""), | 71 | Delimiter::None => ("", ""), |
66 | }; | 72 | }; |
67 | join(self.token_trees.iter()) | 73 | f.write_str(l)?; |
68 | .separator(" ") | 74 | let mut needs_space = false; |
69 | .surround_with(l, r) | 75 | for tt in self.token_trees.iter() { |
70 | .to_fmt(f) | 76 | if needs_space { |
77 | f.write_str(" ")?; | ||
78 | } | ||
79 | needs_space = true; | ||
80 | match tt { | ||
81 | TokenTree::Leaf(Leaf::Punct(p)) => { | ||
82 | needs_space = p.spacing == Spacing::Alone; | ||
83 | fmt::Display::fmt(p, f)? | ||
84 | } | ||
85 | tt => fmt::Display::fmt(tt, f)?, | ||
86 | } | ||
87 | } | ||
88 | f.write_str(r)?; | ||
89 | Ok(()) | ||
71 | } | 90 | } |
72 | } | 91 | } |
73 | 92 | ||
diff --git a/crates/ra_macros/src/tt_cursor.rs b/crates/ra_macros/src/tt_cursor.rs index 6dc9f400d..046770a0f 100644 --- a/crates/ra_macros/src/tt_cursor.rs +++ b/crates/ra_macros/src/tt_cursor.rs | |||
@@ -28,7 +28,7 @@ impl<'a> TtCursor<'a> { | |||
28 | 28 | ||
29 | pub(crate) fn at_char(&self, char: char) -> bool { | 29 | pub(crate) fn at_char(&self, char: char) -> bool { |
30 | match self.at_punct() { | 30 | match self.at_punct() { |
31 | Some(tt::Punct { char: c }) if *c == char => true, | 31 | Some(tt::Punct { char: c, .. }) if *c == char => true, |
32 | _ => false, | 32 | _ => false, |
33 | } | 33 | } |
34 | } | 34 | } |