Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-assists/src/handlers/replace_method_eager_lazy.rs115
-rw-r--r--crates/test-utils/src/minicore.rs4
2 files changed, 112 insertions, 7 deletions
diff --git a/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
index 753f2ab5de..c85ec734c0 100644
--- a/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
+++ b/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
@@ -35,10 +35,7 @@ pub(crate) fn replace_with_lazy_method(acc: &mut Assists, ctx: &AssistContext<'_
let (_, receiver_ty) = callable.receiver_param(ctx.sema.db)?;
let n_params = callable.n_params() + 1;
- let method_name_lazy = format!(
- "{method_name}{}",
- if method_name.text().ends_with("or") { "_else" } else { "_with" }
- );
+ let method_name_lazy = lazy_method_name(&method_name.text());
receiver_ty.iterate_method_candidates_with_traits(
ctx.sema.db,
@@ -70,6 +67,18 @@ pub(crate) fn replace_with_lazy_method(acc: &mut Assists, ctx: &AssistContext<'_
)
}
+fn lazy_method_name(name: &str) -> String {
+ if ends_is(name, "or") {
+ format!("{name}_else")
+ } else if ends_is(name, "and") {
+ format!("{name}_then")
+ } else if ends_is(name, "then_some") {
+ name.strip_suffix("_some").unwrap().to_owned()
+ } else {
+ format!("{name}_with")
+ }
+}
+
fn into_closure(param: &Expr) -> Expr {
(|| {
if let ast::Expr::CallExpr(call) = param {
@@ -117,9 +126,7 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<'
}
let method_name_text = method_name.text();
- let method_name_eager = method_name_text
- .strip_suffix("_else")
- .or_else(|| method_name_text.strip_suffix("_with"))?;
+ let method_name_eager = eager_method_name(&method_name_text)?;
receiver_ty.iterate_method_candidates_with_traits(
ctx.sema.db,
@@ -156,6 +163,20 @@ fn into_call(param: &Expr) -> Expr {
.unwrap_or_else(|| make::expr_call(param.clone(), make::arg_list(Vec::new())).into())
}
+fn eager_method_name(name: &str) -> Option<&str> {
+ if name == "then" {
+ return Some("then_some");
+ }
+
+ name.strip_suffix("_else")
+ .or_else(|| name.strip_suffix("_then"))
+ .or_else(|| name.strip_suffix("_with"))
+}
+
+fn ends_is(name: &str, end: &str) -> bool {
+ name.strip_suffix(end).is_some_and(|s| s.is_empty() || s.ends_with('_'))
+}
+
#[cfg(test)]
mod tests {
use crate::tests::check_assist;
@@ -297,4 +318,84 @@ fn foo() {
"#,
)
}
+
+ #[test]
+ fn replace_and_with_and_then() {
+ check_assist(
+ replace_with_lazy_method,
+ r#"
+//- minicore: option, fn
+fn foo() {
+ let foo = Some("foo");
+ return foo.and$0(Some("bar"));
+}
+"#,
+ r#"
+fn foo() {
+ let foo = Some("foo");
+ return foo.and_then(|| Some("bar"));
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn replace_and_then_with_and() {
+ check_assist(
+ replace_with_eager_method,
+ r#"
+//- minicore: option, fn
+fn foo() {
+ let foo = Some("foo");
+ return foo.and_then$0(|| Some("bar"));
+}
+"#,
+ r#"
+fn foo() {
+ let foo = Some("foo");
+ return foo.and(Some("bar"));
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn replace_then_some_with_then() {
+ check_assist(
+ replace_with_lazy_method,
+ r#"
+//- minicore: option, fn, bool_impl
+fn foo() {
+ let foo = true;
+ let x = foo.then_some$0(2);
+}
+"#,
+ r#"
+fn foo() {
+ let foo = true;
+ let x = foo.then(|| 2);
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn replace_then_with_then_some() {
+ check_assist(
+ replace_with_eager_method,
+ r#"
+//- minicore: option, fn, bool_impl
+fn foo() {
+ let foo = true;
+ let x = foo.then$0(|| 2);
+}
+"#,
+ r#"
+fn foo() {
+ let foo = true;
+ let x = foo.then_some(2);
+}
+"#,
+ )
+ }
}
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 679fe420b0..0fe17e3075 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -1988,6 +1988,10 @@ pub mod num {
// region:bool_impl
#[lang = "bool"]
impl bool {
+ pub fn then_some<T>(self, t: T) -> Option<T> {
+ if self { Some(t) } else { None }
+ }
+
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self { Some(f()) } else { None }
}