diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index ffb518b1e66f..b15e642daae7 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -267,7 +267,7 @@ impl Semantics<'_, DB> { &self, krate: Crate, item: ast::AnyHasAttrs, - ) -> impl Iterator { + ) -> impl DoubleEndedIterator { 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(); diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs index fdc426c32c7b..4a12c5a26d45 100644 --- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -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` diff --git a/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs index 84e63acbc04f..b7ec8fa53fa7 100644 --- a/crates/ide-diagnostics/src/handlers/unused_variables.rs +++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -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( diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index fe04bd175c96..343c28e8f9a4 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -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 { - 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,