rust/crates/ide_assists/src/handlers/inline_local_variable.rs

956 lines
18 KiB
Rust
Raw Normal View History

use either::Either;
use hir::{PathResolution, Semantics};
2021-08-02 08:27:10 -05:00
use ide_db::{
base_db::FileId,
2021-08-02 08:27:10 -05:00
defs::Definition,
search::{FileReference, UsageSearchResult},
RootDatabase,
2021-08-02 08:27:10 -05:00
};
2020-08-12 11:26:51 -05:00
use syntax::{
2021-09-27 05:54:24 -05:00
ast::{self, AstNode, AstToken, HasName},
2021-08-02 08:27:10 -05:00
SyntaxElement, TextRange,
};
2019-03-24 12:05:11 -05:00
use crate::{
assist_context::{AssistContext, Assists},
2020-06-28 17:36:05 -05:00
AssistId, AssistKind,
};
2019-03-24 12:05:11 -05:00
2019-10-26 11:08:13 -05:00
// Assist: inline_local_variable
//
2021-08-02 08:27:10 -05:00
// Inlines a local variable.
2019-10-26 11:08:13 -05:00
//
// ```
// fn main() {
2021-01-06 14:15:48 -06:00
// let x$0 = 1 + 2;
2019-10-26 11:08:13 -05:00
// x * 4;
// }
// ```
// ->
// ```
// fn main() {
// (1 + 2) * 4;
// }
// ```
pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
2021-10-13 07:39:37 -05:00
let file_id = ctx.file_id();
let range = ctx.selection_trimmed();
2021-08-02 08:27:10 -05:00
let InlineData { let_stmt, delete_let, references, target } =
if let Some(path_expr) = ctx.find_node_at_offset::<ast::PathExpr>() {
inline_usage(&ctx.sema, path_expr, range, file_id)
} else if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() {
inline_let(&ctx.sema, let_stmt, range, file_id)
} else {
None
}?;
2019-07-19 03:24:41 -05:00
let initializer_expr = let_stmt.initializer()?;
2020-03-04 07:25:22 -06:00
2021-08-02 08:27:10 -05:00
let delete_range = delete_let.then(|| {
if let Some(whitespace) = let_stmt
.syntax()
.next_sibling_or_token()
2021-08-02 08:27:10 -05:00
.and_then(SyntaxElement::into_token)
.and_then(ast::Whitespace::cast)
{
2021-08-02 08:27:10 -05:00
TextRange::new(
let_stmt.syntax().text_range().start(),
whitespace.syntax().text_range().end(),
2021-08-02 08:27:10 -05:00
)
} else {
2021-08-02 08:27:10 -05:00
let_stmt.syntax().text_range()
}
2021-08-02 08:27:10 -05:00
});
2019-03-24 12:05:11 -05:00
2021-08-02 08:27:10 -05:00
let wrap_in_parens = references
.into_iter()
.filter_map(|FileReference { range, name, .. }| match name {
ast::NameLike::NameRef(name) => Some((range, name)),
_ => None,
})
.map(|(range, name_ref)| {
if range != name_ref.syntax().text_range() {
// Do not rename inside macros
// FIXME: This feels like a bad heuristic for macros
return None;
}
let usage_node =
name_ref.syntax().ancestors().find(|it| ast::PathExpr::can_cast(it.kind()));
let usage_parent_option =
usage_node.and_then(|it| it.parent()).and_then(ast::Expr::cast);
let usage_parent = match usage_parent_option {
Some(u) => u,
None => return Some((range, name_ref, false)),
};
let initializer = matches!(
initializer_expr,
ast::Expr::CallExpr(_)
| ast::Expr::IndexExpr(_)
| ast::Expr::MethodCallExpr(_)
| ast::Expr::FieldExpr(_)
| ast::Expr::TryExpr(_)
| ast::Expr::RefExpr(_)
| ast::Expr::Literal(_)
| ast::Expr::TupleExpr(_)
| ast::Expr::ArrayExpr(_)
| ast::Expr::ParenExpr(_)
| ast::Expr::PathExpr(_)
| ast::Expr::BlockExpr(_),
2021-08-02 08:27:10 -05:00
);
let parent = matches!(
usage_parent,
ast::Expr::CallExpr(_)
| ast::Expr::TupleExpr(_)
| ast::Expr::ArrayExpr(_)
| ast::Expr::ParenExpr(_)
| ast::Expr::ForExpr(_)
| ast::Expr::WhileExpr(_)
| ast::Expr::BreakExpr(_)
| ast::Expr::ReturnExpr(_)
| ast::Expr::MatchExpr(_)
| ast::Expr::BlockExpr(_)
2021-08-02 08:27:10 -05:00
);
Some((range, name_ref, !(initializer || parent)))
2021-01-11 17:05:07 -06:00
})
2021-08-02 08:27:10 -05:00
.collect::<Option<Vec<_>>>()?;
2019-07-19 03:24:41 -05:00
let init_str = initializer_expr.syntax().text().to_string();
let init_in_paren = format!("({})", &init_str);
let target = match target {
ast::NameOrNameRef::Name(it) => it.syntax().text_range(),
ast::NameOrNameRef::NameRef(it) => it.syntax().text_range(),
};
2020-06-28 17:36:05 -05:00
acc.add(
2020-07-02 16:48:35 -05:00
AssistId("inline_local_variable", AssistKind::RefactorInline),
2020-06-28 17:36:05 -05:00
"Inline variable",
target,
move |builder| {
if let Some(range) = delete_range {
builder.delete(range);
}
2021-08-02 08:27:10 -05:00
for (range, name, should_wrap) in wrap_in_parens {
let replacement = if should_wrap { &init_in_paren } else { &init_str };
if ast::RecordExprField::for_field_name(&name).is_some() {
cov_mark::hit!(inline_field_shorthand);
builder.insert(range.end(), format!(": {}", replacement));
} else {
builder.replace(range, replacement.clone())
}
2020-06-28 17:36:05 -05:00
}
},
)
2019-03-24 12:05:11 -05:00
}
struct InlineData {
let_stmt: ast::LetStmt,
delete_let: bool,
target: ast::NameOrNameRef,
2021-08-02 08:27:10 -05:00
references: Vec<FileReference>,
}
fn inline_let(
sema: &Semantics<RootDatabase>,
let_stmt: ast::LetStmt,
range: TextRange,
file_id: FileId,
) -> Option<InlineData> {
let bind_pat = match let_stmt.pat()? {
ast::Pat::IdentPat(pat) => pat,
_ => return None,
};
if bind_pat.mut_token().is_some() {
cov_mark::hit!(test_not_inline_mut_variable);
return None;
}
if !bind_pat.syntax().text_range().contains_range(range) {
cov_mark::hit!(not_applicable_outside_of_bind_pat);
return None;
}
let local = sema.to_def(&bind_pat)?;
let UsageSearchResult { mut references } = Definition::Local(local).usages(sema).all();
match references.remove(&file_id) {
2021-08-02 08:27:10 -05:00
Some(references) => Some(InlineData {
let_stmt,
delete_let: true,
target: ast::NameOrNameRef::Name(bind_pat.name()?),
references,
}),
None => {
cov_mark::hit!(test_not_applicable_if_variable_unused);
None
}
}
}
fn inline_usage(
sema: &Semantics<RootDatabase>,
path_expr: ast::PathExpr,
range: TextRange,
file_id: FileId,
) -> Option<InlineData> {
let path = path_expr.path()?;
2021-08-02 08:27:10 -05:00
let name = path.as_single_name_ref()?;
if !name.syntax().text_range().contains_range(range) {
cov_mark::hit!(test_not_inline_selection_too_broad);
return None;
}
let local = match sema.resolve_path(&path)? {
PathResolution::Local(local) => local,
_ => return None,
};
if local.is_mut(sema.db) {
cov_mark::hit!(test_not_inline_mut_variable_use);
return None;
}
// FIXME: Handle multiple local definitions
let bind_pat = match local.source(sema.db).value {
Either::Left(ident) => ident,
_ => return None,
};
let let_stmt = ast::LetStmt::cast(bind_pat.syntax().parent()?)?;
let UsageSearchResult { mut references } = Definition::Local(local).usages(sema).all();
let mut references = references.remove(&file_id)?;
2021-08-02 08:27:10 -05:00
let delete_let = references.len() == 1;
references.retain(|fref| fref.name.as_name_ref() == Some(&name));
2021-08-02 08:27:10 -05:00
Some(InlineData { let_stmt, delete_let, target: ast::NameOrNameRef::NameRef(name), references })
}
2019-03-24 12:05:11 -05:00
#[cfg(test)]
mod tests {
2020-05-06 03:16:55 -05:00
use crate::tests::{check_assist, check_assist_not_applicable};
2019-03-24 12:05:11 -05:00
use super::*;
#[test]
fn test_inline_let_bind_literal_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize) {}
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = 1;
2019-03-24 12:05:11 -05:00
a + 1;
if a > 10 {
}
while a > 10 {
}
let b = a * 10;
bar(a);
}",
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize) {}
fn foo() {
2020-05-20 16:07:17 -05:00
1 + 1;
2019-03-24 12:05:11 -05:00
if 1 > 10 {
}
while 1 > 10 {
}
let b = 1 * 10;
bar(1);
}",
);
}
#[test]
fn test_inline_let_bind_bin_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize) {}
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = 1 + 1;
2019-03-24 12:05:11 -05:00
a + 1;
if a > 10 {
}
while a > 10 {
}
let b = a * 10;
bar(a);
}",
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize) {}
fn foo() {
2020-05-20 16:07:17 -05:00
(1 + 1) + 1;
2019-03-24 12:05:11 -05:00
if (1 + 1) > 10 {
}
while (1 + 1) > 10 {
}
let b = (1 + 1) * 10;
bar(1 + 1);
2019-03-24 12:05:11 -05:00
}",
);
}
#[test]
fn test_inline_let_bind_function_call_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize) {}
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = bar(1);
2019-03-24 12:05:11 -05:00
a + 1;
if a > 10 {
}
while a > 10 {
}
let b = a * 10;
bar(a);
}",
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize) {}
fn foo() {
2020-05-20 16:07:17 -05:00
bar(1) + 1;
2019-03-24 12:05:11 -05:00
if bar(1) > 10 {
}
while bar(1) > 10 {
}
let b = bar(1) * 10;
bar(bar(1));
}",
);
}
#[test]
fn test_inline_let_bind_cast_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize): usize { a }
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = bar(1) as u64;
2019-03-24 12:05:11 -05:00
a + 1;
if a > 10 {
}
while a > 10 {
}
let b = a * 10;
bar(a);
}",
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn bar(a: usize): usize { a }
fn foo() {
2020-05-20 16:07:17 -05:00
(bar(1) as u64) + 1;
2019-03-24 12:05:11 -05:00
if (bar(1) as u64) > 10 {
}
while (bar(1) as u64) > 10 {
}
let b = (bar(1) as u64) * 10;
bar(bar(1) as u64);
2019-03-24 12:05:11 -05:00
}",
);
}
#[test]
fn test_inline_let_bind_block_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = { 10 + 1 };
2019-03-24 12:05:11 -05:00
a + 1;
if a > 10 {
}
while a > 10 {
}
let b = a * 10;
bar(a);
}",
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn foo() {
2020-05-20 16:07:17 -05:00
{ 10 + 1 } + 1;
2019-03-24 12:05:11 -05:00
if { 10 + 1 } > 10 {
}
while { 10 + 1 } > 10 {
}
let b = { 10 + 1 } * 10;
bar({ 10 + 1 });
}",
);
}
#[test]
fn test_inline_let_bind_paren_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = ( 10 + 1 );
2019-03-24 12:05:11 -05:00
a + 1;
if a > 10 {
}
while a > 10 {
}
let b = a * 10;
bar(a);
}",
2020-03-03 10:03:46 -06:00
r"
2019-03-24 12:05:11 -05:00
fn foo() {
2020-05-20 16:07:17 -05:00
( 10 + 1 ) + 1;
2019-03-24 12:05:11 -05:00
if ( 10 + 1 ) > 10 {
}
while ( 10 + 1 ) > 10 {
}
let b = ( 10 + 1 ) * 10;
bar(( 10 + 1 ));
}",
);
}
#[test]
fn test_not_inline_mut_variable() {
2021-03-08 14:19:44 -06:00
cov_mark::check!(test_not_inline_mut_variable);
2019-03-24 12:05:11 -05:00
check_assist_not_applicable(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 09:56:42 -06:00
r"
2019-03-24 12:05:11 -05:00
fn foo() {
2021-01-06 14:15:48 -06:00
let mut a$0 = 1 + 1;
2019-03-24 12:05:11 -05:00
a + 1;
}",
);
}
#[test]
fn test_not_inline_mut_variable_use() {
cov_mark::check!(test_not_inline_mut_variable_use);
check_assist_not_applicable(
inline_local_variable,
r"
fn foo() {
let mut a = 1 + 1;
a$0 + 1;
}",
);
}
#[test]
fn test_call_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = bar(10 + 1);
let b = a * 10;
let c = a as usize;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
let b = bar(10 + 1) * 10;
let c = bar(10 + 1) as usize;
}",
);
}
#[test]
fn test_index_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let x = vec![1, 2, 3];
2021-01-06 14:15:48 -06:00
let a$0 = x[0];
let b = a * 10;
let c = a as usize;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let x = vec![1, 2, 3];
2020-05-20 16:07:17 -05:00
let b = x[0] * 10;
let c = x[0] as usize;
}",
);
}
#[test]
fn test_method_call_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let bar = vec![1];
2021-01-06 14:15:48 -06:00
let a$0 = bar.len();
let b = a * 10;
let c = a as usize;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let bar = vec![1];
2020-05-20 16:07:17 -05:00
let b = bar.len() * 10;
let c = bar.len() as usize;
}",
);
}
#[test]
fn test_field_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
struct Bar {
foo: usize
}
fn foo() {
let bar = Bar { foo: 1 };
2021-01-06 14:15:48 -06:00
let a$0 = bar.foo;
let b = a * 10;
let c = a as usize;
}",
2020-03-03 10:03:46 -06:00
r"
struct Bar {
foo: usize
}
fn foo() {
let bar = Bar { foo: 1 };
2020-05-20 16:07:17 -05:00
let b = bar.foo * 10;
let c = bar.foo as usize;
}",
);
}
#[test]
fn test_try_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() -> Option<usize> {
let bar = Some(1);
2021-01-06 14:15:48 -06:00
let a$0 = bar?;
let b = a * 10;
let c = a as usize;
None
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() -> Option<usize> {
let bar = Some(1);
2020-05-20 16:07:17 -05:00
let b = bar? * 10;
let c = bar? as usize;
None
}",
);
}
#[test]
fn test_ref_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let bar = 10;
2021-01-06 14:15:48 -06:00
let a$0 = &bar;
let b = a * 10;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let bar = 10;
2020-05-20 16:07:17 -05:00
let b = &bar * 10;
}",
);
}
#[test]
fn test_tuple_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = (10, 20);
let b = a[0];
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
let b = (10, 20)[0];
}",
);
}
#[test]
fn test_array_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = [1, 2, 3];
let b = a.len();
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
let b = [1, 2, 3].len();
}",
);
}
#[test]
fn test_paren() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = (10 + 20);
let b = a * 10;
let c = a as usize;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
let b = (10 + 20) * 10;
let c = (10 + 20) as usize;
}",
);
}
#[test]
fn test_path_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let d = 10;
2021-01-06 14:15:48 -06:00
let a$0 = d;
let b = a * 10;
let c = a as usize;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
let d = 10;
2020-05-20 16:07:17 -05:00
let b = d * 10;
let c = d as usize;
}",
);
}
#[test]
fn test_block_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = { 10 };
let b = a * 10;
let c = a as usize;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
let b = { 10 } * 10;
let c = { 10 } as usize;
}",
);
}
#[test]
fn test_used_in_different_expr1() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = 10 + 20;
let b = a * 10;
let c = (a, 20);
let d = [a, 10];
let e = (a);
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
let b = (10 + 20) * 10;
let c = (10 + 20, 20);
let d = [10 + 20, 10];
let e = (10 + 20);
}",
);
}
#[test]
fn test_used_in_for_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = vec![10, 20];
for i in a {}
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
for i in vec![10, 20] {}
}",
);
}
#[test]
fn test_used_in_while_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = 1 > 0;
while a {}
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
while 1 > 0 {}
}",
);
}
#[test]
fn test_used_in_break_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = 1 + 1;
loop {
break a;
}
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
loop {
break 1 + 1;
}
}",
);
}
#[test]
fn test_used_in_return_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = 1 > 0;
return a;
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
return 1 > 0;
}",
);
}
#[test]
fn test_used_in_match_expr() {
check_assist(
2020-01-19 10:39:53 -06:00
inline_local_variable,
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2021-01-06 14:15:48 -06:00
let a$0 = 1 > 0;
match a {}
}",
2020-03-03 10:03:46 -06:00
r"
fn foo() {
2020-05-20 16:07:17 -05:00
match 1 > 0 {}
2019-03-24 12:05:11 -05:00
}",
);
}
2020-01-25 14:07:21 -06:00
#[test]
fn inline_field_shorthand() {
2021-03-08 14:19:44 -06:00
cov_mark::check!(inline_field_shorthand);
check_assist(
inline_local_variable,
r"
struct S { foo: i32}
fn main() {
2021-01-06 14:15:48 -06:00
let $0foo = 92;
S { foo }
}
",
r"
struct S { foo: i32}
fn main() {
S { foo: 92 }
}
",
);
}
2020-01-25 14:07:21 -06:00
#[test]
fn test_not_applicable_if_variable_unused() {
2021-03-08 14:19:44 -06:00
cov_mark::check!(test_not_applicable_if_variable_unused);
2020-01-25 14:07:21 -06:00
check_assist_not_applicable(
inline_local_variable,
2020-03-03 09:56:42 -06:00
r"
2020-01-25 14:07:21 -06:00
fn foo() {
2021-01-06 14:15:48 -06:00
let $0a = 0;
2020-01-25 14:07:21 -06:00
}
",
)
}
2020-03-03 09:56:42 -06:00
#[test]
fn not_applicable_outside_of_bind_pat() {
2021-03-08 14:19:44 -06:00
cov_mark::check!(not_applicable_outside_of_bind_pat);
2020-03-03 09:56:42 -06:00
check_assist_not_applicable(
inline_local_variable,
r"
fn main() {
2021-01-06 14:15:48 -06:00
let x = $01 + 2;
2020-03-03 09:56:42 -06:00
x * 4;
}
",
)
}
#[test]
fn works_on_local_usage() {
check_assist(
inline_local_variable,
r#"
fn f() {
let xyz = 0;
xyz$0;
}
"#,
r#"
fn f() {
0;
}
"#,
);
}
#[test]
fn does_not_remove_let_when_multiple_usages() {
check_assist(
inline_local_variable,
r#"
fn f() {
let xyz = 0;
xyz$0;
xyz;
}
"#,
r#"
fn f() {
let xyz = 0;
0;
xyz;
}
"#,
);
}
#[test]
fn not_applicable_with_non_ident_pattern() {
check_assist_not_applicable(
inline_local_variable,
r#"
fn main() {
let (x, y) = (0, 1);
x$0;
}
"#,
);
}
#[test]
fn not_applicable_on_local_usage_in_macro() {
check_assist_not_applicable(
inline_local_variable,
r#"
macro_rules! m {
($i:ident) => { $i }
}
fn f() {
let xyz = 0;
m!(xyz$0); // replacing it would break the macro
}
"#,
);
check_assist_not_applicable(
inline_local_variable,
r#"
macro_rules! m {
($i:ident) => { $i }
}
fn f() {
let xyz$0 = 0;
m!(xyz); // replacing it would break the macro
}
"#,
);
}
#[test]
fn test_not_inline_selection_too_broad() {
cov_mark::check!(test_not_inline_selection_too_broad);
check_assist_not_applicable(
inline_local_variable,
r#"
fn f() {
let foo = 0;
let bar = 0;
$0foo + bar$0;
}
"#,
);
}
#[test]
fn test_inline_ref_in_let() {
check_assist(
inline_local_variable,
r#"
fn f() {
let x = {
let y = 0;
y$0
};
}
"#,
r#"
fn f() {
let x = {
0
};
}
"#,
);
}
#[test]
fn test_inline_let_unit_struct() {
check_assist_not_applicable(
inline_local_variable,
r#"
struct S;
fn f() {
let S$0 = S;
S;
}
"#,
);
}
2019-03-24 12:05:11 -05:00
}