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.rs118
1 files changed, 41 insertions, 77 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 3ad30f0c9..038273750 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -248,35 +248,7 @@ mod tests {
248 /// * a diagnostic is produced 248 /// * a diagnostic is produced
249 /// * this diagnostic fix trigger range touches the input cursor position 249 /// * 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 250 /// * 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) { 251 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); 252 let after = trim_indent(ra_fixture_after);
281 253
282 let (analysis, file_position) = fixture::position(ra_fixture_before); 254 let (analysis, file_position) = fixture::position(ra_fixture_before);
@@ -286,10 +258,12 @@ mod tests {
286 .pop() 258 .pop()
287 .unwrap(); 259 .unwrap();
288 let fix = diagnostic.fix.unwrap(); 260 let fix = diagnostic.fix.unwrap();
289 let target_file_contents = analysis.file_text(file_position.file_id).unwrap();
290 let actual = { 261 let actual = {
291 let mut actual = target_file_contents.to_string(); 262 let file_id = fix.source_change.source_file_edits.first().unwrap().file_id;
263 let mut actual = analysis.file_text(file_id).unwrap().to_string();
264
292 // Go from the last one to the first one, so that ranges won't be affected by previous edits. 265 // Go from the last one to the first one, so that ranges won't be affected by previous edits.
266 // FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/4901#issuecomment-644675309
293 for edit in fix.source_change.source_file_edits.iter().rev() { 267 for edit in fix.source_change.source_file_edits.iter().rev() {
294 edit.edit.apply(&mut actual); 268 edit.edit.apply(&mut actual);
295 } 269 }
@@ -305,29 +279,6 @@ mod tests {
305 ); 279 );
306 } 280 }
307 281
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 282 /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
332 /// apply to the file containing the cursor. 283 /// apply to the file containing the cursor.
333 pub(crate) fn check_no_diagnostics(ra_fixture: &str) { 284 pub(crate) fn check_no_diagnostics(ra_fixture: &str) {
@@ -764,25 +715,25 @@ struct Foo {
764 715
765 #[test] 716 #[test]
766 fn test_add_field_in_other_file_from_usage() { 717 fn test_add_field_in_other_file_from_usage() {
767 check_apply_diagnostic_fix_in_other_file( 718 check_fix(
768 r" 719 r#"
769 //- /main.rs 720//- /main.rs
770 mod foo; 721mod foo;
771 722
772 fn main() { 723fn main() {
773 <|>foo::Foo { bar: 3, baz: false}; 724 foo::Foo { bar: 3, <|>baz: false};
774 } 725}
775 //- /foo.rs 726//- /foo.rs
776 struct Foo { 727struct Foo {
777 bar: i32 728 bar: i32
778 } 729}
779 ", 730"#,
780 r" 731 r#"
781 struct Foo { 732struct Foo {
782 bar: i32, 733 bar: i32,
783 pub(crate) baz: bool 734 pub(crate) baz: bool
784 } 735}
785 ", 736"#,
786 ) 737 )
787 } 738 }
788 739
@@ -802,7 +753,7 @@ struct Foo {
802 753
803 #[test] 754 #[test]
804 fn test_rename_incorrect_case() { 755 fn test_rename_incorrect_case() {
805 check_fixes( 756 check_fix(
806 r#" 757 r#"
807pub struct test_struct<|> { one: i32 } 758pub struct test_struct<|> { one: i32 }
808 759
@@ -819,7 +770,7 @@ pub fn some_fn(val: TestStruct) -> TestStruct {
819"#, 770"#,
820 ); 771 );
821 772
822 check_fixes( 773 check_fix(
823 r#" 774 r#"
824pub fn some_fn(NonSnakeCase<|>: u8) -> u8 { 775pub fn some_fn(NonSnakeCase<|>: u8) -> u8 {
825 NonSnakeCase 776 NonSnakeCase
@@ -832,7 +783,7 @@ pub fn some_fn(non_snake_case: u8) -> u8 {
832"#, 783"#,
833 ); 784 );
834 785
835 check_fixes( 786 check_fix(
836 r#" 787 r#"
837pub fn SomeFn<|>(val: u8) -> u8 { 788pub fn SomeFn<|>(val: u8) -> u8 {
838 if val != 0 { SomeFn(val - 1) } else { val } 789 if val != 0 { SomeFn(val - 1) } else { val }
@@ -845,7 +796,7 @@ pub fn some_fn(val: u8) -> u8 {
845"#, 796"#,
846 ); 797 );
847 798
848 check_fixes( 799 check_fix(
849 r#" 800 r#"
850fn some_fn() { 801fn some_fn() {
851 let whatAWeird_Formatting<|> = 10; 802 let whatAWeird_Formatting<|> = 10;
@@ -874,7 +825,7 @@ fn foo() {
874 825
875 #[test] 826 #[test]
876 fn test_rename_incorrect_case_struct_method() { 827 fn test_rename_incorrect_case_struct_method() {
877 check_fixes( 828 check_fix(
878 r#" 829 r#"
879pub struct TestStruct; 830pub struct TestStruct;
880 831
@@ -895,4 +846,17 @@ impl TestStruct {
895"#, 846"#,
896 ); 847 );
897 } 848 }
849
850 #[test]
851 fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() {
852 let input = r#"fn FOO<|>() {}"#;
853 let expected = r#"fn foo() {}"#;
854
855 let (analysis, file_position) = fixture::position(input);
856 let diagnostics =
857 analysis.diagnostics(&DiagnosticsConfig::default(), file_position.file_id).unwrap();
858 assert_eq!(diagnostics.len(), 1);
859
860 check_fix(input, expected);
861 }
898} 862}