Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/unwrap_tuple.rs')
-rw-r--r--crates/ide-assists/src/handlers/unwrap_tuple.rs64
1 files changed, 44 insertions, 20 deletions
diff --git a/crates/ide-assists/src/handlers/unwrap_tuple.rs b/crates/ide-assists/src/handlers/unwrap_tuple.rs
index 46f3e85e12..e03274bbb3 100644
--- a/crates/ide-assists/src/handlers/unwrap_tuple.rs
+++ b/crates/ide-assists/src/handlers/unwrap_tuple.rs
@@ -1,3 +1,6 @@
+use std::iter;
+
+use either::Either;
use syntax::{
AstNode, T,
ast::{self, edit::AstNodeEdit},
@@ -24,11 +27,16 @@ use crate::{AssistContext, AssistId, Assists};
// ```
pub(crate) fn unwrap_tuple(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let let_kw = ctx.find_token_syntax_at_offset(T![let])?;
- let let_stmt = let_kw.parent().and_then(ast::LetStmt::cast)?;
- let indent_level = let_stmt.indent_level().0 as usize;
- let pat = let_stmt.pat()?;
- let ty = let_stmt.ty();
- let init = let_stmt.initializer()?;
+ let let_stmt = let_kw.parent().and_then(Either::<ast::LetStmt, ast::LetExpr>::cast)?;
+ let mut indent_level = let_stmt.indent_level();
+ let pat = either::for_both!(&let_stmt, it => it.pat())?;
+ let (ty, init, prefix, suffix) = match &let_stmt {
+ Either::Left(let_stmt) => (let_stmt.ty(), let_stmt.initializer()?, "", ";"),
+ Either::Right(let_expr) => {
+ indent_level += 1;
+ (None, let_expr.expr()?, "&& ", "")
+ }
+ };
// This only applies for tuple patterns, types, and initializers.
let tuple_pat = match pat {
@@ -60,25 +68,19 @@ pub(crate) fn unwrap_tuple(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
"Unwrap tuple",
let_kw.text_range(),
|edit| {
- let indents = " ".repeat(indent_level);
+ let mut decls = String::new();
// If there is an ascribed type, insert that type for each declaration,
// otherwise, omit that type.
- if let Some(tys) = tuple_ty {
- let mut zipped_decls = String::new();
- for (pat, ty, expr) in
- itertools::izip!(tuple_pat.fields(), tys.fields(), tuple_init.fields())
- {
- zipped_decls.push_str(&format!("{indents}let {pat}: {ty} = {expr};\n"))
- }
- edit.replace(parent.text_range(), zipped_decls.trim());
- } else {
- let mut zipped_decls = String::new();
- for (pat, expr) in itertools::izip!(tuple_pat.fields(), tuple_init.fields()) {
- zipped_decls.push_str(&format!("{indents}let {pat} = {expr};\n"));
- }
- edit.replace(parent.text_range(), zipped_decls.trim());
+ let tys =
+ tuple_ty.into_iter().flat_map(|it| it.fields().map(Some)).chain(iter::repeat(None));
+ for (pat, ty, expr) in itertools::izip!(tuple_pat.fields(), tys, tuple_init.fields()) {
+ let ty = ty.map_or_else(String::new, |ty| format!(": {ty}"));
+ decls.push_str(&format!("{prefix}let {pat}{ty} = {expr}{suffix}\n{indent_level}"))
}
+
+ let s = decls.trim();
+ edit.replace(parent.text_range(), s.strip_prefix(prefix).unwrap_or(s));
},
)
}
@@ -124,6 +126,28 @@ fn main() {
}
#[test]
+ fn unwrap_tuples_in_let_expr() {
+ check_assist(
+ unwrap_tuple,
+ r#"
+fn main() {
+ if $0let (foo, bar) = ("Foo", "Bar") {
+ code();
+ }
+}
+"#,
+ r#"
+fn main() {
+ if let foo = "Foo"
+ && let bar = "Bar" {
+ code();
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn unwrap_tuple_with_types() {
check_assist(
unwrap_tuple,