blob: 77b494328c70c336554b0a0713ae5c2f9cf857d1 [file] [log] [blame]
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::AttributeLintKind;
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
pub(crate) struct IgnoreParser;
impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
const PATH: &[Symbol] = &[sym::ignore];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
Some(AttributeKind::Ignore {
span: cx.attr_span,
reason: match args {
ArgParser::NoArgs => None,
ArgParser::NameValue(name_value) => {
let Some(str_value) = name_value.value_as_str() else {
let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
.suggestions(false, "ignore");
let span = cx.attr_span;
cx.emit_lint(
AttributeLintKind::IllFormedAttributeInput { suggestions },
span,
);
return None;
};
Some(str_value)
}
ArgParser::List(_) => {
let suggestions =
<Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "ignore");
let span = cx.attr_span;
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
return None;
}
},
})
}
}
pub(crate) struct ShouldPanicParser;
impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
const PATH: &[Symbol] = &[sym::should_panic];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate =
template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
Some(AttributeKind::ShouldPanic {
span: cx.attr_span,
reason: match args {
ArgParser::NoArgs => None,
ArgParser::NameValue(name_value) => {
let Some(str_value) = name_value.value_as_str() else {
cx.expected_string_literal(
name_value.value_span,
Some(name_value.value_as_lit()),
);
return None;
};
Some(str_value)
}
ArgParser::List(list) => {
let Some(single) = list.single() else {
cx.expected_single_argument(list.span);
return None;
};
let Some(single) = single.meta_item() else {
cx.expected_name_value(single.span(), Some(sym::expected));
return None;
};
if !single.path().word_is(sym::expected) {
cx.expected_specific_argument_strings(list.span, vec!["expected"]);
return None;
}
let Some(nv) = single.args().name_value() else {
cx.expected_name_value(single.span(), Some(sym::expected));
return None;
};
let Some(expected) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};
Some(expected)
}
},
})
}
}