Skip to content

Commit 22402df

Browse files
committed
Refactoring export attribute
- Enable to use Path syntax. - Remove abstractions that inhibit expansion. - Remove code that only accepts [export = "wrong"]. - Add error message.
1 parent 5e58f6b commit 22402df

File tree

1 file changed

+64
-77
lines changed

1 file changed

+64
-77
lines changed

gdnative-derive/src/methods.rs

Lines changed: 64 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -198,120 +198,107 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
198198

199199
if let Some("export") = last_seg.as_deref() {
200200
let _export_args = export_args.get_or_insert_with(ExportArgs::default);
201-
if !attr.tokens.is_empty() {
202-
use syn::{Meta, MetaNameValue, NestedMeta};
203-
204-
let meta = match attr.parse_meta() {
205-
Ok(val) => val,
201+
use syn::{punctuated::Punctuated, Lit, Meta, NestedMeta};
202+
let nested_meta_iter = match attr.parse_meta() {
206203
Err(err) => {
207204
errors.push(err);
208205
return false;
209206
}
210-
};
211-
212-
let pairs: Vec<_> = match meta {
213-
Meta::List(list) => list
214-
.nested
215-
.into_pairs()
216-
.filter_map(|p| {
217-
let span = p.span();
218-
match p.into_value() {
219-
NestedMeta::Meta(Meta::NameValue(pair)) => {
220-
Some(pair)
221-
}
222-
unexpected => {
223-
let msg = format!(
224-
"unexpected argument in list: {}",
225-
unexpected.into_token_stream()
226-
);
207+
Ok(Meta::NameValue(name_value)) => {
208+
let span = name_value.span();
209+
let msg = "NameValue syntax is not valid";
227210
errors.push(syn::Error::new(span, msg));
228-
None
211+
return false;
229212
}
213+
Ok(Meta::Path(_)) => {
214+
Punctuated::<NestedMeta, syn::token::Comma>::new().into_iter()
230215
}
231-
})
232-
.collect(),
233-
Meta::NameValue(pair) => vec![pair],
234-
meta => {
235-
let span = meta.span();
236-
let msg = format!(
237-
"unexpected attribute argument: {}",
238-
meta.into_token_stream()
239-
);
216+
Ok(Meta::List(list)) => list.nested.into_iter(),
217+
};
218+
for nested_meta in nested_meta_iter {
219+
let (path, lit) = match &nested_meta {
220+
NestedMeta::Lit(param) => {
221+
let span = param.span();
222+
let msg = "Literal item is not valid";
240223
errors.push(syn::Error::new(span, msg));
241-
return false;
224+
continue;
242225
}
243-
};
244-
245-
for MetaNameValue { path, lit, .. } in pairs {
246-
let last = match path.segments.last() {
247-
Some(val) => val,
248-
None => {
249-
errors.push(syn::Error::new(
250-
path.span(),
251-
"the path should not be empty",
252-
));
253-
return false;
226+
NestedMeta::Meta(param) => match param {
227+
Meta::List(list) => {
228+
let span = list.span();
229+
let msg = "List item is not valid";
230+
errors.push(syn::Error::new(span, msg));
231+
continue;
254232
}
233+
Meta::Path(path) => (path, None),
234+
Meta::NameValue(name_value) => {
235+
(&name_value.path, Some(&name_value.lit))
236+
}
237+
},
255238
};
256-
let path = last.ident.to_string();
257-
258-
// Match optional export arguments
259-
match path.as_str() {
239+
if path.is_ident("rpc") {
260240
// rpc mode
261-
"rpc" => {
262-
let value = if let syn::Lit::Str(lit_str) = lit {
263-
lit_str.value()
264-
} else {
241+
match lit {
242+
None => {
265243
errors.push(syn::Error::new(
266-
last.span(),
267-
"unexpected type for rpc value, expected Str",
244+
nested_meta.span(),
245+
"name parameter requires string value",
268246
));
269-
return false;
270-
};
271-
247+
}
248+
Some(Lit::Str(str)) => {
249+
let value = str.value();
272250
if let Some(mode) = RpcMode::parse(value.as_str()) {
273251
if rpc.replace(mode).is_some() {
274252
errors.push(syn::Error::new(
275-
last.span(),
253+
nested_meta.span(),
276254
"rpc mode was set more than once",
277255
));
278-
return false;
279256
}
280257
} else {
281258
errors.push(syn::Error::new(
282-
last.span(),
259+
nested_meta.span(),
283260
format!("unexpected value for rpc: {}", value),
284261
));
285-
return false;
286262
}
287263
}
264+
_ => {
265+
errors.push(syn::Error::new(
266+
nested_meta.span(),
267+
"unexpected type for rpc value, expected string",
268+
));
269+
}
270+
}
271+
} else if path.is_ident("name") {
288272
// name override
289-
"name" => {
290-
let value = if let syn::Lit::Str(lit_str) = lit {
291-
lit_str.value()
292-
} else {
273+
match lit {
274+
None => {
293275
errors.push(syn::Error::new(
294-
last.span(),
295-
"unexpected type for name value, expected Str",
276+
nested_meta.span(),
277+
"name parameter requires string value",
296278
));
297-
return false;
298-
};
299-
300-
if name_override.replace(value).is_some() {
279+
}
280+
Some(Lit::Str(str)) => {
281+
if name_override.replace(str.value()).is_some() {
301282
errors.push(syn::Error::new(
302-
last.span(),
283+
nested_meta.span(),
303284
"name was set more than once",
304285
));
305-
return false;
306286
}
307287
}
308288
_ => {
309-
let msg =
310-
format!("unknown option for export: `{}`", path);
311-
errors.push(syn::Error::new(last.span(), msg));
312-
return false;
289+
errors.push(syn::Error::new(
290+
nested_meta.span(),
291+
"unexpected type for name value, expected string",
292+
));
313293
}
314294
}
295+
}
296+
} else {
297+
let msg = format!(
298+
"unknown option for export: `{}`",
299+
path.to_token_stream()
300+
);
301+
errors.push(syn::Error::new(nested_meta.span(), msg));
315302
}
316303
}
317304
return false;

0 commit comments

Comments
 (0)