diff options
89 files changed, 1189 insertions, 591 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a97ed24ba..94b6aa7c4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml | |||
@@ -94,6 +94,7 @@ jobs: | |||
94 | toolchain: stable | 94 | toolchain: stable |
95 | profile: minimal | 95 | profile: minimal |
96 | override: true | 96 | override: true |
97 | components: rust-src | ||
97 | 98 | ||
98 | - name: Install Nodejs | 99 | - name: Install Nodejs |
99 | uses: actions/setup-node@v1 | 100 | uses: actions/setup-node@v1 |
@@ -108,10 +109,12 @@ jobs: | |||
108 | if: github.ref != 'refs/heads/release' | 109 | if: github.ref != 'refs/heads/release' |
109 | run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly | 110 | run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly |
110 | 111 | ||
111 | - name: Nightly analysis-stats check | 112 | - name: Run analysis-stats on rust-analyzer |
112 | if: github.ref != 'refs/heads/release' | ||
113 | run: target/${{ env.RA_TARGET }}/release/rust-analyzer analysis-stats . | 113 | run: target/${{ env.RA_TARGET }}/release/rust-analyzer analysis-stats . |
114 | 114 | ||
115 | - name: Run analysis-stats on rust std library | ||
116 | run: target/${{ env.RA_TARGET }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std | ||
117 | |||
115 | - name: Upload artifacts | 118 | - name: Upload artifacts |
116 | uses: actions/upload-artifact@v1 | 119 | uses: actions/upload-artifact@v1 |
117 | with: | 120 | with: |
diff --git a/Cargo.lock b/Cargo.lock index 901784bec..bf1b9e417 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -77,15 +77,15 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" | |||
77 | 77 | ||
78 | [[package]] | 78 | [[package]] |
79 | name = "backtrace" | 79 | name = "backtrace" |
80 | version = "0.3.55" | 80 | version = "0.3.56" |
81 | source = "registry+https://github.com/rust-lang/crates.io-index" | 81 | source = "registry+https://github.com/rust-lang/crates.io-index" |
82 | checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" | 82 | checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" |
83 | dependencies = [ | 83 | dependencies = [ |
84 | "addr2line", | 84 | "addr2line", |
85 | "cfg-if 1.0.0", | 85 | "cfg-if 1.0.0", |
86 | "libc", | 86 | "libc", |
87 | "miniz_oxide", | 87 | "miniz_oxide", |
88 | "object 0.22.0", | 88 | "object", |
89 | "rustc-demangle", | 89 | "rustc-demangle", |
90 | ] | 90 | ] |
91 | 91 | ||
@@ -175,9 +175,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |||
175 | 175 | ||
176 | [[package]] | 176 | [[package]] |
177 | name = "chalk-derive" | 177 | name = "chalk-derive" |
178 | version = "0.47.0" | 178 | version = "0.50.0" |
179 | source = "registry+https://github.com/rust-lang/crates.io-index" | 179 | source = "registry+https://github.com/rust-lang/crates.io-index" |
180 | checksum = "3f00f6342a387edc822002d36a381e117afcac9f744951ff75fbf4a218edea5c" | 180 | checksum = "ac605cf409013573e971d7292d4bec6f5495b19d5f98fc9d8b1a12270c3888e0" |
181 | dependencies = [ | 181 | dependencies = [ |
182 | "proc-macro2", | 182 | "proc-macro2", |
183 | "quote", | 183 | "quote", |
@@ -187,9 +187,9 @@ dependencies = [ | |||
187 | 187 | ||
188 | [[package]] | 188 | [[package]] |
189 | name = "chalk-ir" | 189 | name = "chalk-ir" |
190 | version = "0.47.0" | 190 | version = "0.50.0" |
191 | source = "registry+https://github.com/rust-lang/crates.io-index" | 191 | source = "registry+https://github.com/rust-lang/crates.io-index" |
192 | checksum = "c686e69913591ae753e5526e73cbee39db3d9b0a92cc9078ab780cabf1c70aa9" | 192 | checksum = "fa1dbfb3c2c8b67edb5cd981f720550e43579090574f786145731f90c5d401ff" |
193 | dependencies = [ | 193 | dependencies = [ |
194 | "bitflags", | 194 | "bitflags", |
195 | "chalk-derive", | 195 | "chalk-derive", |
@@ -198,9 +198,9 @@ dependencies = [ | |||
198 | 198 | ||
199 | [[package]] | 199 | [[package]] |
200 | name = "chalk-recursive" | 200 | name = "chalk-recursive" |
201 | version = "0.47.0" | 201 | version = "0.50.0" |
202 | source = "registry+https://github.com/rust-lang/crates.io-index" | 202 | source = "registry+https://github.com/rust-lang/crates.io-index" |
203 | checksum = "310fdcac0340dab4163b766baa8067266e3b909108d1ac1b5246c033bde63975" | 203 | checksum = "0882e2a3ba66901717a64f8bb0655e809f800ac6abed05cb605e7a41d4bf8999" |
204 | dependencies = [ | 204 | dependencies = [ |
205 | "chalk-derive", | 205 | "chalk-derive", |
206 | "chalk-ir", | 206 | "chalk-ir", |
@@ -211,9 +211,9 @@ dependencies = [ | |||
211 | 211 | ||
212 | [[package]] | 212 | [[package]] |
213 | name = "chalk-solve" | 213 | name = "chalk-solve" |
214 | version = "0.47.0" | 214 | version = "0.50.0" |
215 | source = "registry+https://github.com/rust-lang/crates.io-index" | 215 | source = "registry+https://github.com/rust-lang/crates.io-index" |
216 | checksum = "c3c3252116111c3548f1164ab8d98c67c49848b3bde10dd11b650fd023e91c72" | 216 | checksum = "0d43cce07150eac39771ff4b198537cefef744734b2218a89c682295b54cd8d0" |
217 | dependencies = [ | 217 | dependencies = [ |
218 | "chalk-derive", | 218 | "chalk-derive", |
219 | "chalk-ir", | 219 | "chalk-ir", |
@@ -274,6 +274,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
274 | checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" | 274 | checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" |
275 | 275 | ||
276 | [[package]] | 276 | [[package]] |
277 | name = "countme" | ||
278 | version = "2.0.0-pre.2" | ||
279 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
280 | checksum = "c5716604cba7c02a846ecad3f4a3fd2d2b641faccc2a24a51efb21aff0d01f35" | ||
281 | dependencies = [ | ||
282 | "dashmap", | ||
283 | "once_cell", | ||
284 | "rustc-hash", | ||
285 | ] | ||
286 | |||
287 | [[package]] | ||
277 | name = "crc32fast" | 288 | name = "crc32fast" |
278 | version = "1.2.1" | 289 | version = "1.2.1" |
279 | source = "registry+https://github.com/rust-lang/crates.io-index" | 290 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -323,7 +334,7 @@ dependencies = [ | |||
323 | "const_fn", | 334 | "const_fn", |
324 | "crossbeam-utils 0.8.1", | 335 | "crossbeam-utils 0.8.1", |
325 | "lazy_static", | 336 | "lazy_static", |
326 | "memoffset 0.6.1", | 337 | "memoffset", |
327 | "scopeguard", | 338 | "scopeguard", |
328 | ] | 339 | ] |
329 | 340 | ||
@@ -350,6 +361,16 @@ dependencies = [ | |||
350 | ] | 361 | ] |
351 | 362 | ||
352 | [[package]] | 363 | [[package]] |
364 | name = "dashmap" | ||
365 | version = "4.0.2" | ||
366 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
367 | checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" | ||
368 | dependencies = [ | ||
369 | "cfg-if 1.0.0", | ||
370 | "num_cpus", | ||
371 | ] | ||
372 | |||
373 | [[package]] | ||
353 | name = "dissimilar" | 374 | name = "dissimilar" |
354 | version = "1.0.2" | 375 | version = "1.0.2" |
355 | source = "registry+https://github.com/rust-lang/crates.io-index" | 376 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -397,13 +418,13 @@ dependencies = [ | |||
397 | 418 | ||
398 | [[package]] | 419 | [[package]] |
399 | name = "filetime" | 420 | name = "filetime" |
400 | version = "0.2.13" | 421 | version = "0.2.14" |
401 | source = "registry+https://github.com/rust-lang/crates.io-index" | 422 | source = "registry+https://github.com/rust-lang/crates.io-index" |
402 | checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe" | 423 | checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" |
403 | dependencies = [ | 424 | dependencies = [ |
404 | "cfg-if 1.0.0", | 425 | "cfg-if 1.0.0", |
405 | "libc", | 426 | "libc", |
406 | "redox_syscall", | 427 | "redox_syscall 0.2.4", |
407 | "winapi 0.3.9", | 428 | "winapi 0.3.9", |
408 | ] | 429 | ] |
409 | 430 | ||
@@ -942,15 +963,6 @@ dependencies = [ | |||
942 | 963 | ||
943 | [[package]] | 964 | [[package]] |
944 | name = "memoffset" | 965 | name = "memoffset" |
945 | version = "0.5.6" | ||
946 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
947 | checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" | ||
948 | dependencies = [ | ||
949 | "autocfg", | ||
950 | ] | ||
951 | |||
952 | [[package]] | ||
953 | name = "memoffset" | ||
954 | version = "0.6.1" | 966 | version = "0.6.1" |
955 | source = "registry+https://github.com/rust-lang/crates.io-index" | 967 | source = "registry+https://github.com/rust-lang/crates.io-index" |
956 | checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" | 968 | checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" |
@@ -1082,12 +1094,6 @@ dependencies = [ | |||
1082 | 1094 | ||
1083 | [[package]] | 1095 | [[package]] |
1084 | name = "object" | 1096 | name = "object" |
1085 | version = "0.22.0" | ||
1086 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1087 | checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" | ||
1088 | |||
1089 | [[package]] | ||
1090 | name = "object" | ||
1091 | version = "0.23.0" | 1097 | version = "0.23.0" |
1092 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1098 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1093 | checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" | 1099 | checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" |
@@ -1124,7 +1130,7 @@ dependencies = [ | |||
1124 | "cfg-if 1.0.0", | 1130 | "cfg-if 1.0.0", |
1125 | "instant", | 1131 | "instant", |
1126 | "libc", | 1132 | "libc", |
1127 | "redox_syscall", | 1133 | "redox_syscall 0.1.57", |
1128 | "smallvec", | 1134 | "smallvec", |
1129 | "winapi 0.3.9", | 1135 | "winapi 0.3.9", |
1130 | ] | 1136 | ] |
@@ -1205,9 +1211,9 @@ dependencies = [ | |||
1205 | 1211 | ||
1206 | [[package]] | 1212 | [[package]] |
1207 | name = "pico-args" | 1213 | name = "pico-args" |
1208 | version = "0.3.4" | 1214 | version = "0.4.0" |
1209 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1210 | checksum = "28b9b4df73455c861d7cbf8be42f01d3b373ed7f02e378d55fa84eafc6f638b1" | 1216 | checksum = "d70072c20945e1ab871c472a285fc772aefd4f5407723c206242f2c6f94595d6" |
1211 | 1217 | ||
1212 | [[package]] | 1218 | [[package]] |
1213 | name = "pin-project-lite" | 1219 | name = "pin-project-lite" |
@@ -1251,7 +1257,7 @@ dependencies = [ | |||
1251 | "libloading", | 1257 | "libloading", |
1252 | "mbe", | 1258 | "mbe", |
1253 | "memmap", | 1259 | "memmap", |
1254 | "object 0.23.0", | 1260 | "object", |
1255 | "proc_macro_api", | 1261 | "proc_macro_api", |
1256 | "proc_macro_test", | 1262 | "proc_macro_test", |
1257 | "serde_derive", | 1263 | "serde_derive", |
@@ -1269,6 +1275,7 @@ name = "profile" | |||
1269 | version = "0.0.0" | 1275 | version = "0.0.0" |
1270 | dependencies = [ | 1276 | dependencies = [ |
1271 | "cfg-if 1.0.0", | 1277 | "cfg-if 1.0.0", |
1278 | "countme", | ||
1272 | "jemalloc-ctl", | 1279 | "jemalloc-ctl", |
1273 | "la-arena", | 1280 | "la-arena", |
1274 | "libc", | 1281 | "libc", |
@@ -1358,6 +1365,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1358 | checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" | 1365 | checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" |
1359 | 1366 | ||
1360 | [[package]] | 1367 | [[package]] |
1368 | name = "redox_syscall" | ||
1369 | version = "0.2.4" | ||
1370 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1371 | checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" | ||
1372 | dependencies = [ | ||
1373 | "bitflags", | ||
1374 | ] | ||
1375 | |||
1376 | [[package]] | ||
1361 | name = "regex" | 1377 | name = "regex" |
1362 | version = "1.4.3" | 1378 | version = "1.4.3" |
1363 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1384,15 +1400,15 @@ checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" | |||
1384 | 1400 | ||
1385 | [[package]] | 1401 | [[package]] |
1386 | name = "rowan" | 1402 | name = "rowan" |
1387 | version = "0.10.6" | 1403 | version = "0.12.1" |
1388 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1389 | checksum = "8a0734142c18710f7214dc21908e2f054e973b908dbb1a602a3e6691615aaaae" | 1405 | checksum = "24c2d78254049413f9d73495f883e7fa0b7a7d4b88468cd72a3bbbd0ad585cd1" |
1390 | dependencies = [ | 1406 | dependencies = [ |
1407 | "countme", | ||
1391 | "hashbrown", | 1408 | "hashbrown", |
1409 | "memoffset", | ||
1392 | "rustc-hash", | 1410 | "rustc-hash", |
1393 | "smol_str", | ||
1394 | "text-size", | 1411 | "text-size", |
1395 | "triomphe", | ||
1396 | ] | 1412 | ] |
1397 | 1413 | ||
1398 | [[package]] | 1414 | [[package]] |
@@ -1448,9 +1464,9 @@ dependencies = [ | |||
1448 | 1464 | ||
1449 | [[package]] | 1465 | [[package]] |
1450 | name = "rustc-ap-rustc_lexer" | 1466 | name = "rustc-ap-rustc_lexer" |
1451 | version = "697.0.0" | 1467 | version = "700.0.0" |
1452 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1453 | checksum = "67adbe260a0a11910624d6d28c0304fcf7b063e666682111005c83b09f73429d" | 1469 | checksum = "5ed36784376b69c941d7aa36e960a52ac712e2663960357121a4d9f2cc58e225" |
1454 | dependencies = [ | 1470 | dependencies = [ |
1455 | "unicode-xid", | 1471 | "unicode-xid", |
1456 | ] | 1472 | ] |
@@ -1544,18 +1560,18 @@ dependencies = [ | |||
1544 | 1560 | ||
1545 | [[package]] | 1561 | [[package]] |
1546 | name = "serde" | 1562 | name = "serde" |
1547 | version = "1.0.119" | 1563 | version = "1.0.120" |
1548 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1549 | checksum = "9bdd36f49e35b61d49efd8aa7fc068fd295961fd2286d0b2ee9a4c7a14e99cc3" | 1565 | checksum = "166b2349061381baf54a58e4b13c89369feb0ef2eaa57198899e2312aac30aab" |
1550 | dependencies = [ | 1566 | dependencies = [ |
1551 | "serde_derive", | 1567 | "serde_derive", |
1552 | ] | 1568 | ] |
1553 | 1569 | ||
1554 | [[package]] | 1570 | [[package]] |
1555 | name = "serde_derive" | 1571 | name = "serde_derive" |
1556 | version = "1.0.119" | 1572 | version = "1.0.120" |
1557 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1573 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1558 | checksum = "552954ce79a059ddd5fd68c271592374bd15cab2274970380c000118aeffe1cd" | 1574 | checksum = "0ca2a8cb5805ce9e3b95435e3765b7b553cecc762d938d409434338386cb5775" |
1559 | dependencies = [ | 1575 | dependencies = [ |
1560 | "proc-macro2", | 1576 | "proc-macro2", |
1561 | "quote", | 1577 | "quote", |
@@ -1639,12 +1655,6 @@ dependencies = [ | |||
1639 | ] | 1655 | ] |
1640 | 1656 | ||
1641 | [[package]] | 1657 | [[package]] |
1642 | name = "stable_deref_trait" | ||
1643 | version = "1.2.0" | ||
1644 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1645 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" | ||
1646 | |||
1647 | [[package]] | ||
1648 | name = "stdx" | 1658 | name = "stdx" |
1649 | version = "0.0.0" | 1659 | version = "0.0.0" |
1650 | dependencies = [ | 1660 | dependencies = [ |
@@ -1872,17 +1882,6 @@ dependencies = [ | |||
1872 | ] | 1882 | ] |
1873 | 1883 | ||
1874 | [[package]] | 1884 | [[package]] |
1875 | name = "triomphe" | ||
1876 | version = "0.1.2" | ||
1877 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1878 | checksum = "6e9d872053cf9e5a833d8c1dd772cdc38ab66a908129d6f73c049c986161d07c" | ||
1879 | dependencies = [ | ||
1880 | "memoffset 0.5.6", | ||
1881 | "serde", | ||
1882 | "stable_deref_trait", | ||
1883 | ] | ||
1884 | |||
1885 | [[package]] | ||
1886 | name = "tt" | 1885 | name = "tt" |
1887 | version = "0.0.0" | 1886 | version = "0.0.0" |
1888 | dependencies = [ | 1887 | dependencies = [ |
diff --git a/crates/assists/src/handlers/generate_function.rs b/crates/assists/src/handlers/generate_function.rs index 06ac85f67..1805c1dfd 100644 --- a/crates/assists/src/handlers/generate_function.rs +++ b/crates/assists/src/handlers/generate_function.rs | |||
@@ -158,11 +158,11 @@ impl FunctionBuilder { | |||
158 | it.text_range().end() | 158 | it.text_range().end() |
159 | } | 159 | } |
160 | GeneratedFunctionTarget::InEmptyItemList(it) => { | 160 | GeneratedFunctionTarget::InEmptyItemList(it) => { |
161 | let indent = IndentLevel::from_node(it.syntax()); | 161 | let indent = IndentLevel::from_node(&it); |
162 | leading_ws = format!("\n{}", indent + 1); | 162 | leading_ws = format!("\n{}", indent + 1); |
163 | fn_def = fn_def.indent(indent + 1); | 163 | fn_def = fn_def.indent(indent + 1); |
164 | trailing_ws = format!("\n{}", indent); | 164 | trailing_ws = format!("\n{}", indent); |
165 | it.syntax().text_range().start() + TextSize::of('{') | 165 | it.text_range().start() + TextSize::of('{') |
166 | } | 166 | } |
167 | }; | 167 | }; |
168 | 168 | ||
@@ -179,14 +179,14 @@ impl FunctionBuilder { | |||
179 | 179 | ||
180 | enum GeneratedFunctionTarget { | 180 | enum GeneratedFunctionTarget { |
181 | BehindItem(SyntaxNode), | 181 | BehindItem(SyntaxNode), |
182 | InEmptyItemList(ast::ItemList), | 182 | InEmptyItemList(SyntaxNode), |
183 | } | 183 | } |
184 | 184 | ||
185 | impl GeneratedFunctionTarget { | 185 | impl GeneratedFunctionTarget { |
186 | fn syntax(&self) -> &SyntaxNode { | 186 | fn syntax(&self) -> &SyntaxNode { |
187 | match self { | 187 | match self { |
188 | GeneratedFunctionTarget::BehindItem(it) => it, | 188 | GeneratedFunctionTarget::BehindItem(it) => it, |
189 | GeneratedFunctionTarget::InEmptyItemList(it) => it.syntax(), | 189 | GeneratedFunctionTarget::InEmptyItemList(it) => it, |
190 | } | 190 | } |
191 | } | 191 | } |
192 | } | 192 | } |
@@ -323,7 +323,16 @@ fn next_space_for_fn_in_module( | |||
323 | if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) { | 323 | if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) { |
324 | GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) | 324 | GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) |
325 | } else { | 325 | } else { |
326 | GeneratedFunctionTarget::InEmptyItemList(it.item_list()?) | 326 | GeneratedFunctionTarget::InEmptyItemList(it.item_list()?.syntax().clone()) |
327 | } | ||
328 | } | ||
329 | hir::ModuleSource::BlockExpr(it) => { | ||
330 | if let Some(last_item) = | ||
331 | it.statements().take_while(|stmt| matches!(stmt, ast::Stmt::Item(_))).last() | ||
332 | { | ||
333 | GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) | ||
334 | } else { | ||
335 | GeneratedFunctionTarget::InEmptyItemList(it.syntax().clone()) | ||
327 | } | 336 | } |
328 | } | 337 | } |
329 | }; | 338 | }; |
diff --git a/crates/assists/src/handlers/generate_impl.rs b/crates/assists/src/handlers/generate_impl.rs index 9af45192b..827477272 100644 --- a/crates/assists/src/handlers/generate_impl.rs +++ b/crates/assists/src/handlers/generate_impl.rs | |||
@@ -1,6 +1,9 @@ | |||
1 | use itertools::Itertools; | 1 | use itertools::Itertools; |
2 | use stdx::format_to; | 2 | use stdx::format_to; |
3 | use syntax::ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner}; | 3 | use syntax::{ |
4 | ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner}, | ||
5 | SmolStr, | ||
6 | }; | ||
4 | 7 | ||
5 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
6 | 9 | ||
@@ -49,16 +52,16 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
49 | format_to!(buf, "{}", type_params.syntax()); | 52 | format_to!(buf, "{}", type_params.syntax()); |
50 | } | 53 | } |
51 | buf.push_str(" "); | 54 | buf.push_str(" "); |
52 | buf.push_str(name.text().as_str()); | 55 | buf.push_str(name.text()); |
53 | if let Some(type_params) = type_params { | 56 | if let Some(type_params) = type_params { |
54 | let lifetime_params = type_params | 57 | let lifetime_params = type_params |
55 | .lifetime_params() | 58 | .lifetime_params() |
56 | .filter_map(|it| it.lifetime()) | 59 | .filter_map(|it| it.lifetime()) |
57 | .map(|it| it.text().clone()); | 60 | .map(|it| SmolStr::from(it.text())); |
58 | let type_params = type_params | 61 | let type_params = type_params |
59 | .type_params() | 62 | .type_params() |
60 | .filter_map(|it| it.name()) | 63 | .filter_map(|it| it.name()) |
61 | .map(|it| it.text().clone()); | 64 | .map(|it| SmolStr::from(it.text())); |
62 | 65 | ||
63 | let generic_params = lifetime_params.chain(type_params).format(", "); | 66 | let generic_params = lifetime_params.chain(type_params).format(", "); |
64 | format_to!(buf, "<{}>", generic_params) | 67 | format_to!(buf, "<{}>", generic_params) |
diff --git a/crates/assists/src/handlers/generate_new.rs b/crates/assists/src/handlers/generate_new.rs index 5c52b2bc8..b7390855a 100644 --- a/crates/assists/src/handlers/generate_new.rs +++ b/crates/assists/src/handlers/generate_new.rs | |||
@@ -3,7 +3,7 @@ use itertools::Itertools; | |||
3 | use stdx::format_to; | 3 | use stdx::format_to; |
4 | use syntax::{ | 4 | use syntax::{ |
5 | ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner}, | 5 | ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner}, |
6 | T, | 6 | SmolStr, T, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 9 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
@@ -95,14 +95,14 @@ fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String { | |||
95 | format_to!(buf, "{}", type_params.syntax()); | 95 | format_to!(buf, "{}", type_params.syntax()); |
96 | } | 96 | } |
97 | buf.push_str(" "); | 97 | buf.push_str(" "); |
98 | buf.push_str(strukt.name().unwrap().text().as_str()); | 98 | buf.push_str(strukt.name().unwrap().text()); |
99 | if let Some(type_params) = type_params { | 99 | if let Some(type_params) = type_params { |
100 | let lifetime_params = type_params | 100 | let lifetime_params = type_params |
101 | .lifetime_params() | 101 | .lifetime_params() |
102 | .filter_map(|it| it.lifetime()) | 102 | .filter_map(|it| it.lifetime()) |
103 | .map(|it| it.text().clone()); | 103 | .map(|it| SmolStr::from(it.text())); |
104 | let type_params = | 104 | let type_params = |
105 | 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| SmolStr::from(it.text())); |
106 | format_to!(buf, "<{}>", lifetime_params.chain(type_params).format(", ")) | 106 | format_to!(buf, "<{}>", lifetime_params.chain(type_params).format(", ")) |
107 | } | 107 | } |
108 | 108 | ||
diff --git a/crates/assists/src/handlers/raw_string.rs b/crates/assists/src/handlers/raw_string.rs index be963f162..d95267607 100644 --- a/crates/assists/src/handlers/raw_string.rs +++ b/crates/assists/src/handlers/raw_string.rs | |||
@@ -138,7 +138,7 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
138 | return None; | 138 | return None; |
139 | } | 139 | } |
140 | 140 | ||
141 | let text = token.text().as_str(); | 141 | let text = token.text(); |
142 | if !text.starts_with("r#") && text.ends_with('#') { | 142 | if !text.starts_with("r#") && text.ends_with('#') { |
143 | return None; | 143 | return None; |
144 | } | 144 | } |
diff --git a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs index bd4c1c806..6aa9d2f2c 100644 --- a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs | |||
@@ -3,7 +3,7 @@ use ide_db::imports_locator; | |||
3 | use itertools::Itertools; | 3 | use itertools::Itertools; |
4 | use syntax::{ | 4 | use syntax::{ |
5 | ast::{self, make, AstNode}, | 5 | ast::{self, make, AstNode}, |
6 | Direction, SmolStr, | 6 | Direction, |
7 | SyntaxKind::{IDENT, WHITESPACE}, | 7 | SyntaxKind::{IDENT, WHITESPACE}, |
8 | TextSize, | 8 | TextSize, |
9 | }; | 9 | }; |
@@ -43,17 +43,18 @@ pub(crate) fn replace_derive_with_manual_impl( | |||
43 | ) -> Option<()> { | 43 | ) -> Option<()> { |
44 | let attr = ctx.find_node_at_offset::<ast::Attr>()?; | 44 | let attr = ctx.find_node_at_offset::<ast::Attr>()?; |
45 | 45 | ||
46 | let attr_name = attr | 46 | let has_derive = attr |
47 | .syntax() | 47 | .syntax() |
48 | .descendants_with_tokens() | 48 | .descendants_with_tokens() |
49 | .filter(|t| t.kind() == IDENT) | 49 | .filter(|t| t.kind() == IDENT) |
50 | .find_map(syntax::NodeOrToken::into_token) | 50 | .find_map(syntax::NodeOrToken::into_token) |
51 | .filter(|t| t.text() == "derive")? | 51 | .filter(|t| t.text() == "derive") |
52 | .text() | 52 | .is_some(); |
53 | .clone(); | 53 | if !has_derive { |
54 | return None; | ||
55 | } | ||
54 | 56 | ||
55 | let trait_token = | 57 | let trait_token = ctx.token_at_offset().find(|t| t.kind() == IDENT && t.text() != "derive")?; |
56 | ctx.token_at_offset().find(|t| t.kind() == IDENT && *t.text() != attr_name)?; | ||
57 | let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_token.text()))); | 58 | let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_token.text()))); |
58 | 59 | ||
59 | let annotated_name = attr.syntax().siblings(Direction::Next).find_map(ast::Name::cast)?; | 60 | let annotated_name = attr.syntax().siblings(Direction::Next).find_map(ast::Name::cast)?; |
@@ -176,9 +177,9 @@ fn update_attribute( | |||
176 | .syntax() | 177 | .syntax() |
177 | .descendants_with_tokens() | 178 | .descendants_with_tokens() |
178 | .filter(|t| t.kind() == IDENT) | 179 | .filter(|t| t.kind() == IDENT) |
179 | .filter_map(|t| t.into_token().map(|t| t.text().clone())) | 180 | .filter_map(|t| t.into_token().map(|t| t.text().to_string())) |
180 | .filter(|t| t != trait_name.text()) | 181 | .filter(|t| t != trait_name.text()) |
181 | .collect::<Vec<SmolStr>>(); | 182 | .collect::<Vec<_>>(); |
182 | let has_more_derives = !new_attr_input.is_empty(); | 183 | let has_more_derives = !new_attr_input.is_empty(); |
183 | 184 | ||
184 | if has_more_derives { | 185 | if has_more_derives { |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index fc9f83bab..44c35bafa 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -223,7 +223,7 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> { | |||
223 | let method = mce.name_ref()?; | 223 | let method = mce.name_ref()?; |
224 | let arg_list = mce.arg_list()?; | 224 | let arg_list = mce.arg_list()?; |
225 | 225 | ||
226 | let method = match method.text().as_str() { | 226 | let method = match method.text() { |
227 | "is_some" => "is_none", | 227 | "is_some" => "is_none", |
228 | "is_none" => "is_some", | 228 | "is_none" => "is_some", |
229 | "is_ok" => "is_err", | 229 | "is_ok" => "is_err", |
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 99fb65bac..9e6a3e155 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | use hir_def::{ | 2 | use hir_def::{ |
3 | attr::{Attrs, Documentation}, | 3 | attr::{Attrs, Documentation}, |
4 | path::ModPath, | 4 | path::ModPath, |
5 | per_ns::PerNs, | ||
5 | resolver::HasResolver, | 6 | resolver::HasResolver, |
6 | AttrDefId, GenericParamId, ModuleDefId, | 7 | AttrDefId, GenericParamId, ModuleDefId, |
7 | }; | 8 | }; |
@@ -112,6 +113,11 @@ fn resolve_doc_path( | |||
112 | let path = ast::Path::parse(link).ok()?; | 113 | let path = ast::Path::parse(link).ok()?; |
113 | let modpath = ModPath::from_src(path, &Hygiene::new_unhygienic()).unwrap(); | 114 | let modpath = ModPath::from_src(path, &Hygiene::new_unhygienic()).unwrap(); |
114 | let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); | 115 | let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); |
116 | if resolved == PerNs::none() { | ||
117 | if let Some(trait_id) = resolver.resolve_module_path_in_trait_items(db.upcast(), &modpath) { | ||
118 | return Some(ModuleDefId::TraitId(trait_id)); | ||
119 | }; | ||
120 | } | ||
115 | let def = match ns { | 121 | let def = match ns { |
116 | Some(Namespace::Types) => resolved.take_types()?, | 122 | Some(Namespace::Types) => resolved.take_types()?, |
117 | Some(Namespace::Values) => resolved.take_values()?, | 123 | Some(Namespace::Values) => resolved.take_values()?, |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index a4141e111..aaa7013b6 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -90,7 +90,7 @@ impl Crate { | |||
90 | } | 90 | } |
91 | 91 | ||
92 | pub fn root_module(self, db: &dyn HirDatabase) -> Module { | 92 | pub fn root_module(self, db: &dyn HirDatabase) -> Module { |
93 | let module_id = db.crate_def_map(self.id).root; | 93 | let module_id = db.crate_def_map(self.id).root(); |
94 | Module::new(self, module_id) | 94 | Module::new(self, module_id) |
95 | } | 95 | } |
96 | 96 | ||
@@ -302,7 +302,7 @@ impl Module { | |||
302 | /// in the module tree of any target in `Cargo.toml`. | 302 | /// in the module tree of any target in `Cargo.toml`. |
303 | pub fn crate_root(self, db: &dyn HirDatabase) -> Module { | 303 | pub fn crate_root(self, db: &dyn HirDatabase) -> Module { |
304 | let def_map = db.crate_def_map(self.id.krate); | 304 | let def_map = db.crate_def_map(self.id.krate); |
305 | self.with_module_id(def_map.root) | 305 | self.with_module_id(def_map.root()) |
306 | } | 306 | } |
307 | 307 | ||
308 | /// Iterates over all child modules. | 308 | /// Iterates over all child modules. |
@@ -1000,7 +1000,7 @@ impl MacroDef { | |||
1000 | /// early, in `hir_expand`, where modules simply do not exist yet. | 1000 | /// early, in `hir_expand`, where modules simply do not exist yet. |
1001 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { | 1001 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { |
1002 | let krate = self.id.krate; | 1002 | let krate = self.id.krate; |
1003 | let module_id = db.crate_def_map(krate).root; | 1003 | let module_id = db.crate_def_map(krate).root(); |
1004 | Some(Module::new(Crate { id: krate }, module_id)) | 1004 | Some(Module::new(Crate { id: krate }, module_id)) |
1005 | } | 1005 | } |
1006 | 1006 | ||
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index d5d4cf5b6..d444f4bbb 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub use hir_def::db::{ | 3 | pub use hir_def::db::{ |
4 | AttrsQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQueryQuery, | 4 | AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, |
5 | CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, ExprScopesQuery, | 5 | CrateDefMapQueryQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, |
6 | FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, InternConstQuery, | 6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, |
7 | InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, InternImplQuery, | 7 | InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, |
8 | InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery, | 8 | InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, |
9 | ItemTreeQuery, LangItemQuery, StaticDataQuery, StructDataQuery, TraitDataQuery, | 9 | InternUnionQuery, ItemTreeQuery, LangItemQuery, StaticDataQuery, StructDataQuery, |
10 | TypeAliasDataQuery, UnionDataQuery, | 10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, |
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 1b09ff816..c72649c41 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -207,6 +207,7 @@ impl Attrs { | |||
207 | mod_data.definition_source(db).as_ref().map(|src| match src { | 207 | mod_data.definition_source(db).as_ref().map(|src| match src { |
208 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, | 208 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, |
209 | ModuleSource::Module(module) => module as &dyn AttrsOwner, | 209 | ModuleSource::Module(module) => module as &dyn AttrsOwner, |
210 | ModuleSource::BlockExpr(block) => block as &dyn AttrsOwner, | ||
210 | }), | 211 | }), |
211 | ), | 212 | ), |
212 | } | 213 | } |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 3b2dd0f6e..2c2c999dd 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -122,7 +122,7 @@ impl Expander { | |||
122 | 122 | ||
123 | let mut err = None; | 123 | let mut err = None; |
124 | let call_id = | 124 | let call_id = |
125 | macro_call.as_call_id_with_errors(db, self.crate_def_map.krate, resolver, &mut |e| { | 125 | macro_call.as_call_id_with_errors(db, self.crate_def_map.krate(), resolver, &mut |e| { |
126 | err.get_or_insert(e); | 126 | err.get_or_insert(e); |
127 | }); | 127 | }); |
128 | let call_id = match call_id { | 128 | let call_id = match call_id { |
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index de77d5fc9..2e5d0a01e 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -6,18 +6,24 @@ use crate::{test_db::TestDB, ModuleDefId}; | |||
6 | use super::*; | 6 | use super::*; |
7 | 7 | ||
8 | fn lower(ra_fixture: &str) -> Arc<Body> { | 8 | fn lower(ra_fixture: &str) -> Arc<Body> { |
9 | let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture); | 9 | let db = crate::test_db::TestDB::with_files(ra_fixture); |
10 | 10 | ||
11 | let krate = db.crate_graph().iter().next().unwrap(); | 11 | let krate = db.crate_graph().iter().next().unwrap(); |
12 | let def_map = db.crate_def_map(krate); | 12 | let def_map = db.crate_def_map(krate); |
13 | let module = def_map.modules_for_file(file_id).next().unwrap(); | 13 | let mut fn_def = None; |
14 | let module = &def_map[module]; | 14 | 'outer: for (_, module) in def_map.modules() { |
15 | let fn_def = match module.scope.declarations().next().unwrap() { | 15 | for decl in module.scope.declarations() { |
16 | ModuleDefId::FunctionId(it) => it, | 16 | match decl { |
17 | _ => panic!(), | 17 | ModuleDefId::FunctionId(it) => { |
18 | }; | 18 | fn_def = Some(it); |
19 | break 'outer; | ||
20 | } | ||
21 | _ => {} | ||
22 | } | ||
23 | } | ||
24 | } | ||
19 | 25 | ||
20 | db.body(fn_def.into()) | 26 | db.body(fn_def.unwrap().into()) |
21 | } | 27 | } |
22 | 28 | ||
23 | fn check_diagnostics(ra_fixture: &str) { | 29 | fn check_diagnostics(ra_fixture: &str) { |
@@ -42,6 +48,25 @@ fn main() { n_nuple!(1,2,3); } | |||
42 | } | 48 | } |
43 | 49 | ||
44 | #[test] | 50 | #[test] |
51 | fn macro_resolve() { | ||
52 | // Regression test for a path resolution bug introduced with inner item handling. | ||
53 | lower( | ||
54 | r" | ||
55 | macro_rules! vec { | ||
56 | () => { () }; | ||
57 | ($elem:expr; $n:expr) => { () }; | ||
58 | ($($x:expr),+ $(,)?) => { () }; | ||
59 | } | ||
60 | mod m { | ||
61 | fn outer() { | ||
62 | let _ = vec![FileSet::default(); self.len()]; | ||
63 | } | ||
64 | } | ||
65 | ", | ||
66 | ); | ||
67 | } | ||
68 | |||
69 | #[test] | ||
45 | fn cfg_diagnostics() { | 70 | fn cfg_diagnostics() { |
46 | check_diagnostics( | 71 | check_diagnostics( |
47 | r" | 72 | r" |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 91c8d45cd..a87c80b8a 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -2,9 +2,9 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | 4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; |
5 | use hir_expand::{db::AstDatabase, HirFileId}; | 5 | use hir_expand::{db::AstDatabase, AstId, HirFileId}; |
6 | use la_arena::ArenaMap; | 6 | use la_arena::ArenaMap; |
7 | use syntax::SmolStr; | 7 | use syntax::{ast, SmolStr}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
@@ -55,6 +55,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
55 | #[salsa::invoke(DefMap::crate_def_map_query)] | 55 | #[salsa::invoke(DefMap::crate_def_map_query)] |
56 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; | 56 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; |
57 | 57 | ||
58 | #[salsa::invoke(DefMap::block_def_map_query)] | ||
59 | fn block_def_map(&self, krate: CrateId, block: AstId<ast::BlockExpr>) -> Arc<DefMap>; | ||
60 | |||
58 | #[salsa::invoke(StructData::struct_data_query)] | 61 | #[salsa::invoke(StructData::struct_data_query)] |
59 | fn struct_data(&self, id: StructId) -> Arc<StructData>; | 62 | fn struct_data(&self, id: StructId) -> Arc<StructData>; |
60 | #[salsa::invoke(StructData::union_data_query)] | 63 | #[salsa::invoke(StructData::union_data_query)] |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 422a6eeb4..db2d125ae 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -51,7 +51,7 @@ fn check_self_super(def_map: &DefMap, item: ItemInNs, from: ModuleId) -> Option< | |||
51 | if item == ItemInNs::Types(from.into()) { | 51 | if item == ItemInNs::Types(from.into()) { |
52 | // - if the item is the module we're in, use `self` | 52 | // - if the item is the module we're in, use `self` |
53 | Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) | 53 | Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) |
54 | } else if let Some(parent_id) = def_map.modules[from.local_id].parent { | 54 | } else if let Some(parent_id) = def_map[from.local_id].parent { |
55 | // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) | 55 | // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) |
56 | if item | 56 | if item |
57 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 57 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { |
@@ -111,7 +111,7 @@ fn find_path_inner( | |||
111 | 111 | ||
112 | // - if the item is already in scope, return the name under which it is | 112 | // - if the item is already in scope, return the name under which it is |
113 | let def_map = db.crate_def_map(from.krate); | 113 | let def_map = db.crate_def_map(from.krate); |
114 | let from_scope: &crate::item_scope::ItemScope = &def_map.modules[from.local_id].scope; | 114 | let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope; |
115 | let scope_name = | 115 | let scope_name = |
116 | if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; | 116 | if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; |
117 | if prefixed.is_none() && scope_name.is_some() { | 117 | if prefixed.is_none() && scope_name.is_some() { |
@@ -123,7 +123,7 @@ fn find_path_inner( | |||
123 | if item | 123 | if item |
124 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 124 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { |
125 | krate: from.krate, | 125 | krate: from.krate, |
126 | local_id: def_map.root, | 126 | local_id: def_map.root(), |
127 | })) | 127 | })) |
128 | { | 128 | { |
129 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 129 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
@@ -136,7 +136,7 @@ fn find_path_inner( | |||
136 | } | 136 | } |
137 | 137 | ||
138 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude | 138 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude |
139 | for (name, def_id) in &def_map.extern_prelude { | 139 | for (name, def_id) in def_map.extern_prelude() { |
140 | if item == ItemInNs::Types(*def_id) { | 140 | if item == ItemInNs::Types(*def_id) { |
141 | let name = scope_name.unwrap_or_else(|| name.clone()); | 141 | let name = scope_name.unwrap_or_else(|| name.clone()); |
142 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); | 142 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); |
@@ -144,10 +144,10 @@ fn find_path_inner( | |||
144 | } | 144 | } |
145 | 145 | ||
146 | // - if the item is in the prelude, return the name from there | 146 | // - if the item is in the prelude, return the name from there |
147 | if let Some(prelude_module) = def_map.prelude { | 147 | if let Some(prelude_module) = def_map.prelude() { |
148 | let prelude_def_map = db.crate_def_map(prelude_module.krate); | 148 | let prelude_def_map = db.crate_def_map(prelude_module.krate); |
149 | let prelude_scope: &crate::item_scope::ItemScope = | 149 | let prelude_scope: &crate::item_scope::ItemScope = |
150 | &prelude_def_map.modules[prelude_module.local_id].scope; | 150 | &prelude_def_map[prelude_module.local_id].scope; |
151 | if let Some((name, vis)) = prelude_scope.name_of(item) { | 151 | if let Some((name, vis)) = prelude_scope.name_of(item) { |
152 | if vis.is_visible_from(db, from) { | 152 | if vis.is_visible_from(db, from) { |
153 | return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()])); | 153 | return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()])); |
@@ -175,7 +175,7 @@ fn find_path_inner( | |||
175 | 175 | ||
176 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 176 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
177 | 177 | ||
178 | let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; | 178 | let crate_root = ModuleId { local_id: def_map.root(), krate: from.krate }; |
179 | let crate_attrs = db.attrs(crate_root.into()); | 179 | let crate_attrs = db.attrs(crate_root.into()); |
180 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 180 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
181 | let mut best_path = None; | 181 | let mut best_path = None; |
@@ -287,7 +287,7 @@ fn find_local_import_locations( | |||
287 | 287 | ||
288 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all | 288 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all |
289 | // of its (recursive) parent modules. | 289 | // of its (recursive) parent modules. |
290 | let data = &def_map.modules[from.local_id]; | 290 | let data = &def_map[from.local_id]; |
291 | let mut worklist = data | 291 | let mut worklist = data |
292 | .children | 292 | .children |
293 | .values() | 293 | .values() |
@@ -296,7 +296,7 @@ fn find_local_import_locations( | |||
296 | let mut parent = data.parent; | 296 | let mut parent = data.parent; |
297 | while let Some(p) = parent { | 297 | while let Some(p) = parent { |
298 | worklist.push(ModuleId { krate: from.krate, local_id: p }); | 298 | worklist.push(ModuleId { krate: from.krate, local_id: p }); |
299 | parent = def_map.modules[p].parent; | 299 | parent = def_map[p].parent; |
300 | } | 300 | } |
301 | 301 | ||
302 | let mut seen: FxHashSet<_> = FxHashSet::default(); | 302 | let mut seen: FxHashSet<_> = FxHashSet::default(); |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index fac0de90c..0251d016b 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -75,7 +75,7 @@ impl ImportMap { | |||
75 | 75 | ||
76 | // We look only into modules that are public(ly reexported), starting with the crate root. | 76 | // We look only into modules that are public(ly reexported), starting with the crate root. |
77 | let empty = ImportPath { segments: vec![] }; | 77 | let empty = ImportPath { segments: vec![] }; |
78 | let root = ModuleId { krate, local_id: def_map.root }; | 78 | let root = ModuleId { krate, local_id: def_map.root() }; |
79 | let mut worklist = vec![(root, empty)]; | 79 | let mut worklist = vec![(root, empty)]; |
80 | while let Some((module, mod_path)) = worklist.pop() { | 80 | while let Some((module, mod_path)) = worklist.pop() { |
81 | let ext_def_map; | 81 | let ext_def_map; |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index ff62928df..b8d7608e7 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -21,6 +21,7 @@ use hir_expand::{ | |||
21 | HirFileId, InFile, | 21 | HirFileId, InFile, |
22 | }; | 22 | }; |
23 | use la_arena::{Arena, Idx, RawIdx}; | 23 | use la_arena::{Arena, Idx, RawIdx}; |
24 | use profile::Count; | ||
24 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
25 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
26 | use syntax::{ast, match_ast}; | 27 | use syntax::{ast, match_ast}; |
@@ -67,15 +68,16 @@ impl GenericParamsId { | |||
67 | /// The item tree of a source file. | 68 | /// The item tree of a source file. |
68 | #[derive(Debug, Eq, PartialEq)] | 69 | #[derive(Debug, Eq, PartialEq)] |
69 | pub struct ItemTree { | 70 | pub struct ItemTree { |
71 | _c: Count<Self>, | ||
72 | |||
70 | top_level: SmallVec<[ModItem; 1]>, | 73 | top_level: SmallVec<[ModItem; 1]>, |
71 | attrs: FxHashMap<AttrOwner, RawAttrs>, | 74 | attrs: FxHashMap<AttrOwner, RawAttrs>, |
72 | inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, | ||
73 | 75 | ||
74 | data: Option<Box<ItemTreeData>>, | 76 | data: Option<Box<ItemTreeData>>, |
75 | } | 77 | } |
76 | 78 | ||
77 | impl ItemTree { | 79 | impl ItemTree { |
78 | pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { | 80 | pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { |
79 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); | 81 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); |
80 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { | 82 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { |
81 | node | 83 | node |
@@ -118,9 +120,9 @@ impl ItemTree { | |||
118 | 120 | ||
119 | fn empty() -> Self { | 121 | fn empty() -> Self { |
120 | Self { | 122 | Self { |
123 | _c: Count::new(), | ||
121 | top_level: Default::default(), | 124 | top_level: Default::default(), |
122 | attrs: Default::default(), | 125 | attrs: Default::default(), |
123 | inner_items: Default::default(), | ||
124 | data: Default::default(), | 126 | data: Default::default(), |
125 | } | 127 | } |
126 | } | 128 | } |
@@ -147,6 +149,7 @@ impl ItemTree { | |||
147 | macro_defs, | 149 | macro_defs, |
148 | vis, | 150 | vis, |
149 | generics, | 151 | generics, |
152 | inner_items, | ||
150 | } = &mut **data; | 153 | } = &mut **data; |
151 | 154 | ||
152 | imports.shrink_to_fit(); | 155 | imports.shrink_to_fit(); |
@@ -169,6 +172,8 @@ impl ItemTree { | |||
169 | 172 | ||
170 | vis.arena.shrink_to_fit(); | 173 | vis.arena.shrink_to_fit(); |
171 | generics.arena.shrink_to_fit(); | 174 | generics.arena.shrink_to_fit(); |
175 | |||
176 | inner_items.shrink_to_fit(); | ||
172 | } | 177 | } |
173 | } | 178 | } |
174 | 179 | ||
@@ -191,16 +196,18 @@ impl ItemTree { | |||
191 | self.raw_attrs(of).clone().filter(db, krate) | 196 | self.raw_attrs(of).clone().filter(db, krate) |
192 | } | 197 | } |
193 | 198 | ||
194 | /// Returns the lowered inner items that `ast` corresponds to. | 199 | pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { |
195 | /// | 200 | match &self.data { |
196 | /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered | 201 | Some(data) => Some(data.inner_items.values().flatten().copied()).into_iter().flatten(), |
197 | /// to multiple items in the `ItemTree`. | 202 | None => None.into_iter().flatten(), |
198 | pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] { | 203 | } |
199 | &self.inner_items[&ast] | ||
200 | } | 204 | } |
201 | 205 | ||
202 | pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { | 206 | pub fn inner_items_of_block(&self, block: FileAstId<ast::BlockExpr>) -> &[ModItem] { |
203 | self.inner_items.values().flatten().copied() | 207 | match &self.data { |
208 | Some(data) => data.inner_items.get(&block).map(|it| &**it).unwrap_or(&[]), | ||
209 | None => &[], | ||
210 | } | ||
204 | } | 211 | } |
205 | 212 | ||
206 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { | 213 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { |
@@ -297,6 +304,8 @@ struct ItemTreeData { | |||
297 | 304 | ||
298 | vis: ItemVisibilities, | 305 | vis: ItemVisibilities, |
299 | generics: GenericParamsStorage, | 306 | generics: GenericParamsStorage, |
307 | |||
308 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | ||
300 | } | 309 | } |
301 | 310 | ||
302 | #[derive(Debug, Eq, PartialEq, Hash)] | 311 | #[derive(Debug, Eq, PartialEq, Hash)] |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5e71ca42c..ce470fc3b 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId} | |||
6 | use smallvec::SmallVec; | 6 | use smallvec::SmallVec; |
7 | use syntax::{ | 7 | use syntax::{ |
8 | ast::{self, ModuleItemOwner}, | 8 | ast::{self, ModuleItemOwner}, |
9 | SyntaxNode, | 9 | SyntaxNode, WalkEvent, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
@@ -37,7 +37,6 @@ pub(super) struct Ctx { | |||
37 | file: HirFileId, | 37 | file: HirFileId, |
38 | source_ast_id_map: Arc<AstIdMap>, | 38 | source_ast_id_map: Arc<AstIdMap>, |
39 | body_ctx: crate::body::LowerCtx, | 39 | body_ctx: crate::body::LowerCtx, |
40 | inner_items: Vec<ModItem>, | ||
41 | forced_visibility: Option<RawVisibilityId>, | 40 | forced_visibility: Option<RawVisibilityId>, |
42 | } | 41 | } |
43 | 42 | ||
@@ -49,7 +48,6 @@ impl Ctx { | |||
49 | file, | 48 | file, |
50 | source_ast_id_map: db.ast_id_map(file), | 49 | source_ast_id_map: db.ast_id_map(file), |
51 | body_ctx: crate::body::LowerCtx::new(db, file), | 50 | body_ctx: crate::body::LowerCtx::new(db, file), |
52 | inner_items: Vec::new(), | ||
53 | forced_visibility: None, | 51 | forced_visibility: None, |
54 | } | 52 | } |
55 | } | 53 | } |
@@ -73,8 +71,6 @@ impl Ctx { | |||
73 | } | 71 | } |
74 | 72 | ||
75 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { | 73 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { |
76 | assert!(inner || self.inner_items.is_empty()); | ||
77 | |||
78 | // Collect inner items for 1-to-1-lowered items. | 74 | // Collect inner items for 1-to-1-lowered items. |
79 | match item { | 75 | match item { |
80 | ast::Item::Struct(_) | 76 | ast::Item::Struct(_) |
@@ -150,14 +146,37 @@ impl Ctx { | |||
150 | 146 | ||
151 | fn collect_inner_items(&mut self, container: &SyntaxNode) { | 147 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
152 | let forced_vis = self.forced_visibility.take(); | 148 | let forced_vis = self.forced_visibility.take(); |
153 | let mut inner_items = mem::take(&mut self.tree.inner_items); | 149 | |
154 | inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( | 150 | let mut block_stack = Vec::new(); |
155 | |item| { | 151 | for event in container.preorder().skip(1) { |
156 | let ast_id = self.source_ast_id_map.ast_id(&item); | 152 | match event { |
157 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) | 153 | WalkEvent::Enter(node) => { |
158 | }, | 154 | match_ast! { |
159 | )); | 155 | match node { |
160 | self.tree.inner_items = inner_items; | 156 | ast::BlockExpr(block) => { |
157 | block_stack.push(self.source_ast_id_map.ast_id(&block)); | ||
158 | }, | ||
159 | ast::Item(item) => { | ||
160 | let mod_items = self.lower_mod_item(&item, true); | ||
161 | let current_block = block_stack.last(); | ||
162 | if let (Some(mod_items), Some(block)) = (mod_items, current_block) { | ||
163 | if !mod_items.0.is_empty() { | ||
164 | self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied()); | ||
165 | } | ||
166 | } | ||
167 | }, | ||
168 | _ => {} | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | WalkEvent::Leave(node) => { | ||
173 | if ast::BlockExpr::cast(node).is_some() { | ||
174 | block_stack.pop(); | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
161 | self.forced_visibility = forced_vis; | 180 | self.forced_visibility = forced_vis; |
162 | } | 181 | } |
163 | 182 | ||
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs index 30188b740..9e90f745c 100644 --- a/crates/hir_def/src/lang_item.rs +++ b/crates/hir_def/src/lang_item.rs | |||
@@ -84,7 +84,7 @@ impl LangItems { | |||
84 | 84 | ||
85 | let crate_def_map = db.crate_def_map(krate); | 85 | let crate_def_map = db.crate_def_map(krate); |
86 | 86 | ||
87 | for (_, module_data) in crate_def_map.modules.iter() { | 87 | for (_, module_data) in crate_def_map.modules() { |
88 | for impl_def in module_data.scope.impls() { | 88 | for impl_def in module_data.scope.impls() { |
89 | lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) | 89 | lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) |
90 | } | 90 | } |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 769a557ad..bd3ea9b8b 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -59,9 +59,10 @@ use std::sync::Arc; | |||
59 | use base_db::{CrateId, Edition, FileId}; | 59 | use base_db::{CrateId, Edition, FileId}; |
60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; | 60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; |
61 | use la_arena::Arena; | 61 | use la_arena::Arena; |
62 | use profile::Count; | ||
62 | use rustc_hash::FxHashMap; | 63 | use rustc_hash::FxHashMap; |
63 | use stdx::format_to; | 64 | use stdx::format_to; |
64 | use syntax::ast; | 65 | use syntax::{ast, AstNode}; |
65 | 66 | ||
66 | use crate::{ | 67 | use crate::{ |
67 | db::DefDatabase, | 68 | db::DefDatabase, |
@@ -75,14 +76,16 @@ use crate::{ | |||
75 | /// Contains all top-level defs from a macro-expanded crate | 76 | /// Contains all top-level defs from a macro-expanded crate |
76 | #[derive(Debug, PartialEq, Eq)] | 77 | #[derive(Debug, PartialEq, Eq)] |
77 | pub struct DefMap { | 78 | pub struct DefMap { |
78 | pub root: LocalModuleId, | 79 | _c: Count<Self>, |
79 | pub modules: Arena<ModuleData>, | 80 | parent: Option<Arc<DefMap>>, |
80 | pub(crate) krate: CrateId, | 81 | root: LocalModuleId, |
82 | modules: Arena<ModuleData>, | ||
83 | krate: CrateId, | ||
81 | /// The prelude module for this crate. This either comes from an import | 84 | /// The prelude module for this crate. This either comes from an import |
82 | /// marked with the `prelude_import` attribute, or (in the normal case) from | 85 | /// marked with the `prelude_import` attribute, or (in the normal case) from |
83 | /// a dependency (`std` or `core`). | 86 | /// a dependency (`std` or `core`). |
84 | pub(crate) prelude: Option<ModuleId>, | 87 | prelude: Option<ModuleId>, |
85 | pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>, | 88 | extern_prelude: FxHashMap<Name, ModuleDefId>, |
86 | 89 | ||
87 | edition: Edition, | 90 | edition: Edition, |
88 | diagnostics: Vec<DefDiagnostic>, | 91 | diagnostics: Vec<DefDiagnostic>, |
@@ -109,6 +112,10 @@ pub enum ModuleOrigin { | |||
109 | Inline { | 112 | Inline { |
110 | definition: AstId<ast::Module>, | 113 | definition: AstId<ast::Module>, |
111 | }, | 114 | }, |
115 | /// Pseudo-module introduced by a block scope (contains only inner items). | ||
116 | BlockExpr { | ||
117 | block: AstId<ast::BlockExpr>, | ||
118 | }, | ||
112 | } | 119 | } |
113 | 120 | ||
114 | impl Default for ModuleOrigin { | 121 | impl Default for ModuleOrigin { |
@@ -122,7 +129,7 @@ impl ModuleOrigin { | |||
122 | match self { | 129 | match self { |
123 | ModuleOrigin::File { declaration: module, .. } | 130 | ModuleOrigin::File { declaration: module, .. } |
124 | | ModuleOrigin::Inline { definition: module, .. } => Some(*module), | 131 | | ModuleOrigin::Inline { definition: module, .. } => Some(*module), |
125 | ModuleOrigin::CrateRoot { .. } => None, | 132 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, |
126 | } | 133 | } |
127 | } | 134 | } |
128 | 135 | ||
@@ -137,7 +144,7 @@ impl ModuleOrigin { | |||
137 | 144 | ||
138 | pub fn is_inline(&self) -> bool { | 145 | pub fn is_inline(&self) -> bool { |
139 | match self { | 146 | match self { |
140 | ModuleOrigin::Inline { .. } => true, | 147 | ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true, |
141 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, | 148 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, |
142 | } | 149 | } |
143 | } | 150 | } |
@@ -155,6 +162,9 @@ impl ModuleOrigin { | |||
155 | definition.file_id, | 162 | definition.file_id, |
156 | ModuleSource::Module(definition.to_node(db.upcast())), | 163 | ModuleSource::Module(definition.to_node(db.upcast())), |
157 | ), | 164 | ), |
165 | ModuleOrigin::BlockExpr { block } => { | ||
166 | InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast()))) | ||
167 | } | ||
158 | } | 168 | } |
159 | } | 169 | } |
160 | } | 170 | } |
@@ -174,24 +184,51 @@ impl DefMap { | |||
174 | let _p = profile::span("crate_def_map_query").detail(|| { | 184 | let _p = profile::span("crate_def_map_query").detail(|| { |
175 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() | 185 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() |
176 | }); | 186 | }); |
177 | let def_map = { | 187 | let edition = db.crate_graph()[krate].edition; |
178 | let edition = db.crate_graph()[krate].edition; | 188 | let def_map = DefMap::empty(krate, edition); |
179 | let mut modules: Arena<ModuleData> = Arena::default(); | 189 | let def_map = collector::collect_defs(db, def_map, None); |
180 | let root = modules.alloc(ModuleData::default()); | ||
181 | DefMap { | ||
182 | krate, | ||
183 | edition, | ||
184 | extern_prelude: FxHashMap::default(), | ||
185 | prelude: None, | ||
186 | root, | ||
187 | modules, | ||
188 | diagnostics: Vec::new(), | ||
189 | } | ||
190 | }; | ||
191 | let def_map = collector::collect_defs(db, def_map); | ||
192 | Arc::new(def_map) | 190 | Arc::new(def_map) |
193 | } | 191 | } |
194 | 192 | ||
193 | pub(crate) fn block_def_map_query( | ||
194 | db: &dyn DefDatabase, | ||
195 | krate: CrateId, | ||
196 | block: AstId<ast::BlockExpr>, | ||
197 | ) -> Arc<DefMap> { | ||
198 | let item_tree = db.item_tree(block.file_id); | ||
199 | let block_items = item_tree.inner_items_of_block(block.value); | ||
200 | |||
201 | let parent = parent_def_map(db, krate, block); | ||
202 | |||
203 | if block_items.is_empty() { | ||
204 | // If there are no inner items, nothing new is brought into scope, so we can just return | ||
205 | // the parent DefMap. This keeps DefMap parent chains short. | ||
206 | return parent; | ||
207 | } | ||
208 | |||
209 | let mut def_map = DefMap::empty(krate, parent.edition); | ||
210 | def_map.parent = Some(parent); | ||
211 | |||
212 | let def_map = collector::collect_defs(db, def_map, Some(block.value)); | ||
213 | Arc::new(def_map) | ||
214 | } | ||
215 | |||
216 | fn empty(krate: CrateId, edition: Edition) -> DefMap { | ||
217 | let mut modules: Arena<ModuleData> = Arena::default(); | ||
218 | let root = modules.alloc(ModuleData::default()); | ||
219 | DefMap { | ||
220 | _c: Count::new(), | ||
221 | parent: None, | ||
222 | krate, | ||
223 | edition, | ||
224 | extern_prelude: FxHashMap::default(), | ||
225 | prelude: None, | ||
226 | root, | ||
227 | modules, | ||
228 | diagnostics: Vec::new(), | ||
229 | } | ||
230 | } | ||
231 | |||
195 | pub fn add_diagnostics( | 232 | pub fn add_diagnostics( |
196 | &self, | 233 | &self, |
197 | db: &dyn DefDatabase, | 234 | db: &dyn DefDatabase, |
@@ -208,6 +245,26 @@ impl DefMap { | |||
208 | .map(|(id, _data)| id) | 245 | .map(|(id, _data)| id) |
209 | } | 246 | } |
210 | 247 | ||
248 | pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ { | ||
249 | self.modules.iter() | ||
250 | } | ||
251 | |||
252 | pub fn root(&self) -> LocalModuleId { | ||
253 | self.root | ||
254 | } | ||
255 | |||
256 | pub(crate) fn krate(&self) -> CrateId { | ||
257 | self.krate | ||
258 | } | ||
259 | |||
260 | pub(crate) fn prelude(&self) -> Option<ModuleId> { | ||
261 | self.prelude | ||
262 | } | ||
263 | |||
264 | pub(crate) fn extern_prelude(&self) -> impl Iterator<Item = (&Name, &ModuleDefId)> + '_ { | ||
265 | self.extern_prelude.iter() | ||
266 | } | ||
267 | |||
211 | pub(crate) fn resolve_path( | 268 | pub(crate) fn resolve_path( |
212 | &self, | 269 | &self, |
213 | db: &dyn DefDatabase, | 270 | db: &dyn DefDatabase, |
@@ -224,7 +281,12 @@ impl DefMap { | |||
224 | // even), as this should be a great debugging aid. | 281 | // even), as this should be a great debugging aid. |
225 | pub fn dump(&self) -> String { | 282 | pub fn dump(&self) -> String { |
226 | let mut buf = String::new(); | 283 | let mut buf = String::new(); |
227 | go(&mut buf, self, "crate", self.root); | 284 | let mut current_map = self; |
285 | while let Some(parent) = ¤t_map.parent { | ||
286 | go(&mut buf, current_map, "block scope", current_map.root); | ||
287 | current_map = &**parent; | ||
288 | } | ||
289 | go(&mut buf, current_map, "crate", current_map.root); | ||
228 | return buf; | 290 | return buf; |
229 | 291 | ||
230 | fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { | 292 | fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { |
@@ -276,10 +338,40 @@ impl ModuleData { | |||
276 | } | 338 | } |
277 | } | 339 | } |
278 | 340 | ||
341 | fn parent_def_map( | ||
342 | db: &dyn DefDatabase, | ||
343 | krate: CrateId, | ||
344 | block: AstId<ast::BlockExpr>, | ||
345 | ) -> Arc<DefMap> { | ||
346 | // FIXME: store this info in the item tree instead of reparsing here | ||
347 | let ast_id_map = db.ast_id_map(block.file_id); | ||
348 | let block_ptr = ast_id_map.get(block.value); | ||
349 | let root = match db.parse_or_expand(block.file_id) { | ||
350 | Some(it) => it, | ||
351 | None => { | ||
352 | return Arc::new(DefMap::empty(krate, Edition::Edition2018)); | ||
353 | } | ||
354 | }; | ||
355 | let ast = block_ptr.to_node(&root); | ||
356 | |||
357 | for ancestor in ast.syntax().ancestors().skip(1) { | ||
358 | if let Some(block_expr) = ast::BlockExpr::cast(ancestor) { | ||
359 | let ancestor_id = ast_id_map.ast_id(&block_expr); | ||
360 | let ast_id = InFile::new(block.file_id, ancestor_id); | ||
361 | let parent_map = db.block_def_map(krate, ast_id); | ||
362 | return parent_map; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | // No enclosing block scope, so the parent is the crate-level DefMap. | ||
367 | db.crate_def_map(krate) | ||
368 | } | ||
369 | |||
279 | #[derive(Debug, Clone, PartialEq, Eq)] | 370 | #[derive(Debug, Clone, PartialEq, Eq)] |
280 | pub enum ModuleSource { | 371 | pub enum ModuleSource { |
281 | SourceFile(ast::SourceFile), | 372 | SourceFile(ast::SourceFile), |
282 | Module(ast::Module), | 373 | Module(ast::Module), |
374 | BlockExpr(ast::BlockExpr), | ||
283 | } | 375 | } |
284 | 376 | ||
285 | mod diagnostics { | 377 | mod diagnostics { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 61da56340..cd68efbe6 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -45,7 +45,11 @@ const GLOB_RECURSION_LIMIT: usize = 100; | |||
45 | const EXPANSION_DEPTH_LIMIT: usize = 128; | 45 | const EXPANSION_DEPTH_LIMIT: usize = 128; |
46 | const FIXED_POINT_LIMIT: usize = 8192; | 46 | const FIXED_POINT_LIMIT: usize = 8192; |
47 | 47 | ||
48 | pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap) -> DefMap { | 48 | pub(super) fn collect_defs( |
49 | db: &dyn DefDatabase, | ||
50 | mut def_map: DefMap, | ||
51 | block: Option<FileAstId<ast::BlockExpr>>, | ||
52 | ) -> DefMap { | ||
49 | let crate_graph = db.crate_graph(); | 53 | let crate_graph = db.crate_graph(); |
50 | 54 | ||
51 | // populate external prelude | 55 | // populate external prelude |
@@ -93,6 +97,14 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap) -> DefMap | |||
93 | exports_proc_macros: false, | 97 | exports_proc_macros: false, |
94 | from_glob_import: Default::default(), | 98 | from_glob_import: Default::default(), |
95 | }; | 99 | }; |
100 | match block { | ||
101 | Some(block) => { | ||
102 | collector.seed_with_inner(block); | ||
103 | } | ||
104 | None => { | ||
105 | collector.seed_with_top_level(); | ||
106 | } | ||
107 | } | ||
96 | collector.collect(); | 108 | collector.collect(); |
97 | collector.finish() | 109 | collector.finish() |
98 | } | 110 | } |
@@ -228,7 +240,7 @@ struct DefCollector<'a> { | |||
228 | } | 240 | } |
229 | 241 | ||
230 | impl DefCollector<'_> { | 242 | impl DefCollector<'_> { |
231 | fn collect(&mut self) { | 243 | fn seed_with_top_level(&mut self) { |
232 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; | 244 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; |
233 | let item_tree = self.db.item_tree(file_id.into()); | 245 | let item_tree = self.db.item_tree(file_id.into()); |
234 | let module_id = self.def_map.root; | 246 | let module_id = self.def_map.root; |
@@ -248,7 +260,31 @@ impl DefCollector<'_> { | |||
248 | } | 260 | } |
249 | .collect(item_tree.top_level_items()); | 261 | .collect(item_tree.top_level_items()); |
250 | } | 262 | } |
263 | } | ||
264 | |||
265 | fn seed_with_inner(&mut self, block: FileAstId<ast::BlockExpr>) { | ||
266 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; | ||
267 | let item_tree = self.db.item_tree(file_id.into()); | ||
268 | let module_id = self.def_map.root; | ||
269 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; | ||
270 | if item_tree | ||
271 | .top_level_attrs(self.db, self.def_map.krate) | ||
272 | .cfg() | ||
273 | .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) | ||
274 | { | ||
275 | ModCollector { | ||
276 | def_collector: &mut *self, | ||
277 | macro_depth: 0, | ||
278 | module_id, | ||
279 | file_id: file_id.into(), | ||
280 | item_tree: &item_tree, | ||
281 | mod_dir: ModDir::root(), | ||
282 | } | ||
283 | .collect(item_tree.inner_items_of_block(block)); | ||
284 | } | ||
285 | } | ||
251 | 286 | ||
287 | fn collect(&mut self) { | ||
252 | // main name resolution fixed-point loop. | 288 | // main name resolution fixed-point loop. |
253 | let mut i = 0; | 289 | let mut i = 0; |
254 | loop { | 290 | loop { |
@@ -1470,7 +1506,6 @@ impl ModCollector<'_, '_> { | |||
1470 | mod tests { | 1506 | mod tests { |
1471 | use crate::{db::DefDatabase, test_db::TestDB}; | 1507 | use crate::{db::DefDatabase, test_db::TestDB}; |
1472 | use base_db::{fixture::WithFixture, SourceDatabase}; | 1508 | use base_db::{fixture::WithFixture, SourceDatabase}; |
1473 | use la_arena::Arena; | ||
1474 | 1509 | ||
1475 | use super::*; | 1510 | use super::*; |
1476 | 1511 | ||
@@ -1489,6 +1524,7 @@ mod tests { | |||
1489 | exports_proc_macros: false, | 1524 | exports_proc_macros: false, |
1490 | from_glob_import: Default::default(), | 1525 | from_glob_import: Default::default(), |
1491 | }; | 1526 | }; |
1527 | collector.seed_with_top_level(); | ||
1492 | collector.collect(); | 1528 | collector.collect(); |
1493 | collector.def_map | 1529 | collector.def_map |
1494 | } | 1530 | } |
@@ -1497,20 +1533,8 @@ mod tests { | |||
1497 | let (db, _file_id) = TestDB::with_single_file(&code); | 1533 | let (db, _file_id) = TestDB::with_single_file(&code); |
1498 | let krate = db.test_crate(); | 1534 | let krate = db.test_crate(); |
1499 | 1535 | ||
1500 | let def_map = { | 1536 | let edition = db.crate_graph()[krate].edition; |
1501 | let edition = db.crate_graph()[krate].edition; | 1537 | let def_map = DefMap::empty(krate, edition); |
1502 | let mut modules: Arena<ModuleData> = Arena::default(); | ||
1503 | let root = modules.alloc(ModuleData::default()); | ||
1504 | DefMap { | ||
1505 | krate, | ||
1506 | edition, | ||
1507 | extern_prelude: FxHashMap::default(), | ||
1508 | prelude: None, | ||
1509 | root, | ||
1510 | modules, | ||
1511 | diagnostics: Vec::new(), | ||
1512 | } | ||
1513 | }; | ||
1514 | do_collect_defs(&db, def_map) | 1538 | do_collect_defs(&db, def_map) |
1515 | } | 1539 | } |
1516 | 1540 | ||
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index 096a7d0ac..ec90f4e65 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -104,6 +104,43 @@ impl DefMap { | |||
104 | path: &ModPath, | 104 | path: &ModPath, |
105 | shadow: BuiltinShadowMode, | 105 | shadow: BuiltinShadowMode, |
106 | ) -> ResolvePathResult { | 106 | ) -> ResolvePathResult { |
107 | let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); | ||
108 | result.segment_index = Some(usize::max_value()); | ||
109 | |||
110 | let mut current_map = self; | ||
111 | loop { | ||
112 | let new = current_map.resolve_path_fp_with_macro_single( | ||
113 | db, | ||
114 | mode, | ||
115 | original_module, | ||
116 | path, | ||
117 | shadow, | ||
118 | ); | ||
119 | |||
120 | // Merge `new` into `result`. | ||
121 | result.resolved_def = result.resolved_def.or(new.resolved_def); | ||
122 | if result.reached_fixedpoint == ReachedFixedPoint::No { | ||
123 | result.reached_fixedpoint = new.reached_fixedpoint; | ||
124 | } | ||
125 | // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates? | ||
126 | result.krate = result.krate.or(new.krate); | ||
127 | result.segment_index = result.segment_index.min(new.segment_index); | ||
128 | |||
129 | match ¤t_map.parent { | ||
130 | Some(map) => current_map = map, | ||
131 | None => return result, | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | pub(super) fn resolve_path_fp_with_macro_single( | ||
137 | &self, | ||
138 | db: &dyn DefDatabase, | ||
139 | mode: ResolveMode, | ||
140 | original_module: LocalModuleId, | ||
141 | path: &ModPath, | ||
142 | shadow: BuiltinShadowMode, | ||
143 | ) -> ResolvePathResult { | ||
107 | let mut segments = path.segments.iter().enumerate(); | 144 | let mut segments = path.segments.iter().enumerate(); |
108 | let mut curr_per_ns: PerNs = match path.kind { | 145 | let mut curr_per_ns: PerNs = match path.kind { |
109 | PathKind::DollarCrate(krate) => { | 146 | PathKind::DollarCrate(krate) => { |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index 723481c36..73e3a4702 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -4,11 +4,13 @@ mod macros; | |||
4 | mod mod_resolution; | 4 | mod mod_resolution; |
5 | mod diagnostics; | 5 | mod diagnostics; |
6 | mod primitives; | 6 | mod primitives; |
7 | mod block; | ||
7 | 8 | ||
8 | use std::sync::Arc; | 9 | use std::sync::Arc; |
9 | 10 | ||
10 | use base_db::{fixture::WithFixture, SourceDatabase}; | 11 | use base_db::{fixture::WithFixture, SourceDatabase}; |
11 | use expect_test::{expect, Expect}; | 12 | use expect_test::{expect, Expect}; |
13 | use hir_expand::db::AstDatabase; | ||
12 | use test_utils::mark; | 14 | use test_utils::mark; |
13 | 15 | ||
14 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 16 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; |
@@ -19,12 +21,30 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | |||
19 | db.crate_def_map(krate) | 21 | db.crate_def_map(krate) |
20 | } | 22 | } |
21 | 23 | ||
24 | fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { | ||
25 | let (db, position) = TestDB::with_position(ra_fixture); | ||
26 | let module = db.module_for_file(position.file_id); | ||
27 | let ast_map = db.ast_id_map(position.file_id.into()); | ||
28 | let ast = db.parse(position.file_id); | ||
29 | let block: ast::BlockExpr = | ||
30 | syntax::algo::find_node_at_offset(&ast.syntax_node(), position.offset).unwrap(); | ||
31 | let block_id = ast_map.ast_id(&block); | ||
32 | |||
33 | db.block_def_map(module.krate, InFile::new(position.file_id.into(), block_id)) | ||
34 | } | ||
35 | |||
22 | fn check(ra_fixture: &str, expect: Expect) { | 36 | fn check(ra_fixture: &str, expect: Expect) { |
23 | let def_map = compute_crate_def_map(ra_fixture); | 37 | let def_map = compute_crate_def_map(ra_fixture); |
24 | let actual = def_map.dump(); | 38 | let actual = def_map.dump(); |
25 | expect.assert_eq(&actual); | 39 | expect.assert_eq(&actual); |
26 | } | 40 | } |
27 | 41 | ||
42 | fn check_at(ra_fixture: &str, expect: Expect) { | ||
43 | let def_map = compute_block_def_map(ra_fixture); | ||
44 | let actual = def_map.dump(); | ||
45 | expect.assert_eq(&actual); | ||
46 | } | ||
47 | |||
28 | #[test] | 48 | #[test] |
29 | fn crate_def_map_smoke_test() { | 49 | fn crate_def_map_smoke_test() { |
30 | check( | 50 | check( |
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs new file mode 100644 index 000000000..01d6326a7 --- /dev/null +++ b/crates/hir_def/src/nameres/tests/block.rs | |||
@@ -0,0 +1,97 @@ | |||
1 | use super::*; | ||
2 | |||
3 | #[test] | ||
4 | fn inner_item_smoke() { | ||
5 | check_at( | ||
6 | r#" | ||
7 | struct inner {} | ||
8 | fn outer() { | ||
9 | $0 | ||
10 | fn inner() {} | ||
11 | } | ||
12 | "#, | ||
13 | expect![[r#" | ||
14 | block scope | ||
15 | inner: v | ||
16 | crate | ||
17 | inner: t | ||
18 | outer: v | ||
19 | "#]], | ||
20 | ); | ||
21 | } | ||
22 | |||
23 | #[test] | ||
24 | fn use_from_crate() { | ||
25 | check_at( | ||
26 | r#" | ||
27 | struct Struct; | ||
28 | fn outer() { | ||
29 | use Struct; | ||
30 | use crate::Struct as CrateStruct; | ||
31 | use self::Struct as SelfStruct; | ||
32 | $0 | ||
33 | } | ||
34 | "#, | ||
35 | expect![[r#" | ||
36 | block scope | ||
37 | CrateStruct: t v | ||
38 | SelfStruct: t v | ||
39 | Struct: t v | ||
40 | crate | ||
41 | Struct: t v | ||
42 | outer: v | ||
43 | "#]], | ||
44 | ); | ||
45 | } | ||
46 | |||
47 | #[test] | ||
48 | fn merge_namespaces() { | ||
49 | check_at( | ||
50 | r#" | ||
51 | struct name {} | ||
52 | fn outer() { | ||
53 | fn name() {} | ||
54 | |||
55 | use name as imported; // should import both `name`s | ||
56 | |||
57 | $0 | ||
58 | } | ||
59 | "#, | ||
60 | expect![[r#" | ||
61 | block scope | ||
62 | imported: t v | ||
63 | name: v | ||
64 | crate | ||
65 | name: t | ||
66 | outer: v | ||
67 | "#]], | ||
68 | ); | ||
69 | } | ||
70 | |||
71 | #[test] | ||
72 | fn nested_blocks() { | ||
73 | check_at( | ||
74 | r#" | ||
75 | fn outer() { | ||
76 | struct inner1 {} | ||
77 | fn inner() { | ||
78 | use inner1; | ||
79 | use outer; | ||
80 | fn inner2() {} | ||
81 | $0 | ||
82 | } | ||
83 | } | ||
84 | "#, | ||
85 | expect![[r#" | ||
86 | block scope | ||
87 | inner1: t | ||
88 | inner2: v | ||
89 | outer: v | ||
90 | block scope | ||
91 | inner: v | ||
92 | inner1: t | ||
93 | crate | ||
94 | outer: v | ||
95 | "#]], | ||
96 | ); | ||
97 | } | ||
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index a505bf2be..b2f577649 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -146,6 +146,19 @@ impl Resolver { | |||
146 | self.resolve_module_path(db, path, BuiltinShadowMode::Module) | 146 | self.resolve_module_path(db, path, BuiltinShadowMode::Module) |
147 | } | 147 | } |
148 | 148 | ||
149 | pub fn resolve_module_path_in_trait_items( | ||
150 | &self, | ||
151 | db: &dyn DefDatabase, | ||
152 | path: &ModPath, | ||
153 | ) -> Option<TraitId> { | ||
154 | let (item_map, module) = self.module_scope()?; | ||
155 | let (module_res, ..) = item_map.resolve_path(db, module, &path, BuiltinShadowMode::Module); | ||
156 | match module_res.take_types()? { | ||
157 | ModuleDefId::TraitId(it) => Some(it), | ||
158 | _ => None, | ||
159 | } | ||
160 | } | ||
161 | |||
149 | pub fn resolve_path_in_type_ns( | 162 | pub fn resolve_path_in_type_ns( |
150 | &self, | 163 | &self, |
151 | db: &dyn DefDatabase, | 164 | db: &dyn DefDatabase, |
@@ -416,7 +429,7 @@ impl Resolver { | |||
416 | let mut traits = FxHashSet::default(); | 429 | let mut traits = FxHashSet::default(); |
417 | for scope in &self.scopes { | 430 | for scope in &self.scopes { |
418 | if let Scope::ModuleScope(m) = scope { | 431 | if let Scope::ModuleScope(m) = scope { |
419 | if let Some(prelude) = m.crate_def_map.prelude { | 432 | if let Some(prelude) = m.crate_def_map.prelude() { |
420 | let prelude_def_map = db.crate_def_map(prelude.krate); | 433 | let prelude_def_map = db.crate_def_map(prelude.krate); |
421 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | 434 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); |
422 | } | 435 | } |
@@ -446,11 +459,11 @@ impl Resolver { | |||
446 | 459 | ||
447 | pub fn module(&self) -> Option<ModuleId> { | 460 | pub fn module(&self) -> Option<ModuleId> { |
448 | let (def_map, local_id) = self.module_scope()?; | 461 | let (def_map, local_id) = self.module_scope()?; |
449 | Some(ModuleId { krate: def_map.krate, local_id }) | 462 | Some(ModuleId { krate: def_map.krate(), local_id }) |
450 | } | 463 | } |
451 | 464 | ||
452 | pub fn krate(&self) -> Option<CrateId> { | 465 | pub fn krate(&self) -> Option<CrateId> { |
453 | self.module_scope().map(|t| t.0.krate) | 466 | self.module_scope().map(|t| t.0.krate()) |
454 | } | 467 | } |
455 | 468 | ||
456 | pub fn where_predicates_in_scope<'a>( | 469 | pub fn where_predicates_in_scope<'a>( |
@@ -509,13 +522,13 @@ impl Scope { | |||
509 | seen.insert((name.clone(), scope)); | 522 | seen.insert((name.clone(), scope)); |
510 | f(name.clone(), ScopeDef::PerNs(scope)); | 523 | f(name.clone(), ScopeDef::PerNs(scope)); |
511 | }); | 524 | }); |
512 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { | 525 | m.crate_def_map.extern_prelude().for_each(|(name, &def)| { |
513 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); | 526 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); |
514 | }); | 527 | }); |
515 | BUILTIN_SCOPE.iter().for_each(|(name, &def)| { | 528 | BUILTIN_SCOPE.iter().for_each(|(name, &def)| { |
516 | f(name.clone(), ScopeDef::PerNs(def)); | 529 | f(name.clone(), ScopeDef::PerNs(def)); |
517 | }); | 530 | }); |
518 | if let Some(prelude) = m.crate_def_map.prelude { | 531 | if let Some(prelude) = m.crate_def_map.prelude() { |
519 | let prelude_def_map = db.crate_def_map(prelude.krate); | 532 | let prelude_def_map = db.crate_def_map(prelude.krate); |
520 | prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { | 533 | prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { |
521 | let seen_tuple = (name.clone(), def); | 534 | let seen_tuple = (name.clone(), def); |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index 574c0201a..4ff219fb7 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -75,7 +75,7 @@ impl TestDB { | |||
75 | pub(crate) fn module_for_file(&self, file_id: FileId) -> crate::ModuleId { | 75 | pub(crate) fn module_for_file(&self, file_id: FileId) -> crate::ModuleId { |
76 | for &krate in self.relevant_crates(file_id).iter() { | 76 | for &krate in self.relevant_crates(file_id).iter() { |
77 | let crate_def_map = self.crate_def_map(krate); | 77 | let crate_def_map = self.crate_def_map(krate); |
78 | for (local_id, data) in crate_def_map.modules.iter() { | 78 | for (local_id, data) in crate_def_map.modules() { |
79 | if data.origin.file_id() == Some(file_id) { | 79 | if data.origin.file_id() == Some(file_id) { |
80 | return crate::ModuleId { krate, local_id }; | 80 | return crate::ModuleId { krate, local_id }; |
81 | } | 81 | } |
@@ -110,7 +110,7 @@ impl TestDB { | |||
110 | let crate_graph = self.crate_graph(); | 110 | let crate_graph = self.crate_graph(); |
111 | for krate in crate_graph.iter() { | 111 | for krate in crate_graph.iter() { |
112 | let crate_def_map = self.crate_def_map(krate); | 112 | let crate_def_map = self.crate_def_map(krate); |
113 | for (module_id, _) in crate_def_map.modules.iter() { | 113 | for (module_id, _) in crate_def_map.modules() { |
114 | let file_id = crate_def_map[module_id].origin.file_id(); | 114 | let file_id = crate_def_map[module_id].origin.file_id(); |
115 | files.extend(file_id) | 115 | files.extend(file_id) |
116 | } | 116 | } |
@@ -135,7 +135,7 @@ impl TestDB { | |||
135 | let crate_def_map = self.crate_def_map(krate); | 135 | let crate_def_map = self.crate_def_map(krate); |
136 | 136 | ||
137 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | 137 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); |
138 | for (module_id, module) in crate_def_map.modules.iter() { | 138 | for (module_id, module) in crate_def_map.modules() { |
139 | crate_def_map.add_diagnostics(self, module_id, &mut sink); | 139 | crate_def_map.add_diagnostics(self, module_id, &mut sink); |
140 | 140 | ||
141 | for decl in module.scope.declarations() { | 141 | for decl in module.scope.declarations() { |
diff --git a/crates/hir_expand/src/ast_id_map.rs b/crates/hir_expand/src/ast_id_map.rs index 2401b0cc5..0991fffd8 100644 --- a/crates/hir_expand/src/ast_id_map.rs +++ b/crates/hir_expand/src/ast_id_map.rs | |||
@@ -13,7 +13,7 @@ use std::{ | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | use la_arena::{Arena, Idx}; | 15 | use la_arena::{Arena, Idx}; |
16 | use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; | 16 | use syntax::{ast, match_ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; |
17 | 17 | ||
18 | /// `AstId` points to an AST node in a specific file. | 18 | /// `AstId` points to an AST node in a specific file. |
19 | pub struct FileAstId<N: AstNode> { | 19 | pub struct FileAstId<N: AstNode> { |
@@ -72,12 +72,20 @@ impl AstIdMap { | |||
72 | // get lower ids then children. That is, adding a new child does not | 72 | // get lower ids then children. That is, adding a new child does not |
73 | // change parent's id. This means that, say, adding a new function to a | 73 | // change parent's id. This means that, say, adding a new function to a |
74 | // trait does not change ids of top-level items, which helps caching. | 74 | // trait does not change ids of top-level items, which helps caching. |
75 | bdfs(node, |it| match ast::Item::cast(it) { | 75 | bdfs(node, |it| { |
76 | Some(module_item) => { | 76 | match_ast! { |
77 | res.alloc(module_item.syntax()); | 77 | match it { |
78 | true | 78 | ast::Item(module_item) => { |
79 | res.alloc(module_item.syntax()); | ||
80 | true | ||
81 | }, | ||
82 | ast::BlockExpr(block) => { | ||
83 | res.alloc(block.syntax()); | ||
84 | true | ||
85 | }, | ||
86 | _ => false, | ||
87 | } | ||
79 | } | 88 | } |
80 | None => false, | ||
81 | }); | 89 | }); |
82 | res | 90 | res |
83 | } | 91 | } |
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index eb257579f..b7f1aae8f 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -102,7 +102,7 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, mbe::ExpandError> { | |||
102 | debug!("name token not found"); | 102 | debug!("name token not found"); |
103 | mbe::ExpandError::ConversionError | 103 | mbe::ExpandError::ConversionError |
104 | })?; | 104 | })?; |
105 | let name_token = tt::Ident { id: name_token_id, text: name.text().clone() }; | 105 | let name_token = tt::Ident { id: name_token_id, text: name.text().into() }; |
106 | let type_params = params.map_or(0, |type_param_list| type_param_list.type_params().count()); | 106 | let type_params = params.map_or(0, |type_param_list| type_param_list.type_params().count()); |
107 | Ok(BasicAdtInfo { name: name_token, type_params }) | 107 | Ok(BasicAdtInfo { name: name_token, type_params }) |
108 | } | 108 | } |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 467516eb7..cb6e23320 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -173,7 +173,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { | |||
173 | }; | 173 | }; |
174 | let loc = db.lookup_intern_macro(id); | 174 | let loc = db.lookup_intern_macro(id); |
175 | let arg = loc.kind.arg(db)?; | 175 | let arg = loc.kind.arg(db)?; |
176 | Some(arg.green().clone()) | 176 | Some(arg.green().to_owned()) |
177 | } | 177 | } |
178 | 178 | ||
179 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 179 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 95d853b6d..d692cec14 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -38,7 +38,7 @@ impl Name { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn new_lifetime(lt: &ast::Lifetime) -> Name { | 40 | pub fn new_lifetime(lt: &ast::Lifetime) -> Name { |
41 | Self::new_text(lt.text().clone()) | 41 | Self::new_text(lt.text().into()) |
42 | } | 42 | } |
43 | 43 | ||
44 | /// Shortcut to create inline plain text name | 44 | /// Shortcut to create inline plain text name |
@@ -47,12 +47,12 @@ impl Name { | |||
47 | } | 47 | } |
48 | 48 | ||
49 | /// Resolve a name from the text of token. | 49 | /// Resolve a name from the text of token. |
50 | fn resolve(raw_text: &SmolStr) -> Name { | 50 | fn resolve(raw_text: &str) -> Name { |
51 | let raw_start = "r#"; | 51 | let raw_start = "r#"; |
52 | if raw_text.as_str().starts_with(raw_start) { | 52 | if raw_text.starts_with(raw_start) { |
53 | Name::new_text(SmolStr::new(&raw_text[raw_start.len()..])) | 53 | Name::new_text(SmolStr::new(&raw_text[raw_start.len()..])) |
54 | } else { | 54 | } else { |
55 | Name::new_text(raw_text.clone()) | 55 | Name::new_text(raw_text.into()) |
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 98434b741..db42a00dc 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -17,9 +17,9 @@ ena = "0.14.0" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.47", default-features = false } | 20 | chalk-solve = { version = "0.50", default-features = false } |
21 | chalk-ir = "0.47" | 21 | chalk-ir = "0.50" |
22 | chalk-recursive = "0.47" | 22 | chalk-recursive = "0.50" |
23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
24 | 24 | ||
25 | stdx = { path = "../stdx", version = "0.0.0" } | 25 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index c67a289f2..247da43f2 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -409,7 +409,7 @@ mod tests { | |||
409 | let crate_def_map = self.crate_def_map(krate); | 409 | let crate_def_map = self.crate_def_map(krate); |
410 | 410 | ||
411 | let mut fns = Vec::new(); | 411 | let mut fns = Vec::new(); |
412 | for (module_id, _) in crate_def_map.modules.iter() { | 412 | for (module_id, _) in crate_def_map.modules() { |
413 | for decl in crate_def_map[module_id].scope.declarations() { | 413 | for decl in crate_def_map[module_id].scope.declarations() { |
414 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | 414 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); |
415 | validate_module_item(self, krate, decl, &mut sink); | 415 | validate_module_item(self, krate, decl, &mut sink); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 9bf3b51b0..d7351d212 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -491,7 +491,10 @@ impl<'a> InferenceContext<'a> { | |||
491 | Expr::Box { expr } => { | 491 | Expr::Box { expr } => { |
492 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 492 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
493 | if let Some(box_) = self.resolve_boxed_box() { | 493 | if let Some(box_) = self.resolve_boxed_box() { |
494 | Ty::apply_one(TypeCtor::Adt(box_), inner_ty) | 494 | let mut sb = Substs::build_for_type_ctor(self.db, TypeCtor::Adt(box_)); |
495 | sb = sb.push(inner_ty); | ||
496 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); | ||
497 | Ty::apply(TypeCtor::Adt(box_), sb.build()) | ||
495 | } else { | 498 | } else { |
496 | Ty::Unknown | 499 | Ty::Unknown |
497 | } | 500 | } |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 8a289f52a..f06aeeb42 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -112,7 +112,7 @@ impl TraitImpls { | |||
112 | let mut impls = Self { map: FxHashMap::default() }; | 112 | let mut impls = Self { map: FxHashMap::default() }; |
113 | 113 | ||
114 | let crate_def_map = db.crate_def_map(krate); | 114 | let crate_def_map = db.crate_def_map(krate); |
115 | for (_module_id, module_data) in crate_def_map.modules.iter() { | 115 | for (_module_id, module_data) in crate_def_map.modules() { |
116 | for impl_id in module_data.scope.impls() { | 116 | for impl_id in module_data.scope.impls() { |
117 | let target_trait = match db.impl_trait(impl_id) { | 117 | let target_trait = match db.impl_trait(impl_id) { |
118 | Some(tr) => tr.value.trait_, | 118 | Some(tr) => tr.value.trait_, |
@@ -198,7 +198,7 @@ impl InherentImpls { | |||
198 | let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default(); | 198 | let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default(); |
199 | 199 | ||
200 | let crate_def_map = db.crate_def_map(krate); | 200 | let crate_def_map = db.crate_def_map(krate); |
201 | for (_module_id, module_data) in crate_def_map.modules.iter() { | 201 | for (_module_id, module_data) in crate_def_map.modules() { |
202 | for impl_id in module_data.scope.impls() { | 202 | for impl_id in module_data.scope.impls() { |
203 | let data = db.impl_data(impl_id); | 203 | let data = db.impl_data(impl_id); |
204 | if data.target_trait.is_some() { | 204 | if data.target_trait.is_some() { |
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs index 646e16bbe..3bbcbc242 100644 --- a/crates/hir_ty/src/test_db.rs +++ b/crates/hir_ty/src/test_db.rs | |||
@@ -81,7 +81,7 @@ impl TestDB { | |||
81 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { | 81 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { |
82 | for &krate in self.relevant_crates(file_id).iter() { | 82 | for &krate in self.relevant_crates(file_id).iter() { |
83 | let crate_def_map = self.crate_def_map(krate); | 83 | let crate_def_map = self.crate_def_map(krate); |
84 | for (local_id, data) in crate_def_map.modules.iter() { | 84 | for (local_id, data) in crate_def_map.modules() { |
85 | if data.origin.file_id() == Some(file_id) { | 85 | if data.origin.file_id() == Some(file_id) { |
86 | return ModuleId { krate, local_id }; | 86 | return ModuleId { krate, local_id }; |
87 | } | 87 | } |
@@ -95,7 +95,7 @@ impl TestDB { | |||
95 | let crate_graph = self.crate_graph(); | 95 | let crate_graph = self.crate_graph(); |
96 | for krate in crate_graph.iter() { | 96 | for krate in crate_graph.iter() { |
97 | let crate_def_map = self.crate_def_map(krate); | 97 | let crate_def_map = self.crate_def_map(krate); |
98 | for (module_id, _) in crate_def_map.modules.iter() { | 98 | for (module_id, _) in crate_def_map.modules() { |
99 | let file_id = crate_def_map[module_id].origin.file_id(); | 99 | let file_id = crate_def_map[module_id].origin.file_id(); |
100 | files.extend(file_id) | 100 | files.extend(file_id) |
101 | } | 101 | } |
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 8d431b920..16682f76f 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -29,6 +29,30 @@ mod boxed { | |||
29 | } | 29 | } |
30 | 30 | ||
31 | #[test] | 31 | #[test] |
32 | fn infer_box_with_allocator() { | ||
33 | check_types( | ||
34 | r#" | ||
35 | //- /main.rs crate:main deps:std | ||
36 | fn test() { | ||
37 | let x = box 1; | ||
38 | let t = (x, box x, box &1, box [1]); | ||
39 | t; | ||
40 | } //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; _], {unknown}>) | ||
41 | |||
42 | //- /std.rs crate:std | ||
43 | #[prelude_import] use prelude::*; | ||
44 | mod boxed { | ||
45 | #[lang = "owned_box"] | ||
46 | pub struct Box<T: ?Sized, A: Allocator> { | ||
47 | inner: *mut T, | ||
48 | allocator: A, | ||
49 | } | ||
50 | } | ||
51 | "#, | ||
52 | ); | ||
53 | } | ||
54 | |||
55 | #[test] | ||
32 | fn infer_adt_self() { | 56 | fn infer_adt_self() { |
33 | check_types( | 57 | check_types( |
34 | r#" | 58 | r#" |
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index 8d08e4763..16fa828ad 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -130,8 +130,7 @@ impl NavigationTarget { | |||
130 | node: InFile<&dyn ast::NameOwner>, | 130 | node: InFile<&dyn ast::NameOwner>, |
131 | kind: SymbolKind, | 131 | kind: SymbolKind, |
132 | ) -> NavigationTarget { | 132 | ) -> NavigationTarget { |
133 | let name = | 133 | let name = node.value.name().map(|it| it.text().into()).unwrap_or_else(|| "_".into()); |
134 | node.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_")); | ||
135 | let focus_range = | 134 | let focus_range = |
136 | node.value.name().map(|it| node.with_value(it.syntax()).original_file_range(db).range); | 135 | node.value.name().map(|it| node.with_value(it.syntax()).original_file_range(db).range); |
137 | let frange = node.map(|it| it.syntax()).original_file_range(db); | 136 | let frange = node.map(|it| it.syntax()).original_file_range(db); |
@@ -272,6 +271,7 @@ impl ToNav for hir::Module { | |||
272 | ModuleSource::Module(node) => { | 271 | ModuleSource::Module(node) => { |
273 | (node.syntax(), node.name().map(|it| it.syntax().text_range())) | 272 | (node.syntax(), node.name().map(|it| it.syntax().text_range())) |
274 | } | 273 | } |
274 | ModuleSource::BlockExpr(node) => (node.syntax(), None), | ||
275 | }; | 275 | }; |
276 | let frange = src.with_value(syntax).original_file_range(db); | 276 | let frange = src.with_value(syntax).original_file_range(db); |
277 | NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, SymbolKind::Module) | 277 | NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, SymbolKind::Module) |
diff --git a/crates/ide/src/display/short_label.rs b/crates/ide/src/display/short_label.rs index 990f740b8..7ac050473 100644 --- a/crates/ide/src/display/short_label.rs +++ b/crates/ide/src/display/short_label.rs | |||
@@ -53,6 +53,12 @@ impl ShortLabel for ast::SourceFile { | |||
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
56 | impl ShortLabel for ast::BlockExpr { | ||
57 | fn short_label(&self) -> Option<String> { | ||
58 | None | ||
59 | } | ||
60 | } | ||
61 | |||
56 | impl ShortLabel for ast::TypeAlias { | 62 | impl ShortLabel for ast::TypeAlias { |
57 | fn short_label(&self) -> Option<String> { | 63 | fn short_label(&self) -> Option<String> { |
58 | short_label_from_node(self, "type ") | 64 | short_label_from_node(self, "type ") |
@@ -90,7 +96,7 @@ impl ShortLabel for ast::Variant { | |||
90 | impl ShortLabel for ast::ConstParam { | 96 | impl ShortLabel for ast::ConstParam { |
91 | fn short_label(&self) -> Option<String> { | 97 | fn short_label(&self) -> Option<String> { |
92 | let mut buf = "const ".to_owned(); | 98 | let mut buf = "const ".to_owned(); |
93 | buf.push_str(self.name()?.text().as_str()); | 99 | buf.push_str(self.name()?.text()); |
94 | if let Some(type_ref) = self.ty() { | 100 | if let Some(type_ref) = self.ty() { |
95 | format_to!(buf, ": {}", type_ref.syntax()); | 101 | format_to!(buf, ": {}", type_ref.syntax()); |
96 | } | 102 | } |
@@ -117,6 +123,6 @@ where | |||
117 | { | 123 | { |
118 | let mut buf = node.visibility().map(|v| format!("{} ", v.syntax())).unwrap_or_default(); | 124 | let mut buf = node.visibility().map(|v| format!("{} ", v.syntax())).unwrap_or_default(); |
119 | buf.push_str(label); | 125 | buf.push_str(label); |
120 | buf.push_str(node.name()?.text().as_str()); | 126 | buf.push_str(node.name()?.text()); |
121 | Some(buf) | 127 | Some(buf) |
122 | } | 128 | } |
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 1f08d7810..730e0dd0a 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -221,14 +221,31 @@ fn rewrite_intra_doc_link( | |||
221 | }?; | 221 | }?; |
222 | let krate = resolved.module(db)?.krate(); | 222 | let krate = resolved.module(db)?.krate(); |
223 | let canonical_path = resolved.canonical_path(db)?; | 223 | let canonical_path = resolved.canonical_path(db)?; |
224 | let new_target = get_doc_url(db, &krate)? | 224 | let mut new_url = get_doc_url(db, &krate)? |
225 | .join(&format!("{}/", krate.display_name(db)?)) | 225 | .join(&format!("{}/", krate.display_name(db)?)) |
226 | .ok()? | 226 | .ok()? |
227 | .join(&canonical_path.replace("::", "/")) | 227 | .join(&canonical_path.replace("::", "/")) |
228 | .ok()? | 228 | .ok()? |
229 | .join(&get_symbol_filename(db, &resolved)?) | 229 | .join(&get_symbol_filename(db, &resolved)?) |
230 | .ok()? | 230 | .ok()?; |
231 | .into_string(); | 231 | |
232 | if let ModuleDef::Trait(t) = resolved { | ||
233 | let items = t.items(db); | ||
234 | if let Some(field_or_assoc_item) = items.iter().find_map(|assoc_item| { | ||
235 | if let Some(name) = assoc_item.name(db) { | ||
236 | if link.to_string() == format!("{}::{}", canonical_path, name) { | ||
237 | return Some(FieldOrAssocItem::AssocItem(*assoc_item)); | ||
238 | } | ||
239 | } | ||
240 | None | ||
241 | }) { | ||
242 | if let Some(fragment) = get_symbol_fragment(db, &field_or_assoc_item) { | ||
243 | new_url = new_url.join(&fragment).ok()?; | ||
244 | } | ||
245 | }; | ||
246 | } | ||
247 | |||
248 | let new_target = new_url.into_string(); | ||
232 | let new_title = strip_prefixes_suffixes(title); | 249 | let new_title = strip_prefixes_suffixes(title); |
233 | Some((new_target, new_title.to_string())) | 250 | Some((new_target, new_title.to_string())) |
234 | } | 251 | } |
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs index 17a540972..2d722dee0 100644 --- a/crates/ide/src/extend_selection.rs +++ b/crates/ide/src/extend_selection.rs | |||
@@ -213,8 +213,8 @@ fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextSize) -> TextRange | |||
213 | let ws_text = ws.text(); | 213 | let ws_text = ws.text(); |
214 | let suffix = TextRange::new(offset, ws.text_range().end()) - ws.text_range().start(); | 214 | let suffix = TextRange::new(offset, ws.text_range().end()) - ws.text_range().start(); |
215 | let prefix = TextRange::new(ws.text_range().start(), offset) - ws.text_range().start(); | 215 | let prefix = TextRange::new(ws.text_range().start(), offset) - ws.text_range().start(); |
216 | let ws_suffix = &ws_text.as_str()[suffix]; | 216 | let ws_suffix = &ws_text[suffix]; |
217 | let ws_prefix = &ws_text.as_str()[prefix]; | 217 | let ws_prefix = &ws_text[prefix]; |
218 | if ws_text.contains('\n') && !ws_suffix.contains('\n') { | 218 | if ws_text.contains('\n') && !ws_suffix.contains('\n') { |
219 | if let Some(node) = ws.next_sibling_or_token() { | 219 | if let Some(node) = ws.next_sibling_or_token() { |
220 | let start = match ws_prefix.rfind('\n') { | 220 | let start = match ws_prefix.rfind('\n') { |
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index a1d2bce1d..1a997fa40 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs | |||
@@ -2,16 +2,14 @@ use either::Either; | |||
2 | use hir::{HasAttrs, ModuleDef, Semantics}; | 2 | use hir::{HasAttrs, ModuleDef, Semantics}; |
3 | use ide_db::{ | 3 | use ide_db::{ |
4 | defs::{Definition, NameClass, NameRefClass}, | 4 | defs::{Definition, NameClass, NameRefClass}, |
5 | symbol_index, RootDatabase, | 5 | RootDatabase, |
6 | }; | 6 | }; |
7 | use syntax::{ | 7 | use syntax::{ |
8 | ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T, | 8 | ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | display::{ToNav, TryToNav}, | 12 | display::TryToNav, doc_links::extract_definitions_from_markdown, runnables::doc_owner_to_def, |
13 | doc_links::extract_definitions_from_markdown, | ||
14 | runnables::doc_owner_to_def, | ||
15 | FilePosition, NavigationTarget, RangeInfo, | 13 | FilePosition, NavigationTarget, RangeInfo, |
16 | }; | 14 | }; |
17 | 15 | ||
@@ -38,28 +36,26 @@ pub(crate) fn goto_definition( | |||
38 | return Some(RangeInfo::new(original_token.text_range(), vec![nav])); | 36 | return Some(RangeInfo::new(original_token.text_range(), vec![nav])); |
39 | } | 37 | } |
40 | 38 | ||
41 | let nav_targets = match_ast! { | 39 | let nav = match_ast! { |
42 | match parent { | 40 | match parent { |
43 | ast::NameRef(name_ref) => { | 41 | ast::NameRef(name_ref) => { |
44 | reference_definition(&sema, Either::Right(&name_ref)).to_vec() | 42 | reference_definition(&sema, Either::Right(&name_ref)) |
45 | }, | 43 | }, |
46 | ast::Name(name) => { | 44 | ast::Name(name) => { |
47 | let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db); | 45 | let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db); |
48 | let nav = def.try_to_nav(sema.db)?; | 46 | def.try_to_nav(sema.db) |
49 | vec![nav] | ||
50 | }, | 47 | }, |
51 | ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, <) { | 48 | ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, <) { |
52 | let def = name_class.referenced_or_defined(sema.db); | 49 | let def = name_class.referenced_or_defined(sema.db); |
53 | let nav = def.try_to_nav(sema.db)?; | 50 | def.try_to_nav(sema.db) |
54 | vec![nav] | ||
55 | } else { | 51 | } else { |
56 | reference_definition(&sema, Either::Left(<)).to_vec() | 52 | reference_definition(&sema, Either::Left(<)) |
57 | }, | 53 | }, |
58 | _ => return None, | 54 | _ => return None, |
59 | } | 55 | } |
60 | }; | 56 | }; |
61 | 57 | ||
62 | Some(RangeInfo::new(original_token.text_range(), nav_targets)) | 58 | Some(RangeInfo::new(original_token.text_range(), nav.into_iter().collect())) |
63 | } | 59 | } |
64 | 60 | ||
65 | fn def_for_doc_comment( | 61 | fn def_for_doc_comment( |
@@ -120,42 +116,16 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
120 | } | 116 | } |
121 | } | 117 | } |
122 | 118 | ||
123 | #[derive(Debug)] | ||
124 | pub(crate) enum ReferenceResult { | ||
125 | Exact(NavigationTarget), | ||
126 | Approximate(Vec<NavigationTarget>), | ||
127 | } | ||
128 | |||
129 | impl ReferenceResult { | ||
130 | fn to_vec(self) -> Vec<NavigationTarget> { | ||
131 | match self { | ||
132 | ReferenceResult::Exact(target) => vec![target], | ||
133 | ReferenceResult::Approximate(vec) => vec, | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | pub(crate) fn reference_definition( | 119 | pub(crate) fn reference_definition( |
139 | sema: &Semantics<RootDatabase>, | 120 | sema: &Semantics<RootDatabase>, |
140 | name_ref: Either<&ast::Lifetime, &ast::NameRef>, | 121 | name_ref: Either<&ast::Lifetime, &ast::NameRef>, |
141 | ) -> ReferenceResult { | 122 | ) -> Option<NavigationTarget> { |
142 | let name_kind = name_ref.either( | 123 | let name_kind = name_ref.either( |
143 | |lifetime| NameRefClass::classify_lifetime(sema, lifetime), | 124 | |lifetime| NameRefClass::classify_lifetime(sema, lifetime), |
144 | |name_ref| NameRefClass::classify(sema, name_ref), | 125 | |name_ref| NameRefClass::classify(sema, name_ref), |
145 | ); | 126 | )?; |
146 | if let Some(def) = name_kind { | 127 | let def = name_kind.referenced(sema.db); |
147 | let def = def.referenced(sema.db); | 128 | def.try_to_nav(sema.db) |
148 | return match def.try_to_nav(sema.db) { | ||
149 | Some(nav) => ReferenceResult::Exact(nav), | ||
150 | None => ReferenceResult::Approximate(Vec::new()), | ||
151 | }; | ||
152 | } | ||
153 | |||
154 | // Fallback index based approach: | ||
155 | let name = name_ref.either(ast::Lifetime::text, ast::NameRef::text); | ||
156 | let navs = | ||
157 | symbol_index::index_resolve(sema.db, name).into_iter().map(|s| s.to_nav(sema.db)).collect(); | ||
158 | ReferenceResult::Approximate(navs) | ||
159 | } | 129 | } |
160 | 130 | ||
161 | #[cfg(test)] | 131 | #[cfg(test)] |
@@ -192,12 +162,12 @@ mod tests { | |||
192 | fn goto_def_for_extern_crate() { | 162 | fn goto_def_for_extern_crate() { |
193 | check( | 163 | check( |
194 | r#" | 164 | r#" |
195 | //- /main.rs crate:main deps:std | 165 | //- /main.rs crate:main deps:std |
196 | extern crate std$0; | 166 | extern crate std$0; |
197 | //- /std/lib.rs crate:std | 167 | //- /std/lib.rs crate:std |
198 | // empty | 168 | // empty |
199 | //^ file | 169 | //^ file |
200 | "#, | 170 | "#, |
201 | ) | 171 | ) |
202 | } | 172 | } |
203 | 173 | ||
@@ -205,12 +175,12 @@ mod tests { | |||
205 | fn goto_def_for_renamed_extern_crate() { | 175 | fn goto_def_for_renamed_extern_crate() { |
206 | check( | 176 | check( |
207 | r#" | 177 | r#" |
208 | //- /main.rs crate:main deps:std | 178 | //- /main.rs crate:main deps:std |
209 | extern crate std as abc$0; | 179 | extern crate std as abc$0; |
210 | //- /std/lib.rs crate:std | 180 | //- /std/lib.rs crate:std |
211 | // empty | 181 | // empty |
212 | //^ file | 182 | //^ file |
213 | "#, | 183 | "#, |
214 | ) | 184 | ) |
215 | } | 185 | } |
216 | 186 | ||
@@ -297,13 +267,13 @@ fn bar() { | |||
297 | fn goto_def_for_macros_from_other_crates() { | 267 | fn goto_def_for_macros_from_other_crates() { |
298 | check( | 268 | check( |
299 | r#" | 269 | r#" |
300 | //- /lib.rs | 270 | //- /lib.rs crate:main deps:foo |
301 | use foo::foo; | 271 | use foo::foo; |
302 | fn bar() { | 272 | fn bar() { |
303 | $0foo!(); | 273 | $0foo!(); |
304 | } | 274 | } |
305 | 275 | ||
306 | //- /foo/lib.rs | 276 | //- /foo/lib.rs crate:foo |
307 | #[macro_export] | 277 | #[macro_export] |
308 | macro_rules! foo { () => { () } } | 278 | macro_rules! foo { () => { () } } |
309 | //^^^ | 279 | //^^^ |
@@ -315,10 +285,10 @@ macro_rules! foo { () => { () } } | |||
315 | fn goto_def_for_macros_in_use_tree() { | 285 | fn goto_def_for_macros_in_use_tree() { |
316 | check( | 286 | check( |
317 | r#" | 287 | r#" |
318 | //- /lib.rs | 288 | //- /lib.rs crate:main deps:foo |
319 | use foo::foo$0; | 289 | use foo::foo$0; |
320 | 290 | ||
321 | //- /foo/lib.rs | 291 | //- /foo/lib.rs crate:foo |
322 | #[macro_export] | 292 | #[macro_export] |
323 | macro_rules! foo { () => { () } } | 293 | macro_rules! foo { () => { () } } |
324 | //^^^ | 294 | //^^^ |
@@ -976,10 +946,10 @@ type Alias<T> = T$0; | |||
976 | fn goto_def_for_macro_container() { | 946 | fn goto_def_for_macro_container() { |
977 | check( | 947 | check( |
978 | r#" | 948 | r#" |
979 | //- /lib.rs | 949 | //- /lib.rs crate:main deps:foo |
980 | foo::module$0::mac!(); | 950 | foo::module$0::mac!(); |
981 | 951 | ||
982 | //- /foo/lib.rs | 952 | //- /foo/lib.rs crate:foo |
983 | pub mod module { | 953 | pub mod module { |
984 | //^^^^^^ | 954 | //^^^^^^ |
985 | #[macro_export] | 955 | #[macro_export] |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 44ebdbd35..d47a4cb0f 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -321,6 +321,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
321 | match it.definition_source(db).value { | 321 | match it.definition_source(db).value { |
322 | ModuleSource::Module(it) => it.short_label(), | 322 | ModuleSource::Module(it) => it.short_label(), |
323 | ModuleSource::SourceFile(it) => it.short_label(), | 323 | ModuleSource::SourceFile(it) => it.short_label(), |
324 | ModuleSource::BlockExpr(it) => it.short_label(), | ||
324 | }, | 325 | }, |
325 | mod_path, | 326 | mod_path, |
326 | ), | 327 | ), |
@@ -1825,6 +1826,35 @@ pub struct B$0ar | |||
1825 | "#]], | 1826 | "#]], |
1826 | ); | 1827 | ); |
1827 | } | 1828 | } |
1829 | #[test] | ||
1830 | fn test_hover_intra_link_reference_to_trait_method() { | ||
1831 | check( | ||
1832 | r#" | ||
1833 | pub trait Foo { | ||
1834 | fn buzz() -> usize; | ||
1835 | } | ||
1836 | /// [Foo][buzz] | ||
1837 | /// | ||
1838 | /// [buzz]: Foo::buzz | ||
1839 | pub struct B$0ar | ||
1840 | "#, | ||
1841 | expect | ||
1855 | "#]], | ||
1856 | ); | ||
1857 | } | ||
1828 | 1858 | ||
1829 | #[test] | 1859 | #[test] |
1830 | fn test_hover_external_url() { | 1860 | fn test_hover_external_url() { |
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index a2039fcc7..54485fd30 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -411,7 +411,7 @@ fn get_string_representation(expr: &ast::Expr) -> Option<String> { | |||
411 | match expr { | 411 | match expr { |
412 | ast::Expr::MethodCallExpr(method_call_expr) => { | 412 | ast::Expr::MethodCallExpr(method_call_expr) => { |
413 | let name_ref = method_call_expr.name_ref()?; | 413 | let name_ref = method_call_expr.name_ref()?; |
414 | match name_ref.text().as_str() { | 414 | match name_ref.text() { |
415 | "clone" => method_call_expr.receiver().map(|rec| rec.to_string()), | 415 | "clone" => method_call_expr.receiver().map(|rec| rec.to_string()), |
416 | name_ref => Some(name_ref.to_owned()), | 416 | name_ref => Some(name_ref.to_owned()), |
417 | } | 417 | } |
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index 981467c8d..631bde0f1 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs | |||
@@ -59,7 +59,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextS | |||
59 | // The node is either the first or the last in the file | 59 | // The node is either the first or the last in the file |
60 | let suff = &token.text()[TextRange::new( | 60 | let suff = &token.text()[TextRange::new( |
61 | offset - token.text_range().start() + TextSize::of('\n'), | 61 | offset - token.text_range().start() + TextSize::of('\n'), |
62 | TextSize::of(token.text().as_str()), | 62 | TextSize::of(token.text()), |
63 | )]; | 63 | )]; |
64 | let spaces = suff.bytes().take_while(|&b| b == b' ').count(); | 64 | let spaces = suff.bytes().take_while(|&b| b == b' ').count(); |
65 | 65 | ||
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index e282b31af..33170906d 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -9,6 +9,7 @@ use syntax::{ | |||
9 | ast::{self, AstNode, AttrsOwner}, | 9 | ast::{self, AstNode, AttrsOwner}, |
10 | match_ast, SyntaxNode, | 10 | match_ast, SyntaxNode, |
11 | }; | 11 | }; |
12 | use test_utils::mark; | ||
12 | 13 | ||
13 | use crate::{ | 14 | use crate::{ |
14 | display::{ToNav, TryToNav}, | 15 | display::{ToNav, TryToNav}, |
@@ -96,28 +97,26 @@ impl Runnable { | |||
96 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { | 97 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { |
97 | let sema = Semantics::new(db); | 98 | let sema = Semantics::new(db); |
98 | let module = match sema.to_module_def(file_id) { | 99 | let module = match sema.to_module_def(file_id) { |
99 | None => return vec![], | 100 | None => return Vec::new(), |
100 | Some(it) => it, | 101 | Some(it) => it, |
101 | }; | 102 | }; |
102 | 103 | ||
103 | runnables_mod(&sema, module) | 104 | let mut res = Vec::new(); |
105 | runnables_mod(&sema, &mut res, module); | ||
106 | res | ||
104 | } | 107 | } |
105 | 108 | ||
106 | fn runnables_mod(sema: &Semantics<RootDatabase>, module: hir::Module) -> Vec<Runnable> { | 109 | fn runnables_mod(sema: &Semantics<RootDatabase>, acc: &mut Vec<Runnable>, module: hir::Module) { |
107 | let mut res: Vec<Runnable> = module | 110 | acc.extend(module.declarations(sema.db).into_iter().filter_map(|def| { |
108 | .declarations(sema.db) | 111 | let runnable = match def { |
109 | .into_iter() | 112 | hir::ModuleDef::Module(it) => runnable_mod(&sema, it), |
110 | .filter_map(|def| { | 113 | hir::ModuleDef::Function(it) => runnable_fn(&sema, it), |
111 | let runnable = match def { | 114 | _ => None, |
112 | hir::ModuleDef::Module(it) => runnable_mod(&sema, it), | 115 | }; |
113 | hir::ModuleDef::Function(it) => runnable_fn(&sema, it), | 116 | runnable.or_else(|| module_def_doctest(&sema, def)) |
114 | _ => None, | 117 | })); |
115 | }; | ||
116 | runnable.or_else(|| module_def_doctest(&sema, def)) | ||
117 | }) | ||
118 | .collect(); | ||
119 | 118 | ||
120 | res.extend(module.impl_defs(sema.db).into_iter().flat_map(|it| it.items(sema.db)).filter_map( | 119 | acc.extend(module.impl_defs(sema.db).into_iter().flat_map(|it| it.items(sema.db)).filter_map( |
121 | |def| match def { | 120 | |def| match def { |
122 | hir::AssocItem::Function(it) => { | 121 | hir::AssocItem::Function(it) => { |
123 | runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into())) | 122 | runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into())) |
@@ -127,12 +126,15 @@ fn runnables_mod(sema: &Semantics<RootDatabase>, module: hir::Module) -> Vec<Run | |||
127 | }, | 126 | }, |
128 | )); | 127 | )); |
129 | 128 | ||
130 | res.extend(module.declarations(sema.db).into_iter().flat_map(|def| match def { | 129 | for def in module.declarations(sema.db) { |
131 | hir::ModuleDef::Module(it) => runnables_mod(sema, it), | 130 | if let hir::ModuleDef::Module(submodule) = def { |
132 | _ => vec![], | 131 | match submodule.definition_source(sema.db).value { |
133 | })); | 132 | hir::ModuleSource::Module(_) => runnables_mod(sema, acc, submodule), |
134 | 133 | hir::ModuleSource::SourceFile(_) => mark::hit!(dont_recurse_in_outline_submodules), | |
135 | res | 134 | hir::ModuleSource::BlockExpr(_) => {} // inner items aren't runnable |
135 | } | ||
136 | } | ||
137 | } | ||
136 | } | 138 | } |
137 | 139 | ||
138 | pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> { | 140 | pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> { |
@@ -326,6 +328,7 @@ fn has_test_function_or_multiple_test_submodules( | |||
326 | #[cfg(test)] | 328 | #[cfg(test)] |
327 | mod tests { | 329 | mod tests { |
328 | use expect_test::{expect, Expect}; | 330 | use expect_test::{expect, Expect}; |
331 | use test_utils::mark; | ||
329 | 332 | ||
330 | use crate::fixture; | 333 | use crate::fixture; |
331 | 334 | ||
@@ -1050,4 +1053,25 @@ mod tests { | |||
1050 | "#]], | 1053 | "#]], |
1051 | ); | 1054 | ); |
1052 | } | 1055 | } |
1056 | |||
1057 | #[test] | ||
1058 | fn dont_recurse_in_outline_submodules() { | ||
1059 | mark::check!(dont_recurse_in_outline_submodules); | ||
1060 | check( | ||
1061 | r#" | ||
1062 | //- /lib.rs | ||
1063 | $0 | ||
1064 | mod m; | ||
1065 | //- /m.rs | ||
1066 | mod tests { | ||
1067 | #[test] | ||
1068 | fn t() {} | ||
1069 | } | ||
1070 | "#, | ||
1071 | &[], | ||
1072 | expect![[r#" | ||
1073 | [] | ||
1074 | "#]], | ||
1075 | ); | ||
1076 | } | ||
1053 | } | 1077 | } |
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs index e10d7c3a4..137c38c0d 100644 --- a/crates/ide/src/status.rs +++ b/crates/ide/src/status.rs | |||
@@ -38,6 +38,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String { | |||
38 | format_to!(buf, "{}\n", syntax_tree_stats(db)); | 38 | format_to!(buf, "{}\n", syntax_tree_stats(db)); |
39 | format_to!(buf, "{} (macros)\n", macro_syntax_tree_stats(db)); | 39 | format_to!(buf, "{} (macros)\n", macro_syntax_tree_stats(db)); |
40 | format_to!(buf, "{} total\n", memory_usage()); | 40 | format_to!(buf, "{} total\n", memory_usage()); |
41 | format_to!(buf, "\ncounts:\n{}", profile::countme::get_all()); | ||
41 | 42 | ||
42 | if let Some(file_id) = file_id { | 43 | if let Some(file_id) = file_id { |
43 | format_to!(buf, "\nfile info:\n"); | 44 | format_to!(buf, "\nfile info:\n"); |
@@ -60,6 +61,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String { | |||
60 | None => format_to!(buf, "does not belong to any crate"), | 61 | None => format_to!(buf, "does not belong to any crate"), |
61 | } | 62 | } |
62 | } | 63 | } |
64 | |||
63 | buf | 65 | buf |
64 | } | 66 | } |
65 | 67 | ||
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs index 63bff6376..8c67a0863 100644 --- a/crates/ide/src/syntax_highlighting/format.rs +++ b/crates/ide/src/syntax_highlighting/format.rs | |||
@@ -31,7 +31,7 @@ fn is_format_string(string: &ast::String) -> Option<()> { | |||
31 | let parent = string.syntax().parent(); | 31 | let parent = string.syntax().parent(); |
32 | 32 | ||
33 | let name = parent.parent().and_then(ast::MacroCall::cast)?.path()?.segment()?.name_ref()?; | 33 | let name = parent.parent().and_then(ast::MacroCall::cast)?.path()?.segment()?.name_ref()?; |
34 | if !matches!(name.text().as_str(), "format_args" | "format_args_nl") { | 34 | if !matches!(name.text(), "format_args" | "format_args_nl") { |
35 | return None; | 35 | return None; |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 281461493..8cdc3688f 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -116,7 +116,7 @@ pub(super) fn doc_comment(hl: &mut Highlights, node: &SyntaxNode) { | |||
116 | None => (), | 116 | None => (), |
117 | } | 117 | } |
118 | 118 | ||
119 | let line: &str = comment.text().as_str(); | 119 | let line: &str = comment.text(); |
120 | let range = comment.syntax().text_range(); | 120 | let range = comment.syntax().text_range(); |
121 | 121 | ||
122 | let mut pos = TextSize::of(comment.prefix()); | 122 | let mut pos = TextSize::of(comment.prefix()); |
diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs index c770a236b..9d9b6de7a 100644 --- a/crates/ide_db/src/apply_change.rs +++ b/crates/ide_db/src/apply_change.rs | |||
@@ -149,6 +149,7 @@ impl RootDatabase { | |||
149 | 149 | ||
150 | // DefDatabase | 150 | // DefDatabase |
151 | hir::db::ItemTreeQuery | 151 | hir::db::ItemTreeQuery |
152 | hir::db::BlockDefMapQuery | ||
152 | hir::db::CrateDefMapQueryQuery | 153 | hir::db::CrateDefMapQueryQuery |
153 | hir::db::StructDataQuery | 154 | hir::db::StructDataQuery |
154 | hir::db::UnionDataQuery | 155 | hir::db::UnionDataQuery |
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index d9875ffef..a8091dbee 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs | |||
@@ -343,7 +343,7 @@ impl NameRefClass { | |||
343 | hir::AssocItem::TypeAlias(it) => Some(*it), | 343 | hir::AssocItem::TypeAlias(it) => Some(*it), |
344 | _ => None, | 344 | _ => None, |
345 | }) | 345 | }) |
346 | .find(|alias| alias.name(sema.db).to_string() == **name_ref.text()) | 346 | .find(|alias| &alias.name(sema.db).to_string() == name_ref.text()) |
347 | { | 347 | { |
348 | return Some(NameRefClass::Definition(Definition::ModuleDef( | 348 | return Some(NameRefClass::Definition(Definition::ModuleDef( |
349 | ModuleDef::TypeAlias(ty), | 349 | ModuleDef::TypeAlias(ty), |
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index 877d4f1c7..fd4035198 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -507,7 +507,7 @@ impl ImportGroup { | |||
507 | PathSegmentKind::SelfKw => ImportGroup::ThisModule, | 507 | PathSegmentKind::SelfKw => ImportGroup::ThisModule, |
508 | PathSegmentKind::SuperKw => ImportGroup::SuperModule, | 508 | PathSegmentKind::SuperKw => ImportGroup::SuperModule, |
509 | PathSegmentKind::CrateKw => ImportGroup::ThisCrate, | 509 | PathSegmentKind::CrateKw => ImportGroup::ThisCrate, |
510 | PathSegmentKind::Name(name) => match name.text().as_str() { | 510 | PathSegmentKind::Name(name) => match name.text() { |
511 | "std" => ImportGroup::Std, | 511 | "std" => ImportGroup::Std, |
512 | "core" => ImportGroup::Std, | 512 | "core" => ImportGroup::Std, |
513 | _ => ImportGroup::ExternCrate, | 513 | _ => ImportGroup::ExternCrate, |
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 0ecb13a64..b9ba0aed5 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -228,6 +228,15 @@ impl Definition { | |||
228 | // so do nothing. | 228 | // so do nothing. |
229 | } | 229 | } |
230 | } | 230 | } |
231 | ModuleSource::BlockExpr(b) => { | ||
232 | if is_first { | ||
233 | let range = Some(b.syntax().text_range()); | ||
234 | res.insert(file_id, range); | ||
235 | } else { | ||
236 | // We have already added the enclosing file to the search scope, | ||
237 | // so do nothing. | ||
238 | } | ||
239 | } | ||
231 | ModuleSource::SourceFile(_) => { | 240 | ModuleSource::SourceFile(_) => { |
232 | res.insert(file_id, None); | 241 | res.insert(file_id, None); |
233 | } | 242 | } |
@@ -257,6 +266,7 @@ impl Definition { | |||
257 | let mut res = FxHashMap::default(); | 266 | let mut res = FxHashMap::default(); |
258 | let range = match module_src.value { | 267 | let range = match module_src.value { |
259 | ModuleSource::Module(m) => Some(m.syntax().text_range()), | 268 | ModuleSource::Module(m) => Some(m.syntax().text_range()), |
269 | ModuleSource::BlockExpr(b) => Some(b.syntax().text_range()), | ||
260 | ModuleSource::SourceFile(_) => None, | 270 | ModuleSource::SourceFile(_) => None, |
261 | }; | 271 | }; |
262 | res.insert(file_id, range); | 272 | res.insert(file_id, range); |
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs index 0aa6a0765..e954bd72e 100644 --- a/crates/ide_db/src/symbol_index.rs +++ b/crates/ide_db/src/symbol_index.rs | |||
@@ -191,7 +191,7 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil | |||
191 | 191 | ||
192 | let def_map = db.crate_def_map(krate); | 192 | let def_map = db.crate_def_map(krate); |
193 | let mut files = Vec::new(); | 193 | let mut files = Vec::new(); |
194 | let mut modules = vec![def_map.root]; | 194 | let mut modules = vec![def_map.root()]; |
195 | while let Some(module) = modules.pop() { | 195 | while let Some(module) = modules.pop() { |
196 | let data = &def_map[module]; | 196 | let data = &def_map[module]; |
197 | files.extend(data.origin.file_id()); | 197 | files.extend(data.origin.file_id()); |
@@ -209,7 +209,7 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil | |||
209 | query.search(&buf) | 209 | query.search(&buf) |
210 | } | 210 | } |
211 | 211 | ||
212 | pub fn index_resolve(db: &RootDatabase, name: &SmolStr) -> Vec<FileSymbol> { | 212 | pub fn index_resolve(db: &RootDatabase, name: &str) -> Vec<FileSymbol> { |
213 | let mut query = Query::new(name.to_string()); | 213 | let mut query = Query::new(name.to_string()); |
214 | query.exact(); | 214 | query.exact(); |
215 | query.limit(4); | 215 | query.limit(4); |
@@ -409,7 +409,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> { | |||
409 | fn decl<N: NameOwner>(node: N) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> { | 409 | fn decl<N: NameOwner>(node: N) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> { |
410 | let name = node.name()?; | 410 | let name = node.name()?; |
411 | let name_range = name.syntax().text_range(); | 411 | let name_range = name.syntax().text_range(); |
412 | let name = name.text().clone(); | 412 | let name = name.text().into(); |
413 | let ptr = SyntaxNodePtr::new(node.syntax()); | 413 | let ptr = SyntaxNodePtr::new(node.syntax()); |
414 | 414 | ||
415 | Some((name, ptr, name_range)) | 415 | Some((name, ptr, name_range)) |
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 51002e7b8..0cdc175be 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs | |||
@@ -507,7 +507,7 @@ impl SrcToken for SynToken { | |||
507 | } | 507 | } |
508 | } | 508 | } |
509 | fn to_text(&self) -> SmolStr { | 509 | fn to_text(&self) -> SmolStr { |
510 | self.token().text().clone() | 510 | self.token().text().into() |
511 | } | 511 | } |
512 | } | 512 | } |
513 | 513 | ||
@@ -682,10 +682,8 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
682 | self.text_pos += TextSize::of(text); | 682 | self.text_pos += TextSize::of(text); |
683 | } | 683 | } |
684 | 684 | ||
685 | let text = SmolStr::new(self.buf.as_str()); | 685 | self.inner.token(kind, self.buf.as_str()); |
686 | self.buf.clear(); | 686 | self.buf.clear(); |
687 | self.inner.token(kind, text); | ||
688 | |||
689 | // Add whitespace between adjoint puncts | 687 | // Add whitespace between adjoint puncts |
690 | let next = last.bump(); | 688 | let next = last.bump(); |
691 | if let ( | 689 | if let ( |
diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml index f7231c2b8..cc7da27f7 100644 --- a/crates/profile/Cargo.toml +++ b/crates/profile/Cargo.toml | |||
@@ -14,6 +14,7 @@ once_cell = "1.3.1" | |||
14 | cfg-if = "1" | 14 | cfg-if = "1" |
15 | libc = "0.2.73" | 15 | libc = "0.2.73" |
16 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 16 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
17 | countme = { version = "2.0.0-pre.2", features = ["enable"] } | ||
17 | jemalloc-ctl = { version = "0.3.3", optional = true } | 18 | jemalloc-ctl = { version = "0.3.3", optional = true } |
18 | 19 | ||
19 | [target.'cfg(target_os = "linux")'.dependencies] | 20 | [target.'cfg(target_os = "linux")'.dependencies] |
diff --git a/crates/profile/src/hprof.rs b/crates/profile/src/hprof.rs index 8957ea016..29d2ed518 100644 --- a/crates/profile/src/hprof.rs +++ b/crates/profile/src/hprof.rs | |||
@@ -3,6 +3,7 @@ use once_cell::sync::Lazy; | |||
3 | use std::{ | 3 | use std::{ |
4 | cell::RefCell, | 4 | cell::RefCell, |
5 | collections::{BTreeMap, HashSet}, | 5 | collections::{BTreeMap, HashSet}, |
6 | env, | ||
6 | io::{stderr, Write}, | 7 | io::{stderr, Write}, |
7 | sync::{ | 8 | sync::{ |
8 | atomic::{AtomicBool, Ordering}, | 9 | atomic::{AtomicBool, Ordering}, |
@@ -18,7 +19,8 @@ use crate::tree::{Idx, Tree}; | |||
18 | /// env RA_PROFILE=foo|bar|baz // enabled only selected entries | 19 | /// env RA_PROFILE=foo|bar|baz // enabled only selected entries |
19 | /// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms | 20 | /// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms |
20 | pub fn init() { | 21 | pub fn init() { |
21 | let spec = std::env::var("RA_PROFILE").unwrap_or_default(); | 22 | countme::enable(env::var("RA_COUNT").is_ok()); |
23 | let spec = env::var("RA_PROFILE").unwrap_or_default(); | ||
22 | init_from(&spec); | 24 | init_from(&spec); |
23 | } | 25 | } |
24 | 26 | ||
diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs index aa6ccc36c..79dba47d5 100644 --- a/crates/profile/src/lib.rs +++ b/crates/profile/src/lib.rs | |||
@@ -15,6 +15,13 @@ pub use crate::{ | |||
15 | stop_watch::{StopWatch, StopWatchSpan}, | 15 | stop_watch::{StopWatch, StopWatchSpan}, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub use countme; | ||
19 | /// Include `_c: Count<Self>` field in important structs to count them. | ||
20 | /// | ||
21 | /// To view the counts, run with `RA_COUNT=1`. The overhead of disabled count is | ||
22 | /// almost zero. | ||
23 | pub use countme::Count; | ||
24 | |||
18 | thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false)); | 25 | thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false)); |
19 | 26 | ||
20 | /// Allows to check if the current code is withing some dynamic scope, can be | 27 | /// Allows to check if the current code is withing some dynamic scope, can be |
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs new file mode 100644 index 000000000..cf32995e0 --- /dev/null +++ b/crates/project_model/src/build_data.rs | |||
@@ -0,0 +1,206 @@ | |||
1 | //! Handles build script specific information | ||
2 | |||
3 | use std::{ | ||
4 | ffi::OsStr, | ||
5 | io::BufReader, | ||
6 | path::{Path, PathBuf}, | ||
7 | process::{Command, Stdio}, | ||
8 | }; | ||
9 | |||
10 | use anyhow::Result; | ||
11 | use cargo_metadata::{BuildScript, Message, Package, PackageId}; | ||
12 | use itertools::Itertools; | ||
13 | use paths::{AbsPath, AbsPathBuf}; | ||
14 | use rustc_hash::FxHashMap; | ||
15 | use stdx::JodChild; | ||
16 | |||
17 | use crate::{cfg_flag::CfgFlag, CargoConfig}; | ||
18 | |||
19 | #[derive(Debug, Clone, Default)] | ||
20 | pub(crate) struct BuildDataMap { | ||
21 | data: FxHashMap<PackageId, BuildData>, | ||
22 | } | ||
23 | #[derive(Debug, Clone, Default, PartialEq, Eq)] | ||
24 | pub struct BuildData { | ||
25 | /// List of config flags defined by this package's build script | ||
26 | pub cfgs: Vec<CfgFlag>, | ||
27 | /// List of cargo-related environment variables with their value | ||
28 | /// | ||
29 | /// If the package has a build script which defines environment variables, | ||
30 | /// they can also be found here. | ||
31 | pub envs: Vec<(String, String)>, | ||
32 | /// Directory where a build script might place its output | ||
33 | pub out_dir: Option<AbsPathBuf>, | ||
34 | /// Path to the proc-macro library file if this package exposes proc-macros | ||
35 | pub proc_macro_dylib_path: Option<AbsPathBuf>, | ||
36 | } | ||
37 | |||
38 | impl BuildDataMap { | ||
39 | pub(crate) fn new( | ||
40 | cargo_toml: &AbsPath, | ||
41 | cargo_features: &CargoConfig, | ||
42 | packages: &Vec<Package>, | ||
43 | progress: &dyn Fn(String), | ||
44 | ) -> Result<BuildDataMap> { | ||
45 | let mut cmd = Command::new(toolchain::cargo()); | ||
46 | cmd.args(&["check", "--workspace", "--message-format=json", "--manifest-path"]) | ||
47 | .arg(cargo_toml.as_ref()); | ||
48 | |||
49 | // --all-targets includes tests, benches and examples in addition to the | ||
50 | // default lib and bins. This is an independent concept from the --targets | ||
51 | // flag below. | ||
52 | cmd.arg("--all-targets"); | ||
53 | |||
54 | if let Some(target) = &cargo_features.target { | ||
55 | cmd.args(&["--target", target]); | ||
56 | } | ||
57 | |||
58 | if cargo_features.all_features { | ||
59 | cmd.arg("--all-features"); | ||
60 | } else { | ||
61 | if cargo_features.no_default_features { | ||
62 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` | ||
63 | // https://github.com/oli-obk/cargo_metadata/issues/79 | ||
64 | cmd.arg("--no-default-features"); | ||
65 | } | ||
66 | if !cargo_features.features.is_empty() { | ||
67 | cmd.arg("--features"); | ||
68 | cmd.arg(cargo_features.features.join(" ")); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); | ||
73 | |||
74 | let mut child = cmd.spawn().map(JodChild)?; | ||
75 | let child_stdout = child.stdout.take().unwrap(); | ||
76 | let stdout = BufReader::new(child_stdout); | ||
77 | |||
78 | let mut res = BuildDataMap::default(); | ||
79 | for message in cargo_metadata::Message::parse_stream(stdout) { | ||
80 | if let Ok(message) = message { | ||
81 | match message { | ||
82 | Message::BuildScriptExecuted(BuildScript { | ||
83 | package_id, | ||
84 | out_dir, | ||
85 | cfgs, | ||
86 | env, | ||
87 | .. | ||
88 | }) => { | ||
89 | let cfgs = { | ||
90 | let mut acc = Vec::new(); | ||
91 | for cfg in cfgs { | ||
92 | match cfg.parse::<CfgFlag>() { | ||
93 | Ok(it) => acc.push(it), | ||
94 | Err(err) => { | ||
95 | anyhow::bail!("invalid cfg from cargo-metadata: {}", err) | ||
96 | } | ||
97 | }; | ||
98 | } | ||
99 | acc | ||
100 | }; | ||
101 | let res = res.data.entry(package_id.clone()).or_default(); | ||
102 | // cargo_metadata crate returns default (empty) path for | ||
103 | // older cargos, which is not absolute, so work around that. | ||
104 | if out_dir != PathBuf::default() { | ||
105 | let out_dir = AbsPathBuf::assert(out_dir); | ||
106 | res.out_dir = Some(out_dir); | ||
107 | res.cfgs = cfgs; | ||
108 | } | ||
109 | |||
110 | res.envs = env; | ||
111 | } | ||
112 | Message::CompilerArtifact(message) => { | ||
113 | progress(format!("metadata {}", message.target.name)); | ||
114 | |||
115 | if message.target.kind.contains(&"proc-macro".to_string()) { | ||
116 | let package_id = message.package_id; | ||
117 | // Skip rmeta file | ||
118 | if let Some(filename) = | ||
119 | message.filenames.iter().find(|name| is_dylib(name)) | ||
120 | { | ||
121 | let filename = AbsPathBuf::assert(filename.clone()); | ||
122 | let res = res.data.entry(package_id.clone()).or_default(); | ||
123 | res.proc_macro_dylib_path = Some(filename); | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | Message::CompilerMessage(message) => { | ||
128 | progress(message.target.name.clone()); | ||
129 | } | ||
130 | Message::Unknown => (), | ||
131 | Message::BuildFinished(_) => {} | ||
132 | Message::TextLine(_) => {} | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | res.inject_cargo_env(packages); | ||
137 | Ok(res) | ||
138 | } | ||
139 | |||
140 | pub(crate) fn with_cargo_env(packages: &Vec<Package>) -> Self { | ||
141 | let mut res = Self::default(); | ||
142 | res.inject_cargo_env(packages); | ||