Bug 1888590 - Mark some subtests on trusted-types-event-handlers.html as failing...
[gecko.git] / third_party / rust / clap_derive / src / attr.rs
blob3bc9ac0140d0e4f33f199f85077ab4a3c8d44fe1
1 use std::iter::FromIterator;
3 use proc_macro2::TokenStream;
4 use quote::quote;
5 use quote::ToTokens;
6 use syn::spanned::Spanned;
7 use syn::{
8     parenthesized,
9     parse::{Parse, ParseStream},
10     punctuated::Punctuated,
11     Attribute, Expr, Ident, LitStr, Token,
14 use crate::utils::Sp;
16 #[derive(Clone)]
17 pub struct ClapAttr {
18     pub kind: Sp<AttrKind>,
19     pub name: Ident,
20     pub magic: Option<MagicAttrName>,
21     pub value: Option<AttrValue>,
24 impl ClapAttr {
25     pub fn parse_all(all_attrs: &[Attribute]) -> Result<Vec<Self>, syn::Error> {
26         let mut parsed = Vec::new();
27         for attr in all_attrs {
28             let kind = if attr.path().is_ident("clap") {
29                 Sp::new(AttrKind::Clap, attr.path().span())
30             } else if attr.path().is_ident("structopt") {
31                 Sp::new(AttrKind::StructOpt, attr.path().span())
32             } else if attr.path().is_ident("command") {
33                 Sp::new(AttrKind::Command, attr.path().span())
34             } else if attr.path().is_ident("group") {
35                 Sp::new(AttrKind::Group, attr.path().span())
36             } else if attr.path().is_ident("arg") {
37                 Sp::new(AttrKind::Arg, attr.path().span())
38             } else if attr.path().is_ident("value") {
39                 Sp::new(AttrKind::Value, attr.path().span())
40             } else {
41                 continue;
42             };
43             for mut attr in
44                 attr.parse_args_with(Punctuated::<ClapAttr, Token![,]>::parse_terminated)?
45             {
46                 attr.kind = kind;
47                 parsed.push(attr);
48             }
49         }
50         Ok(parsed)
51     }
53     pub fn value_or_abort(&self) -> Result<&AttrValue, syn::Error> {
54         self.value
55             .as_ref()
56             .ok_or_else(|| format_err!(self.name, "attribute `{}` requires a value", self.name))
57     }
59     pub fn lit_str_or_abort(&self) -> Result<&LitStr, syn::Error> {
60         let value = self.value_or_abort()?;
61         match value {
62             AttrValue::LitStr(tokens) => Ok(tokens),
63             AttrValue::Expr(_) | AttrValue::Call(_) => {
64                 abort!(
65                     self.name,
66                     "attribute `{}` can only accept string literals",
67                     self.name
68                 )
69             }
70         }
71     }
74 impl Parse for ClapAttr {
75     fn parse(input: ParseStream) -> syn::Result<Self> {
76         let name: Ident = input.parse()?;
77         let name_str = name.to_string();
79         let magic = match name_str.as_str() {
80             "rename_all" => Some(MagicAttrName::RenameAll),
81             "rename_all_env" => Some(MagicAttrName::RenameAllEnv),
82             "skip" => Some(MagicAttrName::Skip),
83             "next_display_order" => Some(MagicAttrName::NextDisplayOrder),
84             "next_help_heading" => Some(MagicAttrName::NextHelpHeading),
85             "default_value_t" => Some(MagicAttrName::DefaultValueT),
86             "default_values_t" => Some(MagicAttrName::DefaultValuesT),
87             "default_value_os_t" => Some(MagicAttrName::DefaultValueOsT),
88             "default_values_os_t" => Some(MagicAttrName::DefaultValuesOsT),
89             "long" => Some(MagicAttrName::Long),
90             "short" => Some(MagicAttrName::Short),
91             "value_parser" => Some(MagicAttrName::ValueParser),
92             "action" => Some(MagicAttrName::Action),
93             "env" => Some(MagicAttrName::Env),
94             "flatten" => Some(MagicAttrName::Flatten),
95             "value_enum" => Some(MagicAttrName::ValueEnum),
96             "from_global" => Some(MagicAttrName::FromGlobal),
97             "subcommand" => Some(MagicAttrName::Subcommand),
98             "external_subcommand" => Some(MagicAttrName::ExternalSubcommand),
99             "verbatim_doc_comment" => Some(MagicAttrName::VerbatimDocComment),
100             "about" => Some(MagicAttrName::About),
101             "long_about" => Some(MagicAttrName::LongAbout),
102             "long_help" => Some(MagicAttrName::LongHelp),
103             "author" => Some(MagicAttrName::Author),
104             "version" => Some(MagicAttrName::Version),
105             _ => None,
106         };
108         let value = if input.peek(Token![=]) {
109             // `name = value` attributes.
110             let assign_token = input.parse::<Token![=]>()?; // skip '='
111             if input.peek(LitStr) {
112                 let lit: LitStr = input.parse()?;
113                 Some(AttrValue::LitStr(lit))
114             } else {
115                 match input.parse::<Expr>() {
116                     Ok(expr) => Some(AttrValue::Expr(expr)),
118                     Err(_) => abort! {
119                         assign_token,
120                         "expected `string literal` or `expression` after `=`"
121                     },
122                 }
123             }
124         } else if input.peek(syn::token::Paren) {
125             // `name(...)` attributes.
126             let nested;
127             parenthesized!(nested in input);
129             let method_args: Punctuated<_, _> = nested.parse_terminated(Expr::parse, Token![,])?;
130             Some(AttrValue::Call(Vec::from_iter(method_args)))
131         } else {
132             None
133         };
135         Ok(Self {
136             kind: Sp::new(AttrKind::Clap, name.span()),
137             name,
138             magic,
139             value,
140         })
141     }
144 #[derive(Copy, Clone, PartialEq, Eq)]
145 pub enum MagicAttrName {
146     Short,
147     Long,
148     ValueParser,
149     Action,
150     Env,
151     Flatten,
152     ValueEnum,
153     FromGlobal,
154     Subcommand,
155     VerbatimDocComment,
156     ExternalSubcommand,
157     About,
158     LongAbout,
159     LongHelp,
160     Author,
161     Version,
162     RenameAllEnv,
163     RenameAll,
164     Skip,
165     DefaultValueT,
166     DefaultValuesT,
167     DefaultValueOsT,
168     DefaultValuesOsT,
169     NextDisplayOrder,
170     NextHelpHeading,
173 #[derive(Clone)]
174 #[allow(clippy::large_enum_variant)]
175 pub enum AttrValue {
176     LitStr(LitStr),
177     Expr(Expr),
178     Call(Vec<Expr>),
181 impl ToTokens for AttrValue {
182     fn to_tokens(&self, tokens: &mut TokenStream) {
183         match self {
184             Self::LitStr(t) => t.to_tokens(tokens),
185             Self::Expr(t) => t.to_tokens(tokens),
186             Self::Call(t) => {
187                 let t = quote!(#(#t),*);
188                 t.to_tokens(tokens)
189             }
190         }
191     }
194 #[derive(Copy, Clone, PartialEq, Eq)]
195 pub enum AttrKind {
196     Clap,
197     StructOpt,
198     Command,
199     Group,
200     Arg,
201     Value,
204 impl AttrKind {
205     pub fn as_str(&self) -> &'static str {
206         match self {
207             Self::Clap => "clap",
208             Self::StructOpt => "structopt",
209             Self::Command => "command",
210             Self::Group => "group",
211             Self::Arg => "arg",
212             Self::Value => "value",
213         }
214     }