diff options
28 files changed, 668 insertions, 474 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 395ce1ef4..77c92512a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml | |||
@@ -1,4 +1,4 @@ | |||
1 | name: CI-Release | 1 | name: release |
2 | on: | 2 | on: |
3 | push: | 3 | push: |
4 | branches: | 4 | branches: |
@@ -132,7 +132,9 @@ jobs: | |||
132 | 132 | ||
133 | - name: Create Release | 133 | - name: Create Release |
134 | id: create_release | 134 | id: create_release |
135 | uses: actions/create-release@v1 | 135 | # uses: actions/create-release@v1 |
136 | # https://github.com/actions/create-release/pull/32 | ||
137 | uses: fleskesvor/create-release@1a72e235c178bf2ae6c51a8ae36febc24568c5fe | ||
136 | env: | 138 | env: |
137 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | 139 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
138 | with: | 140 | with: |
diff --git a/Cargo.lock b/Cargo.lock index 01e86ab0e..8c88f46ed 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -2,7 +2,7 @@ | |||
2 | # It is not intended for manual editing. | 2 | # It is not intended for manual editing. |
3 | [[package]] | 3 | [[package]] |
4 | name = "aho-corasick" | 4 | name = "aho-corasick" |
5 | version = "0.7.6" | 5 | version = "0.7.7" |
6 | source = "registry+https://github.com/rust-lang/crates.io-index" | 6 | source = "registry+https://github.com/rust-lang/crates.io-index" |
7 | dependencies = [ | 7 | dependencies = [ |
8 | "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | 8 | "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -45,7 +45,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
45 | 45 | ||
46 | [[package]] | 46 | [[package]] |
47 | name = "backtrace" | 47 | name = "backtrace" |
48 | version = "0.3.42" | 48 | version = "0.3.43" |
49 | source = "registry+https://github.com/rust-lang/crates.io-index" | 49 | source = "registry+https://github.com/rust-lang/crates.io-index" |
50 | dependencies = [ | 50 | dependencies = [ |
51 | "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", | 51 | "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -300,7 +300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
300 | 300 | ||
301 | [[package]] | 301 | [[package]] |
302 | name = "dtoa" | 302 | name = "dtoa" |
303 | version = "0.4.4" | 303 | version = "0.4.5" |
304 | source = "registry+https://github.com/rust-lang/crates.io-index" | 304 | source = "registry+https://github.com/rust-lang/crates.io-index" |
305 | 305 | ||
306 | [[package]] | 306 | [[package]] |
@@ -419,7 +419,7 @@ name = "globset" | |||
419 | version = "0.4.4" | 419 | version = "0.4.4" |
420 | source = "registry+https://github.com/rust-lang/crates.io-index" | 420 | source = "registry+https://github.com/rust-lang/crates.io-index" |
421 | dependencies = [ | 421 | dependencies = [ |
422 | "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", | 422 | "aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", |
423 | "bstr 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", | 423 | "bstr 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", |
424 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", | 424 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", |
425 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", | 425 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -614,7 +614,7 @@ dependencies = [ | |||
614 | 614 | ||
615 | [[package]] | 615 | [[package]] |
616 | name = "lsp-types" | 616 | name = "lsp-types" |
617 | version = "0.70.0" | 617 | version = "0.70.1" |
618 | source = "registry+https://github.com/rust-lang/crates.io-index" | 618 | source = "registry+https://github.com/rust-lang/crates.io-index" |
619 | dependencies = [ | 619 | dependencies = [ |
620 | "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", | 620 | "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -755,7 +755,7 @@ dependencies = [ | |||
755 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | 755 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", |
756 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", | 756 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", |
757 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", | 757 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", |
758 | "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 758 | "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
759 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", | 759 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", |
760 | ] | 760 | ] |
761 | 761 | ||
@@ -895,7 +895,7 @@ dependencies = [ | |||
895 | "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", | 895 | "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", |
896 | "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 896 | "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
897 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", | 897 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", |
898 | "lsp-types 0.70.0 (registry+https://github.com/rust-lang/crates.io-index)", | 898 | "lsp-types 0.70.1 (registry+https://github.com/rust-lang/crates.io-index)", |
899 | "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", | 899 | "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", |
900 | "serde_json 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", | 900 | "serde_json 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", |
901 | ] | 901 | ] |
@@ -1061,7 +1061,7 @@ dependencies = [ | |||
1061 | "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1061 | "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1062 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", | 1062 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", |
1063 | "lsp-server 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1063 | "lsp-server 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1064 | "lsp-types 0.70.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1064 | "lsp-types 0.70.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1065 | "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1065 | "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1066 | "ra_cargo_watch 0.1.0", | 1066 | "ra_cargo_watch 0.1.0", |
1067 | "ra_ide 0.1.0", | 1067 | "ra_ide 0.1.0", |
@@ -1090,7 +1090,7 @@ dependencies = [ | |||
1090 | "ra_syntax 0.1.0", | 1090 | "ra_syntax 0.1.0", |
1091 | "ra_tt 0.1.0", | 1091 | "ra_tt 0.1.0", |
1092 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1092 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1093 | "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1093 | "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1094 | "test_utils 0.1.0", | 1094 | "test_utils 0.1.0", |
1095 | ] | 1095 | ] |
1096 | 1096 | ||
@@ -1105,7 +1105,7 @@ dependencies = [ | |||
1105 | name = "ra_prof" | 1105 | name = "ra_prof" |
1106 | version = "0.1.0" | 1106 | version = "0.1.0" |
1107 | dependencies = [ | 1107 | dependencies = [ |
1108 | "backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)", | 1108 | "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", |
1109 | "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1109 | "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1110 | "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", | 1110 | "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", |
1111 | "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1111 | "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1365,7 +1365,7 @@ name = "regex" | |||
1365 | version = "1.3.3" | 1365 | version = "1.3.3" |
1366 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1366 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1367 | dependencies = [ | 1367 | dependencies = [ |
1368 | "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", | 1368 | "aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", |
1369 | "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1369 | "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1370 | "regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", | 1370 | "regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", |
1371 | "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1371 | "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1446,7 +1446,7 @@ dependencies = [ | |||
1446 | "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", | 1446 | "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", |
1447 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1447 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1448 | "salsa-macros 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1448 | "salsa-macros 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1449 | "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1449 | "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1450 | ] | 1450 | ] |
1451 | 1451 | ||
1452 | [[package]] | 1452 | [[package]] |
@@ -1530,7 +1530,7 @@ name = "serde_yaml" | |||
1530 | version = "0.8.11" | 1530 | version = "0.8.11" |
1531 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1532 | dependencies = [ | 1532 | dependencies = [ |
1533 | "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", | 1533 | "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", |
1534 | "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1534 | "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1535 | "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", | 1535 | "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", |
1536 | "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", | 1536 | "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1543,7 +1543,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1543 | 1543 | ||
1544 | [[package]] | 1544 | [[package]] |
1545 | name = "smallvec" | 1545 | name = "smallvec" |
1546 | version = "1.1.0" | 1546 | version = "1.2.0" |
1547 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1548 | 1548 | ||
1549 | [[package]] | 1549 | [[package]] |
@@ -1646,7 +1646,7 @@ name = "unicode-normalization" | |||
1646 | version = "0.1.12" | 1646 | version = "0.1.12" |
1647 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1647 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1648 | dependencies = [ | 1648 | dependencies = [ |
1649 | "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1649 | "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1650 | ] | 1650 | ] |
1651 | 1651 | ||
1652 | [[package]] | 1652 | [[package]] |
@@ -1756,14 +1756,14 @@ dependencies = [ | |||
1756 | ] | 1756 | ] |
1757 | 1757 | ||
1758 | [metadata] | 1758 | [metadata] |
1759 | "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" | 1759 | "checksum aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5f56c476256dc249def911d6f7580b5fc7e875895b5d7ee88f5d602208035744" |
1760 | "checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" | 1760 | "checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" |
1761 | "checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" | 1761 | "checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" |
1762 | "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" | 1762 | "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" |
1763 | "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" | 1763 | "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" |
1764 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" | 1764 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" |
1765 | "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" | 1765 | "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" |
1766 | "checksum backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b4b1549d804b6c73f4817df2ba073709e96e426f12987127c48e6745568c350b" | 1766 | "checksum backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f" |
1767 | "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" | 1767 | "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" |
1768 | "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" | 1768 | "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" |
1769 | "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" | 1769 | "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" |
@@ -1792,7 +1792,7 @@ dependencies = [ | |||
1792 | "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" | 1792 | "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" |
1793 | "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" | 1793 | "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" |
1794 | "checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" | 1794 | "checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" |
1795 | "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" | 1795 | "checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" |
1796 | "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" | 1796 | "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" |
1797 | "checksum ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" | 1797 | "checksum ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" |
1798 | "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" | 1798 | "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" |
@@ -1834,7 +1834,7 @@ dependencies = [ | |||
1834 | "checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" | 1834 | "checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" |
1835 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" | 1835 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" |
1836 | "checksum lsp-server 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5383e043329615624bbf45e1ba27bd75c176762b2592855c659bc28ac580a06b" | 1836 | "checksum lsp-server 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5383e043329615624bbf45e1ba27bd75c176762b2592855c659bc28ac580a06b" |
1837 | "checksum lsp-types 0.70.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef197b24cb3f12fc3984667a505691fec9d683204ddff56f12b2d1940e09a988" | 1837 | "checksum lsp-types 0.70.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d267f222864db3db63cf7e18493a2a5c84edab1f4e3c7211c9390ce033365210" |
1838 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" | 1838 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" |
1839 | "checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" | 1839 | "checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" |
1840 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" | 1840 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" |
@@ -1902,7 +1902,7 @@ dependencies = [ | |||
1902 | "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" | 1902 | "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" |
1903 | "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" | 1903 | "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" |
1904 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" | 1904 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" |
1905 | "checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" | 1905 | "checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" |
1906 | "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" | 1906 | "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" |
1907 | "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" | 1907 | "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" |
1908 | "checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" | 1908 | "checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" |
@@ -4,10 +4,9 @@ | |||
4 | 4 | ||
5 | Rust Analyzer is an **experimental** modular compiler frontend for the Rust | 5 | Rust Analyzer is an **experimental** modular compiler frontend for the Rust |
6 | language. It is a part of a larger rls-2.0 effort to create excellent IDE | 6 | language. It is a part of a larger rls-2.0 effort to create excellent IDE |
7 | support for Rust. If you want to get involved, check the rls-2.0 working group | 7 | support for Rust. If you want to get involved, check the rls-2.0 working group: |
8 | in the compiler-team repository: | ||
9 | 8 | ||
10 | https://github.com/rust-lang/compiler-team/tree/master/content/working-groups/rls-2.0 | 9 | https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 |
11 | 10 | ||
12 | Work on the Rust Analyzer is sponsored by | 11 | Work on the Rust Analyzer is sponsored by |
13 | 12 | ||
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs index 9163cc662..69126a1c9 100644 --- a/crates/ra_assists/src/assists/auto_import.rs +++ b/crates/ra_assists/src/assists/auto_import.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | use hir::db::HirDatabase; | 1 | use hir::db::HirDatabase; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | ast::{self, AstNode}, | 3 | ast::{self, AstNode}, |
4 | SmolStr, SyntaxElement, | 4 | SmolStr, |
5 | SyntaxKind::{NAME_REF, USE_ITEM}, | 5 | SyntaxKind::USE_ITEM, |
6 | SyntaxNode, | 6 | SyntaxNode, |
7 | }; | 7 | }; |
8 | 8 | ||
@@ -32,25 +32,28 @@ pub(crate) fn auto_import<F: ImportsLocator>( | |||
32 | ctx: AssistCtx<impl HirDatabase>, | 32 | ctx: AssistCtx<impl HirDatabase>, |
33 | imports_locator: &mut F, | 33 | imports_locator: &mut F, |
34 | ) -> Option<Assist> { | 34 | ) -> Option<Assist> { |
35 | let path: ast::Path = ctx.find_node_at_offset()?; | 35 | let path_to_import: ast::Path = ctx.find_node_at_offset()?; |
36 | let module = path.syntax().ancestors().find_map(ast::Module::cast); | 36 | let path_to_import_syntax = path_to_import.syntax(); |
37 | if path_to_import_syntax.ancestors().find(|ancestor| ancestor.kind() == USE_ITEM).is_some() { | ||
38 | return None; | ||
39 | } | ||
40 | |||
41 | let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast); | ||
37 | let position = match module.and_then(|it| it.item_list()) { | 42 | let position = match module.and_then(|it| it.item_list()) { |
38 | Some(item_list) => item_list.syntax().clone(), | 43 | Some(item_list) => item_list.syntax().clone(), |
39 | None => { | 44 | None => { |
40 | let current_file = path.syntax().ancestors().find_map(ast::SourceFile::cast)?; | 45 | let current_file = path_to_import_syntax.ancestors().find_map(ast::SourceFile::cast)?; |
41 | current_file.syntax().clone() | 46 | current_file.syntax().clone() |
42 | } | 47 | } |
43 | }; | 48 | }; |
44 | let source_analyzer = ctx.source_analyzer(&position, None); | 49 | let source_analyzer = ctx.source_analyzer(&position, None); |
45 | let module_with_name_to_import = source_analyzer.module()?; | 50 | let module_with_name_to_import = source_analyzer.module()?; |
46 | let path_to_import = ctx.covering_element().ancestors().find_map(ast::Path::cast)?; | ||
47 | if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() { | 51 | if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() { |
48 | return None; | 52 | return None; |
49 | } | 53 | } |
50 | 54 | ||
51 | let name_to_import = &find_applicable_name_ref(ctx.covering_element())?.syntax().to_string(); | ||
52 | let proposed_imports = imports_locator | 55 | let proposed_imports = imports_locator |
53 | .find_imports(&name_to_import.to_string()) | 56 | .find_imports(&path_to_import_syntax.to_string()) |
54 | .into_iter() | 57 | .into_iter() |
55 | .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) | 58 | .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) |
56 | .filter(|use_path| !use_path.segments.is_empty()) | 59 | .filter(|use_path| !use_path.segments.is_empty()) |
@@ -64,26 +67,11 @@ pub(crate) fn auto_import<F: ImportsLocator>( | |||
64 | ctx.add_assist_group(AssistId("auto_import"), "auto import", || { | 67 | ctx.add_assist_group(AssistId("auto_import"), "auto import", || { |
65 | proposed_imports | 68 | proposed_imports |
66 | .into_iter() | 69 | .into_iter() |
67 | .map(|import| import_to_action(import, &position, &path_to_import.syntax())) | 70 | .map(|import| import_to_action(import, &position, &path_to_import_syntax)) |
68 | .collect() | 71 | .collect() |
69 | }) | 72 | }) |
70 | } | 73 | } |
71 | 74 | ||
72 | fn find_applicable_name_ref(element: SyntaxElement) -> Option<ast::NameRef> { | ||
73 | if element.ancestors().find(|ancestor| ancestor.kind() == USE_ITEM).is_some() { | ||
74 | None | ||
75 | } else if element.kind() == NAME_REF { | ||
76 | Some(element.as_node().cloned().and_then(ast::NameRef::cast)?) | ||
77 | } else { | ||
78 | let parent = element.parent()?; | ||
79 | if parent.kind() == NAME_REF { | ||
80 | Some(ast::NameRef::cast(parent)?) | ||
81 | } else { | ||
82 | None | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | fn import_to_action(import: String, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { | 75 | fn import_to_action(import: String, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { |
88 | let mut action_builder = ActionBuilder::default(); | 76 | let mut action_builder = ActionBuilder::default(); |
89 | action_builder.label(format!("Import `{}`", &import)); | 77 | action_builder.label(format!("Import `{}`", &import)); |
@@ -110,16 +98,16 @@ mod tests { | |||
110 | auto_import, | 98 | auto_import, |
111 | TestImportsLocator::new, | 99 | TestImportsLocator::new, |
112 | r" | 100 | r" |
113 | PubStruct<|> | 101 | <|>PubStruct |
114 | 102 | ||
115 | pub mod PubMod { | 103 | pub mod PubMod { |
116 | pub struct PubStruct; | 104 | pub struct PubStruct; |
117 | } | 105 | } |
118 | ", | 106 | ", |
119 | r" | 107 | r" |
120 | use PubMod::PubStruct; | 108 | <|>use PubMod::PubStruct; |
121 | 109 | ||
122 | PubStruct<|> | 110 | PubStruct |
123 | 111 | ||
124 | pub mod PubMod { | 112 | pub mod PubMod { |
125 | pub struct PubStruct; | 113 | pub struct PubStruct; |
@@ -134,7 +122,7 @@ mod tests { | |||
134 | auto_import, | 122 | auto_import, |
135 | TestImportsLocator::new, | 123 | TestImportsLocator::new, |
136 | r" | 124 | r" |
137 | PubStruct<|> | 125 | PubSt<|>ruct |
138 | 126 | ||
139 | pub mod PubMod1 { | 127 | pub mod PubMod1 { |
140 | pub struct PubStruct; | 128 | pub struct PubStruct; |
@@ -149,7 +137,7 @@ mod tests { | |||
149 | r" | 137 | r" |
150 | use PubMod1::PubStruct; | 138 | use PubMod1::PubStruct; |
151 | 139 | ||
152 | PubStruct<|> | 140 | PubSt<|>ruct |
153 | 141 | ||
154 | pub mod PubMod1 { | 142 | pub mod PubMod1 { |
155 | pub struct PubStruct; | 143 | pub struct PubStruct; |
diff --git a/crates/ra_cargo_watch/Cargo.toml b/crates/ra_cargo_watch/Cargo.toml index 49e06e0d3..dd814fc9d 100644 --- a/crates/ra_cargo_watch/Cargo.toml +++ b/crates/ra_cargo_watch/Cargo.toml | |||
@@ -11,6 +11,7 @@ log = "0.4.3" | |||
11 | cargo_metadata = "0.9.1" | 11 | cargo_metadata = "0.9.1" |
12 | jod-thread = "0.1.0" | 12 | jod-thread = "0.1.0" |
13 | parking_lot = "0.10.0" | 13 | parking_lot = "0.10.0" |
14 | serde_json = "1.0.45" | ||
14 | 15 | ||
15 | [dev-dependencies] | 16 | [dev-dependencies] |
16 | insta = "0.13.0" | 17 | insta = "0.13.0" |
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs index e7b700c10..ea7ddc86b 100644 --- a/crates/ra_cargo_watch/src/lib.rs +++ b/crates/ra_cargo_watch/src/lib.rs | |||
@@ -9,7 +9,7 @@ use lsp_types::{ | |||
9 | }; | 9 | }; |
10 | use std::{ | 10 | use std::{ |
11 | collections::HashMap, | 11 | collections::HashMap, |
12 | io::BufReader, | 12 | io::{BufRead, BufReader}, |
13 | path::PathBuf, | 13 | path::PathBuf, |
14 | process::{Command, Stdio}, | 14 | process::{Command, Stdio}, |
15 | sync::Arc, | 15 | sync::Arc, |
@@ -216,8 +216,10 @@ impl CheckWatcherThread { | |||
216 | self.last_update_req.take(); | 216 | self.last_update_req.take(); |
217 | task_send.send(CheckTask::ClearDiagnostics).unwrap(); | 217 | task_send.send(CheckTask::ClearDiagnostics).unwrap(); |
218 | 218 | ||
219 | // By replacing the watcher, we drop the previous one which | 219 | // Replace with a dummy watcher first so we drop the original and wait for completion |
220 | // causes it to shut down automatically. | 220 | std::mem::replace(&mut self.watcher, WatchThread::dummy()); |
221 | |||
222 | // Then create the actual new watcher | ||
221 | self.watcher = WatchThread::new(&self.options, &self.workspace_root); | 223 | self.watcher = WatchThread::new(&self.options, &self.workspace_root); |
222 | } | 224 | } |
223 | } | 225 | } |
@@ -348,17 +350,45 @@ impl WatchThread { | |||
348 | // which will break out of the loop, and continue the shutdown | 350 | // which will break out of the loop, and continue the shutdown |
349 | let _ = message_send.send(CheckEvent::Begin); | 351 | let _ = message_send.send(CheckEvent::Begin); |
350 | 352 | ||
351 | for message in | 353 | // We manually read a line at a time, instead of using serde's |
352 | cargo_metadata::parse_messages(BufReader::new(command.stdout.take().unwrap())) | 354 | // stream deserializers, because the deserializer cannot recover |
353 | { | 355 | // from an error, resulting in it getting stuck, because we try to |
356 | // be resillient against failures. | ||
357 | // | ||
358 | // Because cargo only outputs one JSON object per line, we can | ||
359 | // simply skip a line if it doesn't parse, which just ignores any | ||
360 | // erroneus output. | ||
361 | let stdout = BufReader::new(command.stdout.take().unwrap()); | ||
362 | for line in stdout.lines() { | ||
363 | let line = match line { | ||
364 | Ok(line) => line, | ||
365 | Err(err) => { | ||
366 | log::error!("Couldn't read line from cargo: {}", err); | ||
367 | continue; | ||
368 | } | ||
369 | }; | ||
370 | |||
371 | let message = serde_json::from_str::<cargo_metadata::Message>(&line); | ||
354 | let message = match message { | 372 | let message = match message { |
355 | Ok(message) => message, | 373 | Ok(message) => message, |
356 | Err(err) => { | 374 | Err(err) => { |
357 | log::error!("Invalid json from cargo check, ignoring: {}", err); | 375 | log::error!( |
376 | "Invalid json from cargo check, ignoring ({}): {:?} ", | ||
377 | err, | ||
378 | line | ||
379 | ); | ||
358 | continue; | 380 | continue; |
359 | } | 381 | } |
360 | }; | 382 | }; |
361 | 383 | ||
384 | // Skip certain kinds of messages to only spend time on what's useful | ||
385 | match &message { | ||
386 | Message::CompilerArtifact(artifact) if artifact.fresh => continue, | ||
387 | Message::BuildScriptExecuted(_) => continue, | ||
388 | Message::Unknown => continue, | ||
389 | _ => {} | ||
390 | } | ||
391 | |||
362 | match message_send.send(CheckEvent::Msg(message)) { | 392 | match message_send.send(CheckEvent::Msg(message)) { |
363 | Ok(()) => {} | 393 | Ok(()) => {} |
364 | Err(_err) => { | 394 | Err(_err) => { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index e6079b88d..a77bf6de6 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -1,20 +1,24 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub use hir_def::db::{ | 3 | pub use hir_def::db::{ |
4 | BodyQuery, BodyWithSourceMapQuery, ComputeCrateDefMapQuery, ConstDataQuery, | 4 | AttrsQuery, BodyQuery, BodyWithSourceMapQuery, ComputeCrateDefMapQuery, ConstDataQuery, |
5 | CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, | 5 | CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, |
6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, | 6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternConstQuery, |
7 | InternDatabaseStorage, LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, | 7 | InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, InternImplQuery, |
8 | StructDataQuery, TraitDataQuery, TypeAliasDataQuery, | 8 | InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery, |
9 | LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, StructDataQuery, | ||
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | ||
9 | }; | 11 | }; |
10 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
11 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternMacroQuery, MacroArgQuery, MacroDefQuery, |
12 | ParseMacroQuery, | 14 | MacroExpandQuery, ParseMacroQuery, |
13 | }; | 15 | }; |
14 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
15 | AssociatedTyDataQuery, CallableItemSignatureQuery, DoInferQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, DoInferQuery, |
16 | GenericDefaultsQuery, GenericPredicatesQuery, HirDatabase, HirDatabaseStorage, ImplDatumQuery, | 18 | FieldTypesQuery, GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, |
17 | ImplsForTraitQuery, ImplsInCrateQuery, StructDatumQuery, TraitDatumQuery, TraitSolveQuery, | 19 | HirDatabase, HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, |
20 | ImplsForTraitQuery, ImplsInCrateQuery, InternAssocTyValueQuery, InternChalkImplQuery, | ||
21 | InternTypeCtorQuery, StructDatumQuery, TraitDatumQuery, TraitSolveQuery, TraitSolverQuery, | ||
18 | TyQuery, ValueTyQuery, | 22 | TyQuery, ValueTyQuery, |
19 | }; | 23 | }; |
20 | 24 | ||
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs index 8cc2fb160..43b9b124a 100644 --- a/crates/ra_hir_def/src/find_path.rs +++ b/crates/ra_hir_def/src/find_path.rs | |||
@@ -7,10 +7,39 @@ use crate::{ | |||
7 | visibility::Visibility, | 7 | visibility::Visibility, |
8 | CrateId, ModuleDefId, ModuleId, | 8 | CrateId, ModuleDefId, ModuleId, |
9 | }; | 9 | }; |
10 | use hir_expand::name::Name; | 10 | use hir_expand::name::{known, Name}; |
11 | use test_utils::tested_by; | ||
11 | 12 | ||
12 | const MAX_PATH_LEN: usize = 15; | 13 | const MAX_PATH_LEN: usize = 15; |
13 | 14 | ||
15 | impl ModPath { | ||
16 | fn starts_with_std(&self) -> bool { | ||
17 | self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some() | ||
18 | } | ||
19 | |||
20 | // When std library is present, paths starting with `std::` | ||
21 | // should be preferred over paths starting with `core::` and `alloc::` | ||
22 | fn should_start_with_std(&self) -> bool { | ||
23 | self.segments | ||
24 | .first() | ||
25 | .filter(|&first_segment| { | ||
26 | first_segment == &known::alloc || first_segment == &known::core | ||
27 | }) | ||
28 | .is_some() | ||
29 | } | ||
30 | |||
31 | fn len(&self) -> usize { | ||
32 | self.segments.len() | ||
33 | + match self.kind { | ||
34 | PathKind::Plain => 0, | ||
35 | PathKind::Super(i) => i as usize, | ||
36 | PathKind::Crate => 1, | ||
37 | PathKind::Abs => 0, | ||
38 | PathKind::DollarCrate(_) => 1, | ||
39 | } | ||
40 | } | ||
41 | } | ||
42 | |||
14 | // FIXME: handle local items | 43 | // FIXME: handle local items |
15 | 44 | ||
16 | /// Find a path that can be used to refer to a certain item. This can depend on | 45 | /// Find a path that can be used to refer to a certain item. This can depend on |
@@ -112,23 +141,27 @@ fn find_path_inner( | |||
112 | Some(path) => path, | 141 | Some(path) => path, |
113 | }; | 142 | }; |
114 | path.segments.push(name); | 143 | path.segments.push(name); |
115 | if path_len(&path) < best_path_len { | 144 | |
116 | best_path_len = path_len(&path); | 145 | let new_path = |
117 | best_path = Some(path); | 146 | if let Some(best_path) = best_path { select_best_path(best_path, path) } else { path }; |
118 | } | 147 | best_path_len = new_path.len(); |
148 | best_path = Some(new_path); | ||
119 | } | 149 | } |
120 | best_path | 150 | best_path |
121 | } | 151 | } |
122 | 152 | ||
123 | fn path_len(path: &ModPath) -> usize { | 153 | fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath { |
124 | path.segments.len() | 154 | if old_path.starts_with_std() && new_path.should_start_with_std() { |
125 | + match path.kind { | 155 | tested_by!(prefer_std_paths); |
126 | PathKind::Plain => 0, | 156 | old_path |
127 | PathKind::Super(i) => i as usize, | 157 | } else if new_path.starts_with_std() && old_path.should_start_with_std() { |
128 | PathKind::Crate => 1, | 158 | tested_by!(prefer_std_paths); |
129 | PathKind::Abs => 0, | 159 | new_path |
130 | PathKind::DollarCrate(_) => 1, | 160 | } else if new_path.len() < old_path.len() { |
131 | } | 161 | new_path |
162 | } else { | ||
163 | old_path | ||
164 | } | ||
132 | } | 165 | } |
133 | 166 | ||
134 | fn find_importable_locations( | 167 | fn find_importable_locations( |
@@ -201,6 +234,7 @@ mod tests { | |||
201 | use hir_expand::hygiene::Hygiene; | 234 | use hir_expand::hygiene::Hygiene; |
202 | use ra_db::fixture::WithFixture; | 235 | use ra_db::fixture::WithFixture; |
203 | use ra_syntax::ast::AstNode; | 236 | use ra_syntax::ast::AstNode; |
237 | use test_utils::covers; | ||
204 | 238 | ||
205 | /// `code` needs to contain a cursor marker; checks that `find_path` for the | 239 | /// `code` needs to contain a cursor marker; checks that `find_path` for the |
206 | /// item the `path` refers to returns that same path when called from the | 240 | /// item the `path` refers to returns that same path when called from the |
@@ -452,4 +486,41 @@ mod tests { | |||
452 | "#; | 486 | "#; |
453 | check_found_path(code, "crate::foo::S"); | 487 | check_found_path(code, "crate::foo::S"); |
454 | } | 488 | } |
489 | |||
490 | #[test] | ||
491 | fn prefer_std_paths_over_alloc() { | ||
492 | covers!(prefer_std_paths); | ||
493 | let code = r#" | ||
494 | //- /main.rs crate:main deps:alloc,std | ||
495 | <|> | ||
496 | |||
497 | //- /std.rs crate:std deps:alloc | ||
498 | pub mod sync { | ||
499 | pub use alloc::sync::Arc; | ||
500 | } | ||
501 | |||
502 | //- /zzz.rs crate:alloc | ||
503 | pub mod sync { | ||
504 | pub struct Arc; | ||
505 | } | ||
506 | "#; | ||
507 | check_found_path(code, "std::sync::Arc"); | ||
508 | } | ||
509 | |||
510 | #[test] | ||
511 | fn prefer_shorter_paths_if_not_alloc() { | ||
512 | let code = r#" | ||
513 | //- /main.rs crate:main deps:megaalloc,std | ||
514 | <|> | ||
515 | |||
516 | //- /std.rs crate:std deps:megaalloc | ||
517 | pub mod sync { | ||
518 | pub use megaalloc::sync::Arc; | ||
519 | } | ||
520 | |||
521 | //- /zzz.rs crate:megaalloc | ||
522 | pub struct Arc; | ||
523 | "#; | ||
524 | check_found_path(code, "megaalloc::Arc"); | ||
525 | } | ||
455 | } | 526 | } |
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs index 457ba4abe..daa49d5f1 100644 --- a/crates/ra_hir_def/src/marks.rs +++ b/crates/ra_hir_def/src/marks.rs | |||
@@ -13,4 +13,5 @@ test_utils::marks!( | |||
13 | macro_dollar_crate_self | 13 | macro_dollar_crate_self |
14 | macro_dollar_crate_other | 14 | macro_dollar_crate_other |
15 | infer_resolve_while_let | 15 | infer_resolve_while_let |
16 | prefer_std_paths | ||
16 | ); | 17 | ); |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 27c12e46c..852304dd0 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -229,6 +229,46 @@ impl CrateDefMap { | |||
229 | self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow); | 229 | self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow); |
230 | (res.resolved_def, res.segment_index) | 230 | (res.resolved_def, res.segment_index) |
231 | } | 231 | } |
232 | |||
233 | // FIXME: this can use some more human-readable format (ideally, an IR | ||
234 | // even), as this should be a great debugging aid. | ||
235 | pub fn dump(&self) -> String { | ||
236 | let mut buf = String::new(); | ||
237 | go(&mut buf, self, "\ncrate", self.root); | ||
238 | return buf.trim().to_string(); | ||
239 | |||
240 | fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) { | ||
241 | *buf += path; | ||
242 | *buf += "\n"; | ||
243 | |||
244 | let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); | ||
245 | entries.sort_by_key(|(name, _)| name.clone()); | ||
246 | |||
247 | for (name, def) in entries { | ||
248 | *buf += &format!("{}:", name); | ||
249 | |||
250 | if def.types.is_some() { | ||
251 | *buf += " t"; | ||
252 | } | ||
253 | if def.values.is_some() { | ||
254 | *buf += " v"; | ||
255 | } | ||
256 | if def.macros.is_some() { | ||
257 | *buf += " m"; | ||
258 | } | ||
259 | if def.is_none() { | ||
260 | *buf += " _"; | ||
261 | } | ||
262 | |||
263 | *buf += "\n"; | ||
264 | } | ||
265 | |||
266 | for (name, child) in map.modules[module].children.iter() { | ||
267 | let path = path.to_string() + &format!("::{}", name); | ||
268 | go(buf, map, &path, *child); | ||
269 | } | ||
270 | } | ||
271 | } | ||
232 | } | 272 | } |
233 | 273 | ||
234 | impl ModuleData { | 274 | impl ModuleData { |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 78bcdc850..82f0f835c 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -10,11 +10,10 @@ use insta::assert_snapshot; | |||
10 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 10 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
11 | use test_utils::covers; | 11 | use test_utils::covers; |
12 | 12 | ||
13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId}; | 13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; |
14 | 14 | ||
15 | fn def_map(fixture: &str) -> String { | 15 | fn def_map(fixture: &str) -> String { |
16 | let dm = compute_crate_def_map(fixture); | 16 | compute_crate_def_map(fixture).dump() |
17 | render_crate_def_map(&dm) | ||
18 | } | 17 | } |
19 | 18 | ||
20 | fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> { | 19 | fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> { |
@@ -23,44 +22,6 @@ fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> { | |||
23 | db.crate_def_map(krate) | 22 | db.crate_def_map(krate) |
24 | } | 23 | } |
25 | 24 | ||
26 | fn render_crate_def_map(map: &CrateDefMap) -> String { | ||
27 | let mut buf = String::new(); | ||
28 | go(&mut buf, map, "\ncrate", map.root); | ||
29 | return buf.trim().to_string(); | ||
30 | |||
31 | fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) { | ||
32 | *buf += path; | ||
33 | *buf += "\n"; | ||
34 | |||
35 | let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); | ||
36 | entries.sort_by_key(|(name, _)| name.clone()); | ||
37 | |||
38 | for (name, def) in entries { | ||
39 | *buf += &format!("{}:", name); | ||
40 | |||
41 | if def.types.is_some() { | ||
42 | *buf += " t"; | ||
43 | } | ||
44 | if def.values.is_some() { | ||
45 | *buf += " v"; | ||
46 | } | ||
47 | if def.macros.is_some() { | ||
48 | *buf += " m"; | ||
49 | } | ||
50 | if def.is_none() { | ||
51 | *buf += " _"; | ||
52 | } | ||
53 | |||
54 | *buf += "\n"; | ||
55 | } | ||
56 | |||
57 | for (name, child) in map.modules[module].children.iter() { | ||
58 | let path = path.to_string() + &format!("::{}", name); | ||
59 | go(buf, map, &path, *child); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | #[test] | 25 | #[test] |
65 | fn crate_def_map_smoke_test() { | 26 | fn crate_def_map_smoke_test() { |
66 | let map = def_map( | 27 | let map = def_map( |
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index b3fa1efba..b2e10f445 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs | |||
@@ -141,6 +141,8 @@ pub mod known { | |||
141 | macro_rules, | 141 | macro_rules, |
142 | // Components of known path (value or mod name) | 142 | // Components of known path (value or mod name) |
143 | std, | 143 | std, |
144 | core, | ||
145 | alloc, | ||
144 | iter, | 146 | iter, |
145 | ops, | 147 | ops, |
146 | future, | 148 | future, |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 908e4862d..08d501ccd 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -847,7 +847,7 @@ impl HirDisplay for ApplicationTy { | |||
847 | } | 847 | } |
848 | TypeCtor::Array => { | 848 | TypeCtor::Array => { |
849 | let t = self.parameters.as_single(); | 849 | let t = self.parameters.as_single(); |
850 | write!(f, "[{};_]", t.display(f.db))?; | 850 | write!(f, "[{}; _]", t.display(f.db))?; |
851 | } | 851 | } |
852 | TypeCtor::RawPtr(m) => { | 852 | TypeCtor::RawPtr(m) => { |
853 | let t = self.parameters.as_single(); | 853 | let t = self.parameters.as_single(); |
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 7e99a42ed..76a1b46c0 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -71,42 +71,42 @@ fn test2() { | |||
71 | [82; 93) '{ loop {} }': T | 71 | [82; 93) '{ loop {} }': T |
72 | [84; 91) 'loop {}': ! | 72 | [84; 91) 'loop {}': ! |
73 | [89; 91) '{}': () | 73 | [89; 91) '{}': () |
74 | [122; 133) '{ loop {} }': *mut [T;_] | 74 | [122; 133) '{ loop {} }': *mut [T; _] |
75 | [124; 131) 'loop {}': ! | 75 | [124; 131) 'loop {}': ! |
76 | [129; 131) '{}': () | 76 | [129; 131) '{}': () |
77 | [160; 173) '{ gen() }': *mut [U] | 77 | [160; 173) '{ gen() }': *mut [U] |
78 | [166; 169) 'gen': fn gen<U>() -> *mut [T;_] | 78 | [166; 169) 'gen': fn gen<U>() -> *mut [T; _] |
79 | [166; 171) 'gen()': *mut [U;_] | 79 | [166; 171) 'gen()': *mut [U; _] |
80 | [186; 420) '{ ...rr); }': () | 80 | [186; 420) '{ ...rr); }': () |
81 | [196; 199) 'arr': &[u8;_] | 81 | [196; 199) 'arr': &[u8; _] |
82 | [212; 216) '&[1]': &[u8;_] | 82 | [212; 216) '&[1]': &[u8; _] |
83 | [213; 216) '[1]': [u8;_] | 83 | [213; 216) '[1]': [u8; _] |
84 | [214; 215) '1': u8 | 84 | [214; 215) '1': u8 |
85 | [227; 228) 'a': &[u8] | 85 | [227; 228) 'a': &[u8] |
86 | [237; 240) 'arr': &[u8;_] | 86 | [237; 240) 'arr': &[u8; _] |
87 | [250; 251) 'b': u8 | 87 | [250; 251) 'b': u8 |
88 | [254; 255) 'f': fn f<u8>(&[T]) -> T | 88 | [254; 255) 'f': fn f<u8>(&[T]) -> T |
89 | [254; 260) 'f(arr)': u8 | 89 | [254; 260) 'f(arr)': u8 |
90 | [256; 259) 'arr': &[u8;_] | 90 | [256; 259) 'arr': &[u8; _] |
91 | [270; 271) 'c': &[u8] | 91 | [270; 271) 'c': &[u8] |
92 | [280; 287) '{ arr }': &[u8] | 92 | [280; 287) '{ arr }': &[u8] |
93 | [282; 285) 'arr': &[u8;_] | 93 | [282; 285) 'arr': &[u8; _] |
94 | [297; 298) 'd': u8 | 94 | [297; 298) 'd': u8 |
95 | [301; 302) 'g': fn g<u8>(S<&[T]>) -> T | 95 | [301; 302) 'g': fn g<u8>(S<&[T]>) -> T |
96 | [301; 316) 'g(S { a: arr })': u8 | 96 | [301; 316) 'g(S { a: arr })': u8 |
97 | [303; 315) 'S { a: arr }': S<&[u8]> | 97 | [303; 315) 'S { a: arr }': S<&[u8]> |
98 | [310; 313) 'arr': &[u8;_] | 98 | [310; 313) 'arr': &[u8; _] |
99 | [326; 327) 'e': [&[u8];_] | 99 | [326; 327) 'e': [&[u8]; _] |
100 | [341; 346) '[arr]': [&[u8];_] | 100 | [341; 346) '[arr]': [&[u8]; _] |
101 | [342; 345) 'arr': &[u8;_] | 101 | [342; 345) 'arr': &[u8; _] |
102 | [356; 357) 'f': [&[u8];_] | 102 | [356; 357) 'f': [&[u8]; _] |
103 | [371; 379) '[arr; 2]': [&[u8];_] | 103 | [371; 379) '[arr; 2]': [&[u8]; _] |
104 | [372; 375) 'arr': &[u8;_] | 104 | [372; 375) 'arr': &[u8; _] |
105 | [377; 378) '2': usize | 105 | [377; 378) '2': usize |
106 | [389; 390) 'g': (&[u8], &[u8]) | 106 | [389; 390) 'g': (&[u8], &[u8]) |
107 | [407; 417) '(arr, arr)': (&[u8], &[u8]) | 107 | [407; 417) '(arr, arr)': (&[u8], &[u8]) |
108 | [408; 411) 'arr': &[u8;_] | 108 | [408; 411) 'arr': &[u8; _] |
109 | [413; 416) 'arr': &[u8;_] | 109 | [413; 416) 'arr': &[u8; _] |
110 | "### | 110 | "### |
111 | ); | 111 | ); |
112 | } | 112 | } |
@@ -122,8 +122,8 @@ fn test() { | |||
122 | @r###" | 122 | @r###" |
123 | [11; 40) '{ ...[1]; }': () | 123 | [11; 40) '{ ...[1]; }': () |
124 | [21; 22) 'x': &[i32] | 124 | [21; 22) 'x': &[i32] |
125 | [33; 37) '&[1]': &[i32;_] | 125 | [33; 37) '&[1]': &[i32; _] |
126 | [34; 37) '[1]': [i32;_] | 126 | [34; 37) '[1]': [i32; _] |
127 | [35; 36) '1': i32 | 127 | [35; 36) '1': i32 |
128 | "###); | 128 | "###); |
129 | } | 129 | } |
@@ -159,22 +159,22 @@ fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | |||
159 | [334; 335) 'x': C<[T]> | 159 | [334; 335) 'x': C<[T]> |
160 | [355; 360) '{ x }': C<[T]> | 160 | [355; 360) '{ x }': C<[T]> |
161 | [357; 358) 'x': C<[T]> | 161 | [357; 358) 'x': C<[T]> |
162 | [370; 371) 'a': A<[u8;_]> | 162 | [370; 371) 'a': A<[u8; _]> |
163 | [385; 386) 'b': B<[u8;_]> | 163 | [385; 386) 'b': B<[u8; _]> |
164 | [400; 401) 'c': C<[u8;_]> | 164 | [400; 401) 'c': C<[u8; _]> |
165 | [415; 481) '{ ...(c); }': () | 165 | [415; 481) '{ ...(c); }': () |
166 | [425; 426) 'd': A<[{unknown}]> | 166 | [425; 426) 'd': A<[{unknown}]> |
167 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[T]>) -> A<[T]> | 167 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[T]>) -> A<[T]> |
168 | [429; 436) 'foo1(a)': A<[{unknown}]> | 168 | [429; 436) 'foo1(a)': A<[{unknown}]> |
169 | [434; 435) 'a': A<[u8;_]> | 169 | [434; 435) 'a': A<[u8; _]> |
170 | [446; 447) 'e': B<[u8]> | 170 | [446; 447) 'e': B<[u8]> |
171 | [450; 454) 'foo2': fn foo2<u8>(B<[T]>) -> B<[T]> | 171 | [450; 454) 'foo2': fn foo2<u8>(B<[T]>) -> B<[T]> |
172 | [450; 457) 'foo2(b)': B<[u8]> | 172 | [450; 457) 'foo2(b)': B<[u8]> |
173 | [455; 456) 'b': B<[u8;_]> | 173 | [455; 456) 'b': B<[u8; _]> |
174 | [467; 468) 'f': C<[u8]> | 174 | [467; 468) 'f': C<[u8]> |
175 | [471; 475) 'foo3': fn foo3<u8>(C<[T]>) -> C<[T]> | 175 | [471; 475) 'foo3': fn foo3<u8>(C<[T]>) -> C<[T]> |
176 | [471; 478) 'foo3(c)': C<[u8]> | 176 | [471; 478) 'foo3(c)': C<[u8]> |
177 | [476; 477) 'c': C<[u8;_]> | 177 | [476; 477) 'c': C<[u8; _]> |
178 | "### | 178 | "### |
179 | ); | 179 | ); |
180 | } | 180 | } |
@@ -204,12 +204,12 @@ fn test() { | |||
204 | [72; 97) '{ ... }': &[i32] | 204 | [72; 97) '{ ... }': &[i32] |
205 | [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T] | 205 | [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T] |
206 | [82; 91) 'foo(&[1])': &[i32] | 206 | [82; 91) 'foo(&[1])': &[i32] |
207 | [86; 90) '&[1]': &[i32;_] | 207 | [86; 90) '&[1]': &[i32; _] |
208 | [87; 90) '[1]': [i32;_] | 208 | [87; 90) '[1]': [i32; _] |
209 | [88; 89) '1': i32 | 209 | [88; 89) '1': i32 |
210 | [103; 123) '{ ... }': &[i32;_] | 210 | [103; 123) '{ ... }': &[i32; _] |
211 | [113; 117) '&[1]': &[i32;_] | 211 | [113; 117) '&[1]': &[i32; _] |
212 | [114; 117) '[1]': [i32;_] | 212 | [114; 117) '[1]': [i32; _] |
213 | [115; 116) '1': i32 | 213 | [115; 116) '1': i32 |
214 | "### | 214 | "### |
215 | ); | 215 | ); |
@@ -237,15 +237,15 @@ fn test() { | |||
237 | [60; 61) 'x': &[i32] | 237 | [60; 61) 'x': &[i32] |
238 | [64; 123) 'if tru... }': &[i32] | 238 | [64; 123) 'if tru... }': &[i32] |
239 | [67; 71) 'true': bool | 239 | [67; 71) 'true': bool |
240 | [72; 92) '{ ... }': &[i32;_] | 240 | [72; 92) '{ ... }': &[i32; _] |
241 | [82; 86) '&[1]': &[i32;_] | 241 | [82; 86) '&[1]': &[i32; _] |
242 | [83; 86) '[1]': [i32;_] | 242 | [83; 86) '[1]': [i32; _] |
243 | [84; 85) '1': i32 | 243 | [84; 85) '1': i32 |
244 | [98; 123) '{ ... }': &[i32] | 244 | [98; 123) '{ ... }': &[i32] |
245 | [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T] | 245 | [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T] |
246 | [108; 117) 'foo(&[1])': &[i32] | 246 | [108; 117) 'foo(&[1])': &[i32] |
247 | [112; 116) '&[1]': &[i32;_] | 247 | [112; 116) '&[1]': &[i32; _] |
248 | [113; 116) '[1]': [i32;_] | 248 | [113; 116) '[1]': [i32; _] |
249 | [114; 115) '1': i32 | 249 | [114; 115) '1': i32 |
250 | "### | 250 | "### |
251 | ); | 251 | ); |
@@ -277,16 +277,16 @@ fn test(i: i32) { | |||
277 | [88; 89) '2': i32 | 277 | [88; 89) '2': i32 |
278 | [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T] | 278 | [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T] |
279 | [93; 102) 'foo(&[2])': &[i32] | 279 | [93; 102) 'foo(&[2])': &[i32] |
280 | [97; 101) '&[2]': &[i32;_] | 280 | [97; 101) '&[2]': &[i32; _] |
281 | [98; 101) '[2]': [i32;_] | 281 | [98; 101) '[2]': [i32; _] |
282 | [99; 100) '2': i32 | 282 | [99; 100) '2': i32 |
283 | [112; 113) '1': i32 | 283 | [112; 113) '1': i32 |
284 | [117; 121) '&[1]': &[i32;_] | 284 | [117; 121) '&[1]': &[i32; _] |
285 | [118; 121) '[1]': [i32;_] | 285 | [118; 121) '[1]': [i32; _] |
286 | [119; 120) '1': i32 | 286 | [119; 120) '1': i32 |
287 | [131; 132) '_': i32 | 287 | [131; 132) '_': i32 |
288 | [136; 140) '&[3]': &[i32;_] | 288 | [136; 140) '&[3]': &[i32; _] |
289 | [137; 140) '[3]': [i32;_] | 289 | [137; 140) '[3]': [i32; _] |
290 | [138; 139) '3': i32 | 290 | [138; 139) '3': i32 |
291 | "### | 291 | "### |
292 | ); | 292 | ); |
@@ -316,18 +316,18 @@ fn test(i: i32) { | |||
316 | [70; 147) 'match ... }': &[i32] | 316 | [70; 147) 'match ... }': &[i32] |
317 | [76; 77) 'i': i32 | 317 | [76; 77) 'i': i32 |
318 | [88; 89) '1': i32 | 318 | [88; 89) '1': i32 |
319 | [93; 97) '&[1]': &[i32;_] | 319 | [93; 97) '&[1]': &[i32; _] |
320 | [94; 97) '[1]': [i32;_] | 320 | [94; 97) '[1]': [i32; _] |
321 | [95; 96) '1': i32 | 321 | [95; 96) '1': i32 |
322 | [107; 108) '2': i32 | 322 | [107; 108) '2': i32 |
323 | [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T] | 323 | [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T] |
324 | [112; 121) 'foo(&[2])': &[i32] | 324 | [112; 121) 'foo(&[2])': &[i32] |
325 | [116; 120) '&[2]': &[i32;_] | 325 | [116; 120) '&[2]': &[i32; _] |
326 | [117; 120) '[2]': [i32;_] | 326 | [117; 120) '[2]': [i32; _] |
327 | [118; 119) '2': i32 | 327 | [118; 119) '2': i32 |
328 | [131; 132) '_': i32 | 328 | [131; 132) '_': i32 |
329 | [136; 140) '&[3]': &[i32;_] | 329 | [136; 140) '&[3]': &[i32; _] |
330 | [137; 140) '[3]': [i32;_] | 330 | [137; 140) '[3]': [i32; _] |
331 | [138; 139) '3': i32 | 331 | [138; 139) '3': i32 |
332 | "### | 332 | "### |
333 | ); | 333 | ); |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index aa948dcbf..02bab6dbe 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -102,7 +102,7 @@ fn test() { | |||
102 | [11; 48) '{ ...&y]; }': () | 102 | [11; 48) '{ ...&y]; }': () |
103 | [21; 22) 'y': &{unknown} | 103 | [21; 22) 'y': &{unknown} |
104 | [25; 32) 'unknown': &{unknown} | 104 | [25; 32) 'unknown': &{unknown} |
105 | [38; 45) '[y, &y]': [&&{unknown};_] | 105 | [38; 45) '[y, &y]': [&&{unknown}; _] |
106 | [39; 40) 'y': &{unknown} | 106 | [39; 40) 'y': &{unknown} |
107 | [42; 44) '&y': &&{unknown} | 107 | [42; 44) '&y': &&{unknown} |
108 | [43; 44) 'y': &{unknown} | 108 | [43; 44) 'y': &{unknown} |
@@ -128,7 +128,7 @@ fn test() { | |||
128 | [25; 32) 'unknown': &&{unknown} | 128 | [25; 32) 'unknown': &&{unknown} |
129 | [42; 43) 'y': &&{unknown} | 129 | [42; 43) 'y': &&{unknown} |
130 | [46; 53) 'unknown': &&{unknown} | 130 | [46; 53) 'unknown': &&{unknown} |
131 | [59; 77) '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown});_] | 131 | [59; 77) '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] |
132 | [60; 66) '(x, y)': (&&&{unknown}, &&&{unknown}) | 132 | [60; 66) '(x, y)': (&&&{unknown}, &&&{unknown}) |
133 | [61; 62) 'x': &&{unknown} | 133 | [61; 62) 'x': &&{unknown} |
134 | [64; 65) 'y': &&{unknown} | 134 | [64; 65) 'y': &&{unknown} |
@@ -180,8 +180,8 @@ fn test_line_buffer() { | |||
180 | "#), | 180 | "#), |
181 | @r###" | 181 | @r###" |
182 | [23; 53) '{ ...n']; }': () | 182 | [23; 53) '{ ...n']; }': () |
183 | [29; 50) '&[0, b...b'\n']': &[u8;_] | 183 | [29; 50) '&[0, b...b'\n']': &[u8; _] |
184 | [30; 50) '[0, b'...b'\n']': [u8;_] | 184 | [30; 50) '[0, b'...b'\n']': [u8; _] |
185 | [31; 32) '0': u8 | 185 | [31; 32) '0': u8 |
186 | [34; 39) 'b'\n'': u8 | 186 | [34; 39) 'b'\n'': u8 |
187 | [41; 42) '1': u8 | 187 | [41; 42) '1': u8 |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index b7204ec00..fdab9c187 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -28,7 +28,7 @@ mod boxed { | |||
28 | 28 | ||
29 | "#, | 29 | "#, |
30 | ); | 30 | ); |
31 | assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos)); | 31 | assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>)", type_at_pos(&db, pos)); |
32 | } | 32 | } |
33 | 33 | ||
34 | #[test] | 34 | #[test] |
@@ -1061,55 +1061,55 @@ fn test(x: &str, y: isize) { | |||
1061 | [9; 10) 'x': &str | 1061 | [9; 10) 'x': &str |
1062 | [18; 19) 'y': isize | 1062 | [18; 19) 'y': isize |
1063 | [28; 293) '{ ... []; }': () | 1063 | [28; 293) '{ ... []; }': () |
1064 | [38; 39) 'a': [&str;_] | 1064 | [38; 39) 'a': [&str; _] |
1065 | [42; 45) '[x]': [&str;_] | 1065 | [42; 45) '[x]': [&str; _] |
1066 | [43; 44) 'x': &str | 1066 | [43; 44) 'x': &str |
1067 | [55; 56) 'b': [[&str;_];_] | 1067 | [55; 56) 'b': [[&str; _]; _] |
1068 | [59; 65) '[a, a]': [[&str;_];_] | 1068 | [59; 65) '[a, a]': [[&str; _]; _] |
1069 | [60; 61) 'a': [&str;_] | 1069 | [60; 61) 'a': [&str; _] |
1070 | [63; 64) 'a': [&str;_] | 1070 | [63; 64) 'a': [&str; _] |
1071 | [75; 76) 'c': [[[&str;_];_];_] | 1071 | [75; 76) 'c': [[[&str; _]; _]; _] |
1072 | [79; 85) '[b, b]': [[[&str;_];_];_] | 1072 | [79; 85) '[b, b]': [[[&str; _]; _]; _] |
1073 | [80; 81) 'b': [[&str;_];_] | 1073 | [80; 81) 'b': [[&str; _]; _] |
1074 | [83; 84) 'b': [[&str;_];_] | 1074 | [83; 84) 'b': [[&str; _]; _] |
1075 | [96; 97) 'd': [isize;_] | 1075 | [96; 97) 'd': [isize; _] |
1076 | [100; 112) '[y, 1, 2, 3]': [isize;_] | 1076 | [100; 112) '[y, 1, 2, 3]': [isize; _] |
1077 | [101; 102) 'y': isize | 1077 | [101; 102) 'y': isize |
1078 | [104; 105) '1': isize | 1078 | [104; 105) '1': isize |
1079 | [107; 108) '2': isize | 1079 | [107; 108) '2': isize |
1080 | [110; 111) '3': isize | 1080 | [110; 111) '3': isize |
1081 | [122; 123) 'd': [isize;_] | 1081 | [122; 123) 'd': [isize; _] |
1082 | [126; 138) '[1, y, 2, 3]': [isize;_] | 1082 | [126; 138) '[1, y, 2, 3]': [isize; _] |
1083 | [127; 128) '1': isize | 1083 | [127; 128) '1': isize |
1084 | [130; 131) 'y': isize | 1084 | [130; 131) 'y': isize |
1085 | [133; 134) '2': isize | 1085 | [133; 134) '2': isize |
1086 | [136; 137) '3': isize | 1086 | [136; 137) '3': isize |
1087 | [148; 149) 'e': [isize;_] | 1087 | [148; 149) 'e': [isize; _] |
1088 | [152; 155) '[y]': [isize;_] | 1088 | [152; 155) '[y]': [isize; _] |
1089 | [153; 154) 'y': isize | 1089 | [153; 154) 'y': isize |
1090 | [165; 166) 'f': [[isize;_];_] | 1090 | [165; 166) 'f': [[isize; _]; _] |
1091 | [169; 175) '[d, d]': [[isize;_];_] | 1091 | [169; 175) '[d, d]': [[isize; _]; _] |
1092 | [170; 171) 'd': [isize;_] | 1092 | [170; 171) 'd': [isize; _] |
1093 | [173; 174) 'd': [isize;_] | 1093 | [173; 174) 'd': [isize; _] |
1094 | [185; 186) 'g': [[isize;_];_] | 1094 | [185; 186) 'g': [[isize; _]; _] |
1095 | [189; 195) '[e, e]': [[isize;_];_] | 1095 | [189; 195) '[e, e]': [[isize; _]; _] |
1096 | [190; 191) 'e': [isize;_] | 1096 | [190; 191) 'e': [isize; _] |
1097 | [193; 194) 'e': [isize;_] | 1097 | [193; 194) 'e': [isize; _] |
1098 | [206; 207) 'h': [i32;_] | 1098 | [206; 207) 'h': [i32; _] |
1099 | [210; 216) '[1, 2]': [i32;_] | 1099 | [210; 216) '[1, 2]': [i32; _] |
1100 | [211; 212) '1': i32 | 1100 | [211; 212) '1': i32 |
1101 | [214; 215) '2': i32 | 1101 | [214; 215) '2': i32 |
1102 | [226; 227) 'i': [&str;_] | 1102 | [226; 227) 'i': [&str; _] |
1103 | [230; 240) '["a", "b"]': [&str;_] | 1103 | [230; 240) '["a", "b"]': [&str; _] |
1104 | [231; 234) '"a"': &str | 1104 | [231; 234) '"a"': &str |
1105 | [236; 239) '"b"': &str | 1105 | [236; 239) '"b"': &str |
1106 | [251; 252) 'b': [[&str;_];_] | 1106 | [251; 252) 'b': [[&str; _]; _] |
1107 | [255; 265) '[a, ["b"]]': [[&str;_];_] | 1107 | [255; 265) '[a, ["b"]]': [[&str; _]; _] |
1108 | [256; 257) 'a': [&str;_] | 1108 | [256; 257) 'a': [&str; _] |
1109 | [259; 264) '["b"]': [&str;_] | 1109 | [259; 264) '["b"]': [&str; _] |
1110 | [260; 263) '"b"': &str | 1110 | [260; 263) '"b"': &str |
1111 | [275; 276) 'x': [u8;_] | 1111 | [275; 276) 'x': [u8; _] |
1112 | [288; 290) '[]': [u8;_] | 1112 | [288; 290) '[]': [u8; _] |
1113 | "### | 1113 | "### |
1114 | ); | 1114 | ); |
1115 | } | 1115 | } |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index bc20a49cc..a6ac18f86 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -479,7 +479,7 @@ fn indexing_arrays() { | |||
479 | @r###" | 479 | @r###" |
480 | [10; 26) '{ &mut...[2]; }': () | 480 | [10; 26) '{ &mut...[2]; }': () |
481 | [12; 23) '&mut [9][2]': &mut {unknown} | 481 | [12; 23) '&mut [9][2]': &mut {unknown} |
482 | [17; 20) '[9]': [i32;_] | 482 | [17; 20) '[9]': [i32; _] |
483 | [17; 23) '[9][2]': {unknown} | 483 | [17; 23) '[9][2]': {unknown} |
484 | [18; 19) '9': i32 | 484 | [18; 19) '9': i32 |
485 | [21; 22) '2': i32 | 485 | [21; 22) '2': i32 |
diff --git a/crates/ra_ide/src/change.rs b/crates/ra_ide/src/change.rs index ce617840c..45a58690b 100644 --- a/crates/ra_ide/src/change.rs +++ b/crates/ra_ide/src/change.rs | |||
@@ -301,45 +301,74 @@ impl RootDatabase { | |||
301 | )*} | 301 | )*} |
302 | } | 302 | } |
303 | sweep_each_query![ | 303 | sweep_each_query![ |
304 | // SourceDatabase | ||
304 | ra_db::ParseQuery | 305 | ra_db::ParseQuery |
305 | ra_db::SourceRootCratesQuery | 306 | ra_db::SourceRootCratesQuery |
307 | |||
308 | // AstDatabase | ||
306 | hir::db::AstIdMapQuery | 309 | hir::db::AstIdMapQuery |
307 | hir::db::ParseMacroQuery | 310 | hir::db::InternMacroQuery |
308 | hir::db::MacroDefQuery | ||
309 | hir::db::MacroArgQuery | 311 | hir::db::MacroArgQuery |
312 | hir::db::MacroDefQuery | ||
313 | hir::db::ParseMacroQuery | ||
310 | hir::db::MacroExpandQuery | 314 | hir::db::MacroExpandQuery |
315 | |||
316 | // DefDatabase | ||
317 | hir::db::RawItemsQuery | ||
318 | hir::db::ComputeCrateDefMapQuery | ||
311 | hir::db::StructDataQuery | 319 | hir::db::StructDataQuery |
320 | hir::db::UnionDataQuery | ||
312 | hir::db::EnumDataQuery | 321 | hir::db::EnumDataQuery |
322 | hir::db::ImplDataQuery | ||
313 | hir::db::TraitDataQuery | 323 | hir::db::TraitDataQuery |
314 | hir::db::RawItemsQuery | ||
315 | hir::db::ComputeCrateDefMapQuery | ||
316 | hir::db::GenericParamsQuery | ||
317 | hir::db::FunctionDataQuery | ||
318 | hir::db::TypeAliasDataQuery | 324 | hir::db::TypeAliasDataQuery |
325 | hir::db::FunctionDataQuery | ||
319 | hir::db::ConstDataQuery | 326 | hir::db::ConstDataQuery |
320 | hir::db::StaticDataQuery | 327 | hir::db::StaticDataQuery |
328 | hir::db::BodyWithSourceMapQuery | ||
329 | hir::db::BodyQuery | ||
330 | hir::db::ExprScopesQuery | ||
331 | hir::db::GenericParamsQuery | ||
332 | hir::db::AttrsQuery | ||
321 | hir::db::ModuleLangItemsQuery | 333 | hir::db::ModuleLangItemsQuery |
322 | hir::db::CrateLangItemsQuery | 334 | hir::db::CrateLangItemsQuery |
323 | hir::db::LangItemQuery | 335 | hir::db::LangItemQuery |
324 | hir::db::DocumentationQuery | 336 | hir::db::DocumentationQuery |
325 | hir::db::ExprScopesQuery | 337 | |
338 | // InternDatabase | ||
339 | hir::db::InternFunctionQuery | ||
340 | hir::db::InternStructQuery | ||
341 | hir::db::InternUnionQuery | ||
342 | hir::db::InternEnumQuery | ||
343 | hir::db::InternConstQuery | ||
344 | hir::db::InternStaticQuery | ||
345 | hir::db::InternTraitQuery | ||
346 | hir::db::InternTypeAliasQuery | ||
347 | hir::db::InternImplQuery | ||
348 | |||
349 | // HirDatabase | ||
326 | hir::db::DoInferQuery | 350 | hir::db::DoInferQuery |
327 | hir::db::TyQuery | 351 | hir::db::TyQuery |
328 | hir::db::ValueTyQuery | 352 | hir::db::ValueTyQuery |
353 | hir::db::ImplSelfTyQuery | ||
354 | hir::db::ImplTraitQuery | ||
329 | hir::db::FieldTypesQuery | 355 | hir::db::FieldTypesQuery |
330 | hir::db::CallableItemSignatureQuery | 356 | hir::db::CallableItemSignatureQuery |
357 | hir::db::GenericPredicatesForParamQuery | ||
331 | hir::db::GenericPredicatesQuery | 358 | hir::db::GenericPredicatesQuery |
332 | hir::db::GenericDefaultsQuery | 359 | hir::db::GenericDefaultsQuery |
333 | hir::db::BodyWithSourceMapQuery | ||
334 | hir::db::BodyQuery | ||
335 | hir::db::ImplsInCrateQuery | 360 | hir::db::ImplsInCrateQuery |
336 | hir::db::ImplsForTraitQuery | 361 | hir::db::ImplsForTraitQuery |
362 | hir::db::TraitSolverQuery | ||
363 | hir::db::InternTypeCtorQuery | ||
364 | hir::db::InternChalkImplQuery | ||
365 | hir::db::InternAssocTyValueQuery | ||
337 | hir::db::AssociatedTyDataQuery | 366 | hir::db::AssociatedTyDataQuery |
367 | hir::db::AssociatedTyValueQuery | ||
368 | hir::db::TraitSolveQuery | ||
338 | hir::db::TraitDatumQuery | 369 | hir::db::TraitDatumQuery |
339 | hir::db::StructDatumQuery | 370 | hir::db::StructDatumQuery |
340 | hir::db::ImplDatumQuery | 371 | hir::db::ImplDatumQuery |
341 | hir::db::ImplDataQuery | ||
342 | hir::db::TraitSolveQuery | ||
343 | ]; | 372 | ]; |
344 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); | 373 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); |
345 | acc | 374 | acc |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 15bf519c9..d850ded37 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -5,11 +5,18 @@ mod handlers; | |||
5 | mod subscriptions; | 5 | mod subscriptions; |
6 | pub(crate) mod pending_requests; | 6 | pub(crate) mod pending_requests; |
7 | 7 | ||
8 | use std::{error::Error, fmt, panic, path::PathBuf, sync::Arc, time::Instant}; | 8 | use std::{ |
9 | env, | ||
10 | error::Error, | ||
11 | fmt, panic, | ||
12 | path::PathBuf, | ||
13 | sync::Arc, | ||
14 | time::{Duration, Instant}, | ||
15 | }; | ||
9 | 16 | ||
10 | use crossbeam_channel::{select, unbounded, RecvError, Sender}; | 17 | use crossbeam_channel::{select, unbounded, RecvError, Sender}; |
11 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; | 18 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; |
12 | use lsp_types::{ClientCapabilities, NumberOrString, Url}; | 19 | use lsp_types::{ClientCapabilities, NumberOrString}; |
13 | use ra_cargo_watch::{CheckOptions, CheckTask}; | 20 | use ra_cargo_watch::{CheckOptions, CheckTask}; |
14 | use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; | 21 | use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; |
15 | use ra_prof::profile; | 22 | use ra_prof::profile; |
@@ -352,7 +359,7 @@ fn loop_turn( | |||
352 | world_state.maybe_collect_garbage(); | 359 | world_state.maybe_collect_garbage(); |
353 | loop_state.in_flight_libraries -= 1; | 360 | loop_state.in_flight_libraries -= 1; |
354 | } | 361 | } |
355 | Event::CheckWatcher(task) => on_check_task(task, world_state, task_sender)?, | 362 | Event::CheckWatcher(task) => on_check_task(pool, task, world_state, task_sender)?, |
356 | Event::Msg(msg) => match msg { | 363 | Event::Msg(msg) => match msg { |
357 | Message::Request(req) => on_request( | 364 | Message::Request(req) => on_request( |
358 | world_state, | 365 | world_state, |
@@ -425,6 +432,19 @@ fn loop_turn( | |||
425 | loop_state.subscriptions.subscriptions(), | 432 | loop_state.subscriptions.subscriptions(), |
426 | ) | 433 | ) |
427 | } | 434 | } |
435 | |||
436 | let loop_duration = loop_start.elapsed(); | ||
437 | if loop_duration > Duration::from_millis(100) { | ||
438 | log::error!("overly long loop turn: {:?}", loop_duration); | ||
439 | if env::var("RA_PROFILE").is_ok() { | ||
440 | show_message( | ||
441 | req::MessageType::Error, | ||
442 | format!("overly long loop turn: {:?}", loop_duration), | ||
443 | &connection.sender, | ||
444 | ); | ||
445 | } | ||
446 | } | ||
447 | |||
428 | Ok(()) | 448 | Ok(()) |
429 | } | 449 | } |
430 | 450 | ||
@@ -452,7 +472,7 @@ fn on_request( | |||
452 | world: &mut WorldState, | 472 | world: &mut WorldState, |
453 | pending_requests: &mut PendingRequests, | 473 | pending_requests: &mut PendingRequests, |
454 | pool: &ThreadPool, | 474 | pool: &ThreadPool, |
455 | sender: &Sender<Task>, | 475 | task_sender: &Sender<Task>, |
456 | msg_sender: &Sender<Message>, | 476 | msg_sender: &Sender<Message>, |
457 | request_received: Instant, | 477 | request_received: Instant, |
458 | req: Request, | 478 | req: Request, |
@@ -461,7 +481,7 @@ fn on_request( | |||
461 | req: Some(req), | 481 | req: Some(req), |
462 | pool, | 482 | pool, |
463 | world, | 483 | world, |
464 | sender, | 484 | task_sender, |
465 | msg_sender, | 485 | msg_sender, |
466 | pending_requests, | 486 | pending_requests, |
467 | request_received, | 487 | request_received, |
@@ -602,31 +622,23 @@ fn on_notification( | |||
602 | } | 622 | } |
603 | 623 | ||
604 | fn on_check_task( | 624 | fn on_check_task( |
625 | pool: &ThreadPool, | ||
605 | task: CheckTask, | 626 | task: CheckTask, |
606 | world_state: &mut WorldState, | 627 | world_state: &mut WorldState, |
607 | task_sender: &Sender<Task>, | 628 | task_sender: &Sender<Task>, |
608 | ) -> Result<()> { | 629 | ) -> Result<()> { |
609 | match task { | 630 | let urls = match task { |
610 | CheckTask::ClearDiagnostics => { | 631 | CheckTask::ClearDiagnostics => { |
611 | let state = Arc::get_mut(&mut world_state.check_watcher.state) | 632 | let state = Arc::get_mut(&mut world_state.check_watcher.state) |
612 | .expect("couldn't get check watcher state as mutable"); | 633 | .expect("couldn't get check watcher state as mutable"); |
613 | let cleared_files = state.clear(); | 634 | state.clear() |
614 | |||
615 | // Send updated diagnostics for each cleared file | ||
616 | for url in cleared_files { | ||
617 | publish_diagnostics_for_url(&url, world_state, task_sender)?; | ||
618 | } | ||
619 | } | 635 | } |
620 | 636 | ||
621 | CheckTask::AddDiagnostic(url, diagnostic) => { | 637 | CheckTask::AddDiagnostic(url, diagnostic) => { |
622 | let state = Arc::get_mut(&mut world_state.check_watcher.state) | 638 | let state = Arc::get_mut(&mut world_state.check_watcher.state) |
623 | .expect("couldn't get check watcher state as mutable"); | 639 | .expect("couldn't get check watcher state as mutable"); |
624 | state.add_diagnostic_with_fixes(url.clone(), diagnostic); | 640 | state.add_diagnostic_with_fixes(url.clone(), diagnostic); |
625 | 641 | vec![url] | |
626 | // We manually send a diagnostic update when the watcher asks | ||
627 | // us to, to avoid the issue of having to change the file to | ||
628 | // receive updated diagnostics. | ||
629 | publish_diagnostics_for_url(&url, world_state, task_sender)?; | ||
630 | } | 642 | } |
631 | 643 | ||
632 | CheckTask::Status(progress) => { | 644 | CheckTask::Status(progress) => { |
@@ -636,22 +648,30 @@ fn on_check_task( | |||
636 | }; | 648 | }; |
637 | let not = notification_new::<req::Progress>(params); | 649 | let not = notification_new::<req::Progress>(params); |
638 | task_sender.send(Task::Notify(not)).unwrap(); | 650 | task_sender.send(Task::Notify(not)).unwrap(); |
651 | Vec::new() | ||
639 | } | 652 | } |
640 | } | 653 | }; |
641 | Ok(()) | 654 | |
642 | } | 655 | let subscriptions = urls |
656 | .into_iter() | ||
657 | .map(|url| { | ||
658 | let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?; | ||
659 | Ok(world_state.vfs.read().path2file(&path).map(|it| FileId(it.0))) | ||
660 | }) | ||
661 | .filter_map(|res| res.transpose()) | ||
662 | .collect::<Result<Vec<_>>>()?; | ||
663 | |||
664 | // We manually send a diagnostic update when the watcher asks | ||
665 | // us to, to avoid the issue of having to change the file to | ||
666 | // receive updated diagnostics. | ||
667 | update_file_notifications_on_threadpool( | ||
668 | pool, | ||
669 | world_state.snapshot(), | ||
670 | false, | ||
671 | task_sender.clone(), | ||
672 | subscriptions, | ||
673 | ); | ||
643 | 674 | ||
644 | fn publish_diagnostics_for_url( | ||
645 | url: &Url, | ||
646 | world_state: &WorldState, | ||
647 | task_sender: &Sender<Task>, | ||
648 | ) -> Result<()> { | ||
649 | let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?; | ||
650 | if let Some(file_id) = world_state.vfs.read().path2file(&path) { | ||
651 | let params = handlers::publish_diagnostics(&world_state.snapshot(), FileId(file_id.0))?; | ||
652 | let not = notification_new::<req::PublishDiagnostics>(params); | ||
653 | task_sender.send(Task::Notify(not)).unwrap(); | ||
654 | } | ||
655 | Ok(()) | 675 | Ok(()) |
656 | } | 676 | } |
657 | 677 | ||
@@ -661,7 +681,7 @@ struct PoolDispatcher<'a> { | |||
661 | world: &'a mut WorldState, | 681 | world: &'a mut WorldState, |
662 | pending_requests: &'a mut PendingRequests, | 682 | pending_requests: &'a mut PendingRequests, |
663 | msg_sender: &'a Sender<Message>, | 683 | msg_sender: &'a Sender<Message>, |
664 | sender: &'a Sender<Task>, | 684 | task_sender: &'a Sender<Task>, |
665 | request_received: Instant, | 685 | request_received: Instant, |
666 | } | 686 | } |
667 | 687 | ||
@@ -708,7 +728,7 @@ impl<'a> PoolDispatcher<'a> { | |||
708 | 728 | ||
709 | self.pool.execute({ | 729 | self.pool.execute({ |
710 | let world = self.world.snapshot(); | 730 | let world = self.world.snapshot(); |
711 | let sender = self.sender.clone(); | 731 | let sender = self.task_sender.clone(); |
712 | move || { | 732 | move || { |
713 | let result = f(world, params); | 733 | let result = f(world, params); |
714 | let task = result_to_task::<R>(id, result); | 734 | let task = result_to_task::<R>(id, result); |
@@ -786,7 +806,7 @@ fn update_file_notifications_on_threadpool( | |||
786 | pool: &ThreadPool, | 806 | pool: &ThreadPool, |
787 | world: WorldSnapshot, | 807 | world: WorldSnapshot, |
788 | publish_decorations: bool, | 808 | publish_decorations: bool, |
789 | sender: Sender<Task>, | 809 | task_sender: Sender<Task>, |
790 | subscriptions: Vec<FileId>, | 810 | subscriptions: Vec<FileId>, |
791 | ) { | 811 | ) { |
792 | log::trace!("updating notifications for {:?}", subscriptions); | 812 | log::trace!("updating notifications for {:?}", subscriptions); |
@@ -802,7 +822,7 @@ fn update_file_notifications_on_threadpool( | |||
802 | } | 822 | } |
803 | Ok(params) => { | 823 | Ok(params) => { |
804 | let not = notification_new::<req::PublishDiagnostics>(params); | 824 | let not = notification_new::<req::PublishDiagnostics>(params); |
805 | sender.send(Task::Notify(not)).unwrap(); | 825 | task_sender.send(Task::Notify(not)).unwrap(); |
806 | } | 826 | } |
807 | } | 827 | } |
808 | } | 828 | } |
@@ -815,7 +835,7 @@ fn update_file_notifications_on_threadpool( | |||
815 | } | 835 | } |
816 | Ok(params) => { | 836 | Ok(params) => { |
817 | let not = notification_new::<req::PublishDecorations>(params); | 837 | let not = notification_new::<req::PublishDecorations>(params); |
818 | sender.send(Task::Notify(not)).unwrap(); | 838 | task_sender.send(Task::Notify(not)).unwrap(); |
819 | } | 839 | } |
820 | } | 840 | } |
821 | } | 841 | } |
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index c7973ddf4..4a49e9f95 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs | |||
@@ -6,9 +6,9 @@ mod google_cpu_profiler; | |||
6 | 6 | ||
7 | use std::{ | 7 | use std::{ |
8 | cell::RefCell, | 8 | cell::RefCell, |
9 | collections::BTreeMap, | ||
9 | collections::HashSet, | 10 | collections::HashSet, |
10 | io::{stderr, Write}, | 11 | io::{stderr, Write}, |
11 | iter::repeat, | ||
12 | mem, | 12 | mem, |
13 | sync::{ | 13 | sync::{ |
14 | atomic::{AtomicBool, Ordering}, | 14 | atomic::{AtomicBool, Ordering}, |
@@ -17,7 +17,6 @@ use std::{ | |||
17 | time::{Duration, Instant}, | 17 | time::{Duration, Instant}, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | use itertools::Itertools; | ||
21 | use once_cell::sync::Lazy; | 20 | use once_cell::sync::Lazy; |
22 | 21 | ||
23 | pub use crate::memory_usage::{Bytes, MemoryUsage}; | 22 | pub use crate::memory_usage::{Bytes, MemoryUsage}; |
@@ -216,7 +215,7 @@ impl Drop for Profiler { | |||
216 | // (otherwise we could print `0ms` despite user's `>0` filter when | 215 | // (otherwise we could print `0ms` despite user's `>0` filter when |
217 | // `duration` is just a few nanos). | 216 | // `duration` is just a few nanos). |
218 | if duration.as_millis() > longer_than.as_millis() { | 217 | if duration.as_millis() > longer_than.as_millis() { |
219 | print(0, &stack.messages, &mut stdout.lock(), longer_than, None); | 218 | print(&stack.messages, longer_than, &mut stdout.lock()); |
220 | } | 219 | } |
221 | stack.messages.clear(); | 220 | stack.messages.clear(); |
222 | } | 221 | } |
@@ -227,59 +226,85 @@ impl Drop for Profiler { | |||
227 | } | 226 | } |
228 | } | 227 | } |
229 | 228 | ||
230 | fn print( | 229 | fn print(msgs: &[Message], longer_than: Duration, out: &mut impl Write) { |
231 | lvl: usize, | ||
232 | msgs: &[Message], | ||
233 | out: &mut impl Write, | ||
234 | longer_than: Duration, | ||
235 | total: Option<Duration>, | ||
236 | ) { | ||
237 | if msgs.is_empty() { | 230 | if msgs.is_empty() { |
238 | return; | 231 | return; |
239 | } | 232 | } |
240 | // The index of the first element that will be included in the slice when we recurse. | 233 | let children_map = idx_to_children(msgs); |
241 | let mut next_start = 0; | 234 | let root_idx = msgs.len() - 1; |
242 | let indent = repeat(" ").take(lvl).collect::<String>(); | 235 | print_for_idx(root_idx, &children_map, msgs, longer_than, out); |
243 | // We output hierarchy for long calls, but sum up all short calls | 236 | } |
244 | let mut short = Vec::new(); | 237 | |
238 | fn print_for_idx( | ||
239 | current_idx: usize, | ||
240 | children_map: &[Vec<usize>], | ||
241 | msgs: &[Message], | ||
242 | longer_than: Duration, | ||
243 | out: &mut impl Write, | ||
244 | ) { | ||
245 | let current = &msgs[current_idx]; | ||
246 | let current_indent = " ".repeat(current.level); | ||
247 | writeln!(out, "{}{:5}ms - {}", current_indent, current.duration.as_millis(), current.message) | ||
248 | .expect("printing profiling info"); | ||
249 | |||
250 | let longer_than_millis = longer_than.as_millis(); | ||
251 | let children_indices = &children_map[current_idx]; | ||
245 | let mut accounted_for = Duration::default(); | 252 | let mut accounted_for = Duration::default(); |
246 | for (i, &Message { level, duration, message: ref msg }) in msgs.iter().enumerate() { | 253 | let mut short_children = BTreeMap::new(); // Use `BTreeMap` to get deterministic output. |
247 | if level != lvl { | ||
248 | continue; | ||
249 | } | ||
250 | accounted_for += duration; | ||
251 | if duration.as_millis() > longer_than.as_millis() { | ||
252 | writeln!(out, "{}{:5}ms - {}", indent, duration.as_millis(), msg) | ||
253 | .expect("printing profiling info to stdout"); | ||
254 | 254 | ||
255 | print(lvl + 1, &msgs[next_start..i], out, longer_than, Some(duration)); | 255 | for child_idx in children_indices.iter() { |
256 | let child = &msgs[*child_idx]; | ||
257 | if child.duration.as_millis() > longer_than_millis { | ||
258 | print_for_idx(*child_idx, children_map, msgs, longer_than, out); | ||
256 | } else { | 259 | } else { |
257 | short.push((msg, duration)) | 260 | let pair = short_children.entry(&child.message).or_insert((Duration::default(), 0)); |
261 | pair.0 += child.duration; | ||
262 | pair.1 += 1; | ||
258 | } | 263 | } |
264 | accounted_for += child.duration; | ||
265 | } | ||
259 | 266 | ||
260 | next_start = i + 1; | 267 | for (child_msg, (duration, count)) in short_children.iter() { |
268 | let millis = duration.as_millis(); | ||
269 | writeln!(out, " {}{:5}ms - {} ({} calls)", current_indent, millis, child_msg, count) | ||
270 | .expect("printing profiling info"); | ||
261 | } | 271 | } |
262 | short.sort_by_key(|(msg, _time)| *msg); | 272 | |
263 | for (msg, entires) in short.iter().group_by(|(msg, _time)| msg).into_iter() { | 273 | let unaccounted_millis = (current.duration - accounted_for).as_millis(); |
264 | let mut count = 0; | 274 | if !children_indices.is_empty() |
265 | let mut total_duration = Duration::default(); | 275 | && unaccounted_millis > 0 |
266 | entires.for_each(|(_msg, time)| { | 276 | && unaccounted_millis > longer_than_millis |
267 | count += 1; | 277 | { |
268 | total_duration += *time; | 278 | writeln!(out, " {}{:5}ms - ???", current_indent, unaccounted_millis) |
269 | }); | 279 | .expect("printing profiling info"); |
270 | writeln!(out, "{}{:5}ms - {} ({} calls)", indent, total_duration.as_millis(), msg, count) | ||
271 | .expect("printing profiling info to stdout"); | ||
272 | } | 280 | } |
281 | } | ||
273 | 282 | ||
274 | if let Some(total) = total { | 283 | /// Returns a mapping from an index in the `msgs` to the vector with the indices of its children. |
275 | if let Some(unaccounted) = total.checked_sub(accounted_for) { | 284 | /// |
276 | let unaccounted_millis = unaccounted.as_millis(); | 285 | /// This assumes that the entries in `msgs` are in the order of when the calls to `profile` finish. |
277 | if unaccounted_millis > longer_than.as_millis() && unaccounted_millis > 0 { | 286 | /// In other words, a postorder of the call graph. In particular, the root is the last element of |
278 | writeln!(out, "{}{:5}ms - ???", indent, unaccounted_millis) | 287 | /// `msgs`. |
279 | .expect("printing profiling info to stdout"); | 288 | fn idx_to_children(msgs: &[Message]) -> Vec<Vec<usize>> { |
280 | } | 289 | // Initialize with the index of the root; `msgs` and `ancestors` should be never empty. |
290 | assert!(!msgs.is_empty()); | ||
291 | let mut ancestors = vec![msgs.len() - 1]; | ||
292 | let mut result: Vec<Vec<usize>> = vec![vec![]; msgs.len()]; | ||
293 | for (idx, msg) in msgs[..msgs.len() - 1].iter().enumerate().rev() { | ||
294 | // We need to find the parent of the current message, i.e., the last ancestor that has a | ||
295 | // level lower than the current message. | ||
296 | while msgs[*ancestors.last().unwrap()].level >= msg.level { | ||
297 | ancestors.pop(); | ||
281 | } | 298 | } |
299 | result[*ancestors.last().unwrap()].push(idx); | ||
300 | ancestors.push(idx); | ||
301 | } | ||
302 | // Note that above we visited all children from the last to the first one. Let's reverse vectors | ||
303 | // to get the more natural order where the first element is the first child. | ||
304 | for vec in result.iter_mut() { | ||
305 | vec.reverse(); | ||
282 | } | 306 | } |
307 | result | ||
283 | } | 308 | } |
284 | 309 | ||
285 | /// Prints backtrace to stderr, useful for debugging. | 310 | /// Prints backtrace to stderr, useful for debugging. |
@@ -388,7 +413,7 @@ mod tests { | |||
388 | Message { level: 1, duration: Duration::from_nanos(2), message: "bar".to_owned() }, | 413 | Message { level: 1, duration: Duration::from_nanos(2), message: "bar".to_owned() }, |
389 | Message { level: 0, duration: Duration::from_millis(1), message: "foo".to_owned() }, | 414 | Message { level: 0, duration: Duration::from_millis(1), message: "foo".to_owned() }, |
390 | ]; | 415 | ]; |
391 | print(0, &msgs, &mut result, Duration::from_millis(0), Some(Duration::from_millis(1))); | 416 | print(&msgs, Duration::from_millis(0), &mut result); |
392 | // The calls to `bar` are so short that they'll be rounded to 0ms and should get collapsed | 417 | // The calls to `bar` are so short that they'll be rounded to 0ms and should get collapsed |
393 | // when printing. | 418 | // when printing. |
394 | assert_eq!( | 419 | assert_eq!( |
@@ -404,7 +429,7 @@ mod tests { | |||
404 | Message { level: 1, duration: Duration::from_millis(2), message: "bar".to_owned() }, | 429 | Message { level: 1, duration: Duration::from_millis(2), message: "bar".to_owned() }, |
405 | Message { level: 0, duration: Duration::from_millis(5), message: "foo".to_owned() }, | 430 | Message { level: 0, duration: Duration::from_millis(5), message: "foo".to_owned() }, |
406 | ]; | 431 | ]; |
407 | print(0, &msgs, &mut result, Duration::from_millis(0), Some(Duration::from_millis(1))); | 432 | print(&msgs, Duration::from_millis(0), &mut result); |
408 | assert_eq!( | 433 | assert_eq!( |
409 | std::str::from_utf8(&result).unwrap().lines().collect::<Vec<_>>(), | 434 | std::str::from_utf8(&result).unwrap().lines().collect::<Vec<_>>(), |
410 | vec![ | 435 | vec![ |
@@ -426,7 +451,7 @@ mod tests { | |||
426 | Message { level: 1, duration: Duration::from_millis(4), message: "bar".to_owned() }, | 451 | Message { level: 1, duration: Duration::from_millis(4), message: "bar".to_owned() }, |
427 | Message { level: 0, duration: Duration::from_millis(9), message: "foo".to_owned() }, | 452 | Message { level: 0, duration: Duration::from_millis(9), message: "foo".to_owned() }, |
428 | ]; | 453 | ]; |
429 | print(0, &msgs, &mut result, Duration::from_millis(0), None); | 454 | print(&msgs, Duration::from_millis(0), &mut result); |
430 | assert_eq!( | 455 | assert_eq!( |
431 | std::str::from_utf8(&result).unwrap().lines().collect::<Vec<_>>(), | 456 | std::str::from_utf8(&result).unwrap().lines().collect::<Vec<_>>(), |
432 | vec![ | 457 | vec![ |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 659f77b71..336c594a6 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -21,6 +21,12 @@ pub use difference::Changeset as __Changeset; | |||
21 | 21 | ||
22 | pub const CURSOR_MARKER: &str = "<|>"; | 22 | pub const CURSOR_MARKER: &str = "<|>"; |
23 | 23 | ||
24 | /// Asserts that two strings are equal, otherwise displays a rich diff between them. | ||
25 | /// | ||
26 | /// The diff shows changes from the "original" left string to the "actual" right string. | ||
27 | /// | ||
28 | /// All arguments starting from and including the 3rd one are passed to | ||
29 | /// `eprintln!()` macro in case of text inequality. | ||
24 | #[macro_export] | 30 | #[macro_export] |
25 | macro_rules! assert_eq_text { | 31 | macro_rules! assert_eq_text { |
26 | ($left:expr, $right:expr) => { | 32 | ($left:expr, $right:expr) => { |
@@ -42,6 +48,7 @@ macro_rules! assert_eq_text { | |||
42 | }}; | 48 | }}; |
43 | } | 49 | } |
44 | 50 | ||
51 | /// Infallible version of `try_extract_offset()`. | ||
45 | pub fn extract_offset(text: &str) -> (TextUnit, String) { | 52 | pub fn extract_offset(text: &str) -> (TextUnit, String) { |
46 | match try_extract_offset(text) { | 53 | match try_extract_offset(text) { |
47 | None => panic!("text should contain cursor marker"), | 54 | None => panic!("text should contain cursor marker"), |
@@ -49,6 +56,8 @@ pub fn extract_offset(text: &str) -> (TextUnit, String) { | |||
49 | } | 56 | } |
50 | } | 57 | } |
51 | 58 | ||
59 | /// Returns the offset of the first occurence of `<|>` marker and the copy of `text` | ||
60 | /// without the marker. | ||
52 | fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> { | 61 | fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> { |
53 | let cursor_pos = text.find(CURSOR_MARKER)?; | 62 | let cursor_pos = text.find(CURSOR_MARKER)?; |
54 | let mut new_text = String::with_capacity(text.len() - CURSOR_MARKER.len()); | 63 | let mut new_text = String::with_capacity(text.len() - CURSOR_MARKER.len()); |
@@ -58,6 +67,7 @@ fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> { | |||
58 | Some((cursor_pos, new_text)) | 67 | Some((cursor_pos, new_text)) |
59 | } | 68 | } |
60 | 69 | ||
70 | /// Infallible version of `try_extract_range()`. | ||
61 | pub fn extract_range(text: &str) -> (TextRange, String) { | 71 | pub fn extract_range(text: &str) -> (TextRange, String) { |
62 | match try_extract_range(text) { | 72 | match try_extract_range(text) { |
63 | None => panic!("text should contain cursor marker"), | 73 | None => panic!("text should contain cursor marker"), |
@@ -65,6 +75,8 @@ pub fn extract_range(text: &str) -> (TextRange, String) { | |||
65 | } | 75 | } |
66 | } | 76 | } |
67 | 77 | ||
78 | /// Returns `TextRange` between the first two markers `<|>...<|>` and the copy | ||
79 | /// of `text` without both of these markers. | ||
68 | fn try_extract_range(text: &str) -> Option<(TextRange, String)> { | 80 | fn try_extract_range(text: &str) -> Option<(TextRange, String)> { |
69 | let (start, text) = try_extract_offset(text)?; | 81 | let (start, text) = try_extract_offset(text)?; |
70 | let (end, text) = try_extract_offset(&text)?; | 82 | let (end, text) = try_extract_offset(&text)?; |
@@ -85,6 +97,11 @@ impl From<RangeOrOffset> for TextRange { | |||
85 | } | 97 | } |
86 | } | 98 | } |
87 | 99 | ||
100 | /// Extracts `TextRange` or `TextUnit` depending on the amount of `<|>` markers | ||
101 | /// found in `text`. | ||
102 | /// | ||
103 | /// # Panics | ||
104 | /// Panics if no `<|>` marker is present in the `text`. | ||
88 | pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) { | 105 | pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) { |
89 | if let Some((range, text)) = try_extract_range(text) { | 106 | if let Some((range, text)) = try_extract_range(text) { |
90 | return (RangeOrOffset::Range(range), text); | 107 | return (RangeOrOffset::Range(range), text); |
@@ -93,7 +110,7 @@ pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) { | |||
93 | (RangeOrOffset::Offset(offset), text) | 110 | (RangeOrOffset::Offset(offset), text) |
94 | } | 111 | } |
95 | 112 | ||
96 | /// Extracts ranges, marked with `<tag> </tag>` paris from the `text` | 113 | /// Extracts ranges, marked with `<tag> </tag>` pairs from the `text` |
97 | pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { | 114 | pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { |
98 | let open = format!("<{}>", tag); | 115 | let open = format!("<{}>", tag); |
99 | let close = format!("</{}>", tag); | 116 | let close = format!("</{}>", tag); |
@@ -127,9 +144,9 @@ pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { | |||
127 | (ranges, res) | 144 | (ranges, res) |
128 | } | 145 | } |
129 | 146 | ||
147 | /// Inserts `<|>` marker into the `text` at `offset`. | ||
130 | pub fn add_cursor(text: &str, offset: TextUnit) -> String { | 148 | pub fn add_cursor(text: &str, offset: TextUnit) -> String { |
131 | let offset: u32 = offset.into(); | 149 | let offset: usize = offset.to_usize(); |
132 | let offset: usize = offset as usize; | ||
133 | let mut res = String::new(); | 150 | let mut res = String::new(); |
134 | res.push_str(&text[..offset]); | 151 | res.push_str(&text[..offset]); |
135 | res.push_str("<|>"); | 152 | res.push_str("<|>"); |
@@ -152,19 +169,6 @@ pub struct FixtureEntry { | |||
152 | /// // - other meta | 169 | /// // - other meta |
153 | /// ``` | 170 | /// ``` |
154 | pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { | 171 | pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { |
155 | let mut res = Vec::new(); | ||
156 | let mut buf = String::new(); | ||
157 | let mut meta: Option<&str> = None; | ||
158 | |||
159 | macro_rules! flush { | ||
160 | () => { | ||
161 | if let Some(meta) = meta { | ||
162 | res.push(FixtureEntry { meta: meta.to_string(), text: buf.clone() }); | ||
163 | buf.clear(); | ||
164 | } | ||
165 | }; | ||
166 | }; | ||
167 | |||
168 | let margin = fixture | 172 | let margin = fixture |
169 | .lines() | 173 | .lines() |
170 | .filter(|it| it.trim_start().starts_with("//-")) | 174 | .filter(|it| it.trim_start().starts_with("//-")) |
@@ -172,7 +176,7 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { | |||
172 | .next() | 176 | .next() |
173 | .expect("empty fixture"); | 177 | .expect("empty fixture"); |
174 | 178 | ||
175 | let lines = fixture | 179 | let mut lines = fixture |
176 | .split('\n') // don't use `.lines` to not drop `\r\n` | 180 | .split('\n') // don't use `.lines` to not drop `\r\n` |
177 | .filter_map(|line| { | 181 | .filter_map(|line| { |
178 | if line.len() >= margin { | 182 | if line.len() >= margin { |
@@ -184,17 +188,16 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { | |||
184 | } | 188 | } |
185 | }); | 189 | }); |
186 | 190 | ||
187 | for line in lines { | 191 | let mut res: Vec<FixtureEntry> = Vec::new(); |
192 | for line in lines.by_ref() { | ||
188 | if line.starts_with("//-") { | 193 | if line.starts_with("//-") { |
189 | flush!(); | 194 | let meta = line["//-".len()..].trim().to_string(); |
190 | buf.clear(); | 195 | res.push(FixtureEntry { meta, text: String::new() }) |
191 | meta = Some(line["//-".len()..].trim()); | 196 | } else if let Some(entry) = res.last_mut() { |
192 | continue; | 197 | entry.text.push_str(line); |
198 | entry.text.push('\n'); | ||
193 | } | 199 | } |
194 | buf.push_str(line); | ||
195 | buf.push('\n'); | ||
196 | } | 200 | } |
197 | flush!(); | ||
198 | res | 201 | res |
199 | } | 202 | } |
200 | 203 | ||
@@ -236,11 +239,10 @@ fn lines_match_works() { | |||
236 | assert!(!lines_match("b", "cb")); | 239 | assert!(!lines_match("b", "cb")); |
237 | } | 240 | } |
238 | 241 | ||
239 | // Compares JSON object for approximate equality. | 242 | /// Compares JSON object for approximate equality. |
240 | // You can use `[..]` wildcard in strings (useful for OS dependent things such | 243 | /// You can use `[..]` wildcard in strings (useful for OS dependent things such |
241 | // as paths). You can use a `"{...}"` string literal as a wildcard for | 244 | /// as paths). You can use a `"{...}"` string literal as a wildcard for |
242 | // arbitrary nested JSON (useful for parts of object emitted by other programs | 245 | /// arbitrary nested JSON. Arrays are sorted before comparison. |
243 | // (e.g. rustc) rather than Cargo itself). Arrays are sorted before comparison. | ||
244 | pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a Value, &'a Value)> { | 246 | pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a Value, &'a Value)> { |
245 | use serde_json::Value::*; | 247 | use serde_json::Value::*; |
246 | match (expected, actual) { | 248 | match (expected, actual) { |
@@ -286,6 +288,14 @@ pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a | |||
286 | } | 288 | } |
287 | } | 289 | } |
288 | 290 | ||
291 | /// Calls callback `f` with input code and file paths of all `.rs` files from `test_data_dir` | ||
292 | /// subdirectories defined by `paths`. | ||
293 | /// | ||
294 | /// If the content of the matching `.txt` file differs from the output of `f()` | ||
295 | /// the test will fail. | ||
296 | /// | ||
297 | /// If there is no matching `.txt` file it will be created and filled with the | ||
298 | /// output of `f()`, but the test will fail. | ||
289 | pub fn dir_tests<F>(test_data_dir: &Path, paths: &[&str], f: F) | 299 | pub fn dir_tests<F>(test_data_dir: &Path, paths: &[&str], f: F) |
290 | where | 300 | where |
291 | F: Fn(&str, &Path) -> String, | 301 | F: Fn(&str, &Path) -> String, |
@@ -307,6 +317,7 @@ where | |||
307 | } | 317 | } |
308 | } | 318 | } |
309 | 319 | ||
320 | /// Collects all `.rs` files from `test_data_dir` subdirectories defined by `paths`. | ||
310 | pub fn collect_tests(test_data_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, String)> { | 321 | pub fn collect_tests(test_data_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, String)> { |
311 | paths | 322 | paths |
312 | .iter() | 323 | .iter() |
@@ -321,6 +332,7 @@ pub fn collect_tests(test_data_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, Stri | |||
321 | .collect() | 332 | .collect() |
322 | } | 333 | } |
323 | 334 | ||
335 | /// Collects paths to all `.rs` files from `dir` in a sorted `Vec<PathBuf>`. | ||
324 | fn test_from_dir(dir: &Path) -> Vec<PathBuf> { | 336 | fn test_from_dir(dir: &Path) -> Vec<PathBuf> { |
325 | let mut acc = Vec::new(); | 337 | let mut acc = Vec::new(); |
326 | for file in fs::read_dir(&dir).unwrap() { | 338 | for file in fs::read_dir(&dir).unwrap() { |
@@ -334,6 +346,7 @@ fn test_from_dir(dir: &Path) -> Vec<PathBuf> { | |||
334 | acc | 346 | acc |
335 | } | 347 | } |
336 | 348 | ||
349 | /// Returns the path to the root directory of `rust-analyzer` project. | ||
337 | pub fn project_dir() -> PathBuf { | 350 | pub fn project_dir() -> PathBuf { |
338 | let dir = env!("CARGO_MANIFEST_DIR"); | 351 | let dir = env!("CARGO_MANIFEST_DIR"); |
339 | PathBuf::from(dir).parent().unwrap().parent().unwrap().to_owned() | 352 | PathBuf::from(dir).parent().unwrap().parent().unwrap().to_owned() |
@@ -356,6 +369,9 @@ pub fn read_text(path: &Path) -> String { | |||
356 | .replace("\r\n", "\n") | 369 | .replace("\r\n", "\n") |
357 | } | 370 | } |
358 | 371 | ||
372 | /// Returns `false` if slow tests should not run, otherwise returns `true` and | ||
373 | /// also creates a file at `./target/.slow_tests_cookie` which serves as a flag | ||
374 | /// that slow tests did run. | ||
359 | pub fn skip_slow_tests() -> bool { | 375 | pub fn skip_slow_tests() -> bool { |
360 | let should_skip = std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err(); | 376 | let should_skip = std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err(); |
361 | if should_skip { | 377 | if should_skip { |
@@ -367,8 +383,9 @@ pub fn skip_slow_tests() -> bool { | |||
367 | should_skip | 383 | should_skip |
368 | } | 384 | } |
369 | 385 | ||
370 | const REWRITE: bool = false; | 386 | /// Asserts that `expected` and `actual` strings are equal. If they differ only |
371 | 387 | /// in trailing or leading whitespace the test won't fail and | |
388 | /// the contents of `actual` will be written to the file located at `path`. | ||
372 | fn assert_equal_text(expected: &str, actual: &str, path: &Path) { | 389 | fn assert_equal_text(expected: &str, actual: &str, path: &Path) { |
373 | if expected == actual { | 390 | if expected == actual { |
374 | return; | 391 | return; |
@@ -381,6 +398,7 @@ fn assert_equal_text(expected: &str, actual: &str, path: &Path) { | |||
381 | fs::write(path, actual).unwrap(); | 398 | fs::write(path, actual).unwrap(); |
382 | return; | 399 | return; |
383 | } | 400 | } |
401 | const REWRITE: bool = false; | ||
384 | if REWRITE { | 402 | if REWRITE { |
385 | println!("rewriting {}", pretty_path.display()); | 403 | println!("rewriting {}", pretty_path.display()); |
386 | fs::write(path, actual).unwrap(); | 404 | fs::write(path, actual).unwrap(); |
diff --git a/crates/test_utils/src/marks.rs b/crates/test_utils/src/marks.rs index fe1813947..f8fabfaff 100644 --- a/crates/test_utils/src/marks.rs +++ b/crates/test_utils/src/marks.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! This module implements manually tracked test coverage, which useful for | 1 | //! This module implements manually tracked test coverage, which is useful for |
2 | //! quickly finding a test responsible for testing a particular bit of code. | 2 | //! quickly finding a test responsible for testing a particular bit of code. |
3 | //! | 3 | //! |
4 | //! See <https://matklad.github.io/2018/06/18/a-trick-for-test-maintenance.html> | 4 | //! See <https://matklad.github.io/2018/06/18/a-trick-for-test-maintenance.html> |
diff --git a/docs/dev/README.md b/docs/dev/README.md index 2f6215d6b..d30727786 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -26,15 +26,6 @@ Discussion happens in this Zulip stream: | |||
26 | 26 | ||
27 | https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 | 27 | https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 |
28 | 28 | ||
29 | # Work List | ||
30 | |||
31 | We have this "work list" paper document: | ||
32 | |||
33 | https://paper.dropbox.com/doc/RLS-2.0-work-list--AZ3BgHKKCtqszbsi3gi6sjchAQ-42vbnxzuKq2lKwW0mkn8Y | ||
34 | |||
35 | It shows what everyone is working on right now. If you want to (this is not | ||
36 | mandatory), add yourself to the list! | ||
37 | |||
38 | # Issue Labels | 29 | # Issue Labels |
39 | 30 | ||
40 | * [good-first-issue](https://github.com/rust-analyzer/rust-analyzer/labels/good%20first%20issue) | 31 | * [good-first-issue](https://github.com/rust-analyzer/rust-analyzer/labels/good%20first%20issue) |
@@ -50,10 +41,12 @@ mandatory), add yourself to the list! | |||
50 | 41 | ||
51 | # CI | 42 | # CI |
52 | 43 | ||
53 | We use Travis for CI. Most of the things, including formatting, are checked by | 44 | We use GitHub Actions for CI. Most of the things, including formatting, are checked by |
54 | `cargo test` so, if `cargo test` passes locally, that's a good sign that CI will | 45 | `cargo test` so, if `cargo test` passes locally, that's a good sign that CI will |
55 | be green as well. We use bors-ng to enforce the [not rocket | 46 | be green as well. The only exception is that long-running by default a skipped locally. |
56 | science](https://graydon2.dreamwidth.org/1597.html) rule. | 47 | Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite. |
48 | |||
49 | We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule. | ||
57 | 50 | ||
58 | You can run `cargo xtask install-pre-commit-hook` to install git-hook to run rustfmt on commit. | 51 | You can run `cargo xtask install-pre-commit-hook` to install git-hook to run rustfmt on commit. |
59 | 52 | ||
@@ -81,42 +74,41 @@ relevant test and execute it (VS Code includes an action for running a single | |||
81 | test). | 74 | test). |
82 | 75 | ||
83 | However, launching a VS Code instance with locally build language server is | 76 | However, launching a VS Code instance with locally build language server is |
84 | possible. There's even a VS Code task for this, so just <kbd>F5</kbd> should | 77 | possible. There's "Run Extension (Dev Server)" launch configuration for this. |
85 | work (thanks, [@andrew-w-ross](https://github.com/andrew-w-ross)!). | 78 | |
86 | 79 | In general, I use one of the following workflows for fixing bugs and | |
87 | I often just install development version with `cargo xtask install --server --jemalloc` and | 80 | implementing features. |
88 | restart the host VS Code. | 81 | |
89 | 82 | If the problem concerns only internal parts of rust-analyzer (ie, I don't need | |
90 | See [./debugging.md](./debugging.md) for how to attach to rust-analyzer with | 83 | to touch `ra_lsp_server` crate or typescript code), there is a unit-test for it. |
91 | debugger, and don't forget that rust-analyzer has useful `pd` snippet and `dbg` | 84 | So, I use **Rust Analyzer: Run** action in VS Code to run this single test, and |
92 | postfix completion for printf debugging :-) | 85 | then just do printf-driven development/debugging. As a sanity check after I'm |
93 | 86 | done, I use `cargo xtask install --server` and **Reload Window** action in VS | |
94 | # Working With VS Code Extension | 87 | Code to sanity check that the thing works as I expect. |
95 | 88 | ||
96 | To work on the VS Code extension, launch code inside `editors/code` and use `F5` | 89 | If the problem concerns only the VS Code extension, I use **Run Extension** |
97 | to launch/debug. To automatically apply formatter and linter suggestions, use | 90 | launch configuration from `launch.json`. Notably, this uses the usual |
98 | `npm run fix`. | 91 | `ra_lsp_server` binary from `PATH`. After I am done with the fix, I use `cargo |
99 | 92 | xtask install --client-code` to try the new extension for real. | |
100 | Tests are located inside `src/test` and are named `*.test.ts`. They use the | 93 | |
101 | [Mocha](https://mochajs.org) test framework and the builtin Node | 94 | If I need to fix something in the `ra_lsp_server` crate, I feel sad because it's |
102 | [assert](https://nodejs.org/api/assert.html) module. Unlike normal Node tests | 95 | on the boundary between the two processes, and working there is slow. I usually |
103 | they must be hosted inside a VS Code instance. This can be done in one of two | 96 | just `cargo xtask install --server` and poke changes from my live environment. |
104 | ways: | 97 | Note that this uses `--release`, which is usually faster overall, because |
105 | 98 | loading stdlib into debug version of rust-analyzer takes a lot of time. To speed | |
106 | 1. When `F5` debugging in VS Code select the `Extension Tests` configuration | 99 | things up, sometimes I open a temporary hello-world project which has |
107 | from the drop-down at the top of the Debug View. This will launch a temporary | 100 | `"rust-analyzer.withSysroot": false` in `.code/settings.json`. This flag causes |
108 | instance of VS Code. The test results will appear in the "Debug Console" tab | 101 | rust-analyzer to skip loading the sysroot, which greatly reduces the amount of |
109 | of the primary VS Code instance. | 102 | things rust-analyzer needs to do, and makes printf's more useful. Note that you |
110 | 103 | should only use `eprint!` family of macros for debugging: stdout is used for LSP | |
111 | 2. Run `npm test` from the command line. Although this is initiated from the | 104 | communication, and `print!` would break it. |
112 | command line it is not headless; it will also launch a temporary instance of | 105 | |
113 | VS Code. | 106 | If I need to fix something simultaneously in the server and in the client, I |
114 | 107 | feel even more sad. I don't have a specific workflow for this case. | |
115 | Due to the requirements of running the tests inside VS Code they are **not run | 108 | |
116 | on CI**. When making changes to the extension please ensure the tests are not | 109 | Additionally, I use `cargo run --release -p ra_cli -- analysis-stats |
117 | broken locally before opening a Pull Request. | 110 | path/to/some/rust/crate` to run a batch analysis. This is primaraly useful for |
118 | 111 | performance optimiations, or for bug minimization. | |
119 | To install **only** the VS Code extension, use `cargo xtask install --client-code`. | ||
120 | 112 | ||
121 | # Logging | 113 | # Logging |
122 | 114 | ||
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index 629645757..9675ed0b6 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md | |||
@@ -12,6 +12,9 @@ analyzer: | |||
12 | 12 | ||
13 | https://www.youtube.com/playlist?list=PL85XCvVPmGQho7MZkdW-wtPtuJcFpzycE | 13 | https://www.youtube.com/playlist?list=PL85XCvVPmGQho7MZkdW-wtPtuJcFpzycE |
14 | 14 | ||
15 | Note that the guide and videos are pretty dated, this document should be in | ||
16 | generally fresher. | ||
17 | |||
15 | ## The Big Picture | 18 | ## The Big Picture |
16 | 19 | ||
17 |  | 20 |  |
@@ -20,13 +23,12 @@ On the highest level, rust-analyzer is a thing which accepts input source code | |||
20 | from the client and produces a structured semantic model of the code. | 23 | from the client and produces a structured semantic model of the code. |
21 | 24 | ||
22 | More specifically, input data consists of a set of test files (`(PathBuf, | 25 | More specifically, input data consists of a set of test files (`(PathBuf, |
23 | String)` pairs) and information about project structure, captured in the so called | 26 | String)` pairs) and information about project structure, captured in the so |
24 | `CrateGraph`. The crate graph specifies which files are crate roots, which cfg | 27 | called `CrateGraph`. The crate graph specifies which files are crate roots, |
25 | flags are specified for each crate (TODO: actually implement this) and what | 28 | which cfg flags are specified for each crate and what dependencies exist between |
26 | dependencies exist between the crates. The analyzer keeps all this input data in | 29 | the crates. The analyzer keeps all this input data in memory and never does any |
27 | memory and never does any IO. Because the input data is source code, which | 30 | IO. Because the input data are source code, which typically measures in tens of |
28 | typically measures in tens of megabytes at most, keeping all input data in | 31 | megabytes at most, keeping everything in memory is OK. |
29 | memory is OK. | ||
30 | 32 | ||
31 | A "structured semantic model" is basically an object-oriented representation of | 33 | A "structured semantic model" is basically an object-oriented representation of |
32 | modules, functions and types which appear in the source code. This representation | 34 | modules, functions and types which appear in the source code. This representation |
@@ -43,37 +45,39 @@ can be quickly updated for small modifications. | |||
43 | ## Code generation | 45 | ## Code generation |
44 | 46 | ||
45 | Some of the components of this repository are generated through automatic | 47 | Some of the components of this repository are generated through automatic |
46 | processes. These are outlined below: | 48 | processes. `cargo xtask codegen` runs all generation tasks. Generated code is |
49 | commited to the git repository. | ||
50 | |||
51 | In particular, `cargo xtask codegen` generates: | ||
52 | |||
53 | 1. [`syntax_kind/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_parser/src/syntax_kind/generated.rs) | ||
54 | -- the set of terminals and non-terminals of rust grammar. | ||
47 | 55 | ||
48 | - `cargo xtask codegen`: The kinds of tokens that are reused in several places, so a generator | 56 | 2. [`ast/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/src/ast/generated.rs) |
49 | is used. We use `quote!` macro to generate the files listed below, based on | 57 | -- AST data structure. |
50 | the grammar described in [grammar.ron]: | ||
51 | - [ast/generated.rs][ast generated] | ||
52 | - [syntax_kind/generated.rs][syntax_kind generated] | ||
53 | 58 | ||
54 | [grammar.ron]: ../../crates/ra_syntax/src/grammar.ron | 59 | .3 [`doc_tests/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_assists/src/doc_tests/generated.rs), |
55 | [ast generated]: ../../crates/ra_syntax/src/ast/generated.rs | 60 | [`test_data/parser/inline`](https://github.com/rust-analyzer/rust-analyzer/tree/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/test_data/parser/inline) |
56 | [syntax_kind generated]: ../../crates/ra_parser/src/syntax_kind/generated.rs | 61 | -- tests for assists and the parser. |
62 | |||
63 | The source for 1 and 2 is in [`ast_src.rs`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/xtask/src/ast_src.rs). | ||
57 | 64 | ||
58 | ## Code Walk-Through | 65 | ## Code Walk-Through |
59 | 66 | ||
60 | ### `crates/ra_syntax`, `crates/ra_parser` | 67 | ### `crates/ra_syntax`, `crates/ra_parser` |
61 | 68 | ||
62 | Rust syntax tree structure and parser. See | 69 | Rust syntax tree structure and parser. See |
63 | [RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design notes. | 70 | [RFC](https://github.com/rust-lang/rfcs/pull/2256) and [./syntax.md](./syntax.md) for some design notes. |
64 | 71 | ||
65 | - [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees. | 72 | - [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees. |
66 | - `grammar` module is the actual parser. It is a hand-written recursive descent parser, which | 73 | - `grammar` module is the actual parser. It is a hand-written recursive descent parser, which |
67 | produces a sequence of events like "start node X", "finish node Y". It works similarly to [kotlin's parser](https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java), | 74 | produces a sequence of events like "start node X", "finish node Y". It works similarly to [kotlin's parser](https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java), |
68 | which is a good source of inspiration for dealing with syntax errors and incomplete input. Original [libsyntax parser](https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs) | 75 | which is a good source of inspiration for dealing with syntax errors and incomplete input. Original [libsyntax parser](https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs) |
69 | is what we use for the definition of the Rust language. | 76 | is what we use for the definition of the Rust language. |
70 | - `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `rowan` trees. | 77 | - `TreeSink` and `TokenSource` traits bridge the tree-agnostic parser from `grammar` with `rowan` trees. |
71 | This is the thing that turns a flat list of events into a tree (see `EventProcessor`) | ||
72 | - `ast` provides a type safe API on top of the raw `rowan` tree. | 78 | - `ast` provides a type safe API on top of the raw `rowan` tree. |
73 | - `grammar.ron` RON description of the grammar, which is used to | 79 | - `ast_src` description of the grammar, which is used to generate `syntax_kinds` |
74 | generate `syntax_kinds` and `ast` modules, using `cargo xtask codegen` command. | 80 | and `ast` modules, using `cargo xtask codegen` command. |
75 | - `algo`: generic tree algorithms, including `walk` for O(1) stack | ||
76 | space tree traversal (this is cool). | ||
77 | 81 | ||
78 | Tests for ra_syntax are mostly data-driven: `test_data/parser` contains subdirectories with a bunch of `.rs` | 82 | Tests for ra_syntax are mostly data-driven: `test_data/parser` contains subdirectories with a bunch of `.rs` |
79 | (test vectors) and `.txt` files with corresponding syntax trees. During testing, we check | 83 | (test vectors) and `.txt` files with corresponding syntax trees. During testing, we check |
@@ -81,6 +85,10 @@ Tests for ra_syntax are mostly data-driven: `test_data/parser` contains subdirec | |||
81 | tests). Additionally, running `cargo xtask codegen` will walk the grammar module and collect | 85 | tests). Additionally, running `cargo xtask codegen` will walk the grammar module and collect |
82 | all `// test test_name` comments into files inside `test_data/parser/inline` directory. | 86 | all `// test test_name` comments into files inside `test_data/parser/inline` directory. |
83 | 87 | ||
88 | Note | ||
89 | [`api_walkthrough`](https://github.com/rust-analyzer/rust-analyzer/blob/2fb6af89eb794f775de60b82afe56b6f986c2a40/crates/ra_syntax/src/lib.rs#L190-L348) | ||
90 | in particular: it shows off various methods of working with syntax tree. | ||
91 | |||
84 | See [#93](https://github.com/rust-analyzer/rust-analyzer/pull/93) for an example PR which | 92 | See [#93](https://github.com/rust-analyzer/rust-analyzer/pull/93) for an example PR which |
85 | fixes a bug in the grammar. | 93 | fixes a bug in the grammar. |
86 | 94 | ||
@@ -94,18 +102,22 @@ defines most of the "input" queries: facts supplied by the client of the | |||
94 | analyzer. Reading the docs of the `ra_db::input` module should be useful: | 102 | analyzer. Reading the docs of the `ra_db::input` module should be useful: |
95 | everything else is strictly derived from those inputs. | 103 | everything else is strictly derived from those inputs. |
96 | 104 | ||
97 | ### `crates/ra_hir` | 105 | ### `crates/ra_hir*` crates |
98 | 106 | ||
99 | HIR provides high-level "object oriented" access to Rust code. | 107 | HIR provides high-level "object oriented" access to Rust code. |
100 | 108 | ||
101 | The principal difference between HIR and syntax trees is that HIR is bound to a | 109 | The principal difference between HIR and syntax trees is that HIR is bound to a |
102 | particular crate instance. That is, it has cfg flags and features applied (in | 110 | particular crate instance. That is, it has cfg flags and features applied. So, |
103 | theory, in practice this is to be implemented). So, the relation between | 111 | the relation between syntax and HIR is many-to-one. The `source_binder` module |
104 | syntax and HIR is many-to-one. The `source_binder` module is responsible for | 112 | is responsible for guessing a HIR for a particular source position. |
105 | guessing a HIR for a particular source position. | ||
106 | 113 | ||
107 | Underneath, HIR works on top of salsa, using a `HirDatabase` trait. | 114 | Underneath, HIR works on top of salsa, using a `HirDatabase` trait. |
108 | 115 | ||
116 | `ra_hir_xxx` crates have a strong ECS flavor, in that they work with raw ids and | ||
117 | directly query the databse. | ||
118 | |||
119 | The top-level `ra_hir` façade crate wraps ids into a more OO-flavored API. | ||
120 | |||
109 | ### `crates/ra_ide` | 121 | ### `crates/ra_ide` |
110 | 122 | ||
111 | A stateful library for analyzing many Rust files as they change. `AnalysisHost` | 123 | A stateful library for analyzing many Rust files as they change. `AnalysisHost` |
@@ -135,18 +147,9 @@ different from data on disk. This is more or less the single really | |||
135 | platform-dependent component, so it lives in a separate repository and has an | 147 | platform-dependent component, so it lives in a separate repository and has an |
136 | extensive cross-platform CI testing. | 148 | extensive cross-platform CI testing. |
137 | 149 | ||
138 | ### `crates/gen_lsp_server` | ||
139 | |||
140 | A language server scaffold, exposing a synchronous crossbeam-channel based API. | ||
141 | This crate handles protocol handshaking and parsing messages, while you | ||
142 | control the message dispatch loop yourself. | ||
143 | |||
144 | Run with `RUST_LOG=sync_lsp_server=debug` to see all the messages. | ||
145 | |||
146 | ### `crates/ra_cli` | 150 | ### `crates/ra_cli` |
147 | 151 | ||
148 | A CLI interface to rust-analyzer. | 152 | A CLI interface to rust-analyzer, mainly for testing. |
149 | |||
150 | 153 | ||
151 | ## Testing Infrastructure | 154 | ## Testing Infrastructure |
152 | 155 | ||
diff --git a/docs/dev/debugging.md b/docs/dev/debugging.md index f868e6998..1ccf4dca2 100644 --- a/docs/dev/debugging.md +++ b/docs/dev/debugging.md | |||
@@ -1,5 +1,7 @@ | |||
1 | # Debugging vs Code plugin and the Language Server | 1 | # Debugging vs Code plugin and the Language Server |
2 | 2 | ||
3 | **NOTE:** the information here is mostly obsolete | ||
4 | |||
3 | Install [LLDB](https://lldb.llvm.org/) and the [LLDB Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb). | 5 | Install [LLDB](https://lldb.llvm.org/) and the [LLDB Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb). |
4 | 6 | ||
5 | Checkout rust rust-analyzer and open it in vscode. | 7 | Checkout rust rust-analyzer and open it in vscode. |
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index d38a45b85..f92ce1fe2 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json | |||
@@ -25,9 +25,9 @@ | |||
25 | } | 25 | } |
26 | }, | 26 | }, |
27 | "@rollup/plugin-commonjs": { | 27 | "@rollup/plugin-commonjs": { |
28 | "version": "11.0.0", | 28 | "version": "11.0.1", |
29 | "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.0.tgz", | 29 | "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.1.tgz", |
30 | "integrity": "sha512-jnm//T5ZWOZ6zmJ61fReSCBOif+Ax8dHVoVggA+d2NA7T4qCWgQ3KYr+zN2faGEYLpe1wa03IzvhR+sqVLxUWg==", | 30 | "integrity": "sha512-SaVUoaLDg3KnIXC5IBNIspr1APTYDzk05VaYcI6qz+0XX3ZlSCwAkfAhNSOxfd5GAdcm/63Noi4TowOY9MpcDg==", |
31 | "dev": true, | 31 | "dev": true, |
32 | "requires": { | 32 | "requires": { |
33 | "@rollup/pluginutils": "^3.0.0", | 33 | "@rollup/pluginutils": "^3.0.0", |
@@ -38,9 +38,9 @@ | |||
38 | } | 38 | } |
39 | }, | 39 | }, |
40 | "@rollup/plugin-node-resolve": { | 40 | "@rollup/plugin-node-resolve": { |
41 | "version": "6.0.0", | 41 | "version": "6.1.0", |
42 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-6.0.0.tgz", | 42 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-6.1.0.tgz", |
43 | "integrity": "sha512-GqWz1CfXOsqpeVMcoM315+O7zMxpRsmhWyhJoxLFHVSp9S64/u02i7len/FnbTNbmgYs+sZyilasijH8UiuboQ==", | 43 | "integrity": "sha512-Cv7PDIvxdE40SWilY5WgZpqfIUEaDxFxs89zCAHjqyRwlTSuql4M5hjIuc5QYJkOH0/vyiyNXKD72O+LhRipGA==", |
44 | "dev": true, | 44 | "dev": true, |
45 | "requires": { | 45 | "requires": { |
46 | "@rollup/pluginutils": "^3.0.0", | 46 | "@rollup/pluginutils": "^3.0.0", |
@@ -51,34 +51,42 @@ | |||
51 | } | 51 | } |
52 | }, | 52 | }, |
53 | "@rollup/plugin-typescript": { | 53 | "@rollup/plugin-typescript": { |
54 | "version": "2.0.1", | 54 | "version": "2.1.0", |
55 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-2.0.1.tgz", | 55 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-2.1.0.tgz", |
56 | "integrity": "sha512-UA/bN/DlHN19xdOllXmp7G7pM2ac9dQMg0q2T1rg4Bogzb7oHXj2WGafpiNpEm54PivcJdzGRJvRnI6zCISW3w==", | 56 | "integrity": "sha512-7lXKGY06aofrceVez/YnN2axttFdHSqlUBpCJ6ebzDfxwLDKMgSV5lD4ykBcdgE7aK3egxuLkD/HKyRB5L8Log==", |
57 | "dev": true, | 57 | "dev": true, |
58 | "requires": { | 58 | "requires": { |
59 | "@rollup/pluginutils": "^3.0.0", | 59 | "@rollup/pluginutils": "^3.0.0", |
60 | "resolve": "^1.12.2" | 60 | "resolve": "^1.13.1" |
61 | } | 61 | } |
62 | }, | 62 | }, |
63 | "@rollup/pluginutils": { | 63 | "@rollup/pluginutils": { |
64 | "version": "3.0.1", | 64 | "version": "3.0.6", |
65 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.1.tgz", | 65 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.6.tgz", |
66 | "integrity": "sha512-PmNurkecagFimv7ZdKCVOfQuqKDPkrcpLFxRBcQ00LYr4HAjJwhCFxBiY2Xoletll2htTIiXBg6g0Yg21h2M3w==", | 66 | "integrity": "sha512-Nb6U7sg11v8D+E4mxRxwT+UumUL7MSnwI8V1SJB3THyW2MOGD/Q6GyxLtpnjrbT3zTRPSozzDMyVZwemgldO3w==", |
67 | "dev": true, | 67 | "dev": true, |
68 | "requires": { | 68 | "requires": { |
69 | "estree-walker": "^0.6.1" | 69 | "estree-walker": "^1.0.1" |
70 | }, | ||
71 | "dependencies": { | ||
72 | "estree-walker": { | ||
73 | "version": "1.0.1", | ||
74 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", | ||
75 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", | ||
76 | "dev": true | ||
77 | } | ||
70 | } | 78 | } |
71 | }, | 79 | }, |
72 | "@types/estree": { | 80 | "@types/estree": { |
73 | "version": "0.0.41", | 81 | "version": "0.0.39", |
74 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.41.tgz", | 82 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", |
75 | "integrity": "sha512-rIAmXyJlqw4KEBO7+u9gxZZSQHaCNnIzYrnNmYVpgfJhxTqO0brCX0SYpqUTkVI5mwwUwzmtspLBGBKroMeynA==", | 83 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", |
76 | "dev": true | 84 | "dev": true |
77 | }, | 85 | }, |
78 | "@types/node": { | 86 | "@types/node": { |
79 | "version": "12.12.22", | 87 | "version": "12.12.25", |
80 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.22.tgz", | 88 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.25.tgz", |
81 | "integrity": "sha512-r5i93jqbPWGXYXxianGATOxTelkp6ih/U0WVnvaqAvTqM+0U6J3kw6Xk6uq/dWNRkEVw/0SLcO5ORXbVNz4FMQ==", | 89 | "integrity": "sha512-nf1LMGZvgFX186geVZR1xMZKKblJiRfiASTHw85zED2kI1yDKHDwTKMdkaCbTlXoRKlGKaDfYywt+V0As30q3w==", |
82 | "dev": true | 90 | "dev": true |
83 | }, | 91 | }, |
84 | "@types/resolve": { | 92 | "@types/resolve": { |
@@ -429,14 +437,6 @@ | |||
429 | "dev": true, | 437 | "dev": true, |
430 | "requires": { | 438 | "requires": { |
431 | "@types/estree": "0.0.39" | 439 | "@types/estree": "0.0.39" |
432 | }, | ||
433 | "dependencies": { | ||
434 | "@types/estree": { | ||
435 | "version": "0.0.39", | ||
436 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", | ||
437 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", | ||
438 | "dev": true | ||
439 | } | ||
440 | } | 440 | } |
441 | }, | 441 | }, |
442 | "js-tokens": { | 442 | "js-tokens": { |
@@ -486,9 +486,9 @@ | |||
486 | } | 486 | } |
487 | }, | 487 | }, |
488 | "magic-string": { | 488 | "magic-string": { |
489 | "version": "0.25.4", | 489 | "version": "0.25.6", |
490 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz", | 490 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.6.tgz", |
491 | "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==", | 491 | "integrity": "sha512-3a5LOMSGoCTH5rbqobC2HuDNRtE2glHZ8J7pK+QZYppyWA36yuNpsX994rIY2nCuyP7CZYy7lQq/X2jygiZ89g==", |
492 | "dev": true, | 492 | "dev": true, |
493 | "requires": { | 493 | "requires": { |
494 | "sourcemap-codec": "^1.4.4" | 494 | "sourcemap-codec": "^1.4.4" |
@@ -675,9 +675,9 @@ | |||
675 | } | 675 | } |
676 | }, | 676 | }, |
677 | "rollup": { | 677 | "rollup": { |
678 | "version": "1.27.14", | 678 | "version": "1.30.1", |
679 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.14.tgz", | 679 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.30.1.tgz", |
680 | "integrity": "sha512-DuDjEyn8Y79ALYXMt+nH/EI58L5pEw5HU9K38xXdRnxQhvzUTI/nxAawhkAHUQeudANQ//8iyrhVRHJBuR6DSQ==", | 680 | "integrity": "sha512-Uus8mwQXwaO+ZVoNwBcXKhT0AvycFCBW/W8VZtkpVGsotRllWk9oldfCjqWmTnFRI0y7x6BnEqSqc65N+/YdBw==", |
681 | "dev": true, | 681 | "dev": true, |
682 | "requires": { | 682 | "requires": { |
683 | "@types/estree": "*", | 683 | "@types/estree": "*", |
@@ -708,9 +708,9 @@ | |||
708 | "dev": true | 708 | "dev": true |
709 | }, | 709 | }, |
710 | "sourcemap-codec": { | 710 | "sourcemap-codec": { |
711 | "version": "1.4.6", | 711 | "version": "1.4.8", |
712 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", | 712 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", |
713 | "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", | 713 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", |
714 | "dev": true | 714 | "dev": true |
715 | }, | 715 | }, |
716 | "sprintf-js": { | 716 | "sprintf-js": { |
@@ -782,7 +782,7 @@ | |||
782 | "semver": { | 782 | "semver": { |
783 | "version": "5.7.1", | 783 | "version": "5.7.1", |
784 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", | 784 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", |
785 | "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=", | 785 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", |
786 | "dev": true | 786 | "dev": true |
787 | } | 787 | } |
788 | } | 788 | } |
@@ -813,9 +813,9 @@ | |||
813 | } | 813 | } |
814 | }, | 814 | }, |
815 | "typescript": { | 815 | "typescript": { |
816 | "version": "3.7.4", | 816 | "version": "3.7.5", |
817 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.4.tgz", | 817 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", |
818 | "integrity": "sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw==", | 818 | "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", |
819 | "dev": true | 819 | "dev": true |
820 | }, | 820 | }, |
821 | "typescript-formatter": { | 821 | "typescript-formatter": { |
diff --git a/editors/code/package.json b/editors/code/package.json index ce3de1e96..55d470fa0 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -28,16 +28,16 @@ | |||
28 | "vscode-languageclient": "^6.1.0" | 28 | "vscode-languageclient": "^6.1.0" |
29 | }, | 29 | }, |
30 | "devDependencies": { | 30 | "devDependencies": { |
31 | "@rollup/plugin-commonjs": "^11.0.0", | 31 | "@rollup/plugin-commonjs": "^11.0.1", |
32 | "@rollup/plugin-node-resolve": "^6.0.0", | 32 | "@rollup/plugin-node-resolve": "^6.1.0", |
33 | "@rollup/plugin-typescript": "^2.0.1", | 33 | "@rollup/plugin-typescript": "^2.1.0", |
34 | "@types/node": "^12.12.21", | 34 | "@types/node": "^12.12.25", |
35 | "@types/seedrandom": "^2.4.28", | 35 | "@types/seedrandom": "^2.4.28", |
36 | "@types/vscode": "^1.41.0", | 36 | "@types/vscode": "^1.41.0", |
37 | "rollup": "^1.27.14", | 37 | "rollup": "^1.30.1", |
38 | "tslib": "^1.10.0", | 38 | "tslib": "^1.10.0", |
39 | "tslint": "^5.20.1", | 39 | "tslint": "^5.20.1", |
40 | "typescript": "^3.7.3", | 40 | "typescript": "^3.7.5", |
41 | "typescript-formatter": "^7.2.2", | 41 | "typescript-formatter": "^7.2.2", |
42 | "vsce": "^1.71.0" | 42 | "vsce": "^1.71.0" |
43 | }, | 43 | }, |
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 1ff64a930..15e1a0873 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts | |||
@@ -15,7 +15,13 @@ export function createClient(config: Config): lc.LanguageClient { | |||
15 | 15 | ||
16 | const command = expandPathResolving(config.raLspServerPath); | 16 | const command = expandPathResolving(config.raLspServerPath); |
17 | if (spawnSync(command, ["--version"]).status !== 0) { | 17 | if (spawnSync(command, ["--version"]).status !== 0) { |
18 | window.showErrorMessage(`Unable to execute '${command} --version'`); | 18 | window.showErrorMessage( |
19 | `Unable to execute '${command} --version' | ||
20 | |||
21 | Perhaps it is not in $PATH? | ||
22 | |||
23 | PATH=${process.env.PATH} | ||
24 | `); | ||
19 | } | 25 | } |
20 | const run: lc.Executable = { | 26 | const run: lc.Executable = { |
21 | command, | 27 | command, |