aboutsummaryrefslogtreecommitdiff
path: root/crates/proc_macro_api/src/rpc.rs
diff options
context:
space:
mode:
authorZac Pullar-Strecker <[email protected]>2020-08-24 10:19:53 +0100
committerZac Pullar-Strecker <[email protected]>2020-08-24 10:20:13 +0100
commit7bbca7a1b3f9293d2f5cc5745199bc5f8396f2f0 (patch)
treebdb47765991cb973b2cd5481a088fac636bd326c /crates/proc_macro_api/src/rpc.rs
parentca464650eeaca6195891199a93f4f76cf3e7e697 (diff)
parente65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 (diff)
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Diffstat (limited to 'crates/proc_macro_api/src/rpc.rs')
-rw-r--r--crates/proc_macro_api/src/rpc.rs267
1 files changed, 267 insertions, 0 deletions
diff --git a/crates/proc_macro_api/src/rpc.rs b/crates/proc_macro_api/src/rpc.rs
new file mode 100644
index 000000000..47624163e
--- /dev/null
+++ b/crates/proc_macro_api/src/rpc.rs
@@ -0,0 +1,267 @@
1//! Data structure serialization related stuff for RPC
2//!
3//! Defines all necessary rpc serialization data structures,
4//! which includes `tt` related data and some task messages.
5//! Although adding `Serialize` and `Deserialize` traits to `tt` directly seems
6//! to be much easier, we deliberately duplicate `tt` structs with `#[serde(with = "XXDef")]`
7//! for separation of code responsibility.
8
9use std::path::PathBuf;
10
11use serde::{Deserialize, Serialize};
12use tt::{
13 Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId,
14 TokenTree,
15};
16
17#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
18pub struct ListMacrosTask {
19 pub lib: PathBuf,
20}
21
22#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
23pub enum ProcMacroKind {
24 CustomDerive,
25 FuncLike,
26 Attr,
27}
28
29#[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
30pub struct ListMacrosResult {
31 pub macros: Vec<(String, ProcMacroKind)>,
32}
33
34#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
35pub struct ExpansionTask {
36 /// Argument of macro call.
37 ///
38 /// In custom derive this will be a struct or enum; in attribute-like macro - underlying
39 /// item; in function-like macro - the macro body.
40 #[serde(with = "SubtreeDef")]
41 pub macro_body: Subtree,
42
43 /// Name of macro to expand.
44 ///
45 /// In custom derive this is the name of the derived trait (`Serialize`, `Getters`, etc.).
46 /// In attribute-like and function-like macros - single name of macro itself (`show_streams`).
47 pub macro_name: String,
48
49 /// Possible attributes for the attribute-like macros.
50 #[serde(with = "opt_subtree_def")]
51 pub attributes: Option<Subtree>,
52
53 pub lib: PathBuf,
54}
55
56#[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
57pub struct ExpansionResult {
58 #[serde(with = "SubtreeDef")]
59 pub expansion: Subtree,
60}
61
62#[derive(Serialize, Deserialize)]
63#[serde(remote = "DelimiterKind")]
64enum DelimiterKindDef {
65 Parenthesis,
66 Brace,
67 Bracket,
68}
69
70#[derive(Serialize, Deserialize)]
71#[serde(remote = "TokenId")]
72struct TokenIdDef(u32);
73
74#[derive(Serialize, Deserialize)]
75#[serde(remote = "Delimiter")]
76struct DelimiterDef {
77 #[serde(with = "TokenIdDef")]
78 pub id: TokenId,
79 #[serde(with = "DelimiterKindDef")]
80 pub kind: DelimiterKind,
81}
82
83#[derive(Serialize, Deserialize)]
84#[serde(remote = "Subtree")]
85struct SubtreeDef {
86 #[serde(default, with = "opt_delimiter_def")]
87 pub delimiter: Option<Delimiter>,
88 #[serde(with = "vec_token_tree")]
89 pub token_trees: Vec<TokenTree>,
90}
91
92#[derive(Serialize, Deserialize)]
93#[serde(remote = "TokenTree")]
94enum TokenTreeDef {
95 #[serde(with = "LeafDef")]
96 Leaf(Leaf),
97 #[serde(with = "SubtreeDef")]
98 Subtree(Subtree),
99}
100
101#[derive(Serialize, Deserialize)]
102#[serde(remote = "Leaf")]
103enum LeafDef {
104 #[serde(with = "LiteralDef")]
105 Literal(Literal),
106 #[serde(with = "PunctDef")]
107 Punct(Punct),
108 #[serde(with = "IdentDef")]
109 Ident(Ident),
110}
111
112#[derive(Serialize, Deserialize)]
113#[serde(remote = "Literal")]
114struct LiteralDef {
115 pub text: SmolStr,
116 #[serde(with = "TokenIdDef")]
117 pub id: TokenId,
118}
119
120#[derive(Serialize, Deserialize)]
121#[serde(remote = "Punct")]
122struct PunctDef {
123 pub char: char,
124 #[serde(with = "SpacingDef")]
125 pub spacing: Spacing,
126 #[serde(with = "TokenIdDef")]
127 pub id: TokenId,
128}
129
130#[derive(Serialize, Deserialize)]
131#[serde(remote = "Spacing")]
132enum SpacingDef {
133 Alone,
134 Joint,
135}
136
137#[derive(Serialize, Deserialize)]
138#[serde(remote = "Ident")]
139struct IdentDef {
140 pub text: SmolStr,
141 #[serde(with = "TokenIdDef")]
142 pub id: TokenId,
143}
144
145mod opt_delimiter_def {
146 use super::{Delimiter, DelimiterDef};
147 use serde::{Deserialize, Deserializer, Serialize, Serializer};
148
149 pub fn serialize<S>(value: &Option<Delimiter>, serializer: S) -> Result<S::Ok, S::Error>
150 where
151 S: Serializer,
152 {
153 #[derive(Serialize)]
154 struct Helper<'a>(#[serde(with = "DelimiterDef")] &'a Delimiter);
155 value.as_ref().map(Helper).serialize(serializer)
156 }
157
158 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Delimiter>, D::Error>
159 where
160 D: Deserializer<'de>,
161 {
162 #[derive(Deserialize)]
163 struct Helper(#[serde(with = "DelimiterDef")] Delimiter);
164 let helper = Option::deserialize(deserializer)?;
165 Ok(helper.map(|Helper(external)| external))
166 }
167}
168
169mod opt_subtree_def {
170 use super::{Subtree, SubtreeDef};
171 use serde::{Deserialize, Deserializer, Serialize, Serializer};
172
173 pub fn serialize<S>(value: &Option<Subtree>, serializer: S) -> Result<S::Ok, S::Error>
174 where
175 S: Serializer,
176 {
177 #[derive(Serialize)]
178 struct Helper<'a>(#[serde(with = "SubtreeDef")] &'a Subtree);
179 value.as_ref().map(Helper).serialize(serializer)
180 }
181
182 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Subtree>, D::Error>
183 where
184 D: Deserializer<'de>,
185 {
186 #[derive(Deserialize)]
187 struct Helper(#[serde(with = "SubtreeDef")] Subtree);
188 let helper = Option::deserialize(deserializer)?;
189 Ok(helper.map(|Helper(external)| external))
190 }
191}
192
193mod vec_token_tree {
194 use super::{TokenTree, TokenTreeDef};
195 use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
196
197 pub fn serialize<S>(value: &Vec<TokenTree>, serializer: S) -> Result<S::Ok, S::Error>
198 where
199 S: Serializer,
200 {
201 #[derive(Serialize)]
202 struct Helper<'a>(#[serde(with = "TokenTreeDef")] &'a TokenTree);
203
204 let items: Vec<_> = value.iter().map(Helper).collect();
205 let mut seq = serializer.serialize_seq(Some(items.len()))?;
206 for element in items {
207 seq.serialize_element(&element)?;
208 }
209 seq.end()
210 }
211
212 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<TokenTree>, D::Error>
213 where
214 D: Deserializer<'de>,
215 {
216 #[derive(Deserialize)]
217 struct Helper(#[serde(with = "TokenTreeDef")] TokenTree);
218
219 let helper = Vec::deserialize(deserializer)?;
220 Ok(helper.into_iter().map(|Helper(external)| external).collect())
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 fn fixture_token_tree() -> Subtree {
229 let mut subtree = Subtree::default();
230 subtree
231 .token_trees
232 .push(TokenTree::Leaf(Ident { text: "struct".into(), id: TokenId(0) }.into()));
233 subtree
234 .token_trees
235 .push(TokenTree::Leaf(Ident { text: "Foo".into(), id: TokenId(1) }.into()));
236 subtree.token_trees.push(TokenTree::Subtree(
237 Subtree {
238 delimiter: Some(Delimiter { id: TokenId(2), kind: DelimiterKind::Brace }),
239 token_trees: vec![],
240 }
241 .into(),
242 ));
243 subtree
244 }
245
246 #[test]
247 fn test_proc_macro_rpc_works() {
248 let tt = fixture_token_tree();
249 let task = ExpansionTask {
250 macro_body: tt.clone(),
251 macro_name: Default::default(),
252 attributes: None,
253 lib: Default::default(),
254 };
255
256 let json = serde_json::to_string(&task).unwrap();
257 let back: ExpansionTask = serde_json::from_str(&json).unwrap();
258
259 assert_eq!(task.macro_body, back.macro_body);
260
261 let result = ExpansionResult { expansion: tt.clone() };
262 let json = serde_json::to_string(&result).unwrap();
263 let back: ExpansionResult = serde_json::from_str(&json).unwrap();
264
265 assert_eq!(result, back);
266 }
267}