Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/type_mismatch.rs | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 4b653709f0..2f79a603bb 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -110,7 +110,7 @@ fn add_missing_ok_or_some( ) -> Option<()> { let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); let expr = expr_ptr.value.to_node(&root); - let expr_range = expr.syntax().text_range(); + let expr_range = ctx.sema.original_range_opt(expr.syntax())?.range; let scope = ctx.sema.scope(expr.syntax())?; let expected_adt = d.expected.as_adt()?; @@ -144,13 +144,13 @@ fn add_missing_ok_or_some( // Empty block let indent = block_indent + 1; builder.insert( - block.syntax().text_range().start() + TextSize::from(1), + expr_range.start() + TextSize::from(1), format!("\n{indent}{variant_name}(())\n{block_indent}"), ); } else { let indent = IndentLevel::from(1); builder.insert( - block.syntax().text_range().end() - TextSize::from(1), + expr_range.end() - TextSize::from(1), format!("{indent}{variant_name}(())\n{block_indent}"), ); } @@ -167,8 +167,7 @@ fn add_missing_ok_or_some( // Fix for forms like `fn foo() -> Result<(), String> { return; }` if ret_expr.expr().is_none() { let mut builder = TextEdit::builder(); - builder - .insert(ret_expr.syntax().text_range().end(), format!(" {variant_name}(())")); + builder.insert(expr_range.end(), format!(" {variant_name}(())")); let source_change = SourceChange::from_text_edit( expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db), builder.finish(), @@ -181,8 +180,8 @@ fn add_missing_ok_or_some( } let mut builder = TextEdit::builder(); - builder.insert(expr.syntax().text_range().start(), format!("{variant_name}(")); - builder.insert(expr.syntax().text_range().end(), ")".to_owned()); + builder.insert(expr_range.start(), format!("{variant_name}(")); + builder.insert(expr_range.end(), ")".to_owned()); let source_change = SourceChange::from_text_edit( expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db), builder.finish(), @@ -201,6 +200,7 @@ fn remove_unnecessary_wrapper( let db = ctx.sema.db; let root = db.parse_or_expand(expr_ptr.file_id); let expr = expr_ptr.value.to_node(&root); + // FIXME: support inside MacroCall? let expr = ctx.sema.original_ast_node(expr)?; let Expr::CallExpr(call_expr) = expr else { @@ -287,6 +287,7 @@ fn remove_semicolon( return None; } let block = BlockExpr::cast(expr.syntax().clone())?; + // FIXME: support inside MacroCall? let expr_before_semi = block.statements().last().and_then(|s| ExprStmt::cast(s.syntax().clone()))?; let type_before_semi = ctx.sema.type_of_expr(&expr_before_semi.expr()?)?.original(); @@ -320,16 +321,13 @@ fn str_ref_to_owned( let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); let expr = expr_ptr.value.to_node(&root); - let expr_range = expr.syntax().text_range(); + let hir::FileRange { file_id, range } = ctx.sema.original_range_opt(expr.syntax())?; let to_owned = ".to_owned()".to_owned(); - let edit = TextEdit::insert(expr.syntax().text_range().end(), to_owned); - let source_change = SourceChange::from_text_edit( - expr_ptr.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db), - edit, - ); - acc.push(fix("str_ref_to_owned", "Add .to_owned() here", source_change, expr_range)); + let edit = TextEdit::insert(range.end(), to_owned); + let source_change = SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit); + acc.push(fix("str_ref_to_owned", "Add .to_owned() here", source_change, range)); Some(()) } @@ -577,6 +575,32 @@ fn div(x: i32, y: i32) -> Result<i32, ()> { } "#, ); + + check_fix( + r#" +//- minicore: option, result +macro_rules! identity { ($($t:tt)*) => ($($t)*) } +identity! { + fn div(x: i32, y: i32) -> Result<i32, ()> { + if y == 0 { + return Err(()); + } + x / y$0 + } +} +"#, + r#" +macro_rules! identity { ($($t:tt)*) => ($($t)*) } +identity! { + fn div(x: i32, y: i32) -> Result<i32, ()> { + if y == 0 { + return Err(()); + } + Ok(x / y) + } +} +"#, + ); } #[test] @@ -1049,6 +1073,29 @@ fn test() -> String { } "#, ); + + check_fix( + r#" +macro_rules! identity { ($($t:tt)*) => ($($t)*) } +struct String; + +identity! { + fn test() -> String { + "a"$0 + } +} + "#, + r#" +macro_rules! identity { ($($t:tt)*) => ($($t)*) } +struct String; + +identity! { + fn test() -> String { + "a".to_owned() + } +} + "#, + ); } #[test] |