aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_editor
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_editor')
-rw-r--r--crates/ra_editor/src/typing.rs143
1 files changed, 68 insertions, 75 deletions
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index ae82ff89b..3ebdf153e 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -131,78 +131,77 @@ fn remove_newline(
131 node_text: &str, 131 node_text: &str,
132 offset: TextUnit, 132 offset: TextUnit,
133) { 133) {
134 if node.kind() == WHITESPACE && node_text.bytes().filter(|&b| b == b'\n').count() == 1 { 134 if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 {
135 // Special case that turns something like: 135 // The node is either the first or the last in the file
136 // 136 let suff = &node_text[TextRange::from_to(
137 // ``` 137 offset - node.range().start() + TextUnit::of_char('\n'),
138 // my_function({<|> 138 TextUnit::of_str(node_text),
139 // <some-expr> 139 )];
140 // }) 140 let spaces = suff.bytes().take_while(|&b| b == b' ').count();
141 // ``` 141
142 // 142 edit.replace(
143 // into `my_function(<some-expr>)` 143 TextRange::offset_len(offset, ((spaces + 1) as u32).into()),
144 if join_single_expr_block(edit, node).is_some() { 144 " ".to_string(),
145 return 145 );
146 } 146 return;
147 }
147 148
148 if let (Some(prev), Some(next)) = (node.prev_sibling(), node.next_sibling()) { 149 // Special case that turns something like:
149 let range = TextRange::from_to(prev.range().start(), node.range().end()); 150 //
150 if is_trailing_comma(prev.kind(), next.kind()) { 151 // ```
151 // Removes: trailing comma, newline (incl. surrounding whitespace) 152 // my_function({<|>
152 edit.delete(range); 153 // <some-expr>
153 } else if no_space_required(prev.kind(), next.kind()) { 154 // })
154 // Removes: newline (incl. surrounding whitespace) 155 // ```
155 edit.delete(node.range()); 156 //
156 } else if prev.kind() == COMMA && next.kind() == R_CURLY { 157 // into `my_function(<some-expr>)`
157 // Removes: comma, newline (incl. surrounding whitespace) 158 if join_single_expr_block(edit, node).is_some() {
158 // Adds: a single whitespace 159 return
159 edit.replace(range, " ".to_string()); 160 }
160 } else if let (Some(_), Some(next)) = (ast::Comment::cast(prev), ast::Comment::cast(next)) {
161 // Removes: newline (incl. surrounding whitespace), start of the next comment
162 let comment_text = next.text();
163 if let Some(newline_pos) = comment_text.find('\n') {
164 // Special case for multi-line c-like comments: join the comment content but
165 // keep the leading `/*`
166
167 let newline_offset = next.syntax().range().start()
168 + TextUnit::from(newline_pos as u32)
169 + TextUnit::of_char('\n');
170
171 edit.insert(newline_offset, "/*".to_string());
172 edit.delete(TextRange::from_to(
173 node.range().start(),
174 next.syntax().range().start() + TextUnit::of_str(next.prefix())
175 ));
176 } else {
177 // Single-line comments
178 edit.delete(TextRange::from_to(
179 node.range().start(),
180 next.syntax().range().start() + TextUnit::of_str(next.prefix())
181 ));
182 }
183 } else {
184 // Remove newline but add a computed amount of whitespace characters
185 edit.replace(
186 node.range(),
187 compute_ws(prev, next).to_string(),
188 );
189 }
190 161
191 return; 162 // The node is between two other nodes
163 let prev = node.prev_sibling().unwrap();
164 let next = node.next_sibling().unwrap();
165 if is_trailing_comma(prev.kind(), next.kind()) {
166 // Removes: trailing comma, newline (incl. surrounding whitespace)
167 edit.delete(TextRange::from_to(prev.range().start(), node.range().end()));
168 } else if prev.kind() == COMMA && next.kind() == R_CURLY {
169 // Removes: comma, newline (incl. surrounding whitespace)
170 // Adds: a single whitespace
171 edit.replace(
172 TextRange::from_to(prev.range().start(), node.range().end()),
173 " ".to_string()
174 );
175 } else if let (Some(_), Some(next)) = (ast::Comment::cast(prev), ast::Comment::cast(next)) {
176 // Removes: newline (incl. surrounding whitespace), start of the next comment
177 let comment_text = next.text();
178 if let Some(newline_pos) = comment_text.find('\n') {
179 // Special case for multiline comments: join the comment content but
180 // keep the leading `/*`
181
182 let newline_offset = next.syntax().range().start()
183 + TextUnit::from(newline_pos as u32)
184 + TextUnit::of_char('\n');
185
186 edit.insert(newline_offset, "/*".to_string());
187 edit.delete(TextRange::from_to(
188 node.range().start(),
189 next.syntax().range().start() + TextUnit::of_str(next.prefix())
190 ));
191 } else {
192 // Single-line comments
193 edit.delete(TextRange::from_to(
194 node.range().start(),
195 next.syntax().range().start() + TextUnit::of_str(next.prefix())
196 ));
192 } 197 }
198 } else {
199 // Remove newline but add a computed amount of whitespace characters
200 edit.replace(
201 node.range(),
202 compute_ws(prev, next).to_string(),
203 );
193 } 204 }
194
195 // The node is either the first or the last in the file
196 let suff = &node_text[TextRange::from_to(
197 offset - node.range().start() + TextUnit::of_char('\n'),
198 TextUnit::of_str(node_text),
199 )];
200 let spaces = suff.bytes().take_while(|&b| b == b' ').count();
201
202 edit.replace(
203 TextRange::offset_len(offset, ((spaces + 1) as u32).into()),
204 " ".to_string(),
205 );
206} 205}
207 206
208fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { 207fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
@@ -212,13 +211,6 @@ fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
212 } 211 }
213} 212}
214 213
215fn no_space_required(left: SyntaxKind, right: SyntaxKind) -> bool {
216 match (left, right) {
217 (_, DOT) => true,
218 _ => false
219 }
220}
221
222fn join_single_expr_block( 214fn join_single_expr_block(
223 edit: &mut EditBuilder, 215 edit: &mut EditBuilder,
224 node: SyntaxNodeRef, 216 node: SyntaxNodeRef,
@@ -260,6 +252,7 @@ fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str {
260 } 252 }
261 match right.kind() { 253 match right.kind() {
262 R_PAREN | R_BRACK => return "", 254 R_PAREN | R_BRACK => return "",
255 DOT => return "",
263 _ => (), 256 _ => (),
264 } 257 }
265 " " 258 " "