aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api_light
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api_light')
-rw-r--r--crates/ra_ide_api_light/src/join_lines.rs158
-rw-r--r--crates/ra_ide_api_light/src/lib.rs4
2 files changed, 156 insertions, 6 deletions
diff --git a/crates/ra_ide_api_light/src/join_lines.rs b/crates/ra_ide_api_light/src/join_lines.rs
index 970afd327..b5bcd62fb 100644
--- a/crates/ra_ide_api_light/src/join_lines.rs
+++ b/crates/ra_ide_api_light/src/join_lines.rs
@@ -2,8 +2,9 @@ use itertools::Itertools;
2use ra_syntax::{ 2use ra_syntax::{
3 SourceFile, TextRange, TextUnit, AstNode, SyntaxNode, 3 SourceFile, TextRange, TextUnit, AstNode, SyntaxNode,
4 SyntaxKind::{self, WHITESPACE, COMMA, R_CURLY, R_PAREN, R_BRACK}, 4 SyntaxKind::{self, WHITESPACE, COMMA, R_CURLY, R_PAREN, R_BRACK},
5 algo::find_covering_node, 5 algo::{find_covering_node, non_trivia_sibling},
6 ast, 6 ast,
7 Direction,
7}; 8};
8use ra_fmt::{ 9use ra_fmt::{
9 compute_ws, extract_trivial_expression 10 compute_ws, extract_trivial_expression
@@ -120,11 +121,30 @@ fn remove_newline(
120 } 121 }
121} 122}
122 123
124fn has_comma_after(node: &SyntaxNode) -> bool {
125 match non_trivia_sibling(node, Direction::Next) {
126 Some(n) => n.kind() == COMMA,
127 _ => false,
128 }
129}
130
123fn join_single_expr_block(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> { 131fn join_single_expr_block(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> {
124 let block = ast::Block::cast(node.parent()?)?; 132 let block = ast::Block::cast(node.parent()?)?;
125 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; 133 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
126 let expr = extract_trivial_expression(block)?; 134 let expr = extract_trivial_expression(block)?;
127 edit.replace(block_expr.syntax().range(), expr.syntax().text().to_string()); 135
136 let block_range = block_expr.syntax().range();
137 let mut buf = expr.syntax().text().to_string();
138
139 // Match block needs to have a comma after the block
140 if let Some(match_arm) = block_expr.syntax().parent().and_then(ast::MatchArm::cast) {
141 if !has_comma_after(match_arm.syntax()) {
142 buf.push(',');
143 }
144 }
145
146 edit.replace(block_range, buf);
147
128 Some(()) 148 Some(())
129} 149}
130 150
@@ -208,6 +228,140 @@ fn foo() {
208 } 228 }
209 229
210 #[test] 230 #[test]
231 fn join_lines_adds_comma_for_block_in_match_arm() {
232 check_join_lines(
233 r"
234fn foo(e: Result<U, V>) {
235 match e {
236 Ok(u) => <|>{
237 u.foo()
238 }
239 Err(v) => v,
240 }
241}",
242 r"
243fn foo(e: Result<U, V>) {
244 match e {
245 Ok(u) => <|>u.foo(),
246 Err(v) => v,
247 }
248}",
249 );
250 }
251
252 #[test]
253 fn join_lines_keeps_comma_for_block_in_match_arm() {
254 // We already have a comma
255 check_join_lines(
256 r"
257fn foo(e: Result<U, V>) {
258 match e {
259 Ok(u) => <|>{
260 u.foo()
261 },
262 Err(v) => v,
263 }
264}",
265 r"
266fn foo(e: Result<U, V>) {
267 match e {
268 Ok(u) => <|>u.foo(),
269 Err(v) => v,
270 }
271}",
272 );
273
274 // comma with whitespace between brace and ,
275 check_join_lines(
276 r"
277fn foo(e: Result<U, V>) {
278 match e {
279 Ok(u) => <|>{
280 u.foo()
281 } ,
282 Err(v) => v,
283 }
284}",
285 r"
286fn foo(e: Result<U, V>) {
287 match e {
288 Ok(u) => <|>u.foo() ,
289 Err(v) => v,
290 }
291}",
292 );
293
294 // comma with newline between brace and ,
295 check_join_lines(
296 r"
297fn foo(e: Result<U, V>) {
298 match e {
299 Ok(u) => <|>{
300 u.foo()
301 }
302 ,
303 Err(v) => v,
304 }
305}",
306 r"
307fn foo(e: Result<U, V>) {
308 match e {
309 Ok(u) => <|>u.foo()
310 ,
311 Err(v) => v,
312 }
313}",
314 );
315 }
316
317 #[test]
318 fn join_lines_keeps_comma_with_single_arg_tuple() {
319 // A single arg tuple
320 check_join_lines(
321 r"
322fn foo() {
323 let x = (<|>{
324 4
325 },);
326}",
327 r"
328fn foo() {
329 let x = (<|>4,);
330}",
331 );
332
333 // single arg tuple with whitespace between brace and comma
334 check_join_lines(
335 r"
336fn foo() {
337 let x = (<|>{
338 4
339 } ,);
340}",
341 r"
342fn foo() {
343 let x = (<|>4 ,);
344}",
345 );
346
347 // single arg tuple with newline between brace and comma
348 check_join_lines(
349 r"
350fn foo() {
351 let x = (<|>{
352 4
353 }
354 ,);
355}",
356 r"
357fn foo() {
358 let x = (<|>4
359 ,);
360}",
361 );
362 }
363
364 #[test]
211 fn test_join_lines_use_items_left() { 365 fn test_join_lines_use_items_left() {
212 // No space after the '{' 366 // No space after the '{'
213 check_join_lines( 367 check_join_lines(
diff --git a/crates/ra_ide_api_light/src/lib.rs b/crates/ra_ide_api_light/src/lib.rs
index 6d1ce8dbf..43cdd6ea4 100644
--- a/crates/ra_ide_api_light/src/lib.rs
+++ b/crates/ra_ide_api_light/src/lib.rs
@@ -123,10 +123,6 @@ pub fn highlight(root: &SyntaxNode) -> Vec<HighlightedRange> {
123 res 123 res
124} 124}
125 125
126pub fn syntax_tree(file: &SourceFile) -> String {
127 ::ra_syntax::utils::dump_tree(file.syntax())
128}
129
130#[cfg(test)] 126#[cfg(test)]
131mod tests { 127mod tests {
132 use ra_syntax::AstNode; 128 use ra_syntax::AstNode;