aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/syntax/src')
-rw-r--r--crates/syntax/src/ast/edit.rs46
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs44
-rw-r--r--crates/syntax/src/ast/make.rs2
-rw-r--r--crates/syntax/src/ted.rs28
4 files changed, 74 insertions, 46 deletions
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs
index 347862b8a..18820786a 100644
--- a/crates/syntax/src/ast/edit.rs
+++ b/crates/syntax/src/ast/edit.rs
@@ -9,7 +9,7 @@ use std::{
9use arrayvec::ArrayVec; 9use arrayvec::ArrayVec;
10 10
11use crate::{ 11use crate::{
12 algo::{self, neighbor, SyntaxRewriter}, 12 algo::{self, SyntaxRewriter},
13 ast::{ 13 ast::{
14 self, 14 self,
15 make::{self, tokens}, 15 make::{self, tokens},
@@ -322,27 +322,6 @@ impl ast::Use {
322 } 322 }
323 self.clone() 323 self.clone()
324 } 324 }
325
326 pub fn remove(&self) -> SyntaxRewriter<'static> {
327 let mut res = SyntaxRewriter::default();
328 res.delete(self.syntax());
329 let next_ws = self
330 .syntax()
331 .next_sibling_or_token()
332 .and_then(|it| it.into_token())
333 .and_then(ast::Whitespace::cast);
334 if let Some(next_ws) = next_ws {
335 let ws_text = next_ws.syntax().text();
336 if let Some(rest) = ws_text.strip_prefix('\n') {
337 if rest.is_empty() {
338 res.delete(next_ws.syntax())
339 } else {
340 res.replace(next_ws.syntax(), &make::tokens::whitespace(rest));
341 }
342 }
343 }
344 res
345 }
346} 325}
347 326
348impl ast::UseTree { 327impl ast::UseTree {
@@ -396,22 +375,6 @@ impl ast::UseTree {
396 Some(res) 375 Some(res)
397 } 376 }
398 } 377 }
399
400 pub fn remove(&self) -> SyntaxRewriter<'static> {
401 let mut res = SyntaxRewriter::default();
402 res.delete(self.syntax());
403 for &dir in [Direction::Next, Direction::Prev].iter() {
404 if let Some(nb) = neighbor(self, dir) {
405 self.syntax()
406 .siblings_with_tokens(dir)
407 .skip(1)
408 .take_while(|it| it.as_node() != Some(nb.syntax()))
409 .for_each(|el| res.delete(&el));
410 return res;
411 }
412 }
413 res
414 }
415} 378}
416 379
417impl ast::MatchArmList { 380impl ast::MatchArmList {
@@ -592,6 +555,13 @@ impl ops::Add<u8> for IndentLevel {
592} 555}
593 556
594impl IndentLevel { 557impl IndentLevel {
558 pub fn from_element(element: &SyntaxElement) -> IndentLevel {
559 match element {
560 rowan::NodeOrToken::Node(it) => IndentLevel::from_node(it),
561 rowan::NodeOrToken::Token(it) => IndentLevel::from_token(it),
562 }
563 }
564
595 pub fn from_node(node: &SyntaxNode) -> IndentLevel { 565 pub fn from_node(node: &SyntaxNode) -> IndentLevel {
596 match node.first_token() { 566 match node.first_token() {
597 Some(it) => Self::from_token(&it), 567 Some(it) => Self::from_token(&it),
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
index b1eed0a2c..529bd0eb1 100644
--- a/crates/syntax/src/ast/edit_in_place.rs
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -2,13 +2,13 @@
2 2
3use std::iter::empty; 3use std::iter::empty;
4 4
5use ast::{edit::AstNodeEdit, make, GenericParamsOwner, WhereClause};
6use parser::T; 5use parser::T;
7 6
8use crate::{ 7use crate::{
9 ast, 8 algo::neighbor,
9 ast::{self, edit::AstNodeEdit, make, GenericParamsOwner, WhereClause},
10 ted::{self, Position}, 10 ted::{self, Position},
11 AstNode, Direction, 11 AstNode, AstToken, Direction,
12}; 12};
13 13
14use super::NameOwner; 14use super::NameOwner;
@@ -126,3 +126,41 @@ impl ast::TypeBoundList {
126 } 126 }
127 } 127 }
128} 128}
129
130impl ast::UseTree {
131 pub fn remove(&self) {
132 for &dir in [Direction::Next, Direction::Prev].iter() {
133 if let Some(next_use_tree) = neighbor(self, dir) {
134 let separators = self
135 .syntax()
136 .siblings_with_tokens(dir)
137 .skip(1)
138 .take_while(|it| it.as_node() != Some(next_use_tree.syntax()));
139 ted::remove_all_iter(separators);
140 break;
141 }
142 }
143 ted::remove(self.syntax())
144 }
145}
146
147impl ast::Use {
148 pub fn remove(&self) {
149 let next_ws = self
150 .syntax()
151 .next_sibling_or_token()
152 .and_then(|it| it.into_token())
153 .and_then(ast::Whitespace::cast);
154 if let Some(next_ws) = next_ws {
155 let ws_text = next_ws.syntax().text();
156 if let Some(rest) = ws_text.strip_prefix('\n') {
157 if rest.is_empty() {
158 ted::remove(next_ws.syntax())
159 } else {
160 ted::replace(next_ws.syntax(), make::tokens::whitespace(rest))
161 }
162 }
163 }
164 ted::remove(self.syntax())
165 }
166}
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 7049affd9..c08f2c14f 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -560,7 +560,7 @@ pub mod tokens {
560 pub fn whitespace(text: &str) -> SyntaxToken { 560 pub fn whitespace(text: &str) -> SyntaxToken {
561 assert!(text.trim().is_empty()); 561 assert!(text.trim().is_empty());
562 let sf = SourceFile::parse(text).ok().unwrap(); 562 let sf = SourceFile::parse(text).ok().unwrap();
563 sf.syntax().first_child_or_token().unwrap().into_token().unwrap() 563 sf.syntax().clone_for_update().first_child_or_token().unwrap().into_token().unwrap()
564 } 564 }
565 565
566 pub fn doc_comment(text: &str) -> SyntaxToken { 566 pub fn doc_comment(text: &str) -> SyntaxToken {
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs
index be2b846b1..177d4ff67 100644
--- a/crates/syntax/src/ted.rs
+++ b/crates/syntax/src/ted.rs
@@ -2,11 +2,14 @@
2//! 2//!
3//! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix 3//! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix
4//! up elements around the edges. 4//! up elements around the edges.
5use std::ops::RangeInclusive; 5use std::{mem, ops::RangeInclusive};
6 6
7use parser::T; 7use parser::T;
8 8
9use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; 9use crate::{
10 ast::{edit::IndentLevel, make},
11 SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
12};
10 13
11/// Utility trait to allow calling `ted` functions with references or owned 14/// Utility trait to allow calling `ted` functions with references or owned
12/// nodes. Do not use outside of this module. 15/// nodes. Do not use outside of this module.
@@ -101,12 +104,25 @@ pub fn insert_all_raw(position: Position, elements: Vec<SyntaxElement>) {
101} 104}
102 105
103pub fn remove(elem: impl Element) { 106pub fn remove(elem: impl Element) {
104 let elem = elem.syntax_element(); 107 elem.syntax_element().detach()
105 remove_all(elem.clone()..=elem)
106} 108}
107pub fn remove_all(range: RangeInclusive<SyntaxElement>) { 109pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
108 replace_all(range, Vec::new()) 110 replace_all(range, Vec::new())
109} 111}
112pub fn remove_all_iter(range: impl IntoIterator<Item = SyntaxElement>) {
113 let mut it = range.into_iter();
114 if let Some(mut first) = it.next() {
115 match it.last() {
116 Some(mut last) => {
117 if first.index() > last.index() {
118 mem::swap(&mut first, &mut last)
119 }
120 remove_all(first..=last)
121 }
122 None => remove(first),
123 }
124 }
125}
110 126
111pub fn replace(old: impl Element, new: impl Element) { 127pub fn replace(old: impl Element, new: impl Element) {
112 let old = old.syntax_element(); 128 let old = old.syntax_element();
@@ -149,5 +165,9 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken
149 if right.kind() == T![;] || right.kind() == T![,] { 165 if right.kind() == T![;] || right.kind() == T![,] {
150 return None; 166 return None;
151 } 167 }
168 if right.kind() == SyntaxKind::USE {
169 let indent = IndentLevel::from_element(left);
170 return Some(make::tokens::whitespace(&format!("\n{}", indent)));
171 }
152 Some(make::tokens::single_space()) 172 Some(make::tokens::single_space())
153} 173}