1use crate::{fields::Fields, SimplePath};
9use proc_macro2::{Span, TokenStream};
10use proc_macro_error2::emit_error;
11use quote::{ToTokens, TokenStreamExt};
12use syn::punctuated::Punctuated;
13use syn::spanned::Spanned;
14use syn::token::{Brace, Comma, Semi};
15use syn::{
16 parse_quote, Attribute, FieldsNamed, GenericParam, Generics, Ident, ItemImpl, Path, Result,
17 Token, Type, Variant, Visibility,
18};
19
20pub use super::default::{find_impl_default, AttrImplDefault};
21
22pub trait ScopeAttr {
29 fn path(&self) -> SimplePath;
37
38 fn support_repetition(&self) -> bool {
44 false
45 }
46
47 fn apply(&self, attr: Attribute, scope: &mut Scope) -> Result<()>;
57}
58
59#[derive(Debug)]
61pub enum ScopeItem {
62 Enum {
64 token: Token![enum],
66 brace: Brace,
68 variants: Punctuated<Variant, Comma>,
70 },
71 Struct {
75 token: Token![struct],
77 fields: Fields,
79 },
80 Type {
82 token: Token![type],
84 eq_token: Token![=],
86 ty: Box<Type>,
88 },
89 Union {
91 token: Token![union],
93 fields: FieldsNamed,
95 },
96}
97
98impl ScopeItem {
99 pub fn token_span(&self) -> Span {
101 match self {
102 ScopeItem::Enum { token, .. } => token.span,
103 ScopeItem::Struct { token, .. } => token.span,
104 ScopeItem::Type { token, .. } => token.span,
105 ScopeItem::Union { token, .. } => token.span,
106 }
107 }
108}
109
110#[derive(Debug)]
128pub struct Scope {
129 pub attrs: Vec<Attribute>,
131 pub vis: Visibility,
133 pub ident: Ident,
135 pub generics: Generics,
137 pub item: ScopeItem,
139 pub semi: Option<Semi>,
141 pub impls: Vec<ItemImpl>,
143 pub generated: Vec<TokenStream>,
149}
150
151impl Scope {
152 pub fn apply_attrs(&mut self, find_rule: impl Fn(&Path) -> Option<&'static dyn ScopeAttr>) {
157 let mut applied: Vec<(Span, *const dyn ScopeAttr)> = Vec::new();
158
159 let mut i = 0;
160 while i < self.attrs.len() {
161 if let Some(rule) = find_rule(&self.attrs[i].path()) {
162 let attr = self.attrs.remove(i);
163
164 if !rule.support_repetition() {
165 let span = attr.span();
170 let ptr = rule as *const dyn ScopeAttr;
171 if let Some(first) = applied.iter().find(|(_, p)| std::ptr::eq(*p, ptr)) {
172 emit_error!(span, "repeated use of attribute not allowed");
173 emit_error!(first.0, "first usage here");
174 continue;
175 }
176 applied.push((span, ptr));
177 }
178
179 if let Err(err) = rule.apply(attr, self) {
180 emit_error!(err.span(), "{}", err);
181 }
182 continue;
183 }
184
185 i += 1;
186 }
187 }
188
189 pub fn expand_impl_self(&mut self) {
194 for impl_ in self.impls.iter_mut() {
195 if impl_.self_ty == parse_quote! { Self } {
196 let mut ident = self.ident.clone();
197 ident.set_span(impl_.self_ty.span());
198 let (_, ty_generics, _) = self.generics.split_for_impl();
199 impl_.self_ty = parse_quote! { #ident #ty_generics };
200 extend_generics(&mut impl_.generics, &self.generics);
201 }
202 }
203 }
204
205 pub fn expand(mut self) -> TokenStream {
211 self.expand_impl_self();
212 self.to_token_stream()
213 }
214}
215
216mod parsing {
217 use super::*;
218 use crate::fields::parsing::data_struct;
219 use syn::parse::{Parse, ParseStream};
220 use syn::spanned::Spanned;
221 use syn::{braced, Error, Field, Lifetime, Path, TypePath, WhereClause};
222
223 impl Parse for Scope {
224 fn parse(input: ParseStream) -> Result<Self> {
225 let attrs = input.call(Attribute::parse_outer)?;
226 let vis = input.parse::<Visibility>()?;
227
228 enum Token {
229 Enum(Token![enum]),
230 Struct(Token![struct]),
231 Type(Token![type]),
232 Union(Token![union]),
233 }
234 let lookahead = input.lookahead1();
235 let token;
236 if lookahead.peek(Token![enum]) {
237 token = Token::Enum(input.parse()?);
238 } else if lookahead.peek(Token![struct]) {
239 token = Token::Struct(input.parse()?);
240 } else if lookahead.peek(Token![type]) {
241 token = Token::Type(input.parse()?);
242 } else if lookahead.peek(Token![union]) {
243 token = Token::Union(input.parse()?);
244 } else {
245 return Err(lookahead.error());
246 }
247
248 let ident = input.parse::<Ident>()?;
249 let mut generics = input.parse::<Generics>()?;
250
251 let item;
252 let mut semi = None;
253 match token {
254 Token::Enum(token) => {
255 let (wc, brace, variants) = data_enum(input)?;
256 generics.where_clause = wc;
257 item = ScopeItem::Enum {
258 token,
259 brace,
260 variants,
261 };
262 }
263 Token::Struct(token) => {
264 let (wc, fields, semi_token) = data_struct(input)?;
265 generics.where_clause = wc;
266 semi = semi_token;
267 item = ScopeItem::Struct { token, fields };
268 }
269 Token::Type(token) => {
270 let eq_token = input.parse()?;
271 let ty = input.parse()?;
272 let semi_token = input.parse()?;
273 semi = Some(semi_token);
274 item = ScopeItem::Type {
275 token,
276 eq_token,
277 ty,
278 };
279 }
280 Token::Union(token) => {
281 let (wc, fields) = data_union(input)?;
282 generics.where_clause = wc;
283 item = ScopeItem::Union { token, fields };
284 }
285 }
286
287 let mut impls = Vec::new();
288 while !input.is_empty() {
289 impls.push(parse_impl(&ident, input)?);
290 }
291
292 Ok(Scope {
293 attrs,
294 vis,
295 ident,
296 generics,
297 item,
298 semi,
299 impls,
300 generated: vec![],
301 })
302 }
303 }
304
305 fn parse_impl(in_ident: &Ident, input: ParseStream) -> Result<ItemImpl> {
306 let mut attrs = input.call(Attribute::parse_outer)?;
307 let defaultness: Option<Token![default]> = input.parse()?;
308 let unsafety: Option<Token![unsafe]> = input.parse()?;
309 let impl_token: Token![impl] = input.parse()?;
310
311 let has_generics = input.peek(Token![<])
312 && (input.peek2(Token![>])
313 || input.peek2(Token![#])
314 || (input.peek2(Ident) || input.peek2(Lifetime))
315 && (input.peek3(Token![:])
316 || input.peek3(Token![,])
317 || input.peek3(Token![>])
318 || input.peek3(Token![=]))
319 || input.peek2(Token![const]));
320 let mut generics: Generics = if has_generics {
321 input.parse()?
322 } else {
323 Generics::default()
324 };
325
326 let mut first_ty: Type = input.parse()?;
327 let self_ty: Type;
328 let trait_;
329
330 let is_impl_for = input.peek(Token![for]);
331 if is_impl_for {
332 let for_token: Token![for] = input.parse()?;
333 let mut first_ty_ref = &first_ty;
334 while let Type::Group(ty) = first_ty_ref {
335 first_ty_ref = &ty.elem;
336 }
337 if let Type::Path(_) = first_ty_ref {
338 while let Type::Group(ty) = first_ty {
339 first_ty = *ty.elem;
340 }
341 if let Type::Path(TypePath { qself: None, path }) = first_ty {
342 trait_ = Some((None, path, for_token));
343 } else {
344 unreachable!();
345 }
346 } else {
347 return Err(Error::new(for_token.span, "for without target trait"));
348 }
349 self_ty = input.parse()?;
350 } else {
351 trait_ = None;
352 self_ty = first_ty;
353 }
354
355 generics.where_clause = input.parse()?;
356
357 if self_ty != parse_quote! { Self }
358 && !matches!(self_ty, Type::Path(TypePath {
359 qself: None,
360 path: Path {
361 leading_colon: None,
362 ref segments,
363 }
364 }) if segments.len() == 1 && segments.first().unwrap().ident == *in_ident)
365 {
366 return Err(Error::new(
367 self_ty.span(),
368 format!(
369 "expected `Self` or `{0}` or `{0}<...>` or `Trait for Self`, etc",
370 in_ident
371 ),
372 ));
373 }
374
375 let content;
376 let brace_token = braced!(content in input);
377 attrs.extend(Attribute::parse_inner(&content)?);
378
379 let mut items = Vec::new();
380 while !content.is_empty() {
381 items.push(content.parse()?);
382 }
383
384 Ok(ItemImpl {
385 attrs,
386 defaultness,
387 unsafety,
388 impl_token,
389 generics,
390 trait_,
391 self_ty: Box::new(self_ty),
392 brace_token,
393 items,
394 })
395 }
396
397 pub fn data_enum(
398 input: ParseStream,
399 ) -> Result<(Option<WhereClause>, Brace, Punctuated<Variant, Token![,]>)> {
400 let where_clause = input.parse()?;
401
402 let content;
403 let brace = braced!(content in input);
404 let variants = content.parse_terminated(Variant::parse, Token![,])?;
405
406 Ok((where_clause, brace, variants))
407 }
408
409 pub fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
410 let where_clause = input.parse()?;
411 let fields = parse_braced(input)?;
412 Ok((where_clause, fields))
413 }
414
415 pub(crate) fn parse_braced(input: ParseStream) -> Result<FieldsNamed> {
416 let content;
417 let brace_token = braced!(content in input);
418 let named = content.parse_terminated(Field::parse_named, Token![,])?;
419 Ok(FieldsNamed { brace_token, named })
420 }
421}
422
423mod printing {
424 use super::*;
425
426 impl ToTokens for Scope {
427 fn to_tokens(&self, tokens: &mut TokenStream) {
428 tokens.append_all(self.attrs.iter());
429 self.vis.to_tokens(tokens);
430 match &self.item {
431 ScopeItem::Enum { token, .. } => token.to_tokens(tokens),
432 ScopeItem::Struct { token, .. } => token.to_tokens(tokens),
433 ScopeItem::Type { token, .. } => token.to_tokens(tokens),
434 ScopeItem::Union { token, .. } => token.to_tokens(tokens),
435 }
436 self.ident.to_tokens(tokens);
437 self.generics.to_tokens(tokens);
438 match &self.item {
439 ScopeItem::Enum {
440 brace, variants, ..
441 } => {
442 self.generics.where_clause.to_tokens(tokens);
443 brace.surround(tokens, |tokens| {
444 variants.to_tokens(tokens);
445 });
446 }
447 ScopeItem::Struct { fields, .. } => match fields {
448 Fields::Named(fields) => {
449 self.generics.where_clause.to_tokens(tokens);
450 fields.to_tokens(tokens);
451 }
452 Fields::Unnamed(fields) => {
453 fields.to_tokens(tokens);
454 self.generics.where_clause.to_tokens(tokens);
455 }
456 Fields::Unit => {
457 self.generics.where_clause.to_tokens(tokens);
458 }
459 },
460 ScopeItem::Type { eq_token, ty, .. } => {
461 self.generics.where_clause.to_tokens(tokens);
462 eq_token.to_tokens(tokens);
463 ty.to_tokens(tokens);
464 }
465 ScopeItem::Union { fields, .. } => {
466 self.generics.where_clause.to_tokens(tokens);
467 fields.to_tokens(tokens);
468 }
469 }
470 if let Some(semi) = self.semi.as_ref() {
471 semi.to_tokens(tokens);
472 }
473
474 tokens.append_all(self.impls.iter());
475 tokens.append_all(self.generated.iter());
476 }
477 }
478}
479
480fn extend_generics(generics: &mut Generics, in_generics: &Generics) {
482 if generics.lt_token.is_none() {
483 debug_assert!(generics.params.is_empty());
484 debug_assert!(generics.gt_token.is_none());
485 generics.lt_token = in_generics.lt_token;
486 generics.params = in_generics.params.clone();
487 generics.gt_token = in_generics.gt_token;
488 } else if in_generics.lt_token.is_none() {
489 debug_assert!(in_generics.params.is_empty());
490 debug_assert!(in_generics.gt_token.is_none());
491 } else {
492 if !generics.params.empty_or_trailing() {
493 generics.params.push_punct(Default::default());
494 }
495 generics
496 .params
497 .extend(in_generics.params.clone().into_pairs());
498 }
499
500 for param in &mut generics.params {
502 match param {
503 GenericParam::Type(p) => {
504 p.eq_token = None;
505 p.default = None;
506 }
507 GenericParam::Lifetime(_) => (),
508 GenericParam::Const(p) => {
509 p.eq_token = None;
510 p.default = None;
511 }
512 }
513 }
514
515 if let Some(ref mut clause1) = generics.where_clause {
516 if let Some(ref clause2) = in_generics.where_clause {
517 if !clause1.predicates.empty_or_trailing() {
518 clause1.predicates.push_punct(Default::default());
519 }
520 clause1
521 .predicates
522 .extend(clause2.predicates.clone().into_pairs());
523 }
524 } else {
525 generics.where_clause = in_generics.where_clause.clone();
526 }
527}