aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/diagnostics.rs56
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html4
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs26
-rw-r--r--crates/ra_ide/src/typing.rs38
4 files changed, 71 insertions, 53 deletions
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index bf14a467f..f44feaf69 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -321,29 +321,26 @@ mod tests {
321 fn test_wrap_return_type() { 321 fn test_wrap_return_type() {
322 let before = r#" 322 let before = r#"
323 //- /main.rs 323 //- /main.rs
324 use std::{string::String, result::Result::{self, Ok, Err}}; 324 use core::result::Result::{self, Ok, Err};
325 325
326 fn div(x: i32, y: i32) -> Result<i32, String> { 326 fn div(x: i32, y: i32) -> Result<i32, ()> {
327 if y == 0 { 327 if y == 0 {
328 return Err("div by zero".into()); 328 return Err(());
329 } 329 }
330 x / y<|> 330 x / y<|>
331 } 331 }
332 332
333 //- /std/lib.rs 333 //- /core/lib.rs
334 pub mod string {
335 pub struct String { }
336 }
337 pub mod result { 334 pub mod result {
338 pub enum Result<T, E> { Ok(T), Err(E) } 335 pub enum Result<T, E> { Ok(T), Err(E) }
339 } 336 }
340 "#; 337 "#;
341 let after = r#" 338 let after = r#"
342 use std::{string::String, result::Result::{self, Ok, Err}}; 339 use core::result::Result::{self, Ok, Err};
343 340
344 fn div(x: i32, y: i32) -> Result<i32, String> { 341 fn div(x: i32, y: i32) -> Result<i32, ()> {
345 if y == 0 { 342 if y == 0 {
346 return Err("div by zero".into()); 343 return Err(());
347 } 344 }
348 Ok(x / y) 345 Ok(x / y)
349 } 346 }
@@ -355,7 +352,7 @@ mod tests {
355 fn test_wrap_return_type_handles_generic_functions() { 352 fn test_wrap_return_type_handles_generic_functions() {
356 let before = r#" 353 let before = r#"
357 //- /main.rs 354 //- /main.rs
358 use std::result::Result::{self, Ok, Err}; 355 use core::result::Result::{self, Ok, Err};
359 356
360 fn div<T>(x: T) -> Result<T, i32> { 357 fn div<T>(x: T) -> Result<T, i32> {
361 if x == 0 { 358 if x == 0 {
@@ -364,13 +361,13 @@ mod tests {
364 <|>x 361 <|>x
365 } 362 }
366 363
367 //- /std/lib.rs 364 //- /core/lib.rs
368 pub mod result { 365 pub mod result {
369 pub enum Result<T, E> { Ok(T), Err(E) } 366 pub enum Result<T, E> { Ok(T), Err(E) }
370 } 367 }
371 "#; 368 "#;
372 let after = r#" 369 let after = r#"
373 use std::result::Result::{self, Ok, Err}; 370 use core::result::Result::{self, Ok, Err};
374 371
375 fn div<T>(x: T) -> Result<T, i32> { 372 fn div<T>(x: T) -> Result<T, i32> {
376 if x == 0 { 373 if x == 0 {
@@ -386,32 +383,29 @@ mod tests {
386 fn test_wrap_return_type_handles_type_aliases() { 383 fn test_wrap_return_type_handles_type_aliases() {
387 let before = r#" 384 let before = r#"
388 //- /main.rs 385 //- /main.rs
389 use std::{string::String, result::Result::{self, Ok, Err}}; 386 use core::result::Result::{self, Ok, Err};
390 387
391 type MyResult<T> = Result<T, String>; 388 type MyResult<T> = Result<T, ()>;
392 389
393 fn div(x: i32, y: i32) -> MyResult<i32> { 390 fn div(x: i32, y: i32) -> MyResult<i32> {
394 if y == 0 { 391 if y == 0 {
395 return Err("div by zero".into()); 392 return Err(());
396 } 393 }
397 x <|>/ y 394 x <|>/ y
398 } 395 }
399 396
400 //- /std/lib.rs 397 //- /core/lib.rs
401 pub mod string {
402 pub struct String { }
403 }
404 pub mod result { 398 pub mod result {
405 pub enum Result<T, E> { Ok(T), Err(E) } 399 pub enum Result<T, E> { Ok(T), Err(E) }
406 } 400 }
407 "#; 401 "#;
408 let after = r#" 402 let after = r#"
409 use std::{string::String, result::Result::{self, Ok, Err}}; 403 use core::result::Result::{self, Ok, Err};
410 404
411 type MyResult<T> = Result<T, String>; 405 type MyResult<T> = Result<T, ()>;
412 fn div(x: i32, y: i32) -> MyResult<i32> { 406 fn div(x: i32, y: i32) -> MyResult<i32> {
413 if y == 0 { 407 if y == 0 {
414 return Err("div by zero".into()); 408 return Err(());
415 } 409 }
416 Ok(x / y) 410 Ok(x / y)
417 } 411 }
@@ -423,16 +417,13 @@ mod tests {
423 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { 417 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
424 let content = r#" 418 let content = r#"
425 //- /main.rs 419 //- /main.rs
426 use std::{string::String, result::Result::{self, Ok, Err}}; 420 use core::result::Result::{self, Ok, Err};
427 421
428 fn foo() -> Result<String, i32> { 422 fn foo() -> Result<(), i32> {
429 0<|> 423 0<|>
430 } 424 }
431 425
432 //- /std/lib.rs 426 //- /core/lib.rs
433 pub mod string {
434 pub struct String { }
435 }
436 pub mod result { 427 pub mod result {
437 pub enum Result<T, E> { Ok(T), Err(E) } 428 pub enum Result<T, E> { Ok(T), Err(E) }
438 } 429 }
@@ -444,7 +435,7 @@ mod tests {
444 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { 435 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
445 let content = r#" 436 let content = r#"
446 //- /main.rs 437 //- /main.rs
447 use std::{string::String, result::Result::{self, Ok, Err}}; 438 use core::result::Result::{self, Ok, Err};
448 439
449 enum SomeOtherEnum { 440 enum SomeOtherEnum {
450 Ok(i32), 441 Ok(i32),
@@ -455,10 +446,7 @@ mod tests {
455 0<|> 446 0<|>
456 } 447 }
457 448
458 //- /std/lib.rs 449 //- /core/lib.rs
459 pub mod string {
460 pub struct String { }
461 }
462 pub mod result { 450 pub mod result {
463 pub enum Result<T, E> { Ok(T), Err(E) } 451 pub enum Result<T, E> { Ok(T), Err(E) }
464 } 452 }
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index e34ff5a7d..33548d43c 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
@@ -84,7 +84,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
84 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; 84 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>;
85 <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>; 85 <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>;
86 86
87 <span class="variable mutable">y</span>; 87 <span class="keyword">let</span> <span class="struct">Foo</span> { <span class="field">x</span>: <span class="variable declaration">z</span>, <span class="field">y</span> } = <span class="struct">Foo</span> { <span class="field">x</span>: <span class="variable">z</span>, <span class="field">y</span> };
88
89 <span class="variable">y</span>;
88} 90}
89 91
90<span class="keyword">enum</span> <span class="enum declaration">Option</span>&lt;<span class="type_param declaration">T</span>&gt; { 92<span class="keyword">enum</span> <span class="enum declaration">Option</span>&lt;<span class="type_param declaration">T</span>&gt; {
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index 021f8e7e2..949bf59a0 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -7,18 +7,6 @@ use crate::{
7 FileRange, TextRange, 7 FileRange, TextRange,
8}; 8};
9 9
10/// Highlights the code given by the `ra_fixture` argument, renders the
11/// result as HTML, and compares it with the HTML file given as `snapshot`.
12/// Note that the `snapshot` file is overwritten by the rendered HTML.
13fn check_highlighting(ra_fixture: &str, snapshot: &str, rainbow: bool) {
14 let (analysis, file_id) = single_file(ra_fixture);
15 let dst_file = project_dir().join(snapshot);
16 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
17 let expected_html = &read_text(&dst_file);
18 fs::write(dst_file, &actual_html).unwrap();
19 assert_eq_text!(expected_html, actual_html);
20}
21
22#[test] 10#[test]
23fn test_highlighting() { 11fn test_highlighting() {
24 check_highlighting( 12 check_highlighting(
@@ -77,6 +65,8 @@ fn main() {
77 let y = &mut x; 65 let y = &mut x;
78 let z = &y; 66 let z = &y;
79 67
68 let Foo { x: z, y } = Foo { x: z, y };
69
80 y; 70 y;
81} 71}
82 72
@@ -334,3 +324,15 @@ impl Foo {
334 false, 324 false,
335 ) 325 )
336} 326}
327
328/// Highlights the code given by the `ra_fixture` argument, renders the
329/// result as HTML, and compares it with the HTML file given as `snapshot`.
330/// Note that the `snapshot` file is overwritten by the rendered HTML.
331fn check_highlighting(ra_fixture: &str, snapshot: &str, rainbow: bool) {
332 let (analysis, file_id) = single_file(ra_fixture);
333 let dst_file = project_dir().join(snapshot);
334 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
335 let expected_html = &read_text(&dst_file);
336 fs::write(dst_file, &actual_html).unwrap();
337 assert_eq_text!(expected_html, actual_html);
338}
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs
index 533306e2e..83776d2b6 100644
--- a/crates/ra_ide/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
@@ -21,7 +21,9 @@ use ra_ide_db::{source_change::SourceFileEdit, RootDatabase};
21use ra_syntax::{ 21use ra_syntax::{
22 algo::find_node_at_offset, 22 algo::find_node_at_offset,
23 ast::{self, AstToken}, 23 ast::{self, AstToken},
24 AstNode, SourceFile, TextRange, TextSize, 24 AstNode, SourceFile,
25 SyntaxKind::{FIELD_EXPR, METHOD_CALL_EXPR},
26 TextRange, TextSize,
25}; 27};
26 28
27use ra_text_edit::TextEdit; 29use ra_text_edit::TextEdit;
@@ -98,9 +100,12 @@ fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
98 }; 100 };
99 let current_indent_len = TextSize::of(current_indent); 101 let current_indent_len = TextSize::of(current_indent);
100 102
103 let parent = whitespace.syntax().parent();
101 // Make sure dot is a part of call chain 104 // Make sure dot is a part of call chain
102 let field_expr = ast::FieldExpr::cast(whitespace.syntax().parent())?; 105 if !matches!(parent.kind(), FIELD_EXPR | METHOD_CALL_EXPR) {
103 let prev_indent = leading_indent(field_expr.syntax())?; 106 return None;
107 }
108 let prev_indent = leading_indent(&parent)?;
104 let target_indent = format!(" {}", prev_indent); 109 let target_indent = format!(" {}", prev_indent);
105 let target_indent_len = TextSize::of(&target_indent); 110 let target_indent_len = TextSize::of(&target_indent);
106 if current_indent_len == target_indent_len { 111 if current_indent_len == target_indent_len {
@@ -143,11 +148,11 @@ mod tests {
143 }) 148 })
144 } 149 }
145 150
146 fn type_char(char_typed: char, before: &str, after: &str) { 151 fn type_char(char_typed: char, ra_fixture_before: &str, ra_fixture_after: &str) {
147 let actual = do_type_char(char_typed, before) 152 let actual = do_type_char(char_typed, ra_fixture_before)
148 .unwrap_or_else(|| panic!("typing `{}` did nothing", char_typed)); 153 .unwrap_or_else(|| panic!("typing `{}` did nothing", char_typed));
149 154
150 assert_eq_text!(after, &actual); 155 assert_eq_text!(ra_fixture_after, &actual);
151 } 156 }
152 157
153 fn type_char_noop(char_typed: char, before: &str) { 158 fn type_char_noop(char_typed: char, before: &str) {
@@ -249,6 +254,27 @@ fn foo() {
249 } 254 }
250 255
251 #[test] 256 #[test]
257 fn indents_new_chain_call_with_let() {
258 type_char(
259 '.',
260 r#"
261fn main() {
262 let _ = foo
263 <|>
264 bar()
265}
266"#,
267 r#"
268fn main() {
269 let _ = foo
270 .
271 bar()
272}
273"#,
274 );
275 }
276
277 #[test]
252 fn indents_continued_chain_call() { 278 fn indents_continued_chain_call() {
253 type_char( 279 type_char(
254 '.', 280 '.',