mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
strip useless methods, and unary ops in suggest_name
This commit is contained in:
parent
afc68277f6
commit
7066e6b362
@ -29,6 +29,29 @@ const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"];
|
|||||||
/// `args.into_config()` -> `config`
|
/// `args.into_config()` -> `config`
|
||||||
/// `bytes.to_vec()` -> `vec`
|
/// `bytes.to_vec()` -> `vec`
|
||||||
const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"];
|
const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"];
|
||||||
|
/// Useless methods that are stripped from expression
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// `var.name().to_string()` -> `var.name()`
|
||||||
|
const USELESS_METHODS: &[&str] = &[
|
||||||
|
"to_string",
|
||||||
|
"as_str",
|
||||||
|
"to_owned",
|
||||||
|
"as_ref",
|
||||||
|
"clone",
|
||||||
|
"cloned",
|
||||||
|
"expect",
|
||||||
|
"expect_none",
|
||||||
|
"unwrap",
|
||||||
|
"unwrap_none",
|
||||||
|
"unwrap_or",
|
||||||
|
"unwrap_or_default",
|
||||||
|
"unwrap_or_else",
|
||||||
|
"unwrap_unchecked",
|
||||||
|
"iter",
|
||||||
|
"into_iter",
|
||||||
|
"iter_mut",
|
||||||
|
];
|
||||||
|
|
||||||
/// Suggest name of variable for given expression
|
/// Suggest name of variable for given expression
|
||||||
///
|
///
|
||||||
@ -49,10 +72,39 @@ const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"];
|
|||||||
///
|
///
|
||||||
/// Currently it sticks to the first name found.
|
/// Currently it sticks to the first name found.
|
||||||
pub(crate) fn variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String {
|
pub(crate) fn variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String {
|
||||||
from_param(expr, sema)
|
// `from_param` does not benifit from stripping
|
||||||
.or_else(|| from_call(expr))
|
// it need the largest context possible
|
||||||
.or_else(|| from_type(expr, sema))
|
// so we check firstmost
|
||||||
.unwrap_or_else(|| "var_name".to_string())
|
if let Some(name) = from_param(expr, sema) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut next_expr = Some(expr.clone());
|
||||||
|
while let Some(expr) = next_expr {
|
||||||
|
let name = from_call(&expr).or_else(|| from_type(&expr, sema));
|
||||||
|
if let Some(name) = name {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
match expr {
|
||||||
|
ast::Expr::RefExpr(inner) => next_expr = inner.expr(),
|
||||||
|
ast::Expr::BoxExpr(inner) => next_expr = inner.expr(),
|
||||||
|
ast::Expr::AwaitExpr(inner) => next_expr = inner.expr(),
|
||||||
|
// ast::Expr::BlockExpr(block) => expr = block.tail_expr(),
|
||||||
|
ast::Expr::CastExpr(inner) => next_expr = inner.expr(),
|
||||||
|
ast::Expr::MethodCallExpr(method) if is_useless_method(&method) => {
|
||||||
|
next_expr = method.receiver();
|
||||||
|
}
|
||||||
|
ast::Expr::ParenExpr(inner) => next_expr = inner.expr(),
|
||||||
|
ast::Expr::TryExpr(inner) => next_expr = inner.expr(),
|
||||||
|
ast::Expr::PrefixExpr(prefix) if prefix.op_kind() == Some(ast::PrefixOp::Deref) => {
|
||||||
|
next_expr = prefix.expr()
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"var_name".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normalize(name: &str) -> Option<String> {
|
fn normalize(name: &str) -> Option<String> {
|
||||||
@ -76,6 +128,16 @@ fn is_valid_name(name: &str) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_useless_method(method: &ast::MethodCallExpr) -> bool {
|
||||||
|
let ident = method.name_ref().and_then(|it| it.ident_token());
|
||||||
|
|
||||||
|
if let Some(ident) = ident {
|
||||||
|
USELESS_METHODS.contains(&ident.text())
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn from_call(expr: &ast::Expr) -> Option<String> {
|
fn from_call(expr: &ast::Expr) -> Option<String> {
|
||||||
from_func_call(expr).or_else(|| from_method_call(expr))
|
from_func_call(expr).or_else(|| from_method_call(expr))
|
||||||
}
|
}
|
||||||
@ -99,15 +161,20 @@ fn from_method_call(expr: &ast::Expr) -> Option<String> {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let ident = method.name_ref()?.ident_token()?;
|
let ident = method.name_ref()?.ident_token()?;
|
||||||
let name = normalize(ident.text())?;
|
let mut name = ident.text();
|
||||||
|
|
||||||
|
if USELESS_METHODS.contains(&name) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
for prefix in USELESS_METHOD_PREFIXES {
|
for prefix in USELESS_METHOD_PREFIXES {
|
||||||
if let Some(suffix) = name.strip_prefix(prefix) {
|
if let Some(suffix) = name.strip_prefix(prefix) {
|
||||||
return Some(suffix.to_string());
|
name = suffix;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(name)
|
normalize(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> {
|
fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> {
|
||||||
@ -767,4 +834,44 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod variable {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ref_call() {
|
||||||
|
check_name_suggestion(
|
||||||
|
|e, c| Some(variable(e, c)),
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
$0&bar(1, 3)$0
|
||||||
|
}"#,
|
||||||
|
"bar",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn name_to_string() {
|
||||||
|
check_name_suggestion(
|
||||||
|
|e, c| Some(variable(e, c)),
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
$0function.name().to_string()$0
|
||||||
|
}"#,
|
||||||
|
"name",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nested_useless_method() {
|
||||||
|
check_name_suggestion(
|
||||||
|
|e, c| Some(variable(e, c)),
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
$0function.name().as_ref().unwrap().to_string()$0
|
||||||
|
}"#,
|
||||||
|
"name",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user