aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock113
-rw-r--r--README.md6
-rw-r--r--crates/ra_assists/src/flip_binexpr.rs141
-rw-r--r--crates/ra_assists/src/flip_eq_operands.rs86
-rw-r--r--crates/ra_assists/src/inline_local_variable.rs298
-rw-r--r--crates/ra_assists/src/lib.rs6
-rw-r--r--crates/ra_cli/Cargo.toml1
-rw-r--r--crates/ra_cli/src/main.rs2
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_hir/src/code_model_api.rs50
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs35
-rw-r--r--crates/ra_hir/src/db.rs31
-rw-r--r--crates/ra_hir/src/diagnostics.rs115
-rw-r--r--crates/ra_hir/src/expr.rs15
-rw-r--r--crates/ra_hir/src/ids.rs197
-rw-r--r--crates/ra_hir/src/lib.rs10
-rw-r--r--crates/ra_hir/src/mock.rs18
-rw-r--r--crates/ra_hir/src/nameres.rs115
-rw-r--r--crates/ra_hir/src/nameres/collector.rs198
-rw-r--r--crates/ra_hir/src/nameres/raw.rs143
-rw-r--r--crates/ra_hir/src/nameres/tests.rs19
-rw-r--r--crates/ra_hir/src/nameres/tests/incremental.rs46
-rw-r--r--crates/ra_hir/src/resolve.rs17
-rw-r--r--crates/ra_hir/src/source_binder.rs10
-rw-r--r--crates/ra_hir/src/source_id.rs150
-rw-r--r--crates/ra_hir/src/traits.rs52
-rw-r--r--crates/ra_hir/src/ty.rs23
-rw-r--r--crates/ra_hir/src/ty/infer.rs58
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs95
-rw-r--r--crates/ra_hir/src/ty/tests.rs36
-rw-r--r--crates/ra_ide_api/Cargo.toml1
-rw-r--r--crates/ra_ide_api/src/change.rs4
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs87
-rw-r--r--crates/ra_ide_api/src/lib.rs11
-rw-r--r--crates/ra_ide_api/src/parent_module.rs30
-rw-r--r--crates/ra_ide_api/src/references.rs48
-rw-r--r--crates/ra_ide_api/src/snapshots/tests__file_structure.snap (renamed from crates/ra_ide_api_light/src/snapshots/tests__file_structure.snap)2
-rw-r--r--crates/ra_ide_api/src/structure.rs (renamed from crates/ra_ide_api_light/src/structure.rs)0
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs58
-rw-r--r--crates/ra_ide_api/src/syntax_tree.rs257
-rw-r--r--crates/ra_ide_api/tests/test/main.rs392
-rw-r--r--crates/ra_ide_api/tests/test/snapshots/test__unresolved_module_diagnostic.snap28
-rw-r--r--crates/ra_ide_api_light/Cargo.toml26
-rw-r--r--crates/ra_ide_api_light/src/lib.rs12
-rw-r--r--crates/ra_parser/src/grammar.rs4
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron5
-rw-r--r--crates/ra_syntax/src/ptr.rs6
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt17
-rw-r--r--crates/tools/src/lib.rs6
-rw-r--r--docs/dev/architecture.md13
-rw-r--r--docs/user/features.md19
-rw-r--r--editors/emacs/ra-emacs-lsp.el2
54 files changed, 1943 insertions, 1180 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7c07bddf9..669977163 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -76,15 +76,15 @@ dependencies = [
76 76
77[[package]] 77[[package]]
78name = "bit-set" 78name = "bit-set"
79version = "0.5.0" 79version = "0.5.1"
80source = "registry+https://github.com/rust-lang/crates.io-index" 80source = "registry+https://github.com/rust-lang/crates.io-index"
81dependencies = [ 81dependencies = [
82 "bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 82 "bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
83] 83]
84 84
85[[package]] 85[[package]]
86name = "bit-vec" 86name = "bit-vec"
87version = "0.5.0" 87version = "0.5.1"
88source = "registry+https://github.com/rust-lang/crates.io-index" 88source = "registry+https://github.com/rust-lang/crates.io-index"
89 89
90[[package]] 90[[package]]
@@ -118,7 +118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
118 118
119[[package]] 119[[package]]
120name = "cargo_metadata" 120name = "cargo_metadata"
121version = "0.7.3" 121version = "0.7.4"
122source = "registry+https://github.com/rust-lang/crates.io-index" 122source = "registry+https://github.com/rust-lang/crates.io-index"
123dependencies = [ 123dependencies = [
124 "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 124 "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -359,11 +359,11 @@ dependencies = [
359 359
360[[package]] 360[[package]]
361name = "flexi_logger" 361name = "flexi_logger"
362version = "0.11.1" 362version = "0.11.2"
363source = "registry+https://github.com/rust-lang/crates.io-index" 363source = "registry+https://github.com/rust-lang/crates.io-index"
364dependencies = [ 364dependencies = [
365 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 365 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
366 "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 366 "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
367 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 367 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
368 "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 368 "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
369] 369]
@@ -444,6 +444,11 @@ version = "0.2.11"
444source = "registry+https://github.com/rust-lang/crates.io-index" 444source = "registry+https://github.com/rust-lang/crates.io-index"
445 445
446[[package]] 446[[package]]
447name = "glob"
448version = "0.3.0"
449source = "registry+https://github.com/rust-lang/crates.io-index"
450
451[[package]]
447name = "heck" 452name = "heck"
448version = "0.3.1" 453version = "0.3.1"
449source = "registry+https://github.com/rust-lang/crates.io-index" 454source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -503,7 +508,7 @@ dependencies = [
503 508
504[[package]] 509[[package]]
505name = "insta" 510name = "insta"
506version = "0.7.1" 511version = "0.7.4"
507source = "registry+https://github.com/rust-lang/crates.io-index" 512source = "registry+https://github.com/rust-lang/crates.io-index"
508dependencies = [ 513dependencies = [
509 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 514 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -518,7 +523,7 @@ dependencies = [
518 "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 523 "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
519 "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 524 "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
520 "serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", 525 "serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
521 "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 526 "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
522] 527]
523 528
524[[package]] 529[[package]]
@@ -589,9 +594,6 @@ dependencies = [
589name = "lazy_static" 594name = "lazy_static"
590version = "1.3.0" 595version = "1.3.0"
591source = "registry+https://github.com/rust-lang/crates.io-index" 596source = "registry+https://github.com/rust-lang/crates.io-index"
592dependencies = [
593 "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
594]
595 597
596[[package]] 598[[package]]
597name = "lazycell" 599name = "lazycell"
@@ -605,7 +607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
605 607
606[[package]] 608[[package]]
607name = "linked-hash-map" 609name = "linked-hash-map"
608version = "0.5.1" 610version = "0.5.2"
609source = "registry+https://github.com/rust-lang/crates.io-index" 611source = "registry+https://github.com/rust-lang/crates.io-index"
610 612
611[[package]] 613[[package]]
@@ -855,10 +857,10 @@ dependencies = [
855 857
856[[package]] 858[[package]]
857name = "proptest" 859name = "proptest"
858version = "0.9.1" 860version = "0.9.2"
859source = "registry+https://github.com/rust-lang/crates.io-index" 861source = "registry+https://github.com/rust-lang/crates.io-index"
860dependencies = [ 862dependencies = [
861 "bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 863 "bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
862 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 864 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
863 "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 865 "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
864 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 866 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -911,7 +913,7 @@ dependencies = [
911 "ra_hir 0.1.0", 913 "ra_hir 0.1.0",
912 "ra_project_model 0.1.0", 914 "ra_project_model 0.1.0",
913 "ra_syntax 0.1.0", 915 "ra_syntax 0.1.0",
914 "ra_vfs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 916 "ra_vfs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
915 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 917 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
916 "test_utils 0.1.0", 918 "test_utils 0.1.0",
917] 919]
@@ -922,14 +924,13 @@ version = "0.1.0"
922dependencies = [ 924dependencies = [
923 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", 925 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
924 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 926 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
925 "flexi_logger 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", 927 "flexi_logger 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
926 "indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 928 "indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
927 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 929 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
928 "ra_batch 0.1.0", 930 "ra_batch 0.1.0",
929 "ra_db 0.1.0", 931 "ra_db 0.1.0",
930 "ra_hir 0.1.0", 932 "ra_hir 0.1.0",
931 "ra_ide_api 0.1.0", 933 "ra_ide_api 0.1.0",
932 "ra_ide_api_light 0.1.0",
933 "ra_prof 0.1.0", 934 "ra_prof 0.1.0",
934 "ra_syntax 0.1.0", 935 "ra_syntax 0.1.0",
935 "tools 0.1.0", 936 "tools 0.1.0",
@@ -944,7 +945,7 @@ dependencies = [
944 "ra_syntax 0.1.0", 945 "ra_syntax 0.1.0",
945 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 946 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
946 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 947 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
947 "salsa 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 948 "salsa 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
948 "test_utils 0.1.0", 949 "test_utils 0.1.0",
949] 950]
950 951
@@ -962,8 +963,8 @@ version = "0.1.0"
962dependencies = [ 963dependencies = [
963 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 964 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
964 "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 965 "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
965 "flexi_logger 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", 966 "flexi_logger 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
966 "insta 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 967 "insta 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
967 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 968 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
968 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 969 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
969 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 970 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -983,19 +984,18 @@ name = "ra_ide_api"
983version = "0.1.0" 984version = "0.1.0"
984dependencies = [ 985dependencies = [
985 "fst 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 986 "fst 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
986 "insta 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 987 "insta 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
987 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 988 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
988 "jemalloc-ctl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 989 "jemalloc-ctl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
989 "jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 990 "jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
990 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 991 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
991 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 992 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
992 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 993 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
993 "proptest 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", 994 "proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
994 "ra_assists 0.1.0", 995 "ra_assists 0.1.0",
995 "ra_db 0.1.0", 996 "ra_db 0.1.0",
996 "ra_fmt 0.1.0", 997 "ra_fmt 0.1.0",
997 "ra_hir 0.1.0", 998 "ra_hir 0.1.0",
998 "ra_ide_api_light 0.1.0",
999 "ra_syntax 0.1.0", 999 "ra_syntax 0.1.0",
1000 "ra_text_edit 0.1.0", 1000 "ra_text_edit 0.1.0",
1001 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 1001 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1007,29 +1007,13 @@ dependencies = [
1007] 1007]
1008 1008
1009[[package]] 1009[[package]]
1010name = "ra_ide_api_light"
1011version = "0.1.0"
1012dependencies = [
1013 "insta 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1014 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1015 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
1016 "proptest 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
1017 "ra_fmt 0.1.0",
1018 "ra_syntax 0.1.0",
1019 "ra_text_edit 0.1.0",
1020 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1021 "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1022 "test_utils 0.1.0",
1023]
1024
1025[[package]]
1026name = "ra_lsp_server" 1010name = "ra_lsp_server"
1027version = "0.1.0" 1011version = "0.1.0"
1028dependencies = [ 1012dependencies = [
1029 "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1013 "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
1030 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1014 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1031 "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1015 "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1032 "flexi_logger 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", 1016 "flexi_logger 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
1033 "gen_lsp_server 0.1.0", 1017 "gen_lsp_server 0.1.0",
1034 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1018 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1035 "lsp-types 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", 1019 "lsp-types 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1040,7 +1024,7 @@ dependencies = [
1040 "ra_project_model 0.1.0", 1024 "ra_project_model 0.1.0",
1041 "ra_syntax 0.1.0", 1025 "ra_syntax 0.1.0",
1042 "ra_text_edit 0.1.0", 1026 "ra_text_edit 0.1.0",
1043 "ra_vfs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1027 "ra_vfs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1044 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1028 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1045 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1029 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1046 "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 1030 "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1080,7 +1064,7 @@ dependencies = [
1080name = "ra_project_model" 1064name = "ra_project_model"
1081version = "0.1.0" 1065version = "0.1.0"
1082dependencies = [ 1066dependencies = [
1083 "cargo_metadata 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", 1067 "cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
1084 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1068 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1085 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1069 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1086 "ra_arena 0.1.0", 1070 "ra_arena 0.1.0",
@@ -1115,7 +1099,7 @@ dependencies = [
1115name = "ra_text_edit" 1099name = "ra_text_edit"
1116version = "0.1.0" 1100version = "0.1.0"
1117dependencies = [ 1101dependencies = [
1118 "proptest 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", 1102 "proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
1119 "test_utils 0.1.0", 1103 "test_utils 0.1.0",
1120 "text_unit 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 1104 "text_unit 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
1121] 1105]
@@ -1129,7 +1113,7 @@ dependencies = [
1129 1113
1130[[package]] 1114[[package]]
1131name = "ra_vfs" 1115name = "ra_vfs"
1132version = "0.2.0" 1116version = "0.2.1"
1133source = "registry+https://github.com/rust-lang/crates.io-index" 1117source = "registry+https://github.com/rust-lang/crates.io-index"
1134dependencies = [ 1118dependencies = [
1135 "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1119 "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1361,7 +1345,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1361 1345
1362[[package]] 1346[[package]]
1363name = "salsa" 1347name = "salsa"
1364version = "0.10.0" 1348version = "0.11.1"
1365source = "registry+https://github.com/rust-lang/crates.io-index" 1349source = "registry+https://github.com/rust-lang/crates.io-index"
1366dependencies = [ 1350dependencies = [
1367 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 1351 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1370,13 +1354,13 @@ dependencies = [
1370 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1354 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1371 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1355 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1372 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1356 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1373 "salsa-macros 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 1357 "salsa-macros 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
1374 "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 1358 "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
1375] 1359]
1376 1360
1377[[package]] 1361[[package]]
1378name = "salsa-macros" 1362name = "salsa-macros"
1379version = "0.10.0" 1363version = "0.11.1"
1380source = "registry+https://github.com/rust-lang/crates.io-index" 1364source = "registry+https://github.com/rust-lang/crates.io-index"
1381dependencies = [ 1365dependencies = [
1382 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1366 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1446,7 +1430,7 @@ version = "0.8.8"
1446source = "registry+https://github.com/rust-lang/crates.io-index" 1430source = "registry+https://github.com/rust-lang/crates.io-index"
1447dependencies = [ 1431dependencies = [
1448 "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 1432 "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
1449 "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1433 "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1450 "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 1434 "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
1451 "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 1435 "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
1452] 1436]
@@ -1489,11 +1473,6 @@ dependencies = [
1489] 1473]
1490 1474
1491[[package]] 1475[[package]]
1492name = "spin"
1493version = "0.5.0"
1494source = "registry+https://github.com/rust-lang/crates.io-index"
1495
1496[[package]]
1497name = "stable_deref_trait" 1476name = "stable_deref_trait"
1498version = "1.1.1" 1477version = "1.1.1"
1499source = "registry+https://github.com/rust-lang/crates.io-index" 1478source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1786,7 +1765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1786 1765
1787[[package]] 1766[[package]]
1788name = "uuid" 1767name = "uuid"
1789version = "0.7.2" 1768version = "0.7.3"
1790source = "registry+https://github.com/rust-lang/crates.io-index" 1769source = "registry+https://github.com/rust-lang/crates.io-index"
1791dependencies = [ 1770dependencies = [
1792 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1771 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1864,7 +1843,7 @@ name = "yaml-rust"
1864version = "0.4.3" 1843version = "0.4.3"
1865source = "registry+https://github.com/rust-lang/crates.io-index" 1844source = "registry+https://github.com/rust-lang/crates.io-index"
1866dependencies = [ 1845dependencies = [
1867 "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1846 "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1868] 1847]
1869 1848
1870[metadata] 1849[metadata]
@@ -1877,14 +1856,14 @@ dependencies = [
1877"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" 1856"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4"
1878"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" 1857"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
1879"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" 1858"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
1880"checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a" 1859"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
1881"checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf" 1860"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
1882"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" 1861"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
1883"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" 1862"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
1884"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" 1863"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
1885"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" 1864"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
1886"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" 1865"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
1887"checksum cargo_metadata 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bc796c7161c220089dfc7159e13324979181532850a237576b8fb907dd087c0d" 1866"checksum cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "178d62b240c34223f265a4c1e275e37d62da163d421fc8d7f7e3ee340f803c57"
1888"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" 1867"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d"
1889"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" 1868"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
1890"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" 1869"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
@@ -1913,7 +1892,7 @@ dependencies = [
1913"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" 1892"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
1914"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 1893"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
1915"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" 1894"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646"
1916"checksum flexi_logger 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4a7878fc9e06c948c6f9cddf571758e0c44786a509e646a094ef13ade3b1aab7" 1895"checksum flexi_logger 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "005c01dd6942ca46283b7304d14c6d04ec2c87a62f6e62e17c06fb812a574f4a"
1917"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" 1896"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
1918"checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" 1897"checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05"
1919"checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" 1898"checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874"
@@ -1923,6 +1902,7 @@ dependencies = [
1923"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 1902"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
1924"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" 1903"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
1925"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" 1904"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
1905"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
1926"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 1906"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
1927"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" 1907"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
1928"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" 1908"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
@@ -1930,7 +1910,7 @@ dependencies = [
1930"checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c" 1910"checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c"
1931"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" 1911"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
1932"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" 1912"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
1933"checksum insta 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be9f00370d23dc7bd32a4d4506b1a14fb922fa39c576c3300fd25ce5b5dab18f" 1913"checksum insta 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "03e7d88a87d342ce8bd698516151be43e6eb2e84b683db528696cb4a382f734a"
1934"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" 1914"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
1935"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" 1915"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
1936"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" 1916"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
@@ -1942,7 +1922,7 @@ dependencies = [
1942"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" 1922"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
1943"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" 1923"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
1944"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" 1924"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1"
1945"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" 1925"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
1946"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" 1926"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
1947"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" 1927"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
1948"checksum lsp-types 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31954f2cf354421e6f99a48fdcfd5c3113c675a0db311960ffdac0b8d45cf09c" 1928"checksum lsp-types 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31954f2cf354421e6f99a48fdcfd5c3113c675a0db311960ffdac0b8d45cf09c"
@@ -1970,10 +1950,10 @@ dependencies = [
1970"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" 1950"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646"
1971"checksum pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e" 1951"checksum pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e"
1972"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" 1952"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
1973"checksum proptest 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea66c78d75f2c6e9f304269eaef90899798daecc69f1a625d5a3dd793ff3522" 1953"checksum proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24f5844db2f839e97e3021980975f6ebf8691d9b9b2ca67ed3feb38dc3edb52c"
1974"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 1954"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
1975"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" 1955"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
1976"checksum ra_vfs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1839e4e003d865b58b8b6c231aae6c463dfcd01bfbbddffbdb7662a7b5a627" 1956"checksum ra_vfs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d08da053ec832676686c72dfe509fdd1e807191a50ac79087466ffefccb1c"
1977"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 1957"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
1978"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 1958"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
1979"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 1959"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@@ -1999,8 +1979,8 @@ dependencies = [
1999"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" 1979"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
2000"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1980"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
2001"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" 1981"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
2002"checksum salsa 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cad0e2348e2f80725b2980914a08a00267136c3ecf720896d3f7f08eef51e08f" 1982"checksum salsa 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94f14bbb013866db2fbeceb97ed82cf35f42020edd39d35268f0b11f89399c79"
2003"checksum salsa-macros 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c79744109df21b80aef1367669b0a9e4985bc966e76bf0e9321b222ec0b9fbb" 1983"checksum salsa-macros 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1ad27cbae189e9739a96e469d37c6a6deafec36f1282d4fdf4681eae67c9dd39"
2004"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" 1984"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
2005"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 1985"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
2006"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1986"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
@@ -2014,7 +1994,6 @@ dependencies = [
2014"checksum slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" 1994"checksum slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373"
2015"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" 1995"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
2016"checksum smol_str 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9af1035bc5d742ab6b7ab16713e41cc2ffe78cb474f6f43cd696b2d16052007e" 1996"checksum smol_str 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9af1035bc5d742ab6b7ab16713e41cc2ffe78cb474f6f43cd696b2d16052007e"
2017"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
2018"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" 1997"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
2019"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" 1998"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
2020"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" 1999"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
@@ -2048,7 +2027,7 @@ dependencies = [
2048"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" 2027"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
2049"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" 2028"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
2050"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" 2029"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
2051"checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" 2030"checksum uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "600ef8213e9f8a0ac1f876e470e90780ae0478eabce7f76aff41b0f4ef0fd5c0"
2052"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 2031"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
2053"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 2032"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
2054"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" 2033"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
diff --git a/README.md b/README.md
index 3a0c9dee1..8df991246 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,12 @@ We are on the rust-lang Zulip!
51 51
52https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 52https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0
53 53
54## Quick Links
55
56* Work List: https://paper.dropbox.com/doc/RLS-2.0-work-list--AZ3BgHKKCtqszbsi3gi6sjchAQ-42vbnxzuKq2lKwW0mkn8Y
57* API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide_api/index.html
58* CI: https://travis-ci.org/rust-analyzer/rust-analyzer
59
54## License 60## License
55 61
56Rust analyzer is primarily distributed under the terms of both the MIT 62Rust analyzer is primarily distributed under the terms of both the MIT
diff --git a/crates/ra_assists/src/flip_binexpr.rs b/crates/ra_assists/src/flip_binexpr.rs
new file mode 100644
index 000000000..ec377642e
--- /dev/null
+++ b/crates/ra_assists/src/flip_binexpr.rs
@@ -0,0 +1,141 @@
1use hir::db::HirDatabase;
2use ra_syntax::ast::{AstNode, BinExpr, BinOp};
3
4use crate::{AssistCtx, Assist, AssistId};
5
6/// Flip binary expression assist.
7pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
8 let expr = ctx.node_at_offset::<BinExpr>()?;
9 let lhs = expr.lhs()?.syntax();
10 let rhs = expr.rhs()?.syntax();
11 let op_range = expr.op()?.range();
12 // The assist should be applied only if the cursor is on the operator
13 let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
14 if !cursor_in_range {
15 return None;
16 }
17 let action: FlipAction = expr.op_kind()?.into();
18 // The assist should not be applied for certain operators
19 if let FlipAction::DontFlip = action {
20 return None;
21 }
22
23 ctx.add_action(AssistId("flip_binexpr"), "flip binary expression", |edit| {
24 edit.target(op_range);
25 if let FlipAction::FlipAndReplaceOp(new_op) = action {
26 edit.replace(op_range, new_op);
27 }
28 edit.replace(lhs.range(), rhs.text());
29 edit.replace(rhs.range(), lhs.text());
30 });
31
32 ctx.build()
33}
34
35enum FlipAction {
36 // Flip the expression
37 Flip,
38 // Flip the expression and replace the operator with this string
39 FlipAndReplaceOp(&'static str),
40 // Do not flip the expression
41 DontFlip,
42}
43
44impl From<BinOp> for FlipAction {
45 fn from(op_kind: BinOp) -> Self {
46 match op_kind {
47 BinOp::Assignment => FlipAction::DontFlip,
48 BinOp::AddAssign => FlipAction::DontFlip,
49 BinOp::DivAssign => FlipAction::DontFlip,
50 BinOp::MulAssign => FlipAction::DontFlip,
51 BinOp::RemAssign => FlipAction::DontFlip,
52 BinOp::ShrAssign => FlipAction::DontFlip,
53 BinOp::ShlAssign => FlipAction::DontFlip,
54 BinOp::SubAssign => FlipAction::DontFlip,
55 BinOp::BitOrAssign => FlipAction::DontFlip,
56 BinOp::BitAndAssign => FlipAction::DontFlip,
57 BinOp::BitXorAssign => FlipAction::DontFlip,
58 BinOp::GreaterTest => FlipAction::FlipAndReplaceOp("<"),
59 BinOp::GreaterEqualTest => FlipAction::FlipAndReplaceOp("<="),
60 BinOp::LesserTest => FlipAction::FlipAndReplaceOp(">"),
61 BinOp::LesserEqualTest => FlipAction::FlipAndReplaceOp(">="),
62 _ => FlipAction::Flip,
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 use crate::helpers::{ check_assist, check_assist_target, check_assist_not_applicable };
72
73 #[test]
74 fn flip_binexpr_target_is_the_op() {
75 check_assist_target(flip_binexpr, "fn f() { let res = 1 ==<|> 2; }", "==")
76 }
77
78 #[test]
79 fn flip_binexpr_not_applicable_for_assignment() {
80 check_assist_not_applicable(flip_binexpr, "fn f() { let mut _x = 1; _x +=<|> 2 }")
81 }
82
83 #[test]
84 fn flip_binexpr_works_for_eq() {
85 check_assist(
86 flip_binexpr,
87 "fn f() { let res = 1 ==<|> 2; }",
88 "fn f() { let res = 2 ==<|> 1; }",
89 )
90 }
91
92 #[test]
93 fn flip_binexpr_works_for_gt() {
94 check_assist(
95 flip_binexpr,
96 "fn f() { let res = 1 ><|> 2; }",
97 "fn f() { let res = 2 <<|> 1; }",
98 )
99 }
100
101 #[test]
102 fn flip_binexpr_works_for_lteq() {
103 check_assist(
104 flip_binexpr,
105 "fn f() { let res = 1 <=<|> 2; }",
106 "fn f() { let res = 2 >=<|> 1; }",
107 )
108 }
109
110 #[test]
111 fn flip_binexpr_works_for_complex_expr() {
112 check_assist(
113 flip_binexpr,
114 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }",
115 "fn f() { let res = (2 + 2) ==<|> (1 + 1); }",
116 )
117 }
118
119 #[test]
120 fn flip_binexpr_works_inside_match() {
121 check_assist(
122 flip_binexpr,
123 r#"
124 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
125 match other.downcast_ref::<Self>() {
126 None => false,
127 Some(it) => it ==<|> self,
128 }
129 }
130 "#,
131 r#"
132 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
133 match other.downcast_ref::<Self>() {
134 None => false,
135 Some(it) => self ==<|> it,
136 }
137 }
138 "#,
139 )
140 }
141}
diff --git a/crates/ra_assists/src/flip_eq_operands.rs b/crates/ra_assists/src/flip_eq_operands.rs
deleted file mode 100644
index df0bb689d..000000000
--- a/crates/ra_assists/src/flip_eq_operands.rs
+++ /dev/null
@@ -1,86 +0,0 @@
1use hir::db::HirDatabase;
2use ra_syntax::ast::{AstNode, BinExpr, BinOp};
3
4use crate::{AssistCtx, Assist, AssistId};
5
6pub(crate) fn flip_eq_operands(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
7 let expr = ctx.node_at_offset::<BinExpr>()?;
8 let lhs = expr.lhs()?.syntax();
9 let rhs = expr.rhs()?.syntax();
10 let op_range = expr.op()?.range();
11 let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
12 let allowed_ops = [BinOp::EqualityTest, BinOp::NegatedEqualityTest];
13 let expr_op = expr.op_kind()?;
14 if !cursor_in_range || !allowed_ops.iter().any(|o| *o == expr_op) {
15 return None;
16 }
17 ctx.add_action(AssistId("flip_eq_operands"), "flip equality operands", |edit| {
18 edit.target(op_range);
19 edit.replace(lhs.range(), rhs.text());
20 edit.replace(rhs.range(), lhs.text());
21 });
22
23 ctx.build()
24}
25
26#[cfg(test)]
27mod tests {
28 use super::*;
29
30 use crate::helpers::{check_assist, check_assist_target};
31
32 #[test]
33 fn flip_eq_operands_for_simple_stmt() {
34 check_assist(
35 flip_eq_operands,
36 "fn f() { let res = 1 ==<|> 2; }",
37 "fn f() { let res = 2 ==<|> 1; }",
38 )
39 }
40
41 #[test]
42 fn flip_neq_operands_for_simple_stmt() {
43 check_assist(
44 flip_eq_operands,
45 "fn f() { let res = 1 !=<|> 2; }",
46 "fn f() { let res = 2 !=<|> 1; }",
47 )
48 }
49
50 #[test]
51 fn flip_eq_operands_for_complex_stmt() {
52 check_assist(
53 flip_eq_operands,
54 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }",
55 "fn f() { let res = (2 + 2) ==<|> (1 + 1); }",
56 )
57 }
58
59 #[test]
60 fn flip_eq_operands_in_match_expr() {
61 check_assist(
62 flip_eq_operands,
63 r#"
64 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
65 match other.downcast_ref::<Self>() {
66 None => false,
67 Some(it) => it ==<|> self,
68 }
69 }
70 "#,
71 r#"
72 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
73 match other.downcast_ref::<Self>() {
74 None => false,
75 Some(it) => self ==<|> it,
76 }
77 }
78 "#,
79 )
80 }
81
82 #[test]
83 fn flip_eq_operands_target() {
84 check_assist_target(flip_eq_operands, "fn f() { let res = 1 ==<|> 2; }", "==")
85 }
86}
diff --git a/crates/ra_assists/src/inline_local_variable.rs b/crates/ra_assists/src/inline_local_variable.rs
new file mode 100644
index 000000000..bd3cdb970
--- /dev/null
+++ b/crates/ra_assists/src/inline_local_variable.rs
@@ -0,0 +1,298 @@
1use hir::db::HirDatabase;
2use hir::source_binder::function_from_child_node;
3use ra_syntax::{ast::{self, AstNode}, TextRange};
4use ra_syntax::ast::{PatKind, ExprKind};
5
6use crate::{Assist, AssistCtx, AssistId};
7use crate::assist_ctx::AssistBuilder;
8
9pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
10 let let_stmt = ctx.node_at_offset::<ast::LetStmt>()?;
11 let bind_pat = match let_stmt.pat()?.kind() {
12 PatKind::BindPat(pat) => pat,
13 _ => return None,
14 };
15 if bind_pat.is_mutable() {
16 return None;
17 }
18 let initializer = let_stmt.initializer()?;
19 let wrap_in_parens = match initializer.kind() {
20 ExprKind::LambdaExpr(_)
21 | ExprKind::IfExpr(_)
22 | ExprKind::LoopExpr(_)
23 | ExprKind::ForExpr(_)
24 | ExprKind::WhileExpr(_)
25 | ExprKind::ContinueExpr(_)
26 | ExprKind::BreakExpr(_)
27 | ExprKind::Label(_)
28 | ExprKind::ReturnExpr(_)
29 | ExprKind::MatchExpr(_)
30 | ExprKind::StructLit(_)
31 | ExprKind::CastExpr(_)
32 | ExprKind::PrefixExpr(_)
33 | ExprKind::RangeExpr(_)
34 | ExprKind::BinExpr(_) => true,
35 ExprKind::CallExpr(_)
36 | ExprKind::IndexExpr(_)
37 | ExprKind::MethodCallExpr(_)
38 | ExprKind::FieldExpr(_)
39 | ExprKind::TryExpr(_)
40 | ExprKind::RefExpr(_)
41 | ExprKind::Literal(_)
42 | ExprKind::TupleExpr(_)
43 | ExprKind::ArrayExpr(_)
44 | ExprKind::ParenExpr(_)
45 | ExprKind::PathExpr(_)
46 | ExprKind::BlockExpr(_) => false,
47 };
48
49 let delete_range = if let Some(whitespace) =
50 let_stmt.syntax().next_sibling().and_then(ast::Whitespace::cast)
51 {
52 TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end())
53 } else {
54 let_stmt.syntax().range()
55 };
56
57 let init_str = if wrap_in_parens {
58 format!("({})", initializer.syntax().text().to_string())
59 } else {
60 initializer.syntax().text().to_string()
61 };
62 let function = function_from_child_node(ctx.db, ctx.frange.file_id, bind_pat.syntax())?;
63 let scope = function.scopes(ctx.db);
64 let refs = scope.find_all_refs(bind_pat);
65
66 ctx.add_action(
67 AssistId("inline_local_variable"),
68 "inline local variable",
69 move |edit: &mut AssistBuilder| {
70 edit.delete(delete_range);
71 for desc in refs {
72 edit.replace(desc.range, init_str.clone())
73 }
74 edit.set_cursor(delete_range.start())
75 },
76 );
77
78 ctx.build()
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::helpers::{check_assist, check_assist_not_applicable};
84
85 use super::*;
86
87 #[test]
88 fn test_inline_let_bind_literal_expr() {
89 check_assist(
90 inline_local_varialbe,
91 "
92fn bar(a: usize) {}
93fn foo() {
94 let a<|> = 1;
95 a + 1;
96 if a > 10 {
97 }
98
99 while a > 10 {
100
101 }
102 let b = a * 10;
103 bar(a);
104}",
105 "
106fn bar(a: usize) {}
107fn foo() {
108 <|>1 + 1;
109 if 1 > 10 {
110 }
111
112 while 1 > 10 {
113
114 }
115 let b = 1 * 10;
116 bar(1);
117}",
118 );
119 }
120
121 #[test]
122 fn test_inline_let_bind_bin_expr() {
123 check_assist(
124 inline_local_varialbe,
125 "
126fn bar(a: usize) {}
127fn foo() {
128 let a<|> = 1 + 1;
129 a + 1;
130 if a > 10 {
131 }
132
133 while a > 10 {
134
135 }
136 let b = a * 10;
137 bar(a);
138}",
139 "
140fn bar(a: usize) {}
141fn foo() {
142 <|>(1 + 1) + 1;
143 if (1 + 1) > 10 {
144 }
145
146 while (1 + 1) > 10 {
147
148 }
149 let b = (1 + 1) * 10;
150 bar((1 + 1));
151}",
152 );
153 }
154
155 #[test]
156 fn test_inline_let_bind_function_call_expr() {
157 check_assist(
158 inline_local_varialbe,
159 "
160fn bar(a: usize) {}
161fn foo() {
162 let a<|> = bar(1);
163 a + 1;
164 if a > 10 {
165 }
166
167 while a > 10 {
168
169 }
170 let b = a * 10;
171 bar(a);
172}",
173 "
174fn bar(a: usize) {}
175fn foo() {
176 <|>bar(1) + 1;
177 if bar(1) > 10 {
178 }
179
180 while bar(1) > 10 {
181
182 }
183 let b = bar(1) * 10;
184 bar(bar(1));
185}",
186 );
187 }
188
189 #[test]
190 fn test_inline_let_bind_cast_expr() {
191 check_assist(
192 inline_local_varialbe,
193 "
194fn bar(a: usize): usize { a }
195fn foo() {
196 let a<|> = bar(1) as u64;
197 a + 1;
198 if a > 10 {
199 }
200
201 while a > 10 {
202
203 }
204 let b = a * 10;
205 bar(a);
206}",
207 "
208fn bar(a: usize): usize { a }
209fn foo() {
210 <|>(bar(1) as u64) + 1;
211 if (bar(1) as u64) > 10 {
212 }
213
214 while (bar(1) as u64) > 10 {
215
216 }
217 let b = (bar(1) as u64) * 10;
218 bar((bar(1) as u64));
219}",
220 );
221 }
222
223 #[test]
224 fn test_inline_let_bind_block_expr() {
225 check_assist(
226 inline_local_varialbe,
227 "
228fn foo() {
229 let a<|> = { 10 + 1 };
230 a + 1;
231 if a > 10 {
232 }
233
234 while a > 10 {
235
236 }
237 let b = a * 10;
238 bar(a);
239}",
240 "
241fn foo() {
242 <|>{ 10 + 1 } + 1;
243 if { 10 + 1 } > 10 {
244 }
245
246 while { 10 + 1 } > 10 {
247
248 }
249 let b = { 10 + 1 } * 10;
250 bar({ 10 + 1 });
251}",
252 );
253 }
254
255 #[test]
256 fn test_inline_let_bind_paren_expr() {
257 check_assist(
258 inline_local_varialbe,
259 "
260fn foo() {
261 let a<|> = ( 10 + 1 );
262 a + 1;
263 if a > 10 {
264 }
265
266 while a > 10 {
267
268 }
269 let b = a * 10;
270 bar(a);
271}",
272 "
273fn foo() {
274 <|>( 10 + 1 ) + 1;
275 if ( 10 + 1 ) > 10 {
276 }
277
278 while ( 10 + 1 ) > 10 {
279
280 }
281 let b = ( 10 + 1 ) * 10;
282 bar(( 10 + 1 ));
283}",
284 );
285 }
286
287 #[test]
288 fn test_not_inline_mut_variable() {
289 check_assist_not_applicable(
290 inline_local_varialbe,
291 "
292fn foo() {
293 let mut a<|> = 1 + 1;
294 a + 1;
295}",
296 );
297 }
298}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 8900fbc4b..c1514f8e5 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -88,11 +88,12 @@ where
88mod add_derive; 88mod add_derive;
89mod add_impl; 89mod add_impl;
90mod flip_comma; 90mod flip_comma;
91mod flip_eq_operands; 91mod flip_binexpr;
92mod change_visibility; 92mod change_visibility;
93mod fill_match_arms; 93mod fill_match_arms;
94mod fill_struct_fields; 94mod fill_struct_fields;
95mod introduce_variable; 95mod introduce_variable;
96mod inline_local_variable;
96mod replace_if_let_with_match; 97mod replace_if_let_with_match;
97mod split_import; 98mod split_import;
98mod remove_dbg; 99mod remove_dbg;
@@ -107,7 +108,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
107 fill_match_arms::fill_match_arms, 108 fill_match_arms::fill_match_arms,
108 fill_struct_fields::fill_struct_fields, 109 fill_struct_fields::fill_struct_fields,
109 flip_comma::flip_comma, 110 flip_comma::flip_comma,
110 flip_eq_operands::flip_eq_operands, 111 flip_binexpr::flip_binexpr,
111 introduce_variable::introduce_variable, 112 introduce_variable::introduce_variable,
112 replace_if_let_with_match::replace_if_let_with_match, 113 replace_if_let_with_match::replace_if_let_with_match,
113 split_import::split_import, 114 split_import::split_import,
@@ -115,6 +116,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
115 auto_import::auto_import, 116 auto_import::auto_import,
116 add_missing_impl_members::add_missing_impl_members, 117 add_missing_impl_members::add_missing_impl_members,
117 add_missing_impl_members::add_missing_default_members, 118 add_missing_impl_members::add_missing_default_members,
119 inline_local_variable::inline_local_varialbe,
118 ] 120 ]
119} 121}
120 122
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index a92a63257..328b2436f 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -14,7 +14,6 @@ indicatif = "0.11.0"
14 14
15ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
16ra_ide_api = { path = "../ra_ide_api" } 16ra_ide_api = { path = "../ra_ide_api" }
17ra_ide_api_light = { path = "../ra_ide_api_light" }
18tools = { path = "../tools" } 17tools = { path = "../tools" }
19ra_batch = { path = "../ra_batch" } 18ra_batch = { path = "../ra_batch" }
20ra_hir = { path = "../ra_hir" } 19ra_hir = { path = "../ra_hir" }
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index c13c7910c..ecea516f1 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -5,7 +5,7 @@ use std::{fs, io::Read, path::Path};
5use clap::{App, Arg, SubCommand}; 5use clap::{App, Arg, SubCommand};
6use join_to_string::join; 6use join_to_string::join;
7use ra_ide_api::{Analysis, FileRange}; 7use ra_ide_api::{Analysis, FileRange};
8use ra_ide_api_light::file_structure; 8use ra_ide_api::file_structure;
9use ra_syntax::{SourceFile, TextRange, TreeArc, AstNode}; 9use ra_syntax::{SourceFile, TextRange, TreeArc, AstNode};
10use tools::collect_tests; 10use tools::collect_tests;
11use flexi_logger::Logger; 11use flexi_logger::Logger;
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index c9b8f3c8e..581cd32fd 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6 6
7[dependencies] 7[dependencies]
8salsa = "0.10.0" 8salsa = "0.11.1"
9relative-path = "0.4.0" 9relative-path = "0.4.0"
10rustc-hash = "1.0" 10rustc-hash = "1.0"
11parking_lot = "0.7.0" 11parking_lot = "0.7.0"
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 45fa4cd11..624c25c4d 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -1,8 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf;
4use ra_db::{CrateId, SourceRootId, Edition}; 3use ra_db::{CrateId, SourceRootId, Edition};
5use ra_syntax::{ast::self, TreeArc, SyntaxNode}; 4use ra_syntax::{ast::self, TreeArc};
6 5
7use crate::{ 6use crate::{
8 Name, ScopesWithSourceMap, Ty, HirFileId, 7 Name, ScopesWithSourceMap, Ty, HirFileId,
@@ -14,9 +13,11 @@ use crate::{
14 adt::{EnumVariantId, StructFieldId, VariantDef}, 13 adt::{EnumVariantId, StructFieldId, VariantDef},
15 generics::GenericParams, 14 generics::GenericParams,
16 docs::{Documentation, Docs, docs_from_ast}, 15 docs::{Documentation, Docs, docs_from_ast},
17 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, 16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId},
18 impl_block::ImplBlock, 17 impl_block::ImplBlock,
19 resolve::Resolver, 18 resolve::Resolver,
19 diagnostics::DiagnosticSink,
20 traits::{TraitItem, TraitData},
20}; 21};
21 22
22/// hir::Crate describes a single crate. It's the main interface with which 23/// hir::Crate describes a single crate. It's the main interface with which
@@ -95,11 +96,6 @@ pub enum ModuleSource {
95 Module(TreeArc<ast::Module>), 96 Module(TreeArc<ast::Module>),
96} 97}
97 98
98#[derive(Clone, Debug, Hash, PartialEq, Eq)]
99pub enum Problem {
100 UnresolvedModule { candidate: RelativePathBuf },
101}
102
103impl Module { 99impl Module {
104 /// Name of this module. 100 /// Name of this module.
105 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { 101 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
@@ -171,8 +167,24 @@ impl Module {
171 db.crate_def_map(self.krate)[self.module_id].scope.clone() 167 db.crate_def_map(self.krate)[self.module_id].scope.clone()
172 } 168 }
173 169
174 pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { 170 pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
175 self.problems_impl(db) 171 db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink);
172 for decl in self.declarations(db) {
173 match decl {
174 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
175 crate::ModuleDef::Module(f) => f.diagnostics(db, sink),
176 _ => (),
177 }
178 }
179
180 for impl_block in self.impl_blocks(db) {
181 for item in impl_block.items(db) {
182 match item {
183 crate::ImplItem::Method(f) => f.diagnostics(db, sink),
184 _ => (),
185 }
186 }
187 }
176 } 188 }
177 189
178 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 190 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
@@ -519,6 +531,10 @@ impl Function {
519 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; 531 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
520 r 532 r
521 } 533 }
534
535 pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
536 self.infer(db).add_diagnostics(db, *self, sink);
537 }
522} 538}
523 539
524impl Docs for Function { 540impl Docs for Function {
@@ -634,6 +650,18 @@ impl Trait {
634 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { 650 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
635 db.generic_params((*self).into()) 651 db.generic_params((*self).into())
636 } 652 }
653
654 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
655 self.trait_data(db).name().clone()
656 }
657
658 pub fn items(self, db: &impl DefDatabase) -> Vec<TraitItem> {
659 self.trait_data(db).items().to_vec()
660 }
661
662 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
663 db.trait_data(self)
664 }
637} 665}
638 666
639impl Docs for Trait { 667impl Docs for Trait {
@@ -644,7 +672,7 @@ impl Docs for Trait {
644 672
645#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 673#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
646pub struct TypeAlias { 674pub struct TypeAlias {
647 pub(crate) id: TypeId, 675 pub(crate) id: TypeAliasId,
648} 676}
649 677
650impl TypeAlias { 678impl TypeAlias {
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 52a33e981..0edb8ade5 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -1,18 +1,18 @@
1use ra_db::FileId; 1use ra_db::FileId;
2use ra_syntax::{ast, SyntaxNode, TreeArc, AstNode}; 2use ra_syntax::{ast, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Problem, Name, 5 Module, ModuleSource, Name, AstId,
6 nameres::{CrateModuleId, ImportId}, 6 nameres::{CrateModuleId, ImportId},
7 HirDatabase, DefDatabase, 7 HirDatabase, DefDatabase,
8 HirFileId, SourceItemId, 8 HirFileId,
9}; 9};
10 10
11impl ModuleSource { 11impl ModuleSource {
12 pub(crate) fn new( 12 pub(crate) fn new(
13 db: &impl DefDatabase, 13 db: &impl DefDatabase,
14 file_id: Option<FileId>, 14 file_id: Option<FileId>,
15 decl_id: Option<SourceItemId>, 15 decl_id: Option<AstId<ast::Module>>,
16 ) -> ModuleSource { 16 ) -> ModuleSource {
17 match (file_id, decl_id) { 17 match (file_id, decl_id) {
18 (Some(file_id), _) => { 18 (Some(file_id), _) => {
@@ -20,8 +20,7 @@ impl ModuleSource {
20 ModuleSource::SourceFile(source_file) 20 ModuleSource::SourceFile(source_file)
21 } 21 }
22 (None, Some(item_id)) => { 22 (None, Some(item_id)) => {
23 let module = db.file_item(item_id); 23 let module = item_id.to_node(db);
24 let module = ast::Module::cast(&*module).unwrap();
25 assert!(module.item_list().is_some(), "expected inline module"); 24 assert!(module.item_list().is_some(), "expected inline module");
26 ModuleSource::Module(module.to_owned()) 25 ModuleSource::Module(module.to_owned())
27 } 26 }
@@ -55,7 +54,7 @@ impl Module {
55 let decl_id = def_map[self.module_id].declaration; 54 let decl_id = def_map[self.module_id].declaration;
56 let file_id = def_map[self.module_id].definition; 55 let file_id = def_map[self.module_id].definition;
57 let module_source = ModuleSource::new(db, file_id, decl_id); 56 let module_source = ModuleSource::new(db, file_id, decl_id);
58 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id); 57 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
59 (file_id, module_source) 58 (file_id, module_source)
60 } 59 }
61 60
@@ -65,9 +64,8 @@ impl Module {
65 ) -> Option<(HirFileId, TreeArc<ast::Module>)> { 64 ) -> Option<(HirFileId, TreeArc<ast::Module>)> {
66 let def_map = db.crate_def_map(self.krate); 65 let def_map = db.crate_def_map(self.krate);
67 let decl = def_map[self.module_id].declaration?; 66 let decl = def_map[self.module_id].declaration?;
68 let syntax_node = db.file_item(decl); 67 let ast = decl.to_node(db);
69 let ast = ast::Module::cast(&syntax_node).unwrap().to_owned(); 68 Some((decl.file_id(), ast))
70 Some((decl.file_id, ast))
71 } 69 }
72 70
73 pub(crate) fn import_source_impl( 71 pub(crate) fn import_source_impl(
@@ -76,7 +74,7 @@ impl Module {
76 import: ImportId, 74 import: ImportId,
77 ) -> TreeArc<ast::PathSegment> { 75 ) -> TreeArc<ast::PathSegment> {
78 let (file_id, source) = self.definition_source(db); 76 let (file_id, source) = self.definition_source(db);
79 let (_, source_map) = db.raw_items_with_source_map(file_id.original_file(db)); 77 let (_, source_map) = db.raw_items_with_source_map(file_id);
80 source_map.get(&source, import) 78 source_map.get(&source, import)
81 } 79 }
82 80
@@ -108,19 +106,4 @@ impl Module {
108 let parent_id = def_map[self.module_id].parent?; 106 let parent_id = def_map[self.module_id].parent?;
109 Some(self.with_module_id(parent_id)) 107 Some(self.with_module_id(parent_id))
110 } 108 }
111
112 pub(crate) fn problems_impl(
113 &self,
114 db: &impl HirDatabase,
115 ) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
116 let def_map = db.crate_def_map(self.krate);
117 let (my_file_id, _) = self.definition_source(db);
118 // FIXME: not entirely corret filterint by module
119 def_map
120 .problems()
121 .iter()
122 .filter(|(source_item_id, _problem)| my_file_id == source_item_id.file_id)
123 .map(|(source_item_id, problem)| (db.file_item(*source_item_id), problem.clone()))
124 .collect()
125 }
126} 109}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index d3908f8ac..147005848 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,10 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; 3use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
4use ra_db::{SourceDatabase, salsa, FileId}; 4use ra_db::{SourceDatabase, salsa};
5 5
6use crate::{ 6use crate::{
7 HirFileId, SourceFileItems, SourceItemId, Crate, Module, HirInterner, 7 HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, HirInterner,
8 Function, FnSignature, ExprScopes, TypeAlias, 8 Function, FnSignature, ExprScopes, TypeAlias,
9 Struct, Enum, StructField, 9 Struct, Enum, StructField,
10 Const, ConstSignature, Static, 10 Const, ConstSignature, Static,
@@ -14,11 +14,15 @@ use crate::{
14 impl_block::{ModuleImplBlocks, ImplSourceMap}, 14 impl_block::{ModuleImplBlocks, ImplSourceMap},
15 generics::{GenericParams, GenericDef}, 15 generics::{GenericParams, GenericDef},
16 type_ref::TypeRef, 16 type_ref::TypeRef,
17 traits::TraitData, Trait, ty::TraitRef
17}; 18};
18 19
19#[salsa::query_group(DefDatabaseStorage)] 20#[salsa::query_group(DefDatabaseStorage)]
20pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> { 21pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
21 #[salsa::invoke(HirFileId::hir_parse)] 22 #[salsa::invoke(crate::ids::macro_def_query)]
23 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
24
25 #[salsa::invoke(HirFileId::hir_parse_query)]
22 fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; 26 fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>;
23 27
24 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 28 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
@@ -27,17 +31,23 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
27 #[salsa::invoke(crate::adt::EnumData::enum_data_query)] 31 #[salsa::invoke(crate::adt::EnumData::enum_data_query)]
28 fn enum_data(&self, e: Enum) -> Arc<EnumData>; 32 fn enum_data(&self, e: Enum) -> Arc<EnumData>;
29 33
30 #[salsa::invoke(crate::ids::SourceFileItems::file_items_query)] 34 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
31 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; 35 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
36
37 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
38 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
32 39
33 #[salsa::invoke(crate::ids::SourceFileItems::file_item_query)] 40 #[salsa::invoke(crate::source_id::AstIdMap::file_item_query)]
34 fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>; 41 fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> TreeArc<SyntaxNode>;
35 42
36 #[salsa::invoke(RawItems::raw_items_query)] 43 #[salsa::invoke(RawItems::raw_items_query)]
37 fn raw_items(&self, file_id: FileId) -> Arc<RawItems>; 44 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
38 45
39 #[salsa::invoke(RawItems::raw_items_with_source_map_query)] 46 #[salsa::invoke(RawItems::raw_items_with_source_map_query)]
40 fn raw_items_with_source_map(&self, file_id: FileId) -> (Arc<RawItems>, Arc<ImportSourceMap>); 47 fn raw_items_with_source_map(
48 &self,
49 file_id: HirFileId,
50 ) -> (Arc<RawItems>, Arc<ImportSourceMap>);
41 51
42 #[salsa::invoke(CrateDefMap::crate_def_map_query)] 52 #[salsa::invoke(CrateDefMap::crate_def_map_query)]
43 fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>; 53 fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>;
@@ -98,6 +108,9 @@ pub trait HirDatabase: DefDatabase {
98 108
99 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 109 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
100 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 110 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
111
112 #[salsa::invoke(crate::ty::method_resolution::implements)]
113 fn implements(&self, trait_ref: TraitRef) -> bool;
101} 114}
102 115
103#[test] 116#[test]
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
new file mode 100644
index 000000000..d6a51b833
--- /dev/null
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -0,0 +1,115 @@
1use std::{fmt, any::Any};
2
3use ra_syntax::{SyntaxNodePtr, TreeArc, AstPtr, TextRange, ast, SyntaxNode};
4use relative_path::RelativePathBuf;
5
6use crate::{HirFileId, HirDatabase};
7
8/// Diagnostic defines hir API for errors and warnings.
9///
10/// It is used as a `dyn` object, which you can downcast to a concrete
11/// diagnostic. DiagnosticSink are structured, meaning that they include rich
12/// information which can be used by IDE to create fixes. DiagnosticSink are
13/// expressed in terms of macro-expanded syntax tree nodes (so, it's a bad idea
14/// to diagnostic in a salsa value).
15///
16/// Internally, various subsystems of hir produce diagnostics specific to a
17/// subsystem (typically, an `enum`), which are safe to store in salsa but do not
18/// include source locations. Such internal diagnostic are transformed into an
19/// instance of `Diagnostic` on demand.
20pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
21 fn message(&self) -> String;
22 fn file(&self) -> HirFileId;
23 fn syntax_node_ptr(&self) -> SyntaxNodePtr;
24 fn highlight_range(&self) -> TextRange {
25 self.syntax_node_ptr().range()
26 }
27 fn as_any(&self) -> &(dyn Any + Send + 'static);
28}
29
30impl dyn Diagnostic {
31 pub fn syntax_node(&self, db: &impl HirDatabase) -> TreeArc<SyntaxNode> {
32 let source_file = db.hir_parse(self.file());
33 self.syntax_node_ptr().to_node(&source_file).to_owned()
34 }
35 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> {
36 self.as_any().downcast_ref()
37 }
38}
39
40pub struct DiagnosticSink<'a> {
41 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>,
42 default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>,
43}
44
45impl<'a> DiagnosticSink<'a> {
46 pub fn new(cb: impl FnMut(&dyn Diagnostic) + 'a) -> DiagnosticSink<'a> {
47 DiagnosticSink { callbacks: Vec::new(), default_callback: Box::new(cb) }
48 }
49
50 pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> DiagnosticSink<'a> {
51 let cb = move |diag: &dyn Diagnostic| match diag.downcast_ref::<D>() {
52 Some(d) => {
53 cb(d);
54 Ok(())
55 }
56 None => Err(()),
57 };
58 self.callbacks.push(Box::new(cb));
59 self
60 }
61
62 pub(crate) fn push(&mut self, d: impl Diagnostic) {
63 let d: &dyn Diagnostic = &d;
64 for cb in self.callbacks.iter_mut() {
65 match cb(d) {
66 Ok(()) => return,
67 Err(()) => (),
68 }
69 }
70 (self.default_callback)(d)
71 }
72}
73
74#[derive(Debug)]
75pub struct NoSuchField {
76 pub file: HirFileId,
77 pub field: AstPtr<ast::NamedField>,
78}
79
80impl Diagnostic for NoSuchField {
81 fn message(&self) -> String {
82 "no such field".to_string()
83 }
84 fn file(&self) -> HirFileId {
85 self.file
86 }
87 fn syntax_node_ptr(&self) -> SyntaxNodePtr {
88 self.field.into()
89 }
90 fn as_any(&self) -> &(Any + Send + 'static) {
91 self
92 }
93}
94
95#[derive(Debug)]
96pub struct UnresolvedModule {
97 pub file: HirFileId,
98 pub decl: AstPtr<ast::Module>,
99 pub candidate: RelativePathBuf,
100}
101
102impl Diagnostic for UnresolvedModule {
103 fn message(&self) -> String {
104 "unresolved module".to_string()
105 }
106 fn file(&self) -> HirFileId {
107 self.file
108 }
109 fn syntax_node_ptr(&self) -> SyntaxNodePtr {
110 self.decl.into()
111 }
112 fn as_any(&self) -> &(Any + Send + 'static) {
113 self
114 }
115}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index c37fd0454..a85422955 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;
5 5
6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_syntax::{ 7use ra_syntax::{
8 SyntaxNodePtr, AstNode, 8 SyntaxNodePtr, AstPtr, AstNode,
9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor, TypeAscriptionOwner} 9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor, TypeAscriptionOwner}
10}; 10};
11 11
@@ -54,6 +54,7 @@ pub struct BodySourceMap {
54 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>, 54 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>,
55 pat_map: FxHashMap<SyntaxNodePtr, PatId>, 55 pat_map: FxHashMap<SyntaxNodePtr, PatId>,
56 pat_map_back: ArenaMap<PatId, SyntaxNodePtr>, 56 pat_map_back: ArenaMap<PatId, SyntaxNodePtr>,
57 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>,
57} 58}
58 59
59impl Body { 60impl Body {
@@ -138,6 +139,10 @@ impl BodySourceMap {
138 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { 139 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
139 self.pat_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() 140 self.pat_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
140 } 141 }
142
143 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> {
144 self.field_map[&(expr, field)].clone()
145 }
141} 146}
142 147
143#[derive(Debug, Clone, Eq, PartialEq)] 148#[derive(Debug, Clone, Eq, PartialEq)]
@@ -629,8 +634,10 @@ impl ExprCollector {
629 } 634 }
630 ast::ExprKind::StructLit(e) => { 635 ast::ExprKind::StructLit(e) => {
631 let path = e.path().and_then(Path::from_ast); 636 let path = e.path().and_then(Path::from_ast);
637 let mut field_ptrs = Vec::new();
632 let fields = if let Some(nfl) = e.named_field_list() { 638 let fields = if let Some(nfl) = e.named_field_list() {
633 nfl.fields() 639 nfl.fields()
640 .inspect(|field| field_ptrs.push(AstPtr::new(*field)))
634 .map(|field| StructLitField { 641 .map(|field| StructLitField {
635 name: field 642 name: field
636 .name_ref() 643 .name_ref()
@@ -657,7 +664,11 @@ impl ExprCollector {
657 Vec::new() 664 Vec::new()
658 }; 665 };
659 let spread = e.spread().map(|s| self.collect_expr(s)); 666 let spread = e.spread().map(|s| self.collect_expr(s));
660 self.alloc_expr(Expr::StructLit { path, fields, spread }, syntax_ptr) 667 let res = self.alloc_expr(Expr::StructLit { path, fields, spread }, syntax_ptr);
668 for (i, ptr) in field_ptrs.into_iter().enumerate() {
669 self.source_map.field_map.insert((res, i), ptr);
670 }
671 res
661 } 672 }
662 ast::ExprKind::FieldExpr(e) => { 673 ast::ExprKind::FieldExpr(e) => {
663 let expr = self.collect_expr_opt(e.expr()); 674 let expr = self.collect_expr_opt(e.expr());
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 18401f865..eb9939df7 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,16 +1,15 @@
1use std::{ 1use std::{
2 marker::PhantomData,
3 hash::{Hash, Hasher}, 2 hash::{Hash, Hasher},
4 sync::Arc, 3 sync::Arc,
5}; 4};
6 5
7use ra_db::{LocationInterner, FileId}; 6use ra_db::{LocationInterner, FileId};
8use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast}; 7use ra_syntax::{TreeArc, SourceFile, AstNode, ast};
9use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; 8use ra_arena::{RawId, ArenaId, impl_arena_id};
9use mbe::MacroRules;
10 10
11use crate::{ 11use crate::{
12 Module, 12 Module, DefDatabase, AstId, FileAstId,
13 DefDatabase,
14}; 13};
15 14
16#[derive(Debug, Default)] 15#[derive(Debug, Default)]
@@ -22,7 +21,7 @@ pub struct HirInterner {
22 consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>, 21 consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>,
23 statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>, 22 statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>,
24 traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>, 23 traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>,
25 types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeId>, 24 types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeAliasId>,
26} 25}
27 26
28impl HirInterner { 27impl HirInterner {
@@ -68,7 +67,7 @@ impl HirFileId {
68 HirFileIdRepr::File(file_id) => file_id, 67 HirFileIdRepr::File(file_id) => file_id,
69 HirFileIdRepr::Macro(macro_call_id) => { 68 HirFileIdRepr::Macro(macro_call_id) => {
70 let loc = macro_call_id.loc(db); 69 let loc = macro_call_id.loc(db);
71 loc.source_item_id.file_id.original_file(db) 70 loc.ast_id.file_id().original_file(db)
72 } 71 }
73 } 72 }
74 } 73 }
@@ -83,7 +82,10 @@ impl HirFileId {
83 } 82 }
84 } 83 }
85 84
86 pub(crate) fn hir_parse(db: &impl DefDatabase, file_id: HirFileId) -> TreeArc<SourceFile> { 85 pub(crate) fn hir_parse_query(
86 db: &impl DefDatabase,
87 file_id: HirFileId,
88 ) -> TreeArc<SourceFile> {
87 match file_id.0 { 89 match file_id.0 {
88 HirFileIdRepr::File(file_id) => db.parse(file_id), 90 HirFileIdRepr::File(file_id) => db.parse(file_id),
89 HirFileIdRepr::Macro(macro_call_id) => { 91 HirFileIdRepr::Macro(macro_call_id) => {
@@ -96,14 +98,10 @@ impl HirFileId {
96 98
97fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> { 99fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> {
98 let loc = macro_call_id.loc(db); 100 let loc = macro_call_id.loc(db);
99 let syntax = db.file_item(loc.source_item_id); 101 let macro_call = loc.ast_id.to_node(db);
100 let macro_call = ast::MacroCall::cast(&syntax).unwrap();
101 let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?; 102 let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?;
102 103
103 let def_map = db.crate_def_map(loc.module.krate); 104 let macro_rules = db.macro_def(loc.def)?;
104 let (krate, macro_id) = def_map.resolve_macro(macro_call_id)?;
105 let def_map = db.crate_def_map(krate);
106 let macro_rules = &def_map[macro_id];
107 let tt = macro_rules.expand(&macro_arg).ok()?; 105 let tt = macro_rules.expand(&macro_arg).ok()?;
108 Some(mbe::token_tree_to_ast_item_list(&tt)) 106 Some(mbe::token_tree_to_ast_item_list(&tt))
109} 107}
@@ -126,6 +124,17 @@ impl From<MacroCallId> for HirFileId {
126 } 124 }
127} 125}
128 126
127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>);
129
130pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
131 let macro_call = id.0.to_node(db);
132 let arg = macro_call.token_tree()?;
133 let (tt, _) = mbe::ast_to_token_tree(arg)?;
134 let rules = MacroRules::parse(&tt).ok()?;
135 Some(Arc::new(rules))
136}
137
129/// `MacroCallId` identifies a particular macro invocation, like 138/// `MacroCallId` identifies a particular macro invocation, like
130/// `println!("Hello, {}", world)`. 139/// `println!("Hello, {}", world)`.
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -134,8 +143,8 @@ impl_arena_id!(MacroCallId);
134 143
135#[derive(Debug, Clone, PartialEq, Eq, Hash)] 144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136pub struct MacroCallLoc { 145pub struct MacroCallLoc {
137 pub(crate) module: Module, 146 pub(crate) def: MacroDefId,
138 pub(crate) source_item_id: SourceItemId, 147 pub(crate) ast_id: AstId<ast::MacroCall>,
139} 148}
140 149
141impl MacroCallId { 150impl MacroCallId {
@@ -145,7 +154,6 @@ impl MacroCallId {
145} 154}
146 155
147impl MacroCallLoc { 156impl MacroCallLoc {
148 #[allow(unused)]
149 pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId { 157 pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId {
150 db.as_ref().macros.loc2id(&self) 158 db.as_ref().macros.loc2id(&self)
151 } 159 }
@@ -154,26 +162,25 @@ impl MacroCallLoc {
154#[derive(Debug)] 162#[derive(Debug)]
155pub struct ItemLoc<N: AstNode> { 163pub struct ItemLoc<N: AstNode> {
156 pub(crate) module: Module, 164 pub(crate) module: Module,
157 raw: SourceItemId, 165 ast_id: AstId<N>,
158 _ty: PhantomData<N>,
159} 166}
160 167
161impl<N: AstNode> PartialEq for ItemLoc<N> { 168impl<N: AstNode> PartialEq for ItemLoc<N> {
162 fn eq(&self, other: &Self) -> bool { 169 fn eq(&self, other: &Self) -> bool {
163 self.module == other.module && self.raw == other.raw 170 self.module == other.module && self.ast_id == other.ast_id
164 } 171 }
165} 172}
166impl<N: AstNode> Eq for ItemLoc<N> {} 173impl<N: AstNode> Eq for ItemLoc<N> {}
167impl<N: AstNode> Hash for ItemLoc<N> { 174impl<N: AstNode> Hash for ItemLoc<N> {
168 fn hash<H: Hasher>(&self, hasher: &mut H) { 175 fn hash<H: Hasher>(&self, hasher: &mut H) {
169 self.module.hash(hasher); 176 self.module.hash(hasher);
170 self.raw.hash(hasher); 177 self.ast_id.hash(hasher);
171 } 178 }
172} 179}
173 180
174impl<N: AstNode> Clone for ItemLoc<N> { 181impl<N: AstNode> Clone for ItemLoc<N> {
175 fn clone(&self) -> ItemLoc<N> { 182 fn clone(&self) -> ItemLoc<N> {
176 ItemLoc { module: self.module, raw: self.raw, _ty: PhantomData } 183 ItemLoc { module: self.module, ast_id: self.ast_id }
177 } 184 }
178} 185}
179 186
@@ -200,26 +207,19 @@ impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
200pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { 207pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
201 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>; 208 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>;
202 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self { 209 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self {
203 let items = ctx.db.file_items(ctx.file_id); 210 let items = ctx.db.ast_id_map(ctx.file_id);
204 let item_id = items.id_of(ctx.file_id, ast.syntax()); 211 let item_id = items.ast_id(ast);
205 Self::from_source_item_id_unchecked(ctx, item_id) 212 Self::from_ast_id(ctx, item_id)
206 } 213 }
207 fn from_source_item_id_unchecked( 214 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
208 ctx: LocationCtx<&impl DefDatabase>, 215 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
209 item_id: SourceFileItemId,
210 ) -> Self {
211 let raw = SourceItemId { file_id: ctx.file_id, item_id };
212 let loc = ItemLoc { module: ctx.module, raw, _ty: PhantomData };
213
214 Self::interner(ctx.db.as_ref()).loc2id(&loc) 216 Self::interner(ctx.db.as_ref()).loc2id(&loc)
215 } 217 }
216 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) { 218 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) {
217 let int = Self::interner(db.as_ref()); 219 let int = Self::interner(db.as_ref());
218 let loc = int.id2loc(self); 220 let loc = int.id2loc(self);
219 let syntax = db.file_item(loc.raw); 221 let ast = loc.ast_id.to_node(db);
220 let ast = 222 (loc.ast_id.file_id(), ast)
221 N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned();
222 (loc.raw.file_id, ast)
223 } 223 }
224 fn module(self, db: &impl DefDatabase) -> Module { 224 fn module(self, db: &impl DefDatabase) -> Module {
225 let int = Self::interner(db.as_ref()); 225 let int = Self::interner(db.as_ref());
@@ -229,7 +229,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
229} 229}
230 230
231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
232pub struct FunctionId(RawId); 232pub(crate) struct FunctionId(RawId);
233impl_arena_id!(FunctionId); 233impl_arena_id!(FunctionId);
234impl AstItemDef<ast::FnDef> for FunctionId { 234impl AstItemDef<ast::FnDef> for FunctionId {
235 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> { 235 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> {
@@ -238,7 +238,7 @@ impl AstItemDef<ast::FnDef> for FunctionId {
238} 238}
239 239
240#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 240#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
241pub struct StructId(RawId); 241pub(crate) struct StructId(RawId);
242impl_arena_id!(StructId); 242impl_arena_id!(StructId);
243impl AstItemDef<ast::StructDef> for StructId { 243impl AstItemDef<ast::StructDef> for StructId {
244 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> { 244 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> {
@@ -247,7 +247,7 @@ impl AstItemDef<ast::StructDef> for StructId {
247} 247}
248 248
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
250pub struct EnumId(RawId); 250pub(crate) struct EnumId(RawId);
251impl_arena_id!(EnumId); 251impl_arena_id!(EnumId);
252impl AstItemDef<ast::EnumDef> for EnumId { 252impl AstItemDef<ast::EnumDef> for EnumId {
253 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> { 253 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> {
@@ -256,7 +256,7 @@ impl AstItemDef<ast::EnumDef> for EnumId {
256} 256}
257 257
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
259pub struct ConstId(RawId); 259pub(crate) struct ConstId(RawId);
260impl_arena_id!(ConstId); 260impl_arena_id!(ConstId);
261impl AstItemDef<ast::ConstDef> for ConstId { 261impl AstItemDef<ast::ConstDef> for ConstId {
262 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> { 262 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> {
@@ -265,7 +265,7 @@ impl AstItemDef<ast::ConstDef> for ConstId {
265} 265}
266 266
267#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 267#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
268pub struct StaticId(RawId); 268pub(crate) struct StaticId(RawId);
269impl_arena_id!(StaticId); 269impl_arena_id!(StaticId);
270impl AstItemDef<ast::StaticDef> for StaticId { 270impl AstItemDef<ast::StaticDef> for StaticId {
271 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StaticDef>, Self> { 271 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StaticDef>, Self> {
@@ -274,7 +274,7 @@ impl AstItemDef<ast::StaticDef> for StaticId {
274} 274}
275 275
276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
277pub struct TraitId(RawId); 277pub(crate) struct TraitId(RawId);
278impl_arena_id!(TraitId); 278impl_arena_id!(TraitId);
279impl AstItemDef<ast::TraitDef> for TraitId { 279impl AstItemDef<ast::TraitDef> for TraitId {
280 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> { 280 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> {
@@ -283,117 +283,10 @@ impl AstItemDef<ast::TraitDef> for TraitId {
283} 283}
284 284
285#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 285#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
286pub struct TypeId(RawId); 286pub(crate) struct TypeAliasId(RawId);
287impl_arena_id!(TypeId); 287impl_arena_id!(TypeAliasId);
288impl AstItemDef<ast::TypeAliasDef> for TypeId { 288impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
289 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> { 289 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> {
290 &interner.types 290 &interner.types
291 } 291 }
292} 292}
293
294/// Identifier of item within a specific file. This is stable over reparses, so
295/// it's OK to use it as a salsa key/value.
296#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
297pub struct SourceFileItemId(RawId);
298impl_arena_id!(SourceFileItemId);
299
300impl SourceFileItemId {
301 pub(crate) fn with_file_id(self, file_id: HirFileId) -> SourceItemId {
302 SourceItemId { file_id, item_id: self }
303 }
304}
305
306#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
307pub struct SourceItemId {
308 pub(crate) file_id: HirFileId,
309 pub(crate) item_id: SourceFileItemId,
310}
311
312/// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back.
313#[derive(Debug, PartialEq, Eq)]
314pub struct SourceFileItems {
315 file_id: HirFileId,
316 arena: Arena<SourceFileItemId, SyntaxNodePtr>,
317}
318
319impl SourceFileItems {
320 pub(crate) fn file_items_query(
321 db: &impl DefDatabase,
322 file_id: HirFileId,
323 ) -> Arc<SourceFileItems> {
324 let source_file = db.hir_parse(file_id);
325 Arc::new(SourceFileItems::from_source_file(&source_file, file_id))
326 }
327
328 pub(crate) fn file_item_query(
329 db: &impl DefDatabase,
330 source_item_id: SourceItemId,
331 ) -> TreeArc<SyntaxNode> {
332 let source_file = db.hir_parse(source_item_id.file_id);
333 db.file_items(source_item_id.file_id)[source_item_id.item_id]
334 .to_node(&source_file)
335 .to_owned()
336 }
337
338 pub(crate) fn from_source_file(
339 source_file: &SourceFile,
340 file_id: HirFileId,
341 ) -> SourceFileItems {
342 let mut res = SourceFileItems { file_id, arena: Arena::default() };
343 // By walking the tree in bread-first order we make sure that parents
344 // get lower ids then children. That is, adding a new child does not
345 // change parent's id. This means that, say, adding a new function to a
346 // trait does not change ids of top-level items, which helps caching.
347 bfs(source_file.syntax(), |it| {
348 if let Some(module_item) = ast::ModuleItem::cast(it) {
349 res.alloc(module_item.syntax());
350 } else if let Some(macro_call) = ast::MacroCall::cast(it) {
351 res.alloc(macro_call.syntax());
352 }
353 });
354 res
355 }
356
357 fn alloc(&mut self, item: &SyntaxNode) -> SourceFileItemId {
358 self.arena.alloc(SyntaxNodePtr::new(item))
359 }
360 pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId {
361 assert_eq!(
362 self.file_id, file_id,
363 "SourceFileItems: wrong file, expected {:?}, got {:?}",
364 self.file_id, file_id
365 );
366 self.id_of_unchecked(item)
367 }
368 pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId {
369 let ptr = SyntaxNodePtr::new(item);
370 if let Some((id, _)) = self.arena.iter().find(|(_id, i)| **i == ptr) {
371 return id;
372 }
373 panic!(
374 "Can't find {:?} in SourceFileItems:\n{:?}",
375 item,
376 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
377 );
378 }
379}
380
381impl std::ops::Index<SourceFileItemId> for SourceFileItems {
382 type Output = SyntaxNodePtr;
383 fn index(&self, idx: SourceFileItemId) -> &SyntaxNodePtr {
384 &self.arena[idx]
385 }
386}
387
388/// Walks the subtree in bfs order, calling `f` for each node.
389fn bfs(node: &SyntaxNode, mut f: impl FnMut(&SyntaxNode)) {
390 let mut curr_layer = vec![node];
391 let mut next_layer = vec![];
392 while !curr_layer.is_empty() {
393 curr_layer.drain(..).for_each(|node| {
394 next_layer.extend(node.children());
395 f(node);
396 });
397 std::mem::swap(&mut curr_layer, &mut next_layer);
398 }
399}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a89c916f8..7c603bbd3 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -23,10 +23,12 @@ pub mod mock;
23mod path; 23mod path;
24pub mod source_binder; 24pub mod source_binder;
25 25
26mod source_id;
26mod ids; 27mod ids;
27mod name; 28mod name;
28mod nameres; 29mod nameres;
29mod adt; 30mod adt;
31mod traits;
30mod type_alias; 32mod type_alias;
31mod type_ref; 33mod type_ref;
32mod ty; 34mod ty;
@@ -35,6 +37,7 @@ mod expr;
35mod generics; 37mod generics;
36mod docs; 38mod docs;
37mod resolve; 39mod resolve;
40pub mod diagnostics;
38 41
39mod code_model_api; 42mod code_model_api;
40mod code_model_impl; 43mod code_model_impl;
@@ -45,13 +48,14 @@ mod marks;
45use crate::{ 48use crate::{
46 db::{HirDatabase, DefDatabase}, 49 db::{HirDatabase, DefDatabase},
47 name::{AsName, KnownName}, 50 name::{AsName, KnownName},
48 ids::{SourceItemId, SourceFileItems}, 51 source_id::{FileAstId, AstId},
49}; 52};
50 53
51pub use self::{ 54pub use self::{
52 path::{Path, PathKind}, 55 path::{Path, PathKind},
53 name::Name, 56 name::Name,
54 ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, 57 source_id::{AstIdMap, ErasedFileAstId},
58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
55 nameres::{PerNs, Namespace}, 59 nameres::{PerNs, Namespace},
56 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, 60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
57 impl_block::{ImplBlock, ImplItem}, 61 impl_block::{ImplBlock, ImplItem},
@@ -63,7 +67,7 @@ pub use self::{
63 67
64pub use self::code_model_api::{ 68pub use self::code_model_api::{
65 Crate, CrateDependency, 69 Crate, CrateDependency,
66 Module, ModuleDef, ModuleSource, Problem, 70 Module, ModuleDef, ModuleSource,
67 Struct, Enum, EnumVariant, 71 Struct, Enum, EnumVariant,
68 Function, FnSignature, 72 Function, FnSignature,
69 StructField, FieldSource, 73 StructField, FieldSource,
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 10d4c1b8c..aeab6b180 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -9,7 +9,7 @@ use relative_path::RelativePathBuf;
9use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; 9use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
10use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
11 11
12use crate::{db, HirInterner}; 12use crate::{db, HirInterner, diagnostics::DiagnosticSink};
13 13
14pub const WORKSPACE: SourceRootId = SourceRootId(0); 14pub const WORKSPACE: SourceRootId = SourceRootId(0);
15 15
@@ -70,6 +70,22 @@ impl MockDatabase {
70 self.set_crate_graph(Arc::new(crate_graph)) 70 self.set_crate_graph(Arc::new(crate_graph))
71 } 71 }
72 72
73 pub fn diagnostics(&self) -> String {
74 let mut buf = String::from("\n");
75 let mut files: Vec<FileId> = self.files.values().map(|&it| it).collect();
76 files.sort();
77 for file in files {
78 let module = crate::source_binder::module_from_file_id(self, file).unwrap();
79 module.diagnostics(
80 self,
81 &mut DiagnosticSink::new(|d| {
82 buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message());
83 }),
84 )
85 }
86 buf
87 }
88
73 fn from_fixture(fixture: &str) -> (MockDatabase, Option<FilePosition>) { 89 fn from_fixture(fixture: &str) -> (MockDatabase, Option<FilePosition>) {
74 let mut db = MockDatabase::default(); 90 let mut db = MockDatabase::default();
75 91
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 5ac878c79..8adc6d368 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -59,12 +59,16 @@ use rustc_hash::FxHashMap;
59use ra_arena::{Arena, RawId, impl_arena_id}; 59use ra_arena::{Arena, RawId, impl_arena_id};
60use ra_db::{FileId, Edition}; 60use ra_db::{FileId, Edition};
61use test_utils::tested_by; 61use test_utils::tested_by;
62use ra_syntax::ast;
62use ra_prof::profile; 63use ra_prof::profile;
63 64
64use crate::{ 65use crate::{
65 ModuleDef, Name, Crate, Module, Problem, 66 ModuleDef, Name, Crate, Module,
66 DefDatabase, Path, PathKind, HirFileId, 67 DefDatabase, Path, PathKind, HirFileId, Trait,
67 ids::{SourceItemId, SourceFileItemId, MacroCallId}, 68 ids::MacroDefId,
69 diagnostics::DiagnosticSink,
70 nameres::diagnostics::DefDiagnostic,
71 AstId,
68}; 72};
69 73
70pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; 74pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap};
@@ -83,10 +87,8 @@ pub struct CrateDefMap {
83 extern_prelude: FxHashMap<Name, ModuleDef>, 87 extern_prelude: FxHashMap<Name, ModuleDef>,
84 root: CrateModuleId, 88 root: CrateModuleId,
85 modules: Arena<CrateModuleId, ModuleData>, 89 modules: Arena<CrateModuleId, ModuleData>,
86 macros: Arena<CrateMacroId, mbe::MacroRules>, 90 public_macros: FxHashMap<Name, MacroDefId>,
87 public_macros: FxHashMap<Name, CrateMacroId>, 91 diagnostics: Vec<DefDiagnostic>,
88 macro_resolutions: FxHashMap<MacroCallId, (Crate, CrateMacroId)>,
89 problems: CrateDefMapProblems,
90} 92}
91 93
92impl std::ops::Index<CrateModuleId> for CrateDefMap { 94impl std::ops::Index<CrateModuleId> for CrateDefMap {
@@ -96,18 +98,6 @@ impl std::ops::Index<CrateModuleId> for CrateDefMap {
96 } 98 }
97} 99}
98 100
99impl std::ops::Index<CrateMacroId> for CrateDefMap {
100 type Output = mbe::MacroRules;
101 fn index(&self, id: CrateMacroId) -> &mbe::MacroRules {
102 &self.macros[id]
103 }
104}
105
106/// An ID of a macro, **local** to a specific crate
107#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
108pub(crate) struct CrateMacroId(RawId);
109impl_arena_id!(CrateMacroId);
110
111/// An ID of a module, **local** to a specific crate 101/// An ID of a module, **local** to a specific crate
112#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 102#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
113pub(crate) struct CrateModuleId(RawId); 103pub(crate) struct CrateModuleId(RawId);
@@ -119,28 +109,13 @@ pub(crate) struct ModuleData {
119 pub(crate) children: FxHashMap<Name, CrateModuleId>, 109 pub(crate) children: FxHashMap<Name, CrateModuleId>,
120 pub(crate) scope: ModuleScope, 110 pub(crate) scope: ModuleScope,
121 /// None for root 111 /// None for root
122 pub(crate) declaration: Option<SourceItemId>, 112 pub(crate) declaration: Option<AstId<ast::Module>>,
123 /// None for inline modules. 113 /// None for inline modules.
124 /// 114 ///
125 /// Note that non-inline modules, by definition, live inside non-macro file. 115 /// Note that non-inline modules, by definition, live inside non-macro file.
126 pub(crate) definition: Option<FileId>, 116 pub(crate) definition: Option<FileId>,
127} 117}
128 118
129#[derive(Default, Debug, PartialEq, Eq)]
130pub(crate) struct CrateDefMapProblems {
131 problems: Vec<(SourceItemId, Problem)>,
132}
133
134impl CrateDefMapProblems {
135 fn add(&mut self, source_item_id: SourceItemId, problem: Problem) {
136 self.problems.push((source_item_id, problem))
137 }
138
139 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a {
140 self.problems.iter().map(|(s, p)| (s, p))
141 }
142}
143
144#[derive(Debug, Default, PartialEq, Eq, Clone)] 119#[derive(Debug, Default, PartialEq, Eq, Clone)]
145pub struct ModuleScope { 120pub struct ModuleScope {
146 items: FxHashMap<Name, Resolution>, 121 items: FxHashMap<Name, Resolution>,
@@ -153,6 +128,12 @@ impl ModuleScope {
153 pub fn get(&self, name: &Name) -> Option<&Resolution> { 128 pub fn get(&self, name: &Name) -> Option<&Resolution> {
154 self.items.get(name) 129 self.items.get(name)
155 } 130 }
131 pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a {
132 self.items.values().filter_map(|r| match r.def.take_types() {
133 Some(ModuleDef::Trait(t)) => Some(t),
134 _ => None,
135 })
136 }
156} 137}
157 138
158#[derive(Debug, Clone, PartialEq, Eq, Default)] 139#[derive(Debug, Clone, PartialEq, Eq, Default)]
@@ -210,10 +191,8 @@ impl CrateDefMap {
210 prelude: None, 191 prelude: None,
211 root, 192 root,
212 modules, 193 modules,
213 macros: Arena::default(),
214 public_macros: FxHashMap::default(), 194 public_macros: FxHashMap::default(),
215 macro_resolutions: FxHashMap::default(), 195 diagnostics: Vec::new(),
216 problems: CrateDefMapProblems::default(),
217 } 196 }
218 }; 197 };
219 let def_map = collector::collect_defs(db, def_map); 198 let def_map = collector::collect_defs(db, def_map);
@@ -224,10 +203,6 @@ impl CrateDefMap {
224 self.root 203 self.root
225 } 204 }
226 205
227 pub(crate) fn problems(&self) -> &CrateDefMapProblems {
228 &self.problems
229 }
230
231 pub(crate) fn mk_module(&self, module_id: CrateModuleId) -> Module { 206 pub(crate) fn mk_module(&self, module_id: CrateModuleId) -> Module {
232 Module { krate: self.krate, module_id } 207 Module { krate: self.krate, module_id }
233 } 208 }
@@ -240,19 +215,20 @@ impl CrateDefMap {
240 &self.extern_prelude 215 &self.extern_prelude
241 } 216 }
242 217
243 pub(crate) fn resolve_macro( 218 pub(crate) fn add_diagnostics(
244 &self, 219 &self,
245 macro_call_id: MacroCallId, 220 db: &impl DefDatabase,
246 ) -> Option<(Crate, CrateMacroId)> { 221 module: CrateModuleId,
247 self.macro_resolutions.get(&macro_call_id).map(|&it| it) 222 sink: &mut DiagnosticSink,
223 ) {
224 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
248 } 225 }
249 226
250 pub(crate) fn find_module_by_source( 227 pub(crate) fn find_module_by_source(
251 &self, 228 &self,
252 file_id: HirFileId, 229 file_id: HirFileId,
253 decl_id: Option<SourceFileItemId>, 230 decl_id: Option<AstId<ast::Module>>,
254 ) -> Option<CrateModuleId> { 231 ) -> Option<CrateModuleId> {
255 let decl_id = decl_id.map(|it| it.with_file_id(file_id));
256 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| { 232 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
257 if decl_id.is_some() { 233 if decl_id.is_some() {
258 module_data.declaration == decl_id 234 module_data.declaration == decl_id
@@ -452,3 +428,46 @@ impl CrateDefMap {
452 } 428 }
453 } 429 }
454} 430}
431
432mod diagnostics {
433 use relative_path::RelativePathBuf;
434 use ra_syntax::{AstPtr, ast};
435
436 use crate::{
437 AstId, DefDatabase,
438 nameres::CrateModuleId,
439 diagnostics::{DiagnosticSink, UnresolvedModule},
440};
441
442 #[derive(Debug, PartialEq, Eq)]
443 pub(super) enum DefDiagnostic {
444 UnresolvedModule {
445 module: CrateModuleId,
446 declaration: AstId<ast::Module>,
447 candidate: RelativePathBuf,
448 },
449 }
450
451 impl DefDiagnostic {
452 pub(super) fn add_to(
453 &self,
454 db: &impl DefDatabase,
455 target_module: CrateModuleId,
456 sink: &mut DiagnosticSink,
457 ) {
458 match self {
459 DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
460 if *module != target_module {
461 return;
462 }
463 let decl = declaration.to_node(db);
464 sink.push(UnresolvedModule {
465 file: declaration.file_id(),
466 decl: AstPtr::new(&decl),
467 candidate: candidate.clone(),
468 })
469 }
470 }
471 }
472 }
473}
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index c5b73cfbe..39cadc94a 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -3,17 +3,22 @@ use rustc_hash::FxHashMap;
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use test_utils::tested_by; 4use test_utils::tested_by;
5use ra_db::FileId; 5use ra_db::FileId;
6use ra_syntax::ast;
6 7
7use crate::{ 8use crate::{
8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, 9 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
9 DefDatabase, HirFileId, Name, Path, Problem, Crate, 10 DefDatabase, HirFileId, Name, Path,
10 KnownName, 11 KnownName,
11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw}, 12 nameres::{
12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, 13 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode,
14 CrateDefMap, CrateModuleId, ModuleData,
15 diagnostics::DefDiagnostic,
16 raw,
17 },
18 ids::{AstItemDef, LocationCtx, MacroCallLoc, MacroCallId, MacroDefId},
19 AstId,
13}; 20};
14 21
15use super::{CrateDefMap, CrateModuleId, ModuleData, CrateMacroId};
16
17pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 22pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
18 // populate external prelude 23 // populate external prelude
19 for dep in def_map.krate.dependencies(db) { 24 for dep in def_map.krate.dependencies(db) {
@@ -48,8 +53,8 @@ struct DefCollector<DB> {
48 def_map: CrateDefMap, 53 def_map: CrateDefMap,
49 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 54 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
50 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 55 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
51 unexpanded_macros: Vec<(CrateModuleId, MacroCallId, Path, tt::Subtree)>, 56 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>,
52 global_macro_scope: FxHashMap<Name, CrateMacroId>, 57 global_macro_scope: FxHashMap<Name, MacroDefId>,
53} 58}
54 59
55impl<'a, DB> DefCollector<&'a DB> 60impl<'a, DB> DefCollector<&'a DB>
@@ -59,7 +64,7 @@ where
59 fn collect(&mut self) { 64 fn collect(&mut self) {
60 let crate_graph = self.db.crate_graph(); 65 let crate_graph = self.db.crate_graph();
61 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id()); 66 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
62 let raw_items = self.db.raw_items(file_id); 67 let raw_items = self.db.raw_items(file_id.into());
63 let module_id = self.def_map.root; 68 let module_id = self.def_map.root;
64 self.def_map.modules[module_id].definition = Some(file_id); 69 self.def_map.modules[module_id].definition = Some(file_id);
65 ModCollector { 70 ModCollector {
@@ -90,14 +95,11 @@ where
90 } 95 }
91 } 96 }
92 97
93 fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { 98 fn define_macro(&mut self, name: Name, macro_id: MacroDefId, export: bool) {
94 if let Ok(rules) = mbe::MacroRules::parse(tt) { 99 if export {
95 let macro_id = self.def_map.macros.alloc(rules); 100 self.def_map.public_macros.insert(name.clone(), macro_id);
96 if export {
97 self.def_map.public_macros.insert(name.clone(), macro_id);
98 }
99 self.global_macro_scope.insert(name, macro_id);
100 } 101 }
102 self.global_macro_scope.insert(name, macro_id);
101 } 103 }
102 104
103 fn resolve_imports(&mut self) -> ReachedFixedPoint { 105 fn resolve_imports(&mut self) -> ReachedFixedPoint {
@@ -293,7 +295,7 @@ where
293 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 295 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
294 let mut resolved = Vec::new(); 296 let mut resolved = Vec::new();
295 let mut res = ReachedFixedPoint::Yes; 297 let mut res = ReachedFixedPoint::Yes;
296 macros.retain(|(module_id, call_id, path, tt)| { 298 macros.retain(|(module_id, ast_id, path)| {
297 if path.segments.len() != 2 { 299 if path.segments.len() != 2 {
298 return true; 300 return true;
299 } 301 }
@@ -309,47 +311,23 @@ where
309 res = ReachedFixedPoint::No; 311 res = ReachedFixedPoint::No;
310 let def_map = self.db.crate_def_map(krate); 312 let def_map = self.db.crate_def_map(krate);
311 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() { 313 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() {
312 resolved.push((*module_id, *call_id, (krate, macro_id), tt.clone())); 314 let call_id = MacroCallLoc { def: macro_id, ast_id: *ast_id }.id(self.db);
315 resolved.push((*module_id, call_id));
313 } 316 }
314 false 317 false
315 }); 318 });
316 319
317 for (module_id, macro_call_id, macro_def_id, arg) in resolved { 320 for (module_id, macro_call_id) in resolved {
318 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id, arg); 321 self.collect_macro_expansion(module_id, macro_call_id);
319 } 322 }
320 res 323 res
321 } 324 }
322 325
323 fn collect_macro_expansion( 326 fn collect_macro_expansion(&mut self, module_id: CrateModuleId, macro_call_id: MacroCallId) {
324 &mut self, 327 let file_id: HirFileId = macro_call_id.into();
325 module_id: CrateModuleId, 328 let raw_items = self.db.raw_items(file_id);
326 macro_call_id: MacroCallId, 329 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
327 macro_def_id: (Crate, CrateMacroId), 330 .collect(raw_items.items())
328 macro_arg: tt::Subtree,
329 ) {
330 let (macro_krate, macro_id) = macro_def_id;
331 let dm;
332 let rules = if macro_krate == self.def_map.krate {
333 &self.def_map[macro_id]
334 } else {
335 dm = self.db.crate_def_map(macro_krate);
336 &dm[macro_id]
337 };
338 if let Ok(expansion) = rules.expand(&macro_arg) {
339 self.def_map.macro_resolutions.insert(macro_call_id, macro_def_id);
340 // XXX: this **does not** go through a database, because we can't
341 // identify macro_call without adding the whole state of name resolution
342 // as a parameter to the query.
343 //
344 // So, we run the queries "manually" and we must ensure that
345 // `db.hir_parse(macro_call_id)` returns the same source_file.
346 let file_id: HirFileId = macro_call_id.into();
347 let source_file = mbe::token_tree_to_ast_item_list(&expansion);
348
349 let raw_items = raw::RawItems::from_source_file(&source_file, file_id);
350 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
351 .collect(raw_items.items())
352 }
353 } 331 }
354 332
355 fn finish(self) -> CrateDefMap { 333 fn finish(self) -> CrateDefMap {
@@ -387,12 +365,9 @@ where
387 fn collect_module(&mut self, module: &raw::ModuleData) { 365 fn collect_module(&mut self, module: &raw::ModuleData) {
388 match module { 366 match module {
389 // inline module, just recurse 367 // inline module, just recurse
390 raw::ModuleData::Definition { name, items, source_item_id } => { 368 raw::ModuleData::Definition { name, items, ast_id } => {
391 let module_id = self.push_child_module( 369 let module_id =
392 name.clone(), 370 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None);
393 source_item_id.with_file_id(self.file_id),
394 None,
395 );
396 ModCollector { 371 ModCollector {
397 def_collector: &mut *self.def_collector, 372 def_collector: &mut *self.def_collector,
398 module_id, 373 module_id,
@@ -402,28 +377,29 @@ where
402 .collect(&*items); 377 .collect(&*items);
403 } 378 }
404 // out of line module, resovle, parse and recurse 379 // out of line module, resovle, parse and recurse
405 raw::ModuleData::Declaration { name, source_item_id } => { 380 raw::ModuleData::Declaration { name, ast_id } => {
406 let source_item_id = source_item_id.with_file_id(self.file_id); 381 let ast_id = ast_id.with_file_id(self.file_id);
407 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); 382 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none();
408 let (file_ids, problem) = 383 match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) {
409 resolve_submodule(self.def_collector.db, self.file_id, name, is_root); 384 Ok(file_id) => {
410 385 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
411 if let Some(problem) = problem { 386 let raw_items = self.def_collector.db.raw_items(file_id.into());
412 self.def_collector.def_map.problems.add(source_item_id, problem) 387 ModCollector {
413 } 388 def_collector: &mut *self.def_collector,
414 389 module_id,
415 if let Some(&file_id) = file_ids.first() { 390 file_id: file_id.into(),
416 let module_id = 391 raw_items: &raw_items,
417 self.push_child_module(name.clone(), source_item_id, Some(file_id)); 392 }
418 let raw_items = self.def_collector.db.raw_items(file_id); 393 .collect(raw_items.items())
419 ModCollector {
420 def_collector: &mut *self.def_collector,
421 module_id,
422 file_id: file_id.into(),
423 raw_items: &raw_items,
424 } 394 }
425 .collect(raw_items.items()) 395 Err(candidate) => self.def_collector.def_map.diagnostics.push(
426 } 396 DefDiagnostic::UnresolvedModule {
397 module: self.module_id,
398 declaration: ast_id,
399 candidate,
400 },
401 ),
402 };
427 } 403 }
428 } 404 }
429 } 405 }
@@ -431,7 +407,7 @@ where
431 fn push_child_module( 407 fn push_child_module(
432 &mut self, 408 &mut self,
433 name: Name, 409 name: Name,
434 declaration: SourceItemId, 410 declaration: AstId<ast::Module>,
435 definition: Option<FileId>, 411 definition: Option<FileId>,
436 ) -> CrateModuleId { 412 ) -> CrateModuleId {
437 let modules = &mut self.def_collector.def_map.modules; 413 let modules = &mut self.def_collector.def_map.modules;
@@ -453,23 +429,24 @@ where
453 fn define_def(&mut self, def: &raw::DefData) { 429 fn define_def(&mut self, def: &raw::DefData) {
454 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }; 430 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id };
455 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); 431 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into());
456 macro_rules! id { 432
457 () => { 433 macro_rules! def {
458 AstItemDef::from_source_item_id_unchecked(ctx, def.source_item_id) 434 ($kind:ident, $ast_id:ident) => {
435 $kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into()
459 }; 436 };
460 } 437 }
461 let name = def.name.clone(); 438 let name = def.name.clone();
462 let def: PerNs<ModuleDef> = match def.kind { 439 let def: PerNs<ModuleDef> = match def.kind {
463 raw::DefKind::Function => PerNs::values(Function { id: id!() }.into()), 440 raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)),
464 raw::DefKind::Struct => { 441 raw::DefKind::Struct(ast_id) => {
465 let s = Struct { id: id!() }.into(); 442 let s = def!(Struct, ast_id);
466 PerNs::both(s, s) 443 PerNs::both(s, s)
467 } 444 }
468 raw::DefKind::Enum => PerNs::types(Enum { id: id!() }.into()), 445 raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)),
469 raw::DefKind::Const => PerNs::values(Const { id: id!() }.into()), 446 raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)),
470 raw::DefKind::Static => PerNs::values(Static { id: id!() }.into()), 447 raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)),
471 raw::DefKind::Trait => PerNs::types(Trait { id: id!() }.into()), 448 raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)),
472 raw::DefKind::TypeAlias => PerNs::types(TypeAlias { id: id!() }.into()), 449 raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
473 }; 450 };
474 let resolution = Resolution { def, import: None }; 451 let resolution = Resolution { def, import: None };
475 self.def_collector.update(self.module_id, None, &[(name, resolution)]) 452 self.def_collector.update(self.module_id, None, &[(name, resolution)])
@@ -479,39 +456,27 @@ where
479 // Case 1: macro rules, define a macro in crate-global mutable scope 456 // Case 1: macro rules, define a macro in crate-global mutable scope
480 if is_macro_rules(&mac.path) { 457 if is_macro_rules(&mac.path) {
481 if let Some(name) = &mac.name { 458 if let Some(name) = &mac.name {
482 self.def_collector.define_macro(name.clone(), &mac.arg, mac.export) 459 let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id));
460 self.def_collector.define_macro(name.clone(), macro_id, mac.export)
483 } 461 }
484 return; 462 return;
485 } 463 }
486 464
487 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; 465 let ast_id = mac.ast_id.with_file_id(self.file_id);
488 let macro_call_id = MacroCallLoc {
489 module: Module { krate: self.def_collector.def_map.krate, module_id: self.module_id },
490 source_item_id,
491 }
492 .id(self.def_collector.db);
493 466
494 // Case 2: try to expand macro_rules from this crate, triggering 467 // Case 2: try to expand macro_rules from this crate, triggering
495 // recursive item collection. 468 // recursive item collection.
496 if let Some(&macro_id) = 469 if let Some(&macro_id) =
497 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name)) 470 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name))
498 { 471 {
499 self.def_collector.collect_macro_expansion( 472 let macro_call_id = MacroCallLoc { def: macro_id, ast_id }.id(self.def_collector.db);
500 self.module_id, 473
501 macro_call_id, 474 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id);
502 (self.def_collector.def_map.krate, macro_id),
503 mac.arg.clone(),
504 );
505 return; 475 return;
506 } 476 }
507 477
508 // Case 3: path to a macro from another crate, expand during name resolution 478 // Case 3: path to a macro from another crate, expand during name resolution
509 self.def_collector.unexpanded_macros.push(( 479 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone()))
510 self.module_id,
511 macro_call_id,
512 mac.path.clone(),
513 mac.arg.clone(),
514 ))
515 } 480 }
516} 481}
517 482
@@ -524,7 +489,7 @@ fn resolve_submodule(
524 file_id: HirFileId, 489 file_id: HirFileId,
525 name: &Name, 490 name: &Name,
526 is_root: bool, 491 is_root: bool,
527) -> (Vec<FileId>, Option<Problem>) { 492) -> Result<FileId, RelativePathBuf> {
528 // FIXME: handle submodules of inline modules properly 493 // FIXME: handle submodules of inline modules properly
529 let file_id = file_id.original_file(db); 494 let file_id = file_id.original_file(db);
530 let source_root_id = db.file_source_root(file_id); 495 let source_root_id = db.file_source_root(file_id);
@@ -545,17 +510,10 @@ fn resolve_submodule(
545 candidates.push(file_dir_mod.clone()); 510 candidates.push(file_dir_mod.clone());
546 }; 511 };
547 let sr = db.source_root(source_root_id); 512 let sr = db.source_root(source_root_id);
548 let points_to = candidates 513 let mut points_to = candidates.into_iter().filter_map(|path| sr.files.get(&path)).map(|&it| it);
549 .into_iter() 514 // FIXME: handle ambiguity
550 .filter_map(|path| sr.files.get(&path)) 515 match points_to.next() {
551 .map(|&it| it) 516 Some(file_id) => Ok(file_id),
552 .collect::<Vec<_>>(); 517 None => Err(if is_dir_owner { file_mod } else { file_dir_mod }),
553 let problem = if points_to.is_empty() { 518 }
554 Some(Problem::UnresolvedModule {
555 candidate: if is_dir_owner { file_mod } else { file_dir_mod },
556 })
557 } else {
558 None
559 };
560 (points_to, problem)
561} 519}
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index f8ba398ec..0936229ac 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -4,7 +4,6 @@ use std::{
4}; 4};
5 5
6use test_utils::tested_by; 6use test_utils::tested_by;
7use ra_db::FileId;
8use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap}; 7use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap};
9use ra_syntax::{ 8use ra_syntax::{
10 AstNode, SourceFile, AstPtr, TreeArc, 9 AstNode, SourceFile, AstPtr, TreeArc,
@@ -13,9 +12,13 @@ use ra_syntax::{
13 12
14use crate::{ 13use crate::{
15 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, 14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource,
16 ids::{SourceFileItemId, SourceFileItems}, 15 AstIdMap, FileAstId,
17}; 16};
18 17
18/// `RawItems` is a set of top-level items in a file (except for impls).
19///
20/// It is the input to name resolution algorithm. `RawItems` are not invalidated
21/// on most edits.
19#[derive(Debug, Default, PartialEq, Eq)] 22#[derive(Debug, Default, PartialEq, Eq)]
20pub struct RawItems { 23pub struct RawItems {
21 modules: Arena<Module, ModuleData>, 24 modules: Arena<Module, ModuleData>,
@@ -32,11 +35,11 @@ pub struct ImportSourceMap {
32} 35}
33 36
34impl ImportSourceMap { 37impl ImportSourceMap {
35 pub(crate) fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { 38 fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) {
36 self.map.insert(import, AstPtr::new(segment)) 39 self.map.insert(import, AstPtr::new(segment))
37 } 40 }
38 41
39 pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { 42 pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> {
40 let file = match source { 43 let file = match source {
41 ModuleSource::SourceFile(file) => &*file, 44 ModuleSource::SourceFile(file) => &*file,
42 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), 45 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
@@ -47,40 +50,27 @@ impl ImportSourceMap {
47} 50}
48 51
49impl RawItems { 52impl RawItems {
50 pub(crate) fn raw_items_query(db: &impl DefDatabase, file_id: FileId) -> Arc<RawItems> { 53 pub(crate) fn raw_items_query(db: &impl DefDatabase, file_id: HirFileId) -> Arc<RawItems> {
51 db.raw_items_with_source_map(file_id).0 54 db.raw_items_with_source_map(file_id).0
52 } 55 }
53 56
54 pub(crate) fn raw_items_with_source_map_query( 57 pub(crate) fn raw_items_with_source_map_query(
55 db: &impl DefDatabase, 58 db: &impl DefDatabase,
56 file_id: FileId, 59 file_id: HirFileId,
57 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { 60 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
58 let mut collector = RawItemsCollector { 61 let mut collector = RawItemsCollector {
59 raw_items: RawItems::default(), 62 raw_items: RawItems::default(),
60 source_file_items: db.file_items(file_id.into()), 63 source_ast_id_map: db.ast_id_map(file_id.into()),
61 source_map: ImportSourceMap::default(), 64 source_map: ImportSourceMap::default(),
62 }; 65 };
63 let source_file = db.parse(file_id); 66 let source_file = db.hir_parse(file_id);
64 collector.process_module(None, &*source_file); 67 collector.process_module(None, &*source_file);
65 (Arc::new(collector.raw_items), Arc::new(collector.source_map)) 68 (Arc::new(collector.raw_items), Arc::new(collector.source_map))
66 } 69 }
67 70
68 pub(crate) fn items(&self) -> &[RawItem] { 71 pub(super) fn items(&self) -> &[RawItem] {
69 &self.items 72 &self.items
70 } 73 }
71
72 // We can't use queries during name resolution for fear of cycles, so this
73 // is a query-less variant of the above function.
74 pub(crate) fn from_source_file(source_file: &SourceFile, file_id: HirFileId) -> RawItems {
75 let source_file_items = SourceFileItems::from_source_file(source_file, file_id);
76 let mut collector = RawItemsCollector {
77 raw_items: RawItems::default(),
78 source_file_items: Arc::new(source_file_items),
79 source_map: ImportSourceMap::default(),
80 };
81 collector.process_module(None, &*source_file);
82 collector.raw_items
83 }
84} 74}
85 75
86impl Index<Module> for RawItems { 76impl Index<Module> for RawItems {
@@ -112,7 +102,7 @@ impl Index<Macro> for RawItems {
112} 102}
113 103
114#[derive(Debug, PartialEq, Eq, Clone, Copy)] 104#[derive(Debug, PartialEq, Eq, Clone, Copy)]
115pub(crate) enum RawItem { 105pub(super) enum RawItem {
116 Module(Module), 106 Module(Module),
117 Import(ImportId), 107 Import(ImportId),
118 Def(Def), 108 Def(Def),
@@ -120,13 +110,13 @@ pub(crate) enum RawItem {
120} 110}
121 111
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
123pub(crate) struct Module(RawId); 113pub(super) struct Module(RawId);
124impl_arena_id!(Module); 114impl_arena_id!(Module);
125 115
126#[derive(Debug, PartialEq, Eq)] 116#[derive(Debug, PartialEq, Eq)]
127pub(crate) enum ModuleData { 117pub(super) enum ModuleData {
128 Declaration { name: Name, source_item_id: SourceFileItemId }, 118 Declaration { name: Name, ast_id: FileAstId<ast::Module> },
129 Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> }, 119 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
130} 120}
131 121
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -135,51 +125,49 @@ impl_arena_id!(ImportId);
135 125
136#[derive(Debug, Clone, PartialEq, Eq)] 126#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct ImportData { 127pub struct ImportData {
138 pub(crate) path: Path, 128 pub(super) path: Path,
139 pub(crate) alias: Option<Name>, 129 pub(super) alias: Option<Name>,
140 pub(crate) is_glob: bool, 130 pub(super) is_glob: bool,
141 pub(crate) is_prelude: bool, 131 pub(super) is_prelude: bool,
142 pub(crate) is_extern_crate: bool, 132 pub(super) is_extern_crate: bool,
143} 133}
144 134
145#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
146pub(crate) struct Def(RawId); 136pub(super) struct Def(RawId);
147impl_arena_id!(Def); 137impl_arena_id!(Def);
148 138
149#[derive(Debug, PartialEq, Eq)] 139#[derive(Debug, PartialEq, Eq)]
150pub(crate) struct DefData { 140pub(super) struct DefData {
151 pub(crate) source_item_id: SourceFileItemId, 141 pub(super) name: Name,
152 pub(crate) name: Name, 142 pub(super) kind: DefKind,
153 pub(crate) kind: DefKind,
154} 143}
155 144
156#[derive(Debug, PartialEq, Eq, Clone, Copy)] 145#[derive(Debug, PartialEq, Eq, Clone, Copy)]
157pub(crate) enum DefKind { 146pub(super) enum DefKind {
158 Function, 147 Function(FileAstId<ast::FnDef>),
159 Struct, 148 Struct(FileAstId<ast::StructDef>),
160 Enum, 149 Enum(FileAstId<ast::EnumDef>),
161 Const, 150 Const(FileAstId<ast::ConstDef>),
162 Static, 151 Static(FileAstId<ast::StaticDef>),
163 Trait, 152 Trait(FileAstId<ast::TraitDef>),
164 TypeAlias, 153 TypeAlias(FileAstId<ast::TypeAliasDef>),
165} 154}
166 155
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
168pub(crate) struct Macro(RawId); 157pub(super) struct Macro(RawId);
169impl_arena_id!(Macro); 158impl_arena_id!(Macro);
170 159
171#[derive(Debug, PartialEq, Eq)] 160#[derive(Debug, PartialEq, Eq)]
172pub(crate) struct MacroData { 161pub(super) struct MacroData {
173 pub(crate) source_item_id: SourceFileItemId, 162 pub(super) ast_id: FileAstId<ast::MacroCall>,
174 pub(crate) path: Path, 163 pub(super) path: Path,
175 pub(crate) name: Option<Name>, 164 pub(super) name: Option<Name>,
176 pub(crate) arg: tt::Subtree, 165 pub(super) export: bool,
177 pub(crate) export: bool,
178} 166}
179 167
180struct RawItemsCollector { 168struct RawItemsCollector {
181 raw_items: RawItems, 169 raw_items: RawItems,
182 source_file_items: Arc<SourceFileItems>, 170 source_ast_id_map: Arc<AstIdMap>,
183 source_map: ImportSourceMap, 171 source_map: ImportSourceMap,
184} 172}
185 173
@@ -211,18 +199,31 @@ impl RawItemsCollector {
211 // impls don't participate in name resolution 199 // impls don't participate in name resolution
212 return; 200 return;
213 } 201 }
214 ast::ModuleItemKind::StructDef(it) => (DefKind::Struct, it.name()), 202 ast::ModuleItemKind::StructDef(it) => {
215 ast::ModuleItemKind::EnumDef(it) => (DefKind::Enum, it.name()), 203 (DefKind::Struct(self.source_ast_id_map.ast_id(it)), it.name())
216 ast::ModuleItemKind::FnDef(it) => (DefKind::Function, it.name()), 204 }
217 ast::ModuleItemKind::TraitDef(it) => (DefKind::Trait, it.name()), 205 ast::ModuleItemKind::EnumDef(it) => {
218 ast::ModuleItemKind::TypeAliasDef(it) => (DefKind::TypeAlias, it.name()), 206 (DefKind::Enum(self.source_ast_id_map.ast_id(it)), it.name())
219 ast::ModuleItemKind::ConstDef(it) => (DefKind::Const, it.name()), 207 }
220 ast::ModuleItemKind::StaticDef(it) => (DefKind::Static, it.name()), 208 ast::ModuleItemKind::FnDef(it) => {
209 (DefKind::Function(self.source_ast_id_map.ast_id(it)), it.name())
210 }
211 ast::ModuleItemKind::TraitDef(it) => {
212 (DefKind::Trait(self.source_ast_id_map.ast_id(it)), it.name())
213 }
214 ast::ModuleItemKind::TypeAliasDef(it) => {
215 (DefKind::TypeAlias(self.source_ast_id_map.ast_id(it)), it.name())
216 }
217 ast::ModuleItemKind::ConstDef(it) => {
218 (DefKind::Const(self.source_ast_id_map.ast_id(it)), it.name())
219 }
220 ast::ModuleItemKind::StaticDef(it) => {
221 (DefKind::Static(self.source_ast_id_map.ast_id(it)), it.name())
222 }
221 }; 223 };
222 if let Some(name) = name { 224 if let Some(name) = name {
223 let name = name.as_name(); 225 let name = name.as_name();
224 let source_item_id = self.source_file_items.id_of_unchecked(item.syntax()); 226 let def = self.raw_items.defs.alloc(DefData { name, kind });
225 let def = self.raw_items.defs.alloc(DefData { name, kind, source_item_id });
226 self.push_item(current_module, RawItem::Def(def)) 227 self.push_item(current_module, RawItem::Def(def))
227 } 228 }
228 } 229 }
@@ -232,10 +233,9 @@ impl RawItemsCollector {
232 Some(it) => it.as_name(), 233 Some(it) => it.as_name(),
233 None => return, 234 None => return,
234 }; 235 };
235 let source_item_id = self.source_file_items.id_of_unchecked(module.syntax()); 236 let ast_id = self.source_ast_id_map.ast_id(module);
236 if module.has_semi() { 237 if module.has_semi() {
237 let item = 238 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id });
238 self.raw_items.modules.alloc(ModuleData::Declaration { name, source_item_id });
239 self.push_item(current_module, RawItem::Module(item)); 239 self.push_item(current_module, RawItem::Module(item));
240 return; 240 return;
241 } 241 }
@@ -243,7 +243,7 @@ impl RawItemsCollector {
243 if let Some(item_list) = module.item_list() { 243 if let Some(item_list) = module.item_list() {
244 let item = self.raw_items.modules.alloc(ModuleData::Definition { 244 let item = self.raw_items.modules.alloc(ModuleData::Definition {
245 name, 245 name,
246 source_item_id, 246 ast_id,
247 items: Vec::new(), 247 items: Vec::new(),
248 }); 248 });
249 self.process_module(Some(item), item_list); 249 self.process_module(Some(item), item_list);
@@ -291,18 +291,15 @@ impl RawItemsCollector {
291 } 291 }
292 292
293 fn add_macro(&mut self, current_module: Option<Module>, m: &ast::MacroCall) { 293 fn add_macro(&mut self, current_module: Option<Module>, m: &ast::MacroCall) {
294 let (path, arg) = match ( 294 let path = match m.path().and_then(Path::from_ast) {
295 m.path().and_then(Path::from_ast), 295 Some(it) => it,
296 m.token_tree().and_then(mbe::ast_to_token_tree),
297 ) {
298 (Some(path), Some((token_tree, _token_map))) => (path, token_tree),
299 _ => return, 296 _ => return,
300 }; 297 };
301 298
302 let name = m.name().map(|it| it.as_name()); 299 let name = m.name().map(|it| it.as_name());
303 let source_item_id = self.source_file_items.id_of_unchecked(m.syntax()); 300 let ast_id = self.source_ast_id_map.ast_id(m);
304 let export = m.has_atom_attr("macro_export"); 301 let export = m.has_atom_attr("macro_export");
305 let m = self.raw_items.macros.alloc(MacroData { source_item_id, path, arg, name, export }); 302 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
306 self.push_item(current_module, RawItem::Macro(m)); 303 self.push_item(current_module, RawItem::Macro(m));
307 } 304 }
308 305
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index ac9b88520..572bd1bf7 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -552,3 +552,22 @@ foo: v
552"### 552"###
553 ); 553 );
554} 554}
555
556#[test]
557fn unresolved_module_diagnostics() {
558 let diagnostics = MockDatabase::with_files(
559 r"
560 //- /lib.rs
561 mod foo;
562 mod bar;
563 mod baz {}
564 //- /foo.rs
565 ",
566 )
567 .diagnostics();
568
569 assert_snapshot_matches!(diagnostics, @r###"
570"mod bar;": unresolved module
571"###
572 );
573}
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
index 698781923..001f76ac3 100644
--- a/crates/ra_hir/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir/src/nameres/tests/incremental.rs
@@ -90,34 +90,44 @@ fn adding_inner_items_should_not_invalidate_def_map() {
90 ); 90 );
91} 91}
92 92
93// It would be awesome to make this work, but it's unclear how
94#[test] 93#[test]
95#[ignore] 94fn typing_inside_a_macro_should_not_invalidate_def_map() {
96fn typing_inside_a_function_inside_a_macro_should_not_invalidate_def_map() { 95 let (mut db, pos) = MockDatabase::with_position(
97 check_def_map_is_not_recomputed(
98 " 96 "
99 //- /lib.rs 97 //- /lib.rs
98 macro_rules! m {
99 ($ident:ident) => {
100 fn f() {
101 $ident + $ident;
102 };
103 }
104 }
100 mod foo; 105 mod foo;
101 106
102 use crate::foo::bar::Baz;
103
104 //- /foo/mod.rs 107 //- /foo/mod.rs
105 pub mod bar; 108 pub mod bar;
106 109
107 //- /foo/bar.rs 110 //- /foo/bar.rs
108 <|> 111 <|>
109 salsa::query_group! { 112 m!(X);
110 trait Baz {
111 fn foo() -> i32 { 1 + 1 }
112 }
113 }
114 ",
115 "
116 salsa::query_group! {
117 trait Baz {
118 fn foo() -> i32 { 92 }
119 }
120 }
121 ", 113 ",
122 ); 114 );
115 {
116 let events = db.log_executed(|| {
117 let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
118 let decls = module.declarations(&db);
119 assert_eq!(decls.len(), 1);
120 });
121 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
122 }
123 db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));
124
125 {
126 let events = db.log_executed(|| {
127 let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
128 let decls = module.declarations(&db);
129 assert_eq!(decls.len(), 1);
130 });
131 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
132 }
123} 133}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index f28154517..2609585b1 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -11,7 +11,7 @@ use crate::{
11 generics::GenericParams, 11 generics::GenericParams,
12 expr::{scope::{ExprScopes, ScopeId}, PatId, Body}, 12 expr::{scope::{ExprScopes, ScopeId}, PatId, Body},
13 impl_block::ImplBlock, 13 impl_block::ImplBlock,
14 path::Path, 14 path::Path, Trait
15}; 15};
16 16
17#[derive(Debug, Clone, Default)] 17#[derive(Debug, Clone, Default)]
@@ -175,6 +175,21 @@ impl Resolver {
175 names 175 names
176 } 176 }
177 177
178 pub(crate) fn traits_in_scope<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a {
179 // FIXME prelude
180 self.scopes
181 .iter()
182 .rev()
183 .flat_map(|scope| {
184 match scope {
185 Scope::ModuleScope(m) => Some(m.crate_def_map[m.module_id].scope.traits()),
186 _ => None,
187 }
188 .into_iter()
189 })
190 .flatten()
191 }
192
178 fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { 193 fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> {
179 self.scopes.iter().rev().find_map(|scope| match scope { 194 self.scopes.iter().rev().find_map(|scope| match scope {
180 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), 195 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 3645b73b4..9dae4c3d1 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -15,8 +15,8 @@ use ra_syntax::{
15use crate::{ 15use crate::{
16 HirDatabase, Function, Struct, Enum, 16 HirDatabase, Function, Struct, Enum,
17 AsName, Module, HirFileId, Crate, Trait, Resolver, 17 AsName, Module, HirFileId, Crate, Trait, Resolver,
18 ids::{LocationCtx, SourceFileItemId}, 18 ids::LocationCtx,
19 expr 19 expr, AstId
20}; 20};
21 21
22/// Locates the module by `FileId`. Picks topmost module in the file. 22/// Locates the module by `FileId`. Picks topmost module in the file.
@@ -54,8 +54,8 @@ fn module_from_inline(
54) -> Option<Module> { 54) -> Option<Module> {
55 assert!(!module.has_semi()); 55 assert!(!module.has_semi());
56 let file_id = file_id.into(); 56 let file_id = file_id.into();
57 let file_items = db.file_items(file_id); 57 let ast_id_map = db.ast_id_map(file_id);
58 let item_id = file_items.id_of(file_id, module.syntax());