From af6984f6a6fad56f24345c03d018ac29549b169d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 14 Jul 2020 12:05:50 +0200 Subject: Data-driven diagnostics tests --- crates/ra_hir_ty/src/diagnostics.rs | 22 ++++ crates/ra_hir_ty/src/diagnostics/expr.rs | 169 +++++++++++++------------------ crates/ra_hir_ty/src/test_db.rs | 2 +- 3 files changed, 93 insertions(+), 100 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 3623b8569..49a616c6f 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -244,3 +244,25 @@ impl AstDiagnostic for MismatchedArgCount { ast::CallExpr::cast(node).unwrap() } } + +#[cfg(test)] +fn check_diagnostics(ra_fixture: &str) { + use ra_db::{fixture::WithFixture, FileId}; + use ra_syntax::TextRange; + use rustc_hash::FxHashMap; + + use crate::test_db::TestDB; + + let db = TestDB::with_files(ra_fixture); + let annotations = db.extract_annotations(); + + let mut actual: FxHashMap> = FxHashMap::default(); + db.diag(|d| { + // FXIME: macros... + let file_id = d.source().file_id.original_file(&db); + let range = d.syntax_node(&db).text_range(); + actual.entry(file_id).or_default().push((range, d.message().to_owned())); + }); + + assert_eq!(annotations, actual); +} diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs index 239be779f..277ace180 100644 --- a/crates/ra_hir_ty/src/diagnostics/expr.rs +++ b/crates/ra_hir_ty/src/diagnostics/expr.rs @@ -376,146 +376,117 @@ pub fn record_pattern_missing_fields( #[cfg(test)] mod tests { - use expect::{expect, Expect}; - use ra_db::fixture::WithFixture; - - use crate::{diagnostics::MismatchedArgCount, test_db::TestDB}; - - fn check_diagnostic(ra_fixture: &str, expect: Expect) { - let msg = TestDB::with_single_file(ra_fixture).0.diagnostic::().0; - expect.assert_eq(&msg); - } - - fn check_no_diagnostic(ra_fixture: &str) { - let (s, diagnostic_count) = - TestDB::with_single_file(ra_fixture).0.diagnostic::(); - - assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s); - } + use crate::diagnostics::check_diagnostics; #[test] fn simple_free_fn_zero() { - check_diagnostic( - r" - fn zero() {} - fn f() { zero(1); } - ", - expect![["\"zero(1)\": Expected 0 arguments, found 1\n"]], + check_diagnostics( + r#" +fn zero() {} +fn f() { zero(1); } + //^^^^^^^ Expected 0 arguments, found 1 +"#, ); - check_no_diagnostic( - r" - fn zero() {} - fn f() { zero(); } - ", + check_diagnostics( + r#" +fn zero() {} +fn f() { zero(); } +"#, ); } #[test] fn simple_free_fn_one() { - check_diagnostic( - r" - fn one(arg: u8) {} - fn f() { one(); } - ", - expect![["\"one()\": Expected 1 argument, found 0\n"]], + check_diagnostics( + r#" +fn one(arg: u8) {} +fn f() { one(); } + //^^^^^ Expected 1 argument, found 0 +"#, ); - check_no_diagnostic( - r" - fn one(arg: u8) {} - fn f() { one(1); } - ", + check_diagnostics( + r#" +fn one(arg: u8) {} +fn f() { one(1); } +"#, ); } #[test] fn method_as_fn() { - check_diagnostic( - r" - struct S; - impl S { - fn method(&self) {} - } - - fn f() { - S::method(); - } - ", - expect![["\"S::method()\": Expected 1 argument, found 0\n"]], + check_diagnostics( + r#" +struct S; +impl S { fn method(&self) {} } + +fn f() { + S::method(); +} //^^^^^^^^^^^ Expected 1 argument, found 0 +"#, ); - check_no_diagnostic( - r" - struct S; - impl S { - fn method(&self) {} - } + check_diagnostics( + r#" +struct S; +impl S { fn method(&self) {} } - fn f() { - S::method(&S); - S.method(); - } - ", +fn f() { + S::method(&S); + S.method(); +} +"#, ); } #[test] fn method_with_arg() { - check_diagnostic( - r" - struct S; - impl S { - fn method(&self, arg: u8) {} - } + check_diagnostics( + r#" +struct S; +impl S { fn method(&self, arg: u8) {} } fn f() { S.method(); - } - ", - expect![["\"S.method()\": Expected 1 argument, found 0\n"]], + } //^^^^^^^^^^ Expected 1 argument, found 0 + "#, ); - check_no_diagnostic( - r" - struct S; - impl S { - fn method(&self, arg: u8) {} - } + check_diagnostics( + r#" +struct S; +impl S { fn method(&self, arg: u8) {} } - fn f() { - S::method(&S, 0); - S.method(1); - } - ", +fn f() { + S::method(&S, 0); + S.method(1); +} +"#, ); } #[test] fn tuple_struct() { - check_diagnostic( - r" - struct Tup(u8, u16); - fn f() { - Tup(0); - } - ", - expect![["\"Tup(0)\": Expected 2 arguments, found 1\n"]], + check_diagnostics( + r#" +struct Tup(u8, u16); +fn f() { + Tup(0); +} //^^^^^^ Expected 2 arguments, found 1 +"#, ) } #[test] fn enum_variant() { - check_diagnostic( - r" - enum En { - Variant(u8, u16), - } - fn f() { - En::Variant(0); - } - ", - expect![["\"En::Variant(0)\": Expected 2 arguments, found 1\n"]], + check_diagnostics( + r#" +enum En { Variant(u8, u16), } +fn f() { + En::Variant(0); +} //^^^^^^^^^^^^^^ Expected 2 arguments, found 1 +"#, ) } } diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index ddafd0ea1..0bd29f435 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -94,7 +94,7 @@ impl TestDB { panic!("Can't find module for file") } - fn diag(&self, mut cb: F) { + pub(crate) fn diag(&self, mut cb: F) { let crate_graph = self.crate_graph(); for krate in crate_graph.iter() { let crate_def_map = self.crate_def_map(krate); -- cgit v1.2.3 From b031899dac6ad5847cc2f5551766a567657f095d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 14 Jul 2020 13:10:09 +0200 Subject: Compress match checking tests --- crates/ra_hir_ty/src/diagnostics.rs | 5 +- crates/ra_hir_ty/src/diagnostics/match_check.rs | 1561 ++++++----------------- crates/ra_hir_ty/src/test_db.rs | 21 +- 3 files changed, 419 insertions(+), 1168 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 49a616c6f..3016ca3bd 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -261,8 +261,11 @@ fn check_diagnostics(ra_fixture: &str) { // FXIME: macros... let file_id = d.source().file_id.original_file(&db); let range = d.syntax_node(&db).text_range(); - actual.entry(file_id).or_default().push((range, d.message().to_owned())); + // FIXME: support multi-line messages in annotations + let message = d.message().lines().next().unwrap().to_owned(); + actual.entry(file_id).or_default().push((range, message)); }); + actual.values_mut().for_each(|diags| diags.sort_by_key(|it| it.0.start())); assert_eq!(annotations, actual); } diff --git a/crates/ra_hir_ty/src/diagnostics/match_check.rs b/crates/ra_hir_ty/src/diagnostics/match_check.rs index 899025a87..ba48b51b5 100644 --- a/crates/ra_hir_ty/src/diagnostics/match_check.rs +++ b/crates/ra_hir_ty/src/diagnostics/match_check.rs @@ -41,9 +41,9 @@ //! ```ignore //! // x: (Option, Result<()>) //! match x { -//! (Some(true), _) => {} -//! (None, Err(())) => {} -//! (None, Err(_)) => {} +//! (Some(true), _) => (), +//! (None, Err(())) => (), +//! (None, Err(_)) => (), //! } //! ``` //! @@ -837,685 +837,251 @@ fn enum_variant_matches(cx: &MatchCheckCtx, pat_id: PatId, enum_variant_id: Enum #[cfg(test)] mod tests { - use insta::assert_snapshot; - use ra_db::fixture::WithFixture; - - use crate::{diagnostics::MissingMatchArms, test_db::TestDB}; - - fn check_diagnostic_message(ra_fixture: &str) -> String { - TestDB::with_single_file(ra_fixture).0.diagnostic::().0 - } - - fn check_diagnostic(ra_fixture: &str) { - let diagnostic_count = - TestDB::with_single_file(ra_fixture).0.diagnostic::().1; - - assert_eq!(1, diagnostic_count, "no diagnostic reported"); - } - - fn check_no_diagnostic(ra_fixture: &str) { - let (s, diagnostic_count) = - TestDB::with_single_file(ra_fixture).0.diagnostic::(); - - assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s); - } - - #[test] - fn empty_tuple_no_arms_diagnostic_message() { - assert_snapshot!( - check_diagnostic_message(r" - fn test_fn() { - match () { - } - } - "), - @"\"()\": Missing match arm\n" - ); - } - - #[test] - fn empty_tuple_no_arms() { - check_diagnostic( - r" - fn test_fn() { - match () { - } - } - ", - ); - } - - #[test] - fn empty_tuple_wild() { - check_no_diagnostic( - r" - fn test_fn() { - match () { - _ => {} - } - } - ", - ); - } + use crate::diagnostics::check_diagnostics; #[test] - fn empty_tuple_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match () { - () => {} - } - } - ", - ); - } - - #[test] - fn tuple_of_empty_tuple_no_arms() { - check_diagnostic( - r" - fn test_fn() { - match (()) { - } - } - ", - ); - } + fn empty_tuple() { + check_diagnostics( + r#" +fn main() { + match () { } + //^^ Missing match arm + match (()) { } + //^^^^ Missing match arm - #[test] - fn tuple_of_empty_tuple_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (()) { - (()) => {} - } - } - ", - ); - } - - #[test] - fn tuple_of_two_empty_tuple_no_arms() { - check_diagnostic( - r" - fn test_fn() { - match ((), ()) { - } - } - ", - ); - } - - #[test] - fn tuple_of_two_empty_tuple_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match ((), ()) { - ((), ()) => {} - } - } - ", - ); - } - - #[test] - fn bool_no_arms() { - check_diagnostic( - r" - fn test_fn() { - match false { - } - } - ", - ); - } - - #[test] - fn bool_missing_arm() { - check_diagnostic( - r" - fn test_fn() { - match false { - true => {} - } - } - ", - ); - } - - #[test] - fn bool_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match false { - true => {} - false => {} - } - } - ", - ); - } - - #[test] - fn tuple_of_bools_no_arms() { - check_diagnostic( - r" - fn test_fn() { - match (false, true) { - } - } - ", - ); - } - - #[test] - fn tuple_of_bools_missing_arms() { - check_diagnostic( - r" - fn test_fn() { - match (false, true) { - (true, true) => {}, - } - } - ", - ); - } - - #[test] - fn tuple_of_bools_missing_arm() { - check_diagnostic( - r" - fn test_fn() { - match (false, true) { - (false, true) => {}, - (false, false) => {}, - (true, false) => {}, - } - } - ", - ); - } - - #[test] - fn tuple_of_bools_with_wilds() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, true) { - (false, _) => {}, - (true, false) => {}, - (_, true) => {}, - } - } - ", + match () { _ => (), } + match () { () => (), } + match (()) { (()) => (), } +} +"#, ); } #[test] - fn tuple_of_bools_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, true) { - (true, true) => {}, - (true, false) => {}, - (false, true) => {}, - (false, false) => {}, - } - } - ", - ); - } + fn tuple_of_two_empty_tuple() { + check_diagnostics( + r#" +fn main() { + match ((), ()) { } + //^^^^^^^^ Missing match arm - #[test] - fn tuple_of_bools_binding_missing_arms() { - check_diagnostic( - r" - fn test_fn() { - match (false, true) { - (true, _x) => {}, - } - } - ", - ); - } - - #[test] - fn tuple_of_bools_binding_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, true) { - (true, _x) => {}, - (false, true) => {}, - (false, false) => {}, - } - } - ", + match ((), ()) { ((), ()) => (), } +} +"#, + ); + } + + #[test] + fn boolean() { + check_diagnostics( + r#" +fn test_main() { + match false { } + //^^^^^ Missing match arm + match false { true => (), } + //^^^^^ Missing match arm + match (false, true) {} + //^^^^^^^^^^^^^ Missing match arm + match (false, true) { (true, true) => (), } + //^^^^^^^^^^^^^ Missing match arm + match (false, true) { + //^^^^^^^^^^^^^ Missing match arm + (false, true) => (), + (false, false) => (), + (true, false) => (), + } + match (false, true) { (true, _x) => (), } + //^^^^^^^^^^^^^ Missing match arm + + match false { true => (), false => (), } + match (false, true) { + (false, _) => (), + (true, false) => (), + (_, true) => (), + } + match (false, true) { + (true, true) => (), + (true, false) => (), + (false, true) => (), + (false, false) => (), + } + match (false, true) { + (true, _x) => (), + (false, true) => (), + (false, false) => (), + } + match (false, true, false) { + (false, ..) => (), + (true, ..) => (), + } + match (false, true, false) { + (.., false) => (), + (.., true) => (), + } + match (false, true, false) { (..) => (), } +} +"#, ); } #[test] - fn tuple_of_bools_with_ellipsis_at_end_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, true, false) { - (false, ..) => {}, - (true, ..) => {}, - } - } - ", - ); - } + fn tuple_of_tuple_and_bools() { + check_diagnostics( + r#" +fn main() { + match (false, ((), false)) {} + //^^^^^^^^^^^^^^^^^^^^ Missing match arm + match (false, ((), false)) { (true, ((), true)) => (), } + //^^^^^^^^^^^^^^^^^^^^ Missing match arm + match (false, ((), false)) { (true, _) => (), } + //^^^^^^^^^^^^^^^^^^^^ Missing match arm - #[test] - fn tuple_of_bools_with_ellipsis_at_beginning_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, true, false) { - (.., false) => {}, - (.., true) => {}, - } - } - ", - ); + match (false, ((), false)) { + (true, ((), true)) => (), + (true, ((), false)) => (), + (false, ((), true)) => (), + (false, ((), false)) => (), } - - #[test] - fn tuple_of_bools_with_ellipsis_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, true, false) { - (..) => {}, - } - } - ", - ); + match (false, ((), false)) { + (true, ((), true)) => (), + (true, ((), false)) => (), + (false, _) => (), } - - #[test] - fn tuple_of_tuple_and_bools_no_arms() { - check_diagnostic( - r" - fn test_fn() { - match (false, ((), false)) { - } - } - ", +} +"#, ); } #[test] - fn tuple_of_tuple_and_bools_missing_arms() { - check_diagnostic( - r" - fn test_fn() { - match (false, ((), false)) { - (true, ((), true)) => {}, - } - } - ", - ); - } + fn enums() { + check_diagnostics( + r#" +enum Either { A, B, } - #[test] - fn tuple_of_tuple_and_bools_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, ((), false)) { - (true, ((), true)) => {}, - (true, ((), false)) => {}, - (false, ((), true)) => {}, - (false, ((), false)) => {}, - } - } - ", - ); - } +fn main() { + match Either::A { } + //^^^^^^^^^ Missing match arm + match Either::B { Either::A => (), } + //^^^^^^^^^ Missing match arm - #[test] - fn tuple_of_tuple_and_bools_wildcard_missing_arms() { - check_diagnostic( - r" - fn test_fn() { - match (false, ((), false)) { - (true, _) => {}, - } - } - ", - ); + match &Either::B { + //^^^^^^^^^^ Missing match arm + Either::A => (), } - #[test] - fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() { - check_no_diagnostic( - r" - fn test_fn() { - match (false, ((), false)) { - (true, ((), true)) => {}, - (true, ((), false)) => {}, - (false, _) => {}, - } - } - ", - ); + match Either::B { + Either::A => (), Either::B => (), } - - #[test] - fn enum_no_arms() { - check_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match Either::A { - } - } - ", - ); + match &Either::B { + Either::A => (), Either::B => (), } - - #[test] - fn enum_missing_arms() { - check_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match Either::B { - Either::A => {}, - } - } - ", +} +"#, ); } #[test] - fn enum_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match Either::B { - Either::A => {}, - Either::B => {}, - } - } - ", - ); - } + fn enum_containing_bool() { + check_diagnostics( + r#" +enum Either { A(bool), B } - #[test] - fn enum_ref_missing_arms() { - check_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match &Either::B { - Either::A => {}, - } - } - ", - ); +fn main() { + match Either::B { } + //^^^^^^^^^ Missing match arm + match Either::B { + //^^^^^^^^^ Missing match arm + Either::A(true) => (), Either::B => () } - #[test] - fn enum_ref_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match &Either::B { - Either::A => {}, - Either::B => {}, - } - } - ", - ); + match Either::B { + Either::A(true) => (), + Either::A(false) => (), + Either::B => (), } - - #[test] - fn enum_containing_bool_no_arms() { - check_diagnostic( - r" - enum Either { - A(bool), - B, - } - fn test_fn() { - match Either::B { - } - } - ", - ); + match Either::B { + Either::B => (), + _ => (), } - - #[test] - fn enum_containing_bool_missing_arms() { - check_diagnostic( - r" - enum Either { - A(bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(true) => (), - Either::B => (), - } - } - ", - ); + match Either::B { + Either::A(_) => (), + Either::B => (), } - #[test] - fn enum_containing_bool_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(true) => (), - Either::A(false) => (), - Either::B => (), - } - } - ", +} + "#, ); } #[test] - fn enum_containing_bool_with_wild_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool), - B, - } - fn test_fn() { - match Either::B { - Either::B => (), - _ => (), - } - } - ", - ); - } + fn enum_different_sizes() { + check_diagnostics( + r#" +enum Either { A(bool), B(bool, bool) } - #[test] - fn enum_containing_bool_with_wild_2_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(_) => (), - Either::B => (), - } - } - ", - ); +fn main() { + match Either::A(false) { + //^^^^^^^^^^^^^^^^ Missing match arm + Either::A(_) => (), + Either::B(false, _) => (), } - #[test] - fn enum_different_sizes_missing_arms() { - check_diagnostic( - r" - enum Either { - A(bool), - B(bool, bool), - } - fn test_fn() { - match Either::A(false) { - Either::A(_) => (), - Either::B(false, _) => (), - } - } - ", - ); + match Either::A(false) { + Either::A(_) => (), + Either::B(true, _) => (), + Either::B(false, _) => (), } - - #[test] - fn enum_different_sizes_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool), - B(bool, bool), - } - fn test_fn() { - match Either::A(false) { - Either::A(_) => (), - Either::B(true, _) => (), - Either::B(false, _) => (), - } - } - ", - ); + match Either::A(false) { + Either::A(true) | Either::A(false) => (), + Either::B(true, _) => (), + Either::B(false, _) => (), } - - #[test] - fn or_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool), - B(bool, bool), - } - fn test_fn() { - match Either::A(false) { - Either::A(true) | Either::A(false) => (), - Either::B(true, _) => (), - Either::B(false, _) => (), - } - } - ", +} +"#, ); } #[test] fn tuple_of_enum_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool), - B(bool, bool), - } - enum Either2 { - C, - D, - } - fn test_fn() { - match (Either::A(false), Either2::C) { - (Either::A(true), _) | (Either::A(false), _) => (), - (Either::B(true, _), Either2::C) => (), - (Either::B(false, _), Either2::C) => (), - (Either::B(_, _), Either2::D) => (), - } - } - ", - ); + check_diagnostics( + r#" +enum Either { A(bool), B(bool, bool) } +enum Either2 { C, D } + +fn main() { + match (Either::A(false), Either2::C) { + (Either::A(true), _) | (Either::A(false), _) => (), + (Either::B(true, _), Either2::C) => (), + (Either::B(false, _), Either2::C) => (), + (Either::B(_, _), Either2::D) => (), } - - #[test] - fn mismatched_types() { - // Match statements with arms that don't match the - // expression pattern do not fire this diagnostic. - check_no_diagnostic( - r" - enum Either { - A, - B, - } - enum Either2 { - C, - D, - } - fn test_fn() { - match Either::A { - Either2::C => (), - Either2::D => (), - } - } - ", - ); - } - - #[test] - fn mismatched_types_with_different_arity() { - // Match statements with arms that don't match the - // expression pattern do not fire this diagnostic. - check_no_diagnostic( - r" - fn test_fn() { - match (true, false) { - (true, false, true) => (), - (true) => (), - } - } - ", +} +"#, ); } #[test] - fn malformed_match_arm_tuple_missing_pattern() { + fn mismatched_types() { // Match statements with arms that don't match the // expression pattern do not fire this diagnostic. - check_no_diagnostic( - r" - fn test_fn() { - match (0) { - () => (), - } - } - ", + check_diagnostics( + r#" +enum Either { A, B } +enum Either2 { C, D } + +fn main() { + match Either::A { + Either2::C => (), + Either2::D => (), + } + match (true, false) { + (true, false, true) => (), + (true) => (), + } + match (0) { () => () } + match Unresolved::Bar { Unresolved::Baz => () } +} + "#, ); } @@ -1523,517 +1089,247 @@ mod tests { fn malformed_match_arm_tuple_enum_missing_pattern() { // We are testing to be sure we don't panic here when the match // arm `Either::B` is missing its pattern. - check_no_diagnostic( - r" - enum Either { - A, - B(u32), - } - fn test_fn() { - match Either::A { - Either::A => (), - Either::B() => (), - } - } - ", - ); - } + check_diagnostics( + r#" +enum Either { A, B(u32) } - #[test] - fn enum_not_in_scope() { - // The enum is not in scope so we don't perform exhaustiveness - // checking, but we want to be sure we don't panic here (and - // we don't create a diagnostic). - check_no_diagnostic( - r" - fn test_fn() { - match Foo::Bar { - Foo::Baz => (), - } - } - ", +fn main() { + match Either::A { + Either::A => (), + Either::B() => (), + } +} +"#, ); } #[test] fn expr_diverges() { - check_no_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match loop {} { - Either::A => (), - Either::B => (), - } - } - ", - ); - } + check_diagnostics( + r#" +enum Either { A, B } - #[test] - fn expr_loop_with_break() { - check_no_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match loop { break Foo::A } { - Either::A => (), - Either::B => (), - } - } - ", +fn main() { + match loop {} { + Either::A => (), + Either::B => (), + } + match loop {} { + Either::A => (), + } + match loop { break Foo::A } { + //^^^^^^^^^^^^^^^^^^^^^ Missing match arm + Either::A => (), + } + match loop { break Foo::A } { + Either::A => (), + Either::B => (), + } +} +"#, ); } #[test] fn expr_partially_diverges() { - check_no_diagnostic( - r" - enum Either { - A(T), - B, - } - fn foo() -> Either { - Either::B - } - fn test_fn() -> u32 { - match foo() { - Either::A(val) => val, - Either::B => 0, - } - } - ", - ); - } + check_diagnostics( + r#" +enum Either { A(T), B } - #[test] - fn enum_record_no_arms() { - check_diagnostic( - r" - enum Either { - A { foo: bool }, - B, - } - fn test_fn() { - let a = Either::A { foo: true }; - match a { - } - } - ", - ); +fn foo() -> Either { Either::B } +fn main() -> u32 { + match foo() { + Either::A(val) => val, + Either::B => 0, } - - #[test] - fn enum_record_missing_arms() { - check_diagnostic( - r" - enum Either { - A { foo: bool }, - B, - } - fn test_fn() { - let a = Either::A { foo: true }; - match a { - Either::A { foo: true } => (), - } - } - ", +} +"#, ); } #[test] - fn enum_record_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A { foo: bool }, - B, - } - fn test_fn() { - let a = Either::A { foo: true }; - match a { - Either::A { foo: true } => (), - Either::A { foo: false } => (), - Either::B => (), - } - } - ", - ); - } + fn enum_record() { + check_diagnostics( + r#" +enum Either { A { foo: bool }, B } - #[test] - fn enum_record_missing_field_no_diagnostic() { - // When `Either::A` is missing a struct member, we don't want - // to fire the missing match arm diagnostic. This should fire - // some other diagnostic. - check_no_diagnostic( - r" - enum Either { - A { foo: bool }, - B, - } - fn test_fn() { - let a = Either::B; - match a { - Either::A { } => (), - Either::B => (), - } - } - ", - ); +fn main() { + let a = Either::A { foo: true }; + match a { } + //^ Missing match arm + match a { Either::A { foo: true } => () } + //^ Missing match arm + match a { + Either::A { } => (), + //^^^ Missing structure fields: + Either::B => (), } + match a { + //^ Missing match arm + Either::A { } => (), + } //^^^ Missing structure fields: - #[test] - fn enum_record_missing_field_missing_match_arm() { - // Even though `Either::A` is missing fields, we still want to fire - // the missing arm diagnostic here, since we know `Either::B` is missing. - check_diagnostic( - r" - enum Either { - A { foo: bool }, - B, - } - fn test_fn() { - let a = Either::B; - match a { - Either::A { } => (), - } - } - ", - ); + match a { + Either::A { foo: true } => (), + Either::A { foo: false } => (), + Either::B => (), } - - #[test] - fn enum_record_no_diagnostic_wild() { - check_no_diagnostic( - r" - enum Either { - A { foo: bool }, - B, - } - fn test_fn() { - let a = Either::A { foo: true }; - match a { - Either::A { foo: _ } => (), - Either::B => (), - } - } - ", - ); + match a { + Either::A { foo: _ } => (), + Either::B => (), } - - #[test] - fn enum_record_fields_out_of_order_missing_arm() { - check_diagnostic( - r" - enum Either { - A { foo: bool, bar: () }, - B, - } - fn test_fn() { - let a = Either::A { foo: true }; - match a { - Either::A { bar: (), foo: false } => (), - Either::A { foo: true, bar: () } => (), - } - } - ", +} +"#, ); } #[test] - fn enum_record_fields_out_of_order_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A { foo: bool, bar: () }, - B, - } - fn test_fn() { - let a = Either::A { foo: true }; - match a { - Either::A { bar: (), foo: false } => (), - Either::A { foo: true, bar: () } => (), - Either::B => (), - } - } - ", - ); - } + fn enum_record_fields_out_of_order() { + check_diagnostics( + r#" +enum Either { + A { foo: bool, bar: () }, + B, +} - #[test] - fn enum_record_ellipsis_missing_arm() { - check_diagnostic( - r" - enum Either { - A { foo: bool, bar: bool }, - B, - } - fn test_fn() { - match Either::B { - Either::A { foo: true, .. } => (), - Either::B => (), - } - } - ", - ); +fn main() { + let a = Either::A { foo: true, bar: () }; + match a { + //^ Missing match arm + Either::A { bar: (), foo: false } => (), + Either::A { foo: true, bar: () } => (), } - #[test] - fn enum_record_ellipsis_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A { foo: bool, bar: bool }, - B, - } - fn test_fn() { - let a = Either::A { foo: true }; - match a { - Either::A { foo: true, .. } => (), - Either::A { foo: false, .. } => (), - Either::B => (), - } - } - ", - ); + match a { + Either::A { bar: (), foo: false } => (), + Either::A { foo: true, bar: () } => (), + Either::B => (), } - - #[test] - fn enum_record_ellipsis_all_fields_missing_arm() { - check_diagnostic( - r" - enum Either { - A { foo: bool, bar: bool }, - B, - } - fn test_fn() { - let a = Either::B; - match a { - Either::A { .. } => (), - } - } - ", +} +"#, ); } #[test] - fn enum_record_ellipsis_all_fields_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A { foo: bool, bar: bool }, - B, - } - fn test_fn() { - let a = Either::B; - match a { - Either::A { .. } => (), - Either::B => (), - } - } - ", - ); - } + fn enum_record_ellipsis() { + check_diagnostics( + r#" +enum Either { + A { foo: bool, bar: bool }, + B, +} - #[test] - fn enum_tuple_partial_ellipsis_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool, bool, bool, bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(true, .., true) => {}, - Either::A(true, .., false) => {}, - Either::A(false, .., true) => {}, - Either::A(false, .., false) => {}, - Either::B => {}, - } - } - ", - ); +fn main() { + let a = Either::B; + match a { + //^ Missing match arm + Either::A { foo: true, .. } => (), + Either::B => (), } - - #[test] - fn enum_tuple_partial_ellipsis_2_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool, bool, bool, bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(true, .., true) => {}, - Either::A(true, .., false) => {}, - Either::A(.., true) => {}, - Either::A(.., false) => {}, - Either::B => {}, - } - } - ", - ); + match a { + //^ Missing match arm + Either::A { .. } => (), } - #[test] - fn enum_tuple_partial_ellipsis_missing_arm() { - check_diagnostic( - r" - enum Either { - A(bool, bool, bool, bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(true, .., true) => {}, - Either::A(true, .., false) => {}, - Either::A(false, .., false) => {}, - Either::B => {}, - } - } - ", - ); + match a { + Either::A { foo: true, .. } => (), + Either::A { foo: false, .. } => (), + Either::B => (), } - #[test] - fn enum_tuple_partial_ellipsis_2_missing_arm() { - check_diagnostic( - r" - enum Either { - A(bool, bool, bool, bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(true, .., true) => {}, - Either::A(true, .., false) => {}, - Either::A(.., true) => {}, - Either::B => {}, - } - } - ", - ); + match a { + Either::A { .. } => (), + Either::B => (), } - - #[test] - fn enum_tuple_ellipsis_no_diagnostic() { - check_no_diagnostic( - r" - enum Either { - A(bool, bool, bool, bool), - B, - } - fn test_fn() { - match Either::B { - Either::A(..) => {}, - Either::B => {}, - } - } - ", +} +"#, ); } #[test] - fn enum_never() { - check_no_diagnostic( - r" - enum Never {} + fn enum_tuple_partial_ellipsis() { + check_diagnostics( + r#" +enum Either { + A(bool, bool, bool, bool), + B, +} - fn test_fn(never: Never) { - match never {} - } - ", - ); +fn main() { + match Either::B { + //^^^^^^^^^ Missing match arm + Either::A(true, .., true) => (), + Either::A(true, .., false) => (), + Either::A(false, .., false) => (), + Either::B => (), + } + match Either::B { + //^^^^^^^^^ Missing match arm + Either::A(true, .., true) => (), + Either::A(true, .., false) => (), + Either::A(.., true) => (), + Either::B => (), + } + + match Either::B { + Either::A(true, .., true) => (), + Either::A(true, .., false) => (), + Either::A(false, .., true) => (), + Either::A(false, .., false) => (), + Either::B => (), + } + match Either::B { + Either::A(true, .., true) => (), + Either::A(true, .., false) => (), + Either::A(.., true) => (), + Either::A(.., false) => (), + Either::B => (), } - - #[test] - fn type_never() { - check_no_diagnostic( - r" - fn test_fn(never: !) { - match never {} - } - ", +} +"#, ); } #[test] - fn enum_never_ref() { - check_no_diagnostic( - r" - enum Never {} + fn never() { + check_diagnostics( + r#" +enum Never {} - fn test_fn(never: &Never) { - match never {} - } - ", - ); - } - - #[test] - fn expr_diverges_missing_arm() { - check_no_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match loop {} { - Either::A => (), - } - } - ", +fn enum_(never: Never) { + match never {} +} +fn enum_ref(never: &Never) { + match never {} +} +fn bang(never: !) { + match never {} +} +"#, ); } #[test] fn or_pattern_panic() { - check_no_diagnostic( - r" - pub enum Category { - Infinity, - Zero, - } + check_diagnostics( + r#" +pub enum Category { Infinity, Zero } - fn panic(a: Category, b: Category) { - match (a, b) { - (Category::Zero | Category::Infinity, _) => {} - (_, Category::Zero | Category::Infinity) => {} - } - } - ", - ); +fn panic(a: Category, b: Category) { + match (a, b) { + (Category::Zero | Category::Infinity, _) => (), + (_, Category::Zero | Category::Infinity) => (), } - #[test] - fn or_pattern_panic_2() { - // FIXME: This is a false positive, but the code used to cause a panic in the match checker, - // so this acts as a regression test for that. - check_diagnostic( - r" - pub enum Category { - Infinity, - Zero, - } - - fn panic(a: Category, b: Category) { - match (a, b) { - (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => {} - - (Category::Infinity | Category::Zero, _) => {} - } - } - ", + // FIXME: This is a false positive, but the code used to cause a panic in the match checker, + // so this acts as a regression test for that. + match (a, b) { + //^^^^^^ Missing match arm + (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => (), + (Category::Infinity | Category::Zero, _) => (), + } +} +"#, ); } @@ -2051,105 +1347,72 @@ mod tests { #[test] fn integers() { - // This is a false negative. // We don't currently check integer exhaustiveness. - check_no_diagnostic( - r" - fn test_fn() { - match 5 { - 10 => (), - 11..20 => (), - } - } - ", + check_diagnostics( + r#" +fn main() { + match 5 { + 10 => (), + 11..20 => (), + } +} +"#, ); } #[test] fn internal_or() { - // This is a false negative. // We do not currently handle patterns with internal `or`s. - check_no_diagnostic( - r" - fn test_fn() { - enum Either { - A(bool), - B, - } - match Either::B { - Either::A(true | false) => (), - } - } - ", - ); - } - - #[test] - fn expr_loop_missing_arm() { - // This is a false negative. - // We currently infer the type of `loop { break Foo::A }` to `!`, which - // causes us to skip the diagnostic since `Either::A` doesn't type check - // with `!`. - check_diagnostic( - r" - enum Either { - A, - B, - } - fn test_fn() { - match loop { break Foo::A } { - Either::A => (), - } - } - ", + check_diagnostics( + r#" +fn main() { + enum Either { A(bool), B } + match Either::B { + Either::A(true | false) => (), + } +} +"#, ); } #[test] fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { - // This is a false negative. // We don't currently handle tuple patterns with ellipsis. - check_no_diagnostic( - r" - fn test_fn() { - match (false, true, false) { - (false, ..) => {}, - } - } - ", + check_diagnostics( + r#" +fn main() { + match (false, true, false) { + (false, ..) => (), + } +} +"#, ); } #[test] fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { - // This is a false negative. // We don't currently handle tuple patterns with ellipsis. - check_no_diagnostic( - r" - fn test_fn() { - match (false, true, false) { - (.., false) => {}, - } - } - ", + check_diagnostics( + r#" +fn main() { + match (false, true, false) { + (.., false) => (), + } +} +"#, ); } #[test] fn struct_missing_arm() { - // This is a false negative. // We don't currently handle structs. - check_no_diagnostic( - r" - struct Foo { - a: bool, - } - fn test_fn(f: Foo) { - match f { - Foo { a: true } => {}, - } - } - ", + check_diagnostics( + r#" +struct Foo { a: bool } +fn main(f: Foo) { + match f { Foo { a: true } => () } +} +"#, ); } } diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 0bd29f435..fb8723fb7 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -82,7 +82,7 @@ impl FileLoader for TestDB { } impl TestDB { - pub fn module_for_file(&self, file_id: FileId) -> ModuleId { + pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { for &krate in self.relevant_crates(file_id).iter() { let crate_def_map = self.crate_def_map(krate); for (local_id, data) in crate_def_map.modules.iter() { @@ -124,7 +124,7 @@ impl TestDB { } } - pub fn diagnostics(&self) -> (String, u32) { + pub(crate) fn diagnostics(&self) -> (String, u32) { let mut buf = String::new(); let mut count = 0; self.diag(|d| { @@ -134,22 +134,7 @@ impl TestDB { (buf, count) } - /// Like `diagnostics`, but filtered for a single diagnostic. - pub fn diagnostic(&self) -> (String, u32) { - let mut buf = String::new(); - let mut count = 0; - self.diag(|d| { - // We want to filter diagnostics by the particular one we are testing for, to - // avoid surprising results in tests. - if d.downcast_ref::().is_some() { - format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message()); - count += 1; - }; - }); - (buf, count) - } - - pub fn extract_annotations(&self) -> FxHashMap> { + pub(crate) fn extract_annotations(&self) -> FxHashMap> { let mut files = Vec::new(); let crate_graph = self.crate_graph(); for krate in crate_graph.iter() { -- cgit v1.2.3