diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-06-13 18:35:03 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-13 18:35:03 +0100 |
commit | 2ad78924621420cb323efdeb3d875ca3f47d940f (patch) | |
tree | eb34ec6e46f8a15b015e62dc404773a938e45819 /crates/ide/src/diagnostics.rs | |
parent | 60ca03e8aa00956d1511969da5f1844a02483bc9 (diff) | |
parent | b66f4bb8d1748b83a6f4c5edc3c77a46b213e1c2 (diff) |
Merge #9253
9253: internal: refactor missing or or some diagnostic r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ide/src/diagnostics.rs')
-rw-r--r-- | crates/ide/src/diagnostics.rs | 191 |
1 files changed, 7 insertions, 184 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 4c92d0cf4..814e64ae4 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -9,8 +9,11 @@ mod inactive_code; | |||
9 | mod macro_error; | 9 | mod macro_error; |
10 | mod mismatched_arg_count; | 10 | mod mismatched_arg_count; |
11 | mod missing_fields; | 11 | mod missing_fields; |
12 | mod missing_ok_or_some_in_tail_expr; | ||
12 | mod missing_unsafe; | 13 | mod missing_unsafe; |
13 | mod no_such_field; | 14 | mod no_such_field; |
15 | mod remove_this_semicolon; | ||
16 | mod replace_filter_map_next_with_find_map; | ||
14 | mod unimplemented_builtin_macro; | 17 | mod unimplemented_builtin_macro; |
15 | mod unresolved_extern_crate; | 18 | mod unresolved_extern_crate; |
16 | mod unresolved_import; | 19 | mod unresolved_import; |
@@ -162,18 +165,9 @@ pub(crate) fn diagnostics( | |||
162 | } | 165 | } |
163 | let res = RefCell::new(res); | 166 | let res = RefCell::new(res); |
164 | let sink_builder = DiagnosticSinkBuilder::new() | 167 | let sink_builder = DiagnosticSinkBuilder::new() |
165 | .on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| { | ||
166 | res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); | ||
167 | }) | ||
168 | .on::<hir::diagnostics::RemoveThisSemicolon, _>(|d| { | ||
169 | res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); | ||
170 | }) | ||
171 | .on::<hir::diagnostics::IncorrectCase, _>(|d| { | 168 | .on::<hir::diagnostics::IncorrectCase, _>(|d| { |
172 | res.borrow_mut().push(warning_with_fix(d, &sema, resolve)); | 169 | res.borrow_mut().push(warning_with_fix(d, &sema, resolve)); |
173 | }) | 170 | }) |
174 | .on::<hir::diagnostics::ReplaceFilterMapNextWithFindMap, _>(|d| { | ||
175 | res.borrow_mut().push(warning_with_fix(d, &sema, resolve)); | ||
176 | }) | ||
177 | .on::<UnlinkedFile, _>(|d| { | 171 | .on::<UnlinkedFile, _>(|d| { |
178 | // Limit diagnostic to the first few characters in the file. This matches how VS Code | 172 | // Limit diagnostic to the first few characters in the file. This matches how VS Code |
179 | // renders it with the full span, but on other editors, and is less invasive. | 173 | // renders it with the full span, but on other editors, and is less invasive. |
@@ -223,10 +217,13 @@ pub(crate) fn diagnostics( | |||
223 | let d = match diag { | 217 | let d = match diag { |
224 | AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d), | 218 | AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d), |
225 | AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d), | 219 | AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d), |
220 | AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d), | ||
226 | AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), | 221 | AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), |
222 | AnyDiagnostic::MissingOkOrSomeInTailExpr(d) => missing_ok_or_some_in_tail_expr::missing_ok_or_some_in_tail_expr(&ctx, &d), | ||
227 | AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d), | 223 | AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d), |
228 | AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d), | ||
229 | AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d), | 224 | AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d), |
225 | AnyDiagnostic::RemoveThisSemicolon(d) => remove_this_semicolon::remove_this_semicolon(&ctx, &d), | ||
226 | AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d), | ||
230 | AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d), | 227 | AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d), |
231 | AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d), | 228 | AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d), |
232 | AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d), | 229 | AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d), |
@@ -253,16 +250,6 @@ pub(crate) fn diagnostics( | |||
253 | res | 250 | res |
254 | } | 251 | } |
255 | 252 | ||
256 | fn diagnostic_with_fix<D: DiagnosticWithFixes>( | ||
257 | d: &D, | ||
258 | sema: &Semantics<RootDatabase>, | ||
259 | resolve: &AssistResolveStrategy, | ||
260 | ) -> Diagnostic { | ||
261 | Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) | ||
262 | .with_fixes(d.fixes(sema, resolve)) | ||
263 | .with_code(Some(d.code())) | ||
264 | } | ||
265 | |||
266 | fn warning_with_fix<D: DiagnosticWithFixes>( | 253 | fn warning_with_fix<D: DiagnosticWithFixes>( |
267 | d: &D, | 254 | d: &D, |
268 | sema: &Semantics<RootDatabase>, | 255 | sema: &Semantics<RootDatabase>, |
@@ -449,39 +436,6 @@ mod tests { | |||
449 | } | 436 | } |
450 | 437 | ||
451 | #[test] | 438 | #[test] |
452 | fn range_mapping_out_of_macros() { | ||
453 | // FIXME: this is very wrong, but somewhat tricky to fix. | ||
454 | check_fix( | ||
455 | r#" | ||
456 | fn some() {} | ||
457 | fn items() {} | ||
458 | fn here() {} | ||
459 | |||
460 | macro_rules! id { ($($tt:tt)*) => { $($tt)*}; } | ||
461 | |||
462 | fn main() { | ||
463 | let _x = id![Foo { a: $042 }]; | ||
464 | } | ||
465 | |||
466 | pub struct Foo { pub a: i32, pub b: i32 } | ||
467 | "#, | ||
468 | r#" | ||
469 | fn some(, b: () ) {} | ||
470 | fn items() {} | ||
471 | fn here() {} | ||
472 | |||
473 | macro_rules! id { ($($tt:tt)*) => { $($tt)*}; } | ||
474 | |||
475 | fn main() { | ||
476 | let _x = id![Foo { a: 42 }]; | ||
477 | } | ||
478 | |||
479 | pub struct Foo { pub a: i32, pub b: i32 } | ||
480 | "#, | ||
481 | ); | ||
482 | } | ||
483 | |||
484 | #[test] | ||
485 | fn test_check_unnecessary_braces_in_use_statement() { | 439 | fn test_check_unnecessary_braces_in_use_statement() { |
486 | check_diagnostics( | 440 | check_diagnostics( |
487 | r#" | 441 | r#" |
@@ -717,137 +671,6 @@ mod foo; | |||
717 | ); | 671 | ); |
718 | } | 672 | } |
719 | 673 | ||
720 | // Register the required standard library types to make the tests work | ||
721 | fn add_filter_map_with_find_next_boilerplate(body: &str) -> String { | ||
722 | let prefix = r#" | ||
723 | //- /main.rs crate:main deps:core | ||
724 | use core::iter::Iterator; | ||
725 | use core::option::Option::{self, Some, None}; | ||
726 | "#; | ||
727 | let suffix = r#" | ||
728 | //- /core/lib.rs crate:core | ||
729 | pub mod option { | ||
730 | pub enum Option<T> { Some(T), None } | ||
731 | } | ||
732 | pub mod iter { | ||
733 | pub trait Iterator { | ||
734 | type Item; | ||
735 | fn filter_map<B, F>(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option<B> { FilterMap } | ||
736 | fn next(&mut self) -> Option<Self::Item>; | ||
737 | } | ||
738 | pub struct FilterMap {} | ||
739 | impl Iterator for FilterMap { | ||
740 | type Item = i32; | ||
741 | fn next(&mut self) -> i32 { 7 } | ||
742 | } | ||
743 | } | ||
744 | "#; | ||
745 | format!("{}{}{}", prefix, body, suffix) | ||
746 | } | ||
747 | |||
748 | #[test] | ||
749 | fn replace_filter_map_next_with_find_map2() { | ||
750 | check_diagnostics(&add_filter_map_with_find_next_boilerplate( | ||
751 | r#" | ||
752 | fn foo() { | ||
753 | let m = [1, 2, 3].iter().filter_map(|x| if *x == 2 { Some (4) } else { None }).next(); | ||
754 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ replace filter_map(..).next() with find_map(..) | ||
755 | } | ||
756 | "#, | ||
757 | )); | ||
758 | } | ||
759 | |||
760 | #[test] | ||
761 | fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() { | ||
762 | check_diagnostics(&add_filter_map_with_find_next_boilerplate( | ||
763 | r#" | ||
764 | fn foo() { | ||
765 | let m = [1, 2, 3] | ||
766 | .iter() | ||
767 | .filter_map(|x| if *x == 2 { Some (4) } else { None }) | ||
768 | .len(); | ||
769 | } | ||
770 | "#, | ||
771 | )); | ||
772 | } | ||
773 | |||
774 | #[test] | ||
775 | fn replace_filter_map_next_with_find_map_no_diagnostic_with_intervening_methods() { | ||
776 | check_diagnostics(&add_filter_map_with_find_next_boilerplate( | ||
777 | r#" | ||
778 | fn foo() { | ||
779 | let m = [1, 2, 3] | ||
780 | .iter() | ||
781 | .filter_map(|x| if *x == 2 { Some (4) } else { None }) | ||
782 | .map(|x| x + 2) | ||
783 | .len(); | ||
784 | } | ||
785 | "#, | ||
786 | )); | ||
787 | } | ||
788 | |||
789 | #[test] | ||
790 | fn replace_filter_map_next_with_find_map_no_diagnostic_if_not_in_chain() { | ||
791 | check_diagnostics(&add_filter_map_with_find_next_boilerplate( | ||
792 | r#" | ||
793 | fn foo() { | ||
794 | let m = [1, 2, 3] | ||
795 | .iter() | ||
796 | .filter_map(|x| if *x == 2 { Some (4) } else { None }); | ||
797 | let n = m.next(); | ||
798 | } | ||
799 | "#, | ||
800 | )); | ||
801 | } | ||
802 | |||
803 | #[test] | ||
804 | fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() { | ||
805 | check_diagnostics( | ||
806 | r" | ||
807 | struct S { foo: i32, bar: () } | ||
808 | fn baz(s: S) -> i32 { | ||
809 | match s { | ||
810 | S { foo, .. } => foo, | ||
811 | } | ||
812 | } | ||
813 | ", | ||
814 | ) | ||
815 | } | ||
816 | |||
817 | #[test] | ||
818 | fn missing_record_pat_field_box() { | ||
819 | check_diagnostics( | ||
820 | r" | ||
821 | struct S { s: Box<u32> } | ||
822 | fn x(a: S) { | ||
823 | let S { box s } = a; | ||
824 | } | ||
825 | ", | ||
826 | ) | ||
827 | } | ||
828 | |||
829 | #[test] | ||
830 | fn missing_record_pat_field_ref() { | ||
831 | check_diagnostics( | ||
832 | r" | ||
833 | struct S { s: u32 } | ||
834 | fn x(a: S) { | ||
835 | let S { ref s } = a; | ||
836 | } | ||
837 | ", | ||
838 | ) | ||
839 | } | ||
840 | |||
841 | #[test] | ||
842 | fn missing_semicolon() { | ||
843 | check_diagnostics( | ||
844 | r#" | ||
845 | fn test() -> i32 { 123; } | ||
846 | //^^^ Remove this semicolon | ||
847 | "#, | ||
848 | ); | ||
849 | } | ||
850 | |||
851 | #[test] | 674 | #[test] |
852 | fn import_extern_crate_clash_with_inner_item() { | 675 | fn import_extern_crate_clash_with_inner_item() { |
853 | // This is more of a resolver test, but doesn't really work with the hir_def testsuite. | 676 | // This is more of a resolver test, but doesn't really work with the hir_def testsuite. |