derive.rs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. use crate::attr::Attribute;
  3. use crate::data::{Fields, FieldsNamed, Variant};
  4. use crate::generics::Generics;
  5. use crate::ident::Ident;
  6. use crate::punctuated::Punctuated;
  7. use crate::restriction::Visibility;
  8. use crate::token;
  9. ast_struct! {
  10. /// Data structure sent to a `proc_macro_derive` macro.
  11. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
  12. pub struct DeriveInput {
  13. pub attrs: Vec<Attribute>,
  14. pub vis: Visibility,
  15. pub ident: Ident,
  16. pub generics: Generics,
  17. pub data: Data,
  18. }
  19. }
  20. ast_enum! {
  21. /// The storage of a struct, enum or union data structure.
  22. ///
  23. /// # Syntax tree enum
  24. ///
  25. /// This type is a [syntax tree enum].
  26. ///
  27. /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
  28. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
  29. pub enum Data {
  30. Struct(DataStruct),
  31. Enum(DataEnum),
  32. Union(DataUnion),
  33. }
  34. }
  35. ast_struct! {
  36. /// A struct input to a `proc_macro_derive` macro.
  37. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
  38. pub struct DataStruct {
  39. pub struct_token: Token![struct],
  40. pub fields: Fields,
  41. pub semi_token: Option<Token![;]>,
  42. }
  43. }
  44. ast_struct! {
  45. /// An enum input to a `proc_macro_derive` macro.
  46. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
  47. pub struct DataEnum {
  48. pub enum_token: Token![enum],
  49. pub brace_token: token::Brace,
  50. pub variants: Punctuated<Variant, Token![,]>,
  51. }
  52. }
  53. ast_struct! {
  54. /// An untagged union input to a `proc_macro_derive` macro.
  55. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
  56. pub struct DataUnion {
  57. pub union_token: Token![union],
  58. pub fields: FieldsNamed,
  59. }
  60. }
  61. #[cfg(feature = "parsing")]
  62. pub(crate) mod parsing {
  63. use crate::attr::Attribute;
  64. use crate::data::{Fields, FieldsNamed, Variant};
  65. use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
  66. use crate::error::Result;
  67. use crate::generics::{Generics, WhereClause};
  68. use crate::ident::Ident;
  69. use crate::parse::{Parse, ParseStream};
  70. use crate::punctuated::Punctuated;
  71. use crate::restriction::Visibility;
  72. use crate::token;
  73. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  74. impl Parse for DeriveInput {
  75. fn parse(input: ParseStream) -> Result<Self> {
  76. let attrs = input.call(Attribute::parse_outer)?;
  77. let vis = input.parse::<Visibility>()?;
  78. let lookahead = input.lookahead1();
  79. if lookahead.peek(Token![struct]) {
  80. let struct_token = input.parse::<Token![struct]>()?;
  81. let ident = input.parse::<Ident>()?;
  82. let generics = input.parse::<Generics>()?;
  83. let (where_clause, fields, semi) = data_struct(input)?;
  84. Ok(DeriveInput {
  85. attrs,
  86. vis,
  87. ident,
  88. generics: Generics {
  89. where_clause,
  90. ..generics
  91. },
  92. data: Data::Struct(DataStruct {
  93. struct_token,
  94. fields,
  95. semi_token: semi,
  96. }),
  97. })
  98. } else if lookahead.peek(Token![enum]) {
  99. let enum_token = input.parse::<Token![enum]>()?;
  100. let ident = input.parse::<Ident>()?;
  101. let generics = input.parse::<Generics>()?;
  102. let (where_clause, brace, variants) = data_enum(input)?;
  103. Ok(DeriveInput {
  104. attrs,
  105. vis,
  106. ident,
  107. generics: Generics {
  108. where_clause,
  109. ..generics
  110. },
  111. data: Data::Enum(DataEnum {
  112. enum_token,
  113. brace_token: brace,
  114. variants,
  115. }),
  116. })
  117. } else if lookahead.peek(Token![union]) {
  118. let union_token = input.parse::<Token![union]>()?;
  119. let ident = input.parse::<Ident>()?;
  120. let generics = input.parse::<Generics>()?;
  121. let (where_clause, fields) = data_union(input)?;
  122. Ok(DeriveInput {
  123. attrs,
  124. vis,
  125. ident,
  126. generics: Generics {
  127. where_clause,
  128. ..generics
  129. },
  130. data: Data::Union(DataUnion {
  131. union_token,
  132. fields,
  133. }),
  134. })
  135. } else {
  136. Err(lookahead.error())
  137. }
  138. }
  139. }
  140. pub(crate) fn data_struct(
  141. input: ParseStream,
  142. ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
  143. let mut lookahead = input.lookahead1();
  144. let mut where_clause = None;
  145. if lookahead.peek(Token![where]) {
  146. where_clause = Some(input.parse()?);
  147. lookahead = input.lookahead1();
  148. }
  149. if where_clause.is_none() && lookahead.peek(token::Paren) {
  150. let fields = input.parse()?;
  151. lookahead = input.lookahead1();
  152. if lookahead.peek(Token![where]) {
  153. where_clause = Some(input.parse()?);
  154. lookahead = input.lookahead1();
  155. }
  156. if lookahead.peek(Token![;]) {
  157. let semi = input.parse()?;
  158. Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
  159. } else {
  160. Err(lookahead.error())
  161. }
  162. } else if lookahead.peek(token::Brace) {
  163. let fields = input.parse()?;
  164. Ok((where_clause, Fields::Named(fields), None))
  165. } else if lookahead.peek(Token![;]) {
  166. let semi = input.parse()?;
  167. Ok((where_clause, Fields::Unit, Some(semi)))
  168. } else {
  169. Err(lookahead.error())
  170. }
  171. }
  172. pub(crate) fn data_enum(
  173. input: ParseStream,
  174. ) -> Result<(
  175. Option<WhereClause>,
  176. token::Brace,
  177. Punctuated<Variant, Token![,]>,
  178. )> {
  179. let where_clause = input.parse()?;
  180. let content;
  181. let brace = braced!(content in input);
  182. let variants = content.parse_terminated(Variant::parse, Token![,])?;
  183. Ok((where_clause, brace, variants))
  184. }
  185. pub(crate) fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
  186. let where_clause = input.parse()?;
  187. let fields = input.parse()?;
  188. Ok((where_clause, fields))
  189. }
  190. }
  191. #[cfg(feature = "printing")]
  192. mod printing {
  193. use crate::attr::FilterAttrs;
  194. use crate::data::Fields;
  195. use crate::derive::{Data, DeriveInput};
  196. use crate::print::TokensOrDefault;
  197. use proc_macro2::TokenStream;
  198. use quote::ToTokens;
  199. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  200. impl ToTokens for DeriveInput {
  201. fn to_tokens(&self, tokens: &mut TokenStream) {
  202. for attr in self.attrs.outer() {
  203. attr.to_tokens(tokens);
  204. }
  205. self.vis.to_tokens(tokens);
  206. match &self.data {
  207. Data::Struct(d) => d.struct_token.to_tokens(tokens),
  208. Data::Enum(d) => d.enum_token.to_tokens(tokens),
  209. Data::Union(d) => d.union_token.to_tokens(tokens),
  210. }
  211. self.ident.to_tokens(tokens);
  212. self.generics.to_tokens(tokens);
  213. match &self.data {
  214. Data::Struct(data) => match &data.fields {
  215. Fields::Named(fields) => {
  216. self.generics.where_clause.to_tokens(tokens);
  217. fields.to_tokens(tokens);
  218. }
  219. Fields::Unnamed(fields) => {
  220. fields.to_tokens(tokens);
  221. self.generics.where_clause.to_tokens(tokens);
  222. TokensOrDefault(&data.semi_token).to_tokens(tokens);
  223. }
  224. Fields::Unit => {
  225. self.generics.where_clause.to_tokens(tokens);
  226. TokensOrDefault(&data.semi_token).to_tokens(tokens);
  227. }
  228. },
  229. Data::Enum(data) => {
  230. self.generics.where_clause.to_tokens(tokens);
  231. data.brace_token.surround(tokens, |tokens| {
  232. data.variants.to_tokens(tokens);
  233. });
  234. }
  235. Data::Union(data) => {
  236. self.generics.where_clause.to_tokens(tokens);
  237. data.fields.to_tokens(tokens);
  238. }
  239. }
  240. }
  241. }
  242. }