diff options
Diffstat (limited to 'crates/syntax/src/ted.rs')
-rw-r--r-- | crates/syntax/src/ted.rs | 49 |
1 files changed, 47 insertions, 2 deletions
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 @@ | |||
1 | //! Primitive tree editor, ed for trees | 1 | //! Primitive tree editor, ed for trees |
2 | #![allow(unused)] | ||
3 | use std::ops::RangeInclusive; | 2 | use std::ops::RangeInclusive; |
4 | 3 | ||
5 | use crate::{SyntaxElement, SyntaxNode}; | 4 | use parser::T; |
5 | |||
6 | use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; | ||
6 | 7 | ||
7 | #[derive(Debug)] | 8 | #[derive(Debug)] |
8 | pub struct Position { | 9 | pub struct Position { |
@@ -42,9 +43,25 @@ impl Position { | |||
42 | } | 43 | } |
43 | } | 44 | } |
44 | 45 | ||
46 | pub fn insert_ws(position: Position, elem: impl Into<SyntaxElement>) { | ||
47 | insert_all_ws(position, vec![elem.into()]) | ||
48 | } | ||
45 | pub fn insert(position: Position, elem: impl Into<SyntaxElement>) { | 49 | pub fn insert(position: Position, elem: impl Into<SyntaxElement>) { |
46 | insert_all(position, vec![elem.into()]) | 50 | insert_all(position, vec![elem.into()]) |
47 | } | 51 | } |
52 | pub fn insert_all_ws(position: Position, mut elements: Vec<SyntaxElement>) { | ||
53 | if let Some(first) = elements.first() { | ||
54 | if let Some(ws) = ws_before(&position, first) { | ||
55 | elements.insert(0, ws.into()) | ||
56 | } | ||
57 | } | ||
58 | if let Some(last) = elements.last() { | ||
59 | if let Some(ws) = ws_after(&position, last) { | ||
60 | elements.push(ws.into()) | ||
61 | } | ||
62 | } | ||
63 | insert_all(position, elements) | ||
64 | } | ||
48 | pub fn insert_all(position: Position, elements: Vec<SyntaxElement>) { | 65 | pub fn insert_all(position: Position, elements: Vec<SyntaxElement>) { |
49 | let (parent, index) = match position.repr { | 66 | let (parent, index) = match position.repr { |
50 | PositionRepr::FirstChild(parent) => (parent, 0), | 67 | PositionRepr::FirstChild(parent) => (parent, 0), |
@@ -72,7 +89,35 @@ pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement> | |||
72 | parent.splice_children(start..end + 1, new) | 89 | parent.splice_children(start..end + 1, new) |
73 | } | 90 | } |
74 | 91 | ||
92 | pub fn append_child_ws(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { | ||
93 | let position = Position::last_child_of(node); | ||
94 | insert_ws(position, child) | ||
95 | } | ||
75 | pub fn append_child(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { | 96 | pub fn append_child(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { |
76 | let position = Position::last_child_of(node); | 97 | let position = Position::last_child_of(node); |
77 | insert(position, child) | 98 | insert(position, child) |
78 | } | 99 | } |
100 | |||
101 | fn ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> { | ||
102 | let prev = match &position.repr { | ||
103 | PositionRepr::FirstChild(_) => return None, | ||
104 | PositionRepr::After(it) => it, | ||
105 | }; | ||
106 | ws_between(prev, new) | ||
107 | } | ||
108 | fn ws_after(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> { | ||
109 | let next = match &position.repr { | ||
110 | PositionRepr::FirstChild(parent) => parent.first_child_or_token()?, | ||
111 | PositionRepr::After(sibling) => sibling.next_sibling_or_token()?, | ||
112 | }; | ||
113 | ws_between(new, &next) | ||
114 | } | ||
115 | fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken> { | ||
116 | if left.kind() == SyntaxKind::WHITESPACE || right.kind() == SyntaxKind::WHITESPACE { | ||
117 | return None; | ||
118 | } | ||
119 | if right.kind() == T![;] || right.kind() == T![,] { | ||
120 | return None; | ||
121 | } | ||
122 | Some(make::tokens::single_space().into()) | ||
123 | } | ||