aboutsummaryrefslogtreecommitdiff
path: root/crates/proc_macro_srv
diff options
context:
space:
mode:
authorKevin Mehall <[email protected]>2021-03-06 16:46:32 +0000
committerKevin Mehall <[email protected]>2021-03-06 16:48:30 +0000
commit62f594b390e5f648a32b5b08863a6413b4271d19 (patch)
tree47de88bc047e957149544f48f2696f2706b9ed4b /crates/proc_macro_srv
parent632fa8ef4a3c9e7440b79e04a9f7dd9bd23a4de4 (diff)
Refactor TokenStream to hold Vec<TokenTree> instead of tt::Subtree
`TokenStream` assumes that its subtree's delimeter is `None`, and this should be encoded in the type system instead of having a delimiter field that is mostly ignored. `tt::Subtree` is just `pub delimiter: Option<Delimiter>, pub token_trees: Vec<TokenTree>`, so a Subtree that is statically guaranteed not to have a delimiter is just Vec<TokenTree>.
Diffstat (limited to 'crates/proc_macro_srv')
-rw-r--r--crates/proc_macro_srv/src/dylib.rs6
-rw-r--r--crates/proc_macro_srv/src/rustc_server.rs113
-rw-r--r--crates/proc_macro_srv/src/tests/utils.rs2
3 files changed, 56 insertions, 65 deletions
diff --git a/crates/proc_macro_srv/src/dylib.rs b/crates/proc_macro_srv/src/dylib.rs
index 28a6ee547..baf10fea9 100644
--- a/crates/proc_macro_srv/src/dylib.rs
+++ b/crates/proc_macro_srv/src/dylib.rs
@@ -138,7 +138,7 @@ impl Expander {
138 parsed_body, 138 parsed_body,
139 false, 139 false,
140 ); 140 );
141 return res.map(|it| it.subtree); 141 return res.map(|it| it.into_subtree());
142 } 142 }
143 bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { 143 bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
144 let res = client.run( 144 let res = client.run(
@@ -147,7 +147,7 @@ impl Expander {
147 parsed_body, 147 parsed_body,
148 false, 148 false,
149 ); 149 );
150 return res.map(|it| it.subtree); 150 return res.map(|it| it.into_subtree());
151 } 151 }
152 bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { 152 bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
153 let res = client.run( 153 let res = client.run(
@@ -157,7 +157,7 @@ impl Expander {
157 parsed_body, 157 parsed_body,
158 false, 158 false,
159 ); 159 );
160 return res.map(|it| it.subtree); 160 return res.map(|it| it.into_subtree());
161 } 161 }
162 _ => continue, 162 _ => continue,
163 } 163 }
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs
index f02b0af60..2798dbf0d 100644
--- a/crates/proc_macro_srv/src/rustc_server.rs
+++ b/crates/proc_macro_srv/src/rustc_server.rs
@@ -25,36 +25,35 @@ type Span = tt::TokenId;
25 25
26#[derive(Debug, Clone)] 26#[derive(Debug, Clone)]
27pub struct TokenStream { 27pub struct TokenStream {
28 pub subtree: tt::Subtree, 28 pub token_trees: Vec<TokenTree>,
29} 29}
30 30
31impl TokenStream { 31impl TokenStream {
32 pub fn new() -> Self { 32 pub fn new() -> Self {
33 TokenStream { subtree: Default::default() } 33 TokenStream { token_trees: Default::default() }
34 } 34 }
35 35
36 pub fn with_subtree(subtree: tt::Subtree) -> Self { 36 pub fn with_subtree(subtree: tt::Subtree) -> Self {
37 if subtree.delimiter.is_some() { 37 if subtree.delimiter.is_some() {
38 TokenStream { 38 TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
39 subtree: tt::Subtree {
40 token_trees: vec![TokenTree::Subtree(subtree)],
41 delimiter: None,
42 },
43 }
44 } else { 39 } else {
45 TokenStream { subtree } 40 TokenStream { token_trees: subtree.token_trees }
46 } 41 }
47 } 42 }
48 43
44 pub fn into_subtree(self) -> tt::Subtree {
45 tt::Subtree { delimiter: None, token_trees: self.token_trees }
46 }
47
49 pub fn is_empty(&self) -> bool { 48 pub fn is_empty(&self) -> bool {
50 self.subtree.token_trees.is_empty() 49 self.token_trees.is_empty()
51 } 50 }
52} 51}
53 52
54/// Creates a token stream containing a single token tree. 53/// Creates a token stream containing a single token tree.
55impl From<TokenTree> for TokenStream { 54impl From<TokenTree> for TokenStream {
56 fn from(tree: TokenTree) -> TokenStream { 55 fn from(tree: TokenTree) -> TokenStream {
57 TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } } 56 TokenStream { token_trees: vec![tree] }
58 } 57 }
59} 58}
60 59
@@ -87,10 +86,10 @@ impl Extend<TokenStream> for TokenStream {
87 for tkn in item { 86 for tkn in item {
88 match tkn { 87 match tkn {
89 tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => { 88 tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
90 self.subtree.token_trees.extend(subtree.token_trees); 89 self.token_trees.extend(subtree.token_trees);
91 } 90 }
92 _ => { 91 _ => {
93 self.subtree.token_trees.push(tkn); 92 self.token_trees.push(tkn);
94 } 93 }
95 } 94 }
96 } 95 }
@@ -173,7 +172,7 @@ pub mod token_stream {
173 type IntoIter = super::IntoIter<TokenTree>; 172 type IntoIter = super::IntoIter<TokenTree>;
174 173
175 fn into_iter(self) -> Self::IntoIter { 174 fn into_iter(self) -> Self::IntoIter {
176 self.subtree.token_trees.into_iter() 175 self.token_trees.into_iter()
177 } 176 }
178 } 177 }
179 178
@@ -200,32 +199,32 @@ pub mod token_stream {
200 199
201 impl ToString for TokenStream { 200 impl ToString for TokenStream {
202 fn to_string(&self) -> String { 201 fn to_string(&self) -> String {
203 let tt = self.subtree.clone().into(); 202 tokentrees_to_text(&self.token_trees[..])
204 to_text(&tt)
205 } 203 }
206 } 204 }
207 205
208 fn to_text(tkn: &tt::TokenTree) -> String { 206 fn tokentrees_to_text(tkns: &[tt::TokenTree]) -> String {
207 tkns.iter()
208 .fold((String::new(), true), |(last, last_to_joint), tkn| {
209 let s = [last, tokentree_to_text(tkn)].join(if last_to_joint { "" } else { " " });
210 let mut is_joint = false;
211 if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
212 if punct.spacing == tt::Spacing::Joint {
213 is_joint = true;
214 }
215 }
216 (s, is_joint)
217 })
218 .0
219 }
220
221 fn tokentree_to_text(tkn: &tt::TokenTree) -> String {
209 match tkn { 222 match tkn {
210 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(), 223 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
211 tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(), 224 tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
212 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char), 225 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
213 tt::TokenTree::Subtree(subtree) => { 226 tt::TokenTree::Subtree(subtree) => {
214 let content = subtree 227 let content = tokentrees_to_text(&subtree.token_trees);
215 .token_trees
216 .iter()
217 .fold((String::new(), true), |(last, last_to_joint), tkn| {
218 let s = [last, to_text(tkn)].join(if last_to_joint { "" } else { " " });
219 let mut is_joint = false;
220 if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
221 if punct.spacing == tt::Spacing::Joint {
222 is_joint = true;
223 }
224 }
225 (s, is_joint)
226 })
227 .0;
228
229 let (open, close) = match subtree.delimiter.map(|it| it.kind) { 228 let (open, close) = match subtree.delimiter.map(|it| it.kind) {
230 None => ("", ""), 229 None => ("", ""),
231 Some(tt::DelimiterKind::Brace) => ("{", "}"), 230 Some(tt::DelimiterKind::Brace) => ("{", "}"),
@@ -442,10 +441,7 @@ fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
442 441
443impl server::Group for Rustc { 442impl server::Group for Rustc {
444 fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group { 443 fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group {
445 Self::Group { 444 Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees }
446 delimiter: delim_to_internal(delimiter),
447 token_trees: stream.subtree.token_trees,
448 }
449 } 445 }
450 fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter { 446 fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
451 delim_to_external(group.delimiter) 447 delim_to_external(group.delimiter)
@@ -453,9 +449,7 @@ impl server::Group for Rustc {
453 449
454 // NOTE: Return value of do not include delimiter 450 // NOTE: Return value of do not include delimiter
455 fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { 451 fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
456 TokenStream { 452 TokenStream { token_trees: group.token_trees.clone() }
457 subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() },
458 }
459 } 453 }
460 454
461 fn span(&mut self, group: &Self::Group) -> Self::Span { 455 fn span(&mut self, group: &Self::Group) -> Self::Span {
@@ -764,26 +758,23 @@ mod tests {
764 #[test] 758 #[test]
765 fn test_rustc_server_to_string() { 759 fn test_rustc_server_to_string() {
766 let s = TokenStream { 760 let s = TokenStream {
767 subtree: tt::Subtree { 761 token_trees: vec![
768 delimiter: None, 762 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
769 token_trees: vec![ 763 text: "struct".into(),
770 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { 764 id: tt::TokenId::unspecified(),
771 text: "struct".into(), 765 })),
772 id: tt::TokenId::unspecified(), 766 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
773 })), 767 text: "T".into(),
774 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { 768 id: tt::TokenId::unspecified(),
775 text: "T".into(), 769 })),
770 tt::TokenTree::Subtree(tt::Subtree {
771 delimiter: Some(tt::Delimiter {
776 id: tt::TokenId::unspecified(), 772 id: tt::TokenId::unspecified(),
777 })), 773 kind: tt::DelimiterKind::Brace,
778 tt::TokenTree::Subtree(tt::Subtree {
779 delimiter: Some(tt::Delimiter {
780 id: tt::TokenId::unspecified(),
781 kind: tt::DelimiterKind::Brace,
782 }),
783 token_trees: vec![],
784 }), 774 }),
785 ], 775 token_trees: vec![],
786 }, 776 }),
777 ],
787 }; 778 };
788 779
789 assert_eq!(s.to_string(), "struct T {}"); 780 assert_eq!(s.to_string(), "struct T {}");
@@ -804,11 +795,11 @@ mod tests {
804 }); 795 });
805 796
806 let t1 = TokenStream::from_str("(a)").unwrap(); 797 let t1 = TokenStream::from_str("(a)").unwrap();
807 assert_eq!(t1.subtree.token_trees.len(), 1); 798 assert_eq!(t1.token_trees.len(), 1);
808 assert_eq!(t1.subtree.token_trees[0], subtree_paren_a); 799 assert_eq!(t1.token_trees[0], subtree_paren_a);
809 800
810 let t2 = TokenStream::from_str("(a);").unwrap(); 801 let t2 = TokenStream::from_str("(a);").unwrap();
811 assert_eq!(t2.subtree.token_trees.len(), 2); 802 assert_eq!(t2.token_trees.len(), 2);
812 assert_eq!(t2.subtree.token_trees[0], subtree_paren_a); 803 assert_eq!(t2.token_trees[0], subtree_paren_a);
813 } 804 }
814} 805}
diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs
index 22813052d..0484c3af4 100644
--- a/crates/proc_macro_srv/src/tests/utils.rs
+++ b/crates/proc_macro_srv/src/tests/utils.rs
@@ -52,7 +52,7 @@ pub fn assert_expand(
52 let expander = dylib::Expander::new(&path).unwrap(); 52 let expander = dylib::Expander::new(&path).unwrap();
53 let fixture = parse_string(ra_fixture).unwrap(); 53 let fixture = parse_string(ra_fixture).unwrap();
54 54
55 let res = expander.expand(macro_name, &fixture.subtree, None).unwrap(); 55 let res = expander.expand(macro_name, &fixture.into_subtree(), None).unwrap();
56 assert_eq_text!(&expect.trim(), &format!("{:?}", res)); 56 assert_eq_text!(&expect.trim(), &format!("{:?}", res));
57} 57}
58 58