mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-02 12:59:12 +00:00
Migrate AstNodeEdit
This commit is contained in:
parent
58e507d807
commit
6f101d9cc7
8 changed files with 74 additions and 35 deletions
|
|
@ -228,8 +228,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
|
||||||
closure_body,
|
closure_body,
|
||||||
Some(ast::ElseBranch::Block(make.block_expr(None, Some(none_path)))),
|
Some(ast::ElseBranch::Block(make.block_expr(None, Some(none_path)))),
|
||||||
)
|
)
|
||||||
.indent(mcall.indent_level())
|
.indent(mcall.indent_level());
|
||||||
.clone_for_update();
|
|
||||||
editor.replace(mcall.syntax().clone(), if_expr.syntax().clone());
|
editor.replace(mcall.syntax().clone(), if_expr.syntax().clone());
|
||||||
|
|
||||||
editor.add_mappings(make.finish_with_mappings());
|
editor.add_mappings(make.finish_with_mappings());
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ fn if_expr_to_guarded_return(
|
||||||
|
|
||||||
then_block.syntax().last_child_or_token().filter(|t| t.kind() == T!['}'])?;
|
then_block.syntax().last_child_or_token().filter(|t| t.kind() == T!['}'])?;
|
||||||
|
|
||||||
let then_block_items = then_block.dedent(IndentLevel(1)).clone_for_update();
|
let then_block_items = then_block.dedent(IndentLevel(1));
|
||||||
|
|
||||||
let end_of_then = then_block_items.syntax().last_child_or_token()?;
|
let end_of_then = then_block_items.syntax().last_child_or_token()?;
|
||||||
let end_of_then = if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
|
let end_of_then = if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
|
||||||
|
|
@ -143,7 +143,7 @@ fn if_expr_to_guarded_return(
|
||||||
let cond = invert_boolean_expression_legacy(cond_expr);
|
let cond = invert_boolean_expression_legacy(cond_expr);
|
||||||
make::expr_if(cond, then_branch, None).indent(if_indent_level)
|
make::expr_if(cond, then_branch, None).indent(if_indent_level)
|
||||||
};
|
};
|
||||||
new_expr.syntax().clone_for_update()
|
new_expr.syntax().clone()
|
||||||
}
|
}
|
||||||
Some(pat) => {
|
Some(pat) => {
|
||||||
// If-let.
|
// If-let.
|
||||||
|
|
@ -154,7 +154,7 @@ fn if_expr_to_guarded_return(
|
||||||
ast::make::tail_only_block_expr(early_expression),
|
ast::make::tail_only_block_expr(early_expression),
|
||||||
);
|
);
|
||||||
let let_else_stmt = let_else_stmt.indent(if_indent_level);
|
let let_else_stmt = let_else_stmt.indent(if_indent_level);
|
||||||
let_else_stmt.syntax().clone_for_update()
|
let_else_stmt.syntax().clone()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -225,7 +225,7 @@ fn let_stmt_to_guarded_return(
|
||||||
ast::make::tail_only_block_expr(early_expression),
|
ast::make::tail_only_block_expr(early_expression),
|
||||||
);
|
);
|
||||||
let let_else_stmt = let_else_stmt.indent(let_indent_level);
|
let let_else_stmt = let_else_stmt.indent(let_indent_level);
|
||||||
let_else_stmt.syntax().clone_for_update()
|
let_else_stmt.syntax().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
ted::replace(let_stmt.syntax(), replacement)
|
ted::replace(let_stmt.syntax(), replacement)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ use syntax::{
|
||||||
NodeOrToken, SyntaxKind, SyntaxNode, T,
|
NodeOrToken, SyntaxKind, SyntaxNode, T,
|
||||||
algo::ancestors_at_offset,
|
algo::ancestors_at_offset,
|
||||||
ast::{
|
ast::{
|
||||||
self, AstNode, edit::IndentLevel, edit_in_place::Indent, make,
|
self, AstNode,
|
||||||
|
edit::{AstNodeEdit, IndentLevel},
|
||||||
|
make,
|
||||||
syntax_factory::SyntaxFactory,
|
syntax_factory::SyntaxFactory,
|
||||||
},
|
},
|
||||||
syntax_editor::Position,
|
syntax_editor::Position,
|
||||||
|
|
@ -253,12 +255,11 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
|
||||||
// `expr_replace` is a descendant of `to_wrap`, so we just replace it with `name_expr`.
|
// `expr_replace` is a descendant of `to_wrap`, so we just replace it with `name_expr`.
|
||||||
editor.replace(expr_replace, name_expr.syntax());
|
editor.replace(expr_replace, name_expr.syntax());
|
||||||
make.block_expr([new_stmt], Some(to_wrap.clone()))
|
make.block_expr([new_stmt], Some(to_wrap.clone()))
|
||||||
};
|
}
|
||||||
|
// fixup indentation of block
|
||||||
|
.indent_with_mapping(indent_to, &make);
|
||||||
|
|
||||||
editor.replace(to_wrap.syntax(), block.syntax());
|
editor.replace(to_wrap.syntax(), block.syntax());
|
||||||
|
|
||||||
// fixup indentation of block
|
|
||||||
block.indent(indent_to);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,7 @@ fn func_assoc_item(
|
||||||
)
|
)
|
||||||
.clone_for_update();
|
.clone_for_update();
|
||||||
|
|
||||||
Some(AssocItem::Fn(func.indent(edit::IndentLevel(1)).clone_for_update()))
|
Some(AssocItem::Fn(func.indent(edit::IndentLevel(1))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> Option<AssocItem> {
|
fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> Option<AssocItem> {
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ pub fn add_trait_assoc_items_to_impl(
|
||||||
),
|
),
|
||||||
new_indent_level,
|
new_indent_level,
|
||||||
);
|
);
|
||||||
ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax())
|
ted::replace(fn_.get_or_create_body().syntax(), body.syntax())
|
||||||
}
|
}
|
||||||
ast::AssocItem::TypeAlias(type_alias) => {
|
ast::AssocItem::TypeAlias(type_alias) => {
|
||||||
if let Some(type_bound_list) = type_alias.type_bound_list() {
|
if let Some(type_bound_list) = type_alias.type_bound_list() {
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
|
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
|
||||||
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
|
ted::replace(func.body()?.syntax(), body.syntax());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +248,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
|
|
||||||
let body = make::block_expr(None, Some(match_expr.into()));
|
let body = make::block_expr(None, Some(match_expr.into()));
|
||||||
let body = body.indent(ast::edit::IndentLevel(1));
|
let body = body.indent(ast::edit::IndentLevel(1));
|
||||||
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
|
ted::replace(func.body()?.syntax(), body.syntax());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,7 +296,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
let method = make::name_ref("finish");
|
let method = make::name_ref("finish");
|
||||||
let expr = make::expr_method_call(expr, method, make::arg_list(None)).into();
|
let expr = make::expr_method_call(expr, method, make::arg_list(None)).into();
|
||||||
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
|
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
|
||||||
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
|
ted::replace(func.body()?.syntax(), body.syntax());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,7 +342,7 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
|
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
|
||||||
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
|
ted::replace(func.body()?.syntax(), body.syntax());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -400,7 +400,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
|
ted::replace(func.body()?.syntax(), body.syntax());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -595,7 +595,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef<'_>
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
|
ted::replace(func.body()?.syntax(), body.syntax());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -686,7 +686,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef<'_
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
|
ted::replace(func.body()?.syntax(), body.syntax());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@ use std::{fmt, iter, ops};
|
||||||
use crate::{
|
use crate::{
|
||||||
AstToken, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
|
AstToken, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
|
||||||
ast::{self, AstNode, make},
|
ast::{self, AstNode, make},
|
||||||
|
syntax_editor::{SyntaxEditor, SyntaxMappingBuilder},
|
||||||
ted,
|
ted,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::syntax_factory::SyntaxFactory;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct IndentLevel(pub u8);
|
pub struct IndentLevel(pub u8);
|
||||||
|
|
||||||
|
|
@ -95,6 +98,24 @@ impl IndentLevel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn clone_increase_indent(self, node: &SyntaxNode) -> SyntaxNode {
|
||||||
|
let node = node.clone_subtree();
|
||||||
|
let mut editor = SyntaxEditor::new(node.clone());
|
||||||
|
let tokens = node
|
||||||
|
.preorder_with_tokens()
|
||||||
|
.filter_map(|event| match event {
|
||||||
|
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.filter_map(ast::Whitespace::cast)
|
||||||
|
.filter(|ws| ws.text().contains('\n'));
|
||||||
|
for ws in tokens {
|
||||||
|
let new_ws = make::tokens::whitespace(&format!("{}{self}", ws.syntax()));
|
||||||
|
editor.replace(ws.syntax(), &new_ws);
|
||||||
|
}
|
||||||
|
editor.finish().new_root().clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn decrease_indent(self, node: &SyntaxNode) {
|
pub(super) fn decrease_indent(self, node: &SyntaxNode) {
|
||||||
let tokens = node.preorder_with_tokens().filter_map(|event| match event {
|
let tokens = node.preorder_with_tokens().filter_map(|event| match event {
|
||||||
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
|
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
|
||||||
|
|
@ -111,36 +132,54 @@ impl IndentLevel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn clone_decrease_indent(self, node: &SyntaxNode) -> SyntaxNode {
|
||||||
|
let node = node.clone_subtree();
|
||||||
|
let mut editor = SyntaxEditor::new(node.clone());
|
||||||
|
let tokens = node
|
||||||
|
.preorder_with_tokens()
|
||||||
|
.filter_map(|event| match event {
|
||||||
|
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.filter_map(ast::Whitespace::cast)
|
||||||
|
.filter(|ws| ws.text().contains('\n'));
|
||||||
|
for ws in tokens {
|
||||||
|
let new_ws =
|
||||||
|
make::tokens::whitespace(&ws.syntax().text().replace(&format!("\n{self}"), "\n"));
|
||||||
|
editor.replace(ws.syntax(), &new_ws);
|
||||||
|
}
|
||||||
|
editor.finish().new_root().clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
|
fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
|
||||||
iter::successors(Some(token), |token| token.prev_token())
|
iter::successors(Some(token), |token| token.prev_token())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Soft-deprecated in favor of mutable tree editing API `edit_in_place::Ident`.
|
|
||||||
pub trait AstNodeEdit: AstNode + Clone + Sized {
|
pub trait AstNodeEdit: AstNode + Clone + Sized {
|
||||||
fn indent_level(&self) -> IndentLevel {
|
fn indent_level(&self) -> IndentLevel {
|
||||||
IndentLevel::from_node(self.syntax())
|
IndentLevel::from_node(self.syntax())
|
||||||
}
|
}
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn indent(&self, level: IndentLevel) -> Self {
|
fn indent(&self, level: IndentLevel) -> Self {
|
||||||
fn indent_inner(node: &SyntaxNode, level: IndentLevel) -> SyntaxNode {
|
Self::cast(level.clone_increase_indent(self.syntax())).unwrap()
|
||||||
let res = node.clone_subtree().clone_for_update();
|
}
|
||||||
level.increase_indent(&res);
|
#[must_use]
|
||||||
res.clone_subtree()
|
fn indent_with_mapping(&self, level: IndentLevel, make: &SyntaxFactory) -> Self {
|
||||||
|
let new_node = self.indent(level);
|
||||||
|
if let Some(mut mapping) = make.mappings() {
|
||||||
|
let mut builder = SyntaxMappingBuilder::new(new_node.syntax().clone());
|
||||||
|
for (old, new) in self.syntax().children().zip(new_node.syntax().children()) {
|
||||||
|
builder.map_node(old, new);
|
||||||
|
}
|
||||||
|
builder.finish(&mut mapping);
|
||||||
}
|
}
|
||||||
|
new_node
|
||||||
Self::cast(indent_inner(self.syntax(), level)).unwrap()
|
|
||||||
}
|
}
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn dedent(&self, level: IndentLevel) -> Self {
|
fn dedent(&self, level: IndentLevel) -> Self {
|
||||||
fn dedent_inner(node: &SyntaxNode, level: IndentLevel) -> SyntaxNode {
|
Self::cast(level.clone_decrease_indent(self.syntax())).unwrap()
|
||||||
let res = node.clone_subtree().clone_for_update();
|
|
||||||
level.decrease_indent(&res);
|
|
||||||
res.clone_subtree()
|
|
||||||
}
|
|
||||||
|
|
||||||
Self::cast(dedent_inner(self.syntax(), level)).unwrap()
|
|
||||||
}
|
}
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn reset_indent(&self) -> Self {
|
fn reset_indent(&self) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ impl SyntaxFactory {
|
||||||
self.mappings.as_ref().map(|mappings| mappings.take()).unwrap_or_default()
|
self.mappings.as_ref().map(|mappings| mappings.take()).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mappings(&self) -> Option<RefMut<'_, SyntaxMapping>> {
|
pub(crate) fn mappings(&self) -> Option<RefMut<'_, SyntaxMapping>> {
|
||||||
self.mappings.as_ref().map(|it| it.borrow_mut())
|
self.mappings.as_ref().map(|it| it.borrow_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue