aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--ARCHITECTURE.md2
-rw-r--r--Cargo.lock186
-rw-r--r--Cargo.toml1
-rw-r--r--crates/ra_analysis/Cargo.toml3
-rw-r--r--crates/ra_analysis/src/completion/complete_dot.rs15
-rw-r--r--crates/ra_analysis/src/db.rs1
-rw-r--r--crates/ra_analysis/src/goto_defenition.rs73
-rw-r--r--crates/ra_analysis/src/imp.rs40
-rw-r--r--crates/ra_analysis/src/lib.rs13
-rw-r--r--crates/ra_analysis/src/mock_analysis.rs7
-rw-r--r--crates/ra_analysis/src/symbol_index.rs78
-rw-r--r--crates/ra_analysis/src/syntax_highlighting.rs10
-rw-r--r--crates/ra_analysis/tests/test/main.rs (renamed from crates/ra_analysis/tests/tests.rs)35
-rw-r--r--crates/ra_analysis/tests/test/runnables.rs (renamed from crates/ra_analysis/tests/runnables.rs)11
-rw-r--r--crates/ra_analysis/tests/test/type_of.rs (renamed from crates/ra_analysis/tests/type_of.rs)4
-rw-r--r--crates/ra_arena/Cargo.toml5
-rw-r--r--crates/ra_arena/src/lib.rs97
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_editor/src/assists.rs188
-rw-r--r--crates/ra_editor/src/assists/add_derive.rs84
-rw-r--r--crates/ra_editor/src/assists/add_impl.rs66
-rw-r--r--crates/ra_editor/src/assists/change_visibility.rs116
-rw-r--r--crates/ra_editor/src/assists/flip_comma.rs31
-rw-r--r--crates/ra_editor/src/assists/introduce_variable.rs144
-rw-r--r--crates/ra_editor/src/assists/split_import.rs44
-rw-r--r--crates/ra_editor/src/code_actions.rs415
-rw-r--r--crates/ra_editor/src/diagnostics.rs6
-rw-r--r--crates/ra_editor/src/lib.rs6
-rw-r--r--crates/ra_editor/src/structure.rs6
-rw-r--r--crates/ra_editor/src/typing.rs68
-rw-r--r--crates/ra_hir/Cargo.toml4
-rw-r--r--crates/ra_hir/src/arena.rs66
-rw-r--r--crates/ra_hir/src/db.rs6
-rw-r--r--crates/ra_hir/src/function.rs17
-rw-r--r--crates/ra_hir/src/function/scope.rs12
-rw-r--r--crates/ra_hir/src/ids.rs31
-rw-r--r--crates/ra_hir/src/impl_block.rs180
-rw-r--r--crates/ra_hir/src/krate.rs2
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_hir/src/macros.rs18
-rw-r--r--crates/ra_hir/src/mock.rs5
-rw-r--r--crates/ra_hir/src/module.rs32
-rw-r--r--crates/ra_hir/src/module/nameres.rs10
-rw-r--r--crates/ra_hir/src/name.rs5
-rw-r--r--crates/ra_hir/src/path.rs5
-rw-r--r--crates/ra_hir/src/source_binder.rs39
-rw-r--r--crates/ra_hir/src/ty.rs168
-rw-r--r--crates/ra_hir/src/ty/tests.rs19
-rw-r--r--crates/ra_hir/src/ty/tests/data/0007_self.txt6
-rw-r--r--crates/ra_lsp_server/src/conv.rs53
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs4
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs5
-rw-r--r--crates/ra_lsp_server/src/req.rs22
-rw-r--r--crates/ra_lsp_server/src/server_world.rs32
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/main.rs23
-rw-r--r--crates/ra_syntax/src/ast.rs70
-rw-r--r--crates/ra_syntax/src/ast/generated.rs166
-rw-r--r--crates/ra_syntax/src/grammar.ron28
-rw-r--r--crates/ra_syntax/src/grammar/items.rs4
-rw-r--r--crates/ra_syntax/src/grammar/items/traits.rs6
-rw-r--r--crates/ra_syntax/src/parser_api.rs21
-rw-r--r--crates/ra_syntax/src/parser_impl.rs71
-rw-r--r--crates/ra_syntax/src/parser_impl/event.rs53
-rw-r--r--crates/ra_syntax/src/parser_impl/input.rs27
-rw-r--r--crates/ra_syntax/src/reparsing.rs2
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs4
-rw-r--r--crates/ra_syntax/src/yellow/builder.rs4
-rw-r--r--crates/ra_syntax/src/yellow/syntax_text.rs24
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0018_incomplete_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0022_bad_exprs.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt4
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt12
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.rs (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_block_neg.txt (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.txt)2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.rs (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_block.txt (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.txt)2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0037_mod.rs5
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0037_mod.txt16
-rw-r--r--crates/ra_text_edit/src/text_edit.rs5
-rw-r--r--crates/ra_vfs/Cargo.toml1
-rw-r--r--crates/ra_vfs/src/arena.rs53
-rw-r--r--crates/ra_vfs/src/lib.rs34
-rw-r--r--editors/code/package-lock.json872
-rw-r--r--editors/code/package.json2
-rw-r--r--editors/code/src/commands/apply_source_change.ts46
94 files changed, 2595 insertions, 1486 deletions
diff --git a/.travis.yml b/.travis.yml
index 04bb3be37..86bce93d6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,7 @@ build: &rust_build
10 script: 10 script:
11 - cargo gen-tests --verify 11 - cargo gen-tests --verify
12 - cargo gen-syntax --verify 12 - cargo gen-syntax --verify
13 - cargo test --no-run # let's measure compile time separately
13 - cargo test 14 - cargo test
14 env: 15 env:
15 - RUSTFLAGS="-D warnings", CARGO_INCREMENTAL=0 16 - RUSTFLAGS="-D warnings", CARGO_INCREMENTAL=0
@@ -25,7 +26,7 @@ matrix:
25 - cd editors/code && npm ci && npm run travis 26 - cd editors/code && npm ci && npm run travis
26 27
27 - os: windows 28 - os: windows
28 if: branch = master 29 if: branch = master AND type = push
29 before_script: 30 before_script:
30 - dos2unix ./crates/ra_syntax/tests/data/parser/**/*.txt 31 - dos2unix ./crates/ra_syntax/tests/data/parser/**/*.txt
31 - dos2unix ./crates/ra_syntax/tests/data/parser/**/*.rs 32 - dos2unix ./crates/ra_syntax/tests/data/parser/**/*.rs
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index b326f9c71..277b29c12 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -87,7 +87,7 @@ fixes a bug in the grammar.
87 87
88### `crates/ra_db` 88### `crates/ra_db`
89 89
90We use [salsa][https://github.com/salsa-rs/salsa] crate for incremental and 90We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and
91on-demand computation. Roughly, you can think of salsa as a key-value store, but 91on-demand computation. Roughly, you can think of salsa as a key-value store, but
92it also can compute derived values using specified functions. The `ra_db` crate 92it also can compute derived values using specified functions. The `ra_db` crate
93provides a basic infrastructure for interacting with salsa. Crucially, it 93provides a basic infrastructure for interacting with salsa. Crucially, it
diff --git a/Cargo.lock b/Cargo.lock
index 5f82e92f4..dbadfc64e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,7 +32,7 @@ name = "atty"
32version = "0.2.11" 32version = "0.2.11"
33source = "registry+https://github.com/rust-lang/crates.io-index" 33source = "registry+https://github.com/rust-lang/crates.io-index"
34dependencies = [ 34dependencies = [
35 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 35 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
36 "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 36 "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
37 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 37 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
38] 38]
@@ -50,8 +50,8 @@ dependencies = [
50 "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 50 "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
51 "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", 51 "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
52 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 52 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
53 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 53 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
54 "rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 54 "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
55 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 55 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
56] 56]
57 57
@@ -61,7 +61,7 @@ version = "0.1.28"
61source = "registry+https://github.com/rust-lang/crates.io-index" 61source = "registry+https://github.com/rust-lang/crates.io-index"
62dependencies = [ 62dependencies = [
63 "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", 63 "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
64 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 64 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
65] 65]
66 66
67[[package]] 67[[package]]
@@ -170,8 +170,8 @@ version = "0.3.6"
170source = "registry+https://github.com/rust-lang/crates.io-index" 170source = "registry+https://github.com/rust-lang/crates.io-index"
171dependencies = [ 171dependencies = [
172 "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 172 "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
173 "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 173 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
174 "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 174 "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
175 "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 175 "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
176] 176]
177 177
@@ -270,16 +270,16 @@ dependencies = [
270 270
271[[package]] 271[[package]]
272name = "failure" 272name = "failure"
273version = "0.1.4" 273version = "0.1.5"
274source = "registry+https://github.com/rust-lang/crates.io-index" 274source = "registry+https://github.com/rust-lang/crates.io-index"
275dependencies = [ 275dependencies = [
276 "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", 276 "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
277 "failure_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 277 "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
278] 278]
279 279
280[[package]] 280[[package]]
281name = "failure_derive" 281name = "failure_derive"
282version = "0.1.4" 282version = "0.1.5"
283source = "registry+https://github.com/rust-lang/crates.io-index" 283source = "registry+https://github.com/rust-lang/crates.io-index"
284dependencies = [ 284dependencies = [
285 "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 285 "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -337,7 +337,7 @@ name = "gen_lsp_server"
337version = "0.1.0" 337version = "0.1.0"
338dependencies = [ 338dependencies = [
339 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 339 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
340 "failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 340 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
341 "languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)", 341 "languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)",
342 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 342 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
343 "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", 343 "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -371,11 +371,6 @@ version = "1.1.0"
371source = "registry+https://github.com/rust-lang/crates.io-index" 371source = "registry+https://github.com/rust-lang/crates.io-index"
372 372
373[[package]] 373[[package]]
374name = "id-arena"
375version = "2.0.0"
376source = "registry+https://github.com/rust-lang/crates.io-index"
377
378[[package]]
379name = "idna" 374name = "idna"
380version = "0.1.5" 375version = "0.1.5"
381source = "registry+https://github.com/rust-lang/crates.io-index" 376source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -439,7 +434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
439 434
440[[package]] 435[[package]]
441name = "libc" 436name = "libc"
442version = "0.2.45" 437version = "0.2.46"
443source = "registry+https://github.com/rust-lang/crates.io-index" 438source = "registry+https://github.com/rust-lang/crates.io-index"
444 439
445[[package]] 440[[package]]
@@ -475,7 +470,7 @@ version = "2.1.2"
475source = "registry+https://github.com/rust-lang/crates.io-index" 470source = "registry+https://github.com/rust-lang/crates.io-index"
476dependencies = [ 471dependencies = [
477 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 472 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
478 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 473 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
479 "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 474 "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
480] 475]
481 476
@@ -484,7 +479,7 @@ name = "memmap"
484version = "0.6.2" 479version = "0.6.2"
485source = "registry+https://github.com/rust-lang/crates.io-index" 480source = "registry+https://github.com/rust-lang/crates.io-index"
486dependencies = [ 481dependencies = [
487 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 482 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
488 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 483 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
489] 484]
490 485
@@ -527,7 +522,7 @@ name = "num_cpus"
527version = "1.9.0" 522version = "1.9.0"
528source = "registry+https://github.com/rust-lang/crates.io-index" 523source = "registry+https://github.com/rust-lang/crates.io-index"
529dependencies = [ 524dependencies = [
530 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 525 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
531] 526]
532 527
533[[package]] 528[[package]]
@@ -540,16 +535,7 @@ dependencies = [
540 535
541[[package]] 536[[package]]
542name = "parking_lot" 537name = "parking_lot"
543version = "0.6.4" 538version = "0.7.1"
544source = "registry+https://github.com/rust-lang/crates.io-index"
545dependencies = [
546 "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
547 "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
548]
549
550[[package]]
551name = "parking_lot"
552version = "0.7.0"
553source = "registry+https://github.com/rust-lang/crates.io-index" 539source = "registry+https://github.com/rust-lang/crates.io-index"
554dependencies = [ 540dependencies = [
555 "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 541 "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -558,23 +544,11 @@ dependencies = [
558 544
559[[package]] 545[[package]]
560name = "parking_lot_core" 546name = "parking_lot_core"
561version = "0.3.1"
562source = "registry+https://github.com/rust-lang/crates.io-index"
563dependencies = [
564 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
565 "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
566 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
567 "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
568 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
569]
570
571[[package]]
572name = "parking_lot_core"
573version = "0.4.0" 547version = "0.4.0"
574source = "registry+https://github.com/rust-lang/crates.io-index" 548source = "registry+https://github.com/rust-lang/crates.io-index"
575dependencies = [ 549dependencies = [
576 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 550 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
577 "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 551 "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
578 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 552 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
579 "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 553 "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
580 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 554 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -669,7 +643,7 @@ dependencies = [
669 "fst 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 643 "fst 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
670 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 644 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
671 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 645 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
672 "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 646 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
673 "ra_db 0.1.0", 647 "ra_db 0.1.0",
674 "ra_editor 0.1.0", 648 "ra_editor 0.1.0",
675 "ra_hir 0.1.0", 649 "ra_hir 0.1.0",
@@ -678,16 +652,21 @@ dependencies = [
678 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 652 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
679 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 653 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
680 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 654 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
681 "salsa 0.9.0 (git+https://github.com/matklad/salsa.git?branch=transitive-untracked)", 655 "salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
682 "test_utils 0.1.0", 656 "test_utils 0.1.0",
657 "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
683] 658]
684 659
685[[package]] 660[[package]]
661name = "ra_arena"
662version = "0.1.0"
663
664[[package]]
686name = "ra_cli" 665name = "ra_cli"
687version = "0.1.0" 666version = "0.1.0"
688dependencies = [ 667dependencies = [
689 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", 668 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
690 "failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 669 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
691 "join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 670 "join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
692 "ra_editor 0.1.0", 671 "ra_editor 0.1.0",
693 "ra_syntax 0.1.0", 672 "ra_syntax 0.1.0",
@@ -698,12 +677,12 @@ dependencies = [
698name = "ra_db" 677name = "ra_db"
699version = "0.1.0" 678version = "0.1.0"
700dependencies = [ 679dependencies = [
701 "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 680 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
702 "ra_editor 0.1.0", 681 "ra_editor 0.1.0",
703 "ra_syntax 0.1.0", 682 "ra_syntax 0.1.0",
704 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 683 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
705 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 684 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
706 "salsa 0.9.0 (git+https://github.com/matklad/salsa.git?branch=transitive-untracked)", 685 "salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
707 "test_utils 0.1.0", 686 "test_utils 0.1.0",
708] 687]
709 688
@@ -728,15 +707,15 @@ dependencies = [
728 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 707 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
729 "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 708 "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
730 "flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", 709 "flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
731 "id-arena 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
732 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 710 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
733 "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 711 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
712 "ra_arena 0.1.0",
734 "ra_db 0.1.0", 713 "ra_db 0.1.0",
735 "ra_editor 0.1.0", 714 "ra_editor 0.1.0",
736 "ra_syntax 0.1.0", 715 "ra_syntax 0.1.0",
737 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 716 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
738 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 717 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
739 "salsa 0.9.0 (git+https://github.com/matklad/salsa.git?branch=transitive-untracked)", 718 "salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
740 "test_utils 0.1.0", 719 "test_utils 0.1.0",
741] 720]
742 721
@@ -747,14 +726,14 @@ dependencies = [
747 "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 726 "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
748 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 727 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
749 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 728 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
750 "failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 729 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
751 "failure_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 730 "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
752 "flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", 731 "flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
753 "gen_lsp_server 0.1.0", 732 "gen_lsp_server 0.1.0",
754 "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 733 "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
755 "languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)", 734 "languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)",
756 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 735 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
757 "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 736 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
758 "ra_analysis 0.1.0", 737 "ra_analysis 0.1.0",
759 "ra_editor 0.1.0", 738 "ra_editor 0.1.0",
760 "ra_syntax 0.1.0", 739 "ra_syntax 0.1.0",
@@ -783,9 +762,9 @@ dependencies = [
783 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 762 "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
784 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 763 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
785 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 764 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
786 "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 765 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
787 "ra_text_edit 0.1.0", 766 "ra_text_edit 0.1.0",
788 "rowan 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 767 "rowan 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
789 "test_utils 0.1.0", 768 "test_utils 0.1.0",
790 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 769 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
791 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 770 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -807,6 +786,7 @@ version = "0.1.0"
807dependencies = [ 786dependencies = [
808 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 787 "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
809 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 788 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
789 "ra_arena 0.1.0",
810 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 790 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
811 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 791 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
812 "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 792 "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -821,36 +801,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
821dependencies = [ 801dependencies = [
822 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 802 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
823 "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 803 "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
824 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 804 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
825 "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 805 "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
826 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 806 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
827] 807]
828 808
829[[package]] 809[[package]]
830name = "rand" 810name = "rand"
831version = "0.6.1" 811version = "0.6.3"
832source = "registry+https://github.com/rust-lang/crates.io-index" 812source = "registry+https://github.com/rust-lang/crates.io-index"
833dependencies = [ 813dependencies = [
834 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 814 "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
835 "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 815 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
836 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 816 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
837 "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
838 "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 817 "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
839 "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 818 "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
840 "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 819 "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
820 "rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
841 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 821 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
842 "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 822 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
843 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
844 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 823 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
845] 824]
846 825
847[[package]] 826[[package]]
848name = "rand_chacha" 827name = "rand_chacha"
849version = "0.1.0" 828version = "0.1.1"
850source = "registry+https://github.com/rust-lang/crates.io-index" 829source = "registry+https://github.com/rust-lang/crates.io-index"
851dependencies = [ 830dependencies = [
831 "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
852 "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 832 "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
853 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
854] 833]
855 834
856[[package]] 835[[package]]
@@ -883,6 +862,18 @@ dependencies = [
883] 862]
884 863
885[[package]] 864[[package]]
865name = "rand_os"
866version = "0.1.0"
867source = "registry+https://github.com/rust-lang/crates.io-index"
868dependencies = [
869 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
870 "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
871 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
872 "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
873 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
874]
875
876[[package]]
886name = "rand_pcg" 877name = "rand_pcg"
887version = "0.1.1" 878version = "0.1.1"
888source = "registry+https://github.com/rust-lang/crates.io-index" 879source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -893,7 +884,7 @@ dependencies = [
893 884
894[[package]] 885[[package]]
895name = "rand_xorshift" 886name = "rand_xorshift"
896version = "0.1.0" 887version = "0.1.1"
897source = "registry+https://github.com/rust-lang/crates.io-index" 888source = "registry+https://github.com/rust-lang/crates.io-index"
898dependencies = [ 889dependencies = [
899 "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 890 "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -916,7 +907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
916dependencies = [ 907dependencies = [
917 "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 908 "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
918 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 909 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
919 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 910 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
920 "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 911 "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
921] 912]
922 913
@@ -978,17 +969,17 @@ dependencies = [
978 969
979[[package]] 970[[package]]
980name = "rowan" 971name = "rowan"
981version = "0.1.3" 972version = "0.1.4"
982source = "registry+https://github.com/rust-lang/crates.io-index" 973source = "registry+https://github.com/rust-lang/crates.io-index"
983dependencies = [ 974dependencies = [
984 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 975 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
985 "smol_str 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 976 "smol_str 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
986 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 977 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
987] 978]
988 979
989[[package]] 980[[package]]
990name = "rustc-demangle" 981name = "rustc-demangle"
991version = "0.1.11" 982version = "0.1.13"
992source = "registry+https://github.com/rust-lang/crates.io-index" 983source = "registry+https://github.com/rust-lang/crates.io-index"
993 984
994[[package]] 985[[package]]
@@ -1030,14 +1021,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1030 1021
1031[[package]] 1022[[package]]
1032name = "salsa" 1023name = "salsa"
1033version = "0.9.0" 1024version = "0.9.1"
1034source = "git+https://github.com/matklad/salsa.git?branch=transitive-untracked#a2198f1f8a1d09894b842035a1af6b0b4c133c93" 1025source = "registry+https://github.com/rust-lang/crates.io-index"
1035dependencies = [ 1026dependencies = [
1036 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 1027 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1037 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1028 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1038 "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1029 "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1039 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1030 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1040 "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1031 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1041 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1032 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1042 "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 1033 "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
1043] 1034]
@@ -1174,8 +1165,8 @@ version = "3.0.5"
1174source = "registry+https://github.com/rust-lang/crates.io-index" 1165source = "registry+https://github.com/rust-lang/crates.io-index"
1175dependencies = [ 1166dependencies = [
1176 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 1167 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
1177 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 1168 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
1178 "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 1169 "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
1179 "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", 1170 "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
1180 "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1171 "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1181 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1172 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1206,7 +1197,7 @@ name = "teraron"
1206version = "0.0.1" 1197version = "0.0.1"
1207source = "registry+https://github.com/rust-lang/crates.io-index" 1198source = "registry+https://github.com/rust-lang/crates.io-index"
1208dependencies = [ 1199dependencies = [
1209 "failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 1200 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1210 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1201 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1211 "ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1202 "ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1212 "tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)", 1203 "tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1217,7 +1208,7 @@ name = "termion"
1217version = "1.5.1" 1208version = "1.5.1"
1218source = "registry+https://github.com/rust-lang/crates.io-index" 1209source = "registry+https://github.com/rust-lang/crates.io-index"
1219dependencies = [ 1210dependencies = [
1220 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 1211 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
1221 "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", 1212 "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
1222 "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1213 "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1223] 1214]
@@ -1278,7 +1269,7 @@ name = "time"
1278version = "0.1.41" 1269version = "0.1.41"
1279source = "registry+https://github.com/rust-lang/crates.io-index" 1270source = "registry+https://github.com/rust-lang/crates.io-index"
1280dependencies = [ 1271dependencies = [
1281 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 1272 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
1282 "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", 1273 "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
1283 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1274 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
1284] 1275]
@@ -1288,7 +1279,7 @@ name = "tools"
1288version = "0.1.0" 1279version = "0.1.0"
1289dependencies = [ 1280dependencies = [
1290 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", 1281 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
1291 "failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 1282 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1292 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1283 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1293 "teraron 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1284 "teraron 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1294 "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 1285 "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1354,6 +1345,14 @@ dependencies = [
1354] 1345]
1355 1346
1356[[package]] 1347[[package]]
1348name = "unicase"
1349version = "2.2.0"
1350source = "registry+https://github.com/rust-lang/crates.io-index"
1351dependencies = [
1352 "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1353]
1354
1355[[package]]
1357name = "unicode-bidi" 1356name = "unicode-bidi"
1358version = "0.3.4" 1357version = "0.3.4"
1359source = "registry+https://github.com/rust-lang/crates.io-index" 1358source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1433,7 +1432,7 @@ name = "wait-timeout"
1433version = "0.1.5" 1432version = "0.1.5"
1434source = "registry+https://github.com/rust-lang/crates.io-index" 1433source = "registry+https://github.com/rust-lang/crates.io-index"
1435dependencies = [ 1434dependencies = [
1436 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", 1435 "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
1437] 1436]
1438 1437
1439[[package]] 1438[[package]]
@@ -1508,8 +1507,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1508"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" 1507"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
1509"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" 1508"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00"
1510"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" 1509"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
1511"checksum failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e945b93ec214c6e97b520ec6c5d80267fc97af327658ee5b9f35984626e51fbf" 1510"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
1512"checksum failure_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c395a14ab27b42704e85bf2435c5c51f334ad7a96e16fe23c6e63a1cad6cc12" 1511"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
1513"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 1512"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
1514"checksum flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4dda06444ccc8b0a6da19d939989b4a4e83f328710ada449eedaed48c8b903cd" 1513"checksum flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4dda06444ccc8b0a6da19d939989b4a4e83f328710ada449eedaed48c8b903cd"
1515"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 1514"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
@@ -1520,7 +1519,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1520"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" 1519"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
1521"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 1520"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
1522"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" 1521"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
1523"checksum id-arena 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a7250033feafee46a1cecd2c2616a64aec1d064f38c9ae2bdd297728542843e"
1524"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" 1522"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
1525"checksum im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9c7f9bb8aee47fc16d535a705f7867a9fc83bb822e5e1043bb98e77ffeed3c" 1523"checksum im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9c7f9bb8aee47fc16d535a705f7867a9fc83bb822e5e1043bb98e77ffeed3c"
1526"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" 1524"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
@@ -1529,7 +1527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1529"checksum join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7bddc885f3fd69dd4b5d747c2efe6dd2c36d795ea9938281ed50910e32c95e31" 1527"checksum join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7bddc885f3fd69dd4b5d747c2efe6dd2c36d795ea9938281ed50910e32c95e31"
1530"checksum languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7c01845f71b8b3b3557a8179af4434a4b2570829da12371f05272d28183a06ce" 1528"checksum languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7c01845f71b8b3b3557a8179af4434a4b2570829da12371f05272d28183a06ce"
1531"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" 1529"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
1532"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" 1530"checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd"
1533"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" 1531"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
1534"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" 1532"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
1535"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" 1533"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
@@ -1543,9 +1541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1543"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" 1541"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
1544"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" 1542"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238"
1545"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" 1543"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
1546"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" 1544"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
1547"checksum parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9723236a9525c757d9725b993511e3fc941e33f27751942232f0058298297edf"
1548"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c"
1549"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" 1545"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
1550"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" 1546"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
1551"checksum pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54f0c72a98d8ab3c99560bfd16df8059cc10e1f9a8e83e6e3b97718dd766e9c3" 1547"checksum pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54f0c72a98d8ab3c99560bfd16df8059cc10e1f9a8e83e6e3b97718dd766e9c3"
@@ -1557,14 +1553,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1557"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 1553"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
1558"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" 1554"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
1559"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" 1555"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
1560"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" 1556"checksum rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b65e163105a6284f841bd23100a015895f54340e88a5ffc9ca7b8b33827cfce0"
1561"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" 1557"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
1562"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" 1558"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
1563"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" 1559"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
1564"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 1560"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
1565"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 1561"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
1562"checksum rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de5ac4de1c2973e1391dc305cb0fbf8788cb58068e98255439b7485a77022273"
1566"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" 1563"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
1567"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" 1564"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
1568"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" 1565"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473"
1569"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" 1566"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"
1570"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" 1567"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2"
@@ -1574,14 +1571,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1574"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c" 1571"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c"
1575"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" 1572"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
1576"checksum ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48677d8a9247a4e0d1f3f9cb4b0a8e29167fdc3c04f383a5e669cd7a960ae0f" 1573"checksum ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48677d8a9247a4e0d1f3f9cb4b0a8e29167fdc3c04f383a5e669cd7a960ae0f"
1577"checksum rowan 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9ccca91953e9c549cac18e8f41daa5d49dad1c9a4c9bb977ac42718bb34e1bf" 1574"checksum rowan 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c218b4430ab922850b71b14fa9bca224425097f935f6155c0b6a4b1f398a54f0"
1578"checksum rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "01b90379b8664dd83460d59bdc5dd1fd3172b8913788db483ed1325171eab2f7" 1575"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
1579"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" 1576"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
1580"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1577"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1581"checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c" 1578"checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c"
1582"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" 1579"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
1583"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" 1580"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
1584"checksum salsa 0.9.0 (git+https://github.com/matklad/salsa.git?branch=transitive-untracked)" = "<none>" 1581"checksum salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "442ef4acdb48c0e24ddaf4f3b62555af2d1da7047f2f26acd54ae73010aa0c02"
1585"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" 1582"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
1586"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 1583"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
1587"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1584"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
@@ -1616,6 +1613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1616"checksum unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ca47cbb09fb5fcd066b5867d11dc528302fa465277882797d6a836e1ee6f9e" 1613"checksum unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ca47cbb09fb5fcd066b5867d11dc528302fa465277882797d6a836e1ee6f9e"
1617"checksum unic-ucd-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48f1a08ce0409a9e391b88d1930118eec48af12742fc538bcec55f775865776e" 1614"checksum unic-ucd-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48f1a08ce0409a9e391b88d1930118eec48af12742fc538bcec55f775865776e"
1618"checksum unic-ucd-version 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1f5e6c6c53c2d0ece4a5964bc55fcff8602153063cb4fab20958ff32998ff6" 1615"checksum unic-ucd-version 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1f5e6c6c53c2d0ece4a5964bc55fcff8602153063cb4fab20958ff32998ff6"
1616"checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90"
1619"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1617"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
1620"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" 1618"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
1621"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" 1619"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
diff --git a/Cargo.toml b/Cargo.toml
index dd8499c06..c5155e899 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,4 +6,3 @@ incremental = true
6debug = true 6debug = true
7 7
8[patch.'crates-io'] 8[patch.'crates-io']
9salsa = { git = "https://github.com/matklad/salsa.git", branch = "transitive-untracked" }
diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml
index c0174cdc5..11c78ced8 100644
--- a/crates/ra_analysis/Cargo.toml
+++ b/crates/ra_analysis/Cargo.toml
@@ -10,9 +10,10 @@ log = "0.4.5"
10relative-path = "0.4.0" 10relative-path = "0.4.0"
11rayon = "1.0.2" 11rayon = "1.0.2"
12fst = "0.3.1" 12fst = "0.3.1"
13salsa = "0.9.0" 13salsa = "0.9.1"
14rustc-hash = "1.0" 14rustc-hash = "1.0"
15parking_lot = "0.7.0" 15parking_lot = "0.7.0"
16unicase = "2.2.0"
16 17
17ra_syntax = { path = "../ra_syntax" } 18ra_syntax = { path = "../ra_syntax" }
18ra_editor = { path = "../ra_editor" } 19ra_editor = { path = "../ra_editor" }
diff --git a/crates/ra_analysis/src/completion/complete_dot.rs b/crates/ra_analysis/src/completion/complete_dot.rs
index f24835d17..031d8b98f 100644
--- a/crates/ra_analysis/src/completion/complete_dot.rs
+++ b/crates/ra_analysis/src/completion/complete_dot.rs
@@ -73,6 +73,21 @@ mod tests {
73 } 73 }
74 74
75 #[test] 75 #[test]
76 fn test_struct_field_completion_self() {
77 check_ref_completion(
78 r"
79 struct A { the_field: u32 }
80 impl A {
81 fn foo(self) {
82 self.<|>
83 }
84 }
85 ",
86 r#"the_field"#,
87 );
88 }
89
90 #[test]
76 fn test_no_struct_field_completion_for_method_call() { 91 fn test_no_struct_field_completion_for_method_call() {
77 check_ref_completion( 92 check_ref_completion(
78 r" 93 r"
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index d7740f0c4..5422a400b 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -105,6 +105,7 @@ salsa::database_storage! {
105 fn type_for_field() for hir::db::TypeForFieldQuery; 105 fn type_for_field() for hir::db::TypeForFieldQuery;
106 fn struct_data() for hir::db::StructDataQuery; 106 fn struct_data() for hir::db::StructDataQuery;
107 fn enum_data() for hir::db::EnumDataQuery; 107 fn enum_data() for hir::db::EnumDataQuery;
108 fn impls_in_module() for hir::db::ImplsInModuleQuery;
108 } 109 }
109 } 110 }
110} 111}
diff --git a/crates/ra_analysis/src/goto_defenition.rs b/crates/ra_analysis/src/goto_defenition.rs
new file mode 100644
index 000000000..607a25115
--- /dev/null
+++ b/crates/ra_analysis/src/goto_defenition.rs
@@ -0,0 +1,73 @@
1use ra_db::FileId;
2use ra_syntax::ast;
3
4use crate::db::RootDatabase;
5
6pub fn goto_defenition(db: &RootDatabase, position: FilePosition,
7) -> Cancelable<Option<Vec<NavigationTarget>>> {
8 let file = db.source_file(position.file_id);
9 let syntax = file.syntax();
10 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
11 return Ok(Some(reference_defenition(db, position.file_id, name_ref)));
12 }
13 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
14 return Ok(Some(name_defenition(db, position.file_idname)));
15 }
16 Ok(None)
17}
18
19fn reference_defenition(db: &RootDatabase, file_id: FileId, name_ref: ast::NameRef) -> Cancelable<Vec<Nav>> {
20 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
21 let mut rr = ReferenceResolution::new(name_ref.syntax().range());
22 if let Some(fn_descr) =
23 source_binder::function_from_child_node(self, position.file_id, name_ref.syntax())?
24 {
25 let scope = fn_descr.scopes(self);
26 // First try to resolve the symbol locally
27 if let Some(entry) = scope.resolve_local_name(name_ref) {
28 rr.resolves_to.push(NavigationTarget {
29 file_id: position.file_id,
30 name: entry.name().to_string().into(),
31 range: entry.ptr().range(),
32 kind: NAME,
33 ptr: None,
34 });
35 return Ok(Some(rr));
36 };
37 }
38 // If that fails try the index based approach.
39 rr.resolves_to.extend(
40 self.index_resolve(name_ref)?
41 .into_iter()
42 .map(NavigationTarget::from_symbol),
43 );
44 return Ok(Some(rr));
45 }
46 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
47 let mut rr = ReferenceResolution::new(name.syntax().range());
48 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
49 if module.has_semi() {
50 if let Some(child_module) =
51 source_binder::module_from_declaration(self, position.file_id, module)?
52 {
53 let file_id = child_module.file_id();
54 let name = match child_module.name() {
55 Some(name) => name.to_string().into(),
56 None => "".into(),
57 };
58 let symbol = NavigationTarget {
59 file_id,
60 name,
61 range: TextRange::offset_len(0.into(), 0.into()),
62 kind: MODULE,
63 ptr: None,
64 };
65 rr.resolves_to.push(symbol);
66 return Ok(Some(rr));
67 }
68 }
69 }
70 }
71 Ok(None)
72
73}
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index b812c3441..eae73c2c4 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -6,7 +6,7 @@ use hir::{
6 self, FnSignatureInfo, Problem, source_binder, 6 self, FnSignatureInfo, Problem, source_binder,
7}; 7};
8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; 8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase};
9use ra_editor::{self, find_node_at_offset, LocalEdit, Severity}; 9use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity};
10use ra_syntax::{ 10use ra_syntax::{
11 algo::{find_covering_node, visit::{visitor, Visitor}}, 11 algo::{find_covering_node, visit::{visitor, Visitor}},
12 ast::{self, ArgListOwner, Expr, FnDef, NameOwner}, 12 ast::{self, ArgListOwner, Expr, FnDef, NameOwner},
@@ -165,9 +165,11 @@ impl db::RootDatabase {
165 }; 165 };
166 } 166 }
167 // If that fails try the index based approach. 167 // If that fails try the index based approach.
168 for (file_id, symbol) in self.index_resolve(name_ref)? { 168 rr.resolves_to.extend(
169 rr.add_resolution(file_id, symbol); 169 self.index_resolve(name_ref)?
170 } 170 .into_iter()
171 .map(NavigationTarget::from_symbol),
172 );
171 return Ok(Some(rr)); 173 return Ok(Some(rr));
172 } 174 }
173 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { 175 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
@@ -333,19 +335,9 @@ impl db::RootDatabase {
333 335
334 pub(crate) fn assists(&self, frange: FileRange) -> Vec<SourceChange> { 336 pub(crate) fn assists(&self, frange: FileRange) -> Vec<SourceChange> {
335 let file = self.source_file(frange.file_id); 337 let file = self.source_file(frange.file_id);
336 let offset = frange.range.start(); 338 assists::assists(&file, frange.range)
337 let actions = vec![
338 ra_editor::flip_comma(&file, offset).map(|f| f()),
339 ra_editor::add_derive(&file, offset).map(|f| f()),
340 ra_editor::add_impl(&file, offset).map(|f| f()),
341 ra_editor::make_pub_crate(&file, offset).map(|f| f()),
342 ra_editor::introduce_variable(&file, frange.range).map(|f| f()),
343 ];
344 actions
345 .into_iter() 339 .into_iter()
346 .filter_map(|local_edit| { 340 .map(|local_edit| SourceChange::from_local_edit(frange.file_id, local_edit))
347 Some(SourceChange::from_local_edit(frange.file_id, local_edit?))
348 })
349 .collect() 341 .collect()
350 } 342 }
351 343
@@ -362,13 +354,15 @@ impl db::RootDatabase {
362 354
363 // Resolve the function's NameRef (NOTE: this isn't entirely accurate). 355 // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
364 let file_symbols = self.index_resolve(name_ref)?; 356 let file_symbols = self.index_resolve(name_ref)?;
365 for (fn_file_id, fs) in file_symbols { 357 for symbol in file_symbols {
366 if fs.ptr.kind() == FN_DEF { 358 if symbol.ptr.kind() == FN_DEF {
367 let fn_file = self.source_file(fn_file_id); 359 let fn_file = self.source_file(symbol.file_id);
368 let fn_def = fs.ptr.resolve(&fn_file); 360 let fn_def = symbol.ptr.resolve(&fn_file);
369 let fn_def = ast::FnDef::cast(fn_def.borrowed()).unwrap(); 361 let fn_def = ast::FnDef::cast(fn_def.borrowed()).unwrap();
370 let descr = ctry!(source_binder::function_from_source( 362 let descr = ctry!(source_binder::function_from_source(
371 self, fn_file_id, fn_def 363 self,
364 symbol.file_id,
365 fn_def
372 )?); 366 )?);
373 if let Some(descriptor) = descr.signature_info(self) { 367 if let Some(descriptor) = descr.signature_info(self) {
374 // If we have a calling expression let's find which argument we are on 368 // If we have a calling expression let's find which argument we are on
@@ -440,7 +434,7 @@ impl db::RootDatabase {
440 .map(|(file_id, text_range)| SourceFileEdit { 434 .map(|(file_id, text_range)| SourceFileEdit {
441 file_id: *file_id, 435 file_id: *file_id,
442 edit: { 436 edit: {
443 let mut builder = ra_text_edit::TextEditBuilder::new(); 437 let mut builder = ra_text_edit::TextEditBuilder::default();
444 builder.replace(*text_range, new_name.into()); 438 builder.replace(*text_range, new_name.into());
445 builder.finish() 439 builder.finish()
446 }, 440 },
@@ -448,7 +442,7 @@ impl db::RootDatabase {
448 .collect::<Vec<_>>(); 442 .collect::<Vec<_>>();
449 Ok(res) 443 Ok(res)
450 } 444 }
451 fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable<Vec<(FileId, FileSymbol)>> { 445 fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable<Vec<FileSymbol>> {
452 let name = name_ref.text(); 446 let name = name_ref.text();
453 let mut query = Query::new(name.to_string()); 447 let mut query = Query::new(name.to_string());
454 query.exact(); 448 query.exact();
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 61af676b2..1e26a2889 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -237,11 +237,11 @@ pub struct NavigationTarget {
237} 237}
238 238
239impl NavigationTarget { 239impl NavigationTarget {
240 fn from_symbol(file_id: FileId, symbol: FileSymbol) -> NavigationTarget { 240 fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
241 NavigationTarget { 241 NavigationTarget {
242 file_id: symbol.file_id,
242 name: symbol.name.clone(), 243 name: symbol.name.clone(),
243 kind: symbol.ptr.kind(), 244 kind: symbol.ptr.kind(),
244 file_id,
245 range: symbol.ptr.range(), 245 range: symbol.ptr.range(),
246 ptr: Some(symbol.ptr.clone()), 246 ptr: Some(symbol.ptr.clone()),
247 } 247 }
@@ -278,11 +278,6 @@ impl ReferenceResolution {
278 resolves_to: Vec::new(), 278 resolves_to: Vec::new(),
279 } 279 }
280 } 280 }
281
282 fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
283 self.resolves_to
284 .push(NavigationTarget::from_symbol(file_id, symbol))
285 }
286} 281}
287 282
288/// `AnalysisHost` stores the current state of the world. 283/// `AnalysisHost` stores the current state of the world.
@@ -380,7 +375,7 @@ impl Analysis {
380 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { 375 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
381 let res = symbol_index::world_symbols(&*self.db, query)? 376 let res = symbol_index::world_symbols(&*self.db, query)?
382 .into_iter() 377 .into_iter()
383 .map(|(file_id, symbol)| NavigationTarget::from_symbol(file_id, symbol)) 378 .map(NavigationTarget::from_symbol)
384 .collect(); 379 .collect();
385 Ok(res) 380 Ok(res)
386 } 381 }
@@ -399,7 +394,7 @@ impl Analysis {
399 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> { 394 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
400 self.db.doc_text_for(nav) 395 self.db.doc_text_for(nav)
401 } 396 }
402 /// Returns a `mod name;` declaration whihc created the current module. 397 /// Returns a `mod name;` declaration which created the current module.
403 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { 398 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
404 self.db.parent_module(position) 399 self.db.parent_module(position)
405 } 400 }
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs
index 960529404..846c76cfe 100644
--- a/crates/ra_analysis/src/mock_analysis.rs
+++ b/crates/ra_analysis/src/mock_analysis.rs
@@ -4,7 +4,7 @@ use relative_path::RelativePathBuf;
4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; 4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
5use ra_db::mock::FileMap; 5use ra_db::mock::FileMap;
6 6
7use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FilePosition, FileRange, SourceRootId}; 7use crate::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FilePosition, FileRange, SourceRootId};
8 8
9/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis 9/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
10/// from a set of in-memory files. 10/// from a set of in-memory files.
@@ -87,12 +87,17 @@ impl MockAnalysis {
87 let source_root = SourceRootId(0); 87 let source_root = SourceRootId(0);
88 let mut change = AnalysisChange::new(); 88 let mut change = AnalysisChange::new();
89 change.add_root(source_root, true); 89 change.add_root(source_root, true);
90 let mut crate_graph = CrateGraph::default();
90 for (path, contents) in self.files.into_iter() { 91 for (path, contents) in self.files.into_iter() {
91 assert!(path.starts_with('/')); 92 assert!(path.starts_with('/'));
92 let path = RelativePathBuf::from_path(&path[1..]).unwrap(); 93 let path = RelativePathBuf::from_path(&path[1..]).unwrap();
93 let file_id = file_map.add(path.clone()); 94 let file_id = file_map.add(path.clone());
95 if path == "/lib.rs" || path == "/main.rs" {
96 crate_graph.add_crate_root(file_id);
97 }
94 change.add_file(source_root, file_id, path, Arc::new(contents)); 98 change.add_file(source_root, file_id, path, Arc::new(contents));
95 } 99 }
100 change.set_crate_graph(crate_graph);
96 // change.set_file_resolver(Arc::new(file_map)); 101 // change.set_file_resolver(Arc::new(file_map));
97 host.apply_change(change); 102 host.apply_change(change);
98 host 103 host
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
index 10d8e8059..e2b1c88fe 100644
--- a/crates/ra_analysis/src/symbol_index.rs
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -20,6 +20,7 @@
20//! file in the current workspace, and run a query aginst the union of all 20//! file in the current workspace, and run a query aginst the union of all
21//! thouse fsts. 21//! thouse fsts.
22use std::{ 22use std::{
23 cmp::Ordering,
23 hash::{Hash, Hasher}, 24 hash::{Hash, Hasher},
24 sync::Arc, 25 sync::Arc,
25}; 26};
@@ -27,11 +28,11 @@ use std::{
27use fst::{self, Streamer}; 28use fst::{self, Streamer};
28use ra_syntax::{ 29use ra_syntax::{
29 SyntaxNodeRef, SourceFileNode, SmolStr, 30 SyntaxNodeRef, SourceFileNode, SmolStr,
30 algo::visit::{visitor, Visitor}, 31 algo::{visit::{visitor, Visitor}, find_covering_node},
31 SyntaxKind::{self, *}, 32 SyntaxKind::{self, *},
32 ast::{self, NameOwner}, 33 ast::{self, NameOwner},
33}; 34};
34use ra_db::{SyntaxDatabase, SourceRootId, FilesDatabase, LocalSyntaxPtr}; 35use ra_db::{SourceRootId, FilesDatabase, LocalSyntaxPtr};
35use salsa::ParallelDatabase; 36use salsa::ParallelDatabase;
36use rayon::prelude::*; 37use rayon::prelude::*;
37 38
@@ -41,7 +42,7 @@ use crate::{
41}; 42};
42 43
43salsa::query_group! { 44salsa::query_group! {
44 pub(crate) trait SymbolsDatabase: SyntaxDatabase { 45 pub(crate) trait SymbolsDatabase: hir::db::HirDatabase {
45 fn file_symbols(file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { 46 fn file_symbols(file_id: FileId) -> Cancelable<Arc<SymbolIndex>> {
46 type FileSymbolsQuery; 47 type FileSymbolsQuery;
47 } 48 }
@@ -52,16 +53,26 @@ salsa::query_group! {
52 } 53 }
53} 54}
54 55
55fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { 56fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> {
56 db.check_canceled()?; 57 db.check_canceled()?;
57 let syntax = db.source_file(file_id); 58 let source_file = db.source_file(file_id);
58 Ok(Arc::new(SymbolIndex::for_file(file_id, syntax))) 59 let mut symbols = source_file
60 .syntax()
61 .descendants()
62 .filter_map(to_symbol)
63 .map(move |(name, ptr)| FileSymbol { name, ptr, file_id })
64 .collect::<Vec<_>>();
65
66 for (name, text_range) in hir::source_binder::macro_symbols(db, file_id)? {
67 let node = find_covering_node(source_file.syntax(), text_range);
68 let ptr = LocalSyntaxPtr::new(node);
69 symbols.push(FileSymbol { file_id, name, ptr })
70 }
71
72 Ok(Arc::new(SymbolIndex::new(symbols)))
59} 73}
60 74
61pub(crate) fn world_symbols( 75pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Cancelable<Vec<FileSymbol>> {
62 db: &RootDatabase,
63 query: Query,
64) -> Cancelable<Vec<(FileId, FileSymbol)>> {
65 /// Need to wrap Snapshot to provide `Clone` impl for `map_with` 76 /// Need to wrap Snapshot to provide `Clone` impl for `map_with`
66 struct Snap(salsa::Snapshot<RootDatabase>); 77 struct Snap(salsa::Snapshot<RootDatabase>);
67 impl Clone for Snap { 78 impl Clone for Snap {
@@ -95,7 +106,7 @@ pub(crate) fn world_symbols(
95 106
96#[derive(Default, Debug)] 107#[derive(Default, Debug)]
97pub(crate) struct SymbolIndex { 108pub(crate) struct SymbolIndex {
98 symbols: Vec<(FileId, FileSymbol)>, 109 symbols: Vec<FileSymbol>,
99 map: fst::Map, 110 map: fst::Map,
100} 111}
101 112
@@ -114,6 +125,17 @@ impl Hash for SymbolIndex {
114} 125}
115 126
116impl SymbolIndex { 127impl SymbolIndex {
128 fn new(mut symbols: Vec<FileSymbol>) -> SymbolIndex {
129 fn cmp(s1: &FileSymbol, s2: &FileSymbol) -> Ordering {
130 unicase::Ascii::new(s1.name.as_str()).cmp(&unicase::Ascii::new(s2.name.as_str()))
131 }
132 symbols.par_sort_by(cmp);
133 symbols.dedup_by(|s1, s2| cmp(s1, s2) == Ordering::Equal);
134 let names = symbols.iter().map(|it| it.name.as_str().to_lowercase());
135 let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap();
136 SymbolIndex { symbols, map }
137 }
138
117 pub(crate) fn len(&self) -> usize { 139 pub(crate) fn len(&self) -> usize {
118 self.symbols.len() 140 self.symbols.len()
119 } 141 }
@@ -121,30 +143,21 @@ impl SymbolIndex {
121 pub(crate) fn for_files( 143 pub(crate) fn for_files(
122 files: impl ParallelIterator<Item = (FileId, SourceFileNode)>, 144 files: impl ParallelIterator<Item = (FileId, SourceFileNode)>,
123 ) -> SymbolIndex { 145 ) -> SymbolIndex {
124 let mut symbols = files 146 let symbols = files
125 .flat_map(|(file_id, file)| { 147 .flat_map(|(file_id, file)| {
126 file.syntax() 148 file.syntax()
127 .descendants() 149 .descendants()
128 .filter_map(to_symbol) 150 .filter_map(to_symbol)
129 .map(move |symbol| (symbol.name.as_str().to_lowercase(), (file_id, symbol))) 151 .map(move |(name, ptr)| FileSymbol { name, ptr, file_id })
130 .collect::<Vec<_>>() 152 .collect::<Vec<_>>()
131 }) 153 })
132 .collect::<Vec<_>>(); 154 .collect::<Vec<_>>();
133 symbols.par_sort_by(|s1, s2| s1.0.cmp(&s2.0)); 155 SymbolIndex::new(symbols)
134 symbols.dedup_by(|s1, s2| s1.0 == s2.0);
135 let (names, symbols): (Vec<String>, Vec<(FileId, FileSymbol)>) =
136 symbols.into_iter().unzip();
137 let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap();
138 SymbolIndex { symbols, map }
139 }
140
141 pub(crate) fn for_file(file_id: FileId, file: SourceFileNode) -> SymbolIndex {
142 SymbolIndex::for_files(rayon::iter::once((file_id, file)))
143 } 156 }
144} 157}
145 158
146impl Query { 159impl Query {
147 pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<(FileId, FileSymbol)> { 160 pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> {
148 let mut op = fst::map::OpBuilder::new(); 161 let mut op = fst::map::OpBuilder::new();
149 for file_symbols in indices.iter() { 162 for file_symbols in indices.iter() {
150 let automaton = fst::automaton::Subsequence::new(&self.lowercased); 163 let automaton = fst::automaton::Subsequence::new(&self.lowercased);
@@ -160,14 +173,14 @@ impl Query {
160 let file_symbols = &indices[indexed_value.index]; 173 let file_symbols = &indices[indexed_value.index];
161 let idx = indexed_value.value as usize; 174 let idx = indexed_value.value as usize;
162 175
163 let (file_id, symbol) = &file_symbols.symbols[idx]; 176 let symbol = &file_symbols.symbols[idx];
164 if self.only_types && !is_type(symbol.ptr.kind()) { 177 if self.only_types && !is_type(symbol.ptr.kind()) {
165 continue; 178 continue;
166 } 179 }
167 if self.exact && symbol.name != self.query { 180 if self.exact && symbol.name != self.query {
168 continue; 181 continue;
169 } 182 }
170 res.push((*file_id, symbol.clone())); 183 res.push(symbol.clone());
171 } 184 }
172 } 185 }
173 res 186 res
@@ -185,17 +198,16 @@ fn is_type(kind: SyntaxKind) -> bool {
185/// possible. 198/// possible.
186#[derive(Debug, Clone, PartialEq, Eq, Hash)] 199#[derive(Debug, Clone, PartialEq, Eq, Hash)]
187pub(crate) struct FileSymbol { 200pub(crate) struct FileSymbol {
201 pub(crate) file_id: FileId,
188 pub(crate) name: SmolStr, 202 pub(crate) name: SmolStr,
189 pub(crate) ptr: LocalSyntaxPtr, 203 pub(crate) ptr: LocalSyntaxPtr,
190} 204}
191 205
192fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { 206fn to_symbol(node: SyntaxNodeRef) -> Option<(SmolStr, LocalSyntaxPtr)> {
193 fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<FileSymbol> { 207 fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<(SmolStr, LocalSyntaxPtr)> {
194 let name = node.name()?; 208 let name = node.name()?.text();
195 Some(FileSymbol { 209 let ptr = LocalSyntaxPtr::new(node.syntax());
196 name: name.text(), 210 Some((name, ptr))
197 ptr: LocalSyntaxPtr::new(node.syntax()),
198 })
199 } 211 }
200 visitor() 212 visitor()
201 .visit(decl::<ast::FnDef>) 213 .visit(decl::<ast::FnDef>)
diff --git a/crates/ra_analysis/src/syntax_highlighting.rs b/crates/ra_analysis/src/syntax_highlighting.rs
index ccea4aee3..35e153ca0 100644
--- a/crates/ra_analysis/src/syntax_highlighting.rs
+++ b/crates/ra_analysis/src/syntax_highlighting.rs
@@ -43,6 +43,7 @@ mod tests {
43 " 43 "
44 fn main() { 44 fn main() {
45 ctry!({ let x = 92; x}); 45 ctry!({ let x = 92; x});
46 vec![{ let x = 92; x}];
46 } 47 }
47 ", 48 ",
48 ); 49 );
@@ -53,10 +54,17 @@ mod tests {
53 HighlightedRange { range: [41; 46), tag: "macro" }, 54 HighlightedRange { range: [41; 46), tag: "macro" },
54 HighlightedRange { range: [49; 52), tag: "keyword" }, 55 HighlightedRange { range: [49; 52), tag: "keyword" },
55 HighlightedRange { range: [57; 59), tag: "literal" }, 56 HighlightedRange { range: [57; 59), tag: "literal" },
57 HighlightedRange { range: [82; 86), tag: "macro" },
58 HighlightedRange { range: [89; 92), tag: "keyword" },
59 HighlightedRange { range: [97; 99), tag: "literal" },
56 HighlightedRange { range: [49; 52), tag: "keyword" }, 60 HighlightedRange { range: [49; 52), tag: "keyword" },
57 HighlightedRange { range: [53; 54), tag: "function" }, 61 HighlightedRange { range: [53; 54), tag: "function" },
58 HighlightedRange { range: [57; 59), tag: "literal" }, 62 HighlightedRange { range: [57; 59), tag: "literal" },
59 HighlightedRange { range: [61; 62), tag: "text" }]"#, 63 HighlightedRange { range: [61; 62), tag: "text" },
64 HighlightedRange { range: [89; 92), tag: "keyword" },
65 HighlightedRange { range: [93; 94), tag: "function" },
66 HighlightedRange { range: [97; 99), tag: "literal" },
67 HighlightedRange { range: [101; 102), tag: "text" }]"#,
60 &highlights, 68 &highlights,
61 ) 69 )
62 } 70 }
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/test/main.rs
index bcf29d29c..beeae1e19 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/test/main.rs
@@ -1,9 +1,12 @@
1mod runnables;
2mod type_of;
3
1use ra_syntax::TextRange; 4use ra_syntax::TextRange;
2use test_utils::{assert_eq_dbg, assert_eq_text}; 5use test_utils::{assert_eq_dbg, assert_eq_text};
3 6
4use ra_analysis::{ 7use ra_analysis::{
5 mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis}, 8 mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis},
6 AnalysisChange, CrateGraph, FileId, FnSignatureInfo, 9 AnalysisChange, CrateGraph, FileId, FnSignatureInfo, Query
7}; 10};
8 11
9fn get_signature(text: &str) -> (FnSignatureInfo, Option<usize>) { 12fn get_signature(text: &str) -> (FnSignatureInfo, Option<usize>) {
@@ -135,14 +138,14 @@ fn test_resolve_parent_module_for_inline() {
135fn test_resolve_crate_root() { 138fn test_resolve_crate_root() {
136 let mock = MockAnalysis::with_files( 139 let mock = MockAnalysis::with_files(
137 " 140 "
138 //- /lib.rs 141 //- /bar.rs
139 mod foo; 142 mod foo;
140 //- /foo.rs 143 //- /bar/foo.rs
141 // emtpy <|> 144 // emtpy <|>
142 ", 145 ",
143 ); 146 );
144 let root_file = mock.id_of("/lib.rs"); 147 let root_file = mock.id_of("/bar.rs");
145 let mod_file = mock.id_of("/foo.rs"); 148 let mod_file = mock.id_of("/bar/foo.rs");
146 let mut host = mock.analysis_host(); 149 let mut host = mock.analysis_host();
147 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); 150 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
148 151
@@ -246,7 +249,8 @@ fn bar() {
246fn test_fn_signature_with_docs_simple() { 249fn test_fn_signature_with_docs_simple() {
247 let (desc, param) = get_signature( 250 let (desc, param) = get_signature(
248 r#" 251 r#"
249// test 252/// test
253// non-doc-comment
250fn foo(j: u32) -> u32 { 254fn foo(j: u32) -> u32 {
251 j 255 j
252} 256}
@@ -528,10 +532,11 @@ fn test_rename_for_mut_param() {
528 }"#, 532 }"#,
529 ); 533 );
530} 534}
535
531fn test_rename(text: &str, new_name: &str, expected: &str) { 536fn test_rename(text: &str, new_name: &str, expected: &str) {
532 let (analysis, position) = single_file_with_position(text); 537 let (analysis, position) = single_file_with_position(text);
533 let edits = analysis.rename(position, new_name).unwrap(); 538 let edits = analysis.rename(position, new_name).unwrap();
534 let mut text_edit_bulder = ra_text_edit::TextEditBuilder::new(); 539 let mut text_edit_bulder = ra_text_edit::TextEditBuilder::default();
535 let mut file_id: Option<FileId> = None; 540 let mut file_id: Option<FileId> = None;
536 for edit in edits { 541 for edit in edits {
537 file_id = Some(edit.file_id); 542 file_id = Some(edit.file_id);
@@ -544,3 +549,19 @@ fn test_rename(text: &str, new_name: &str, expected: &str) {
544 .apply(&*analysis.file_text(file_id.unwrap())); 549 .apply(&*analysis.file_text(file_id.unwrap()));
545 assert_eq_text!(expected, &*result); 550 assert_eq_text!(expected, &*result);
546} 551}
552
553#[test]
554fn world_symbols_include_stuff_from_macros() {
555 let (analysis, _) = single_file(
556 "
557salsa::query_group! {
558pub trait HirDatabase: SyntaxDatabase {}
559}
560 ",
561 );
562
563 let mut symbols = analysis.symbol_search(Query::new("Hir".into())).unwrap();
564 let s = symbols.pop().unwrap();
565 assert_eq!(s.name(), "HirDatabase");
566 assert_eq!(s.range(), TextRange::from_to(33.into(), 44.into()));
567}
diff --git a/crates/ra_analysis/tests/runnables.rs b/crates/ra_analysis/tests/test/runnables.rs
index 9e5342c46..e6e0afbc3 100644
--- a/crates/ra_analysis/tests/runnables.rs
+++ b/crates/ra_analysis/tests/test/runnables.rs
@@ -1,15 +1,6 @@
1extern crate ra_analysis;
2extern crate ra_editor;
3extern crate ra_syntax;
4extern crate relative_path;
5extern crate rustc_hash;
6extern crate test_utils;
7
8use test_utils::assert_eq_dbg; 1use test_utils::assert_eq_dbg;
9 2
10use ra_analysis::{ 3use ra_analysis::mock_analysis::analysis_and_position;
11 mock_analysis::{analysis_and_position},
12};
13 4
14#[test] 5#[test]
15fn test_runnables() { 6fn test_runnables() {
diff --git a/crates/ra_analysis/tests/type_of.rs b/crates/ra_analysis/tests/test/type_of.rs
index 375f808bb..9d15b52a8 100644
--- a/crates/ra_analysis/tests/type_of.rs
+++ b/crates/ra_analysis/tests/test/type_of.rs
@@ -1,6 +1,4 @@
1use ra_analysis::{ 1use ra_analysis::mock_analysis::single_file_with_range;
2 mock_analysis::{single_file_with_range},
3};
4 2
5#[test] 3#[test]
6fn test_type_of_for_function() { 4fn test_type_of_for_function() {
diff --git a/crates/ra_arena/Cargo.toml b/crates/ra_arena/Cargo.toml
new file mode 100644
index 000000000..9594e2d0f
--- /dev/null
+++ b/crates/ra_arena/Cargo.toml
@@ -0,0 +1,5 @@
1[package]
2edition = "2018"
3name = "ra_arena"
4version = "0.1.0"
5authors = ["Aleksey Kladov <[email protected]>"]
diff --git a/crates/ra_arena/src/lib.rs b/crates/ra_arena/src/lib.rs
new file mode 100644
index 000000000..a5eeb4118
--- /dev/null
+++ b/crates/ra_arena/src/lib.rs
@@ -0,0 +1,97 @@
1//! Yet another index-based arena.
2
3use std::{
4 fmt,
5 marker::PhantomData,
6 ops::{Index, IndexMut},
7};
8
9#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct RawId(u32);
11
12impl From<RawId> for u32 {
13 fn from(raw: RawId) -> u32 {
14 raw.0
15 }
16}
17
18impl From<u32> for RawId {
19 fn from(id: u32) -> RawId {
20 RawId(id)
21 }
22}
23
24impl fmt::Debug for RawId {
25 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26 self.0.fmt(f)
27 }
28}
29
30impl fmt::Display for RawId {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 self.0.fmt(f)
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq)]
37pub struct Arena<ID: ArenaId, T> {
38 data: Vec<T>,
39 _ty: PhantomData<ID>,
40}
41
42#[macro_export]
43macro_rules! impl_arena_id {
44 ($name:ident) => {
45 impl $crate::ArenaId for $name {
46 fn from_raw(raw: $crate::RawId) -> Self {
47 $name(raw)
48 }
49 fn into_raw(self) -> $crate::RawId {
50 self.0
51 }
52 }
53 };
54}
55
56pub trait ArenaId {
57 fn from_raw(raw: RawId) -> Self;
58 fn into_raw(self) -> RawId;
59}
60
61impl<ID: ArenaId, T> Arena<ID, T> {
62 pub fn alloc(&mut self, value: T) -> ID {
63 let id = RawId(self.data.len() as u32);
64 self.data.push(value);
65 ID::from_raw(id)
66 }
67 pub fn iter<'a>(&'a self) -> impl Iterator<Item = (ID, &'a T)> {
68 self.data
69 .iter()
70 .enumerate()
71 .map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
72 }
73}
74
75impl<ID: ArenaId, T> Default for Arena<ID, T> {
76 fn default() -> Arena<ID, T> {
77 Arena {
78 data: Vec::new(),
79 _ty: PhantomData,
80 }
81 }
82}
83
84impl<ID: ArenaId, T> Index<ID> for Arena<ID, T> {
85 type Output = T;
86 fn index(&self, idx: ID) -> &T {
87 let idx = idx.into_raw().0 as usize;
88 &self.data[idx]
89 }
90}
91
92impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> {
93 fn index_mut(&mut self, idx: ID) -> &mut T {
94 let idx = idx.into_raw().0 as usize;
95 &mut self.data[idx]
96 }
97}
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index ecc56d953..c0e83a140 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -6,7 +6,7 @@ authors = ["Aleksey Kladov <[email protected]>"]
6 6
7[dependencies] 7[dependencies]
8relative-path = "0.4.0" 8relative-path = "0.4.0"
9salsa = "0.9.0" 9salsa = "0.9.1"
10rustc-hash = "1.0" 10rustc-hash = "1.0"
11parking_lot = "0.7.0" 11parking_lot = "0.7.0"
12ra_syntax = { path = "../ra_syntax" } 12ra_syntax = { path = "../ra_syntax" }
diff --git a/crates/ra_editor/src/assists.rs b/crates/ra_editor/src/assists.rs
new file mode 100644
index 000000000..57b78342a
--- /dev/null
+++ b/crates/ra_editor/src/assists.rs
@@ -0,0 +1,188 @@
1//! This modules contains various "assits": suggestions for source code edits
2//! which are likely to occur at a given cursor positon. For example, if the
3//! cursor is on the `,`, a possible assist is swapping the elments around the
4//! comma.
5
6mod flip_comma;
7mod add_derive;
8mod add_impl;
9mod introduce_variable;
10mod change_visibility;
11mod split_import;
12
13use ra_text_edit::{TextEdit, TextEditBuilder};
14use ra_syntax::{
15 Direction, SyntaxNodeRef, TextUnit, TextRange,SourceFileNode, AstNode,
16 algo::{find_leaf_at_offset, find_covering_node, LeafAtOffset},
17};
18
19use crate::find_node_at_offset;
20
21pub use self::{
22 flip_comma::flip_comma,
23 add_derive::add_derive,
24 add_impl::add_impl,
25 introduce_variable::introduce_variable,
26 change_visibility::change_visibility,
27 split_import::split_import,
28};
29
30/// Return all the assists applicable at the given position.
31pub fn assists(file: &SourceFileNode, range: TextRange) -> Vec<LocalEdit> {
32 let ctx = AssistCtx::new(file, range);
33 [
34 flip_comma,
35 add_derive,
36 add_impl,
37 introduce_variable,
38 change_visibility,
39 split_import,
40 ]
41 .iter()
42 .filter_map(|&assist| ctx.clone().apply(assist))
43 .collect()
44}
45
46#[derive(Debug)]
47pub struct LocalEdit {
48 pub label: String,
49 pub edit: TextEdit,
50 pub cursor_position: Option<TextUnit>,
51}
52
53fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> {
54 node.siblings(direction)
55 .skip(1)
56 .find(|node| !node.kind().is_trivia())
57}
58
59/// `AssistCtx` allows to apply an assist or check if it could be applied.
60///
61/// Assists use a somewhat overengeneered approach, given the current needs. The
62/// assists workflow consists of two phases. In the first phase, a user asks for
63/// the list of available assists. In the second phase, the user picks a
64/// particular assist and it gets applied.
65///
66/// There are two peculiarities here:
67///
68/// * first, we ideally avoid computing more things then neccessary to answer
69/// "is assist applicable" in the first phase.
70/// * second, when we are appling assist, we don't have a gurantee that there
71/// weren't any changes between the point when user asked for assists and when
72/// they applied a particular assist. So, when applying assist, we need to do
73/// all the checks from scratch.
74///
75/// To avoid repeating the same code twice for both "check" and "apply"
76/// functions, we use an approach remeniscent of that of Django's function based
77/// views dealing with forms. Each assist receives a runtime parameter,
78/// `should_compute_edit`. It first check if an edit is applicable (potentially
79/// computing info required to compute the actual edit). If it is applicable,
80/// and `should_compute_edit` is `true`, it then computes the actual edit.
81///
82/// So, to implement the original assists workflow, we can first apply each edit
83/// with `should_compute_edit = false`, and then applying the selected edit
84/// again, with `should_compute_edit = true` this time.
85///
86/// Note, however, that we don't actually use such two-phase logic at the
87/// moment, because the LSP API is pretty awkward in this place, and it's much
88/// easier to just compute the edit eagarly :-)
89#[derive(Debug, Clone)]
90pub struct AssistCtx<'a> {
91 source_file: &'a SourceFileNode,
92 range: TextRange,
93 should_compute_edit: bool,
94}
95
96#[derive(Debug)]
97pub enum Assist {
98 Applicable,
99 Edit(LocalEdit),
100}
101
102#[derive(Default)]
103struct AssistBuilder {
104 edit: TextEditBuilder,
105 cursor_position: Option<TextUnit>,
106}
107
108impl<'a> AssistCtx<'a> {
109 pub fn new(source_file: &'a SourceFileNode, range: TextRange) -> AssistCtx {
110 AssistCtx {
111 source_file,
112 range,
113 should_compute_edit: false,
114 }
115 }
116
117 pub fn apply(mut self, assist: fn(AssistCtx) -> Option<Assist>) -> Option<LocalEdit> {
118 self.should_compute_edit = true;
119 match assist(self) {
120 None => None,
121 Some(Assist::Edit(e)) => Some(e),
122 Some(Assist::Applicable) => unreachable!(),
123 }
124 }
125
126 pub fn check(mut self, assist: fn(AssistCtx) -> Option<Assist>) -> bool {
127 self.should_compute_edit = false;
128 match assist(self) {
129 None => false,
130 Some(Assist::Edit(_)) => unreachable!(),
131 Some(Assist::Applicable) => true,
132 }
133 }
134
135 fn build(self, label: impl Into<String>, f: impl FnOnce(&mut AssistBuilder)) -> Option<Assist> {
136 if !self.should_compute_edit {
137 return Some(Assist::Applicable);
138 }
139 let mut edit = AssistBuilder::default();
140 f(&mut edit);
141 Some(Assist::Edit(LocalEdit {
142 label: label.into(),
143 edit: edit.edit.finish(),
144 cursor_position: edit.cursor_position,
145 }))
146 }
147
148 pub(crate) fn leaf_at_offset(&self) -> LeafAtOffset<SyntaxNodeRef<'a>> {
149 find_leaf_at_offset(self.source_file.syntax(), self.range.start())
150 }
151 pub(crate) fn node_at_offset<N: AstNode<'a>>(&self) -> Option<N> {
152 find_node_at_offset(self.source_file.syntax(), self.range.start())
153 }
154 pub(crate) fn covering_node(&self) -> SyntaxNodeRef<'a> {
155 find_covering_node(self.source_file.syntax(), self.range)
156 }
157}
158
159impl AssistBuilder {
160 fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
161 self.edit.replace(range, replace_with.into())
162 }
163 #[allow(unused)]
164 fn delete(&mut self, range: TextRange) {
165 self.edit.delete(range)
166 }
167 fn insert(&mut self, offset: TextUnit, text: impl Into<String>) {
168 self.edit.insert(offset, text.into())
169 }
170 fn set_cursor(&mut self, offset: TextUnit) {
171 self.cursor_position = Some(offset)
172 }
173}
174
175#[cfg(test)]
176fn check_assist(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) {
177 crate::test_utils::check_action(before, after, |file, off| {
178 let range = TextRange::offset_len(off, 0.into());
179 AssistCtx::new(file, range).apply(assist)
180 })
181}
182
183#[cfg(test)]
184fn check_assist_range(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) {
185 crate::test_utils::check_action_range(before, after, |file, range| {
186 AssistCtx::new(file, range).apply(assist)
187 })
188}
diff --git a/crates/ra_editor/src/assists/add_derive.rs b/crates/ra_editor/src/assists/add_derive.rs
new file mode 100644
index 000000000..1e2cd4f30
--- /dev/null
+++ b/crates/ra_editor/src/assists/add_derive.rs
@@ -0,0 +1,84 @@
1use ra_syntax::{
2 ast::{self, AstNode, AttrsOwner},
3 SyntaxKind::{WHITESPACE, COMMENT},
4 TextUnit,
5};
6
7use crate::assists::{AssistCtx, Assist};
8
9pub fn add_derive(ctx: AssistCtx) -> Option<Assist> {
10 let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
11 let node_start = derive_insertion_offset(nominal)?;
12 ctx.build("add `#[derive]`", |edit| {
13 let derive_attr = nominal
14 .attrs()
15 .filter_map(|x| x.as_call())
16 .filter(|(name, _arg)| name == "derive")
17 .map(|(_name, arg)| arg)
18 .next();
19 let offset = match derive_attr {
20 None => {
21 edit.insert(node_start, "#[derive()]\n");
22 node_start + TextUnit::of_str("#[derive(")
23 }
24 Some(tt) => tt.syntax().range().end() - TextUnit::of_char(')'),
25 };
26 edit.set_cursor(offset)
27 })
28}
29
30// Insert `derive` after doc comments.
31fn derive_insertion_offset(nominal: ast::NominalDef) -> Option<TextUnit> {
32 let non_ws_child = nominal
33 .syntax()
34 .children()
35 .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
36 Some(non_ws_child.range().start())
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use crate::assists::check_assist;
43
44 #[test]
45 fn add_derive_new() {
46 check_assist(
47 add_derive,
48 "struct Foo { a: i32, <|>}",
49 "#[derive(<|>)]\nstruct Foo { a: i32, }",
50 );
51 check_assist(
52 add_derive,
53 "struct Foo { <|> a: i32, }",
54 "#[derive(<|>)]\nstruct Foo { a: i32, }",
55 );
56 }
57
58 #[test]
59 fn add_derive_existing() {
60 check_assist(
61 add_derive,
62 "#[derive(Clone)]\nstruct Foo { a: i32<|>, }",
63 "#[derive(Clone<|>)]\nstruct Foo { a: i32, }",
64 );
65 }
66
67 #[test]
68 fn add_derive_new_with_doc_comment() {
69 check_assist(
70 add_derive,
71 "
72/// `Foo` is a pretty important struct.
73/// It does stuff.
74struct Foo { a: i32<|>, }
75 ",
76 "
77/// `Foo` is a pretty important struct.
78/// It does stuff.
79#[derive(<|>)]
80struct Foo { a: i32, }
81 ",
82 );
83 }
84}
diff --git a/crates/ra_editor/src/assists/add_impl.rs b/crates/ra_editor/src/assists/add_impl.rs
new file mode 100644
index 000000000..9353e2717
--- /dev/null
+++ b/crates/ra_editor/src/assists/add_impl.rs
@@ -0,0 +1,66 @@
1use join_to_string::join;
2use ra_syntax::{
3 ast::{self, AstNode, NameOwner, TypeParamsOwner},
4 TextUnit,
5};
6
7use crate::assists::{AssistCtx, Assist};
8
9pub fn add_impl(ctx: AssistCtx) -> Option<Assist> {
10 let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
11 let name = nominal.name()?;
12 ctx.build("add impl", |edit| {
13 let type_params = nominal.type_param_list();
14 let start_offset = nominal.syntax().range().end();
15 let mut buf = String::new();
16 buf.push_str("\n\nimpl");
17 if let Some(type_params) = type_params {
18 type_params.syntax().text().push_to(&mut buf);
19 }
20 buf.push_str(" ");
21 buf.push_str(name.text().as_str());
22 if let Some(type_params) = type_params {
23 let lifetime_params = type_params
24 .lifetime_params()
25 .filter_map(|it| it.lifetime())
26 .map(|it| it.text());
27 let type_params = type_params
28 .type_params()
29 .filter_map(|it| it.name())
30 .map(|it| it.text());
31 join(lifetime_params.chain(type_params))
32 .surround_with("<", ">")
33 .to_buf(&mut buf);
34 }
35 buf.push_str(" {\n");
36 edit.set_cursor(start_offset + TextUnit::of_str(&buf));
37 buf.push_str("\n}");
38 edit.insert(start_offset, buf);
39 })
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::assists::check_assist;
46
47 #[test]
48 fn test_add_impl() {
49 check_assist(
50 add_impl,
51 "struct Foo {<|>}\n",
52 "struct Foo {}\n\nimpl Foo {\n<|>\n}\n",
53 );
54 check_assist(
55 add_impl,
56 "struct Foo<T: Clone> {<|>}",
57 "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n<|>\n}",
58 );
59 check_assist(
60 add_impl,
61 "struct Foo<'a, T: Foo<'a>> {<|>}",
62 "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n<|>\n}",
63 );
64 }
65
66}
diff --git a/crates/ra_editor/src/assists/change_visibility.rs b/crates/ra_editor/src/assists/change_visibility.rs
new file mode 100644
index 000000000..6c8466394
--- /dev/null
+++ b/crates/ra_editor/src/assists/change_visibility.rs
@@ -0,0 +1,116 @@
1use ra_syntax::{
2 AstNode,
3 ast::{self, VisibilityOwner, NameOwner},
4 SyntaxKind::{VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF, IDENT},
5};
6
7use crate::assists::{AssistCtx, Assist};
8
9pub fn change_visibility(ctx: AssistCtx) -> Option<Assist> {
10 if let Some(vis) = ctx.node_at_offset::<ast::Visibility>() {
11 return change_vis(ctx, vis);
12 }
13 add_vis(ctx)
14}
15
16fn add_vis(ctx: AssistCtx) -> Option<Assist> {
17 let item_keyword = ctx.leaf_at_offset().find(|leaf| match leaf.kind() {
18 FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true,
19 _ => false,
20 });
21
22 let offset = if let Some(keyword) = item_keyword {
23 let parent = keyword.parent()?;
24 let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF];
25 // Parent is not a definition, can't add visibility
26 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
27 return None;
28 }
29 // Already have visibility, do nothing
30 if parent.children().any(|child| child.kind() == VISIBILITY) {
31 return None;
32 }
33 parent.range().start()
34 } else {
35 let ident = ctx.leaf_at_offset().find(|leaf| leaf.kind() == IDENT)?;
36 let field = ident.ancestors().find_map(ast::NamedFieldDef::cast)?;
37 if field.name()?.syntax().range() != ident.range() && field.visibility().is_some() {
38 return None;
39 }
40 field.syntax().range().start()
41 };
42
43 ctx.build("make pub(crate)", |edit| {
44 edit.insert(offset, "pub(crate) ");
45 edit.set_cursor(offset);
46 })
47}
48
49fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option<Assist> {
50 if vis.syntax().text() != "pub" {
51 return None;
52 }
53 ctx.build("chage to pub(crate)", |edit| {
54 edit.replace(vis.syntax().range(), "pub(crate)");
55 edit.set_cursor(vis.syntax().range().start());
56 })
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use crate::assists::check_assist;
63
64 #[test]
65 fn change_visibility_adds_pub_crate_to_items() {
66 check_assist(
67 change_visibility,
68 "<|>fn foo() {}",
69 "<|>pub(crate) fn foo() {}",
70 );
71 check_assist(
72 change_visibility,
73 "f<|>n foo() {}",
74 "<|>pub(crate) fn foo() {}",
75 );
76 check_assist(
77 change_visibility,
78 "<|>struct Foo {}",
79 "<|>pub(crate) struct Foo {}",
80 );
81 check_assist(
82 change_visibility,
83 "<|>mod foo {}",
84 "<|>pub(crate) mod foo {}",
85 );
86 check_assist(
87 change_visibility,
88 "<|>trait Foo {}",
89 "<|>pub(crate) trait Foo {}",
90 );
91 check_assist(change_visibility, "m<|>od {}", "<|>pub(crate) mod {}");
92 check_assist(
93 change_visibility,
94 "unsafe f<|>n foo() {}",
95 "<|>pub(crate) unsafe fn foo() {}",
96 );
97 }
98
99 #[test]
100 fn change_visibility_works_with_struct_fields() {
101 check_assist(
102 change_visibility,
103 "struct S { <|>field: u32 }",
104 "struct S { <|>pub(crate) field: u32 }",
105 )
106 }
107
108 #[test]
109 fn change_visibility_pub_to_pub_crate() {
110 check_assist(
111 change_visibility,
112 "<|>pub fn foo() {}",
113 "<|>pub(crate) fn foo() {}",
114 )
115 }
116}
diff --git a/crates/ra_editor/src/assists/flip_comma.rs b/crates/ra_editor/src/assists/flip_comma.rs
new file mode 100644
index 000000000..a343413cc
--- /dev/null
+++ b/crates/ra_editor/src/assists/flip_comma.rs
@@ -0,0 +1,31 @@
1use ra_syntax::{
2 Direction,
3 SyntaxKind::COMMA,
4};
5
6use crate::assists::{non_trivia_sibling, AssistCtx, Assist};
7
8pub fn flip_comma(ctx: AssistCtx) -> Option<Assist> {
9 let comma = ctx.leaf_at_offset().find(|leaf| leaf.kind() == COMMA)?;
10 let prev = non_trivia_sibling(comma, Direction::Prev)?;
11 let next = non_trivia_sibling(comma, Direction::Next)?;
12 ctx.build("flip comma", |edit| {
13 edit.replace(prev.range(), next.text());
14 edit.replace(next.range(), prev.text());
15 })
16}
17
18#[cfg(test)]
19mod tests {
20 use super::*;
21 use crate::assists::check_assist;
22
23 #[test]
24 fn flip_comma_works_for_function_parameters() {
25 check_assist(
26 flip_comma,
27 "fn foo(x: i32,<|> y: Result<(), ()>) {}",
28 "fn foo(y: Result<(), ()>,<|> x: i32) {}",
29 )
30 }
31}
diff --git a/crates/ra_editor/src/assists/introduce_variable.rs b/crates/ra_editor/src/assists/introduce_variable.rs
new file mode 100644
index 000000000..782861023
--- /dev/null
+++ b/crates/ra_editor/src/assists/introduce_variable.rs
@@ -0,0 +1,144 @@
1use ra_syntax::{
2 ast::{self, AstNode},
3 SyntaxKind::WHITESPACE,
4 SyntaxNodeRef, TextUnit,
5};
6
7use crate::assists::{AssistCtx, Assist};
8
9pub fn introduce_variable<'a>(ctx: AssistCtx) -> Option<Assist> {
10 let node = ctx.covering_node();
11 let expr = node.ancestors().filter_map(ast::Expr::cast).next()?;
12
13 let anchor_stmt = anchor_stmt(expr)?;
14 let indent = anchor_stmt.prev_sibling()?;
15 if indent.kind() != WHITESPACE {
16 return None;
17 }
18 ctx.build("introduce variable", move |edit| {
19 let mut buf = String::new();
20
21 buf.push_str("let var_name = ");
22 expr.syntax().text().push_to(&mut buf);
23 let is_full_stmt = if let Some(expr_stmt) = ast::ExprStmt::cast(anchor_stmt) {
24 Some(expr.syntax()) == expr_stmt.expr().map(|e| e.syntax())
25 } else {
26 false
27 };
28 if is_full_stmt {
29 edit.replace(expr.syntax().range(), buf);
30 } else {
31 buf.push_str(";");
32 indent.text().push_to(&mut buf);
33 edit.replace(expr.syntax().range(), "var_name".to_string());
34 edit.insert(anchor_stmt.range().start(), buf);
35 }
36 edit.set_cursor(anchor_stmt.range().start() + TextUnit::of_str("let "));
37 })
38}
39
40/// Statement or last in the block expression, which will follow
41/// the freshly introduced var.
42fn anchor_stmt(expr: ast::Expr) -> Option<SyntaxNodeRef> {
43 expr.syntax().ancestors().find(|&node| {
44 if ast::Stmt::cast(node).is_some() {
45 return true;
46 }
47 if let Some(expr) = node
48 .parent()
49 .and_then(ast::Block::cast)
50 .and_then(|it| it.expr())
51 {
52 if expr.syntax() == node {
53 return true;
54 }
55 }
56 false
57 })
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use crate::assists::check_assist_range;
64
65 #[test]
66 fn test_introduce_var_simple() {
67 check_assist_range(
68 introduce_variable,
69 "
70fn foo() {
71 foo(<|>1 + 1<|>);
72}",
73 "
74fn foo() {
75 let <|>var_name = 1 + 1;
76 foo(var_name);
77}",
78 );
79 }
80
81 #[test]
82 fn test_introduce_var_expr_stmt() {
83 check_assist_range(
84 introduce_variable,
85 "
86fn foo() {
87 <|>1 + 1<|>;
88}",
89 "
90fn foo() {
91 let <|>var_name = 1 + 1;
92}",
93 );
94 }
95
96 #[test]
97 fn test_introduce_var_part_of_expr_stmt() {
98 check_assist_range(
99 introduce_variable,
100 "
101fn foo() {
102 <|>1<|> + 1;
103}",
104 "
105fn foo() {
106 let <|>var_name = 1;
107 var_name + 1;
108}",
109 );
110 }
111
112 #[test]
113 fn test_introduce_var_last_expr() {
114 check_assist_range(
115 introduce_variable,
116 "
117fn foo() {
118 bar(<|>1 + 1<|>)
119}",
120 "
121fn foo() {
122 let <|>var_name = 1 + 1;
123 bar(var_name)
124}",
125 );
126 }
127
128 #[test]
129 fn test_introduce_var_last_full_expr() {
130 check_assist_range(
131 introduce_variable,
132 "
133fn foo() {
134 <|>bar(1 + 1)<|>
135}",
136 "
137fn foo() {
138 let <|>var_name = bar(1 + 1);
139 var_name
140}",
141 );
142 }
143
144}
diff --git a/crates/ra_editor/src/assists/split_import.rs b/crates/ra_editor/src/assists/split_import.rs
new file mode 100644
index 000000000..75f9e8dfb
--- /dev/null
+++ b/crates/ra_editor/src/assists/split_import.rs
@@ -0,0 +1,44 @@
1use ra_syntax::{
2 TextUnit, AstNode, SyntaxKind::COLONCOLON,
3 ast,
4 algo::generate,
5};
6
7use crate::assists::{AssistCtx, Assist};
8
9pub fn split_import(ctx: AssistCtx) -> Option<Assist> {
10 let colon_colon = ctx
11 .leaf_at_offset()
12 .find(|leaf| leaf.kind() == COLONCOLON)?;
13 let path = colon_colon.parent().and_then(ast::Path::cast)?;
14 let top_path = generate(Some(path), |it| it.parent_path()).last()?;
15
16 let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast);
17 if use_tree.is_none() {
18 return None;
19 }
20
21 let l_curly = colon_colon.range().end();
22 let r_curly = top_path.syntax().range().end();
23
24 ctx.build("split import", |edit| {
25 edit.insert(l_curly, "{");
26 edit.insert(r_curly, "}");
27 edit.set_cursor(l_curly + TextUnit::of_str("{"));
28 })
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34 use crate::assists::check_assist;
35
36 #[test]
37 fn test_split_import() {
38 check_assist(
39 split_import,
40 "use crate::<|>db::RootDatabase;",
41 "use crate::{<|>db::RootDatabase};",
42 )
43 }
44}
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs
deleted file mode 100644
index 7615f37a6..000000000
--- a/crates/ra_editor/src/code_actions.rs
+++ /dev/null
@@ -1,415 +0,0 @@
1use join_to_string::join;
2
3use ra_syntax::{
4 algo::{find_covering_node, find_leaf_at_offset},
5 ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
6 Direction, SourceFileNode,
7 SyntaxKind::{COMMA, WHITESPACE, COMMENT, VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF},
8 SyntaxNodeRef, TextRange, TextUnit,
9};
10
11use crate::{find_node_at_offset, TextEdit, TextEditBuilder};
12
13#[derive(Debug)]
14pub struct LocalEdit {
15 pub label: String,
16 pub edit: TextEdit,
17 pub cursor_position: Option<TextUnit>,
18}
19
20pub fn flip_comma<'a>(
21 file: &'a SourceFileNode,
22 offset: TextUnit,
23) -> Option<impl FnOnce() -> LocalEdit + 'a> {
24 let syntax = file.syntax();
25
26 let comma = find_leaf_at_offset(syntax, offset).find(|leaf| leaf.kind() == COMMA)?;
27 let prev = non_trivia_sibling(comma, Direction::Prev)?;
28 let next = non_trivia_sibling(comma, Direction::Next)?;
29 Some(move || {
30 let mut edit = TextEditBuilder::new();
31 edit.replace(prev.range(), next.text().to_string());
32 edit.replace(next.range(), prev.text().to_string());
33 LocalEdit {
34 label: "flip comma".to_string(),
35 edit: edit.finish(),
36 cursor_position: None,
37 }
38 })
39}
40
41pub fn add_derive<'a>(
42 file: &'a SourceFileNode,
43 offset: TextUnit,
44) -> Option<impl FnOnce() -> LocalEdit + 'a> {
45 let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?;
46 let node_start = derive_insertion_offset(nominal)?;
47 return Some(move || {
48 let derive_attr = nominal
49 .attrs()
50 .filter_map(|x| x.as_call())
51 .filter(|(name, _arg)| name == "derive")
52 .map(|(_name, arg)| arg)
53 .next();
54 let mut edit = TextEditBuilder::new();
55 let offset = match derive_attr {
56 None => {
57 edit.insert(node_start, "#[derive()]\n".to_string());
58 node_start + TextUnit::of_str("#[derive(")
59 }
60 Some(tt) => tt.syntax().range().end() - TextUnit::of_char(')'),
61 };
62 LocalEdit {
63 label: "add `#[derive]`".to_string(),
64 edit: edit.finish(),
65 cursor_position: Some(offset),
66 }
67 });
68
69 // Insert `derive` after doc comments.
70 fn derive_insertion_offset(nominal: ast::NominalDef) -> Option<TextUnit> {
71 let non_ws_child = nominal
72 .syntax()
73 .children()
74 .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
75 Some(non_ws_child.range().start())
76 }
77}
78
79pub fn add_impl<'a>(
80 file: &'a SourceFileNode,
81 offset: TextUnit,
82) -> Option<impl FnOnce() -> LocalEdit + 'a> {
83 let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?;
84 let name = nominal.name()?;
85
86 Some(move || {
87 let type_params = nominal.type_param_list();
88 let mut edit = TextEditBuilder::new();
89 let start_offset = nominal.syntax().range().end();
90 let mut buf = String::new();
91 buf.push_str("\n\nimpl");
92 if let Some(type_params) = type_params {
93 type_params.syntax().text().push_to(&mut buf);
94 }
95 buf.push_str(" ");
96 buf.push_str(name.text().as_str());
97 if let Some(type_params) = type_params {
98 let lifetime_params = type_params
99 .lifetime_params()
100 .filter_map(|it| it.lifetime())
101 .map(|it| it.text());
102 let type_params = type_params
103 .type_params()
104 .filter_map(|it| it.name())
105 .map(|it| it.text());
106 join(lifetime_params.chain(type_params))
107 .surround_with("<", ">")
108 .to_buf(&mut buf);
109 }
110 buf.push_str(" {\n");
111 let offset = start_offset + TextUnit::of_str(&buf);
112 buf.push_str("\n}");
113 edit.insert(start_offset, buf);
114 LocalEdit {
115 label: "add impl".to_string(),
116 edit: edit.finish(),
117 cursor_position: Some(offset),
118 }
119 })
120}
121
122pub fn introduce_variable<'a>(
123 file: &'a SourceFileNode,
124 range: TextRange,
125) -> Option<impl FnOnce() -> LocalEdit + 'a> {
126 let node = find_covering_node(file.syntax(), range);
127 let expr = node.ancestors().filter_map(ast::Expr::cast).next()?;
128
129 let anchor_stmt = anchor_stmt(expr)?;
130 let indent = anchor_stmt.prev_sibling()?;
131 if indent.kind() != WHITESPACE {
132 return None;
133 }
134 return Some(move || {
135 let mut buf = String::new();
136 let mut edit = TextEditBuilder::new();
137
138 buf.push_str("let var_name = ");
139 expr.syntax().text().push_to(&mut buf);
140 let is_full_stmt = if let Some(expr_stmt) = ast::ExprStmt::cast(anchor_stmt) {
141 Some(expr.syntax()) == expr_stmt.expr().map(|e| e.syntax())
142 } else {
143 false
144 };
145 if is_full_stmt {
146 edit.replace(expr.syntax().range(), buf);
147 } else {
148 buf.push_str(";");
149 indent.text().push_to(&mut buf);
150 edit.replace(expr.syntax().range(), "var_name".to_string());
151 edit.insert(anchor_stmt.range().start(), buf);
152 }
153 let cursor_position = anchor_stmt.range().start() + TextUnit::of_str("let ");
154 LocalEdit {
155 label: "introduce variable".to_string(),
156 edit: edit.finish(),
157 cursor_position: Some(cursor_position),
158 }
159 });
160
161 /// Statement or last in the block expression, which will follow
162 /// the freshly introduced var.
163 fn anchor_stmt(expr: ast::Expr) -> Option<SyntaxNodeRef> {
164 expr.syntax().ancestors().find(|&node| {
165 if ast::Stmt::cast(node).is_some() {
166 return true;
167 }
168 if let Some(expr) = node
169 .parent()
170 .and_then(ast::Block::cast)
171 .and_then(|it| it.expr())
172 {
173 if expr.syntax() == node {
174 return true;
175 }
176 }
177 false
178 })
179 }
180}
181
182pub fn make_pub_crate<'a>(
183 file: &'a SourceFileNode,
184 offset: TextUnit,
185) -> Option<impl FnOnce() -> LocalEdit + 'a> {
186 let syntax = file.syntax();
187
188 let keyword = find_leaf_at_offset(syntax, offset).find(|leaf| match leaf.kind() {
189 FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true,
190 _ => false,
191 })?;
192 let parent = keyword.parent()?;
193 let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF];
194 let node_start = parent.range().start();
195 Some(move || {
196 let mut edit = TextEditBuilder::new();
197
198 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind())
199 || parent.children().any(|child| child.kind() == VISIBILITY)
200 {
201 return LocalEdit {
202 label: "make pub crate".to_string(),
203 edit: edit.finish(),
204 cursor_position: Some(offset),
205 };
206 }
207
208 edit.insert(node_start, "pub(crate) ".to_string());
209 LocalEdit {
210 label: "make pub crate".to_string(),
211 edit: edit.finish(),
212 cursor_position: Some(node_start),
213 }
214 })
215}
216
217fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> {
218 node.siblings(direction)
219 .skip(1)
220 .find(|node| !node.kind().is_trivia())
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226 use crate::test_utils::{check_action, check_action_range};
227
228 #[test]
229 fn test_swap_comma() {
230 check_action(
231 "fn foo(x: i32,<|> y: Result<(), ()>) {}",
232 "fn foo(y: Result<(), ()>,<|> x: i32) {}",
233 |file, off| flip_comma(file, off).map(|f| f()),
234 )
235 }
236
237 #[test]
238 fn add_derive_new() {
239 check_action(
240 "struct Foo { a: i32, <|>}",
241 "#[derive(<|>)]\nstruct Foo { a: i32, }",
242 |file, off| add_derive(file, off).map(|f| f()),
243 );
244 check_action(
245 "struct Foo { <|> a: i32, }",
246 "#[derive(<|>)]\nstruct Foo { a: i32, }",
247 |file, off| add_derive(file, off).map(|f| f()),
248 );
249 }
250
251 #[test]
252 fn add_derive_existing() {
253 check_action(
254 "#[derive(Clone)]\nstruct Foo { a: i32<|>, }",
255 "#[derive(Clone<|>)]\nstruct Foo { a: i32, }",
256 |file, off| add_derive(file, off).map(|f| f()),
257 );
258 }
259
260 #[test]
261 fn add_derive_new_with_doc_comment() {
262 check_action(
263 "
264/// `Foo` is a pretty important struct.
265/// It does stuff.
266struct Foo { a: i32<|>, }
267 ",
268 "
269/// `Foo` is a pretty important struct.
270/// It does stuff.
271#[derive(<|>)]
272struct Foo { a: i32, }
273 ",
274 |file, off| add_derive(file, off).map(|f| f()),
275 );
276 }
277
278 #[test]
279 fn test_add_impl() {
280 check_action(
281 "struct Foo {<|>}\n",
282 "struct Foo {}\n\nimpl Foo {\n<|>\n}\n",
283 |file, off| add_impl(file, off).map(|f| f()),
284 );
285 check_action(
286 "struct Foo<T: Clone> {<|>}",
287 "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n<|>\n}",
288 |file, off| add_impl(file, off).map(|f| f()),
289 );
290 check_action(
291 "struct Foo<'a, T: Foo<'a>> {<|>}",
292 "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n<|>\n}",
293 |file, off| add_impl(file, off).map(|f| f()),
294 );
295 }
296
297 #[test]
298 fn test_introduce_var_simple() {
299 check_action_range(
300 "
301fn foo() {
302 foo(<|>1 + 1<|>);
303}",
304 "
305fn foo() {
306 let <|>var_name = 1 + 1;
307 foo(var_name);
308}",
309 |file, range| introduce_variable(file, range).map(|f| f()),
310 );
311 }
312
313 #[test]
314 fn test_introduce_var_expr_stmt() {
315 check_action_range(
316 "
317fn foo() {
318 <|>1 + 1<|>;
319}",
320 "
321fn foo() {
322 let <|>var_name = 1 + 1;
323}",
324 |file, range| introduce_variable(file, range).map(|f| f()),
325 );
326 }
327
328 #[test]
329 fn test_introduce_var_part_of_expr_stmt() {
330 check_action_range(
331 "
332fn foo() {
333 <|>1<|> + 1;
334}",
335 "
336fn foo() {
337 let <|>var_name = 1;
338 var_name + 1;
339}",
340 |file, range| introduce_variable(file, range).map(|f| f()),
341 );
342 }
343
344 #[test]
345 fn test_introduce_var_last_expr() {
346 check_action_range(
347 "
348fn foo() {
349 bar(<|>1 + 1<|>)
350}",
351 "
352fn foo() {
353 let <|>var_name = 1 + 1;
354 bar(var_name)
355}",
356 |file, range| introduce_variable(file, range).map(|f| f()),
357 );
358 }
359
360 #[test]
361 fn test_introduce_var_last_full_expr() {
362 check_action_range(
363 "
364fn foo() {
365 <|>bar(1 + 1)<|>
366}",
367 "
368fn foo() {
369 let <|>var_name = bar(1 + 1);
370 var_name
371}",
372 |file, range| introduce_variable(file, range).map(|f| f()),
373 );
374 }
375
376 #[test]
377 fn test_make_pub_crate() {
378 check_action(
379 "<|>fn foo() {}",
380 "<|>pub(crate) fn foo() {}",
381 |file, off| make_pub_crate(file, off).map(|f| f()),
382 );
383 check_action(
384 "f<|>n foo() {}",
385 "<|>pub(crate) fn foo() {}",
386 |file, off| make_pub_crate(file, off).map(|f| f()),
387 );
388 check_action(
389 "<|>struct Foo {}",
390 "<|>pub(crate) struct Foo {}",
391 |file, off| make_pub_crate(file, off).map(|f| f()),
392 );
393 check_action("<|>mod foo {}", "<|>pub(crate) mod foo {}", |file, off| {
394 make_pub_crate(file, off).map(|f| f())
395 });
396 check_action(
397 "<|>trait Foo {}",
398 "<|>pub(crate) trait Foo {}",
399 |file, off| make_pub_crate(file, off).map(|f| f()),
400 );
401 check_action("m<|>od {}", "<|>pub(crate) mod {}", |file, off| {
402 make_pub_crate(file, off).map(|f| f())
403 });
404 check_action(
405 "pub(crate) f<|>n foo() {}",
406 "pub(crate) f<|>n foo() {}",
407 |file, off| make_pub_crate(file, off).map(|f| f()),
408 );
409 check_action(
410 "unsafe f<|>n foo() {}",
411 "<|>pub(crate) unsafe fn foo() {}",
412 |file, off| make_pub_crate(file, off).map(|f| f()),
413 );
414 }
415}
diff --git a/crates/ra_editor/src/diagnostics.rs b/crates/ra_editor/src/diagnostics.rs
index 1b336cfe2..199b0e502 100644
--- a/crates/ra_editor/src/diagnostics.rs
+++ b/crates/ra_editor/src/diagnostics.rs
@@ -57,7 +57,7 @@ fn check_unnecessary_braces_in_use_statement(
57 text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(single_use_tree) 57 text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(single_use_tree)
58 .unwrap_or_else(|| { 58 .unwrap_or_else(|| {
59 let to_replace = single_use_tree.syntax().text().to_string(); 59 let to_replace = single_use_tree.syntax().text().to_string();
60 let mut edit_builder = TextEditBuilder::new(); 60 let mut edit_builder = TextEditBuilder::default();
61 edit_builder.delete(range); 61 edit_builder.delete(range);
62 edit_builder.insert(range.start(), to_replace); 62 edit_builder.insert(range.start(), to_replace);
63 edit_builder.finish() 63 edit_builder.finish()
@@ -93,7 +93,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
93 let start = use_tree_list_node.prev_sibling()?.range().start(); 93 let start = use_tree_list_node.prev_sibling()?.range().start();
94 let end = use_tree_list_node.range().end(); 94 let end = use_tree_list_node.range().end();
95 let range = TextRange::from_to(start, end); 95 let range = TextRange::from_to(start, end);
96 let mut edit_builder = TextEditBuilder::new(); 96 let mut edit_builder = TextEditBuilder::default();
97 edit_builder.delete(range); 97 edit_builder.delete(range);
98 return Some(edit_builder.finish()); 98 return Some(edit_builder.finish());
99 } 99 }
@@ -111,7 +111,7 @@ fn check_struct_shorthand_initialization(
111 let field_name = name_ref.syntax().text().to_string(); 111 let field_name = name_ref.syntax().text().to_string();
112 let field_expr = expr.syntax().text().to_string(); 112 let field_expr = expr.syntax().text().to_string();
113 if field_name == field_expr { 113 if field_name == field_expr {
114 let mut edit_builder = TextEditBuilder::new(); 114 let mut edit_builder = TextEditBuilder::default();
115 edit_builder.delete(named_field.syntax().range()); 115 edit_builder.delete(named_field.syntax().range());
116 edit_builder.insert(named_field.syntax().range().start(), field_name); 116 edit_builder.insert(named_field.syntax().range().start(), field_name);
117 let edit = edit_builder.finish(); 117 let edit = edit_builder.finish();
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index bfc745e58..ac283e2e0 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -1,4 +1,4 @@
1mod code_actions; 1pub mod assists;
2mod extend_selection; 2mod extend_selection;
3mod folding_ranges; 3mod folding_ranges;
4mod line_index; 4mod line_index;
@@ -10,7 +10,7 @@ mod typing;
10mod diagnostics; 10mod diagnostics;
11 11
12pub use self::{ 12pub use self::{
13 code_actions::{add_derive, add_impl, flip_comma, introduce_variable, make_pub_crate, LocalEdit}, 13 assists::LocalEdit,
14 extend_selection::extend_selection, 14 extend_selection::extend_selection,
15 folding_ranges::{folding_ranges, Fold, FoldKind}, 15 folding_ranges::{folding_ranges, Fold, FoldKind},
16 line_index::{LineCol, LineIndex}, 16 line_index::{LineCol, LineIndex},
@@ -19,7 +19,7 @@ pub use self::{
19 typing::{join_lines, on_enter, on_eq_typed}, 19 typing::{join_lines, on_enter, on_eq_typed},
20 diagnostics::diagnostics 20 diagnostics::diagnostics
21}; 21};
22use ra_text_edit::{TextEdit, TextEditBuilder}; 22use ra_text_edit::TextEditBuilder;
23use ra_syntax::{ 23use ra_syntax::{
24 algo::find_leaf_at_offset, 24 algo::find_leaf_at_offset,
25 ast::{self, AstNode}, 25 ast::{self, AstNode},
diff --git a/crates/ra_editor/src/structure.rs b/crates/ra_editor/src/structure.rs
index 2292b1ddf..32d59e335 100644
--- a/crates/ra_editor/src/structure.rs
+++ b/crates/ra_editor/src/structure.rs
@@ -60,7 +60,7 @@ fn structure_node(node: SyntaxNodeRef) -> Option<StructureNode> {
60 .visit(decl::<ast::TypeDef>) 60 .visit(decl::<ast::TypeDef>)
61 .visit(decl::<ast::ConstDef>) 61 .visit(decl::<ast::ConstDef>)
62 .visit(decl::<ast::StaticDef>) 62 .visit(decl::<ast::StaticDef>)
63 .visit(|im: ast::ImplItem| { 63 .visit(|im: ast::ImplBlock| {
64 let target_type = im.target_type()?; 64 let target_type = im.target_type()?;
65 let target_trait = im.target_trait(); 65 let target_trait = im.target_trait();
66 let label = match target_trait { 66 let label = match target_trait {
@@ -121,8 +121,8 @@ impl fmt::Debug for E {}
121 StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF }, 121 StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF },
122 StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF }, 122 StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF },
123 StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF }, 123 StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF },
124 StructureNode { parent: None, label: "impl E", navigation_range: [134; 135), node_range: [129; 138), kind: IMPL_ITEM }, 124 StructureNode { parent: None, label: "impl E", navigation_range: [134; 135), node_range: [129; 138), kind: IMPL_BLOCK },
125 StructureNode { parent: None, label: "impl fmt::Debug for E", navigation_range: [160; 161), node_range: [140; 164), kind: IMPL_ITEM }]"#, 125 StructureNode { parent: None, label: "impl fmt::Debug for E", navigation_range: [160; 161), node_range: [140; 164), kind: IMPL_BLOCK }]"#,
126 &structure, 126 &structure,
127 ) 127 )
128 } 128 }
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 21d068a7b..1b568e96c 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -21,7 +21,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
21 None => { 21 None => {
22 return LocalEdit { 22 return LocalEdit {
23 label: "join lines".to_string(), 23 label: "join lines".to_string(),
24 edit: TextEditBuilder::new().finish(), 24 edit: TextEditBuilder::default().finish(),
25 cursor_position: None, 25 cursor_position: None,
26 }; 26 };
27 } 27 }
@@ -33,7 +33,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
33 }; 33 };
34 34
35 let node = find_covering_node(file.syntax(), range); 35 let node = find_covering_node(file.syntax(), range);
36 let mut edit = TextEditBuilder::new(); 36 let mut edit = TextEditBuilder::default();
37 for node in node.descendants() { 37 for node in node.descendants() {
38 let text = match node.leaf_text() { 38 let text = match node.leaf_text() {
39 Some(text) => text, 39 Some(text) => text,
@@ -76,7 +76,7 @@ pub fn on_enter(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> {
76 let indent = node_indent(file, comment.syntax())?; 76 let indent = node_indent(file, comment.syntax())?;
77 let inserted = format!("\n{}{} ", indent, prefix); 77 let inserted = format!("\n{}{} ", indent, prefix);
78 let cursor_position = offset + TextUnit::of_str(&inserted); 78 let cursor_position = offset + TextUnit::of_str(&inserted);
79 let mut edit = TextEditBuilder::new(); 79 let mut edit = TextEditBuilder::default();
80 edit.insert(offset, inserted); 80 edit.insert(offset, inserted);
81 Some(LocalEdit { 81 Some(LocalEdit {
82 label: "on enter".to_string(), 82 label: "on enter".to_string(),
@@ -127,7 +127,7 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit>
127 return None; 127 return None;
128 } 128 }
129 let offset = let_stmt.syntax().range().end(); 129 let offset = let_stmt.syntax().range().end();
130 let mut edit = TextEditBuilder::new(); 130 let mut edit = TextEditBuilder::default();
131 edit.insert(offset, ";".to_string()); 131 edit.insert(offset, ";".to_string());
132 Some(LocalEdit { 132 Some(LocalEdit {
133 label: "add semicolon".to_string(), 133 label: "add semicolon".to_string(),
@@ -188,10 +188,14 @@ fn remove_newline(
188 edit.delete(TextRange::from_to(prev.range().start(), node.range().end())); 188 edit.delete(TextRange::from_to(prev.range().start(), node.range().end()));
189 } else if prev.kind() == COMMA && next.kind() == R_CURLY { 189 } else if prev.kind() == COMMA && next.kind() == R_CURLY {
190 // Removes: comma, newline (incl. surrounding whitespace) 190 // Removes: comma, newline (incl. surrounding whitespace)
191 // Adds: a single whitespace 191 let space = if let Some(left) = prev.prev_sibling() {
192 compute_ws(left, next)
193 } else {
194 " "
195 };
192 edit.replace( 196 edit.replace(
193 TextRange::from_to(prev.range().start(), node.range().end()), 197 TextRange::from_to(prev.range().start(), node.range().end()),
194 " ".to_string(), 198 space.to_string(),
195 ); 199 );
196 } else if let (Some(_), Some(next)) = (ast::Comment::cast(prev), ast::Comment::cast(next)) { 200 } else if let (Some(_), Some(next)) = (ast::Comment::cast(prev), ast::Comment::cast(next)) {
197 // Removes: newline (incl. surrounding whitespace), start of the next comment 201 // Removes: newline (incl. surrounding whitespace), start of the next comment
@@ -256,10 +260,20 @@ fn join_single_use_tree(edit: &mut TextEditBuilder, node: SyntaxNodeRef) -> Opti
256fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str { 260fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str {
257 match left.kind() { 261 match left.kind() {
258 L_PAREN | L_BRACK => return "", 262 L_PAREN | L_BRACK => return "",
263 L_CURLY => {
264 if let USE_TREE = right.kind() {
265 return "";
266 }
267 }
259 _ => (), 268 _ => (),
260 } 269 }
261 match right.kind() { 270 match right.kind() {
262 R_PAREN | R_BRACK => return "", 271 R_PAREN | R_BRACK => return "",
272 R_CURLY => {
273 if let USE_TREE = left.kind() {
274 return "";
275 }
276 }
263 DOT => return "", 277 DOT => return "",
264 _ => (), 278 _ => (),
265 } 279 }
@@ -331,6 +345,48 @@ fn foo() {
331 } 345 }
332 346
333 #[test] 347 #[test]
348 fn test_join_lines_use_items_left() {
349 // No space after the '{'
350 check_join_lines(
351 r"
352<|>use ra_syntax::{
353 TextUnit, TextRange,
354};",
355 r"
356<|>use ra_syntax::{TextUnit, TextRange,
357};",
358 );
359 }
360
361 #[test]
362 fn test_join_lines_use_items_right() {
363 // No space after the '}'
364 check_join_lines(
365 r"
366use ra_syntax::{
367<|> TextUnit, TextRange
368};",
369 r"
370use ra_syntax::{
371<|> TextUnit, TextRange};",
372 );
373 }
374
375 #[test]
376 fn test_join_lines_use_items_right_comma() {
377 // No space after the '}'
378 check_join_lines(
379 r"
380use ra_syntax::{
381<|> TextUnit, TextRange,
382};",
383 r"
384use ra_syntax::{
385<|> TextUnit, TextRange};",
386 );
387 }
388
389 #[test]
334 fn test_join_lines_use_tree() { 390 fn test_join_lines_use_tree() {
335 check_join_lines( 391 check_join_lines(
336 r" 392 r"
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index c3fbd327d..245a21ce3 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -8,12 +8,12 @@ authors = ["Aleksey Kladov <[email protected]>"]
8arrayvec = "0.4.10" 8arrayvec = "0.4.10"
9log = "0.4.5" 9log = "0.4.5"
10relative-path = "0.4.0" 10relative-path = "0.4.0"
11salsa = "0.9.0" 11salsa = "0.9.1"
12rustc-hash = "1.0" 12rustc-hash = "1.0"
13parking_lot = "0.7.0" 13parking_lot = "0.7.0"
14id-arena = "2.0"
15ena = "0.11" 14ena = "0.11"
16ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
16ra_arena = { path = "../ra_arena" }
17ra_editor = { path = "../ra_editor" } 17ra_editor = { path = "../ra_editor" }
18ra_db = { path = "../ra_db" } 18ra_db = { path = "../ra_db" }
19test_utils = { path = "../test_utils" } 19test_utils = { path = "../test_utils" }
diff --git a/crates/ra_hir/src/arena.rs b/crates/ra_hir/src/arena.rs
deleted file mode 100644
index d4f9d9cb9..000000000
--- a/crates/ra_hir/src/arena.rs
+++ /dev/null
@@ -1,66 +0,0 @@
1//! A simple id-based arena, similar to https://github.com/fitzgen/id-arena.
2//! We use our own version for more compact id's and to allow inherent impls
3//! on Ids.
4
5use std::{
6 fmt,
7 hash::{Hash, Hasher},
8 marker::PhantomData,
9};
10
11pub struct Id<T> {
12 idx: u32,
13 _ty: PhantomData<fn() -> T>,
14}
15
16impl<T> fmt::Debug for Id<T> {
17 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18 f.debug_tuple("Id").field(&self.idx).finish()
19 }
20}
21impl<T> Copy for Id<T> {}
22impl<T> Clone for Id<T> {
23 fn clone(&self) -> Id<T> {
24 *self
25 }
26}
27
28impl<T> PartialEq for Id<T> {
29 fn eq(&self, other: &Id<T>) -> bool {
30 self.idx == other.idx
31 }
32}
33
34impl<T> Eq for Id<T> {}
35
36impl<T> Hash for Id<T> {
37 fn hash<H: Hasher>(&self, h: &mut H) {
38 self.idx.hash(h);
39 }
40}
41
42#[derive(Debug, PartialEq, Eq)]
43pub(crate) struct ArenaBehavior<T> {
44 _ty: PhantomData<T>,
45}
46
47impl<T> id_arena::ArenaBehavior for ArenaBehavior<T> {
48 type Id = Id<T>;
49 fn new_arena_id() -> u32 {
50 0
51 }
52 fn new_id(_arena_id: u32, index: usize) -> Id<T> {
53 Id {
54 idx: index as u32,
55 _ty: PhantomData,
56 }
57 }
58 fn index(id: Id<T>) -> usize {
59 id.idx as usize
60 }
61 fn arena_id(_id: Id<T>) -> u32 {
62 0
63 }
64}
65
66pub(crate) type Arena<T> = id_arena::Arena<T, ArenaBehavior<T>>;
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 73a4cdc5c..58296fc6f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -13,6 +13,7 @@ use crate::{
13 nameres::{ItemMap, InputModuleItems}}, 13 nameres::{ItemMap, InputModuleItems}},
14 ty::{InferenceResult, Ty}, 14 ty::{InferenceResult, Ty},
15 adt::{StructData, EnumData}, 15 adt::{StructData, EnumData},
16 impl_block::ModuleImplBlocks,
16}; 17};
17 18
18salsa::query_group! { 19salsa::query_group! {
@@ -87,6 +88,11 @@ pub trait HirDatabase: SyntaxDatabase
87 type ModuleTreeQuery; 88 type ModuleTreeQuery;
88 use fn crate::module::imp::module_tree; 89 use fn crate::module::imp::module_tree;
89 } 90 }
91
92 fn impls_in_module(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleImplBlocks>> {
93 type ImplsInModuleQuery;
94 use fn crate::impl_block::impls_in_module;
95 }
90} 96}
91 97
92} 98}
diff --git a/crates/ra_hir/src/function.rs b/crates/ra_hir/src/function.rs
index 5a44132fc..75ef308ae 100644
--- a/crates/ra_hir/src/function.rs
+++ b/crates/ra_hir/src/function.rs
@@ -11,11 +11,11 @@ use ra_syntax::{
11 ast::{self, AstNode, DocCommentsOwner, NameOwner}, 11 ast::{self, AstNode, DocCommentsOwner, NameOwner},
12}; 12};
13 13
14use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module}; 14use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock};
15 15
16pub use self::scope::FnScopes; 16pub use self::scope::FnScopes;
17 17
18#[derive(Debug)] 18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Function { 19pub struct Function {
20 def_id: DefId, 20 def_id: DefId,
21} 21}
@@ -25,6 +25,10 @@ impl Function {
25 Function { def_id } 25 Function { def_id }
26 } 26 }
27 27
28 pub fn def_id(&self) -> DefId {
29 self.def_id
30 }
31
28 pub fn syntax(&self, db: &impl HirDatabase) -> ast::FnDefNode { 32 pub fn syntax(&self, db: &impl HirDatabase) -> ast::FnDefNode {
29 let def_loc = self.def_id.loc(db); 33 let def_loc = self.def_id.loc(db);
30 assert!(def_loc.kind == DefKind::Function); 34 assert!(def_loc.kind == DefKind::Function);
@@ -48,6 +52,15 @@ impl Function {
48 pub fn module(&self, db: &impl HirDatabase) -> Cancelable<Module> { 52 pub fn module(&self, db: &impl HirDatabase) -> Cancelable<Module> {
49 self.def_id.module(db) 53 self.def_id.module(db)
50 } 54 }
55
56 pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> {
57 self.def_id.krate(db)
58 }
59
60 /// The containing impl block, if this is a method.
61 pub fn impl_block(&self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> {
62 self.def_id.impl_block(db)
63 }
51} 64}
52 65
53#[derive(Debug, Clone)] 66#[derive(Debug, Clone)]
diff --git a/crates/ra_hir/src/function/scope.rs b/crates/ra_hir/src/function/scope.rs
index 3e4cfad0c..42bfe4f32 100644
--- a/crates/ra_hir/src/function/scope.rs
+++ b/crates/ra_hir/src/function/scope.rs
@@ -5,19 +5,19 @@ use ra_syntax::{
5 algo::generate, 5 algo::generate,
6 ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, 6 ast::{self, ArgListOwner, LoopBodyOwner, NameOwner},
7}; 7};
8use ra_arena::{Arena, RawId, impl_arena_id};
8use ra_db::LocalSyntaxPtr; 9use ra_db::LocalSyntaxPtr;
9 10
10use crate::{ 11use crate::{Name, AsName};
11 arena::{Arena, Id},
12 Name, AsName,
13};
14 12
15pub(crate) type ScopeId = Id<ScopeData>; 13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct ScopeId(RawId);
15impl_arena_id!(ScopeId);
16 16
17#[derive(Debug, PartialEq, Eq)] 17#[derive(Debug, PartialEq, Eq)]
18pub struct FnScopes { 18pub struct FnScopes {
19 pub self_param: Option<LocalSyntaxPtr>, 19 pub self_param: Option<LocalSyntaxPtr>,
20 scopes: Arena<ScopeData>, 20 scopes: Arena<ScopeId, ScopeData>,
21 scope_for: FxHashMap<LocalSyntaxPtr, ScopeId>, 21 scope_for: FxHashMap<LocalSyntaxPtr, ScopeId>,
22} 22}
23 23
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index a09dee8b1..4d6378e02 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,10 +1,8 @@
1use ra_db::{SourceRootId, LocationIntener, Cancelable, FileId}; 1use ra_db::{SourceRootId, LocationIntener, Cancelable, FileId};
2use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, SourceFile, AstNode, ast}; 2use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, SourceFile, AstNode, ast};
3use ra_arena::{Arena, RawId, impl_arena_id};
3 4
4use crate::{ 5use crate::{HirDatabase, PerNs, ModuleId, Module, Def, Function, Struct, Enum, ImplBlock, Crate};
5 HirDatabase, PerNs, ModuleId, Module, Def, Function, Struct, Enum,
6 arena::{Arena, Id},
7};
8 6
9/// hir makes a heavy use of ids: integer (u32) handlers to various things. You 7/// hir makes a heavy use of ids: integer (u32) handlers to various things. You
10/// can think of id as a pointer (but without a lifetime) or a file descriptor 8/// can think of id as a pointer (but without a lifetime) or a file descriptor
@@ -48,6 +46,13 @@ impl HirFileId {
48 } 46 }
49 } 47 }
50 48
49 pub(crate) fn as_macro_call_id(self) -> Option<MacroCallId> {
50 match self.0 {
51 HirFileIdRepr::Macro(it) => Some(it),
52 _ => None,
53 }
54 }
55
51 pub(crate) fn hir_source_file(db: &impl HirDatabase, file_id: HirFileId) -> SourceFileNode { 56 pub(crate) fn hir_source_file(db: &impl HirDatabase, file_id: HirFileId) -> SourceFileNode {
52 match file_id.0 { 57 match file_id.0 {
53 HirFileIdRepr::File(file_id) => db.source_file(file_id), 58 HirFileIdRepr::File(file_id) => db.source_file(file_id),
@@ -172,6 +177,18 @@ impl DefId {
172 let loc = self.loc(db); 177 let loc = self.loc(db);
173 Module::new(db, loc.source_root_id, loc.module_id) 178 Module::new(db, loc.source_root_id, loc.module_id)
174 } 179 }
180
181 /// Returns the containing crate.
182 pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> {
183 Ok(self.module(db)?.krate(db))
184 }
185
186 /// Returns the containing impl block, if this is an impl item.
187 pub fn impl_block(self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> {
188 let loc = self.loc(db);
189 let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id)?;
190 Ok(ImplBlock::containing(module_impls, self))
191 }
175} 192}
176 193
177impl DefLoc { 194impl DefLoc {
@@ -199,7 +216,9 @@ impl DefKind {
199 216
200/// Identifier of item within a specific file. This is stable over reparses, so 217/// Identifier of item within a specific file. This is stable over reparses, so
201/// it's OK to use it as a salsa key/value. 218/// it's OK to use it as a salsa key/value.
202pub(crate) type SourceFileItemId = Id<SyntaxNode>; 219#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
220pub struct SourceFileItemId(RawId);
221impl_arena_id!(SourceFileItemId);
203 222
204#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 223#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
205pub struct SourceItemId { 224pub struct SourceItemId {
@@ -212,7 +231,7 @@ pub struct SourceItemId {
212#[derive(Debug, PartialEq, Eq)] 231#[derive(Debug, PartialEq, Eq)]
213pub struct SourceFileItems { 232pub struct SourceFileItems {
214 file_id: HirFileId, 233 file_id: HirFileId,
215 arena: Arena<SyntaxNode>, 234 arena: Arena<SourceFileItemId, SyntaxNode>,
216} 235}
217 236
218impl SourceFileItems { 237impl SourceFileItems {
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
new file mode 100644
index 000000000..01afa84c4
--- /dev/null
+++ b/crates/ra_hir/src/impl_block.rs
@@ -0,0 +1,180 @@
1use std::sync::Arc;
2use rustc_hash::FxHashMap;
3
4use ra_arena::{Arena, RawId, impl_arena_id};
5use ra_syntax::ast::{self, AstNode};
6use ra_db::{LocationIntener, Cancelable, SourceRootId};
7
8use crate::{
9 DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
10 Module, Function,
11 db::HirDatabase,
12 type_ref::TypeRef,
13 module::{ModuleSourceNode, ModuleId},
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ImplBlock {
18 module_impl_blocks: Arc<ModuleImplBlocks>,
19 impl_id: ImplId,
20}
21
22impl ImplBlock {
23 pub(crate) fn containing(
24 module_impl_blocks: Arc<ModuleImplBlocks>,
25 def_id: DefId,
26 ) -> Option<ImplBlock> {
27 let impl_id = *module_impl_blocks.impls_by_def.get(&def_id)?;
28 Some(ImplBlock {
29 module_impl_blocks,
30 impl_id,
31 })
32 }
33
34 fn impl_data(&self) -> &ImplData {
35 &self.module_impl_blocks.impls[self.impl_id]
36 }
37
38 pub fn target_trait(&self) -> Option<&TypeRef> {
39 self.impl_data().target_trait.as_ref()
40 }
41
42 pub fn target_type(&self) -> &TypeRef {
43 &self.impl_data().target_type
44 }
45
46 pub fn items(&self) -> &[ImplItem] {
47 &self.impl_data().items
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct ImplData {
53 target_trait: Option<TypeRef>,
54 target_type: TypeRef,
55 items: Vec<ImplItem>,
56}
57
58impl ImplData {
59 pub(crate) fn from_ast(
60 db: &impl AsRef<LocationIntener<DefLoc, DefId>>,
61 file_items: &SourceFileItems,
62 module: &Module,
63 node: ast::ImplBlock,
64 ) -> Self {
65 let target_trait = node.target_type().map(TypeRef::from_ast);
66 let target_type = TypeRef::from_ast_opt(node.target_type());
67 let file_id = module.source().file_id();
68 let items = if let Some(item_list) = node.item_list() {
69 item_list
70 .impl_items()
71 .map(|item_node| {
72 let kind = match item_node {
73 ast::ImplItem::FnDef(..) => DefKind::Function,
74 ast::ImplItem::ConstDef(..) => DefKind::Item,
75 ast::ImplItem::TypeDef(..) => DefKind::Item,
76 };
77 let item_id = file_items.id_of_unchecked(item_node.syntax());
78 let def_loc = DefLoc {
79 kind,
80 source_root_id: module.source_root_id,
81 module_id: module.module_id,
82 source_item_id: SourceItemId {
83 file_id,
84 item_id: Some(item_id),
85 },
86 };
87 let def_id = def_loc.id(db);
88 match item_node {
89 ast::ImplItem::FnDef(..) => ImplItem::Method(Function::new(def_id)),
90 ast::ImplItem::ConstDef(..) => ImplItem::Const(def_id),
91 ast::ImplItem::TypeDef(..) => ImplItem::Type(def_id),
92 }
93 })
94 .collect()
95 } else {
96 Vec::new()
97 };
98 ImplData {
99 target_trait,
100 target_type,
101 items,
102 }
103 }
104}
105
106#[derive(Debug, Clone, PartialEq, Eq)]
107pub enum ImplItem {
108 Method(Function),
109 // these don't have their own types yet
110 Const(DefId),
111 Type(DefId),
112 // Existential
113}
114
115impl ImplItem {
116 pub fn def_id(&self) -> DefId {
117 match self {
118 ImplItem::Method(f) => f.def_id(),
119 ImplItem::Const(def_id) => *def_id,
120 ImplItem::Type(def_id) => *def_id,
121 }
122 }
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
126pub struct ImplId(pub RawId);
127impl_arena_id!(ImplId);
128
129/// Collection of impl blocks is a two-step process: First we collect the blocks
130/// per-module; then we build an index of all impl blocks in the crate. This
131/// way, we avoid having to do this process for the whole crate whenever someone
132/// types in any file; as long as the impl blocks in the file don't change, we
133/// don't need to do the second step again.
134///
135/// (The second step does not yet exist currently.)
136#[derive(Debug, PartialEq, Eq)]
137pub struct ModuleImplBlocks {
138 impls: Arena<ImplId, ImplData>,
139 impls_by_def: FxHashMap<DefId, ImplId>,
140}
141
142impl ModuleImplBlocks {
143 fn new() -> Self {
144 ModuleImplBlocks {
145 impls: Arena::default(),
146 impls_by_def: FxHashMap::default(),