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