|
1 | 1 | //! Structural editing for ast using `SyntaxEditor`
|
2 | 2 |
|
3 | 3 | use crate::{
|
| 4 | + algo::neighbor, |
4 | 5 | ast::{
|
5 |
| - self, edit::IndentLevel, make, syntax_factory::SyntaxFactory, AstNode, Fn, GenericParam, |
6 |
| - HasGenericParams, HasName, |
| 6 | + self, edit::IndentLevel, make, syntax_factory::SyntaxFactory, AstNode, AstToken, Fn, |
| 7 | + GenericParam, HasGenericParams, HasName, |
7 | 8 | },
|
8 | 9 | syntax_editor::{Position, SyntaxEditor},
|
9 | 10 | Direction, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T,
|
@@ -143,6 +144,68 @@ fn normalize_ws_between_braces(editor: &mut SyntaxEditor, node: &SyntaxNode) ->
|
143 | 144 | Some(())
|
144 | 145 | }
|
145 | 146 |
|
| 147 | +pub trait Removable: AstNode { |
| 148 | + fn remove(&self, editor: &mut SyntaxEditor); |
| 149 | +} |
| 150 | + |
| 151 | +impl Removable for ast::Use { |
| 152 | + fn remove(&self, editor: &mut SyntaxEditor) { |
| 153 | + let make = SyntaxFactory::new(); |
| 154 | + |
| 155 | + let next_ws = self |
| 156 | + .syntax() |
| 157 | + .next_sibling_or_token() |
| 158 | + .and_then(|it| it.into_token()) |
| 159 | + .and_then(ast::Whitespace::cast); |
| 160 | + if let Some(next_ws) = next_ws { |
| 161 | + let ws_text = next_ws.syntax().text(); |
| 162 | + if let Some(rest) = ws_text.strip_prefix('\n') { |
| 163 | + if rest.is_empty() { |
| 164 | + editor.delete(next_ws.syntax()); |
| 165 | + } else { |
| 166 | + editor.replace(next_ws.syntax(), make.whitespace(rest)); |
| 167 | + } |
| 168 | + } |
| 169 | + } |
| 170 | + let prev_ws = self |
| 171 | + .syntax() |
| 172 | + .prev_sibling_or_token() |
| 173 | + .and_then(|it| it.into_token()) |
| 174 | + .and_then(ast::Whitespace::cast); |
| 175 | + if let Some(prev_ws) = prev_ws { |
| 176 | + let ws_text = prev_ws.syntax().text(); |
| 177 | + let prev_newline = ws_text.rfind('\n').map(|x| x + 1).unwrap_or(0); |
| 178 | + let rest = &ws_text[0..prev_newline]; |
| 179 | + if rest.is_empty() { |
| 180 | + editor.delete(prev_ws.syntax()); |
| 181 | + } else { |
| 182 | + editor.replace(prev_ws.syntax(), make.whitespace(rest)); |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + editor.delete(self.syntax()); |
| 187 | + } |
| 188 | +} |
| 189 | + |
| 190 | +impl Removable for ast::UseTree { |
| 191 | + fn remove(&self, editor: &mut SyntaxEditor) { |
| 192 | + for dir in [Direction::Next, Direction::Prev] { |
| 193 | + if let Some(next_use_tree) = neighbor(self, dir) { |
| 194 | + let separators = self |
| 195 | + .syntax() |
| 196 | + .siblings_with_tokens(dir) |
| 197 | + .skip(1) |
| 198 | + .take_while(|it| it.as_node() != Some(next_use_tree.syntax())); |
| 199 | + for sep in separators { |
| 200 | + editor.delete(sep); |
| 201 | + } |
| 202 | + break; |
| 203 | + } |
| 204 | + } |
| 205 | + editor.delete(self.syntax()); |
| 206 | + } |
| 207 | +} |
| 208 | + |
146 | 209 | #[cfg(test)]
|
147 | 210 | mod tests {
|
148 | 211 | use parser::Edition;
|
|
0 commit comments