aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock82
-rw-r--r--crates/ra_assists/src/add_explicit_type.rs89
-rw-r--r--crates/ra_assists/src/add_missing_impl_members.rs15
-rw-r--r--crates/ra_assists/src/fill_match_arms.rs10
-rw-r--r--crates/ra_assists/src/fill_struct_fields.rs12
-rw-r--r--crates/ra_assists/src/inline_local_variable.rs11
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/split_import.rs5
-rw-r--r--crates/ra_batch/src/lib.rs12
-rw-r--r--crates/ra_db/src/lib.rs6
-rw-r--r--crates/ra_db/src/loc2id.rs103
-rw-r--r--crates/ra_fmt/src/lib.rs4
-rw-r--r--crates/ra_hir/src/code_model_api.rs140
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs14
-rw-r--r--crates/ra_hir/src/db.rs33
-rw-r--r--crates/ra_hir/src/either.rs28
-rw-r--r--crates/ra_hir/src/expr.rs54
-rw-r--r--crates/ra_hir/src/expr/scope.rs233
-rw-r--r--crates/ra_hir/src/generics.rs37
-rw-r--r--crates/ra_hir/src/ids.rs145
-rw-r--r--crates/ra_hir/src/impl_block.rs30
-rw-r--r--crates/ra_hir/src/lib.rs18
-rw-r--r--crates/ra_hir/src/mock.rs11
-rw-r--r--crates/ra_hir/src/nameres.rs2
-rw-r--r--crates/ra_hir/src/nameres/raw.rs33
-rw-r--r--crates/ra_hir/src/resolve.rs18
-rw-r--r--crates/ra_hir/src/source_binder.rs406
-rw-r--r--crates/ra_hir/src/traits.rs33
-rw-r--r--crates/ra_hir/src/ty.rs47
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs4
-rw-r--r--crates/ra_hir/src/ty/infer.rs243
-rw-r--r--crates/ra_hir/src/ty/lower.rs109
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs60
-rw-r--r--crates/ra_hir/src/ty/tests.rs115
-rw-r--r--crates/ra_hir/src/ty/traits.rs112
-rw-r--r--crates/ra_ide_api/src/call_info.rs157
-rw-r--r--crates/ra_ide_api/src/completion.rs41
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs198
-rw-r--r--crates/ra_ide_api/src/completion/complete_fn_param.rs85
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs10
-rw-r--r--crates/ra_ide_api/src/completion/complete_pattern.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs4
-rw-r--r--crates/ra_ide_api/src/completion/complete_struct_literal.rs11
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs15
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs5
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__dont_show_both_completions_for_shadowing.snap14
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__method_attr_filtering.snap16
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__method_completion.snap16
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__no_non_self_method.snap7
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__no_struct_field_completion_for_method_call.snap7
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_last_param.snap15
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_nth_param.snap15
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_trait_param.snap15
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__return_type.snap6
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion.snap16
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap24
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap27
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__tuple_field_completion.snap24
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__tuple_field_inference.snap16
-rw-r--r--crates/ra_ide_api/src/db.rs9
-rw-r--r--crates/ra_ide_api/src/display.rs82
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs101
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs (renamed from crates/ra_ide_api/src/navigation_target.rs)105
-rw-r--r--crates/ra_ide_api/src/display/snapshots/tests__file_structure.snap (renamed from crates/ra_ide_api/src/snapshots/tests__file_structure.snap)6
-rw-r--r--crates/ra_ide_api/src/display/structure.rs (renamed from crates/ra_ide_api/src/structure.rs)0
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs149
-rw-r--r--crates/ra_ide_api/src/hover.rs128
-rw-r--r--crates/ra_ide_api/src/lib.rs12
-rw-r--r--crates/ra_ide_api/src/references.rs29
-rw-r--r--crates/ra_ide_api/src/runnables.rs1
-rw-r--r--crates/ra_ide_api/src/status.rs7
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs2
-rw-r--r--crates/ra_lsp_server/src/conv.rs22
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs23
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs18
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs.tera18
-rw-r--r--crates/ra_syntax/Cargo.toml2
-rw-r--r--crates/ra_syntax/src/algo.rs10
-rw-r--r--crates/ra_syntax/src/ast.rs4
-rw-r--r--crates/ra_syntax/src/ast/generated.rs230
-rw-r--r--crates/ra_syntax/src/ast/generated.rs.tera6
-rw-r--r--crates/ra_syntax/src/lib.rs2
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs2
-rw-r--r--crates/ra_syntax/src/ptr.rs9
-rw-r--r--crates/ra_syntax/src/syntax_node.rs71
-rw-r--r--crates/ra_syntax/tests/test.rs2
-rw-r--r--docs/user/features.md32
87 files changed, 2277 insertions, 1827 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0400c6a94..5a5edc3e2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -53,7 +53,7 @@ dependencies = [
53 "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", 53 "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
54 "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 54 "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
55 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", 55 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
56 "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 56 "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
57 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 57 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
58] 58]
59 59
@@ -62,7 +62,7 @@ name = "backtrace-sys"
62version = "0.1.28" 62version = "0.1.28"
63source = "registry+https://github.com/rust-lang/crates.io-index" 63source = "registry+https://github.com/rust-lang/crates.io-index"
64dependencies = [ 64dependencies = [
65 "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", 65 "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
66 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", 66 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
67] 67]
68 68
@@ -130,7 +130,7 @@ dependencies = [
130 130
131[[package]] 131[[package]]
132name = "cc" 132name = "cc"
133version = "1.0.34" 133version = "1.0.35"
134source = "registry+https://github.com/rust-lang/crates.io-index" 134source = "registry+https://github.com/rust-lang/crates.io-index"
135 135
136[[package]] 136[[package]]
@@ -156,14 +156,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
156 156
157[[package]] 157[[package]]
158name = "clap" 158name = "clap"
159version = "2.32.0" 159version = "2.33.0"
160source = "registry+https://github.com/rust-lang/crates.io-index" 160source = "registry+https://github.com/rust-lang/crates.io-index"
161dependencies = [ 161dependencies = [
162 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 162 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
163 "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 163 "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
164 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 164 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
165 "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 165 "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
166 "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 166 "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
167 "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 167 "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
168 "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 168 "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
169] 169]
@@ -264,7 +264,7 @@ version = "0.5.6"
264source = "registry+https://github.com/rust-lang/crates.io-index" 264source = "registry+https://github.com/rust-lang/crates.io-index"
265dependencies = [ 265dependencies = [
266 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 266 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
267 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 267 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
268 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", 268 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
269] 269]
270 270
@@ -337,7 +337,7 @@ version = "0.1.5"
337source = "registry+https://github.com/rust-lang/crates.io-index" 337source = "registry+https://github.com/rust-lang/crates.io-index"
338dependencies = [ 338dependencies = [
339 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 339 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
340 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 340 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
341 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", 341 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
342 "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", 342 "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
343] 343]
@@ -354,7 +354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
354dependencies = [ 354dependencies = [
355 "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 355 "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
356 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", 356 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
357 "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", 357 "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
358] 358]
359 359
360[[package]] 360[[package]]
@@ -562,7 +562,7 @@ name = "jemalloc-sys"
562version = "0.1.8" 562version = "0.1.8"
563source = "registry+https://github.com/rust-lang/crates.io-index" 563source = "registry+https://github.com/rust-lang/crates.io-index"
564dependencies = [ 564dependencies = [
565 "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", 565 "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
566 "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 566 "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
567 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", 567 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
568] 568]
@@ -741,7 +741,7 @@ version = "0.2.4"
741source = "registry+https://github.com/rust-lang/crates.io-index" 741source = "registry+https://github.com/rust-lang/crates.io-index"
742dependencies = [ 742dependencies = [
743 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 743 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
744 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 744 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
745 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", 745 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
746] 746]
747 747
@@ -833,7 +833,7 @@ dependencies = [
833 "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 833 "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
834 "pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 834 "pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
835 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 835 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
836 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 836 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
837 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", 837 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
838] 838]
839 839
@@ -879,7 +879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
879 879
880[[package]] 880[[package]]
881name = "quote" 881name = "quote"
882version = "0.6.11" 882version = "0.6.12"
883source = "registry+https://github.com/rust-lang/crates.io-index" 883source = "registry+https://github.com/rust-lang/crates.io-index"
884dependencies = [ 884dependencies = [
885 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 885 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -913,7 +913,7 @@ dependencies = [
913 "ra_hir 0.1.0", 913 "ra_hir 0.1.0",
914 "ra_project_model 0.1.0", 914 "ra_project_model 0.1.0",
915 "ra_syntax 0.1.0", 915 "ra_syntax 0.1.0",
916 "ra_vfs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 916 "ra_vfs 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
917 "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)",
918 "test_utils 0.1.0", 918 "test_utils 0.1.0",
919] 919]
@@ -922,7 +922,7 @@ dependencies = [
922name = "ra_cli" 922name = "ra_cli"
923version = "0.1.0" 923version = "0.1.0"
924dependencies = [ 924dependencies = [
925 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", 925 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
926 "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)",
927 "flexi_logger 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", 927 "flexi_logger 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
928 "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)",
@@ -1024,7 +1024,7 @@ dependencies = [
1024 "ra_project_model 0.1.0", 1024 "ra_project_model 0.1.0",
1025 "ra_syntax 0.1.0", 1025 "ra_syntax 0.1.0",
1026 "ra_text_edit 0.1.0", 1026 "ra_text_edit 0.1.0",
1027 "ra_vfs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 1027 "ra_vfs 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
1028 "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)",
1029 "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)",
1030 "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", 1030 "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1088,7 +1088,7 @@ dependencies = [
1088 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1088 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1089 "ra_parser 0.1.0", 1089 "ra_parser 0.1.0",
1090 "ra_text_edit 0.1.0", 1090 "ra_text_edit 0.1.0",
1091 "rowan 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1091 "rowan 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
1092 "smol_str 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 1092 "smol_str 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1093 "test_utils 0.1.0", 1093 "test_utils 0.1.0",
1094 "text_unit 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 1094 "text_unit 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1114,7 +1114,7 @@ dependencies = [
1114 1114
1115[[package]] 1115[[package]]
1116name = "ra_vfs" 1116name = "ra_vfs"
1117version = "0.2.1" 1117version = "0.2.2"
1118source = "registry+https://github.com/rust-lang/crates.io-index" 1118source = "registry+https://github.com/rust-lang/crates.io-index"
1119dependencies = [ 1119dependencies = [
1120 "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1120 "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1253,7 +1253,7 @@ dependencies = [
1253 1253
1254[[package]] 1254[[package]]
1255name = "redox_syscall" 1255name = "redox_syscall"
1256version = "0.1.52" 1256version = "0.1.54"
1257source = "registry+https://github.com/rust-lang/crates.io-index" 1257source = "registry+https://github.com/rust-lang/crates.io-index"
1258 1258
1259[[package]] 1259[[package]]
@@ -1261,7 +1261,7 @@ name = "redox_termios"
1261version = "0.1.1" 1261version = "0.1.1"
1262source = "registry+https://github.com/rust-lang/crates.io-index" 1262source = "registry+https://github.com/rust-lang/crates.io-index"
1263dependencies = [ 1263dependencies = [
1264 "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", 1264 "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
1265] 1265]
1266 1266
1267[[package]] 1267[[package]]
@@ -1309,7 +1309,7 @@ dependencies = [
1309 1309
1310[[package]] 1310[[package]]
1311name = "rowan" 1311name = "rowan"
1312version = "0.4.0" 1312version = "0.5.0"
1313source = "registry+https://github.com/rust-lang/crates.io-index" 1313source = "registry+https://github.com/rust-lang/crates.io-index"
1314dependencies = [ 1314dependencies = [
1315 "colosseum 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 1315 "colosseum 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1320,7 +1320,7 @@ dependencies = [
1320 1320
1321[[package]] 1321[[package]]
1322name = "rustc-demangle" 1322name = "rustc-demangle"
1323version = "0.1.13" 1323version = "0.1.14"
1324source = "registry+https://github.com/rust-lang/crates.io-index" 1324source = "registry+https://github.com/rust-lang/crates.io-index"
1325 1325
1326[[package]] 1326[[package]]
@@ -1366,7 +1366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1366dependencies = [ 1366dependencies = [
1367 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1367 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1368 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 1368 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
1369 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 1369 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
1370 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", 1370 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
1371] 1371]
1372 1372
@@ -1411,7 +1411,7 @@ version = "1.0.90"
1411source = "registry+https://github.com/rust-lang/crates.io-index" 1411source = "registry+https://github.com/rust-lang/crates.io-index"
1412dependencies = [ 1412dependencies = [
1413 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 1413 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
1414 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 1414 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
1415 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", 1415 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
1416] 1416]
1417 1417
@@ -1480,7 +1480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1480 1480
1481[[package]] 1481[[package]]
1482name = "strsim" 1482name = "strsim"
1483version = "0.7.0" 1483version = "0.8.0"
1484source = "registry+https://github.com/rust-lang/crates.io-index" 1484source = "registry+https://github.com/rust-lang/crates.io-index"
1485 1485
1486[[package]] 1486[[package]]
@@ -1494,7 +1494,7 @@ version = "0.15.30"
1494source = "registry+https://github.com/rust-lang/crates.io-index" 1494source = "registry+https://github.com/rust-lang/crates.io-index"
1495dependencies = [ 1495dependencies = [
1496 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 1496 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
1497 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 1497 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
1498 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1498 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1499] 1499]
1500 1500
@@ -1504,7 +1504,7 @@ version = "0.10.1"
1504source = "registry+https://github.com/rust-lang/crates.io-index" 1504source = "registry+https://github.com/rust-lang/crates.io-index"
1505dependencies = [ 1505dependencies = [
1506 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 1506 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
1507 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 1507 "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
1508 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", 1508 "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
1509 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1509 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1510] 1510]
@@ -1517,7 +1517,7 @@ dependencies = [
1517 "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1517 "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1518 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", 1518 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
1519 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1519 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
1520 "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", 1520 "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
1521 "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1521 "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1522 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 1522 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
1523] 1523]
@@ -1559,7 +1559,7 @@ version = "1.5.1"
1559source = "registry+https://github.com/rust-lang/crates.io-index" 1559source = "registry+https://github.com/rust-lang/crates.io-index"
1560dependencies = [ 1560dependencies = [
1561 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", 1561 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
1562 "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", 1562 "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
1563 "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1563 "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1564] 1564]
1565 1565
@@ -1591,7 +1591,7 @@ dependencies = [
1591 1591
1592[[package]] 1592[[package]]
1593name = "textwrap" 1593name = "textwrap"
1594version = "0.10.0" 1594version = "0.11.0"
1595source = "registry+https://github.com/rust-lang/crates.io-index" 1595source = "registry+https://github.com/rust-lang/crates.io-index"
1596dependencies = [ 1596dependencies = [
1597 "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1597 "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1627,7 +1627,7 @@ version = "0.1.42"
1627source = "registry+https://github.com/rust-lang/crates.io-index" 1627source = "registry+https://github.com/rust-lang/crates.io-index"
1628dependencies = [ 1628dependencies = [
1629 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", 1629 "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
1630 "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", 1630 "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
1631 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 1631 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
1632] 1632]
1633 1633
@@ -1635,7 +1635,7 @@ dependencies = [
1635name = "tools" 1635name = "tools"
1636version = "0.1.0" 1636version = "0.1.0"
1637dependencies = [ 1637dependencies = [
1638 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", 1638 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
1639 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1639 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1640 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1640 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1641 "teraron 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1641 "teraron 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1865,11 +1865,11 @@ dependencies = [
1865"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" 1865"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
1866"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" 1866"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
1867"checksum cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "178d62b240c34223f265a4c1e275e37d62da163d421fc8d7f7e3ee340f803c57" 1867"checksum cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "178d62b240c34223f265a4c1e275e37d62da163d421fc8d7f7e3ee340f803c57"
1868"checksum cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd" 1868"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83"
1869"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" 1869"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
1870"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" 1870"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
1871"checksum ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e881307a989a3a5e20d52a32cc05950e3c2178cccfcc9428271a6cde09f902" 1871"checksum ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e881307a989a3a5e20d52a32cc05950e3c2178cccfcc9428271a6cde09f902"
1872"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" 1872"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
1873"checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9" 1873"checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9"
1874"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 1874"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
1875"checksum colosseum 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "370c83b49aedf022ee27942e8ae1d9de1cf40dc9653ee6550e4455d08f6406f9" 1875"checksum colosseum 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "370c83b49aedf022ee27942e8ae1d9de1cf40dc9653ee6550e4455d08f6406f9"
@@ -1953,8 +1953,8 @@ dependencies = [
1953"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" 1953"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
1954"checksum proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24f5844db2f839e97e3021980975f6ebf8691d9b9b2ca67ed3feb38dc3edb52c" 1954"checksum proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24f5844db2f839e97e3021980975f6ebf8691d9b9b2ca67ed3feb38dc3edb52c"
1955"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 1955"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
1956"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" 1956"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
1957"checksum ra_vfs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d08da053ec832676686c72dfe509fdd1e807191a50ac79087466ffefccb1c" 1957"checksum ra_vfs 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "411d8ce8abf262b08421e6446c4fd5b420206cf221cd21fcfc793445fb3825b2"
1958"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 1958"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
1959"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 1959"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
1960"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 1960"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@@ -1968,15 +1968,15 @@ dependencies = [
1968"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" 1968"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473"
1969"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" 1969"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"
1970"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 1970"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
1971"checksum redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)" = "d32b3053e5ced86e4bc0411fec997389532bf56b000e66cb4884eeeb41413d69" 1971"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
1972"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 1972"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
1973"checksum regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "559008764a17de49a3146b234641644ed37d118d1ef641a0bb573d146edc6ce0" 1973"checksum regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "559008764a17de49a3146b234641644ed37d118d1ef641a0bb573d146edc6ce0"
1974"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" 1974"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
1975"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c" 1975"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c"
1976"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" 1976"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
1977"checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f" 1977"checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f"
1978"checksum rowan 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "397cd19c109641f10f3c66433440285e232d8cbd37406cf8f944a15ab1e63a8e" 1978"checksum rowan 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91237e0f16ac1073139acd696d9d386c3225ba1d6eafc09b105984905994068d"
1979"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" 1979"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
1980"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" 1980"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
1981"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1981"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1982"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" 1982"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
@@ -1996,7 +1996,7 @@ dependencies = [
1996"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" 1996"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
1997"checksum smol_str 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d077b3367211e9c6e2e012fb804c444e0d80ab5a51ae4137739b58e6446dcaef" 1997"checksum smol_str 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d077b3367211e9c6e2e012fb804c444e0d80ab5a51ae4137739b58e6446dcaef"
1998"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" 1998"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
1999"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" 1999"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
2000"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" 2000"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
2001"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2" 2001"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2"
2002"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" 2002"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
@@ -2006,7 +2006,7 @@ dependencies = [
2006"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" 2006"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
2007"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" 2007"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
2008"checksum text_unit 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "158bb1c22b638b1da3c95a8ad9f061ea40d4d39fd0301be3a520f92efeeb189e" 2008"checksum text_unit 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "158bb1c22b638b1da3c95a8ad9f061ea40d4d39fd0301be3a520f92efeeb189e"
2009"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" 2009"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
2010"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" 2010"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
2011"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" 2011"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
2012"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 2012"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
diff --git a/crates/ra_assists/src/add_explicit_type.rs b/crates/ra_assists/src/add_explicit_type.rs
new file mode 100644
index 000000000..cb0ac9885
--- /dev/null
+++ b/crates/ra_assists/src/add_explicit_type.rs
@@ -0,0 +1,89 @@
1use hir::{
2 HirDisplay, Ty,
3 db::HirDatabase,
4};
5use ra_syntax::{
6 SyntaxKind,
7 ast::{LetStmt, PatKind, NameOwner, AstNode}
8};
9
10use crate::{AssistCtx, Assist, AssistId};
11
12/// Add explicit type assist.
13pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
14 let stmt = ctx.node_at_offset::<LetStmt>()?;
15 let expr = stmt.initializer()?;
16 let pat = stmt.pat()?;
17 // Must be a binding
18 let pat = match pat.kind() {
19 PatKind::BindPat(bind_pat) => bind_pat,
20 _ => return None,
21 };
22 let pat_range = pat.syntax().range();
23 // The binding must have a name
24 let name = pat.name()?;
25 let name_range = name.syntax().range();
26 // Assist not applicable if the type has already been specified
27 if stmt.syntax().children_with_tokens().any(|child| child.kind() == SyntaxKind::COLON) {
28 return None;
29 }
30 // Infer type
31 let db = ctx.db;
32 let analyzer = hir::SourceAnalyzer::new(db, ctx.frange.file_id, stmt.syntax(), None);
33 let ty = analyzer.type_of(db, expr)?;
34 // Assist not applicable if the type is unknown
35 if is_unknown(&ty) {
36 return None;
37 }
38
39 ctx.add_action(AssistId("add_explicit_type"), "add explicit type", |edit| {
40 edit.target(pat_range);
41 edit.insert(name_range.end(), format!(": {}", ty.display(db)));
42 });
43 ctx.build()
44}
45
46/// Returns true if any type parameter is unknown
47fn is_unknown(ty: &Ty) -> bool {
48 match ty {
49 Ty::Unknown => true,
50 Ty::Apply(a_ty) => a_ty.parameters.iter().any(is_unknown),
51 _ => false,
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 use crate::helpers::{ check_assist, check_assist_target, check_assist_not_applicable };
60
61 #[test]
62 fn add_explicit_type_target() {
63 check_assist_target(add_explicit_type, "fn f() { let a<|> = 1; }", "a");
64 }
65
66 #[test]
67 fn add_explicit_type_works_for_simple_expr() {
68 check_assist(
69 add_explicit_type,
70 "fn f() { let a<|> = 1; }",
71 "fn f() { let a<|>: i32 = 1; }",
72 );
73 }
74
75 #[test]
76 fn add_explicit_type_not_applicable_if_ty_not_inferred() {
77 check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }");
78 }
79
80 #[test]
81 fn add_explicit_type_not_applicable_if_ty_already_specified() {
82 check_assist_not_applicable(add_explicit_type, "fn f() { let a<|>: i32 = 1; }");
83 }
84
85 #[test]
86 fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() {
87 check_assist_not_applicable(add_explicit_type, "fn f() { let a<|>: (i32, i32) = (3, 4); }");
88 }
89}
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index 19a2d05bc..100ebb7b6 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -2,7 +2,6 @@ use std::fmt::Write;
2 2
3use crate::{Assist, AssistId, AssistCtx}; 3use crate::{Assist, AssistId, AssistCtx};
4 4
5use hir::Resolver;
6use hir::db::HirDatabase; 5use hir::db::HirDatabase;
7use ra_syntax::{SmolStr, SyntaxKind, TextRange, TextUnit, TreeArc}; 6use ra_syntax::{SmolStr, SyntaxKind, TextRange, TextUnit, TreeArc};
8use ra_syntax::ast::{self, AstNode, AstToken, FnDef, ImplItem, ImplItemKind, NameOwner}; 7use ra_syntax::ast::{self, AstNode, AstToken, FnDef, ImplItem, ImplItemKind, NameOwner};
@@ -46,9 +45,9 @@ fn add_missing_impl_members_inner(
46 let trait_def = { 45 let trait_def = {
47 let file_id = ctx.frange.file_id; 46 let file_id = ctx.frange.file_id;
48 let position = FilePosition { file_id, offset: impl_node.syntax().range().start() }; 47 let position = FilePosition { file_id, offset: impl_node.syntax().range().start() };
49 let resolver = hir::source_binder::resolver_for_position(ctx.db, position); 48 let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None);
50 49
51 resolve_target_trait_def(ctx.db, &resolver, impl_node)? 50 resolve_target_trait_def(ctx.db, &analyzer, impl_node)?
52 }; 51 };
53 52
54 let missing_fns: Vec<_> = { 53 let missing_fns: Vec<_> = {
@@ -122,14 +121,14 @@ fn add_missing_impl_members_inner(
122/// implemented) to a `ast::TraitDef`. 121/// implemented) to a `ast::TraitDef`.
123fn resolve_target_trait_def( 122fn resolve_target_trait_def(
124 db: &impl HirDatabase, 123 db: &impl HirDatabase,
125 resolver: &Resolver, 124 analyzer: &hir::SourceAnalyzer,
126 impl_block: &ast::ImplBlock, 125 impl_block: &ast::ImplBlock,
127) -> Option<TreeArc<ast::TraitDef>> { 126) -> Option<TreeArc<ast::TraitDef>> {
128 let ast_path = impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?; 127 let ast_path =
129 let hir_path = ast_path.path().and_then(hir::Path::from_ast)?; 128 impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?.path()?;
130 129
131 match resolver.resolve_path(db, &hir_path).take_types() { 130 match analyzer.resolve_path(db, &ast_path) {
132 Some(hir::Resolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).1), 131 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).1),
133 _ => None, 132 _ => None,
134 } 133 }
135} 134}
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index da67ab667..45e327cd4 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -1,7 +1,7 @@
1use std::fmt::Write; 1use std::fmt::Write;
2 2
3use hir::{ 3use hir::{
4 AdtDef, FieldSource, source_binder, 4 AdtDef, FieldSource,
5 db::HirDatabase, 5 db::HirDatabase,
6}; 6};
7use ra_syntax::ast::{self, AstNode}; 7use ra_syntax::ast::{self, AstNode};
@@ -20,12 +20,8 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
20 } 20 }
21 21
22 let expr = match_expr.expr()?; 22 let expr = match_expr.expr()?;
23 let function = 23 let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, expr.syntax(), None);
24 source_binder::function_from_child_node(ctx.db, ctx.frange.file_id, expr.syntax())?; 24 let match_expr_ty = analyzer.type_of(ctx.db, expr)?;
25 let infer_result = function.infer(ctx.db);
26 let source_map = function.body_source_map(ctx.db);
27 let node_expr = source_map.node_expr(expr)?;
28 let match_expr_ty = infer_result[node_expr].clone();
29 let enum_def = match_expr_ty.autoderef(ctx.db).find_map(|ty| match ty.as_adt() { 25 let enum_def = match_expr_ty.autoderef(ctx.db).find_map(|ty| match ty.as_adt() {
30 Some((AdtDef::Enum(e), _)) => Some(e), 26 Some((AdtDef::Enum(e), _)) => Some(e),
31 _ => None, 27 _ => None,
diff --git a/crates/ra_assists/src/fill_struct_fields.rs b/crates/ra_assists/src/fill_struct_fields.rs
index c7790dc72..663b4f669 100644
--- a/crates/ra_assists/src/fill_struct_fields.rs
+++ b/crates/ra_assists/src/fill_struct_fields.rs
@@ -1,6 +1,6 @@
1use std::fmt::Write; 1use std::fmt::Write;
2 2
3use hir::{AdtDef, db::HirDatabase, source_binder::function_from_child_node}; 3use hir::{AdtDef, db::HirDatabase};
4 4
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::ast::{self, AstNode};
6 6
@@ -51,15 +51,13 @@ where
51 } 51 }
52 52
53 fn evaluate_struct_def_fields(&mut self) -> Option<()> { 53 fn evaluate_struct_def_fields(&mut self) -> Option<()> {
54 let function = function_from_child_node( 54 let analyzer = hir::SourceAnalyzer::new(
55 self.ctx.db, 55 self.ctx.db,
56 self.ctx.frange.file_id, 56 self.ctx.frange.file_id,
57 self.struct_lit.syntax(), 57 self.struct_lit.syntax(),
58 )?; 58 None,
59 let infer_result = function.infer(self.ctx.db); 59 );
60 let source_map = function.body_source_map(self.ctx.db); 60 let struct_lit_ty = analyzer.type_of(self.ctx.db, self.struct_lit.into())?;
61 let node_expr = source_map.node_expr(self.struct_lit.into())?;
62 let struct_lit_ty = infer_result[node_expr].clone();
63 let struct_def = match struct_lit_ty.as_adt() { 61 let struct_def = match struct_lit_ty.as_adt() {
64 Some((AdtDef::Struct(s), _)) => s, 62 Some((AdtDef::Struct(s), _)) => s,
65 _ => return None, 63 _ => return None,
diff --git a/crates/ra_assists/src/inline_local_variable.rs b/crates/ra_assists/src/inline_local_variable.rs
index 950c2910b..e0479ef13 100644
--- a/crates/ra_assists/src/inline_local_variable.rs
+++ b/crates/ra_assists/src/inline_local_variable.rs
@@ -1,7 +1,4 @@
1use hir::{ 1use hir::db::HirDatabase;
2 db::HirDatabase,
3 source_binder::function_from_child_node,
4};
5use ra_syntax::{ 2use ra_syntax::{
6 ast::{self, AstNode, AstToken, PatKind, ExprKind}, 3 ast::{self, AstNode, AstToken, PatKind, ExprKind},
7 TextRange, 4 TextRange,
@@ -29,10 +26,8 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
29 } else { 26 } else {
30 let_stmt.syntax().range() 27 let_stmt.syntax().range()
31 }; 28 };
32 29 let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None);
33 let function = function_from_child_node(ctx.db, ctx.frange.file_id, bind_pat.syntax())?; 30 let refs = analyzer.find_all_refs(bind_pat);
34 let scope = function.scopes(ctx.db);
35 let refs = scope.find_all_refs(bind_pat);
36 31
37 let mut wrap_in_parens = vec![true; refs.len()]; 32 let mut wrap_in_parens = vec![true; refs.len()];
38 33
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index c1514f8e5..ded401b63 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -86,6 +86,7 @@ where
86} 86}
87 87
88mod add_derive; 88mod add_derive;
89mod add_explicit_type;
89mod add_impl; 90mod add_impl;
90mod flip_comma; 91mod flip_comma;
91mod flip_binexpr; 92mod flip_binexpr;
@@ -103,6 +104,7 @@ mod add_missing_impl_members;
103fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] { 104fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] {
104 &[ 105 &[
105 add_derive::add_derive, 106 add_derive::add_derive,
107 add_explicit_type::add_explicit_type,
106 add_impl::add_impl, 108 add_impl::add_impl,
107 change_visibility::change_visibility, 109 change_visibility::change_visibility,
108 fill_match_arms::fill_match_arms, 110 fill_match_arms::fill_match_arms,
diff --git a/crates/ra_assists/src/split_import.rs b/crates/ra_assists/src/split_import.rs
index 4bf1852db..57e0efaf2 100644
--- a/crates/ra_assists/src/split_import.rs
+++ b/crates/ra_assists/src/split_import.rs
@@ -1,8 +1,9 @@
1use std::iter::successors;
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 TextUnit, AstNode, SyntaxKind::COLONCOLON, 5 TextUnit, AstNode, SyntaxKind::COLONCOLON,
4 ast, 6 ast,
5 algo::generate,
6}; 7};
7 8
8use crate::{AssistCtx, Assist, AssistId}; 9use crate::{AssistCtx, Assist, AssistId};
@@ -10,7 +11,7 @@ use crate::{AssistCtx, Assist, AssistId};
10pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 11pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let colon_colon = ctx.token_at_offset().find(|leaf| leaf.kind() == COLONCOLON)?; 12 let colon_colon = ctx.token_at_offset().find(|leaf| leaf.kind() == COLONCOLON)?;
12 let path = ast::Path::cast(colon_colon.parent())?; 13 let path = ast::Path::cast(colon_colon.parent())?;
13 let top_path = generate(Some(path), |it| it.parent_path()).last()?; 14 let top_path = successors(Some(path), |it| it.parent_path()).last()?;
14 15
15 let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast); 16 let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast);
16 if use_tree.is_none() { 17 if use_tree.is_none() {
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index 5bb47afb2..0cafe617d 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -9,7 +9,7 @@ use rustc_hash::FxHashMap;
9use ra_db::{ 9use ra_db::{
10 CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa, 10 CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa,
11}; 11};
12use ra_hir::{db, HirInterner}; 12use ra_hir::db;
13use ra_project_model::ProjectWorkspace; 13use ra_project_model::ProjectWorkspace;
14use ra_vfs::{Vfs, VfsChange}; 14use ra_vfs::{Vfs, VfsChange};
15use vfs_filter::IncludeRustFiles; 15use vfs_filter::IncludeRustFiles;
@@ -20,7 +20,6 @@ type Result<T> = std::result::Result<T, failure::Error>;
20#[derive(Debug)] 20#[derive(Debug)]
21pub struct BatchDatabase { 21pub struct BatchDatabase {
22 runtime: salsa::Runtime<BatchDatabase>, 22 runtime: salsa::Runtime<BatchDatabase>,
23 interner: Arc<HirInterner>,
24} 23}
25 24
26impl salsa::Database for BatchDatabase { 25impl salsa::Database for BatchDatabase {
@@ -29,12 +28,6 @@ impl salsa::Database for BatchDatabase {
29 } 28 }
30} 29}
31 30
32impl AsRef<HirInterner> for BatchDatabase {
33 fn as_ref(&self) -> &HirInterner {
34 &self.interner
35 }
36}
37
38fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { 31fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
39 FileId(f.0.into()) 32 FileId(f.0.into())
40} 33}
@@ -44,8 +37,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
44 37
45impl BatchDatabase { 38impl BatchDatabase {
46 pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase { 39 pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase {
47 let mut db = 40 let mut db = BatchDatabase { runtime: salsa::Runtime::default() };
48 BatchDatabase { runtime: salsa::Runtime::default(), interner: Default::default() };
49 db.set_crate_graph(Arc::new(crate_graph)); 41 db.set_crate_graph(Arc::new(crate_graph));
50 42
51 // wait until Vfs has loaded all roots 43 // wait until Vfs has loaded all roots
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index f3389c91f..1cd400752 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -1,11 +1,8 @@
1//! ra_db defines basic database traits. The concrete DB is defined by ra_ide_api. 1//! ra_db defines basic database traits. The concrete DB is defined by ra_ide_api.
2mod cancellation; 2mod cancellation;
3mod input; 3mod input;
4mod loc2id;
5 4
6use std::{ 5use std::{panic, sync::Arc};
7 panic, sync::Arc,
8};
9 6
10use ra_syntax::{TextUnit, TextRange, SourceFile, TreeArc}; 7use ra_syntax::{TextUnit, TextRange, SourceFile, TreeArc};
11use relative_path::RelativePathBuf; 8use relative_path::RelativePathBuf;
@@ -16,7 +13,6 @@ pub use crate::{
16 input::{ 13 input::{
17 FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, Edition, 14 FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, Edition,
18 }, 15 },
19 loc2id::LocationInterner,
20}; 16};
21 17
22pub trait CheckCanceled: panic::RefUnwindSafe { 18pub trait CheckCanceled: panic::RefUnwindSafe {
diff --git a/crates/ra_db/src/loc2id.rs b/crates/ra_db/src/loc2id.rs
deleted file mode 100644
index eae64a4eb..000000000
--- a/crates/ra_db/src/loc2id.rs
+++ /dev/null
@@ -1,103 +0,0 @@
1use std::{panic, hash::Hash};
2
3use parking_lot::Mutex;
4use rustc_hash::FxHashMap;
5use ra_arena::{Arena, ArenaId};
6
7/// There are two principle ways to refer to things:
8/// - by their location (module in foo/bar/baz.rs at line 42)
9/// - by their numeric id (module `ModuleId(42)`)
10///
11/// The first one is more powerful (you can actually find the thing in question
12/// by id), but the second one is so much more compact.
13///
14/// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a
15/// bidirectional mapping between positional and numeric ids, we can use compact
16/// representation which still allows us to get the actual item.
17#[derive(Debug)]
18struct Loc2IdMap<LOC, ID>
19where
20 ID: ArenaId + Clone,
21 LOC: Clone + Eq + Hash,
22{
23 id2loc: Arena<ID, LOC>,
24 loc2id: FxHashMap<LOC, ID>,
25}
26
27impl<LOC, ID> Default for Loc2IdMap<LOC, ID>
28where
29 ID: ArenaId + Clone,
30 LOC: Clone + Eq + Hash,
31{
32 fn default() -> Self {
33 Loc2IdMap { id2loc: Arena::default(), loc2id: FxHashMap::default() }
34 }
35}
36
37impl<LOC, ID> Loc2IdMap<LOC, ID>
38where
39 ID: ArenaId + Clone,
40 LOC: Clone + Eq + Hash,
41{
42 pub fn len(&self) -> usize {
43 self.id2loc.len()
44 }
45
46 pub fn loc2id(&mut self, loc: &LOC) -> ID {
47 match self.loc2id.get(loc) {
48 Some(id) => return id.clone(),
49 None => (),
50 }
51 let id = self.id2loc.alloc(loc.clone());
52 self.loc2id.insert(loc.clone(), id.clone());
53 id
54 }
55
56 pub fn id2loc(&self, id: ID) -> LOC {
57 self.id2loc[id].clone()
58 }
59}
60
61#[derive(Debug)]
62pub struct LocationInterner<LOC, ID>
63where
64 ID: ArenaId + Clone,
65 LOC: Clone + Eq + Hash,
66{
67 map: Mutex<Loc2IdMap<LOC, ID>>,
68}
69
70impl<LOC, ID> panic::RefUnwindSafe for LocationInterner<LOC, ID>
71where
72 ID: ArenaId + Clone,
73 LOC: Clone + Eq + Hash,
74 ID: panic::RefUnwindSafe,
75 LOC: panic::RefUnwindSafe,
76{
77}
78
79impl<LOC, ID> Default for LocationInterner<LOC, ID>
80where
81 ID: ArenaId + Clone,
82 LOC: Clone + Eq + Hash,
83{
84 fn default() -> Self {
85 LocationInterner { map: Default::default() }
86 }
87}
88
89impl<LOC, ID> LocationInterner<LOC, ID>
90where
91 ID: ArenaId + Clone,
92 LOC: Clone + Eq + Hash,
93{
94 pub fn len(&self) -> usize {
95 self.map.lock().len()
96 }
97 pub fn loc2id(&self, loc: &LOC) -> ID {
98 self.map.lock().loc2id(loc)
99 }
100 pub fn id2loc(&self, id: ID) -> LOC {
101 self.map.lock().id2loc(id)
102 }
103}
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index 85b7ce250..603be1854 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -1,10 +1,10 @@
1//! This crate provides some utilities for indenting rust code. 1//! This crate provides some utilities for indenting rust code.
2//! 2//!
3use std::iter::successors;
3use itertools::Itertools; 4use itertools::Itertools;
4use ra_syntax::{ 5use ra_syntax::{
5 SyntaxNode, SyntaxKind::*, SyntaxToken, SyntaxKind, 6 SyntaxNode, SyntaxKind::*, SyntaxToken, SyntaxKind,
6 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
7 algo::generate,
8}; 8};
9 9
10pub fn reindent(text: &str, indent: &str) -> String { 10pub fn reindent(text: &str, indent: &str) -> String {
@@ -29,7 +29,7 @@ pub fn leading_indent(node: &SyntaxNode) -> Option<&str> {
29} 29}
30 30
31fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> { 31fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
32 generate(token.prev_token(), |&token| token.prev_token()) 32 successors(token.prev_token(), |&token| token.prev_token())
33} 33}
34 34
35pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> { 35pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> {
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 9e6170440..8f1ed1086 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -4,14 +4,14 @@ use ra_db::{CrateId, SourceRootId, Edition};
4use ra_syntax::{ast::self, TreeArc}; 4use ra_syntax::{ast::self, TreeArc};
5 5
6use crate::{ 6use crate::{
7 Name, ScopesWithSourceMap, Ty, HirFileId, ImportSource, 7 Name, Ty, HirFileId, Either,
8 HirDatabase, DefDatabase, 8 HirDatabase, DefDatabase,
9 type_ref::TypeRef, 9 type_ref::TypeRef,
10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, 10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
11 expr::{Body, BodySourceMap}, 11 expr::{Body, BodySourceMap},
12 ty::InferenceResult, 12 ty::InferenceResult,
13 adt::{EnumVariantId, StructFieldId, VariantDef}, 13 adt::{EnumVariantId, StructFieldId, VariantDef},
14 generics::GenericParams, 14 generics::HasGenericParams,
15 docs::{Documentation, Docs, docs_from_ast}, 15 docs::{Documentation, Docs, docs_from_ast},
16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId}, 16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId},
17 impl_block::ImplBlock, 17 impl_block::ImplBlock,
@@ -117,8 +117,14 @@ impl Module {
117 } 117 }
118 118
119 /// Returns the syntax of the last path segment corresponding to this import 119 /// Returns the syntax of the last path segment corresponding to this import
120 pub fn import_source(&self, db: &impl HirDatabase, import: ImportId) -> ImportSource { 120 pub fn import_source(
121 self.import_source_impl(db, import) 121 &self,
122 db: &impl HirDatabase,
123 import: ImportId,
124 ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> {
125 let (file_id, source) = self.definition_source(db);
126 let (_, source_map) = db.raw_items_with_source_map(file_id);
127 source_map.get(&source, import)
122 } 128 }
123 129
124 /// Returns the crate this module is part of. 130 /// Returns the crate this module is part of.
@@ -183,12 +189,12 @@ impl Module {
183 } 189 }
184 } 190 }
185 191
186 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 192 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
187 let def_map = db.crate_def_map(self.krate); 193 let def_map = db.crate_def_map(self.krate);
188 Resolver::default().push_module_scope(def_map, self.module_id) 194 Resolver::default().push_module_scope(def_map, self.module_id)
189 } 195 }
190 196
191 pub fn declarations(self, db: &impl HirDatabase) -> Vec<ModuleDef> { 197 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
192 let def_map = db.crate_def_map(self.krate); 198 let def_map = db.crate_def_map(self.krate);
193 def_map[self.module_id] 199 def_map[self.module_id]
194 .scope 200 .scope
@@ -293,10 +299,6 @@ impl Struct {
293 .map(|(id, _)| StructField { parent: (*self).into(), id }) 299 .map(|(id, _)| StructField { parent: (*self).into(), id })
294 } 300 }
295 301
296 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
297 db.generic_params((*self).into())
298 }
299
300 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 302 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
301 db.type_for_def((*self).into(), Namespace::Types) 303 db.type_for_def((*self).into(), Namespace::Types)
302 } 304 }
@@ -307,7 +309,7 @@ impl Struct {
307 309
308 // FIXME move to a more general type 310 // FIXME move to a more general type
309 /// Builds a resolver for type references inside this struct. 311 /// Builds a resolver for type references inside this struct.
310 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 312 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
311 // take the outer scope... 313 // take the outer scope...
312 let r = self.module(db).resolver(db); 314 let r = self.module(db).resolver(db);
313 // ...and add generic params, if present 315 // ...and add generic params, if present
@@ -357,17 +359,13 @@ impl Enum {
357 .map(|(id, _)| EnumVariant { parent: *self, id }) 359 .map(|(id, _)| EnumVariant { parent: *self, id })
358 } 360 }
359 361
360 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
361 db.generic_params((*self).into())
362 }
363
364 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 362 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
365 db.type_for_def((*self).into(), Namespace::Types) 363 db.type_for_def((*self).into(), Namespace::Types)
366 } 364 }
367 365
368 // FIXME: move to a more general type 366 // FIXME: move to a more general type
369 /// Builds a resolver for type references inside this struct. 367 /// Builds a resolver for type references inside this struct.
370 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 368 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
371 // take the outer scope... 369 // take the outer scope...
372 let r = self.module(db).resolver(db); 370 let r = self.module(db).resolver(db);
373 // ...and add generic params, if present 371 // ...and add generic params, if present
@@ -444,28 +442,22 @@ impl DefWithBody {
444 db.infer(*self) 442 db.infer(*self)
445 } 443 }
446 444
447 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
448 db.body_with_source_map(*self).1
449 }
450
451 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 445 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
452 db.body_hir(*self) 446 db.body_hir(*self)
453 } 447 }
454 448
449 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
450 db.body_with_source_map(*self).1
451 }
452
455 /// Builds a resolver for code inside this item. 453 /// Builds a resolver for code inside this item.
456 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 454 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
457 match *self { 455 match *self {
458 DefWithBody::Const(ref c) => c.resolver(db), 456 DefWithBody::Const(ref c) => c.resolver(db),
459 DefWithBody::Function(ref f) => f.resolver(db), 457 DefWithBody::Function(ref f) => f.resolver(db),
460 DefWithBody::Static(ref s) => s.resolver(db), 458 DefWithBody::Static(ref s) => s.resolver(db),
461 } 459 }
462 } 460 }
463
464 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
465 let scopes = db.expr_scopes(*self);
466 let source_map = db.body_with_source_map(*self).1;
467 ScopesWithSourceMap { scopes, source_map }
468 }
469} 461}
470 462
471#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 463#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -517,7 +509,7 @@ impl Function {
517 self.signature(db).name.clone() 509 self.signature(db).name.clone()
518 } 510 }
519 511
520 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { 512 pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
521 db.body_with_source_map((*self).into()).1 513 db.body_with_source_map((*self).into()).1
522 } 514 }
523 515
@@ -529,12 +521,6 @@ impl Function {
529 db.type_for_def((*self).into(), Namespace::Values) 521 db.type_for_def((*self).into(), Namespace::Values)
530 } 522 }
531 523
532 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
533 let scopes = db.expr_scopes((*self).into());
534 let source_map = db.body_with_source_map((*self).into()).1;
535 ScopesWithSourceMap { scopes, source_map }
536 }
537
538 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { 524 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
539 db.fn_signature(*self) 525 db.fn_signature(*self)
540 } 526 }
@@ -543,24 +529,32 @@ impl Function {
543 db.infer((*self).into()) 529 db.infer((*self).into())
544 } 530 }
545 531
546 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
547 db.generic_params((*self).into())
548 }
549
550 /// The containing impl block, if this is a method. 532 /// The containing impl block, if this is a method.
551 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { 533 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
552 let module_impls = db.impls_in_module(self.module(db)); 534 let module_impls = db.impls_in_module(self.module(db));
553 ImplBlock::containing(module_impls, (*self).into()) 535 ImplBlock::containing(module_impls, (*self).into())
554 } 536 }
555 537
538 /// The containing trait, if this is a trait method definition.
539 pub fn parent_trait(&self, db: &impl DefDatabase) -> Option<Trait> {
540 db.trait_items_index(self.module(db)).get_parent_trait((*self).into())
541 }
542
543 pub fn container(&self, db: &impl DefDatabase) -> Option<Container> {
544 if let Some(impl_block) = self.impl_block(db) {
545 Some(impl_block.into())
546 } else if let Some(trait_) = self.parent_trait(db) {
547 Some(trait_.into())
548 } else {
549 None
550 }
551 }
552
556 // FIXME: move to a more general type for 'body-having' items 553 // FIXME: move to a more general type for 'body-having' items
557 /// Builds a resolver for code inside this item. 554 /// Builds a resolver for code inside this item.
558 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 555 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
559 // take the outer scope... 556 // take the outer scope...
560 let r = self 557 let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db));
561 .impl_block(db)
562 .map(|ib| ib.resolver(db))
563 .unwrap_or_else(|| self.module(db).resolver(db));
564 // ...and add generic params, if present 558 // ...and add generic params, if present
565 let p = self.generic_params(db); 559 let p = self.generic_params(db);
566 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; 560 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
@@ -600,10 +594,6 @@ impl Const {
600 db.infer((*self).into()) 594 db.infer((*self).into())
601 } 595 }
602 596
603 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
604 db.body_with_source_map((*self).into()).1
605 }
606
607 /// The containing impl block, if this is a method. 597 /// The containing impl block, if this is a method.
608 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { 598 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
609 let module_impls = db.impls_in_module(self.module(db)); 599 let module_impls = db.impls_in_module(self.module(db));
@@ -612,7 +602,7 @@ impl Const {
612 602
613 // FIXME: move to a more general type for 'body-having' items 603 // FIXME: move to a more general type for 'body-having' items
614 /// Builds a resolver for code inside this item. 604 /// Builds a resolver for code inside this item.
615 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 605 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
616 // take the outer scope... 606 // take the outer scope...
617 let r = self 607 let r = self
618 .impl_block(db) 608 .impl_block(db)
@@ -664,7 +654,7 @@ impl Static {
664 } 654 }
665 655
666 /// Builds a resolver for code inside this item. 656 /// Builds a resolver for code inside this item.
667 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 657 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
668 // take the outer scope... 658 // take the outer scope...
669 self.module(db).resolver(db) 659 self.module(db).resolver(db)
670 } 660 }
@@ -672,10 +662,6 @@ impl Static {
672 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 662 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
673 db.infer((*self).into()) 663 db.infer((*self).into())
674 } 664 }
675
676 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
677 db.body_with_source_map((*self).into()).1
678 }
679} 665}
680 666
681impl Docs for Static { 667impl Docs for Static {
@@ -698,10 +684,6 @@ impl Trait {
698 self.id.module(db) 684 self.id.module(db)
699 } 685 }
700 686
701 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
702 db.generic_params((*self).into())
703 }
704
705 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 687 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
706 self.trait_data(db).name().clone() 688 self.trait_data(db).name().clone()
707 } 689 }
@@ -713,6 +695,14 @@ impl Trait {
713 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 695 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
714 db.trait_data(self) 696 db.trait_data(self)
715 } 697 }
698
699 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
700 let r = self.module(db).resolver(db);
701 // add generic params, if present
702 let p = self.generic_params(db);
703 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
704 r
705 }
716} 706}
717 707
718impl Docs for Trait { 708impl Docs for Trait {
@@ -731,10 +721,6 @@ impl TypeAlias {
731 self.id.source(db) 721 self.id.source(db)
732 } 722 }
733 723
734 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
735 db.generic_params((*self).into())
736 }
737
738 pub fn module(&self, db: &impl DefDatabase) -> Module { 724 pub fn module(&self, db: &impl DefDatabase) -> Module {
739 self.id.module(db) 725 self.id.module(db)
740 } 726 }
@@ -745,12 +731,27 @@ impl TypeAlias {
745 ImplBlock::containing(module_impls, (*self).into()) 731 ImplBlock::containing(module_impls, (*self).into())
746 } 732 }
747 733
734 /// The containing trait, if this is a trait method definition.
735 pub fn parent_trait(&self, db: &impl DefDatabase) -> Option<Trait> {
736 db.trait_items_index(self.module(db)).get_parent_trait((*self).into())
737 }
738
739 pub fn container(&self, db: &impl DefDatabase) -> Option<Container> {
740 if let Some(impl_block) = self.impl_block(db) {
741 Some(impl_block.into())
742 } else if let Some(trait_) = self.parent_trait(db) {
743 Some(trait_.into())
744 } else {
745 None
746 }
747 }
748
748 pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> { 749 pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> {
749 db.type_alias_ref(self) 750 db.type_alias_ref(self)
750 } 751 }
751 752
752 /// Builds a resolver for the type references in this type alias. 753 /// Builds a resolver for the type references in this type alias.
753 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 754 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
754 // take the outer scope... 755 // take the outer scope...
755 let r = self 756 let r = self
756 .impl_block(db) 757 .impl_block(db)
@@ -768,3 +769,18 @@ impl Docs for TypeAlias {
768 docs_from_ast(&*self.source(db).1) 769 docs_from_ast(&*self.source(db).1)
769 } 770 }
770} 771}
772
773pub enum Container {
774 Trait(Trait),
775 ImplBlock(ImplBlock),
776}
777impl_froms!(Container: Trait, ImplBlock);
778
779impl Container {
780 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
781 match self {
782 Container::Trait(trait_) => trait_.resolver(db),
783 Container::ImplBlock(impl_block) => impl_block.resolver(db),
784 }
785 }
786}
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 88dee3a69..5c2ea73ce 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -3,9 +3,9 @@ use ra_syntax::{ast, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Name, AstId, 5 Module, ModuleSource, Name, AstId,
6 nameres::{CrateModuleId, ImportId}, 6 nameres::CrateModuleId,
7 HirDatabase, DefDatabase, 7 HirDatabase, DefDatabase,
8 HirFileId, ImportSource, 8 HirFileId,
9}; 9};
10 10
11impl ModuleSource { 11impl ModuleSource {
@@ -68,16 +68,6 @@ impl Module {
68 Some((decl.file_id(), ast)) 68 Some((decl.file_id(), ast))
69 } 69 }
70 70
71 pub(crate) fn import_source_impl(
72 &self,
73 db: &impl HirDatabase,
74 import: ImportId,
75 ) -> ImportSource {
76 let (file_id, source) = self.definition_source(db);
77 let (_, source_map) = db.raw_items_with_source_map(file_id);
78 source_map.get(&source, import)
79 }
80
81 pub(crate) fn crate_root_impl(&self, db: &impl DefDatabase) -> Module { 71 pub(crate) fn crate_root_impl(&self, db: &impl DefDatabase) -> Module {
82 let def_map = db.crate_def_map(self.krate); 72 let def_map = db.crate_def_map(self.krate);
83 self.with_module_id(def_map.root()) 73 self.with_module_id(def_map.root())
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index be8a8c98b..18627bbc2 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, ast};
4use ra_db::{SourceDatabase, salsa}; 4use ra_db::{SourceDatabase, salsa};
5 5
6use crate::{ 6use crate::{
7 HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, HirInterner, 7 HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, MacroCallLoc,
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,
@@ -15,11 +15,29 @@ use crate::{
15 impl_block::{ModuleImplBlocks, ImplSourceMap}, 15 impl_block::{ModuleImplBlocks, ImplSourceMap},
16 generics::{GenericParams, GenericDef}, 16 generics::{GenericParams, GenericDef},
17 type_ref::TypeRef, 17 type_ref::TypeRef,
18 traits::TraitData, Trait, ty::TraitRef 18 traits::TraitData, Trait, ty::TraitRef,
19 ids
19}; 20};
20 21
21#[salsa::query_group(DefDatabaseStorage)] 22#[salsa::query_group(DefDatabaseStorage)]
22pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> { 23pub trait DefDatabase: SourceDatabase {
24 #[salsa::interned]
25 fn intern_macro(&self, macro_call: MacroCallLoc) -> ids::MacroCallId;
26 #[salsa::interned]
27 fn intern_function(&self, loc: ids::ItemLoc<ast::FnDef>) -> ids::FunctionId;
28 #[salsa::interned]
29 fn intern_struct(&self, loc: ids::ItemLoc<ast::StructDef>) -> ids::StructId;
30 #[salsa::interned]
31 fn intern_enum(&self, loc: ids::ItemLoc<ast::EnumDef>) -> ids::EnumId;
32 #[salsa::interned]
33 fn intern_const(&self, loc: ids::ItemLoc<ast::ConstDef>) -> ids::ConstId;
34 #[salsa::interned]
35 fn intern_static(&self, loc: ids::ItemLoc<ast::StaticDef>) -> ids::StaticId;
36 #[salsa::interned]
37 fn intern_trait(&self, loc: ids::ItemLoc<ast::TraitDef>) -> ids::TraitId;
38 #[salsa::interned]
39 fn intern_type_alias(&self, loc: ids::ItemLoc<ast::TypeAliasDef>) -> ids::TypeAliasId;
40
23 #[salsa::invoke(crate::ids::macro_def_query)] 41 #[salsa::invoke(crate::ids::macro_def_query)]
24 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; 42 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
25 43
@@ -35,6 +53,9 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
35 #[salsa::invoke(crate::traits::TraitData::trait_data_query)] 53 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
36 fn trait_data(&self, t: Trait) -> Arc<TraitData>; 54 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
37 55
56 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
57 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
58
38 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] 59 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
39 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; 60 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
40 61
@@ -110,8 +131,8 @@ pub trait HirDatabase: DefDatabase {
110 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 131 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
111 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 132 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
112 133
113 #[salsa::invoke(crate::ty::method_resolution::implements)] 134 #[salsa::invoke(crate::ty::traits::implements)]
114 fn implements(&self, trait_ref: TraitRef) -> bool; 135 fn implements(&self, trait_ref: TraitRef) -> Option<crate::ty::traits::Solution>;
115} 136}
116 137
117#[test] 138#[test]
diff --git a/crates/ra_hir/src/either.rs b/crates/ra_hir/src/either.rs
new file mode 100644
index 000000000..4073cc82e
--- /dev/null
+++ b/crates/ra_hir/src/either.rs
@@ -0,0 +1,28 @@
1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub enum Either<A, B> {
3 A(A),
4 B(B),
5}
6
7impl<A, B> Either<A, B> {
8 pub fn either<R, F1, F2>(self, f1: F1, f2: F2) -> R
9 where
10 F1: FnOnce(A) -> R,
11 F2: FnOnce(B) -> R,
12 {
13 match self {
14 Either::A(a) => f1(a),
15 Either::B(b) => f2(b),
16 }
17 }
18 pub fn map<U, V, F1, F2>(self, f1: F1, f2: F2) -> Either<U, V>
19 where
20 F1: FnOnce(A) -> U,
21 F2: FnOnce(B) -> V,
22 {
23 match self {
24 Either::A(a) => Either::A(f1(a)),
25 Either::B(b) => Either::B(f2(b)),
26 }
27 }
28}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 589a9b2db..817e660f9 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -10,13 +10,13 @@ use ra_syntax::{
10}; 10};
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Resolver,DefWithBody, 13 Path, Name, HirDatabase, Resolver,DefWithBody, Either,
14 name::AsName, 14 name::AsName,
15 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeRef},
16}; 16};
17use crate::{ path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; 17use crate::{path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}};
18 18
19pub use self::scope::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}; 19pub use self::scope::ExprScopes;
20 20
21pub(crate) mod scope; 21pub(crate) mod scope;
22 22
@@ -51,11 +51,13 @@ pub struct Body {
51pub struct BodySourceMap { 51pub struct BodySourceMap {
52 expr_map: FxHashMap<SyntaxNodePtr, ExprId>, 52 expr_map: FxHashMap<SyntaxNodePtr, ExprId>,
53 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>, 53 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>,
54 pat_map: FxHashMap<SyntaxNodePtr, PatId>, 54 pat_map: FxHashMap<PatPtr, PatId>,
55 pat_map_back: ArenaMap<PatId, SyntaxNodePtr>, 55 pat_map_back: ArenaMap<PatId, PatPtr>,
56 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>, 56 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>,
57} 57}
58 58
59type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
60
59impl Body { 61impl Body {
60 pub fn params(&self) -> &[PatId] { 62 pub fn params(&self) -> &[PatId] {
61 &self.params 63 &self.params
@@ -79,19 +81,23 @@ impl Body {
79} 81}
80 82
81// needs arbitrary_self_types to be a method... or maybe move to the def? 83// needs arbitrary_self_types to be a method... or maybe move to the def?
82pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { 84pub(crate) fn resolver_for_expr(
85 body: Arc<Body>,
86 db: &impl HirDatabase,
87 expr_id: ExprId,
88) -> Resolver {
83 let scopes = db.expr_scopes(body.owner); 89 let scopes = db.expr_scopes(body.owner);
84 resolver_for_scope(body, db, scopes.scope_for(expr_id)) 90 resolver_for_scope(body, db, scopes.scope_for(expr_id))
85} 91}
86 92
87pub fn resolver_for_scope( 93pub(crate) fn resolver_for_scope(
88 body: Arc<Body>, 94 body: Arc<Body>,
89 db: &impl HirDatabase, 95 db: &impl HirDatabase,
90 scope_id: Option<scope::ScopeId>, 96 scope_id: Option<scope::ScopeId>,
91) -> Resolver { 97) -> Resolver {
92 let mut r = body.owner.resolver(db); 98 let mut r = body.owner.resolver(db);
93 let scopes = db.expr_scopes(body.owner); 99 let scopes = db.expr_scopes(body.owner);
94 let scope_chain = scopes.scope_chain_for(scope_id).collect::<Vec<_>>(); 100 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
95 for scope in scope_chain.into_iter().rev() { 101 for scope in scope_chain.into_iter().rev() {
96 r = r.push_expr_scope(Arc::clone(&scopes), scope); 102 r = r.push_expr_scope(Arc::clone(&scopes), scope);
97 } 103 }
@@ -115,31 +121,27 @@ impl Index<PatId> for Body {
115} 121}
116 122
117impl BodySourceMap { 123impl BodySourceMap {
118 pub fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> { 124 pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> {
119 self.expr_map_back.get(expr).cloned() 125 self.expr_map_back.get(expr).cloned()
120 } 126 }
121 127
122 pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> { 128 pub(crate) fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
123 self.expr_map.get(&ptr).cloned() 129 self.expr_map.get(&ptr).cloned()
124 } 130 }
125 131
126 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 132 pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
127 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() 133 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
128 } 134 }
129 135
130 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> { 136 pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> {
131 self.pat_map_back.get(pat).cloned() 137 self.pat_map_back.get(pat).cloned()
132 } 138 }
133 139
134 pub fn syntax_pat(&self, ptr: SyntaxNodePtr) -> Option<PatId> { 140 pub(crate) fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
135 self.pat_map.get(&ptr).cloned() 141 self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
136 }
137
138 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
139 self.pat_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
140 } 142 }
141 143
142 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> { 144 pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> {
143 self.field_map[&(expr, field)].clone() 145 self.field_map[&(expr, field)].clone()
144 } 146 }
145} 147}
@@ -504,10 +506,10 @@ impl ExprCollector {
504 id 506 id
505 } 507 }
506 508
507 fn alloc_pat(&mut self, pat: Pat, syntax_ptr: SyntaxNodePtr) -> PatId { 509 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
508 let id = self.pats.alloc(pat); 510 let id = self.pats.alloc(pat);
509 self.source_map.pat_map.insert(syntax_ptr, id); 511 self.source_map.pat_map.insert(ptr, id);
510 self.source_map.pat_map_back.insert(id, syntax_ptr); 512 self.source_map.pat_map_back.insert(id, ptr);
511 id 513 id
512 } 514 }
513 515
@@ -886,8 +888,8 @@ impl ExprCollector {
886 ast::PatKind::LiteralPat(_) => Pat::Missing, 888 ast::PatKind::LiteralPat(_) => Pat::Missing,
887 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing, 889 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
888 }; 890 };
889 let syntax_ptr = SyntaxNodePtr::new(pat.syntax()); 891 let ptr = AstPtr::new(pat);
890 self.alloc_pat(pattern, syntax_ptr) 892 self.alloc_pat(pattern, Either::A(ptr))
891 } 893 }
892 894
893 fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId { 895 fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId {
@@ -911,14 +913,14 @@ impl ExprCollector {
911 fn collect_fn_body(&mut self, node: &ast::FnDef) { 913 fn collect_fn_body(&mut self, node: &ast::FnDef) {
912 if let Some(param_list) = node.param_list() { 914 if let Some(param_list) = node.param_list() {
913 if let Some(self_param) = param_list.self_param() { 915 if let Some(self_param) = param_list.self_param() {
914 let self_param = SyntaxNodePtr::new(self_param.syntax()); 916 let ptr = AstPtr::new(self_param);
915 let param_pat = self.alloc_pat( 917 let param_pat = self.alloc_pat(
916 Pat::Bind { 918 Pat::Bind {
917 name: Name::self_param(), 919 name: Name::self_param(),
918 mode: BindingAnnotation::Unannotated, 920 mode: BindingAnnotation::Unannotated,
919 subpat: None, 921 subpat: None,
920 }, 922 },
921 self_param, 923 Either::B(ptr),
922 ); 924 );
923 self.params.push(param_pat); 925 self.params.push(param_pat);
924 } 926 }
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 48283907b..58f365128 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -1,17 +1,11 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::FxHashMap;
4
5use ra_syntax::{
6 AstNode, SyntaxNode, TextUnit, TextRange, SyntaxNodePtr,
7 algo::generate,
8 ast,
9};
10use ra_arena::{Arena, RawId, impl_arena_id}; 4use ra_arena::{Arena, RawId, impl_arena_id};
11 5
12use crate::{ 6use crate::{
13 Name, AsName,DefWithBody, 7 Name, DefWithBody,
14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap}, 8 expr::{PatId, ExprId, Pat, Expr, Body, Statement},
15 HirDatabase, 9 HirDatabase,
16}; 10};
17 11
@@ -23,23 +17,32 @@ impl_arena_id!(ScopeId);
23pub struct ExprScopes { 17pub struct ExprScopes {
24 body: Arc<Body>, 18 body: Arc<Body>,
25 scopes: Arena<ScopeId, ScopeData>, 19 scopes: Arena<ScopeId, ScopeData>,
26 scope_for: FxHashMap<ExprId, ScopeId>, 20 scope_by_expr: FxHashMap<ExprId, ScopeId>,
27} 21}
28 22
29#[derive(Debug, PartialEq, Eq)] 23#[derive(Debug, PartialEq, Eq)]
30pub struct ScopeEntry { 24pub(crate) struct ScopeEntry {
31 name: Name, 25 name: Name,
32 pat: PatId, 26 pat: PatId,
33} 27}
34 28
29impl ScopeEntry {
30 pub(crate) fn name(&self) -> &Name {
31 &self.name
32 }
33
34 pub(crate) fn pat(&self) -> PatId {
35 self.pat
36 }
37}
38
35#[derive(Debug, PartialEq, Eq)] 39#[derive(Debug, PartialEq, Eq)]
36pub struct ScopeData { 40pub(crate) struct ScopeData {
37 parent: Option<ScopeId>, 41 parent: Option<ScopeId>,
38 entries: Vec<ScopeEntry>, 42 entries: Vec<ScopeEntry>,
39} 43}
40 44
41impl ExprScopes { 45impl ExprScopes {
42 // FIXME: This should take something more general than Function
43 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<ExprScopes> { 46 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<ExprScopes> {
44 let body = db.body_hir(def); 47 let body = db.body_hir(def);
45 let res = ExprScopes::new(body); 48 let res = ExprScopes::new(body);
@@ -50,7 +53,7 @@ impl ExprScopes {
50 let mut scopes = ExprScopes { 53 let mut scopes = ExprScopes {
51 body: body.clone(), 54 body: body.clone(),
52 scopes: Arena::default(), 55 scopes: Arena::default(),
53 scope_for: FxHashMap::default(), 56 scope_by_expr: FxHashMap::default(),
54 }; 57 };
55 let root = scopes.root_scope(); 58 let root = scopes.root_scope();
56 scopes.add_params_bindings(root, body.params()); 59 scopes.add_params_bindings(root, body.params());
@@ -58,19 +61,23 @@ impl ExprScopes {
58 scopes 61 scopes
59 } 62 }
60 63
61 pub fn body(&self) -> Arc<Body> { 64 pub(crate) fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
62 self.body.clone()
63 }
64
65 pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
66 &self.scopes[scope].entries 65 &self.scopes[scope].entries
67 } 66 }
68 67
69 pub fn scope_chain_for<'a>( 68 pub(crate) fn scope_chain<'a>(
70 &'a self, 69 &'a self,
71 scope: Option<ScopeId>, 70 scope: Option<ScopeId>,
72 ) -> impl Iterator<Item = ScopeId> + 'a { 71 ) -> impl Iterator<Item = ScopeId> + 'a {
73 generate(scope, move |&scope| self.scopes[scope].parent) 72 std::iter::successors(scope, move |&scope| self.scopes[scope].parent)
73 }
74
75 pub(crate) fn scope_for(&self, expr: ExprId) -> Option<ScopeId> {
76 self.scope_by_expr.get(&expr).map(|&scope| scope)
77 }
78
79 pub(crate) fn scope_by_expr(&self) -> &FxHashMap<ExprId, ScopeId> {
80 &self.scope_by_expr
74 } 81 }
75 82
76 fn root_scope(&mut self) -> ScopeId { 83 fn root_scope(&mut self) -> ScopeId {
@@ -99,130 +106,7 @@ impl ExprScopes {
99 } 106 }
100 107
101 fn set_scope(&mut self, node: ExprId, scope: ScopeId) { 108 fn set_scope(&mut self, node: ExprId, scope: ScopeId) {
102 self.scope_for.insert(node, scope); 109 self.scope_by_expr.insert(node, scope);
103 }
104
105 pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> {
106 self.scope_for.get(&expr).map(|&scope| scope)
107 }
108}
109
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct ScopesWithSourceMap {
112 pub source_map: Arc<BodySourceMap>,
113 pub scopes: Arc<ExprScopes>,
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct ScopeEntryWithSyntax {
118 name: Name,
119 ptr: SyntaxNodePtr,
120}
121
122impl ScopeEntryWithSyntax {
123 pub fn name(&self) -> &Name {
124 &self.name
125 }
126
127 pub fn ptr(&self) -> SyntaxNodePtr {
128 self.ptr
129 }
130}
131
132impl ScopesWithSourceMap {
133 fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a {
134 generate(self.scope_for(node), move |&scope| self.scopes.scopes[scope].parent)
135 }
136
137 pub fn scope_for_offset(&self, offset: TextUnit) -> Option<ScopeId> {
138 self.scopes
139 .scope_for
140 .iter()
141 .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope)))
142 // find containing scope
143 .min_by_key(|(ptr, _scope)| {
144 (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len())
145 })
146 .map(|(ptr, scope)| self.adjust(ptr, *scope, offset))
147 }
148
149 // XXX: during completion, cursor might be outside of any particular
150 // expression. Try to figure out the correct scope...
151 // FIXME: move this to source binder?
152 fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId {
153 let r = ptr.range();
154 let child_scopes = self
155 .scopes
156 .scope_for
157 .iter()
158 .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope)))
159 .map(|(ptr, scope)| (ptr.range(), scope))
160 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r);
161
162 child_scopes
163 .max_by(|(r1, _), (r2, _)| {
164 if r2.is_subrange(&r1) {
165 std::cmp::Ordering::Greater
166 } else if r1.is_subrange(&r2) {
167 std::cmp::Ordering::Less
168 } else {
169 r1.start().cmp(&r2.start())
170 }
171 })
172 .map(|(_ptr, scope)| *scope)
173 .unwrap_or(original_scope)
174 }
175
176 pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> {
177 let mut shadowed = FxHashSet::default();
178 let name = name_ref.as_name();
179 let ret = self
180 .scope_chain(name_ref.syntax())
181 .flat_map(|scope| self.scopes.entries(scope).iter())
182 .filter(|entry| shadowed.insert(entry.name()))
183 .filter(|entry| entry.name() == &name)
184 .nth(0);
185 ret.and_then(|entry| {
186 Some(ScopeEntryWithSyntax {
187 name: entry.name().clone(),
188 ptr: self.source_map.pat_syntax(entry.pat())?,
189 })
190 })
191 }
192
193 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
194 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
195 let name_ptr = SyntaxNodePtr::new(pat.syntax());
196 fn_def
197 .syntax()
198 .descendants()
199 .filter_map(ast::NameRef::cast)
200 .filter(|name_ref| match self.resolve_local_name(*name_ref) {
201 None => false,
202 Some(entry) => entry.ptr() == name_ptr,
203 })
204 .map(|name_ref| ReferenceDescriptor {
205 name: name_ref.syntax().text().to_string(),
206 range: name_ref.syntax().range(),
207 })
208 .collect()
209 }
210
211 pub fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> {
212 node.ancestors()
213 .map(SyntaxNodePtr::new)
214 .filter_map(|ptr| self.source_map.syntax_expr(ptr))
215 .find_map(|it| self.scopes.scope_for(it))
216 }
217}
218
219impl ScopeEntry {
220 pub fn name(&self) -> &Name {
221 &self.name
222 }
223
224 pub fn pat(&self) -> PatId {
225 self.pat
226 } 110 }
227} 111}
228 112
@@ -286,22 +170,13 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
286 }; 170 };
287} 171}
288 172
289#[derive(Debug)]
290pub struct ReferenceDescriptor {
291 pub range: TextRange,
292 pub name: String,
293}
294
295#[cfg(test)] 173#[cfg(test)]
296mod tests { 174mod tests {
297 use ra_syntax::{SourceFile, algo::find_node_at_offset}; 175 use ra_db::SourceDatabase;
176 use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr, ast};
298 use test_utils::{extract_offset, assert_eq_text}; 177 use test_utils::{extract_offset, assert_eq_text};
299 use ra_arena::ArenaId;
300 use crate::Function;
301
302 use crate::expr::{ExprCollector};
303 178
304 use super::*; 179 use crate::{source_binder::SourceAnalyzer, mock::MockDatabase};
305 180
306 fn do_check(code: &str, expected: &[&str]) { 181 fn do_check(code: &str, expected: &[&str]) {
307 let (off, code) = extract_offset(code); 182 let (off, code) = extract_offset(code);
@@ -313,17 +188,20 @@ mod tests {
313 buf.push_str(&code[off..]); 188 buf.push_str(&code[off..]);
314 buf 189 buf
315 }; 190 };
316 let file = SourceFile::parse(&code); 191
192 let (db, _source_root, file_id) = MockDatabase::with_single_file(&code);
193 let file = db.parse(file_id);
317 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 194 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
318 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 195 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None);
319 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) }; 196
320 let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); 197 let scopes = analyzer.scopes();
321 let scopes = ExprScopes::new(Arc::new(body)); 198 let expr_id =
322 let scopes = 199 analyzer.body_source_map().syntax_expr(SyntaxNodePtr::new(marker.syntax())).unwrap();
323 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; 200 let scope = scopes.scope_for(expr_id);
201
324 let actual = scopes 202 let actual = scopes
325 .scope_chain(marker.syntax()) 203 .scope_chain(scope)
326 .flat_map(|scope| scopes.scopes.entries(scope)) 204 .flat_map(|scope| scopes.entries(scope))
327 .map(|it| it.name().to_string()) 205 .map(|it| it.name().to_string())
328 .collect::<Vec<_>>() 206 .collect::<Vec<_>>()
329 .join("\n"); 207 .join("\n");
@@ -406,28 +284,19 @@ mod tests {
406 ); 284 );
407 } 285 }
408 286
409 fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) {
410 let mut collector = ExprCollector::new(DefWithBody::Function(function));
411 collector.collect_fn_body(node);
412 collector.finish()
413 }
414
415 fn do_check_local_name(code: &str, expected_offset: u32) { 287 fn do_check_local_name(code: &str, expected_offset: u32) {
416 let (off, code) = extract_offset(code); 288 let (off, code) = extract_offset(code);
417 let file = SourceFile::parse(&code); 289
290 let (db, _source_root, file_id) = MockDatabase::with_single_file(&code);
291 let file = db.parse(file_id);
418 let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) 292 let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into())
419 .expect("failed to find a name at the target offset"); 293 .expect("failed to find a name at the target offset");
420
421 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
422 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 294 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
295 let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None);
423 296
424 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) }; 297 let local_name_entry = analyzer.resolve_local_name(name_ref).unwrap();
425 let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); 298 let local_name =
426 let scopes = ExprScopes::new(Arc::new(body)); 299 local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
427 let scopes =
428 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) };
429 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
430 let local_name = local_name_entry.ptr();
431 assert_eq!(local_name.range(), expected_name.syntax().range()); 300 assert_eq!(local_name.range(), expected_name.syntax().range());
432 } 301 }
433 302
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 84fe94289..5625c2459 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -9,7 +9,7 @@ use ra_syntax::ast::{self, NameOwner, TypeParamsOwner};
9 9
10use crate::{ 10use crate::{
11 db::DefDatabase, 11 db::DefDatabase,
12 Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock 12 Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container
13}; 13};
14 14
15/// Data about a generic parameter (to a function, struct, impl, ...). 15/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -27,6 +27,7 @@ pub struct GenericParams {
27 pub(crate) params: Vec<GenericParam>, 27 pub(crate) params: Vec<GenericParam>,
28} 28}
29 29
30// FIXME: consts can have type parameters from their parents (i.e. associated consts of traits)
30#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 31#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
31pub enum GenericDef { 32pub enum GenericDef {
32 Function(Function), 33 Function(Function),
@@ -45,18 +46,22 @@ impl GenericParams {
45 ) -> Arc<GenericParams> { 46 ) -> Arc<GenericParams> {
46 let mut generics = GenericParams::default(); 47 let mut generics = GenericParams::default();
47 let parent = match def { 48 let parent = match def {
48 GenericDef::Function(it) => it.impl_block(db), 49 GenericDef::Function(it) => it.container(db).map(GenericDef::from),
49 GenericDef::TypeAlias(it) => it.impl_block(db), 50 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from),
50 GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, 51 GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None,
51 GenericDef::ImplBlock(_) => None, 52 GenericDef::ImplBlock(_) => None,
52 }; 53 };
53 generics.parent_params = parent.map(|p| p.generic_params(db)); 54 generics.parent_params = parent.map(|p| db.generic_params(p));
54 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; 55 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
55 match def { 56 match def {
56 GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), 57 GenericDef::Function(it) => generics.fill(&*it.source(db).1, start),
57 GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), 58 GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start),
58 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), 59 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
59 GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start), 60 GenericDef::Trait(it) => {
61 // traits get the Self type as an implicit first type parameter
62 generics.params.push(GenericParam { idx: start, name: Name::self_type() });
63 generics.fill(&*it.source(db).1, start + 1);
64 }
60 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), 65 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start),
61 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), 66 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start),
62 } 67 }
@@ -104,3 +109,25 @@ impl GenericParams {
104 vec 109 vec
105 } 110 }
106} 111}
112
113impl From<Container> for GenericDef {
114 fn from(c: Container) -> Self {
115 match c {
116 Container::Trait(trait_) => trait_.into(),
117 Container::ImplBlock(impl_block) => impl_block.into(),
118 }
119 }
120}
121
122pub trait HasGenericParams {
123 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams>;
124}
125
126impl<T> HasGenericParams for T
127where
128 T: Into<GenericDef>,
129{
130 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> {
131 db.generic_params(self.into())
132 }
133}
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index eb9939df7..141c9072f 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -3,40 +3,14 @@ use std::{
3 sync::Arc, 3 sync::Arc,
4}; 4};
5 5
6use ra_db::{LocationInterner, FileId}; 6use ra_db::{FileId, salsa};
7use ra_syntax::{TreeArc, SourceFile, AstNode, ast}; 7use ra_syntax::{TreeArc, SourceFile, AstNode, ast};
8use ra_arena::{RawId, ArenaId, impl_arena_id};
9use mbe::MacroRules; 8use mbe::MacroRules;
10 9
11use crate::{ 10use crate::{
12 Module, DefDatabase, AstId, FileAstId, 11 Module, DefDatabase, AstId, FileAstId,
13}; 12};
14 13
15#[derive(Debug, Default)]
16pub struct HirInterner {
17 macros: LocationInterner<MacroCallLoc, MacroCallId>,
18 fns: LocationInterner<ItemLoc<ast::FnDef>, FunctionId>,
19 structs: LocationInterner<ItemLoc<ast::StructDef>, StructId>,
20 enums: LocationInterner<ItemLoc<ast::EnumDef>, EnumId>,
21 consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>,
22 statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>,
23 traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>,
24 types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeAliasId>,
25}
26
27impl HirInterner {
28 pub fn len(&self) -> usize {
29 self.macros.len()
30 + self.fns.len()
31 + self.structs.len()
32 + self.enums.len()
33 + self.consts.len()
34 + self.statics.len()
35 + self.traits.len()
36 + self.types.len()
37 }
38}
39
40/// hir makes heavy use of ids: integer (u32) handlers to various things. You 14/// hir makes heavy use of ids: integer (u32) handlers to various things. You
41/// can think of id as a pointer (but without a lifetime) or a file descriptor 15/// can think of id as a pointer (but without a lifetime) or a file descriptor
42/// (but for hir objects). 16/// (but for hir objects).
@@ -135,11 +109,24 @@ pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<A
135 Some(Arc::new(rules)) 109 Some(Arc::new(rules))
136} 110}
137 111
112macro_rules! impl_intern_key {
113 ($name:ident) => {
114 impl salsa::InternKey for $name {
115 fn from_intern_id(v: salsa::InternId) -> Self {
116 $name(v)
117 }
118 fn as_intern_id(&self) -> salsa::InternId {
119 self.0
120 }
121 }
122 };
123}
124
138/// `MacroCallId` identifies a particular macro invocation, like 125/// `MacroCallId` identifies a particular macro invocation, like
139/// `println!("Hello, {}", world)`. 126/// `println!("Hello, {}", world)`.
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
141pub struct MacroCallId(RawId); 128pub struct MacroCallId(salsa::InternId);
142impl_arena_id!(MacroCallId); 129impl_intern_key!(MacroCallId);
143 130
144#[derive(Debug, Clone, PartialEq, Eq, Hash)] 131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
145pub struct MacroCallLoc { 132pub struct MacroCallLoc {
@@ -148,14 +135,14 @@ pub struct MacroCallLoc {
148} 135}
149 136
150impl MacroCallId { 137impl MacroCallId {
151 pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> MacroCallLoc { 138 pub(crate) fn loc(self, db: &impl DefDatabase) -> MacroCallLoc {
152 db.as_ref().macros.id2loc(self) 139 db.lookup_intern_macro(self)
153 } 140 }
154} 141}
155 142
156impl MacroCallLoc { 143impl MacroCallLoc {
157 pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId { 144 pub(crate) fn id(self, db: &impl DefDatabase) -> MacroCallId {
158 db.as_ref().macros.loc2id(&self) 145 db.intern_macro(self)
159 } 146 }
160} 147}
161 148
@@ -204,8 +191,10 @@ impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
204 } 191 }
205} 192}
206 193
207pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { 194pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
208 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>; 195 fn intern(db: &impl DefDatabase, loc: ItemLoc<N>) -> Self;
196 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<N>;
197
209 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self { 198 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self {
210 let items = ctx.db.ast_id_map(ctx.file_id); 199 let items = ctx.db.ast_id_map(ctx.file_id);
211 let item_id = items.ast_id(ast); 200 let item_id = items.ast_id(ast);
@@ -213,80 +202,100 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
213 } 202 }
214 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self { 203 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
215 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) }; 204 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
216 Self::interner(ctx.db.as_ref()).loc2id(&loc) 205 Self::intern(ctx.db, loc)
217 } 206 }
218 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) { 207 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) {
219 let int = Self::interner(db.as_ref()); 208 let loc = self.lookup_intern(db);
220 let loc = int.id2loc(self);
221 let ast = loc.ast_id.to_node(db); 209 let ast = loc.ast_id.to_node(db);
222 (loc.ast_id.file_id(), ast) 210 (loc.ast_id.file_id(), ast)
223 } 211 }
224 fn module(self, db: &impl DefDatabase) -> Module { 212 fn module(self, db: &impl DefDatabase) -> Module {
225 let int = Self::interner(db.as_ref()); 213 let loc = self.lookup_intern(db);
226 let loc = int.id2loc(self);
227 loc.module 214 loc.module
228 } 215 }
229} 216}
230 217
231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 218#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
232pub(crate) struct FunctionId(RawId); 219pub struct FunctionId(salsa::InternId);
233impl_arena_id!(FunctionId); 220impl_intern_key!(FunctionId);
221
234impl AstItemDef<ast::FnDef> for FunctionId { 222impl AstItemDef<ast::FnDef> for FunctionId {
235 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> { 223 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::FnDef>) -> Self {
236 &interner.fns 224 db.intern_function(loc)
225 }
226 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::FnDef> {
227 db.lookup_intern_function(self)
237 } 228 }
238} 229}
239 230
240#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
241pub(crate) struct StructId(RawId); 232pub struct StructId(salsa::InternId);
242impl_arena_id!(StructId); 233impl_intern_key!(StructId);
243impl AstItemDef<ast::StructDef> for StructId { 234impl AstItemDef<ast::StructDef> for StructId {
244 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> { 235 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
245 &interner.structs 236 db.intern_struct(loc)
237 }
238 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StructDef> {
239 db.lookup_intern_struct(self)
246 } 240 }
247} 241}
248 242
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 243#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
250pub(crate) struct EnumId(RawId); 244pub struct EnumId(salsa::InternId);
251impl_arena_id!(EnumId); 245impl_intern_key!(EnumId);
252impl AstItemDef<ast::EnumDef> for EnumId { 246impl AstItemDef<ast::EnumDef> for EnumId {
253 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> { 247 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::EnumDef>) -> Self {
254 &interner.enums 248 db.intern_enum(loc)
249 }
250 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::EnumDef> {
251 db.lookup_intern_enum(self)
255 } 252 }
256} 253}
257 254
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 255#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
259pub(crate) struct ConstId(RawId); 256pub struct ConstId(salsa::InternId);
260impl_arena_id!(ConstId); 257impl_intern_key!(ConstId);
261impl AstItemDef<ast::ConstDef> for ConstId { 258impl AstItemDef<ast::ConstDef> for ConstId {
262 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> { 259 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::ConstDef>) -> Self {
263 &interner.consts 260 db.intern_const(loc)
261 }
262 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::ConstDef> {
263 db.lookup_intern_const(self)
264 } 264 }
265} 265}
266 266
267#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 267#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
268pub(crate) struct StaticId(RawId); 268pub struct StaticId(salsa::InternId);
269impl_arena_id!(StaticId); 269impl_intern_key!(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 intern(db: &impl DefDatabase, loc: ItemLoc<ast::StaticDef>) -> Self {
272 &interner.statics 272 db.intern_static(loc)
273 }
274 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StaticDef> {
275 db.lookup_intern_static(self)
273 } 276 }
274} 277}
275 278
276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 279#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
277pub(crate) struct TraitId(RawId); 280pub struct TraitId(salsa::InternId);
278impl_arena_id!(TraitId); 281impl_intern_key!(TraitId);
279impl AstItemDef<ast::TraitDef> for TraitId { 282impl AstItemDef<ast::TraitDef> for TraitId {
280 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> { 283 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TraitDef>) -> Self {
281 &interner.traits 284 db.intern_trait(loc)
285 }
286 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TraitDef> {
287 db.lookup_intern_trait(self)
282 } 288 }
283} 289}
284 290
285#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 291#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
286pub(crate) struct TypeAliasId(RawId); 292pub struct TypeAliasId(salsa::InternId);
287impl_arena_id!(TypeAliasId); 293impl_intern_key!(TypeAliasId);
288impl AstItemDef<ast::TypeAliasDef> for TypeAliasId { 294impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
289 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> { 295 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self {
290 &interner.types 296 db.intern_type_alias(loc)
297 }
298 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TypeAliasDef> {
299 db.lookup_intern_type_alias(self)
291 } 300 }
292} 301}
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 40d368cd9..a8a466e43 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -9,16 +9,15 @@ use ra_syntax::{
9 9
10use crate::{ 10use crate::{
11 Const, TypeAlias, Function, HirFileId, 11 Const, TypeAlias, Function, HirFileId,
12 HirDatabase, DefDatabase, 12 HirDatabase, DefDatabase, TraitRef,
13 ModuleDef, Trait, Resolution,
14 type_ref::TypeRef, 13 type_ref::TypeRef,
15 ids::LocationCtx, 14 ids::LocationCtx,
16 resolve::Resolver, 15 resolve::Resolver,
17 ty::Ty, generics::GenericParams, 16 ty::Ty,
17 generics::HasGenericParams,
18 code_model_api::{Module, ModuleSource}
18}; 19};
19 20
20use crate::code_model_api::{Module, ModuleSource};
21
22#[derive(Debug, Default, PartialEq, Eq)] 21#[derive(Debug, Default, PartialEq, Eq)]
23pub struct ImplSourceMap { 22pub struct ImplSourceMap {
24 map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>, 23 map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
@@ -73,7 +72,7 @@ impl ImplBlock {
73 self.module 72 self.module
74 } 73 }
75 74
76 pub fn target_trait_ref(&self, db: &impl DefDatabase) -> Option<TypeRef> { 75 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
77 db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() 76 db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned()
78 } 77 }
79 78
@@ -85,27 +84,16 @@ impl ImplBlock {
85 Ty::from_hir(db, &self.resolver(db), &self.target_type(db)) 84 Ty::from_hir(db, &self.resolver(db), &self.target_type(db))
86 } 85 }
87 86
88 pub fn target_trait(&self, db: &impl HirDatabase) -> Option<Trait> { 87 pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
89 if let Some(TypeRef::Path(path)) = self.target_trait_ref(db) { 88 let target_ty = self.target_ty(db);
90 let resolver = self.resolver(db); 89 TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty))
91 if let Some(Resolution::Def(ModuleDef::Trait(tr))) =
92 resolver.resolve_path(db, &path).take_types()
93 {
94 return Some(tr);
95 }
96 }
97 None
98 } 90 }
99 91
100 pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> { 92 pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> {
101 db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() 93 db.impls_in_module(self.module).impls[self.impl_id].items().to_vec()
102 } 94 }
103 95
104 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { 96 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
105 db.generic_params((*self).into())
106 }
107
108 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
109 let r = self.module().resolver(db); 97 let r = self.module().resolver(db);
110 // add generic params, if present 98 // add generic params, if present
111 let p = self.generic_params(db); 99 let p = self.generic_params(db);
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index c19450f39..9292de1b5 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -17,6 +17,8 @@ macro_rules! impl_froms {
17 } 17 }
18} 18}
19 19
20mod either;
21
20pub mod db; 22pub mod db;
21#[macro_use] 23#[macro_use]
22pub mod mock; 24pub mod mock;
@@ -49,20 +51,24 @@ use crate::{
49 db::{HirDatabase, DefDatabase}, 51 db::{HirDatabase, DefDatabase},
50 name::{AsName, KnownName}, 52 name::{AsName, KnownName},
51 source_id::{FileAstId, AstId}, 53 source_id::{FileAstId, AstId},
54 resolve::Resolver,
52}; 55};
53 56
54pub use self::{ 57pub use self::{
58 either::Either,
55 path::{Path, PathKind}, 59 path::{Path, PathKind},
56 name::Name, 60 name::Name,
57 source_id::{AstIdMap, ErasedFileAstId}, 61 source_id::{AstIdMap, ErasedFileAstId},
58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner}, 62 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc},
59 nameres::{PerNs, Namespace, ImportId, ImportSource}, 63 nameres::{PerNs, Namespace, ImportId},
60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, 64 ty::{Ty, ApplicationTy, TypeCtor, TraitRef, Substs, display::HirDisplay, CallableDef},
61 impl_block::{ImplBlock, ImplItem}, 65 impl_block::{ImplBlock, ImplItem},
62 docs::{Docs, Documentation}, 66 docs::{Docs, Documentation},
63 adt::AdtDef, 67 adt::AdtDef,
64 expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, 68 expr::ExprScopes,
65 resolve::{Resolver, Resolution}, 69 resolve::Resolution,
70 generics::{GenericParams, GenericParam, HasGenericParams},
71 source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax},
66}; 72};
67 73
68pub use self::code_model_api::{ 74pub use self::code_model_api::{
@@ -73,5 +79,5 @@ pub use self::code_model_api::{
73 Function, FnSignature, 79 Function, FnSignature,
74 StructField, FieldSource, 80 StructField, FieldSource,
75 Static, Const, ConstSignature, 81 Static, Const, ConstSignature,
76 Trait, TypeAlias, 82 Trait, TypeAlias, Container,
77}; 83};
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index aeab6b180..fa5882dea 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, diagnostics::DiagnosticSink}; 12use crate::{db, diagnostics::DiagnosticSink};
13 13
14pub const WORKSPACE: SourceRootId = SourceRootId(0); 14pub const WORKSPACE: SourceRootId = SourceRootId(0);
15 15
@@ -18,7 +18,6 @@ pub const WORKSPACE: SourceRootId = SourceRootId(0);
18pub struct MockDatabase { 18pub struct MockDatabase {
19 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, 19 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>,
20 runtime: salsa::Runtime<MockDatabase>, 20 runtime: salsa::Runtime<MockDatabase>,
21 interner: Arc<HirInterner>,
22 files: FxHashMap<String, FileId>, 21 files: FxHashMap<String, FileId>,
23} 22}
24 23
@@ -195,7 +194,6 @@ impl Default for MockDatabase {
195 let mut db = MockDatabase { 194 let mut db = MockDatabase {
196 events: Default::default(), 195 events: Default::default(),
197 runtime: salsa::Runtime::default(), 196 runtime: salsa::Runtime::default(),
198 interner: Default::default(),
199 files: FxHashMap::default(), 197 files: FxHashMap::default(),
200 }; 198 };
201 db.set_crate_graph(Default::default()); 199 db.set_crate_graph(Default::default());
@@ -208,19 +206,12 @@ impl salsa::ParallelDatabase for MockDatabase {
208 salsa::Snapshot::new(MockDatabase { 206 salsa::Snapshot::new(MockDatabase {
209 events: Default::default(), 207 events: Default::default(),
210 runtime: self.runtime.snapshot(self), 208 runtime: self.runtime.snapshot(self),
211 interner: Arc::clone(&self.interner),
212 // only the root database can be used to get file_id by path. 209 // only the root database can be used to get file_id by path.
213 files: FxHashMap::default(), 210 files: FxHashMap::default(),
214 }) 211 })
215 } 212 }
216} 213}
217 214
218impl AsRef<HirInterner> for MockDatabase {
219 fn as_ref(&self) -> &HirInterner {
220 &self.interner
221 }
222}
223
224impl MockDatabase { 215impl MockDatabase {
225 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> { 216 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
226 *self.events.lock() = Some(Vec::new()); 217 *self.events.lock() = Some(Vec::new());
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 4ae04514a..0eddfab12 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -75,7 +75,7 @@ pub(crate) use self::raw::{RawItems, ImportSourceMap};
75 75
76pub use self::{ 76pub use self::{
77 per_ns::{PerNs, Namespace}, 77 per_ns::{PerNs, Namespace},
78 raw::{ImportId, ImportSource}, 78 raw::ImportId,
79}; 79};
80 80
81/// Contans all top-level defs from a macro-expanded crate 81/// Contans all top-level defs from a macro-expanded crate
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index b7416ede6..43c97a0bf 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -12,7 +12,7 @@ use ra_syntax::{
12 12
13use crate::{ 13use crate::{
14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, 14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource,
15 AstIdMap, FileAstId, 15 AstIdMap, FileAstId, Either,
16}; 16};
17 17
18/// `RawItems` is a set of top-level items in a file (except for impls). 18/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -34,28 +34,15 @@ pub struct ImportSourceMap {
34 map: ArenaMap<ImportId, ImportSourcePtr>, 34 map: ArenaMap<ImportId, ImportSourcePtr>,
35} 35}
36 36
37#[derive(Debug, PartialEq, Eq, Clone, Copy)] 37type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
38enum ImportSourcePtr { 38type ImportSource = Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>>;
39 UseTree(AstPtr<ast::UseTree>),
40 ExternCrate(AstPtr<ast::ExternCrateItem>),
41}
42 39
43impl ImportSourcePtr { 40impl ImportSourcePtr {
44 fn to_node(self, file: &SourceFile) -> ImportSource { 41 fn to_node(self, file: &SourceFile) -> ImportSource {
45 match self { 42 self.map(|ptr| ptr.to_node(file).to_owned(), |ptr| ptr.to_node(file).to_owned())
46 ImportSourcePtr::UseTree(ptr) => ImportSource::UseTree(ptr.to_node(file).to_owned()),
47 ImportSourcePtr::ExternCrate(ptr) => {
48 ImportSource::ExternCrate(ptr.to_node(file).to_owned())
49 }
50 }
51 } 43 }
52} 44}
53 45
54pub enum ImportSource {
55 UseTree(TreeArc<ast::UseTree>),
56 ExternCrate(TreeArc<ast::ExternCrateItem>),
57}
58
59impl ImportSourceMap { 46impl ImportSourceMap {
60 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { 47 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
61 self.map.insert(import, ptr) 48 self.map.insert(import, ptr)
@@ -281,11 +268,7 @@ impl RawItemsCollector {
281 Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| { 268 Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
282 let import_data = 269 let import_data =
283 ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false }; 270 ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false };
284 self.push_import( 271 self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree)));
285 current_module,
286 import_data,
287 ImportSourcePtr::UseTree(AstPtr::new(use_tree)),
288 );
289 }) 272 })
290 } 273 }
291 274
@@ -304,11 +287,7 @@ impl RawItemsCollector {
304 is_prelude: false, 287 is_prelude: false,
305 is_extern_crate: true, 288 is_extern_crate: true,
306 }; 289 };
307 self.push_import( 290 self.push_import(current_module, import_data, Either::B(AstPtr::new(extern_crate)));
308 current_module,
309 import_data,
310 ImportSourcePtr::ExternCrate(AstPtr::new(extern_crate)),
311 );
312 } 291 }
313 } 292 }
314 293
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 2609585b1..685f4b8b1 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -9,13 +9,13 @@ use crate::{
9 name::{Name, KnownName}, 9 name::{Name, KnownName},
10 nameres::{PerNs, CrateDefMap, CrateModuleId}, 10 nameres::{PerNs, CrateDefMap, CrateModuleId},
11 generics::GenericParams, 11 generics::GenericParams,
12 expr::{scope::{ExprScopes, ScopeId}, PatId, Body}, 12 expr::{scope::{ExprScopes, ScopeId}, PatId},
13 impl_block::ImplBlock, 13 impl_block::ImplBlock,
14 path::Path, Trait 14 path::Path, Trait
15}; 15};
16 16
17#[derive(Debug, Clone, Default)] 17#[derive(Debug, Clone, Default)]
18pub struct Resolver { 18pub(crate) struct Resolver {
19 scopes: Vec<Scope>, 19 scopes: Vec<Scope>,
20} 20}
21 21
@@ -117,7 +117,7 @@ pub enum Resolution {
117} 117}
118 118
119impl Resolver { 119impl Resolver {
120 pub fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs<Resolution> { 120 pub(crate) fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs<Resolution> {
121 let mut resolution = PerNs::none(); 121 let mut resolution = PerNs::none();
122 for scope in self.scopes.iter().rev() { 122 for scope in self.scopes.iter().rev() {
123 resolution = resolution.or(scope.resolve_name(db, name)); 123 resolution = resolution.or(scope.resolve_name(db, name));
@@ -154,12 +154,12 @@ impl Resolver {
154 154
155 /// Returns the fully resolved path if we were able to resolve it. 155 /// Returns the fully resolved path if we were able to resolve it.
156 /// otherwise returns `PerNs::none` 156 /// otherwise returns `PerNs::none`
157 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> { 157 pub(crate) fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> {
158 // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise 158 // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise
159 self.resolve_path_segments(db, path).into_fully_resolved() 159 self.resolve_path_segments(db, path).into_fully_resolved()
160 } 160 }
161 161
162 pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<Resolution>> { 162 pub(crate) fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<Resolution>> {
163 let mut names = FxHashMap::default(); 163 let mut names = FxHashMap::default();
164 for scope in self.scopes.iter().rev() { 164 for scope in self.scopes.iter().rev() {
165 scope.collect_names(db, &mut |name, res| { 165 scope.collect_names(db, &mut |name, res| {
@@ -197,14 +197,6 @@ impl Resolver {
197 _ => None, 197 _ => None,
198 }) 198 })
199 } 199 }
200
201 /// The body from which any `LocalBinding` resolutions in this resolver come.
202 pub fn body(&self) -> Option<Arc<Body>> {
203 self.scopes.iter().rev().find_map(|scope| match scope {
204 Scope::ExprScope(expr_scope) => Some(expr_scope.expr_scopes.body()),
205 _ => None,
206 })
207 }
208} 200}
209 201
210impl Resolver { 202impl Resolver {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 182ed4c91..bd035ced9 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -5,16 +5,21 @@
5/// 5///
6/// So, this modules should not be used during hir construction, it exists 6/// So, this modules should not be used during hir construction, it exists
7/// purely for "IDE needs". 7/// purely for "IDE needs".
8use std::sync::Arc;
9
10use rustc_hash::{FxHashSet, FxHashMap};
8use ra_db::{FileId, FilePosition}; 11use ra_db::{FileId, FilePosition};
9use ra_syntax::{ 12use ra_syntax::{
10 SyntaxNode, 13 SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, TextRange,
11 ast::{self, AstNode, NameOwner}, 14 ast::{self, AstNode, NameOwner},
12 algo::{find_node_at_offset, find_token_at_offset}, 15 algo::find_node_at_offset,
16 SyntaxKind::*,
13}; 17};
14 18
15use crate::{ 19use crate::{
16 HirDatabase, Function, Struct, Enum,Const,Static, 20 HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name,
17 AsName, Module, HirFileId, Crate, Trait, Resolver, 21 AsName, Module, HirFileId, Crate, Trait, Resolver,
22 expr::{BodySourceMap, scope::{ScopeId, ExprScopes}},
18 ids::LocationCtx, 23 ids::LocationCtx,
19 expr, AstId 24 expr, AstId
20}; 25};
@@ -87,63 +92,6 @@ fn module_from_source(
87 ) 92 )
88} 93}
89 94
90pub fn const_from_source(
91 db: &impl HirDatabase,
92 file_id: FileId,
93 const_def: &ast::ConstDef,
94) -> Option<Const> {
95 let module = module_from_child_node(db, file_id, const_def.syntax())?;
96 let res = const_from_module(db, module, const_def);
97 Some(res)
98}
99
100pub fn const_from_module(
101 db: &impl HirDatabase,
102 module: Module,
103 const_def: &ast::ConstDef,
104) -> Const {
105 let (file_id, _) = module.definition_source(db);
106 let file_id = file_id.into();
107 let ctx = LocationCtx::new(db, module, file_id);
108 Const { id: ctx.to_def(const_def) }
109}
110
111pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
112 let file = db.parse(position.file_id);
113 let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
114 function_from_source(db, position.file_id, fn_def)
115}
116
117pub fn function_from_source(
118 db: &impl HirDatabase,
119 file_id: FileId,
120 fn_def: &ast::FnDef,
121) -> Option<Function> {
122 let module = module_from_child_node(db, file_id, fn_def.syntax())?;
123 let res = function_from_module(db, module, fn_def);
124 Some(res)
125}
126
127pub fn function_from_module(
128 db: &impl HirDatabase,
129 module: Module,
130 fn_def: &ast::FnDef,
131) -> Function {
132 let (file_id, _) = module.definition_source(db);
133 let file_id = file_id.into();
134 let ctx = LocationCtx::new(db, module, file_id);
135 Function { id: ctx.to_def(fn_def) }
136}
137
138pub fn function_from_child_node(
139 db: &impl HirDatabase,
140 file_id: FileId,
141 node: &SyntaxNode,
142) -> Option<Function> {
143 let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
144 function_from_source(db, file_id, fn_def)
145}
146
147pub fn struct_from_module( 95pub fn struct_from_module(
148 db: &impl HirDatabase, 96 db: &impl HirDatabase,
149 module: Module, 97 module: Module,
@@ -155,27 +103,6 @@ pub fn struct_from_module(
155 Struct { id: ctx.to_def(struct_def) } 103 Struct { id: ctx.to_def(struct_def) }
156} 104}
157 105
158pub fn static_from_source(
159 db: &impl HirDatabase,
160 file_id: FileId,
161 static_def: &ast::StaticDef,
162) -> Option<Static> {
163 let module = module_from_child_node(db, file_id, static_def.syntax())?;
164 let res = static_from_module(db, module, static_def);
165 Some(res)
166}
167
168pub fn static_from_module(
169 db: &impl HirDatabase,
170 module: Module,
171 static_def: &ast::StaticDef,
172) -> Static {
173 let (file_id, _) = module.definition_source(db);
174 let file_id = file_id.into();
175 let ctx = LocationCtx::new(db, module, file_id);
176 Static { id: ctx.to_def(static_def) }
177}
178
179pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { 106pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
180 let (file_id, _) = module.definition_source(db); 107 let (file_id, _) = module.definition_source(db);
181 let file_id = file_id.into(); 108 let file_id = file_id.into();
@@ -194,48 +121,6 @@ pub fn trait_from_module(
194 Trait { id: ctx.to_def(trait_def) } 121 Trait { id: ctx.to_def(trait_def) }
195} 122}
196 123
197pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver {
198 let file_id = position.file_id;
199 let file = db.parse(file_id);
200 find_token_at_offset(file.syntax(), position.offset)
201 .find_map(|token| {
202 token.parent().ancestors().find_map(|node| {
203 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
204 if let Some(func) = function_from_child_node(db, file_id, node) {
205 let scopes = func.scopes(db);
206 let scope = scopes.scope_for_offset(position.offset);
207 Some(expr::resolver_for_scope(func.body(db), db, scope))
208 } else {
209 // FIXME const/static/array length
210 None
211 }
212 } else {
213 try_get_resolver_for_node(db, file_id, node)
214 }
215 })
216 })
217 .unwrap_or_default()
218}
219
220pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver {
221 node.ancestors()
222 .find_map(|node| {
223 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
224 if let Some(func) = function_from_child_node(db, file_id, node) {
225 let scopes = func.scopes(db);
226 let scope = scopes.scope_for(&node);
227 Some(expr::resolver_for_scope(func.body(db), db, scope))
228 } else {
229 // FIXME const/static/array length
230 None
231 }
232 } else {
233 try_get_resolver_for_node(db, file_id, node)
234 }
235 })
236 .unwrap_or_default()
237}
238
239fn try_get_resolver_for_node( 124fn try_get_resolver_for_node(
240 db: &impl HirDatabase, 125 db: &impl HirDatabase,
241 file_id: FileId, 126 file_id: FileId,
@@ -251,10 +136,281 @@ fn try_get_resolver_for_node(
251 } else if let Some(e) = ast::EnumDef::cast(node) { 136 } else if let Some(e) = ast::EnumDef::cast(node) {
252 let module = module_from_child_node(db, file_id, e.syntax())?; 137 let module = module_from_child_node(db, file_id, e.syntax())?;
253 Some(enum_from_module(db, module, e).resolver(db)) 138 Some(enum_from_module(db, module, e).resolver(db))
254 } else if let Some(f) = ast::FnDef::cast(node) { 139 } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
255 function_from_source(db, file_id, f).map(|f| f.resolver(db)) 140 Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db))
256 } else { 141 } else {
257 // FIXME add missing cases 142 // FIXME add missing cases
258 None 143 None
259 } 144 }
260} 145}
146
147fn def_with_body_from_child_node(
148 db: &impl HirDatabase,
149 file_id: FileId,
150 node: &SyntaxNode,
151) -> Option<DefWithBody> {
152 let module = module_from_child_node(db, file_id, node)?;
153 let ctx = LocationCtx::new(db, module, file_id.into());
154 node.ancestors().find_map(|node| {
155 if let Some(def) = ast::FnDef::cast(node) {
156 return Some(Function { id: ctx.to_def(def) }.into());
157 }
158 if let Some(def) = ast::ConstDef::cast(node) {
159 return Some(Const { id: ctx.to_def(def) }.into());
160 }
161 if let Some(def) = ast::StaticDef::cast(node) {
162 return Some(Static { id: ctx.to_def(def) }.into());
163 }
164 None
165 })
166}
167
168/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
169/// original source files. It should not be used inside the HIR itself.
170#[derive(Debug)]
171pub struct SourceAnalyzer {
172 resolver: Resolver,
173 body_source_map: Option<Arc<BodySourceMap>>,
174 infer: Option<Arc<crate::ty::InferenceResult>>,
175 scopes: Option<Arc<crate::expr::ExprScopes>>,
176}
177
178#[derive(Debug, Clone, PartialEq, Eq)]
179pub enum PathResolution {
180 /// An item
181 Def(crate::ModuleDef),
182 /// A local binding (only value namespace)
183 LocalBinding(Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>),
184 /// A generic parameter
185 GenericParam(u32),
186 SelfType(crate::ImplBlock),
187 AssocItem(crate::ImplItem),
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub struct ScopeEntryWithSyntax {
192 pub(crate) name: Name,
193 pub(crate) ptr: Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>,
194}
195
196impl ScopeEntryWithSyntax {
197 pub fn name(&self) -> &Name {
198 &self.name
199 }
200
201 pub fn ptr(&self) -> Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>> {
202 self.ptr
203 }
204}
205
206#[derive(Debug)]
207pub struct ReferenceDescriptor {
208 pub range: TextRange,
209 pub name: String,
210}
211
212impl SourceAnalyzer {
213 pub fn new(
214 db: &impl HirDatabase,
215 file_id: FileId,
216 node: &SyntaxNode,
217 offset: Option<TextUnit>,
218 ) -> SourceAnalyzer {
219 let def_with_body = def_with_body_from_child_node(db, file_id, node);
220 if let Some(def) = def_with_body {
221 let source_map = def.body_source_map(db);
222 let scopes = db.expr_scopes(def);
223 let scope = match offset {
224 None => scope_for(&scopes, &source_map, &node),
225 Some(offset) => scope_for_offset(&scopes, &source_map, offset),
226 };
227 let resolver = expr::resolver_for_scope(def.body(db), db, scope);
228 SourceAnalyzer {
229 resolver,
230 body_source_map: Some(source_map),
231 infer: Some(def.infer(db)),
232 scopes: Some(scopes),
233 }
234 } else {
235 SourceAnalyzer {
236 resolver: node
237 .ancestors()
238 .find_map(|node| try_get_resolver_for_node(db, file_id, node))
239 .unwrap_or_default(),
240 body_source_map: None,
241 infer: None,
242 scopes: None,
243 }
244 }
245 }
246
247 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> {
248 let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?;
249 Some(self.infer.as_ref()?[expr_id].clone())
250 }
251
252 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> {
253 let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?;
254 Some(self.infer.as_ref()?[pat_id].clone())
255 }
256
257 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
258 let expr_id = self.body_source_map.as_ref()?.node_expr(call.into())?;
259 self.infer.as_ref()?.method_resolution(expr_id)
260 }
261
262 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
263 let expr_id = self.body_source_map.as_ref()?.node_expr(field.into())?;
264 self.infer.as_ref()?.field_resolution(expr_id)
265 }
266
267 pub fn resolve_hir_path(
268 &self,
269 db: &impl HirDatabase,
270 path: &crate::Path,
271 ) -> PerNs<crate::Resolution> {
272 self.resolver.resolve_path(db, path)
273 }
274
275 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
276 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
277 let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?;
278 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
279 return Some(PathResolution::AssocItem(assoc));
280 }
281 }
282 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
283 let pat_id = self.body_source_map.as_ref()?.node_pat(path_pat.into())?;
284 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
285 return Some(PathResolution::AssocItem(assoc));
286 }
287 }
288 let hir_path = crate::Path::from_ast(path)?;
289 let res = self.resolver.resolve_path(db, &hir_path);
290 let res = res.clone().take_types().or_else(|| res.take_values())?;
291 let res = match res {
292 crate::Resolution::Def(it) => PathResolution::Def(it),
293 crate::Resolution::LocalBinding(it) => {
294 PathResolution::LocalBinding(self.body_source_map.as_ref()?.pat_syntax(it)?)
295 }
296 crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it),
297 crate::Resolution::SelfType(it) => PathResolution::SelfType(it),
298 };
299 Some(res)
300 }
301
302 pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> {
303 let mut shadowed = FxHashSet::default();
304 let name = name_ref.as_name();
305 let source_map = self.body_source_map.as_ref()?;
306 let scopes = self.scopes.as_ref()?;
307 let scope = scope_for(scopes, source_map, name_ref.syntax());
308 let ret = scopes
309 .scope_chain(scope)
310 .flat_map(|scope| scopes.entries(scope).iter())
311 .filter(|entry| shadowed.insert(entry.name()))
312 .filter(|entry| entry.name() == &name)
313 .nth(0);
314 ret.and_then(|entry| {
315 Some(ScopeEntryWithSyntax {
316 name: entry.name().clone(),
317 ptr: source_map.pat_syntax(entry.pat())?,
318 })
319 })
320 }
321
322 pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<crate::Resolution>> {
323 self.resolver.all_names(db)
324 }
325
326 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
327 // FIXME: at least, this should work with any DefWithBody, but ideally
328 // this should be hir-based altogether
329 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
330 let ptr = Either::A(AstPtr::new(pat.into()));
331 fn_def
332 .syntax()
333 .descendants()
334 .filter_map(ast::NameRef::cast)
335 .filter(|name_ref| match self.resolve_local_name(*name_ref) {
336 None => false,
337 Some(entry) => entry.ptr() == ptr,
338 })
339 .map(|name_ref| ReferenceDescriptor {
340 name: name_ref.text().to_string(),
341 range: name_ref.syntax().range(),
342 })
343 .collect()
344 }
345
346 #[cfg(test)]
347 pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> {
348 self.body_source_map.clone().unwrap()
349 }
350
351 #[cfg(test)]
352 pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> {
353 self.infer.clone().unwrap()
354 }
355
356 #[cfg(test)]
357 pub(crate) fn scopes(&self) -> Arc<ExprScopes> {
358 self.scopes.clone().unwrap()
359 }
360}
361
362fn scope_for(
363 scopes: &ExprScopes,
364 source_map: &BodySourceMap,
365 node: &SyntaxNode,
366) -> Option<ScopeId> {
367 node.ancestors()
368 .map(SyntaxNodePtr::new)
369 .filter_map(|ptr| source_map.syntax_expr(ptr))
370 .find_map(|it| scopes.scope_for(it))
371}
372
373fn scope_for_offset(
374 scopes: &ExprScopes,
375 source_map: &BodySourceMap,
376 offset: TextUnit,
377) -> Option<ScopeId> {
378 scopes
379 .scope_by_expr()
380 .iter()
381 .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope)))
382 // find containing scope
383 .min_by_key(|(ptr, _scope)| {
384 (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len())
385 })
386 .map(|(ptr, scope)| adjust(scopes, source_map, ptr, offset).unwrap_or(*scope))
387}
388
389// XXX: during completion, cursor might be outside of any particular
390// expression. Try to figure out the correct scope...
391fn adjust(
392 scopes: &ExprScopes,
393 source_map: &BodySourceMap,
394 ptr: SyntaxNodePtr,
395 offset: TextUnit,
396) -> Option<ScopeId> {
397 let r = ptr.range();
398 let child_scopes = scopes
399 .scope_by_expr()
400 .iter()
401 .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope)))
402 .map(|(ptr, scope)| (ptr.range(), scope))
403 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r);
404
405 child_scopes
406 .max_by(|(r1, _), (r2, _)| {
407 if r2.is_subrange(&r1) {
408 std::cmp::Ordering::Greater
409 } else if r1.is_subrange(&r2) {
410 std::cmp::Ordering::Less
411 } else {
412 r1.start().cmp(&r2.start())
413 }
414 })
415 .map(|(_ptr, scope)| *scope)
416}
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
index 725bdd5cb..15f0977b7 100644
--- a/crates/ra_hir/src/traits.rs
+++ b/crates/ra_hir/src/traits.rs
@@ -1,10 +1,11 @@
1//! HIR for trait definitions. 1//! HIR for trait definitions.
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4use rustc_hash::FxHashMap;
4 5
5use ra_syntax::ast::{self, NameOwner}; 6use ra_syntax::ast::{self, NameOwner};
6 7
7use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationCtx, name::AsName}; 8use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationCtx, name::AsName, Module};
8 9
9#[derive(Debug, Clone, PartialEq, Eq)] 10#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct TraitData { 11pub struct TraitData {
@@ -49,4 +50,34 @@ pub enum TraitItem {
49 TypeAlias(TypeAlias), 50 TypeAlias(TypeAlias),
50 // Existential 51 // Existential
51} 52}
53// FIXME: not every function, ... is actually a trait item. maybe we should make
54// sure that you can only turn actual trait items into TraitItems. This would
55// require not implementing From, and instead having some checked way of
56// casting them.
52impl_froms!(TraitItem: Function, Const, TypeAlias); 57impl_froms!(TraitItem: Function, Const, TypeAlias);
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct TraitItemsIndex {
61 traits_by_def: FxHashMap<TraitItem, Trait>,
62}
63
64impl TraitItemsIndex {
65 pub(crate) fn trait_items_index(db: &impl DefDatabase, module: Module) -> TraitItemsIndex {
66 let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() };
67 for decl in module.declarations(db) {
68 match decl {
69 crate::ModuleDef::Trait(tr) => {
70 for item in tr.trait_data(db).items() {
71 index.traits_by_def.insert(*item, tr);
72