diff options
196 files changed, 3138 insertions, 1782 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2acd44012..f977c88be 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml | |||
@@ -88,11 +88,14 @@ jobs: | |||
88 | if: matrix.os == 'windows-latest' | 88 | if: matrix.os == 'windows-latest' |
89 | run: Remove-Item ./target/debug/xtask.exe, ./target/debug/deps/xtask.exe | 89 | run: Remove-Item ./target/debug/xtask.exe, ./target/debug/deps/xtask.exe |
90 | 90 | ||
91 | # Weird target to catch non-portable code | 91 | # Weird targets to catch non-portable code |
92 | rust-power: | 92 | rust-cross: |
93 | name: Rust Power | 93 | name: Rust Cross |
94 | runs-on: ubuntu-latest | 94 | runs-on: ubuntu-latest |
95 | 95 | ||
96 | env: | ||
97 | targets: "powerpc-unknown-linux-gnu x86_64-unknown-linux-musl" | ||
98 | |||
96 | steps: | 99 | steps: |
97 | - name: Checkout repository | 100 | - name: Checkout repository |
98 | uses: actions/checkout@v2 | 101 | uses: actions/checkout@v2 |
@@ -103,7 +106,9 @@ jobs: | |||
103 | toolchain: stable | 106 | toolchain: stable |
104 | profile: minimal | 107 | profile: minimal |
105 | override: true | 108 | override: true |
106 | target: 'powerpc-unknown-linux-gnu' | 109 | |
110 | - name: Install Rust targets | ||
111 | run: rustup target add ${{ env.targets }} | ||
107 | 112 | ||
108 | - name: Cache cargo directories | 113 | - name: Cache cargo directories |
109 | uses: actions/cache@v2 | 114 | uses: actions/cache@v2 |
@@ -114,7 +119,10 @@ jobs: | |||
114 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | 119 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} |
115 | 120 | ||
116 | - name: Check | 121 | - name: Check |
117 | run: cargo check --target=powerpc-unknown-linux-gnu --all-targets | 122 | run: | |
123 | for target in ${{ env.targets }}; do | ||
124 | cargo check --target=$target --all-targets | ||
125 | done | ||
118 | 126 | ||
119 | typescript: | 127 | typescript: |
120 | name: TypeScript | 128 | name: TypeScript |
diff --git a/Cargo.lock b/Cargo.lock index c974022a2..265889162 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -125,9 +125,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | |||
125 | 125 | ||
126 | [[package]] | 126 | [[package]] |
127 | name = "chalk-derive" | 127 | name = "chalk-derive" |
128 | version = "0.19.0" | 128 | version = "0.21.0" |
129 | source = "registry+https://github.com/rust-lang/crates.io-index" | 129 | source = "registry+https://github.com/rust-lang/crates.io-index" |
130 | checksum = "654c611946ba2629c5028cb7708687af975faf2c29d731824cb294c873df4697" | 130 | checksum = "c1df0dbb57d74b4acd20f20fa66ab2acd09776b79eaeb9d8f947b2f3e01c40bf" |
131 | dependencies = [ | 131 | dependencies = [ |
132 | "proc-macro2", | 132 | "proc-macro2", |
133 | "quote", | 133 | "quote", |
@@ -137,9 +137,9 @@ dependencies = [ | |||
137 | 137 | ||
138 | [[package]] | 138 | [[package]] |
139 | name = "chalk-ir" | 139 | name = "chalk-ir" |
140 | version = "0.19.0" | 140 | version = "0.21.0" |
141 | source = "registry+https://github.com/rust-lang/crates.io-index" | 141 | source = "registry+https://github.com/rust-lang/crates.io-index" |
142 | checksum = "0a5341fbc654ca886b73b804a36aebf0e621057ccc1a68e9815b5b39b3ac9ae8" | 142 | checksum = "44361a25dbdb1dc428f56ad7a3c21ba9ca12f3225c26a47919ff6fcb10a583d4" |
143 | dependencies = [ | 143 | dependencies = [ |
144 | "chalk-derive", | 144 | "chalk-derive", |
145 | "lazy_static", | 145 | "lazy_static", |
@@ -147,9 +147,9 @@ dependencies = [ | |||
147 | 147 | ||
148 | [[package]] | 148 | [[package]] |
149 | name = "chalk-recursive" | 149 | name = "chalk-recursive" |
150 | version = "0.19.0" | 150 | version = "0.21.0" |
151 | source = "registry+https://github.com/rust-lang/crates.io-index" | 151 | source = "registry+https://github.com/rust-lang/crates.io-index" |
152 | checksum = "4484807b155b5a411e6135d330295f9ba5042e2920b8712c6574ca6ea91e9ee5" | 152 | checksum = "dd89556b98de156d5eaf21077d297cd2198628f10f2df140798ea3a5dd84bc86" |
153 | dependencies = [ | 153 | dependencies = [ |
154 | "chalk-derive", | 154 | "chalk-derive", |
155 | "chalk-ir", | 155 | "chalk-ir", |
@@ -160,9 +160,9 @@ dependencies = [ | |||
160 | 160 | ||
161 | [[package]] | 161 | [[package]] |
162 | name = "chalk-solve" | 162 | name = "chalk-solve" |
163 | version = "0.19.0" | 163 | version = "0.21.0" |
164 | source = "registry+https://github.com/rust-lang/crates.io-index" | 164 | source = "registry+https://github.com/rust-lang/crates.io-index" |
165 | checksum = "281f82facd2538997fbe52132b1941ed213d266748215c31d15f62a8664429ad" | 165 | checksum = "a886da37a0dc457057d86f78f026f7a09c6d8088aa13f4f4127fdb8dc80119a3" |
166 | dependencies = [ | 166 | dependencies = [ |
167 | "chalk-derive", | 167 | "chalk-derive", |
168 | "chalk-ir", | 168 | "chalk-ir", |
@@ -279,9 +279,9 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" | |||
279 | 279 | ||
280 | [[package]] | 280 | [[package]] |
281 | name = "drop_bomb" | 281 | name = "drop_bomb" |
282 | version = "0.1.4" | 282 | version = "0.1.5" |
283 | source = "registry+https://github.com/rust-lang/crates.io-index" | 283 | source = "registry+https://github.com/rust-lang/crates.io-index" |
284 | checksum = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" | 284 | checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" |
285 | 285 | ||
286 | [[package]] | 286 | [[package]] |
287 | name = "either" | 287 | name = "either" |
@@ -318,9 +318,9 @@ dependencies = [ | |||
318 | 318 | ||
319 | [[package]] | 319 | [[package]] |
320 | name = "filetime" | 320 | name = "filetime" |
321 | version = "0.2.11" | 321 | version = "0.2.12" |
322 | source = "registry+https://github.com/rust-lang/crates.io-index" | 322 | source = "registry+https://github.com/rust-lang/crates.io-index" |
323 | checksum = "e500da2fab70bdc43f8f0e0b350a227f31c72311c56aba48f01d5cd62bb0345b" | 323 | checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" |
324 | dependencies = [ | 324 | dependencies = [ |
325 | "cfg-if", | 325 | "cfg-if", |
326 | "libc", | 326 | "libc", |
@@ -418,9 +418,9 @@ dependencies = [ | |||
418 | 418 | ||
419 | [[package]] | 419 | [[package]] |
420 | name = "hashbrown" | 420 | name = "hashbrown" |
421 | version = "0.8.1" | 421 | version = "0.8.2" |
422 | source = "registry+https://github.com/rust-lang/crates.io-index" | 422 | source = "registry+https://github.com/rust-lang/crates.io-index" |
423 | checksum = "34f595585f103464d8d2f6e9864682d74c1601fed5e07d62b1c9058dba8246fb" | 423 | checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" |
424 | dependencies = [ | 424 | dependencies = [ |
425 | "autocfg", | 425 | "autocfg", |
426 | ] | 426 | ] |
@@ -465,9 +465,9 @@ dependencies = [ | |||
465 | 465 | ||
466 | [[package]] | 466 | [[package]] |
467 | name = "indexmap" | 467 | name = "indexmap" |
468 | version = "1.5.0" | 468 | version = "1.5.1" |
469 | source = "registry+https://github.com/rust-lang/crates.io-index" | 469 | source = "registry+https://github.com/rust-lang/crates.io-index" |
470 | checksum = "5b88cd59ee5f71fea89a62248fc8f387d44400cefe05ef548466d61ced9029a7" | 470 | checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" |
471 | dependencies = [ | 471 | dependencies = [ |
472 | "autocfg", | 472 | "autocfg", |
473 | "hashbrown", | 473 | "hashbrown", |
@@ -852,9 +852,9 @@ dependencies = [ | |||
852 | 852 | ||
853 | [[package]] | 853 | [[package]] |
854 | name = "perf-event-open-sys" | 854 | name = "perf-event-open-sys" |
855 | version = "0.3.1" | 855 | version = "0.3.2" |
856 | source = "registry+https://github.com/rust-lang/crates.io-index" | 856 | source = "registry+https://github.com/rust-lang/crates.io-index" |
857 | checksum = "95db63e37862bc1b842135d2234ef9418f222cc660c6752f45e7cf9ddfb97f96" | 857 | checksum = "83e7183862f36d10263d0a1ccaef50fef734ade948bf026afd1bd97355c78273" |
858 | dependencies = [ | 858 | dependencies = [ |
859 | "libc", | 859 | "libc", |
860 | ] | 860 | ] |
@@ -871,9 +871,9 @@ dependencies = [ | |||
871 | 871 | ||
872 | [[package]] | 872 | [[package]] |
873 | name = "pico-args" | 873 | name = "pico-args" |
874 | version = "0.3.3" | 874 | version = "0.3.4" |
875 | source = "registry+https://github.com/rust-lang/crates.io-index" | 875 | source = "registry+https://github.com/rust-lang/crates.io-index" |
876 | checksum = "1b1eee8b1f4966c8343d7ca0f5a8452cd35d5610a2e0efbe2a68cae44bef2046" | 876 | checksum = "28b9b4df73455c861d7cbf8be42f01d3b373ed7f02e378d55fa84eafc6f638b1" |
877 | 877 | ||
878 | [[package]] | 878 | [[package]] |
879 | name = "plain" | 879 | name = "plain" |
@@ -1371,9 +1371,9 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" | |||
1371 | 1371 | ||
1372 | [[package]] | 1372 | [[package]] |
1373 | name = "salsa" | 1373 | name = "salsa" |
1374 | version = "0.15.1" | 1374 | version = "0.15.2" |
1375 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1375 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1376 | checksum = "d4cdc109fcc9e9450c7ef47fb7474e99bffd51799da03ed0a6c7f0e2cb3848a6" | 1376 | checksum = "9ab29056d4fb4048a5f0d169c9b6e5526160c9ec37aded5a6879c2c9c445a8e4" |
1377 | dependencies = [ | 1377 | dependencies = [ |
1378 | "crossbeam-utils", | 1378 | "crossbeam-utils", |
1379 | "indexmap", | 1379 | "indexmap", |
@@ -1388,9 +1388,9 @@ dependencies = [ | |||
1388 | 1388 | ||
1389 | [[package]] | 1389 | [[package]] |
1390 | name = "salsa-macros" | 1390 | name = "salsa-macros" |
1391 | version = "0.15.0" | 1391 | version = "0.15.2" |
1392 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1392 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1393 | checksum = "2c280ac85b15ac214b86ac4b407626a48e6a1c4f90769a582fec74aa57942b9f" | 1393 | checksum = "a1c3aec007c63c4ed4cd7a018529fb0b5575c4562575fc6a40d6cd2ae0b792ef" |
1394 | dependencies = [ | 1394 | dependencies = [ |
1395 | "heck", | 1395 | "heck", |
1396 | "proc-macro2", | 1396 | "proc-macro2", |
@@ -1533,9 +1533,9 @@ version = "0.1.0" | |||
1533 | 1533 | ||
1534 | [[package]] | 1534 | [[package]] |
1535 | name = "syn" | 1535 | name = "syn" |
1536 | version = "1.0.36" | 1536 | version = "1.0.38" |
1537 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1538 | checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250" | 1538 | checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" |
1539 | dependencies = [ | 1539 | dependencies = [ |
1540 | "proc-macro2", | 1540 | "proc-macro2", |
1541 | "quote", | 1541 | "quote", |
@@ -1622,9 +1622,9 @@ checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed" | |||
1622 | 1622 | ||
1623 | [[package]] | 1623 | [[package]] |
1624 | name = "tracing" | 1624 | name = "tracing" |
1625 | version = "0.1.17" | 1625 | version = "0.1.18" |
1626 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1626 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1627 | checksum = "dbdf4ccd1652592b01286a5dbe1e2a77d78afaa34beadd9872a5f7396f92aaa9" | 1627 | checksum = "f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178" |
1628 | dependencies = [ | 1628 | dependencies = [ |
1629 | "cfg-if", | 1629 | "cfg-if", |
1630 | "tracing-attributes", | 1630 | "tracing-attributes", |
@@ -1644,9 +1644,9 @@ dependencies = [ | |||
1644 | 1644 | ||
1645 | [[package]] | 1645 | [[package]] |
1646 | name = "tracing-core" | 1646 | name = "tracing-core" |
1647 | version = "0.1.11" | 1647 | version = "0.1.13" |
1648 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1648 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1649 | checksum = "94ae75f0d28ae10786f3b1895c55fe72e79928fd5ccdebb5438c75e93fec178f" | 1649 | checksum = "d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9" |
1650 | dependencies = [ | 1650 | dependencies = [ |
1651 | "lazy_static", | 1651 | "lazy_static", |
1652 | ] | 1652 | ] |
@@ -1674,9 +1674,9 @@ dependencies = [ | |||
1674 | 1674 | ||
1675 | [[package]] | 1675 | [[package]] |
1676 | name = "tracing-subscriber" | 1676 | name = "tracing-subscriber" |
1677 | version = "0.2.9" | 1677 | version = "0.2.10" |
1678 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1678 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1679 | checksum = "e4f5dd7095c2481b7b3cbed71c8de53085fb3542bc3c2b4c73cba43e8f11c7ba" | 1679 | checksum = "f7b33f8b2ef2ab0c3778c12646d9c42a24f7772bee4cdafc72199644a9f58fdc" |
1680 | dependencies = [ | 1680 | dependencies = [ |
1681 | "ansi_term", | 1681 | "ansi_term", |
1682 | "chrono", | 1682 | "chrono", |
@@ -1694,9 +1694,9 @@ dependencies = [ | |||
1694 | 1694 | ||
1695 | [[package]] | 1695 | [[package]] |
1696 | name = "tracing-tree" | 1696 | name = "tracing-tree" |
1697 | version = "0.1.4" | 1697 | version = "0.1.5" |
1698 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1698 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1699 | checksum = "37ee7f0f53ed2093971a698db799ef56a2dfd89b32e3aeb5165f0e637a02be04" | 1699 | checksum = "e1a3dc4774db3a6b2d66a4f8d8de670e874ec3ed55615860c994927419b32c5f" |
1700 | dependencies = [ | 1700 | dependencies = [ |
1701 | "ansi_term", | 1701 | "ansi_term", |
1702 | "atty", | 1702 | "atty", |
@@ -1708,9 +1708,9 @@ dependencies = [ | |||
1708 | 1708 | ||
1709 | [[package]] | 1709 | [[package]] |
1710 | name = "ungrammar" | 1710 | name = "ungrammar" |
1711 | version = "0.1.0" | 1711 | version = "1.1.1" |
1712 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1713 | checksum = "0ee12e4891ab3acc2d95d5023022ace22020247bb8a8d1ece875a443f7dab37d" | 1713 | checksum = "c4e20e58a08ee1bcf8a4695cf74550cf054d6c489105f594beacb2c684210aad" |
1714 | 1714 | ||
1715 | [[package]] | 1715 | [[package]] |
1716 | name = "unicode-bidi" | 1716 | name = "unicode-bidi" |
@@ -1833,9 +1833,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | |||
1833 | 1833 | ||
1834 | [[package]] | 1834 | [[package]] |
1835 | name = "write-json" | 1835 | name = "write-json" |
1836 | version = "0.1.0" | 1836 | version = "0.1.2" |
1837 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1837 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1838 | checksum = "8b3f9a784c809a99e38d2e825907617cb03bd880d5421153bc4548e9317f59d0" | 1838 | checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" |
1839 | 1839 | ||
1840 | [[package]] | 1840 | [[package]] |
1841 | name = "ws2_32-sys" | 1841 | name = "ws2_32-sys" |
diff --git a/crates/expect/src/lib.rs b/crates/expect/src/lib.rs index 21a458d47..bd83895f7 100644 --- a/crates/expect/src/lib.rs +++ b/crates/expect/src/lib.rs | |||
@@ -74,7 +74,7 @@ impl fmt::Display for Position { | |||
74 | impl Expect { | 74 | impl Expect { |
75 | pub fn assert_eq(&self, actual: &str) { | 75 | pub fn assert_eq(&self, actual: &str) { |
76 | let trimmed = self.trimmed(); | 76 | let trimmed = self.trimmed(); |
77 | if &trimmed == actual { | 77 | if trimmed == actual { |
78 | return; | 78 | return; |
79 | } | 79 | } |
80 | Runtime::fail_expect(self, &trimmed, actual); | 80 | Runtime::fail_expect(self, &trimmed, actual); |
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 7c38f5ef9..31e14246d 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! cargo_check provides the functionality needed to run `cargo check` or | 1 | //! Flycheck provides the functionality needed to run `cargo check` or |
2 | //! another compatible command (f.x. clippy) in a background thread and provide | 2 | //! another compatible command (f.x. clippy) in a background thread and provide |
3 | //! LSP diagnostics based on the output of the command. | 3 | //! LSP diagnostics based on the output of the command. |
4 | 4 | ||
@@ -147,6 +147,12 @@ impl FlycheckActor { | |||
147 | // avoid busy-waiting. | 147 | // avoid busy-waiting. |
148 | let cargo_handle = self.cargo_handle.take().unwrap(); | 148 | let cargo_handle = self.cargo_handle.take().unwrap(); |
149 | let res = cargo_handle.join(); | 149 | let res = cargo_handle.join(); |
150 | if res.is_err() { | ||
151 | log::error!( | ||
152 | "Flycheck failed to run the following command: {:?}", | ||
153 | self.check_command() | ||
154 | ) | ||
155 | } | ||
150 | self.send(Message::Progress(Progress::DidFinish(res))); | 156 | self.send(Message::Progress(Progress::DidFinish(res))); |
151 | } | 157 | } |
152 | Event::CheckEvent(Some(message)) => match message { | 158 | Event::CheckEvent(Some(message)) => match message { |
@@ -253,7 +259,7 @@ impl CargoHandle { | |||
253 | return Err(io::Error::new( | 259 | return Err(io::Error::new( |
254 | io::ErrorKind::Other, | 260 | io::ErrorKind::Other, |
255 | format!( | 261 | format!( |
256 | "Cargo watcher failed,the command produced no valid metadata (exit code: {:?})", | 262 | "Cargo watcher failed, the command produced no valid metadata (exit code: {:?})", |
257 | exit_status | 263 | exit_status |
258 | ), | 264 | ), |
259 | )); | 265 | )); |
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index 3407df856..afd3fd4b9 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs | |||
@@ -73,6 +73,10 @@ impl<'a> AssistContext<'a> { | |||
73 | self.sema.db | 73 | self.sema.db |
74 | } | 74 | } |
75 | 75 | ||
76 | pub(crate) fn source_file(&self) -> &SourceFile { | ||
77 | &self.source_file | ||
78 | } | ||
79 | |||
76 | // NB, this ignores active selection. | 80 | // NB, this ignores active selection. |
77 | pub(crate) fn offset(&self) -> TextSize { | 81 | pub(crate) fn offset(&self) -> TextSize { |
78 | self.frange.range.start() | 82 | self.frange.range.start() |
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs index 28f3f3546..07c978378 100644 --- a/crates/ra_assists/src/ast_transform.rs +++ b/crates/ra_assists/src/ast_transform.rs | |||
@@ -51,7 +51,7 @@ impl<'a> SubstituteTypeParams<'a> { | |||
51 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky | 51 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky |
52 | .skip(1) | 52 | .skip(1) |
53 | // The actual list of trait type parameters may be longer than the one | 53 | // The actual list of trait type parameters may be longer than the one |
54 | // used in the `impl` block due to trailing default type parametrs. | 54 | // used in the `impl` block due to trailing default type parameters. |
55 | // For that case we extend the `substs` with an empty iterator so we | 55 | // For that case we extend the `substs` with an empty iterator so we |
56 | // can still hit those trailing values and check if they actually have | 56 | // can still hit those trailing values and check if they actually have |
57 | // a default type. If they do, go for that type from `hir` to `ast` so | 57 | // a default type. If they do, go for that type from `hir` to `ast` so |
@@ -63,7 +63,7 @@ impl<'a> SubstituteTypeParams<'a> { | |||
63 | let default = k.default(source_scope.db)?; | 63 | let default = k.default(source_scope.db)?; |
64 | Some(( | 64 | Some(( |
65 | k, | 65 | k, |
66 | ast::make::type_ref( | 66 | ast::make::ty( |
67 | &default | 67 | &default |
68 | .display_source_code(source_scope.db, source_scope.module()?.into()) | 68 | .display_source_code(source_scope.db, source_scope.module()?.into()) |
69 | .ok()?, | 69 | .ok()?, |
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index b67438b6b..ebdf00e67 100644 --- a/crates/ra_assists/src/handlers/add_custom_impl.rs +++ b/crates/ra_assists/src/handlers/add_custom_impl.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | use itertools::Itertools; | ||
1 | use ra_syntax::{ | 2 | use ra_syntax::{ |
2 | ast::{self, AstNode}, | 3 | ast::{self, AstNode}, |
3 | Direction, SmolStr, | 4 | Direction, SmolStr, |
4 | SyntaxKind::{IDENT, WHITESPACE}, | 5 | SyntaxKind::{IDENT, WHITESPACE}, |
5 | TextRange, TextSize, | 6 | TextRange, TextSize, |
6 | }; | 7 | }; |
7 | use stdx::SepBy; | ||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | assist_context::{AssistContext, Assists}, | 10 | assist_context::{AssistContext, Assists}, |
@@ -61,9 +61,9 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
61 | .filter(|t| t != trait_token.text()) | 61 | .filter(|t| t != trait_token.text()) |
62 | .collect::<Vec<SmolStr>>(); | 62 | .collect::<Vec<SmolStr>>(); |
63 | let has_more_derives = !new_attr_input.is_empty(); | 63 | let has_more_derives = !new_attr_input.is_empty(); |
64 | let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string(); | ||
65 | 64 | ||
66 | if has_more_derives { | 65 | if has_more_derives { |
66 | let new_attr_input = format!("({})", new_attr_input.iter().format(", ")); | ||
67 | builder.replace(input.syntax().text_range(), new_attr_input); | 67 | builder.replace(input.syntax().text_range(), new_attr_input); |
68 | } else { | 68 | } else { |
69 | let attr_range = attr.syntax().text_range(); | 69 | let attr_range = attr.syntax().text_range(); |
diff --git a/crates/ra_assists/src/handlers/add_turbo_fish.rs b/crates/ra_assists/src/handlers/add_turbo_fish.rs index 0c565e89a..537322a72 100644 --- a/crates/ra_assists/src/handlers/add_turbo_fish.rs +++ b/crates/ra_assists/src/handlers/add_turbo_fish.rs | |||
@@ -41,7 +41,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
41 | let name_ref = ast::NameRef::cast(ident.parent())?; | 41 | let name_ref = ast::NameRef::cast(ident.parent())?; |
42 | let def = match classify_name_ref(&ctx.sema, &name_ref)? { | 42 | let def = match classify_name_ref(&ctx.sema, &name_ref)? { |
43 | NameRefClass::Definition(def) => def, | 43 | NameRefClass::Definition(def) => def, |
44 | NameRefClass::FieldShorthand { .. } => return None, | 44 | NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None, |
45 | }; | 45 | }; |
46 | let fun = match def { | 46 | let fun = match def { |
47 | Definition::ModuleDef(hir::ModuleDef::Function(it)) => it, | 47 | Definition::ModuleDef(hir::ModuleDef::Function(it)) => it, |
diff --git a/crates/ra_assists/src/handlers/apply_demorgan.rs b/crates/ra_assists/src/handlers/apply_demorgan.rs index de701f8b8..3ac4aed7d 100644 --- a/crates/ra_assists/src/handlers/apply_demorgan.rs +++ b/crates/ra_assists/src/handlers/apply_demorgan.rs | |||
@@ -4,7 +4,7 @@ use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKin | |||
4 | 4 | ||
5 | // Assist: apply_demorgan | 5 | // Assist: apply_demorgan |
6 | // | 6 | // |
7 | // Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). | 7 | // Apply https://en.wikipedia.org/wiki/De_Morgan%27s_laws[De Morgan's law]. |
8 | // This transforms expressions of the form `!l || !r` into `!(l && r)`. | 8 | // This transforms expressions of the form `!l || !r` into `!(l && r)`. |
9 | // This also works with `&&`. This assist can only be applied with the cursor | 9 | // This also works with `&&`. This assist can only be applied with the cursor |
10 | // on either `||` or `&&`, with both operands being a negation of some kind. | 10 | // on either `||` or `&&`, with both operands being a negation of some kind. |
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs index 69852b611..6816a2709 100644 --- a/crates/ra_assists/src/handlers/early_return.rs +++ b/crates/ra_assists/src/handlers/early_return.rs | |||
@@ -123,7 +123,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
123 | let happy_arm = { | 123 | let happy_arm = { |
124 | let pat = make::tuple_struct_pat( | 124 | let pat = make::tuple_struct_pat( |
125 | path, | 125 | path, |
126 | once(make::bind_pat(make::name("it")).into()), | 126 | once(make::ident_pat(make::name("it")).into()), |
127 | ); | 127 | ); |
128 | let expr = { | 128 | let expr = { |
129 | let name_ref = make::name_ref("it"); | 129 | let name_ref = make::name_ref("it"); |
@@ -136,7 +136,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
136 | 136 | ||
137 | let sad_arm = make::match_arm( | 137 | let sad_arm = make::match_arm( |
138 | // FIXME: would be cool to use `None` or `Err(_)` if appropriate | 138 | // FIXME: would be cool to use `None` or `Err(_)` if appropriate |
139 | once(make::placeholder_pat().into()), | 139 | once(make::wildcard_pat().into()), |
140 | early_expression, | 140 | early_expression, |
141 | ); | 141 | ); |
142 | 142 | ||
@@ -144,7 +144,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
144 | }; | 144 | }; |
145 | 145 | ||
146 | let let_stmt = make::let_stmt( | 146 | let let_stmt = make::let_stmt( |
147 | make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), | 147 | make::ident_pat(make::name(&bound_ident.syntax().to_string())).into(), |
148 | Some(match_expr), | 148 | Some(match_expr), |
149 | ); | 149 | ); |
150 | let let_stmt = let_stmt.indent(if_indent_level); | 150 | let let_stmt = let_stmt.indent(if_indent_level); |
diff --git a/crates/ra_assists/src/handlers/expand_glob_import.rs b/crates/ra_assists/src/handlers/expand_glob_import.rs new file mode 100644 index 000000000..eb216a81a --- /dev/null +++ b/crates/ra_assists/src/handlers/expand_glob_import.rs | |||
@@ -0,0 +1,391 @@ | |||
1 | use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope}; | ||
2 | use ra_ide_db::{ | ||
3 | defs::{classify_name_ref, Definition, NameRefClass}, | ||
4 | RootDatabase, | ||
5 | }; | ||
6 | use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T}; | ||
7 | |||
8 | use crate::{ | ||
9 | assist_context::{AssistBuilder, AssistContext, Assists}, | ||
10 | AssistId, AssistKind, | ||
11 | }; | ||
12 | |||
13 | use either::Either; | ||
14 | |||
15 | // Assist: expand_glob_import | ||
16 | // | ||
17 | // Expands glob imports. | ||
18 | // | ||
19 | // ``` | ||
20 | // mod foo { | ||
21 | // pub struct Bar; | ||
22 | // pub struct Baz; | ||
23 | // } | ||
24 | // | ||
25 | // use foo::*<|>; | ||
26 | // | ||
27 | // fn qux(bar: Bar, baz: Baz) {} | ||
28 | // ``` | ||
29 | // -> | ||
30 | // ``` | ||
31 | // mod foo { | ||
32 | // pub struct Bar; | ||
33 | // pub struct Baz; | ||
34 | // } | ||
35 | // | ||
36 | // use foo::{Baz, Bar}; | ||
37 | // | ||
38 | // fn qux(bar: Bar, baz: Baz) {} | ||
39 | // ``` | ||
40 | pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
41 | let star = ctx.find_token_at_offset(T![*])?; | ||
42 | let mod_path = find_mod_path(&star)?; | ||
43 | |||
44 | let source_file = ctx.source_file(); | ||
45 | let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset()); | ||
46 | |||
47 | let defs_in_mod = find_defs_in_mod(ctx, scope, &mod_path)?; | ||
48 | let name_refs_in_source_file = | ||
49 | source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect(); | ||
50 | let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file); | ||
51 | |||
52 | let parent = star.parent().parent()?; | ||
53 | acc.add( | ||
54 | AssistId("expand_glob_import", AssistKind::RefactorRewrite), | ||
55 | "Expand glob import", | ||
56 | parent.text_range(), | ||
57 | |builder| { | ||
58 | replace_ast(builder, &parent, mod_path, used_names); | ||
59 | }, | ||
60 | ) | ||
61 | } | ||
62 | |||
63 | fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> { | ||
64 | star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path())) | ||
65 | } | ||
66 | |||
67 | #[derive(PartialEq)] | ||
68 | enum Def { | ||
69 | ModuleDef(ModuleDef), | ||
70 | MacroDef(MacroDef), | ||
71 | } | ||
72 | |||
73 | impl Def { | ||
74 | fn name(&self, db: &RootDatabase) -> Option<Name> { | ||
75 | match self { | ||
76 | Def::ModuleDef(def) => def.name(db), | ||
77 | Def::MacroDef(def) => def.name(db), | ||
78 | } | ||
79 | } | ||
80 | } | ||
81 | |||
82 | fn find_defs_in_mod( | ||
83 | ctx: &AssistContext, | ||
84 | from: SemanticsScope<'_>, | ||
85 | path: &ast::Path, | ||
86 | ) -> Option<Vec<Def>> { | ||
87 | let hir_path = ctx.sema.lower_path(&path)?; | ||
88 | let module = if let Some(PathResolution::Def(ModuleDef::Module(module))) = | ||
89 | from.resolve_hir_path_qualifier(&hir_path) | ||
90 | { | ||
91 | module | ||
92 | } else { | ||
93 | return None; | ||
94 | }; | ||
95 | |||
96 | let module_scope = module.scope(ctx.db(), from.module()); | ||
97 | |||
98 | let mut defs = vec![]; | ||
99 | for (_, def) in module_scope { | ||
100 | match def { | ||
101 | ScopeDef::ModuleDef(def) => defs.push(Def::ModuleDef(def)), | ||
102 | ScopeDef::MacroDef(def) => defs.push(Def::MacroDef(def)), | ||
103 | _ => continue, | ||
104 | } | ||
105 | } | ||
106 | |||
107 | Some(defs) | ||
108 | } | ||
109 | |||
110 | fn find_used_names( | ||
111 | ctx: &AssistContext, | ||
112 | defs_in_mod: Vec<Def>, | ||
113 | name_refs_in_source_file: Vec<ast::NameRef>, | ||
114 | ) -> Vec<Name> { | ||
115 | let defs_in_source_file = name_refs_in_source_file | ||
116 | .iter() | ||
117 | .filter_map(|r| classify_name_ref(&ctx.sema, r)) | ||
118 | .filter_map(|rc| match rc { | ||
119 | NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)), | ||
120 | NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)), | ||
121 | _ => None, | ||
122 | }) | ||
123 | .collect::<Vec<Def>>(); | ||
124 | |||
125 | defs_in_mod | ||
126 | .iter() | ||
127 | .filter(|def| { | ||
128 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = def { | ||
129 | for item in tr.items(ctx.db()) { | ||
130 | if let AssocItem::Function(f) = item { | ||
131 | if defs_in_source_file.contains(&Def::ModuleDef(ModuleDef::Function(f))) { | ||
132 | return true; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | defs_in_source_file.contains(def) | ||
139 | }) | ||
140 | .filter_map(|d| d.name(ctx.db())) | ||
141 | .collect() | ||
142 | } | ||
143 | |||
144 | fn replace_ast( | ||
145 | builder: &mut AssistBuilder, | ||
146 | node: &SyntaxNode, | ||
147 | path: ast::Path, | ||
148 | used_names: Vec<Name>, | ||
149 | ) { | ||
150 | let replacement: Either<ast::UseTree, ast::UseTreeList> = match used_names.as_slice() { | ||
151 | [name] => Either::Left(ast::make::use_tree( | ||
152 | ast::make::path_from_text(&format!("{}::{}", path, name)), | ||
153 | None, | ||
154 | None, | ||
155 | false, | ||
156 | )), | ||
157 | names => Either::Right(ast::make::use_tree_list(names.iter().map(|n| { | ||
158 | ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false) | ||
159 | }))), | ||
160 | }; | ||
161 | |||
162 | let mut replace_node = |replacement: Either<ast::UseTree, ast::UseTreeList>| { | ||
163 | algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone())) | ||
164 | .into_text_edit(builder.text_edit_builder()); | ||
165 | }; | ||
166 | |||
167 | match_ast! { | ||
168 | match node { | ||
169 | ast::UseTree(use_tree) => { | ||
170 | replace_node(replacement); | ||
171 | }, | ||
172 | ast::UseTreeList(use_tree_list) => { | ||
173 | replace_node(replacement); | ||
174 | }, | ||
175 | ast::Use(use_item) => { | ||
176 | builder.replace_ast(use_item, ast::make::use_(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false)))); | ||
177 | }, | ||
178 | _ => {}, | ||
179 | } | ||
180 | } | ||
181 | } | ||
182 | |||
183 | #[cfg(test)] | ||
184 | mod tests { | ||
185 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
186 | |||
187 | use super::*; | ||
188 | |||
189 | #[test] | ||
190 | fn expanding_glob_import() { | ||
191 | check_assist( | ||
192 | expand_glob_import, | ||
193 | r" | ||
194 | mod foo { | ||
195 | pub struct Bar; | ||
196 | pub struct Baz; | ||
197 | pub struct Qux; | ||
198 | |||
199 | pub fn f() {} | ||
200 | } | ||
201 | |||
202 | use foo::*<|>; | ||
203 | |||
204 | fn qux(bar: Bar, baz: Baz) { | ||
205 | f(); | ||
206 | } | ||
207 | ", | ||
208 | r" | ||
209 | mod foo { | ||
210 | pub struct Bar; | ||
211 | pub struct Baz; | ||
212 | pub struct Qux; | ||
213 | |||
214 | pub fn f() {} | ||
215 | } | ||
216 | |||
217 | use foo::{Baz, Bar, f}; | ||
218 | |||
219 | fn qux(bar: Bar, baz: Baz) { | ||
220 | f(); | ||
221 | } | ||
222 | ", | ||
223 | ) | ||
224 | } | ||
225 | |||
226 | #[test] | ||
227 | fn expanding_glob_import_with_existing_explicit_names() { | ||
228 | check_assist( | ||
229 | expand_glob_import, | ||
230 | r" | ||
231 | mod foo { | ||
232 | pub struct Bar; | ||
233 | pub struct Baz; | ||
234 | pub struct Qux; | ||
235 | |||
236 | pub fn f() {} | ||
237 | } | ||
238 | |||
239 | use foo::{*<|>, f}; | ||
240 | |||
241 | fn qux(bar: Bar, baz: Baz) { | ||
242 | f(); | ||
243 | } | ||
244 | ", | ||
245 | r" | ||
246 | mod foo { | ||
247 | pub struct Bar; | ||
248 | pub struct Baz; | ||
249 | pub struct Qux; | ||
250 | |||
251 | pub fn f() {} | ||
252 | } | ||
253 | |||
254 | use foo::{Baz, Bar, f}; | ||
255 | |||
256 | fn qux(bar: Bar, baz: Baz) { | ||
257 | f(); | ||
258 | } | ||
259 | ", | ||
260 | ) | ||
261 | } | ||
262 | |||
263 | #[test] | ||
264 | fn expanding_nested_glob_import() { | ||
265 | check_assist( | ||
266 | expand_glob_import, | ||
267 | r" | ||
268 | mod foo { | ||
269 | mod bar { | ||
270 | pub struct Bar; | ||
271 | pub struct Baz; | ||
272 | pub struct Qux; | ||
273 | |||
274 | pub fn f() {} | ||
275 | } | ||
276 | |||
277 | mod baz { | ||
278 | pub fn g() {} | ||
279 | } | ||
280 | } | ||
281 | |||
282 | use foo::{bar::{*<|>, f}, baz::*}; | ||
283 | |||
284 | fn qux(bar: Bar, baz: Baz) { | ||
285 | f(); | ||
286 | g(); | ||
287 | } | ||
288 | ", | ||
289 | r" | ||
290 | mod foo { | ||
291 | mod bar { | ||
292 | pub struct Bar; | ||
293 | pub struct Baz; | ||
294 | pub struct Qux; | ||
295 | |||
296 | pub fn f() {} | ||
297 | } | ||
298 | |||
299 | mod baz { | ||
300 | pub fn g() {} | ||
301 | } | ||
302 | } | ||
303 | |||
304 | use foo::{bar::{Baz, Bar, f}, baz::*}; | ||
305 | |||
306 | fn qux(bar: Bar, baz: Baz) { | ||
307 | f(); | ||
308 | g(); | ||
309 | } | ||
310 | ", | ||
311 | ) | ||
312 | } | ||
313 | |||
314 | #[test] | ||
315 | fn expanding_glob_import_with_macro_defs() { | ||
316 | check_assist( | ||
317 | expand_glob_import, | ||
318 | r" | ||
319 | //- /lib.rs crate:foo | ||
320 | #[macro_export] | ||
321 | macro_rules! bar { | ||
322 | () => () | ||
323 | } | ||
324 | |||
325 | pub fn baz() {} | ||
326 | |||
327 | //- /main.rs crate:main deps:foo | ||
328 | use foo::*<|>; | ||
329 | |||
330 | fn main() { | ||
331 | bar!(); | ||
332 | baz(); | ||
333 | } | ||
334 | ", | ||
335 | r" | ||
336 | use foo::{bar, baz}; | ||
337 | |||
338 | fn main() { | ||
339 | bar!(); | ||
340 | baz(); | ||
341 | } | ||
342 | ", | ||
343 | ) | ||
344 | } | ||
345 | |||
346 | #[test] | ||
347 | fn expanding_glob_import_with_trait_method_uses() { | ||
348 | check_assist( | ||
349 | expand_glob_import, | ||
350 | r" | ||
351 | //- /lib.rs crate:foo | ||
352 | pub trait Tr { | ||
353 | fn method(&self) {} | ||
354 | } | ||
355 | impl Tr for () {} | ||
356 | |||
357 | //- /main.rs crate:main deps:foo | ||
358 | use foo::*<|>; | ||
359 | |||
360 | fn main() { | ||
361 | ().method(); | ||
362 | } | ||
363 | ", | ||
364 | r" | ||
365 | use foo::Tr; | ||
366 | |||
367 | fn main() { | ||
368 | ().method(); | ||
369 | } | ||
370 | ", | ||
371 | ) | ||
372 | } | ||
373 | |||
374 | #[test] | ||
375 | fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() { | ||
376 | check_assist_not_applicable( | ||
377 | expand_glob_import, | ||
378 | r" | ||
379 | mod foo { | ||
380 | pub struct Bar; | ||
381 | pub struct Baz; | ||
382 | pub struct Qux; | ||
383 | } | ||
384 | |||
385 | use foo::Bar<|>; | ||
386 | |||
387 | fn qux(bar: Bar, baz: Baz) {} | ||
388 | ", | ||
389 | ) | ||
390 | } | ||
391 | } | ||
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index b2e14f9d7..6698d1a27 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs | |||
@@ -197,12 +197,11 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O | |||
197 | // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though | 197 | // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though |
198 | let pat: ast::Pat = match var.source(db).value.kind() { | 198 | let pat: ast::Pat = match var.source(db).value.kind() { |
199 | ast::StructKind::Tuple(field_list) => { | 199 | ast::StructKind::Tuple(field_list) => { |
200 | let pats = | 200 | let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count()); |
201 | iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count()); | ||
202 | make::tuple_struct_pat(path, pats).into() | 201 | make::tuple_struct_pat(path, pats).into() |
203 | } | 202 | } |
204 | ast::StructKind::Record(field_list) => { | 203 | ast::StructKind::Record(field_list) => { |
205 | let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into()); | 204 | let pats = field_list.fields().map(|f| make::ident_pat(f.name().unwrap()).into()); |
206 | make::record_pat(path, pats).into() | 205 | make::record_pat(path, pats).into() |
207 | } | 206 | } |
208 | ast::StructKind::Unit => make::path_pat(path), | 207 | ast::StructKind::Unit => make::path_pat(path), |
diff --git a/crates/ra_assists/src/handlers/fix_visibility.rs b/crates/ra_assists/src/handlers/fix_visibility.rs index 1aefa79cc..a19dbf33f 100644 --- a/crates/ra_assists/src/handlers/fix_visibility.rs +++ b/crates/ra_assists/src/handlers/fix_visibility.rs | |||
@@ -121,7 +121,7 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
121 | Some(cap) => match current_visibility { | 121 | Some(cap) => match current_visibility { |
122 | Some(current_visibility) => builder.replace_snippet( | 122 | Some(current_visibility) => builder.replace_snippet( |
123 | cap, | 123 | cap, |
124 | dbg!(current_visibility.syntax()).text_range(), | 124 | current_visibility.syntax().text_range(), |
125 | format!("$0{}", missing_visibility), | 125 | format!("$0{}", missing_visibility), |
126 | ), | 126 | ), |
127 | None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | 127 | None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), |
diff --git a/crates/ra_assists/src/handlers/generate_function.rs b/crates/ra_assists/src/handlers/generate_function.rs index 56510861d..acc97e648 100644 --- a/crates/ra_assists/src/handlers/generate_function.rs +++ b/crates/ra_assists/src/handlers/generate_function.rs | |||
@@ -142,7 +142,7 @@ impl FunctionBuilder { | |||
142 | let fn_body = make::block_expr(vec![], Some(placeholder_expr)); | 142 | let fn_body = make::block_expr(vec![], Some(placeholder_expr)); |
143 | let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None }; | 143 | let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None }; |
144 | let mut fn_def = | 144 | let mut fn_def = |
145 | make::fn_def(visibility, self.fn_name, self.type_params, self.params, fn_body); | 145 | make::fn_(visibility, self.fn_name, self.type_params, self.params, fn_body); |
146 | let leading_ws; | 146 | let leading_ws; |
147 | let trailing_ws; | 147 | let trailing_ws; |
148 | 148 | ||
diff --git a/crates/ra_assists/src/handlers/generate_impl.rs b/crates/ra_assists/src/handlers/generate_impl.rs index d9b87c9c0..7162dc184 100644 --- a/crates/ra_assists/src/handlers/generate_impl.rs +++ b/crates/ra_assists/src/handlers/generate_impl.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | use itertools::Itertools; | ||
1 | use ra_syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner}; | 2 | use ra_syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner}; |
2 | use stdx::{format_to, SepBy}; | 3 | use stdx::format_to; |
3 | 4 | ||
4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 5 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
5 | 6 | ||
@@ -50,7 +51,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
50 | .filter_map(|it| it.name()) | 51 | .filter_map(|it| it.name()) |
51 | .map(|it| it.text().clone()); | 52 | .map(|it| it.text().clone()); |
52 | 53 | ||
53 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); | 54 | let generic_params = lifetime_params.chain(type_params).format(", "); |
54 | format_to!(buf, "<{}>", generic_params) | 55 | format_to!(buf, "<{}>", generic_params) |
55 | } | 56 | } |
56 | match ctx.config.snippet_cap { | 57 | match ctx.config.snippet_cap { |
diff --git a/crates/ra_assists/src/handlers/generate_new.rs b/crates/ra_assists/src/handlers/generate_new.rs index b84aa24b6..32dfed274 100644 --- a/crates/ra_assists/src/handlers/generate_new.rs +++ b/crates/ra_assists/src/handlers/generate_new.rs | |||
@@ -1,9 +1,10 @@ | |||
1 | use hir::Adt; | 1 | use hir::Adt; |
2 | use itertools::Itertools; | ||
2 | use ra_syntax::{ | 3 | use ra_syntax::{ |
3 | ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner}, | 4 | ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner}, |
4 | T, | 5 | T, |
5 | }; | 6 | }; |
6 | use stdx::{format_to, SepBy}; | 7 | use stdx::format_to; |
7 | 8 | ||
8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 9 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
9 | 10 | ||
@@ -52,8 +53,8 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
52 | let params = field_list | 53 | let params = field_list |
53 | .fields() | 54 | .fields() |
54 | .filter_map(|f| Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax()))) | 55 | .filter_map(|f| Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax()))) |
55 | .sep_by(", "); | 56 | .format(", "); |
56 | let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", "); | 57 | let fields = field_list.fields().filter_map(|f| f.name()).format(", "); |
57 | 58 | ||
58 | format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); | 59 | format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); |
59 | 60 | ||
@@ -102,7 +103,7 @@ fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String { | |||
102 | .map(|it| it.text().clone()); | 103 | .map(|it| it.text().clone()); |
103 | let type_params = | 104 | let type_params = |
104 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); | 105 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); |
105 | format_to!(buf, "<{}>", lifetime_params.chain(type_params).sep_by(", ")) | 106 | format_to!(buf, "<{}>", lifetime_params.chain(type_params).format(", ")) |
106 | } | 107 | } |
107 | 108 | ||
108 | format_to!(buf, " {{\n{}\n}}\n", code); | 109 | format_to!(buf, " {{\n{}\n}}\n", code); |
diff --git a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs index 4537c73a1..fbaf3c06b 100644 --- a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs +++ b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs | |||
@@ -68,7 +68,7 @@ fn generate_fn_def_assist( | |||
68 | let fn_params_without_lifetime: Vec<_> = param_list | 68 | let fn_params_without_lifetime: Vec<_> = param_list |
69 | .params() | 69 | .params() |
70 | .filter_map(|param| match param.ty() { | 70 | .filter_map(|param| match param.ty() { |
71 | Some(ast::Type::ReferenceType(ascribed_type)) | 71 | Some(ast::Type::RefType(ascribed_type)) |
72 | if ascribed_type.lifetime_token() == None => | 72 | if ascribed_type.lifetime_token() == None => |
73 | { | 73 | { |
74 | Some(ascribed_type.amp_token()?.text_range().end()) | 74 | Some(ascribed_type.amp_token()?.text_range().end()) |
diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs index 4e8a0c2db..4c797178f 100644 --- a/crates/ra_assists/src/handlers/raw_string.rs +++ b/crates/ra_assists/src/handlers/raw_string.rs | |||
@@ -173,7 +173,7 @@ fn test_required_hashes() { | |||
173 | } | 173 | } |
174 | 174 | ||
175 | #[cfg(test)] | 175 | #[cfg(test)] |
176 | mod test { | 176 | mod tests { |
177 | use test_utils::mark; | 177 | use test_utils::mark; |
178 | 178 | ||
179 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; | 179 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; |
diff --git a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs index b7e30a7f2..ecafb74a1 100644 --- a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs | |||
@@ -65,7 +65,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
65 | .type_of_pat(&pat) | 65 | .type_of_pat(&pat) |
66 | .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) | 66 | .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty)) |
67 | .map(|it| it.sad_pattern()) | 67 | .map(|it| it.sad_pattern()) |
68 | .unwrap_or_else(|| make::placeholder_pat().into()); | 68 | .unwrap_or_else(|| make::wildcard_pat().into()); |
69 | let else_expr = unwrap_trivial_block(else_block); | 69 | let else_expr = unwrap_trivial_block(else_block); |
70 | make::match_arm(vec![pattern], else_expr) | 70 | make::match_arm(vec![pattern], else_expr) |
71 | }; | 71 | }; |
diff --git a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs index 64ad15a23..e4d436dec 100644 --- a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs +++ b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs | |||
@@ -50,10 +50,10 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> | |||
50 | target, | 50 | target, |
51 | |edit| { | 51 | |edit| { |
52 | let with_placeholder: ast::Pat = match happy_variant { | 52 | let with_placeholder: ast::Pat = match happy_variant { |
53 | None => make::placeholder_pat().into(), | 53 | None => make::wildcard_pat().into(), |
54 | Some(var_name) => make::tuple_struct_pat( | 54 | Some(var_name) => make::tuple_struct_pat( |
55 | make::path_unqualified(make::path_segment(make::name_ref(var_name))), | 55 | make::path_unqualified(make::path_segment(make::name_ref(var_name))), |
56 | once(make::placeholder_pat().into()), | 56 | once(make::wildcard_pat().into()), |
57 | ) | 57 | ) |
58 | .into(), | 58 | .into(), |
59 | }; | 59 | }; |
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs index 53496ede1..da0a860c5 100644 --- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -643,4 +643,46 @@ fn main() { | |||
643 | ", | 643 | ", |
644 | ); | 644 | ); |
645 | } | 645 | } |
646 | |||
647 | #[test] | ||
648 | fn does_not_replace_pub_use() { | ||
649 | check_assist( | ||
650 | replace_qualified_name_with_use, | ||
651 | r" | ||
652 | pub use std::fmt; | ||
653 | |||
654 | impl std::io<|> for Foo { | ||
655 | } | ||
656 | ", | ||
657 | r" | ||
658 | use std::io; | ||
659 | |||
660 | pub use std::fmt; | ||
661 | |||
662 | impl io for Foo { | ||
663 | } | ||
664 | ", | ||
665 | ); | ||
666 | } | ||
667 | |||
668 | #[test] | ||
669 | fn does_not_replace_pub_crate_use() { | ||
670 | check_assist( | ||
671 | replace_qualified_name_with_use, | ||
672 | r" | ||
673 | pub(crate) use std::fmt; | ||
674 | |||
675 | impl std::io<|> for Foo { | ||
676 | } | ||
677 | ", | ||
678 | r" | ||
679 | use std::io; | ||
680 | |||
681 | pub(crate) use std::fmt; | ||
682 | |||
683 | impl io for Foo { | ||
684 | } | ||
685 | ", | ||
686 | ); | ||
687 | } | ||
646 | } | 688 | } |
diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs index e5a4bb23c..d69f2c1b0 100644 --- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs | |||
@@ -52,7 +52,7 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
52 | target, | 52 | target, |
53 | |builder| { | 53 | |builder| { |
54 | let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); | 54 | let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); |
55 | let it = make::bind_pat(make::name("a")).into(); | 55 | let it = make::ident_pat(make::name("a")).into(); |
56 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); | 56 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); |
57 | 57 | ||
58 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); | 58 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); |
@@ -60,7 +60,7 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
60 | 60 | ||
61 | let unreachable_call = make::expr_unreachable(); | 61 | let unreachable_call = make::expr_unreachable(); |
62 | let err_arm = | 62 | let err_arm = |
63 | make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); | 63 | make::match_arm(iter::once(make::wildcard_pat().into()), unreachable_call); |
64 | 64 | ||
65 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); | 65 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); |
66 | let match_expr = make::expr_match(caller.clone(), match_arm_list) | 66 | let match_expr = make::expr_match(caller.clone(), match_arm_list) |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 465b90415..890996a68 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -66,13 +66,13 @@ pub struct GroupLabel(pub String); | |||
66 | 66 | ||
67 | #[derive(Debug, Clone)] | 67 | #[derive(Debug, Clone)] |
68 | pub struct Assist { | 68 | pub struct Assist { |
69 | pub id: AssistId, | 69 | id: AssistId, |
70 | /// Short description of the assist, as shown in the UI. | 70 | /// Short description of the assist, as shown in the UI. |
71 | pub label: String, | 71 | label: String, |
72 | pub group: Option<GroupLabel>, | 72 | group: Option<GroupLabel>, |
73 | /// Target ranges are used to sort assists: the smaller the target range, | 73 | /// Target ranges are used to sort assists: the smaller the target range, |
74 | /// the more specific assist is, and so it should be sorted first. | 74 | /// the more specific assist is, and so it should be sorted first. |
75 | pub target: TextRange, | 75 | target: TextRange, |
76 | } | 76 | } |
77 | 77 | ||
78 | #[derive(Debug, Clone)] | 78 | #[derive(Debug, Clone)] |
@@ -120,10 +120,25 @@ impl Assist { | |||
120 | group: Option<GroupLabel>, | 120 | group: Option<GroupLabel>, |
121 | target: TextRange, | 121 | target: TextRange, |
122 | ) -> Assist { | 122 | ) -> Assist { |
123 | // FIXME: make fields private, so that this invariant can't be broken | ||
124 | assert!(label.starts_with(|c: char| c.is_uppercase())); | 123 | assert!(label.starts_with(|c: char| c.is_uppercase())); |
125 | Assist { id, label, group, target } | 124 | Assist { id, label, group, target } |
126 | } | 125 | } |
126 | |||
127 | pub fn id(&self) -> AssistId { | ||
128 | self.id | ||
129 | } | ||
130 | |||
131 | pub fn label(&self) -> String { | ||
132 | self.label.clone() | ||
133 | } | ||
134 | |||
135 | pub fn group(&self) -> Option<GroupLabel> { | ||
136 | self.group.clone() | ||
137 | } | ||
138 | |||
139 | pub fn target(&self) -> TextRange { | ||
140 | self.target | ||
141 | } | ||
127 | } | 142 | } |
128 | 143 | ||
129 | mod handlers { | 144 | mod handlers { |
@@ -140,6 +155,7 @@ mod handlers { | |||
140 | mod change_return_type_to_result; | 155 | mod change_return_type_to_result; |
141 | mod change_visibility; | 156 | mod change_visibility; |
142 | mod early_return; | 157 | mod early_return; |
158 | mod expand_glob_import; | ||
143 | mod extract_struct_from_enum_variant; | 159 | mod extract_struct_from_enum_variant; |
144 | mod extract_variable; | 160 | mod extract_variable; |
145 | mod fill_match_arms; | 161 | mod fill_match_arms; |
@@ -181,6 +197,7 @@ mod handlers { | |||
181 | change_return_type_to_result::change_return_type_to_result, | 197 | change_return_type_to_result::change_return_type_to_result, |
182 | change_visibility::change_visibility, | 198 | change_visibility::change_visibility, |
183 | early_return::convert_to_guarded_return, | 199 | early_return::convert_to_guarded_return, |
200 | expand_glob_import::expand_glob_import, | ||
184 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, | 201 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, |
185 | extract_variable::extract_variable, | 202 | extract_variable::extract_variable, |
186 | fill_match_arms::fill_match_arms, | 203 | fill_match_arms::fill_match_arms, |
diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs index 18fcb9049..e73836422 100644 --- a/crates/ra_assists/src/tests.rs +++ b/crates/ra_assists/src/tests.rs | |||
@@ -20,7 +20,7 @@ pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_ | |||
20 | 20 | ||
21 | // FIXME: instead of having a separate function here, maybe use | 21 | // FIXME: instead of having a separate function here, maybe use |
22 | // `extract_ranges` and mark the target as `<target> </target>` in the | 22 | // `extract_ranges` and mark the target as `<target> </target>` in the |
23 | // fixuture? | 23 | // fixture? |
24 | pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) { | 24 | pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) { |
25 | check(assist, ra_fixture, ExpectedResult::Target(target)); | 25 | check(assist, ra_fixture, ExpectedResult::Target(target)); |
26 | } | 26 | } |
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs index eff7feded..97978e7a2 100644 --- a/crates/ra_assists/src/tests/generated.rs +++ b/crates/ra_assists/src/tests/generated.rs | |||
@@ -229,6 +229,33 @@ fn main() { | |||
229 | } | 229 | } |
230 | 230 | ||
231 | #[test] | 231 | #[test] |
232 | fn doctest_expand_glob_import() { | ||
233 | check_doc_test( | ||
234 | "expand_glob_import", | ||
235 | r#####" | ||
236 | mod foo { | ||
237 | pub struct Bar; | ||
238 | pub struct Baz; | ||
239 | } | ||
240 | |||
241 | use foo::*<|>; | ||
242 | |||
243 | fn qux(bar: Bar, baz: Baz) {} | ||
244 | "#####, | ||
245 | r#####" | ||
246 | mod foo { | ||
247 | pub struct Bar; | ||
248 | pub struct Baz; | ||
249 | } | ||
250 | |||
251 | use foo::{Baz, Bar}; | ||
252 | |||
253 | fn qux(bar: Bar, baz: Baz) {} | ||
254 | "#####, | ||
255 | ) | ||
256 | } | ||
257 | |||
258 | #[test] | ||
232 | fn doctest_extract_struct_from_enum_variant() { | 259 | fn doctest_extract_struct_from_enum_variant() { |
233 | check_doc_test( | 260 | check_doc_test( |
234 | "extract_struct_from_enum_variant", | 261 | "extract_struct_from_enum_variant", |
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 373de273c..0de6fdf3f 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs | |||
@@ -181,10 +181,10 @@ impl TryEnum { | |||
181 | match self { | 181 | match self { |
182 | TryEnum::Result => make::tuple_struct_pat( | 182 | TryEnum::Result => make::tuple_struct_pat( |
183 | make::path_unqualified(make::path_segment(make::name_ref("Err"))), | 183 | make::path_unqualified(make::path_segment(make::name_ref("Err"))), |
184 | iter::once(make::placeholder_pat().into()), | 184 | iter::once(make::wildcard_pat().into()), |
185 | ) | 185 | ) |
186 | .into(), | 186 | .into(), |
187 | TryEnum::Option => make::bind_pat(make::name("None")).into(), | 187 | TryEnum::Option => make::ident_pat(make::name("None")).into(), |
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
@@ -257,7 +257,7 @@ pub use prelude::*; | |||
257 | .find(|dep| &dep.name.to_string() == std_crate)? | 257 | .find(|dep| &dep.name.to_string() == std_crate)? |
258 | .krate; | 258 | .krate; |
259 | 259 | ||
260 | let mut module = std_crate.root_module(db)?; | 260 | let mut module = std_crate.root_module(db); |
261 | for segment in path { | 261 | for segment in path { |
262 | module = module.children(db).find_map(|child| { | 262 | module = module.children(db).find_map(|child| { |
263 | let name = child.name(db)?; | 263 | let name = child.name(db)?; |
diff --git a/crates/ra_assists/src/utils/insert_use.rs b/crates/ra_assists/src/utils/insert_use.rs index 617afe2e9..32780fceb 100644 --- a/crates/ra_assists/src/utils/insert_use.rs +++ b/crates/ra_assists/src/utils/insert_use.rs | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | use hir::{self, ModPath}; | 5 | use hir::{self, ModPath}; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | ast::{self, NameOwner}, | 7 | ast::{self, NameOwner, VisibilityOwner}, |
8 | AstNode, Direction, SmolStr, | 8 | AstNode, Direction, SmolStr, |
9 | SyntaxKind::{PATH, PATH_SEGMENT}, | 9 | SyntaxKind::{PATH, PATH_SEGMENT}, |
10 | SyntaxNode, T, | 10 | SyntaxNode, T, |
@@ -378,6 +378,7 @@ fn best_action_for_target( | |||
378 | let best_action = container | 378 | let best_action = container |
379 | .children() | 379 | .children() |
380 | .filter_map(ast::Use::cast) | 380 | .filter_map(ast::Use::cast) |
381 | .filter(|u| u.visibility().is_none()) | ||
381 | .filter_map(|it| it.use_tree()) | 382 | .filter_map(|it| it.use_tree()) |
382 | .map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target)) | 383 | .map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target)) |
383 | .fold(None, |best, a| match best { | 384 | .fold(None, |best, a| match best { |
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml index 5f334d04f..fe73dc015 100644 --- a/crates/ra_db/Cargo.toml +++ b/crates/ra_db/Cargo.toml | |||
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" | |||
9 | doctest = false | 9 | doctest = false |
10 | 10 | ||
11 | [dependencies] | 11 | [dependencies] |
12 | salsa = "0.15.0" | 12 | salsa = "0.15.2" |
13 | rustc-hash = "1.1.0" | 13 | rustc-hash = "1.1.0" |
14 | 14 | ||
15 | ra_syntax = { path = "../ra_syntax" } | 15 | ra_syntax = { path = "../ra_syntax" } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 27cdabea0..0007d7fa8 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -4,6 +4,7 @@ use std::{iter, sync::Arc}; | |||
4 | use arrayvec::ArrayVec; | 4 | use arrayvec::ArrayVec; |
5 | use either::Either; | 5 | use either::Either; |
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | adt::ReprKind, | ||
7 | adt::StructKind, | 8 | adt::StructKind, |
8 | adt::VariantData, | 9 | adt::VariantData, |
9 | builtin_type::BuiltinType, | 10 | builtin_type::BuiltinType, |
@@ -83,9 +84,9 @@ impl Crate { | |||
83 | .collect() | 84 | .collect() |
84 | } | 85 | } |
85 | 86 | ||
86 | pub fn root_module(self, db: &dyn HirDatabase) -> Option<Module> { | 87 | pub fn root_module(self, db: &dyn HirDatabase) -> Module { |
87 | let module_id = db.crate_def_map(self.id).root; | 88 | let module_id = db.crate_def_map(self.id).root; |
88 | Some(Module::new(self, module_id)) | 89 | Module::new(self, module_id) |
89 | } | 90 | } |
90 | 91 | ||
91 | pub fn root_file(self, db: &dyn HirDatabase) -> FileId { | 92 | pub fn root_file(self, db: &dyn HirDatabase) -> FileId { |
@@ -431,6 +432,10 @@ impl Struct { | |||
431 | Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) | 432 | Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) |
432 | } | 433 | } |
433 | 434 | ||
435 | pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> { | ||
436 | db.struct_data(self.id).repr.clone() | ||
437 | } | ||
438 | |||
434 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { | 439 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { |
435 | db.struct_data(self.id).variant_data.clone() | 440 | db.struct_data(self.id).variant_data.clone() |
436 | } | 441 | } |
@@ -1253,6 +1258,19 @@ impl Type { | |||
1253 | ) | 1258 | ) |
1254 | } | 1259 | } |
1255 | 1260 | ||
1261 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | ||
1262 | let adt_id = match self.ty.value { | ||
1263 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id, | ||
1264 | _ => return false, | ||
1265 | }; | ||
1266 | |||
1267 | let adt = adt_id.into(); | ||
1268 | match adt { | ||
1269 | Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)), | ||
1270 | _ => false, | ||
1271 | } | ||
1272 | } | ||
1273 | |||
1256 | pub fn is_raw_ptr(&self) -> bool { | 1274 | pub fn is_raw_ptr(&self) -> bool { |
1257 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) | 1275 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) |
1258 | } | 1276 | } |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index a2b9f3e35..07333c453 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -13,14 +13,7 @@ pub use hir_expand::db::{ | |||
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, |
14 | MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, | 14 | MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, |
15 | }; | 15 | }; |
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::*; |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | ||
18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, | ||
19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery, | ||
20 | InherentImplsInCrateQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, | ||
21 | TraitDatumQuery, TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, | ||
22 | ValueTyQuery, | ||
23 | }; | ||
24 | 17 | ||
25 | #[test] | 18 | #[test] |
26 | fn hir_database_is_object_safe() { | 19 | fn hir_database_is_object_safe() { |
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs index 266b513dc..363164b9b 100644 --- a/crates/ra_hir/src/diagnostics.rs +++ b/crates/ra_hir/src/diagnostics.rs | |||
@@ -1,8 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | pub use hir_def::diagnostics::UnresolvedModule; | 2 | pub use hir_def::diagnostics::UnresolvedModule; |
3 | pub use hir_expand::diagnostics::{ | 3 | pub use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticSinkBuilder}; |
4 | AstDiagnostic, Diagnostic, DiagnosticSink, DiagnosticSinkBuilder, | ||
5 | }; | ||
6 | pub use hir_ty::diagnostics::{ | 4 | pub use hir_ty::diagnostics::{ |
7 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, | 5 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, |
8 | }; | 6 | }; |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 31f3241c9..34b02c536 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -49,7 +49,7 @@ pub use hir_def::{ | |||
49 | docs::Documentation, | 49 | docs::Documentation, |
50 | nameres::ModuleSource, | 50 | nameres::ModuleSource, |
51 | path::{ModPath, Path, PathKind}, | 51 | path::{ModPath, Path, PathKind}, |
52 | type_ref::Mutability, | 52 | type_ref::{Mutability, TypeRef}, |
53 | }; | 53 | }; |
54 | pub use hir_expand::{ | 54 | pub use hir_expand::{ |
55 | hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, | 55 | hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 307b336f2..36b688ccb 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -8,7 +8,7 @@ use hir_def::{ | |||
8 | resolver::{self, HasResolver, Resolver}, | 8 | resolver::{self, HasResolver, Resolver}, |
9 | AsMacroCall, FunctionId, TraitId, VariantId, | 9 | AsMacroCall, FunctionId, TraitId, VariantId, |
10 | }; | 10 | }; |
11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; | 11 | use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; |
12 | use hir_ty::associated_type_shorthand_candidates; | 12 | use hir_ty::associated_type_shorthand_candidates; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use ra_db::{FileId, FileRange}; | 14 | use ra_db::{FileId, FileRange}; |
@@ -24,8 +24,9 @@ use crate::{ | |||
24 | diagnostics::Diagnostic, | 24 | diagnostics::Diagnostic, |
25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, | 26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, |
27 | AssocItem, Callable, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, | 27 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, |
28 | ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, | 28 | Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, TypeRef, |
29 | VariantDef, | ||
29 | }; | 30 | }; |
30 | use resolver::TypeNs; | 31 | use resolver::TypeNs; |
31 | 32 | ||
@@ -109,13 +110,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
109 | self.imp.parse(file_id) | 110 | self.imp.parse(file_id) |
110 | } | 111 | } |
111 | 112 | ||
112 | pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST { | ||
113 | let file_id = d.source().file_id; | ||
114 | let root = self.db.parse_or_expand(file_id).unwrap(); | ||
115 | self.imp.cache(root, file_id); | ||
116 | d.ast(self.db.upcast()) | ||
117 | } | ||
118 | |||
119 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | 113 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { |
120 | self.imp.expand(macro_call) | 114 | self.imp.expand(macro_call) |
121 | } | 115 | } |
@@ -145,8 +139,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
145 | self.imp.original_range(node) | 139 | self.imp.original_range(node) |
146 | } | 140 | } |
147 | 141 | ||
148 | pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | 142 | pub fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { |
149 | self.imp.diagnostics_range(diagnostics) | 143 | self.imp.diagnostics_display_range(diagnostics) |
150 | } | 144 | } |
151 | 145 | ||
152 | pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { | 146 | pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { |
@@ -228,6 +222,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
228 | self.imp.resolve_path(path) | 222 | self.imp.resolve_path(path) |
229 | } | 223 | } |
230 | 224 | ||
225 | pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { | ||
226 | self.imp.resolve_extern_crate(extern_crate) | ||
227 | } | ||
228 | |||
231 | pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> { | 229 | pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> { |
232 | self.imp.resolve_variant(record_lit).map(VariantDef::from) | 230 | self.imp.resolve_variant(record_lit).map(VariantDef::from) |
233 | } | 231 | } |
@@ -275,6 +273,18 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
275 | pub fn assert_contains_node(&self, node: &SyntaxNode) { | 273 | pub fn assert_contains_node(&self, node: &SyntaxNode) { |
276 | self.imp.assert_contains_node(node) | 274 | self.imp.assert_contains_node(node) |
277 | } | 275 | } |
276 | |||
277 | pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { | ||
278 | self.imp.is_unsafe_method_call(method_call_expr) | ||
279 | } | ||
280 | |||
281 | pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { | ||
282 | self.imp.is_unsafe_ref_expr(ref_expr) | ||
283 | } | ||
284 | |||
285 | pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { | ||
286 | self.imp.is_unsafe_ident_pat(ident_pat) | ||
287 | } | ||
278 | } | 288 | } |
279 | 289 | ||
280 | impl<'db> SemanticsImpl<'db> { | 290 | impl<'db> SemanticsImpl<'db> { |
@@ -372,10 +382,11 @@ impl<'db> SemanticsImpl<'db> { | |||
372 | original_range(self.db, node.as_ref()) | 382 | original_range(self.db, node.as_ref()) |
373 | } | 383 | } |
374 | 384 | ||
375 | fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | 385 | fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { |
376 | let src = diagnostics.source(); | 386 | let src = diagnostics.display_source(); |
377 | let root = self.db.parse_or_expand(src.file_id).unwrap(); | 387 | let root = self.db.parse_or_expand(src.file_id).unwrap(); |
378 | let node = src.value.to_node(&root); | 388 | let node = src.value.to_node(&root); |
389 | self.cache(root, src.file_id); | ||
379 | original_range(self.db, src.with_value(&node)) | 390 | original_range(self.db, src.with_value(&node)) |
380 | } | 391 | } |
381 | 392 | ||
@@ -443,6 +454,17 @@ impl<'db> SemanticsImpl<'db> { | |||
443 | self.analyze(path.syntax()).resolve_path(self.db, path) | 454 | self.analyze(path.syntax()).resolve_path(self.db, path) |
444 | } | 455 | } |
445 | 456 | ||
457 | fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { | ||
458 | let krate = self.scope(extern_crate.syntax()).krate()?; | ||
459 | krate.dependencies(self.db).into_iter().find_map(|dep| { | ||
460 | if dep.name == extern_crate.name_ref()?.as_name() { | ||
461 | Some(dep.krate) | ||
462 | } else { | ||
463 | None | ||
464 | } | ||
465 | }) | ||
466 | } | ||
467 | |||
446 | fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { | 468 | fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { |
447 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) | 469 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) |
448 | } | 470 | } |
@@ -559,6 +581,90 @@ impl<'db> SemanticsImpl<'db> { | |||
559 | }); | 581 | }); |
560 | InFile::new(file_id, node) | 582 | InFile::new(file_id, node) |
561 | } | 583 | } |
584 | |||
585 | pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { | ||
586 | method_call_expr | ||
587 | .expr() | ||
588 | .and_then(|expr| { | ||
589 | let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { | ||
590 | field_expr | ||
591 | } else { | ||
592 | return None; | ||
593 | }; | ||
594 | let ty = self.type_of_expr(&field_expr.expr()?)?; | ||
595 | if !ty.is_packed(self.db) { | ||
596 | return None; | ||
597 | } | ||
598 | |||
599 | let func = self.resolve_method_call(&method_call_expr).map(Function::from)?; | ||
600 | let is_unsafe = func.has_self_param(self.db) | ||
601 | && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..))); | ||
602 | Some(is_unsafe) | ||
603 | }) | ||
604 | .unwrap_or(false) | ||
605 | } | ||
606 | |||
607 | pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { | ||
608 | ref_expr | ||
609 | .expr() | ||
610 | .and_then(|expr| { | ||
611 | let field_expr = match expr { | ||
612 | ast::Expr::FieldExpr(field_expr) => field_expr, | ||
613 | _ => return None, | ||
614 | }; | ||
615 | let expr = field_expr.expr()?; | ||
616 | self.type_of_expr(&expr) | ||
617 | }) | ||
618 | // Binding a reference to a packed type is possibly unsafe. | ||
619 | .map(|ty| ty.is_packed(self.db)) | ||
620 | .unwrap_or(false) | ||
621 | |||
622 | // FIXME This needs layout computation to be correct. It will highlight | ||
623 | // more than it should with the current implementation. | ||
624 | } | ||
625 | |||
626 | pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { | ||
627 | if !ident_pat.ref_token().is_some() { | ||
628 | return false; | ||
629 | } | ||
630 | |||
631 | ident_pat | ||
632 | .syntax() | ||
633 | .parent() | ||
634 | .and_then(|parent| { | ||
635 | // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or | ||
636 | // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`, | ||
637 | // so this tries to lookup the `IdentPat` anywhere along that structure to the | ||
638 | // `RecordPat` so we can get the containing type. | ||
639 | let record_pat = ast::RecordPatField::cast(parent.clone()) | ||
640 | .and_then(|record_pat| record_pat.syntax().parent()) | ||
641 | .or_else(|| Some(parent.clone())) | ||
642 | .and_then(|parent| { | ||
643 | ast::RecordPatFieldList::cast(parent)? | ||
644 | .syntax() | ||
645 | .parent() | ||
646 | .and_then(ast::RecordPat::cast) | ||
647 | }); | ||
648 | |||
649 | // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if | ||
650 | // this is initialized from a `FieldExpr`. | ||
651 | if let Some(record_pat) = record_pat { | ||
652 | self.type_of_pat(&ast::Pat::RecordPat(record_pat)) | ||
653 | } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { | ||
654 | let field_expr = match let_stmt.initializer()? { | ||
655 | ast::Expr::FieldExpr(field_expr) => field_expr, | ||
656 | _ => return None, | ||
657 | }; | ||
658 | |||
659 | self.type_of_expr(&field_expr.expr()?) | ||
660 | } else { | ||
661 | None | ||
662 | } | ||
663 | }) | ||
664 | // Binding a reference to a packed type is possibly unsafe. | ||
665 | .map(|ty| ty.is_packed(self.db)) | ||
666 | .unwrap_or(false) | ||
667 | } | ||
562 | } | 668 | } |
563 | 669 | ||
564 | pub trait ToDef: AstNode + Clone { | 670 | pub trait ToDef: AstNode + Clone { |
@@ -612,6 +718,10 @@ impl<'a> SemanticsScope<'a> { | |||
612 | Some(Module { id: self.resolver.module()? }) | 718 | Some(Module { id: self.resolver.module()? }) |
613 | } | 719 | } |
614 | 720 | ||
721 | pub fn krate(&self) -> Option<Crate> { | ||
722 | Some(Crate { id: self.resolver.krate()? }) | ||
723 | } | ||
724 | |||
615 | /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type | 725 | /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type |
616 | // FIXME: rename to visible_traits to not repeat scope? | 726 | // FIXME: rename to visible_traits to not repeat scope? |
617 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { | 727 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index d0cb62ef0..d3d62debf 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -265,8 +265,7 @@ impl SourceAnalyzer { | |||
265 | } | 265 | } |
266 | 266 | ||
267 | // This must be a normal source file rather than macro file. | 267 | // This must be a normal source file rather than macro file. |
268 | let hir_path = | 268 | let hir_path = Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; |
269 | crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; | ||
270 | 269 | ||
271 | // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we | 270 | // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we |
272 | // trying to resolve foo::bar. | 271 | // trying to resolve foo::bar. |
@@ -451,7 +450,7 @@ fn adjust( | |||
451 | pub(crate) fn resolve_hir_path( | 450 | pub(crate) fn resolve_hir_path( |
452 | db: &dyn HirDatabase, | 451 | db: &dyn HirDatabase, |
453 | resolver: &Resolver, | 452 | resolver: &Resolver, |
454 | path: &crate::Path, | 453 | path: &Path, |
455 | ) -> Option<PathResolution> { | 454 | ) -> Option<PathResolution> { |
456 | let types = | 455 | let types = |
457 | resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { | 456 | resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { |
@@ -512,7 +511,7 @@ pub(crate) fn resolve_hir_path( | |||
512 | pub(crate) fn resolve_hir_path_qualifier( | 511 | pub(crate) fn resolve_hir_path_qualifier( |
513 | db: &dyn HirDatabase, | 512 | db: &dyn HirDatabase, |
514 | resolver: &Resolver, | 513 | resolver: &Resolver, |
515 | path: &crate::Path, | 514 | path: &Path, |
516 | ) -> Option<PathResolution> { | 515 | ) -> Option<PathResolution> { |
517 | let items = resolver | 516 | let items = resolver |
518 | .resolve_module_path_in_items(db.upcast(), path.mod_path()) | 517 | .resolve_module_path_in_items(db.upcast(), path.mod_path()) |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 6cb56a1cd..35c3a9140 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -9,11 +9,12 @@ use hir_expand::{ | |||
9 | }; | 9 | }; |
10 | use ra_arena::{map::ArenaMap, Arena}; | 10 | use ra_arena::{map::ArenaMap, Arena}; |
11 | use ra_syntax::ast::{self, NameOwner, VisibilityOwner}; | 11 | use ra_syntax::ast::{self, NameOwner, VisibilityOwner}; |
12 | use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}; | ||
12 | 13 | ||
13 | use crate::{ | 14 | use crate::{ |
14 | body::{CfgExpander, LowerCtx}, | 15 | body::{CfgExpander, LowerCtx}, |
15 | db::DefDatabase, | 16 | db::DefDatabase, |
16 | item_tree::{Field, Fields, ItemTree}, | 17 | item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem}, |
17 | src::HasChildSource, | 18 | src::HasChildSource, |
18 | src::HasSource, | 19 | src::HasSource, |
19 | trace::Trace, | 20 | trace::Trace, |
@@ -29,6 +30,7 @@ use ra_cfg::CfgOptions; | |||
29 | pub struct StructData { | 30 | pub struct StructData { |
30 | pub name: Name, | 31 | pub name: Name, |
31 | pub variant_data: Arc<VariantData>, | 32 | pub variant_data: Arc<VariantData>, |
33 | pub repr: Option<ReprKind>, | ||
32 | } | 34 | } |
33 | 35 | ||
34 | #[derive(Debug, Clone, PartialEq, Eq)] | 36 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -58,26 +60,58 @@ pub struct FieldData { | |||
58 | pub visibility: RawVisibility, | 60 | pub visibility: RawVisibility, |
59 | } | 61 | } |
60 | 62 | ||
63 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
64 | pub enum ReprKind { | ||
65 | Packed, | ||
66 | Other, | ||
67 | } | ||
68 | |||
69 | fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> { | ||
70 | item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt) | ||
71 | } | ||
72 | |||
73 | fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { | ||
74 | match tt.delimiter { | ||
75 | Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {} | ||
76 | _ => return None, | ||
77 | } | ||
78 | |||
79 | let mut it = tt.token_trees.iter(); | ||
80 | match it.next()? { | ||
81 | TokenTree::Leaf(Leaf::Ident(ident)) if ident.text == "packed" => Some(ReprKind::Packed), | ||
82 | _ => Some(ReprKind::Other), | ||
83 | } | ||
84 | } | ||
85 | |||
61 | impl StructData { | 86 | impl StructData { |
62 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { | 87 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { |
63 | let loc = id.lookup(db); | 88 | let loc = id.lookup(db); |
64 | let item_tree = db.item_tree(loc.id.file_id); | 89 | let item_tree = db.item_tree(loc.id.file_id); |
90 | let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); | ||
65 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 91 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); |
66 | 92 | ||
67 | let strukt = &item_tree[loc.id.value]; | 93 | let strukt = &item_tree[loc.id.value]; |
68 | let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields); | 94 | let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields); |
69 | 95 | Arc::new(StructData { | |
70 | Arc::new(StructData { name: strukt.name.clone(), variant_data: Arc::new(variant_data) }) | 96 | name: strukt.name.clone(), |
97 | variant_data: Arc::new(variant_data), | ||
98 | repr, | ||
99 | }) | ||
71 | } | 100 | } |
72 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { | 101 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { |
73 | let loc = id.lookup(db); | 102 | let loc = id.lookup(db); |
74 | let item_tree = db.item_tree(loc.id.file_id); | 103 | let item_tree = db.item_tree(loc.id.file_id); |
104 | let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); | ||
75 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 105 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); |
76 | 106 | ||
77 | let union = &item_tree[loc.id.value]; | 107 | let union = &item_tree[loc.id.value]; |
78 | let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields); | 108 | let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields); |
79 | 109 | ||
80 | Arc::new(StructData { name: union.name.clone(), variant_data: Arc::new(variant_data) }) | 110 | Arc::new(StructData { |
111 | name: union.name.clone(), | ||
112 | variant_data: Arc::new(variant_data), | ||
113 | repr, | ||
114 | }) | ||
81 | } | 115 | } |
82 | } | 116 | } |
83 | 117 | ||
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs index 30db48f86..71d177070 100644 --- a/crates/ra_hir_def/src/diagnostics.rs +++ b/crates/ra_hir_def/src/diagnostics.rs | |||
@@ -18,7 +18,7 @@ impl Diagnostic for UnresolvedModule { | |||
18 | fn message(&self) -> String { | 18 | fn message(&self) -> String { |
19 | "unresolved module".to_string() | 19 | "unresolved module".to_string() |
20 | } | 20 | } |
21 | fn source(&self) -> InFile<SyntaxNodePtr> { | 21 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
22 | InFile::new(self.file, self.decl.clone().into()) | 22 | InFile::new(self.file, self.decl.clone().into()) |
23 | } | 23 | } |
24 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 24 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index fe6619d9f..6f7884ffe 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -94,7 +94,7 @@ impl TypeRef { | |||
94 | .map(TypeRef::Path) | 94 | .map(TypeRef::Path) |
95 | .unwrap_or(TypeRef::Error) | 95 | .unwrap_or(TypeRef::Error) |
96 | } | 96 | } |
97 | ast::Type::PointerType(inner) => { | 97 | ast::Type::PtrType(inner) => { |
98 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); | 98 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); |
99 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 99 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
100 | TypeRef::RawPtr(Box::new(inner_ty), mutability) | 100 | TypeRef::RawPtr(Box::new(inner_ty), mutability) |
@@ -105,13 +105,13 @@ impl TypeRef { | |||
105 | ast::Type::SliceType(inner) => { | 105 | ast::Type::SliceType(inner) => { |
106 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) | 106 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) |
107 | } | 107 | } |
108 | ast::Type::ReferenceType(inner) => { | 108 | ast::Type::RefType(inner) => { |
109 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); | 109 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); |
110 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 110 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
111 | TypeRef::Reference(Box::new(inner_ty), mutability) | 111 | TypeRef::Reference(Box::new(inner_ty), mutability) |
112 | } | 112 | } |
113 | ast::Type::InferType(_inner) => TypeRef::Placeholder, | 113 | ast::Type::InferType(_inner) => TypeRef::Placeholder, |
114 | ast::Type::FnPointerType(inner) => { | 114 | ast::Type::FnPtrType(inner) => { |
115 | let ret_ty = inner | 115 | let ret_ty = inner |
116 | .ret_type() | 116 | .ret_type() |
117 | .and_then(|rt| rt.ty()) | 117 | .and_then(|rt| rt.ty()) |
diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs index 84ba97b14..b138500e7 100644 --- a/crates/ra_hir_expand/src/diagnostics.rs +++ b/crates/ra_hir_expand/src/diagnostics.rs | |||
@@ -16,35 +16,20 @@ | |||
16 | 16 | ||
17 | use std::{any::Any, fmt}; | 17 | use std::{any::Any, fmt}; |
18 | 18 | ||
19 | use ra_syntax::{SyntaxNode, SyntaxNodePtr}; | 19 | use ra_syntax::SyntaxNodePtr; |
20 | 20 | ||
21 | use crate::{db::AstDatabase, InFile}; | 21 | use crate::InFile; |
22 | 22 | ||
23 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { | 23 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { |
24 | fn message(&self) -> String; | 24 | fn message(&self) -> String; |
25 | fn source(&self) -> InFile<SyntaxNodePtr>; | 25 | /// Used in highlighting and related purposes |
26 | fn display_source(&self) -> InFile<SyntaxNodePtr>; | ||
26 | fn as_any(&self) -> &(dyn Any + Send + 'static); | 27 | fn as_any(&self) -> &(dyn Any + Send + 'static); |
27 | fn is_experimental(&self) -> bool { | 28 | fn is_experimental(&self) -> bool { |
28 | false | 29 | false |
29 | } | 30 | } |
30 | } | 31 | } |
31 | 32 | ||
32 | pub trait AstDiagnostic { | ||
33 | type AST; | ||
34 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST; | ||
35 | } | ||
36 | |||
37 | impl dyn Diagnostic { | ||
38 | pub fn syntax_node(&self, db: &impl AstDatabase) -> SyntaxNode { | ||
39 | let node = db.parse_or_expand(self.source().file_id).unwrap(); | ||
40 | self.source().value.to_node(&node) | ||
41 | } | ||
42 | |||
43 | pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> { | ||
44 | self.as_any().downcast_ref() | ||
45 | } | ||
46 | } | ||
47 | |||
48 | pub struct DiagnosticSink<'a> { | 33 | pub struct DiagnosticSink<'a> { |
49 | callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, | 34 | callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, |
50 | filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>, | 35 | filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>, |
@@ -89,7 +74,7 @@ impl<'a> DiagnosticSinkBuilder<'a> { | |||
89 | } | 74 | } |
90 | 75 | ||
91 | pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> Self { | 76 | pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> Self { |
92 | let cb = move |diag: &dyn Diagnostic| match diag.downcast_ref::<D>() { | 77 | let cb = move |diag: &dyn Diagnostic| match diag.as_any().downcast_ref::<D>() { |
93 | Some(d) => { | 78 | Some(d) => { |
94 | cb(d); | 79 | cb(d); |
95 | Ok(()) | 80 | Ok(()) |
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs index 6b482a60c..aefe47bd3 100644 --- a/crates/ra_hir_expand/src/hygiene.rs +++ b/crates/ra_hir_expand/src/hygiene.rs | |||
@@ -17,7 +17,7 @@ pub struct Hygiene { | |||
17 | // This is what `$crate` expands to | 17 | // This is what `$crate` expands to |
18 | def_crate: Option<CrateId>, | 18 | def_crate: Option<CrateId>, |
19 | 19 | ||
20 | // Indiciate this is a local inner macro | 20 | // Indicate this is a local inner macro |
21 | local_inner: bool, | 21 | local_inner: bool, |
22 | } | 22 | } |
23 | 23 | ||
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 2e8d63691..8bb735fc6 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -44,7 +44,8 @@ mod test_db; | |||
44 | /// containing the call plus the offset of the macro call in the file. Note that | 44 | /// containing the call plus the offset of the macro call in the file. Note that |
45 | /// this is a recursive definition! However, the size_of of `HirFileId` is | 45 | /// this is a recursive definition! However, the size_of of `HirFileId` is |
46 | /// finite (because everything bottoms out at the real `FileId`) and small | 46 | /// finite (because everything bottoms out at the real `FileId`) and small |
47 | /// (`MacroCallId` uses the location interner). | 47 | /// (`MacroCallId` uses the location interning. You can check details here: |
48 | /// https://en.wikipedia.org/wiki/String_interning). | ||
48 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 49 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
49 | pub struct HirFileId(HirFileIdRepr); | 50 | pub struct HirFileId(HirFileIdRepr); |
50 | 51 | ||
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs index 04c026004..2c0ec41d2 100644 --- a/crates/ra_hir_expand/src/proc_macro.rs +++ b/crates/ra_hir_expand/src/proc_macro.rs | |||
@@ -101,7 +101,7 @@ fn remove_derive_attrs(tt: &tt::Subtree) -> Option<tt::Subtree> { | |||
101 | } | 101 | } |
102 | 102 | ||
103 | #[cfg(test)] | 103 | #[cfg(test)] |
104 | mod test { | 104 | mod tests { |
105 | use super::*; | 105 | use super::*; |
106 | use test_utils::assert_eq_text; | 106 | use test_utils::assert_eq_text; |
107 | 107 | ||
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 623ce261a..83397d579 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -28,9 +28,9 @@ test_utils = { path = "../test_utils" } | |||
28 | 28 | ||
29 | scoped-tls = "1" | 29 | scoped-tls = "1" |
30 | 30 | ||
31 | chalk-solve = { version = "0.19.0" } | 31 | chalk-solve = { version = "0.21.0" } |
32 | chalk-ir = { version = "0.19.0" } | 32 | chalk-ir = { version = "0.21.0" } |
33 | chalk-recursive = { version = "0.19.0" } | 33 | chalk-recursive = { version = "0.21.0" } |
34 | 34 | ||
35 | [dev-dependencies] | 35 | [dev-dependencies] |
36 | expect = { path = "../expect" } | 36 | expect = { path = "../expect" } |
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 977c0525b..7ab7f79db 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -6,10 +6,10 @@ mod unsafe_check; | |||
6 | use std::any::Any; | 6 | use std::any::Any; |
7 | 7 | ||
8 | use hir_def::DefWithBodyId; | 8 | use hir_def::DefWithBodyId; |
9 | use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; | 9 | use hir_expand::diagnostics::{Diagnostic, DiagnosticSink}; |
10 | use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; | 10 | use hir_expand::{name::Name, HirFileId, InFile}; |
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; | 12 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; |
13 | use stdx::format_to; | 13 | use stdx::format_to; |
14 | 14 | ||
15 | use crate::db::HirDatabase; | 15 | use crate::db::HirDatabase; |
@@ -37,7 +37,7 @@ impl Diagnostic for NoSuchField { | |||
37 | "no such field".to_string() | 37 | "no such field".to_string() |
38 | } | 38 | } |
39 | 39 | ||
40 | fn source(&self) -> InFile<SyntaxNodePtr> { | 40 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
41 | InFile::new(self.file, self.field.clone().into()) | 41 | InFile::new(self.file, self.field.clone().into()) |
42 | } | 42 | } |
43 | 43 | ||
@@ -46,20 +46,11 @@ impl Diagnostic for NoSuchField { | |||
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | impl AstDiagnostic for NoSuchField { | ||
50 | type AST = ast::RecordExprField; | ||
51 | |||
52 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
53 | let root = db.parse_or_expand(self.source().file_id).unwrap(); | ||
54 | let node = self.source().value.to_node(&root); | ||
55 | ast::RecordExprField::cast(node).unwrap() | ||
56 | } | ||
57 | } | ||
58 | |||
59 | #[derive(Debug)] | 49 | #[derive(Debug)] |
60 | pub struct MissingFields { | 50 | pub struct MissingFields { |
61 | pub file: HirFileId, | 51 | pub file: HirFileId, |
62 | pub field_list: AstPtr<ast::RecordExprFieldList>, | 52 | pub field_list_parent: AstPtr<ast::RecordExpr>, |
53 | pub field_list_parent_path: Option<AstPtr<ast::Path>>, | ||
63 | pub missed_fields: Vec<Name>, | 54 | pub missed_fields: Vec<Name>, |
64 | } | 55 | } |
65 | 56 | ||
@@ -71,28 +62,28 @@ impl Diagnostic for MissingFields { | |||
71 | } | 62 | } |
72 | buf | 63 | buf |
73 | } | 64 | } |
74 | fn source(&self) -> InFile<SyntaxNodePtr> { | 65 | |
75 | InFile { file_id: self.file, value: self.field_list.clone().into() } | 66 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
67 | InFile { | ||
68 | file_id: self.file, | ||
69 | value: self | ||
70 | .field_list_parent_path | ||
71 | .clone() | ||
72 | .map(SyntaxNodePtr::from) | ||
73 | .unwrap_or_else(|| self.field_list_parent.clone().into()), | ||
74 | } | ||
76 | } | 75 | } |
76 | |||
77 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 77 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
78 | self | 78 | self |
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
82 | impl AstDiagnostic for MissingFields { | ||
83 | type AST = ast::RecordExprFieldList; | ||
84 | |||
85 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
86 | let root = db.parse_or_expand(self.source().file_id).unwrap(); | ||
87 | let node = self.source().value.to_node(&root); | ||
88 | ast::RecordExprFieldList::cast(node).unwrap() | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #[derive(Debug)] | 82 | #[derive(Debug)] |
93 | pub struct MissingPatFields { | 83 | pub struct MissingPatFields { |
94 | pub file: HirFileId, | 84 | pub file: HirFileId, |
95 | pub field_list: AstPtr<ast::RecordPatFieldList>, | 85 | pub field_list_parent: AstPtr<ast::RecordPat>, |
86 | pub field_list_parent_path: Option<AstPtr<ast::Path>>, | ||
96 | pub missed_fields: Vec<Name>, | 87 | pub missed_fields: Vec<Name>, |
97 | } | 88 | } |
98 | 89 | ||
@@ -104,8 +95,15 @@ impl Diagnostic for MissingPatFields { | |||
104 | } | 95 | } |
105 | buf | 96 | buf |
106 | } | 97 | } |
107 | fn source(&self) -> InFile<SyntaxNodePtr> { | 98 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
108 | InFile { file_id: self.file, value: self.field_list.clone().into() } | 99 | InFile { |
100 | file_id: self.file, | ||
101 | value: self | ||
102 | .field_list_parent_path | ||
103 | .clone() | ||
104 | .map(SyntaxNodePtr::from) | ||
105 | .unwrap_or_else(|| self.field_list_parent.clone().into()), | ||
106 | } | ||
109 | } | 107 | } |
110 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 108 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
111 | self | 109 | self |
@@ -123,7 +121,7 @@ impl Diagnostic for MissingMatchArms { | |||
123 | fn message(&self) -> String { | 121 | fn message(&self) -> String { |
124 | String::from("Missing match arm") | 122 | String::from("Missing match arm") |
125 | } | 123 | } |
126 | fn source(&self) -> InFile<SyntaxNodePtr> { | 124 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
127 | InFile { file_id: self.file, value: self.match_expr.clone().into() } | 125 | InFile { file_id: self.file, value: self.match_expr.clone().into() } |
128 | } | 126 | } |
129 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 127 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -141,7 +139,7 @@ impl Diagnostic for MissingOkInTailExpr { | |||
141 | fn message(&self) -> String { | 139 | fn message(&self) -> String { |
142 | "wrap return expression in Ok".to_string() | 140 | "wrap return expression in Ok".to_string() |
143 | } | 141 | } |
144 | fn source(&self) -> InFile<SyntaxNodePtr> { | 142 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
145 | InFile { file_id: self.file, value: self.expr.clone().into() } | 143 | InFile { file_id: self.file, value: self.expr.clone().into() } |
146 | } | 144 | } |
147 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 145 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -149,16 +147,6 @@ impl Diagnostic for MissingOkInTailExpr { | |||
149 | } | 147 | } |
150 | } | 148 | } |
151 | 149 | ||
152 | impl AstDiagnostic for MissingOkInTailExpr { | ||
153 | type AST = ast::Expr; | ||
154 | |||
155 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
156 | let root = db.parse_or_expand(self.file).unwrap(); | ||
157 | let node = self.source().value.to_node(&root); | ||
158 | ast::Expr::cast(node).unwrap() | ||
159 | } | ||
160 | } | ||
161 | |||
162 | #[derive(Debug)] | 150 | #[derive(Debug)] |
163 | pub struct BreakOutsideOfLoop { | 151 | pub struct BreakOutsideOfLoop { |
164 | pub file: HirFileId, | 152 | pub file: HirFileId, |
@@ -169,7 +157,7 @@ impl Diagnostic for BreakOutsideOfLoop { | |||
169 | fn message(&self) -> String { | 157 | fn message(&self) -> String { |
170 | "break outside of loop".to_string() | 158 | "break outside of loop".to_string() |
171 | } | 159 | } |
172 | fn source(&self) -> InFile<SyntaxNodePtr> { | 160 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
173 | InFile { file_id: self.file, value: self.expr.clone().into() } | 161 | InFile { file_id: self.file, value: self.expr.clone().into() } |
174 | } | 162 | } |
175 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 163 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -177,16 +165,6 @@ impl Diagnostic for BreakOutsideOfLoop { | |||
177 | } | 165 | } |
178 | } | 166 | } |
179 | 167 | ||
180 | impl AstDiagnostic for BreakOutsideOfLoop { | ||
181 | type AST = ast::Expr; | ||
182 | |||
183 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
184 | let root = db.parse_or_expand(self.file).unwrap(); | ||
185 | let node = self.source().value.to_node(&root); | ||
186 | ast::Expr::cast(node).unwrap() | ||
187 | } | ||
188 | } | ||
189 | |||
190 | #[derive(Debug)] | 168 | #[derive(Debug)] |
191 | pub struct MissingUnsafe { | 169 | pub struct MissingUnsafe { |
192 | pub file: HirFileId, | 170 | pub file: HirFileId, |
@@ -197,7 +175,7 @@ impl Diagnostic for MissingUnsafe { | |||
197 | fn message(&self) -> String { | 175 | fn message(&self) -> String { |
198 | format!("This operation is unsafe and requires an unsafe function or block") | 176 | format!("This operation is unsafe and requires an unsafe function or block") |
199 | } | 177 | } |
200 | fn source(&self) -> InFile<SyntaxNodePtr> { | 178 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
201 | InFile { file_id: self.file, value: self.expr.clone().into() } | 179 | InFile { file_id: self.file, value: self.expr.clone().into() } |
202 | } | 180 | } |
203 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 181 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -205,16 +183,6 @@ impl Diagnostic for MissingUnsafe { | |||
205 | } | 183 | } |
206 | } | 184 | } |
207 | 185 | ||
208 | impl AstDiagnostic for MissingUnsafe { | ||
209 | type AST = ast::Expr; | ||
210 | |||
211 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
212 | let root = db.parse_or_expand(self.source().file_id).unwrap(); | ||
213 | let node = self.source().value.to_node(&root); | ||
214 | ast::Expr::cast(node).unwrap() | ||
215 | } | ||
216 | } | ||
217 | |||
218 | #[derive(Debug)] | 186 | #[derive(Debug)] |
219 | pub struct MismatchedArgCount { | 187 | pub struct MismatchedArgCount { |
220 | pub file: HirFileId, | 188 | pub file: HirFileId, |
@@ -228,7 +196,7 @@ impl Diagnostic for MismatchedArgCount { | |||
228 | let s = if self.expected == 1 { "" } else { "s" }; | 196 | let s = if self.expected == 1 { "" } else { "s" }; |
229 | format!("Expected {} argument{}, found {}", self.expected, s, self.found) | 197 | format!("Expected {} argument{}, found {}", self.expected, s, self.found) |
230 | } | 198 | } |
231 | fn source(&self) -> InFile<SyntaxNodePtr> { | 199 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
232 | InFile { file_id: self.file, value: self.call_expr.clone().into() } | 200 | InFile { file_id: self.file, value: self.call_expr.clone().into() } |
233 | } | 201 | } |
234 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 202 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -239,19 +207,13 @@ impl Diagnostic for MismatchedArgCount { | |||
239 | } | 207 | } |
240 | } | 208 | } |
241 | 209 | ||
242 | impl AstDiagnostic for MismatchedArgCount { | ||
243 | type AST = ast::CallExpr; | ||
244 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
245 | let root = db.parse_or_expand(self.source().file_id).unwrap(); | ||
246 | let node = self.source().value.to_node(&root); | ||
247 | ast::CallExpr::cast(node).unwrap() | ||
248 | } | ||
249 | } | ||
250 | |||
251 | #[cfg(test)] | 210 | #[cfg(test)] |
252 | mod tests { | 211 | mod tests { |
253 | use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; | 212 | use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; |
254 | use hir_expand::diagnostics::{Diagnostic, DiagnosticSinkBuilder}; | 213 | use hir_expand::{ |
214 | db::AstDatabase, | ||
215 | diagnostics::{Diagnostic, DiagnosticSinkBuilder}, | ||
216 | }; | ||
255 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; | 217 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; |
256 | use ra_syntax::{TextRange, TextSize}; | 218 | use ra_syntax::{TextRange, TextSize}; |
257 | use rustc_hash::FxHashMap; | 219 | use rustc_hash::FxHashMap; |
@@ -296,9 +258,11 @@ mod tests { | |||
296 | 258 | ||
297 | let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default(); | 259 | let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default(); |
298 | db.diagnostics(|d| { | 260 | db.diagnostics(|d| { |
299 | // FXIME: macros... | 261 | let src = d.display_source(); |
300 | let file_id = d.source().file_id.original_file(&db); | 262 | let root = db.parse_or_expand(src.file_id).unwrap(); |
301 | let range = d.syntax_node(&db).text_range(); | 263 | // FIXME: macros... |
264 | let file_id = src.file_id.original_file(&db); | ||
265 | let range = src.value.to_node(&root).text_range(); | ||
302 | let message = d.message().to_owned(); | 266 | let message = d.message().to_owned(); |
303 | actual.entry(file_id).or_default().push((range, message)); | 267 | actual.entry(file_id).or_default().push((range, message)); |
304 | }); | 268 | }); |
@@ -326,8 +290,8 @@ struct S { foo: i32, bar: () } | |||
326 | impl S { | 290 | impl S { |
327 | fn new() -> S { | 291 | fn new() -> S { |
328 | S { | 292 | S { |
329 | //^... Missing structure fields: | 293 | //^ Missing structure fields: |
330 | //| - bar | 294 | //| - bar |
331 | foo: 92, | 295 | foo: 92, |
332 | baz: 62, | 296 | baz: 62, |
333 | //^^^^^^^ no such field | 297 | //^^^^^^^ no such field |
@@ -448,8 +412,8 @@ impl Foo { | |||
448 | struct S { foo: i32, bar: () } | 412 | struct S { foo: i32, bar: () } |
449 | fn baz(s: S) { | 413 | fn baz(s: S) { |
450 | let S { foo: _ } = s; | 414 | let S { foo: _ } = s; |
451 | //^^^^^^^^^^ Missing structure fields: | 415 | //^ Missing structure fields: |
452 | // | - bar | 416 | //| - bar |
453 | } | 417 | } |
454 | "#, | 418 | "#, |
455 | ); | 419 | ); |
diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs index 95bbf2d95..51adcecaf 100644 --- a/crates/ra_hir_ty/src/diagnostics/expr.rs +++ b/crates/ra_hir_ty/src/diagnostics/expr.rs | |||
@@ -100,8 +100,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
100 | 100 | ||
101 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 101 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
102 | let root = source_ptr.file_syntax(db.upcast()); | 102 | let root = source_ptr.file_syntax(db.upcast()); |
103 | if let ast::Expr::RecordExpr(record_lit) = &source_ptr.value.to_node(&root) { | 103 | if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) { |
104 | if let Some(field_list) = record_lit.record_expr_field_list() { | 104 | if let Some(_) = record_expr.record_expr_field_list() { |
105 | let variant_data = variant_data(db.upcast(), variant_def); | 105 | let variant_data = variant_data(db.upcast(), variant_def); |
106 | let missed_fields = missed_fields | 106 | let missed_fields = missed_fields |
107 | .into_iter() | 107 | .into_iter() |
@@ -109,7 +109,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
109 | .collect(); | 109 | .collect(); |
110 | self.sink.push(MissingFields { | 110 | self.sink.push(MissingFields { |
111 | file: source_ptr.file_id, | 111 | file: source_ptr.file_id, |
112 | field_list: AstPtr::new(&field_list), | 112 | field_list_parent: AstPtr::new(&record_expr), |
113 | field_list_parent_path: record_expr.path().map(|path| AstPtr::new(&path)), | ||
113 | missed_fields, | 114 | missed_fields, |
114 | }) | 115 | }) |
115 | } | 116 | } |
@@ -131,7 +132,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
131 | if let Some(expr) = source_ptr.value.as_ref().left() { | 132 | if let Some(expr) = source_ptr.value.as_ref().left() { |
132 | let root = source_ptr.file_syntax(db.upcast()); | 133 | let root = source_ptr.file_syntax(db.upcast()); |
133 | if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { | 134 | if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { |
134 | if let Some(field_list) = record_pat.record_pat_field_list() { | 135 | if let Some(_) = record_pat.record_pat_field_list() { |
135 | let variant_data = variant_data(db.upcast(), variant_def); | 136 | let variant_data = variant_data(db.upcast(), variant_def); |
136 | let missed_fields = missed_fields | 137 | let missed_fields = missed_fields |
137 | .into_iter() | 138 | .into_iter() |
@@ -139,7 +140,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
139 | .collect(); | 140 | .collect(); |
140 | self.sink.push(MissingPatFields { | 141 | self.sink.push(MissingPatFields { |
141 | file: source_ptr.file_id, | 142 | file: source_ptr.file_id, |
142 | field_list: AstPtr::new(&field_list), | 143 | field_list_parent: AstPtr::new(&record_pat), |
144 | field_list_parent_path: record_pat | ||
145 | .path() | ||
146 | .map(|path| AstPtr::new(&path)), | ||
143 | missed_fields, | 147 | missed_fields, |
144 | }) | 148 | }) |
145 | } | 149 | } |
diff --git a/crates/ra_hir_ty/src/diagnostics/match_check.rs b/crates/ra_hir_ty/src/diagnostics/match_check.rs index 507edcb7d..deca244db 100644 --- a/crates/ra_hir_ty/src/diagnostics/match_check.rs +++ b/crates/ra_hir_ty/src/diagnostics/match_check.rs | |||
@@ -1161,15 +1161,15 @@ fn main() { | |||
1161 | //^ Missing match arm | 1161 | //^ Missing match arm |
1162 | match a { | 1162 | match a { |
1163 | Either::A { } => (), | 1163 | Either::A { } => (), |
1164 | //^^^ Missing structure fields: | 1164 | //^^^^^^^^^ Missing structure fields: |
1165 | // | - foo | 1165 | // | - foo |
1166 | Either::B => (), | 1166 | Either::B => (), |
1167 | } | 1167 | } |
1168 | match a { | 1168 | match a { |
1169 | //^ Missing match arm | 1169 | //^ Missing match arm |
1170 | Either::A { } => (), | 1170 | Either::A { } => (), |
1171 | } //^^^ Missing structure fields: | 1171 | } //^^^^^^^^^ Missing structure fields: |
1172 | // | - foo | 1172 | // | - foo |
1173 | 1173 | ||
1174 | match a { | 1174 | match a { |
1175 | Either::A { foo: true } => (), | 1175 | Either::A { foo: true } => (), |
diff --git a/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs index 5cc76bdce..61ffbf5d1 100644 --- a/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs | |||
@@ -6,6 +6,7 @@ use std::sync::Arc; | |||
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | body::Body, | 7 | body::Body, |
8 | expr::{Expr, ExprId, UnaryOp}, | 8 | expr::{Expr, ExprId, UnaryOp}, |
9 | resolver::{resolver_for_expr, ResolveValueResult, ValueNs}, | ||
9 | DefWithBodyId, | 10 | DefWithBodyId, |
10 | }; | 11 | }; |
11 | use hir_expand::diagnostics::DiagnosticSink; | 12 | use hir_expand::diagnostics::DiagnosticSink; |
@@ -70,7 +71,7 @@ pub fn unsafe_expressions( | |||
70 | ) -> Vec<UnsafeExpr> { | 71 | ) -> Vec<UnsafeExpr> { |
71 | let mut unsafe_exprs = vec![]; | 72 | let mut unsafe_exprs = vec![]; |
72 | let body = db.body(def); | 73 | let body = db.body(def); |
73 | walk_unsafe(&mut unsafe_exprs, db, infer, &body, body.body_expr, false); | 74 | walk_unsafe(&mut unsafe_exprs, db, infer, def, &body, body.body_expr, false); |
74 | 75 | ||
75 | unsafe_exprs | 76 | unsafe_exprs |
76 | } | 77 | } |
@@ -79,6 +80,7 @@ fn walk_unsafe( | |||
79 | unsafe_exprs: &mut Vec<UnsafeExpr>, | 80 | unsafe_exprs: &mut Vec<UnsafeExpr>, |
80 | db: &dyn HirDatabase, | 81 | db: &dyn HirDatabase, |
81 | infer: &InferenceResult, | 82 | infer: &InferenceResult, |
83 | def: DefWithBodyId, | ||
82 | body: &Body, | 84 | body: &Body, |
83 | current: ExprId, | 85 | current: ExprId, |
84 | inside_unsafe_block: bool, | 86 | inside_unsafe_block: bool, |
@@ -97,6 +99,15 @@ fn walk_unsafe( | |||
97 | } | 99 | } |
98 | } | 100 | } |
99 | } | 101 | } |
102 | Expr::Path(path) => { | ||
103 | let resolver = resolver_for_expr(db.upcast(), def, current); | ||
104 | let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path.mod_path()); | ||
105 | if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial { | ||
106 | if db.static_data(id).mutable { | ||
107 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | ||
108 | } | ||
109 | } | ||
110 | } | ||
100 | Expr::MethodCall { .. } => { | 111 | Expr::MethodCall { .. } => { |
101 | if infer | 112 | if infer |
102 | .method_resolution(current) | 113 | .method_resolution(current) |
@@ -112,13 +123,13 @@ fn walk_unsafe( | |||
112 | } | 123 | } |
113 | } | 124 | } |
114 | Expr::Unsafe { body: child } => { | 125 | Expr::Unsafe { body: child } => { |
115 | return walk_unsafe(unsafe_exprs, db, infer, body, *child, true); | 126 | return walk_unsafe(unsafe_exprs, db, infer, def, body, *child, true); |
116 | } | 127 | } |
117 | _ => {} | 128 | _ => {} |
118 | } | 129 | } |
119 | 130 | ||
120 | expr.walk_child_exprs(|child| { | 131 | expr.walk_child_exprs(|child| { |
121 | walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block); | 132 | walk_unsafe(unsafe_exprs, db, infer, def, body, child, inside_unsafe_block); |
122 | }); | 133 | }); |
123 | } | 134 | } |
124 | 135 | ||
@@ -170,4 +181,25 @@ fn main() { | |||
170 | "#, | 181 | "#, |
171 | ); | 182 | ); |
172 | } | 183 | } |
184 | |||
185 | #[test] | ||
186 | fn missing_unsafe_diagnostic_with_static_mut() { | ||
187 | check_diagnostics( | ||
188 | r#" | ||
189 | struct Ty { | ||
190 | a: u8, | ||
191 | } | ||
192 | |||
193 | static mut static_mut: Ty = Ty { a: 0 }; | ||
194 | |||
195 | fn main() { | ||
196 | let x = static_mut.a; | ||
197 | //^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block | ||
198 | unsafe { | ||
199 | let x = static_mut.a; | ||
200 | } | ||
201 | } | ||
202 | "#, | ||
203 | ); | ||
204 | } | ||
173 | } | 205 | } |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 28f32a0a4..3d12039a6 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -440,6 +440,12 @@ impl<'a> InferenceContext<'a> { | |||
440 | let ty = self.insert_type_vars(ty.subst(&substs)); | 440 | let ty = self.insert_type_vars(ty.subst(&substs)); |
441 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) | 441 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) |
442 | } | 442 | } |
443 | TypeNs::AdtId(AdtId::UnionId(u)) => { | ||
444 | let substs = Ty::substs_from_path(&ctx, path, u.into(), true); | ||
445 | let ty = self.db.ty(u.into()); | ||
446 | let ty = self.insert_type_vars(ty.subst(&substs)); | ||
447 | forbid_unresolved_segments((ty, Some(u.into())), unresolved) | ||
448 | } | ||
443 | TypeNs::EnumVariantId(var) => { | 449 | TypeNs::EnumVariantId(var) => { |
444 | let substs = Ty::substs_from_path(&ctx, path, var.into(), true); | 450 | let substs = Ty::substs_from_path(&ctx, path, var.into(), true); |
445 | let ty = self.db.ty(var.parent.into()); | 451 | let ty = self.db.ty(var.parent.into()); |
@@ -490,10 +496,7 @@ impl<'a> InferenceContext<'a> { | |||
490 | // FIXME potentially resolve assoc type | 496 | // FIXME potentially resolve assoc type |
491 | (Ty::Unknown, None) | 497 | (Ty::Unknown, None) |
492 | } | 498 | } |
493 | TypeNs::AdtId(AdtId::EnumId(_)) | 499 | TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => { |
494 | | TypeNs::AdtId(AdtId::UnionId(_)) | ||
495 | | TypeNs::BuiltinType(_) | ||
496 | | TypeNs::TraitId(_) => { | ||
497 | // FIXME diagnostic | 500 | // FIXME diagnostic |
498 | (Ty::Unknown, None) | 501 | (Ty::Unknown, None) |
499 | } | 502 | } |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 1eacc6f95..7638f167b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -518,6 +518,7 @@ impl Ty { | |||
518 | let (segment, generic_def) = match resolved { | 518 | let (segment, generic_def) = match resolved { |
519 | ValueTyDefId::FunctionId(it) => (last, Some(it.into())), | 519 | ValueTyDefId::FunctionId(it) => (last, Some(it.into())), |
520 | ValueTyDefId::StructId(it) => (last, Some(it.into())), | 520 | ValueTyDefId::StructId(it) => (last, Some(it.into())), |
521 | ValueTyDefId::UnionId(it) => (last, Some(it.into())), | ||
521 | ValueTyDefId::ConstId(it) => (last, Some(it.into())), | 522 | ValueTyDefId::ConstId(it) => (last, Some(it.into())), |
522 | ValueTyDefId::StaticId(_) => (last, None), | 523 | ValueTyDefId::StaticId(_) => (last, None), |
523 | ValueTyDefId::EnumVariantId(var) => { | 524 | ValueTyDefId::EnumVariantId(var) => { |
@@ -1148,11 +1149,12 @@ impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefI | |||
1148 | pub enum ValueTyDefId { | 1149 | pub enum ValueTyDefId { |
1149 | FunctionId(FunctionId), | 1150 | FunctionId(FunctionId), |
1150 | StructId(StructId), | 1151 | StructId(StructId), |
1152 | UnionId(UnionId), | ||
1151 | EnumVariantId(EnumVariantId), | 1153 | EnumVariantId(EnumVariantId), |
1152 | ConstId(ConstId), | 1154 | ConstId(ConstId), |
1153 | StaticId(StaticId), | 1155 | StaticId(StaticId), |
1154 | } | 1156 | } |
1155 | impl_from!(FunctionId, StructId, EnumVariantId, ConstId, StaticId for ValueTyDefId); | 1157 | impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId); |
1156 | 1158 | ||
1157 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 1159 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
1158 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 1160 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
@@ -1179,6 +1181,7 @@ pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders | |||
1179 | match def { | 1181 | match def { |
1180 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), | 1182 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), |
1181 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), | 1183 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), |
1184 | ValueTyDefId::UnionId(it) => type_for_adt(db, it.into()), | ||
1182 | ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), | 1185 | ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), |
1183 | ValueTyDefId::ConstId(it) => type_for_const(db, it), | 1186 | ValueTyDefId::ConstId(it) => type_for_const(db, it), |
1184 | ValueTyDefId::StaticId(it) => type_for_static(db, it), | 1187 | ValueTyDefId::StaticId(it) => type_for_static(db, it), |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 3fd7d5cd4..5a7cf9455 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -334,16 +334,44 @@ fn infer_union() { | |||
334 | bar: f32, | 334 | bar: f32, |
335 | } | 335 | } |
336 | 336 | ||
337 | fn test() { | ||
338 | let u = MyUnion { foo: 0 }; | ||
339 | unsafe { baz(u); } | ||
340 | let u = MyUnion { bar: 0.0 }; | ||
341 | unsafe { baz(u); } | ||
342 | } | ||
343 | |||
337 | unsafe fn baz(u: MyUnion) { | 344 | unsafe fn baz(u: MyUnion) { |
338 | let inner = u.foo; | 345 | let inner = u.foo; |
346 | let inner = u.bar; | ||
339 | } | 347 | } |
340 | "#, | 348 | "#, |
341 | expect![[r#" | 349 | expect![[r#" |
342 | 61..62 'u': MyUnion | 350 | 57..172 '{ ...); } }': () |
343 | 73..99 '{ ...foo; }': () | 351 | 67..68 'u': MyUnion |
344 | 83..88 'inner': u32 | 352 | 71..89 'MyUnio...o: 0 }': MyUnion |
345 | 91..92 'u': MyUnion | 353 | 86..87 '0': u32 |
346 | 91..96 'u.foo': u32 | 354 | 95..113 'unsafe...(u); }': () |
355 | 102..113 '{ baz(u); }': () | ||
356 | 104..107 'baz': fn baz(MyUnion) | ||
357 | 104..110 'baz(u)': () | ||
358 | 108..109 'u': MyUnion | ||
359 | 122..123 'u': MyUnion | ||
360 | 126..146 'MyUnio... 0.0 }': MyUnion | ||
361 | 141..144 '0.0': f32 | ||
362 | 152..170 'unsafe...(u); }': () | ||
363 | 159..170 '{ baz(u); }': () | ||
364 | 161..164 'baz': fn baz(MyUnion) | ||
365 | 161..167 'baz(u)': () | ||
366 | 165..166 'u': MyUnion | ||
367 | 188..189 'u': MyUnion | ||
368 | 200..249 '{ ...bar; }': () | ||
369 | 210..215 'inner': u32 | ||
370 | 218..219 'u': MyUnion | ||
371 | 218..223 'u.foo': u32 | ||
372 | 233..238 'inner': f32 | ||
373 | 241..242 'u': MyUnion | ||
374 | 241..246 'u.bar': f32 | ||
347 | "#]], | 375 | "#]], |
348 | ); | 376 | ); |
349 | } | 377 | } |
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs index 28d8f7876..4368e4eec 100644 --- a/crates/ra_ide/src/completion/complete_snippet.rs +++ b/crates/ra_ide/src/completion/complete_snippet.rs | |||
@@ -36,7 +36,7 @@ pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte | |||
36 | snippet( | 36 | snippet( |
37 | ctx, | 37 | ctx, |
38 | cap, | 38 | cap, |
39 | "Test module", | 39 | "tmod (Test module)", |
40 | "\ | 40 | "\ |
41 | #[cfg(test)] | 41 | #[cfg(test)] |
42 | mod tests { | 42 | mod tests { |
@@ -54,7 +54,7 @@ mod tests { | |||
54 | snippet( | 54 | snippet( |
55 | ctx, | 55 | ctx, |
56 | cap, | 56 | cap, |
57 | "Test function", | 57 | "tfn (Test function)", |
58 | "\ | 58 | "\ |
59 | #[test] | 59 | #[test] |
60 | fn ${1:feature}() { | 60 | fn ${1:feature}() { |
@@ -106,10 +106,10 @@ mod tests { | |||
106 | } | 106 | } |
107 | "#, | 107 | "#, |
108 | expect![[r#" | 108 | expect![[r#" |
109 | sn Test function | ||
110 | sn Test module | ||
111 | sn macro_rules | 109 | sn macro_rules |
112 | sn pub(crate) | 110 | sn pub(crate) |
111 | sn tfn (Test function) | ||
112 | sn tmod (Test module) | ||
113 | "#]], | 113 | "#]], |
114 | ) | 114 | ) |
115 | } | 115 | } |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 6b03b30bb..4aa761148 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -27,7 +27,7 @@ pub(crate) struct CompletionContext<'a> { | |||
27 | pub(super) scope: SemanticsScope<'a>, | 27 | pub(super) scope: SemanticsScope<'a>, |
28 | pub(super) db: &'a RootDatabase, | 28 | pub(super) db: &'a RootDatabase, |
29 | pub(super) config: &'a CompletionConfig, | 29 | pub(super) config: &'a CompletionConfig, |
30 | pub(super) offset: TextSize, | 30 | pub(super) position: FilePosition, |
31 | /// The token before the cursor, in the original file. | 31 | /// The token before the cursor, in the original file. |
32 | pub(super) original_token: SyntaxToken, | 32 | pub(super) original_token: SyntaxToken, |
33 | /// The token before the cursor, in the macro-expanded file. | 33 | /// The token before the cursor, in the macro-expanded file. |
@@ -117,7 +117,7 @@ impl<'a> CompletionContext<'a> { | |||
117 | config, | 117 | config, |
118 | original_token, | 118 | original_token, |
119 | token, | 119 | token, |
120 | offset: position.offset, | 120 | position, |
121 | krate, | 121 | krate, |
122 | expected_type: None, | 122 | expected_type: None, |
123 | name_ref_syntax: None, | 123 | name_ref_syntax: None, |
@@ -209,7 +209,7 @@ impl<'a> CompletionContext<'a> { | |||
209 | mark::hit!(completes_if_prefix_is_keyword); | 209 | mark::hit!(completes_if_prefix_is_keyword); |
210 | self.original_token.text_range() | 210 | self.original_token.text_range() |
211 | } else { | 211 | } else { |
212 | TextRange::empty(self.offset) | 212 | TextRange::empty(self.position.offset) |
213 | } | 213 | } |
214 | } | 214 | } |
215 | 215 | ||
@@ -379,8 +379,8 @@ impl<'a> CompletionContext<'a> { | |||
379 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | 379 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); |
380 | self.has_type_args = segment.generic_arg_list().is_some(); | 380 | self.has_type_args = segment.generic_arg_list().is_some(); |
381 | 381 | ||
382 | #[allow(deprecated)] | 382 | let hygiene = hir::Hygiene::new(self.db, self.position.file_id.into()); |
383 | if let Some(path) = hir::Path::from_ast(path.clone()) { | 383 | if let Some(path) = hir::Path::from_src(path.clone(), &hygiene) { |
384 | if let Some(path_prefix) = path.qualifier() { | 384 | if let Some(path_prefix) = path.qualifier() { |
385 | self.path_prefix = Some(path_prefix); | 385 | self.path_prefix = Some(path_prefix); |
386 | return; | 386 | return; |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 9a94ff476..59f1b1424 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -2,8 +2,8 @@ | |||
2 | //! It also handles scoring (sorting) completions. | 2 | //! It also handles scoring (sorting) completions. |
3 | 3 | ||
4 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type}; | 4 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type}; |
5 | use itertools::Itertools; | ||
5 | use ra_syntax::ast::NameOwner; | 6 | use ra_syntax::ast::NameOwner; |
6 | use stdx::SepBy; | ||
7 | use test_utils::mark; | 7 | use test_utils::mark; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
@@ -289,16 +289,16 @@ impl Completions { | |||
289 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); | 289 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); |
290 | let variant_kind = variant.kind(ctx.db); | 290 | let variant_kind = variant.kind(ctx.db); |
291 | let detail = match variant_kind { | 291 | let detail = match variant_kind { |
292 | StructKind::Tuple | StructKind::Unit => detail_types | 292 | StructKind::Tuple | StructKind::Unit => format!( |
293 | .map(|(_, t)| t.display(ctx.db).to_string()) | 293 | "({})", |
294 | .sep_by(", ") | 294 | detail_types.map(|(_, t)| t.display(ctx.db).to_string()).format(", ") |
295 | .surround_with("(", ")") | 295 | ), |
296 | .to_string(), | 296 | StructKind::Record => format!( |
297 | StructKind::Record => detail_types | 297 | "{{ {} }}", |
298 | .map(|(n, t)| format!("{}: {}", n, t.display(ctx.db).to_string())) | 298 | detail_types |
299 | .sep_by(", ") | 299 | .map(|(n, t)| format!("{}: {}", n, t.display(ctx.db).to_string())) |
300 | .surround_with("{ ", " }") | 300 | .format(", ") |
301 | .to_string(), | 301 | ), |
302 | }; | 302 | }; |
303 | let mut res = CompletionItem::new( | 303 | let mut res = CompletionItem::new( |
304 | CompletionKind::Reference, | 304 | CompletionKind::Reference, |
@@ -412,11 +412,10 @@ impl Builder { | |||
412 | self = self.trigger_call_info(); | 412 | self = self.trigger_call_info(); |
413 | let snippet = match (ctx.config.add_call_argument_snippets, params) { | 413 | let snippet = match (ctx.config.add_call_argument_snippets, params) { |
414 | (true, Params::Named(params)) => { | 414 | (true, Params::Named(params)) => { |
415 | let function_params_snippet = params | 415 | let function_params_snippet = |
416 | .iter() | 416 | params.iter().enumerate().format_with(", ", |(index, param_name), f| { |
417 | .enumerate() | 417 | f(&format_args!("${{{}:{}}}", index + 1, param_name)) |
418 | .map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name)) | 418 | }); |
419 | .sep_by(", "); | ||
420 | format!("{}({})$0", name, function_params_snippet) | 419 | format!("{}({})$0", name, function_params_snippet) |
421 | } | 420 | } |
422 | _ => { | 421 | _ => { |
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index dd8a7ffd9..1046d7ab3 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -6,22 +6,21 @@ | |||
6 | 6 | ||
7 | use std::cell::RefCell; | 7 | use std::cell::RefCell; |
8 | 8 | ||
9 | use hir::{ | 9 | use hir::{diagnostics::DiagnosticSinkBuilder, Semantics}; |
10 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSinkBuilder}, | ||
11 | HasSource, HirDisplay, Semantics, VariantDef, | ||
12 | }; | ||
13 | use itertools::Itertools; | 10 | use itertools::Itertools; |
14 | use ra_db::SourceDatabase; | 11 | use ra_db::SourceDatabase; |
15 | use ra_ide_db::RootDatabase; | 12 | use ra_ide_db::RootDatabase; |
16 | use ra_prof::profile; | 13 | use ra_prof::profile; |
17 | use ra_syntax::{ | 14 | use ra_syntax::{ |
18 | algo, | 15 | ast::{self, AstNode}, |
19 | ast::{self, edit::IndentLevel, make, AstNode}, | ||
20 | SyntaxNode, TextRange, T, | 16 | SyntaxNode, TextRange, T, |
21 | }; | 17 | }; |
22 | use ra_text_edit::{TextEdit, TextEditBuilder}; | 18 | use ra_text_edit::{TextEdit, TextEditBuilder}; |
23 | 19 | ||
24 | use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit}; | 20 | use crate::{Diagnostic, FileId, Fix, SourceFileEdit}; |
21 | |||
22 | mod diagnostics_with_fix; | ||
23 | use diagnostics_with_fix::DiagnosticWithFix; | ||
25 | 24 | ||
26 | #[derive(Debug, Copy, Clone)] | 25 | #[derive(Debug, Copy, Clone)] |
27 | pub enum Severity { | 26 | pub enum Severity { |
@@ -54,71 +53,16 @@ pub(crate) fn diagnostics( | |||
54 | let res = RefCell::new(res); | 53 | let res = RefCell::new(res); |
55 | let mut sink = DiagnosticSinkBuilder::new() | 54 | let mut sink = DiagnosticSinkBuilder::new() |
56 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { | 55 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { |
57 | let original_file = d.source().file_id.original_file(db); | 56 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
58 | let fix = Fix::new( | ||
59 | "Create module", | ||
60 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() } | ||
61 | .into(), | ||
62 | ); | ||
63 | res.borrow_mut().push(Diagnostic { | ||
64 | range: sema.diagnostics_range(d).range, | ||
65 | message: d.message(), | ||
66 | severity: Severity::Error, | ||
67 | fix: Some(fix), | ||
68 | }) | ||
69 | }) | 57 | }) |
70 | .on::<hir::diagnostics::MissingFields, _>(|d| { | 58 | .on::<hir::diagnostics::MissingFields, _>(|d| { |
71 | // Note that although we could add a diagnostics to | 59 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
72 | // fill the missing tuple field, e.g : | ||
73 | // `struct A(usize);` | ||
74 | // `let a = A { 0: () }` | ||
75 | // but it is uncommon usage and it should not be encouraged. | ||
76 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { | ||
77 | None | ||
78 | } else { | ||
79 | let mut field_list = d.ast(db); | ||
80 | for f in d.missed_fields.iter() { | ||
81 | let field = | ||
82 | make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); | ||
83 | field_list = field_list.append_field(&field); | ||
84 | } | ||
85 | |||
86 | let edit = { | ||
87 | let mut builder = TextEditBuilder::default(); | ||
88 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()) | ||
89 | .into_text_edit(&mut builder); | ||
90 | builder.finish() | ||
91 | }; | ||
92 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) | ||
93 | }; | ||
94 | |||
95 | res.borrow_mut().push(Diagnostic { | ||
96 | range: sema.diagnostics_range(d).range, | ||
97 | message: d.message(), | ||
98 | severity: Severity::Error, | ||
99 | fix, | ||
100 | }) | ||
101 | }) | 60 | }) |
102 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { | 61 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { |
103 | let node = d.ast(db); | 62 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
104 | let replacement = format!("Ok({})", node.syntax()); | ||
105 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); | ||
106 | let source_change = SourceFileEdit { file_id, edit }.into(); | ||
107 | let fix = Fix::new("Wrap with ok", source_change); | ||
108 | res.borrow_mut().push(Diagnostic { | ||
109 | range: sema.diagnostics_range(d).range, | ||
110 | message: d.message(), | ||
111 | severity: Severity::Error, | ||
112 | fix: Some(fix), | ||
113 | }) | ||
114 | }) | 63 | }) |
115 | .on::<hir::diagnostics::NoSuchField, _>(|d| { | 64 | .on::<hir::diagnostics::NoSuchField, _>(|d| { |
116 | res.borrow_mut().push(Diagnostic { | 65 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
117 | range: sema.diagnostics_range(d).range, | ||
118 | message: d.message(), | ||
119 | severity: Severity::Error, | ||
120 | fix: missing_struct_field_fix(&sema, file_id, d), | ||
121 | }) | ||
122 | }) | 66 | }) |
123 | // Only collect experimental diagnostics when they're enabled. | 67 | // Only collect experimental diagnostics when they're enabled. |
124 | .filter(|diag| !diag.is_experimental() || enable_experimental) | 68 | .filter(|diag| !diag.is_experimental() || enable_experimental) |
@@ -126,7 +70,7 @@ pub(crate) fn diagnostics( | |||
126 | .build(|d| { | 70 | .build(|d| { |
127 | res.borrow_mut().push(Diagnostic { | 71 | res.borrow_mut().push(Diagnostic { |
128 | message: d.message(), | 72 | message: d.message(), |
129 | range: sema.diagnostics_range(d).range, | 73 | range: sema.diagnostics_display_range(d).range, |
130 | severity: Severity::Error, | 74 | severity: Severity::Error, |
131 | fix: None, | 75 | fix: None, |
132 | }) | 76 | }) |
@@ -139,77 +83,12 @@ pub(crate) fn diagnostics( | |||
139 | res.into_inner() | 83 | res.into_inner() |
140 | } | 84 | } |
141 | 85 | ||
142 | fn missing_struct_field_fix( | 86 | fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { |
143 | sema: &Semantics<RootDatabase>, | 87 | Diagnostic { |
144 | usage_file_id: FileId, | 88 | range: sema.diagnostics_display_range(d).range, |
145 | d: &hir::diagnostics::NoSuchField, | 89 | message: d.message(), |
146 | ) -> Option<Fix> { | 90 | severity: Severity::Error, |
147 | let record_expr = sema.ast(d); | 91 | fix: d.fix(&sema), |
148 | |||
149 | let record_lit = ast::RecordExpr::cast(record_expr.syntax().parent()?.parent()?)?; | ||
150 | let def_id = sema.resolve_variant(record_lit)?; | ||
151 | let module; | ||
152 | let def_file_id; | ||
153 | let record_fields = match VariantDef::from(def_id) { | ||
154 | VariantDef::Struct(s) => { | ||
155 | module = s.module(sema.db); | ||
156 | let source = s.source(sema.db); | ||
157 | def_file_id = source.file_id; | ||
158 | let fields = source.value.field_list()?; | ||
159 | record_field_list(fields)? | ||
160 | } | ||
161 | VariantDef::Union(u) => { | ||
162 | module = u.module(sema.db); | ||
163 | let source = u.source(sema.db); | ||
164 | def_file_id = source.file_id; | ||
165 | source.value.record_field_list()? | ||
166 | } | ||
167 | VariantDef::EnumVariant(e) => { | ||
168 | module = e.module(sema.db); | ||
169 | let source = e.source(sema.db); | ||
170 | def_file_id = source.file_id; | ||
171 | let fields = source.value.field_list()?; | ||
172 | record_field_list(fields)? | ||
173 | } | ||
174 | }; | ||
175 | let def_file_id = def_file_id.original_file(sema.db); | ||
176 | |||
177 | let new_field_type = sema.type_of_expr(&record_expr.expr()?)?; | ||
178 | if new_field_type.is_unknown() { | ||
179 | return None; | ||
180 | } | ||
181 | let new_field = make::record_field_def( | ||
182 | record_expr.field_name()?, | ||
183 | make::type_ref(&new_field_type.display_source_code(sema.db, module.into()).ok()?), | ||
184 | ); | ||
185 | |||
186 | let last_field = record_fields.fields().last()?; | ||
187 | let last_field_syntax = last_field.syntax(); | ||
188 | let indent = IndentLevel::from_node(last_field_syntax); | ||
189 | |||
190 | let mut new_field = new_field.to_string(); | ||
191 | if usage_file_id != def_file_id { | ||
192 | new_field = format!("pub(crate) {}", new_field); | ||
193 | } | ||
194 | new_field = format!("\n{}{}", indent, new_field); | ||
195 | |||
196 | let needs_comma = !last_field_syntax.to_string().ends_with(','); | ||
197 | if needs_comma { | ||
198 | new_field = format!(",{}", new_field); | ||
199 | } | ||
200 | |||
201 | let source_change = SourceFileEdit { | ||
202 | file_id: def_file_id, | ||
203 | edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field), | ||
204 | }; | ||
205 | let fix = Fix::new("Create field", source_change.into()); | ||
206 | return Some(fix); | ||
207 | |||
208 | fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> { | ||
209 | match field_def_list { | ||
210 | ast::FieldList::RecordFieldList(it) => Some(it), | ||
211 | ast::FieldList::TupleFieldList(_) => None, | ||
212 | } | ||
213 | } | 92 | } |
214 | } | 93 | } |
215 | 94 | ||
@@ -220,24 +99,25 @@ fn check_unnecessary_braces_in_use_statement( | |||
220 | ) -> Option<()> { | 99 | ) -> Option<()> { |
221 | let use_tree_list = ast::UseTreeList::cast(node.clone())?; | 100 | let use_tree_list = ast::UseTreeList::cast(node.clone())?; |
222 | if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() { | 101 | if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() { |
223 | let range = use_tree_list.syntax().text_range(); | 102 | let use_range = use_tree_list.syntax().text_range(); |
224 | let edit = | 103 | let edit = |
225 | text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree) | 104 | text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree) |
226 | .unwrap_or_else(|| { | 105 | .unwrap_or_else(|| { |
227 | let to_replace = single_use_tree.syntax().text().to_string(); | 106 | let to_replace = single_use_tree.syntax().text().to_string(); |
228 | let mut edit_builder = TextEditBuilder::default(); | 107 | let mut edit_builder = TextEditBuilder::default(); |
229 | edit_builder.delete(range); | 108 | edit_builder.delete(use_range); |
230 | edit_builder.insert(range.start(), to_replace); | 109 | edit_builder.insert(use_range.start(), to_replace); |
231 | edit_builder.finish() | 110 | edit_builder.finish() |
232 | }); | 111 | }); |
233 | 112 | ||
234 | acc.push(Diagnostic { | 113 | acc.push(Diagnostic { |
235 | range, | 114 | range: use_range, |
236 | message: "Unnecessary braces in use statement".to_string(), | 115 | message: "Unnecessary braces in use statement".to_string(), |
237 | severity: Severity::WeakWarning, | 116 | severity: Severity::WeakWarning, |
238 | fix: Some(Fix::new( | 117 | fix: Some(Fix::new( |
239 | "Remove unnecessary braces", | 118 | "Remove unnecessary braces", |
240 | SourceFileEdit { file_id, edit }.into(), | 119 | SourceFileEdit { file_id, edit }.into(), |
120 | use_range, | ||
241 | )), | 121 | )), |
242 | }); | 122 | }); |
243 | } | 123 | } |
@@ -252,8 +132,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement( | |||
252 | if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] { | 132 | if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] { |
253 | let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start(); | 133 | let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start(); |
254 | let end = use_tree_list_node.text_range().end(); | 134 | let end = use_tree_list_node.text_range().end(); |
255 | let range = TextRange::new(start, end); | 135 | return Some(TextEdit::delete(TextRange::new(start, end))); |
256 | return Some(TextEdit::delete(range)); | ||
257 | } | 136 | } |
258 | None | 137 | None |
259 | } | 138 | } |
@@ -276,13 +155,15 @@ fn check_struct_shorthand_initialization( | |||
276 | edit_builder.insert(record_field.syntax().text_range().start(), field_name); | 155 | edit_builder.insert(record_field.syntax().text_range().start(), field_name); |
277 | let edit = edit_builder.finish(); | 156 | let edit = edit_builder.finish(); |
278 | 157 | ||
158 | let field_range = record_field.syntax().text_range(); | ||
279 | acc.push(Diagnostic { | 159 | acc.push(Diagnostic { |
280 | range: record_field.syntax().text_range(), | 160 | range: field_range, |
281 | message: "Shorthand struct initialization".to_string(), | 161 | message: "Shorthand struct initialization".to_string(), |
282 | severity: Severity::WeakWarning, | 162 | severity: Severity::WeakWarning, |
283 | fix: Some(Fix::new( | 163 | fix: Some(Fix::new( |
284 | "Use struct shorthand initialization", | 164 | "Use struct shorthand initialization", |
285 | SourceFileEdit { file_id, edit }.into(), | 165 | SourceFileEdit { file_id, edit }.into(), |
166 | field_range, | ||
286 | )), | 167 | )), |
287 | }); | 168 | }); |
288 | } | 169 | } |
@@ -302,7 +183,7 @@ mod tests { | |||
302 | /// Takes a multi-file input fixture with annotated cursor positions, | 183 | /// Takes a multi-file input fixture with annotated cursor positions, |
303 | /// and checks that: | 184 | /// and checks that: |
304 | /// * a diagnostic is produced | 185 | /// * a diagnostic is produced |
305 | /// * this diagnostic touches the input cursor position | 186 | /// * this diagnostic fix trigger range touches the input cursor position |
306 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied | 187 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied |
307 | fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { | 188 | fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { |
308 | let after = trim_indent(ra_fixture_after); | 189 | let after = trim_indent(ra_fixture_after); |
@@ -320,10 +201,10 @@ mod tests { | |||
320 | 201 | ||
321 | assert_eq_text!(&after, &actual); | 202 | assert_eq_text!(&after, &actual); |
322 | assert!( | 203 | assert!( |
323 | diagnostic.range.start() <= file_position.offset | 204 | fix.fix_trigger_range.start() <= file_position.offset |
324 | && diagnostic.range.end() >= file_position.offset, | 205 | && fix.fix_trigger_range.end() >= file_position.offset, |
325 | "diagnostic range {:?} does not touch cursor position {:?}", | 206 | "diagnostic fix range {:?} does not touch cursor position {:?}", |
326 | diagnostic.range, | 207 | fix.fix_trigger_range, |
327 | file_position.offset | 208 | file_position.offset |
328 | ); | 209 | ); |
329 | } | 210 | } |
@@ -640,6 +521,7 @@ fn test_fn() { | |||
640 | ], | 521 | ], |
641 | is_snippet: false, | 522 | is_snippet: false, |
642 | }, | 523 | }, |
524 | fix_trigger_range: 0..8, | ||
643 | }, | 525 | }, |
644 | ), | 526 | ), |
645 | }, | 527 | }, |
diff --git a/crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs b/crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs new file mode 100644 index 000000000..f7c73773f --- /dev/null +++ b/crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs | |||
@@ -0,0 +1,171 @@ | |||
1 | //! Provides a way to attach fixes to the diagnostics. | ||
2 | //! The same module also has all curret custom fixes for the diagnostics implemented. | ||
3 | use crate::Fix; | ||
4 | use ast::{edit::IndentLevel, make}; | ||
5 | use hir::{ | ||
6 | db::AstDatabase, | ||
7 | diagnostics::{Diagnostic, MissingFields, MissingOkInTailExpr, NoSuchField, UnresolvedModule}, | ||
8 | HasSource, HirDisplay, Semantics, VariantDef, | ||
9 | }; | ||
10 | use ra_db::FileId; | ||
11 | use ra_ide_db::{ | ||
12 | source_change::{FileSystemEdit, SourceFileEdit}, | ||
13 | RootDatabase, | ||
14 | }; | ||
15 | use ra_syntax::{algo, ast, AstNode}; | ||
16 | use ra_text_edit::{TextEdit, TextEditBuilder}; | ||
17 | |||
18 | /// A [Diagnostic] that potentially has a fix available. | ||
19 | /// | ||
20 | /// [Diagnostic]: hir::diagnostics::Diagnostic | ||
21 | pub trait DiagnosticWithFix: Diagnostic { | ||
22 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix>; | ||
23 | } | ||
24 | |||
25 | impl DiagnosticWithFix for UnresolvedModule { | ||
26 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | ||
27 | let root = sema.db.parse_or_expand(self.file)?; | ||
28 | let unresolved_module = self.decl.to_node(&root); | ||
29 | Some(Fix::new( | ||
30 | "Create module", | ||
31 | FileSystemEdit::CreateFile { | ||
32 | anchor: self.file.original_file(sema.db), | ||
33 | dst: self.candidate.clone(), | ||
34 | } | ||
35 | .into(), | ||
36 | unresolved_module.syntax().text_range(), | ||
37 | )) | ||
38 | } | ||
39 | } | ||
40 | |||
41 | impl DiagnosticWithFix for NoSuchField { | ||
42 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | ||
43 | let root = sema.db.parse_or_expand(self.file)?; | ||
44 | missing_record_expr_field_fix( | ||
45 | &sema, | ||
46 | self.file.original_file(sema.db), | ||
47 | &self.field.to_node(&root), | ||
48 | ) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | impl DiagnosticWithFix for MissingFields { | ||
53 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | ||
54 | // Note that although we could add a diagnostics to | ||
55 | // fill the missing tuple field, e.g : | ||
56 | // `struct A(usize);` | ||
57 | // `let a = A { 0: () }` | ||
58 | // but it is uncommon usage and it should not be encouraged. | ||
59 | if self.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { | ||
60 | return None; | ||
61 | } | ||
62 | |||
63 | let root = sema.db.parse_or_expand(self.file)?; | ||
64 | let old_field_list = self.field_list_parent.to_node(&root).record_expr_field_list()?; | ||
65 | let mut new_field_list = old_field_list.clone(); | ||
66 | for f in self.missed_fields.iter() { | ||
67 | let field = | ||
68 | make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); | ||
69 | new_field_list = new_field_list.append_field(&field); | ||
70 | } | ||
71 | |||
72 | let edit = { | ||
73 | let mut builder = TextEditBuilder::default(); | ||
74 | algo::diff(&old_field_list.syntax(), &new_field_list.syntax()) | ||
75 | .into_text_edit(&mut builder); | ||
76 | builder.finish() | ||
77 | }; | ||
78 | Some(Fix::new( | ||
79 | "Fill struct fields", | ||
80 | SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(), | ||
81 | sema.original_range(&old_field_list.syntax()).range, | ||
82 | )) | ||
83 | } | ||
84 | } | ||
85 | |||
86 | impl DiagnosticWithFix for MissingOkInTailExpr { | ||
87 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | ||
88 | let root = sema.db.parse_or_expand(self.file)?; | ||
89 | let tail_expr = self.expr.to_node(&root); | ||
90 | let tail_expr_range = tail_expr.syntax().text_range(); | ||
91 | let edit = TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax())); | ||
92 | let source_change = | ||
93 | SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(); | ||
94 | Some(Fix::new("Wrap with ok", source_change, tail_expr_range)) | ||
95 | } | ||
96 | } | ||
97 | |||
98 | fn missing_record_expr_field_fix( | ||
99 | sema: &Semantics<RootDatabase>, | ||
100 | usage_file_id: FileId, | ||
101 | record_expr_field: &ast::RecordExprField, | ||
102 | ) -> Option<Fix> { | ||
103 | let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?; | ||
104 | let def_id = sema.resolve_variant(record_lit)?; | ||
105 | let module; | ||
106 | let def_file_id; | ||
107 | let record_fields = match VariantDef::from(def_id) { | ||
108 | VariantDef::Struct(s) => { | ||
109 | module = s.module(sema.db); | ||
110 | let source = s.source(sema.db); | ||
111 | def_file_id = source.file_id; | ||
112 | let fields = source.value.field_list()?; | ||
113 | record_field_list(fields)? | ||
114 | } | ||
115 | VariantDef::Union(u) => { | ||
116 | module = u.module(sema.db); | ||
117 | let source = u.source(sema.db); | ||
118 | def_file_id = source.file_id; | ||
119 | source.value.record_field_list()? | ||
120 | } | ||
121 | VariantDef::EnumVariant(e) => { | ||
122 | module = e.module(sema.db); | ||
123 | let source = e.source(sema.db); | ||
124 | def_file_id = source.file_id; | ||
125 | let fields = source.value.field_list()?; | ||
126 | record_field_list(fields)? | ||
127 | } | ||
128 | }; | ||
129 | let def_file_id = def_file_id.original_file(sema.db); | ||
130 | |||
131 | let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?; | ||
132 | if new_field_type.is_unknown() { | ||
133 | return None; | ||
134 | } | ||
135 | let new_field = make::record_field( | ||
136 | record_expr_field.field_name()?, | ||
137 | make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?), | ||
138 | ); | ||
139 | |||
140 | let last_field = record_fields.fields().last()?; | ||
141 | let last_field_syntax = last_field.syntax(); | ||
142 | let indent = IndentLevel::from_node(last_field_syntax); | ||
143 | |||
144 | let mut new_field = new_field.to_string(); | ||
145 | if usage_file_id != def_file_id { | ||
146 | new_field = format!("pub(crate) {}", new_field); | ||
147 | } | ||
148 | new_field = format!("\n{}{}", indent, new_field); | ||
149 | |||
150 | let needs_comma = !last_field_syntax.to_string().ends_with(','); | ||
151 | if needs_comma { | ||
152 | new_field = format!(",{}", new_field); | ||
153 | } | ||
154 | |||
155 | let source_change = SourceFileEdit { | ||
156 | file_id: def_file_id, | ||
157 | edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field), | ||
158 | }; | ||
159 | return Some(Fix::new( | ||
160 | "Create field", | ||
161 | source_change.into(), | ||
162 | record_expr_field.syntax().text_range(), | ||
163 | )); | ||
164 | |||
165 | fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> { | ||
166 | match field_def_list { | ||
167 | ast::FieldList::RecordFieldList(it) => Some(it), | ||
168 | ast::FieldList::TupleFieldList(_) => None, | ||
169 | } | ||
170 | } | ||
171 | } | ||
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs index 0fdf8e9a5..010c34705 100644 --- a/crates/ra_ide/src/display/short_label.rs +++ b/crates/ra_ide/src/display/short_label.rs | |||
@@ -47,6 +47,12 @@ impl ShortLabel for ast::Module { | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | impl ShortLabel for ast::SourceFile { | ||
51 | fn short_label(&self) -> Option<String> { | ||
52 | None | ||
53 | } | ||
54 | } | ||
55 | |||
50 | impl ShortLabel for ast::TypeAlias { | 56 | impl ShortLabel for ast::TypeAlias { |
51 | fn short_label(&self) -> Option<String> { | 57 | fn short_label(&self) -> Option<String> { |
52 | short_label_from_node(self, "type ") | 58 | short_label_from_node(self, "type ") |
@@ -55,7 +61,11 @@ impl ShortLabel for ast::TypeAlias { | |||
55 | 61 | ||
56 | impl ShortLabel for ast::Const { | 62 | impl ShortLabel for ast::Const { |
57 | fn short_label(&self) -> Option<String> { | 63 | fn short_label(&self) -> Option<String> { |
58 | short_label_from_ty(self, self.ty(), "const ") | 64 | let mut new_buf = short_label_from_ty(self, self.ty(), "const ")?; |
65 | if let Some(expr) = self.body() { | ||
66 | format_to!(new_buf, " = {}", expr.syntax()); | ||
67 | } | ||
68 | Some(new_buf) | ||
59 | } | 69 | } |
60 | } | 70 | } |
61 | 71 | ||
diff --git a/crates/ra_ide/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs index 903c34996..0fbc9babd 100644 --- a/crates/ra_ide/src/folding_ranges.rs +++ b/crates/ra_ide/src/folding_ranges.rs | |||
@@ -85,7 +85,8 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> { | |||
85 | COMMENT => Some(FoldKind::Comment), | 85 | COMMENT => Some(FoldKind::Comment), |
86 | USE => Some(FoldKind::Imports), | 86 | USE => Some(FoldKind::Imports), |
87 | ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList), | 87 | ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList), |
88 | RECORD_FIELD_LIST | 88 | ASSOC_ITEM_LIST |
89 | | RECORD_FIELD_LIST | ||
89 | | RECORD_PAT_FIELD_LIST | 90 | | RECORD_PAT_FIELD_LIST |
90 | | RECORD_EXPR_FIELD_LIST | 91 | | RECORD_EXPR_FIELD_LIST |
91 | | ITEM_LIST | 92 | | ITEM_LIST |
@@ -337,6 +338,26 @@ fn main() <fold block>{ | |||
337 | } | 338 | } |
338 | 339 | ||
339 | #[test] | 340 | #[test] |
341 | fn test_folds_structs() { | ||
342 | check( | ||
343 | r#" | ||
344 | struct Foo <fold block>{ | ||
345 | }</fold> | ||
346 | "#, | ||
347 | ); | ||
348 | } | ||
349 | |||
350 | #[test] | ||
351 | fn test_folds_traits() { | ||
352 | check( | ||
353 | r#" | ||
354 | trait Foo <fold block>{ | ||
355 | }</fold> | ||
356 | "#, | ||
357 | ); | ||
358 | } | ||
359 | |||
360 | #[test] | ||
340 | fn test_folds_macros() { | 361 | fn test_folds_macros() { |
341 | check( | 362 | check( |
342 | r#" | 363 | r#" |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 4e3f428fa..45389fd23 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use hir::Semantics; | 1 | use hir::Semantics; |
2 | use ra_ide_db::{ | 2 | use ra_ide_db::{ |
3 | defs::{classify_name, classify_name_ref, NameClass}, | 3 | defs::{classify_name, classify_name_ref}, |
4 | symbol_index, RootDatabase, | 4 | symbol_index, RootDatabase, |
5 | }; | 5 | }; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
@@ -40,10 +40,7 @@ pub(crate) fn goto_definition( | |||
40 | reference_definition(&sema, &name_ref).to_vec() | 40 | reference_definition(&sema, &name_ref).to_vec() |
41 | }, | 41 | }, |
42 | ast::Name(name) => { | 42 | ast::Name(name) => { |
43 | let def = match classify_name(&sema, &name)? { | 43 | let def = classify_name(&sema, &name)?.definition(sema.db); |
44 | NameClass::Definition(def) | NameClass::ConstReference(def) => def, | ||
45 | NameClass::FieldShorthand { local: _, field } => field, | ||
46 | }; | ||
47 | let nav = def.try_to_nav(sema.db)?; | 44 | let nav = def.try_to_nav(sema.db)?; |
48 | vec![nav] | 45 | vec![nav] |
49 | }, | 46 | }, |
@@ -86,8 +83,7 @@ pub(crate) fn reference_definition( | |||
86 | ) -> ReferenceResult { | 83 | ) -> ReferenceResult { |
87 | let name_kind = classify_name_ref(sema, name_ref); | 84 | let name_kind = classify_name_ref(sema, name_ref); |
88 | if let Some(def) = name_kind { | 85 | if let Some(def) = name_kind { |
89 | let def = def.definition(); | 86 | let def = def.definition(sema.db); |
90 | |||
91 | return match def.try_to_nav(sema.db) { | 87 | return match def.try_to_nav(sema.db) { |
92 | Some(nav) => ReferenceResult::Exact(nav), | 88 | Some(nav) => ReferenceResult::Exact(nav), |
93 | None => ReferenceResult::Approximate(Vec::new()), | 89 | None => ReferenceResult::Approximate(Vec::new()), |
@@ -134,6 +130,32 @@ mod tests { | |||
134 | } | 130 | } |
135 | 131 | ||
136 | #[test] | 132 | #[test] |
133 | fn goto_def_for_extern_crate() { | ||
134 | check( | ||
135 | r#" | ||
136 | //- /main.rs | ||
137 | extern crate std<|>; | ||
138 | //- /std/lib.rs | ||
139 | // empty | ||
140 | //^ file | ||
141 | "#, | ||
142 | ) | ||
143 | } | ||
144 | |||
145 | #[test] | ||
146 | fn goto_def_for_renamed_extern_crate() { | ||
147 | check( | ||
148 | r#" | ||
149 | //- /main.rs | ||
150 | extern crate std as abc<|>; | ||
151 | //- /std/lib.rs | ||
152 | // empty | ||
153 | //^ file | ||
154 | "#, | ||
155 | ) | ||
156 | } | ||
157 | |||
158 | #[test] | ||
137 | fn goto_def_in_items() { | 159 | fn goto_def_in_items() { |
138 | check( | 160 | check( |
139 | r#" | 161 | r#" |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index aa48cb412..f66f62bfb 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -85,8 +85,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
85 | let node = token.parent(); | 85 | let node = token.parent(); |
86 | let definition = match_ast! { | 86 | let definition = match_ast! { |
87 | match node { | 87 | match node { |
88 | ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition()), | 88 | ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition(sema.db)), |
89 | ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition()), | 89 | ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition(sema.db)), |
90 | _ => None, | 90 | _ => None, |
91 | } | 91 | } |
92 | }; | 92 | }; |
@@ -304,7 +304,10 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
304 | let docs = Documentation::from_ast(&it).map(Into::into); | 304 | let docs = Documentation::from_ast(&it).map(Into::into); |
305 | hover_markup(docs, it.short_label(), mod_path) | 305 | hover_markup(docs, it.short_label(), mod_path) |
306 | } | 306 | } |
307 | _ => None, | 307 | ModuleSource::SourceFile(it) => { |
308 | let docs = Documentation::from_ast(&it).map(Into::into); | ||
309 | hover_markup(docs, it.short_label(), mod_path) | ||
310 | } | ||
308 | }, | 311 | }, |
309 | ModuleDef::Function(it) => from_def_source(db, it, mod_path), | 312 | ModuleDef::Function(it) => from_def_source(db, it, mod_path), |
310 | ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), | 313 | ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), |
@@ -509,6 +512,37 @@ fn main() { } | |||
509 | } | 512 | } |
510 | 513 | ||
511 | #[test] | 514 | #[test] |
515 | fn hover_shows_fn_doc() { | ||
516 | check( | ||
517 | r#" | ||
518 | /// # Example | ||
519 | /// ``` | ||
520 | /// # use std::path::Path; | ||
521 | /// # | ||
522 | /// foo(Path::new("hello, world!")) | ||
523 | /// ``` | ||
524 | pub fn foo<|>(_: &Path) {} | ||
525 | |||
526 | fn main() { } | ||
527 | "#, | ||
528 | expect![[r#" | ||
529 | *foo* | ||
530 | ```rust | ||
531 | pub fn foo(_: &Path) | ||
532 | ``` | ||
533 | ___ | ||
534 | |||
535 | # Example | ||
536 | ``` | ||
537 | # use std::path::Path; | ||
538 | # | ||
539 | foo(Path::new("hello, world!")) | ||
540 | ``` | ||
541 | "#]], | ||
542 | ); | ||
543 | } | ||
544 | |||
545 | #[test] | ||
512 | fn hover_shows_struct_field_info() { | 546 | fn hover_shows_struct_field_info() { |
513 | // Hovering over the field when instantiating | 547 | // Hovering over the field when instantiating |
514 | check( | 548 | check( |
@@ -556,16 +590,16 @@ fn main() { | |||
556 | #[test] | 590 | #[test] |
557 | fn hover_const_static() { | 591 | fn hover_const_static() { |
558 | check( | 592 | check( |
559 | r#"const foo<|>: u32 = 0;"#, | 593 | r#"const foo<|>: u32 = 123;"#, |
560 | expect![[r#" | 594 | expect![[r#" |
561 | *foo* | 595 | *foo* |
562 | ```rust | 596 | ```rust |
563 | const foo: u32 | 597 | const foo: u32 = 123 |
564 | ``` | 598 | ``` |
565 | "#]], | 599 | "#]], |
566 | ); | 600 | ); |
567 | check( | 601 | check( |
568 | r#"static foo<|>: u32 = 0;"#, | 602 | r#"static foo<|>: u32 = 456;"#, |
569 | expect![[r#" | 603 | expect![[r#" |
570 | *foo* | 604 | *foo* |
571 | ```rust | 605 | ```rust |
@@ -800,7 +834,7 @@ fn main() { | |||
800 | expect![[r#" | 834 | expect![[r#" |
801 | *C* | 835 | *C* |
802 | ```rust | 836 | ```rust |
803 | const C: u32 | 837 | const C: u32 = 1 |
804 | ``` | 838 | ``` |
805 | "#]], | 839 | "#]], |
806 | ) | 840 | ) |
@@ -1107,6 +1141,46 @@ fn bar() { fo<|>o(); } | |||
1107 | } | 1141 | } |
1108 | 1142 | ||
1109 | #[test] | 1143 | #[test] |
1144 | fn test_hover_extern_crate() { | ||
1145 | check( | ||
1146 | r#" | ||
1147 | //- /main.rs | ||
1148 | extern crate st<|>d; | ||
1149 | //- /std/lib.rs | ||
1150 | //! Standard library for this test | ||
1151 | //! | ||
1152 | //! Printed? | ||
1153 | //! abc123 | ||
1154 | "#, | ||
1155 | expect![[r#" | ||
1156 | *std* | ||
1157 | Standard library for this test | ||
1158 | |||
1159 | Printed? | ||
1160 | abc123 | ||
1161 | "#]], | ||
1162 | ); | ||
1163 | check( | ||
1164 | r#" | ||
1165 | //- /main.rs | ||
1166 | extern crate std as ab<|>c; | ||
1167 | //- /std/lib.rs | ||
1168 | //! Standard library for this test | ||
1169 | //! | ||
1170 | //! Printed? | ||
1171 | //! abc123 | ||
1172 | "#, | ||
1173 | expect![[r#" | ||
1174 | *abc* | ||
1175 | Standard library for this test | ||
1176 | |||
1177 | Printed? | ||
1178 | abc123 | ||
1179 | "#]], | ||
1180 | ); | ||
1181 | } | ||
1182 | |||
1183 | #[test] | ||
1110 | fn test_hover_mod_with_same_name_as_function() { | 1184 | fn test_hover_mod_with_same_name_as_function() { |
1111 | check( | 1185 | check( |
1112 | r#" | 1186 | r#" |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 0fede0d87..89fcb6f17 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -112,13 +112,19 @@ pub struct Diagnostic { | |||
112 | pub struct Fix { | 112 | pub struct Fix { |
113 | pub label: String, | 113 | pub label: String, |
114 | pub source_change: SourceChange, | 114 | pub source_change: SourceChange, |
115 | /// Allows to trigger the fix only when the caret is in the range given | ||
116 | pub fix_trigger_range: TextRange, | ||
115 | } | 117 | } |
116 | 118 | ||
117 | impl Fix { | 119 | impl Fix { |
118 | pub fn new(label: impl Into<String>, source_change: SourceChange) -> Self { | 120 | pub fn new( |
121 | label: impl Into<String>, | ||
122 | source_change: SourceChange, | ||
123 | fix_trigger_range: TextRange, | ||
124 | ) -> Self { | ||
119 | let label = label.into(); | 125 | let label = label.into(); |
120 | assert!(label.starts_with(char::is_uppercase) && !label.ends_with('.')); | 126 | assert!(label.starts_with(char::is_uppercase) && !label.ends_with('.')); |
121 | Self { label, source_change } | 127 | Self { label, source_change, fix_trigger_range } |
122 | } | 128 | } |
123 | } | 129 | } |
124 | 130 | ||
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index cf456630a..453985de3 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -130,13 +130,13 @@ fn find_name( | |||
130 | opt_name: Option<ast::Name>, | 130 | opt_name: Option<ast::Name>, |
131 | ) -> Option<RangeInfo<Definition>> { | 131 | ) -> Option<RangeInfo<Definition>> { |
132 | if let Some(name) = opt_name { | 132 | if let Some(name) = opt_name { |
133 | let def = classify_name(sema, &name)?.definition(); | 133 | let def = classify_name(sema, &name)?.definition(sema.db); |
134 | let range = name.syntax().text_range(); | 134 | let range = name.syntax().text_range(); |
135 | return Some(RangeInfo::new(range, def)); | 135 | return Some(RangeInfo::new(range, def)); |
136 | } | 136 | } |
137 | let name_ref = | 137 | let name_ref = |
138 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; | 138 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; |
139 | let def = classify_name_ref(sema, &name_ref)?.definition(); | 139 | let def = classify_name_ref(sema, &name_ref)?.definition(sema.db); |
140 | let range = name_ref.syntax().text_range(); | 140 | let range = name_ref.syntax().text_range(); |
141 | Some(RangeInfo::new(range, def)) | 141 | Some(RangeInfo::new(range, def)) |
142 | } | 142 | } |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 3cd6c815b..c8d80fcf7 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -157,7 +157,7 @@ fn rename_to_self( | |||
157 | } | 157 | } |
158 | let first_param = params.params().next()?; | 158 | let first_param = params.params().next()?; |
159 | let mutable = match first_param.ty() { | 159 | let mutable = match first_param.ty() { |
160 | Some(ast::Type::ReferenceType(rt)) => rt.mut_token().is_some(), | 160 | Some(ast::Type::RefType(rt)) => rt.mut_token().is_some(), |
161 | _ => return None, // not renaming other types | 161 | _ => return None, // not renaming other types |
162 | }; | 162 | }; |
163 | 163 | ||
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 32f34ef10..c10e15db8 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -4,7 +4,7 @@ mod injection; | |||
4 | #[cfg(test)] | 4 | #[cfg(test)] |
5 | mod tests; | 5 | mod tests; |
6 | 6 | ||
7 | use hir::{Name, Semantics}; | 7 | use hir::{Name, Semantics, VariantDef}; |
8 | use ra_ide_db::{ | 8 | use ra_ide_db::{ |
9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, | 9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, |
10 | RootDatabase, | 10 | RootDatabase, |
@@ -455,6 +455,18 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
455 | Some(TextRange::new(range_start, range_end)) | 455 | Some(TextRange::new(range_start, range_end)) |
456 | } | 456 | } |
457 | 457 | ||
458 | fn is_possibly_unsafe(name_ref: &ast::NameRef) -> bool { | ||
459 | name_ref | ||
460 | .syntax() | ||
461 | .parent() | ||
462 | .and_then(|parent| { | ||
463 | ast::FieldExpr::cast(parent.clone()) | ||
464 | .map(|_| true) | ||
465 | .or_else(|| ast::RecordPatField::cast(parent).map(|_| true)) | ||
466 | }) | ||
467 | .unwrap_or(false) | ||
468 | } | ||
469 | |||
458 | fn highlight_element( | 470 | fn highlight_element( |
459 | sema: &Semantics<RootDatabase>, | 471 | sema: &Semantics<RootDatabase>, |
460 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 472 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
@@ -483,11 +495,21 @@ fn highlight_element( | |||
483 | }; | 495 | }; |
484 | 496 | ||
485 | match name_kind { | 497 | match name_kind { |
498 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), | ||
486 | Some(NameClass::Definition(def)) => { | 499 | Some(NameClass::Definition(def)) => { |
487 | highlight_name(db, def) | HighlightModifier::Definition | 500 | highlight_name(sema, db, def, None, false) | HighlightModifier::Definition |
501 | } | ||
502 | Some(NameClass::ConstReference(def)) => highlight_name(sema, db, def, None, false), | ||
503 | Some(NameClass::FieldShorthand { field, .. }) => { | ||
504 | let mut h = HighlightTag::Field.into(); | ||
505 | if let Definition::Field(field) = field { | ||
506 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
507 | h |= HighlightModifier::Unsafe; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | h | ||
488 | } | 512 | } |
489 | Some(NameClass::ConstReference(def)) => highlight_name(db, def), | ||
490 | Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(), | ||
491 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, | 513 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, |
492 | } | 514 | } |
493 | } | 515 | } |
@@ -498,8 +520,10 @@ fn highlight_element( | |||
498 | } | 520 | } |
499 | NAME_REF => { | 521 | NAME_REF => { |
500 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 522 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
523 | let possibly_unsafe = is_possibly_unsafe(&name_ref); | ||
501 | match classify_name_ref(sema, &name_ref) { | 524 | match classify_name_ref(sema, &name_ref) { |
502 | Some(name_kind) => match name_kind { | 525 | Some(name_kind) => match name_kind { |
526 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), | ||
503 | NameRefClass::Definition(def) => { | 527 | NameRefClass::Definition(def) => { |
504 | if let Definition::Local(local) = &def { | 528 | if let Definition::Local(local) = &def { |
505 | if let Some(name) = local.name(db) { | 529 | if let Some(name) = local.name(db) { |
@@ -508,11 +532,13 @@ fn highlight_element( | |||
508 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 532 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) |
509 | } | 533 | } |
510 | }; | 534 | }; |
511 | highlight_name(db, def) | 535 | highlight_name(sema, db, def, Some(name_ref), possibly_unsafe) |
512 | } | 536 | } |
513 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 537 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
514 | }, | 538 | }, |
515 | None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref), | 539 | None if syntactic_name_ref_highlighting => { |
540 | highlight_name_ref_by_syntax(name_ref, sema) | ||
541 | } | ||
516 | None => HighlightTag::UnresolvedReference.into(), | 542 | None => HighlightTag::UnresolvedReference.into(), |
517 | } | 543 | } |
518 | } | 544 | } |
@@ -540,13 +566,24 @@ fn highlight_element( | |||
540 | } | 566 | } |
541 | } | 567 | } |
542 | p if p.is_punct() => match p { | 568 | p if p.is_punct() => match p { |
543 | T![::] | T![->] | T![=>] | T![&] | T![..] | T![=] | T![@] => { | 569 | T![&] => { |
544 | HighlightTag::Operator.into() | 570 | let h = HighlightTag::Operator.into(); |
571 | let is_unsafe = element | ||
572 | .parent() | ||
573 | .and_then(ast::RefExpr::cast) | ||
574 | .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)) | ||
575 | .unwrap_or(false); | ||
576 | if is_unsafe { | ||
577 | h | HighlightModifier::Unsafe | ||
578 | } else { | ||
579 | h | ||
580 | } | ||
545 | } | 581 | } |
582 | T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] => HighlightTag::Operator.into(), | ||
546 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | 583 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { |
547 | HighlightTag::Macro.into() | 584 | HighlightTag::Macro.into() |
548 | } | 585 | } |
549 | T![*] if element.parent().and_then(ast::PointerType::cast).is_some() => { | 586 | T![*] if element.parent().and_then(ast::PtrType::cast).is_some() => { |
550 | HighlightTag::Keyword.into() | 587 | HighlightTag::Keyword.into() |
551 | } | 588 | } |
552 | T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | 589 | T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { |
@@ -623,6 +660,18 @@ fn highlight_element( | |||
623 | HighlightTag::SelfKeyword.into() | 660 | HighlightTag::SelfKeyword.into() |
624 | } | 661 | } |
625 | } | 662 | } |
663 | T![ref] => element | ||
664 | .parent() | ||
665 | .and_then(ast::IdentPat::cast) | ||
666 | .and_then(|ident_pat| { | ||
667 | if sema.is_unsafe_ident_pat(&ident_pat) { | ||
668 | Some(HighlightModifier::Unsafe) | ||
669 | } else { | ||
670 | None | ||
671 | } | ||
672 | }) | ||
673 | .map(|modifier| h | modifier) | ||
674 | .unwrap_or(h), | ||
626 | _ => h, | 675 | _ => h, |
627 | } | 676 | } |
628 | } | 677 | } |
@@ -652,16 +701,40 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
652 | } | 701 | } |
653 | } | 702 | } |
654 | 703 | ||
655 | fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { | 704 | fn highlight_name( |
705 | sema: &Semantics<RootDatabase>, | ||
706 | db: &RootDatabase, | ||
707 | def: Definition, | ||
708 | name_ref: Option<ast::NameRef>, | ||
709 | possibly_unsafe: bool, | ||
710 | ) -> Highlight { | ||
656 | match def { | 711 | match def { |
657 | Definition::Macro(_) => HighlightTag::Macro, | 712 | Definition::Macro(_) => HighlightTag::Macro, |
658 | Definition::Field(_) => HighlightTag::Field, | 713 | Definition::Field(field) => { |
714 | let mut h = HighlightTag::Field.into(); | ||
715 | if possibly_unsafe { | ||
716 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
717 | h |= HighlightModifier::Unsafe; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | return h; | ||
722 | } | ||
659 | Definition::ModuleDef(def) => match def { | 723 | Definition::ModuleDef(def) => match def { |
660 | hir::ModuleDef::Module(_) => HighlightTag::Module, | 724 | hir::ModuleDef::Module(_) => HighlightTag::Module, |
661 | hir::ModuleDef::Function(func) => { | 725 | hir::ModuleDef::Function(func) => { |
662 | let mut h = HighlightTag::Function.into(); | 726 | let mut h = HighlightTag::Function.into(); |
663 | if func.is_unsafe(db) { | 727 | if func.is_unsafe(db) { |
664 | h |= HighlightModifier::Unsafe; | 728 | h |= HighlightModifier::Unsafe; |
729 | } else { | ||
730 | let is_unsafe = name_ref | ||
731 | .and_then(|name_ref| name_ref.syntax().parent()) | ||
732 | .and_then(ast::MethodCallExpr::cast) | ||
733 | .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) | ||
734 | .unwrap_or(false); | ||
735 | if is_unsafe { | ||
736 | h |= HighlightModifier::Unsafe; | ||
737 | } | ||
665 | } | 738 | } |
666 | return h; | 739 | return h; |
667 | } | 740 | } |
@@ -677,6 +750,7 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { | |||
677 | let mut h = Highlight::new(HighlightTag::Static); | 750 | let mut h = Highlight::new(HighlightTag::Static); |
678 | if s.is_mut(db) { | 751 | if s.is_mut(db) { |
679 | h |= HighlightModifier::Mutable; | 752 | h |= HighlightModifier::Mutable; |
753 | h |= HighlightModifier::Unsafe; | ||
680 | } | 754 | } |
681 | return h; | 755 | return h; |
682 | } | 756 | } |
@@ -724,7 +798,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
724 | tag.into() | 798 | tag.into() |
725 | } | 799 | } |
726 | 800 | ||
727 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | 801 | fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { |
728 | let default = HighlightTag::UnresolvedReference; | 802 | let default = HighlightTag::UnresolvedReference; |
729 | 803 | ||
730 | let parent = match name.syntax().parent() { | 804 | let parent = match name.syntax().parent() { |
@@ -732,9 +806,36 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | |||
732 | _ => return default.into(), | 806 | _ => return default.into(), |
733 | }; | 807 | }; |
734 | 808 | ||
735 | let tag = match parent.kind() { | 809 | match parent.kind() { |
736 | METHOD_CALL_EXPR => HighlightTag::Function, | 810 | METHOD_CALL_EXPR => { |
737 | FIELD_EXPR => HighlightTag::Field, | 811 | let mut h = Highlight::new(HighlightTag::Function); |
812 | let is_unsafe = ast::MethodCallExpr::cast(parent) | ||
813 | .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) | ||
814 | .unwrap_or(false); | ||
815 | if is_unsafe { | ||
816 | h |= HighlightModifier::Unsafe; | ||
817 | } | ||
818 | |||
819 | h | ||
820 | } | ||
821 | FIELD_EXPR => { | ||
822 | let h = HighlightTag::Field; | ||
823 | let is_union = ast::FieldExpr::cast(parent) | ||
824 | .and_then(|field_expr| { | ||
825 | let field = sema.resolve_field(&field_expr)?; | ||
826 | Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { | ||
827 | true | ||
828 | } else { | ||
829 | false | ||
830 | }) | ||
831 | }) | ||
832 | .unwrap_or(false); | ||
833 | if is_union { | ||
834 | h | HighlightModifier::Unsafe | ||
835 | } else { | ||
836 | h.into() | ||
837 | } | ||
838 | } | ||
738 | PATH_SEGMENT => { | 839 | PATH_SEGMENT => { |
739 | let path = match parent.parent().and_then(ast::Path::cast) { | 840 | let path = match parent.parent().and_then(ast::Path::cast) { |
740 | Some(it) => it, | 841 | Some(it) => it, |
@@ -758,18 +859,15 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | |||
758 | }; | 859 | }; |
759 | 860 | ||
760 | match parent.kind() { | 861 | match parent.kind() { |
761 | CALL_EXPR => HighlightTag::Function, | 862 | CALL_EXPR => HighlightTag::Function.into(), |
762 | _ => { | 863 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { |
763 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | 864 | HighlightTag::Struct.into() |
764 | HighlightTag::Struct | 865 | } else { |
765 | } else { | 866 | HighlightTag::Constant |
766 | HighlightTag::Constant | ||
767 | } | ||
768 | } | 867 | } |
868 | .into(), | ||
769 | } | 869 | } |
770 | } | 870 | } |
771 | _ => default, | 871 | _ => default.into(), |
772 | }; | 872 | } |
773 | |||
774 | tag.into() | ||
775 | } | 873 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs index 8665b480f..6046643ef 100644 --- a/crates/ra_ide/src/syntax_highlighting/injection.rs +++ b/crates/ra_ide/src/syntax_highlighting/injection.rs | |||
@@ -4,8 +4,8 @@ use std::{collections::BTreeMap, convert::TryFrom}; | |||
4 | 4 | ||
5 | use ast::{HasQuotes, HasStringValue}; | 5 | use ast::{HasQuotes, HasStringValue}; |
6 | use hir::Semantics; | 6 | use hir::Semantics; |
7 | use itertools::Itertools; | ||
7 | use ra_syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize}; | 8 | use ra_syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize}; |
8 | use stdx::SepBy; | ||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | call_info::ActiveParameter, Analysis, Highlight, HighlightModifier, HighlightTag, | 11 | call_info::ActiveParameter, Analysis, Highlight, HighlightModifier, HighlightTag, |
@@ -129,8 +129,7 @@ pub(super) fn extract_doc_comments( | |||
129 | 129 | ||
130 | line[pos..].to_owned() | 130 | line[pos..].to_owned() |
131 | }) | 131 | }) |
132 | .sep_by("\n") | 132 | .join("\n"); |
133 | .to_string(); | ||
134 | 133 | ||
135 | if doctest.is_empty() { | 134 | if doctest.is_empty() { |
136 | return None; | 135 | return None; |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 87a6e2523..a8087635a 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -9,6 +9,9 @@ use crate::{mock_analysis::single_file, FileRange, TextRange}; | |||
9 | fn test_highlighting() { | 9 | fn test_highlighting() { |
10 | check_highlighting( | 10 | check_highlighting( |
11 | r#" | 11 | r#" |
12 | use inner::{self as inner_mod}; | ||
13 | mod inner {} | ||
14 | |||
12 | #[derive(Clone, Debug)] | 15 | #[derive(Clone, Debug)] |
13 | struct Foo { | 16 | struct Foo { |
14 | pub x: i32, | 17 | pub x: i32, |
@@ -272,19 +275,64 @@ fn test_unsafe_highlighting() { | |||
272 | r#" | 275 | r#" |
273 | unsafe fn unsafe_fn() {} | 276 | unsafe fn unsafe_fn() {} |
274 | 277 | ||
278 | union Union { | ||
279 | a: u32, | ||
280 | b: f32, | ||
281 | } | ||
282 | |||
275 | struct HasUnsafeFn; | 283 | struct HasUnsafeFn; |
276 | 284 | ||
277 | impl HasUnsafeFn { | 285 | impl HasUnsafeFn { |
278 | unsafe fn unsafe_method(&self) {} | 286 | unsafe fn unsafe_method(&self) {} |
279 | } | 287 | } |
280 | 288 | ||
289 | struct TypeForStaticMut { | ||
290 | a: u8 | ||
291 | } | ||
292 | |||
293 | static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; | ||
294 | |||
295 | #[repr(packed)] | ||
296 | struct Packed { | ||
297 | a: u16, | ||
298 | } | ||
299 | |||
300 | trait DoTheAutoref { | ||
301 | fn calls_autoref(&self); | ||
302 | } | ||
303 | |||
304 | impl DoTheAutoref for u16 { | ||
305 | fn calls_autoref(&self) {} | ||
306 | } | ||
307 | |||
281 | fn main() { | 308 | fn main() { |
282 | let x = &5 as *const usize; | 309 | let x = &5 as *const _ as *const usize; |
310 | let u = Union { b: 0 }; | ||
283 | unsafe { | 311 | unsafe { |
312 | // unsafe fn and method calls | ||
284 | unsafe_fn(); | 313 | unsafe_fn(); |
314 | let b = u.b; | ||
315 | match u { | ||
316 | Union { b: 0 } => (), | ||
317 | Union { a } => (), | ||
318 | } | ||
285 | HasUnsafeFn.unsafe_method(); | 319 | HasUnsafeFn.unsafe_method(); |
286 | let y = *(x); | 320 | |
287 | let z = -x; | 321 | // unsafe deref |
322 | let y = *x; | ||
323 | |||
324 | // unsafe access to a static mut | ||
325 | let a = global_mut.a; | ||
326 | |||
327 | // unsafe ref of packed fields | ||
328 | let packed = Packed { a: 0 }; | ||
329 | let a = &packed.a; | ||
330 | let ref a = packed.a; | ||
331 | let Packed { ref a } = packed; | ||
332 | let Packed { a: ref _a } = packed; | ||
333 | |||
334 | // unsafe auto ref of packed field | ||
335 | packed.a.calls_autoref(); | ||
288 | } | 336 | } |
289 | } | 337 | } |
290 | "# | 338 | "# |
@@ -370,6 +418,23 @@ macro_rules! noop { | |||
370 | ); | 418 | ); |
371 | } | 419 | } |
372 | 420 | ||
421 | #[test] | ||
422 | fn test_extern_crate() { | ||
423 | check_highlighting( | ||
424 | r#" | ||
425 | //- /main.rs | ||
426 | extern crate std; | ||
427 | extern crate alloc as abc; | ||
428 | //- /std/lib.rs | ||
429 | pub struct S; | ||
430 | //- /alloc/lib.rs | ||
431 | pub struct A | ||
432 | "#, | ||
433 | expect_file!["crates/ra_ide/test_data/highlight_extern_crate.html"], | ||
434 | false, | ||
435 | ); | ||
436 | } | ||
437 | |||
373 | /// Highlights the code given by the `ra_fixture` argument, renders the | 438 | /// Highlights the code given by the `ra_fixture` argument, renders the |
374 | /// result as HTML, and compares it with the HTML file given as `snapshot`. | 439 | /// result as HTML, and compares it with the HTML file given as `snapshot`. |
375 | /// Note that the `snapshot` file is overwritten by the rendered HTML. | 440 | /// Note that the `snapshot` file is overwritten by the rendered HTML. |
diff --git a/crates/ra_ide/test_data/highlight_extern_crate.html b/crates/ra_ide/test_data/highlight_extern_crate.html new file mode 100644 index 000000000..800d894c7 --- /dev/null +++ b/crates/ra_ide/test_data/highlight_extern_crate.html | |||
@@ -0,0 +1,40 @@ | |||
1 | |||
2 | <style> | ||
3 | body { margin: 0; } | ||
4 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } | ||
5 | |||
6 | .lifetime { color: #DFAF8F; font-style: italic; } | ||
7 | .comment { color: #7F9F7F; } | ||
8 | .documentation { color: #629755; } | ||
9 | .injected { opacity: 0.65 ; } | ||
10 | .struct, .enum { color: #7CB8BB; } | ||
11 | .enum_variant { color: #BDE0F3; } | ||
12 | .string_literal { color: #CC9393; } | ||
13 | .field { color: #94BFF3; } | ||
14 | .function { color: #93E0E3; } | ||
15 | .function.unsafe { color: #BC8383; } | ||
16 | .operator.unsafe { color: #BC8383; } | ||
17 | .parameter { color: #94BFF3; } | ||
18 | .text { color: #DCDCCC; } | ||
19 | .type { color: #7CB8BB; } | ||
20 | .builtin_type { color: #8CD0D3; } | ||
21 | .type_param { color: #DFAF8F; } | ||
22 | .attribute { color: #94BFF3; } | ||
23 | .numeric_literal { color: #BFEBBF; } | ||
24 | .bool_literal { color: #BFE6EB; } | ||
25 | .macro { color: #94BFF3; } | ||
26 | .module { color: #AFD8AF; } | ||
27 | .value_param { color: #DCDCCC; } | ||
28 | .variable { color: #DCDCCC; } | ||
29 | .format_specifier { color: #CC696B; } | ||
30 | .mutable { text-decoration: underline; } | ||
31 | .escape_sequence { color: #94BFF3; } | ||
32 | .keyword { color: #F0DFAF; font-weight: bold; } | ||
33 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | ||
34 | .control { font-style: italic; } | ||
35 | |||
36 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | ||
37 | </style> | ||
38 | <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">std</span><span class="punctuation">;</span> | ||
39 | <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">alloc</span> <span class="keyword">as</span> <span class="module">abc</span><span class="punctuation">;</span> | ||
40 | </code></pre> \ No newline at end of file | ||
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html index b81b6f1c3..552fea668 100644 --- a/crates/ra_ide/test_data/highlight_unsafe.html +++ b/crates/ra_ide/test_data/highlight_unsafe.html | |||
@@ -37,18 +37,63 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
37 | </style> | 37 | </style> |
38 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 38 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> |
39 | 39 | ||
40 | <span class="keyword">union</span> <span class="union declaration">Union</span> <span class="punctuation">{</span> | ||
41 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span> | ||
42 | <span class="field declaration">b</span><span class="punctuation">:</span> <span class="builtin_type">f32</span><span class="punctuation">,</span> | ||
43 | <span class="punctuation">}</span> | ||
44 | |||
40 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> | 45 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> |
41 | 46 | ||
42 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> | 47 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> |
43 | <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_method</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 48 | <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_method</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> |
44 | <span class="punctuation">}</span> | 49 | <span class="punctuation">}</span> |
45 | 50 | ||
51 | <span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="punctuation">{</span> | ||
52 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u8</span> | ||
53 | <span class="punctuation">}</span> | ||
54 | |||
55 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | ||
56 | |||
57 | <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">repr</span><span class="punctuation">(</span><span class="attribute">packed</span><span class="punctuation">)</span><span class="attribute">]</span> | ||
58 | <span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="punctuation">{</span> | ||
59 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u16</span><span class="punctuation">,</span> | ||
60 | <span class="punctuation">}</span> | ||
61 | |||
62 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="punctuation">{</span> | ||
63 | <span class="keyword">fn</span> <span class="function declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span> | ||
64 | <span class="punctuation">}</span> | ||
65 | |||
66 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="punctuation">{</span> | ||
67 | <span class="keyword">fn</span> <span class="function declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | ||
68 | <span class="punctuation">}</span> | ||
69 | |||
46 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 70 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
47 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> | 71 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> |
72 | <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | ||
48 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> | 73 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> |
74 | <span class="comment">// unsafe fn and method calls</span> | ||
49 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 75 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
76 | <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="punctuation">.</span><span class="field unsafe">b</span><span class="punctuation">;</span> | ||
77 | <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> | ||
78 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | ||
79 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | ||
80 | <span class="punctuation">}</span> | ||
50 | <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 81 | <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
51 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="punctuation">(</span><span class="variable">x</span><span class="punctuation">)</span><span class="punctuation">;</span> | 82 | |
52 | <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="variable">x</span><span class="punctuation">;</span> | 83 | <span class="comment">// unsafe deref</span> |
84 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="punctuation">;</span> | ||
85 | |||
86 | <span class="comment">// unsafe access to a static mut</span> | ||
87 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="static mutable unsafe">global_mut</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> | ||
88 | |||
89 | <span class="comment">// unsafe ref of packed fields</span> | ||
90 | <span class="keyword">let</span> <span class="variable declaration">packed</span> <span class="operator">=</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | ||
91 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="operator unsafe">&</span><span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> | ||
92 | <span class="keyword">let</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> | ||
93 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="keyword unsafe">ref</span> <span class="field">a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span> | ||
94 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span> | ||
95 | |||
96 | <span class="comment">// unsafe auto ref of packed field</span> | ||
97 | <span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">.</span><span class="function unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | ||
53 | <span class="punctuation">}</span> | 98 | <span class="punctuation">}</span> |
54 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 99 | <span class="punctuation">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ra_ide/test_data/highlighting.html b/crates/ra_ide/test_data/highlighting.html index 345a2f023..8e0160eee 100644 --- a/crates/ra_ide/test_data/highlighting.html +++ b/crates/ra_ide/test_data/highlighting.html | |||
@@ -35,7 +35,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
35 | 35 | ||
36 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 36 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
37 | </style> | 37 | </style> |
38 | <pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Clone</span><span class="punctuation">,</span><span class="attribute"> Debug</span><span class="punctuation">)</span><span class="attribute">]</span> | 38 | <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span> |
39 | <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span> | ||
40 | |||
41 | <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Clone</span><span class="punctuation">,</span><span class="attribute"> Debug</span><span class="punctuation">)</span><span class="attribute">]</span> | ||
39 | <span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span> | 42 | <span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span> |
40 | <span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> | 43 | <span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> |
41 | <span class="keyword">pub</span> <span class="field declaration">y</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> | 44 | <span class="keyword">pub</span> <span class="field declaration">y</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> |
@@ -61,7 +64,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
61 | <span class="punctuation">}</span> | 64 | <span class="punctuation">}</span> |
62 | <span class="punctuation">}</span> | 65 | <span class="punctuation">}</span> |
63 | 66 | ||
64 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> | 67 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> |
65 | 68 | ||
66 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation"><</span><span class="lifetime declaration">'a</span><span class="punctuation">,</span> <span class="type_param declaration">T</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="type_param">T</span> <span class="punctuation">{</span> | 69 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation"><</span><span class="lifetime declaration">'a</span><span class="punctuation">,</span> <span class="type_param declaration">T</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="type_param">T</span> <span class="punctuation">{</span> |
67 | <span class="function">foo</span><span class="operator">::</span><span class="punctuation"><</span><span class="lifetime">'a</span><span class="punctuation">,</span> <span class="builtin_type">i32</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> | 70 | <span class="function">foo</span><span class="operator">::</span><span class="punctuation"><</span><span class="lifetime">'a</span><span class="punctuation">,</span> <span class="builtin_type">i32</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> |
@@ -94,7 +97,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
94 | <span class="punctuation">}</span> | 97 | <span class="punctuation">}</span> |
95 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> | 98 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> |
96 | <span class="variable mutable">vec</span><span class="punctuation">.</span><span class="unresolved_reference">set_len</span><span class="punctuation">(</span><span class="numeric_literal">0</span><span class="punctuation">)</span><span class="punctuation">;</span> | 99 | <span class="variable mutable">vec</span><span class="punctuation">.</span><span class="unresolved_reference">set_len</span><span class="punctuation">(</span><span class="numeric_literal">0</span><span class="punctuation">)</span><span class="punctuation">;</span> |
97 | <span class="static mutable">STATIC_MUT</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="punctuation">;</span> | 100 | <span class="static mutable unsafe">STATIC_MUT</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="punctuation">;</span> |
98 | <span class="punctuation">}</span> | 101 | <span class="punctuation">}</span> |
99 | 102 | ||
100 | <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> <span class="punctuation">{</span> | 103 | <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> <span class="punctuation">{</span> |
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs index 32d9a8d1f..b13df8b85 100644 --- a/crates/ra_ide_db/src/change.rs +++ b/crates/ra_ide_db/src/change.rs | |||
@@ -190,11 +190,24 @@ impl RootDatabase { | |||
190 | let q: $q = Default::default(); | 190 | let q: $q = Default::default(); |
191 | let name = format!("{:?} (deps)", q); | 191 | let name = format!("{:?} (deps)", q); |
192 | acc.push((name, before - after)); | 192 | acc.push((name, before - after)); |
193 | |||
194 | let before = memory_usage().allocated; | ||
195 | $q.in_db(self).purge(); | ||
196 | let after = memory_usage().allocated; | ||
197 | let q: $q = Default::default(); | ||
198 | let name = format!("{:?} (purge)", q); | ||
199 | acc.push((name, before - after)); | ||
193 | )*} | 200 | )*} |
194 | } | 201 | } |
195 | sweep_each_query![ | 202 | sweep_each_query![ |
196 | // SourceDatabase | 203 | // SourceDatabase |
197 | ra_db::ParseQuery | 204 | ra_db::ParseQuery |
205 | ra_db::CrateGraphQuery | ||
206 | |||
207 | // SourceDatabaseExt | ||
208 | ra_db::FileTextQuery | ||
209 | ra_db::FileSourceRootQuery | ||
210 | ra_db::SourceRootQuery | ||
198 | ra_db::SourceRootCratesQuery | 211 | ra_db::SourceRootCratesQuery |
199 | 212 | ||
200 | // AstDatabase | 213 | // AstDatabase |
@@ -242,15 +255,24 @@ impl RootDatabase { | |||
242 | hir::db::TraitImplsInCrateQuery | 255 | hir::db::TraitImplsInCrateQuery |
243 | hir::db::TraitImplsInDepsQuery | 256 | hir::db::TraitImplsInDepsQuery |
244 | hir::db::AssociatedTyDataQuery | 257 | hir::db::AssociatedTyDataQuery |
258 | hir::db::AssociatedTyDataQuery | ||
245 | hir::db::TraitDatumQuery | 259 | hir::db::TraitDatumQuery |
246 | hir::db::StructDatumQuery | 260 | hir::db::StructDatumQuery |
247 | hir::db::ImplDatumQuery | 261 | hir::db::ImplDatumQuery |
262 | hir::db::FnDefDatumQuery | ||
263 | hir::db::ReturnTypeImplTraitsQuery | ||
264 | hir::db::InternCallableDefQuery | ||
265 | hir::db::InternTypeParamIdQuery | ||
266 | hir::db::InternImplTraitIdQuery | ||
267 | hir::db::InternClosureQuery | ||
248 | hir::db::AssociatedTyValueQuery | 268 | hir::db::AssociatedTyValueQuery |
249 | hir::db::TraitSolveQuery | 269 | hir::db::TraitSolveQuery |
250 | hir::db::ReturnTypeImplTraitsQuery | ||
251 | 270 | ||
252 | // SymbolsDatabase | 271 | // SymbolsDatabase |
253 | crate::symbol_index::FileSymbolsQuery | 272 | crate::symbol_index::FileSymbolsQuery |
273 | crate::symbol_index::LibrarySymbolsQuery | ||
274 | crate::symbol_index::LocalRootsQuery | ||
275 | crate::symbol_index::LibraryRootsQuery | ||
254 | 276 | ||
255 | // LineIndexDatabase | 277 | // LineIndexDatabase |
256 | crate::LineIndexQuery | 278 | crate::LineIndexQuery |
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 66c048714..9bb95277d 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -6,13 +6,13 @@ | |||
6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). | 6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). |
7 | 7 | ||
8 | use hir::{ | 8 | use hir::{ |
9 | Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution, | 9 | db::HirDatabase, Crate, Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, |
10 | Semantics, TypeParam, Visibility, | 10 | Name, PathResolution, Semantics, TypeParam, Visibility, |
11 | }; | 11 | }; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ |
14 | ast::{self, AstNode}, | 14 | ast::{self, AstNode}, |
15 | match_ast, | 15 | match_ast, SyntaxNode, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | use crate::RootDatabase; | 18 | use crate::RootDatabase; |
@@ -80,6 +80,7 @@ impl Definition { | |||
80 | 80 | ||
81 | #[derive(Debug)] | 81 | #[derive(Debug)] |
82 | pub enum NameClass { | 82 | pub enum NameClass { |
83 | ExternCrate(Crate), | ||
83 | Definition(Definition), | 84 | Definition(Definition), |
84 | /// `None` in `if let None = Some(82) {}` | 85 | /// `None` in `if let None = Some(82) {}` |
85 | ConstReference(Definition), | 86 | ConstReference(Definition), |
@@ -90,16 +91,18 @@ pub enum NameClass { | |||
90 | } | 91 | } |
91 | 92 | ||
92 | impl NameClass { | 93 | impl NameClass { |
93 | pub fn into_definition(self) -> Option<Definition> { | 94 | pub fn into_definition(self, db: &dyn HirDatabase) -> Option<Definition> { |
94 | match self { | 95 | Some(match self { |
95 | NameClass::Definition(it) => Some(it), | 96 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), |
96 | NameClass::ConstReference(_) => None, | 97 | NameClass::Definition(it) => it, |
97 | NameClass::FieldShorthand { local, field: _ } => Some(Definition::Local(local)), | 98 | NameClass::ConstReference(_) => return None, |
98 | } | 99 | NameClass::FieldShorthand { local, field: _ } => Definition::Local(local), |
100 | }) | ||
99 | } | 101 | } |
100 | 102 | ||
101 | pub fn definition(self) -> Definition { | 103 | pub fn definition(self, db: &dyn HirDatabase) -> Definition { |
102 | match self { | 104 | match self { |
105 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), | ||
103 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, | 106 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, |
104 | NameClass::FieldShorthand { local: _, field } => field, | 107 | NameClass::FieldShorthand { local: _, field } => field, |
105 | } | 108 | } |
@@ -120,13 +123,37 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
120 | match_ast! { | 123 | match_ast! { |
121 | match parent { | 124 | match parent { |
122 | ast::Rename(it) => { | 125 | ast::Rename(it) => { |
123 | let use_tree = it.syntax().parent().and_then(ast::UseTree::cast)?; | 126 | if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) { |
124 | let path = use_tree.path()?; | 127 | let path = use_tree.path()?; |
125 | let path_segment = path.segment()?; | 128 | let path_segment = path.segment()?; |
126 | let name_ref = path_segment.name_ref()?; | 129 | let name_ref_class = path_segment |
127 | let name_ref_class = classify_name_ref(sema, &name_ref)?; | 130 | .name_ref() |
131 | // The rename might be from a `self` token, so fallback to the name higher | ||
132 | // in the use tree. | ||
133 | .or_else(||{ | ||
134 | if path_segment.self_token().is_none() { | ||
135 | return None; | ||
136 | } | ||
128 | 137 | ||
129 | Some(NameClass::Definition(name_ref_class.definition())) | 138 | let use_tree = use_tree |
139 | .syntax() | ||
140 | .parent() | ||
141 | .as_ref() | ||
142 | // Skip over UseTreeList | ||
143 | .and_then(SyntaxNode::parent) | ||
144 | .and_then(ast::UseTree::cast)?; | ||
145 | let path = use_tree.path()?; | ||
146 | let path_segment = path.segment()?; | ||
147 | path_segment.name_ref() | ||
148 | }) | ||
149 | .and_then(|name_ref| classify_name_ref(sema, &name_ref))?; | ||
150 | |||
151 | Some(NameClass::Definition(name_ref_class.definition(sema.db))) | ||
152 | } else { | ||
153 | let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; | ||
154 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | ||
155 | Some(NameClass::ExternCrate(resolved)) | ||
156 | } | ||
130 | }, | 157 | }, |
131 | ast::IdentPat(it) => { | 158 | ast::IdentPat(it) => { |
132 | let local = sema.to_def(&it)?; | 159 | let local = sema.to_def(&it)?; |
@@ -201,13 +228,15 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
201 | 228 | ||
202 | #[derive(Debug)] | 229 | #[derive(Debug)] |
203 | pub enum NameRefClass { | 230 | pub enum NameRefClass { |
231 | ExternCrate(Crate), | ||
204 | Definition(Definition), | 232 | Definition(Definition), |
205 | FieldShorthand { local: Local, field: Definition }, | 233 | FieldShorthand { local: Local, field: Definition }, |
206 | } | 234 | } |
207 | 235 | ||
208 | impl NameRefClass { | 236 | impl NameRefClass { |
209 | pub fn definition(self) -> Definition { | 237 | pub fn definition(self, db: &dyn HirDatabase) -> Definition { |
210 | match self { | 238 | match self { |
239 | NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), | ||
211 | NameRefClass::Definition(def) => def, | 240 | NameRefClass::Definition(def) => def, |
212 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), | 241 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), |
213 | } | 242 | } |
@@ -288,9 +317,15 @@ pub fn classify_name_ref( | |||
288 | } | 317 | } |
289 | } | 318 | } |
290 | 319 | ||
291 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 320 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { |
292 | let resolved = sema.resolve_path(&path)?; | 321 | if let Some(resolved) = sema.resolve_path(&path) { |
293 | Some(NameRefClass::Definition(resolved.into())) | 322 | return Some(NameRefClass::Definition(resolved.into())); |
323 | } | ||
324 | } | ||
325 | |||
326 | let extern_crate = ast::ExternCrate::cast(parent)?; | ||
327 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | ||
328 | Some(NameRefClass::ExternCrate(resolved)) | ||
294 | } | 329 | } |
295 | 330 | ||
296 | impl From<PathResolution> for Definition { | 331 | impl From<PathResolution> for Definition { |
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs index 1fba71ff8..9e040973b 100644 --- a/crates/ra_ide_db/src/imports_locator.rs +++ b/crates/ra_ide_db/src/imports_locator.rs | |||
@@ -61,5 +61,5 @@ fn get_name_definition<'a>( | |||
61 | candidate_node | 61 | candidate_node |
62 | }; | 62 | }; |
63 | let name = ast::Name::cast(candidate_name_node)?; | 63 | let name = ast::Name::cast(candidate_name_node)?; |
64 | classify_name(sema, &name)?.into_definition() | 64 | classify_name(sema, &name)?.into_definition(sema.db) |
65 | } | 65 | } |
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index f9e515b81..933a3a3b5 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs | |||
@@ -276,7 +276,7 @@ impl<'a> TtIter<'a> { | |||
276 | Ok(tt::Subtree { | 276 | Ok(tt::Subtree { |
277 | delimiter: None, | 277 | delimiter: None, |
278 | token_trees: vec![ | 278 | token_trees: vec![ |
279 | tt::Leaf::Punct(punct.clone()).into(), | 279 | tt::Leaf::Punct(*punct).into(), |
280 | tt::Leaf::Ident(ident.clone()).into(), | 280 | tt::Leaf::Ident(ident.clone()).into(), |
281 | ], | 281 | ], |
282 | } | 282 | } |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index c2e1d701e..88468bc97 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -110,7 +110,7 @@ pub(crate) mod fragments { | |||
110 | } | 110 | } |
111 | 111 | ||
112 | pub(crate) fn item(p: &mut Parser) { | 112 | pub(crate) fn item(p: &mut Parser) { |
113 | items::item_or_macro(p, true, items::ItemFlavor::Mod) | 113 | items::item_or_macro(p, true) |
114 | } | 114 | } |
115 | 115 | ||
116 | pub(crate) fn macro_items(p: &mut Parser) { | 116 | pub(crate) fn macro_items(p: &mut Parser) { |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index e1c25a838..3291e3f14 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -73,7 +73,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
73 | 73 | ||
74 | // test block_items | 74 | // test block_items |
75 | // fn a() { fn b() {} } | 75 | // fn a() { fn b() {} } |
76 | let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { | 76 | let m = match items::maybe_item(p, m) { |
77 | Ok(()) => return, | 77 | Ok(()) => return, |
78 | Err(m) => m, | 78 | Err(m) => m, |
79 | }; | 79 | }; |
@@ -509,7 +509,6 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
509 | // x.1i32; | 509 | // x.1i32; |
510 | // x.0x01; | 510 | // x.0x01; |
511 | // } | 511 | // } |
512 | #[allow(clippy::if_same_then_else)] | ||
513 | fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 512 | fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
514 | assert!(p.at(T![.])); | 513 | assert!(p.at(T![.])); |
515 | let m = lhs.precede(p); | 514 | let m = lhs.precede(p); |
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index cca524cea..d091b0fbb 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs | |||
@@ -22,24 +22,19 @@ use super::*; | |||
22 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { | 22 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { |
23 | attributes::inner_attributes(p); | 23 | attributes::inner_attributes(p); |
24 | while !(stop_on_r_curly && p.at(T!['}']) || p.at(EOF)) { | 24 | while !(stop_on_r_curly && p.at(T!['}']) || p.at(EOF)) { |
25 | item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod) | 25 | item_or_macro(p, stop_on_r_curly) |
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | pub(super) enum ItemFlavor { | ||
30 | Mod, | ||
31 | Trait, | ||
32 | } | ||
33 | |||
34 | pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ | 29 | pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ |
35 | FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, | 30 | FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, |
36 | CRATE_KW, USE_KW, MACRO_KW | 31 | CRATE_KW, USE_KW, MACRO_KW |
37 | ]; | 32 | ]; |
38 | 33 | ||
39 | pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { | 34 | pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool) { |
40 | let m = p.start(); | 35 | let m = p.start(); |
41 | attributes::outer_attributes(p); | 36 | attributes::outer_attributes(p); |
42 | let m = match maybe_item(p, m, flavor) { | 37 | let m = match maybe_item(p, m) { |
43 | Ok(()) => { | 38 | Ok(()) => { |
44 | if p.at(T![;]) { | 39 | if p.at(T![;]) { |
45 | p.err_and_bump( | 40 | p.err_and_bump( |
@@ -76,7 +71,7 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF | |||
76 | } | 71 | } |
77 | } | 72 | } |
78 | 73 | ||
79 | pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> { | 74 | pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> { |
80 | // test_err pub_expr | 75 | // test_err pub_expr |
81 | // fn foo() { pub 92; } | 76 | // fn foo() { pub 92; } |
82 | let has_visibility = opt_visibility(p); | 77 | let has_visibility = opt_visibility(p); |
@@ -114,38 +109,31 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul | |||
114 | has_mods = true; | 109 | has_mods = true; |
115 | } | 110 | } |
116 | 111 | ||
117 | if p.at(IDENT) | 112 | // test default_item |
118 | && p.at_contextual_kw("default") | 113 | // default impl T for Foo {} |
119 | && (match p.nth(1) { | 114 | if p.at(IDENT) && p.at_contextual_kw("default") { |
120 | T![impl] => true, | 115 | match p.nth(1) { |
116 | T![fn] | T![type] | T![const] | T![impl] => { | ||
117 | p.bump_remap(T![default]); | ||
118 | has_mods = true; | ||
119 | } | ||
121 | T![unsafe] => { | 120 | T![unsafe] => { |
122 | // test default_unsafe_impl | 121 | // test default_unsafe_item |
123 | // default unsafe impl Foo {} | 122 | // default unsafe impl T for Foo { |
124 | |||
125 | // test default_unsafe_fn | ||
126 | // impl T for Foo { | ||
127 | // default unsafe fn foo() {} | 123 | // default unsafe fn foo() {} |
128 | // } | 124 | // } |
129 | if p.nth(2) == T![impl] || p.nth(2) == T![fn] { | 125 | if matches!(p.nth(2), T![impl] | T![fn]) { |
130 | p.bump_remap(T![default]); | 126 | p.bump_remap(T![default]); |
131 | p.bump(T![unsafe]); | 127 | p.bump(T![unsafe]); |
132 | has_mods = true; | 128 | has_mods = true; |
133 | } | 129 | } |
134 | false | ||
135 | } | 130 | } |
136 | T![fn] | T![type] | T![const] => { | 131 | _ => (), |
137 | if let ItemFlavor::Mod = flavor { | 132 | } |
138 | true | ||
139 | } else { | ||
140 | false | ||
141 | } | ||
142 | } | ||
143 | _ => false, | ||
144 | }) | ||
145 | { | ||
146 | p.bump_remap(T![default]); | ||
147 | has_mods = true; | ||
148 | } | 133 | } |
134 | |||
135 | // test existential_type | ||
136 | // existential type Foo: Fn() -> usize; | ||
149 | if p.at(IDENT) && p.at_contextual_kw("existential") && p.nth(1) == T![type] { | 137 | if p.at(IDENT) && p.at_contextual_kw("existential") && p.nth(1) == T![type] { |
150 | p.bump_remap(T![existential]); | 138 | p.bump_remap(T![existential]); |
151 | has_mods = true; | 139 | has_mods = true; |
@@ -153,79 +141,31 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul | |||
153 | 141 | ||
154 | // items | 142 | // items |
155 | match p.current() { | 143 | match p.current() { |
156 | // test async_fn | 144 | // test fn |
157 | // async fn foo() {} | 145 | // fn foo() {} |
158 | |||
159 | // test extern_fn | ||
160 | // extern fn foo() {} | ||
161 | |||
162 | // test const_fn | ||
163 | // const fn foo() {} | ||
164 | |||
165 | // test const_unsafe_fn | ||
166 | // const unsafe fn foo() {} | ||
167 | |||
168 | // test unsafe_extern_fn | ||
169 | // unsafe extern "C" fn foo() {} | ||
170 | |||
171 | // test unsafe_fn | ||
172 | // unsafe fn foo() {} | ||
173 | |||
174 | // test combined_fns | ||
175 | // async unsafe fn foo() {} | ||
176 | // const unsafe fn bar() {} | ||
177 | |||
178 | // test_err wrong_order_fns | ||
179 | // unsafe async fn foo() {} | ||
180 | // unsafe const fn bar() {} | ||
181 | T![fn] => { | 146 | T![fn] => { |
182 | fn_def(p); | 147 | fn_def(p); |
183 | m.complete(p, FN); | 148 | m.complete(p, FN); |
184 | } | 149 | } |
185 | 150 | ||
186 | // test unsafe_trait | 151 | // test trait |
187 | // unsafe trait T {} | 152 | // trait T {} |
188 | |||
189 | // test auto_trait | ||
190 | // auto trait T {} | ||
191 | |||
192 | // test unsafe_auto_trait | ||
193 | // unsafe auto trait T {} | ||
194 | T![trait] => { | 153 | T![trait] => { |
195 | traits::trait_def(p); | 154 | traits::trait_def(p); |
196 | m.complete(p, TRAIT); | 155 | m.complete(p, TRAIT); |
197 | } | 156 | } |
198 | 157 | ||
199 | // test unsafe_impl | ||
200 | // unsafe impl Foo {} | ||
201 | |||
202 | // test default_impl | ||
203 | // default impl Foo {} | ||
204 | |||
205 | // test_err default_fn_type | ||
206 | // trait T { | ||
207 | // default type T = Bar; | ||
208 | // default fn foo() {} | ||
209 | // } | ||
210 | |||
211 | // test default_fn_type | ||
212 | // impl T for Foo { | ||
213 | // default type T = Bar; | ||
214 | // default fn foo() {} | ||
215 | // } | ||
216 | T![const] => { | 158 | T![const] => { |
217 | consts::const_def(p, m); | 159 | consts::const_def(p, m); |
218 | } | 160 | } |
219 | 161 | ||
220 | // test unsafe_default_impl | 162 | // test impl |
221 | // unsafe default impl Foo {} | 163 | // impl T for S {} |
222 | T![impl] => { | 164 | T![impl] => { |
223 | traits::impl_def(p); | 165 | traits::impl_def(p); |
224 | m.complete(p, IMPL); | 166 | m.complete(p, IMPL); |
225 | } | 167 | } |
226 | 168 | ||
227 | // test existential_type | ||
228 | // existential type Foo: Fn() -> usize; | ||
229 | T![type] => { | 169 | T![type] => { |
230 | type_def(p, m); | 170 | type_def(p, m); |
231 | } | 171 | } |
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs index ef9c8ff5b..751ce65f2 100644 --- a/crates/ra_parser/src/grammar/items/traits.rs +++ b/crates/ra_parser/src/grammar/items/traits.rs | |||
@@ -47,7 +47,7 @@ pub(crate) fn trait_item_list(p: &mut Parser) { | |||
47 | error_block(p, "expected an item"); | 47 | error_block(p, "expected an item"); |
48 | continue; | 48 | continue; |
49 | } | 49 | } |
50 | item_or_macro(p, true, ItemFlavor::Trait); | 50 | item_or_macro(p, true); |
51 | } | 51 | } |
52 | p.expect(T!['}']); | 52 | p.expect(T!['}']); |
53 | m.complete(p, ASSOC_ITEM_LIST); | 53 | m.complete(p, ASSOC_ITEM_LIST); |
@@ -104,7 +104,7 @@ pub(crate) fn impl_item_list(p: &mut Parser) { | |||
104 | error_block(p, "expected an item"); | 104 | error_block(p, "expected an item"); |
105 | continue; | 105 | continue; |
106 | } | 106 | } |
107 | item_or_macro(p, true, ItemFlavor::Mod); | 107 | item_or_macro(p, true); |
108 | } | 108 | } |
109 | p.expect(T!['}']); | 109 | p.expect(T!['}']); |
110 | m.complete(p, ASSOC_ITEM_LIST); | 110 | m.complete(p, ASSOC_ITEM_LIST); |
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index e9a20fbf1..0aa173a52 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs | |||
@@ -117,7 +117,7 @@ fn pointer_type(p: &mut Parser) { | |||
117 | }; | 117 | }; |
118 | 118 | ||
119 | type_no_bounds(p); | 119 | type_no_bounds(p); |
120 | m.complete(p, POINTER_TYPE); | 120 | m.complete(p, PTR_TYPE); |
121 | } | 121 | } |
122 | 122 | ||
123 | fn array_or_slice_type(p: &mut Parser) { | 123 | fn array_or_slice_type(p: &mut Parser) { |
@@ -163,7 +163,7 @@ fn reference_type(p: &mut Parser) { | |||
163 | p.eat(LIFETIME); | 163 | p.eat(LIFETIME); |
164 | p.eat(T![mut]); | 164 | p.eat(T![mut]); |
165 | type_no_bounds(p); | 165 | type_no_bounds(p); |
166 | m.complete(p, REFERENCE_TYPE); | 166 | m.complete(p, REF_TYPE); |
167 | } | 167 | } |
168 | 168 | ||
169 | // test placeholder_type | 169 | // test placeholder_type |
@@ -201,7 +201,7 @@ fn fn_pointer_type(p: &mut Parser) { | |||
201 | // test fn_pointer_type_with_ret | 201 | // test fn_pointer_type_with_ret |
202 | // type F = fn() -> (); | 202 | // type F = fn() -> (); |
203 | opt_fn_ret_type(p); | 203 | opt_fn_ret_type(p); |
204 | m.complete(p, FN_POINTER_TYPE); | 204 | m.complete(p, FN_PTR_TYPE); |
205 | } | 205 | } |
206 | 206 | ||
207 | pub(super) fn for_binder(p: &mut Parser) { | 207 | pub(super) fn for_binder(p: &mut Parser) { |
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs index d797f2cc9..d2487acc3 100644 --- a/crates/ra_parser/src/parser.rs +++ b/crates/ra_parser/src/parser.rs | |||
@@ -269,8 +269,8 @@ impl Marker { | |||
269 | pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { | 269 | pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { |
270 | self.bomb.defuse(); | 270 | self.bomb.defuse(); |
271 | let idx = self.pos as usize; | 271 | let idx = self.pos as usize; |
272 | match p.events[idx] { | 272 | match &mut p.events[idx] { |
273 | Event::Start { kind: ref mut slot, .. } => { | 273 | Event::Start { kind: slot, .. } => { |
274 | *slot = kind; | 274 | *slot = kind; |
275 | } | 275 | } |
276 | _ => unreachable!(), | 276 | _ => unreachable!(), |
@@ -320,8 +320,8 @@ impl CompletedMarker { | |||
320 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { | 320 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { |
321 | let new_pos = p.start(); | 321 | let new_pos = p.start(); |
322 | let idx = self.start_pos as usize; | 322 | let idx = self.start_pos as usize; |
323 | match p.events[idx] { | 323 | match &mut p.events[idx] { |
324 | Event::Start { ref mut forward_parent, .. } => { | 324 | Event::Start { forward_parent, .. } => { |
325 | *forward_parent = Some(new_pos.pos - self.start_pos); | 325 | *forward_parent = Some(new_pos.pos - self.start_pos); |
326 | } | 326 | } |
327 | _ => unreachable!(), | 327 | _ => unreachable!(), |
@@ -333,12 +333,12 @@ impl CompletedMarker { | |||
333 | pub(crate) fn undo_completion(self, p: &mut Parser) -> Marker { | 333 | pub(crate) fn undo_completion(self, p: &mut Parser) -> Marker { |
334 | let start_idx = self.start_pos as usize; | 334 | let start_idx = self.start_pos as usize; |
335 | let finish_idx = self.finish_pos as usize; | 335 | let finish_idx = self.finish_pos as usize; |
336 | match p.events[start_idx] { | 336 | match &mut p.events[start_idx] { |
337 | Event::Start { ref mut kind, forward_parent: None } => *kind = TOMBSTONE, | 337 | Event::Start { kind, forward_parent: None } => *kind = TOMBSTONE, |
338 | _ => unreachable!(), | 338 | _ => unreachable!(), |
339 | } | 339 | } |
340 | match p.events[finish_idx] { | 340 | match &mut p.events[finish_idx] { |
341 | ref mut slot @ Event::Finish => *slot = Event::tombstone(), | 341 | slot @ Event::Finish => *slot = Event::tombstone(), |
342 | _ => unreachable!(), | 342 | _ => unreachable!(), |
343 | } | 343 | } |
344 | Marker::new(self.start_pos) | 344 | Marker::new(self.start_pos) |
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index b18653aa5..192ecd864 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs | |||
@@ -143,12 +143,12 @@ pub enum SyntaxKind { | |||
143 | TUPLE_TYPE, | 143 | TUPLE_TYPE, |
144 | NEVER_TYPE, | 144 | NEVER_TYPE, |
145 | PATH_TYPE, | 145 | PATH_TYPE, |
146 | POINTER_TYPE, | 146 | PTR_TYPE, |
147 | ARRAY_TYPE, | 147 | ARRAY_TYPE, |
148 | SLICE_TYPE, | 148 | SLICE_TYPE, |
149 | REFERENCE_TYPE, | 149 | REF_TYPE, |
150 | INFER_TYPE, | 150 | INFER_TYPE, |
151 | FN_POINTER_TYPE, | 151 | FN_PTR_TYPE, |
152 | FOR_TYPE, | 152 | FOR_TYPE, |
153 | IMPL_TRAIT_TYPE, | 153 | IMPL_TRAIT_TYPE, |
154 | DYN_TRAIT_TYPE, | 154 | DYN_TRAIT_TYPE, |
diff --git a/crates/ra_proc_macro/src/process.rs b/crates/ra_proc_macro/src/process.rs index 5bcdacb48..37dd3f496 100644 --- a/crates/ra_proc_macro/src/process.rs +++ b/crates/ra_proc_macro/src/process.rs | |||
@@ -90,7 +90,7 @@ impl ProcMacroProcessSrv { | |||
90 | } | 90 | } |
91 | Some(it) => it, | 91 | Some(it) => it, |
92 | }; | 92 | }; |
93 | sender.send(Task { req: req.into(), result_tx }).unwrap(); | 93 | sender.send(Task { req, result_tx }).unwrap(); |
94 | let res = result_rx | 94 | let res = result_rx |
95 | .recv() | 95 | .recv() |
96 | .map_err(|_| ra_tt::ExpansionError::Unknown("Proc macro thread is closed.".into()))?; | 96 | .map_err(|_| ra_tt::ExpansionError::Unknown("Proc macro thread is closed.".into()))?; |
diff --git a/crates/ra_prof/src/memory_usage.rs b/crates/ra_prof/src/memory_usage.rs index c2ecbd33c..83390212a 100644 --- a/crates/ra_prof/src/memory_usage.rs +++ b/crates/ra_prof/src/memory_usage.rs | |||
@@ -24,7 +24,7 @@ impl std::ops::Sub for MemoryUsage { | |||
24 | impl MemoryUsage { | 24 | impl MemoryUsage { |
25 | pub fn current() -> MemoryUsage { | 25 | pub fn current() -> MemoryUsage { |
26 | cfg_if! { | 26 | cfg_if! { |
27 | if #[cfg(target_os = "linux")] { | 27 | if #[cfg(all(target_os = "linux", target_env = "gnu"))] { |
28 | // Note: This is incredibly slow. | 28 | // Note: This is incredibly slow. |
29 | let alloc = unsafe { libc::mallinfo() }.uordblks as isize; | 29 | let alloc = unsafe { libc::mallinfo() }.uordblks as isize; |
30 | MemoryUsage { allocated: Bytes(alloc) } | 30 | MemoryUsage { allocated: Bytes(alloc) } |
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ra_ssr/src/lib.rs index 73abfecb2..c780b460a 100644 --- a/crates/ra_ssr/src/lib.rs +++ b/crates/ra_ssr/src/lib.rs | |||
@@ -66,12 +66,7 @@ impl<'db> MatchFinder<'db> { | |||
66 | restrict_ranges.retain(|range| !range.range.is_empty()); | 66 | restrict_ranges.retain(|range| !range.range.is_empty()); |
67 | let sema = Semantics::new(db); | 67 | let sema = Semantics::new(db); |
68 | let resolution_scope = resolving::ResolutionScope::new(&sema, lookup_context); | 68 | let resolution_scope = resolving::ResolutionScope::new(&sema, lookup_context); |
69 | MatchFinder { | 69 | MatchFinder { sema, rules: Vec::new(), resolution_scope, restrict_ranges } |
70 | sema: Semantics::new(db), | ||
71 | rules: Vec::new(), | ||
72 | resolution_scope, | ||
73 | restrict_ranges, | ||
74 | } | ||
75 | } | 70 | } |
76 | 71 | ||
77 | /// Constructs an instance using the start of the first file in `db` as the lookup context. | 72 | /// Constructs an instance using the start of the first file in `db` as the lookup context. |
diff --git a/crates/ra_ssr/src/resolving.rs b/crates/ra_ssr/src/resolving.rs index d5b65eaac..d53bd46c7 100644 --- a/crates/ra_ssr/src/resolving.rs +++ b/crates/ra_ssr/src/resolving.rs | |||
@@ -11,6 +11,7 @@ use test_utils::mark; | |||
11 | pub(crate) struct ResolutionScope<'db> { | 11 | pub(crate) struct ResolutionScope<'db> { |
12 | scope: hir::SemanticsScope<'db>, | 12 | scope: hir::SemanticsScope<'db>, |
13 | hygiene: hir::Hygiene, | 13 | hygiene: hir::Hygiene, |
14 | node: SyntaxNode, | ||
14 | } | 15 | } |
15 | 16 | ||
16 | pub(crate) struct ResolvedRule { | 17 | pub(crate) struct ResolvedRule { |
@@ -25,6 +26,7 @@ pub(crate) struct ResolvedPattern { | |||
25 | // Paths in `node` that we've resolved. | 26 | // Paths in `node` that we've resolved. |
26 | pub(crate) resolved_paths: FxHashMap<SyntaxNode, ResolvedPath>, | 27 | pub(crate) resolved_paths: FxHashMap<SyntaxNode, ResolvedPath>, |
27 | pub(crate) ufcs_function_calls: FxHashMap<SyntaxNode, hir::Function>, | 28 | pub(crate) ufcs_function_calls: FxHashMap<SyntaxNode, hir::Function>, |
29 | pub(crate) contains_self: bool, | ||
28 | } | 30 | } |
29 | 31 | ||
30 | pub(crate) struct ResolvedPath { | 32 | pub(crate) struct ResolvedPath { |
@@ -68,6 +70,7 @@ struct Resolver<'a, 'db> { | |||
68 | 70 | ||
69 | impl Resolver<'_, '_> { | 71 | impl Resolver<'_, '_> { |
70 | fn resolve_pattern_tree(&self, pattern: SyntaxNode) -> Result<ResolvedPattern, SsrError> { | 72 | fn resolve_pattern_tree(&self, pattern: SyntaxNode) -> Result<ResolvedPattern, SsrError> { |
73 | use ra_syntax::{SyntaxElement, T}; | ||
71 | let mut resolved_paths = FxHashMap::default(); | 74 | let mut resolved_paths = FxHashMap::default(); |
72 | self.resolve(pattern.clone(), 0, &mut resolved_paths)?; | 75 | self.resolve(pattern.clone(), 0, &mut resolved_paths)?; |
73 | let ufcs_function_calls = resolved_paths | 76 | let ufcs_function_calls = resolved_paths |
@@ -85,11 +88,17 @@ impl Resolver<'_, '_> { | |||
85 | None | 88 | None |
86 | }) | 89 | }) |
87 | .collect(); | 90 | .collect(); |
91 | let contains_self = | ||
92 | pattern.descendants_with_tokens().any(|node_or_token| match node_or_token { | ||
93 | SyntaxElement::Token(t) => t.kind() == T![self], | ||
94 | _ => false, | ||
95 | }); | ||
88 | Ok(ResolvedPattern { | 96 | Ok(ResolvedPattern { |
89 | node: pattern, | 97 | node: pattern, |
90 | resolved_paths, | 98 | resolved_paths, |
91 | placeholders_by_stand_in: self.placeholders_by_stand_in.clone(), | 99 | placeholders_by_stand_in: self.placeholders_by_stand_in.clone(), |
92 | ufcs_function_calls, | 100 | ufcs_function_calls, |
101 | contains_self, | ||
93 | }) | 102 | }) |
94 | } | 103 | } |
95 | 104 | ||
@@ -101,6 +110,10 @@ impl Resolver<'_, '_> { | |||
101 | ) -> Result<(), SsrError> { | 110 | ) -> Result<(), SsrError> { |
102 | use ra_syntax::ast::AstNode; | 111 | use ra_syntax::ast::AstNode; |
103 | if let Some(path) = ast::Path::cast(node.clone()) { | 112 | if let Some(path) = ast::Path::cast(node.clone()) { |
113 | if is_self(&path) { | ||
114 | // Self cannot be resolved like other paths. | ||
115 | return Ok(()); | ||
116 | } | ||
104 | // Check if this is an appropriate place in the path to resolve. If the path is | 117 | // Check if this is an appropriate place in the path to resolve. If the path is |
105 | // something like `a::B::<i32>::c` then we want to resolve `a::B`. If the path contains | 118 | // something like `a::B::<i32>::c` then we want to resolve `a::B`. If the path contains |
106 | // a placeholder. e.g. `a::$b::c` then we want to resolve `a`. | 119 | // a placeholder. e.g. `a::$b::c` then we want to resolve `a`. |
@@ -180,9 +193,15 @@ impl<'db> ResolutionScope<'db> { | |||
180 | ResolutionScope { | 193 | ResolutionScope { |
181 | scope, | 194 | scope, |
182 | hygiene: hir::Hygiene::new(sema.db, resolve_context.file_id.into()), | 195 | hygiene: hir::Hygiene::new(sema.db, resolve_context.file_id.into()), |
196 | node, | ||
183 | } | 197 | } |
184 | } | 198 | } |
185 | 199 | ||
200 | /// Returns the function in which SSR was invoked, if any. | ||
201 | pub(crate) fn current_function(&self) -> Option<SyntaxNode> { | ||
202 | self.node.ancestors().find(|node| node.kind() == SyntaxKind::FN).map(|node| node.clone()) | ||
203 | } | ||
204 | |||
186 | fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> { | 205 | fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> { |
187 | let hir_path = hir::Path::from_src(path.clone(), &self.hygiene)?; | 206 | let hir_path = hir::Path::from_src(path.clone(), &self.hygiene)?; |
188 | // First try resolving the whole path. This will work for things like | 207 | // First try resolving the whole path. This will work for things like |
@@ -209,6 +228,10 @@ impl<'db> ResolutionScope<'db> { | |||
209 | } | 228 | } |
210 | } | 229 | } |
211 | 230 | ||
231 | fn is_self(path: &ast::Path) -> bool { | ||
232 | path.segment().map(|segment| segment.self_token().is_some()).unwrap_or(false) | ||
233 | } | ||
234 | |||
212 | /// Returns a suitable node for resolving paths in the current scope. If we create a scope based on | 235 | /// Returns a suitable node for resolving paths in the current scope. If we create a scope based on |
213 | /// a statement node, then we can't resolve local variables that were defined in the current scope | 236 | /// a statement node, then we can't resolve local variables that were defined in the current scope |
214 | /// (only in parent scopes). So we find another node, ideally a child of the statement where local | 237 | /// (only in parent scopes). So we find another node, ideally a child of the statement where local |
diff --git a/crates/ra_ssr/src/search.rs b/crates/ra_ssr/src/search.rs index 213dc494f..85ffa2ac2 100644 --- a/crates/ra_ssr/src/search.rs +++ b/crates/ra_ssr/src/search.rs | |||
@@ -33,6 +33,15 @@ impl<'db> MatchFinder<'db> { | |||
33 | usage_cache: &mut UsageCache, | 33 | usage_cache: &mut UsageCache, |
34 | matches_out: &mut Vec<Match>, | 34 | matches_out: &mut Vec<Match>, |
35 | ) { | 35 | ) { |
36 | if rule.pattern.contains_self { | ||
37 | // If the pattern contains `self` we restrict the scope of the search to just the | ||
38 | // current method. No other method can reference the same `self`. This makes the | ||
39 | // behavior of `self` consistent with other variables. | ||
40 | if let Some(current_function) = self.resolution_scope.current_function() { | ||
41 | self.slow_scan_node(¤t_function, rule, &None, matches_out); | ||
42 | } | ||
43 | return; | ||
44 | } | ||
36 | if pick_path_for_usages(&rule.pattern).is_none() { | 45 | if pick_path_for_usages(&rule.pattern).is_none() { |
37 | self.slow_scan(rule, matches_out); | 46 | self.slow_scan(rule, matches_out); |
38 | return; | 47 | return; |
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs index 0a49a46e3..7d4d470c0 100644 --- a/crates/ra_ssr/src/tests.rs +++ b/crates/ra_ssr/src/tests.rs | |||
@@ -1108,3 +1108,38 @@ fn replace_nonpath_within_selection() { | |||
1108 | }"#]], | 1108 | }"#]], |
1109 | ); | 1109 | ); |
1110 | } | 1110 | } |
1111 | |||
1112 | #[test] | ||
1113 | fn replace_self() { | ||
1114 | // `foo(self)` occurs twice in the code, however only the first occurrence is the `self` that's | ||
1115 | // in scope where the rule is invoked. | ||
1116 | assert_ssr_transform( | ||
1117 | "foo(self) ==>> bar(self)", | ||
1118 | r#" | ||
1119 | struct S1 {} | ||
1120 | fn foo(_: &S1) {} | ||
1121 | fn bar(_: &S1) {} | ||
1122 | impl S1 { | ||
1123 | fn f1(&self) { | ||
1124 | foo(self)<|> | ||
1125 | } | ||
1126 | fn f2(&self) { | ||
1127 | foo(self) | ||
1128 | } | ||
1129 | } | ||
1130 | "#, | ||
1131 | expect![[r#" | ||
1132 | struct S1 {} | ||
1133 | fn foo(_: &S1) {} | ||
1134 | fn bar(_: &S1) {} | ||
1135 | impl S1 { | ||
1136 | fn f1(&self) { | ||
1137 | bar(self) | ||
1138 | } | ||
1139 | fn f2(&self) { | ||
1140 | foo(self) | ||
1141 | } | ||
1142 | } | ||
1143 | "#]], | ||
1144 | ); | ||
1145 | } | ||
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 667a9294f..5ed123f91 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -621,7 +621,7 @@ fn single_node(element: impl Into<SyntaxElement>) -> RangeInclusive<SyntaxElemen | |||
621 | #[test] | 621 | #[test] |
622 | fn test_increase_indent() { | 622 | fn test_increase_indent() { |
623 | let arm_list = { | 623 | let arm_list = { |
624 | let arm = make::match_arm(iter::once(make::placeholder_pat().into()), make::expr_unit()); | 624 | let arm = make::match_arm(iter::once(make::wildcard_pat().into()), make::expr_unit()); |
625 | make::match_arm_list(vec![arm.clone(), arm]) | 625 | make::match_arm_list(vec![arm.clone(), arm]) |
626 | }; | 626 | }; |
627 | assert_eq!( | 627 | assert_eq!( |
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 5f51c7536..3d49309d1 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs | |||
@@ -1006,10 +1006,10 @@ impl DynTraitType { | |||
1006 | pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) } | 1006 | pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) } |
1007 | } | 1007 | } |
1008 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1008 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1009 | pub struct FnPointerType { | 1009 | pub struct FnPtrType { |
1010 | pub(crate) syntax: SyntaxNode, | 1010 | pub(crate) syntax: SyntaxNode, |
1011 | } | 1011 | } |
1012 | impl FnPointerType { | 1012 | impl FnPtrType { |
1013 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | 1013 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } |
1014 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } | 1014 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } |
1015 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | 1015 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } |
@@ -1059,20 +1059,20 @@ impl ParenType { | |||
1059 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | 1059 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } |
1060 | } | 1060 | } |
1061 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1061 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1062 | pub struct PointerType { | 1062 | pub struct PtrType { |
1063 | pub(crate) syntax: SyntaxNode, | 1063 | pub(crate) syntax: SyntaxNode, |
1064 | } | 1064 | } |
1065 | impl PointerType { | 1065 | impl PtrType { |
1066 | pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } | 1066 | pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } |
1067 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | 1067 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } |
1068 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | 1068 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } |
1069 | pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } | 1069 | pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } |
1070 | } | 1070 | } |
1071 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1071 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1072 | pub struct ReferenceType { | 1072 | pub struct RefType { |
1073 | pub(crate) syntax: SyntaxNode, | 1073 | pub(crate) syntax: SyntaxNode, |
1074 | } | 1074 | } |
1075 | impl ReferenceType { | 1075 | impl RefType { |
1076 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | 1076 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } |
1077 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | 1077 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { |
1078 | support::token(&self.syntax, T![lifetime]) | 1078 | support::token(&self.syntax, T![lifetime]) |
@@ -1263,15 +1263,15 @@ pub enum GenericArg { | |||
1263 | pub enum Type { | 1263 | pub enum Type { |
1264 | ArrayType(ArrayType), | 1264 | ArrayType(ArrayType), |
1265 | DynTraitType(DynTraitType), | 1265 | DynTraitType(DynTraitType), |
1266 | FnPointerType(FnPointerType), | 1266 | FnPtrType(FnPtrType), |
1267 | ForType(ForType), | 1267 | ForType(ForType), |
1268 | ImplTraitType(ImplTraitType), | 1268 | ImplTraitType(ImplTraitType), |
1269 | InferType(InferType), | 1269 | InferType(InferType), |
1270 | NeverType(NeverType), | 1270 | NeverType(NeverType), |
1271 | ParenType(ParenType), | 1271 | ParenType(ParenType), |
1272 | PathType(PathType), | 1272 | PathType(PathType), |
1273 | PointerType(PointerType), | 1273 | PtrType(PtrType), |
1274 | ReferenceType(ReferenceType), | 1274 | RefType(RefType), |
1275 | SliceType(SliceType), | 1275 | SliceType(SliceType), |
1276 | TupleType(TupleType), | 1276 | TupleType(TupleType), |
1277 | } | 1277 | } |
@@ -1377,8 +1377,8 @@ impl ast::NameOwner for AssocItem {} | |||
1377 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1377 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1378 | pub enum ExternItem { | 1378 | pub enum ExternItem { |
1379 | Fn(Fn), | 1379 | Fn(Fn), |
1380 | Static(Static), | ||
1381 | MacroCall(MacroCall), | 1380 | MacroCall(MacroCall), |
1381 | Static(Static), | ||
1382 | } | 1382 | } |
1383 | impl ast::AttrsOwner for ExternItem {} | 1383 | impl ast::AttrsOwner for ExternItem {} |
1384 | impl ast::NameOwner for ExternItem {} | 1384 | impl ast::NameOwner for ExternItem {} |
@@ -2434,8 +2434,8 @@ impl AstNode for DynTraitType { | |||
2434 | } | 2434 | } |
2435 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2435 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2436 | } | 2436 | } |
2437 | impl AstNode for FnPointerType { | 2437 | impl AstNode for FnPtrType { |
2438 | fn can_cast(kind: SyntaxKind) -> bool { kind == FN_POINTER_TYPE } | 2438 | fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE } |
2439 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2439 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
2440 | if Self::can_cast(syntax.kind()) { | 2440 | if Self::can_cast(syntax.kind()) { |
2441 | Some(Self { syntax }) | 2441 | Some(Self { syntax }) |
@@ -2500,8 +2500,8 @@ impl AstNode for ParenType { | |||
2500 | } | 2500 | } |
2501 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2501 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2502 | } | 2502 | } |
2503 | impl AstNode for PointerType { | 2503 | impl AstNode for PtrType { |
2504 | fn can_cast(kind: SyntaxKind) -> bool { kind == POINTER_TYPE } | 2504 | fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE } |
2505 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2505 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
2506 | if Self::can_cast(syntax.kind()) { | 2506 | if Self::can_cast(syntax.kind()) { |
2507 | Some(Self { syntax }) | 2507 | Some(Self { syntax }) |
@@ -2511,8 +2511,8 @@ impl AstNode for PointerType { | |||
2511 | } | 2511 | } |
2512 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2512 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2513 | } | 2513 | } |
2514 | impl AstNode for ReferenceType { | 2514 | impl AstNode for RefType { |
2515 | fn can_cast(kind: SyntaxKind) -> bool { kind == REFERENCE_TYPE } | 2515 | fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE } |
2516 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2516 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
2517 | if Self::can_cast(syntax.kind()) { | 2517 | if Self::can_cast(syntax.kind()) { |
2518 | Some(Self { syntax }) | 2518 | Some(Self { syntax }) |
@@ -2786,8 +2786,8 @@ impl From<ArrayType> for Type { | |||
2786 | impl From<DynTraitType> for Type { | 2786 | impl From<DynTraitType> for Type { |
2787 | fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) } | 2787 | fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) } |
2788 | } | 2788 | } |
2789 | impl From<FnPointerType> for Type { | 2789 | impl From<FnPtrType> for Type { |
2790 | fn from(node: FnPointerType) -> Type { Type::FnPointerType(node) } | 2790 | fn from(node: FnPtrType) -> Type { Type::FnPtrType(node) } |
2791 | } | 2791 | } |
2792 | impl From<ForType> for Type { | 2792 | impl From<ForType> for Type { |
2793 | fn from(node: ForType) -> Type { Type::ForType(node) } | 2793 | fn from(node: ForType) -> Type { Type::ForType(node) } |
@@ -2807,11 +2807,11 @@ impl From<ParenType> for Type { | |||
2807 | impl From<PathType> for Type { | 2807 | impl From<PathType> for Type { |
2808 | fn from(node: PathType) -> Type { Type::PathType(node) } | 2808 | fn from(node: PathType) -> Type { Type::PathType(node) } |
2809 | } | 2809 | } |
2810 | impl From<PointerType> for Type { | 2810 | impl From<PtrType> for Type { |
2811 | fn from(node: PointerType) -> Type { Type::PointerType(node) } | 2811 | fn from(node: PtrType) -> Type { Type::PtrType(node) } |
2812 | } | 2812 | } |
2813 | impl From<ReferenceType> for Type { | 2813 | impl From<RefType> for Type { |
2814 | fn from(node: ReferenceType) -> Type { Type::ReferenceType(node) } | 2814 | fn from(node: RefType) -> Type { Type::RefType(node) } |
2815 | } | 2815 | } |
2816 | impl From<SliceType> for Type { | 2816 | impl From<SliceType> for Type { |
2817 | fn from(node: SliceType) -> Type { Type::SliceType(node) } | 2817 | fn from(node: SliceType) -> Type { Type::SliceType(node) } |
@@ -2822,9 +2822,9 @@ impl From<TupleType> for Type { | |||
2822 | impl AstNode for Type { | 2822 | impl AstNode for Type { |
2823 | fn can_cast(kind: SyntaxKind) -> bool { | 2823 | fn can_cast(kind: SyntaxKind) -> bool { |
2824 | match kind { | 2824 | match kind { |
2825 | ARRAY_TYPE | DYN_TRAIT_TYPE | FN_POINTER_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | 2825 | ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE |
2826 | | INFER_TYPE | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | POINTER_TYPE | REFERENCE_TYPE | 2826 | | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE | SLICE_TYPE |
2827 | | SLICE_TYPE | TUPLE_TYPE => true, | 2827 | | TUPLE_TYPE => true, |
2828 | _ => false, | 2828 | _ => false, |
2829 | } | 2829 | } |
2830 | } | 2830 | } |
@@ -2832,15 +2832,15 @@ impl AstNode for Type { | |||
2832 | let res = match syntax.kind() { | 2832 | let res = match syntax.kind() { |
2833 | ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }), | 2833 | ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }), |
2834 | DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }), | 2834 | DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }), |
2835 | FN_POINTER_TYPE => Type::FnPointerType(FnPointerType { syntax }), | 2835 | FN_PTR_TYPE => Type::FnPtrType(FnPtrType { syntax }), |
2836 | FOR_TYPE => Type::ForType(ForType { syntax }), | 2836 | FOR_TYPE => Type::ForType(ForType { syntax }), |
2837 | IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }), | 2837 | IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }), |
2838 | INFER_TYPE => Type::InferType(InferType { syntax }), | 2838 | INFER_TYPE => Type::InferType(InferType { syntax }), |
2839 | NEVER_TYPE => Type::NeverType(NeverType { syntax }), | 2839 | NEVER_TYPE => Type::NeverType(NeverType { syntax }), |
2840 | PAREN_TYPE => Type::ParenType(ParenType { syntax }), | 2840 | PAREN_TYPE => Type::ParenType(ParenType { syntax }), |
2841 | PATH_TYPE => Type::PathType(PathType { syntax }), | 2841 | PATH_TYPE => Type::PathType(PathType { syntax }), |
2842 | POINTER_TYPE => Type::PointerType(PointerType { syntax }), | 2842 | PTR_TYPE => Type::PtrType(PtrType { syntax }), |
2843 | REFERENCE_TYPE => Type::ReferenceType(ReferenceType { syntax }), | 2843 | REF_TYPE => Type::RefType(RefType { syntax }), |
2844 | SLICE_TYPE => Type::SliceType(SliceType { syntax }), | 2844 | SLICE_TYPE => Type::SliceType(SliceType { syntax }), |
2845 | TUPLE_TYPE => Type::TupleType(TupleType { syntax }), | 2845 | TUPLE_TYPE => Type::TupleType(TupleType { syntax }), |
2846 | _ => return None, | 2846 | _ => return None, |
@@ -2851,15 +2851,15 @@ impl AstNode for Type { | |||
2851 | match self { | 2851 | match self { |
2852 | Type::ArrayType(it) => &it.syntax, | 2852 | Type::ArrayType(it) => &it.syntax, |
2853 | Type::DynTraitType(it) => &it.syntax, | 2853 | Type::DynTraitType(it) => &it.syntax, |
2854 | Type::FnPointerType(it) => &it.syntax, | 2854 | Type::FnPtrType(it) => &it.syntax, |
2855 | Type::ForType(it) => &it.syntax, | 2855 | Type::ForType(it) => &it.syntax, |
2856 | Type::ImplTraitType(it) => &it.syntax, | 2856 | Type::ImplTraitType(it) => &it.syntax, |
2857 | Type::InferType(it) => &it.syntax, | 2857 | Type::InferType(it) => &it.syntax, |
2858 | Type::NeverType(it) => &it.syntax, | 2858 | Type::NeverType(it) => &it.syntax, |
2859 | Type::ParenType(it) => &it.syntax, | 2859 | Type::ParenType(it) => &it.syntax, |
2860 | Type::PathType(it) => &it.syntax, | 2860 | Type::PathType(it) => &it.syntax, |
2861 | Type::PointerType(it) => &it.syntax, | 2861 | Type::PtrType(it) => &it.syntax, |
2862 | Type::ReferenceType(it) => &it.syntax, | 2862 | Type::RefType(it) => &it.syntax, |
2863 | Type::SliceType(it) => &it.syntax, | 2863 | Type::SliceType(it) => &it.syntax, |
2864 | Type::TupleType(it) => &it.syntax, | 2864 | Type::TupleType(it) => &it.syntax, |
2865 | } | 2865 | } |
@@ -3332,24 +3332,24 @@ impl AstNode for AssocItem { | |||
3332 | impl From<Fn> for ExternItem { | 3332 | impl From<Fn> for ExternItem { |
3333 | fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) } | 3333 | fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) } |
3334 | } | 3334 | } |
3335 | impl From<Static> for ExternItem { | ||
3336 | fn from(node: Static) -> ExternItem { ExternItem::Static(node) } | ||
3337 | } | ||
3338 | impl From<MacroCall> for ExternItem { | 3335 | impl From<MacroCall> for ExternItem { |
3339 | fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) } | 3336 | fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) } |
3340 | } | 3337 | } |
3338 | impl From<Static> for ExternItem { | ||
3339 | fn from(node: Static) -> ExternItem { ExternItem::Static(node) } | ||
3340 | } | ||
3341 | impl AstNode for ExternItem { | 3341 | impl AstNode for ExternItem { |
3342 | fn can_cast(kind: SyntaxKind) -> bool { | 3342 | fn can_cast(kind: SyntaxKind) -> bool { |
3343 | match kind { | 3343 | match kind { |
3344 | FN | STATIC | MACRO_CALL => true, | 3344 | FN | MACRO_CALL | STATIC => true, |
3345 | _ => false, | 3345 | _ => false, |
3346 | } | 3346 | } |
3347 | } | 3347 | } |
3348 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 3348 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
3349 | let res = match syntax.kind() { | 3349 | let res = match syntax.kind() { |
3350 | FN => ExternItem::Fn(Fn { syntax }), | 3350 | FN => ExternItem::Fn(Fn { syntax }), |
3351 | STATIC => ExternItem::Static(Static { syntax }), | ||
3352 | MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }), | 3351 | MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }), |
3352 | STATIC => ExternItem::Static(Static { syntax }), | ||
3353 | _ => return None, | 3353 | _ => return None, |
3354 | }; | 3354 | }; |
3355 | Some(res) | 3355 | Some(res) |
@@ -3357,8 +3357,8 @@ impl AstNode for ExternItem { | |||
3357 | fn syntax(&self) -> &SyntaxNode { | 3357 | fn syntax(&self) -> &SyntaxNode { |
3358 | match self { | 3358 | match self { |
3359 | ExternItem::Fn(it) => &it.syntax, | 3359 | ExternItem::Fn(it) => &it.syntax, |
3360 | ExternItem::Static(it) => &it.syntax, | ||
3361 | ExternItem::MacroCall(it) => &it.syntax, | 3360 | ExternItem::MacroCall(it) => &it.syntax, |
3361 | ExternItem::Static(it) => &it.syntax, | ||
3362 | } | 3362 | } |
3363 | } | 3363 | } |
3364 | } | 3364 | } |
@@ -3925,7 +3925,7 @@ impl std::fmt::Display for DynTraitType { | |||
3925 | std::fmt::Display::fmt(self.syntax(), f) | 3925 | std::fmt::Display::fmt(self.syntax(), f) |
3926 | } | 3926 | } |
3927 | } | 3927 | } |
3928 | impl std::fmt::Display for FnPointerType { | 3928 | impl std::fmt::Display for FnPtrType { |
3929 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 3929 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
3930 | std::fmt::Display::fmt(self.syntax(), f) | 3930 | std::fmt::Display::fmt(self.syntax(), f) |
3931 | } | 3931 | } |
@@ -3955,12 +3955,12 @@ impl std::fmt::Display for ParenType { | |||
3955 | std::fmt::Display::fmt(self.syntax(), f) | 3955 | std::fmt::Display::fmt(self.syntax(), f) |
3956 | } | 3956 | } |
3957 | } | 3957 | } |
3958 | impl std::fmt::Display for PointerType { | 3958 | impl std::fmt::Display for PtrType { |
3959 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 3959 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
3960 | std::fmt::Display::fmt(self.syntax(), f) | 3960 | std::fmt::Display::fmt(self.syntax(), f) |
3961 | } | 3961 | } |
3962 | } | 3962 | } |
3963 | impl std::fmt::Display for ReferenceType { | 3963 | impl std::fmt::Display for RefType { |
3964 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 3964 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
3965 | std::fmt::Display::fmt(self.syntax(), f) | 3965 | std::fmt::Display::fmt(self.syntax(), f) |
3966 | } | 3966 | } |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 673777015..254a37fe3 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -17,7 +17,7 @@ pub fn name_ref(text: &str) -> ast::NameRef { | |||
17 | ast_from_text(&format!("fn f() {{ {}; }}", text)) | 17 | ast_from_text(&format!("fn f() {{ {}; }}", text)) |
18 | } | 18 | } |
19 | 19 | ||
20 | pub fn type_ref(text: &str) -> ast::Type { | 20 | pub fn ty(text: &str) -> ast::Type { |
21 | ast_from_text(&format!("impl {} for D {{}};", text)) | 21 | ast_from_text(&format!("impl {} for D {{}};", text)) |
22 | } | 22 | } |
23 | 23 | ||
@@ -30,7 +30,7 @@ pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path { | |||
30 | pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { | 30 | pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { |
31 | path_from_text(&format!("{}::{}", qual, segment)) | 31 | path_from_text(&format!("{}::{}", qual, segment)) |
32 | } | 32 | } |
33 | fn path_from_text(text: &str) -> ast::Path { | 33 | pub fn path_from_text(text: &str) -> ast::Path { |
34 | ast_from_text(text) | 34 | ast_from_text(text) |
35 | } | 35 | } |
36 | 36 | ||
@@ -60,11 +60,11 @@ pub fn use_tree_list(use_trees: impl IntoIterator<Item = ast::UseTree>) -> ast:: | |||
60 | ast_from_text(&format!("use {{{}}};", use_trees)) | 60 | ast_from_text(&format!("use {{{}}};", use_trees)) |
61 | } | 61 | } |
62 | 62 | ||
63 | pub fn use_item(use_tree: ast::UseTree) -> ast::Use { | 63 | pub fn use_(use_tree: ast::UseTree) -> ast::Use { |
64 | ast_from_text(&format!("use {};", use_tree)) | 64 | ast_from_text(&format!("use {};", use_tree)) |
65 | } | 65 | } |
66 | 66 | ||
67 | pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField { | 67 | pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField { |
68 | return match expr { | 68 | return match expr { |
69 | Some(expr) => from_text(&format!("{}: {}", name, expr)), | 69 | Some(expr) => from_text(&format!("{}: {}", name, expr)), |
70 | None => from_text(&name.to_string()), | 70 | None => from_text(&name.to_string()), |
@@ -75,7 +75,7 @@ pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordE | |||
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | pub fn record_field_def(name: ast::NameRef, ty: ast::Type) -> ast::RecordField { | 78 | pub fn record_field(name: ast::NameRef, ty: ast::Type) -> ast::RecordField { |
79 | ast_from_text(&format!("struct S {{ {}: {}, }}", name, ty)) | 79 | ast_from_text(&format!("struct S {{ {}: {}, }}", name, ty)) |
80 | } | 80 | } |
81 | 81 | ||
@@ -148,7 +148,7 @@ pub fn condition(expr: ast::Expr, pattern: Option<ast::Pat>) -> ast::Condition { | |||
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | pub fn bind_pat(name: ast::Name) -> ast::IdentPat { | 151 | pub fn ident_pat(name: ast::Name) -> ast::IdentPat { |
152 | return from_text(name.text()); | 152 | return from_text(name.text()); |
153 | 153 | ||
154 | fn from_text(text: &str) -> ast::IdentPat { | 154 | fn from_text(text: &str) -> ast::IdentPat { |
@@ -156,7 +156,7 @@ pub fn bind_pat(name: ast::Name) -> ast::IdentPat { | |||
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | pub fn placeholder_pat() -> ast::WildcardPat { | 159 | pub fn wildcard_pat() -> ast::WildcardPat { |
160 | return from_text("_"); | 160 | return from_text("_"); |
161 | 161 | ||
162 | fn from_text(text: &str) -> ast::WildcardPat { | 162 | fn from_text(text: &str) -> ast::WildcardPat { |
@@ -288,7 +288,7 @@ pub fn visibility_pub_crate() -> ast::Visibility { | |||
288 | ast_from_text("pub(crate) struct S") | 288 | ast_from_text("pub(crate) struct S") |
289 | } | 289 | } |
290 | 290 | ||
291 | pub fn fn_def( | 291 | pub fn fn_( |
292 | visibility: Option<ast::Visibility>, | 292 | visibility: Option<ast::Visibility>, |
293 | fn_name: ast::Name, | 293 | fn_name: ast::Name, |
294 | type_params: Option<ast::GenericParamList>, | 294 | type_params: Option<ast::GenericParamList>, |
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index 3a56b1674..0bdc22d95 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Various traits that are implemented by ast nodes. | 1 | //! Various traits that are implemented by ast nodes. |
2 | //! | 2 | //! |
3 | //! The implementations are usually trivial, and live in generated.rs | 3 | //! The implementations are usually trivial, and live in generated.rs |
4 | use stdx::SepBy; | 4 | use itertools::Itertools; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | ast::{self, support, AstChildren, AstNode, AstToken}, | 7 | ast::{self, support, AstChildren, AstNode, AstToken}, |
@@ -119,8 +119,7 @@ impl CommentIter { | |||
119 | // of a line in markdown. | 119 | // of a line in markdown. |
120 | line[pos..end].to_owned() | 120 | line[pos..end].to_owned() |
121 | }) | 121 | }) |
122 | .sep_by("\n") | 122 | .join("\n"); |
123 | .to_string(); | ||
124 | 123 | ||
125 | if has_comments { | 124 | if has_comments { |
126 | Some(docs) | 125 | Some(docs) |
diff --git a/crates/ra_syntax/test_data/parser/err/0012_broken_lambda.rast b/crates/ra_syntax/test_data/parser/err/0012_broken_lambda.rast index c131b79a7..f31c27633 100644 --- a/crates/ra_syntax/test_data/parser/err/0012_broken_lambda.rast +++ b/crates/ra_syntax/test_data/parser/err/0012_broken_lambda.rast | |||
@@ -39,7 +39,7 @@ [email protected] | |||
39 | [email protected] "builder" | 39 | [email protected] "builder" |
40 | [email protected] | 40 | [email protected] |
41 | [email protected] | 41 | [email protected] |
42 | REFERENCE[email protected] | 42 | [email protected] |
43 | [email protected] | 43 | [email protected] |
44 | [email protected] | 44 | [email protected] |
45 | [email protected] | 45 | [email protected] |
@@ -56,7 +56,7 @@ [email protected] | |||
56 | [email protected] "tokens" | 56 | [email protected] "tokens" |
57 | [email protected] | 57 | [email protected] |
58 | [email protected] | 58 | [email protected] |
59 | REFERENCE[email protected] | 59 | [email protected] |
60 | [email protected] | 60 | [email protected] |
61 | [email protected] | 61 | [email protected] |
62 | [email protected] | 62 | [email protected] |
@@ -126,7 +126,7 @@ [email protected] | |||
126 | [email protected] "idx" | 126 | [email protected] "idx" |
127 | [email protected] | 127 | [email protected] |
128 | [email protected] | 128 | [email protected] |
129 | REFERENCE[email protected] | 129 | [email protected] |
130 | [email protected] | 130 | [email protected] |
131 | [email protected] | 131 | [email protected] |
132 | [email protected] | 132 | [email protected] |
diff --git a/crates/ra_syntax/test_data/parser/err/0043_default_const.rast b/crates/ra_syntax/test_data/parser/err/0043_default_const.rast deleted file mode 100644 index 51ad2a846..000000000 --- a/crates/ra_syntax/test_data/parser/err/0043_default_const.rast +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "trait" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "T" | ||
7 | [email protected] " " | ||
8 | [email protected] | ||
9 | [email protected] "{" | ||
10 | [email protected] "\n " | ||
11 | [email protected] | ||
12 | [email protected] | ||
13 | [email protected] | ||
14 | [email protected] | ||
15 | [email protected] "default" | ||
16 | [email protected] " " | ||
17 | [email protected] | ||
18 | [email protected] "const" | ||
19 | [email protected] " " | ||
20 | [email protected] | ||
21 | [email protected] "f" | ||
22 | [email protected] ":" | ||
23 | [email protected] " " | ||
24 | [email protected] | ||
25 | [email protected] | ||
26 | [email protected] | ||
27 | [email protected] | ||
28 | [email protected] "u8" | ||
29 | [email protected] " " | ||
30 | [email protected] "=" | ||
31 | [email protected] " " | ||
32 | [email protected] | ||
33 | [email protected] "0" | ||
34 | [email protected] ";" | ||
35 | [email protected] "\n" | ||
36 | [email protected] "}" | ||
37 | [email protected] "\n" | ||
38 | error 19..19: expected BANG | ||
39 | error 19..19: expected `{`, `[`, `(` | ||
40 | error 19..19: expected SEMICOLON | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0043_default_const.rs b/crates/ra_syntax/test_data/parser/err/0043_default_const.rs deleted file mode 100644 index 80f15474a..000000000 --- a/crates/ra_syntax/test_data/parser/err/0043_default_const.rs +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | trait T { | ||
2 | default const f: u8 = 0; | ||
3 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rast b/crates/ra_syntax/test_data/parser/err/0043_weird_blocks.rast index df29017e7..df29017e7 100644 --- a/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rast +++ b/crates/ra_syntax/test_data/parser/err/0043_weird_blocks.rast | |||
diff --git a/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rs b/crates/ra_syntax/test_data/parser/err/0043_weird_blocks.rs index 8fa324c1a..8fa324c1a 100644 --- a/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rs +++ b/crates/ra_syntax/test_data/parser/err/0043_weird_blocks.rs | |||
diff --git a/crates/ra_syntax/test_data/parser/err/0044_unexpected_for_type.rast b/crates/ra_syntax/test_data/parser/err/0044_unexpected_for_type.rast index 082625c13..71aa86494 100644 --- a/crates/ra_syntax/test_data/parser/err/0044_unexpected_for_type.rast +++ b/crates/ra_syntax/test_data/parser/err/0044_unexpected_for_type.rast | |||
@@ -15,7 +15,7 @@ [email protected] | |||
15 | [email protected] "\'a" | 15 | [email protected] "\'a" |
16 | [email protected] ">" | 16 | [email protected] ">" |
17 | [email protected] " " | 17 | [email protected] " " |
18 | REFERENCE[email protected] | 18 | [email protected] |
19 | [email protected] "&" | 19 | [email protected] "&" |
20 | [email protected] "\'a" | 20 | [email protected] "\'a" |
21 | [email protected] " " | 21 | [email protected] " " |
@@ -44,7 +44,7 @@ [email protected] | |||
44 | [email protected] " " | 44 | [email protected] " " |
45 | [email protected] | 45 | [email protected] |
46 | [email protected] "(" | 46 | [email protected] "(" |
47 | REFERENCE[email protected] | 47 | [email protected] |
48 | [email protected] "&" | 48 | [email protected] "&" |
49 | [email protected] "\'a" | 49 | [email protected] "\'a" |
50 | [email protected] " " | 50 | [email protected] " " |
@@ -107,12 +107,12 @@ [email protected] | |||
107 | [email protected] "\'b" | 107 | [email protected] "\'b" |
108 | [email protected] ">" | 108 | [email protected] ">" |
109 | [email protected] " " | 109 | [email protected] " " |
110 | FN_POINTE[email protected] | 110 | [email protected] |
111 | [email protected] "fn" | 111 | [email protected] "fn" |
112 | [email protected] | 112 | [email protected] |
113 | [email protected] "(" | 113 | [email protected] "(" |
114 | [email protected] | 114 | [email protected] |
115 | REFERENCE[email protected] | 115 | [email protected] |
116 | [email protected] "&" | 116 | [email protected] "&" |
117 | [email protected] "\'a" | 117 | [email protected] "\'a" |
118 | [email protected] " " | 118 | [email protected] " " |
@@ -124,7 +124,7 @@ [email protected] | |||
124 | [email protected] "," | 124 | [email protected] "," |
125 | [email protected] " " | 125 | [email protected] " " |
126 | [email protected] | 126 | [email protected] |
127 | REFERENCE[email protected] | 127 | [email protected] |
128 | [email protected] "&" | 128 | [email protected] "&" |
129 | [email protected] "\'b" | 129 | [email protected] "\'b" |
130 | [email protected] " " | 130 | [email protected] " " |
@@ -178,12 +178,12 @@ [email protected] | |||
178 | [email protected] "\'c" | 178 | [email protected] "\'c" |
179 | [email protected] ">" | 179 | [email protected] ">" |
180 | [email protected] " " | 180 | [email protected] " " |
181 | FN_POINTE[email protected] | 181 | [email protected] |
182 | [email protected] "fn" | 182 | [email protected] "fn" |
183 | [email protected] | 183 | [email protected] |
184 | [email protected] "(" | 184 | [email protected] "(" |
185 | [email protected] | 185 | [email protected] |
186 | REFERENCE[email protected] | 186 | [email protected] |
187 | [email protected] "&" | 187 | [email protected] "&" |
188 | [email protected] "\'a" | 188 | [email protected] "\'a" |
189 | [email protected] " " | 189 | [email protected] " " |
@@ -195,7 +195,7 @@ [email protected] | |||
195 | [email protected] "," | 195 | [email protected] "," |
196 | [email protected] " " | 196 | [email protected] " " |
197 | [email protected] | 197 | [email protected] |
198 | REFERENCE[email protected] | 198 | [email protected] |
199 | [email protected] "&" | 199 | [email protected] "&" |
200 | [email protected] "\'b" | 200 | [email protected] "\'b" |
201 | [email protected] " " | 201 | [email protected] " " |
@@ -207,7 +207,7 @@ [email protected] | |||
207 | [email protected] "," | 207 | [email protected] "," |
208 | [email protected] " " | 208 | [email protected] " " |
209 | [email protected] | 209 | [email protected] |
210 | REFERENCE[email protected] | 210 | [email protected] |
211 | [email protected] "&" | 211 | [email protected] "&" |
212 | [email protected] "\'c" | 212 | [email protected] "\'c" |
213 | [email protected] " " | 213 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rast b/crates/ra_syntax/test_data/parser/err/0045_item_modifiers.rast index a6e6552a9..a6e6552a9 100644 --- a/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rast +++ b/crates/ra_syntax/test_data/parser/err/0045_item_modifiers.rast | |||
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rs b/crates/ra_syntax/test_data/parser/err/0045_item_modifiers.rs index 731e58013..731e58013 100644 --- a/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rs +++ b/crates/ra_syntax/test_data/parser/err/0045_item_modifiers.rs | |||
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast b/crates/ra_syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast index 2409eefe7..0d8bf6dd6 100644 --- a/crates/ra_syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast +++ b/crates/ra_syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast | |||
@@ -7,7 +7,7 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | POINTE[email protected] | 10 | [email protected] |
11 | [email protected] "*" | 11 | [email protected] "*" |
12 | [email protected] | 12 | [email protected] |
13 | [email protected] "(" | 13 | [email protected] "(" |
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast b/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast deleted file mode 100644 index acd72094b..000000000 --- a/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "trait" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "T" | ||
7 | [email protected] " " | ||
8 | [email protected] | ||
9 | [email protected] "{" | ||
10 | [email protected] "\n " | ||
11 | [email protected] | ||
12 | [email protected] | ||
13 | [email protected] | ||
14 | [email protected] | ||
15 | [email protected] "default" | ||
16 | [email protected] " " | ||
17 | [email protected] | ||
18 | [email protected] "type" | ||
19 | [email protected] " " | ||
20 | [email protected] | ||
21 | [email protected] "T" | ||
22 | [email protected] " " | ||
23 | [email protected] "=" | ||
24 | [email protected] " " | ||
25 | [email protected] | ||
26 | [email protected] | ||
27 | [email protected] | ||
28 | [email protected] | ||
29 | [email protected] "Bar" | ||
30 | [email protected] ";" | ||
31 | [email protected] "\n " | ||
32 | [email protected] | ||
33 | [email protected] | ||
34 | [email protected] | ||
35 | [email protected] | ||
36 | [email protected] "default" | ||
37 | [email protected] " " | ||
38 | [email protected] | ||
39 | [email protected] "fn" | ||
40 | [email protected] " " | ||
41 | [email protected] | ||
42 | [email protected] "foo" | ||
43 | [email protected] | ||
44 | [email protected] "(" | ||
45 | [email protected] ")" | ||
46 | [email protected] " " | ||
47 | [email protected] | ||
48 | [email protected] "{" | ||
49 | [email protected] "}" | ||
50 | [email protected] "\n" | ||
51 | [email protected] "}" | ||
52 | [email protected] "\n" | ||
53 | error 21..21: expected BANG | ||
54 | error 21..21: expected `{`, `[`, `(` | ||
55 | error 21..21: expected SEMICOLON | ||
56 | error 47..47: expected BANG | ||
57 | error 47..47: expected `{`, `[`, `(` | ||
58 | error 47..47: expected SEMICOLON | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rs b/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rs deleted file mode 100644 index 15ba8f4a8..000000000 --- a/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rs +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | trait T { | ||
2 | default type T = Bar; | ||
3 | default fn foo() {} | ||
4 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast b/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast index b0f2b5888..62da7b887 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast | |||
@@ -42,7 +42,7 @@ [email protected] | |||
42 | [email protected] | 42 | [email protected] |
43 | [email protected] "(" | 43 | [email protected] "(" |
44 | [email protected] | 44 | [email protected] |
45 | REFERENCE[email protected] | 45 | [email protected] |
46 | [email protected] "&" | 46 | [email protected] "&" |
47 | [email protected] "\'a" | 47 | [email protected] "\'a" |
48 | [email protected] " " | 48 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast b/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast index 44d92aedb..b650735ba 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast | |||
@@ -31,7 +31,7 @@ [email protected] | |||
31 | [email protected] "," | 31 | [email protected] "," |
32 | [email protected] " " | 32 | [email protected] " " |
33 | [email protected] | 33 | [email protected] |
34 | REFERENCE[email protected] | 34 | [email protected] |
35 | [email protected] "&" | 35 | [email protected] "&" |
36 | [email protected] | 36 | [email protected] |
37 | [email protected] | 37 | [email protected] |
@@ -41,7 +41,7 @@ [email protected] | |||
41 | [email protected] "," | 41 | [email protected] "," |
42 | [email protected] " " | 42 | [email protected] " " |
43 | [email protected] | 43 | [email protected] |
44 | REFERENCE[email protected] | 44 | [email protected] |
45 | [email protected] "&" | 45 | [email protected] "&" |
46 | [email protected] | 46 | [email protected] |
47 | [email protected] | 47 | [email protected] |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast b/crates/ra_syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast index 845b32e6d..d33215b50 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast | |||
@@ -7,7 +7,7 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | POINTE[email protected] | 10 | [email protected] |
11 | [email protected] "*" | 11 | [email protected] "*" |
12 | [email protected] "mut" | 12 | [email protected] "mut" |
13 | [email protected] " " | 13 | [email protected] " " |
@@ -24,7 +24,7 @@ [email protected] | |||
24 | [email protected] " " | 24 | [email protected] " " |
25 | [email protected] "=" | 25 | [email protected] "=" |
26 | [email protected] " " | 26 | [email protected] " " |
27 | POINTE[email protected] | 27 | [email protected] |
28 | [email protected] "*" | 28 | [email protected] "*" |
29 | [email protected] "mut" | 29 | [email protected] "mut" |
30 | [email protected] " " | 30 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0016_unsafe_trait.rast b/crates/ra_syntax/test_data/parser/inline/ok/0016_unsafe_trait.rast deleted file mode 100644 index 625ab4c2d..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0016_unsafe_trait.rast +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "unsafe" | ||
4 | [email protected] " " | ||
5 | [email protected] "trait" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] "T" | ||
9 | [email protected] " " | ||
10 | [email protected] | ||
11 | [email protected] "{" | ||
12 | [email protected] "}" | ||
13 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0016_unsafe_trait.rs b/crates/ra_syntax/test_data/parser/inline/ok/0016_unsafe_trait.rs deleted file mode 100644 index 04e021550..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0016_unsafe_trait.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | unsafe trait T {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast b/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast index 1b31aa95a..ddbd66588 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast | |||
@@ -22,7 +22,7 @@ [email protected] | |||
22 | [email protected] "self" | 22 | [email protected] "self" |
23 | [email protected] ":" | 23 | [email protected] ":" |
24 | [email protected] " " | 24 | [email protected] " " |
25 | REFERENCE[email protected] | 25 | [email protected] |
26 | [email protected] "&" | 26 | [email protected] "&" |
27 | [email protected] | 27 | [email protected] |
28 | [email protected] | 28 | [email protected] |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast b/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast index 79a5ee339..dda6577ed 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast | |||
@@ -7,7 +7,7 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | FN_POINTE[email protected] | 10 | [email protected] |
11 | [email protected] "fn" | 11 | [email protected] "fn" |
12 | [email protected] | 12 | [email protected] |
13 | [email protected] "(" | 13 | [email protected] "(" |
@@ -22,7 +22,7 @@ [email protected] | |||
22 | [email protected] " " | 22 | [email protected] " " |
23 | [email protected] "=" | 23 | [email protected] "=" |
24 | [email protected] " " | 24 | [email protected] " " |
25 | FN_POINTE[email protected] | 25 | [email protected] |
26 | [email protected] "unsafe" | 26 | [email protected] "unsafe" |
27 | [email protected] " " | 27 | [email protected] " " |
28 | [email protected] "fn" | 28 | [email protected] "fn" |
@@ -39,7 +39,7 @@ [email protected] | |||
39 | [email protected] " " | 39 | [email protected] " " |
40 | [email protected] "=" | 40 | [email protected] "=" |
41 | [email protected] " " | 41 | [email protected] " " |
42 | FN_POINTE[email protected] | 42 | [email protected] |
43 | [email protected] "unsafe" | 43 | [email protected] "unsafe" |
44 | [email protected] " " | 44 | [email protected] " " |
45 | [email protected] | 45 | [email protected] |
@@ -61,7 +61,7 @@ [email protected] | |||
61 | [email protected] " " | 61 | [email protected] " " |
62 | [email protected] "=" | 62 | [email protected] "=" |
63 | [email protected] " " | 63 | [email protected] " " |
64 | FN_POINTE[email protected] | 64 | [email protected] |
65 | [email protected] | 65 | [email protected] |
66 | [email protected] "extern" | 66 | [email protected] "extern" |
67 | [email protected] " " | 67 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0033_reference_type;.rast b/crates/ra_syntax/test_data/parser/inline/ok/0033_reference_type;.rast index c522f76cf..974df9f9a 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0033_reference_type;.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0033_reference_type;.rast | |||
@@ -7,7 +7,7 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | REFERENCE[email protected] | 10 | [email protected] |
11 | [email protected] "&" | 11 | [email protected] "&" |
12 | [email protected] | 12 | [email protected] |
13 | [email protected] "(" | 13 | [email protected] "(" |
@@ -22,7 +22,7 @@ [email protected] | |||
22 | [email protected] " " | 22 | [email protected] " " |
23 | [email protected] "=" | 23 | [email protected] "=" |
24 | [email protected] " " | 24 | [email protected] " " |
25 | REFERENCE[email protected] | 25 | [email protected] |
26 | [email protected] "&" | 26 | [email protected] "&" |
27 | [email protected] "\'static" | 27 | [email protected] "\'static" |
28 | [email protected] " " | 28 | [email protected] " " |
@@ -39,7 +39,7 @@ [email protected] | |||
39 | [email protected] " " | 39 | [email protected] " " |
40 | [email protected] "=" | 40 | [email protected] "=" |
41 | [email protected] " " | 41 | [email protected] " " |
42 | REFERENCE[email protected] | 42 | [email protected] |
43 | [email protected] "&" | 43 | [email protected] "&" |
44 | [email protected] "mut" | 44 | [email protected] "mut" |
45 | [email protected] " " | 45 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast deleted file mode 100644 index 293b1d64c..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "unsafe" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "extern" | ||
7 | [email protected] " " | ||
8 | [email protected] "\"C\"" | ||
9 | [email protected] " " | ||
10 | [email protected] "fn" | ||
11 | [email protected] " " | ||
12 | [email protected] | ||
13 | [email protected] "foo" | ||
14 | [email protected] | ||
15 | [email protected] "(" | ||
16 | [email protected] ")" | ||
17 | [email protected] " " | ||
18 | [email protected] | ||
19 | [email protected] "{" | ||
20 | [email protected] "}" | ||
21 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rs deleted file mode 100644 index 1295c2cd2..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | unsafe extern "C" fn foo() {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast b/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast index c100d1c71..6baea6e3c 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast | |||
@@ -21,7 +21,7 @@ [email protected] | |||
21 | [email protected] | 21 | [email protected] |
22 | [email protected] "(" | 22 | [email protected] "(" |
23 | [email protected] | 23 | [email protected] |
24 | REFERENCE[email protected] | 24 | [email protected] |
25 | [email protected] "&" | 25 | [email protected] "&" |
26 | [email protected] "mut" | 26 | [email protected] "mut" |
27 | [email protected] " " | 27 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0047_unsafe_default_impl.rast b/crates/ra_syntax/test_data/parser/inline/ok/0047_unsafe_default_impl.rast deleted file mode 100644 index d6dfa83b7..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0047_unsafe_default_impl.rast +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "unsafe" | ||
4 | [email protected] " " | ||
5 | [email protected] "default" | ||
6 | [email protected] " " | ||
7 | [email protected] "impl" | ||
8 | [email protected] " " | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] | ||
12 | [email protected] | ||
13 | [email protected] "Foo" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] "{" | ||
17 | [email protected] "}" | ||
18 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0047_unsafe_default_impl.rs b/crates/ra_syntax/test_data/parser/inline/ok/0047_unsafe_default_impl.rs deleted file mode 100644 index 9cd6c57bd..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0047_unsafe_default_impl.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | unsafe default impl Foo {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast deleted file mode 100644 index 97548a5ee..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "const" | ||
4 | [email protected] " " | ||
5 | [email protected] "fn" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] "foo" | ||
9 | [email protected] | ||
10 | [email protected] "(" | ||
11 | [email protected] ")" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] "{" | ||
15 | [email protected] "}" | ||
16 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rs deleted file mode 100644 index 8c84d9cd7..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | const fn foo() {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast index 5f4807522..f319d5141 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast | |||
@@ -15,7 +15,7 @@ [email protected] | |||
15 | [email protected] "\'a" | 15 | [email protected] "\'a" |
16 | [email protected] ">" | 16 | [email protected] ">" |
17 | [email protected] " " | 17 | [email protected] " " |
18 | FN_POINTE[email protected] | 18 | [email protected] |
19 | [email protected] "fn" | 19 | [email protected] "fn" |
20 | [email protected] | 20 | [email protected] |
21 | [email protected] "(" | 21 | [email protected] "(" |
@@ -45,7 +45,7 @@ [email protected] | |||
45 | [email protected] "\'a" | 45 | [email protected] "\'a" |
46 | [email protected] ">" | 46 | [email protected] ">" |
47 | [email protected] " " | 47 | [email protected] " " |
48 | FN_POINTE[email protected] | 48 | [email protected] |
49 | [email protected] "unsafe" | 49 | [email protected] "unsafe" |
50 | [email protected] " " | 50 | [email protected] " " |
51 | [email protected] | 51 | [email protected] |
@@ -57,7 +57,7 @@ [email protected] | |||
57 | [email protected] | 57 | [email protected] |
58 | [email protected] "(" | 58 | [email protected] "(" |
59 | [email protected] | 59 | [email protected] |
60 | REFERENCE[email protected] | 60 | [email protected] |
61 | [email protected] "&" | 61 | [email protected] "&" |
62 | [email protected] "\'a" | 62 | [email protected] "\'a" |
63 | [email protected] " " | 63 | [email protected] " " |
@@ -98,7 +98,7 @@ [email protected] | |||
98 | [email protected] | 98 | [email protected] |
99 | [email protected] "<" | 99 | [email protected] "<" |
100 | [email protected] | 100 | [email protected] |
101 | REFERENCE[email protected] | 101 | [email protected] |
102 | [email protected] "&" | 102 | [email protected] "&" |
103 | [email protected] "\'a" | 103 | [email protected] "\'a" |
104 | [email protected] " " | 104 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0087_unsafe_impl.rast b/crates/ra_syntax/test_data/parser/inline/ok/0087_unsafe_impl.rast deleted file mode 100644 index 43c09affe..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0087_unsafe_impl.rast +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "unsafe" | ||
4 | [email protected] " " | ||
5 | [email protected] "impl" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] "Foo" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] "{" | ||
15 | [email protected] "}" | ||
16 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0087_unsafe_impl.rs b/crates/ra_syntax/test_data/parser/inline/ok/0087_unsafe_impl.rs deleted file mode 100644 index 41055f41d..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0087_unsafe_impl.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | unsafe impl Foo {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast deleted file mode 100644 index 405b6a259..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] | ||
4 | [email protected] "extern" | ||
5 | [email protected] " " | ||
6 | [email protected] "fn" | ||
7 | [email protected] " " | ||
8 | [email protected] | ||
9 | [email protected] "foo" | ||
10 | [email protected] | ||
11 | [email protected] "(" | ||
12 | [email protected] ")" | ||
13 | [email protected] " " | ||
14 | [email protected] | ||
15 | [email protected] "{" | ||
16 | [email protected] "}" | ||
17 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rs deleted file mode 100644 index 394a049f0..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | extern fn foo() {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0091_auto_trait.rast b/crates/ra_syntax/test_data/parser/inline/ok/0091_auto_trait.rast deleted file mode 100644 index 0cac9ac43..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0091_auto_trait.rast +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "auto" | ||
4 | [email protected] " " | ||
5 | [email protected] "trait" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] "T" | ||
9 | [email protected] " " | ||
10 | [email protected] | ||
11 | [email protected] "{" | ||
12 | [email protected] "}" | ||
13 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0091_auto_trait.rs b/crates/ra_syntax/test_data/parser/inline/ok/0091_auto_trait.rs deleted file mode 100644 index 72adf6035..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0091_auto_trait.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | auto trait T {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast b/crates/ra_syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast index 95686977f..f80326465 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast | |||
@@ -7,7 +7,7 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | FN_POINTE[email protected] | 10 | [email protected] |
11 | [email protected] "fn" | 11 | [email protected] "fn" |
12 | [email protected] | 12 | [email protected] |
13 | [email protected] "(" | 13 | [email protected] "(" |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0094_unsafe_auto_trait.rast b/crates/ra_syntax/test_data/parser/inline/ok/0094_unsafe_auto_trait.rast deleted file mode 100644 index 0ef11c682..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0094_unsafe_auto_trait.rast +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "unsafe" | ||
4 | [email protected] " " | ||
5 | [email protected] "auto" | ||
6 | [email protected] " " | ||
7 | [email protected] "trait" | ||
8 | [email protected] " " | ||
9 | [email protected] | ||
10 | [email protected] "T" | ||
11 | [email protected] " " | ||
12 | [email protected] | ||
13 | [email protected] "{" | ||
14 | [email protected] "}" | ||
15 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0094_unsafe_auto_trait.rs b/crates/ra_syntax/test_data/parser/inline/ok/0094_unsafe_auto_trait.rs deleted file mode 100644 index 03d29f324..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0094_unsafe_auto_trait.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | unsafe auto trait T {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0097_default_impl.rast b/crates/ra_syntax/test_data/parser/inline/ok/0097_default_impl.rast deleted file mode 100644 index 0a1b21d6e..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0097_default_impl.rast +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "default" | ||
4 | [email protected] " " | ||
5 | [email protected] "impl" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] "Foo" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] "{" | ||
15 | [email protected] "}" | ||
16 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0097_default_impl.rs b/crates/ra_syntax/test_data/parser/inline/ok/0097_default_impl.rs deleted file mode 100644 index ef6aa84a2..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0097_default_impl.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | default impl Foo {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast deleted file mode 100644 index 32a77ba49..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "const" | ||
4 | [email protected] " " | ||
5 | [email protected] "unsafe" | ||
6 | [email protected] " " | ||
7 | [email protected] "fn" | ||
8 | [email protected] " " | ||
9 | [email protected] | ||
10 | [email protected] "foo" | ||
11 | [email protected] | ||
12 | [email protected] "(" | ||
13 | [email protected] ")" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] "{" | ||
17 | [email protected] "}" | ||
18 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rs deleted file mode 100644 index 31a1e435f..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | const unsafe fn foo() {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast deleted file mode 100644 index 73c94e5d4..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "unsafe" | ||
4 | [email protected] " " | ||
5 | [email protected] "fn" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] "foo" | ||
9 | [email protected] | ||
10 | [email protected] "(" | ||
11 | [email protected] ")" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] "{" | ||
15 | [email protected] "}" | ||
16 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rs deleted file mode 100644 index 33cfc4cd7..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | unsafe fn foo() {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast b/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast index 8d029b592..570b95205 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast | |||
@@ -47,7 +47,7 @@ [email protected] | |||
47 | [email protected] "_" | 47 | [email protected] "_" |
48 | [email protected] ":" | 48 | [email protected] ":" |
49 | [email protected] " " | 49 | [email protected] " " |
50 | REFERENCE[email protected] | 50 | [email protected] |
51 | [email protected] "&" | 51 | [email protected] "&" |
52 | [email protected] "\'a" | 52 | [email protected] "\'a" |
53 | [email protected] " " | 53 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast b/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast index 27c4f141f..7cdec6634 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast | |||
@@ -21,7 +21,7 @@ [email protected] | |||
21 | [email protected] "format" | 21 | [email protected] "format" |
22 | [email protected] ":" | 22 | [email protected] ":" |
23 | [email protected] " " | 23 | [email protected] " " |
24 | POINTE[email protected] | 24 | [email protected] |
25 | [email protected] "*" | 25 | [email protected] "*" |
26 | [email protected] "const" | 26 | [email protected] "const" |
27 | [email protected] " " | 27 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast deleted file mode 100644 index a7df188bd..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "async" | ||
4 | [email protected] " " | ||
5 | [email protected] "fn" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] "foo" | ||
9 | [email protected] | ||
10 | [email protected] "(" | ||
11 | [email protected] ")" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] "{" | ||
15 | [email protected] "}" | ||
16 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rs deleted file mode 100644 index f4adcb62b..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | async fn foo() {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast b/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast deleted file mode 100644 index 98a20f36d..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "async" | ||
4 | [email protected] " " | ||
5 | [email protected] "unsafe" | ||
6 | [email protected] " " | ||
7 | [email protected] "fn" | ||
8 | [email protected] " " | ||
9 | [email protected] | ||
10 | [email protected] "foo" | ||
11 | [email protected] | ||
12 | [email protected] "(" | ||
13 | [email protected] ")" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] "{" | ||
17 | [email protected] "}" | ||
18 | [email protected] "\n" | ||
19 | [email protected] | ||
20 | [email protected] "const" | ||
21 | [email protected] " " | ||
22 | [email protected] "unsafe" | ||
23 | [email protected] " " | ||
24 | [email protected] "fn" | ||
25 | [email protected] " " | ||
26 | [email protected] | ||
27 | [email protected] "bar" | ||
28 | [email protected] | ||
29 | [email protected] "(" | ||
30 | [email protected] ")" | ||
31 | [email protected] " " | ||
32 | [email protected] | ||
33 | [email protected] "{" | ||
34 | [email protected] "}" | ||
35 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rs b/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rs deleted file mode 100644 index 126287145..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rs +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | async unsafe fn foo() {} | ||
2 | const unsafe fn bar() {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast b/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast deleted file mode 100644 index b8d26a53a..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "impl" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] "T" | ||
10 | [email protected] " " | ||
11 | [email protected] "for" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] "Foo" | ||
18 | [email protected] " " | ||
19 | [email protected] | ||
20 | [email protected] "{" | ||
21 | [email protected] "\n " | ||
22 | [email protected] | ||
23 | [email protected] "default" | ||
24 | [email protected] " " | ||
25 | [email protected] "type" | ||
26 | [email protected] " " | ||
27 | [email protected] | ||
28 | [email protected] "T" | ||
29 | [email protected] " " | ||
30 | [email protected] "=" | ||
31 | [email protected] " " | ||
32 | [email protected] | ||
33 | [email protected] | ||
34 | [email protected] | ||
35 | [email protected] | ||
36 | [email protected] "Bar" | ||
37 | [email protected] ";" | ||
38 | [email protected] "\n " | ||
39 | [email protected] | ||
40 | [email protected] "default" | ||
41 | [email protected] " " | ||
42 | [email protected] "fn" | ||
43 | [email protected] " " | ||
44 | [email protected] | ||
45 | [email protected] "foo" | ||
46 | [email protected] | ||
47 | [email protected] "(" | ||
48 | [email protected] ")" | ||
49 | [email protected] " " | ||
50 | [email protected] | ||
51 | [email protected] "{" | ||
52 | [email protected] "}" | ||
53 | [email protected] "\n" | ||
54 | [email protected] "}" | ||
55 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rs b/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rs deleted file mode 100644 index 8f5d61113..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rs +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | impl T for Foo { | ||
2 | default type T = Bar; | ||
3 | default fn foo() {} | ||
4 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast index ca739825a..a36cc8dab 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast | |||
@@ -27,7 +27,7 @@ [email protected] | |||
27 | [email protected] " " | 27 | [email protected] " " |
28 | [email protected] "as" | 28 | [email protected] "as" |
29 | [email protected] " " | 29 | [email protected] " " |
30 | POINTE[email protected] | 30 | [email protected] |
31 | [email protected] "*" | 31 | [email protected] "*" |
32 | [email protected] "const" | 32 | [email protected] "const" |
33 | [email protected] " " | 33 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0150_array_attrs.rast b/crates/ra_syntax/test_data/parser/inline/ok/0150_array_attrs.rast index 0c35bf2b7..f284aafcd 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0150_array_attrs.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0150_array_attrs.rast | |||
@@ -6,7 +6,7 @@ [email protected] | |||
6 | [email protected] "A" | 6 | [email protected] "A" |
7 | [email protected] ":" | 7 | [email protected] ":" |
8 | [email protected] " " | 8 | [email protected] " " |
9 | REFERENCE[email protected] | 9 | [email protected] |
10 | [email protected] "&" | 10 | [email protected] "&" |
11 | [email protected] | 11 | [email protected] |
12 | [email protected] "[" | 12 | [email protected] "[" |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0151_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0151_fn.rast new file mode 100644 index 000000000..23c4269b3 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0151_fn.rast | |||
@@ -0,0 +1,14 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "fn" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "foo" | ||
7 | [email protected] | ||
8 | [email protected] "(" | ||
9 | [email protected] ")" | ||
10 | [email protected] " " | ||
11 | [email protected] | ||
12 | [email protected] "{" | ||
13 | [email protected] "}" | ||
14 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0151_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0151_fn.rs new file mode 100644 index 000000000..8f3b7ef11 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0151_fn.rs | |||
@@ -0,0 +1 @@ | |||
fn foo() {} | |||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0152_impl.rast b/crates/ra_syntax/test_data/parser/inline/ok/0152_impl.rast new file mode 100644 index 000000000..7968cf9ff --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0152_impl.rast | |||
@@ -0,0 +1,22 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "impl" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] "T" | ||
10 | [email protected] " " | ||
11 | [email protected] "for" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] "S" | ||
18 | [email protected] " " | ||
19 | [email protected] | ||
20 | [email protected] "{" | ||
21 | [email protected] "}" | ||
22 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0152_impl.rs b/crates/ra_syntax/test_data/parser/inline/ok/0152_impl.rs new file mode 100644 index 000000000..a1a550d8a --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0152_impl.rs | |||
@@ -0,0 +1 @@ | |||
impl T for S {} | |||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0153_trait.rast b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait.rast new file mode 100644 index 000000000..9881e5048 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait.rast | |||
@@ -0,0 +1,11 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "trait" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "T" | ||
7 | [email protected] " " | ||
8 | [email protected] | ||
9 | [email protected] "{" | ||
10 | [email protected] "}" | ||
11 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0153_trait.rs b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait.rs new file mode 100644 index 000000000..8d183dbb5 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait.rs | |||
@@ -0,0 +1 @@ | |||
trait T {} | |||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast b/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast index c48fed03e..e6aff7b37 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast | |||
@@ -7,7 +7,7 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | FN_POINTE[email protected] | 10 | [email protected] |
11 | [email protected] "fn" | 11 | [email protected] "fn" |
12 | [email protected] | 12 | [email protected] |
13 | [email protected] "(" | 13 | [email protected] "(" |
@@ -33,7 +33,7 @@ [email protected] | |||
33 | [email protected] " " | 33 | [email protected] " " |
34 | [email protected] "=" | 34 | [email protected] "=" |
35 | [email protected] " " | 35 | [email protected] " " |
36 | FN_POINTE[email protected] | 36 | [email protected] |
37 | [email protected] "fn" | 37 | [email protected] "fn" |
38 | [email protected] | 38 | [email protected] |
39 | [email protected] "(" | 39 | [email protected] "(" |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast b/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast index 3079e5bf8..6abb4fe5a 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast | |||
@@ -7,7 +7,7 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | FN_POINTE[email protected] | 10 | [email protected] |
11 | [email protected] "fn" | 11 | [email protected] "fn" |
12 | [email protected] | 12 | [email protected] |
13 | [email protected] "(" | 13 | [email protected] "(" |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rast deleted file mode 100644 index 1269621dc..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rast +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "impl" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] "T" | ||
10 | [email protected] " " | ||
11 | [email protected] "for" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] "Foo" | ||
18 | [email protected] " " | ||
19 | [email protected] | ||
20 | [email protected] "{" | ||
21 | [email protected] "\n " | ||
22 | [email protected] | ||
23 | [email protected] "default" | ||
24 | [email protected] " " | ||
25 | [email protected] "unsafe" | ||
26 | [email protected] " " | ||
27 | [email protected] "fn" | ||
28 | [email protected] " " | ||
29 | [email protected] | ||
30 | [email protected] "foo" | ||
31 | [email protected] | ||
32 | [email protected] "(" | ||
33 | [email protected] ")" | ||
34 | [email protected] " " | ||
35 | [email protected] | ||
36 | [email protected] "{" | ||
37 | [email protected] "}" | ||
38 | [email protected] "\n" | ||
39 | [email protected] "}" | ||
40 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_impl.rast b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_impl.rast deleted file mode 100644 index 6bfe925af..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_impl.rast +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "default" | ||
4 | [email protected] " " | ||
5 | [email protected] "unsafe" | ||
6 | [email protected] " " | ||
7 | [email protected] "impl" | ||
8 | [email protected] " " | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] | ||
12 | [email protected] | ||
13 | [email protected] "Foo" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] "{" | ||
17 | [email protected] "}" | ||
18 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_impl.rs b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_impl.rs deleted file mode 100644 index ba0998ff4..000000000 --- a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_impl.rs +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | default unsafe impl Foo {} | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rast b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rast new file mode 100644 index 000000000..f2e201460 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rast | |||
@@ -0,0 +1,44 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "default" | ||
4 | [email protected] " " | ||
5 | [email protected] "unsafe" | ||
6 | [email protected] " " | ||
7 | [email protected] "impl" | ||
8 | [email protected] " " | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] | ||
12 | [email protected] | ||
13 | [email protected] "T" | ||
14 | [email protected] " " | ||
15 | [email protected] "for" | ||
16 | [email protected] " " | ||
17 | [email protected] | ||
18 | [email protected] | ||
19 | [email protected] | ||
20 | [email protected] | ||
21 | [email protected] "Foo" | ||
22 | [email protected] " " | ||
23 | [email protected] | ||
24 | [email protected] "{" | ||
25 | [email protected] "\n " | ||
26 | [email protected] | ||
27 | [email protected] "default" | ||
28 | [email protected] " " | ||
29 | [email protected] "unsafe" | ||
30 | [email protected] " " | ||
31 | [email protected] "fn" | ||
32 | [email protected] " " | ||
33 | [email protected] | ||
34 | [email protected] "foo" | ||
35 | [email protected] | ||
36 | [email protected] "(" | ||
37 | [email protected] ")" | ||
38 | [email protected] " " | ||
39 | [email protected] | ||
40 | [email protected] "{" | ||
41 | [email protected] "}" | ||
42 | [email protected] "\n" | ||
43 | [email protected] "}" | ||
44 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rs index 12926cd8a..96340f84a 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rs | |||
@@ -1,3 +1,3 @@ | |||
1 | impl T for Foo { | 1 | default unsafe impl T for Foo { |
2 | default unsafe fn foo() {} | 2 | default unsafe fn foo() {} |
3 | } | 3 | } |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0164_default_item.rast b/crates/ra_syntax/test_data/parser/inline/ok/0164_default_item.rast new file mode 100644 index 000000000..9282772f3 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0164_default_item.rast | |||
@@ -0,0 +1,24 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "default" | ||
4 | [email protected] " " | ||
5 | [email protected] "impl" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] "T" | ||
12 | [email protected] " " | ||
13 | [email protected] "for" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] | ||
18 | [email protected] | ||
19 | [email protected] "Foo" | ||
20 | [email protected] " " | ||
21 | [email protected] | ||
22 | [email protected] "{" | ||
23 | [email protected] "}" | ||
24 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0164_default_item.rs b/crates/ra_syntax/test_data/parser/inline/ok/0164_default_item.rs new file mode 100644 index 000000000..a6836cbd5 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0164_default_item.rs | |||
@@ -0,0 +1 @@ | |||
default impl T for Foo {} | |||
diff --git a/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast b/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast deleted file mode 100644 index 5524efaaf..000000000 --- a/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] | ||
4 | [email protected] "extern" | ||
5 | [email protected] " " | ||
6 | [email protected] "fn" | ||
7 | [email protected] " " | ||
8 | [email protected] | ||
9 | [email protected] "foo" | ||
10 | [email protected] | ||
11 | [email protected] "(" | ||
12 | [email protected] ")" | ||
13 | [email protected] " " | ||
14 | [email protected] | ||
15 | [email protected] "{" | ||
16 | [email protected] "\n" | ||
17 | [email protected] "}" | ||
18 | [email protected] "\n\n" | ||
19 | [email protected] | ||
20 | [email protected] | ||
21 | [email protected] "extern" | ||
22 | [email protected] " " | ||
23 | [email protected] "\"C\"" | ||
24 | [email protected] " " | ||
25 | [email protected] "fn" | ||
26 | [email protected] " " | ||
27 | [email protected] | ||
28 | [email protected] "bar" | ||
29 | [email protected] | ||
30 | [email protected] "(" | ||
31 | [email protected] ")" | ||
32 | [email protected] " " | ||
33 | [email protected] | ||
34 | [email protected] "{" | ||
35 | [email protected] "\n" | ||
36 | [email protected] "}" | ||
37 | [email protected] "\n\n" | ||
38 | [email protected] | ||
39 | [email protected] | ||
40 | [email protected] "extern" | ||
41 | [email protected] " " | ||
42 | [email protected] "r\"D\"" | ||
43 | [email protected] " " | ||
44 | [email protected] "fn" | ||
45 | [email protected] " " | ||
46 | [email protected] | ||
47 | [email protected] "baz" | ||
48 | [email protected] | ||
49 | [email protected] "(" | ||
50 | [email protected] ")" | ||
51 | [email protected] " " | ||
52 | [email protected] | ||
53 | [email protected] "{" | ||
54 | [email protected] "\n" | ||
55 | [email protected] "}" | ||
56 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rs b/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rs deleted file mode 100644 index e929eef74..000000000 --- a/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rs +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | extern fn foo() { | ||
2 | } | ||
3 | |||
4 | extern "C" fn bar() { | ||
5 | } | ||
6 | |||
7 | extern r"D" fn baz() { | ||
8 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/ok/0031_extern.rast b/crates/ra_syntax/test_data/parser/ok/0031_extern.rast index 79ea098a2..8150d445f 100644 --- a/crates/ra_syntax/test_data/parser/ok/0031_extern.rast +++ b/crates/ra_syntax/test_data/parser/ok/0031_extern.rast | |||
@@ -99,7 +99,7 @@ [email protected] | |||
99 | [email protected] "addr" | 99 | [email protected] "addr" |
100 | [email protected] ":" | 100 | [email protected] ":" |
101 | [email protected] " " | 101 | [email protected] " " |
102 | POINTE[email protected] | 102 | [email protected] |
103 | [email protected] "*" | 103 | [email protected] "*" |
104 | [email protected] "const" | 104 | [email protected] "const" |
105 | [email protected] " " | 105 | [email protected] " " |
@@ -164,7 +164,7 @@ [email protected] | |||
164 | [email protected] "address" | 164 | [email protected] "address" |
165 | [email protected] ":" | 165 | [email protected] ":" |
166 | [email protected] " " | 166 | [email protected] " " |
167 | POINTE[email protected] | 167 | [email protected] |
168 | [email protected] "*" | 168 | [email protected] "*" |
169 | [email protected] "const" | 169 | [email protected] "const" |
170 | [email protected] " " | 170 | [email protected] " " |
@@ -278,7 +278,7 @@ [email protected] | |||
278 | [email protected] "address" | 278 | [email protected] "address" |
279 | [email protected] ":" | 279 | [email protected] ":" |
280 | [email protected] " " | 280 | [email protected] " " |
281 | POINTE[email protected] | 281 | [email protected] |
282 | [email protected] "*" | 282 | [email protected] "*" |
283 | [email protected] "mut" | 283 | [email protected] "mut" |
284 | [email protected] " " | 284 | [email protected] " " |
@@ -295,7 +295,7 @@ [email protected] | |||
295 | [email protected] "address_len" | 295 | [email protected] "address_len" |
296 | [email protected] ":" | 296 | [email protected] ":" |
297 | [email protected] " " | 297 | [email protected] " " |
298 | POINTE[email protected] | 298 | [email protected] |
299 | [email protected] "*" | 299 | [email protected] "*" |
300 | [email protected] "mut" | 300 | [email protected] "mut" |
301 | [email protected] " " | 301 | [email protected] " " |
@@ -375,7 +375,7 @@ [email protected] | |||
375 | [email protected] "optval" | 375 | [email protected] "optval" |
376 | [email protected] ":" | 376 | [email protected] ":" |
377 | [email protected] " " | 377 | [email protected] " " |
378 | POINTE[email protected] | 378 | [email protected] |
379 | [email protected] "*" | 379 | [email protected] "*" |
380 | [email protected] "mut" | 380 | [email protected] "mut" |
381 | [email protected] " " | 381 | [email protected] " " |
@@ -393,7 +393,7 @@ [email protected] | |||
393 | [email protected] "optlen" | 393 | [email protected] "optlen" |
394 | [email protected] ":" | 394 | [email protected] ":" |
395 | [email protected] " " | 395 | [email protected] " " |
396 | POINTE[email protected] | 396 | [email protected] |
397 | [email protected] "*" | 397 | [email protected] "*" |
398 | [email protected] "mut" | 398 | [email protected] "mut" |
399 | [email protected] " " | 399 | [email protected] " " |
@@ -474,7 +474,7 @@ [email protected] | |||
474 | [email protected] "value" | 474 | [email protected] "value" |
475 | [email protected] ":" | 475 | [email protected] ":" |
476 | [email protected] " " | 476 | [email protected] " " |
477 | POINTE[email protected] | 477 | [email protected] |
478 | [email protected] "*" | 478 | [email protected] "*" |
479 | [email protected] "const" | 479 | [email protected] "const" |
480 | [email protected] " " | 480 | [email protected] " " |
@@ -540,7 +540,7 @@ [email protected] | |||
540 | [email protected] "address" | 540 | [email protected] "address" |
541 | [email protected] ":" | 541 | [email protected] ":" |
542 | [email protected] " " | 542 | [email protected] " " |
543 | POINTE[email protected] | 543 | [email protected] |
544 | [email protected] "*" | 544 | [email protected] "*" |
545 | [email protected] "mut" | 545 | [email protected] "mut" |
546 | [email protected] " " | 546 | [email protected] " " |
@@ -557,7 +557,7 @@ [email protected] | |||
557 | [email protected] "address_len" | 557 | [email protected] "address_len" |
558 | [email protected] ":" | 558 | [email protected] ":" |
559 | [email protected] " " | 559 | [email protected] " " |
560 | POINTE[email protected] | 560 | [email protected] |
561 | [email protected] "*" | 561 | [email protected] "*" |
562 | [email protected] "mut" | 562 | [email protected] "mut" |
563 | [email protected] " " | 563 | [email protected] " " |
@@ -609,7 +609,7 @@ [email protected] | |||
609 | [email protected] "buf" | 609 | [email protected] "buf" |
610 | [email protected] ":" | 610 | [email protected] ":" |
611 | [email protected] " " | 611 | [email protected] " " |
612 | POINTE[email protected] | 612 | [email protected] |
613 | [email protected] "*" | 613 | [email protected] "*" |
614 | [email protected] "const" | 614 | [email protected] "const" |
615 | [email protected] " " | 615 | [email protected] " " |
@@ -655,7 +655,7 @@ [email protected] | |||
655 | [email protected] "addr" | 655 | [email protected] "addr" |
656 | [email protected] ":" | 656 | [email protected] ":" |
657 | [email protected] " " | 657 | [email protected] " " |
658 | POINTE[email protected] | 658 | [email protected] |
659 | [email protected] "*" | 659 | [email protected] "*" |
660 | [email protected] "const" | 660 | [email protected] "const" |
661 | [email protected] " " | 661 | [email protected] " " |
@@ -720,7 +720,7 @@ [email protected] | |||
720 | [email protected] "buf" | 720 | [email protected] "buf" |
721 | [email protected] ":" | 721 | [email protected] ":" |
722 | [email protected] " " | 722 | [email protected] " " |
723 | POINTE[email protected] | 723 | [email protected] |
724 | [email protected] "*" | 724 | [email protected] "*" |
725 | [email protected] "const" | 725 | [email protected] "const" |
726 | [email protected] " " | 726 | [email protected] " " |
@@ -801,7 +801,7 @@ [email protected] | |||
801 | [email protected] "buf" | 801 | [email protected] "buf" |
802 | [email protected] ":" | 802 | [email protected] ":" |
803 | [email protected] " " | 803 | [email protected] " " |
804 | POINTE[email protected] | 804 | [email protected] |
805 | [email protected] "*" | 805 | [email protected] "*" |
806 | [email protected] "mut" | 806 | [email protected] "mut" |
807 | [email protected] " " | 807 | [email protected] " " |
@@ -847,7 +847,7 @@ [email protected] | |||
847 | [email protected] "addr" | 847 | [email protected] "addr" |
848 | [email protected] ":" | 848 | [email protected] ":" |
849 | [email protected] " " | 849 | [email protected] " " |
850 | POINTE[email protected] | 850 | [email protected] |
851 | [email protected] "*" | 851 | [email protected] "*" |
852 | [email protected] "mut" | 852 | [email protected] "mut" |
853 | [email protected] " " | 853 | [email protected] " " |
@@ -865,7 +865,7 @@ [email protected] | |||
865 | [email protected] "addrlen" | 865 | [email protected] "addrlen" |
866 | [email protected] ":" | 866 | [email protected] ":" |
867 | [email protected] " " | 867 | [email protected] " " |
868 | POINTE[email protected] | 868 | [email protected] |
869 | [email protected] "*" | 869 | [email protected] "*" |
870 | [email protected] "mut" | 870 | [email protected] "mut" |
871 | [email protected] " " | 871 | [email protected] " " |
@@ -918,7 +918,7 @@ [email protected] | |||
918 | [email protected] "buf" | 918 | [email protected] "buf" |
919 | [email protected] ":" | 919 | [email protected] ":" |
920 | [email protected] " " | 920 | [email protected] " " |
921 | POINTE[email protected] | 921 | [email protected] |
922 | [email protected] "*" | 922 | [email protected] "*" |
923 | [email protected] "mut" | 923 | [email protected] "mut" |
924 | [email protected] " " | 924 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast index 5bb9363a8..7c61b5006 100644 --- a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast +++ b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast | |||
@@ -242,7 +242,7 @@ [email protected] | |||
242 | [email protected] "x" | 242 | [email protected] "x" |
243 | [email protected] ":" | 243 | [email protected] ":" |
244 | [email protected] " " | 244 | [email protected] " " |
245 | REFERENCE[email protected] | 245 | [email protected] |
246 | [email protected] "&" | 246 | [email protected] "&" |
247 | [email protected] | 247 | [email protected] |
248 | [email protected] | 248 | [email protected] |
@@ -1579,7 +1579,7 @@ [email protected] | |||
1579 | [email protected] "union" | 1579 | [email protected] "union" |
1580 | [email protected] ":" | 1580 | [email protected] ":" |
1581 | [email protected] " " | 1581 | [email protected] " " |
1582 | REFERENCE[email protected] | 1582 | [email protected] |
1583 | [email protected] "&" | 1583 | [email protected] "&" |
1584 | [email protected] "\'union" | 1584 | [email protected] "\'union" |
1585 | [email protected] " " | 1585 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast index 0303b198f..d4f05f279 100644 --- a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast +++ b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast | |||
@@ -96,7 +96,7 @@ [email protected] | |||
96 | [email protected] "format" | 96 | [email protected] "format" |
97 | [email protected] ":" | 97 | [email protected] ":" |
98 | [email protected] " " | 98 | [email protected] " " |
99 | POINTE[email protected] | 99 | [email protected] |
100 | [email protected] "*" | 100 | [email protected] "*" |
101 | [email protected] "const" | 101 | [email protected] "const" |
102 | [email protected] " " | 102 | [email protected] " " |
@@ -163,7 +163,7 @@ [email protected] | |||
163 | [email protected] "]" | 163 | [email protected] "]" |
164 | [email protected] " " | 164 | [email protected] " " |
165 | [email protected] | 165 | [email protected] |
166 | REFERENCE[email protected] | 166 | [email protected] |
167 | [email protected] "&" | 167 | [email protected] "&" |
168 | [email protected] "mut" | 168 | [email protected] "mut" |
169 | [email protected] " " | 169 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast index f71ceecd7..f25c9ac36 100644 --- a/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast +++ b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast | |||
@@ -102,7 +102,7 @@ [email protected] | |||
102 | [email protected] | 102 | [email protected] |
103 | [email protected] "(" | 103 | [email protected] "(" |
104 | [email protected] | 104 | [email protected] |
105 | REFERENCE[email protected] | 105 | [email protected] |
106 | [email protected] "&" | 106 | [email protected] "&" |
107 | [email protected] | 107 | [email protected] |
108 | [email protected] | 108 | [email protected] |
diff --git a/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast b/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast index 42680b283..8eda59976 100644 --- a/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast +++ b/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast | |||
@@ -140,9 +140,9 @@ [email protected] | |||
140 | [email protected] "a" | 140 | [email protected] "a" |
141 | [email protected] ":" | 141 | [email protected] ":" |
142 | [email protected] " " | 142 | [email protected] " " |
143 | REFERENCE[email protected] | 143 | [email protected] |
144 | [email protected] "&" | 144 | [email protected] "&" |
145 | REFERENCE[email protected] | 145 | [email protected] |
146 | [email protected] "&" | 146 | [email protected] "&" |
147 | [email protected] | 147 | [email protected] |
148 | [email protected] | 148 | [email protected] |
diff --git a/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rast b/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rast index a132591f0..4009b3ff8 100644 --- a/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rast +++ b/crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rast | |||
@@ -20,7 +20,7 @@ [email protected] | |||
20 | [email protected] "_" | 20 | [email protected] "_" |
21 | [email protected] ":" | 21 | [email protected] ":" |
22 | [email protected] " " | 22 | [email protected] " " |
23 | POINTE[email protected] | 23 | [email protected] |
24 | [email protected] "*" | 24 | [email protected] "*" |
25 | [email protected] "mut" | 25 | [email protected] "mut" |
26 | [email protected] " " | 26 | [email protected] " " |
@@ -49,7 +49,7 @@ [email protected] | |||
49 | [email protected] "_" | 49 | [email protected] "_" |
50 | [email protected] ":" | 50 | [email protected] ":" |
51 | [email protected] " " | 51 | [email protected] " " |
52 | POINTE[email protected] | 52 | [email protected] |
53 | [email protected] "*" | 53 | [email protected] "*" |
54 | [email protected] "mut" | 54 | [email protected] "mut" |
55 | [email protected] " " | 55 | [email protected] " " |
@@ -81,7 +81,7 @@ [email protected] | |||
81 | [email protected] "_" | 81 | [email protected] "_" |
82 | [email protected] ":" | 82 | [email protected] ":" |
83 | [email protected] " " | 83 | [email protected] " " |
84 | POINTE[email protected] | 84 | [email protected] |
85 | [email protected] "*" | 85 | [email protected] "*" |
86 | [email protected] "mut" | 86 | [email protected] "mut" |
87 | [email protected] " " | 87 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast b/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast index 94260db7c..a3c6ed82e 100644 --- a/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast +++ b/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast | |||
@@ -143,9 +143,9 @@ [email protected] | |||
143 | [email protected] "a" | 143 | [email protected] "a" |
144 | [email protected] ":" | 144 | [email protected] ":" |
145 | [email protected] " " | 145 | [email protected] " " |
146 | REFERENCE[email protected] | 146 | [email protected] |
147 | [email protected] "&" | 147 | [email protected] "&" |
148 | REFERENCE[email protected] | 148 | [email protected] |
149 | [email protected] "&" | 149 | [email protected] "&" |
150 | [email protected] | 150 | [email protected] |
151 | [email protected] | 151 | [email protected] |
diff --git a/crates/ra_syntax/test_data/parser/ok/0066_default_const.rast b/crates/ra_syntax/test_data/parser/ok/0066_default_const.rast deleted file mode 100644 index 6246a31a6..000000000 --- a/crates/ra_syntax/test_data/parser/ok/0066_default_const.rast +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "impl" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] "T" | ||
10 | [email protected] " " | ||
11 | [email protected] "for" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] "Foo" | ||
18 | [email protected] " " | ||
19 | [email protected] | ||
20 | [email protected] "{" | ||
21 | [email protected] "\n " | ||
22 | [email protected] | ||
23 | [email protected] "default" | ||
24 | [email protected] " " | ||
25 | [email protected] "const" | ||
26 | [email protected] " " | ||
27 | [email protected] | ||
28 | [email protected] "f" | ||
29 | [email protected] ":" | ||
30 | [email protected] " " | ||
31 | [email protected] | ||
32 | [email protected] | ||
33 | [email protected] | ||
34 | [email protected] | ||
35 | [email protected] "u8" | ||
36 | [email protected] " " | ||
37 | [email protected] "=" | ||
38 | [email protected] " " | ||
39 | [email protected] | ||
40 | [email protected] "0" | ||
41 | [email protected] ";" | ||
42 | [email protected] "\n" | ||
43 | [email protected] "}" | ||
44 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/ok/0066_default_const.rs b/crates/ra_syntax/test_data/parser/ok/0066_default_const.rs deleted file mode 100644 index dfb3b92dc..000000000 --- a/crates/ra_syntax/test_data/parser/ok/0066_default_const.rs +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | impl T for Foo { | ||
2 | default const f: u8 = 0; | ||
3 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/ok/0066_default_modifier.rast b/crates/ra_syntax/test_data/parser/ok/0066_default_modifier.rast new file mode 100644 index 000000000..e9b57ec3b --- /dev/null +++ b/crates/ra_syntax/test_data/parser/ok/0066_default_modifier.rast | |||
@@ -0,0 +1,218 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "trait" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "T" | ||
7 | [email protected] " " | ||
8 | [email protected] | ||
9 | [email protected] "{" | ||
10 | [email protected] "\n " | ||
11 | [email protected] | ||
12 | [email protected] "default" | ||
13 | [email protected] " " | ||
14 | [email protected] "type" | ||
15 | [email protected] " " | ||
16 | [email protected] | ||
17 | [email protected] "T" | ||
18 | [email protected] " " | ||
19 | [email protected] "=" | ||
20 | [email protected] " " | ||
21 | [email protected] | ||
22 | [email protected] | ||
23 | [email protected] | ||
24 | [email protected] | ||
25 | [email protected] "Bar" | ||
26 | [email protected] ";" | ||
27 | [email protected] "\n " | ||
28 | [email protected] | ||
29 | [email protected] "default" | ||
30 | [email protected] " " | ||
31 | [email protected] "const" | ||
32 | [email protected] " " | ||
33 | [email protected] | ||
34 | [email protected] "f" | ||
35 | [email protected] ":" | ||
36 | [email protected] " " | ||
37 | [email protected] | ||
38 | [email protected] | ||
39 | [email protected] | ||
40 | [email protected] | ||
41 | [email protected] "u8" | ||
42 | [email protected] " " | ||
43 | [email protected] "=" | ||
44 | [email protected] " " | ||
45 | [email protected] | ||
46 | [email protected] "0" | ||
47 | [email protected] ";" | ||
48 | [email protected] "\n " | ||
49 | [email protected] | ||
50 | [email protected] "default" | ||
51 | [email protected] " " | ||
52 | [email protected] "fn" | ||
53 | [email protected] " " | ||
54 | [email protected] | ||
55 | [email protected] "foo" | ||
56 | [email protected] | ||
57 | [email protected] "(" | ||
58 | [email protected] ")" | ||
59 | [email protected] " " | ||
60 | [email protected] | ||
61 | [email protected] "{" | ||
62 | [email protected] "}" | ||
63 | [email protected] "\n " | ||
64 | [email protected] | ||
65 | [email protected] "default" | ||
66 | [email protected] " " | ||
67 | [email protected] "unsafe" | ||
68 | [email protected] " " | ||
69 | [email protected] "fn" | ||
70 | [email protected] " " | ||
71 | [email protected] | ||
72 | [email protected] "bar" | ||
73 | [email protected] | ||
74 | [email protected] "(" | ||
75 | [email protected] ")" | ||
76 | [email protected] " " | ||
77 | [email protected] | ||
78 | [email protected] "{" | ||
79 | [email protected] "}" | ||
80 | [email protected] "\n" | ||
81 | [email protected] "}" | ||
82 | [email protected] "\n\n" | ||
83 | [email protected] | ||
84 | [email protected] "impl" | ||
85 | [email protected] " " | ||
86 | [email protected] | ||
87 | [email protected] | ||
88 | [email protected] | ||
89 | [email protected] | ||
90 | [email protected] "T" | ||
91 | [email protected] " " | ||
92 | [email protected] "for" | ||
93 | [email protected] " " | ||
94 | [email protected] | ||
95 | [email protected] | ||
96 | [email protected] | ||
97 | [email protected] | ||
98 | [email protected] "Foo" | ||
99 | [email protected] " " | ||
100 | [email protected] | ||
101 | [email protected] "{" | ||
102 | [email protected] "\n " | ||
103 | [email protected] | ||
104 | [email protected] "default" | ||
105 | [email protected] " " | ||
106 | [email protected] "type" | ||
107 | [email protected] " " | ||
108 | [email protected] | ||
109 | [email protected] "T" | ||
110 | [email protected] " " | ||
111 | [email protected] "=" | ||
112 | [email protected] " " | ||
113 | [email protected] | ||
114 | [email protected] | ||
115 | [email protected] | ||
116 | [email protected] | ||
117 | [email protected] "Bar" | ||
118 | [email protected] ";" | ||
119 | [email protected] "\n " | ||
120 | [email protected] | ||
121 | [email protected] "default" | ||
122 | [email protected] " " | ||
123 | [email protected] "const" | ||
124 | [email protected] " " | ||
125 | [email protected] | ||
126 | [email protected] "f" | ||
127 | [email protected] ":" | ||
128 | [email protected] " " | ||
129 | [email protected] | ||
130 | [email protected] | ||
131 | [email protected] | ||
132 | [email protected] | ||
133 | [email protected] "u8" | ||
134 | [email protected] " " | ||
135 | [email protected] "=" | ||
136 | [email protected] " " | ||
137 | [email protected] | ||
138 | [email protected] "0" | ||
139 | [email protected] ";" | ||
140 | [email protected] "\n " | ||
141 | [email protected] | ||
142 | [email protected] "default" | ||
143 | [email protected] " " | ||
144 | [email protected] "fn" | ||
145 | [email protected] " " | ||
146 | [email protected] | ||
147 | [email protected] "foo" | ||
148 | [email protected] | ||
149 | [email protected] "(" | ||
150 | [email protected] ")" | ||
151 | [email protected] " " | ||
152 | [email protected] | ||
153 | [email protected] "{" | ||
154 | [email protected] "}" | ||
155 | [email protected] "\n " | ||
156 | [email protected] | ||
157 | [email protected] "default" | ||
158 | [email protected] " " | ||
159 | [email protected] "unsafe" | ||
160 | [email protected] " " | ||
161 | [email protected] "fn" | ||
162 | [email protected] " " | ||
163 | [email protected] | ||
164 | [email protected] "bar" | ||
165 | [email protected] | ||
166 | [email protected] "(" | ||
167 | [email protected] ")" | ||
168 | [email protected] " " | ||
169 | [email protected] | ||
170 | [email protected] "{" | ||
171 | [email protected] "}" | ||
172 | [email protected] "\n" | ||
173 | [email protected] "}" | ||
174 | [email protected] "\n\n" | ||
175 | [email protected] | ||
176 | [email protected] "default" | ||
177 | [email protected] " " | ||
178 | [email protected] "impl" | ||
179 | [email protected] " " | ||
180 | [email protected] | ||
181 | [email protected] | ||
182 | [email protected] | ||
183 | [email protected] | ||
184 | [email protected] "T" | ||
185 | [email protected] " " | ||
186 | [email protected] "for" | ||
187 | [email protected] " " | ||
188 | [email protected] | ||
189 | [email protected] "(" | ||
190 | [email protected] ")" | ||
191 | [email protected] " " | ||
192 | [email protected] | ||
193 | [email protected] "{" | ||
194 | [email protected] "}" | ||
195 | [email protected] "\n" | ||
196 | [email protected] | ||
197 | [email protected] "default" | ||
198 | [email protected] " " | ||
199 | [email protected] "unsafe" | ||
200 | [email protected] " " | ||
201 | [email protected] "impl" | ||
202 | [email protected] " " | ||
203 | [email protected] | ||
204 | [email protected] | ||
205 | [email protected] | ||
206 | [email protected] | ||
207 | [email protected] "T" | ||
208 | [email protected] " " | ||
209 | [email protected] "for" | ||
210 | [email protected] " " | ||
211 | [email protected] | ||
212 | [email protected] "(" | ||
213 | [email protected] ")" | ||
214 | [email protected] " " | ||
215 | [email protected] | ||
216 | [email protected] "{" | ||
217 | [email protected] "}" | ||
218 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/ok/0066_default_modifier.rs b/crates/ra_syntax/test_data/parser/ok/0066_default_modifier.rs new file mode 100644 index 000000000..e443e3495 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/ok/0066_default_modifier.rs | |||
@@ -0,0 +1,16 @@ | |||
1 | trait T { | ||
2 | default type T = Bar; | ||
3 | default const f: u8 = 0; | ||
4 | default fn foo() {} | ||
5 | default unsafe fn bar() {} | ||
6 | } | ||
7 | |||
8 | impl T for Foo { | ||
9 | default type T = Bar; | ||
10 | default const f: u8 = 0; | ||
11 | default fn foo() {} | ||
12 | default unsafe fn bar() {} | ||
13 | } | ||
14 | |||
15 | default impl T for () {} | ||
16 | default unsafe impl T for () {} | ||
diff --git a/crates/ra_syntax/test_data/parser/ok/0067_where_for_pred.rast b/crates/ra_syntax/test_data/parser/ok/0067_where_for_pred.rast index fae9467fc..8f8639a37 100644 --- a/crates/ra_syntax/test_data/parser/ok/0067_where_for_pred.rast +++ b/crates/ra_syntax/test_data/parser/ok/0067_where_for_pred.rast | |||
@@ -42,7 +42,7 @@ [email protected] | |||
42 | [email protected] | 42 | [email protected] |
43 | [email protected] "(" | 43 | [email protected] "(" |
44 | [email protected] | 44 | [email protected] |
45 | REFERENCE[email protected] | 45 | [email protected] |
46 | [email protected] "&" | 46 | [email protected] "&" |
47 | [email protected] "\'a" | 47 | [email protected] "\'a" |
48 | [email protected] " " | 48 | [email protected] " " |
@@ -85,7 +85,7 @@ [email protected] | |||
85 | [email protected] "\'a" | 85 | [email protected] "\'a" |
86 | [email protected] ">" | 86 | [email protected] ">" |
87 | [email protected] " " | 87 | [email protected] " " |
88 | REFERENCE[email protected] | 88 | [email protected] |
89 | [email protected] "&" | 89 | [email protected] "&" |
90 | [email protected] "\'a" | 90 | [email protected] "\'a" |
91 | [email protected] " " | 91 | [email protected] " " |
@@ -138,7 +138,7 @@ [email protected] | |||
138 | [email protected] " " | 138 | [email protected] " " |
139 | [email protected] | 139 | [email protected] |
140 | [email protected] "(" | 140 | [email protected] "(" |
141 | REFERENCE[email protected] | 141 | [email protected] |
142 | [email protected] "&" | 142 | [email protected] "&" |
143 | [email protected] "\'a" | 143 | [email protected] "\'a" |
144 | [email protected] " " | 144 | [email protected] " " |
@@ -160,7 +160,7 @@ [email protected] | |||
160 | [email protected] | 160 | [email protected] |
161 | [email protected] "(" | 161 | [email protected] "(" |
162 | [email protected] | 162 | [email protected] |
163 | REFERENCE[email protected] | 163 | [email protected] |
164 | [email protected] "&" | 164 | [email protected] "&" |
165 | [email protected] "\'a" | 165 | [email protected] "\'a" |
166 | [email protected] " " | 166 | [email protected] " " |
@@ -205,7 +205,7 @@ [email protected] | |||
205 | [email protected] " " | 205 | [email protected] " " |
206 | [email protected] | 206 | [email protected] |
207 | [email protected] "[" | 207 | [email protected] "[" |
208 | REFERENCE[email protected] | 208 | [email protected] |
209 | [email protected] "&" | 209 | [email protected] "&" |
210 | [email protected] "\'a" | 210 | [email protected] "\'a" |
211 | [email protected] " " | 211 | [email protected] " " |
@@ -250,7 +250,7 @@ [email protected] | |||
250 | [email protected] "_t" | 250 | [email protected] "_t" |
251 | [email protected] ":" | 251 | [email protected] ":" |
252 | [email protected] " " | 252 | [email protected] " " |
253 | REFERENCE[email protected] | 253 | [email protected] |
254 | [email protected] "&" | 254 | [email protected] "&" |
255 | [email protected] | 255 | [email protected] |
256 | [email protected] | 256 | [email protected] |
@@ -275,7 +275,7 @@ [email protected] | |||
275 | [email protected] | 275 | [email protected] |
276 | [email protected] | 276 | [email protected] |
277 | [email protected] "<" | 277 | [email protected] "<" |
278 | REFERENCE[email protected] | 278 | [email protected] |
279 | [email protected] "&" | 279 | [email protected] "&" |
280 | [email protected] "\'a" | 280 | [email protected] "\'a" |
281 | [email protected] " " | 281 | [email protected] " " |
@@ -347,12 +347,12 @@ [email protected] | |||
347 | [email protected] "\'b" | 347 | [email protected] "\'b" |
348 | [email protected] ">" | 348 | [email protected] ">" |
349 | [email protected] " " | 349 | [email protected] " " |
350 | FN_POINTE[email protected] | 350 | [email protected] |
351 | [email protected] "fn" | 351 | [email protected] "fn" |
352 | [email protected] | 352 | [email protected] |
353 | [email protected] "(" | 353 | [email protected] "(" |
354 | [email protected] | 354 | [email protected] |
355 | REFERENCE[email protected] | 355 | [email protected] |
356 | [email protected] "&" | 356 | [email protected] "&" |
357 | [email protected] "\'a" | 357 | [email protected] "\'a" |
358 | [email protected] " " | 358 | [email protected] " " |
@@ -364,7 +364,7 @@ [email protected] | |||
364 | [email protected] "," | 364 | [email protected] "," |
365 | [email protected] " " | 365 | [email protected] " " |
366 | [email protected] | 366 | [email protected] |
367 | REFERENCE[email protected] | 367 | [email protected] |
368 | [email protected] "&" | 368 | [email protected] "&" |
369 | [email protected] "\'b" | 369 | [email protected] "\'b" |
370 | [email protected] " " | 370 | [email protected] " " |
diff --git a/crates/ra_syntax/test_data/parser/ok/0068_item_modifiers.rast b/crates/ra_syntax/test_data/parser/ok/0068_item_modifiers.rast new file mode 100644 index 000000000..50a6d8ee9 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/ok/0068_item_modifiers.rast | |||
@@ -0,0 +1,218 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "async" | ||
4 | [email protected] " " | ||
5 | [email protected] "fn" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] "foo" | ||
9 | [email protected] | ||
10 | [email protected] "(" | ||
11 | [email protected] ")" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] "{" | ||
15 | [email protected] "}" | ||
16 | [email protected] "\n" | ||
17 | [email protected] | ||
18 | [email protected] | ||
19 | [email protected] "extern" | ||
20 | [email protected] " " | ||
21 | [email protected] "fn" | ||
22 | [email protected] " " | ||
23 | [email protected] | ||
24 | [email protected] "foo" | ||
25 | [email protected] | ||
26 | [email protected] "(" | ||
27 | [email protected] ")" | ||
28 | [email protected] " " | ||
29 | [email protected] | ||
30 | [email protected] "{" | ||
31 | [email protected] "}" | ||
32 | [email protected] "\n" | ||
33 | [email protected] | ||
34 | [email protected] "const" | ||
35 | [email protected] " " | ||
36 | [email protected] "fn" | ||
37 | [email protected] " " | ||
38 | [email protected] | ||
39 | [email protected] "foo" | ||
40 | [email protected] | ||
41 | [email protected] "(" | ||
42 | [email protected] ")" | ||
43 | [email protected] " " | ||
44 | [email protected] | ||
45 | [email protected] "{" | ||
46 | [email protected] "}" | ||
47 | [email protected] "\n" | ||
48 | [email protected] | ||
49 | [email protected] "const" | ||
50 | [email protected] " " | ||
51 | [email protected] "unsafe" | ||
52 | [email protected] " " | ||
53 | [email protected] "fn" | ||
54 | [email protected] " " | ||
55 | [email protected] | ||
56 | [email protected] "foo" | ||
57 | [email protected] | ||
58 | [email protected] "(" | ||
59 | [email protected] ")" | ||
60 | [email protected] " " | ||
61 | [email protected] | ||
62 | [email protected] "{" | ||
63 | [email protected] "}" | ||
64 | [email protected] "\n" | ||
65 | [email protected] | ||
66 | [email protected] "unsafe" | ||
67 | [email protected] " " | ||
68 | [email protected] | ||
69 | [email protected] "extern" | ||
70 | [email protected] " " | ||
71 | [email protected] "\"C\"" | ||
72 | [email protected] " " | ||
73 | [email protected] "fn" | ||
74 | [email protected] " " | ||
75 | [email protected] | ||
76 | [email protected] "foo" | ||
77 | [email protected] | ||
78 | [email protected] "(" | ||
79 | [email protected] ")" | ||
80 | [email protected] " " | ||
81 | [email protected] | ||
82 | [email protected] "{" | ||
83 | [email protected] "}" | ||
84 | [email protected] "\n" | ||
85 | [email protected] | ||
86 | [email protected] "unsafe" | ||
87 | [email protected] " " | ||
88 | [email protected] "fn" | ||
89 | [email protected] " " | ||
90 | [email protected] | ||
91 | [email protected] "foo" | ||
92 | [email protected] | ||
93 | [email protected] "(" | ||
94 | [email protected] ")" | ||
95 | [email protected] " " | ||
96 | [email protected] | ||
97 | [email protected] "{" | ||
98 | [email protected] "}" | ||
99 | [email protected] "\n" | ||
100 | [email protected] | ||
101 | [email protected] "async" | ||
102 | [email protected] " " | ||
103 | [email protected] "unsafe" | ||
104 | [email protected] " " | ||
105 | [email protected] "fn" | ||
106 | [email protected] " " | ||
107 | [email protected] | ||
108 | [email protected] "foo" | ||
109 | [email protected] | ||
110 | [email protected] "(" | ||
111 | [email protected] ")" | ||
112 | [email protected] " " | ||
113 | [email protected] | ||
114 | [email protected] "{" | ||
115 | [email protected] "}" | ||
116 | [email protected] "\n" | ||
117 | [email protected] | ||
118 | [email protected] "const" | ||
119 | [email protected] " " | ||
120 | [email protected] "unsafe" | ||
121 | [email protected] " " | ||
122 | [email protected] "fn" | ||
123 | [email protected] " " | ||
124 | [email protected] | ||
125 | [email protected] "bar" | ||
126 | [email protected] | ||
127 | [email protected] "(" | ||
128 | [email protected] ")" | ||
129 | [email protected] " " | ||
130 | [email protected] | ||
131 | [email protected] "{" | ||
132 | [email protected] "}" | ||
133 | [email protected] "\n\n" | ||
134 | [email protected] | ||
135 | [email protected] "unsafe" | ||
136 | [email protected] " " | ||
137 | [email protected] "trait" | ||
138 | [email protected] " " | ||
139 | [email protected] | ||
140 | [email protected] "T" | ||
141 | [email protected] " " | ||
142 | [email protected] | ||
143 | [email protected] "{" | ||
144 | [email protected] "}" | ||
145 | [email protected] "\n" | ||
146 | [email protected] | ||
147 | [email protected] "auto" | ||
148 | [email protected] " " | ||
149 | [email protected] "trait" | ||
150 | [email protected] " " | ||
151 | [email protected] | ||
152 | [email protected] "T" | ||
153 | [email protected] " " | ||
154 | [email protected] | ||
155 | [email protected] "{" | ||
156 | [email protected] "}" | ||
157 | [email protected] "\n" | ||
158 | [email protected] | ||
159 | [email protected] "unsafe" | ||
160 | [email protected] " " | ||
161 | [email protected] "auto" | ||
162 | [email protected] " " | ||
163 | [email protected] "trait" | ||
164 | [email protected] " " | ||
165 | [email protected] | ||
166 | [email protected] "T" | ||
167 | [email protected] " " | ||
168 | [email protected] | ||
169 | [email protected] "{" | ||
170 | [email protected] "}" | ||
171 | [email protected] "\n\n" | ||
172 | [email protected] | ||
173 | [email protected] "unsafe" | ||
174 | [email protected] " " | ||
175 | [email protected] "impl" | ||
176 | [email protected] " " | ||
177 | [email protected] | ||
178 | [email protected] | ||
179 | [email protected] | ||
180 | [email protected] | ||
181 | [email protected] "Foo" | ||
182 | [email protected] " " | ||
183 | [email protected] | ||
184 | [email protected] "{" | ||
185 | [email protected] "}" | ||
186 | [email protected] "\n" | ||
187 | [email protected] | ||
188 | [email protected] "default" | ||
189 | [email protected] " " | ||
190 | [email protected] "impl" | ||
191 | [email protected] " " | ||
192 | [email protected] | ||
193 | [email protected] | ||
194 | [email protected] | ||
195 | [email protected] | ||
196 | [email protected] "Foo" | ||
197 | [email protected] " " | ||
198 | [email protected] | ||
199 | [email protected] "{" | ||
200 | [email protected] "}" | ||
201 | [email protected] "\n" | ||
202 | [email protected] | ||
203 | [email protected] "unsafe" | ||
204 | [email protected] " " | ||
205 | [email protected] "default" | ||
206 | [email protected] " " | ||
207 | [email protected] "impl" | ||
208 | [email protected] " " | ||
209 | [email protected] | ||
210 | [email protected] | ||
211 | [email protected] | ||
212 | [email protected] | ||
213 | [email protected] "Foo" | ||
214 | [email protected] " " | ||
215 | [email protected] | ||
216 | [email protected] "{" | ||
217 | [email protected] "}" | ||
218 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/ok/0068_item_modifiers.rs b/crates/ra_syntax/test_data/parser/ok/0068_item_modifiers.rs new file mode 100644 index 000000000..8d697c04b --- /dev/null +++ b/crates/ra_syntax/test_data/parser/ok/0068_item_modifiers.rs | |||
@@ -0,0 +1,16 @@ | |||
1 | async fn foo() {} | ||
2 | extern fn foo() {} | ||
3 | const fn foo() {} | ||
4 | const unsafe fn foo() {} | ||
5 | unsafe extern "C" fn foo() {} | ||
6 | unsafe fn foo() {} | ||
7 | async unsafe fn foo() {} | ||
8 | const unsafe fn bar() {} | ||
9 | |||
10 | unsafe trait T {} | ||
11 | auto trait T {} | ||
12 | unsafe auto trait T {} | ||
13 | |||
14 | unsafe impl Foo {} | ||
15 | default impl Foo {} | ||
16 | unsafe default impl Foo {} | ||
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs index 25554f583..d68791cf1 100644 --- a/crates/ra_text_edit/src/lib.rs +++ b/crates/ra_text_edit/src/lib.rs | |||
@@ -76,10 +76,6 @@ impl TextEdit { | |||
76 | self.indels.iter() | 76 | self.indels.iter() |
77 | } | 77 | } |
78 | 78 | ||
79 | pub fn into_iter(self) -> vec::IntoIter<Indel> { | ||
80 | self.indels.into_iter() | ||
81 | } | ||
82 | |||
83 | pub fn apply(&self, text: &mut String) { | 79 | pub fn apply(&self, text: &mut String) { |
84 | match self.len() { | 80 | match self.len() { |
85 | 0 => return, | 81 | 0 => return, |
@@ -141,6 +137,15 @@ impl TextEdit { | |||
141 | } | 137 | } |
142 | } | 138 | } |
143 | 139 | ||
140 | impl IntoIterator for TextEdit { | ||
141 | type Item = Indel; | ||
142 | type IntoIter = vec::IntoIter<Self::Item>; | ||
143 | |||
144 | fn into_iter(self) -> Self::IntoIter { | ||
145 | self.indels.into_iter() | ||
146 | } | ||
147 | } | ||
148 | |||
144 | impl TextEditBuilder { | 149 | impl TextEditBuilder { |
145 | pub fn replace(&mut self, range: TextRange, replace_with: String) { | 150 | pub fn replace(&mut self, range: TextRange, replace_with: String) { |
146 | self.indels.push(Indel::replace(range, replace_with)) | 151 | self.indels.push(Indel::replace(range, replace_with)) |
diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 8faf1cc67..20c3f5eab 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs | |||
@@ -107,7 +107,7 @@ fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usi | |||
107 | for (idx, child) in subtree.token_trees.iter().enumerate() { | 107 | for (idx, child) in subtree.token_trees.iter().enumerate() { |
108 | print_debug_token(f, child, level + 1)?; | 108 | print_debug_token(f, child, level + 1)?; |
109 | if idx != subtree.token_trees.len() - 1 { | 109 | if idx != subtree.token_trees.len() - 1 { |
110 | writeln!(f, "")?; | 110 | writeln!(f)?; |
111 | } | 111 | } |
112 | } | 112 | } |
113 | } | 113 | } |
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs index f16e35d86..d3081e88b 100644 --- a/crates/rust-analyzer/src/bin/args.rs +++ b/crates/rust-analyzer/src/bin/args.rs | |||
@@ -44,15 +44,16 @@ pub(crate) enum Command { | |||
44 | ProcMacro, | 44 | ProcMacro, |
45 | RunServer, | 45 | RunServer, |
46 | Version, | 46 | Version, |
47 | Help, | ||
47 | } | 48 | } |
48 | 49 | ||
49 | impl Args { | 50 | impl Args { |
50 | pub(crate) fn parse() -> Result<Result<Args, HelpPrinted>> { | 51 | pub(crate) fn parse() -> Result<Args> { |
51 | let mut matches = Arguments::from_env(); | 52 | let mut matches = Arguments::from_env(); |
52 | 53 | ||
53 | if matches.contains("--version") { | 54 | if matches.contains("--version") { |
54 | matches.finish().or_else(handle_extra_flags)?; | 55 | matches.finish().or_else(handle_extra_flags)?; |
55 | return Ok(Ok(Args { verbosity: Verbosity::Normal, command: Command::Version })); | 56 | return Ok(Args { verbosity: Verbosity::Normal, command: Command::Version }); |
56 | } | 57 | } |
57 | 58 | ||
58 | let verbosity = match ( | 59 | let verbosity = match ( |
@@ -68,15 +69,16 @@ impl Args { | |||
68 | (false, true, true) => bail!("Invalid flags: -q conflicts with -v"), | 69 | (false, true, true) => bail!("Invalid flags: -q conflicts with -v"), |
69 | }; | 70 | }; |
70 | 71 | ||
72 | let help = Ok(Args { verbosity, command: Command::Help }); | ||
71 | let subcommand = match matches.subcommand()? { | 73 | let subcommand = match matches.subcommand()? { |
72 | Some(it) => it, | 74 | Some(it) => it, |
73 | None => { | 75 | None => { |
74 | if matches.contains(["-h", "--help"]) { | 76 | if matches.contains(["-h", "--help"]) { |
75 | print_subcommands(); | 77 | print_subcommands(); |
76 | return Ok(Err(HelpPrinted)); | 78 | return help; |
77 | } | 79 | } |
78 | matches.finish().or_else(handle_extra_flags)?; | 80 | matches.finish().or_else(handle_extra_flags)?; |
79 | return Ok(Ok(Args { verbosity, command: Command::RunServer })); | 81 | return Ok(Args { verbosity, command: Command::RunServer }); |
80 | } | 82 | } |
81 | }; | 83 | }; |
82 | let command = match subcommand.as_str() { | 84 | let command = match subcommand.as_str() { |
@@ -93,7 +95,7 @@ FLAGS: | |||
93 | -h, --help Prints help information | 95 | -h, --help Prints help information |
94 | --no-dump" | 96 | --no-dump" |
95 | ); | 97 | ); |
96 | return Ok(Err(HelpPrinted)); | 98 | return help; |
97 | } | 99 | } |
98 | 100 | ||
99 | let no_dump = matches.contains("--no-dump"); | 101 | let no_dump = matches.contains("--no-dump"); |
@@ -112,7 +114,7 @@ USAGE: | |||
112 | FLAGS: | 114 | FLAGS: |
113 | -h, --help Prints help inforamtion" | 115 | -h, --help Prints help inforamtion" |
114 | ); | 116 | ); |
115 | return Ok(Err(HelpPrinted)); | 117 | return help; |
116 | } | 118 | } |
117 | 119 | ||
118 | matches.finish().or_else(handle_extra_flags)?; | 120 | matches.finish().or_else(handle_extra_flags)?; |
@@ -132,7 +134,7 @@ FLAGS: | |||
132 | -h, --help Prints help information | 134 | -h, --help Prints help information |
133 | -r, --rainbow" | 135 | -r, --rainbow" |
134 | ); | 136 | ); |
135 | return Ok(Err(HelpPrinted)); | 137 | return help; |
136 | } | 138 | } |
137 | 139 | ||
138 | let rainbow = matches.contains(["-r", "--rainbow"]); | 140 | let rainbow = matches.contains(["-r", "--rainbow"]); |
@@ -166,7 +168,7 @@ OPTIONS: | |||
166 | ARGS: | 168 | ARGS: |
167 | <PATH>" | 169 | <PATH>" |
168 | ); | 170 | ); |
169 | return Ok(Err(HelpPrinted)); | 171 | return help; |
170 | } | 172 | } |
171 | 173 | ||
172 | let randomize = matches.contains("--randomize"); | 174 | let randomize = matches.contains("--randomize"); |
@@ -220,7 +222,7 @@ OPTIONS: | |||
220 | ARGS: | 222 | ARGS: |
221 | <PATH> Project to analyse" | 223 | <PATH> Project to analyse" |
222 | ); | 224 | ); |
223 | return Ok(Err(HelpPrinted)); | 225 | return help; |
224 | } | 226 | } |
225 | 227 | ||
226 | let path: PathBuf = matches.opt_value_from_str("--project")?.unwrap_or_default(); | 228 | let path: PathBuf = matches.opt_value_from_str("--project")?.unwrap_or_default(); |
@@ -266,7 +268,7 @@ FLAGS: | |||
266 | ARGS: | 268 | ARGS: |
267 | <PATH>" | 269 | <PATH>" |
268 | ); | 270 | ); |
269 | return Ok(Err(HelpPrinted)); | 271 | return help; |
270 | } | 272 | } |
271 | 273 | ||
272 | let load_output_dirs = matches.contains("--load-output-dirs"); | 274 | let load_output_dirs = matches.contains("--load-output-dirs"); |
@@ -302,7 +304,7 @@ FLAGS: | |||
302 | ARGS: | 304 | ARGS: |
303 | <RULE> A structured search replace rule" | 305 | <RULE> A structured search replace rule" |
304 | ); | 306 | ); |
305 | return Ok(Err(HelpPrinted)); | 307 | return help; |
306 | } | 308 | } |
307 | let mut rules = Vec::new(); | 309 | let mut rules = Vec::new(); |
308 | while let Some(rule) = matches.free_from_str()? { | 310 | while let Some(rule) = matches.free_from_str()? { |
@@ -329,7 +331,7 @@ FLAGS: | |||
329 | ARGS: | 331 | ARGS: |
330 | <PATTERN> A structured search pattern" | 332 | <PATTERN> A structured search pattern" |
331 | ); | 333 | ); |
332 | return Ok(Err(HelpPrinted)); | 334 | return help; |
333 | } | 335 | } |
334 | let debug_snippet = matches.opt_value_from_str("--debug")?; | 336 | let debug_snippet = matches.opt_value_from_str("--debug")?; |
335 | let mut patterns = Vec::new(); | 337 | let mut patterns = Vec::new(); |
@@ -340,10 +342,10 @@ ARGS: | |||
340 | } | 342 | } |
341 | _ => { | 343 | _ => { |
342 | print_subcommands(); | 344 | print_subcommands(); |
343 | return Ok(Err(HelpPrinted)); | 345 | return help; |
344 | } | 346 | } |
345 | }; | 347 | }; |
346 | Ok(Ok(Args { verbosity, command })) | 348 | Ok(Args { verbosity, command }) |
347 | } | 349 | } |
348 | } | 350 | } |
349 | 351 | ||
@@ -371,8 +373,6 @@ SUBCOMMANDS: | |||
371 | ) | 373 | ) |
372 | } | 374 | } |
373 | 375 | ||
374 | pub(crate) struct HelpPrinted; | ||
375 | |||
376 | fn handle_extra_flags(e: pico_args::Error) -> Result<()> { | 376 | fn handle_extra_flags(e: pico_args::Error) -> Result<()> { |
377 | if let pico_args::Error::UnusedArgsLeft(flags) = e { | 377 | if let pico_args::Error::UnusedArgsLeft(flags) = e { |
378 | let mut invalid_flags = String::new(); | 378 | let mut invalid_flags = String::new(); |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index ff8234495..fc7f8b01d 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | //! Based on cli flags, either spawns an LSP server, or runs a batch analysis | 3 | //! Based on cli flags, either spawns an LSP server, or runs a batch analysis |
4 | mod args; | 4 | mod args; |
5 | 5 | ||
6 | use std::convert::TryFrom; | 6 | use std::{convert::TryFrom, process}; |
7 | 7 | ||
8 | use lsp_server::Connection; | 8 | use lsp_server::Connection; |
9 | use ra_project_model::ProjectManifest; | 9 | use ra_project_model::ProjectManifest; |
@@ -14,18 +14,20 @@ use rust_analyzer::{ | |||
14 | }; | 14 | }; |
15 | use vfs::AbsPathBuf; | 15 | use vfs::AbsPathBuf; |
16 | 16 | ||
17 | use crate::args::HelpPrinted; | ||
18 | |||
19 | #[cfg(all(feature = "mimalloc"))] | 17 | #[cfg(all(feature = "mimalloc"))] |
20 | #[global_allocator] | 18 | #[global_allocator] |
21 | static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; | 19 | static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; |
22 | 20 | ||
23 | fn main() -> Result<()> { | 21 | fn main() { |
22 | if let Err(err) = try_main() { | ||
23 | eprintln!("{}", err); | ||
24 | process::exit(101); | ||
25 | } | ||
26 | } | ||
27 | |||
28 | fn try_main() -> Result<()> { | ||
24 | setup_logging()?; | 29 | setup_logging()?; |
25 | let args = match args::Args::parse()? { | 30 | let args = args::Args::parse()?; |
26 | Ok(it) => it, | ||
27 | Err(HelpPrinted) => return Ok(()), | ||
28 | }; | ||
29 | match args.command { | 31 | match args.command { |
30 | args::Command::RunServer => run_server()?, | 32 | args::Command::RunServer => run_server()?, |
31 | args::Command::ProcMacro => ra_proc_macro_srv::cli::run()?, | 33 | args::Command::ProcMacro => ra_proc_macro_srv::cli::run()?, |
@@ -45,6 +47,7 @@ fn main() -> Result<()> { | |||
45 | cli::search_for_patterns(patterns, debug_snippet)?; | 47 | cli::search_for_patterns(patterns, debug_snippet)?; |
46 | } | 48 | } |
47 | args::Command::Version => println!("rust-analyzer {}", env!("REV")), | 49 | args::Command::Version => println!("rust-analyzer {}", env!("REV")), |
50 | args::Command::Help => {} | ||
48 | } | 51 | } |
49 | Ok(()) | 52 | Ok(()) |
50 | } | 53 | } |
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 37d695448..92a743fd8 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
@@ -76,7 +76,9 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti | |||
76 | token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(), | 76 | token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(), |
77 | }, | 77 | }, |
78 | 78 | ||
79 | document_provider: Some(SemanticTokensDocumentProvider::Bool(true)), | 79 | document_provider: Some(SemanticTokensDocumentProvider::Edits { |
80 | edits: Some(true), | ||
81 | }), | ||
80 | range_provider: Some(true), | 82 | range_provider: Some(true), |
81 | work_done_progress_options: Default::default(), | 83 | work_done_progress_options: Default::default(), |
82 | } | 84 | } |
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 721d41a58..0d386841e 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -72,7 +72,7 @@ impl AnalysisStatsCmd { | |||
72 | shuffle(&mut rng, &mut krates); | 72 | shuffle(&mut rng, &mut krates); |
73 | } | 73 | } |
74 | for krate in krates { | 74 | for krate in krates { |
75 | let module = krate.root_module(db).expect("crate without root module"); | 75 | let module = krate.root_module(db); |
76 | let file_id = module.definition_source(db).file_id; | 76 | let file_id = module.definition_source(db).file_id; |
77 | let file_id = file_id.original_file(db); | 77 | let file_id = file_id.original_file(db); |
78 | let source_root = db.file_source_root(file_id); | 78 | let source_root = db.file_source_root(file_id); |
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 4ac8c8772..f17fc5dfe 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs | |||
@@ -28,7 +28,7 @@ pub fn diagnostics( | |||
28 | let mut work = Vec::new(); | 28 | let mut work = Vec::new(); |
29 | let krates = Crate::all(db); | 29 | let krates = Crate::all(db); |
30 | for krate in krates { | 30 | for krate in krates { |
31 | let module = krate.root_module(db).expect("crate without root module"); | 31 | let module = krate.root_module(db); |
32 | let file_id = module.definition_source(db).file_id; | 32 | let file_id = module.definition_source(db).file_id; |
33 | let file_id = file_id.original_file(db); | 33 | let file_id = file_id.original_file(db); |
34 | let source_root = db.file_source_root(file_id); | 34 | let source_root = db.file_source_root(file_id); |
diff --git a/crates/rust-analyzer/src/document.rs b/crates/rust-analyzer/src/document.rs index 43219e633..e882c9865 100644 --- a/crates/rust-analyzer/src/document.rs +++ b/crates/rust-analyzer/src/document.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | //! In-memory document information. | 1 | //! In-memory document information. |
2 | 2 | ||
3 | /// Information about a document that the Language Client | 3 | /// Information about a document that the Language Client |
4 | // knows about. | 4 | /// knows about. |
5 | // Its lifetime is driven by the textDocument/didOpen and textDocument/didClose | 5 | /// Its lifetime is driven by the textDocument/didOpen and textDocument/didClose |
6 | // client notifications. | 6 | /// client notifications. |
7 | #[derive(Debug, Clone)] | 7 | #[derive(Debug, Clone)] |
8 | pub(crate) struct DocumentData { | 8 | pub(crate) struct DocumentData { |
9 | pub version: Option<i64>, | 9 | pub version: Option<i64>, |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index b2d65a6d1..658a50d15 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -7,8 +7,8 @@ use std::{sync::Arc, time::Instant}; | |||
7 | 7 | ||
8 | use crossbeam_channel::{unbounded, Receiver, Sender}; | 8 | use crossbeam_channel::{unbounded, Receiver, Sender}; |
9 | use flycheck::FlycheckHandle; | 9 | use flycheck::FlycheckHandle; |
10 | use lsp_types::Url; | 10 | use lsp_types::{SemanticTokens, Url}; |
11 | use parking_lot::RwLock; | 11 | use parking_lot::{Mutex, RwLock}; |
12 | use ra_db::{CrateId, VfsPath}; | 12 | use ra_db::{CrateId, VfsPath}; |
13 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId}; | 13 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId}; |
14 | use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; | 14 | use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; |
@@ -71,7 +71,9 @@ pub(crate) struct GlobalState { | |||
71 | pub(crate) analysis_host: AnalysisHost, | 71 | pub(crate) analysis_host: AnalysisHost, |
72 | pub(crate) diagnostics: DiagnosticCollection, | 72 | pub(crate) diagnostics: DiagnosticCollection, |
73 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, | 73 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, |
74 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, | ||
74 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 75 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
76 | pub(crate) shutdown_requested: bool, | ||
75 | pub(crate) status: Status, | 77 | pub(crate) status: Status, |
76 | pub(crate) source_root_config: SourceRootConfig, | 78 | pub(crate) source_root_config: SourceRootConfig, |
77 | pub(crate) proc_macro_client: ProcMacroClient, | 79 | pub(crate) proc_macro_client: ProcMacroClient, |
@@ -86,6 +88,7 @@ pub(crate) struct GlobalStateSnapshot { | |||
86 | pub(crate) check_fixes: CheckFixes, | 88 | pub(crate) check_fixes: CheckFixes, |
87 | pub(crate) latest_requests: Arc<RwLock<LatestRequests>>, | 89 | pub(crate) latest_requests: Arc<RwLock<LatestRequests>>, |
88 | mem_docs: FxHashMap<VfsPath, DocumentData>, | 90 | mem_docs: FxHashMap<VfsPath, DocumentData>, |
91 | pub semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, | ||
89 | vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 92 | vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
90 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, | 93 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, |
91 | } | 94 | } |
@@ -120,7 +123,9 @@ impl GlobalState { | |||
120 | analysis_host, | 123 | analysis_host, |
121 | diagnostics: Default::default(), | 124 | diagnostics: Default::default(), |
122 | mem_docs: FxHashMap::default(), | 125 | mem_docs: FxHashMap::default(), |
126 | semantic_tokens_cache: Arc::new(Default::default()), | ||
123 | vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), | 127 | vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), |
128 | shutdown_requested: false, | ||
124 | status: Status::default(), | 129 | status: Status::default(), |
125 | source_root_config: SourceRootConfig::default(), | 130 | source_root_config: SourceRootConfig::default(), |
126 | proc_macro_client: ProcMacroClient::dummy(), | 131 | proc_macro_client: ProcMacroClient::dummy(), |
@@ -186,6 +191,7 @@ impl GlobalState { | |||
186 | latest_requests: Arc::clone(&self.latest_requests), | 191 | latest_requests: Arc::clone(&self.latest_requests), |
187 | check_fixes: Arc::clone(&self.diagnostics.check_fixes), | 192 | check_fixes: Arc::clone(&self.diagnostics.check_fixes), |
188 | mem_docs: self.mem_docs.clone(), | 193 | mem_docs: self.mem_docs.clone(), |
194 | semantic_tokens_cache: Arc::clone(&self.semantic_tokens_cache), | ||
189 | } | 195 | } |
190 | } | 196 | } |
191 | 197 | ||
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index e73b3a211..785dd2a26 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -13,9 +13,10 @@ use lsp_types::{ | |||
13 | CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, | 13 | CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, |
14 | CodeActionKind, CodeLens, Command, CompletionItem, Diagnostic, DocumentFormattingParams, | 14 | CodeActionKind, CodeLens, Command, CompletionItem, Diagnostic, DocumentFormattingParams, |
15 | DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, HoverContents, Location, | 15 | DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, HoverContents, Location, |
16 | Position, PrepareRenameResponse, Range, RenameParams, SemanticTokensParams, | 16 | Position, PrepareRenameResponse, Range, RenameParams, SemanticTokensEditResult, |
17 | SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, | 17 | SemanticTokensEditsParams, SemanticTokensParams, SemanticTokensRangeParams, |
18 | SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit, | 18 | SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, SymbolTag, |
19 | TextDocumentIdentifier, Url, WorkspaceEdit, | ||
19 | }; | 20 | }; |
20 | use ra_ide::{ | 21 | use ra_ide::{ |
21 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, | 22 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, |
@@ -709,11 +710,6 @@ pub(crate) fn handle_formatting( | |||
709 | } | 710 | } |
710 | }; | 711 | }; |
711 | 712 | ||
712 | if let Ok(path) = params.text_document.uri.to_file_path() { | ||
713 | if let Some(parent) = path.parent() { | ||
714 | rustfmt.current_dir(parent); | ||
715 | } | ||
716 | } | ||
717 | let mut rustfmt = rustfmt.stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?; | 713 | let mut rustfmt = rustfmt.stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?; |
718 | 714 | ||
719 | rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?; | 715 | rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?; |
@@ -777,12 +773,11 @@ fn handle_fixes( | |||
777 | 773 | ||
778 | let diagnostics = snap.analysis.diagnostics(file_id, snap.config.experimental_diagnostics)?; | 774 | let diagnostics = snap.analysis.diagnostics(file_id, snap.config.experimental_diagnostics)?; |
779 | 775 | ||
780 | let fixes_from_diagnostics = diagnostics | 776 | for fix in diagnostics |
781 | .into_iter() | 777 | .into_iter() |
782 | .filter_map(|d| Some((d.range, d.fix?))) | 778 | .filter_map(|d| d.fix) |
783 | .filter(|(diag_range, _fix)| diag_range.intersect(range).is_some()) | 779 | .filter(|fix| fix.fix_trigger_range.intersect(range).is_some()) |
784 | .map(|(_range, fix)| fix); | 780 | { |
785 | for fix in fixes_from_diagnostics { | ||
786 | let title = fix.label; | 781 | let title = fix.label; |
787 | let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?; | 782 | let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?; |
788 | let action = lsp_ext::CodeAction { | 783 | let action = lsp_ext::CodeAction { |
@@ -868,7 +863,7 @@ pub(crate) fn handle_resolve_code_action( | |||
868 | let (id_string, index) = split_once(¶ms.id, ':').unwrap(); | 863 | let (id_string, index) = split_once(¶ms.id, ':').unwrap(); |
869 | let index = index.parse::<usize>().unwrap(); | 864 | let index = index.parse::<usize>().unwrap(); |
870 | let assist = &assists[index]; | 865 | let assist = &assists[index]; |
871 | assert!(assist.assist.id.0 == id_string); | 866 | assert!(assist.assist.id().0 == id_string); |
872 | Ok(to_proto::resolved_code_action(&snap, assist.clone())?.edit) | 867 | Ok(to_proto::resolved_code_action(&snap, assist.clone())?.edit) |
873 | } | 868 | } |
874 | 869 | ||
@@ -896,7 +891,7 @@ pub(crate) fn handle_code_lens( | |||
896 | } | 891 | } |
897 | 892 | ||
898 | let action = runnable.action(); | 893 | let action = runnable.action(); |
899 | let range = to_proto::range(&line_index, runnable.nav.focus_or_full_range()); | 894 | let range = to_proto::range(&line_index, runnable.nav.full_range); |
900 | let r = to_proto::runnable(&snap, file_id, runnable)?; | 895 | let r = to_proto::runnable(&snap, file_id, runnable)?; |
901 | if snap.config.lens.run { | 896 | if snap.config.lens.run { |
902 | let lens = CodeLens { | 897 | let lens = CodeLens { |
@@ -1184,6 +1179,40 @@ pub(crate) fn handle_semantic_tokens( | |||
1184 | 1179 | ||
1185 | let highlights = snap.analysis.highlight(file_id)?; | 1180 | let highlights = snap.analysis.highlight(file_id)?; |
1186 | let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); | 1181 | let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); |
1182 | |||
1183 | // Unconditionally cache the tokens | ||
1184 | snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens.clone()); | ||
1185 | |||
1186 | Ok(Some(semantic_tokens.into())) | ||
1187 | } | ||
1188 | |||
1189 | pub(crate) fn handle_semantic_tokens_edits( | ||
1190 | snap: GlobalStateSnapshot, | ||
1191 | params: SemanticTokensEditsParams, | ||
1192 | ) -> Result<Option<SemanticTokensEditResult>> { | ||
1193 | let _p = profile("handle_semantic_tokens_edits"); | ||
1194 | |||
1195 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | ||
1196 | let text = snap.analysis.file_text(file_id)?; | ||
1197 | let line_index = snap.analysis.file_line_index(file_id)?; | ||
1198 | |||
1199 | let highlights = snap.analysis.highlight(file_id)?; | ||
1200 | |||
1201 | let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); | ||
1202 | |||
1203 | let mut cache = snap.semantic_tokens_cache.lock(); | ||
1204 | let cached_tokens = cache.entry(params.text_document.uri).or_default(); | ||
1205 | |||
1206 | if let Some(prev_id) = &cached_tokens.result_id { | ||
1207 | if *prev_id == params.previous_result_id { | ||
1208 | let edits = to_proto::semantic_token_edits(&cached_tokens, &semantic_tokens); | ||
1209 | *cached_tokens = semantic_tokens; | ||
1210 | return Ok(Some(edits.into())); | ||
1211 | } | ||
1212 | } | ||
1213 | |||
1214 | *cached_tokens = semantic_tokens.clone(); | ||
1215 | |||
1187 | Ok(Some(semantic_tokens.into())) | 1216 | Ok(Some(semantic_tokens.into())) |
1188 | } | 1217 | } |
1189 | 1218 | ||
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs index d4cc9dd04..0bc3ff115 100644 --- a/crates/rust-analyzer/src/lsp_utils.rs +++ b/crates/rust-analyzer/src/lsp_utils.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! Utilities for LSP-related boilerplate code. | 1 | //! Utilities for LSP-related boilerplate code. |
2 | use std::{borrow::Cow, error::Error, ops::Range}; | 2 | use std::{error::Error, ops::Range}; |
3 | 3 | ||
4 | use lsp_server::Notification; | 4 | use lsp_server::Notification; |
5 | use ra_db::Canceled; | 5 | use ra_db::Canceled; |
@@ -84,8 +84,8 @@ impl GlobalState { | |||
84 | pub(crate) fn apply_document_changes( | 84 | pub(crate) fn apply_document_changes( |
85 | old_text: &mut String, | 85 | old_text: &mut String, |
86 | content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>, | 86 | content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>, |
87 | mut line_index: Cow<'_, LineIndex>, | ||
88 | ) { | 87 | ) { |
88 | let mut line_index = LineIndex::new(old_text); | ||
89 | // The changes we got must be applied sequentially, but can cross lines so we | 89 | // The changes we got must be applied sequentially, but can cross lines so we |
90 | // have to keep our line index updated. | 90 | // have to keep our line index updated. |
91 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we | 91 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we |
@@ -110,7 +110,7 @@ pub(crate) fn apply_document_changes( | |||
110 | match change.range { | 110 | match change.range { |
111 | Some(range) => { | 111 | Some(range) => { |
112 | if !index_valid.covers(range.end.line) { | 112 | if !index_valid.covers(range.end.line) { |
113 | line_index = Cow::Owned(LineIndex::new(old_text)); | 113 | line_index = LineIndex::new(&old_text); |
114 | } | 114 | } |
115 | index_valid = IndexValid::UpToLineExclusive(range.start.line); | 115 | index_valid = IndexValid::UpToLineExclusive(range.start.line); |
116 | let range = from_proto::text_range(&line_index, range); | 116 | let range = from_proto::text_range(&line_index, range); |
@@ -145,15 +145,10 @@ mod tests { | |||
145 | }; | 145 | }; |
146 | } | 146 | } |
147 | 147 | ||
148 | fn run(text: &mut String, changes: Vec<TextDocumentContentChangeEvent>) { | ||
149 | let line_index = Cow::Owned(LineIndex::new(&text)); | ||
150 | super::apply_document_changes(text, changes, line_index); | ||
151 | } | ||
152 | |||
153 | let mut text = String::new(); | 148 | let mut text = String::new(); |
154 | run(&mut text, vec![]); | 149 | apply_document_changes(&mut text, vec![]); |
155 | assert_eq!(text, ""); | 150 | assert_eq!(text, ""); |
156 | run( | 151 | apply_document_changes( |
157 | &mut text, | 152 | &mut text, |
158 | vec![TextDocumentContentChangeEvent { | 153 | vec![TextDocumentContentChangeEvent { |
159 | range: None, | 154 | range: None, |
@@ -162,36 +157,39 @@ mod tests { | |||
162 | }], | 157 | }], |
163 | ); | 158 | ); |
164 | assert_eq!(text, "the"); | 159 | assert_eq!(text, "the"); |
165 | run(&mut text, c![0, 3; 0, 3 => " quick"]); | 160 | apply_document_changes(&mut text, c![0, 3; 0, 3 => " quick"]); |
166 | assert_eq!(text, "the quick"); | 161 | assert_eq!(text, "the quick"); |
167 | run(&mut text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); | 162 | apply_document_changes(&mut text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); |
168 | assert_eq!(text, "quick foxes"); | 163 | assert_eq!(text, "quick foxes"); |
169 | run(&mut text, c![0, 11; 0, 11 => "\ndream"]); | 164 | apply_document_changes(&mut text, c![0, 11; 0, 11 => "\ndream"]); |
170 | assert_eq!(text, "quick foxes\ndream"); | 165 | assert_eq!(text, "quick foxes\ndream"); |
171 | run(&mut text, c![1, 0; 1, 0 => "have "]); | 166 | apply_document_changes(&mut text, c![1, 0; 1, 0 => "have "]); |
172 | assert_eq!(text, "quick foxes\nhave dream"); | 167 | assert_eq!(text, "quick foxes\nhave dream"); |
173 | run(&mut text, c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"]); | 168 | apply_document_changes( |
169 | &mut text, | ||
170 | c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"], | ||
171 | ); | ||
174 | assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); | 172 | assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); |
175 | run(&mut text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]); | 173 | apply_document_changes(&mut text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]); |
176 | assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); | 174 | assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); |
177 | run( | 175 | apply_document_changes( |
178 | &mut text, | 176 | &mut text, |
179 | c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], | 177 | c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], |
180 | ); | 178 | ); |
181 | assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); | 179 | assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); |
182 | run(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); | 180 | apply_document_changes(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); |
183 | assert_eq!(text, "the quick \nthey have quiet dreams\n"); | 181 | assert_eq!(text, "the quick \nthey have quiet dreams\n"); |
184 | 182 | ||
185 | text = String::from("❤️"); | 183 | text = String::from("❤️"); |
186 | run(&mut text, c![0, 0; 0, 0 => "a"]); | 184 | apply_document_changes(&mut text, c![0, 0; 0, 0 => "a"]); |
187 | assert_eq!(text, "a❤️"); | 185 | assert_eq!(text, "a❤️"); |
188 | 186 | ||
189 | text = String::from("a\nb"); | 187 | text = String::from("a\nb"); |
190 | run(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); | 188 | apply_document_changes(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); |
191 | assert_eq!(text, "adcb"); | 189 | assert_eq!(text, "adcb"); |
192 | 190 | ||
193 | text = String::from("a\nb"); | 191 | text = String::from("a\nb"); |
194 | run(&mut text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); | 192 | apply_document_changes(&mut text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); |
195 | assert_eq!(text, "ațc\ncb"); | 193 | assert_eq!(text, "ațc\ncb"); |
196 | } | 194 | } |
197 | } | 195 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 0ace4cb45..e6cf46df2 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -1,14 +1,13 @@ | |||
1 | //! The main loop of `rust-analyzer` responsible for dispatching LSP | 1 | //! The main loop of `rust-analyzer` responsible for dispatching LSP |
2 | //! requests/replies and notifications back to the client. | 2 | //! requests/replies and notifications back to the client. |
3 | use std::{ | 3 | use std::{ |
4 | borrow::Cow, | ||
5 | env, fmt, panic, | 4 | env, fmt, panic, |
6 | time::{Duration, Instant}, | 5 | time::{Duration, Instant}, |
7 | }; | 6 | }; |
8 | 7 | ||
9 | use crossbeam_channel::{select, Receiver}; | 8 | use crossbeam_channel::{select, Receiver}; |
10 | use lsp_server::{Connection, Notification, Request, Response}; | 9 | use lsp_server::{Connection, Notification, Request, Response}; |
11 | use lsp_types::{notification::Notification as _, DidChangeTextDocumentParams}; | 10 | use lsp_types::notification::Notification as _; |
12 | use ra_db::VfsPath; | 11 | use ra_db::VfsPath; |
13 | use ra_ide::{Canceled, FileId}; | 12 | use ra_ide::{Canceled, FileId}; |
14 | use ra_prof::profile; | 13 | use ra_prof::profile; |
@@ -48,7 +47,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
48 | SetThreadPriority(thread, thread_priority_above_normal); | 47 | SetThreadPriority(thread, thread_priority_above_normal); |
49 | } | 48 | } |
50 | 49 | ||
51 | GlobalState::new(connection.sender.clone(), config).run(connection.receiver) | 50 | GlobalState::new(connection.sender, config).run(connection.receiver) |
52 | } | 51 | } |
53 | 52 | ||
54 | enum Event { | 53 | enum Event { |
@@ -338,11 +337,34 @@ impl GlobalState { | |||
338 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { | 337 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { |
339 | self.register_request(&req, request_received); | 338 | self.register_request(&req, request_received); |
340 | 339 | ||
340 | if self.shutdown_requested { | ||
341 | self.respond(Response::new_err( | ||
342 | req.id, | ||
343 | lsp_server::ErrorCode::InvalidRequest as i32, | ||
344 | "Shutdown already requested.".to_owned(), | ||
345 | )); | ||
346 | |||
347 | return Ok(()); | ||
348 | } | ||
349 | |||
350 | if self.status == Status::Loading && req.method != "shutdown" { | ||
351 | self.respond(lsp_server::Response::new_err( | ||
352 | req.id, | ||
353 | // FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion) | ||
354 | lsp_server::ErrorCode::ContentModified as i32, | ||
355 | "Rust Analyzer is still loading...".to_owned(), | ||
356 | )); | ||
357 | return Ok(()); | ||
358 | } | ||
359 | |||
341 | RequestDispatcher { req: Some(req), global_state: self } | 360 | RequestDispatcher { req: Some(req), global_state: self } |
342 | .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))? | 361 | .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))? |
343 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? | 362 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? |
344 | .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? | 363 | .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? |
345 | .on_sync::<lsp_types::request::Shutdown>(|_, ()| Ok(()))? | 364 | .on_sync::<lsp_types::request::Shutdown>(|s, ()| { |
365 | s.shutdown_requested = true; | ||
366 | Ok(()) | ||
367 | })? | ||
346 | .on_sync::<lsp_types::request::SelectionRangeRequest>(|s, p| { | 368 | .on_sync::<lsp_types::request::SelectionRangeRequest>(|s, p| { |
347 | handlers::handle_selection_range(s.snapshot(), p) | 369 | handlers::handle_selection_range(s.snapshot(), p) |
348 | })? | 370 | })? |
@@ -387,6 +409,9 @@ impl GlobalState { | |||
387 | handlers::handle_call_hierarchy_outgoing, | 409 | handlers::handle_call_hierarchy_outgoing, |
388 | )? | 410 | )? |
389 | .on::<lsp_types::request::SemanticTokensRequest>(handlers::handle_semantic_tokens)? | 411 | .on::<lsp_types::request::SemanticTokensRequest>(handlers::handle_semantic_tokens)? |
412 | .on::<lsp_types::request::SemanticTokensEditsRequest>( | ||
413 | handlers::handle_semantic_tokens_edits, | ||
414 | )? | ||
390 | .on::<lsp_types::request::SemanticTokensRangeRequest>( | 415 | .on::<lsp_types::request::SemanticTokensRangeRequest>( |
391 | handlers::handle_semantic_tokens_range, | 416 | handlers::handle_semantic_tokens_range, |
392 | )? | 417 | )? |
@@ -422,20 +447,15 @@ impl GlobalState { | |||
422 | })? | 447 | })? |
423 | .on::<lsp_types::notification::DidChangeTextDocument>(|this, params| { | 448 | .on::<lsp_types::notification::DidChangeTextDocument>(|this, params| { |
424 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { | 449 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { |
425 | let DidChangeTextDocumentParams { text_document, content_changes } = params; | 450 | let doc = this.mem_docs.get_mut(&path).unwrap(); |
426 | let vfs = &mut this.vfs.write().0; | 451 | let vfs = &mut this.vfs.write().0; |
427 | let world = this.snapshot(); | ||
428 | let file_id = vfs.file_id(&path).unwrap(); | 452 | let file_id = vfs.file_id(&path).unwrap(); |
429 | |||
430 | // let file_id = vfs.file_id(&path).unwrap(); | ||
431 | let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap(); | 453 | let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap(); |
432 | let line_index = world.analysis.file_line_index(file_id)?; | 454 | apply_document_changes(&mut text, params.content_changes); |
433 | apply_document_changes(&mut text, content_changes, Cow::Borrowed(&line_index)); | ||
434 | 455 | ||
435 | // The version passed in DidChangeTextDocument is the version after all edits are applied | 456 | // The version passed in DidChangeTextDocument is the version after all edits are applied |
436 | // so we should apply it before the vfs is notified. | 457 | // so we should apply it before the vfs is notified. |
437 | let doc = this.mem_docs.get_mut(&path).unwrap(); | 458 | doc.version = params.text_document.version; |
438 | doc.version = text_document.version; | ||
439 | 459 | ||
440 | vfs.set_file_contents(path.clone(), Some(text.into_bytes())); | 460 | vfs.set_file_contents(path.clone(), Some(text.into_bytes())); |
441 | } | 461 | } |
@@ -449,6 +469,8 @@ impl GlobalState { | |||
449 | None => log::error!("orphan DidCloseTextDocument: {}", path), | 469 | None => log::error!("orphan DidCloseTextDocument: {}", path), |
450 | } | 470 | } |
451 | 471 | ||
472 | this.semantic_tokens_cache.lock().remove(¶ms.text_document.uri); | ||
473 | |||
452 | if let Some(path) = path.as_path() { | 474 | if let Some(path) = path.as_path() { |
453 | this.loader.handle.invalidate(path.to_path_buf()); | 475 | this.loader.handle.invalidate(path.to_path_buf()); |
454 | } | 476 | } |
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index 576bd8adc..afc38fb4e 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs | |||
@@ -2,7 +2,10 @@ | |||
2 | 2 | ||
3 | use std::ops; | 3 | use std::ops; |
4 | 4 | ||
5 | use lsp_types::{Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens}; | 5 | use lsp_types::{ |
6 | Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens, | ||
7 | SemanticTokensEdit, | ||
8 | }; | ||
6 | 9 | ||
7 | macro_rules! define_semantic_token_types { | 10 | macro_rules! define_semantic_token_types { |
8 | ($(($ident:ident, $string:literal)),*$(,)?) => { | 11 | ($(($ident:ident, $string:literal)),*$(,)?) => { |
@@ -89,14 +92,18 @@ impl ops::BitOrAssign<SemanticTokenModifier> for ModifierSet { | |||
89 | /// Tokens are encoded relative to each other. | 92 | /// Tokens are encoded relative to each other. |
90 | /// | 93 | /// |
91 | /// This is a direct port of https://github.com/microsoft/vscode-languageserver-node/blob/f425af9de46a0187adb78ec8a46b9b2ce80c5412/server/src/sematicTokens.proposed.ts#L45 | 94 | /// This is a direct port of https://github.com/microsoft/vscode-languageserver-node/blob/f425af9de46a0187adb78ec8a46b9b2ce80c5412/server/src/sematicTokens.proposed.ts#L45 |
92 | #[derive(Default)] | ||
93 | pub(crate) struct SemanticTokensBuilder { | 95 | pub(crate) struct SemanticTokensBuilder { |
96 | id: String, | ||
94 | prev_line: u32, | 97 | prev_line: u32, |
95 | prev_char: u32, | 98 | prev_char: u32, |
96 | data: Vec<SemanticToken>, | 99 | data: Vec<SemanticToken>, |
97 | } | 100 | } |
98 | 101 | ||
99 | impl SemanticTokensBuilder { | 102 | impl SemanticTokensBuilder { |
103 | pub fn new(id: String) -> Self { | ||
104 | SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Default::default() } | ||
105 | } | ||
106 | |||
100 | /// Push a new token onto the builder | 107 | /// Push a new token onto the builder |
101 | pub fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) { | 108 | pub fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) { |
102 | let mut push_line = range.start.line as u32; | 109 | let mut push_line = range.start.line as u32; |
@@ -127,10 +134,136 @@ impl SemanticTokensBuilder { | |||
127 | } | 134 | } |
128 | 135 | ||
129 | pub fn build(self) -> SemanticTokens { | 136 | pub fn build(self) -> SemanticTokens { |
130 | SemanticTokens { result_id: None, data: self.data } | 137 | SemanticTokens { result_id: Some(self.id), data: self.data } |
138 | } | ||
139 | } | ||
140 | |||
141 | pub fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<SemanticTokensEdit> { | ||
142 | let offset = new.iter().zip(old.iter()).take_while(|&(n, p)| n == p).count(); | ||
143 | |||
144 | let (_, old) = old.split_at(offset); | ||
145 | let (_, new) = new.split_at(offset); | ||
146 | |||
147 | let offset_from_end = | ||
148 | new.iter().rev().zip(old.iter().rev()).take_while(|&(n, p)| n == p).count(); | ||
149 | |||
150 | let (old, _) = old.split_at(old.len() - offset_from_end); | ||
151 | let (new, _) = new.split_at(new.len() - offset_from_end); | ||
152 | |||
153 | if old.is_empty() && new.is_empty() { | ||
154 | vec![] | ||
155 | } else { | ||
156 | // The lsp data field is actually a byte-diff but we | ||
157 | // travel in tokens so `start` and `delete_count` are in multiples of the | ||
158 | // serialized size of `SemanticToken`. | ||
159 | vec![SemanticTokensEdit { | ||
160 | start: 5 * offset as u32, | ||
161 | delete_count: 5 * old.len() as u32, | ||
162 | data: Some(new.into()), | ||
163 | }] | ||
131 | } | 164 | } |
132 | } | 165 | } |
133 | 166 | ||
134 | pub fn type_index(type_: SemanticTokenType) -> u32 { | 167 | pub fn type_index(type_: SemanticTokenType) -> u32 { |
135 | SUPPORTED_TYPES.iter().position(|it| *it == type_).unwrap() as u32 | 168 | SUPPORTED_TYPES.iter().position(|it| *it == type_).unwrap() as u32 |
136 | } | 169 | } |
170 | |||
171 | #[cfg(test)] | ||
172 | mod tests { | ||
173 | use super::*; | ||
174 | |||
175 | fn from(t: (u32, u32, u32, u32, u32)) -> SemanticToken { | ||
176 | SemanticToken { | ||
177 | delta_line: t.0, | ||
178 | delta_start: t.1, | ||
179 | length: t.2, | ||
180 | token_type: t.3, | ||
181 | token_modifiers_bitset: t.4, | ||
182 | } | ||
183 | } | ||
184 | |||
185 | #[test] | ||
186 | fn test_diff_insert_at_end() { | ||
187 | let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
188 | let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))]; | ||
189 | |||
190 | let edits = diff_tokens(&before, &after); | ||
191 | assert_eq!( | ||
192 | edits[0], | ||
193 | SemanticTokensEdit { | ||
194 | start: 10, | ||
195 | delete_count: 0, | ||
196 | data: Some(vec![from((11, 12, 13, 14, 15))]) | ||
197 | } | ||
198 | ); | ||
199 | } | ||
200 | |||
201 | #[test] | ||
202 | fn test_diff_insert_at_beginning() { | ||
203 | let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
204 | let after = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
205 | |||
206 | let edits = diff_tokens(&before, &after); | ||
207 | assert_eq!( | ||
208 | edits[0], | ||
209 | SemanticTokensEdit { | ||
210 | start: 0, | ||
211 | delete_count: 0, | ||
212 | data: Some(vec![from((11, 12, 13, 14, 15))]) | ||
213 | } | ||
214 | ); | ||
215 | } | ||
216 | |||
217 | #[test] | ||
218 | fn test_diff_insert_in_middle() { | ||
219 | let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
220 | let after = [ | ||
221 | from((1, 2, 3, 4, 5)), | ||
222 | from((10, 20, 30, 40, 50)), | ||
223 | from((60, 70, 80, 90, 100)), | ||
224 | from((6, 7, 8, 9, 10)), | ||
225 | ]; | ||
226 | |||
227 | let edits = diff_tokens(&before, &after); | ||
228 | assert_eq!( | ||
229 | edits[0], | ||
230 | SemanticTokensEdit { | ||
231 | start: 5, | ||
232 | delete_count: 0, | ||
233 | data: Some(vec![from((10, 20, 30, 40, 50)), from((60, 70, 80, 90, 100))]) | ||
234 | } | ||
235 | ); | ||
236 | } | ||
237 | |||
238 | #[test] | ||
239 | fn test_diff_remove_from_end() { | ||
240 | let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))]; | ||
241 | let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
242 | |||
243 | let edits = diff_tokens(&before, &after); | ||
244 | assert_eq!(edits[0], SemanticTokensEdit { start: 10, delete_count: 5, data: Some(vec![]) }); | ||
245 | } | ||
246 | |||
247 | #[test] | ||
248 | fn test_diff_remove_from_beginning() { | ||
249 | let before = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
250 | let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
251 | |||
252 | let edits = diff_tokens(&before, &after); | ||
253 | assert_eq!(edits[0], SemanticTokensEdit { start: 0, delete_count: 5, data: Some(vec![]) }); | ||
254 | } | ||
255 | |||
256 | #[test] | ||
257 | fn test_diff_remove_from_middle() { | ||
258 | let before = [ | ||
259 | from((1, 2, 3, 4, 5)), | ||
260 | from((10, 20, 30, 40, 50)), | ||
261 | from((60, 70, 80, 90, 100)), | ||
262 | from((6, 7, 8, 9, 10)), | ||
263 | ]; | ||
264 | let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))]; | ||
265 | |||
266 | let edits = diff_tokens(&before, &after); | ||
267 | assert_eq!(edits[0], SemanticTokensEdit { start: 5, delete_count: 10, data: Some(vec![]) }); | ||
268 | } | ||
269 | } | ||
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index fadcc5853..62fda8a1f 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -1,5 +1,8 @@ | |||
1 | //! Conversion of rust-analyzer specific types to lsp_types equivalents. | 1 | //! Conversion of rust-analyzer specific types to lsp_types equivalents. |
2 | use std::path::{self, Path}; | 2 | use std::{ |
3 | path::{self, Path}, | ||
4 | sync::atomic::{AtomicU32, Ordering}, | ||
5 | }; | ||
3 | 6 | ||
4 | use itertools::Itertools; | 7 | use itertools::Itertools; |
5 | use ra_db::{FileId, FileRange}; | 8 | use ra_db::{FileId, FileRange}; |
@@ -303,12 +306,15 @@ pub(crate) fn inlay_int(line_index: &LineIndex, inlay_hint: InlayHint) -> lsp_ex | |||
303 | } | 306 | } |
304 | } | 307 | } |
305 | 308 | ||
309 | static TOKEN_RESULT_COUNTER: AtomicU32 = AtomicU32::new(1); | ||
310 | |||
306 | pub(crate) fn semantic_tokens( | 311 | pub(crate) fn semantic_tokens( |
307 | text: &str, | 312 | text: &str, |
308 | line_index: &LineIndex, | 313 | line_index: &LineIndex, |
309 | highlights: Vec<HighlightedRange>, | 314 | highlights: Vec<HighlightedRange>, |
310 | ) -> lsp_types::SemanticTokens { | 315 | ) -> lsp_types::SemanticTokens { |
311 | let mut builder = semantic_tokens::SemanticTokensBuilder::default(); | 316 | let id = TOKEN_RESULT_COUNTER.fetch_add(1, Ordering::SeqCst).to_string(); |
317 | let mut builder = semantic_tokens::SemanticTokensBuilder::new(id); | ||
312 | 318 | ||
313 | for highlight_range in highlights { | 319 | for highlight_range in highlights { |
314 | let (type_, mods) = semantic_token_type_and_modifiers(highlight_range.highlight); | 320 | let (type_, mods) = semantic_token_type_and_modifiers(highlight_range.highlight); |
@@ -328,6 +334,15 @@ pub(crate) fn semantic_tokens( | |||
328 | builder.build() | 334 | builder.build() |
329 | } | 335 | } |
330 | 336 | ||
337 | pub(crate) fn semantic_token_edits( | ||
338 | previous: &lsp_types::SemanticTokens, | ||
339 | current: &lsp_types::SemanticTokens, | ||
340 | ) -> lsp_types::SemanticTokensEdits { | ||
341 | let result_id = current.result_id.clone(); | ||
342 | let edits = semantic_tokens::diff_tokens(&previous.data, ¤t.data); | ||
343 | lsp_types::SemanticTokensEdits { result_id, edits } | ||
344 | } | ||
345 | |||
331 | fn semantic_token_type_and_modifiers( | 346 | fn semantic_token_type_and_modifiers( |
332 | highlight: Highlight, | 347 | highlight: Highlight, |
333 | ) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) { | 348 | ) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) { |
@@ -689,10 +704,10 @@ pub(crate) fn unresolved_code_action( | |||
689 | index: usize, | 704 | index: usize, |
690 | ) -> Result<lsp_ext::CodeAction> { | 705 | ) -> Result<lsp_ext::CodeAction> { |
691 | let res = lsp_ext::CodeAction { | 706 | let res = lsp_ext::CodeAction { |
692 | title: assist.label, | 707 | title: assist.label(), |
693 | id: Some(format!("{}:{}", assist.id.0.to_owned(), index.to_string())), | 708 | id: Some(format!("{}:{}", assist.id().0.to_owned(), index.to_string())), |
694 | group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0), | 709 | group: assist.group().filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0), |
695 | kind: Some(code_action_kind(assist.id.1)), | 710 | kind: Some(code_action_kind(assist.id().1)), |
696 | edit: None, | 711 | edit: None, |
697 | is_preferred: None, | 712 | is_preferred: None, |
698 | }; | 713 | }; |
@@ -740,7 +755,8 @@ pub(crate) fn runnable( | |||
740 | } | 755 | } |
741 | 756 | ||
742 | pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { | 757 | pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { |
743 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value: markup.into() } | 758 | let value = crate::markdown::format_docs(markup.as_str()); |
759 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } | ||
744 | } | 760 | } |
745 | 761 | ||
746 | #[cfg(test)] | 762 | #[cfg(test)] |
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index b65875c96..3c5027fe5 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! Missing batteries for standard libraries. | 1 | //! Missing batteries for standard libraries. |
2 | use std::{cell::Cell, fmt, time::Instant}; | 2 | use std::time::Instant; |
3 | 3 | ||
4 | mod macros; | 4 | mod macros; |
5 | 5 | ||
@@ -8,69 +8,6 @@ pub fn is_ci() -> bool { | |||
8 | option_env!("CI").is_some() | 8 | option_env!("CI").is_some() |
9 | } | 9 | } |
10 | 10 | ||
11 | pub trait SepBy: Sized { | ||
12 | /// Returns an `impl fmt::Display`, which joins elements via a separator. | ||
13 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self>; | ||
14 | } | ||
15 | |||
16 | impl<I> SepBy for I | ||
17 | where | ||
18 | I: Iterator, | ||
19 | I::Item: fmt::Display, | ||
20 | { | ||
21 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self> { | ||
22 | SepByBuilder::new(sep, self) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | pub struct SepByBuilder<'a, I> { | ||
27 | sep: &'a str, | ||
28 | prefix: &'a str, | ||
29 | suffix: &'a str, | ||
30 | iter: Cell<Option<I>>, | ||
31 | } | ||
32 | |||
33 | impl<'a, I> SepByBuilder<'a, I> { | ||
34 | fn new(sep: &'a str, iter: I) -> SepByBuilder<'a, I> { | ||
35 | SepByBuilder { sep, prefix: "", suffix: "", iter: Cell::new(Some(iter)) } | ||
36 | } | ||
37 | |||
38 | pub fn prefix(mut self, prefix: &'a str) -> Self { | ||
39 | self.prefix = prefix; | ||
40 | self | ||
41 | } | ||
42 | |||
43 | pub fn suffix(mut self, suffix: &'a str) -> Self { | ||
44 | self.suffix = suffix; | ||
45 | self | ||
46 | } | ||
47 | |||
48 | /// Set both suffix and prefix. | ||
49 | pub fn surround_with(self, prefix: &'a str, suffix: &'a str) -> Self { | ||
50 | self.prefix(prefix).suffix(suffix) | ||
51 | } | ||
52 | } | ||
53 | |||
54 | impl<I> fmt::Display for SepByBuilder<'_, I> | ||
55 | where | ||
56 | I: Iterator, | ||
57 | I::Item: fmt::Display, | ||
58 | { | ||
59 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
60 | f.write_str(self.prefix)?; | ||
61 | let mut first = true; | ||
62 | for item in self.iter.take().unwrap() { | ||
63 | if !first { | ||
64 | f.write_str(self.sep)?; | ||
65 | } | ||
66 | first = false; | ||
67 | fmt::Display::fmt(&item, f)?; | ||
68 | } | ||
69 | f.write_str(self.suffix)?; | ||
70 | Ok(()) | ||
71 | } | ||
72 | } | ||
73 | |||
74 | #[must_use] | 11 | #[must_use] |
75 | pub fn timeit(label: &'static str) -> impl Drop { | 12 | pub fn timeit(label: &'static str) -> impl Drop { |
76 | struct Guard { | 13 | struct Guard { |
diff --git a/docs/dev/README.md b/docs/dev/README.md index 2896d333e..51cf716b3 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -50,277 +50,85 @@ We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.o | |||
50 | 50 | ||
51 | 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. |
52 | 52 | ||
53 | # Code organization | ||
54 | |||
55 | All Rust code lives in the `crates` top-level directory, and is organized as a | ||
56 | single Cargo workspace. The `editors` top-level directory contains code for | ||
57 | integrating with editors. Currently, it contains the plugin for VS Code (in | ||
58 | TypeScript). The `docs` top-level directory contains both developer and user | ||
59 | documentation. | ||
60 | |||
61 | We have some automation infra in Rust in the `xtask` package. It contains | ||
62 | stuff like formatting checking, code generation and powers `cargo xtask install`. | ||
63 | The latter syntax is achieved with the help of cargo aliases (see `.cargo` | ||
64 | directory). | ||
65 | |||
66 | # Launching rust-analyzer | 53 | # Launching rust-analyzer |
67 | 54 | ||
68 | Debugging the language server can be tricky: LSP is rather chatty, so driving it | 55 | Debugging the language server can be tricky. |
69 | from the command line is not really feasible, driving it via VS Code requires | 56 | LSP is rather chatty, so driving it from the command line is not really feasible, driving it via VS Code requires interacting with two processes. |
70 | interacting with two processes. | ||
71 | 57 | ||
72 | For this reason, the best way to see how rust-analyzer works is to find a | 58 | For this reason, the best way to see how rust-analyzer works is to find a relevant test and execute it. |
73 | relevant test and execute it (VS Code includes an action for running a single | 59 | VS Code & Emacs include an action for running a single test. |
74 | test). | ||
75 | 60 | ||
76 | However, launching a VS Code instance with a locally built language server is | 61 | Launching a VS Code instance with a locally built language server is also possible. |
77 | possible. There's **"Run Extension (Debug Build)"** launch configuration for this. | 62 | There's **"Run Extension (Debug Build)"** launch configuration for this in VS Code. |
78 | 63 | ||
79 | In general, I use one of the following workflows for fixing bugs and | 64 | In general, I use one of the following workflows for fixing bugs and implementing features: |
80 | implementing features. | ||
81 | 65 | ||
82 | If the problem concerns only internal parts of rust-analyzer (i.e. I don't need | 66 | If the problem concerns only internal parts of rust-analyzer (i.e. I don't need to touch the `rust-analyzer` crate or TypeScript code), there is a unit-test for it. |
83 | to touch the `rust-analyzer` crate or TypeScript code), there is a unit-test for it. | 67 | So, I use **Rust Analyzer: Run** action in VS Code to run this single test, and then just do printf-driven development/debugging. |
84 | So, I use **Rust Analyzer: Run** action in VS Code to run this single test, and | 68 | As a sanity check after I'm done, I use `cargo xtask install --server` and **Reload Window** action in VS Code to verify that the thing works as I expect. |
85 | then just do printf-driven development/debugging. As a sanity check after I'm | ||
86 | done, I use `cargo xtask install --server` and **Reload Window** action in VS | ||
87 | Code to sanity check that the thing works as I expect. | ||
88 | 69 | ||
89 | If the problem concerns only the VS Code extension, I use **Run Installed Extension** | 70 | If the problem concerns only the VS Code extension, I use **Run Installed Extension** launch configuration from `launch.json`. |
90 | launch configuration from `launch.json`. Notably, this uses the usual | 71 | Notably, this uses the usual `rust-analyzer` binary from `PATH`. |
91 | `rust-analyzer` binary from `PATH`. For this, it is important to have the following | 72 | For this, it is important to have the following in your `settings.json` file: |
92 | in your `settings.json` file: | ||
93 | ```json | 73 | ```json |
94 | { | 74 | { |
95 | "rust-analyzer.serverPath": "rust-analyzer" | 75 | "rust-analyzer.serverPath": "rust-analyzer" |
96 | } | 76 | } |
97 | ``` | 77 | ``` |
98 | After I am done with the fix, I use `cargo | 78 | After I am done with the fix, I use `cargo xtask install --client-code` to try the new extension for real. |
99 | xtask install --client-code` to try the new extension for real. | ||
100 | |||
101 | If I need to fix something in the `rust-analyzer` crate, I feel sad because it's | ||
102 | on the boundary between the two processes, and working there is slow. I usually | ||
103 | just `cargo xtask install --server` and poke changes from my live environment. | ||
104 | Note that this uses `--release`, which is usually faster overall, because | ||
105 | loading stdlib into debug version of rust-analyzer takes a lot of time. To speed | ||
106 | things up, sometimes I open a temporary hello-world project which has | ||
107 | `"rust-analyzer.withSysroot": false` in `.code/settings.json`. This flag causes | ||
108 | rust-analyzer to skip loading the sysroot, which greatly reduces the amount of | ||
109 | things rust-analyzer needs to do, and makes printf's more useful. Note that you | ||
110 | should only use the `eprint!` family of macros for debugging: stdout is used for LSP | ||
111 | communication, and `print!` would break it. | ||
112 | |||
113 | If I need to fix something simultaneously in the server and in the client, I | ||
114 | feel even more sad. I don't have a specific workflow for this case. | ||
115 | |||
116 | Additionally, I use `cargo run --release -p rust-analyzer -- analysis-stats | ||
117 | path/to/some/rust/crate` to run a batch analysis. This is primarily useful for | ||
118 | performance optimizations, or for bug minimization. | ||
119 | |||
120 | # Code Style & Review Process | ||
121 | |||
122 | Our approach to "clean code" is two-fold: | ||
123 | |||
124 | * We generally don't block PRs on style changes. | ||
125 | * At the same time, all code in rust-analyzer is constantly refactored. | ||
126 | |||
127 | It is explicitly OK for a reviewer to flag only some nits in the PR, and then send a follow-up cleanup PR for things which are easier to explain by example, cc-ing the original author. | ||
128 | Sending small cleanup PRs (like renaming a single local variable) is encouraged. | ||
129 | |||
130 | ## Scale of Changes | ||
131 | |||
132 | Everyone knows that it's better to send small & focused pull requests. | ||
133 | The problem is, sometimes you *have* to, eg, rewrite the whole compiler, and that just doesn't fit into a set of isolated PRs. | ||
134 | |||
135 | The main things to keep an eye on are the boundaries between various components. | ||
136 | There are three kinds of changes: | ||
137 | |||
138 | 1. Internals of a single component are changed. | ||
139 | Specifically, you don't change any `pub` items. | ||
140 | A good example here would be an addition of a new assist. | ||
141 | |||
142 | 2. API of a component is expanded. | ||
143 | Specifically, you add a new `pub` function which wasn't there before. | ||
144 | A good example here would be expansion of assist API, for example, to implement lazy assists or assists groups. | ||
145 | |||
146 | 3. A new dependency between components is introduced. | ||
147 | Specifically, you add a `pub use` reexport from another crate or you add a new line to the `[dependencies]` section of `Cargo.toml`. | ||
148 | A good example here would be adding reference search capability to the assists crates. | ||
149 | |||
150 | For the first group, the change is generally merged as long as: | ||
151 | |||
152 | * it works for the happy case, | ||
153 | * it has tests, | ||
154 | * it doesn't panic for the unhappy case. | ||
155 | |||
156 | For the second group, the change would be subjected to quite a bit of scrutiny and iteration. | ||
157 | The new API needs to be right (or at least easy to change later). | ||
158 | The actual implementation doesn't matter that much. | ||
159 | It's very important to minimize the amount of changed lines of code for changes of the second kind. | ||
160 | Often, you start doing a change of the first kind, only to realise that you need to elevate to a change of the second kind. | ||
161 | In this case, we'll probably ask you to split API changes into a separate PR. | ||
162 | |||
163 | Changes of the third group should be pretty rare, so we don't specify any specific process for them. | ||
164 | That said, adding an innocent-looking `pub use` is a very simple way to break encapsulation, keep an eye on it! | ||
165 | |||
166 | Note: if you enjoyed this abstract hand-waving about boundaries, you might appreciate | ||
167 | https://www.tedinski.com/2018/02/06/system-boundaries.html | ||
168 | |||
169 | ## Crates.io Dependencies | ||
170 | |||
171 | We try to be very conservative with usage of crates.io dependencies. | ||
172 | Don't use small "helper" crates (exception: `itertools` is allowed). | ||
173 | If there's some general reusable bit of code you need, consider adding it to the `stdx` crate. | ||
174 | |||
175 | ## Minimal Tests | ||
176 | |||
177 | Most tests in rust-analyzer start with a snippet of Rust code. | ||
178 | This snippets should be minimal -- if you copy-paste a snippet of real code into the tests, make sure to remove everything which could be removed. | ||
179 | There are many benefits to this: | ||
180 | |||
181 | * less to read or to scroll past | ||
182 | * easier to understand what exactly is tested | ||
183 | * less stuff printed during printf-debugging | ||
184 | * less time to run test | ||
185 | |||
186 | It also makes sense to format snippets more compactly (for example, by placing enum defitions like `enum E { Foo, Bar }` on a single line), | ||
187 | as long as they are still readable. | ||
188 | |||
189 | ## Order of Imports | ||
190 | |||
191 | We separate import groups with blank lines | ||
192 | |||
193 | ```rust | ||
194 | mod x; | ||
195 | mod y; | ||
196 | |||
197 | use std::{ ... } | ||
198 | |||
199 | use crate_foo::{ ... } | ||
200 | use crate_bar::{ ... } | ||
201 | |||
202 | use crate::{} | ||
203 | |||
204 | use super::{} // but prefer `use crate::` | ||
205 | ``` | ||
206 | |||
207 | ## Import Style | ||
208 | |||
209 | Items from `hir` and `ast` should be used qualified: | ||
210 | |||
211 | ```rust | ||
212 | // Good | ||
213 | use ra_syntax::ast; | ||
214 | |||
215 | fn frobnicate(func: hir::Function, strukt: ast::StructDef) {} | ||
216 | |||
217 | // Not as good | ||
218 | use hir::Function; | ||
219 | use ra_syntax::ast::StructDef; | ||
220 | |||
221 | fn frobnicate(func: Function, strukt: StructDef) {} | ||
222 | ``` | ||
223 | |||
224 | Avoid local `use MyEnum::*` imports. | ||
225 | |||
226 | Prefer `use crate::foo::bar` to `use super::bar`. | ||
227 | |||
228 | ## Order of Items | ||
229 | |||
230 | Optimize for the reader who sees the file for the first time, and wants to get the general idea about what's going on. | ||
231 | People read things from top to bottom, so place most important things first. | ||
232 | |||
233 | Specifically, if all items except one are private, always put the non-private item on top. | ||
234 | |||
235 | Put `struct`s and `enum`s first, functions and impls last. | ||
236 | |||
237 | Do | ||
238 | |||
239 | ```rust | ||
240 | // Good | ||
241 | struct Foo { | ||
242 | bars: Vec<Bar> | ||
243 | } | ||
244 | |||
245 | struct Bar; | ||
246 | ``` | ||
247 | |||
248 | rather than | ||
249 | 79 | ||
250 | ```rust | 80 | If I need to fix something in the `rust-analyzer` crate, I feel sad because it's on the boundary between the two processes, and working there is slow. |
251 | // Not as good | 81 | I usually just `cargo xtask install --server` and poke changes from my live environment. |
252 | struct Bar; | 82 | Note that this uses `--release`, which is usually faster overall, because loading stdlib into debug version of rust-analyzer takes a lot of time. |
83 | To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.withSysroot": false` in `.code/settings.json`. | ||
84 | This flag causes rust-analyzer to skip loading the sysroot, which greatly reduces the amount of things rust-analyzer needs to do, and makes printf's more useful. | ||
85 | Note that you should only use the `eprint!` family of macros for debugging: stdout is used for LSP communication, and `print!` would break it. | ||
253 | 86 | ||
254 | struct Foo { | 87 | If I need to fix something simultaneously in the server and in the client, I feel even more sad. |
255 | bars: Vec<Bar> | 88 | I don't have a specific workflow for this case. |
256 | } | ||
257 | ``` | ||
258 | 89 | ||
259 | ## Variable Naming | 90 | Additionally, I use `cargo run --release -p rust-analyzer -- analysis-stats path/to/some/rust/crate` to run a batch analysis. |
91 | This is primarily useful for performance optimizations, or for bug minimization. | ||
260 | 92 | ||
261 | We generally use boring and long names for local variables ([yay code completion](https://github.com/rust-analyzer/rust-analyzer/pull/4162#discussion_r417130973)). | 93 | ## Parser Tests |
262 | The default name is a lowercased name of the type: `global_state: GlobalState`. | ||
263 | Avoid ad-hoc acronyms and contractions, but use the ones that exist consistently (`db`, `ctx`, `acc`). | ||
264 | The default name for "result of the function" local variable is `res`. | ||
265 | |||
266 | ## Collection types | ||
267 | 94 | ||
268 | We prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. | 95 | Tests for the parser (`ra_parser`) live in the `ra_syntax` crate (see `test_data` directory). |
269 | They use a hasher that's slightly faster and using them consistently will reduce code size by some small amount. | 96 | There are two kinds of tests: |
270 | 97 | ||
271 | ## Preconditions | 98 | * Manually written test cases in `parser/ok` and `parser/err` |
99 | * "Inline" tests in `parser/inline` (these are generated) from comments in `ra_parser` crate. | ||
272 | 100 | ||
273 | Function preconditions should generally be expressed in types and provided by the caller (rather than checked by callee): | 101 | The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for. |
102 | If you are tempted to add a large inline test, it might be a good idea to leave only the simplest example in place, and move the test to a manual `parser/ok` test. | ||
274 | 103 | ||
275 | ```rust | 104 | To update test data, run with `UPDATE_EXPECT` variable: |
276 | // Good | ||
277 | fn frbonicate(walrus: Walrus) { | ||
278 | ... | ||
279 | } | ||
280 | 105 | ||
281 | // Not as good | 106 | ```bash |
282 | fn frobnicate(walrus: Option<Walrus>) { | 107 | env UPDATE_EXPECT=1 cargo qt |
283 | let walrus = match walrus { | ||
284 | Some(it) => it, | ||
285 | None => return, | ||
286 | }; | ||
287 | ... | ||
288 | } | ||
289 | ``` | 108 | ``` |
290 | 109 | ||
291 | ## Premature Pessimization | 110 | After adding a new inline test you need to run `cargo xtest codegen` and also update the test data as described above. |
292 | |||
293 | While we don't specifically optimize code yet, avoid writing code which is slower than it needs to be. | ||
294 | Don't allocate a `Vec` where an iterator would do, don't allocate strings needlessly. | ||
295 | 111 | ||
296 | ```rust | 112 | ## TypeScript Tests |
297 | // Good | ||
298 | use itertools::Itertools; | ||
299 | 113 | ||
300 | let (first_word, second_word) = match text.split_ascii_whitespace().collect_tuple() { | 114 | If you change files under `editors/code` and would like to run the tests and linter, install npm and run: |
301 | Some(it) => it, | ||
302 | None => return, | ||
303 | } | ||
304 | 115 | ||
305 | // Not as good | 116 | ```bash |
306 | let words = text.split_ascii_whitespace().collect::<Vec<_>>(); | 117 | cd editors/code |
307 | if words.len() != 2 { | 118 | npm ci |
308 | return | 119 | npm run lint |
309 | } | ||
310 | ``` | 120 | ``` |
311 | 121 | ||
312 | ## Documentation | 122 | # Code organization |
313 | |||
314 | For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines. | ||
315 | If the line is too long, you want to split the sentence in two :-) | ||
316 | |||
317 | ## Commit Style | ||
318 | 123 | ||
319 | We don't have specific rules around git history hygiene. | 124 | All Rust code lives in the `crates` top-level directory, and is organized as a single Cargo workspace. |
320 | Maintaining clean git history is encouraged, but not enforced. | 125 | The `editors` top-level directory contains code for integrating with editors. |
321 | We use rebase workflow, it's OK to rewrite history during PR review process. | 126 | Currently, it contains the plugin for VS Code (in TypeScript). |
127 | The `docs` top-level directory contains both developer and user documentation. | ||
322 | 128 | ||
323 | Avoid @mentioning people in commit messages and pull request descriptions (they are added to commit message by bors), as such messages create a lot of duplicate notification traffic during rebases. | 129 | We have some automation infra in Rust in the `xtask` package. |
130 | It contains stuff like formatting checking, code generation and powers `cargo xtask install`. | ||
131 | The latter syntax is achieved with the help of cargo aliases (see `.cargo` directory). | ||
324 | 132 | ||
325 | # Architecture Invariants | 133 | # Architecture Invariants |
326 | 134 | ||
@@ -355,35 +163,11 @@ The main IDE crate (`ra_ide`) uses "Plain Old Data" for the API. | |||
355 | Rather than talking in definitions and references, it talks in Strings and textual offsets. | 163 | Rather than talking in definitions and references, it talks in Strings and textual offsets. |
356 | In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath. | 164 | In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath. |
357 | The results are 100% Rust specific though. | 165 | The results are 100% Rust specific though. |
166 | Shout outs to LSP developers for popularizing the idea that "UI" is a good place to draw a boundary at. | ||
358 | 167 | ||
359 | ## Parser Tests | 168 | # Code Style & Review Process |
360 | |||
361 | Tests for the parser (`ra_parser`) live in the `ra_syntax` crate (see `test_data` directory). | ||
362 | There are two kinds of tests: | ||
363 | |||
364 | * Manually written test cases in `parser/ok` and `parser/err` | ||
365 | * "Inline" tests in `parser/inline` (these are generated) from comments in `ra_parser` crate. | ||
366 | |||
367 | The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for. | ||
368 | If you are tempted to add a large inline test, it might be a good idea to leave only the simplest example in place, and move the test to a manual `parser/ok` test. | ||
369 | |||
370 | To update test data, run with `UPDATE_EXPECT` variable: | ||
371 | |||
372 | ```bash | ||
373 | env UPDATE_EXPECT=1 cargo qt | ||
374 | ``` | ||
375 | |||
376 | After adding a new inline test you need to run `cargo xtest codegen` and also update the test data as described above. | ||
377 | |||
378 | ## TypeScript Tests | ||
379 | |||
380 | If you change files under `editors/code` and would like to run the tests and linter, install npm and run: | ||
381 | 169 | ||
382 | ```bash | 170 | Do see [./style.md](./style.md). |
383 | cd editors/code | ||
384 | npm ci | ||
385 | npm run lint | ||
386 | ``` | ||
387 | 171 | ||
388 | # Logging | 172 | # Logging |
389 | 173 | ||
@@ -451,3 +235,34 @@ For measuring time of incremental analysis, use either of these: | |||
451 | $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight ../chalk/chalk-engine/src/logic.rs | 235 | $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight ../chalk/chalk-engine/src/logic.rs |
452 | $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0 | 236 | $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0 |
453 | ``` | 237 | ``` |
238 | |||
239 | # Release Process | ||
240 | |||
241 | Release process is handled by `release`, `dist` and `promote` xtasks, `release` being the main one. | ||
242 | |||
243 | `release` assumes that you have checkouts of `rust-analyzer`, `rust-analyzer.github.io`, and `rust-lang/rust` in the same directory: | ||
244 | |||
245 | ``` | ||
246 | ./rust-analyzer | ||
247 | ./rust-analyzer.github.io | ||
248 | ./rust-rust-analyzer # Note the name! | ||
249 | ``` | ||
250 | |||
251 | Additionally, it assumes that remote for `rust-analyzer` is called `upstream` (I use `origin` to point to my fork). | ||
252 | |||
253 | Release steps: | ||
254 | |||
255 | 1. Inside rust-analyzer, run `cargo xtask release`. This will: | ||
256 | * checkout the `release` branch | ||
257 | * reset it to `upstream/nightly` | ||
258 | * push it to `upstream`. This triggers GitHub Actions which: | ||
259 | * runs `cargo xtask dist` to package binaries and VS Code extension | ||
260 | * makes a GitHub release | ||
261 | * pushes VS Code extension to the marketplace | ||
262 | * create new changelog in `rust-analyzer.github.io` | ||
263 | * create `rust-analyzer.github.io/git.log` file with the log of merge commits since last release | ||
264 | 2. While the release is in progress, fill-in the changelog using `git.log` | ||
265 | 3. Commit & push the changelog | ||
266 | 4. Tweet | ||
267 | 5. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's submodule. | ||
268 | Self-approve the PR. | ||
diff --git a/docs/dev/style.md b/docs/dev/style.md new file mode 100644 index 000000000..1c68f5702 --- /dev/null +++ b/docs/dev/style.md | |||
@@ -0,0 +1,212 @@ | |||
1 | Our approach to "clean code" is two-fold: | ||
2 | |||
3 | * We generally don't block PRs on style changes. | ||
4 | * At the same time, all code in rust-analyzer is constantly refactored. | ||
5 | |||
6 | It is explicitly OK for a reviewer to flag only some nits in the PR, and then send a follow-up cleanup PR for things which are easier to explain by example, cc-ing the original author. | ||
7 | Sending small cleanup PRs (like renaming a single local variable) is encouraged. | ||
8 | |||
9 | # Scale of Changes | ||
10 | |||
11 | Everyone knows that it's better to send small & focused pull requests. | ||
12 | The problem is, sometimes you *have* to, eg, rewrite the whole compiler, and that just doesn't fit into a set of isolated PRs. | ||
13 | |||
14 | The main things to keep an eye on are the boundaries between various components. | ||
15 | There are three kinds of changes: | ||
16 | |||
17 | 1. Internals of a single component are changed. | ||
18 | Specifically, you don't change any `pub` items. | ||
19 | A good example here would be an addition of a new assist. | ||
20 | |||
21 | 2. API of a component is expanded. | ||
22 | Specifically, you add a new `pub` function which wasn't there before. | ||
23 | A good example here would be expansion of assist API, for example, to implement lazy assists or assists groups. | ||
24 | |||
25 | 3. A new dependency between components is introduced. | ||
26 | Specifically, you add a `pub use` reexport from another crate or you add a new line to the `[dependencies]` section of `Cargo.toml`. | ||
27 | A good example here would be adding reference search capability to the assists crates. | ||
28 | |||
29 | For the first group, the change is generally merged as long as: | ||
30 | |||
31 | * it works for the happy case, | ||
32 | * it has tests, | ||
33 | * it doesn't panic for the unhappy case. | ||
34 | |||
35 | For the second group, the change would be subjected to quite a bit of scrutiny and iteration. | ||
36 | The new API needs to be right (or at least easy to change later). | ||
37 | The actual implementation doesn't matter that much. | ||
38 | It's very important to minimize the amount of changed lines of code for changes of the second kind. | ||
39 | Often, you start doing a change of the first kind, only to realise that you need to elevate to a change of the second kind. | ||
40 | In this case, we'll probably ask you to split API changes into a separate PR. | ||
41 | |||
42 | Changes of the third group should be pretty rare, so we don't specify any specific process for them. | ||
43 | That said, adding an innocent-looking `pub use` is a very simple way to break encapsulation, keep an eye on it! | ||
44 | |||
45 | Note: if you enjoyed this abstract hand-waving about boundaries, you might appreciate | ||
46 | https://www.tedinski.com/2018/02/06/system-boundaries.html | ||
47 | |||
48 | # Crates.io Dependencies | ||
49 | |||
50 | We try to be very conservative with usage of crates.io dependencies. | ||
51 | Don't use small "helper" crates (exception: `itertools` is allowed). | ||
52 | If there's some general reusable bit of code you need, consider adding it to the `stdx` crate. | ||
53 | |||
54 | # Minimal Tests | ||
55 | |||
56 | Most tests in rust-analyzer start with a snippet of Rust code. | ||
57 | This snippets should be minimal -- if you copy-paste a snippet of real code into the tests, make sure to remove everything which could be removed. | ||
58 | There are many benefits to this: | ||
59 | |||
60 | * less to read or to scroll past | ||
61 | * easier to understand what exactly is tested | ||
62 | * less stuff printed during printf-debugging | ||
63 | * less time to run test | ||
64 | |||
65 | It also makes sense to format snippets more compactly (for example, by placing enum definitions like `enum E { Foo, Bar }` on a single line), | ||
66 | as long as they are still readable. | ||
67 | |||
68 | ## Order of Imports | ||
69 | |||
70 | Separate import groups with blank lines. | ||
71 | Use one `use` per crate. | ||
72 | |||
73 | ```rust | ||
74 | mod x; | ||
75 | mod y; | ||
76 | |||
77 | // First std. | ||
78 | use std::{ ... } | ||
79 | |||
80 | // Second, external crates (both crates.io crates and other rust-analyzer crates). | ||
81 | use crate_foo::{ ... } | ||
82 | use crate_bar::{ ... } | ||
83 | |||
84 | // Then current crate. | ||
85 | use crate::{} | ||
86 | |||
87 | // Finally, parent and child modules, but prefer `use crate::`. | ||
88 | use super::{} | ||
89 | ``` | ||
90 | |||
91 | Module declarations come before the imports. | ||
92 | Order them in "suggested reading order" for a person new to the code base. | ||
93 | |||
94 | ## Import Style | ||
95 | |||
96 | Qualify items from `hir` and `ast`. | ||
97 | |||
98 | ```rust | ||
99 | // Good | ||
100 | use ra_syntax::ast; | ||
101 | |||
102 | fn frobnicate(func: hir::Function, strukt: ast::StructDef) {} | ||
103 | |||
104 | // Not as good | ||
105 | use hir::Function; | ||
106 | use ra_syntax::ast::StructDef; | ||
107 | |||
108 | fn frobnicate(func: Function, strukt: StructDef) {} | ||
109 | ``` | ||
110 | |||
111 | Avoid local `use MyEnum::*` imports. | ||
112 | |||
113 | Prefer `use crate::foo::bar` to `use super::bar`. | ||
114 | |||
115 | ## Order of Items | ||
116 | |||
117 | Optimize for the reader who sees the file for the first time, and wants to get a general idea about what's going on. | ||
118 | People read things from top to bottom, so place most important things first. | ||
119 | |||
120 | Specifically, if all items except one are private, always put the non-private item on top. | ||
121 | |||
122 | Put `struct`s and `enum`s first, functions and impls last. | ||
123 | |||
124 | Do | ||
125 | |||
126 | ```rust | ||
127 | // Good | ||
128 | struct Foo { | ||
129 | bars: Vec<Bar> | ||
130 | } | ||
131 | |||
132 | struct Bar; | ||
133 | ``` | ||
134 | |||
135 | rather than | ||
136 | |||
137 | ```rust | ||
138 | // Not as good | ||
139 | struct Bar; | ||
140 | |||
141 | struct Foo { | ||
142 | bars: Vec<Bar> | ||
143 | } | ||
144 | ``` | ||
145 | |||
146 | ## Variable Naming | ||
147 | |||
148 | Use boring and long names for local variables ([yay code completion](https://github.com/rust-analyzer/rust-analyzer/pull/4162#discussion_r417130973)). | ||
149 | The default name is a lowercased name of the type: `global_state: GlobalState`. | ||
150 | Avoid ad-hoc acronyms and contractions, but use the ones that exist consistently (`db`, `ctx`, `acc`). | ||
151 | The default name for "result of the function" local variable is `res`. | ||
152 | The default name for "I don't really care about the name" variable is `it`. | ||
153 | |||
154 | ## Collection types | ||
155 | |||
156 | Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. | ||
157 | They use a hasher that's slightly faster and using them consistently will reduce code size by some small amount. | ||
158 | |||
159 | ## Preconditions | ||
160 | |||
161 | Express function preconditions in types and force the caller to provide them (rather than checking in callee): | ||
162 | |||
163 | ```rust | ||
164 | // Good | ||
165 | fn frbonicate(walrus: Walrus) { | ||
166 | ... | ||
167 | } | ||
168 | |||
169 | // Not as good | ||
170 | fn frobnicate(walrus: Option<Walrus>) { | ||
171 | let walrus = match walrus { | ||
172 | Some(it) => it, | ||
173 | None => return, | ||
174 | }; | ||
175 | ... | ||
176 | } | ||
177 | ``` | ||
178 | |||
179 | ## Premature Pessimization | ||
180 | |||
181 | Avoid writing code which is slower than it needs to be. | ||
182 | Don't allocate a `Vec` where an iterator would do, don't allocate strings needlessly. | ||
183 | |||
184 | ```rust | ||
185 | // Good | ||
186 | use itertools::Itertools; | ||
187 | |||
188 | let (first_word, second_word) = match text.split_ascii_whitespace().collect_tuple() { | ||
189 | Some(it) => it, | ||
190 | None => return, | ||
191 | } | ||
192 | |||
193 | // Not as good | ||
194 | let words = text.split_ascii_whitespace().collect::<Vec<_>>(); | ||
195 | if words.len() != 2 { | ||
196 | return | ||
197 | } | ||
198 | ``` | ||
199 | |||
200 | ## Documentation | ||
201 | |||
202 | For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines. | ||
203 | If the line is too long, you want to split the sentence in two :-) | ||
204 | |||
205 | ## Commit Style | ||
206 | |||
207 | We don't have specific rules around git history hygiene. | ||
208 | Maintaining clean git history is encouraged, but not enforced. | ||
209 | Use rebase workflow, it's OK to rewrite history during PR review process. | ||
210 | |||
211 | Avoid @mentioning people in commit messages and pull request descriptions(they are added to commit message by bors). | ||
212 | Such messages create a lot of duplicate notification traffic during rebases. | ||
diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md index d4bc4b07c..f1bcdc4af 100644 --- a/docs/dev/syntax.md +++ b/docs/dev/syntax.md | |||
@@ -74,7 +74,7 @@ Points of note: | |||
74 | * The original text can be recovered by concatenating the texts of all tokens in order. | 74 | * The original text can be recovered by concatenating the texts of all tokens in order. |
75 | * Accessing a child of particular type (for example, parameter list of a function) generally involves linerary traversing the children, looking for a specific `kind`. | 75 | * Accessing a child of particular type (for example, parameter list of a function) generally involves linerary traversing the children, looking for a specific `kind`. |
76 | * Modifying the tree is roughly `O(depth)`. | 76 | * Modifying the tree is roughly `O(depth)`. |
77 | We don't make special efforts to guarantree that the depth is not liner, but, in practice, syntax trees are branchy and shallow. | 77 | We don't make special efforts to guarantee that the depth is not linear, but, in practice, syntax trees are branchy and shallow. |
78 | * If mandatory (grammar wise) node is missing from the input, it's just missing from the tree. | 78 | * If mandatory (grammar wise) node is missing from the input, it's just missing from the tree. |
79 | * If an extra erroneous input is present, it is wrapped into a node with `ERROR` kind, and treated just like any other node. | 79 | * If an extra erroneous input is present, it is wrapped into a node with `ERROR` kind, and treated just like any other node. |
80 | * Parser errors are not a part of syntax tree. | 80 | * Parser errors are not a part of syntax tree. |
diff --git a/editors/code/package.json b/editors/code/package.json index 1adf055d0..ee5f96bf3 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -607,7 +607,7 @@ | |||
607 | "items": { | 607 | "items": { |
608 | "type": "string" | 608 | "type": "string" |
609 | }, | 609 | }, |
610 | "description": "List of warnings warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.", | 610 | "description": "List of warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.", |
611 | "default": [] | 611 | "default": [] |
612 | } | 612 | } |
613 | } | 613 | } |
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 18948cb3c..f5db55b8c 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts | |||
@@ -4,7 +4,7 @@ import * as ra from '../src/lsp_ext'; | |||
4 | import * as Is from 'vscode-languageclient/lib/utils/is'; | 4 | import * as Is from 'vscode-languageclient/lib/utils/is'; |
5 | 5 | ||
6 | import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed'; | 6 | import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed'; |
7 | import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; | 7 | import { SemanticTokensFeature } from 'vscode-languageclient/lib/semanticTokens.proposed'; |
8 | import { assert } from './util'; | 8 | import { assert } from './util'; |
9 | 9 | ||
10 | function renderCommand(cmd: ra.CommandLink) { | 10 | function renderCommand(cmd: ra.CommandLink) { |
@@ -44,12 +44,6 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient | |||
44 | diagnosticCollectionName: "rustc", | 44 | diagnosticCollectionName: "rustc", |
45 | traceOutputChannel, | 45 | traceOutputChannel, |
46 | middleware: { | 46 | middleware: { |
47 | // Workaround for https://github.com/microsoft/vscode-languageserver-node/issues/576 | ||
48 | async provideDocumentSemanticTokens(document: vscode.TextDocument, token: vscode.CancellationToken, next: DocumentSemanticsTokensSignature) { | ||
49 | const res = await next(document, token); | ||
50 | if (res === undefined) throw new Error('busy'); | ||
51 | return res; | ||
52 | }, | ||
53 | async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, _next: lc.ProvideHoverSignature) { | 47 | async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, _next: lc.ProvideHoverSignature) { |
54 | return client.sendRequest(lc.HoverRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then( | 48 | return client.sendRequest(lc.HoverRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then( |
55 | (result) => { | 49 | (result) => { |
@@ -135,7 +129,7 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient | |||
135 | ); | 129 | ); |
136 | } | 130 | } |
137 | 131 | ||
138 | } as any | 132 | } |
139 | }; | 133 | }; |
140 | 134 | ||
141 | const client = new lc.LanguageClient( | 135 | const client = new lc.LanguageClient( |
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 970fedb37..49d2d1c6f 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts | |||
@@ -64,7 +64,8 @@ export async function sendRequestWithRetry<TParam, TRet>( | |||
64 | param: TParam, | 64 | param: TParam, |
65 | token?: vscode.CancellationToken, | 65 | token?: vscode.CancellationToken, |
66 | ): Promise<TRet> { | 66 | ): Promise<TRet> { |
67 | for (const delay of [2, 4, 6, 8, 10, null]) { | 67 | // The sequence is `10 * (2 ** (2 * n))` where n is 1, 2, 3... |
68 | for (const delay of [40, 160, 640, 2560, 10240, null]) { | ||
68 | try { | 69 | try { |
69 | return await (token | 70 | return await (token |
70 | ? client.sendRequest(reqType, param, token) | 71 | ? client.sendRequest(reqType, param, token) |
@@ -84,8 +85,7 @@ export async function sendRequestWithRetry<TParam, TRet>( | |||
84 | log.warn("LSP request failed", { method: reqType.method, param, error }); | 85 | log.warn("LSP request failed", { method: reqType.method, param, error }); |
85 | throw error; | 86 | throw error; |
86 | } | 87 | } |
87 | 88 | await sleep(delay); | |
88 | await sleep(10 * (1 << delay)); | ||
89 | } | 89 | } |
90 | } | 90 | } |
91 | throw 'unreachable'; | 91 | throw 'unreachable'; |
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 72a2ae26b..1a1140b04 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml | |||
@@ -15,6 +15,6 @@ flate2 = "1.0" | |||
15 | pico-args = "0.3.1" | 15 | pico-args = "0.3.1" |
16 | proc-macro2 = "1.0.8" | 16 | proc-macro2 = "1.0.8" |
17 | quote = "1.0.2" | 17 | quote = "1.0.2" |
18 | ungrammar = "0.1.0" | 18 | ungrammar = "1.1.1" |
19 | walkdir = "2.3.1" | 19 | walkdir = "2.3.1" |
20 | write-json = "0.1.0" | 20 | write-json = "0.1.0" |
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 1386fc4e7..adc191254 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -113,12 +113,12 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
113 | "TUPLE_TYPE", | 113 | "TUPLE_TYPE", |
114 | "NEVER_TYPE", | 114 | "NEVER_TYPE", |
115 | "PATH_TYPE", | 115 | "PATH_TYPE", |
116 | "POINTER_TYPE", | 116 | "PTR_TYPE", |
117 | "ARRAY_TYPE", | 117 | "ARRAY_TYPE", |
118 | "SLICE_TYPE", | 118 | "SLICE_TYPE", |
119 | "REFERENCE_TYPE", | 119 | "REF_TYPE", |
120 | "INFER_TYPE", | 120 | "INFER_TYPE", |
121 | "FN_POINTER_TYPE", | 121 | "FN_PTR_TYPE", |
122 | "FOR_TYPE", | 122 | "FOR_TYPE", |
123 | "IMPL_TRAIT_TYPE", | 123 | "IMPL_TRAIT_TYPE", |
124 | "DYN_TRAIT_TYPE", | 124 | "DYN_TRAIT_TYPE", |
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 4602ff1d7..cafad8070 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -10,7 +10,7 @@ use std::{ | |||
10 | 10 | ||
11 | use proc_macro2::{Punct, Spacing}; | 11 | use proc_macro2::{Punct, Spacing}; |
12 | use quote::{format_ident, quote}; | 12 | use quote::{format_ident, quote}; |
13 | use ungrammar::{Grammar, Rule}; | 13 | use ungrammar::{rust_grammar, Grammar, Rule}; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC}, | 16 | ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC}, |
@@ -19,9 +19,7 @@ use crate::{ | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | pub fn generate_syntax(mode: Mode) -> Result<()> { | 21 | pub fn generate_syntax(mode: Mode) -> Result<()> { |
22 | let grammar = include_str!("rust.ungram") | 22 | let grammar = rust_grammar(); |
23 | .parse::<Grammar>() | ||
24 | .unwrap_or_else(|err| panic!("\n \x1b[91merror\x1b[0m: {}\n", err)); | ||
25 | let ast = lower(&grammar); | 23 | let ast = lower(&grammar); |
26 | 24 | ||
27 | let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); | 25 | let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); |
@@ -538,6 +536,7 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> { | |||
538 | for alternative in alternatives { | 536 | for alternative in alternatives { |
539 | match alternative { | 537 | match alternative { |
540 | Rule::Node(it) => variants.push(grammar[*it].name.clone()), | 538 | Rule::Node(it) => variants.push(grammar[*it].name.clone()), |
539 | Rule::Token(it) if grammar[*it].name == ";" => (), | ||
541 | _ => return None, | 540 | _ => return None, |
542 | } | 541 | } |
543 | } | 542 | } |
@@ -591,8 +590,8 @@ fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, r | |||
591 | | "index" | 590 | | "index" |
592 | | "base" | 591 | | "base" |
593 | | "value" | 592 | | "value" |
594 | | "target_type" | 593 | | "trait" |
595 | | "target_trait" | 594 | | "self_ty" |
596 | ); | 595 | ); |
597 | if manually_implemented { | 596 | if manually_implemented { |
598 | return; | 597 | return; |
diff --git a/xtask/tests/tidy.rs b/xtask/tests/tidy.rs index d65a2acbc..4ff72865e 100644 --- a/xtask/tests/tidy.rs +++ b/xtask/tests/tidy.rs | |||
@@ -44,11 +44,26 @@ fn rust_files_are_tidy() { | |||
44 | let text = fs2::read_to_string(&path).unwrap(); | 44 | let text = fs2::read_to_string(&path).unwrap(); |
45 | check_todo(&path, &text); | 45 | check_todo(&path, &text); |
46 | check_trailing_ws(&path, &text); | 46 | check_trailing_ws(&path, &text); |
47 | deny_clippy(&path, &text); | ||
47 | tidy_docs.visit(&path, &text); | 48 | tidy_docs.visit(&path, &text); |
48 | } | 49 | } |
49 | tidy_docs.finish(); | 50 | tidy_docs.finish(); |
50 | } | 51 | } |
51 | 52 | ||
53 | fn deny_clippy(path: &PathBuf, text: &String) { | ||
54 | if text.contains("[\u{61}llow(clippy") { | ||
55 | panic!( | ||
56 | "\n\nallowing lints is forbidden: {}. | ||
57 | rust-analyzer intentionally doesn't check clippy on CI. | ||
58 | You can allow lint globally via `xtask clippy`. | ||
59 | See https://github.com/rust-lang/rust-clippy/issues/5537 for discussion. | ||
60 | |||
61 | ", | ||
62 | path.display() | ||
63 | ) | ||
64 | } | ||
65 | } | ||
66 | |||
52 | #[test] | 67 | #[test] |
53 | fn check_licenses() { | 68 | fn check_licenses() { |
54 | let expected = " | 69 | let expected = " |