1 use hir::{db::AstDatabase, diagnostics::MissingOkOrSomeInTailExpr, Semantics};
2 use ide_assists::{Assist, AssistResolveStrategy};
3 use ide_db::{source_change::SourceChange, RootDatabase};
5 use text_edit::TextEdit;
7 use crate::diagnostics::{fix, DiagnosticWithFix};
9 impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
12 sema: &Semantics<RootDatabase>,
13 _resolve: &AssistResolveStrategy,
15 let root = sema.db.parse_or_expand(self.file)?;
16 let tail_expr = self.expr.to_node(&root);
17 let tail_expr_range = tail_expr.syntax().text_range();
18 let replacement = format!("{}({})", self.required, tail_expr.syntax());
19 let edit = TextEdit::replace(tail_expr_range, replacement);
20 let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);
21 let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" };
22 Some(fix("wrap_tail_expr", name, source_change, tail_expr_range))
28 use crate::diagnostics::tests::{check_fix, check_no_diagnostics};
31 fn test_wrap_return_type_option() {
34 //- /main.rs crate:main deps:core
35 use core::option::Option::{self, Some, None};
37 fn div(x: i32, y: i32) -> Option<i32> {
43 //- /core/lib.rs crate:core
45 pub enum Result<T, E> { Ok(T), Err(E) }
48 pub enum Option<T> { Some(T), None }
52 use core::option::Option::{self, Some, None};
54 fn div(x: i32, y: i32) -> Option<i32> {
65 fn test_wrap_return_type() {
68 //- /main.rs crate:main deps:core
69 use core::result::Result::{self, Ok, Err};
71 fn div(x: i32, y: i32) -> Result<i32, ()> {
77 //- /core/lib.rs crate:core
79 pub enum Result<T, E> { Ok(T), Err(E) }
82 pub enum Option<T> { Some(T), None }
86 use core::result::Result::{self, Ok, Err};
88 fn div(x: i32, y: i32) -> Result<i32, ()> {
99 fn test_wrap_return_type_handles_generic_functions() {
102 //- /main.rs crate:main deps:core
103 use core::result::Result::{self, Ok, Err};
105 fn div<T>(x: T) -> Result<T, i32> {
111 //- /core/lib.rs crate:core
113 pub enum Result<T, E> { Ok(T), Err(E) }
116 pub enum Option<T> { Some(T), None }
120 use core::result::Result::{self, Ok, Err};
122 fn div<T>(x: T) -> Result<T, i32> {
133 fn test_wrap_return_type_handles_type_aliases() {
136 //- /main.rs crate:main deps:core
137 use core::result::Result::{self, Ok, Err};
139 type MyResult<T> = Result<T, ()>;
141 fn div(x: i32, y: i32) -> MyResult<i32> {
147 //- /core/lib.rs crate:core
149 pub enum Result<T, E> { Ok(T), Err(E) }
152 pub enum Option<T> { Some(T), None }
156 use core::result::Result::{self, Ok, Err};
158 type MyResult<T> = Result<T, ()>;
160 fn div(x: i32, y: i32) -> MyResult<i32> {
171 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
172 check_no_diagnostics(
174 //- /main.rs crate:main deps:core
175 use core::result::Result::{self, Ok, Err};
177 fn foo() -> Result<(), i32> { 0 }
179 //- /core/lib.rs crate:core
181 pub enum Result<T, E> { Ok(T), Err(E) }
184 pub enum Option<T> { Some(T), None }
191 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() {
192 check_no_diagnostics(
194 //- /main.rs crate:main deps:core
195 use core::result::Result::{self, Ok, Err};
197 enum SomeOtherEnum { Ok(i32), Err(String) }
199 fn foo() -> SomeOtherEnum { 0 }
201 //- /core/lib.rs crate:core
203 pub enum Result<T, E> { Ok(T), Err(E) }
206 pub enum Option<T> { Some(T), None }