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