aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock174
-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_batch/Cargo.toml2
-rw-r--r--crates/ra_cli/Cargo.toml2
-rw-r--r--crates/ra_hir/src/code_model.rs5
-rw-r--r--crates/ra_hir/src/code_model/attrs.rs92
-rw-r--r--crates/ra_hir/src/db.rs8
-rw-r--r--crates/ra_hir/src/expr/scope.rs8
-rw-r--r--crates/ra_hir/src/lib.rs10
-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.rs270
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs10
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs12
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs261
-rw-r--r--crates/ra_hir_def/src/nameres/per_ns.rs8
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs48
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs109
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs27
-rw-r--r--crates/ra_lsp_server/Cargo.toml4
-rw-r--r--crates/ra_parser/src/grammar/types.rs6
-rw-r--r--xtask/src/codegen.rs8
30 files changed, 830 insertions, 774 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3879204d9..b67637fe8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10,14 +10,6 @@ dependencies = [
10 10
11[[package]] 11[[package]]
12name = "arrayvec" 12name = "arrayvec"
13version = "0.4.12"
14source = "registry+https://github.com/rust-lang/crates.io-index"
15dependencies = [
16 "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
17]
18
19[[package]]
20name = "arrayvec"
21version = "0.5.1" 13version = "0.5.1"
22source = "registry+https://github.com/rust-lang/crates.io-index" 14source = "registry+https://github.com/rust-lang/crates.io-index"
23 15
@@ -51,7 +43,7 @@ name = "backtrace-sys"
51version = "0.1.32" 43version = "0.1.32"
52source = "registry+https://github.com/rust-lang/crates.io-index" 44source = "registry+https://github.com/rust-lang/crates.io-index"
53dependencies = [ 45dependencies = [
54 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 46 "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)", 47 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
56] 48]
57 49
@@ -115,7 +107,7 @@ dependencies = [
115 107
116[[package]] 108[[package]]
117name = "cc" 109name = "cc"
118version = "1.0.46" 110version = "1.0.47"
119source = "registry+https://github.com/rust-lang/crates.io-index" 111source = "registry+https://github.com/rust-lang/crates.io-index"
120 112
121[[package]] 113[[package]]
@@ -220,7 +212,7 @@ dependencies = [
220 212
221[[package]] 213[[package]]
222name = "console" 214name = "console"
223version = "0.9.0" 215version = "0.9.1"
224source = "registry+https://github.com/rust-lang/crates.io-index" 216source = "registry+https://github.com/rust-lang/crates.io-index"
225dependencies = [ 217dependencies = [
226 "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 218 "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -235,44 +227,44 @@ dependencies = [
235 227
236[[package]] 228[[package]]
237name = "crossbeam" 229name = "crossbeam"
238version = "0.7.2" 230version = "0.7.3"
239source = "registry+https://github.com/rust-lang/crates.io-index" 231source = "registry+https://github.com/rust-lang/crates.io-index"
240dependencies = [ 232dependencies = [
241 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 233 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
242 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 234 "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
243 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 235 "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
244 "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 236 "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
245 "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 237 "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
246 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 238 "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
247] 239]
248 240
249[[package]] 241[[package]]
250name = "crossbeam-channel" 242name = "crossbeam-channel"
251version = "0.3.9" 243version = "0.4.0"
252source = "registry+https://github.com/rust-lang/crates.io-index" 244source = "registry+https://github.com/rust-lang/crates.io-index"
253dependencies = [ 245dependencies = [
254 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 246 "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
255] 247]
256 248
257[[package]] 249[[package]]
258name = "crossbeam-deque" 250name = "crossbeam-deque"
259version = "0.7.1" 251version = "0.7.2"
260source = "registry+https://github.com/rust-lang/crates.io-index" 252source = "registry+https://github.com/rust-lang/crates.io-index"
261dependencies = [ 253dependencies = [
262 "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 254 "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
263 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 255 "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
264] 256]
265 257
266[[package]] 258[[package]]
267name = "crossbeam-epoch" 259name = "crossbeam-epoch"
268version = "0.7.2" 260version = "0.8.0"
269source = "registry+https://github.com/rust-lang/crates.io-index" 261source = "registry+https://github.com/rust-lang/crates.io-index"
270dependencies = [ 262dependencies = [
271 "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 263 "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
272 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 264 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
273 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 265 "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
274 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 266 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
275 "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 267 "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
276 "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 268 "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
277] 269]
278 270
@@ -285,6 +277,14 @@ dependencies = [
285] 277]
286 278
287[[package]] 279[[package]]
280name = "crossbeam-queue"
281version = "0.2.0"
282source = "registry+https://github.com/rust-lang/crates.io-index"
283dependencies = [
284 "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
285]
286
287[[package]]
288name = "crossbeam-utils" 288name = "crossbeam-utils"
289version = "0.6.6" 289version = "0.6.6"
290source = "registry+https://github.com/rust-lang/crates.io-index" 290source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -294,6 +294,16 @@ dependencies = [
294] 294]
295 295
296[[package]] 296[[package]]
297name = "crossbeam-utils"
298version = "0.7.0"
299source = "registry+https://github.com/rust-lang/crates.io-index"
300dependencies = [
301 "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
302 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
303 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
304]
305
306[[package]]
297name = "derive-new" 307name = "derive-new"
298version = "0.5.8" 308version = "0.5.8"
299source = "registry+https://github.com/rust-lang/crates.io-index" 309source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -354,7 +364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
354 364
355[[package]] 365[[package]]
356name = "flexi_logger" 366name = "flexi_logger"
357version = "0.14.4" 367version = "0.14.5"
358source = "registry+https://github.com/rust-lang/crates.io-index" 368source = "registry+https://github.com/rust-lang/crates.io-index"
359dependencies = [ 369dependencies = [
360 "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", 370 "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -473,7 +483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
473dependencies = [ 483dependencies = [
474 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 484 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
475 "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 485 "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
476 "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 486 "unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
477] 487]
478 488
479[[package]] 489[[package]]
@@ -486,10 +496,10 @@ dependencies = [
486 496
487[[package]] 497[[package]]
488name = "indicatif" 498name = "indicatif"
489version = "0.12.0" 499version = "0.13.0"
490source = "registry+https://github.com/rust-lang/crates.io-index" 500source = "registry+https://github.com/rust-lang/crates.io-index"
491dependencies = [ 501dependencies = [
492 "console 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 502 "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)", 503 "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)", 504 "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)", 505 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -518,7 +528,7 @@ name = "insta"
518version = "0.12.0" 528version = "0.12.0"
519source = "registry+https://github.com/rust-lang/crates.io-index" 529source = "registry+https://github.com/rust-lang/crates.io-index"
520dependencies = [ 530dependencies = [
521 "console 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 531 "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)", 532 "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)", 533 "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)", 534 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -563,7 +573,7 @@ name = "jemalloc-sys"
563version = "0.3.2" 573version = "0.3.2"
564source = "registry+https://github.com/rust-lang/crates.io-index" 574source = "registry+https://github.com/rust-lang/crates.io-index"
565dependencies = [ 575dependencies = [
566 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 576 "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)", 577 "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)", 578 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
569] 579]
@@ -639,10 +649,10 @@ dependencies = [
639 649
640[[package]] 650[[package]]
641name = "lsp-server" 651name = "lsp-server"
642version = "0.2.0" 652version = "0.3.0"
643source = "registry+https://github.com/rust-lang/crates.io-index" 653source = "registry+https://github.com/rust-lang/crates.io-index"
644dependencies = [ 654dependencies = [
645 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 655 "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
646 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 656 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
647 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 657 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
648 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 658 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -666,13 +676,18 @@ version = "0.1.8"
666source = "registry+https://github.com/rust-lang/crates.io-index" 676source = "registry+https://github.com/rust-lang/crates.io-index"
667 677
668[[package]] 678[[package]]
679name = "maybe-uninit"
680version = "2.0.0"
681source = "registry+https://github.com/rust-lang/crates.io-index"
682
683[[package]]
669name = "memchr" 684name = "memchr"
670version = "2.2.1" 685version = "2.2.1"
671source = "registry+https://github.com/rust-lang/crates.io-index" 686source = "registry+https://github.com/rust-lang/crates.io-index"
672 687
673[[package]] 688[[package]]
674name = "memoffset" 689name = "memoffset"
675version = "0.5.2" 690version = "0.5.3"
676source = "registry+https://github.com/rust-lang/crates.io-index" 691source = "registry+https://github.com/rust-lang/crates.io-index"
677dependencies = [ 692dependencies = [
678 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 693 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -728,11 +743,6 @@ dependencies = [
728] 743]
729 744
730[[package]] 745[[package]]
731name = "nodrop"
732version = "0.1.14"
733source = "registry+https://github.com/rust-lang/crates.io-index"
734
735[[package]]
736name = "notify" 746name = "notify"
737version = "4.0.14" 747version = "4.0.14"
738source = "registry+https://github.com/rust-lang/crates.io-index" 748source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -811,7 +821,7 @@ dependencies = [
811 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 821 "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)", 822 "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)", 823 "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)", 824 "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)", 825 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
816] 826]
817 827
@@ -896,10 +906,10 @@ dependencies = [
896 906
897[[package]] 907[[package]]
898name = "psm" 908name = "psm"
899version = "0.1.5" 909version = "0.1.6"
900source = "registry+https://github.com/rust-lang/crates.io-index" 910source = "registry+https://github.com/rust-lang/crates.io-index"
901dependencies = [ 911dependencies = [
902 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 912 "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
903] 913]
904 914
905[[package]] 915[[package]]
@@ -939,13 +949,13 @@ dependencies = [
939name = "ra_batch" 949name = "ra_batch"
940version = "0.1.0" 950version = "0.1.0"
941dependencies = [ 951dependencies = [
942 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 952 "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
943 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 953 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
944 "ra_db 0.1.0", 954 "ra_db 0.1.0",
945 "ra_hir 0.1.0", 955 "ra_hir 0.1.0",
946 "ra_ide_api 0.1.0", 956 "ra_ide_api 0.1.0",
947 "ra_project_model 0.1.0", 957 "ra_project_model 0.1.0",
948 "ra_vfs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 958 "ra_vfs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
949 "ra_vfs_glob 0.1.0", 959 "ra_vfs_glob 0.1.0",
950 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 960 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
951] 961]
@@ -964,8 +974,8 @@ dependencies = [
964name = "ra_cli" 974name = "ra_cli"
965version = "0.1.0" 975version = "0.1.0"
966dependencies = [ 976dependencies = [
967 "flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", 977 "flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)",
968 "indicatif 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 978 "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)", 979 "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
970 "ra_batch 0.1.0", 980 "ra_batch 0.1.0",
971 "ra_db 0.1.0", 981 "ra_db 0.1.0",
@@ -1087,11 +1097,11 @@ dependencies = [
1087name = "ra_lsp_server" 1097name = "ra_lsp_server"
1088version = "0.1.0" 1098version = "0.1.0"
1089dependencies = [ 1099dependencies = [
1090 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 1100 "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1091 "flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", 1101 "flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)",
1092 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1102 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1093 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1103 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1094 "lsp-server 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1104 "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1095 "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", 1105 "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)",
1096 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 1106 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1097 "ra_ide_api 0.1.0", 1107 "ra_ide_api 0.1.0",
@@ -1099,7 +1109,7 @@ dependencies = [
1099 "ra_project_model 0.1.0", 1109 "ra_project_model 0.1.0",
1100 "ra_syntax 0.1.0", 1110 "ra_syntax 0.1.0",
1101 "ra_text_edit 0.1.0", 1111 "ra_text_edit 0.1.0",
1102 "ra_vfs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 1112 "ra_vfs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1103 "ra_vfs_glob 0.1.0", 1113 "ra_vfs_glob 0.1.0",
1104 "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 1114 "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1105 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1115 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1119,7 +1129,7 @@ dependencies = [
1119 "ra_syntax 0.1.0", 1129 "ra_syntax 0.1.0",
1120 "ra_tt 0.1.0", 1130 "ra_tt 0.1.0",
1121 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1131 "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)", 1132 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
1123 "test_utils 0.1.0", 1133 "test_utils 0.1.0",
1124] 1134]
1125 1135
@@ -1190,10 +1200,10 @@ dependencies = [
1190 1200
1191[[package]] 1201[[package]]
1192name = "ra_vfs" 1202name = "ra_vfs"
1193version = "0.5.0" 1203version = "0.5.1"
1194source = "registry+https://github.com/rust-lang/crates.io-index" 1204source = "registry+https://github.com/rust-lang/crates.io-index"
1195dependencies = [ 1205dependencies = [
1196 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 1206 "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1197 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1207 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1198 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1208 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1199 "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)", 1209 "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1208,7 +1218,7 @@ name = "ra_vfs_glob"
1208version = "0.1.0" 1218version = "0.1.0"
1209dependencies = [ 1219dependencies = [
1210 "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 1220 "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1211 "ra_vfs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 1221 "ra_vfs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1212] 1222]
1213 1223
1214[[package]] 1224[[package]]
@@ -1358,7 +1368,7 @@ name = "rayon"
1358version = "1.2.0" 1368version = "1.2.0"
1359source = "registry+https://github.com/rust-lang/crates.io-index" 1369source = "registry+https://github.com/rust-lang/crates.io-index"
1360dependencies = [ 1370dependencies = [
1361 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1371 "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1362 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 1372 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
1363 "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 1373 "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
1364] 1374]
@@ -1368,7 +1378,7 @@ name = "rayon-core"
1368version = "1.6.0" 1378version = "1.6.0"
1369source = "registry+https://github.com/rust-lang/crates.io-index" 1379source = "registry+https://github.com/rust-lang/crates.io-index"
1370dependencies = [ 1380dependencies = [
1371 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1381 "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1372 "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 1382 "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1373 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 1383 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
1374 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1384 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1476,7 +1486,7 @@ name = "salsa"
1476version = "0.13.2" 1486version = "0.13.2"
1477source = "registry+https://github.com/rust-lang/crates.io-index" 1487source = "registry+https://github.com/rust-lang/crates.io-index"
1478dependencies = [ 1488dependencies = [
1479 "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1489 "crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
1480 "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", 1490 "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
1481 "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1491 "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1482 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1492 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1484,7 +1494,7 @@ dependencies = [
1484 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1494 "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)", 1495 "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)", 1496 "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)", 1497 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
1488] 1498]
1489 1499
1490[[package]] 1500[[package]]
@@ -1581,8 +1591,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1581 1591
1582[[package]] 1592[[package]]
1583name = "smallvec" 1593name = "smallvec"
1584version = "0.6.12" 1594version = "0.6.13"
1585source = "registry+https://github.com/rust-lang/crates.io-index" 1595source = "registry+https://github.com/rust-lang/crates.io-index"
1596dependencies = [
1597 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1598]
1586 1599
1587[[package]] 1600[[package]]
1588name = "smol_str" 1601name = "smol_str"
@@ -1597,10 +1610,10 @@ name = "stacker"
1597version = "0.1.6" 1610version = "0.1.6"
1598source = "registry+https://github.com/rust-lang/crates.io-index" 1611source = "registry+https://github.com/rust-lang/crates.io-index"
1599dependencies = [ 1612dependencies = [
1600 "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", 1613 "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)", 1614 "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)", 1615 "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)", 1616 "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)", 1617 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
1605] 1618]
1606 1619
@@ -1698,10 +1711,10 @@ dependencies = [
1698 1711
1699[[package]] 1712[[package]]
1700name = "unicode-normalization" 1713name = "unicode-normalization"
1701version = "0.1.8" 1714version = "0.1.9"
1702source = "registry+https://github.com/rust-lang/crates.io-index" 1715source = "registry+https://github.com/rust-lang/crates.io-index"
1703dependencies = [ 1716dependencies = [
1704 "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 1717 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
1705] 1718]
1706 1719
1707[[package]] 1720[[package]]
@@ -1832,7 +1845,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1832 1845
1833[metadata] 1846[metadata]
1834"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" 1847"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
1835"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
1836"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" 1848"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
1837"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" 1849"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
1838"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" 1850"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
@@ -1846,7 +1858,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" 1858"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" 1859"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" 1860"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" 1861"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" 1862"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>" 1863"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>" 1864"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
@@ -1857,13 +1869,15 @@ 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" 1869"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" 1870"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" 1871"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" 1872"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" 1873"checksum crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e"
1862"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" 1874"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
1863"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" 1875"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
1864"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" 1876"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
1865"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" 1877"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
1878"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700"
1866"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" 1879"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
1880"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
1867"checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" 1881"checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"
1868"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" 1882"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
1869"checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" 1883"checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f"
@@ -1873,7 +1887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1873"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 1887"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
1874"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" 1888"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469"
1875"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" 1889"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
1876"checksum flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d20d127f22dd09495f5a5de83dc9f51cf90932735b642910062c577082dd3b36" 1890"checksum flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a13ea6b8a4debecf47bf3966d56db0e21366bc3a3649ba159e1a9e6fdd36a4f4"
1877"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 1891"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
1878"checksum format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aea5a5909a74969507051a3b17adc84737e31a5f910559892aedce026f4d53" 1892"checksum format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aea5a5909a74969507051a3b17adc84737e31a5f910559892aedce026f4d53"
1879"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" 1893"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
@@ -1890,7 +1904,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" 1904"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" 1905"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" 1906"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" 1907"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" 1908"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" 1909"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" 1910"checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349"
@@ -1910,16 +1924,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1910"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" 1924"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
1911"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" 1925"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
1912"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 1926"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
1913"checksum lsp-server 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "148cfb1c0b3295c23d9fb4a20fd1b242f5e6f46c525fdcc7f5c0a65710362012" 1927"checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12"
1914"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf" 1928"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" 1929"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
1930"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" 1931"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" 1932"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
1918"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" 1933"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23"
1919"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" 1934"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
1920"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 1935"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
1921"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" 1936"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
1922"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
1923"checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b" 1937"checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b"
1924"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" 1938"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
1925"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" 1939"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
@@ -1938,10 +1952,10 @@ 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" 1952"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" 1953"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" 1954"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" 1955"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" 1956"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" 1957"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" 1958"checksum ra_vfs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a95d3d1edc70a98d9e42f145bc92c2071dfdc532571591c9eac407c0e4feb89"
1945"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 1959"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
1946"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" 1960"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
1947"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 1961"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
@@ -1984,7 +1998,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" 1998"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" 1999"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" 2000"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" 2001"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" 2002"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" 2003"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" 2004"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
@@ -1997,7 +2011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1997"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 2011"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
1998"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" 2012"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150"
1999"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 2013"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
2000"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" 2014"checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf"
2001"checksum unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49f5526225fd8b77342d5986ab5f6055552e9c0776193b5b63fd53b46debfad7" 2015"checksum unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49f5526225fd8b77342d5986ab5f6055552e9c0776193b5b63fd53b46debfad7"
2002"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" 2016"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
2003"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 2017"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
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_batch/Cargo.toml b/crates/ra_batch/Cargo.toml
index c85da7a2c..d08c5ceac 100644
--- a/crates/ra_batch/Cargo.toml
+++ b/crates/ra_batch/Cargo.toml
@@ -7,7 +7,7 @@ authors = ["rust-analyzer developers"]
7[dependencies] 7[dependencies]
8log = "0.4.5" 8log = "0.4.5"
9rustc-hash = "1.0" 9rustc-hash = "1.0"
10crossbeam-channel = "0.3.5" 10crossbeam-channel = "0.4.0"
11 11
12ra_vfs = "0.5.0" 12ra_vfs = "0.5.0"
13ra_vfs_glob = { path = "../ra_vfs_glob" } 13ra_vfs_glob = { path = "../ra_vfs_glob" }
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 181c5d47a..9d0db8024 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -2,6 +2,7 @@
2 2
3pub(crate) mod src; 3pub(crate) mod src;
4pub(crate) mod docs; 4pub(crate) mod docs;
5pub(crate) mod attrs;
5 6
6use std::sync::Arc; 7use std::sync::Arc;
7 8
@@ -30,8 +31,8 @@ use crate::{
30 impl_block::ImplBlock, 31 impl_block::ImplBlock,
31 resolve::{Resolver, Scope, TypeNs}, 32 resolve::{Resolver, Scope, TypeNs},
32 traits::TraitData, 33 traits::TraitData,
33 ty::{InferenceResult, TraitRef}, 34 ty::{InferenceResult, Namespace, TraitRef},
34 Either, HasSource, Name, ScopeDef, Ty, {ImportId, Namespace}, 35 Either, HasSource, ImportId, Name, ScopeDef, Ty,
35}; 36};
36 37
37/// 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/code_model/attrs.rs b/crates/ra_hir/src/code_model/attrs.rs
new file mode 100644
index 000000000..f7db36b66
--- /dev/null
+++ b/crates/ra_hir/src/code_model/attrs.rs
@@ -0,0 +1,92 @@
1//! FIXME: write short doc here
2
3use crate::{
4 db::{AstDatabase, DefDatabase, HirDatabase},
5 Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static,
6 Struct, StructField, Trait, TypeAlias, Union,
7};
8use hir_def::attr::Attr;
9use hir_expand::hygiene::Hygiene;
10use ra_syntax::ast;
11use std::sync::Arc;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum AttrDef {
15 Module(Module),
16 StructField(StructField),
17 Adt(Adt),
18 Function(Function),
19 EnumVariant(EnumVariant),
20 Static(Static),
21 Const(Const),
22 Trait(Trait),
23 TypeAlias(TypeAlias),
24 MacroDef(MacroDef),
25}
26
27impl_froms!(
28 AttrDef: Module,
29 StructField,
30 Adt(Struct, Enum, Union),
31 EnumVariant,
32 Static,
33 Const,
34 Function,
35 Trait,
36 TypeAlias,
37 MacroDef
38);
39
40pub trait Attrs {
41 fn attrs(&self, db: &impl HirDatabase) -> Option<Arc<[Attr]>>;
42}
43
44pub(crate) fn attributes_query(
45 db: &(impl DefDatabase + AstDatabase),
46 def: AttrDef,
47) -> Option<Arc<[Attr]>> {
48 match def {
49 AttrDef::Module(it) => {
50 let src = it.declaration_source(db)?;
51 let hygiene = Hygiene::new(db, src.file_id);
52 Attr::from_attrs_owner(&src.ast, &hygiene)
53 }
54 AttrDef::StructField(it) => match it.source(db).ast {
55 FieldSource::Named(named) => {
56 let src = it.source(db);
57 let hygiene = Hygiene::new(db, src.file_id);
58 Attr::from_attrs_owner(&named, &hygiene)
59 }
60 FieldSource::Pos(..) => None,
61 },
62 AttrDef::Adt(it) => match it {
63 Adt::Struct(it) => attrs_from_ast(it, db),
64 Adt::Enum(it) => attrs_from_ast(it, db),
65 Adt::Union(it) => attrs_from_ast(it, db),
66 },
67 AttrDef::EnumVariant(it) => attrs_from_ast(it, db),
68 AttrDef::Static(it) => attrs_from_ast(it, db),
69 AttrDef::Const(it) => attrs_from_ast(it, db),
70 AttrDef::Function(it) => attrs_from_ast(it, db),
71 AttrDef::Trait(it) => attrs_from_ast(it, db),
72 AttrDef::TypeAlias(it) => attrs_from_ast(it, db),
73 AttrDef::MacroDef(it) => attrs_from_ast(it, db),
74 }
75}
76
77fn attrs_from_ast<T, D>(node: T, db: &D) -> Option<Arc<[Attr]>>
78where
79 T: HasSource,
80 T::Ast: ast::AttrsOwner,
81 D: DefDatabase + AstDatabase,
82{
83 let src = node.source(db);
84 let hygiene = Hygiene::new(db, src.file_id);
85 Attr::from_attrs_owner(&src.ast, &hygiene)
86}
87
88impl<T: Into<AttrDef> + Copy> Attrs for T {
89 fn attrs(&self, db: &impl HirDatabase) -> Option<Arc<[Attr]>> {
90 db.attrs((*self).into())
91 }
92}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index eb66325f7..75c322c99 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -2,6 +2,7 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::attr::Attr;
5use ra_db::salsa; 6use ra_db::salsa;
6use ra_syntax::SmolStr; 7use ra_syntax::SmolStr;
7 8
@@ -14,10 +15,10 @@ use crate::{
14 traits::TraitData, 15 traits::TraitData,
15 ty::{ 16 ty::{
16 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, 17 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate,
17 InferenceResult, Substs, Ty, TypableDef, TypeCtor, 18 InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor,
18 }, 19 },
19 type_alias::TypeAliasData, 20 type_alias::TypeAliasData,
20 Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Namespace, Static, 21 Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static,
21 StructField, Trait, TypeAlias, 22 StructField, Trait, TypeAlias,
22}; 23};
23 24
@@ -75,6 +76,9 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
75 76
76 #[salsa::invoke(crate::code_model::docs::documentation_query)] 77 #[salsa::invoke(crate::code_model::docs::documentation_query)]
77 fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>; 78 fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>;
79
80 #[salsa::invoke(crate::code_model::attrs::attributes_query)]
81 fn attrs(&self, def: crate::AttrDef) -> Option<Arc<[Attr]>>;
78} 82}
79 83
80#[salsa::query_group(HirDatabaseStorage)] 84#[salsa::query_group(HirDatabaseStorage)]
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 3ba99d92d..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;
@@ -61,6 +61,7 @@ use crate::{ids::MacroFileKind, resolve::Resolver};
61pub use crate::{ 61pub use crate::{
62 adt::VariantDef, 62 adt::VariantDef,
63 code_model::{ 63 code_model::{
64 attrs::{AttrDef, Attrs},
64 docs::{DocDef, Docs, Documentation}, 65 docs::{DocDef, Docs, Documentation},
65 src::{HasBodySource, HasSource}, 66 src::{HasBodySource, HasSource},
66 Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, 67 Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
@@ -81,10 +82,7 @@ pub use crate::{
81 82
82pub use hir_def::{ 83pub use hir_def::{
83 builtin_type::BuiltinType, 84 builtin_type::BuiltinType,
84 nameres::{ 85 nameres::{per_ns::PerNs, raw::ImportId},
85 per_ns::{Namespace, PerNs},
86 raw::ImportId,
87 },
88 path::{Path, PathKind}, 86 path::{Path, PathKind},
89 type_ref::Mutability, 87 type_ref::Mutability,
90}; 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..d3ecabb9b 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -14,10 +14,10 @@
14//! 14//!
15//! ## Collecting RawItems 15//! ## Collecting RawItems
16//! 16//!
17//! This happens in the `raw` module, which parses a single source file into a 17//! This happens in the `raw` module, which parses a single source file into a
18//! set of top-level items. Nested imports are desugared to flat imports in 18//! set of top-level items. Nested imports are desugared to flat imports in this
19//! this phase. Macro calls are represented as a triple of (Path, Option<Name>, 19//! phase. Macro calls are represented as a triple of (Path, Option<Name>,
20//! TokenTree). 20//! TokenTree).
21//! 21//!
22//! ## Collecting Modules 22//! ## Collecting Modules
23//! 23//!
@@ -44,14 +44,14 @@
44//! Macros from other crates (including proc-macros) can be used with 44//! Macros from other crates (including proc-macros) can be used with
45//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of 45//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
46//! unexpanded macros. On every iteration, we try to resolve each macro call 46//! unexpanded macros. On every iteration, we try to resolve each macro call
47//! path and, upon success, we run macro expansion and "collect module" phase 47//! path and, upon success, we run macro expansion and "collect module" phase on
48//! on the result 48//! the result
49 49
50// FIXME: review privacy of submodules
51pub mod raw; 50pub mod raw;
52pub mod per_ns; 51pub mod per_ns;
53pub mod collector; 52mod collector;
54pub mod mod_resolution; 53mod mod_resolution;
54mod path_resolution;
55 55
56#[cfg(test)] 56#[cfg(test)]
57mod tests; 57mod tests;
@@ -65,14 +65,15 @@ use ra_db::{CrateId, Edition, FileId};
65use ra_prof::profile; 65use ra_prof::profile;
66use ra_syntax::ast; 66use ra_syntax::ast;
67use rustc_hash::{FxHashMap, FxHashSet}; 67use rustc_hash::{FxHashMap, FxHashSet};
68use test_utils::tested_by;
69 68
70use crate::{ 69use crate::{
71 builtin_type::BuiltinType, 70 builtin_type::BuiltinType,
72 db::DefDatabase2, 71 db::DefDatabase2,
73 nameres::{diagnostics::DefDiagnostic, per_ns::PerNs, raw::ImportId}, 72 nameres::{
74 path::{Path, PathKind}, 73 diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId,
75 AdtId, AstId, CrateModuleId, EnumVariantId, ModuleDefId, ModuleId, TraitId, 74 },
75 path::Path,
76 AstId, CrateModuleId, ModuleDefId, ModuleId, TraitId,
76}; 77};
77 78
78/// Contains all top-level defs from a macro-expanded crate 79/// Contains all top-level defs from a macro-expanded crate
@@ -195,45 +196,6 @@ pub struct Resolution {
195 pub import: Option<ImportId>, 196 pub import: Option<ImportId>,
196} 197}
197 198
198impl Resolution {
199 pub(crate) fn from_macro(macro_: MacroDefId) -> Self {
200 Resolution { def: PerNs::macros(macro_), import: None }
201 }
202}
203
204#[derive(Debug, Clone)]
205struct ResolvePathResult {
206 resolved_def: PerNs,
207 segment_index: Option<usize>,
208 reached_fixedpoint: ReachedFixedPoint,
209}
210
211impl ResolvePathResult {
212 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
213 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
214 }
215
216 fn with(
217 resolved_def: PerNs,
218 reached_fixedpoint: ReachedFixedPoint,
219 segment_index: Option<usize>,
220 ) -> ResolvePathResult {
221 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index }
222 }
223}
224
225#[derive(Debug, Clone, Copy, PartialEq, Eq)]
226enum ResolveMode {
227 Import,
228 Other,
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq)]
232enum ReachedFixedPoint {
233 Yes,
234 No,
235}
236
237impl CrateDefMap { 199impl CrateDefMap {
238 pub(crate) fn crate_def_map_query( 200 pub(crate) fn crate_def_map_query(
239 // Note that this doesn't have `+ AstDatabase`! 201 // Note that this doesn't have `+ AstDatabase`!
@@ -296,210 +258,6 @@ impl CrateDefMap {
296 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); 258 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
297 (res.resolved_def, res.segment_index) 259 (res.resolved_def, res.segment_index)
298 } 260 }
299
300 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
301 // the result.
302 fn resolve_path_fp_with_macro(
303 &self,
304 db: &impl DefDatabase2,
305 mode: ResolveMode,
306 original_module: CrateModuleId,
307 path: &Path,
308 ) -> ResolvePathResult {
309 let mut segments = path.segments.iter().enumerate();
310 let mut curr_per_ns: PerNs = match path.kind {
311 PathKind::DollarCrate(krate) => {
312 if krate == self.krate {
313 tested_by!(macro_dollar_crate_self);
314 PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into())
315 } else {
316 let def_map = db.crate_def_map(krate);
317 let module = ModuleId { krate, module_id: def_map.root };
318 tested_by!(macro_dollar_crate_other);
319 PerNs::types(module.into())
320 }
321 }
322 PathKind::Crate => {
323 PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into())
324 }
325 PathKind::Self_ => {
326 PerNs::types(ModuleId { krate: self.krate, module_id: original_module }.into())
327 }
328 // plain import or absolute path in 2015: crate-relative with
329 // fallback to extern prelude (with the simplification in
330 // rust-lang/rust#57745)
331 // FIXME there must be a nicer way to write this condition
332 PathKind::Plain | PathKind::Abs
333 if self.edition == Edition::Edition2015
334 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
335 {
336 let segment = match segments.next() {
337 Some((_, segment)) => segment,
338 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
339 };
340 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
341 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
342 }
343 PathKind::Plain => {
344 let segment = match segments.next() {
345 Some((_, segment)) => segment,
346 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
347 };
348 log::debug!("resolving {:?} in module", segment);
349 self.resolve_name_in_module(db, original_module, &segment.name)
350 }
351 PathKind::Super => {
352 if let Some(p) = self.modules[original_module].parent {
353 PerNs::types(ModuleId { krate: self.krate, module_id: p }.into())
354 } else {
355 log::debug!("super path in root module");
356 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
357 }
358 }
359 PathKind::Abs => {
360 // 2018-style absolute path -- only extern prelude
361 let segment = match segments.next() {
362 Some((_, segment)) => segment,
363 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
364 };
365 if let Some(def) = self.extern_prelude.get(&segment.name) {
366 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
367 PerNs::types(*def)
368 } else {
369 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
370 }
371 }
372 PathKind::Type(_) => {
373 // This is handled in `infer::infer_path_expr`
374 // The result returned here does not matter
375 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
376 }
377 };
378
379 for (i, segment) in segments {
380 let curr = match curr_per_ns.take_types() {
381 Some(r) => r,
382 None => {
383 // we still have path segments left, but the path so far
384 // didn't resolve in the types namespace => no resolution
385 // (don't break here because `curr_per_ns` might contain
386 // something in the value namespace, and it would be wrong
387 // to return that)
388 return ResolvePathResult::empty(ReachedFixedPoint::No);
389 }
390 };
391 // resolve segment in curr
392
393 curr_per_ns = match curr {
394 ModuleDefId::ModuleId(module) => {
395 if module.krate != self.krate {
396 let path =
397 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
398 log::debug!("resolving {:?} in other crate", path);
399 let defp_map = db.crate_def_map(module.krate);
400 let (def, s) = defp_map.resolve_path(db, module.module_id, &path);
401 return ResolvePathResult::with(
402 def,
403 ReachedFixedPoint::Yes,
404 s.map(|s| s + i),
405 );
406 }
407
408 // Since it is a qualified path here, it should not contains legacy macros
409 match self[module.module_id].scope.get(&segment.name) {
410 Some(res) => res.def,
411 _ => {
412 log::debug!("path segment {:?} not found", segment.name);
413 return ResolvePathResult::empty(ReachedFixedPoint::No);
414 }
415 }
416 }
417 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
418 // enum variant
419 tested_by!(can_import_enum_variant);
420 let enum_data = db.enum_data(e);
421 match enum_data.variant(&segment.name) {
422 Some(local_id) => {
423 let variant = EnumVariantId { parent: e, local_id };
424 PerNs::both(variant.into(), variant.into())
425 }
426 None => {
427 return ResolvePathResult::with(
428 PerNs::types(e.into()),
429 ReachedFixedPoint::Yes,
430 Some(i),
431 );
432 }
433 }
434 }
435 s => {
436 // could be an inherent method call in UFCS form
437 // (`Struct::method`), or some other kind of associated item
438 log::debug!(
439 "path segment {:?} resolved to non-module {:?}, but is not last",
440 segment.name,
441 curr,
442 );
443
444 return ResolvePathResult::with(
445 PerNs::types(s),
446 ReachedFixedPoint::Yes,
447 Some(i),
448 );
449 }
450 };
451 }
452 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
453 }
454
455 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs {
456 let from_crate_root =
457 self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
458 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
459
460 from_crate_root.or(from_extern_prelude)
461 }
462
463 pub(crate) fn resolve_name_in_module(
464 &self,
465 db: &impl DefDatabase2,
466 module: CrateModuleId,
467 name: &Name,
468 ) -> PerNs {
469 // Resolve in:
470 // - legacy scope of macro
471 // - current module / scope
472 // - extern prelude
473 // - std prelude
474 let from_legacy_macro =
475 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
476 let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
477 let from_extern_prelude =
478 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
479 let from_prelude = self.resolve_in_prelude(db, name);
480
481 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
482 }
483
484 fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
485 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
486 }
487
488 fn resolve_in_prelude(&self, db: &impl DefDatabase2, name: &Name) -> PerNs {
489 if let Some(prelude) = self.prelude {
490 let keep;
491 let def_map = if prelude.krate == self.krate {
492 self
493 } else {
494 // Extend lifetime
495 keep = db.crate_def_map(prelude.krate);
496 &keep
497 };
498 def_map[prelude.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
499 } else {
500 PerNs::none()
501 }
502 }
503} 261}
504 262
505mod diagnostics { 263mod diagnostics {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 3b61d9895..aacd50df8 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -14,8 +14,8 @@ use crate::{
14 attr::Attr, 14 attr::Attr,
15 db::DefDatabase2, 15 db::DefDatabase2,
16 nameres::{ 16 nameres::{
17 diagnostics::DefDiagnostic, mod_resolution::ModDir, per_ns::PerNs, raw, CrateDefMap, 17 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
18 ModuleData, ReachedFixedPoint, Resolution, ResolveMode, 18 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
19 }, 19 },
20 path::{Path, PathKind}, 20 path::{Path, PathKind},
21 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, 21 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId,
@@ -182,7 +182,11 @@ where
182 // In Rust, `#[macro_export]` macros are unconditionally visible at the 182 // In Rust, `#[macro_export]` macros are unconditionally visible at the
183 // crate root, even if the parent modules is **not** visible. 183 // crate root, even if the parent modules is **not** visible.
184 if export { 184 if export {
185 self.update(self.def_map.root, None, &[(name, Resolution::from_macro(macro_))]); 185 self.update(
186 self.def_map.root,
187 None,
188 &[(name, Resolution { def: PerNs::macros(macro_), import: None })],
189 );
186 } 190 }
187 } 191 }
188 192
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/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
new file mode 100644
index 000000000..95692f826
--- /dev/null
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -0,0 +1,261 @@
1//! This modules implements a function to resolve a path `foo::bar::baz` to a
2//! def, which is used within the name resolution.
3//!
4//! When name resolution is finished, the result of resolving a path is either
5//! `Some(def)` or `None`. However, when we are in process of resolving imports
6//! or macros, there's a third possibility:
7//!
8//! I can't resolve this path right now, but I might be resolve this path
9//! later, when more macros are expanded.
10//!
11//! `ReachedFixedPoint` signals about this.
12
13use hir_expand::name::Name;
14use ra_db::Edition;
15use test_utils::tested_by;
16
17use crate::{
18 db::DefDatabase2,
19 nameres::{per_ns::PerNs, CrateDefMap},
20 path::{Path, PathKind},
21 AdtId, CrateModuleId, EnumVariantId, ModuleDefId, ModuleId,
22};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub(super) enum ResolveMode {
26 Import,
27 Other,
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub(super) enum ReachedFixedPoint {
32 Yes,
33 No,
34}
35
36#[derive(Debug, Clone)]
37pub(super) struct ResolvePathResult {
38 pub(super) resolved_def: PerNs,
39 pub(super) segment_index: Option<usize>,
40 pub(super) reached_fixedpoint: ReachedFixedPoint,
41}
42
43impl ResolvePathResult {
44 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
45 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
46 }
47
48 fn with(
49 resolved_def: PerNs,
50 reached_fixedpoint: ReachedFixedPoint,
51 segment_index: Option<usize>,
52 ) -> ResolvePathResult {
53 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index }
54 }
55}
56
57impl CrateDefMap {
58 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
59 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
60 }
61
62 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
63 // the result.
64 pub(super) fn resolve_path_fp_with_macro(
65 &self,
66 db: &impl DefDatabase2,
67 mode: ResolveMode,
68 original_module: CrateModuleId,
69 path: &Path,
70 ) -> ResolvePathResult {
71 let mut segments = path.segments.iter().enumerate();
72 let mut curr_per_ns: PerNs = match path.kind {
73 PathKind::DollarCrate(krate) => {
74 if krate == self.krate {
75 tested_by!(macro_dollar_crate_self);
76 PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into())
77 } else {
78 let def_map = db.crate_def_map(krate);
79 let module = ModuleId { krate, module_id: def_map.root };
80 tested_by!(macro_dollar_crate_other);
81 PerNs::types(module.into())
82 }
83 }
84 PathKind::Crate => {
85 PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into())
86 }
87 PathKind::Self_ => {
88 PerNs::types(ModuleId { krate: self.krate, module_id: original_module }.into())
89 }
90 // plain import or absolute path in 2015: crate-relative with
91 // fallback to extern prelude (with the simplification in
92 // rust-lang/rust#57745)
93 // FIXME there must be a nicer way to write this condition
94 PathKind::Plain | PathKind::Abs
95 if self.edition == Edition::Edition2015
96 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
97 {
98 let segment = match segments.next() {
99 Some((_, segment)) => segment,
100 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
101 };
102 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
103 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
104 }
105 PathKind::Plain => {
106 let segment = match segments.next() {
107 Some((_, segment)) => segment,
108 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
109 };
110 log::debug!("resolving {:?} in module", segment);
111 self.resolve_name_in_module(db, original_module, &segment.name)
112 }
113 PathKind::Super => {
114 if let Some(p) = self.modules[original_module].parent {
115 PerNs::types(ModuleId { krate: self.krate, module_id: p }.into())
116 } else {
117 log::debug!("super path in root module");
118 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
119 }
120 }
121 PathKind::Abs => {
122 // 2018-style absolute path -- only extern prelude
123 let segment = match segments.next() {
124 Some((_, segment)) => segment,
125 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
126 };
127 if let Some(def) = self.extern_prelude.get(&segment.name) {
128 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
129 PerNs::types(*def)
130 } else {
131 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
132 }
133 }
134 PathKind::Type(_) => {
135 // This is handled in `infer::infer_path_expr`
136 // The result returned here does not matter
137 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
138 }
139 };
140
141 for (i, segment) in segments {
142 let curr = match curr_per_ns.take_types() {
143 Some(r) => r,
144 None => {
145 // we still have path segments left, but the path so far
146 // didn't resolve in the types namespace => no resolution
147 // (don't break here because `curr_per_ns` might contain
148 // something in the value namespace, and it would be wrong
149 // to return that)
150 return ResolvePathResult::empty(ReachedFixedPoint::No);
151 }
152 };
153 // resolve segment in curr
154
155 curr_per_ns = match curr {
156 ModuleDefId::ModuleId(module) => {
157 if module.krate != self.krate {
158 let path =
159 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
160 log::debug!("resolving {:?} in other crate", path);
161 let defp_map = db.crate_def_map(module.krate);
162 let (def, s) = defp_map.resolve_path(db, module.module_id, &path);
163 return ResolvePathResult::with(
164 def,
165 ReachedFixedPoint::Yes,
166 s.map(|s| s + i),
167 );
168 }
169
170 // Since it is a qualified path here, it should not contains legacy macros
171 match self[module.module_id].scope.get(&segment.name) {
172 Some(res) => res.def,
173 _ => {
174 log::debug!("path segment {:?} not found", segment.name);
175 return ResolvePathResult::empty(ReachedFixedPoint::No);
176 }
177 }
178 }
179 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
180 // enum variant
181 tested_by!(can_import_enum_variant);
182 let enum_data = db.enum_data(e);
183 match enum_data.variant(&segment.name) {
184 Some(local_id) => {
185 let variant = EnumVariantId { parent: e, local_id };
186 PerNs::both(variant.into(), variant.into())
187 }
188 None => {
189 return ResolvePathResult::with(
190 PerNs::types(e.into()),
191 ReachedFixedPoint::Yes,
192 Some(i),
193 );
194 }
195 }
196 }
197 s => {
198 // could be an inherent method call in UFCS form
199 // (`Struct::method`), or some other kind of associated item
200 log::debug!(
201 "path segment {:?} resolved to non-module {:?}, but is not last",
202 segment.name,
203 curr,
204 );
205
206 return ResolvePathResult::with(
207 PerNs::types(s),
208 ReachedFixedPoint::Yes,
209 Some(i),
210 );
211 }
212 };
213 }
214 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
215 }
216
217 fn resolve_name_in_module(
218 &self,
219 db: &impl DefDatabase2,
220 module: CrateModuleId,
221 name: &Name,
222 ) -> PerNs {
223 // Resolve in:
224 // - legacy scope of macro
225 // - current module / scope
226 // - extern prelude
227 // - std prelude
228 let from_legacy_macro =
229 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
230 let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
231 let from_extern_prelude =
232 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
233 let from_prelude = self.resolve_in_prelude(db, name);
234
235 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
236 }
237
238 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs {
239 let from_crate_root =
240 self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
241 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
242
243 from_crate_root.or(from_extern_prelude)
244 }
245
246 fn resolve_in_prelude(&self, db: &impl DefDatabase2, name: &Name) -> PerNs {
247 if let Some(prelude) = self.prelude {
248 let keep;
249 let def_map = if prelude.krate == self.krate {
250 self
251 } else {
252 // Extend lifetime
253 keep = db.crate_def_map(prelude.krate);
254 &keep
255 };
256 def_map[prelude.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
257 } else {
258 PerNs::none()
259 }
260 }
261}
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_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index cb47fa317..369376f30 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -88,7 +88,7 @@ impl RawItems {
88 (Arc::new(collector.raw_items), Arc::new(collector.source_map)) 88 (Arc::new(collector.raw_items), Arc::new(collector.source_map))
89 } 89 }
90 90
91 pub fn items(&self) -> &[RawItem] { 91 pub(super) fn items(&self) -> &[RawItem] {
92 &self.items 92 &self.items
93 } 93 }
94} 94}
@@ -125,19 +125,19 @@ impl Index<Macro> for RawItems {
125type Attrs = Option<Arc<[Attr]>>; 125type Attrs = Option<Arc<[Attr]>>;
126 126
127#[derive(Debug, PartialEq, Eq, Clone)] 127#[derive(Debug, PartialEq, Eq, Clone)]
128pub struct RawItem { 128pub(super) struct RawItem {
129 attrs: Attrs, 129 attrs: Attrs,
130 pub kind: RawItemKind, 130 pub(super) kind: RawItemKind,
131} 131}
132 132
133impl RawItem { 133impl RawItem {
134 pub fn attrs(&self) -> &[Attr] { 134 pub(super) fn attrs(&self) -> &[Attr] {
135 self.attrs.as_ref().map_or(&[], |it| &*it) 135 self.attrs.as_ref().map_or(&[], |it| &*it)
136 } 136 }
137} 137}
138 138
139#[derive(Debug, PartialEq, Eq, Clone, Copy)] 139#[derive(Debug, PartialEq, Eq, Clone, Copy)]
140pub enum RawItemKind { 140pub(super) enum RawItemKind {
141 Module(Module), 141 Module(Module),
142 Import(ImportId), 142 Import(ImportId),
143 Def(Def), 143 Def(Def),
@@ -145,11 +145,11 @@ pub enum RawItemKind {
145} 145}
146 146
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
148pub struct Module(RawId); 148pub(super) struct Module(RawId);
149impl_arena_id!(Module); 149impl_arena_id!(Module);
150 150
151#[derive(Debug, PartialEq, Eq)] 151#[derive(Debug, PartialEq, Eq)]
152pub enum ModuleData { 152pub(super) enum ModuleData {
153 Declaration { name: Name, ast_id: FileAstId<ast::Module> }, 153 Declaration { name: Name, ast_id: FileAstId<ast::Module> },
154 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 154 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
155} 155}
@@ -160,26 +160,26 @@ impl_arena_id!(ImportId);
160 160
161#[derive(Debug, Clone, PartialEq, Eq)] 161#[derive(Debug, Clone, PartialEq, Eq)]
162pub struct ImportData { 162pub struct ImportData {
163 pub path: Path, 163 pub(super) path: Path,
164 pub alias: Option<Name>, 164 pub(super) alias: Option<Name>,
165 pub is_glob: bool, 165 pub(super) is_glob: bool,
166 pub is_prelude: bool, 166 pub(super) is_prelude: bool,
167 pub is_extern_crate: bool, 167 pub(super) is_extern_crate: bool,
168 pub is_macro_use: bool, 168 pub(super) is_macro_use: bool,
169} 169}
170 170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 171#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
172pub struct Def(RawId); 172pub(super) struct Def(RawId);
173impl_arena_id!(Def); 173impl_arena_id!(Def);
174 174
175#[derive(Debug, PartialEq, Eq)] 175#[derive(Debug, PartialEq, Eq)]
176pub struct DefData { 176pub(super) struct DefData {
177 pub name: Name, 177 pub(super) name: Name,
178 pub kind: DefKind, 178 pub(super) kind: DefKind,
179} 179}
180 180
181#[derive(Debug, PartialEq, Eq, Clone, Copy)] 181#[derive(Debug, PartialEq, Eq, Clone, Copy)]
182pub enum DefKind { 182pub(super) enum DefKind {
183 Function(FileAstId<ast::FnDef>), 183 Function(FileAstId<ast::FnDef>),
184 Struct(FileAstId<ast::StructDef>), 184 Struct(FileAstId<ast::StructDef>),
185 Union(FileAstId<ast::StructDef>), 185 Union(FileAstId<ast::StructDef>),
@@ -191,15 +191,15 @@ pub enum DefKind {
191} 191}
192 192
193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
194pub struct Macro(RawId); 194pub(super) struct Macro(RawId);
195impl_arena_id!(Macro); 195impl_arena_id!(Macro);
196 196
197#[derive(Debug, PartialEq, Eq)] 197#[derive(Debug, PartialEq, Eq)]
198pub struct MacroData { 198pub(super) struct MacroData {
199 pub ast_id: FileAstId<ast::MacroCall>, 199 pub(super) ast_id: FileAstId<ast::MacroCall>,
200 pub path: Path, 200 pub(super) path: Path,
201 pub name: Option<Name>, 201 pub(super) name: Option<Name>,
202 pub export: bool, 202 pub(super) export: bool,
203} 203}
204 204
205struct RawItemsCollector { 205struct RawItemsCollector {
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_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index cb55d1875..d861303b7 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -1,8 +1,8 @@
1//! This modules takes care of rendering various definitions as completion items. 1//! This modules takes care of rendering various definitions as completion items.
2 2
3use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; 3use hir::{db::HirDatabase, Attrs, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
4use join_to_string::join; 4use join_to_string::join;
5use ra_syntax::ast::{AttrsOwner, NameOwner}; 5use ra_syntax::ast::NameOwner;
6use test_utils::tested_by; 6use test_utils::tested_by;
7 7
8use crate::completion::{ 8use crate::completion::{
@@ -18,11 +18,7 @@ impl Completions {
18 field: hir::StructField, 18 field: hir::StructField,
19 substs: &hir::Substs, 19 substs: &hir::Substs,
20 ) { 20 ) {
21 let ast_node = field.source(ctx.db).ast; 21 let is_deprecated = is_deprecated(field, ctx.db);
22 let is_deprecated = match ast_node {
23 hir::FieldSource::Named(m) => is_deprecated(m),
24 hir::FieldSource::Pos(m) => is_deprecated(m),
25 };
26 CompletionItem::new( 22 CompletionItem::new(
27 CompletionKind::Reference, 23 CompletionKind::Reference,
28 ctx.source_range(), 24 ctx.source_range(),
@@ -185,7 +181,7 @@ impl Completions {
185 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), &macro_declaration) 181 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), &macro_declaration)
186 .kind(CompletionItemKind::Macro) 182 .kind(CompletionItemKind::Macro)
187 .set_documentation(docs.clone()) 183 .set_documentation(docs.clone())
188 .set_deprecated(is_deprecated(ast_node)) 184 .set_deprecated(is_deprecated(macro_, ctx.db))
189 .detail(detail); 185 .detail(detail);
190 186
191 builder = if ctx.use_item_syntax.is_some() { 187 builder = if ctx.use_item_syntax.is_some() {
@@ -218,7 +214,7 @@ impl Completions {
218 CompletionItemKind::Function 214 CompletionItemKind::Function
219 }) 215 })
220 .set_documentation(func.docs(ctx.db)) 216 .set_documentation(func.docs(ctx.db))
221 .set_deprecated(is_deprecated(ast_node)) 217 .set_deprecated(is_deprecated(func, ctx.db))
222 .detail(detail); 218 .detail(detail);
223 219
224 // Add `<>` for generic types 220 // Add `<>` for generic types
@@ -250,7 +246,7 @@ impl Completions {
250 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) 246 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
251 .kind(CompletionItemKind::Const) 247 .kind(CompletionItemKind::Const)
252 .set_documentation(constant.docs(ctx.db)) 248 .set_documentation(constant.docs(ctx.db))
253 .set_deprecated(is_deprecated(ast_node)) 249 .set_deprecated(is_deprecated(constant, ctx.db))
254 .detail(detail) 250 .detail(detail)
255 .add_to(self); 251 .add_to(self);
256 } 252 }
@@ -266,13 +262,13 @@ impl Completions {
266 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) 262 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
267 .kind(CompletionItemKind::TypeAlias) 263 .kind(CompletionItemKind::TypeAlias)
268 .set_documentation(type_alias.docs(ctx.db)) 264 .set_documentation(type_alias.docs(ctx.db))
269 .set_deprecated(is_deprecated(type_def)) 265 .set_deprecated(is_deprecated(type_alias, ctx.db))
270 .detail(detail) 266 .detail(detail)
271 .add_to(self); 267 .add_to(self);
272 } 268 }
273 269
274 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { 270 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
275 let is_deprecated = is_deprecated(variant.source(ctx.db).ast); 271 let is_deprecated = is_deprecated(variant, ctx.db);
276 let name = match variant.name(ctx.db) { 272 let name = match variant.name(ctx.db) {
277 Some(it) => it, 273 Some(it) => it,
278 None => return, 274 None => return,
@@ -291,8 +287,11 @@ impl Completions {
291 } 287 }
292} 288}
293 289
294fn is_deprecated(node: impl AttrsOwner) -> bool { 290fn is_deprecated(node: impl Attrs, db: &impl HirDatabase) -> bool {
295 node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated") 291 match node.attrs(db) {
292 None => false,
293 Some(attrs) => attrs.iter().any(|x| x.is_simple_atom("deprecated")),
294 }
296} 295}
297 296
298fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { 297fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index dd4d3bf9a..743f6a60a 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -9,7 +9,7 @@ threadpool = "1.7.1"
9relative-path = "1.0.0" 9relative-path = "1.0.0"
10serde_json = "1.0.34" 10serde_json = "1.0.34"
11serde = { version = "1.0.83", features = ["derive"] } 11serde = { version = "1.0.83", features = ["derive"] }
12crossbeam-channel = "0.3.5" 12crossbeam-channel = "0.4"
13flexi_logger = "0.14.0" 13flexi_logger = "0.14.0"
14log = "0.4.3" 14log = "0.4.3"
15lsp-types = { version = "0.61.0", features = ["proposed"] } 15lsp-types = { version = "0.61.0", features = ["proposed"] }
@@ -20,7 +20,7 @@ ra_vfs = "0.5.0"
20ra_syntax = { path = "../ra_syntax" } 20ra_syntax = { path = "../ra_syntax" }
21ra_text_edit = { path = "../ra_text_edit" } 21ra_text_edit = { path = "../ra_text_edit" }
22ra_ide_api = { path = "../ra_ide_api" } 22ra_ide_api = { path = "../ra_ide_api" }
23lsp-server = "0.2.0" 23lsp-server = "0.3.0"
24ra_project_model = { path = "../ra_project_model" } 24ra_project_model = { path = "../ra_project_model" }
25ra_prof = { path = "../ra_prof" } 25ra_prof = { path = "../ra_prof" }
26ra_vfs_glob = { path = "../ra_vfs_glob" } 26ra_vfs_glob = { path = "../ra_vfs_glob" }
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index d4ca94fca..9b2e440fb 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -28,7 +28,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
28 T![fn] | T![unsafe] | T![extern] => fn_pointer_type(p), 28 T![fn] | T![unsafe] | T![extern] => fn_pointer_type(p),
29 T![for] => for_type(p), 29 T![for] => for_type(p),
30 T![impl] => impl_trait_type(p), 30 T![impl] => impl_trait_type(p),
31 T![dyn ] => dyn_trait_type(p), 31 T![dyn] => dyn_trait_type(p),
32 // Some path types are not allowed to have bounds (no plus) 32 // Some path types are not allowed to have bounds (no plus)
33 T![<] => path_type_(p, allow_bounds), 33 T![<] => path_type_(p, allow_bounds),
34 _ if paths::is_use_path_start(p) => path_or_macro_type_(p, allow_bounds), 34 _ if paths::is_use_path_start(p) => path_or_macro_type_(p, allow_bounds),
@@ -234,9 +234,9 @@ fn impl_trait_type(p: &mut Parser) {
234// test dyn_trait_type 234// test dyn_trait_type
235// type A = dyn Iterator<Item=Foo<'a>> + 'a; 235// type A = dyn Iterator<Item=Foo<'a>> + 'a;
236fn dyn_trait_type(p: &mut Parser) { 236fn dyn_trait_type(p: &mut Parser) {
237 assert!(p.at(T![dyn ])); 237 assert!(p.at(T![dyn]));
238 let m = p.start(); 238 let m = p.start();
239 p.bump(T![dyn ]); 239 p.bump(T![dyn]);
240 type_params::bounds_without_colon(p); 240 type_params::bounds_without_colon(p);
241 m.complete(p, DYN_TRAIT_TYPE); 241 m.complete(p, DYN_TRAIT_TYPE);
242} 242}
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> {