]>
Commit | Line | Data |
---|---|---|
353b0b11 | 1 | use hir::db::ExpandDatabase; |
064997fb FG |
2 | use ide_db::{assists::Assist, base_db::AnchoredPathBuf, source_change::FileSystemEdit}; |
3 | use itertools::Itertools; | |
4 | use syntax::AstNode; | |
5 | ||
add651ee | 6 | use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext}; |
064997fb FG |
7 | |
8 | // Diagnostic: unresolved-module | |
9 | // | |
10 | // This diagnostic is triggered if rust-analyzer is unable to discover referred module. | |
11 | pub(crate) fn unresolved_module( | |
12 | ctx: &DiagnosticsContext<'_>, | |
13 | d: &hir::UnresolvedModule, | |
14 | ) -> Diagnostic { | |
add651ee FG |
15 | Diagnostic::new_with_syntax_node_ptr( |
16 | ctx, | |
17 | DiagnosticCode::RustcHardError("E0583"), | |
064997fb FG |
18 | match &*d.candidates { |
19 | [] => "unresolved module".to_string(), | |
9c376795 | 20 | [candidate] => format!("unresolved module, can't find module file: {candidate}"), |
064997fb FG |
21 | [candidates @ .., last] => { |
22 | format!( | |
23 | "unresolved module, can't find module file: {}, or {}", | |
24 | candidates.iter().format(", "), | |
25 | last | |
26 | ) | |
27 | } | |
28 | }, | |
add651ee | 29 | d.decl.clone().map(|it| it.into()), |
064997fb FG |
30 | ) |
31 | .with_fixes(fixes(ctx, d)) | |
32 | } | |
33 | ||
34 | fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedModule) -> Option<Vec<Assist>> { | |
fe692bf9 | 35 | let root = ctx.sema.db.parse_or_expand(d.decl.file_id); |
064997fb FG |
36 | let unresolved_module = d.decl.value.to_node(&root); |
37 | Some( | |
38 | d.candidates | |
39 | .iter() | |
40 | .map(|candidate| { | |
41 | fix( | |
42 | "create_module", | |
43 | &format!("Create module at `{candidate}`"), | |
44 | FileSystemEdit::CreateFile { | |
45 | dst: AnchoredPathBuf { | |
46 | anchor: d.decl.file_id.original_file(ctx.sema.db), | |
47 | path: candidate.clone(), | |
48 | }, | |
49 | initial_contents: "".to_string(), | |
50 | } | |
51 | .into(), | |
52 | unresolved_module.syntax().text_range(), | |
53 | ) | |
54 | }) | |
55 | .collect(), | |
56 | ) | |
57 | } | |
58 | ||
59 | #[cfg(test)] | |
60 | mod tests { | |
61 | use expect_test::expect; | |
62 | ||
63 | use crate::tests::{check_diagnostics, check_expect}; | |
64 | ||
65 | #[test] | |
66 | fn unresolved_module() { | |
67 | check_diagnostics( | |
68 | r#" | |
69 | //- /lib.rs | |
70 | mod foo; | |
71 | mod bar; | |
72 | //^^^^^^^^ 💡 error: unresolved module, can't find module file: bar.rs, or bar/mod.rs | |
73 | mod baz {} | |
74 | //- /foo.rs | |
75 | "#, | |
76 | ); | |
77 | } | |
78 | ||
79 | #[test] | |
80 | fn test_unresolved_module_diagnostic() { | |
81 | check_expect( | |
82 | r#"mod foo;"#, | |
83 | expect![[r#" | |
84 | [ | |
85 | Diagnostic { | |
add651ee FG |
86 | code: RustcHardError( |
87 | "E0583", | |
064997fb FG |
88 | ), |
89 | message: "unresolved module, can't find module file: foo.rs, or foo/mod.rs", | |
90 | range: 0..8, | |
91 | severity: Error, | |
92 | unused: false, | |
93 | experimental: false, | |
94 | fixes: Some( | |
95 | [ | |
96 | Assist { | |
97 | id: AssistId( | |
98 | "create_module", | |
99 | QuickFix, | |
100 | ), | |
101 | label: "Create module at `foo.rs`", | |
102 | group: None, | |
103 | target: 0..8, | |
104 | source_change: Some( | |
105 | SourceChange { | |
106 | source_file_edits: {}, | |
107 | file_system_edits: [ | |
108 | CreateFile { | |
109 | dst: AnchoredPathBuf { | |
110 | anchor: FileId( | |
111 | 0, | |
112 | ), | |
113 | path: "foo.rs", | |
114 | }, | |
115 | initial_contents: "", | |
116 | }, | |
117 | ], | |
118 | is_snippet: false, | |
119 | }, | |
120 | ), | |
121 | trigger_signature_help: false, | |
122 | }, | |
123 | Assist { | |
124 | id: AssistId( | |
125 | "create_module", | |
126 | QuickFix, | |
127 | ), | |
128 | label: "Create module at `foo/mod.rs`", | |
129 | group: None, | |
130 | target: 0..8, | |
131 | source_change: Some( | |
132 | SourceChange { | |
133 | source_file_edits: {}, | |
134 | file_system_edits: [ | |
135 | CreateFile { | |
136 | dst: AnchoredPathBuf { | |
137 | anchor: FileId( | |
138 | 0, | |
139 | ), | |
140 | path: "foo/mod.rs", | |
141 | }, | |
142 | initial_contents: "", | |
143 | }, | |
144 | ], | |
145 | is_snippet: false, | |
146 | }, | |
147 | ), | |
148 | trigger_signature_help: false, | |
149 | }, | |
150 | ], | |
151 | ), | |
add651ee FG |
152 | main_node: Some( |
153 | InFile { | |
154 | file_id: FileId( | |
155 | FileId( | |
156 | 0, | |
157 | ), | |
158 | ), | |
159 | value: MODULE@0..8 | |
160 | MOD_KW@0..3 "mod" | |
161 | WHITESPACE@3..4 " " | |
162 | NAME@4..7 | |
163 | IDENT@4..7 "foo" | |
164 | SEMICOLON@7..8 ";" | |
165 | , | |
166 | }, | |
167 | ), | |
064997fb FG |
168 | }, |
169 | ] | |
170 | "#]], | |
171 | ); | |
172 | } | |
173 | } |