]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_ast/src/attr/mod.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_ast / src / attr / mod.rs
CommitLineData
e1599b0c 1//! Functions dealing with attributes and meta items.
8faf50e0 2
9fa01778 3use crate::ast;
6a06907d
XL
4use crate::ast::{AttrId, AttrItem, AttrKind, AttrStyle, Attribute};
5use crate::ast::{Lit, LitKind};
60c5eb7d 6use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
f9f354fc 7use crate::ast::{Path, PathSegment};
3dfed10e 8use crate::token::{self, CommentKind, Token};
cdc7bbd5
XL
9use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
10use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing};
11use crate::tokenstream::{LazyTokenStream, TokenStream};
9fa01778 12
74b04a01 13use rustc_index::bit_set::GrowableBitSet;
6a06907d 14use rustc_span::source_map::BytePos;
f9f354fc 15use rustc_span::symbol::{sym, Ident, Symbol};
dfeec247 16use rustc_span::Span;
8faf50e0
XL
17
18use std::iter;
19
3dfed10e 20pub struct MarkedAttrs(GrowableBitSet<AttrId>);
74b04a01 21
3dfed10e
XL
22impl MarkedAttrs {
23 // We have no idea how many attributes there will be, so just
24 // initiate the vectors with 0 bits. We'll grow them as necessary.
25 pub fn new() -> Self {
26 MarkedAttrs(GrowableBitSet::new_empty())
74b04a01 27 }
74b04a01 28
3dfed10e
XL
29 pub fn mark(&mut self, attr: &Attribute) {
30 self.0.insert(attr.id);
31 }
8faf50e0 32
3dfed10e
XL
33 pub fn is_marked(&self, attr: &Attribute) -> bool {
34 self.0.contains(attr.id)
35 }
8faf50e0
XL
36}
37
8faf50e0 38impl NestedMetaItem {
e1599b0c 39 /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
8faf50e0 40 pub fn meta_item(&self) -> Option<&MetaItem> {
532ac7d7
XL
41 match *self {
42 NestedMetaItem::MetaItem(ref item) => Some(item),
dfeec247 43 _ => None,
8faf50e0
XL
44 }
45 }
46
e1599b0c 47 /// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s.
8faf50e0 48 pub fn literal(&self) -> Option<&Lit> {
532ac7d7
XL
49 match *self {
50 NestedMetaItem::Literal(ref lit) => Some(lit),
dfeec247 51 _ => None,
8faf50e0
XL
52 }
53 }
54
9fa01778 55 /// Returns `true` if this list item is a MetaItem with a name of `name`.
3dfed10e
XL
56 pub fn has_name(&self, name: Symbol) -> bool {
57 self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
8faf50e0
XL
58 }
59
e1599b0c 60 /// For a single-segment meta item, returns its name; otherwise, returns `None`.
9fa01778
XL
61 pub fn ident(&self) -> Option<Ident> {
62 self.meta_item().and_then(|meta_item| meta_item.ident())
63 }
48663c56 64 pub fn name_or_empty(&self) -> Symbol {
29967ef6 65 self.ident().unwrap_or_else(Ident::invalid).name
8faf50e0
XL
66 }
67
e1599b0c
XL
68 /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
69 /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
8faf50e0
XL
70 pub fn value_str(&self) -> Option<Symbol> {
71 self.meta_item().and_then(|meta_item| meta_item.value_str())
72 }
73
e1599b0c 74 /// Returns a name and single literal value tuple of the `MetaItem`.
f9f354fc 75 pub fn name_value_literal(&self) -> Option<(Symbol, &Lit)> {
dfeec247
XL
76 self.meta_item().and_then(|meta_item| {
77 meta_item.meta_item_list().and_then(|meta_item_list| {
78 if meta_item_list.len() == 1 {
79 if let Some(ident) = meta_item.ident() {
80 if let Some(lit) = meta_item_list[0].literal() {
81 return Some((ident.name, lit));
8faf50e0
XL
82 }
83 }
dfeec247
XL
84 }
85 None
86 })
87 })
8faf50e0
XL
88 }
89
e1599b0c 90 /// Gets a list of inner meta items from a list `MetaItem` type.
8faf50e0
XL
91 pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
92 self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
93 }
94
e1599b0c 95 /// Returns `true` if the variant is `MetaItem`.
8faf50e0
XL
96 pub fn is_meta_item(&self) -> bool {
97 self.meta_item().is_some()
98 }
99
e1599b0c 100 /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
8faf50e0 101 pub fn is_word(&self) -> bool {
9fa01778 102 self.meta_item().map_or(false, |meta_item| meta_item.is_word())
8faf50e0
XL
103 }
104
cdc7bbd5 105 /// See [`MetaItem::name_value_literal_span`].
fc512014
XL
106 pub fn name_value_literal_span(&self) -> Option<Span> {
107 self.meta_item()?.name_value_literal_span()
108 }
8faf50e0
XL
109}
110
8faf50e0 111impl Attribute {
6a06907d 112 #[inline]
60c5eb7d
XL
113 pub fn has_name(&self, name: Symbol) -> bool {
114 match self.kind {
29967ef6 115 AttrKind::Normal(ref item, _) => item.path == name,
3dfed10e 116 AttrKind::DocComment(..) => false,
8faf50e0 117 }
8faf50e0
XL
118 }
119
e1599b0c 120 /// For a single-segment attribute, returns its name; otherwise, returns `None`.
9fa01778 121 pub fn ident(&self) -> Option<Ident> {
60c5eb7d 122 match self.kind {
29967ef6 123 AttrKind::Normal(ref item, _) => {
60c5eb7d
XL
124 if item.path.segments.len() == 1 {
125 Some(item.path.segments[0].ident)
126 } else {
127 None
128 }
129 }
3dfed10e 130 AttrKind::DocComment(..) => None,
9fa01778
XL
131 }
132 }
48663c56 133 pub fn name_or_empty(&self) -> Symbol {
29967ef6 134 self.ident().unwrap_or_else(Ident::invalid).name
8faf50e0
XL
135 }
136
137 pub fn value_str(&self) -> Option<Symbol> {
60c5eb7d 138 match self.kind {
29967ef6 139 AttrKind::Normal(ref item, _) => item.meta(self.span).and_then(|meta| meta.value_str()),
dfeec247 140 AttrKind::DocComment(..) => None,
60c5eb7d 141 }
8faf50e0
XL
142 }
143
144 pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
60c5eb7d 145 match self.kind {
29967ef6 146 AttrKind::Normal(ref item, _) => match item.meta(self.span) {
dfeec247
XL
147 Some(MetaItem { kind: MetaItemKind::List(list), .. }) => Some(list),
148 _ => None,
149 },
3dfed10e 150 AttrKind::DocComment(..) => None,
8faf50e0
XL
151 }
152 }
153
154 pub fn is_word(&self) -> bool {
29967ef6 155 if let AttrKind::Normal(item, _) = &self.kind {
60c5eb7d
XL
156 matches!(item.args, MacArgs::Empty)
157 } else {
158 false
159 }
8faf50e0 160 }
8faf50e0
XL
161}
162
163impl MetaItem {
e1599b0c 164 /// For a single-segment meta item, returns its name; otherwise, returns `None`.
9fa01778 165 pub fn ident(&self) -> Option<Ident> {
dfeec247 166 if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
9fa01778 167 }
48663c56 168 pub fn name_or_empty(&self) -> Symbol {
29967ef6 169 self.ident().unwrap_or_else(Ident::invalid).name
8faf50e0
XL
170 }
171
e1599b0c
XL
172 // Example:
173 // #[attribute(name = "value")]
174 // ^^^^^^^^^^^^^^
a1dfa0c6 175 pub fn name_value_literal(&self) -> Option<&Lit> {
e74abb32 176 match &self.kind {
a1dfa0c6
XL
177 MetaItemKind::NameValue(v) => Some(v),
178 _ => None,
179 }
180 }
181
8faf50e0 182 pub fn value_str(&self) -> Option<Symbol> {
e74abb32 183 match self.kind {
dfeec247
XL
184 MetaItemKind::NameValue(ref v) => match v.kind {
185 LitKind::Str(ref s, _) => Some(*s),
186 _ => None,
8faf50e0 187 },
dfeec247 188 _ => None,
8faf50e0
XL
189 }
190 }
191
192 pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
e74abb32 193 match self.kind {
8faf50e0 194 MetaItemKind::List(ref l) => Some(&l[..]),
dfeec247 195 _ => None,
8faf50e0
XL
196 }
197 }
198
199 pub fn is_word(&self) -> bool {
5869c6ff 200 matches!(self.kind, MetaItemKind::Word)
8faf50e0
XL
201 }
202
3dfed10e 203 pub fn has_name(&self, name: Symbol) -> bool {
532ac7d7 204 self.path == name
8faf50e0
XL
205 }
206
fc512014
XL
207 /// This is used in case you want the value span instead of the whole attribute. Example:
208 ///
209 /// ```text
210 /// #[doc(alias = "foo")]
211 /// ```
212 ///
213 /// In here, it'll return a span for `"foo"`.
214 pub fn name_value_literal_span(&self) -> Option<Span> {
215 Some(self.name_value_literal()?.span)
216 }
8faf50e0
XL
217}
218
e74abb32 219impl AttrItem {
74b04a01
XL
220 pub fn span(&self) -> Span {
221 self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
222 }
223
60c5eb7d 224 pub fn meta(&self, span: Span) -> Option<MetaItem> {
8faf50e0 225 Some(MetaItem {
532ac7d7 226 path: self.path.clone(),
60c5eb7d 227 kind: MetaItemKind::from_mac_args(&self.args)?,
e74abb32 228 span,
8faf50e0
XL
229 })
230 }
e74abb32 231}
8faf50e0 232
e74abb32 233impl Attribute {
60c5eb7d
XL
234 pub fn is_doc_comment(&self) -> bool {
235 match self.kind {
29967ef6 236 AttrKind::Normal(..) => false,
3dfed10e 237 AttrKind::DocComment(..) => true,
60c5eb7d 238 }
8faf50e0
XL
239 }
240
dfeec247
XL
241 pub fn doc_str(&self) -> Option<Symbol> {
242 match self.kind {
3dfed10e 243 AttrKind::DocComment(.., data) => Some(data),
29967ef6 244 AttrKind::Normal(ref item, _) if item.path == sym::doc => {
dfeec247
XL
245 item.meta(self.span).and_then(|meta| meta.value_str())
246 }
247 _ => None,
248 }
249 }
250
60c5eb7d
XL
251 pub fn get_normal_item(&self) -> &AttrItem {
252 match self.kind {
29967ef6 253 AttrKind::Normal(ref item, _) => item,
3dfed10e 254 AttrKind::DocComment(..) => panic!("unexpected doc comment"),
60c5eb7d
XL
255 }
256 }
257
258 pub fn unwrap_normal_item(self) -> AttrItem {
259 match self.kind {
29967ef6 260 AttrKind::Normal(item, _) => item,
3dfed10e 261 AttrKind::DocComment(..) => panic!("unexpected doc comment"),
60c5eb7d
XL
262 }
263 }
264
265 /// Extracts the MetaItem from inside this Attribute.
266 pub fn meta(&self) -> Option<MetaItem> {
267 match self.kind {
29967ef6 268 AttrKind::Normal(ref item, _) => item.meta(self.span),
dfeec247 269 AttrKind::DocComment(..) => None,
60c5eb7d 270 }
8faf50e0 271 }
29967ef6 272
cdc7bbd5 273 pub fn tokens(&self) -> AttrAnnotatedTokenStream {
29967ef6
XL
274 match self.kind {
275 AttrKind::Normal(_, ref tokens) => tokens
276 .as_ref()
277 .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self))
278 .create_token_stream(),
cdc7bbd5
XL
279 AttrKind::DocComment(comment_kind, data) => AttrAnnotatedTokenStream::from((
280 AttrAnnotatedTokenTree::Token(Token::new(
281 token::DocComment(comment_kind, self.style, data),
282 self.span,
283 )),
284 Spacing::Alone,
29967ef6
XL
285 )),
286 }
287 }
8faf50e0
XL
288}
289
290/* Constructors */
291
e1599b0c
XL
292pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
293 let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked);
294 mk_name_value_item(ident, lit_kind, str_span)
8faf50e0
XL
295}
296
416331ca 297pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem {
48663c56 298 let lit = Lit::from_lit_kind(lit_kind, lit_span);
416331ca 299 let span = ident.span.to(lit_span);
e74abb32 300 MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) }
8faf50e0
XL
301}
302
416331ca 303pub fn mk_list_item(ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
e74abb32 304 MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::List(items) }
8faf50e0
XL
305}
306
307pub fn mk_word_item(ident: Ident) -> MetaItem {
e74abb32 308 MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::Word }
8faf50e0
XL
309}
310
311pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
532ac7d7 312 NestedMetaItem::MetaItem(mk_word_item(ident))
8faf50e0
XL
313}
314
416331ca 315crate fn mk_attr_id() -> AttrId {
ba9703b0 316 use std::sync::atomic::AtomicU32;
8faf50e0
XL
317 use std::sync::atomic::Ordering;
318
ba9703b0 319 static NEXT_ATTR_ID: AtomicU32 = AtomicU32::new(0);
8faf50e0
XL
320
321 let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
ba9703b0
XL
322 assert!(id != u32::MAX);
323 AttrId::from_u32(id)
8faf50e0
XL
324}
325
60c5eb7d 326pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
29967ef6 327 mk_attr_from_item(AttrItem { path, args, tokens: None }, None, style, span)
60c5eb7d
XL
328}
329
29967ef6
XL
330pub fn mk_attr_from_item(
331 item: AttrItem,
332 tokens: Option<LazyTokenStream>,
333 style: AttrStyle,
334 span: Span,
335) -> Attribute {
336 Attribute { kind: AttrKind::Normal(item, tokens), id: mk_attr_id(), style, span }
8faf50e0
XL
337}
338
e1599b0c
XL
339/// Returns an inner attribute with the given value and span.
340pub fn mk_attr_inner(item: MetaItem) -> Attribute {
60c5eb7d 341 mk_attr(AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
e1599b0c
XL
342}
343
8faf50e0 344/// Returns an outer attribute with the given value and span.
416331ca 345pub fn mk_attr_outer(item: MetaItem) -> Attribute {
60c5eb7d 346 mk_attr(AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
8faf50e0
XL
347}
348
3dfed10e
XL
349pub fn mk_doc_comment(
350 comment_kind: CommentKind,
351 style: AttrStyle,
352 data: Symbol,
353 span: Span,
354) -> Attribute {
355 Attribute { kind: AttrKind::DocComment(comment_kind, data), id: mk_attr_id(), style, span }
8faf50e0
XL
356}
357
48663c56 358pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
3dfed10e 359 items.iter().any(|item| item.has_name(name))
8faf50e0
XL
360}
361
362impl MetaItem {
1b1a35ee 363 fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
8faf50e0 364 let mut idents = vec![];
29967ef6 365 let mut last_pos = BytePos(0_u32);
532ac7d7 366 for (i, segment) in self.path.segments.iter().enumerate() {
8faf50e0
XL
367 let is_first = i == 0;
368 if !is_first {
dfeec247 369 let mod_sep_span =
c295e0f8 370 Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
dc9dc135 371 idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
8faf50e0 372 }
dc9dc135 373 idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
8faf50e0
XL
374 last_pos = segment.ident.span.hi();
375 }
1b1a35ee 376 idents.extend(self.kind.token_trees_and_spacings(self.span));
e74abb32 377 idents
8faf50e0
XL
378 }
379
380 fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
dfeec247
XL
381 where
382 I: Iterator<Item = TokenTree>,
8faf50e0
XL
383 {
384 // FIXME: Share code with `parse_path`.
74b04a01 385 let path = match tokens.next().map(TokenTree::uninterpolate) {
ba9703b0
XL
386 Some(TokenTree::Token(Token {
387 kind: kind @ (token::Ident(..) | token::ModSep),
388 span,
389 })) => 'arm: {
dc9dc135 390 let mut segments = if let token::Ident(name, _) = kind {
dfeec247
XL
391 if let Some(TokenTree::Token(Token { kind: token::ModSep, .. })) = tokens.peek()
392 {
9fa01778 393 tokens.next();
dc9dc135 394 vec![PathSegment::from_ident(Ident::new(name, span))]
9fa01778 395 } else {
dc9dc135 396 break 'arm Path::from_ident(Ident::new(name, span));
8faf50e0 397 }
8faf50e0 398 } else {
9fa01778
XL
399 vec![PathSegment::path_root(span)]
400 };
401 loop {
dfeec247 402 if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) =
74b04a01 403 tokens.next().map(TokenTree::uninterpolate)
dfeec247 404 {
dc9dc135 405 segments.push(PathSegment::from_ident(Ident::new(name, span)));
9fa01778
XL
406 } else {
407 return None;
408 }
dfeec247
XL
409 if let Some(TokenTree::Token(Token { kind: token::ModSep, .. })) = tokens.peek()
410 {
9fa01778
XL
411 tokens.next();
412 } else {
413 break;
414 }
8faf50e0 415 }
9fa01778 416 let span = span.with_hi(segments.last().unwrap().ident.span.hi());
1b1a35ee 417 Path { span, segments, tokens: None }
8faf50e0 418 }
dc9dc135 419 Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt {
e74abb32 420 token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span),
8faf50e0
XL
421 token::Nonterminal::NtPath(ref path) => path.clone(),
422 _ => return None,
423 },
424 _ => return None,
425 };
426 let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi());
e74abb32
XL
427 let kind = MetaItemKind::from_tokens(tokens)?;
428 let hi = match kind {
8faf50e0 429 MetaItemKind::NameValue(ref lit) => lit.span.hi(),
532ac7d7
XL
430 MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()),
431 _ => path.span.hi(),
8faf50e0 432 };
532ac7d7 433 let span = path.span.with_hi(hi);
e74abb32 434 Some(MetaItem { path, kind, span })
8faf50e0
XL
435 }
436}
437
438impl MetaItemKind {
60c5eb7d
XL
439 pub fn mac_args(&self, span: Span) -> MacArgs {
440 match self {
441 MetaItemKind::Word => MacArgs::Empty,
5869c6ff 442 MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.to_token()),
60c5eb7d
XL
443 MetaItemKind::List(list) => {
444 let mut tts = Vec::new();
445 for (i, item) in list.iter().enumerate() {
446 if i > 0 {
447 tts.push(TokenTree::token(token::Comma, span).into());
448 }
1b1a35ee 449 tts.extend(item.token_trees_and_spacings())
60c5eb7d
XL
450 }
451 MacArgs::Delimited(
dfeec247
XL
452 DelimSpan::from_single(span),
453 MacDelimiter::Parenthesis,
454 TokenStream::new(tts),
60c5eb7d
XL
455 )
456 }
457 }
458 }
459
1b1a35ee 460 fn token_trees_and_spacings(&self, span: Span) -> Vec<TreeAndSpacing> {
8faf50e0 461 match *self {
e74abb32 462 MetaItemKind::Word => vec![],
8faf50e0 463 MetaItemKind::NameValue(ref lit) => {
5869c6ff
XL
464 vec![
465 TokenTree::token(token::Eq, span).into(),
466 TokenTree::Token(lit.to_token()).into(),
467 ]
8faf50e0
XL
468 }
469 MetaItemKind::List(ref list) => {
470 let mut tokens = Vec::new();
471 for (i, item) in list.iter().enumerate() {
472 if i > 0 {
dc9dc135 473 tokens.push(TokenTree::token(token::Comma, span).into());
8faf50e0 474 }
1b1a35ee 475 tokens.extend(item.token_trees_and_spacings())
8faf50e0 476 }
e74abb32
XL
477 vec![
478 TokenTree::Delimited(
479 DelimSpan::from_single(span),
480 token::Paren,
74b04a01 481 TokenStream::new(tokens),
dfeec247
XL
482 )
483 .into(),
e74abb32 484 ]
8faf50e0
XL
485 }
486 }
487 }
488
60c5eb7d
XL
489 fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
490 let mut tokens = tokens.into_trees().peekable();
8faf50e0 491 let mut result = Vec::new();
5869c6ff 492 while tokens.peek().is_some() {
532ac7d7
XL
493 let item = NestedMetaItem::from_tokens(&mut tokens)?;
494 result.push(item);
8faf50e0 495 match tokens.next() {
dc9dc135 496 None | Some(TokenTree::Token(Token { kind: token::Comma, .. })) => {}
8faf50e0
XL
497 _ => return None,
498 }
499 }
500 Some(MetaItemKind::List(result))
501 }
60c5eb7d
XL
502
503 fn name_value_from_tokens(
504 tokens: &mut impl Iterator<Item = TokenTree>,
505 ) -> Option<MetaItemKind> {
506 match tokens.next() {
f035d41b
XL
507 Some(TokenTree::Delimited(_, token::NoDelim, inner_tokens)) => {
508 MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees())
509 }
dfeec247
XL
510 Some(TokenTree::Token(token)) => {
511 Lit::from_token(&token).ok().map(MetaItemKind::NameValue)
512 }
60c5eb7d
XL
513 _ => None,
514 }
515 }
516
517 fn from_mac_args(args: &MacArgs) -> Option<MetaItemKind> {
518 match args {
dfeec247
XL
519 MacArgs::Delimited(_, MacDelimiter::Parenthesis, tokens) => {
520 MetaItemKind::list_from_tokens(tokens.clone())
521 }
60c5eb7d 522 MacArgs::Delimited(..) => None,
5869c6ff 523 MacArgs::Eq(_, token) => Lit::from_token(token).ok().map(MetaItemKind::NameValue),
60c5eb7d
XL
524 MacArgs::Empty => Some(MetaItemKind::Word),
525 }
526 }
527
528 fn from_tokens(
529 tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
530 ) -> Option<MetaItemKind> {
531 match tokens.peek() {
532 Some(TokenTree::Delimited(_, token::Paren, inner_tokens)) => {
533 let inner_tokens = inner_tokens.clone();
534 tokens.next();
535 MetaItemKind::list_from_tokens(inner_tokens)
536 }
537 Some(TokenTree::Delimited(..)) => None,
538 Some(TokenTree::Token(Token { kind: token::Eq, .. })) => {
539 tokens.next();
540 MetaItemKind::name_value_from_tokens(tokens)
541 }
542 _ => Some(MetaItemKind::Word),
543 }
544 }
8faf50e0
XL
545}
546
532ac7d7
XL
547impl NestedMetaItem {
548 pub fn span(&self) -> Span {
8faf50e0 549 match *self {
532ac7d7
XL
550 NestedMetaItem::MetaItem(ref item) => item.span,
551 NestedMetaItem::Literal(ref lit) => lit.span,
8faf50e0
XL
552 }
553 }
554
1b1a35ee 555 fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
8faf50e0 556 match *self {
1b1a35ee 557 NestedMetaItem::MetaItem(ref item) => item.token_trees_and_spacings(),
5869c6ff 558 NestedMetaItem::Literal(ref lit) => vec![TokenTree::Token(lit.to_token()).into()],
8faf50e0
XL
559 }
560 }
561
532ac7d7 562 fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
dfeec247
XL
563 where
564 I: Iterator<Item = TokenTree>,
8faf50e0 565 {
f035d41b 566 match tokens.peek() {
94222f64
XL
567 Some(TokenTree::Token(token))
568 if let Ok(lit) = Lit::from_token(token) =>
569 {
570 tokens.next();
571 return Some(NestedMetaItem::Literal(lit));
f035d41b
XL
572 }
573 Some(TokenTree::Delimited(_, token::NoDelim, inner_tokens)) => {
574 let inner_tokens = inner_tokens.clone();
8faf50e0 575 tokens.next();
f035d41b 576 return NestedMetaItem::from_tokens(&mut inner_tokens.into_trees().peekable());
8faf50e0 577 }
f035d41b 578 _ => {}
8faf50e0 579 }
532ac7d7 580 MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem)
8faf50e0
XL
581 }
582}