mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-12-23 08:48:08 +00:00
Merge 2499492754 into 10418b49d0
This commit is contained in:
commit
64981d059e
1 changed files with 44 additions and 20 deletions
|
|
@ -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 = 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));
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -123,6 +125,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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue