aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/diagnostics.rs')
-rw-r--r--crates/ide/src/diagnostics.rs141
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#"
649use a;
650use a::{
651 c,
652 // d::e
653};
654
655mod 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; 743mod foo;
770 744
771 fn main() { 745fn 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 { 749struct Foo {
776 bar: i32 750 bar: i32
777 } 751}
778 ", 752"#,
779 r" 753 r#"
780 struct Foo { 754struct 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#"
806pub struct test_struct<|> { one: i32 } 780pub 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#"
823pub fn some_fn(NonSnakeCase<|>: u8) -> u8 { 797pub 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#"
836pub fn SomeFn<|>(val: u8) -> u8 { 810pub 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#"
849fn some_fn() { 823fn 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#"
878pub struct TestStruct; 852pub 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}