use std::collections::HashSet;
use rowan::ast::AstNode as _;
use crate::ast::CallExpr;
use crate::linter::diagnostic::{Diagnostic, Severity, ViolationData};
use crate::linter::rules::matchers;
use crate::linter::rules::{Rule, RuleContext};
use crate::syntax::{SyntaxElement, SyntaxKind};
pub struct DuplicatedArguments;
impl Rule for DuplicatedArguments {
fn id(&self) -> &'static str {
"duplicated-arguments"
}
fn interests(&self) -> &'static [SyntaxKind] {
&[SyntaxKind::CALL_EXPR]
}
fn check(&self, el: &SyntaxElement, _ctx: &RuleContext<'_>, sink: &mut Vec<Diagnostic>) {
let Some(call) = el.as_node().cloned().and_then(CallExpr::cast) else {
return;
};
let mut seen: HashSet<String> = HashSet::new();
for arg in matchers::args(&call) {
let (Some(name), Some(token)) = (arg.name, arg.name_token) else {
continue;
};
if !seen.insert(name.to_string()) {
sink.push(Diagnostic {
rule: "duplicated-arguments",
severity: Severity::Warning,
path: Default::default(),
range: token.text_range(),
message: ViolationData::new(
"duplicated-arguments",
format!("argument `{name}` is supplied more than once in this call"),
)
.with_suggestion("Remove or rename the duplicate argument."),
fix: None,
});
}
}
}
}