From 34555593caeea25d460703e25c446b13132b1c5b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 16 Mar 2021 22:51:37 +0300 Subject: Auto-magical whitespace --- crates/syntax/src/ast/edit_in_place.rs | 32 ++++++++-------------- crates/syntax/src/ted.rs | 49 ++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 23 deletions(-) (limited to 'crates/syntax') diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 1788f2a40..7adfe5e16 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -8,7 +8,7 @@ use parser::T; use crate::{ ast, ted::{self, Position}, - AstNode, Direction, SyntaxKind, + AstNode, Direction, SyntaxElement, }; use super::NameOwner; @@ -27,7 +27,7 @@ impl GenericParamsOwnerEdit for ast::Fn { } else { Position::last_child_of(self.syntax().clone()) }; - create_where_clause(position, true) + create_where_clause(position) } self.where_clause().unwrap() } @@ -41,7 +41,7 @@ impl GenericParamsOwnerEdit for ast::Impl { } else { Position::last_child_of(self.syntax().clone()) }; - create_where_clause(position, false) + create_where_clause(position) } self.where_clause().unwrap() } @@ -55,7 +55,7 @@ impl GenericParamsOwnerEdit for ast::Trait { } else { Position::last_child_of(self.syntax().clone()) }; - create_where_clause(position, false) + create_where_clause(position) } self.where_clause().unwrap() } @@ -77,7 +77,7 @@ impl GenericParamsOwnerEdit for ast::Struct { } else { Position::last_child_of(self.syntax().clone()) }; - create_where_clause(position, true) + create_where_clause(position) } self.where_clause().unwrap() } @@ -93,21 +93,16 @@ impl GenericParamsOwnerEdit for ast::Enum { } else { Position::last_child_of(self.syntax().clone()) }; - create_where_clause(position, true) + create_where_clause(position) } self.where_clause().unwrap() } } -fn create_where_clause(position: Position, after: bool) { - let mut elements = vec![make::where_clause(empty()).clone_for_update().syntax().clone().into()]; - let ws = make::tokens::single_space().into(); - if after { - elements.insert(0, ws) - } else { - elements.push(ws) - } - ted::insert_all(position, elements); +fn create_where_clause(position: Position) { + let where_clause: SyntaxElement = + make::where_clause(empty()).clone_for_update().syntax().clone().into(); + ted::insert_ws(position, where_clause); } impl ast::WhereClause { @@ -117,12 +112,7 @@ impl ast::WhereClause { ted::append_child(self.syntax().clone(), make::token(T![,])); } } - if self.syntax().children_with_tokens().last().map(|it| it.kind()) - != Some(SyntaxKind::WHITESPACE) - { - ted::append_child(self.syntax().clone(), make::tokens::single_space()); - } - ted::append_child(self.syntax().clone(), predicate.syntax().clone()) + ted::append_child_ws(self.syntax().clone(), predicate.syntax().clone()) } } diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs index 8d6175ed9..f2166bbd3 100644 --- a/crates/syntax/src/ted.rs +++ b/crates/syntax/src/ted.rs @@ -1,8 +1,9 @@ //! Primitive tree editor, ed for trees -#![allow(unused)] use std::ops::RangeInclusive; -use crate::{SyntaxElement, SyntaxNode}; +use parser::T; + +use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; #[derive(Debug)] pub struct Position { @@ -42,9 +43,25 @@ impl Position { } } +pub fn insert_ws(position: Position, elem: impl Into) { + insert_all_ws(position, vec![elem.into()]) +} pub fn insert(position: Position, elem: impl Into) { insert_all(position, vec![elem.into()]) } +pub fn insert_all_ws(position: Position, mut elements: Vec) { + if let Some(first) = elements.first() { + if let Some(ws) = ws_before(&position, first) { + elements.insert(0, ws.into()) + } + } + if let Some(last) = elements.last() { + if let Some(ws) = ws_after(&position, last) { + elements.push(ws.into()) + } + } + insert_all(position, elements) +} pub fn insert_all(position: Position, elements: Vec) { let (parent, index) = match position.repr { PositionRepr::FirstChild(parent) => (parent, 0), @@ -72,7 +89,35 @@ pub fn replace_all(range: RangeInclusive, new: Vec parent.splice_children(start..end + 1, new) } +pub fn append_child_ws(node: impl Into, child: impl Into) { + let position = Position::last_child_of(node); + insert_ws(position, child) +} pub fn append_child(node: impl Into, child: impl Into) { let position = Position::last_child_of(node); insert(position, child) } + +fn ws_before(position: &Position, new: &SyntaxElement) -> Option { + let prev = match &position.repr { + PositionRepr::FirstChild(_) => return None, + PositionRepr::After(it) => it, + }; + ws_between(prev, new) +} +fn ws_after(position: &Position, new: &SyntaxElement) -> Option { + let next = match &position.repr { + PositionRepr::FirstChild(parent) => parent.first_child_or_token()?, + PositionRepr::After(sibling) => sibling.next_sibling_or_token()?, + }; + ws_between(new, &next) +} +fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option { + if left.kind() == SyntaxKind::WHITESPACE || right.kind() == SyntaxKind::WHITESPACE { + return None; + } + if right.kind() == T![;] || right.kind() == T![,] { + return None; + } + Some(make::tokens::single_space().into()) +} -- cgit v1.2.3