fix: respect rustc's lint attribute application order
Reverse the order of returned lint attributes for a `SyntaxNode` to match rustc's behavior. When multiple lint attributes are present, rustc overrides earlier ones with the last defined attribute. The previous iteration order was incorrect, causing earlier attributes to override the later ones.
This commit is contained in:
parent
b3e6363a47
commit
8bd369063e
4 changed files with 60 additions and 10 deletions
|
|
@ -267,7 +267,7 @@ impl<DB: HirDatabase + ?Sized> Semantics<'_, DB> {
|
|||
&self,
|
||||
krate: Crate,
|
||||
item: ast::AnyHasAttrs,
|
||||
) -> impl Iterator<Item = (LintAttr, SmolStr)> {
|
||||
) -> impl DoubleEndedIterator<Item = (LintAttr, SmolStr)> {
|
||||
let mut cfg_options = None;
|
||||
let cfg_options = || *cfg_options.get_or_insert_with(|| krate.id.cfg_options(self.db));
|
||||
let mut result = Vec::new();
|
||||
|
|
|
|||
|
|
@ -1000,7 +1000,8 @@ mod OtherBadCase;
|
|||
// ^^^^^^^^^^^^ 💡 error: Module `OtherBadCase` should have snake_case name, e.g. `other_bad_case`
|
||||
|
||||
//- /BAD_CASE/OtherBadCase.rs
|
||||
#![deny(non_snake_case)]
|
||||
#![allow(non_snake_case)]
|
||||
#![deny(non_snake_case)] // The lint level has been overridden.
|
||||
|
||||
fn FOO() {}
|
||||
// ^^^ 💡 error: Function `FOO` should have snake_case name, e.g. `foo`
|
||||
|
|
|
|||
|
|
@ -182,6 +182,61 @@ fn main2() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_last_lint_attribute_when_multiple_are_present() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
#![allow(unused_variables)]
|
||||
#![warn(unused_variables)]
|
||||
#![deny(unused_variables)]
|
||||
|
||||
fn main() {
|
||||
let x = 2;
|
||||
//^ 💡 error: unused variable
|
||||
|
||||
#[deny(unused_variables)]
|
||||
#[warn(unused_variables)]
|
||||
#[allow(unused_variables)]
|
||||
let y = 0;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefer_closest_ancestor_lint_attribute() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn main() {
|
||||
#![warn(unused_variables)]
|
||||
|
||||
#[deny(unused_variables)]
|
||||
let x = 2;
|
||||
//^ 💡 error: unused variable
|
||||
}
|
||||
|
||||
#[warn(unused_variables)]
|
||||
fn main2() {
|
||||
#[deny(unused_variables)]
|
||||
let x = 2;
|
||||
//^ 💡 error: unused variable
|
||||
}
|
||||
|
||||
#[warn(unused_variables)]
|
||||
fn main3() {
|
||||
let x = 2;
|
||||
//^ 💡 warn: unused variable
|
||||
}
|
||||
|
||||
fn main4() {
|
||||
let x = 2;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fix_unused_variable() {
|
||||
check_fix(
|
||||
|
|
|
|||
|
|
@ -643,19 +643,13 @@ fn find_outline_mod_lint_severity(
|
|||
|
||||
let mod_def = sema.to_module_def(&mod_node)?;
|
||||
let module_source_file = sema.module_definition_node(mod_def);
|
||||
let mut result = None;
|
||||
let lint_groups = lint_groups(&diag.code, edition);
|
||||
lint_attrs(
|
||||
sema,
|
||||
krate,
|
||||
ast::AnyHasAttrs::cast(module_source_file.value).expect("SourceFile always has attrs"),
|
||||
)
|
||||
.for_each(|(lint, severity)| {
|
||||
if lint_groups.contains(&lint) {
|
||||
result = Some(severity);
|
||||
}
|
||||
});
|
||||
result
|
||||
.find_map(|(lint, severity)| lint_groups.contains(&lint).then_some(severity))
|
||||
}
|
||||
|
||||
fn lint_severity_at(
|
||||
|
|
@ -682,7 +676,7 @@ fn lint_attrs(
|
|||
krate: hir::Crate,
|
||||
ancestor: ast::AnyHasAttrs,
|
||||
) -> impl Iterator<Item = (SmolStr, Severity)> {
|
||||
sema.lint_attrs(krate, ancestor).map(|(lint_attr, lint)| {
|
||||
sema.lint_attrs(krate, ancestor).rev().map(|(lint_attr, lint)| {
|
||||
let severity = match lint_attr {
|
||||
hir::LintAttr::Allow | hir::LintAttr::Expect => Severity::Allow,
|
||||
hir::LintAttr::Warn => Severity::Warning,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue