internal: introduce in-place indenting API

This commit is contained in:
Dawer 2021-08-18 16:05:23 +05:00
parent dcbaa75bc1
commit d6c4165182
2 changed files with 61 additions and 18 deletions

View File

@ -117,9 +117,8 @@ impl IndentLevel {
/// } /// }
/// ``` /// ```
/// if you indent the block, the `{` token would stay put. /// if you indent the block, the `{` token would stay put.
fn increase_indent(self, node: SyntaxNode) -> SyntaxNode { pub(in super) fn increase_indent(self, node: &SyntaxNode) {
let res = node.clone_subtree().clone_for_update(); let tokens = node.preorder_with_tokens().filter_map(|event| match event {
let tokens = res.preorder_with_tokens().filter_map(|event| match event {
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it), rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
_ => None, _ => None,
}); });
@ -131,12 +130,10 @@ impl IndentLevel {
} }
} }
} }
res.clone_subtree()
} }
fn decrease_indent(self, node: SyntaxNode) -> SyntaxNode { pub(in super) fn decrease_indent(self, node: &SyntaxNode) {
let res = node.clone_subtree().clone_for_update(); let tokens = node.preorder_with_tokens().filter_map(|event| match event {
let tokens = res.preorder_with_tokens().filter_map(|event| match event {
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it), rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
_ => None, _ => None,
}); });
@ -150,7 +147,6 @@ impl IndentLevel {
} }
} }
} }
res.clone_subtree()
} }
} }
@ -158,17 +154,30 @@ 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 {
Self::cast(level.increase_indent(self.syntax().clone())).unwrap() 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(indent_inner(self.syntax(), level)).unwrap()
} }
#[must_use] #[must_use]
fn dedent(&self, level: IndentLevel) -> Self { fn dedent(&self, level: IndentLevel) -> Self {
Self::cast(level.decrease_indent(self.syntax().clone())).unwrap() 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()
} }
#[must_use] #[must_use]
fn reset_indent(&self) -> Self { fn reset_indent(&self) -> Self {

View File

@ -7,11 +7,7 @@ use rowan::SyntaxElement;
use crate::{ use crate::{
algo::neighbor, algo::neighbor,
ast::{ ast::{self, edit::IndentLevel, make, GenericParamsOwner},
self,
edit::{AstNodeEdit, IndentLevel},
make, GenericParamsOwner,
},
ted::{self, Position}, ted::{self, Position},
AstNode, AstToken, Direction, AstNode, AstToken, Direction,
SyntaxKind::{ATTR, COMMENT, WHITESPACE}, SyntaxKind::{ATTR, COMMENT, WHITESPACE},
@ -20,7 +16,7 @@ use crate::{
use super::NameOwner; use super::NameOwner;
pub trait GenericParamsOwnerEdit: ast::GenericParamsOwner + AstNodeEdit { pub trait GenericParamsOwnerEdit: ast::GenericParamsOwner {
fn get_or_create_generic_param_list(&self) -> ast::GenericParamList; fn get_or_create_generic_param_list(&self) -> ast::GenericParamList;
fn get_or_create_where_clause(&self) -> ast::WhereClause; fn get_or_create_where_clause(&self) -> ast::WhereClause;
} }
@ -198,7 +194,7 @@ fn create_generic_param_list(position: Position) -> ast::GenericParamList {
gpl gpl
} }
pub trait AttrsOwnerEdit: ast::AttrsOwner + AstNodeEdit { pub trait AttrsOwnerEdit: ast::AttrsOwner {
fn remove_attrs_and_docs(&self) { fn remove_attrs_and_docs(&self) {
remove_attrs_and_docs(self.syntax()); remove_attrs_and_docs(self.syntax());
@ -222,7 +218,7 @@ pub trait AttrsOwnerEdit: ast::AttrsOwner + AstNodeEdit {
} }
} }
impl<T: ast::AttrsOwner + AstNodeEdit> AttrsOwnerEdit for T {} impl<T: ast::AttrsOwner> AttrsOwnerEdit for T {}
impl ast::GenericParamList { impl ast::GenericParamList {
pub fn add_generic_param(&self, generic_param: ast::GenericParam) { pub fn add_generic_param(&self, generic_param: ast::GenericParam) {
@ -487,6 +483,26 @@ fn normalize_ws_between_braces(node: &SyntaxNode) -> Option<()> {
Some(()) Some(())
} }
pub trait Indent: AstNode + Clone + Sized {
fn indent_level(&self) -> IndentLevel {
IndentLevel::from_node(self.syntax())
}
fn indent(&self, level: IndentLevel) -> &Self {
level.increase_indent(self.syntax());
self
}
fn dedent(&self, level: IndentLevel) -> &Self {
level.decrease_indent(self.syntax());
self
}
fn reset_indent(&self) -> &Self {
let level = IndentLevel::from_node(self.syntax());
self.dedent(level)
}
}
impl<N: AstNode + Clone> Indent for N {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::fmt; use std::fmt;
@ -526,4 +542,22 @@ mod tests {
check_create_gpl::<ast::Enum>("enum E", "enum E<>"); check_create_gpl::<ast::Enum>("enum E", "enum E<>");
check_create_gpl::<ast::Enum>("enum E {", "enum E<> {"); check_create_gpl::<ast::Enum>("enum E {", "enum E<> {");
} }
#[test]
fn test_increase_indent() {
let arm_list = ast_mut_from_text::<ast::Fn>(
"fn foo() {
;
;
}",
);
arm_list.indent(IndentLevel(2));
assert_eq!(
arm_list.to_string(),
"fn foo() {
;
;
}",
);
}
} }