aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/diagnostics.rs')
-rw-r--r--crates/ide/src/diagnostics.rs88
1 files changed, 33 insertions, 55 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 1fbb7131d..1a4800832 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -6,6 +6,8 @@
6 6
7mod unresolved_module; 7mod unresolved_module;
8mod unresolved_extern_crate; 8mod unresolved_extern_crate;
9mod unresolved_import;
10mod unresolved_macro_call;
9mod missing_fields; 11mod missing_fields;
10 12
11mod fixes; 13mod fixes;
@@ -15,9 +17,8 @@ mod unlinked_file;
15use std::cell::RefCell; 17use std::cell::RefCell;
16 18
17use hir::{ 19use hir::{
18 db::AstDatabase,
19 diagnostics::{AnyDiagnostic, Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder}, 20 diagnostics::{AnyDiagnostic, Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder},
20 InFile, Semantics, 21 Semantics,
21}; 22};
22use ide_assists::AssistResolveStrategy; 23use ide_assists::AssistResolveStrategy;
23use ide_db::{base_db::SourceDatabase, RootDatabase}; 24use ide_db::{base_db::SourceDatabase, RootDatabase};
@@ -43,17 +44,39 @@ pub struct Diagnostic {
43 pub fixes: Option<Vec<Assist>>, 44 pub fixes: Option<Vec<Assist>>,
44 pub unused: bool, 45 pub unused: bool,
45 pub code: Option<DiagnosticCode>, 46 pub code: Option<DiagnosticCode>,
47 pub experimental: bool,
46} 48}
47 49
48impl Diagnostic { 50impl Diagnostic {
49 fn new(code: &'static str, message: impl Into<String>, range: TextRange) -> Diagnostic { 51 fn new(code: &'static str, message: impl Into<String>, range: TextRange) -> Diagnostic {
50 let message = message.into(); 52 let message = message.into();
51 let code = Some(DiagnosticCode(code)); 53 let code = Some(DiagnosticCode(code));
52 Self { message, range, severity: Severity::Error, fixes: None, unused: false, code } 54 Self {
55 message,
56 range,
57 severity: Severity::Error,
58 fixes: None,
59 unused: false,
60 code,
61 experimental: false,
62 }
63 }
64
65 fn experimental(mut self) -> Diagnostic {
66 self.experimental = true;
67 self
53 } 68 }
54 69
55 fn error(range: TextRange, message: String) -> Self { 70 fn error(range: TextRange, message: String) -> Self {
56 Self { message, range, severity: Severity::Error, fixes: None, unused: false, code: None } 71 Self {
72 message,
73 range,
74 severity: Severity::Error,
75 fixes: None,
76 unused: false,
77 code: None,
78 experimental: false,
79 }
57 } 80 }
58 81
59 fn hint(range: TextRange, message: String) -> Self { 82 fn hint(range: TextRange, message: String) -> Self {
@@ -64,6 +87,7 @@ impl Diagnostic {
64 fixes: None, 87 fixes: None,
65 unused: false, 88 unused: false,
66 code: None, 89 code: None,
90 experimental: false,
67 } 91 }
68 } 92 }
69 93
@@ -179,20 +203,6 @@ pub(crate) fn diagnostics(
179 res.borrow_mut() 203 res.borrow_mut()
180 .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code()))); 204 .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code())));
181 }) 205 })
182 .on::<hir::diagnostics::UnresolvedMacroCall, _>(|d| {
183 let last_path_segment = sema.db.parse_or_expand(d.file).and_then(|root| {
184 d.node
185 .to_node(&root)
186 .path()
187 .and_then(|it| it.segment())
188 .and_then(|it| it.name_ref())
189 .map(|it| InFile::new(d.file, SyntaxNodePtr::new(it.syntax())))
190 });
191 let diagnostics = last_path_segment.unwrap_or_else(|| d.display_source());
192 let display_range = sema.diagnostics_display_range(diagnostics).range;
193 res.borrow_mut()
194 .push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code())));
195 })
196 .on::<hir::diagnostics::UnimplementedBuiltinMacro, _>(|d| { 206 .on::<hir::diagnostics::UnimplementedBuiltinMacro, _>(|d| {
197 let display_range = sema.diagnostics_display_range(d.display_source()).range; 207 let display_range = sema.diagnostics_display_range(d.display_source()).range;
198 res.borrow_mut() 208 res.borrow_mut()
@@ -234,6 +244,8 @@ pub(crate) fn diagnostics(
234 let d = match diag { 244 let d = match diag {
235 AnyDiagnostic::UnresolvedModule(d) => unresolved_module::unresolved_module(&ctx, &d), 245 AnyDiagnostic::UnresolvedModule(d) => unresolved_module::unresolved_module(&ctx, &d),
236 AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d), 246 AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
247 AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d),
248 AnyDiagnostic::UnresolvedMacroCall(d) => unresolved_macro_call::unresolved_macro_call(&ctx, &d),
237 AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), 249 AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
238 }; 250 };
239 if let Some(code) = d.code { 251 if let Some(code) = d.code {
@@ -241,6 +253,9 @@ pub(crate) fn diagnostics(
241 continue; 253 continue;
242 } 254 }
243 } 255 }
256 if ctx.config.disable_experimental && d.experimental {
257 continue;
258 }
244 res.push(d) 259 res.push(d)
245 } 260 }
246 261
@@ -453,43 +468,6 @@ mod tests {
453 } 468 }
454 469
455 #[test] 470 #[test]
456 fn test_unresolved_macro_range() {
457 check_diagnostics(
458 r#"
459foo::bar!(92);
460 //^^^ unresolved macro `foo::bar!`
461"#,
462 );
463 }
464
465 #[test]
466 fn unresolved_import_in_use_tree() {
467 // Only the relevant part of a nested `use` item should be highlighted.
468 check_diagnostics(
469 r#"
470use does_exist::{Exists, DoesntExist};
471 //^^^^^^^^^^^ unresolved import
472
473use {does_not_exist::*, does_exist};
474 //^^^^^^^^^^^^^^^^^ unresolved import
475
476use does_not_exist::{
477 a,
478 //^ unresolved import
479 b,
480 //^ unresolved import
481 c,
482 //^ unresolved import
483};
484
485mod does_exist {
486 pub struct Exists;
487}
488"#,
489 );
490 }
491
492 #[test]
493 fn range_mapping_out_of_macros() { 471 fn range_mapping_out_of_macros() {
494 // FIXME: this is very wrong, but somewhat tricky to fix. 472 // FIXME: this is very wrong, but somewhat tricky to fix.
495 check_fix( 473 check_fix(