aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/diagnostics')
-rw-r--r--crates/ide/src/diagnostics/unresolved_import.rs90
-rw-r--r--crates/ide/src/diagnostics/unresolved_macro_call.rs72
-rw-r--r--crates/ide/src/diagnostics/unresolved_module.rs1
3 files changed, 163 insertions, 0 deletions
diff --git a/crates/ide/src/diagnostics/unresolved_import.rs b/crates/ide/src/diagnostics/unresolved_import.rs
new file mode 100644
index 000000000..1cbf96ba1
--- /dev/null
+++ b/crates/ide/src/diagnostics/unresolved_import.rs
@@ -0,0 +1,90 @@
1use crate::diagnostics::{Diagnostic, DiagnosticsContext};
2
3// Diagnostic: unresolved-import
4//
5// This diagnostic is triggered if rust-analyzer is unable to resolve a path in
6// a `use` declaration.
7pub(super) fn unresolved_import(
8 ctx: &DiagnosticsContext<'_>,
9 d: &hir::UnresolvedImport,
10) -> Diagnostic {
11 Diagnostic::new(
12 "unresolved-import",
13 "unresolved import",
14 ctx.sema.diagnostics_display_range(d.decl.clone().map(|it| it.into())).range,
15 )
16 // This currently results in false positives in the following cases:
17 // - `cfg_if!`-generated code in libstd (we don't load the sysroot correctly)
18 // - `core::arch` (we don't handle `#[path = "../<path>"]` correctly)
19 // - proc macros and/or proc macro generated code
20 .experimental()
21}
22
23#[cfg(test)]
24mod tests {
25 use crate::diagnostics::tests::check_diagnostics;
26
27 #[test]
28 fn unresolved_import() {
29 check_diagnostics(
30 r#"
31use does_exist;
32use does_not_exist;
33 //^^^^^^^^^^^^^^ unresolved import
34
35mod does_exist {}
36"#,
37 );
38 }
39
40 #[test]
41 fn unresolved_import_in_use_tree() {
42 // Only the relevant part of a nested `use` item should be highlighted.
43 check_diagnostics(
44 r#"
45use does_exist::{Exists, DoesntExist};
46 //^^^^^^^^^^^ unresolved import
47
48use {does_not_exist::*, does_exist};
49 //^^^^^^^^^^^^^^^^^ unresolved import
50
51use does_not_exist::{
52 a,
53 //^ unresolved import
54 b,
55 //^ unresolved import
56 c,
57 //^ unresolved import
58};
59
60mod does_exist {
61 pub struct Exists;
62}
63"#,
64 );
65 }
66
67 #[test]
68 fn dedup_unresolved_import_from_unresolved_crate() {
69 check_diagnostics(
70 r#"
71//- /main.rs crate:main
72mod a {
73 extern crate doesnotexist;
74 //^^^^^^^^^^^^^^^^^^^^^^^^^^ unresolved extern crate
75
76 // Should not error, since we already errored for the missing crate.
77 use doesnotexist::{self, bla, *};
78
79 use crate::doesnotexist;
80 //^^^^^^^^^^^^^^^^^^^ unresolved import
81}
82
83mod m {
84 use super::doesnotexist;
85 //^^^^^^^^^^^^^^^^^^^ unresolved import
86}
87"#,
88 );
89 }
90}
diff --git a/crates/ide/src/diagnostics/unresolved_macro_call.rs b/crates/ide/src/diagnostics/unresolved_macro_call.rs
new file mode 100644
index 000000000..a3af332a4
--- /dev/null
+++ b/crates/ide/src/diagnostics/unresolved_macro_call.rs
@@ -0,0 +1,72 @@
1use hir::{db::AstDatabase, InFile};
2use syntax::{AstNode, SyntaxNodePtr};
3
4use crate::diagnostics::{Diagnostic, DiagnosticsContext};
5
6// Diagnostic: unresolved-macro-call
7//
8// This diagnostic is triggered if rust-analyzer is unable to resolve the path
9// to a macro in a macro invocation.
10pub(super) fn unresolved_macro_call(
11 ctx: &DiagnosticsContext<'_>,
12 d: &hir::UnresolvedMacroCall,
13) -> Diagnostic {
14 let last_path_segment = ctx.sema.db.parse_or_expand(d.macro_call.file_id).and_then(|root| {
15 d.macro_call
16 .value
17 .to_node(&root)
18 .path()
19 .and_then(|it| it.segment())
20 .and_then(|it| it.name_ref())
21 .map(|it| InFile::new(d.macro_call.file_id, SyntaxNodePtr::new(it.syntax())))
22 });
23 let diagnostics = last_path_segment.unwrap_or_else(|| d.macro_call.clone().map(|it| it.into()));
24
25 Diagnostic::new(
26 "unresolved-macro-call",
27 format!("unresolved macro `{}!`", d.path),
28 ctx.sema.diagnostics_display_range(diagnostics).range,
29 )
30 .experimental()
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::diagnostics::tests::check_diagnostics;
36
37 #[test]
38 fn test_unresolved_macro_range() {
39 check_diagnostics(
40 r#"
41foo::bar!(92);
42 //^^^ unresolved macro `foo::bar!`
43"#,
44 );
45 }
46
47 #[test]
48 fn unresolved_legacy_scope_macro() {
49 check_diagnostics(
50 r#"
51macro_rules! m { () => {} }
52
53m!(); m2!();
54 //^^ unresolved macro `self::m2!`
55"#,
56 );
57 }
58
59 #[test]
60 fn unresolved_module_scope_macro() {
61 check_diagnostics(
62 r#"
63mod mac {
64#[macro_export]
65macro_rules! m { () => {} } }
66
67self::m!(); self::m2!();
68 //^^ unresolved macro `self::m2!`
69"#,
70 );
71 }
72}
diff --git a/crates/ide/src/diagnostics/unresolved_module.rs b/crates/ide/src/diagnostics/unresolved_module.rs
index 4c8c74ff7..b1da8f0e1 100644
--- a/crates/ide/src/diagnostics/unresolved_module.rs
+++ b/crates/ide/src/diagnostics/unresolved_module.rs
@@ -104,6 +104,7 @@ mod baz {}
104 "unresolved-module", 104 "unresolved-module",
105 ), 105 ),
106 ), 106 ),
107 experimental: false,
107 }, 108 },
108 ] 109 ]
109 "#]], 110 "#]],