diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index d2056b1e7cdb..4fb449117d00 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -543,6 +543,10 @@ impl<'db> SemanticsImpl<'db> { node } + pub fn to_node_syntax(&self, ptr: InFile) -> SyntaxNode { + ptr.value.to_node(&self.parse_or_expand(ptr.file_id)) + } + pub fn to_node(&self, ptr: InFile>) -> N { ptr.value.to_node(&self.parse_or_expand(ptr.file_id)) } diff --git a/crates/ide-diagnostics/src/handlers/field_shorthand.rs b/crates/ide-diagnostics/src/handlers/field_shorthand.rs index 1dc6a7bf9cae..0c77fbbd555b 100644 --- a/crates/ide-diagnostics/src/handlers/field_shorthand.rs +++ b/crates/ide-diagnostics/src/handlers/field_shorthand.rs @@ -220,4 +220,24 @@ fn f(a: A) { "#, ); } + + #[test] + fn diagnostic_range_respect_allows() { + check_diagnostics( + r#" +#![allow(clippy::redundant_field_names, unused)] + +struct Foo { + bar: u32, +} + +fn main() { + let bar = 23; + let foo = Foo { + bar: bar, + }; +} + "#, + ); + } } diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index a490d48fed6a..e2e465e26c78 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -228,6 +228,25 @@ impl Diagnostic { self.unused = unused; self } + + fn main_node(&self, sema: &Semantics<'_, RootDatabase>) -> Option> { + self.main_node.map(|ptr| ptr.with_value(sema.to_node_syntax(ptr))).or_else(|| { + let token = sema + .parse_guess_edition(self.range.file_id) + .syntax() + .token_at_offset(self.range.range.start()) + .right_biased()?; + sema.descend_into_macros(token).into_iter().find_map(|token| { + let node = sema.ancestors_with_macros(token.parent().unwrap()).find(|node| { + let original_range = sema.original_range(node); + original_range.file_id.file_id(sema.db) == self.range.file_id + && original_range.range.contains_range(self.range.range) + })?; + let file = sema.hir_file_for(&node); + Some(InFile::new(file, node)) + }) + }) + } } #[derive(Debug, Clone)] @@ -511,14 +530,7 @@ pub fn semantic_diagnostics( let mut lints = res .iter_mut() .filter(|it| matches!(it.code, DiagnosticCode::Clippy(_) | DiagnosticCode::RustcLint(_))) - .filter_map(|it| { - Some(( - it.main_node.map(|ptr| { - ptr.map(|node| node.to_node(&ctx.sema.parse_or_expand(ptr.file_id))) - })?, - it, - )) - }) + .filter_map(|it| Some((it.main_node(&ctx.sema)?, it))) .collect::>(); // The edition isn't accurate (each diagnostics may have its own edition due to macros),