aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics/missing_ok_or_some_in_tail_expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/diagnostics/missing_ok_or_some_in_tail_expr.rs')
-rw-r--r--crates/ide/src/diagnostics/missing_ok_or_some_in_tail_expr.rs230
1 files changed, 0 insertions, 230 deletions
diff --git a/crates/ide/src/diagnostics/missing_ok_or_some_in_tail_expr.rs b/crates/ide/src/diagnostics/missing_ok_or_some_in_tail_expr.rs
deleted file mode 100644
index 06005d156..000000000
--- a/crates/ide/src/diagnostics/missing_ok_or_some_in_tail_expr.rs
+++ /dev/null
@@ -1,230 +0,0 @@
1use hir::db::AstDatabase;
2use ide_assists::Assist;
3use ide_db::source_change::SourceChange;
4use syntax::AstNode;
5use text_edit::TextEdit;
6
7use crate::diagnostics::{fix, Diagnostic, DiagnosticsContext};
8
9// Diagnostic: missing-ok-or-some-in-tail-expr
10//
11// This diagnostic is triggered if a block that should return `Result` returns a value not wrapped in `Ok`,
12// or if a block that should return `Option` returns a value not wrapped in `Some`.
13//
14// Example:
15//
16// ```rust
17// fn foo() -> Result<u8, ()> {
18// 10
19// }
20// ```
21pub(super) fn missing_ok_or_some_in_tail_expr(
22 ctx: &DiagnosticsContext<'_>,
23 d: &hir::MissingOkOrSomeInTailExpr,
24) -> Diagnostic {
25 Diagnostic::new(
26 "missing-ok-or-some-in-tail-expr",
27 format!("wrap return expression in {}", d.required),
28 ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range,
29 )
30 .with_fixes(fixes(ctx, d))
31}
32
33fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingOkOrSomeInTailExpr) -> Option<Vec<Assist>> {
34 let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
35 let tail_expr = d.expr.value.to_node(&root);
36 let tail_expr_range = tail_expr.syntax().text_range();
37 let replacement = format!("{}({})", d.required, tail_expr.syntax());
38 let edit = TextEdit::replace(tail_expr_range, replacement);
39 let source_change =
40 SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);
41 let name = if d.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" };
42 Some(vec![fix("wrap_tail_expr", name, source_change, tail_expr_range)])
43}
44
45#[cfg(test)]
46mod tests {
47 use crate::diagnostics::tests::{check_diagnostics, check_fix};
48
49 #[test]
50 fn test_wrap_return_type_option() {
51 check_fix(
52 r#"
53//- /main.rs crate:main deps:core
54use core::option::Option::{self, Some, None};
55
56fn div(x: i32, y: i32) -> Option<i32> {
57 if y == 0 {
58 return None;
59 }
60 x / y$0
61}
62//- /core/lib.rs crate:core
63pub mod result {
64 pub enum Result<T, E> { Ok(T), Err(E) }
65}
66pub mod option {
67 pub enum Option<T> { Some(T), None }
68}
69"#,
70 r#"
71use core::option::Option::{self, Some, None};
72
73fn div(x: i32, y: i32) -> Option<i32> {
74 if y == 0 {
75 return None;
76 }
77 Some(x / y)
78}
79"#,
80 );
81 }
82
83 #[test]
84 fn test_wrap_return_type() {
85 check_fix(
86 r#"
87//- /main.rs crate:main deps:core
88use core::result::Result::{self, Ok, Err};
89
90fn div(x: i32, y: i32) -> Result<i32, ()> {
91 if y == 0 {
92 return Err(());
93 }
94 x / y$0
95}
96//- /core/lib.rs crate:core
97pub mod result {
98 pub enum Result<T, E> { Ok(T), Err(E) }
99}
100pub mod option {
101 pub enum Option<T> { Some(T), None }
102}
103"#,
104 r#"
105use core::result::Result::{self, Ok, Err};
106
107fn div(x: i32, y: i32) -> Result<i32, ()> {
108 if y == 0 {
109 return Err(());
110 }
111 Ok(x / y)
112}
113"#,
114 );
115 }
116
117 #[test]
118 fn test_wrap_return_type_handles_generic_functions() {
119 check_fix(
120 r#"
121//- /main.rs crate:main deps:core
122use core::result::Result::{self, Ok, Err};
123
124fn div<T>(x: T) -> Result<T, i32> {
125 if x == 0 {
126 return Err(7);
127 }
128 $0x
129}
130//- /core/lib.rs crate:core
131pub mod result {
132 pub enum Result<T, E> { Ok(T), Err(E) }
133}
134pub mod option {
135 pub enum Option<T> { Some(T), None }
136}
137"#,
138 r#"
139use core::result::Result::{self, Ok, Err};
140
141fn div<T>(x: T) -> Result<T, i32> {
142 if x == 0 {
143 return Err(7);
144 }
145 Ok(x)
146}
147"#,
148 );
149 }
150
151 #[test]
152 fn test_wrap_return_type_handles_type_aliases() {
153 check_fix(
154 r#"
155//- /main.rs crate:main deps:core
156use core::result::Result::{self, Ok, Err};
157
158type MyResult<T> = Result<T, ()>;
159
160fn div(x: i32, y: i32) -> MyResult<i32> {
161 if y == 0 {
162 return Err(());
163 }
164 x $0/ y
165}
166//- /core/lib.rs crate:core
167pub mod result {
168 pub enum Result<T, E> { Ok(T), Err(E) }
169}
170pub mod option {
171 pub enum Option<T> { Some(T), None }
172}
173"#,
174 r#"
175use core::result::Result::{self, Ok, Err};
176
177type MyResult<T> = Result<T, ()>;
178
179fn div(x: i32, y: i32) -> MyResult<i32> {
180 if y == 0 {
181 return Err(());
182 }
183 Ok(x / y)
184}
185"#,
186 );
187 }
188
189 #[test]
190 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
191 check_diagnostics(
192 r#"
193//- /main.rs crate:main deps:core
194use core::result::Result::{self, Ok, Err};
195
196fn foo() -> Result<(), i32> { 0 }
197
198//- /core/lib.rs crate:core
199pub mod result {
200 pub enum Result<T, E> { Ok(T), Err(E) }
201}
202pub mod option {
203 pub enum Option<T> { Some(T), None }
204}
205"#,
206 );
207 }
208
209 #[test]
210 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() {
211 check_diagnostics(
212 r#"
213//- /main.rs crate:main deps:core
214use core::result::Result::{self, Ok, Err};
215
216enum SomeOtherEnum { Ok(i32), Err(String) }
217
218fn foo() -> SomeOtherEnum { 0 }
219
220//- /core/lib.rs crate:core
221pub mod result {
222 pub enum Result<T, E> { Ok(T), Err(E) }
223}
224pub mod option {
225 pub enum Option<T> { Some(T), None }
226}
227"#,
228 );
229 }
230}