Introduce var works with tail exprs

This commit is contained in:
Aleksey Kladov 2018-11-05 15:44:34 +03:00
parent 8d7b888481
commit 420725f256

View file

@ -103,35 +103,52 @@ pub fn introduce_variable<'a>(
) -> Option<impl FnOnce() -> LocalEdit + 'a> { ) -> Option<impl FnOnce() -> LocalEdit + 'a> {
let node = find_covering_node(file.syntax(), range); let node = find_covering_node(file.syntax(), range);
let expr = node.ancestors().filter_map(ast::Expr::cast).next()?; let expr = node.ancestors().filter_map(ast::Expr::cast).next()?;
let anchor_stmt = expr
.syntax() let anchor_stmt = ahchor_stmt(expr)?;
.ancestors() let indent = anchor_stmt.prev_sibling()?;
.filter_map(ast::Stmt::cast)
.next()?;
let indent = anchor_stmt.syntax().prev_sibling()?;
if indent.kind() != WHITESPACE { if indent.kind() != WHITESPACE {
return None; return None;
} }
Some(move || { return Some(move || {
let mut buf = String::new(); let mut buf = String::new();
let mut edit = EditBuilder::new(); let mut edit = EditBuilder::new();
buf.push_str("let var_name = "); buf.push_str("let var_name = ");
expr.syntax().text().push_to(&mut buf); expr.syntax().text().push_to(&mut buf);
if expr.syntax().range().start() == anchor_stmt.syntax().range().start() { if expr.syntax().range().start() == anchor_stmt.range().start() {
edit.replace(expr.syntax().range(), buf); edit.replace(expr.syntax().range(), buf);
} else { } else {
buf.push_str(";"); buf.push_str(";");
indent.text().push_to(&mut buf); indent.text().push_to(&mut buf);
edit.replace(expr.syntax().range(), "var_name".to_string()); edit.replace(expr.syntax().range(), "var_name".to_string());
edit.insert(anchor_stmt.syntax().range().start(), buf); edit.insert(anchor_stmt.range().start(), buf);
} }
let cursor_position = anchor_stmt.syntax().range().start() + TextUnit::of_str("let "); let cursor_position = anchor_stmt.range().start() + TextUnit::of_str("let ");
LocalEdit { LocalEdit {
edit: edit.finish(), edit: edit.finish(),
cursor_position: Some(cursor_position), cursor_position: Some(cursor_position),
} }
}) });
/// Statement or last in the block expression, which will follow
/// the freshly introduced var.
fn ahchor_stmt(expr: ast::Expr) -> Option<SyntaxNodeRef> {
expr.syntax().ancestors().find(|&node| {
if ast::Stmt::cast(node).is_some() {
return true;
}
if let Some(expr) = node
.parent()
.and_then(ast::Block::cast)
.and_then(|it| it.expr())
{
if expr.syntax() == node {
return true;
}
}
false
})
}
} }
fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> { fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> {
@ -207,6 +224,7 @@ fn foo() {
|file, range| introduce_variable(file, range).map(|f| f()), |file, range| introduce_variable(file, range).map(|f| f()),
); );
} }
#[test] #[test]
fn test_intrdoduce_var_expr_stmt() { fn test_intrdoduce_var_expr_stmt() {
check_action_range( check_action_range(
@ -222,4 +240,20 @@ fn foo() {
); );
} }
#[test]
fn test_intrdoduce_var_last_expr() {
check_action_range(
"
fn foo() {
bar(<|>1 + 1<|>)
}",
"
fn foo() {
let <|>var_name = 1 + 1;
bar(var_name)
}",
|file, range| introduce_variable(file, range).map(|f| f()),
);
}
} }