diff options
author | Aleksey Kladov <[email protected]> | 2021-03-16 19:51:37 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-03-16 19:51:37 +0000 |
commit | 34555593caeea25d460703e25c446b13132b1c5b (patch) | |
tree | a1cafd28b016ccb758dc87415b277b57a1eec270 /crates/syntax/src | |
parent | d733c9bdad81e23959b1a43421a9fa6ea92eda9f (diff) |
Auto-magical whitespace
Diffstat (limited to 'crates/syntax/src')
-rw-r--r-- | crates/syntax/src/ast/edit_in_place.rs | 32 | ||||
-rw-r--r-- | crates/syntax/src/ted.rs | 49 |
2 files changed, 58 insertions, 23 deletions
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; | |||
8 | use crate::{ | 8 | use crate::{ |
9 | ast, | 9 | ast, |
10 | ted::{self, Position}, | 10 | ted::{self, Position}, |
11 | AstNode, Direction, SyntaxKind, | 11 | AstNode, Direction, SyntaxElement, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use super::NameOwner; | 14 | use super::NameOwner; |
@@ -27,7 +27,7 @@ impl GenericParamsOwnerEdit for ast::Fn { | |||
27 | } else { | 27 | } else { |
28 | Position::last_child_of(self.syntax().clone()) | 28 | Position::last_child_of(self.syntax().clone()) |
29 | }; | 29 | }; |
30 | create_where_clause(position, true) | 30 | create_where_clause(position) |
31 | } | 31 | } |
32 | self.where_clause().unwrap() | 32 | self.where_clause().unwrap() |
33 | } | 33 | } |
@@ -41,7 +41,7 @@ impl GenericParamsOwnerEdit for ast::Impl { | |||
41 | } else { | 41 | } else { |
42 | Position::last_child_of(self.syntax().clone()) | 42 | Position::last_child_of(self.syntax().clone()) |
43 | }; | 43 | }; |
44 | create_where_clause(position, false) | 44 | create_where_clause(position) |
45 | } | 45 | } |
46 | self.where_clause().unwrap() | 46 | self.where_clause().unwrap() |
47 | } | 47 | } |
@@ -55,7 +55,7 @@ impl GenericParamsOwnerEdit for ast::Trait { | |||
55 | } else { | 55 | } else { |
56 | Position::last_child_of(self.syntax().clone()) | 56 | Position::last_child_of(self.syntax().clone()) |
57 | }; | 57 | }; |
58 | create_where_clause(position, false) | 58 | create_where_clause(position) |
59 | } | 59 | } |
60 | self.where_clause().unwrap() | 60 | self.where_clause().unwrap() |
61 | } | 61 | } |
@@ -77,7 +77,7 @@ impl GenericParamsOwnerEdit for ast::Struct { | |||
77 | } else { | 77 | } else { |
78 | Position::last_child_of(self.syntax().clone()) | 78 | Position::last_child_of(self.syntax().clone()) |
79 | }; | 79 | }; |
80 | create_where_clause(position, true) | 80 | create_where_clause(position) |
81 | } | 81 | } |
82 | self.where_clause().unwrap() | 82 | self.where_clause().unwrap() |
83 | } | 83 | } |
@@ -93,21 +93,16 @@ impl GenericParamsOwnerEdit for ast::Enum { | |||
93 | } else { | 93 | } else { |
94 | Position::last_child_of(self.syntax().clone()) | 94 | Position::last_child_of(self.syntax().clone()) |
95 | }; | 95 | }; |
96 | create_where_clause(position, true) | 96 | create_where_clause(position) |
97 | } | 97 | } |
98 | self.where_clause().unwrap() | 98 | self.where_clause().unwrap() |
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | fn create_where_clause(position: Position, after: bool) { | 102 | fn create_where_clause(position: Position) { |
103 | let mut elements = vec![make::where_clause(empty()).clone_for_update().syntax().clone().into()]; | 103 | let where_clause: SyntaxElement = |
104 | let ws = make::tokens::single_space().into(); | 104 | make::where_clause(empty()).clone_for_update().syntax().clone().into(); |
105 | if after { | 105 | ted::insert_ws(position, where_clause); |
106 | elements.insert(0, ws) | ||
107 | } else { | ||
108 | elements.push(ws) | ||
109 | } | ||
110 | ted::insert_all(position, elements); | ||
111 | } | 106 | } |
112 | 107 | ||
113 | impl ast::WhereClause { | 108 | impl ast::WhereClause { |
@@ -117,12 +112,7 @@ impl ast::WhereClause { | |||
117 | ted::append_child(self.syntax().clone(), make::token(T![,])); | 112 | ted::append_child(self.syntax().clone(), make::token(T![,])); |
118 | } | 113 | } |
119 | } | 114 | } |
120 | if self.syntax().children_with_tokens().last().map(|it| it.kind()) | 115 | ted::append_child_ws(self.syntax().clone(), predicate.syntax().clone()) |
121 | != Some(SyntaxKind::WHITESPACE) | ||
122 | { | ||
123 | ted::append_child(self.syntax().clone(), make::tokens::single_space()); | ||
124 | } | ||
125 | ted::append_child(self.syntax().clone(), predicate.syntax().clone()) | ||
126 | } | 116 | } |
127 | } | 117 | } |
128 | 118 | ||
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 | } | ||