@@ -60,7 +60,7 @@ use crate::attributes::test_attrs::*;
6060use crate :: attributes:: traits:: * ;
6161use crate :: attributes:: transparency:: * ;
6262use crate :: attributes:: { AttributeParser as _, Combine , Single , WithoutArgs } ;
63- use crate :: parser:: { ArgParser , RefPathParser } ;
63+ use crate :: parser:: { ArgParser , MetaItemOrLitParser , RefPathParser } ;
6464use crate :: session_diagnostics:: {
6565 AttributeParseError , AttributeParseErrorReason , AttributeParseErrorSuggestions ,
6666 ParsedDescription ,
@@ -502,6 +502,36 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
502502 pub ( crate ) fn adcx ( & mut self ) -> AttributeDiagnosticContext < ' _ , ' f , ' sess , S > {
503503 AttributeDiagnosticContext { ctx : self , custom_suggestions : Vec :: new ( ) }
504504 }
505+
506+ /// Asserts that this MetaItem is a list that contains a single element. Emits an error and
507+ /// returns `None` if it is not the case.
508+ ///
509+ /// Some examples:
510+ ///
511+ /// - In `#[allow(warnings)]`, `warnings` is returned
512+ /// - In `#[cfg_attr(docsrs, doc = "foo")]`, `None` is returned, "expected a single argument
513+ /// here" is emitted.
514+ /// - In `#[cfg()]`, `None` is returned, "expected an argument here" is emitted.
515+ ///
516+ /// The provided span is used as a fallback for diagnostic generation in case `arg` does not
517+ /// contain any. It should be the span of the node that contains `arg`.
518+ pub ( crate ) fn single_element_list < ' arg > (
519+ & mut self ,
520+ arg : & ' arg ArgParser ,
521+ span : Span ,
522+ ) -> Option < & ' arg MetaItemOrLitParser > {
523+ let ArgParser :: List ( l) = arg else {
524+ self . adcx ( ) . expected_list ( span, arg) ;
525+ return None ;
526+ } ;
527+
528+ let Some ( single) = l. single ( ) else {
529+ self . adcx ( ) . expected_single_argument ( l. span , l. len ( ) ) ;
530+ return None ;
531+ } ;
532+
533+ Some ( single)
534+ }
505535}
506536
507537impl < ' f , ' sess , S : Stage > Deref for AcceptContext < ' f , ' sess , S > {
@@ -689,6 +719,8 @@ where
689719 )
690720 }
691721
722+ /// The provided span is used as a fallback in case `args` does not contain any. It should be
723+ /// the span of the node that contains `args`.
692724 pub ( crate ) fn expected_list ( & mut self , span : Span , args : & ArgParser ) -> ErrorGuaranteed {
693725 let span = match args {
694726 ArgParser :: NoArgs => span,
@@ -745,7 +777,7 @@ where
745777 self . emit_parse_error ( span, AttributeParseErrorReason :: DuplicateKey ( key) )
746778 }
747779
748- /// An error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser)
780+ /// An error that should be emitted when a [`MetaItemOrLitParser`]
749781 /// was expected *not* to be a literal, but instead a meta item.
750782 pub ( crate ) fn expected_not_literal ( & mut self , span : Span ) -> ErrorGuaranteed {
751783 self . emit_parse_error ( span, AttributeParseErrorReason :: ExpectedNotLiteral )
0 commit comments