diff --git a/crates/ide_assists/src/handlers/replace_turbofish_with_explicit_type.rs b/crates/ide_assists/src/handlers/replace_turbofish_with_explicit_type.rs index 399e39cb66a..46e03e20da0 100644 --- a/crates/ide_assists/src/handlers/replace_turbofish_with_explicit_type.rs +++ b/crates/ide_assists/src/handlers/replace_turbofish_with_explicit_type.rs @@ -1,5 +1,5 @@ use syntax::{ - ast::{Expr, GenericArg, GenericArgList}, + ast::{Expr, GenericArg}, ast::{LetStmt, Type::InferType}, AstNode, TextRange, }; @@ -34,15 +34,13 @@ pub(crate) fn replace_turbofish_with_explicit_type( let initializer = let_stmt.initializer()?; - let (turbofish_range, turbofish_type) = match &initializer { + let generic_args = match &initializer { Expr::MethodCallExpr(ce) => { - let generic_args = ce.generic_arg_list()?; - (turbofish_range(&generic_args)?, turbofish_type(&generic_args)?) + ce.generic_arg_list()? } Expr::CallExpr(ce) => { if let Expr::PathExpr(pe) = ce.expr()? { - let generic_args = pe.path()?.segment()?.generic_arg_list()?; - (turbofish_range(&generic_args)?, turbofish_type(&generic_args)?) + pe.path()?.segment()?.generic_arg_list()? } else { cov_mark::hit!(not_applicable_if_non_path_function_call); return None; @@ -54,6 +52,23 @@ pub(crate) fn replace_turbofish_with_explicit_type( } }; + // Find range of ::<_> + let colon2 = generic_args.coloncolon_token()?; + let r_angle = generic_args.r_angle_token()?; + let turbofish_range = TextRange::new(colon2.text_range().start(), r_angle.text_range().end()); + + let turbofish_args: Vec = generic_args.generic_args().into_iter().collect(); + + // Find type of ::<_> + if turbofish_args.len() != 1 { + cov_mark::hit!(not_applicable_if_not_single_arg); + return None; + } + + // An improvement would be to check that this is correctly part of the return value of the + // function call, or sub in the actual return type. + let turbofish_type = &turbofish_args[0]; + let initializer_start = initializer.syntax().text_range().start(); if ctx.offset() > turbofish_range.end() || ctx.offset() < initializer_start { cov_mark::hit!(not_applicable_outside_turbofish); @@ -67,7 +82,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( return acc.add( AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite), - format!("Replace turbofish with explicit type `: <{}>`", turbofish_type), + "Replace turbofish with explicit type", TextRange::new(initializer_start, turbofish_range.end()), |builder| { builder.insert(ident_range.end(), format!(": {}", turbofish_type)); @@ -82,10 +97,10 @@ pub(crate) fn replace_turbofish_with_explicit_type( return acc.add( AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite), - format!("Replace `_` with turbofish type `{}`", turbofish_type), + "Replace `_` with turbofish type", turbofish_range, |builder| { - builder.replace(underscore_range, turbofish_type); + builder.replace(underscore_range, turbofish_type.to_string()); builder.delete(turbofish_range); }, ); @@ -94,31 +109,6 @@ pub(crate) fn replace_turbofish_with_explicit_type( None } -/// Returns the type of the turbofish as a String. -/// Returns None if there are 0 or >1 arguments. -fn turbofish_type(generic_args: &GenericArgList) -> Option { - let turbofish_args: Vec = generic_args.generic_args().into_iter().collect(); - - if turbofish_args.len() != 1 { - cov_mark::hit!(not_applicable_if_not_single_arg); - return None; - } - - // An improvement would be to check that this is correctly part of the return value of the - // function call, or sub in the actual return type. - let turbofish_type = turbofish_args[0].to_string(); - - Some(turbofish_type) -} - -/// Returns the TextRange of the whole turbofish expression, and the generic argument as a String. -fn turbofish_range(generic_args: &GenericArgList) -> Option { - let colon2 = generic_args.coloncolon_token()?; - let r_angle = generic_args.r_angle_token()?; - - Some(TextRange::new(colon2.text_range().start(), r_angle.text_range().end())) -} - #[cfg(test)] mod tests { use super::*;