Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-diagnostics/src/lib.rs')
| -rw-r--r-- | crates/ide-diagnostics/src/lib.rs | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 6744895f3c..6541bf6057 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -23,7 +23,7 @@ //! There are also a couple of ad-hoc diagnostics implemented directly here, we //! don't yet have a great pattern for how to do them properly. -#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![warn(rust_2018_idioms, unused_lifetimes)] mod handlers { pub(crate) mod break_outside_of_loop; @@ -47,6 +47,7 @@ mod handlers { pub(crate) mod trait_impl_orphan; pub(crate) mod trait_impl_incorrect_safety; pub(crate) mod trait_impl_missing_assoc_item; + pub(crate) mod trait_impl_redundant_assoc_item; pub(crate) mod typed_hole; pub(crate) mod type_mismatch; pub(crate) mod unimplemented_builtin_macro; @@ -89,7 +90,7 @@ use stdx::never; use syntax::{ algo::find_node_at_range, ast::{self, AstNode}, - SyntaxNode, SyntaxNodePtr, TextRange, + AstPtr, SyntaxNode, SyntaxNodePtr, TextRange, }; // FIXME: Make this an enum @@ -133,7 +134,7 @@ impl DiagnosticCode { pub struct Diagnostic { pub code: DiagnosticCode, pub message: String, - pub range: TextRange, + pub range: FileRange, pub severity: Severity, pub unused: bool, pub experimental: bool, @@ -143,7 +144,7 @@ pub struct Diagnostic { } impl Diagnostic { - fn new(code: DiagnosticCode, message: impl Into<String>, range: TextRange) -> Diagnostic { + fn new(code: DiagnosticCode, message: impl Into<String>, range: FileRange) -> Diagnostic { let message = message.into(); Diagnostic { code, @@ -172,7 +173,7 @@ impl Diagnostic { node: InFile<SyntaxNodePtr>, ) -> Diagnostic { let file_id = node.file_id; - Diagnostic::new(code, message, ctx.sema.diagnostics_display_range(node.clone()).range) + Diagnostic::new(code, message, ctx.sema.diagnostics_display_range(node.clone())) .with_main_node(node.map(|x| x.to_node(&ctx.sema.parse_or_expand(file_id)))) } @@ -267,7 +268,7 @@ impl DiagnosticsContext<'_> { &self, node: &InFile<SyntaxNodePtr>, precise_location: Option<TextRange>, - ) -> TextRange { + ) -> FileRange { let sema = &self.sema; (|| { let precise_location = precise_location?; @@ -280,10 +281,11 @@ impl DiagnosticsContext<'_> { } })() .unwrap_or_else(|| sema.diagnostics_display_range(node.clone())) - .range } } +/// Request diagnostics for the given [`FileId`]. The produced diagnostics may point to other files +/// due to macros. pub fn diagnostics( db: &RootDatabase, config: &DiagnosticsConfig, @@ -300,7 +302,7 @@ pub fn diagnostics( Diagnostic::new( DiagnosticCode::RustcHardError("syntax-error"), format!("Syntax Error: {err}"), - err.range(), + FileRange { file_id, range: err.range() }, ) })); @@ -363,6 +365,7 @@ pub fn diagnostics( AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => handlers::replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d), AnyDiagnostic::TraitImplIncorrectSafety(d) => handlers::trait_impl_incorrect_safety::trait_impl_incorrect_safety(&ctx, &d), AnyDiagnostic::TraitImplMissingAssocItems(d) => handlers::trait_impl_missing_assoc_item::trait_impl_missing_assoc_item(&ctx, &d), + AnyDiagnostic::TraitImplRedundantAssocItems(d) => handlers::trait_impl_redundant_assoc_item::trait_impl_redundant_assoc_item(&ctx, &d), AnyDiagnostic::TraitImplOrphan(d) => handlers::trait_impl_orphan::trait_impl_orphan(&ctx, &d), AnyDiagnostic::TypedHole(d) => handlers::typed_hole::typed_hole(&ctx, &d), AnyDiagnostic::TypeMismatch(d) => handlers::type_mismatch::type_mismatch(&ctx, &d), @@ -569,12 +572,28 @@ fn adjusted_display_range<N: AstNode>( ctx: &DiagnosticsContext<'_>, diag_ptr: InFile<SyntaxNodePtr>, adj: &dyn Fn(N) -> Option<TextRange>, -) -> TextRange { +) -> FileRange { let FileRange { file_id, range } = ctx.sema.diagnostics_display_range(diag_ptr); let source_file = ctx.sema.db.parse(file_id); - find_node_at_range::<N>(&source_file.syntax_node(), range) - .filter(|it| it.syntax().text_range() == range) - .and_then(adj) - .unwrap_or(range) + FileRange { + file_id, + range: find_node_at_range::<N>(&source_file.syntax_node(), range) + .filter(|it| it.syntax().text_range() == range) + .and_then(adj) + .unwrap_or(range), + } +} + +// FIXME Replace the one above with this one? +fn adjusted_display_range_new<N: AstNode>( + ctx: &DiagnosticsContext<'_>, + diag_ptr: InFile<AstPtr<N>>, + adj: &dyn Fn(N) -> Option<TextRange>, +) -> FileRange { + let source_file = ctx.sema.parse_or_expand(diag_ptr.file_id); + let node = diag_ptr.value.to_node(&source_file); + diag_ptr + .with_value(adj(node).unwrap_or_else(|| diag_ptr.value.text_range())) + .original_node_file_range_rooted(ctx.sema.db) } |