aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock117
-rw-r--r--crates/ra_assists/src/ast_editor.rs30
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/move_bounds.rs135
-rw-r--r--crates/ra_hir/src/nameres.rs1
-rw-r--r--crates/ra_hir/src/nameres/collector.rs190
-rw-r--r--crates/ra_hir/src/nameres/mod_resolution.rs182
-rw-r--r--crates/ra_hir/src/nameres/tests.rs2
-rw-r--r--crates/ra_hir/src/nameres/tests/mod_resolution.rs (renamed from crates/ra_hir/src/nameres/tests/mods.rs)0
-rw-r--r--crates/ra_ide_api/src/lib.rs4
-rw-r--r--crates/ra_ide_api/src/references.rs154
-rw-r--r--crates/ra_ide_api/src/syntax_tree.rs714
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs14
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs5
-rw-r--r--crates/ra_project_model/src/lib.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0002_duplicate_shebang.txt2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0035_use_recover.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/err/0035_use_recover.txt54
-rw-r--r--docs/user/features.md10
-rw-r--r--rustfmt.toml1
21 files changed, 938 insertions, 688 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 27e0a82af..904d46b94 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,7 +32,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
32 32
33[[package]] 33[[package]]
34name = "backtrace" 34name = "backtrace"
35version = "0.3.35" 35version = "0.3.37"
36source = "registry+https://github.com/rust-lang/crates.io-index" 36source = "registry+https://github.com/rust-lang/crates.io-index"
37dependencies = [ 37dependencies = [
38 "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", 38 "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -78,7 +78,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
78 78
79[[package]] 79[[package]]
80name = "bstr" 80name = "bstr"
81version = "0.2.7" 81version = "0.2.8"
82source = "registry+https://github.com/rust-lang/crates.io-index" 82source = "registry+https://github.com/rust-lang/crates.io-index"
83dependencies = [ 83dependencies = [
84 "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 84 "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -176,7 +176,7 @@ dependencies = [
176 176
177[[package]] 177[[package]]
178name = "chrono" 178name = "chrono"
179version = "0.4.7" 179version = "0.4.9"
180source = "registry+https://github.com/rust-lang/crates.io-index" 180source = "registry+https://github.com/rust-lang/crates.io-index"
181dependencies = [ 181dependencies = [
182 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 182 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -223,7 +223,7 @@ dependencies = [
223 "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 223 "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
224 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 224 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
225 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 225 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
226 "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 226 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
227 "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 227 "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
228 "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 228 "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
229 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 229 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -252,15 +252,6 @@ dependencies = [
252 252
253[[package]] 253[[package]]
254name = "crossbeam-deque" 254name = "crossbeam-deque"
255version = "0.6.3"
256source = "registry+https://github.com/rust-lang/crates.io-index"
257dependencies = [
258 "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
259 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
260]
261
262[[package]]
263name = "crossbeam-deque"
264version = "0.7.1" 255version = "0.7.1"
265source = "registry+https://github.com/rust-lang/crates.io-index" 256source = "registry+https://github.com/rust-lang/crates.io-index"
266dependencies = [ 257dependencies = [
@@ -303,7 +294,7 @@ name = "derive-new"
303version = "0.5.8" 294version = "0.5.8"
304source = "registry+https://github.com/rust-lang/crates.io-index" 295source = "registry+https://github.com/rust-lang/crates.io-index"
305dependencies = [ 296dependencies = [
306 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 297 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
307 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 298 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
308 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 299 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
309] 300]
@@ -346,7 +337,7 @@ name = "failure"
346version = "0.1.5" 337version = "0.1.5"
347source = "registry+https://github.com/rust-lang/crates.io-index" 338source = "registry+https://github.com/rust-lang/crates.io-index"
348dependencies = [ 339dependencies = [
349 "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", 340 "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
350 "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 341 "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
351] 342]
352 343
@@ -363,12 +354,13 @@ dependencies = [
363 354
364[[package]] 355[[package]]
365name = "filetime" 356name = "filetime"
366version = "0.2.5" 357version = "0.2.7"
367source = "registry+https://github.com/rust-lang/crates.io-index" 358source = "registry+https://github.com/rust-lang/crates.io-index"
368dependencies = [ 359dependencies = [
369 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 360 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
370 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 361 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
371 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 362 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
363 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
372] 364]
373 365
374[[package]] 366[[package]]
@@ -381,10 +373,10 @@ name = "flexi_logger"
381version = "0.14.3" 373version = "0.14.3"
382source = "registry+https://github.com/rust-lang/crates.io-index" 374source = "registry+https://github.com/rust-lang/crates.io-index"
383dependencies = [ 375dependencies = [
384 "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", 376 "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
385 "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 377 "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
386 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 378 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
387 "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 379 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
388 "yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 380 "yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
389] 381]
390 382
@@ -468,10 +460,10 @@ version = "0.4.4"
468source = "registry+https://github.com/rust-lang/crates.io-index" 460source = "registry+https://github.com/rust-lang/crates.io-index"
469dependencies = [ 461dependencies = [
470 "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", 462 "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
471 "bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 463 "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
472 "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 464 "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
473 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 465 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
474 "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 466 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
475] 467]
476 468
477[[package]] 469[[package]]
@@ -506,7 +498,7 @@ dependencies = [
506 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 498 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
507 "number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 499 "number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
508 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 500 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
509 "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 501 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
510] 502]
511 503
512[[package]] 504[[package]]
@@ -749,11 +741,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
749 741
750[[package]] 742[[package]]
751name = "notify" 743name = "notify"
752version = "4.0.12" 744version = "4.0.13"
753source = "registry+https://github.com/rust-lang/crates.io-index" 745source = "registry+https://github.com/rust-lang/crates.io-index"
754dependencies = [ 746dependencies = [
755 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 747 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
756 "filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", 748 "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
757 "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 749 "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
758 "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 750 "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
759 "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 751 "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -800,7 +792,7 @@ dependencies = [
800 792
801[[package]] 793[[package]]
802name = "once_cell" 794name = "once_cell"
803version = "1.0.1" 795version = "1.0.2"
804source = "registry+https://github.com/rust-lang/crates.io-index" 796source = "registry+https://github.com/rust-lang/crates.io-index"
805 797
806[[package]] 798[[package]]
@@ -847,7 +839,7 @@ version = "0.1.6"
847source = "registry+https://github.com/rust-lang/crates.io-index" 839source = "registry+https://github.com/rust-lang/crates.io-index"
848dependencies = [ 840dependencies = [
849 "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", 841 "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
850 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 842 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
851 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 843 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
852 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 844 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
853] 845]
@@ -876,7 +868,7 @@ name = "proc-macro-hack"
876version = "0.5.9" 868version = "0.5.9"
877source = "registry+https://github.com/rust-lang/crates.io-index" 869source = "registry+https://github.com/rust-lang/crates.io-index"
878dependencies = [ 870dependencies = [
879 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 871 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
880 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 872 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
881 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 873 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
882] 874]
@@ -891,7 +883,7 @@ dependencies = [
891 883
892[[package]] 884[[package]]
893name = "proc-macro2" 885name = "proc-macro2"
894version = "1.0.1" 886version = "1.0.2"
895source = "registry+https://github.com/rust-lang/crates.io-index" 887source = "registry+https://github.com/rust-lang/crates.io-index"
896dependencies = [ 888dependencies = [
897 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 889 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -911,7 +903,7 @@ dependencies = [
911 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 903 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
912 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 904 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
913 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 905 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
914 "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 906 "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
915] 907]
916 908
917[[package]] 909[[package]]
@@ -932,7 +924,7 @@ name = "quote"
932version = "1.0.2" 924version = "1.0.2"
933source = "registry+https://github.com/rust-lang/crates.io-index" 925source = "registry+https://github.com/rust-lang/crates.io-index"
934dependencies = [ 926dependencies = [
935 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 927 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
936] 928]
937 929
938[[package]] 930[[package]]
@@ -947,7 +939,7 @@ dependencies = [
947 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 939 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
948 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 940 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
949 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 941 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
950 "once_cell 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 942 "once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
951 "ra_db 0.1.0", 943 "ra_db 0.1.0",
952 "ra_fmt 0.1.0", 944 "ra_fmt 0.1.0",
953 "ra_hir 0.1.0", 945 "ra_hir 0.1.0",
@@ -1017,7 +1009,7 @@ dependencies = [
1017 "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 1009 "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
1018 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", 1010 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
1019 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1011 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1020 "once_cell 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1012 "once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1021 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 1013 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1022 "ra_arena 0.1.0", 1014 "ra_arena 0.1.0",
1023 "ra_db 0.1.0", 1015 "ra_db 0.1.0",
@@ -1049,12 +1041,12 @@ dependencies = [
1049 "ra_syntax 0.1.0", 1041 "ra_syntax 0.1.0",
1050 "ra_text_edit 0.1.0", 1042 "ra_text_edit 0.1.0",
1051 "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1043 "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1052 "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1044 "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1053 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1045 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1054 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1046 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1055 "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 1047 "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1056 "test_utils 0.1.0", 1048 "test_utils 0.1.0",
1057 "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1049 "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1058] 1050]
1059 1051
1060[[package]] 1052[[package]]
@@ -1108,11 +1100,11 @@ dependencies = [
1108name = "ra_prof" 1100name = "ra_prof"
1109version = "0.1.0" 1101version = "0.1.0"
1110dependencies = [ 1102dependencies = [
1111 "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", 1103 "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
1112 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1104 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1113 "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 1105 "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
1114 "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 1106 "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
1115 "once_cell 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1107 "once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1116] 1108]
1117 1109
1118[[package]] 1110[[package]]
@@ -1165,7 +1157,7 @@ version = "0.1.0"
1165dependencies = [ 1157dependencies = [
1166 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", 1158 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
1167 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1159 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1168 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1160 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1169 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1161 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1170 "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1162 "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1171 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1163 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1187,7 +1179,7 @@ dependencies = [
1187 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 1179 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1188 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1180 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1189 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1181 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1190 "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", 1182 "notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
1191 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 1183 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1192 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1184 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1193 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1185 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1347,20 +1339,20 @@ dependencies = [
1347 1339
1348[[package]] 1340[[package]]
1349name = "rayon" 1341name = "rayon"
1350version = "1.1.0" 1342version = "1.2.0"
1351source = "registry+https://github.com/rust-lang/crates.io-index" 1343source = "registry+https://github.com/rust-lang/crates.io-index"
1352dependencies = [ 1344dependencies = [
1353 "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 1345 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1354 "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 1346 "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1355 "rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 1347 "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
1356] 1348]
1357 1349
1358[[package]] 1350[[package]]
1359name = "rayon-core" 1351name = "rayon-core"
1360version = "1.5.0" 1352version = "1.6.0"
1361source = "registry+https://github.com/rust-lang/crates.io-index" 1353source = "registry+https://github.com/rust-lang/crates.io-index"
1362dependencies = [ 1354dependencies = [
1363 "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 1355 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1364 "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 1356 "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1365 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 1357 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
1366 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1358 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1382,18 +1374,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1382 1374
1383[[package]] 1375[[package]]
1384name = "regex" 1376name = "regex"
1385version = "1.2.1" 1377version = "1.3.1"
1386source = "registry+https://github.com/rust-lang/crates.io-index" 1378source = "registry+https://github.com/rust-lang/crates.io-index"
1387dependencies = [ 1379dependencies = [
1388 "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", 1380 "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
1389 "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 1381 "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1390 "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 1382 "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
1391 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1383 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
1392] 1384]
1393 1385
1394[[package]] 1386[[package]]
1395name = "regex-syntax" 1387name = "regex-syntax"
1396version = "0.6.11" 1388version = "0.6.12"
1397source = "registry+https://github.com/rust-lang/crates.io-index" 1389source = "registry+https://github.com/rust-lang/crates.io-index"
1398 1390
1399[[package]] 1391[[package]]
@@ -1477,7 +1469,7 @@ version = "0.13.1"
1477source = "registry+https://github.com/rust-lang/crates.io-index" 1469source = "registry+https://github.com/rust-lang/crates.io-index"
1478dependencies = [ 1470dependencies = [
1479 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1471 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1480 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1472 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1481 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1473 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1482 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1474 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1483] 1475]
@@ -1522,7 +1514,7 @@ name = "serde_derive"
1522version = "1.0.99" 1514version = "1.0.99"
1523source = "registry+https://github.com/rust-lang/crates.io-index" 1515source = "registry+https://github.com/rust-lang/crates.io-index"
1524dependencies = [ 1516dependencies = [
1525 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1517 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1526 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1518 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1527 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1519 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1528] 1520]
@@ -1542,7 +1534,7 @@ name = "serde_repr"
1542version = "0.1.5" 1534version = "0.1.5"
1543source = "registry+https://github.com/rust-lang/crates.io-index" 1535source = "registry+https://github.com/rust-lang/crates.io-index"
1544dependencies = [ 1536dependencies = [
1545 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1537 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1546 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1538 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1547 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1539 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1548] 1540]
@@ -1607,7 +1599,7 @@ name = "syn"
1607version = "1.0.5" 1599version = "1.0.5"
1608source = "registry+https://github.com/rust-lang/crates.io-index" 1600source = "registry+https://github.com/rust-lang/crates.io-index"
1609dependencies = [ 1601dependencies = [
1610 "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1602 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1611 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1603 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1612 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1604 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1613] 1605]
@@ -1694,7 +1686,7 @@ dependencies = [
1694 1686
1695[[package]] 1687[[package]]
1696name = "unicase" 1688name = "unicase"
1697version = "2.4.0" 1689version = "2.5.1"
1698source = "registry+https://github.com/rust-lang/crates.io-index" 1690source = "registry+https://github.com/rust-lang/crates.io-index"
1699dependencies = [ 1691dependencies = [
1700 "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1692 "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1847,13 +1839,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1847"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" 1839"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
1848"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" 1840"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
1849"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" 1841"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
1850"checksum backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55" 1842"checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2"
1851"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" 1843"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
1852"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" 1844"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
1853"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" 1845"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
1854"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" 1846"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
1855"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" 1847"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
1856"checksum bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94cdf78eb7e94c566c1f5dbe2abf8fc70a548fc902942a48c4b3a98b48ca9ade" 1848"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245"
1857"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 1849"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
1858"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" 1850"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
1859"checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" 1851"checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426"
@@ -1864,14 +1856,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1864"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1856"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)" = "<none>"
1865"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1857"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>"
1866"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1858"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>"
1867"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" 1859"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
1868"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" 1860"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
1869"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" 1861"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e"
1870"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 1862"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
1871"checksum console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147390a412132d75d10dd3b7b175a69cf5fd95032f7503c7091b8831ba10242" 1863"checksum console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147390a412132d75d10dd3b7b175a69cf5fd95032f7503c7091b8831ba10242"
1872"checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c" 1864"checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c"
1873"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" 1865"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
1874"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
1875"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" 1866"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
1876"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" 1867"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
1877"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" 1868"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
@@ -1885,7 +1876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1885"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 1876"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
1886"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" 1877"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
1887"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" 1878"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
1888"checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" 1879"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469"
1889"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" 1880"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
1890"checksum flexi_logger 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66473c1b6a0d2a72f6ed983d33021a4c744a1d179e6f4265867b7d0a9dd679c5" 1881"checksum flexi_logger 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66473c1b6a0d2a72f6ed983d33021a4c744a1d179e6f4265867b7d0a9dd679c5"
1891"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 1882"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
@@ -1933,12 +1924,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1933"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 1924"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
1934"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" 1925"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
1935"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" 1926"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
1936"checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" 1927"checksum notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1191efa2b8fe041decb55c238a125b7a1aeb6fad7a525133a02be5ec949ff3cb"
1937"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" 1928"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
1938"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" 1929"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
1939"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" 1930"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
1940"checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee" 1931"checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee"
1941"checksum once_cell 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c9192c5a4c3b5488dae8d3886ef9df6b5eb246d36323dc7a5078595a154e7771" 1932"checksum once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd38c1bb51148ca239ec38ef1bb4f7570d432861f03e91774d53b01c2ba2132f"
1942"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" 1933"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
1943"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" 1934"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
1944"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" 1935"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
@@ -1949,7 +1940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1949"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" 1940"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
1950"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" 1941"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8"
1951"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" 1942"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
1952"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" 1943"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
1953"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f" 1944"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f"
1954"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 1945"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
1955"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" 1946"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
@@ -1971,12 +1962,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1971"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" 1962"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
1972"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6" 1963"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6"
1973"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 1964"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
1974"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" 1965"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
1975"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" 1966"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
1976"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 1967"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
1977"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 1968"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
1978"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" 1969"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
1979"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" 1970"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
1980"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c" 1971"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c"
1981"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" 1972"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
1982"checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5" 1973"checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"
@@ -2011,7 +2002,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2011"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" 2002"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
2012"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" 2003"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
2013"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 2004"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
2014"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" 2005"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150"
2015"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 2006"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
2016"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" 2007"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
2017"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" 2008"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
index 048478662..a710edce8 100644
--- a/crates/ra_assists/src/ast_editor.rs
+++ b/crates/ra_assists/src/ast_editor.rs
@@ -297,6 +297,11 @@ impl AstBuilder<ast::Path> {
297 ast_node_from_file_text(text) 297 ast_node_from_file_text(text)
298 } 298 }
299 299
300 pub fn from_name(name: ast::Name) -> ast::Path {
301 let name = name.syntax().to_string();
302 Self::from_text(name.as_str())
303 }
304
300 pub fn from_pieces(enum_name: ast::Name, var_name: ast::Name) -> ast::Path { 305 pub fn from_pieces(enum_name: ast::Name, var_name: ast::Name) -> ast::Path {
301 Self::from_text(&format!("{}::{}", enum_name.syntax(), var_name.syntax())) 306 Self::from_text(&format!("{}::{}", enum_name.syntax(), var_name.syntax()))
302 } 307 }
@@ -380,6 +385,31 @@ impl AstBuilder<ast::MatchArmList> {
380 } 385 }
381} 386}
382 387
388impl AstBuilder<ast::WherePred> {
389 fn from_text(text: &str) -> ast::WherePred {
390 ast_node_from_file_text(&format!("fn f() where {} {{ }}", text))
391 }
392
393 pub fn from_pieces(
394 path: ast::Path,
395 bounds: impl Iterator<Item = ast::TypeBound>,
396 ) -> ast::WherePred {
397 let bounds = bounds.map(|b| b.syntax().to_string()).collect::<Vec<_>>().join(" + ");
398 Self::from_text(&format!("{}: {}", path.syntax(), bounds))
399 }
400}
401
402impl AstBuilder<ast::WhereClause> {
403 fn from_text(text: &str) -> ast::WhereClause {
404 ast_node_from_file_text(&format!("fn f() where {} {{ }}", text))
405 }
406
407 pub fn from_predicates(preds: impl Iterator<Item = ast::WherePred>) -> ast::WhereClause {
408 let preds = preds.map(|p| p.syntax().to_string()).collect::<Vec<_>>().join(", ");
409 Self::from_text(preds.as_str())
410 }
411}
412
383fn ast_node_from_file_text<N: AstNode>(text: &str) -> N { 413fn ast_node_from_file_text<N: AstNode>(text: &str) -> N {
384 let parse = SourceFile::parse(text); 414 let parse = SourceFile::parse(text);
385 let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); 415 let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap();
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 03eec73ad..10ccc345c 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -102,6 +102,7 @@ mod remove_dbg;
102pub mod auto_import; 102pub mod auto_import;
103mod add_missing_impl_members; 103mod add_missing_impl_members;
104mod move_guard; 104mod move_guard;
105mod move_bounds;
105 106
106fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] { 107fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] {
107 &[ 108 &[
@@ -123,6 +124,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
123 inline_local_variable::inline_local_varialbe, 124 inline_local_variable::inline_local_varialbe,
124 move_guard::move_guard_to_arm_body, 125 move_guard::move_guard_to_arm_body,
125 move_guard::move_arm_cond_to_match_guard, 126 move_guard::move_arm_cond_to_match_guard,
127 move_bounds::move_bounds_to_where_clause,
126 ] 128 ]
127} 129}
128 130
diff --git a/crates/ra_assists/src/move_bounds.rs b/crates/ra_assists/src/move_bounds.rs
new file mode 100644
index 000000000..526de1d98
--- /dev/null
+++ b/crates/ra_assists/src/move_bounds.rs
@@ -0,0 +1,135 @@
1use hir::db::HirDatabase;
2use ra_syntax::{
3 ast::{self, AstNode, NameOwner, TypeBoundsOwner},
4 SyntaxElement,
5 SyntaxKind::*,
6 TextRange,
7};
8
9use crate::{ast_editor::AstBuilder, Assist, AssistCtx, AssistId};
10
11pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
12 let type_param_list = ctx.node_at_offset::<ast::TypeParamList>()?;
13
14 let mut type_params = type_param_list.type_params();
15 if type_params.all(|p| p.type_bound_list().is_none()) {
16 return None;
17 }
18
19 let parent = type_param_list.syntax().parent()?;
20 if parent.children_with_tokens().find(|it| it.kind() == WHERE_CLAUSE).is_some() {
21 return None;
22 }
23
24 let anchor: SyntaxElement = match parent.kind() {
25 FN_DEF => ast::FnDef::cast(parent)?.body()?.syntax().clone().into(),
26 TRAIT_DEF => ast::TraitDef::cast(parent)?.item_list()?.syntax().clone().into(),
27 IMPL_BLOCK => ast::ImplBlock::cast(parent)?.item_list()?.syntax().clone().into(),
28 ENUM_DEF => ast::EnumDef::cast(parent)?.variant_list()?.syntax().clone().into(),
29 STRUCT_DEF => parent
30 .children_with_tokens()
31 .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == SEMI)?,
32 _ => return None,
33 };
34
35 ctx.add_action(
36 AssistId("move_bounds_to_where_clause"),
37 "move_bounds_to_where_clause",
38 |edit| {
39 let type_params = type_param_list.type_params().collect::<Vec<_>>();
40
41 for param in &type_params {
42 if let Some(bounds) = param.type_bound_list() {
43 let colon = param
44 .syntax()
45 .children_with_tokens()
46 .find(|it| it.kind() == COLON)
47 .unwrap();
48 let start = colon.text_range().start();
49 let end = bounds.syntax().text_range().end();
50 edit.delete(TextRange::from_to(start, end));
51 }
52 }
53
54 let predicates = type_params.iter().filter_map(build_predicate);
55 let where_clause = AstBuilder::<ast::WhereClause>::from_predicates(predicates);
56
57 let to_insert = match anchor.prev_sibling_or_token() {
58 Some(ref elem) if elem.kind() == WHITESPACE => {
59 format!("{} ", where_clause.syntax())
60 }
61 _ => format!(" {}", where_clause.syntax()),
62 };
63 edit.insert(anchor.text_range().start(), to_insert);
64 edit.target(type_param_list.syntax().text_range());
65 },
66 );
67
68 ctx.build()
69}
70
71fn build_predicate(param: &ast::TypeParam) -> Option<ast::WherePred> {
72 let path = AstBuilder::<ast::Path>::from_name(param.name()?);
73 let predicate =
74 AstBuilder::<ast::WherePred>::from_pieces(path, param.type_bound_list()?.bounds());
75 Some(predicate)
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 use crate::helpers::check_assist;
83
84 #[test]
85 fn move_bounds_to_where_clause_fn() {
86 check_assist(
87 move_bounds_to_where_clause,
88 r#"
89 fn foo<T: u32, <|>F: FnOnce(T) -> T>() {}
90 "#,
91 r#"
92 fn foo<T, <|>F>() where T: u32, F: FnOnce(T) -> T {}
93 "#,
94 );
95 }
96
97 #[test]
98 fn move_bounds_to_where_clause_impl() {
99 check_assist(
100 move_bounds_to_where_clause,
101 r#"
102 impl<U: u32, <|>T> A<U, T> {}
103 "#,
104 r#"
105 impl<U, <|>T> A<U, T> where U: u32 {}
106 "#,
107 );
108 }
109
110 #[test]
111 fn move_bounds_to_where_clause_struct() {
112 check_assist(
113 move_bounds_to_where_clause,
114 r#"
115 struct A<<|>T: Iterator<Item = u32>> {}
116 "#,
117 r#"
118 struct A<<|>T> where T: Iterator<Item = u32> {}
119 "#,
120 );
121 }
122
123 #[test]
124 fn move_bounds_to_where_clause_tuple_struct() {
125 check_assist(
126 move_bounds_to_where_clause,
127 r#"
128 struct Pair<<|>T: u32>(T, T);
129 "#,
130 r#"
131 struct Pair<<|>T>(T, T) where T: u32;
132 "#,
133 );
134 }
135}
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index f69179bf6..dc2e2172b 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -50,6 +50,7 @@
50mod per_ns; 50mod per_ns;
51mod raw; 51mod raw;
52mod collector; 52mod collector;
53mod mod_resolution;
53#[cfg(test)] 54#[cfg(test)]
54mod tests; 55mod tests;
55 56
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 698e40247..5af26f953 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -1,9 +1,5 @@
1use std::borrow::Cow; 1use ra_db::FileId;
2use std::sync::Arc; 2use ra_syntax::ast;
3
4use ra_db::{FileId, SourceRoot};
5use ra_syntax::{ast, SmolStr};
6use relative_path::RelativePathBuf;
7use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
8use test_utils::tested_by; 4use test_utils::tested_by;
9 5
@@ -12,8 +8,10 @@ use crate::{
12 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, 8 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
13 name::MACRO_RULES, 9 name::MACRO_RULES,
14 nameres::{ 10 nameres::{
15 diagnostics::DefDiagnostic, raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, 11 diagnostics::DefDiagnostic,
16 ModuleDef, PerNs, ReachedFixedPoint, Resolution, ResolveMode, 12 mod_resolution::{resolve_submodule, ParentModule},
13 raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, ModuleDef, PerNs,
14 ReachedFixedPoint, Resolution, ResolveMode,
17 }, 15 },
18 AstId, Const, DefDatabase, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static, 16 AstId, Const, DefDatabase, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static,
19 Struct, Trait, TypeAlias, Union, 17 Struct, Trait, TypeAlias, Union,
@@ -583,7 +581,7 @@ where
583 name, 581 name,
584 is_root, 582 is_root,
585 attr_path.as_ref(), 583 attr_path.as_ref(),
586 self.parent_module.as_ref(), 584 self.parent_module,
587 ) { 585 ) {
588 Ok(file_id) => { 586 Ok(file_id) => {
589 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 587 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
@@ -694,180 +692,6 @@ fn is_macro_rules(path: &Path) -> bool {
694 path.as_ident() == Some(&MACRO_RULES) 692 path.as_ident() == Some(&MACRO_RULES)
695} 693}
696 694
697fn resolve_submodule(
698 db: &impl DefDatabase,
699 file_id: HirFileId,
700 name: &Name,
701 is_root: bool,
702 attr_path: Option<&SmolStr>,
703 parent_module: Option<&ParentModule>,
704) -> Result<FileId, RelativePathBuf> {
705 let file_id = file_id.original_file(db);
706 let source_root_id = db.file_source_root(file_id);
707 let path = db.file_relative_path(file_id);
708 let root = RelativePathBuf::default();
709 let dir_path = path.parent().unwrap_or(&root);
710 let mod_name = path.file_stem().unwrap_or("unknown");
711
712 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
713 (Some(file_path), Some(parent_module)) => {
714 let file_path = normalize_attribute_path(file_path);
715 match parent_module.attribute_path() {
716 Some(parent_module_attr_path) => {
717 let path = dir_path
718 .join(format!(
719 "{}/{}",
720 normalize_attribute_path(parent_module_attr_path),
721 file_path
722 ))
723 .normalize();
724 ResolutionMode::InlineModuleWithAttributePath(
725 InsideInlineModuleMode::WithAttributePath(path),
726 )
727 }
728 None => {
729 let path =
730 dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize();
731 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(
732 path,
733 ))
734 }
735 }
736 }
737 (None, Some(parent_module)) => match parent_module.attribute_path() {
738 Some(parent_module_attr_path) => {
739 let path = dir_path.join(format!(
740 "{}/{}.rs",
741 normalize_attribute_path(parent_module_attr_path),
742 name
743 ));
744 ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path))
745 }
746 None => {
747 let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name));
748 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
749 }
750 },
751 (Some(file_path), None) => {
752 let file_path = normalize_attribute_path(file_path);
753 let path = dir_path.join(file_path.as_ref()).normalize();
754 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
755 }
756 _ => {
757 let is_dir_owner = is_root || mod_name == "mod";
758 if is_dir_owner {
759 let file_mod = dir_path.join(format!("{}.rs", name));
760 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
761 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
762 file: file_mod,
763 directory: dir_mod,
764 })
765 } else {
766 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
767 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
768 }
769 }
770 };
771
772 resolve_mode.resolve(db.source_root(source_root_id))
773}
774
775fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
776 let current_dir = "./";
777 let windows_path_separator = r#"\"#;
778 let current_dir_normalize = if file_path.starts_with(current_dir) {
779 &file_path[current_dir.len()..]
780 } else {
781 file_path.as_str()
782 };
783 if current_dir_normalize.contains(windows_path_separator) {
784 Cow::Owned(current_dir_normalize.replace(windows_path_separator, "/"))
785 } else {
786 Cow::Borrowed(current_dir_normalize)
787 }
788}
789
790enum OutOfLineMode {
791 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
792 FileInDirectory(RelativePathBuf),
793 WithAttributePath(RelativePathBuf),
794}
795
796impl OutOfLineMode {
797 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
798 match self {
799 OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
800 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
801 file_id => resolve_find_result(file_id, file),
802 },
803 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
804 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
805 }
806 }
807}
808
809enum InsideInlineModuleMode {
810 File(RelativePathBuf),
811 WithAttributePath(RelativePathBuf),
812}
813
814impl InsideInlineModuleMode {
815 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
816 match self {
817 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
818 InsideInlineModuleMode::WithAttributePath(path) => {
819 resolve_simple_path(source_root, path)
820 }
821 }
822 }
823}
824
825enum ResolutionMode {
826 OutOfLine(OutOfLineMode),
827 InsideInlineModule(InsideInlineModuleMode),
828 InlineModuleWithAttributePath(InsideInlineModuleMode),
829}
830
831impl ResolutionMode {
832 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
833 use self::ResolutionMode::*;
834
835 match self {
836 OutOfLine(mode) => mode.resolve(source_root),
837 InsideInlineModule(mode) => mode.resolve(source_root),
838 InlineModuleWithAttributePath(mode) => mode.resolve(source_root),
839 }
840 }
841}
842
843fn resolve_simple_path(
844 source_root: Arc<SourceRoot>,
845 path: &RelativePathBuf,
846) -> Result<FileId, RelativePathBuf> {
847 resolve_find_result(source_root.files.get(path), path)
848}
849
850fn resolve_find_result(
851 file_id: Option<&FileId>,
852 path: &RelativePathBuf,
853) -> Result<FileId, RelativePathBuf> {
854 match file_id {
855 Some(file_id) => Ok(file_id.clone()),
856 None => Err(path.clone()),
857 }
858}
859
860struct ParentModule<'a> {
861 name: &'a Name,
862 attr_path: Option<&'a SmolStr>,
863}
864
865impl<'a> ParentModule<'a> {
866 pub fn attribute_path(&self) -> Option<&SmolStr> {
867 self.attr_path.filter(|p| !p.is_empty())
868 }
869}
870
871#[cfg(test)] 695#[cfg(test)]
872mod tests { 696mod tests {
873 use ra_db::SourceDatabase; 697 use ra_db::SourceDatabase;
diff --git a/crates/ra_hir/src/nameres/mod_resolution.rs b/crates/ra_hir/src/nameres/mod_resolution.rs
new file mode 100644
index 000000000..94c9946ff
--- /dev/null
+++ b/crates/ra_hir/src/nameres/mod_resolution.rs
@@ -0,0 +1,182 @@
1use std::{borrow::Cow, sync::Arc};
2
3use ra_db::{FileId, SourceRoot};
4use ra_syntax::SmolStr;
5use relative_path::RelativePathBuf;
6
7use crate::{DefDatabase, HirFileId, Name};
8
9#[derive(Clone, Copy)]
10pub(super) struct ParentModule<'a> {
11 pub(super) name: &'a Name,
12 pub(super) attr_path: Option<&'a SmolStr>,
13}
14
15impl<'a> ParentModule<'a> {
16 fn attribute_path(&self) -> Option<&SmolStr> {
17 self.attr_path.filter(|p| !p.is_empty())
18 }
19}
20
21pub(super) fn resolve_submodule(
22 db: &impl DefDatabase,
23 file_id: HirFileId,
24 name: &Name,
25 is_root: bool,
26 attr_path: Option<&SmolStr>,
27 parent_module: Option<ParentModule<'_>>,
28) -> Result<FileId, RelativePathBuf> {
29 let file_id = file_id.original_file(db);
30 let source_root_id = db.file_source_root(file_id);
31 let path = db.file_relative_path(file_id);
32 let root = RelativePathBuf::default();
33 let dir_path = path.parent().unwrap_or(&root);
34 let mod_name = path.file_stem().unwrap_or("unknown");
35
36 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
37 (Some(file_path), Some(parent_module)) => {
38 let file_path = normalize_attribute_path(file_path);
39 match parent_module.attribute_path() {
40 Some(parent_module_attr_path) => {
41 let path = dir_path
42 .join(format!(
43 "{}/{}",
44 normalize_attribute_path(parent_module_attr_path),
45 file_path
46 ))
47 .normalize();
48 ResolutionMode::InlineModuleWithAttributePath(
49 InsideInlineModuleMode::WithAttributePath(path),
50 )
51 }
52 None => {
53 let path =
54 dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize();
55 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(
56 path,
57 ))
58 }
59 }
60 }
61 (None, Some(parent_module)) => match parent_module.attribute_path() {
62 Some(parent_module_attr_path) => {
63 let path = dir_path.join(format!(
64 "{}/{}.rs",
65 normalize_attribute_path(parent_module_attr_path),
66 name
67 ));
68 ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path))
69 }
70 None => {
71 let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name));
72 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
73 }
74 },
75 (Some(file_path), None) => {
76 let file_path = normalize_attribute_path(file_path);
77 let path = dir_path.join(file_path.as_ref()).normalize();
78 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
79 }
80 _ => {
81 let is_dir_owner = is_root || mod_name == "mod";
82 if is_dir_owner {
83 let file_mod = dir_path.join(format!("{}.rs", name));
84 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
85 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
86 file: file_mod,
87 directory: dir_mod,
88 })
89 } else {
90 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
91 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
92 }
93 }
94 };
95
96 resolve_mode.resolve(db.source_root(source_root_id))
97}
98
99fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
100 let current_dir = "./";
101 let windows_path_separator = r#"\"#;
102 let current_dir_normalize = if file_path.starts_with(current_dir) {
103 &file_path[current_dir.len()..]
104 } else {
105 file_path.as_str()
106 };
107 if current_dir_normalize.contains(windows_path_separator) {
108 Cow::Owned(current_dir_normalize.replace(windows_path_separator, "/"))
109 } else {
110 Cow::Borrowed(current_dir_normalize)
111 }
112}
113
114enum OutOfLineMode {
115 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
116 FileInDirectory(RelativePathBuf),
117 WithAttributePath(RelativePathBuf),
118}
119
120impl OutOfLineMode {
121 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
122 match self {
123 OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
124 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
125 file_id => resolve_find_result(file_id, file),
126 },
127 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
128 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
129 }
130 }
131}
132
133enum InsideInlineModuleMode {
134 File(RelativePathBuf),
135 WithAttributePath(RelativePathBuf),
136}
137
138impl InsideInlineModuleMode {
139 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
140 match self {
141 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
142 InsideInlineModuleMode::WithAttributePath(path) => {
143 resolve_simple_path(source_root, path)
144 }
145 }
146 }
147}
148
149enum ResolutionMode {
150 OutOfLine(OutOfLineMode),
151 InsideInlineModule(InsideInlineModuleMode),
152 InlineModuleWithAttributePath(InsideInlineModuleMode),
153}
154
155impl ResolutionMode {
156 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
157 use self::ResolutionMode::*;
158
159 match self {
160 OutOfLine(mode) => mode.resolve(source_root),
161 InsideInlineModule(mode) => mode.resolve(source_root),
162 InlineModuleWithAttributePath(mode) => mode.resolve(source_root),
163 }
164 }
165}
166
167fn resolve_simple_path(
168 source_root: Arc<SourceRoot>,
169 path: &RelativePathBuf,
170) -> Result<FileId, RelativePathBuf> {
171 resolve_find_result(source_root.files.get(path), path)
172}
173
174fn resolve_find_result(
175 file_id: Option<&FileId>,
176 path: &RelativePathBuf,
177) -> Result<FileId, RelativePathBuf> {
178 match file_id {
179 Some(file_id) => Ok(file_id.clone()),
180 None => Err(path.clone()),
181 }
182}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index c1dbad283..4ff897ca5 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -2,7 +2,7 @@ mod macros;
2mod globs; 2mod globs;
3mod incremental; 3mod incremental;
4mod primitives; 4mod primitives;
5mod mods; 5mod mod_resolution;
6 6
7use std::sync::Arc; 7use std::sync::Arc;
8 8
diff --git a/crates/ra_hir/src/nameres/tests/mods.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
index 4f8398460..4f8398460 100644
--- a/crates/ra_hir/src/nameres/tests/mods.rs
+++ b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 514dcaf96..e90fbd428 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -466,7 +466,7 @@ impl Analysis {
466 &self, 466 &self,
467 position: FilePosition, 467 position: FilePosition,
468 ) -> Cancelable<Option<ReferenceSearchResult>> { 468 ) -> Cancelable<Option<ReferenceSearchResult>> {
469 self.with_db(|db| references::find_all_refs(db, position)) 469 self.with_db(|db| references::find_all_refs(db, position).map(|it| it.info))
470 } 470 }
471 471
472 /// Returns a short text describing element at position. 472 /// Returns a short text describing element at position.
@@ -536,7 +536,7 @@ impl Analysis {
536 &self, 536 &self,
537 position: FilePosition, 537 position: FilePosition,
538 new_name: &str, 538 new_name: &str,
539 ) -> Cancelable<Option<SourceChange>> { 539 ) -> Cancelable<Option<RangeInfo<SourceChange>>> {
540 self.with_db(|db| references::rename(db, position, new_name)) 540 self.with_db(|db| references::rename(db, position, new_name))
541 } 541 }
542 542
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index d8a00067f..5f1f0efc3 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -4,7 +4,7 @@ use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode}
4use relative_path::{RelativePath, RelativePathBuf}; 4use relative_path::{RelativePath, RelativePathBuf};
5 5
6use crate::{ 6use crate::{
7 db::RootDatabase, FileId, FilePosition, FileRange, FileSystemEdit, NavigationTarget, 7 db::RootDatabase, FileId, FilePosition, FileRange, FileSystemEdit, NavigationTarget, RangeInfo,
8 SourceChange, SourceFileEdit, TextRange, 8 SourceChange, SourceFileEdit, TextRange,
9}; 9};
10 10
@@ -48,9 +48,9 @@ impl IntoIterator for ReferenceSearchResult {
48pub(crate) fn find_all_refs( 48pub(crate) fn find_all_refs(
49 db: &RootDatabase, 49 db: &RootDatabase,
50 position: FilePosition, 50 position: FilePosition,
51) -> Option<ReferenceSearchResult> { 51) -> Option<RangeInfo<ReferenceSearchResult>> {
52 let parse = db.parse(position.file_id); 52 let parse = db.parse(position.file_id);
53 let (binding, analyzer) = find_binding(db, &parse.tree(), position)?; 53 let RangeInfo { range, info: (binding, analyzer) } = find_binding(db, &parse.tree(), position)?;
54 let declaration = NavigationTarget::from_bind_pat(position.file_id, &binding); 54 let declaration = NavigationTarget::from_bind_pat(position.file_id, &binding);
55 55
56 let references = analyzer 56 let references = analyzer
@@ -59,24 +59,26 @@ pub(crate) fn find_all_refs(
59 .map(move |ref_desc| FileRange { file_id: position.file_id, range: ref_desc.range }) 59 .map(move |ref_desc| FileRange { file_id: position.file_id, range: ref_desc.range })
60 .collect::<Vec<_>>(); 60 .collect::<Vec<_>>();
61 61
62 return Some(ReferenceSearchResult { declaration, references }); 62 return Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references }));
63 63
64 fn find_binding<'a>( 64 fn find_binding<'a>(
65 db: &RootDatabase, 65 db: &RootDatabase,
66 source_file: &SourceFile, 66 source_file: &SourceFile,
67 position: FilePosition, 67 position: FilePosition,
68 ) -> Option<(ast::BindPat, hir::SourceAnalyzer)> { 68 ) -> Option<RangeInfo<(ast::BindPat, hir::SourceAnalyzer)>> {
69 let syntax = source_file.syntax(); 69 let syntax = source_file.syntax();
70 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) { 70 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
71 let range = binding.syntax().text_range();
71 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, binding.syntax(), None); 72 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, binding.syntax(), None);
72 return Some((binding, analyzer)); 73 return Some(RangeInfo::new(range, (binding, analyzer)));
73 }; 74 };
74 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?; 75 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?;
76 let range = name_ref.syntax().text_range();
75 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None); 77 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
76 let resolved = analyzer.resolve_local_name(&name_ref)?; 78 let resolved = analyzer.resolve_local_name(&name_ref)?;
77 if let Either::A(ptr) = resolved.ptr() { 79 if let Either::A(ptr) = resolved.ptr() {
78 if let ast::Pat::BindPat(binding) = ptr.to_node(source_file.syntax()) { 80 if let ast::Pat::BindPat(binding) = ptr.to_node(source_file.syntax()) {
79 return Some((binding, analyzer)); 81 return Some(RangeInfo::new(range, (binding, analyzer)));
80 } 82 }
81 } 83 }
82 None 84 None
@@ -87,12 +89,14 @@ pub(crate) fn rename(
87 db: &RootDatabase, 89 db: &RootDatabase,
88 position: FilePosition, 90 position: FilePosition,
89 new_name: &str, 91 new_name: &str,
90) -> Option<SourceChange> { 92) -> Option<RangeInfo<SourceChange>> {
91 let parse = db.parse(position.file_id); 93 let parse = db.parse(position.file_id);
92 if let Some((ast_name, ast_module)) = 94 if let Some((ast_name, ast_module)) =
93 find_name_and_module_at_offset(parse.tree().syntax(), position) 95 find_name_and_module_at_offset(parse.tree().syntax(), position)
94 { 96 {
97 let range = ast_name.syntax().text_range();
95 rename_mod(db, &ast_name, &ast_module, position, new_name) 98 rename_mod(db, &ast_name, &ast_module, position, new_name)
99 .map(|info| RangeInfo::new(range, info))
96 } else { 100 } else {
97 rename_reference(db, position, new_name) 101 rename_reference(db, position, new_name)
98 } 102 }
@@ -107,7 +111,7 @@ fn find_name_and_module_at_offset(
107 Some((ast_name, ast_module)) 111 Some((ast_name, ast_module))
108} 112}
109 113
110fn source_edit_from_fileid_range( 114fn source_edit_from_file_id_range(
111 file_id: FileId, 115 file_id: FileId,
112 range: TextRange, 116 range: TextRange,
113 new_name: &str, 117 new_name: &str,
@@ -179,19 +183,19 @@ fn rename_reference(
179 db: &RootDatabase, 183 db: &RootDatabase,
180 position: FilePosition, 184 position: FilePosition,
181 new_name: &str, 185 new_name: &str,
182) -> Option<SourceChange> { 186) -> Option<RangeInfo<SourceChange>> {
183 let refs = find_all_refs(db, position)?; 187 let RangeInfo { range, info: refs } = find_all_refs(db, position)?;
184 188
185 let edit = refs 189 let edit = refs
186 .into_iter() 190 .into_iter()
187 .map(|range| source_edit_from_fileid_range(range.file_id, range.range, new_name)) 191 .map(|range| source_edit_from_file_id_range(range.file_id, range.range, new_name))
188 .collect::<Vec<_>>(); 192 .collect::<Vec<_>>();
189 193
190 if edit.is_empty() { 194 if edit.is_empty() {
191 return None; 195 return None;
192 } 196 }
193 197
194 Some(SourceChange::source_file_edits("rename", edit)) 198 Some(RangeInfo::new(range, SourceChange::source_file_edits("rename", edit)))
195} 199}
196 200
197#[cfg(test)] 201#[cfg(test)]
@@ -342,38 +346,43 @@ mod tests {
342 let new_name = "foo2"; 346 let new_name = "foo2";
343 let source_change = analysis.rename(position, new_name).unwrap(); 347 let source_change = analysis.rename(position, new_name).unwrap();
344 assert_debug_snapshot!(&source_change, 348 assert_debug_snapshot!(&source_change,
345@r#"Some( 349@r###"
346 SourceChange { 350 Some(
347 label: "rename", 351 RangeInfo {
348 source_file_edits: [ 352 range: [4; 7),
349 SourceFileEdit { 353 info: SourceChange {
350 file_id: FileId( 354 label: "rename",
351 2, 355 source_file_edits: [
352 ), 356 SourceFileEdit {
353 edit: TextEdit { 357 file_id: FileId(
354 atoms: [ 358 2,
355 AtomTextEdit { 359 ),
356 delete: [4; 7), 360 edit: TextEdit {
357 insert: "foo2", 361 atoms: [
362 AtomTextEdit {
363 delete: [4; 7),
364 insert: "foo2",
365 },
366 ],
367 },
368 },
369 ],
370 file_system_edits: [
371 MoveFile {
372 src: FileId(
373 3,
374 ),
375 dst_source_root: SourceRootId(
376 0,
377 ),
378 dst_path: "bar/foo2.rs",
358 }, 379 },
359 ], 380 ],
381 cursor_position: None,
360 }, 382 },
361 }, 383 },
362 ], 384 )
363 file_system_edits: [ 385 "###);
364 MoveFile {
365 src: FileId(
366 3,
367 ),
368 dst_source_root: SourceRootId(
369 0,
370 ),
371 dst_path: "bar/foo2.rs",
372 },
373 ],
374 cursor_position: None,
375 },
376)"#);
377 } 386 }
378 387
379 #[test] 388 #[test]
@@ -389,38 +398,43 @@ mod tests {
389 let new_name = "foo2"; 398 let new_name = "foo2";
390 let source_change = analysis.rename(position, new_name).unwrap(); 399 let source_change = analysis.rename(position, new_name).unwrap();
391 assert_debug_snapshot!(&source_change, 400 assert_debug_snapshot!(&source_change,
392 @r###"Some( 401 @r###"
393 SourceChange { 402 Some(
394 label: "rename", 403 RangeInfo {
395 source_file_edits: [ 404 range: [4; 7),
396 SourceFileEdit { 405 info: SourceChange {
397 file_id: FileId( 406 label: "rename",
398 1, 407 source_file_edits: [
399 ), 408 SourceFileEdit {
400 edit: TextEdit { 409 file_id: FileId(
401 atoms: [ 410 1,
402 AtomTextEdit { 411 ),
403 delete: [4; 7), 412 edit: TextEdit {
404 insert: "foo2", 413 atoms: [
414 AtomTextEdit {
415 delete: [4; 7),
416 insert: "foo2",
417 },
418 ],
419 },
420 },
421 ],
422 file_system_edits: [
423 MoveFile {
424 src: FileId(
425 2,
426 ),
427 dst_source_root: SourceRootId(
428 0,
429 ),
430 dst_path: "foo2/mod.rs",
405 }, 431 },
406 ], 432 ],
433 cursor_position: None,
407 }, 434 },
408 }, 435 },
409 ], 436 )
410 file_system_edits: [ 437 "###
411 MoveFile {
412 src: FileId(
413 2,
414 ),
415 dst_source_root: SourceRootId(
416 0,
417 ),
418 dst_path: "foo2/mod.rs",
419 },
420 ],
421 cursor_position: None,
422 },
423)"###
424 ); 438 );
425 } 439 }
426 440
@@ -430,7 +444,7 @@ mod tests {
430 let mut text_edit_builder = ra_text_edit::TextEditBuilder::default(); 444 let mut text_edit_builder = ra_text_edit::TextEditBuilder::default();
431 let mut file_id: Option<FileId> = None; 445 let mut file_id: Option<FileId> = None;
432 if let Some(change) = source_change { 446 if let Some(change) = source_change {
433 for edit in change.source_file_edits { 447 for edit in change.info.source_file_edits {
434 file_id = Some(edit.file_id); 448 file_id = Some(edit.file_id);
435 for atom in edit.edit.as_atoms() { 449 for atom in edit.edit.as_atoms() {
436 text_edit_builder.replace(atom.delete, atom.insert.clone()); 450 text_edit_builder.replace(atom.delete, atom.insert.clone());
diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide_api/src/syntax_tree.rs
index 914759709..e2bb120b4 100644
--- a/crates/ra_ide_api/src/syntax_tree.rs
+++ b/crates/ra_ide_api/src/syntax_tree.rs
@@ -1,357 +1,357 @@
1use crate::db::RootDatabase; 1use crate::db::RootDatabase;
2use ra_db::SourceDatabase; 2use ra_db::SourceDatabase;
3use ra_syntax::{ 3use ra_syntax::{
4 algo, AstNode, NodeOrToken, SourceFile, 4 algo, AstNode, NodeOrToken, SourceFile,
5 SyntaxKind::{RAW_STRING, STRING}, 5 SyntaxKind::{RAW_STRING, STRING},
6 SyntaxToken, TextRange, 6 SyntaxToken, TextRange,
7}; 7};
8 8
9pub use ra_db::FileId; 9pub use ra_db::FileId;
10 10
11pub(crate) fn syntax_tree( 11pub(crate) fn syntax_tree(
12 db: &RootDatabase, 12 db: &RootDatabase,
13 file_id: FileId, 13 file_id: FileId,
14 text_range: Option<TextRange>, 14 text_range: Option<TextRange>,
15) -> String { 15) -> String {
16 let parse = db.parse(file_id); 16 let parse = db.parse(file_id);
17 if let Some(text_range) = text_range { 17 if let Some(text_range) = text_range {
18 let node = match algo::find_covering_element(parse.tree().syntax(), text_range) { 18 let node = match algo::find_covering_element(parse.tree().syntax(), text_range) {
19 NodeOrToken::Node(node) => node, 19 NodeOrToken::Node(node) => node,
20 NodeOrToken::Token(token) => { 20 NodeOrToken::Token(token) => {
21 if let Some(tree) = syntax_tree_for_string(&token, text_range) { 21 if let Some(tree) = syntax_tree_for_string(&token, text_range) {
22 return tree; 22 return tree;
23 } 23 }
24 token.parent() 24 token.parent()
25 } 25 }
26 }; 26 };
27 27
28 format!("{:#?}", node) 28 format!("{:#?}", node)
29 } else { 29 } else {
30 format!("{:#?}", parse.tree().syntax()) 30 format!("{:#?}", parse.tree().syntax())
31 } 31 }
32} 32}
33 33
34/// Attempts parsing the selected contents of a string literal 34/// Attempts parsing the selected contents of a string literal
35/// as rust syntax and returns its syntax tree 35/// as rust syntax and returns its syntax tree
36fn syntax_tree_for_string(token: &SyntaxToken, text_range: TextRange) -> Option<String> { 36fn syntax_tree_for_string(token: &SyntaxToken, text_range: TextRange) -> Option<String> {
37 // When the range is inside a string 37 // When the range is inside a string
38 // we'll attempt parsing it as rust syntax 38 // we'll attempt parsing it as rust syntax
39 // to provide the syntax tree of the contents of the string 39 // to provide the syntax tree of the contents of the string
40 match token.kind() { 40 match token.kind() {
41 STRING | RAW_STRING => syntax_tree_for_token(token, text_range), 41 STRING | RAW_STRING => syntax_tree_for_token(token, text_range),
42 _ => None, 42 _ => None,
43 } 43 }
44} 44}
45 45
46fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> { 46fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> {
47 // Range of the full node 47 // Range of the full node
48 let node_range = node.text_range(); 48 let node_range = node.text_range();
49 let text = node.text().to_string(); 49 let text = node.text().to_string();
50 50
51 // We start at some point inside the node 51 // We start at some point inside the node
52 // Either we have selected the whole string 52 // Either we have selected the whole string
53 // or our selection is inside it 53 // or our selection is inside it
54 let start = text_range.start() - node_range.start(); 54 let start = text_range.start() - node_range.start();
55 55
56 // how many characters we have selected 56 // how many characters we have selected
57 let len = text_range.len().to_usize(); 57 let len = text_range.len().to_usize();
58 58
59 let node_len = node_range.len().to_usize(); 59 let node_len = node_range.len().to_usize();
60 60
61 let start = start.to_usize(); 61 let start = start.to_usize();
62 62
63 // We want to cap our length 63 // We want to cap our length
64 let len = len.min(node_len); 64 let len = len.min(node_len);
65 65
66 // Ensure our slice is inside the actual string 66 // Ensure our slice is inside the actual string
67 let end = if start + len < text.len() { start + len } else { text.len() - start }; 67 let end = if start + len < text.len() { start + len } else { text.len() - start };
68 68
69 let text = &text[start..end]; 69 let text = &text[start..end];
70 70
71 // Remove possible extra string quotes from the start 71 // Remove possible extra string quotes from the start
72 // and the end of the string 72 // and the end of the string
73 let text = text 73 let text = text
74 .trim_start_matches('r') 74 .trim_start_matches('r')
75 .trim_start_matches('#') 75 .trim_start_matches('#')
76 .trim_start_matches('"') 76 .trim_start_matches('"')
77 .trim_end_matches('#') 77 .trim_end_matches('#')
78 .trim_end_matches('"') 78 .trim_end_matches('"')
79 .trim() 79 .trim()
80 // Remove custom markers 80 // Remove custom markers
81 .replace("<|>", ""); 81 .replace("<|>", "");
82 82
83 let parsed = SourceFile::parse(&text); 83 let parsed = SourceFile::parse(&text);
84 84
85 // If the "file" parsed without errors, 85 // If the "file" parsed without errors,
86 // return its syntax 86 // return its syntax
87 if parsed.errors().is_empty() { 87 if parsed.errors().is_empty() {
88 return Some(format!("{:#?}", parsed.tree().syntax())); 88 return Some(format!("{:#?}", parsed.tree().syntax()));
89 } 89 }
90 90
91 None 91 None
92} 92}
93 93
94#[cfg(test)] 94#[cfg(test)]
95mod tests { 95mod tests {
96 use test_utils::assert_eq_text; 96 use test_utils::assert_eq_text;
97 97
98 use crate::mock_analysis::{single_file, single_file_with_range}; 98 use crate::mock_analysis::{single_file, single_file_with_range};
99 99
100 #[test] 100 #[test]
101 fn test_syntax_tree_without_range() { 101 fn test_syntax_tree_without_range() {
102 // Basic syntax 102 // Basic syntax
103 let (analysis, file_id) = single_file(r#"fn foo() {}"#); 103 let (analysis, file_id) = single_file(r#"fn foo() {}"#);
104 let syn = analysis.syntax_tree(file_id, None).unwrap(); 104 let syn = analysis.syntax_tree(file_id, None).unwrap();
105 105
106 assert_eq_text!( 106 assert_eq_text!(
107 syn.trim(), 107 syn.trim(),
108 r#" 108 r#"
109SOURCE_FILE@[0; 11) 109SOURCE_FILE@[0; 11)
110 FN_DEF@[0; 11) 110 FN_DEF@[0; 11)
111 FN_KW@[0; 2) "fn" 111 FN_KW@[0; 2) "fn"
112 WHITESPACE@[2; 3) " " 112 WHITESPACE@[2; 3) " "
113 NAME@[3; 6) 113 NAME@[3; 6)
114 IDENT@[3; 6) "foo" 114 IDENT@[3; 6) "foo"
115 PARAM_LIST@[6; 8) 115 PARAM_LIST@[6; 8)
116 L_PAREN@[6; 7) "(" 116 L_PAREN@[6; 7) "("
117 R_PAREN@[7; 8) ")" 117 R_PAREN@[7; 8) ")"
118 WHITESPACE@[8; 9) " " 118 WHITESPACE@[8; 9) " "
119 BLOCK_EXPR@[9; 11) 119 BLOCK_EXPR@[9; 11)
120 BLOCK@[9; 11) 120 BLOCK@[9; 11)
121 L_CURLY@[9; 10) "{" 121 L_CURLY@[9; 10) "{"
122 R_CURLY@[10; 11) "}" 122 R_CURLY@[10; 11) "}"
123"# 123"#
124 .trim() 124 .trim()
125 ); 125 );
126 126
127 let (analysis, file_id) = single_file( 127 let (analysis, file_id) = single_file(
128 r#" 128 r#"
129fn test() { 129fn test() {
130 assert!(" 130 assert!("
131 fn foo() { 131 fn foo() {
132 } 132 }
133 ", ""); 133 ", "");
134}"# 134}"#
135 .trim(), 135 .trim(),
136 ); 136 );
137 let syn = analysis.syntax_tree(file_id, None).unwrap(); 137 let syn = analysis.syntax_tree(file_id, None).unwrap();
138 138
139 assert_eq_text!( 139 assert_eq_text!(
140 syn.trim(), 140 syn.trim(),
141 r#" 141 r#"
142SOURCE_FILE@[0; 60) 142SOURCE_FILE@[0; 60)
143 FN_DEF@[0; 60) 143 FN_DEF@[0; 60)
144 FN_KW@[0; 2) "fn" 144 FN_KW@[0; 2) "fn"
145 WHITESPACE@[2; 3) " " 145 WHITESPACE@[2; 3) " "
146 NAME@[3; 7) 146 NAME@[3; 7)
147 IDENT@[3; 7) "test" 147 IDENT@[3; 7) "test"
148 PARAM_LIST@[7; 9) 148 PARAM_LIST@[7; 9)
149 L_PAREN@[7; 8) "(" 149 L_PAREN@[7; 8) "("
150 R_PAREN@[8; 9) ")" 150 R_PAREN@[8; 9) ")"
151 WHITESPACE@[9; 10) " " 151 WHITESPACE@[9; 10) " "
152 BLOCK_EXPR@[10; 60) 152 BLOCK_EXPR@[10; 60)
153 BLOCK@[10; 60) 153 BLOCK@[10; 60)
154 L_CURLY@[10; 11) "{" 154 L_CURLY@[10; 11) "{"
155 WHITESPACE@[11; 16) "\n " 155 WHITESPACE@[11; 16) "\n "
156 EXPR_STMT@[16; 58) 156 EXPR_STMT@[16; 58)
157 MACRO_CALL@[16; 57) 157 MACRO_CALL@[16; 57)
158 PATH@[16; 22) 158 PATH@[16; 22)
159 PATH_SEGMENT@[16; 22) 159 PATH_SEGMENT@[16; 22)
160 NAME_REF@[16; 22) 160 NAME_REF@[16; 22)
161 IDENT@[16; 22) "assert" 161 IDENT@[16; 22) "assert"
162 EXCL@[22; 23) "!" 162 EXCL@[22; 23) "!"
163 TOKEN_TREE@[23; 57) 163 TOKEN_TREE@[23; 57)
164 L_PAREN@[23; 24) "(" 164 L_PAREN@[23; 24) "("
165 STRING@[24; 52) "\"\n fn foo() {\n ..." 165 STRING@[24; 52) "\"\n fn foo() {\n ..."
166 COMMA@[52; 53) "," 166 COMMA@[52; 53) ","
167 WHITESPACE@[53; 54) " " 167 WHITESPACE@[53; 54) " "
168 STRING@[54; 56) "\"\"" 168 STRING@[54; 56) "\"\""
169 R_PAREN@[56; 57) ")" 169 R_PAREN@[56; 57) ")"
170 SEMI@[57; 58) ";" 170 SEMI@[57; 58) ";"
171 WHITESPACE@[58; 59) "\n" 171 WHITESPACE@[58; 59) "\n"
172 R_CURLY@[59; 60) "}" 172 R_CURLY@[59; 60) "}"
173"# 173"#
174 .trim() 174 .trim()
175 ); 175 );
176 } 176 }
177 177
178 #[test] 178 #[test]
179 fn test_syntax_tree_with_range() { 179 fn test_syntax_tree_with_range() {
180 let (analysis, range) = single_file_with_range(r#"<|>fn foo() {}<|>"#.trim()); 180 let (analysis, range) = single_file_with_range(r#"<|>fn foo() {}<|>"#.trim());
181 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 181 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
182 182
183 assert_eq_text!( 183 assert_eq_text!(
184 syn.trim(), 184 syn.trim(),
185 r#" 185 r#"
186FN_DEF@[0; 11) 186FN_DEF@[0; 11)
187 FN_KW@[0; 2) "fn" 187 FN_KW@[0; 2) "fn"
188 WHITESPACE@[2; 3) " " 188 WHITESPACE@[2; 3) " "
189 NAME@[3; 6) 189 NAME@[3; 6)
190 IDENT@[3; 6) "foo" 190 IDENT@[3; 6) "foo"
191 PARAM_LIST@[6; 8) 191 PARAM_LIST@[6; 8)
192 L_PAREN@[6; 7) "(" 192 L_PAREN@[6; 7) "("
193 R_PAREN@[7; 8) ")" 193 R_PAREN@[7; 8) ")"
194 WHITESPACE@[8; 9) " " 194 WHITESPACE@[8; 9) " "
195 BLOCK_EXPR@[9; 11) 195 BLOCK_EXPR@[9; 11)
196 BLOCK@[9; 11) 196 BLOCK@[9; 11)
197 L_CURLY@[9; 10) "{" 197 L_CURLY@[9; 10) "{"
198 R_CURLY@[10; 11) "}" 198 R_CURLY@[10; 11) "}"
199"# 199"#
200 .trim() 200 .trim()
201 ); 201 );
202 202
203 let (analysis, range) = single_file_with_range( 203 let (analysis, range) = single_file_with_range(
204 r#"fn test() { 204 r#"fn test() {
205 <|>assert!(" 205 <|>assert!("
206 fn foo() { 206 fn foo() {
207 } 207 }
208 ", "");<|> 208 ", "");<|>
209}"# 209}"#
210 .trim(), 210 .trim(),
211 ); 211 );
212 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 212 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
213 213
214 assert_eq_text!( 214 assert_eq_text!(
215 syn.trim(), 215 syn.trim(),
216 r#" 216 r#"
217EXPR_STMT@[16; 58) 217EXPR_STMT@[16; 58)
218 MACRO_CALL@[16; 57) 218 MACRO_CALL@[16; 57)
219 PATH@[16; 22) 219 PATH@[16; 22)
220 PATH_SEGMENT@[16; 22) 220 PATH_SEGMENT@[16; 22)
221 NAME_REF@[16; 22) 221 NAME_REF@[16; 22)
222 IDENT@[16; 22) "assert" 222 IDENT@[16; 22) "assert"
223 EXCL@[22; 23) "!" 223 EXCL@[22; 23) "!"
224 TOKEN_TREE@[23; 57) 224 TOKEN_TREE@[23; 57)
225 L_PAREN@[23; 24) "(" 225 L_PAREN@[23; 24) "("
226 STRING@[24; 52) "\"\n fn foo() {\n ..." 226 STRING@[24; 52) "\"\n fn foo() {\n ..."
227 COMMA@[52; 53) "," 227 COMMA@[52; 53) ","
228 WHITESPACE@[53; 54) " " 228 WHITESPACE@[53; 54) " "
229 STRING@[54; 56) "\"\"" 229 STRING@[54; 56) "\"\""
230 R_PAREN@[56; 57) ")" 230 R_PAREN@[56; 57) ")"
231 SEMI@[57; 58) ";" 231 SEMI@[57; 58) ";"
232"# 232"#
233 .trim() 233 .trim()
234 ); 234 );
235 } 235 }
236 236
237 #[test] 237 #[test]
238 fn test_syntax_tree_inside_string() { 238 fn test_syntax_tree_inside_string() {
239 let (analysis, range) = single_file_with_range( 239 let (analysis, range) = single_file_with_range(
240 r#"fn test() { 240 r#"fn test() {
241 assert!(" 241 assert!("
242<|>fn foo() { 242<|>fn foo() {
243}<|> 243}<|>
244fn bar() { 244fn bar() {
245} 245}
246 ", ""); 246 ", "");
247}"# 247}"#
248 .trim(), 248 .trim(),
249 ); 249 );
250 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 250 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
251 assert_eq_text!( 251 assert_eq_text!(
252 syn.trim(), 252 syn.trim(),
253 r#" 253 r#"
254SOURCE_FILE@[0; 12) 254SOURCE_FILE@[0; 12)
255 FN_DEF@[0; 12) 255 FN_DEF@[0; 12)
256 FN_KW@[0; 2) "fn" 256 FN_KW@[0; 2) "fn"
257 WHITESPACE@[2; 3) " " 257 WHITESPACE@[2; 3) " "
258 NAME@[3; 6) 258 NAME@[3; 6)
259 IDENT@[3; 6) "foo" 259 IDENT@[3; 6) "foo"
260 PARAM_LIST@[6; 8) 260 PARAM_LIST@[6; 8)
261 L_PAREN@[6; 7) "(" 261 L_PAREN@[6; 7) "("
262 R_PAREN@[7; 8) ")" 262 R_PAREN@[7; 8) ")"
263 WHITESPACE@[8; 9) " " 263 WHITESPACE@[8; 9) " "
264 BLOCK_EXPR@[9; 12) 264 BLOCK_EXPR@[9; 12)
265 BLOCK@[9; 12) 265 BLOCK@[9; 12)
266 L_CURLY@[9; 10) "{" 266 L_CURLY@[9; 10) "{"
267 WHITESPACE@[10; 11) "\n" 267 WHITESPACE@[10; 11) "\n"
268 R_CURLY@[11; 12) "}" 268 R_CURLY@[11; 12) "}"
269"# 269"#
270 .trim() 270 .trim()
271 ); 271 );
272 272
273 // With a raw string 273 // With a raw string
274 let (analysis, range) = single_file_with_range( 274 let (analysis, range) = single_file_with_range(
275 r###"fn test() { 275 r###"fn test() {
276 assert!(r#" 276 assert!(r#"
277<|>fn foo() { 277<|>fn foo() {
278}<|> 278}<|>
279fn bar() { 279fn bar() {
280} 280}
281 "#, ""); 281 "#, "");
282}"### 282}"###
283 .trim(), 283 .trim(),
284 ); 284 );
285 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 285 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
286 assert_eq_text!( 286 assert_eq_text!(
287 syn.trim(), 287 syn.trim(),
288 r#" 288 r#"
289SOURCE_FILE@[0; 12) 289SOURCE_FILE@[0; 12)
290 FN_DEF@[0; 12) 290 FN_DEF@[0; 12)
291 FN_KW@[0; 2) "fn" 291 FN_KW@[0; 2) "fn"
292 WHITESPACE@[2; 3) " " 292 WHITESPACE@[2; 3) " "
293 NAME@[3; 6) 293 NAME@[3; 6)
294 IDENT@[3; 6) "foo" 294 IDENT@[3; 6) "foo"
295 PARAM_LIST@[6; 8) 295 PARAM_LIST@[6; 8)
296 L_PAREN@[6; 7) "(" 296 L_PAREN@[6; 7) "("
297 R_PAREN@[7; 8) ")" 297 R_PAREN@[7; 8) ")"
298 WHITESPACE@[8; 9) " " 298 WHITESPACE@[8; 9) " "
299 BLOCK_EXPR@[9; 12) 299 BLOCK_EXPR@[9; 12)
300 BLOCK@[9; 12) 300 BLOCK@[9; 12)
301 L_CURLY@[9; 10) "{" 301 L_CURLY@[9; 10) "{"
302 WHITESPACE@[10; 11) "\n" 302 WHITESPACE@[10; 11) "\n"
303 R_CURLY@[11; 12) "}" 303 R_CURLY@[11; 12) "}"
304"# 304"#
305 .trim() 305 .trim()
306 ); 306 );
307 307
308 // With a raw string 308 // With a raw string
309 let (analysis, range) = single_file_with_range( 309 let (analysis, range) = single_file_with_range(
310 r###"fn test() { 310 r###"fn test() {
311 assert!(r<|>#" 311 assert!(r<|>#"
312fn foo() { 312fn foo() {
313} 313}
314fn bar() { 314fn bar() {
315}"<|>#, ""); 315}"<|>#, "");
316}"### 316}"###
317 .trim(), 317 .trim(),
318 ); 318 );
319 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 319 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
320 assert_eq_text!( 320 assert_eq_text!(
321 syn.trim(), 321 syn.trim(),
322 r#" 322 r#"
323SOURCE_FILE@[0; 25) 323SOURCE_FILE@[0; 25)
324 FN_DEF@[0; 12) 324 FN_DEF@[0; 12)
325 FN_KW@[0; 2) "fn" 325 FN_KW@[0; 2) "fn"
326 WHITESPACE@[2; 3) " " 326 WHITESPACE@[2; 3) " "
327 NAME@[3; 6) 327 NAME@[3; 6)
328 IDENT@[3; 6) "foo" 328 IDENT@[3; 6) "foo"
329 PARAM_LIST@[6; 8) 329 PARAM_LIST@[6; 8)
330 L_PAREN@[6; 7) "(" 330 L_PAREN@[6; 7) "("
331 R_PAREN@[7; 8) ")" 331 R_PAREN@[7; 8) ")"
332 WHITESPACE@[8; 9) " " 332 WHITESPACE@[8; 9) " "
333 BLOCK_EXPR@[9; 12) 333 BLOCK_EXPR@[9; 12)
334 BLOCK@[9; 12) 334 BLOCK@[9; 12)
335 L_CURLY@[9; 10) "{" 335 L_CURLY@[9; 10) "{"
336 WHITESPACE@[10; 11) "\n" 336 WHITESPACE@[10; 11) "\n"
337 R_CURLY@[11; 12) "}" 337 R_CURLY@[11; 12) "}"
338 WHITESPACE@[12; 13) "\n" 338 WHITESPACE@[12; 13) "\n"
339 FN_DEF@[13; 25) 339 FN_DEF@[13; 25)
340 FN_KW@[13; 15) "fn" 340 FN_KW@[13; 15) "fn"
341 WHITESPACE@[15; 16) " " 341 WHITESPACE@[15; 16) " "
342 NAME@[16; 19) 342 NAME@[16; 19)
343 IDENT@[16; 19) "bar" 343 IDENT@[16; 19) "bar"
344 PARAM_LIST@[19; 21) 344 PARAM_LIST@[19; 21)
345 L_PAREN@[19; 20) "(" 345 L_PAREN@[19; 20) "("
346 R_PAREN@[20; 21) ")" 346 R_PAREN@[20; 21) ")"
347 WHITESPACE@[21; 22) " " 347 WHITESPACE@[21; 22) " "
348 BLOCK_EXPR@[22; 25) 348 BLOCK_EXPR@[22; 25)
349 BLOCK@[22; 25) 349 BLOCK@[22; 25)
350 L_CURLY@[22; 23) "{" 350 L_CURLY@[22; 23) "{"
351 WHITESPACE@[23; 24) "\n" 351 WHITESPACE@[23; 24) "\n"
352 R_CURLY@[24; 25) "}" 352 R_CURLY@[24; 25) "}"
353"# 353"#
354 .trim() 354 .trim()
355 ); 355 );
356 } 356 }
357} 357}
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index eb805a6d3..948d543ea 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -460,18 +460,16 @@ pub fn handle_prepare_rename(
460 460
461 // We support renaming references like handle_rename does. 461 // We support renaming references like handle_rename does.
462 // In the future we may want to reject the renaming of things like keywords here too. 462 // In the future we may want to reject the renaming of things like keywords here too.
463 let refs = match world.analysis().find_all_refs(position)? { 463 let optional_change = world.analysis().rename(position, "dummy")?;
464 let range = match optional_change {
464 None => return Ok(None), 465 None => return Ok(None),
465 Some(refs) => refs, 466 Some(it) => it.range,
466 }; 467 };
467 468
468 // Refs should always have a declaration
469 let r = refs.declaration();
470 let file_id = params.text_document.try_conv_with(&world)?; 469 let file_id = params.text_document.try_conv_with(&world)?;
471 let line_index = world.analysis().file_line_index(file_id)?; 470 let line_index = world.analysis().file_line_index(file_id)?;
472 let loc = to_location(r.file_id(), r.range(), &world, &line_index)?; 471 let range = range.conv_with(&line_index);
473 472 Ok(Some(PrepareRenameResponse::Range(range)))
474 Ok(Some(PrepareRenameResponse::Range(loc.range)))
475} 473}
476 474
477pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Option<WorkspaceEdit>> { 475pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Option<WorkspaceEdit>> {
@@ -488,7 +486,7 @@ pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Optio
488 let optional_change = world.analysis().rename(position, &*params.new_name)?; 486 let optional_change = world.analysis().rename(position, &*params.new_name)?;
489 let change = match optional_change { 487 let change = match optional_change {
490 None => return Ok(None), 488 None => return Ok(None),
491 Some(it) => it, 489 Some(it) => it.info,
492 }; 490 };
493 491
494 let source_change_req = change.try_conv_with(&world)?; 492 let source_change_req = change.try_conv_with(&world)?;
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 6d426206e..b4327b78f 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -31,7 +31,7 @@ pub(super) enum ItemFlavor {
31 31
32pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ 32pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![
33 FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, 33 FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW,
34 CRATE_KW 34 CRATE_KW, USE_KW
35]; 35];
36 36
37pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { 37pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
index c0c7d0ec6..83a65e226 100644
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -101,7 +101,10 @@ fn use_tree(p: &mut Parser) {
101 } 101 }
102 _ => { 102 _ => {
103 m.abandon(p); 103 m.abandon(p);
104 p.err_and_bump("expected one of `*`, `::`, `{`, `self`, `super` or an indentifier"); 104 p.err_recover(
105 "expected one of `*`, `::`, `{`, `self`, `super` or an identifier",
106 ITEM_RECOVERY_SET,
107 );
105 return; 108 return;
106 } 109 }
107 } 110 }
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 676dc4941..9b2f534e7 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -153,7 +153,7 @@ impl ProjectWorkspace {
153 if let Some(file_id) = load(krate.root(&sysroot)) { 153 if let Some(file_id) = load(krate.root(&sysroot)) {
154 sysroot_crates.insert( 154 sysroot_crates.insert(
155 krate, 155 krate,
156 crate_graph.add_crate_root(file_id, Edition::Edition2015), 156 crate_graph.add_crate_root(file_id, Edition::Edition2018),
157 ); 157 );
158 } 158 }
159 } 159 }
diff --git a/crates/ra_syntax/test_data/parser/err/0002_duplicate_shebang.txt b/crates/ra_syntax/test_data/parser/err/0002_duplicate_shebang.txt
index 84867026f..bdb5fa6c5 100644
--- a/crates/ra_syntax/test_data/parser/err/0002_duplicate_shebang.txt
+++ b/crates/ra_syntax/test_data/parser/err/0002_duplicate_shebang.txt
@@ -28,7 +28,7 @@ SOURCE_FILE@[0; 42)
28 WHITESPACE@[41; 42) "\n" 28 WHITESPACE@[41; 42) "\n"
29error 23: expected `[` 29error 23: expected `[`
30error 23: expected an item 30error 23: expected an item
31error 27: expected one of `*`, `::`, `{`, `self`, `super` or an indentifier 31error 27: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
32error 28: expected SEMI 32error 28: expected SEMI
33error 31: expected EXCL 33error 31: expected EXCL
34error 31: expected `{`, `[`, `(` 34error 31: expected `{`, `[`, `(`
diff --git a/crates/ra_syntax/test_data/parser/err/0035_use_recover.rs b/crates/ra_syntax/test_data/parser/err/0035_use_recover.rs
new file mode 100644
index 000000000..4a2668126
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0035_use_recover.rs
@@ -0,0 +1,5 @@
1use foo::bar;
2use
3use crate::baz;
4use
5fn f() {}
diff --git a/crates/ra_syntax/test_data/parser/err/0035_use_recover.txt b/crates/ra_syntax/test_data/parser/err/0035_use_recover.txt
new file mode 100644
index 000000000..636840828
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0035_use_recover.txt
@@ -0,0 +1,54 @@
1SOURCE_FILE@[0; 48)
2 USE_ITEM@[0; 13)
3 USE_KW@[0; 3) "use"
4 WHITESPACE@[3; 4) " "
5 USE_TREE@[4; 12)
6 PATH@[4; 12)
7 PATH@[4; 7)
8 PATH_SEGMENT@[4; 7)
9 NAME_REF@[4; 7)
10 IDENT@[4; 7) "foo"
11 COLONCOLON@[7; 9) "::"
12 PATH_SEGMENT@[9; 12)
13 NAME_REF@[9; 12)
14 IDENT@[9; 12) "bar"
15 SEMI@[12; 13) ";"
16 WHITESPACE@[13; 14) "\n"
17 USE_ITEM@[14; 17)
18 USE_KW@[14; 17) "use"
19 WHITESPACE@[17; 18) "\n"
20 USE_ITEM@[18; 33)
21 USE_KW@[18; 21) "use"
22 WHITESPACE@[21; 22) " "
23 USE_TREE@[22; 32)
24 PATH@[22; 32)
25 PATH@[22; 27)
26 PATH_SEGMENT@[22; 27)
27 CRATE_KW@[22; 27) "crate"
28 COLONCOLON@[27; 29) "::"
29 PATH_SEGMENT@[29; 32)
30 NAME_REF@[29; 32)
31 IDENT@[29; 32) "baz"
32 SEMI@[32; 33) ";"
33 WHITESPACE@[33; 34) "\n"
34 USE_ITEM@[34; 37)
35 USE_KW@[34; 37) "use"
36 WHITESPACE@[37; 38) "\n"
37 FN_DEF@[38; 47)
38 FN_KW@[38; 40) "fn"
39 WHITESPACE@[40; 41) " "
40 NAME@[41; 42)
41 IDENT@[41; 42) "f"
42 PARAM_LIST@[42; 44)
43 L_PAREN@[42; 43) "("
44 R_PAREN@[43; 44) ")"
45 WHITESPACE@[44; 45) " "
46 BLOCK_EXPR@[45; 47)
47 BLOCK@[45; 47)
48 L_CURLY@[45; 46) "{"
49 R_CURLY@[46; 47) "}"
50 WHITESPACE@[47; 48) "\n"
51error 17: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
52error 17: expected SEMI
53error 37: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
54error 37: expected SEMI
diff --git a/docs/user/features.md b/docs/user/features.md
index b6e6008c4..1034a5117 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -435,6 +435,16 @@ fn f() {
435} 435}
436``` 436```
437 437
438- Move type bounds to where clause
439
440```rust
441// before:
442fn foo<T: u32, F: FnOnce(T) -> T>() {}
443
444// after:
445fn foo<T, F>() where T: u32, F: FnOnce(T) -> T {}
446```
447
438### Magic Completions 448### Magic Completions
439 449
440In addition to usual reference completion, rust-analyzer provides some ✨magic✨ 450In addition to usual reference completion, rust-analyzer provides some ✨magic✨
diff --git a/rustfmt.toml b/rustfmt.toml
index 71007de81..f2e164618 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,2 +1,3 @@
1reorder_modules = false 1reorder_modules = false
2use_small_heuristics = "Max" 2use_small_heuristics = "Max"
3newline_style = "Unix"