aboutsummaryrefslogtreecommitdiff
path: root/crates/proc_macro_srv
diff options
context:
space:
mode:
Diffstat (limited to 'crates/proc_macro_srv')
-rw-r--r--crates/proc_macro_srv/Cargo.toml2
-rw-r--r--crates/proc_macro_srv/src/dylib.rs6
-rw-r--r--crates/proc_macro_srv/src/proc_macro/bridge/client.rs2
-rw-r--r--crates/proc_macro_srv/src/proc_macro/bridge/mod.rs2
-rw-r--r--crates/proc_macro_srv/src/rustc_server.rs221
-rw-r--r--crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt2
-rw-r--r--crates/proc_macro_srv/src/tests/utils.rs2
7 files changed, 134 insertions, 103 deletions
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml
index 4c1b3036a..63b3f1532 100644
--- a/crates/proc_macro_srv/Cargo.toml
+++ b/crates/proc_macro_srv/Cargo.toml
@@ -17,9 +17,9 @@ memmap2 = "0.2.0"
17tt = { path = "../tt", version = "0.0.0" } 17tt = { path = "../tt", version = "0.0.0" }
18mbe = { path = "../mbe", version = "0.0.0" } 18mbe = { path = "../mbe", version = "0.0.0" }
19proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } 19proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" }
20test_utils = { path = "../test_utils", version = "0.0.0" }
21 20
22[dev-dependencies] 21[dev-dependencies]
22test_utils = { path = "../test_utils" }
23cargo_metadata = "0.13" 23cargo_metadata = "0.13"
24 24
25# used as proc macro test targets 25# used as proc macro test targets
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/proc_macro/bridge/client.rs b/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
index ca6749b9b..b036d4e20 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
@@ -238,7 +238,7 @@ macro_rules! define_client_side {
238 $(impl $name { 238 $(impl $name {
239 #[allow(unused)] 239 #[allow(unused)]
240 $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)* { 240 $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)* {
241 panic!("hello"); 241 panic!("crates should be linked against the sysroot version of proc_macro, not this one from rust-analyzer");
242 // Bridge::with(|bridge| { 242 // Bridge::with(|bridge| {
243 // let mut b = bridge.cached_buffer.take(); 243 // let mut b = bridge.cached_buffer.take();
244 244
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs b/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
index e4006a5ab..e67902682 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
@@ -268,7 +268,7 @@ trait Mark {
268 fn mark(unmarked: Self::Unmarked) -> Self; 268 fn mark(unmarked: Self::Unmarked) -> Self;
269} 269}
270 270
271/// Unwrap types wrapped by `Mark::mark` (see `Mark` for details). 271/// Unwrap types wrapped by `cov_mark::mark` (see `Mark` for details).
272trait Unmark { 272trait Unmark {
273 type Unmarked; 273 type Unmarked;
274 fn unmark(self) -> Self::Unmarked; 274 fn unmark(self) -> Self::Unmarked;
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs
index 952b4a97f..ceefd187d 100644
--- a/crates/proc_macro_srv/src/rustc_server.rs
+++ b/crates/proc_macro_srv/src/rustc_server.rs
@@ -25,27 +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 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 }
38 } 46 }
39 47
40 pub fn is_empty(&self) -> bool { 48 pub fn is_empty(&self) -> bool {
41 self.subtree.token_trees.is_empty() 49 self.token_trees.is_empty()
42 } 50 }
43} 51}
44 52
45/// Creates a token stream containing a single token tree. 53/// Creates a token stream containing a single token tree.
46impl From<TokenTree> for TokenStream { 54impl From<TokenTree> for TokenStream {
47 fn from(tree: TokenTree) -> TokenStream { 55 fn from(tree: TokenTree) -> TokenStream {
48 TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } } 56 TokenStream { token_trees: vec![tree] }
49 } 57 }
50} 58}
51 59
@@ -78,10 +86,10 @@ impl Extend<TokenStream> for TokenStream {
78 for tkn in item { 86 for tkn in item {
79 match tkn { 87 match tkn {
80 tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => { 88 tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
81 self.subtree.token_trees.extend(subtree.token_trees); 89 self.token_trees.extend(subtree.token_trees);
82 } 90 }
83 _ => { 91 _ => {
84 self.subtree.token_trees.push(tkn); 92 self.token_trees.push(tkn);
85 } 93 }
86 } 94 }
87 } 95 }
@@ -164,7 +172,7 @@ pub mod token_stream {
164 type IntoIter = super::IntoIter<TokenTree>; 172 type IntoIter = super::IntoIter<TokenTree>;
165 173
166 fn into_iter(self) -> Self::IntoIter { 174 fn into_iter(self) -> Self::IntoIter {
167 self.subtree.token_trees.into_iter() 175 self.token_trees.into_iter()
168 } 176 }
169 } 177 }
170 178
@@ -184,28 +192,23 @@ pub mod token_stream {
184 let (subtree, _token_map) = 192 let (subtree, _token_map) =
185 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")?;
186 194
187 Ok(TokenStream { subtree }) 195 let subtree = subtree_replace_token_ids_with_unspecified(subtree);
196 Ok(TokenStream::with_subtree(subtree))
188 } 197 }
189 } 198 }
190 199
191 impl ToString for TokenStream { 200 impl ToString for TokenStream {
192 fn to_string(&self) -> String { 201 fn to_string(&self) -> String {
193 let tt = self.subtree.clone().into(); 202 return tokentrees_to_text(&self.token_trees[..]);
194 to_text(&tt)
195 }
196 }
197 203
198 fn to_text(tkn: &tt::TokenTree) -> String { 204 fn tokentrees_to_text(tkns: &[tt::TokenTree]) -> String {
199 match tkn { 205 tkns.iter()
200 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
201 tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
202 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
203 tt::TokenTree::Subtree(subtree) => {
204 let content = subtree
205 .token_trees
206 .iter()
207 .fold((String::new(), true), |(last, last_to_joint), tkn| { 206 .fold((String::new(), true), |(last, last_to_joint), tkn| {
208 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 });
209 let mut is_joint = false; 212 let mut is_joint = false;
210 if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn { 213 if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
211 if punct.spacing == tt::Spacing::Joint { 214 if punct.spacing == tt::Spacing::Joint {
@@ -214,15 +217,63 @@ pub mod token_stream {
214 } 217 }
215 (s, is_joint) 218 (s, is_joint)
216 }) 219 })
217 .0; 220 .0
218 221 }
219 let (open, close) = match subtree.delimiter.map(|it| it.kind) { 222
220 None => ("", ""), 223 fn tokentree_to_text(tkn: &tt::TokenTree) -> String {
221 Some(tt::DelimiterKind::Brace) => ("{", "}"), 224 match tkn {
222 Some(tt::DelimiterKind::Parenthesis) => ("(", ")"), 225 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
223 Some(tt::DelimiterKind::Bracket) => ("[", "]"), 226 tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
224 }; 227 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
225 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 })
226 } 277 }
227 } 278 }
228 } 279 }
@@ -277,42 +328,6 @@ impl server::FreeFunctions for Rustc {
277 } 328 }
278} 329}
279 330
280fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree {
281 tt::Subtree {
282 delimiter: subtree.delimiter.map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }),
283 token_trees: subtree
284 .token_trees
285 .into_iter()
286 .map(|t| token_tree_replace_token_ids_with_unspecified(t))
287 .collect(),
288 }
289}
290
291fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree {
292 match tt {
293 tt::TokenTree::Leaf(leaf) => {
294 tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf))
295 }
296 tt::TokenTree::Subtree(subtree) => {
297 tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree))
298 }
299 }
300}
301
302fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf {
303 match leaf {
304 tt::Leaf::Literal(lit) => {
305 tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit })
306 }
307 tt::Leaf::Punct(punct) => {
308 tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct })
309 }
310 tt::Leaf::Ident(ident) => {
311 tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident })
312 }
313 }
314}
315
316impl server::TokenStream for Rustc { 331impl server::TokenStream for Rustc {
317 fn new(&mut self) -> Self::TokenStream { 332 fn new(&mut self) -> Self::TokenStream {
318 Self::TokenStream::new() 333 Self::TokenStream::new()
@@ -322,8 +337,9 @@ impl server::TokenStream for Rustc {
322 stream.is_empty() 337 stream.is_empty()
323 } 338 }
324 fn from_str(&mut self, src: &str) -> Self::TokenStream { 339 fn from_str(&mut self, src: &str) -> Self::TokenStream {
325 let (subtree, _) = mbe::parse_to_token_tree(src).expect("cannot parse string"); 340 use std::str::FromStr;
326 TokenStream::with_subtree(subtree_replace_token_ids_with_unspecified(subtree)) 341
342 Self::TokenStream::from_str(src).expect("cannot parse string")
327 } 343 }
328 fn to_string(&mut self, stream: &Self::TokenStream) -> String { 344 fn to_string(&mut self, stream: &Self::TokenStream) -> String {
329 stream.to_string() 345 stream.to_string()
@@ -429,10 +445,7 @@ fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
429 445
430impl server::Group for Rustc { 446impl server::Group for Rustc {
431 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 {
432 Self::Group { 448 Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees }
433 delimiter: delim_to_internal(delimiter),
434 token_trees: stream.subtree.token_trees,
435 }
436 } 449 }
437 fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter { 450 fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
438 delim_to_external(group.delimiter) 451 delim_to_external(group.delimiter)
@@ -440,9 +453,7 @@ impl server::Group for Rustc {
440 453
441 // NOTE: Return value of do not include delimiter 454 // NOTE: Return value of do not include delimiter
442 fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { 455 fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
443 TokenStream { 456 TokenStream { token_trees: group.token_trees.clone() }
444 subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() },
445 }
446 } 457 }
447 458
448 fn span(&mut self, group: &Self::Group) -> Self::Span { 459 fn span(&mut self, group: &Self::Group) -> Self::Span {
@@ -751,28 +762,48 @@ mod tests {
751 #[test] 762 #[test]
752 fn test_rustc_server_to_string() { 763 fn test_rustc_server_to_string() {
753 let s = TokenStream { 764 let s = TokenStream {
754 subtree: tt::Subtree { 765 token_trees: vec![
755 delimiter: None, 766 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
756 token_trees: vec![ 767 text: "struct".into(),
757 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { 768 id: tt::TokenId::unspecified(),
758 text: "struct".into(), 769 })),
759 id: tt::TokenId::unspecified(), 770 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
760 })), 771 text: "T".into(),
761 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { 772 id: tt::TokenId::unspecified(),
762 text: "T".into(), 773 })),
774 tt::TokenTree::Subtree(tt::Subtree {
775 delimiter: Some(tt::Delimiter {
763 id: tt::TokenId::unspecified(), 776 id: tt::TokenId::unspecified(),
764 })), 777 kind: tt::DelimiterKind::Brace,
765 tt::TokenTree::Subtree(tt::Subtree {
766 delimiter: Some(tt::Delimiter {
767 id: tt::TokenId::unspecified(),
768 kind: tt::DelimiterKind::Brace,
769 }),
770 token_trees: vec![],
771 }), 778 }),
772 ], 779 token_trees: vec![],
773 }, 780 }),
781 ],
774 }; 782 };
775 783
776 assert_eq!(s.to_string(), "struct T {}"); 784 assert_eq!(s.to_string(), "struct T {}");
777 } 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 }
778} 809}
diff --git a/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt b/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
index ea34e688f..fa581f110 100644
--- a/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
+++ b/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
@@ -101,7 +101,7 @@ SUBTREE $
101 PUNCH : [alone] 4294967295 101 PUNCH : [alone] 4294967295
102 IDENT Serialize 4294967295 102 IDENT Serialize 4294967295
103 IDENT for 4294967295 103 IDENT for 4294967295
104 IDENT Foo 1 104 IDENT Foo 4294967295
105 SUBTREE {} 4294967295 105 SUBTREE {} 4294967295
106 IDENT fn 4294967295 106 IDENT fn 4294967295
107 IDENT serialize 4294967295 107 IDENT serialize 4294967295
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