Unnamed repository; edit this file 'description' to name the repository.
Avoid allocations
Wang Ruochen 2022-05-06
parent a70beea · commit 81d7cbb
-rw-r--r--crates/ide-assists/src/handlers/convert_let_else_to_match.rs69
1 files changed, 37 insertions, 32 deletions
diff --git a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs
index cfd176fcf2..e7560b0c18 100644
--- a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs
+++ b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs
@@ -1,73 +1,77 @@
-use syntax::ast::{edit::AstNodeEdit, AstNode, HasName, LetStmt, Pat};
+use hir::Semantics;
+use ide_db::RootDatabase;
+use syntax::ast::{edit::AstNodeEdit, AstNode, HasName, LetStmt, Name, Pat};
use syntax::T;
use crate::{AssistContext, AssistId, AssistKind, Assists};
/// Gets a list of binders in a pattern, and whether they are mut.
-fn binders_in_pat(pat: &Pat) -> Option<Vec<(String, bool)>> {
+fn binders_in_pat(
+ acc: &mut Vec<(Name, bool)>,
+ pat: &Pat,
+ sem: &Semantics<RootDatabase>,
+) -> Option<()> {
use Pat::*;
match pat {
IdentPat(p) => {
- let ident = p.name()?.text().to_string();
+ let ident = p.name()?;
let ismut = p.ref_token().is_none() && p.mut_token().is_some();
- let mut res = vec![(ident, ismut)];
+ acc.push((ident, ismut));
if let Some(inner) = p.pat() {
- res.extend(binders_in_pat(&inner)?);
+ binders_in_pat(acc, &inner, sem)?;
}
- Some(res)
+ Some(())
}
- BoxPat(p) => p.pat().and_then(|p| binders_in_pat(&p)),
- RestPat(_) | LiteralPat(_) | PathPat(_) | WildcardPat(_) | ConstBlockPat(_) => Some(vec![]),
+ BoxPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
+ RestPat(_) | LiteralPat(_) | PathPat(_) | WildcardPat(_) | ConstBlockPat(_) => Some(()),
OrPat(p) => {
- let mut v = vec![];
for p in p.pats() {
- v.extend(binders_in_pat(&p)?);
+ binders_in_pat(acc, &p, sem)?;
}
- Some(v)
+ Some(())
}
- ParenPat(p) => p.pat().and_then(|p| binders_in_pat(&p)),
+ ParenPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
RangePat(p) => {
- let mut start = if let Some(st) = p.start() { binders_in_pat(&st)? } else { vec![] };
- let end = if let Some(st) = p.end() { binders_in_pat(&st)? } else { vec![] };
- start.extend(end);
- Some(start)
+ if let Some(st) = p.start() {
+ binders_in_pat(acc, &st, sem)?
+ }
+ if let Some(ed) = p.end() {
+ binders_in_pat(acc, &ed, sem)?
+ }
+ Some(())
}
RecordPat(p) => {
- let mut v = vec![];
for f in p.record_pat_field_list()?.fields() {
let pat = f.pat()?;
- v.extend(binders_in_pat(&pat)?);
+ binders_in_pat(acc, &pat, sem)?;
}
- Some(v)
+ Some(())
}
- RefPat(p) => p.pat().and_then(|p| binders_in_pat(&p)),
+ RefPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
SlicePat(p) => {
- let mut v = vec![];
for p in p.pats() {
- v.extend(binders_in_pat(&p)?);
+ binders_in_pat(acc, &p, sem)?;
}
- Some(v)
+ Some(())
}
TuplePat(p) => {
- let mut v = vec![];
for p in p.fields() {
- v.extend(binders_in_pat(&p)?);
+ binders_in_pat(acc, &p, sem)?;
}
- Some(v)
+ Some(())
}
TupleStructPat(p) => {
- let mut v = vec![];
for p in p.fields() {
- v.extend(binders_in_pat(&p)?);
+ binders_in_pat(acc, &p, sem)?;
}
- Some(v)
+ Some(())
}
// don't support macro pat yet
MacroPat(_) => None,
}
}
-fn binders_to_str(binders: &[(String, bool)], addmut: bool) -> String {
+fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String {
let vars = binders
.iter()
.map(
@@ -119,7 +123,8 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext)
return None;
}
let pat = let_stmt.pat()?;
- let binders = binders_in_pat(&pat)?;
+ let mut binders = Vec::new();
+ binders_in_pat(&mut binders, &pat, &ctx.sema)?;
let target = let_stmt.syntax().text_range();
acc.add(
@@ -139,7 +144,7 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext)
// remove the mut from the pattern
for (b, ismut) in binders.iter() {
if *ismut {
- pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), b);
+ pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string());
}
}