aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/tests.rs')
-rw-r--r--crates/ra_hir_ty/src/tests.rs436
1 files changed, 28 insertions, 408 deletions
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index eeac34d14..45bc14c37 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -10,6 +10,7 @@ mod display_source_code;
10 10
11use std::sync::Arc; 11use std::sync::Arc;
12 12
13use expect::Expect;
13use hir_def::{ 14use hir_def::{
14 body::{BodySourceMap, SyntheticSyntax}, 15 body::{BodySourceMap, SyntheticSyntax},
15 child_by_source::ChildBySource, 16 child_by_source::ChildBySource,
@@ -20,8 +21,7 @@ use hir_def::{
20 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, 21 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
21}; 22};
22use hir_expand::{db::AstDatabase, InFile}; 23use hir_expand::{db::AstDatabase, InFile};
23use insta::assert_snapshot; 24use ra_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt};
24use ra_db::{fixture::WithFixture, salsa::Database, FileRange, SourceDatabase};
25use ra_syntax::{ 25use ra_syntax::{
26 algo, 26 algo,
27 ast::{self, AstNode}, 27 ast::{self, AstNode},
@@ -34,8 +34,21 @@ use crate::{
34}; 34};
35 35
36// These tests compare the inference results for all expressions in a file 36// These tests compare the inference results for all expressions in a file
37// against snapshots of the expected results using insta. Use cargo-insta to 37// against snapshots of the expected results using expect. Use
38// update the snapshots. 38// `env UPDATE_EXPECT=1 cargo test -p ra_hir_ty` to update the snapshots.
39
40fn setup_tracing() -> tracing::subscriber::DefaultGuard {
41 use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
42 use tracing_tree::HierarchicalLayer;
43 let filter = EnvFilter::from_env("CHALK_DEBUG");
44 let layer = HierarchicalLayer::default()
45 .with_indent_lines(true)
46 .with_ansi(false)
47 .with_indent_amount(2)
48 .with_writer(std::io::stderr);
49 let subscriber = Registry::default().with(filter).with(layer);
50 tracing::subscriber::set_default(subscriber)
51}
39 52
40fn check_types(ra_fixture: &str) { 53fn check_types(ra_fixture: &str) {
41 check_types_impl(ra_fixture, false) 54 check_types_impl(ra_fixture, false)
@@ -46,6 +59,7 @@ fn check_types_source_code(ra_fixture: &str) {
46} 59}
47 60
48fn check_types_impl(ra_fixture: &str, display_source: bool) { 61fn check_types_impl(ra_fixture: &str, display_source: bool) {
62 let _tracing = setup_tracing();
49 let db = TestDB::with_files(ra_fixture); 63 let db = TestDB::with_files(ra_fixture);
50 let mut checked_one = false; 64 let mut checked_one = false;
51 for (file_id, annotations) in db.extract_annotations() { 65 for (file_id, annotations) in db.extract_annotations() {
@@ -86,6 +100,7 @@ fn infer(ra_fixture: &str) -> String {
86} 100}
87 101
88fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { 102fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
103 let _tracing = setup_tracing();
89 let (db, file_id) = TestDB::with_single_file(content); 104 let (db, file_id) = TestDB::with_single_file(content);
90 105
91 let mut buf = String::new(); 106 let mut buf = String::new();
@@ -317,7 +332,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
317 " 332 "
318 .to_string(); 333 .to_string();
319 334
320 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text)); 335 db.set_file_text(pos.file_id, Arc::new(new_text));
321 336
322 { 337 {
323 let events = db.log_executed(|| { 338 let events = db.log_executed(|| {
@@ -331,409 +346,14 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
331 } 346 }
332} 347}
333 348
334#[test] 349fn check_infer(ra_fixture: &str, expect: Expect) {
335fn no_such_field_diagnostics() { 350 let mut actual = infer(ra_fixture);
336 let diagnostics = TestDB::with_files( 351 actual.push('\n');
337 r" 352 expect.assert_eq(&actual);
338 //- /lib.rs
339 struct S { foo: i32, bar: () }
340 impl S {
341 fn new() -> S {
342 S {
343 foo: 92,
344 baz: 62,
345 }
346 }
347 }
348 ",
349 )
350 .diagnostics()
351 .0;
352
353 assert_snapshot!(diagnostics, @r###"
354 "baz: 62": no such field
355 "{\n foo: 92,\n baz: 62,\n }": Missing structure fields:
356 - bar
357 "###
358 );
359}
360
361#[test]
362fn no_such_field_with_feature_flag_diagnostics() {
363 let diagnostics = TestDB::with_files(
364 r#"
365 //- /lib.rs crate:foo cfg:feature=foo
366 struct MyStruct {
367 my_val: usize,
368 #[cfg(feature = "foo")]
369 bar: bool,
370 }
371
372 impl MyStruct {
373 #[cfg(feature = "foo")]
374 pub(crate) fn new(my_val: usize, bar: bool) -> Self {
375 Self { my_val, bar }
376 }
377
378 #[cfg(not(feature = "foo"))]
379 pub(crate) fn new(my_val: usize, _bar: bool) -> Self {
380 Self { my_val }
381 }
382 }
383 "#,
384 )
385 .diagnostics()
386 .0;
387
388 assert_snapshot!(diagnostics, @r###""###);
389}
390
391#[test]
392fn no_such_field_enum_with_feature_flag_diagnostics() {
393 let diagnostics = TestDB::with_files(
394 r#"
395 //- /lib.rs crate:foo cfg:feature=foo
396 enum Foo {
397 #[cfg(not(feature = "foo"))]
398 Buz,
399 #[cfg(feature = "foo")]
400 Bar,
401 Baz
402 }
403
404 fn test_fn(f: Foo) {
405 match f {
406 Foo::Bar => {},
407 Foo::Baz => {},
408 }
409 }
410 "#,
411 )
412 .diagnostics()
413 .0;
414
415 assert_snapshot!(diagnostics, @r###""###);
416}
417
418#[test]
419fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() {
420 let diagnostics = TestDB::with_files(
421 r#"
422 //- /lib.rs crate:foo cfg:feature=foo
423 struct S {
424 #[cfg(feature = "foo")]
425 foo: u32,
426 #[cfg(not(feature = "foo"))]
427 bar: u32,
428 }
429
430 impl S {
431 #[cfg(feature = "foo")]
432 fn new(foo: u32) -> Self {
433 Self { foo }
434 }
435 #[cfg(not(feature = "foo"))]
436 fn new(bar: u32) -> Self {
437 Self { bar }
438 }
439 }
440 "#,
441 )
442 .diagnostics()
443 .0;
444
445 assert_snapshot!(diagnostics, @r###""###);
446}
447
448#[test]
449fn no_such_field_with_feature_flag_diagnostics_on_block_expr() {
450 let diagnostics = TestDB::with_files(
451 r#"
452 //- /lib.rs crate:foo cfg:feature=foo
453 struct S {
454 #[cfg(feature = "foo")]
455 foo: u32,
456 #[cfg(not(feature = "foo"))]
457 bar: u32,
458 }
459
460 impl S {
461 fn new(bar: u32) -> Self {
462 #[cfg(feature = "foo")]
463 {
464 Self { foo: bar }
465 }
466 #[cfg(not(feature = "foo"))]
467 {
468 Self { bar }
469 }
470 }
471 }
472 "#,
473 )
474 .diagnostics()
475 .0;
476
477 assert_snapshot!(diagnostics, @r###""###);
478}
479
480#[test]
481fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() {
482 let diagnostics = TestDB::with_files(
483 r#"
484 //- /lib.rs crate:foo cfg:feature=foo
485 struct S {
486 #[cfg(feature = "foo")]
487 foo: u32,
488 #[cfg(not(feature = "foo"))]
489 bar: u32,
490 }
491
492 impl S {
493 fn new(val: u32) -> Self {
494 Self {
495 #[cfg(feature = "foo")]
496 foo: val,
497 #[cfg(not(feature = "foo"))]
498 bar: val,
499 }
500 }
501 }
502 "#,
503 )
504 .diagnostics()
505 .0;
506
507 assert_snapshot!(diagnostics, @r###""###);
508}
509
510#[test]
511fn no_such_field_with_type_macro() {
512 let diagnostics = TestDB::with_files(
513 r"
514 macro_rules! Type {
515 () => { u32 };
516 }
517
518 struct Foo {
519 bar: Type![],
520 }
521 impl Foo {
522 fn new() -> Self {
523 Foo { bar: 0 }
524 }
525 }
526 ",
527 )
528 .diagnostics()
529 .0;
530
531 assert_snapshot!(diagnostics, @r###""###);
532} 353}
533 354
534#[test] 355fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) {
535fn missing_record_pat_field_diagnostic() { 356 let mut actual = infer_with_mismatches(ra_fixture, true);
536 let diagnostics = TestDB::with_files( 357 actual.push('\n');
537 r" 358 expect.assert_eq(&actual);
538 //- /lib.rs
539 struct S { foo: i32, bar: () }
540 fn baz(s: S) {
541 let S { foo: _ } = s;
542 }
543 ",
544 )
545 .diagnostics()
546 .0;
547
548 assert_snapshot!(diagnostics, @r###"
549 "{ foo: _ }": Missing structure fields:
550 - bar
551 "###
552 );
553}
554
555#[test]
556fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
557 let diagnostics = TestDB::with_files(
558 r"
559 //- /lib.rs
560 struct S { foo: i32, bar: () }
561 fn baz(s: S) -> i32 {
562 match s {
563 S { foo, .. } => foo,
564 }
565 }
566 ",
567 )
568 .diagnostics()
569 .0;
570
571 assert_snapshot!(diagnostics, @"");
572}
573
574#[test]
575fn missing_unsafe_diagnostic_with_raw_ptr() {
576 let diagnostics = TestDB::with_files(
577 r"
578//- /lib.rs
579fn missing_unsafe() {
580 let x = &5 as *const usize;
581 let y = *x;
582}
583",
584 )
585 .diagnostics()
586 .0;
587
588 assert_snapshot!(diagnostics, @r#""*x": This operation is unsafe and requires an unsafe function or block"#);
589}
590
591#[test]
592fn missing_unsafe_diagnostic_with_unsafe_call() {
593 let diagnostics = TestDB::with_files(
594 r"
595//- /lib.rs
596unsafe fn unsafe_fn() {
597 let x = &5 as *const usize;
598 let y = *x;
599}
600
601fn missing_unsafe() {
602 unsafe_fn();
603}
604",
605 )
606 .diagnostics()
607 .0;
608
609 assert_snapshot!(diagnostics, @r#""unsafe_fn()": This operation is unsafe and requires an unsafe function or block"#);
610}
611
612#[test]
613fn missing_unsafe_diagnostic_with_unsafe_method_call() {
614 let diagnostics = TestDB::with_files(
615 r"
616struct HasUnsafe;
617
618impl HasUnsafe {
619 unsafe fn unsafe_fn(&self) {
620 let x = &5 as *const usize;
621 let y = *x;
622 }
623}
624
625fn missing_unsafe() {
626 HasUnsafe.unsafe_fn();
627}
628
629",
630 )
631 .diagnostics()
632 .0;
633
634 assert_snapshot!(diagnostics, @r#""HasUnsafe.unsafe_fn()": This operation is unsafe and requires an unsafe function or block"#);
635}
636
637#[test]
638fn no_missing_unsafe_diagnostic_with_raw_ptr_in_unsafe_block() {
639 let diagnostics = TestDB::with_files(
640 r"
641fn nothing_to_see_move_along() {
642 let x = &5 as *const usize;
643 unsafe {
644 let y = *x;
645 }
646}
647",
648 )
649 .diagnostics()
650 .0;
651
652 assert_snapshot!(diagnostics, @"");
653}
654
655#[test]
656fn missing_unsafe_diagnostic_with_raw_ptr_outside_unsafe_block() {
657 let diagnostics = TestDB::with_files(
658 r"
659fn nothing_to_see_move_along() {
660 let x = &5 as *const usize;
661 unsafe {
662 let y = *x;
663 }
664 let z = *x;
665}
666",
667 )
668 .diagnostics()
669 .0;
670
671 assert_snapshot!(diagnostics, @r#""*x": This operation is unsafe and requires an unsafe function or block"#);
672}
673
674#[test]
675fn no_missing_unsafe_diagnostic_with_unsafe_call_in_unsafe_block() {
676 let diagnostics = TestDB::with_files(
677 r"
678unsafe fn unsafe_fn() {
679 let x = &5 as *const usize;
680 let y = *x;
681}
682
683fn nothing_to_see_move_along() {
684 unsafe {
685 unsafe_fn();
686 }
687}
688",
689 )
690 .diagnostics()
691 .0;
692
693 assert_snapshot!(diagnostics, @"");
694}
695
696#[test]
697fn no_missing_unsafe_diagnostic_with_unsafe_method_call_in_unsafe_block() {
698 let diagnostics = TestDB::with_files(
699 r"
700struct HasUnsafe;
701
702impl HasUnsafe {
703 unsafe fn unsafe_fn() {
704 let x = &5 as *const usize;
705 let y = *x;
706 }
707}
708
709fn nothing_to_see_move_along() {
710 unsafe {
711 HasUnsafe.unsafe_fn();
712 }
713}
714
715",
716 )
717 .diagnostics()
718 .0;
719
720 assert_snapshot!(diagnostics, @"");
721}
722
723#[test]
724fn break_outside_of_loop() {
725 let diagnostics = TestDB::with_files(
726 r"
727 //- /lib.rs
728 fn foo() {
729 break;
730 }
731 ",
732 )
733 .diagnostics()
734 .0;
735
736 assert_snapshot!(diagnostics, @r###""break": break outside of loop
737 "###
738 );
739} 359}