Skip to content

Commit 7066e6b

Browse files
cpud36matklad
authored andcommitted
strip useless methods, and unary ops in suggest_name
1 parent afc6827 commit 7066e6b

File tree

1 file changed

+114
-7
lines changed

1 file changed

+114
-7
lines changed

crates/ide_assists/src/utils/suggest_name.rs

Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,29 @@ const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"];
2929
/// `args.into_config()` -> `config`
3030
/// `bytes.to_vec()` -> `vec`
3131
const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"];
32+
/// Useless methods that are stripped from expression
33+
///
34+
/// # Examples
35+
/// `var.name().to_string()` -> `var.name()`
36+
const USELESS_METHODS: &[&str] = &[
37+
"to_string",
38+
"as_str",
39+
"to_owned",
40+
"as_ref",
41+
"clone",
42+
"cloned",
43+
"expect",
44+
"expect_none",
45+
"unwrap",
46+
"unwrap_none",
47+
"unwrap_or",
48+
"unwrap_or_default",
49+
"unwrap_or_else",
50+
"unwrap_unchecked",
51+
"iter",
52+
"into_iter",
53+
"iter_mut",
54+
];
3255

3356
/// Suggest name of variable for given expression
3457
///
@@ -49,10 +72,39 @@ const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"];
4972
///
5073
/// Currently it sticks to the first name found.
5174
pub(crate) fn variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String {
52-
from_param(expr, sema)
53-
.or_else(|| from_call(expr))
54-
.or_else(|| from_type(expr, sema))
55-
.unwrap_or_else(|| "var_name".to_string())
75+
// `from_param` does not benifit from stripping
76+
// it need the largest context possible
77+
// so we check firstmost
78+
if let Some(name) = from_param(expr, sema) {
79+
return name;
80+
}
81+
82+
let mut next_expr = Some(expr.clone());
83+
while let Some(expr) = next_expr {
84+
let name = from_call(&expr).or_else(|| from_type(&expr, sema));
85+
if let Some(name) = name {
86+
return name;
87+
}
88+
89+
match expr {
90+
ast::Expr::RefExpr(inner) => next_expr = inner.expr(),
91+
ast::Expr::BoxExpr(inner) => next_expr = inner.expr(),
92+
ast::Expr::AwaitExpr(inner) => next_expr = inner.expr(),
93+
// ast::Expr::BlockExpr(block) => expr = block.tail_expr(),
94+
ast::Expr::CastExpr(inner) => next_expr = inner.expr(),
95+
ast::Expr::MethodCallExpr(method) if is_useless_method(&method) => {
96+
next_expr = method.receiver();
97+
}
98+
ast::Expr::ParenExpr(inner) => next_expr = inner.expr(),
99+
ast::Expr::TryExpr(inner) => next_expr = inner.expr(),
100+
ast::Expr::PrefixExpr(prefix) if prefix.op_kind() == Some(ast::PrefixOp::Deref) => {
101+
next_expr = prefix.expr()
102+
}
103+
_ => break,
104+
}
105+
}
106+
107+
"var_name".to_string()
56108
}
57109

58110
fn normalize(name: &str) -> Option<String> {
@@ -76,6 +128,16 @@ fn is_valid_name(name: &str) -> bool {
76128
}
77129
}
78130

131+
fn is_useless_method(method: &ast::MethodCallExpr) -> bool {
132+
let ident = method.name_ref().and_then(|it| it.ident_token());
133+
134+
if let Some(ident) = ident {
135+
USELESS_METHODS.contains(&ident.text())
136+
} else {
137+
false
138+
}
139+
}
140+
79141
fn from_call(expr: &ast::Expr) -> Option<String> {
80142
from_func_call(expr).or_else(|| from_method_call(expr))
81143
}
@@ -99,15 +161,20 @@ fn from_method_call(expr: &ast::Expr) -> Option<String> {
99161
_ => return None,
100162
};
101163
let ident = method.name_ref()?.ident_token()?;
102-
let name = normalize(ident.text())?;
164+
let mut name = ident.text();
165+
166+
if USELESS_METHODS.contains(&name) {
167+
return None;
168+
}
103169

104170
for prefix in USELESS_METHOD_PREFIXES {
105171
if let Some(suffix) = name.strip_prefix(prefix) {
106-
return Some(suffix.to_string());
172+
name = suffix;
173+
break;
107174
}
108175
}
109176

110-
Some(name)
177+
normalize(&name)
111178
}
112179

113180
fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> {
@@ -767,4 +834,44 @@ mod tests {
767834
);
768835
}
769836
}
837+
838+
mod variable {
839+
use super::*;
840+
841+
#[test]
842+
fn ref_call() {
843+
check_name_suggestion(
844+
|e, c| Some(variable(e, c)),
845+
r#"
846+
fn foo() {
847+
$0&bar(1, 3)$0
848+
}"#,
849+
"bar",
850+
);
851+
}
852+
853+
#[test]
854+
fn name_to_string() {
855+
check_name_suggestion(
856+
|e, c| Some(variable(e, c)),
857+
r#"
858+
fn foo() {
859+
$0function.name().to_string()$0
860+
}"#,
861+
"name",
862+
);
863+
}
864+
865+
#[test]
866+
fn nested_useless_method() {
867+
check_name_suggestion(
868+
|e, c| Some(variable(e, c)),
869+
r#"
870+
fn foo() {
871+
$0function.name().as_ref().unwrap().to_string()$0
872+
}"#,
873+
"name",
874+
);
875+
}
876+
}
770877
}

0 commit comments

Comments
 (0)