mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-27 10:17:15 +00:00
Merge pull request #20269 from Hmikihiro/migrate_indent_mapping
Some checks are pending
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
Some checks are pending
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
Migrate AstNodeEdit::Indent to SyntaxEditor
This commit is contained in:
commit
bdfc7709bf
8 changed files with 74 additions and 35 deletions
|
|
@ -6,9 +6,12 @@ use std::{fmt, iter, ops};
|
|||
use crate::{
|
||||
AstToken, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
|
||||
ast::{self, AstNode, make},
|
||||
syntax_editor::{SyntaxEditor, SyntaxMappingBuilder},
|
||||
ted,
|
||||
};
|
||||
|
||||
use super::syntax_factory::SyntaxFactory;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
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) {
|
||||
let tokens = node.preorder_with_tokens().filter_map(|event| match event {
|
||||
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> {
|
||||
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 {
|
||||
fn indent_level(&self) -> IndentLevel {
|
||||
IndentLevel::from_node(self.syntax())
|
||||
}
|
||||
#[must_use]
|
||||
fn indent(&self, level: IndentLevel) -> Self {
|
||||
fn indent_inner(node: &SyntaxNode, level: IndentLevel) -> SyntaxNode {
|
||||
let res = node.clone_subtree().clone_for_update();
|
||||
level.increase_indent(&res);
|
||||
res.clone_subtree()
|
||||
Self::cast(level.clone_increase_indent(self.syntax())).unwrap()
|
||||
}
|
||||
#[must_use]
|
||||
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);
|
||||
}
|
||||
|
||||
Self::cast(indent_inner(self.syntax(), level)).unwrap()
|
||||
new_node
|
||||
}
|
||||
#[must_use]
|
||||
fn dedent(&self, level: IndentLevel) -> Self {
|
||||
fn dedent_inner(node: &SyntaxNode, level: IndentLevel) -> SyntaxNode {
|
||||
let res = node.clone_subtree().clone_for_update();
|
||||
level.decrease_indent(&res);
|
||||
res.clone_subtree()
|
||||
}
|
||||
|
||||
Self::cast(dedent_inner(self.syntax(), level)).unwrap()
|
||||
Self::cast(level.clone_decrease_indent(self.syntax())).unwrap()
|
||||
}
|
||||
#[must_use]
|
||||
fn reset_indent(&self) -> Self {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ impl SyntaxFactory {
|
|||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue