aboutsummaryrefslogtreecommitdiff
path: root/crates/proc_macro_srv/src/rustc_server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/proc_macro_srv/src/rustc_server.rs')
-rw-r--r--crates/proc_macro_srv/src/rustc_server.rs183
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;
14use std::hash::Hash; 14use std::hash::Hash;
15use std::iter::FromIterator; 15use std::iter::FromIterator;
16use std::ops::Bound; 16use std::ops::Bound;
17use std::str::FromStr;
18use std::{ascii, vec::IntoIter}; 17use std::{ascii, vec::IntoIter};
19 18
20type Group = tt::Subtree; 19type Group = tt::Subtree;
@@ -26,27 +25,35 @@ type Span = tt::TokenId;
26 25
27#[derive(Debug, Clone)] 26#[derive(Debug, Clone)]
28pub struct TokenStream { 27pub struct TokenStream {
29 pub subtree: tt::Subtree, 28 pub token_trees: Vec<TokenTree>,
30} 29}
31 30
32impl TokenStream { 31impl 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.
47impl From<TokenTree> for TokenStream { 54impl 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
394impl server::Group for Rustc { 446impl 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}