use super::*;
define_rule! {
AttributeArgumentsRule {
id: "attribute-arguments",
message: "invalid attribute arguments",
run(context) {
let mut diagnostics = Vec::new();
for attribute in context.attributes() {
let attribute_name = &attribute.name.value;
let matching = context.builtin_attributes(attribute_name);
if matching.is_empty() {
continue;
}
let argument_count = attribute.arguments.len();
let has_arguments = argument_count > 0;
let parameter_mismatch = matching.iter().copied().all(|attr| {
if let Builtin::Attribute { parameters, .. } = attr {
(parameters.is_some() && !has_arguments)
|| (parameters.is_none() && has_arguments)
|| (parameters.map_or(0, |_| 1) < argument_count)
} else {
false
}
});
if parameter_mismatch {
let required_argument_count = matching
.iter()
.copied()
.find_map(|attr| {
if let Builtin::Attribute { parameters, .. } = attr {
parameters.map(|_| 1)
} else {
None
}
})
.unwrap_or(0);
diagnostics.push(Diagnostic::error(
format!(
"Attribute `{attribute_name}` got {argument_count} {} but takes {required_argument_count} {}",
Count("argument", argument_count),
Count("argument", required_argument_count),
),
attribute.range,
));
}
}
diagnostics
}
}
}