diff options
Diffstat (limited to 'crates/ide/src/diagnostics.rs')
-rw-r--r-- | crates/ide/src/diagnostics.rs | 141 |
1 files changed, 64 insertions, 77 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 049f808dc..79d126ff2 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -199,6 +199,12 @@ fn check_unnecessary_braces_in_use_statement( | |||
199 | ) -> Option<()> { | 199 | ) -> Option<()> { |
200 | let use_tree_list = ast::UseTreeList::cast(node.clone())?; | 200 | let use_tree_list = ast::UseTreeList::cast(node.clone())?; |
201 | if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() { | 201 | if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() { |
202 | // If there is a comment inside the bracketed `use`, | ||
203 | // assume it is a commented out module path and don't show diagnostic. | ||
204 | if use_tree_list.has_inner_comment() { | ||
205 | return Some(()); | ||
206 | } | ||
207 | |||
202 | let use_range = use_tree_list.syntax().text_range(); | 208 | let use_range = use_tree_list.syntax().text_range(); |
203 | let edit = | 209 | let edit = |
204 | text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree) | 210 | text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree) |
@@ -248,35 +254,7 @@ mod tests { | |||
248 | /// * a diagnostic is produced | 254 | /// * a diagnostic is produced |
249 | /// * this diagnostic fix trigger range touches the input cursor position | 255 | /// * this diagnostic fix trigger range touches the input cursor position |
250 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied | 256 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied |
251 | pub(super) fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { | 257 | pub(crate) fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { |
252 | let after = trim_indent(ra_fixture_after); | ||
253 | |||
254 | let (analysis, file_position) = fixture::position(ra_fixture_before); | ||
255 | let diagnostic = analysis | ||
256 | .diagnostics(&DiagnosticsConfig::default(), file_position.file_id) | ||
257 | .unwrap() | ||
258 | .pop() | ||
259 | .unwrap(); | ||
260 | let mut fix = diagnostic.fix.unwrap(); | ||
261 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | ||
262 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); | ||
263 | let actual = { | ||
264 | let mut actual = target_file_contents.to_string(); | ||
265 | edit.apply(&mut actual); | ||
266 | actual | ||
267 | }; | ||
268 | |||
269 | assert_eq_text!(&after, &actual); | ||
270 | assert!( | ||
271 | fix.fix_trigger_range.contains_inclusive(file_position.offset), | ||
272 | "diagnostic fix range {:?} does not touch cursor position {:?}", | ||
273 | fix.fix_trigger_range, | ||
274 | file_position.offset | ||
275 | ); | ||
276 | } | ||
277 | |||
278 | /// Similar to `check_fix`, but applies all the available fixes. | ||
279 | fn check_fixes(ra_fixture_before: &str, ra_fixture_after: &str) { | ||
280 | let after = trim_indent(ra_fixture_after); | 258 | let after = trim_indent(ra_fixture_after); |
281 | 259 | ||
282 | let (analysis, file_position) = fixture::position(ra_fixture_before); | 260 | let (analysis, file_position) = fixture::position(ra_fixture_before); |
@@ -286,10 +264,12 @@ mod tests { | |||
286 | .pop() | 264 | .pop() |
287 | .unwrap(); | 265 | .unwrap(); |
288 | let fix = diagnostic.fix.unwrap(); | 266 | let fix = diagnostic.fix.unwrap(); |
289 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); | ||
290 | let actual = { | 267 | let actual = { |
291 | let mut actual = target_file_contents.to_string(); | 268 | let file_id = fix.source_change.source_file_edits.first().unwrap().file_id; |
269 | let mut actual = analysis.file_text(file_id).unwrap().to_string(); | ||
270 | |||
292 | // Go from the last one to the first one, so that ranges won't be affected by previous edits. | 271 | // Go from the last one to the first one, so that ranges won't be affected by previous edits. |
272 | // FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/4901#issuecomment-644675309 | ||
293 | for edit in fix.source_change.source_file_edits.iter().rev() { | 273 | for edit in fix.source_change.source_file_edits.iter().rev() { |
294 | edit.edit.apply(&mut actual); | 274 | edit.edit.apply(&mut actual); |
295 | } | 275 | } |
@@ -305,29 +285,6 @@ mod tests { | |||
305 | ); | 285 | ); |
306 | } | 286 | } |
307 | 287 | ||
308 | /// Checks that a diagnostic applies to the file containing the `<|>` cursor marker | ||
309 | /// which has a fix that can apply to other files. | ||
310 | fn check_apply_diagnostic_fix_in_other_file(ra_fixture_before: &str, ra_fixture_after: &str) { | ||
311 | let ra_fixture_after = &trim_indent(ra_fixture_after); | ||
312 | let (analysis, file_pos) = fixture::position(ra_fixture_before); | ||
313 | let current_file_id = file_pos.file_id; | ||
314 | let diagnostic = analysis | ||
315 | .diagnostics(&DiagnosticsConfig::default(), current_file_id) | ||
316 | .unwrap() | ||
317 | .pop() | ||
318 | .unwrap(); | ||
319 | let mut fix = diagnostic.fix.unwrap(); | ||
320 | let edit = fix.source_change.source_file_edits.pop().unwrap(); | ||
321 | let changed_file_id = edit.file_id; | ||
322 | let before = analysis.file_text(changed_file_id).unwrap(); | ||
323 | let actual = { | ||
324 | let mut actual = before.to_string(); | ||
325 | edit.edit.apply(&mut actual); | ||
326 | actual | ||
327 | }; | ||
328 | assert_eq_text!(ra_fixture_after, &actual); | ||
329 | } | ||
330 | |||
331 | /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics | 288 | /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics |
332 | /// apply to the file containing the cursor. | 289 | /// apply to the file containing the cursor. |
333 | pub(crate) fn check_no_diagnostics(ra_fixture: &str) { | 290 | pub(crate) fn check_no_diagnostics(ra_fixture: &str) { |
@@ -619,6 +576,7 @@ fn test_fn() { | |||
619 | ), | 576 | ), |
620 | path: "foo.rs", | 577 | path: "foo.rs", |
621 | }, | 578 | }, |
579 | initial_contents: "", | ||
622 | }, | 580 | }, |
623 | ], | 581 | ], |
624 | is_snippet: false, | 582 | is_snippet: false, |
@@ -686,6 +644,22 @@ mod a { | |||
686 | } | 644 | } |
687 | "#, | 645 | "#, |
688 | ); | 646 | ); |
647 | check_no_diagnostics( | ||
648 | r#" | ||
649 | use a; | ||
650 | use a::{ | ||
651 | c, | ||
652 | // d::e | ||
653 | }; | ||
654 | |||
655 | mod a { | ||
656 | mod c {} | ||
657 | mod d { | ||
658 | mod e {} | ||
659 | } | ||
660 | } | ||
661 | "#, | ||
662 | ); | ||
689 | check_fix( | 663 | check_fix( |
690 | r" | 664 | r" |
691 | mod b {} | 665 | mod b {} |
@@ -763,25 +737,25 @@ struct Foo { | |||
763 | 737 | ||
764 | #[test] | 738 | #[test] |
765 | fn test_add_field_in_other_file_from_usage() { | 739 | fn test_add_field_in_other_file_from_usage() { |
766 | check_apply_diagnostic_fix_in_other_file( | 740 | check_fix( |
767 | r" | 741 | r#" |
768 | //- /main.rs | 742 | //- /main.rs |
769 | mod foo; | 743 | mod foo; |
770 | 744 | ||
771 | fn main() { | 745 | fn main() { |
772 | <|>foo::Foo { bar: 3, baz: false}; | 746 | foo::Foo { bar: 3, <|>baz: false}; |
773 | } | 747 | } |
774 | //- /foo.rs | 748 | //- /foo.rs |
775 | struct Foo { | 749 | struct Foo { |
776 | bar: i32 | 750 | bar: i32 |
777 | } | 751 | } |
778 | ", | 752 | "#, |
779 | r" | 753 | r#" |
780 | struct Foo { | 754 | struct Foo { |
781 | bar: i32, | 755 | bar: i32, |
782 | pub(crate) baz: bool | 756 | pub(crate) baz: bool |
783 | } | 757 | } |
784 | ", | 758 | "#, |
785 | ) | 759 | ) |
786 | } | 760 | } |
787 | 761 | ||
@@ -801,7 +775,7 @@ struct Foo { | |||
801 | 775 | ||
802 | #[test] | 776 | #[test] |
803 | fn test_rename_incorrect_case() { | 777 | fn test_rename_incorrect_case() { |
804 | check_fixes( | 778 | check_fix( |
805 | r#" | 779 | r#" |
806 | pub struct test_struct<|> { one: i32 } | 780 | pub struct test_struct<|> { one: i32 } |
807 | 781 | ||
@@ -818,7 +792,7 @@ pub fn some_fn(val: TestStruct) -> TestStruct { | |||
818 | "#, | 792 | "#, |
819 | ); | 793 | ); |
820 | 794 | ||
821 | check_fixes( | 795 | check_fix( |
822 | r#" | 796 | r#" |
823 | pub fn some_fn(NonSnakeCase<|>: u8) -> u8 { | 797 | pub fn some_fn(NonSnakeCase<|>: u8) -> u8 { |
824 | NonSnakeCase | 798 | NonSnakeCase |
@@ -831,7 +805,7 @@ pub fn some_fn(non_snake_case: u8) -> u8 { | |||
831 | "#, | 805 | "#, |
832 | ); | 806 | ); |
833 | 807 | ||
834 | check_fixes( | 808 | check_fix( |
835 | r#" | 809 | r#" |
836 | pub fn SomeFn<|>(val: u8) -> u8 { | 810 | pub fn SomeFn<|>(val: u8) -> u8 { |
837 | if val != 0 { SomeFn(val - 1) } else { val } | 811 | if val != 0 { SomeFn(val - 1) } else { val } |
@@ -844,7 +818,7 @@ pub fn some_fn(val: u8) -> u8 { | |||
844 | "#, | 818 | "#, |
845 | ); | 819 | ); |
846 | 820 | ||
847 | check_fixes( | 821 | check_fix( |
848 | r#" | 822 | r#" |
849 | fn some_fn() { | 823 | fn some_fn() { |
850 | let whatAWeird_Formatting<|> = 10; | 824 | let whatAWeird_Formatting<|> = 10; |
@@ -873,7 +847,7 @@ fn foo() { | |||
873 | 847 | ||
874 | #[test] | 848 | #[test] |
875 | fn test_rename_incorrect_case_struct_method() { | 849 | fn test_rename_incorrect_case_struct_method() { |
876 | check_fixes( | 850 | check_fix( |
877 | r#" | 851 | r#" |
878 | pub struct TestStruct; | 852 | pub struct TestStruct; |
879 | 853 | ||
@@ -894,4 +868,17 @@ impl TestStruct { | |||
894 | "#, | 868 | "#, |
895 | ); | 869 | ); |
896 | } | 870 | } |
871 | |||
872 | #[test] | ||
873 | fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() { | ||
874 | let input = r#"fn FOO<|>() {}"#; | ||
875 | let expected = r#"fn foo() {}"#; | ||
876 | |||
877 | let (analysis, file_position) = fixture::position(input); | ||
878 | let diagnostics = | ||
879 | analysis.diagnostics(&DiagnosticsConfig::default(), file_position.file_id).unwrap(); | ||
880 | assert_eq!(diagnostics.len(), 1); | ||
881 | |||
882 | check_fix(input, expected); | ||
883 | } | ||
897 | } | 884 | } |