mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
fix: Check whether a parameter can be converted to a local
This commit is contained in:
parent
399559e597
commit
15e7112da3
3 changed files with 41 additions and 24 deletions
|
@ -1506,10 +1506,15 @@ impl Param {
|
||||||
db.function_data(self.func.id).params[self.idx].0.clone()
|
db.function_data(self.func.id).params[self.idx].0.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_local(&self, db: &dyn HirDatabase) -> Local {
|
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
|
||||||
let parent = DefWithBodyId::FunctionId(self.func.into());
|
let parent = DefWithBodyId::FunctionId(self.func.into());
|
||||||
let body = db.body(parent);
|
let body = db.body(parent);
|
||||||
Local { parent, pat_id: body.params[self.idx] }
|
let pat_id = body.params[self.idx];
|
||||||
|
if let Pat::Bind { .. } = &body[pat_id] {
|
||||||
|
Some(Local { parent, pat_id: body.params[self.idx] })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
|
pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
|
||||||
|
|
|
@ -219,8 +219,13 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe
|
||||||
let first_param = params
|
let first_param = params
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| format_err!("Cannot rename local to self unless it is a parameter"))?;
|
.ok_or_else(|| format_err!("Cannot rename local to self unless it is a parameter"))?;
|
||||||
if first_param.as_local(sema.db) != local {
|
match first_param.as_local(sema.db) {
|
||||||
bail!("Only the first parameter may be renamed to self");
|
Some(plocal) => {
|
||||||
|
if plocal != local {
|
||||||
|
bail!("Only the first parameter may be renamed to self");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => bail!("rename_to_self invoked on destructuring parameter"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let assoc_item = fn_def
|
let assoc_item = fn_def
|
||||||
|
|
|
@ -317,30 +317,37 @@ fn inline(
|
||||||
if !matches!(pat, ast::Pat::IdentPat(pat) if pat.is_simple_ident()) {
|
if !matches!(pat, ast::Pat::IdentPat(pat) if pat.is_simple_ident()) {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
usages_for_locals(param.as_local(sema.db))
|
// FIXME: we need to fetch all locals declared in the parameter here
|
||||||
.map(|FileReference { name, range, .. }| match name {
|
// not only the local if it is a simple binding
|
||||||
ast::NameLike::NameRef(_) => body
|
match param.as_local(sema.db) {
|
||||||
.syntax()
|
Some(l) => usages_for_locals(l)
|
||||||
.covering_element(range)
|
.map(|FileReference { name, range, .. }| match name {
|
||||||
.ancestors()
|
ast::NameLike::NameRef(_) => body
|
||||||
.nth(3)
|
.syntax()
|
||||||
.and_then(ast::PathExpr::cast),
|
.covering_element(range)
|
||||||
_ => None,
|
.ancestors()
|
||||||
})
|
.nth(3)
|
||||||
.collect::<Option<Vec<_>>>()
|
.and_then(ast::PathExpr::cast),
|
||||||
.unwrap_or_default()
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect::<Option<Vec<_>>>()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
None => Vec::new(),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if function.self_param(sema.db).is_some() {
|
if function.self_param(sema.db).is_some() {
|
||||||
let this = || make::name_ref("this").syntax().clone_for_update();
|
let this = || make::name_ref("this").syntax().clone_for_update();
|
||||||
usages_for_locals(params[0].2.as_local(sema.db))
|
if let Some(self_local) = params[0].2.as_local(sema.db) {
|
||||||
.flat_map(|FileReference { name, range, .. }| match name {
|
usages_for_locals(self_local)
|
||||||
ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)),
|
.flat_map(|FileReference { name, range, .. }| match name {
|
||||||
_ => None,
|
ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)),
|
||||||
})
|
_ => None,
|
||||||
.for_each(|it| {
|
})
|
||||||
ted::replace(it, &this());
|
.for_each(|it| {
|
||||||
})
|
ted::replace(it, &this());
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Inline parameter expressions or generate `let` statements depending on whether inlining works or not.
|
// Inline parameter expressions or generate `let` statements depending on whether inlining works or not.
|
||||||
for ((pat, param_ty, _), usages, expr) in izip!(params, param_use_nodes, arguments).rev() {
|
for ((pat, param_ty, _), usages, expr) in izip!(params, param_use_nodes, arguments).rev() {
|
||||||
|
|
Loading…
Reference in a new issue