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