use crate::linter::diagnostic::{Diagnostic, Severity, ViolationData};
use crate::linter::rules::{Rule, RuleContext};
use crate::semantic::BindingKind;
pub struct ShadowedBuiltin;
impl Rule for ShadowedBuiltin {
fn id(&self) -> &'static str {
"shadowed-builtin"
}
fn default_severity(&self) -> Severity {
Severity::Warning
}
fn run(&self, ctx: &RuleContext<'_>) -> Vec<Diagnostic> {
let mut out = Vec::new();
for (binding_idx, binding) in ctx.model.bindings().iter().enumerate() {
if !matches!(binding.kind, BindingKind::Local | BindingKind::Param) {
continue;
}
if !ctx.symbols.is_base(&binding.name) {
continue;
}
let id = crate::semantic::BindingId(binding_idx as u32);
let triggered = ctx.model.idents().iter().any(|ident| {
ident.name == binding.name
&& u32::from(ident.range.start()) > u32::from(binding.def_range.end())
&& ctx.model.resolve_local(ident) == Some(id)
});
if !triggered {
continue;
}
out.push(Diagnostic {
rule: "shadowed-builtin",
severity: Severity::Warning,
path: Default::default(),
range: binding.def_range,
message: ViolationData::new(
"shadowed-builtin",
format!(
"local binding `{}` shadows a base-R name later used in this scope",
binding.name
),
)
.with_suggestion(
"Rename the local, or fully qualify the base call (e.g. `base::c`).",
),
fix: None,
});
}
out
}
}