diff options
author | Aleksey Kladov <[email protected]> | 2021-02-28 11:12:11 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-02-28 11:29:10 +0000 |
commit | 05729fd3c4aa542d162b54e7352c0d4bade62684 (patch) | |
tree | 5e0c37057750cc897031a02ec4860462a4cea9ef /crates/ide | |
parent | c412d5f8d13cd55dc1873fb55e742a317c7846a8 (diff) |
For unresolved macros, hightlight only the last segment
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/diagnostics.rs | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 8607139ba..fe32f39b6 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -10,15 +10,16 @@ mod field_shorthand; | |||
10 | use std::cell::RefCell; | 10 | use std::cell::RefCell; |
11 | 11 | ||
12 | use hir::{ | 12 | use hir::{ |
13 | db::AstDatabase, | ||
13 | diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder}, | 14 | diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder}, |
14 | Semantics, | 15 | InFile, Semantics, |
15 | }; | 16 | }; |
16 | use ide_db::{base_db::SourceDatabase, RootDatabase}; | 17 | use ide_db::{base_db::SourceDatabase, RootDatabase}; |
17 | use itertools::Itertools; | 18 | use itertools::Itertools; |
18 | use rustc_hash::FxHashSet; | 19 | use rustc_hash::FxHashSet; |
19 | use syntax::{ | 20 | use syntax::{ |
20 | ast::{self, AstNode}, | 21 | ast::{self, AstNode}, |
21 | SyntaxNode, TextRange, | 22 | SyntaxNode, SyntaxNodePtr, TextRange, |
22 | }; | 23 | }; |
23 | use text_edit::TextEdit; | 24 | use text_edit::TextEdit; |
24 | 25 | ||
@@ -147,20 +148,38 @@ pub(crate) fn diagnostics( | |||
147 | 148 | ||
148 | // Override severity and mark as unused. | 149 | // Override severity and mark as unused. |
149 | res.borrow_mut().push( | 150 | res.borrow_mut().push( |
150 | Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message()) | 151 | Diagnostic::hint( |
151 | .with_unused(true) | 152 | sema.diagnostics_display_range(d.display_source()).range, |
152 | .with_code(Some(d.code())), | 153 | d.message(), |
154 | ) | ||
155 | .with_unused(true) | ||
156 | .with_code(Some(d.code())), | ||
153 | ); | 157 | ); |
154 | }) | 158 | }) |
155 | .on::<hir::diagnostics::UnresolvedProcMacro, _>(|d| { | 159 | .on::<hir::diagnostics::UnresolvedProcMacro, _>(|d| { |
156 | // Use more accurate position if available. | 160 | // Use more accurate position if available. |
157 | let display_range = | 161 | let display_range = d |
158 | d.precise_location.unwrap_or_else(|| sema.diagnostics_display_range(d).range); | 162 | .precise_location |
163 | .unwrap_or_else(|| sema.diagnostics_display_range(d.display_source()).range); | ||
159 | 164 | ||
160 | // FIXME: it would be nice to tell the user whether proc macros are currently disabled | 165 | // FIXME: it would be nice to tell the user whether proc macros are currently disabled |
161 | res.borrow_mut() | 166 | res.borrow_mut() |
162 | .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code()))); | 167 | .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code()))); |
163 | }) | 168 | }) |
169 | .on::<hir::diagnostics::UnresolvedMacroCall, _>(|d| { | ||
170 | let last_path_segment = sema.db.parse_or_expand(d.file).and_then(|root| { | ||
171 | d.node | ||
172 | .to_node(&root) | ||
173 | .path() | ||
174 | .and_then(|it| it.segment()) | ||
175 | .and_then(|it| it.name_ref()) | ||
176 | .map(|it| InFile::new(d.file, SyntaxNodePtr::new(it.syntax()))) | ||
177 | }); | ||
178 | let diagnostics = last_path_segment.unwrap_or_else(|| d.display_source()); | ||
179 | let display_range = sema.diagnostics_display_range(diagnostics).range; | ||
180 | res.borrow_mut() | ||
181 | .push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code()))); | ||
182 | }) | ||
164 | // Only collect experimental diagnostics when they're enabled. | 183 | // Only collect experimental diagnostics when they're enabled. |
165 | .filter(|diag| !(diag.is_experimental() && config.disable_experimental)) | 184 | .filter(|diag| !(diag.is_experimental() && config.disable_experimental)) |
166 | .filter(|diag| !config.disabled.contains(diag.code().as_str())); | 185 | .filter(|diag| !config.disabled.contains(diag.code().as_str())); |
@@ -170,8 +189,11 @@ pub(crate) fn diagnostics( | |||
170 | // Diagnostics not handled above get no fix and default treatment. | 189 | // Diagnostics not handled above get no fix and default treatment. |
171 | .build(|d| { | 190 | .build(|d| { |
172 | res.borrow_mut().push( | 191 | res.borrow_mut().push( |
173 | Diagnostic::error(sema.diagnostics_display_range(d).range, d.message()) | 192 | Diagnostic::error( |
174 | .with_code(Some(d.code())), | 193 | sema.diagnostics_display_range(d.display_source()).range, |
194 | d.message(), | ||
195 | ) | ||
196 | .with_code(Some(d.code())), | ||
175 | ); | 197 | ); |
176 | }); | 198 | }); |
177 | 199 | ||
@@ -183,13 +205,13 @@ pub(crate) fn diagnostics( | |||
183 | } | 205 | } |
184 | 206 | ||
185 | fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { | 207 | fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { |
186 | Diagnostic::error(sema.diagnostics_display_range(d).range, d.message()) | 208 | Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) |
187 | .with_fix(d.fix(&sema)) | 209 | .with_fix(d.fix(&sema)) |
188 | .with_code(Some(d.code())) | 210 | .with_code(Some(d.code())) |
189 | } | 211 | } |
190 | 212 | ||
191 | fn warning_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { | 213 | fn warning_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { |
192 | Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message()) | 214 | Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) |
193 | .with_fix(d.fix(&sema)) | 215 | .with_fix(d.fix(&sema)) |
194 | .with_code(Some(d.code())) | 216 | .with_code(Some(d.code())) |
195 | } | 217 | } |
@@ -646,6 +668,29 @@ fn test_fn() { | |||
646 | } | 668 | } |
647 | 669 | ||
648 | #[test] | 670 | #[test] |
671 | fn test_unresolved_macro_range() { | ||
672 | check_expect( | ||
673 | r#"foo::bar!(92);"#, | ||
674 | expect![[r#" | ||
675 | [ | ||
676 | Diagnostic { | ||
677 | message: "unresolved macro call", | ||
678 | range: 5..8, | ||
679 | severity: Error, | ||
680 | fix: None, | ||
681 | unused: false, | ||
682 | code: Some( | ||
683 | DiagnosticCode( | ||
684 | "unresolved-macro-call", | ||
685 | ), | ||
686 | ), | ||
687 | }, | ||
688 | ] | ||
689 | "#]], | ||
690 | ); | ||
691 | } | ||
692 | |||
693 | #[test] | ||
649 | fn range_mapping_out_of_macros() { | 694 | fn range_mapping_out_of_macros() { |
650 | // FIXME: this is very wrong, but somewhat tricky to fix. | 695 | // FIXME: this is very wrong, but somewhat tricky to fix. |
651 | check_fix( | 696 | check_fix( |