aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock53
-rw-r--r--crates/ra_assists/src/doc_tests.rs7
-rw-r--r--crates/ra_assists/src/lib.rs40
-rw-r--r--crates/ra_assists/src/test_db.rs45
-rw-r--r--crates/ra_cli/Cargo.toml2
-rw-r--r--crates/ra_hir/src/code_model.rs4
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/expr/scope.rs8
-rw-r--r--crates/ra_hir/src/lib.rs9
-rw-r--r--crates/ra_hir/src/mock.rs262
-rw-r--r--crates/ra_hir/src/test_db.rs120
-rw-r--r--crates/ra_hir/src/ty.rs2
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs6
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs4
-rw-r--r--crates/ra_hir/src/ty/lower.rs15
-rw-r--r--crates/ra_hir/src/ty/tests.rs32
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs7
-rw-r--r--crates/ra_hir_def/src/nameres.rs8
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs12
-rw-r--r--crates/ra_hir_def/src/nameres/per_ns.rs8
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs109
-rw-r--r--crates/ra_mbe/src/lib.rs45
-rw-r--r--crates/ra_mbe/src/tests.rs27
-rw-r--r--xtask/src/codegen.rs8
24 files changed, 418 insertions, 419 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3879204d9..af97b7659 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -51,7 +51,7 @@ name = "backtrace-sys"
51version = "0.1.32" 51version = "0.1.32"
52source = "registry+https://github.com/rust-lang/crates.io-index" 52source = "registry+https://github.com/rust-lang/crates.io-index"
53dependencies = [ 53dependencies = [
54 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 54 "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
55 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 55 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
56] 56]
57 57
@@ -115,7 +115,7 @@ dependencies = [
115 115
116[[package]] 116[[package]]
117name = "cc" 117name = "cc"
118version = "1.0.46" 118version = "1.0.47"
119source = "registry+https://github.com/rust-lang/crates.io-index" 119source = "registry+https://github.com/rust-lang/crates.io-index"
120 120
121[[package]] 121[[package]]
@@ -220,7 +220,7 @@ dependencies = [
220 220
221[[package]] 221[[package]]
222name = "console" 222name = "console"
223version = "0.9.0" 223version = "0.9.1"
224source = "registry+https://github.com/rust-lang/crates.io-index" 224source = "registry+https://github.com/rust-lang/crates.io-index"
225dependencies = [ 225dependencies = [
226 "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 226 "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -486,10 +486,10 @@ dependencies = [
486 486
487[[package]] 487[[package]]
488name = "indicatif" 488name = "indicatif"
489version = "0.12.0" 489version = "0.13.0"
490source = "registry+https://github.com/rust-lang/crates.io-index" 490source = "registry+https://github.com/rust-lang/crates.io-index"
491dependencies = [ 491dependencies = [
492 "console 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 492 "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
493 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 493 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
494 "number_prefix 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 494 "number_prefix 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
495 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 495 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -518,7 +518,7 @@ name = "insta"
518version = "0.12.0" 518version = "0.12.0"
519source = "registry+https://github.com/rust-lang/crates.io-index" 519source = "registry+https://github.com/rust-lang/crates.io-index"
520dependencies = [ 520dependencies = [
521 "console 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 521 "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
522 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 522 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
523 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 523 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
524 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 524 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -563,7 +563,7 @@ name = "jemalloc-sys"
563version = "0.3.2" 563version = "0.3.2"
564source = "registry+https://github.com/rust-lang/crates.io-index" 564source = "registry+https://github.com/rust-lang/crates.io-index"
565dependencies = [ 565dependencies = [
566 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 566 "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
567 "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 567 "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
568 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 568 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
569] 569]
@@ -666,6 +666,11 @@ version = "0.1.8"
666source = "registry+https://github.com/rust-lang/crates.io-index" 666source = "registry+https://github.com/rust-lang/crates.io-index"
667 667
668[[package]] 668[[package]]
669name = "maybe-uninit"
670version = "2.0.0"
671source = "registry+https://github.com/rust-lang/crates.io-index"
672
673[[package]]
669name = "memchr" 674name = "memchr"
670version = "2.2.1" 675version = "2.2.1"
671source = "registry+https://github.com/rust-lang/crates.io-index" 676source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -811,7 +816,7 @@ dependencies = [
811 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 816 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
812 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 817 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
813 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 818 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
814 "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 819 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
815 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 820 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
816] 821]
817 822
@@ -896,10 +901,10 @@ dependencies = [
896 901
897[[package]] 902[[package]]
898name = "psm" 903name = "psm"
899version = "0.1.5" 904version = "0.1.6"
900source = "registry+https://github.com/rust-lang/crates.io-index" 905source = "registry+https://github.com/rust-lang/crates.io-index"
901dependencies = [ 906dependencies = [
902 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 907 "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
903] 908]
904 909
905[[package]] 910[[package]]
@@ -965,7 +970,7 @@ name = "ra_cli"
965version = "0.1.0" 970version = "0.1.0"
966dependencies = [ 971dependencies = [
967 "flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", 972 "flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
968 "indicatif 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 973 "indicatif 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
969 "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 974 "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
970 "ra_batch 0.1.0", 975 "ra_batch 0.1.0",
971 "ra_db 0.1.0", 976 "ra_db 0.1.0",
@@ -1119,7 +1124,7 @@ dependencies = [
1119 "ra_syntax 0.1.0", 1124 "ra_syntax 0.1.0",
1120 "ra_tt 0.1.0", 1125 "ra_tt 0.1.0",
1121 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1126 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1122 "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 1127 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
1123 "test_utils 0.1.0", 1128 "test_utils 0.1.0",
1124] 1129]
1125 1130
@@ -1484,7 +1489,7 @@ dependencies = [
1484 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1489 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1485 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1490 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1486 "salsa-macros 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", 1491 "salsa-macros 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
1487 "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 1492 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
1488] 1493]
1489 1494
1490[[package]] 1495[[package]]
@@ -1581,8 +1586,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1581 1586
1582[[package]] 1587[[package]]
1583name = "smallvec" 1588name = "smallvec"
1584version = "0.6.12" 1589version = "0.6.13"
1585source = "registry+https://github.com/rust-lang/crates.io-index" 1590source = "registry+https://github.com/rust-lang/crates.io-index"
1591dependencies = [
1592 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1593]
1586 1594
1587[[package]] 1595[[package]]
1588name = "smol_str" 1596name = "smol_str"
@@ -1597,10 +1605,10 @@ name = "stacker"
1597version = "0.1.6" 1605version = "0.1.6"
1598source = "registry+https://github.com/rust-lang/crates.io-index" 1606source = "registry+https://github.com/rust-lang/crates.io-index"
1599dependencies = [ 1607dependencies = [
1600 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 1608 "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
1601 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 1609 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1602 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 1610 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
1603 "psm 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1611 "psm 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
1604 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1612 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
1605] 1613]
1606 1614
@@ -1701,7 +1709,7 @@ name = "unicode-normalization"
1701version = "0.1.8" 1709version = "0.1.8"
1702source = "registry+https://github.com/rust-lang/crates.io-index" 1710source = "registry+https://github.com/rust-lang/crates.io-index"
1703dependencies = [ 1711dependencies = [
1704 "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 1712 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
1705] 1713]
1706 1714
1707[[package]] 1715[[package]]
@@ -1846,7 +1854,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1846"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 1854"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
1847"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" 1855"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
1848"checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" 1856"checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d"
1849"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" 1857"checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8"
1850"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 1858"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
1851"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>" 1859"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
1852"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>" 1860"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
@@ -1857,7 +1865,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1857"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" 1865"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
1858"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" 1866"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e"
1859"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 1867"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
1860"checksum console 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62828f51cfa18f8c31d3d55a43c6ce6af3f87f754cba9fbba7ff38089b9f5612" 1868"checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f"
1861"checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c" 1869"checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c"
1862"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" 1870"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
1863"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" 1871"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
@@ -1890,7 +1898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1890"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" 1898"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120"
1891"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" 1899"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
1892"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" 1900"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2"
1893"checksum indicatif 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8d596a9576eaa1446996092642d72bfef35cf47243129b7ab883baf5faec31e" 1901"checksum indicatif 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8572bccfb0665e70b7faf44ee28841b8e0823450cd4ad562a76b5a3c4bf48487"
1894"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" 1902"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
1895"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" 1903"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
1896"checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349" 1904"checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349"
@@ -1913,6 +1921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1913"checksum lsp-server 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "148cfb1c0b3295c23d9fb4a20fd1b242f5e6f46c525fdcc7f5c0a65710362012" 1921"checksum lsp-server 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "148cfb1c0b3295c23d9fb4a20fd1b242f5e6f46c525fdcc7f5c0a65710362012"
1914"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf" 1922"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf"
1915"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1923"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
1924"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
1916"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" 1925"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
1917"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc" 1926"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc"
1918"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" 1927"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23"
@@ -1938,7 +1947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1938"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" 1947"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
1939"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" 1948"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
1940"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f" 1949"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f"
1941"checksum psm 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "54639efee26275dfadc49644039c31c73673edde0ef2815acf25a8db526ee193" 1950"checksum psm 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b14fc68b454f875abc8354c2555e1d56596f74833ddc0f77f87f4871ed6a30e0"
1942"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 1951"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
1943"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 1952"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
1944"checksum ra_vfs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc8f508bc7a9871b81b6ee75e15d0bbc9f81a96698364a090a8d10b0f8b970b7" 1953"checksum ra_vfs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc8f508bc7a9871b81b6ee75e15d0bbc9f81a96698364a090a8d10b0f8b970b7"
@@ -1984,7 +1993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1984"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" 1993"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573"
1985"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" 1994"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
1986"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1995"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1987"checksum smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "533e29e15d0748f28afbaf4ff7cab44d73e483a8e50b38c40bd13b7f3d48f542" 1996"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
1988"checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" 1997"checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b"
1989"checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" 1998"checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a"
1990"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" 1999"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs
index 6e1e3de84..a8f8446cb 100644
--- a/crates/ra_assists/src/doc_tests.rs
+++ b/crates/ra_assists/src/doc_tests.rs
@@ -5,13 +5,14 @@
5 5
6mod generated; 6mod generated;
7 7
8use hir::mock::MockDatabase; 8use ra_db::{fixture::WithFixture, FileRange};
9use ra_db::FileRange;
10use test_utils::{assert_eq_text, extract_range_or_offset}; 9use test_utils::{assert_eq_text, extract_range_or_offset};
11 10
11use crate::test_db::TestDB;
12
12fn check(assist_id: &str, before: &str, after: &str) { 13fn check(assist_id: &str, before: &str, after: &str) {
13 let (selection, before) = extract_range_or_offset(before); 14 let (selection, before) = extract_range_or_offset(before);
14 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 15 let (db, file_id) = TestDB::with_single_file(&before);
15 let frange = FileRange { file_id, range: selection.into() }; 16 let frange = FileRange { file_id, range: selection.into() };
16 17
17 let (_assist_id, action) = crate::assists(&db, frange) 18 let (_assist_id, action) = crate::assists(&db, frange)
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 38599d4f1..39c1c283f 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -9,6 +9,8 @@ mod assist_ctx;
9mod marks; 9mod marks;
10#[cfg(test)] 10#[cfg(test)]
11mod doc_tests; 11mod doc_tests;
12#[cfg(test)]
13mod test_db;
12 14
13use hir::db::HirDatabase; 15use hir::db::HirDatabase;
14use ra_db::FileRange; 16use ra_db::FileRange;
@@ -146,20 +148,19 @@ mod assists {
146 148
147#[cfg(test)] 149#[cfg(test)]
148mod helpers { 150mod helpers {
149 use hir::mock::MockDatabase; 151 use ra_db::{fixture::WithFixture, FileRange};
150 use ra_db::FileRange;
151 use ra_syntax::TextRange; 152 use ra_syntax::TextRange;
152 use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; 153 use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range};
153 154
154 use crate::{Assist, AssistCtx}; 155 use crate::{test_db::TestDB, Assist, AssistCtx};
155 156
156 pub(crate) fn check_assist( 157 pub(crate) fn check_assist(
157 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 158 assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
158 before: &str, 159 before: &str,
159 after: &str, 160 after: &str,
160 ) { 161 ) {
161 let (before_cursor_pos, before) = extract_offset(before); 162 let (before_cursor_pos, before) = extract_offset(before);
162 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 163 let (db, file_id) = TestDB::with_single_file(&before);
163 let frange = 164 let frange =
164 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; 165 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
165 let assist = 166 let assist =
@@ -182,12 +183,12 @@ mod helpers {
182 } 183 }
183 184
184 pub(crate) fn check_assist_range( 185 pub(crate) fn check_assist_range(
185 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 186 assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
186 before: &str, 187 before: &str,
187 after: &str, 188 after: &str,
188 ) { 189 ) {
189 let (range, before) = extract_range(before); 190 let (range, before) = extract_range(before);
190 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 191 let (db, file_id) = TestDB::with_single_file(&before);
191 let frange = FileRange { file_id, range }; 192 let frange = FileRange { file_id, range };
192 let assist = 193 let assist =
193 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); 194 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
@@ -204,12 +205,12 @@ mod helpers {
204 } 205 }
205 206
206 pub(crate) fn check_assist_target( 207 pub(crate) fn check_assist_target(
207 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 208 assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
208 before: &str, 209 before: &str,
209 target: &str, 210 target: &str,
210 ) { 211 ) {
211 let (before_cursor_pos, before) = extract_offset(before); 212 let (before_cursor_pos, before) = extract_offset(before);
212 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 213 let (db, file_id) = TestDB::with_single_file(&before);
213 let frange = 214 let frange =
214 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; 215 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
215 let assist = 216 let assist =
@@ -224,12 +225,12 @@ mod helpers {
224 } 225 }
225 226
226 pub(crate) fn check_assist_range_target( 227 pub(crate) fn check_assist_range_target(
227 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 228 assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
228 before: &str, 229 before: &str,
229 target: &str, 230 target: &str,
230 ) { 231 ) {
231 let (range, before) = extract_range(before); 232 let (range, before) = extract_range(before);
232 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 233 let (db, file_id) = TestDB::with_single_file(&before);
233 let frange = FileRange { file_id, range }; 234 let frange = FileRange { file_id, range };
234 let assist = 235 let assist =
235 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); 236 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
@@ -243,11 +244,11 @@ mod helpers {
243 } 244 }
244 245
245 pub(crate) fn check_assist_not_applicable( 246 pub(crate) fn check_assist_not_applicable(
246 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 247 assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
247 before: &str, 248 before: &str,
248 ) { 249 ) {
249 let (before_cursor_pos, before) = extract_offset(before); 250 let (before_cursor_pos, before) = extract_offset(before);
250 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 251 let (db, file_id) = TestDB::with_single_file(&before);
251 let frange = 252 let frange =
252 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; 253 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
253 let assist = AssistCtx::with_ctx(&db, frange, true, assist); 254 let assist = AssistCtx::with_ctx(&db, frange, true, assist);
@@ -255,11 +256,11 @@ mod helpers {
255 } 256 }
256 257
257 pub(crate) fn check_assist_range_not_applicable( 258 pub(crate) fn check_assist_range_not_applicable(
258 assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, 259 assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
259 before: &str, 260 before: &str,
260 ) { 261 ) {
261 let (range, before) = extract_range(before); 262 let (range, before) = extract_range(before);
262 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 263 let (db, file_id) = TestDB::with_single_file(&before);
263 let frange = FileRange { file_id, range }; 264 let frange = FileRange { file_id, range };
264 let assist = AssistCtx::with_ctx(&db, frange, true, assist); 265 let assist = AssistCtx::with_ctx(&db, frange, true, assist);
265 assert!(assist.is_none()); 266 assert!(assist.is_none());
@@ -268,16 +269,17 @@ mod helpers {
268 269
269#[cfg(test)] 270#[cfg(test)]
270mod tests { 271mod tests {
271 use hir::mock::MockDatabase; 272 use ra_db::{fixture::WithFixture, FileRange};
272 use ra_db::FileRange;
273 use ra_syntax::TextRange; 273 use ra_syntax::TextRange;
274 use test_utils::{extract_offset, extract_range}; 274 use test_utils::{extract_offset, extract_range};
275 275
276 use crate::test_db::TestDB;
277
276 #[test] 278 #[test]
277 fn assist_order_field_struct() { 279 fn assist_order_field_struct() {
278 let before = "struct Foo { <|>bar: u32 }"; 280 let before = "struct Foo { <|>bar: u32 }";
279 let (before_cursor_pos, before) = extract_offset(before); 281 let (before_cursor_pos, before) = extract_offset(before);
280 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 282 let (db, file_id) = TestDB::with_single_file(&before);
281 let frange = 283 let frange =
282 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; 284 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
283 let assists = super::assists(&db, frange); 285 let assists = super::assists(&db, frange);
@@ -298,7 +300,7 @@ mod tests {
298 } 300 }
299 }"; 301 }";
300 let (range, before) = extract_range(before); 302 let (range, before) = extract_range(before);
301 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 303 let (db, file_id) = TestDB::with_single_file(&before);
302 let frange = FileRange { file_id, range }; 304 let frange = FileRange { file_id, range };
303 let assists = super::assists(&db, frange); 305 let assists = super::assists(&db, frange);
304 let mut assists = assists.iter(); 306 let mut assists = assists.iter();
diff --git a/crates/ra_assists/src/test_db.rs b/crates/ra_assists/src/test_db.rs
new file mode 100644
index 000000000..5be7383ed
--- /dev/null
+++ b/crates/ra_assists/src/test_db.rs
@@ -0,0 +1,45 @@
1//! Database used for testing `ra_assists`.
2
3use std::sync::Arc;
4
5use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath};
6
7#[salsa::database(
8 ra_db::SourceDatabaseExtStorage,
9 ra_db::SourceDatabaseStorage,
10 hir::db::InternDatabaseStorage,
11 hir::db::AstDatabaseStorage,
12 hir::db::DefDatabaseStorage,
13 hir::db::DefDatabase2Storage,
14 hir::db::HirDatabaseStorage
15)]
16#[derive(Debug, Default)]
17pub struct TestDB {
18 runtime: salsa::Runtime<TestDB>,
19}
20
21impl salsa::Database for TestDB {
22 fn salsa_runtime(&self) -> &salsa::Runtime<Self> {
23 &self.runtime
24 }
25}
26
27impl std::panic::RefUnwindSafe for TestDB {}
28
29impl FileLoader for TestDB {
30 fn file_text(&self, file_id: FileId) -> Arc<String> {
31 FileLoaderDelegate(self).file_text(file_id)
32 }
33 fn resolve_relative_path(
34 &self,
35 anchor: FileId,
36 relative_path: &RelativePath,
37 ) -> Option<FileId> {
38 FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
39 }
40 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
41 FileLoaderDelegate(self).relevant_crates(file_id)
42 }
43}
44
45impl hir::debug::HirDebugHelper for TestDB {}
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index fcd102e8b..c9d3bdb77 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -8,7 +8,7 @@ publish = false
8[dependencies] 8[dependencies]
9pico-args = "0.3.0" 9pico-args = "0.3.0"
10flexi_logger = "0.14.0" 10flexi_logger = "0.14.0"
11indicatif = "0.12.0" 11indicatif = "0.13.0"
12 12
13ra_syntax = { path = "../ra_syntax" } 13ra_syntax = { path = "../ra_syntax" }
14ra_ide_api = { path = "../ra_ide_api" } 14ra_ide_api = { path = "../ra_ide_api" }
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index c29c2448e..9d0db8024 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -31,8 +31,8 @@ use crate::{
31 impl_block::ImplBlock, 31 impl_block::ImplBlock,
32 resolve::{Resolver, Scope, TypeNs}, 32 resolve::{Resolver, Scope, TypeNs},
33 traits::TraitData, 33 traits::TraitData,
34 ty::{InferenceResult, TraitRef}, 34 ty::{InferenceResult, Namespace, TraitRef},
35 Either, HasSource, Name, ScopeDef, Ty, {ImportId, Namespace}, 35 Either, HasSource, ImportId, Name, ScopeDef, Ty,
36}; 36};
37 37
38/// hir::Crate describes a single crate. It's the main interface with which 38/// hir::Crate describes a single crate. It's the main interface with which
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 799cc0209..75c322c99 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -15,10 +15,10 @@ use crate::{
15 traits::TraitData, 15 traits::TraitData,
16 ty::{ 16 ty::{
17 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, 17 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate,
18 InferenceResult, Substs, Ty, TypableDef, TypeCtor, 18 InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor,
19 }, 19 },
20 type_alias::TypeAliasData, 20 type_alias::TypeAliasData,
21 Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Namespace, Static, 21 Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static,
22 StructField, Trait, TypeAlias, 22 StructField, Trait, TypeAlias,
23}; 23};
24 24
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 5496822e7..c14c2ab66 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -174,11 +174,11 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
174 174
175#[cfg(test)] 175#[cfg(test)]
176mod tests { 176mod tests {
177 use ra_db::SourceDatabase; 177 use ra_db::{fixture::WithFixture, SourceDatabase};
178 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 178 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
179 use test_utils::{assert_eq_text, extract_offset}; 179 use test_utils::{assert_eq_text, extract_offset};
180 180
181 use crate::{mock::MockDatabase, source_binder::SourceAnalyzer}; 181 use crate::{source_binder::SourceAnalyzer, test_db::TestDB};
182 182
183 fn do_check(code: &str, expected: &[&str]) { 183 fn do_check(code: &str, expected: &[&str]) {
184 let (off, code) = extract_offset(code); 184 let (off, code) = extract_offset(code);
@@ -191,7 +191,7 @@ mod tests {
191 buf 191 buf
192 }; 192 };
193 193
194 let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); 194 let (db, file_id) = TestDB::with_single_file(&code);
195 let file = db.parse(file_id).ok().unwrap(); 195 let file = db.parse(file_id).ok().unwrap();
196 let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 196 let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
197 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); 197 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None);
@@ -288,7 +288,7 @@ mod tests {
288 fn do_check_local_name(code: &str, expected_offset: u32) { 288 fn do_check_local_name(code: &str, expected_offset: u32) {
289 let (off, code) = extract_offset(code); 289 let (off, code) = extract_offset(code);
290 290
291 let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); 291 let (db, file_id) = TestDB::with_single_file(&code);
292 let file = db.parse(file_id).ok().unwrap(); 292 let file = db.parse(file_id).ok().unwrap();
293 let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) 293 let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into())
294 .expect("failed to find a name at the target offset"); 294 .expect("failed to find a name at the target offset");
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 4003f0b7a..131f6c797 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -29,8 +29,6 @@ macro_rules! impl_froms {
29pub mod debug; 29pub mod debug;
30 30
31pub mod db; 31pub mod db;
32#[macro_use]
33pub mod mock;
34pub mod source_binder; 32pub mod source_binder;
35 33
36mod ids; 34mod ids;
@@ -52,6 +50,8 @@ mod code_model;
52pub mod from_source; 50pub mod from_source;
53 51
54#[cfg(test)] 52#[cfg(test)]
53mod test_db;
54#[cfg(test)]
55mod marks; 55mod marks;
56 56
57use hir_expand::AstId; 57use hir_expand::AstId;
@@ -82,10 +82,7 @@ pub use crate::{
82 82
83pub use hir_def::{ 83pub use hir_def::{
84 builtin_type::BuiltinType, 84 builtin_type::BuiltinType,
85 nameres::{ 85 nameres::{per_ns::PerNs, raw::ImportId},
86 per_ns::{Namespace, PerNs},
87 raw::ImportId,
88 },
89 path::{Path, PathKind}, 86 path::{Path, PathKind},
90 type_ref::Mutability, 87 type_ref::Mutability,
91}; 88};
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
deleted file mode 100644
index ab97a09b9..000000000
--- a/crates/ra_hir/src/mock.rs
+++ /dev/null
@@ -1,262 +0,0 @@
1//! FIXME: write short doc here
2
3use std::{panic, sync::Arc};
4
5use hir_expand::diagnostics::DiagnosticSink;
6use parking_lot::Mutex;
7use ra_cfg::CfgOptions;
8use ra_db::{
9 salsa, CrateGraph, CrateId, Edition, FileId, FileLoader, FileLoaderDelegate, FilePosition,
10 RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
11};
12use rustc_hash::FxHashMap;
13use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
14
15use crate::{db, debug::HirDebugHelper};
16
17pub const WORKSPACE: SourceRootId = SourceRootId(0);
18
19#[salsa::database(
20 ra_db::SourceDatabaseExtStorage,
21 ra_db::SourceDatabaseStorage,
22 db::InternDatabaseStorage,
23 db::AstDatabaseStorage,
24 db::DefDatabaseStorage,
25 db::DefDatabase2Storage,
26 db::HirDatabaseStorage
27)]
28#[derive(Debug)]
29pub struct MockDatabase {
30 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>,
31 runtime: salsa::Runtime<MockDatabase>,
32 files: FxHashMap<String, FileId>,
33 crate_names: Arc<FxHashMap<CrateId, String>>,
34 file_paths: Arc<FxHashMap<FileId, String>>,
35}
36
37impl panic::RefUnwindSafe for MockDatabase {}
38
39impl FileLoader for MockDatabase {
40 fn file_text(&self, file_id: FileId) -> Arc<String> {
41 FileLoaderDelegate(self).file_text(file_id)
42 }
43 fn resolve_relative_path(
44 &self,
45 anchor: FileId,
46 relative_path: &RelativePath,
47 ) -> Option<FileId> {
48 FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
49 }
50 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
51 FileLoaderDelegate(self).relevant_crates(file_id)
52 }
53}
54
55impl HirDebugHelper for MockDatabase {
56 fn crate_name(&self, krate: CrateId) -> Option<String> {
57 self.crate_names.get(&krate).cloned()
58 }
59
60 fn file_path(&self, file_id: FileId) -> Option<String> {
61 self.file_paths.get(&file_id).cloned()
62 }
63}
64
65impl MockDatabase {
66 pub fn with_files(fixture: &str) -> MockDatabase {
67 let (db, position) = MockDatabase::from_fixture(fixture);
68 assert!(position.is_none());
69 db
70 }
71
72 pub fn with_single_file(text: &str) -> (MockDatabase, SourceRoot, FileId) {
73 let mut db = MockDatabase::default();
74 let mut source_root = SourceRoot::default();
75 let file_id = db.add_file(WORKSPACE, "/", &mut source_root, "/main.rs", text);
76 db.set_source_root(WORKSPACE, Arc::new(source_root.clone()));
77 (db, source_root, file_id)
78 }
79
80 pub fn file_id_of(&self, path: &str) -> FileId {
81 match self.files.get(path) {
82 Some(it) => *it,
83 None => panic!("unknown file: {:?}\nexisting files:\n{:#?}", path, self.files),
84 }
85 }
86
87 pub fn diagnostics(&self) -> String {
88 let mut buf = String::new();
89 let mut files: Vec<FileId> = self.files.values().copied().collect();
90 files.sort();
91 for file in files {
92 let src = crate::Source {
93 file_id: file.into(),
94 ast: crate::ModuleSource::new(self, Some(file), None),
95 };
96 let module = crate::Module::from_definition(self, src).unwrap();
97 module.diagnostics(
98 self,
99 &mut DiagnosticSink::new(|d| {
100 buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message());
101 }),
102 )
103 }
104 buf
105 }
106
107 fn from_fixture(fixture: &str) -> (MockDatabase, Option<FilePosition>) {
108 let mut db = MockDatabase::default();
109
110 let pos = db.add_fixture(fixture);
111
112 (db, pos)
113 }
114
115 fn add_fixture(&mut self, fixture: &str) -> Option<FilePosition> {
116 let mut position = None;
117 let mut source_root = SourceRoot::default();
118 let mut source_root_id = WORKSPACE;
119 let mut source_root_prefix = "/".to_string();
120 for entry in parse_fixture(fixture) {
121 if entry.meta.starts_with("root") {
122 self.set_source_root(source_root_id, Arc::new(source_root));
123 source_root = SourceRoot::default();
124
125 source_root_id = SourceRootId(source_root_id.0 + 1);
126 source_root_prefix = entry.meta["root".len()..].trim().to_string();
127 continue;
128 }
129 if entry.text.contains(CURSOR_MARKER) {
130 assert!(position.is_none(), "only one marker (<|>) per fixture is allowed");
131 position = Some(self.add_file_with_position(
132 source_root_id,
133 &source_root_prefix,
134 &mut source_root,
135 &entry.meta,
136 &entry.text,
137 ));
138 } else {
139 self.add_file(
140 source_root_id,
141 &source_root_prefix,
142 &mut source_root,
143 &entry.meta,
144 &entry.text,
145 );
146 }
147 }
148 self.set_source_root(source_root_id, Arc::new(source_root));
149 position
150 }
151
152 fn add_file(
153 &mut self,
154 source_root_id: SourceRootId,
155 source_root_prefix: &str,
156 source_root: &mut SourceRoot,
157 path: &str,
158 text: &str,
159 ) -> FileId {
160 assert!(source_root_prefix.starts_with('/'));
161 assert!(source_root_prefix.ends_with('/'));
162 assert!(path.starts_with(source_root_prefix));
163 let rel_path = RelativePathBuf::from_path(&path[source_root_prefix.len()..]).unwrap();
164
165 let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs";
166
167 let file_id = FileId(self.files.len() as u32);
168
169 let prev = self.files.insert(path.to_string(), file_id);
170 assert!(prev.is_none(), "duplicate files in the text fixture");
171 Arc::make_mut(&mut self.file_paths).insert(file_id, path.to_string());
172
173 let text = Arc::new(text.to_string());
174 self.set_file_text(file_id, text);
175 self.set_file_relative_path(file_id, rel_path.clone());
176 self.set_file_source_root(file_id, source_root_id);
177 source_root.insert_file(rel_path, file_id);
178
179 if is_crate_root {
180 let mut crate_graph = CrateGraph::default();
181 crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default());
182 self.set_crate_graph(Arc::new(crate_graph));
183 }
184 file_id
185 }
186
187 fn add_file_with_position(
188 &mut self,
189 source_root_id: SourceRootId,
190 source_root_prefix: &str,
191 source_root: &mut SourceRoot,
192 path: &str,
193 text: &str,
194 ) -> FilePosition {
195 let (offset, text) = extract_offset(text);
196 let file_id = self.add_file(source_root_id, source_root_prefix, source_root, path, &text);
197 FilePosition { file_id, offset }
198 }
199}
200
201impl salsa::Database for MockDatabase {
202 fn salsa_runtime(&self) -> &salsa::Runtime<MockDatabase> {
203 &self.runtime
204 }
205
206 fn salsa_event(&self, event: impl Fn() -> salsa::Event<MockDatabase>) {
207 let mut events = self.events.lock();
208 if let Some(events) = &mut *events {
209 events.push(event());
210 }
211 }
212}
213
214impl Default for MockDatabase {
215 fn default() -> MockDatabase {
216 let mut db = MockDatabase {
217 events: Default::default(),
218 runtime: salsa::Runtime::default(),
219 files: FxHashMap::default(),
220 crate_names: Default::default(),
221 file_paths: Default::default(),
222 };
223 db.set_crate_graph(Default::default());
224 db
225 }
226}
227
228impl salsa::ParallelDatabase for MockDatabase {
229 fn snapshot(&self) -> salsa::Snapshot<MockDatabase> {
230 salsa::Snapshot::new(MockDatabase {
231 events: Default::default(),
232 runtime: self.runtime.snapshot(self),
233 // only the root database can be used to get file_id by path.
234 files: FxHashMap::default(),
235 file_paths: Arc::clone(&self.file_paths),
236 crate_names: Arc::clone(&self.crate_names),
237 })
238 }
239}
240
241impl MockDatabase {
242 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
243 *self.events.lock() = Some(Vec::new());
244 f();
245 self.events.lock().take().unwrap()
246 }
247
248 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
249 let events = self.log(f);
250 events
251 .into_iter()
252 .filter_map(|e| match e.kind {
253 // This pretty horrible, but `Debug` is the only way to inspect
254 // QueryDescriptor at the moment.
255 salsa::EventKind::WillExecute { database_key } => {
256 Some(format!("{:?}", database_key))
257 }
258 _ => None,
259 })
260 .collect()
261 }
262}
diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs
new file mode 100644
index 000000000..5237b303a
--- /dev/null
+++ b/crates/ra_hir/src/test_db.rs
@@ -0,0 +1,120 @@
1//! Database used for testing `hir`.
2
3use std::{panic, sync::Arc};
4
5use hir_def::{db::DefDatabase2, ModuleId};
6use hir_expand::diagnostics::DiagnosticSink;
7use parking_lot::Mutex;
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase};
9
10use crate::{db, debug::HirDebugHelper};
11
12#[salsa::database(
13 ra_db::SourceDatabaseExtStorage,
14 ra_db::SourceDatabaseStorage,
15 db::InternDatabaseStorage,
16 db::AstDatabaseStorage,
17 db::DefDatabaseStorage,
18 db::DefDatabase2Storage,
19 db::HirDatabaseStorage
20)]
21#[derive(Debug, Default)]
22pub struct TestDB {
23 events: Mutex<Option<Vec<salsa::Event<TestDB>>>>,
24 runtime: salsa::Runtime<TestDB>,
25}
26
27impl salsa::Database for TestDB {
28 fn salsa_runtime(&self) -> &salsa::Runtime<TestDB> {
29 &self.runtime
30 }
31
32 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
33 let mut events = self.events.lock();
34 if let Some(events) = &mut *events {
35 events.push(event());
36 }
37 }
38}
39
40impl salsa::ParallelDatabase for TestDB {
41 fn snapshot(&self) -> salsa::Snapshot<TestDB> {
42 salsa::Snapshot::new(TestDB {
43 events: Default::default(),
44 runtime: self.runtime.snapshot(self),
45 })
46 }
47}
48
49impl panic::RefUnwindSafe for TestDB {}
50
51impl FileLoader for TestDB {
52 fn file_text(&self, file_id: FileId) -> Arc<String> {
53 FileLoaderDelegate(self).file_text(file_id)
54 }
55 fn resolve_relative_path(
56 &self,
57 anchor: FileId,
58 relative_path: &RelativePath,
59 ) -> Option<FileId> {
60 FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
61 }
62 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
63 FileLoaderDelegate(self).relevant_crates(file_id)
64 }
65}
66
67// FIXME: improve `WithFixture` to bring useful hir debugging back
68impl HirDebugHelper for TestDB {
69 fn crate_name(&self, _krate: CrateId) -> Option<String> {
70 None
71 }
72
73 fn file_path(&self, _file_id: FileId) -> Option<String> {
74 None
75 }
76}
77
78impl TestDB {
79 pub fn diagnostics(&self) -> String {
80 let mut buf = String::new();
81 let crate_graph = self.crate_graph();
82 for krate in crate_graph.iter().next() {
83 let crate_def_map = self.crate_def_map(krate);
84 for (module_id, _) in crate_def_map.modules.iter() {
85 let module_id = ModuleId { krate, module_id };
86 let module = crate::Module::from(module_id);
87 module.diagnostics(
88 self,
89 &mut DiagnosticSink::new(|d| {
90 buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message());
91 }),
92 )
93 }
94 }
95 buf
96 }
97}
98
99impl TestDB {
100 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> {
101 *self.events.lock() = Some(Vec::new());
102 f();
103 self.events.lock().take().unwrap()
104 }
105
106 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
107 let events = self.log(f);
108 events
109 .into_iter()
110 .filter_map(|e| match e.kind {
111 // This pretty horrible, but `Debug` is the only way to inspect
112 // QueryDescriptor at the moment.
113 salsa::EventKind::WillExecute { database_key } => {
114 Some(format!("{:?}", database_key))
115 }
116 _ => None,
117 })
118 .collect()
119 }
120}
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index d1a9d7411..cd2ac0e8b 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -27,7 +27,7 @@ pub(crate) use infer::{infer_query, InferTy, InferenceResult};
27pub use lower::CallableDef; 27pub use lower::CallableDef;
28pub(crate) use lower::{ 28pub(crate) use lower::{
29 callable_item_sig, generic_defaults_query, generic_predicates_for_param_query, 29 callable_item_sig, generic_defaults_query, generic_predicates_for_param_query,
30 generic_predicates_query, type_for_def, type_for_field, TypableDef, 30 generic_predicates_query, type_for_def, type_for_field, Namespace, TypableDef,
31}; 31};
32pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 32pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
33 33
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index a09ef5c5d..4af1d65ee 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -12,10 +12,10 @@ use crate::{
12 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 12 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
13 generics::{GenericParams, HasGenericParams}, 13 generics::{GenericParams, HasGenericParams},
14 ty::{ 14 ty::{
15 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation, 15 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Namespace,
16 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 16 Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
17 }, 17 },
18 Adt, Name, Namespace, 18 Adt, Name,
19}; 19};
20 20
21impl<'a, D: HirDatabase> InferenceContext<'a, D> { 21impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 59b7f7eb6..865ced5a1 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -6,8 +6,8 @@ use super::{ExprOrPatId, InferenceContext, TraitRef};
6use crate::{ 6use crate::{
7 db::HirDatabase, 7 db::HirDatabase,
8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
9 ty::{method_resolution, Substs, Ty, TypableDef, TypeWalk}, 9 ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk},
10 AssocItem, Container, HasGenericParams, Name, Namespace, Path, 10 AssocItem, Container, HasGenericParams, Name, Path,
11}; 11};
12 12
13impl<'a, D: HirDatabase> InferenceContext<'a, D> { 13impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index e29ab8492..d26b16cb2 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -29,10 +29,21 @@ use crate::{
29 Adt, 29 Adt,
30 }, 30 },
31 util::make_mut_slice, 31 util::make_mut_slice,
32 Const, Enum, EnumVariant, Function, ModuleDef, Namespace, Path, Static, Struct, StructField, 32 Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait,
33 Trait, TypeAlias, Union, 33 TypeAlias, Union,
34}; 34};
35 35
36// FIXME: this is only really used in `type_for_def`, which contains a bunch of
37// impossible cases. Perhaps we should recombine `TypeableDef` and `Namespace`
38// into a `AsTypeDef`, `AsValueDef` enums?
39#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub enum Namespace {
41 Types,
42 Values,
43 // Note that only type inference uses this enum, and it doesn't care about macros.
44 // Macro,
45}
46
36impl Ty { 47impl Ty {
37 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { 48 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
38 match type_ref { 49 match type_ref {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 4b7e34878..e56b9356e 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11use test_utils::covers; 11use test_utils::covers;
12 12
13use crate::{ 13use crate::{
14 expr::BodySourceMap, mock::MockDatabase, ty::display::HirDisplay, ty::InferenceResult, 14 expr::BodySourceMap, test_db::TestDB, ty::display::HirDisplay, ty::InferenceResult,
15 SourceAnalyzer, 15 SourceAnalyzer,
16}; 16};
17 17
@@ -24,7 +24,7 @@ mod coercion;
24 24
25#[test] 25#[test]
26fn cfg_impl_block() { 26fn cfg_impl_block() {
27 let (db, pos) = MockDatabase::with_position( 27 let (db, pos) = TestDB::with_position(
28 r#" 28 r#"
29//- /main.rs crate:main deps:foo cfg:test 29//- /main.rs crate:main deps:foo cfg:test
30use foo::S as T; 30use foo::S as T;
@@ -64,7 +64,7 @@ impl S {
64 64
65#[test] 65#[test]
66fn infer_await() { 66fn infer_await() {
67 let (db, pos) = MockDatabase::with_position( 67 let (db, pos) = TestDB::with_position(
68 r#" 68 r#"
69//- /main.rs crate:main deps:std 69//- /main.rs crate:main deps:std
70 70
@@ -95,7 +95,7 @@ mod future {
95 95
96#[test] 96#[test]
97fn infer_box() { 97fn infer_box() {
98 let (db, pos) = MockDatabase::with_position( 98 let (db, pos) = TestDB::with_position(
99 r#" 99 r#"
100//- /main.rs crate:main deps:std 100//- /main.rs crate:main deps:std
101 101
@@ -122,7 +122,7 @@ mod boxed {
122 122
123#[test] 123#[test]
124fn infer_adt_self() { 124fn infer_adt_self() {
125 let (db, pos) = MockDatabase::with_position( 125 let (db, pos) = TestDB::with_position(
126 r#" 126 r#"
127//- /main.rs 127//- /main.rs
128enum Nat { Succ(Self), Demo(Nat), Zero } 128enum Nat { Succ(Self), Demo(Nat), Zero }
@@ -141,7 +141,7 @@ fn test() {
141 141
142#[test] 142#[test]
143fn infer_try() { 143fn infer_try() {
144 let (db, pos) = MockDatabase::with_position( 144 let (db, pos) = TestDB::with_position(
145 r#" 145 r#"
146//- /main.rs crate:main deps:std 146//- /main.rs crate:main deps:std
147 147
@@ -181,7 +181,7 @@ mod result {
181 181
182#[test] 182#[test]
183fn infer_for_loop() { 183fn infer_for_loop() {
184 let (db, pos) = MockDatabase::with_position( 184 let (db, pos) = TestDB::with_position(
185 r#" 185 r#"
186//- /main.rs crate:main deps:std 186//- /main.rs crate:main deps:std
187 187
@@ -223,7 +223,7 @@ mod collections {
223#[test] 223#[test]
224fn infer_while_let() { 224fn infer_while_let() {
225 covers!(infer_while_let); 225 covers!(infer_while_let);
226 let (db, pos) = MockDatabase::with_position( 226 let (db, pos) = TestDB::with_position(
227 r#" 227 r#"
228//- /main.rs 228//- /main.rs
229enum Option<T> { Some(T), None } 229enum Option<T> { Some(T), None }
@@ -2484,7 +2484,7 @@ pub fn main_loop() {
2484 2484
2485#[test] 2485#[test]
2486fn cross_crate_associated_method_call() { 2486fn cross_crate_associated_method_call() {
2487 let (db, pos) = MockDatabase::with_position( 2487 let (db, pos) = TestDB::with_position(
2488 r#" 2488 r#"
2489//- /main.rs crate:main deps:other_crate 2489//- /main.rs crate:main deps:other_crate
2490fn test() { 2490fn test() {
@@ -3378,7 +3378,7 @@ fn test() { S.foo()<|>; }
3378 3378
3379#[test] 3379#[test]
3380fn infer_macro_with_dollar_crate_is_correct_in_expr() { 3380fn infer_macro_with_dollar_crate_is_correct_in_expr() {
3381 let (db, pos) = MockDatabase::with_position( 3381 let (db, pos) = TestDB::with_position(
3382 r#" 3382 r#"
3383//- /main.rs crate:main deps:foo 3383//- /main.rs crate:main deps:foo
3384fn test() { 3384fn test() {
@@ -3482,7 +3482,7 @@ fn test() { (&S).foo()<|>; }
3482 3482
3483#[test] 3483#[test]
3484fn method_resolution_trait_from_prelude() { 3484fn method_resolution_trait_from_prelude() {
3485 let (db, pos) = MockDatabase::with_position( 3485 let (db, pos) = TestDB::with_position(
3486 r#" 3486 r#"
3487//- /main.rs crate:main deps:other_crate 3487//- /main.rs crate:main deps:other_crate
3488struct S; 3488struct S;
@@ -4651,7 +4651,7 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
4651 assert_eq!(t, "{unknown}"); 4651 assert_eq!(t, "{unknown}");
4652} 4652}
4653 4653
4654fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 4654fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
4655 let file = db.parse(pos.file_id).ok().unwrap(); 4655 let file = db.parse(pos.file_id).ok().unwrap();
4656 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 4656 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
4657 let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset)); 4657 let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset));
@@ -4660,12 +4660,12 @@ fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
4660} 4660}
4661 4661
4662fn type_at(content: &str) -> String { 4662fn type_at(content: &str) -> String {
4663 let (db, file_pos) = MockDatabase::with_position(content); 4663 let (db, file_pos) = TestDB::with_position(content);
4664 type_at_pos(&db, file_pos) 4664 type_at_pos(&db, file_pos)
4665} 4665}
4666 4666
4667fn infer(content: &str) -> String { 4667fn infer(content: &str) -> String {
4668 let (db, _, file_id) = MockDatabase::with_single_file(content); 4668 let (db, file_id) = TestDB::with_single_file(content);
4669 let source_file = db.parse(file_id).ok().unwrap(); 4669 let source_file = db.parse(file_id).ok().unwrap();
4670 4670
4671 let mut acc = String::new(); 4671 let mut acc = String::new();
@@ -4748,7 +4748,7 @@ fn ellipsize(mut text: String, max_len: usize) -> String {
4748 4748
4749#[test] 4749#[test]
4750fn typing_whitespace_inside_a_function_should_not_invalidate_types() { 4750fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
4751 let (mut db, pos) = MockDatabase::with_position( 4751 let (mut db, pos) = TestDB::with_position(
4752 " 4752 "
4753 //- /lib.rs 4753 //- /lib.rs
4754 fn foo() -> i32 { 4754 fn foo() -> i32 {
@@ -4788,7 +4788,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
4788 4788
4789#[test] 4789#[test]
4790fn no_such_field_diagnostics() { 4790fn no_such_field_diagnostics() {
4791 let diagnostics = MockDatabase::with_files( 4791 let diagnostics = TestDB::with_files(
4792 r" 4792 r"
4793 //- /lib.rs 4793 //- /lib.rs
4794 struct S { foo: i32, bar: () } 4794 struct S { foo: i32, bar: () }
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 39ef92182..c694952f3 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -18,7 +18,10 @@ use crate::{
18 db::HirDatabase, 18 db::HirDatabase,
19 generics::GenericDef, 19 generics::GenericDef,
20 ty::display::HirDisplay, 20 ty::display::HirDisplay,
21 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, 21 ty::{
22 ApplicationTy, GenericPredicate, Namespace, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
23 TypeWalk,
24 },
22 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, 25 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias,
23}; 26};
24 27
@@ -652,7 +655,7 @@ fn impl_block_datum(
652 }) 655 })
653 .filter_map(|t| { 656 .filter_map(|t| {
654 let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?; 657 let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?;
655 let ty = db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars); 658 let ty = db.type_for_def(t.into(), Namespace::Types).subst(&bound_vars);
656 Some(chalk_rust_ir::AssociatedTyValue { 659 Some(chalk_rust_ir::AssociatedTyValue {
657 impl_id, 660 impl_id,
658 associated_ty_id: assoc_ty.to_chalk(db), 661 associated_ty_id: assoc_ty.to_chalk(db),
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index 433bdde48..e1959cdb9 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -50,8 +50,8 @@
50// FIXME: review privacy of submodules 50// FIXME: review privacy of submodules
51pub mod raw; 51pub mod raw;
52pub mod per_ns; 52pub mod per_ns;
53pub mod collector; 53mod collector;
54pub mod mod_resolution; 54mod mod_resolution;
55 55
56#[cfg(test)] 56#[cfg(test)]
57mod tests; 57mod tests;
@@ -196,7 +196,7 @@ pub struct Resolution {
196} 196}
197 197
198impl Resolution { 198impl Resolution {
199 pub(crate) fn from_macro(macro_: MacroDefId) -> Self { 199 fn from_macro(macro_: MacroDefId) -> Self {
200 Resolution { def: PerNs::macros(macro_), import: None } 200 Resolution { def: PerNs::macros(macro_), import: None }
201 } 201 }
202} 202}
@@ -460,7 +460,7 @@ impl CrateDefMap {
460 from_crate_root.or(from_extern_prelude) 460 from_crate_root.or(from_extern_prelude)
461 } 461 }
462 462
463 pub(crate) fn resolve_name_in_module( 463 fn resolve_name_in_module(
464 &self, 464 &self,
465 db: &impl DefDatabase2, 465 db: &impl DefDatabase2,
466 module: CrateModuleId, 466 module: CrateModuleId,
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs
index f6b0b8fb1..b3b1379d0 100644
--- a/crates/ra_hir_def/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs
@@ -6,7 +6,7 @@ use ra_syntax::SmolStr;
6use crate::{db::DefDatabase2, HirFileId}; 6use crate::{db::DefDatabase2, HirFileId};
7 7
8#[derive(Clone, Debug)] 8#[derive(Clone, Debug)]
9pub struct ModDir { 9pub(super) struct ModDir {
10 /// `.` for `mod.rs`, `lib.rs` 10 /// `.` for `mod.rs`, `lib.rs`
11 /// `./foo` for `foo.rs` 11 /// `./foo` for `foo.rs`
12 /// `./foo/bar` for `mod bar { mod x; }` nested in `foo.rs` 12 /// `./foo/bar` for `mod bar { mod x; }` nested in `foo.rs`
@@ -16,11 +16,15 @@ pub struct ModDir {
16} 16}
17 17
18impl ModDir { 18impl ModDir {
19 pub fn root() -> ModDir { 19 pub(super) fn root() -> ModDir {
20 ModDir { path: RelativePathBuf::default(), root_non_dir_owner: false } 20 ModDir { path: RelativePathBuf::default(), root_non_dir_owner: false }
21 } 21 }
22 22
23 pub fn descend_into_definition(&self, name: &Name, attr_path: Option<&SmolStr>) -> ModDir { 23 pub(super) fn descend_into_definition(
24 &self,
25 name: &Name,
26 attr_path: Option<&SmolStr>,
27 ) -> ModDir {
24 let mut path = self.path.clone(); 28 let mut path = self.path.clone();
25 match attr_to_path(attr_path) { 29 match attr_to_path(attr_path) {
26 None => path.push(&name.to_string()), 30 None => path.push(&name.to_string()),
@@ -34,7 +38,7 @@ impl ModDir {
34 ModDir { path, root_non_dir_owner: false } 38 ModDir { path, root_non_dir_owner: false }
35 } 39 }
36 40
37 pub fn resolve_declaration( 41 pub(super) fn resolve_declaration(
38 &self, 42 &self,
39 db: &impl DefDatabase2, 43 db: &impl DefDatabase2,
40 file_id: HirFileId, 44 file_id: HirFileId,
diff --git a/crates/ra_hir_def/src/nameres/per_ns.rs b/crates/ra_hir_def/src/nameres/per_ns.rs
index 298b0b0c7..717ed1ef9 100644
--- a/crates/ra_hir_def/src/nameres/per_ns.rs
+++ b/crates/ra_hir_def/src/nameres/per_ns.rs
@@ -4,14 +4,6 @@ use hir_expand::MacroDefId;
4 4
5use crate::ModuleDefId; 5use crate::ModuleDefId;
6 6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub enum Namespace {
9 Types,
10 Values,
11 // Note that only type inference uses this enum, and it doesn't care about macros.
12 // Macro,
13}
14
15#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 7#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
16pub struct PerNs { 8pub struct PerNs {
17 pub types: Option<ModuleDefId>, 9 pub types: Option<ModuleDefId>,
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index 60ed3518b..4f9565441 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -1,5 +1,9 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Ty, TypeCtor};
4use ra_syntax::{ast::AstNode, TextRange, TextUnit};
5use ra_text_edit::TextEdit;
6
3use crate::{ 7use crate::{
4 completion::{ 8 completion::{
5 completion_context::CompletionContext, 9 completion_context::CompletionContext,
@@ -7,9 +11,53 @@ use crate::{
7 }, 11 },
8 CompletionItem, 12 CompletionItem,
9}; 13};
10use hir::{Ty, TypeCtor}; 14
11use ra_syntax::{ast::AstNode, TextRange, TextUnit}; 15pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
12use ra_text_edit::TextEdit; 16 let dot_receiver = match &ctx.dot_receiver {
17 Some(it) => it,
18 None => return,
19 };
20
21 let receiver_text = if ctx.dot_receiver_is_ambiguous_float_literal {
22 let text = dot_receiver.syntax().text();
23 let without_dot = ..text.len() - TextUnit::of_char('.');
24 text.slice(without_dot).to_string()
25 } else {
26 dot_receiver.syntax().text().to_string()
27 };
28
29 let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver);
30
31 if is_bool_or_unknown(receiver_ty) {
32 postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text))
33 .add_to(acc);
34 postfix_snippet(
35 ctx,
36 "while",
37 "while expr {}",
38 &format!("while {} {{\n$0\n}}", receiver_text),
39 )
40 .add_to(acc);
41 }
42
43 postfix_snippet(ctx, "not", "!expr", &format!("!{}", receiver_text)).add_to(acc);
44
45 postfix_snippet(ctx, "ref", "&expr", &format!("&{}", receiver_text)).add_to(acc);
46 postfix_snippet(ctx, "refm", "&mut expr", &format!("&mut {}", receiver_text)).add_to(acc);
47
48 postfix_snippet(
49 ctx,
50 "match",
51 "match expr {}",
52 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text),
53 )
54 .add_to(acc);
55
56 postfix_snippet(ctx, "dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)).add_to(acc);
57
58 postfix_snippet(ctx, "box", "Box::new(expr)", &format!("Box::new({})", receiver_text))
59 .add_to(acc);
60}
13 61
14fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { 62fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder {
15 let edit = { 63 let edit = {
@@ -24,62 +72,19 @@ fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet:
24} 72}
25 73
26fn is_bool_or_unknown(ty: Option<Ty>) -> bool { 74fn is_bool_or_unknown(ty: Option<Ty>) -> bool {
27 if let Some(ty) = ty { 75 match &ty {
28 match ty { 76 Some(Ty::Apply(app)) if app.ctor == TypeCtor::Bool => true,
29 Ty::Apply(at) => match at.ctor { 77 Some(Ty::Unknown) | None => true,
30 TypeCtor::Bool => true, 78 Some(_) => false,
31 _ => false,
32 },
33 Ty::Unknown => true,
34 _ => false,
35 }
36 } else {
37 true
38 }
39}
40
41pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
42 if let Some(dot_receiver) = &ctx.dot_receiver {
43 let receiver_text = if ctx.dot_receiver_is_ambiguous_float_literal {
44 let text = dot_receiver.syntax().text();
45 let without_dot = ..text.len() - TextUnit::of_char('.');
46 text.slice(without_dot).to_string()
47 } else {
48 dot_receiver.syntax().text().to_string()
49 };
50 let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver);
51 if is_bool_or_unknown(receiver_ty) {
52 postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text))
53 .add_to(acc);
54 postfix_snippet(
55 ctx,
56 "while",
57 "while expr {}",
58 &format!("while {} {{\n$0\n}}", receiver_text),
59 )
60 .add_to(acc);
61 }
62 postfix_snippet(ctx, "not", "!expr", &format!("!{}", receiver_text)).add_to(acc);
63 postfix_snippet(ctx, "ref", "&expr", &format!("&{}", receiver_text)).add_to(acc);
64 postfix_snippet(ctx, "refm", "&mut expr", &format!("&mut {}", receiver_text)).add_to(acc);
65 postfix_snippet(
66 ctx,
67 "match",
68 "match expr {}",
69 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text),
70 )
71 .add_to(acc);
72 postfix_snippet(ctx, "dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)).add_to(acc);
73 postfix_snippet(ctx, "box", "Box::new(expr)", &format!("Box::new({})", receiver_text))
74 .add_to(acc);
75 } 79 }
76} 80}
77 81
78#[cfg(test)] 82#[cfg(test)]
79mod tests { 83mod tests {
80 use crate::completion::{do_completion, CompletionItem, CompletionKind};
81 use insta::assert_debug_snapshot; 84 use insta::assert_debug_snapshot;
82 85
86 use crate::completion::{do_completion, CompletionItem, CompletionKind};
87
83 fn do_postfix_completion(code: &str) -> Vec<CompletionItem> { 88 fn do_postfix_completion(code: &str) -> Vec<CompletionItem> {
84 do_completion(code, CompletionKind::Postfix) 89 do_completion(code, CompletionKind::Postfix)
85 } 90 }
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index afdbee84e..15f000175 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -42,6 +42,8 @@ pub use crate::syntax_bridge::{
42#[derive(Clone, Debug, PartialEq, Eq)] 42#[derive(Clone, Debug, PartialEq, Eq)]
43pub struct MacroRules { 43pub struct MacroRules {
44 pub(crate) rules: Vec<Rule>, 44 pub(crate) rules: Vec<Rule>,
45 /// Highest id of the token we have in TokenMap
46 pub(crate) shift: u32,
45} 47}
46 48
47#[derive(Clone, Debug, PartialEq, Eq)] 49#[derive(Clone, Debug, PartialEq, Eq)]
@@ -50,6 +52,38 @@ pub(crate) struct Rule {
50 pub(crate) rhs: tt::Subtree, 52 pub(crate) rhs: tt::Subtree,
51} 53}
52 54
55// Find the max token id inside a subtree
56fn max_id(subtree: &tt::Subtree) -> Option<u32> {
57 subtree
58 .token_trees
59 .iter()
60 .filter_map(|tt| match tt {
61 tt::TokenTree::Subtree(subtree) => max_id(subtree),
62 tt::TokenTree::Leaf(tt::Leaf::Ident(ident))
63 if ident.id != tt::TokenId::unspecified() =>
64 {
65 Some(ident.id.0)
66 }
67 _ => None,
68 })
69 .max()
70}
71
72/// Shift given TokenTree token id
73fn shift_subtree(tt: &mut tt::Subtree, shift: u32) {
74 for t in tt.token_trees.iter_mut() {
75 match t {
76 tt::TokenTree::Leaf(leaf) => match leaf {
77 tt::Leaf::Ident(ident) if ident.id != tt::TokenId::unspecified() => {
78 ident.id.0 += shift;
79 }
80 _ => (),
81 },
82 tt::TokenTree::Subtree(tt) => shift_subtree(tt, shift),
83 }
84 }
85}
86
53impl MacroRules { 87impl MacroRules {
54 pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> { 88 pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
55 // Note: this parsing can be implemented using mbe machinery itself, by 89 // Note: this parsing can be implemented using mbe machinery itself, by
@@ -72,10 +106,17 @@ impl MacroRules {
72 validate(&rule.lhs)?; 106 validate(&rule.lhs)?;
73 } 107 }
74 108
75 Ok(MacroRules { rules }) 109 // Note that TokenId is started from zero,
110 // We have to add 1 to prevent duplication.
111 let shift = max_id(tt).map_or(0, |it| it + 1);
112 Ok(MacroRules { rules, shift })
76 } 113 }
114
77 pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> { 115 pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
78 mbe_expander::expand(self, tt) 116 // apply shift
117 let mut tt = tt.clone();
118 shift_subtree(&mut tt, self.shift);
119 mbe_expander::expand(self, &tt)
79 } 120 }
80} 121}
81 122
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index f34ab52e1..a23e3afe3 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -59,6 +59,33 @@ mod rule_parsing {
59// * Make it pass :-) 59// * Make it pass :-)
60 60
61#[test] 61#[test]
62fn test_token_id_shift() {
63 let macro_definition = r#"
64macro_rules! foobar {
65 ($e:ident) => { foo bar $e }
66}
67"#;
68 let rules = create_rules(macro_definition);
69 let expansion = expand(&rules, "foobar!(baz);");
70
71 fn get_id(t: &tt::TokenTree) -> Option<u32> {
72 if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t {
73 return Some(ident.id.0);
74 }
75 None
76 }
77
78 assert_eq!(expansion.token_trees.len(), 3);
79 // ($e:ident) => { foo bar $e }
80 // 0 1 2 3 4
81 assert_eq!(get_id(&expansion.token_trees[0]), Some(2));
82 assert_eq!(get_id(&expansion.token_trees[1]), Some(3));
83
84 // So baz should be 5
85 assert_eq!(get_id(&expansion.token_trees[2]), Some(5));
86}
87
88#[test]
62fn test_convert_tt() { 89fn test_convert_tt() {
63 let macro_definition = r#" 90 let macro_definition = r#"
64macro_rules! impl_froms { 91macro_rules! impl_froms {
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index 4ec8ab75a..770b55a9a 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -46,7 +46,7 @@ pub enum Mode {
46/// With verify = false, 46/// With verify = false,
47fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { 47fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> {
48 match fs::read_to_string(path) { 48 match fs::read_to_string(path) {
49 Ok(ref old_contents) if old_contents == contents => { 49 Ok(ref old_contents) if normalize(old_contents) == normalize(contents) => {
50 return Ok(()); 50 return Ok(());
51 } 51 }
52 _ => (), 52 _ => (),
@@ -56,7 +56,11 @@ fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> {
56 } 56 }
57 eprintln!("updating {}", path.display()); 57 eprintln!("updating {}", path.display());
58 fs::write(path, contents)?; 58 fs::write(path, contents)?;
59 Ok(()) 59 return Ok(());
60
61 fn normalize(s: &str) -> String {
62 s.replace("\r\n", "\n")
63 }
60} 64}
61 65
62fn reformat(text: impl std::fmt::Display) -> Result<String> { 66fn reformat(text: impl std::fmt::Display) -> Result<String> {