diff options
Diffstat (limited to 'crates/ide/src/diagnostics/unresolved_module.rs')
-rw-r--r-- | crates/ide/src/diagnostics/unresolved_module.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/crates/ide/src/diagnostics/unresolved_module.rs b/crates/ide/src/diagnostics/unresolved_module.rs new file mode 100644 index 000000000..977b46414 --- /dev/null +++ b/crates/ide/src/diagnostics/unresolved_module.rs | |||
@@ -0,0 +1,111 @@ | |||
1 | use hir::db::AstDatabase; | ||
2 | use ide_assists::Assist; | ||
3 | use ide_db::{base_db::AnchoredPathBuf, source_change::FileSystemEdit}; | ||
4 | use syntax::AstNode; | ||
5 | |||
6 | use crate::diagnostics::{fix, Diagnostic, DiagnosticsContext}; | ||
7 | |||
8 | // Diagnostic: unresolved-module | ||
9 | // | ||
10 | // This diagnostic is triggered if rust-analyzer is unable to discover referred module. | ||
11 | pub(super) fn unresolved_module( | ||
12 | ctx: &DiagnosticsContext<'_>, | ||
13 | d: &hir::UnresolvedModule, | ||
14 | ) -> Diagnostic { | ||
15 | Diagnostic::new( | ||
16 | "unresolved-module", | ||
17 | "unresolved module", | ||
18 | ctx.sema.diagnostics_display_range(d.decl.clone().map(|it| it.into())).range, | ||
19 | ) | ||
20 | .with_fixes(fixes(ctx, d)) | ||
21 | } | ||
22 | |||
23 | fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedModule) -> Option<Vec<Assist>> { | ||
24 | let root = ctx.sema.db.parse_or_expand(d.decl.file_id)?; | ||
25 | let unresolved_module = d.decl.value.to_node(&root); | ||
26 | Some(vec![fix( | ||
27 | "create_module", | ||
28 | "Create module", | ||
29 | FileSystemEdit::CreateFile { | ||
30 | dst: AnchoredPathBuf { | ||
31 | anchor: d.decl.file_id.original_file(ctx.sema.db), | ||
32 | path: d.candidate.clone(), | ||
33 | }, | ||
34 | initial_contents: "".to_string(), | ||
35 | } | ||
36 | .into(), | ||
37 | unresolved_module.syntax().text_range(), | ||
38 | )]) | ||
39 | } | ||
40 | |||
41 | #[cfg(test)] | ||
42 | mod tests { | ||
43 | use expect_test::expect; | ||
44 | |||
45 | use crate::diagnostics::tests::{check_diagnostics, check_expect}; | ||
46 | |||
47 | #[test] | ||
48 | fn unresolved_module() { | ||
49 | check_diagnostics( | ||
50 | r#" | ||
51 | //- /lib.rs | ||
52 | mod foo; | ||
53 | mod bar; | ||
54 | //^^^^^^^^ unresolved module | ||
55 | mod baz {} | ||
56 | //- /foo.rs | ||
57 | "#, | ||
58 | ); | ||
59 | } | ||
60 | |||
61 | #[test] | ||
62 | fn test_unresolved_module_diagnostic() { | ||
63 | check_expect( | ||
64 | r#"mod foo;"#, | ||
65 | expect![[r#" | ||
66 | [ | ||
67 | Diagnostic { | ||
68 | code: DiagnosticCode( | ||
69 | "unresolved-module", | ||
70 | ), | ||
71 | message: "unresolved module", | ||
72 | range: 0..8, | ||
73 | severity: Error, | ||
74 | unused: false, | ||
75 | experimental: false, | ||
76 | fixes: Some( | ||
77 | [ | ||
78 | Assist { | ||
79 | id: AssistId( | ||
80 | "create_module", | ||
81 | QuickFix, | ||
82 | ), | ||
83 | label: "Create module", | ||
84 | group: None, | ||
85 | target: 0..8, | ||
86 | source_change: Some( | ||
87 | SourceChange { | ||
88 | source_file_edits: {}, | ||
89 | file_system_edits: [ | ||
90 | CreateFile { | ||
91 | dst: AnchoredPathBuf { | ||
92 | anchor: FileId( | ||
93 | 0, | ||
94 | ), | ||
95 | path: "foo.rs", | ||
96 | }, | ||
97 | initial_contents: "", | ||
98 | }, | ||
99 | ], | ||
100 | is_snippet: false, | ||
101 | }, | ||
102 | ), | ||
103 | }, | ||
104 | ], | ||
105 | ), | ||
106 | }, | ||
107 | ] | ||
108 | "#]], | ||
109 | ); | ||
110 | } | ||
111 | } | ||