diff options
Diffstat (limited to 'crates/proc_macro_srv/src/rustc_server.rs')
-rw-r--r-- | crates/proc_macro_srv/src/rustc_server.rs | 183 |
1 files changed, 125 insertions, 58 deletions
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs index a8504f762..ceefd187d 100644 --- a/crates/proc_macro_srv/src/rustc_server.rs +++ b/crates/proc_macro_srv/src/rustc_server.rs | |||
@@ -14,7 +14,6 @@ use std::collections::HashMap; | |||
14 | use std::hash::Hash; | 14 | use std::hash::Hash; |
15 | use std::iter::FromIterator; | 15 | use std::iter::FromIterator; |
16 | use std::ops::Bound; | 16 | use std::ops::Bound; |
17 | use std::str::FromStr; | ||
18 | use std::{ascii, vec::IntoIter}; | 17 | use std::{ascii, vec::IntoIter}; |
19 | 18 | ||
20 | type Group = tt::Subtree; | 19 | type Group = tt::Subtree; |
@@ -26,27 +25,35 @@ type Span = tt::TokenId; | |||
26 | 25 | ||
27 | #[derive(Debug, Clone)] | 26 | #[derive(Debug, Clone)] |
28 | pub struct TokenStream { | 27 | pub struct TokenStream { |
29 | pub subtree: tt::Subtree, | 28 | pub token_trees: Vec<TokenTree>, |
30 | } | 29 | } |
31 | 30 | ||
32 | impl TokenStream { | 31 | impl TokenStream { |
33 | pub fn new() -> Self { | 32 | pub fn new() -> Self { |
34 | TokenStream { subtree: Default::default() } | 33 | TokenStream { token_trees: Default::default() } |
35 | } | 34 | } |
36 | 35 | ||
37 | pub fn with_subtree(subtree: tt::Subtree) -> Self { | 36 | pub fn with_subtree(subtree: tt::Subtree) -> Self { |
38 | TokenStream { subtree } | 37 | if subtree.delimiter.is_some() { |
38 | TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] } | ||
39 | } else { | ||
40 | TokenStream { token_trees: subtree.token_trees } | ||
41 | } | ||
42 | } | ||
43 | |||
44 | pub fn into_subtree(self) -> tt::Subtree { | ||
45 | tt::Subtree { delimiter: None, token_trees: self.token_trees } | ||
39 | } | 46 | } |
40 | 47 | ||
41 | pub fn is_empty(&self) -> bool { | 48 | pub fn is_empty(&self) -> bool { |
42 | self.subtree.token_trees.is_empty() | 49 | self.token_trees.is_empty() |
43 | } | 50 | } |
44 | } | 51 | } |
45 | 52 | ||
46 | /// Creates a token stream containing a single token tree. | 53 | /// Creates a token stream containing a single token tree. |
47 | impl From<TokenTree> for TokenStream { | 54 | impl From<TokenTree> for TokenStream { |
48 | fn from(tree: TokenTree) -> TokenStream { | 55 | fn from(tree: TokenTree) -> TokenStream { |
49 | TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } } | 56 | TokenStream { token_trees: vec![tree] } |
50 | } | 57 | } |
51 | } | 58 | } |
52 | 59 | ||
@@ -79,10 +86,10 @@ impl Extend<TokenStream> for TokenStream { | |||
79 | for tkn in item { | 86 | for tkn in item { |
80 | match tkn { | 87 | match tkn { |
81 | tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => { | 88 | tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => { |
82 | self.subtree.token_trees.extend(subtree.token_trees); | 89 | self.token_trees.extend(subtree.token_trees); |
83 | } | 90 | } |
84 | _ => { | 91 | _ => { |
85 | self.subtree.token_trees.push(tkn); | 92 | self.token_trees.push(tkn); |
86 | } | 93 | } |
87 | } | 94 | } |
88 | } | 95 | } |
@@ -165,7 +172,7 @@ pub mod token_stream { | |||
165 | type IntoIter = super::IntoIter<TokenTree>; | 172 | type IntoIter = super::IntoIter<TokenTree>; |
166 | 173 | ||
167 | fn into_iter(self) -> Self::IntoIter { | 174 | fn into_iter(self) -> Self::IntoIter { |
168 | self.subtree.token_trees.into_iter() | 175 | self.token_trees.into_iter() |
169 | } | 176 | } |
170 | } | 177 | } |
171 | 178 | ||
@@ -185,28 +192,23 @@ pub mod token_stream { | |||
185 | let (subtree, _token_map) = | 192 | let (subtree, _token_map) = |
186 | mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?; | 193 | mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?; |
187 | 194 | ||
188 | Ok(TokenStream { subtree }) | 195 | let subtree = subtree_replace_token_ids_with_unspecified(subtree); |
196 | Ok(TokenStream::with_subtree(subtree)) | ||
189 | } | 197 | } |
190 | } | 198 | } |
191 | 199 | ||
192 | impl ToString for TokenStream { | 200 | impl ToString for TokenStream { |
193 | fn to_string(&self) -> String { | 201 | fn to_string(&self) -> String { |
194 | let tt = self.subtree.clone().into(); | 202 | return tokentrees_to_text(&self.token_trees[..]); |
195 | to_text(&tt) | ||
196 | } | ||
197 | } | ||
198 | 203 | ||
199 | fn to_text(tkn: &tt::TokenTree) -> String { | 204 | fn tokentrees_to_text(tkns: &[tt::TokenTree]) -> String { |
200 | match tkn { | 205 | tkns.iter() |
201 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(), | ||
202 | tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(), | ||
203 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char), | ||
204 | tt::TokenTree::Subtree(subtree) => { | ||
205 | let content = subtree | ||
206 | .token_trees | ||
207 | .iter() | ||
208 | .fold((String::new(), true), |(last, last_to_joint), tkn| { | 206 | .fold((String::new(), true), |(last, last_to_joint), tkn| { |
209 | let s = [last, to_text(tkn)].join(if last_to_joint { "" } else { " " }); | 207 | let s = [last, tokentree_to_text(tkn)].join(if last_to_joint { |
208 | "" | ||
209 | } else { | ||
210 | " " | ||
211 | }); | ||
210 | let mut is_joint = false; | 212 | let mut is_joint = false; |
211 | if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn { | 213 | if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn { |
212 | if punct.spacing == tt::Spacing::Joint { | 214 | if punct.spacing == tt::Spacing::Joint { |
@@ -215,15 +217,63 @@ pub mod token_stream { | |||
215 | } | 217 | } |
216 | (s, is_joint) | 218 | (s, is_joint) |
217 | }) | 219 | }) |
218 | .0; | 220 | .0 |
219 | 221 | } | |
220 | let (open, close) = match subtree.delimiter.map(|it| it.kind) { | 222 | |
221 | None => ("", ""), | 223 | fn tokentree_to_text(tkn: &tt::TokenTree) -> String { |
222 | Some(tt::DelimiterKind::Brace) => ("{", "}"), | 224 | match tkn { |
223 | Some(tt::DelimiterKind::Parenthesis) => ("(", ")"), | 225 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(), |
224 | Some(tt::DelimiterKind::Bracket) => ("[", "]"), | 226 | tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(), |
225 | }; | 227 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char), |
226 | format!("{}{}{}", open, content, close) | 228 | tt::TokenTree::Subtree(subtree) => { |
229 | let content = tokentrees_to_text(&subtree.token_trees); | ||
230 | let (open, close) = match subtree.delimiter.map(|it| it.kind) { | ||
231 | None => ("", ""), | ||
232 | Some(tt::DelimiterKind::Brace) => ("{", "}"), | ||
233 | Some(tt::DelimiterKind::Parenthesis) => ("(", ")"), | ||
234 | Some(tt::DelimiterKind::Bracket) => ("[", "]"), | ||
235 | }; | ||
236 | format!("{}{}{}", open, content, close) | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree { | ||
244 | tt::Subtree { | ||
245 | delimiter: subtree | ||
246 | .delimiter | ||
247 | .map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }), | ||
248 | token_trees: subtree | ||
249 | .token_trees | ||
250 | .into_iter() | ||
251 | .map(|t| token_tree_replace_token_ids_with_unspecified(t)) | ||
252 | .collect(), | ||
253 | } | ||
254 | } | ||
255 | |||
256 | fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree { | ||
257 | match tt { | ||
258 | tt::TokenTree::Leaf(leaf) => { | ||
259 | tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf)) | ||
260 | } | ||
261 | tt::TokenTree::Subtree(subtree) => { | ||
262 | tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree)) | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf { | ||
268 | match leaf { | ||
269 | tt::Leaf::Literal(lit) => { | ||
270 | tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit }) | ||
271 | } | ||
272 | tt::Leaf::Punct(punct) => { | ||
273 | tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct }) | ||
274 | } | ||
275 | tt::Leaf::Ident(ident) => { | ||
276 | tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident }) | ||
227 | } | 277 | } |
228 | } | 278 | } |
229 | } | 279 | } |
@@ -287,6 +337,8 @@ impl server::TokenStream for Rustc { | |||
287 | stream.is_empty() | 337 | stream.is_empty() |
288 | } | 338 | } |
289 | fn from_str(&mut self, src: &str) -> Self::TokenStream { | 339 | fn from_str(&mut self, src: &str) -> Self::TokenStream { |
340 | use std::str::FromStr; | ||
341 | |||
290 | Self::TokenStream::from_str(src).expect("cannot parse string") | 342 | Self::TokenStream::from_str(src).expect("cannot parse string") |
291 | } | 343 | } |
292 | fn to_string(&mut self, stream: &Self::TokenStream) -> String { | 344 | fn to_string(&mut self, stream: &Self::TokenStream) -> String { |
@@ -393,10 +445,7 @@ fn spacing_to_external(spacing: Spacing) -> bridge::Spacing { | |||
393 | 445 | ||
394 | impl server::Group for Rustc { | 446 | impl server::Group for Rustc { |
395 | fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group { | 447 | fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group { |
396 | Self::Group { | 448 | Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees } |
397 | delimiter: delim_to_internal(delimiter), | ||
398 | token_trees: stream.subtree.token_trees, | ||
399 | } | ||
400 | } | 449 | } |
401 | fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter { | 450 | fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter { |
402 | delim_to_external(group.delimiter) | 451 | delim_to_external(group.delimiter) |
@@ -404,9 +453,7 @@ impl server::Group for Rustc { | |||
404 | 453 | ||
405 | // NOTE: Return value of do not include delimiter | 454 | // NOTE: Return value of do not include delimiter |
406 | fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { | 455 | fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { |
407 | TokenStream { | 456 | TokenStream { token_trees: group.token_trees.clone() } |
408 | subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() }, | ||
409 | } | ||
410 | } | 457 | } |
411 | 458 | ||
412 | fn span(&mut self, group: &Self::Group) -> Self::Span { | 459 | fn span(&mut self, group: &Self::Group) -> Self::Span { |
@@ -715,28 +762,48 @@ mod tests { | |||
715 | #[test] | 762 | #[test] |
716 | fn test_rustc_server_to_string() { | 763 | fn test_rustc_server_to_string() { |
717 | let s = TokenStream { | 764 | let s = TokenStream { |
718 | subtree: tt::Subtree { | 765 | token_trees: vec![ |
719 | delimiter: None, | 766 | tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { |
720 | token_trees: vec![ | 767 | text: "struct".into(), |
721 | tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { | 768 | id: tt::TokenId::unspecified(), |
722 | text: "struct".into(), | 769 | })), |
723 | id: tt::TokenId::unspecified(), | 770 | tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { |
724 | })), | 771 | text: "T".into(), |
725 | tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { | 772 | id: tt::TokenId::unspecified(), |
726 | text: "T".into(), | 773 | })), |
774 | tt::TokenTree::Subtree(tt::Subtree { | ||
775 | delimiter: Some(tt::Delimiter { | ||
727 | id: tt::TokenId::unspecified(), | 776 | id: tt::TokenId::unspecified(), |
728 | })), | 777 | kind: tt::DelimiterKind::Brace, |
729 | tt::TokenTree::Subtree(tt::Subtree { | ||
730 | delimiter: Some(tt::Delimiter { | ||
731 | id: tt::TokenId::unspecified(), | ||
732 | kind: tt::DelimiterKind::Brace, | ||
733 | }), | ||
734 | token_trees: vec![], | ||
735 | }), | 778 | }), |
736 | ], | 779 | token_trees: vec![], |
737 | }, | 780 | }), |
781 | ], | ||
738 | }; | 782 | }; |
739 | 783 | ||
740 | assert_eq!(s.to_string(), "struct T {}"); | 784 | assert_eq!(s.to_string(), "struct T {}"); |
741 | } | 785 | } |
786 | |||
787 | #[test] | ||
788 | fn test_rustc_server_from_str() { | ||
789 | use std::str::FromStr; | ||
790 | let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree { | ||
791 | delimiter: Some(tt::Delimiter { | ||
792 | id: tt::TokenId::unspecified(), | ||
793 | kind: tt::DelimiterKind::Parenthesis, | ||
794 | }), | ||
795 | token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { | ||
796 | text: "a".into(), | ||
797 | id: tt::TokenId::unspecified(), | ||
798 | }))], | ||
799 | }); | ||
800 | |||
801 | let t1 = TokenStream::from_str("(a)").unwrap(); | ||
802 | assert_eq!(t1.token_trees.len(), 1); | ||
803 | assert_eq!(t1.token_trees[0], subtree_paren_a); | ||
804 | |||
805 | let t2 = TokenStream::from_str("(a);").unwrap(); | ||
806 | assert_eq!(t2.token_trees.len(), 2); | ||
807 | assert_eq!(t2.token_trees[0], subtree_paren_a); | ||
808 | } | ||
742 | } | 809 | } |