| author | bors <bors@rust-lang.org> 2026-07-07 08:25:59 UTC |
| committer | bors <bors@rust-lang.org> 2026-07-07 08:25:59 UTC |
| log | f10db292a3733b5c67c8da8c7661195ff4b05774 |
| tree | fd7846c9f264a9adf3d766d0d07e552ebbdcf10c |
| parent | bcd9ae8b77e8a1d03d73b51f1fd9cb99565cfdc5 |
| parent | 75e1b3d341a2736043062c7b6be17a2bf9b380f1 |
`rust-analyzer` subtree update
Subtree update of `rust-analyzer` to https://github.com/rust-lang/rust-analyzer/commit/7ae18ed96a90dbb8972fc886321651fdda80f7de.
Created using https://github.com/rust-lang/josh-sync.
r? @ghost155 files changed, 4139 insertions(+), 2760 deletions(-)
src/tools/rust-analyzer/AI_POLICY.md+6| ... | ... | @@ -23,6 +23,12 @@ We understand that AI is useful when communicating as a non-native English speak |
| 23 | 23 | If you are using AI to edit your comments for this purpose, please take the time to ensure it reflects your own voice and ideas. |
| 24 | 24 | If using AI for translation, we recommend writing in your native language and including the AI translation in a quote block. |
| 25 | 25 | |
| 26 | **AI should not be used to author code for E-easy+E-has-instructions issues**. | |
| 27 | ||
| 28 | E-easy issues are usually easier for maintainers to just fix directly than write instructions for. When we write instructions for them, we do that because this provides an opportunity for newcomers to learn the codebase. Using AI to author the code for you annihilates this benefit. | |
| 29 | ||
| 30 | AI *may* be used to understand the codebase for E-easy+E-has-instructions contributions, but not to write any code. | |
| 31 | ||
| 26 | 32 | This policy was adapted from [uv's AI policy]. |
| 27 | 33 | |
| 28 | 34 | [uv's AI policy]: https://github.com/astral-sh/.github/blob/c5187e200db51bfe11d56e13053d29bd3793fdd8/AI_POLICY.md |
src/tools/rust-analyzer/Cargo.lock+71-162| ... | ... | @@ -65,15 +65,6 @@ version = "0.7.6" |
| 65 | 65 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 66 | 66 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" |
| 67 | 67 | |
| 68 | [[package]] | |
| 69 | name = "atomic-polyfill" | |
| 70 | version = "1.0.3" | |
| 71 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 72 | checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" | |
| 73 | dependencies = [ | |
| 74 | "critical-section", | |
| 75 | ] | |
| 76 | ||
| 77 | 68 | [[package]] |
| 78 | 69 | name = "autocfg" |
| 79 | 70 | version = "1.5.1" |
| ... | ... | @@ -137,12 +128,6 @@ version = "0.8.0" |
| 137 | 128 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 138 | 129 | checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" |
| 139 | 130 | |
| 140 | [[package]] | |
| 141 | name = "bitflags" | |
| 142 | version = "1.3.2" | |
| 143 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 144 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | |
| 145 | ||
| 146 | 131 | [[package]] |
| 147 | 132 | name = "bitflags" |
| 148 | 133 | version = "2.12.1" |
| ... | ... | @@ -180,12 +165,6 @@ version = "3.20.3" |
| 180 | 165 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 181 | 166 | checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" |
| 182 | 167 | |
| 183 | [[package]] | |
| 184 | name = "byteorder" | |
| 185 | version = "1.5.0" | |
| 186 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 187 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" | |
| 188 | ||
| 189 | 168 | [[package]] |
| 190 | 169 | name = "bytes" |
| 191 | 170 | version = "1.11.1" |
| ... | ... | @@ -384,12 +363,6 @@ dependencies = [ |
| 384 | 363 | "itertools 0.13.0", |
| 385 | 364 | ] |
| 386 | 365 | |
| 387 | [[package]] | |
| 388 | name = "critical-section" | |
| 389 | version = "1.2.0" | |
| 390 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 391 | checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" | |
| 392 | ||
| 393 | 366 | [[package]] |
| 394 | 367 | name = "crossbeam-channel" |
| 395 | 368 | version = "0.5.15" |
| ... | ... | @@ -538,7 +511,7 @@ version = "0.3.1" |
| 538 | 511 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 539 | 512 | checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" |
| 540 | 513 | dependencies = [ |
| 541 | "bitflags 2.12.1", | |
| 514 | "bitflags", | |
| 542 | 515 | "block2", |
| 543 | 516 | "libc", |
| 544 | 517 | "objc2", |
| ... | ... | @@ -724,6 +697,17 @@ dependencies = [ |
| 724 | 697 | "slab", |
| 725 | 698 | ] |
| 726 | 699 | |
| 700 | [[package]] | |
| 701 | name = "gen-lsp-types" | |
| 702 | version = "0.4.0" | |
| 703 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 704 | checksum = "c5b8ec601e62362b666a3def1fed667ee87b10a4507402618376d142a05373c6" | |
| 705 | dependencies = [ | |
| 706 | "serde", | |
| 707 | "serde_json", | |
| 708 | "url", | |
| 709 | ] | |
| 710 | ||
| 727 | 711 | [[package]] |
| 728 | 712 | name = "getrandom" |
| 729 | 713 | version = "0.2.17" |
| ... | ... | @@ -777,15 +761,6 @@ dependencies = [ |
| 777 | 761 | "zerocopy", |
| 778 | 762 | ] |
| 779 | 763 | |
| 780 | [[package]] | |
| 781 | name = "hash32" | |
| 782 | version = "0.2.1" | |
| 783 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 784 | checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" | |
| 785 | dependencies = [ | |
| 786 | "byteorder", | |
| 787 | ] | |
| 788 | ||
| 789 | 764 | [[package]] |
| 790 | 765 | name = "hashbrown" |
| 791 | 766 | version = "0.14.5" |
| ... | ... | @@ -801,15 +776,6 @@ dependencies = [ |
| 801 | 776 | "foldhash 0.1.5", |
| 802 | 777 | ] |
| 803 | 778 | |
| 804 | [[package]] | |
| 805 | name = "hashbrown" | |
| 806 | version = "0.16.1" | |
| 807 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 808 | checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" | |
| 809 | dependencies = [ | |
| 810 | "foldhash 0.2.0", | |
| 811 | ] | |
| 812 | ||
| 813 | 779 | [[package]] |
| 814 | 780 | name = "hashbrown" |
| 815 | 781 | version = "0.17.1" |
| ... | ... | @@ -823,25 +789,11 @@ dependencies = [ |
| 823 | 789 | |
| 824 | 790 | [[package]] |
| 825 | 791 | name = "hashlink" |
| 826 | version = "0.11.0" | |
| 792 | version = "0.12.0" | |
| 827 | 793 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 828 | checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" | |
| 794 | checksum = "a5081f264ed7adee96ea4b4778b6bb9da0a7228b084587aa3bd3ff05da7c5a3b" | |
| 829 | 795 | dependencies = [ |
| 830 | "hashbrown 0.16.1", | |
| 831 | ] | |
| 832 | ||
| 833 | [[package]] | |
| 834 | name = "heapless" | |
| 835 | version = "0.7.17" | |
| 836 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 837 | checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" | |
| 838 | dependencies = [ | |
| 839 | "atomic-polyfill", | |
| 840 | "hash32", | |
| 841 | "rustc_version", | |
| 842 | "serde", | |
| 843 | "spin", | |
| 844 | "stable_deref_trait", | |
| 796 | "hashbrown 0.17.1", | |
| 845 | 797 | ] |
| 846 | 798 | |
| 847 | 799 | [[package]] |
| ... | ... | @@ -869,7 +821,7 @@ dependencies = [ |
| 869 | 821 | "hir-expand", |
| 870 | 822 | "hir-ty", |
| 871 | 823 | "intern", |
| 872 | "itertools 0.14.0", | |
| 824 | "itertools 0.15.0", | |
| 873 | 825 | "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", |
| 874 | 826 | "ra-ap-rustc_type_ir", |
| 875 | 827 | "rustc-hash 2.1.2", |
| ... | ... | @@ -894,7 +846,7 @@ version = "0.0.0" |
| 894 | 846 | dependencies = [ |
| 895 | 847 | "arrayvec", |
| 896 | 848 | "base-db", |
| 897 | "bitflags 2.12.1", | |
| 849 | "bitflags", | |
| 898 | 850 | "cfg", |
| 899 | 851 | "cov-mark", |
| 900 | 852 | "drop_bomb", |
| ... | ... | @@ -904,7 +856,7 @@ dependencies = [ |
| 904 | 856 | "hir-expand", |
| 905 | 857 | "indexmap", |
| 906 | 858 | "intern", |
| 907 | "itertools 0.14.0", | |
| 859 | "itertools 0.15.0", | |
| 908 | 860 | "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", |
| 909 | 861 | "query-group-macro", |
| 910 | 862 | "ra-ap-rustc_abi", |
| ... | ... | @@ -936,7 +888,7 @@ dependencies = [ |
| 936 | 888 | "either", |
| 937 | 889 | "expect-test", |
| 938 | 890 | "intern", |
| 939 | "itertools 0.14.0", | |
| 891 | "itertools 0.15.0", | |
| 940 | 892 | "mbe", |
| 941 | 893 | "parser", |
| 942 | 894 | "query-group-macro", |
| ... | ... | @@ -960,7 +912,7 @@ version = "0.0.0" |
| 960 | 912 | dependencies = [ |
| 961 | 913 | "arrayvec", |
| 962 | 914 | "base-db", |
| 963 | "bitflags 2.12.1", | |
| 915 | "bitflags", | |
| 964 | 916 | "cov-mark", |
| 965 | 917 | "either", |
| 966 | 918 | "ena", |
| ... | ... | @@ -969,7 +921,7 @@ dependencies = [ |
| 969 | 921 | "hir-expand", |
| 970 | 922 | "indexmap", |
| 971 | 923 | "intern", |
| 972 | "itertools 0.14.0", | |
| 924 | "itertools 0.15.0", | |
| 973 | 925 | "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", |
| 974 | 926 | "macros", |
| 975 | 927 | "oorandom", |
| ... | ... | @@ -1106,7 +1058,7 @@ dependencies = [ |
| 1106 | 1058 | "ide-db", |
| 1107 | 1059 | "ide-diagnostics", |
| 1108 | 1060 | "ide-ssr", |
| 1109 | "itertools 0.14.0", | |
| 1061 | "itertools 0.15.0", | |
| 1110 | 1062 | "macros", |
| 1111 | 1063 | "nohash-hasher", |
| 1112 | 1064 | "oorandom", |
| ... | ... | @@ -1135,7 +1087,7 @@ dependencies = [ |
| 1135 | 1087 | "expect-test", |
| 1136 | 1088 | "hir", |
| 1137 | 1089 | "ide-db", |
| 1138 | "itertools 0.14.0", | |
| 1090 | "itertools 0.15.0", | |
| 1139 | 1091 | "smallvec", |
| 1140 | 1092 | "stdx", |
| 1141 | 1093 | "syntax", |
| ... | ... | @@ -1153,7 +1105,7 @@ dependencies = [ |
| 1153 | 1105 | "expect-test", |
| 1154 | 1106 | "hir", |
| 1155 | 1107 | "ide-db", |
| 1156 | "itertools 0.14.0", | |
| 1108 | "itertools 0.15.0", | |
| 1157 | 1109 | "macros", |
| 1158 | 1110 | "smallvec", |
| 1159 | 1111 | "stdx", |
| ... | ... | @@ -1169,14 +1121,14 @@ version = "0.0.0" |
| 1169 | 1121 | dependencies = [ |
| 1170 | 1122 | "arrayvec", |
| 1171 | 1123 | "base-db", |
| 1172 | "bitflags 2.12.1", | |
| 1124 | "bitflags", | |
| 1173 | 1125 | "cov-mark", |
| 1174 | 1126 | "crossbeam-channel", |
| 1175 | 1127 | "either", |
| 1176 | 1128 | "expect-test", |
| 1177 | 1129 | "fst", |
| 1178 | 1130 | "hir", |
| 1179 | "itertools 0.14.0", | |
| 1131 | "itertools 0.15.0", | |
| 1180 | 1132 | "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", |
| 1181 | 1133 | "macros", |
| 1182 | 1134 | "memchr", |
| ... | ... | @@ -1208,7 +1160,7 @@ dependencies = [ |
| 1208 | 1160 | "expect-test", |
| 1209 | 1161 | "hir", |
| 1210 | 1162 | "ide-db", |
| 1211 | "itertools 0.14.0", | |
| 1163 | "itertools 0.15.0", | |
| 1212 | 1164 | "paths", |
| 1213 | 1165 | "serde_json", |
| 1214 | 1166 | "stdx", |
| ... | ... | @@ -1226,7 +1178,7 @@ dependencies = [ |
| 1226 | 1178 | "expect-test", |
| 1227 | 1179 | "hir", |
| 1228 | 1180 | "ide-db", |
| 1229 | "itertools 0.14.0", | |
| 1181 | "itertools 0.15.0", | |
| 1230 | 1182 | "parser", |
| 1231 | 1183 | "syntax", |
| 1232 | 1184 | "test-fixture", |
| ... | ... | @@ -1273,7 +1225,7 @@ version = "0.11.2" |
| 1273 | 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1274 | 1226 | checksum = "533e68a5842e734946fe159fb03fc9bbbb254f590dd0d8ad321ae5ff7beca2c1" |
| 1275 | 1227 | dependencies = [ |
| 1276 | "bitflags 2.12.1", | |
| 1228 | "bitflags", | |
| 1277 | 1229 | "inotify-sys", |
| 1278 | 1230 | "libc", |
| 1279 | 1231 | ] |
| ... | ... | @@ -1328,9 +1280,9 @@ dependencies = [ |
| 1328 | 1280 | |
| 1329 | 1281 | [[package]] |
| 1330 | 1282 | name = "itertools" |
| 1331 | version = "0.14.0" | |
| 1283 | version = "0.15.0" | |
| 1332 | 1284 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1333 | checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" | |
| 1285 | checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" | |
| 1334 | 1286 | dependencies = [ |
| 1335 | 1287 | "either", |
| 1336 | 1288 | ] |
| ... | ... | @@ -1375,7 +1327,7 @@ version = "1.1.2" |
| 1375 | 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1376 | 1328 | checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" |
| 1377 | 1329 | dependencies = [ |
| 1378 | "bitflags 2.12.1", | |
| 1330 | "bitflags", | |
| 1379 | 1331 | "libc", |
| 1380 | 1332 | ] |
| 1381 | 1333 | |
| ... | ... | @@ -1465,7 +1417,7 @@ dependencies = [ |
| 1465 | 1417 | "hir-expand", |
| 1466 | 1418 | "ide-db", |
| 1467 | 1419 | "intern", |
| 1468 | "itertools 0.14.0", | |
| 1420 | "itertools 0.15.0", | |
| 1469 | 1421 | "proc-macro-api", |
| 1470 | 1422 | "project-model", |
| 1471 | 1423 | "span", |
| ... | ... | @@ -1493,43 +1445,30 @@ checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" |
| 1493 | 1445 | [[package]] |
| 1494 | 1446 | name = "lsp-server" |
| 1495 | 1447 | version = "0.7.9" |
| 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1449 | checksum = "7d6ada348dbc2703cbe7637b2dda05cff84d3da2819c24abcb305dd613e0ba2e" | |
| 1496 | 1450 | dependencies = [ |
| 1497 | "anyhow", | |
| 1498 | 1451 | "crossbeam-channel", |
| 1499 | "ctrlc", | |
| 1500 | 1452 | "log", |
| 1501 | "lsp-types", | |
| 1502 | "rustc-hash 2.1.2", | |
| 1503 | 1453 | "serde", |
| 1504 | 1454 | "serde_derive", |
| 1505 | 1455 | "serde_json", |
| 1506 | "toolchain", | |
| 1507 | 1456 | ] |
| 1508 | 1457 | |
| 1509 | 1458 | [[package]] |
| 1510 | 1459 | name = "lsp-server" |
| 1511 | version = "0.7.9" | |
| 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1513 | checksum = "7d6ada348dbc2703cbe7637b2dda05cff84d3da2819c24abcb305dd613e0ba2e" | |
| 1460 | version = "0.8.0" | |
| 1514 | 1461 | dependencies = [ |
| 1462 | "anyhow", | |
| 1515 | 1463 | "crossbeam-channel", |
| 1464 | "ctrlc", | |
| 1465 | "gen-lsp-types", | |
| 1516 | 1466 | "log", |
| 1467 | "rustc-hash 2.1.2", | |
| 1517 | 1468 | "serde", |
| 1518 | 1469 | "serde_derive", |
| 1519 | 1470 | "serde_json", |
| 1520 | ] | |
| 1521 | ||
| 1522 | [[package]] | |
| 1523 | name = "lsp-types" | |
| 1524 | version = "0.95.0" | |
| 1525 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1526 | checksum = "158c1911354ef73e8fe42da6b10c0484cb65c7f1007f28022e847706c1ab6984" | |
| 1527 | dependencies = [ | |
| 1528 | "bitflags 1.3.2", | |
| 1529 | "serde", | |
| 1530 | "serde_json", | |
| 1531 | "serde_repr", | |
| 1532 | "url", | |
| 1471 | "toolchain", | |
| 1533 | 1472 | ] |
| 1534 | 1473 | |
| 1535 | 1474 | [[package]] |
| ... | ... | @@ -1547,7 +1486,7 @@ name = "mbe" |
| 1547 | 1486 | version = "0.0.0" |
| 1548 | 1487 | dependencies = [ |
| 1549 | 1488 | "arrayvec", |
| 1550 | "bitflags 2.12.1", | |
| 1489 | "bitflags", | |
| 1551 | 1490 | "cov-mark", |
| 1552 | 1491 | "expect-test", |
| 1553 | 1492 | "intern", |
| ... | ... | @@ -1631,7 +1570,7 @@ version = "0.31.3" |
| 1631 | 1570 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1632 | 1571 | checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" |
| 1633 | 1572 | dependencies = [ |
| 1634 | "bitflags 2.12.1", | |
| 1573 | "bitflags", | |
| 1635 | 1574 | "cfg-if", |
| 1636 | 1575 | "cfg_aliases", |
| 1637 | 1576 | "libc", |
| ... | ... | @@ -1649,7 +1588,7 @@ version = "8.2.0" |
| 1649 | 1588 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1650 | 1589 | checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" |
| 1651 | 1590 | dependencies = [ |
| 1652 | "bitflags 2.12.1", | |
| 1591 | "bitflags", | |
| 1653 | 1592 | "fsevent-sys", |
| 1654 | 1593 | "inotify", |
| 1655 | 1594 | "kqueue", |
| ... | ... | @@ -1667,7 +1606,7 @@ version = "2.1.0" |
| 1667 | 1606 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1668 | 1607 | checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" |
| 1669 | 1608 | dependencies = [ |
| 1670 | "bitflags 2.12.1", | |
| 1609 | "bitflags", | |
| 1671 | 1610 | ] |
| 1672 | 1611 | |
| 1673 | 1612 | [[package]] |
| ... | ... | @@ -1890,7 +1829,6 @@ dependencies = [ |
| 1890 | 1829 | "cobs", |
| 1891 | 1830 | "embedded-io 0.4.0", |
| 1892 | 1831 | "embedded-io 0.6.1", |
| 1893 | "heapless", | |
| 1894 | 1832 | "serde", |
| 1895 | 1833 | ] |
| 1896 | 1834 | |
| ... | ... | @@ -2025,7 +1963,7 @@ dependencies = [ |
| 2025 | 1963 | "cfg", |
| 2026 | 1964 | "expect-test", |
| 2027 | 1965 | "intern", |
| 2028 | "itertools 0.14.0", | |
| 1966 | "itertools 0.15.0", | |
| 2029 | 1967 | "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", |
| 2030 | 1968 | "paths", |
| 2031 | 1969 | "rustc-hash 2.1.2", |
| ... | ... | @@ -2050,7 +1988,7 @@ checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" |
| 2050 | 1988 | dependencies = [ |
| 2051 | 1989 | "bit-set", |
| 2052 | 1990 | "bit-vec", |
| 2053 | "bitflags 2.12.1", | |
| 1991 | "bitflags", | |
| 2054 | 1992 | "num-traits", |
| 2055 | 1993 | "rand", |
| 2056 | 1994 | "rand_chacha", |
| ... | ... | @@ -2087,7 +2025,7 @@ version = "0.9.6" |
| 2087 | 2025 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2088 | 2026 | checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" |
| 2089 | 2027 | dependencies = [ |
| 2090 | "bitflags 2.12.1", | |
| 2028 | "bitflags", | |
| 2091 | 2029 | "memchr", |
| 2092 | 2030 | "unicase", |
| 2093 | 2031 | ] |
| ... | ... | @@ -2146,7 +2084,7 @@ version = "0.165.0" |
| 2146 | 2084 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2147 | 2085 | checksum = "2f25a779e21ca3bba6795193b16508c8ab159f96ee4b07349893fd272065b525" |
| 2148 | 2086 | dependencies = [ |
| 2149 | "bitflags 2.12.1", | |
| 2087 | "bitflags", | |
| 2150 | 2088 | "ra-ap-rustc_hashes", |
| 2151 | 2089 | "ra-ap-rustc_index", |
| 2152 | 2090 | "tracing", |
| ... | ... | @@ -2241,7 +2179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2241 | 2179 | checksum = "8c5d9a4d3e7bee7313599bc6d794037247ac0165f03857379cf4fc3097199e05" |
| 2242 | 2180 | dependencies = [ |
| 2243 | 2181 | "arrayvec", |
| 2244 | "bitflags 2.12.1", | |
| 2182 | "bitflags", | |
| 2245 | 2183 | "derive-where", |
| 2246 | 2184 | "ena", |
| 2247 | 2185 | "indexmap", |
| ... | ... | @@ -2331,7 +2269,7 @@ version = "0.5.18" |
| 2331 | 2269 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2332 | 2270 | checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" |
| 2333 | 2271 | dependencies = [ |
| 2334 | "bitflags 2.12.1", | |
| 2272 | "bitflags", | |
| 2335 | 2273 | ] |
| 2336 | 2274 | |
| 2337 | 2275 | [[package]] |
| ... | ... | @@ -2376,9 +2314,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" |
| 2376 | 2314 | |
| 2377 | 2315 | [[package]] |
| 2378 | 2316 | name = "rowan" |
| 2379 | version = "0.15.18" | |
| 2317 | version = "0.15.19" | |
| 2380 | 2318 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2381 | checksum = "62f509095fc8cc0c8c8564016771d458079c11a8d857e65861f045145c0d3208" | |
| 2319 | checksum = "a2441aaccb50f4267d4f0f58b21e0138e96a449f361ed57a2673a83c9bca0772" | |
| 2382 | 2320 | dependencies = [ |
| 2383 | 2321 | "countme", |
| 2384 | 2322 | "hashbrown 0.14.5", |
| ... | ... | @@ -2400,6 +2338,7 @@ dependencies = [ |
| 2400 | 2338 | "dirs", |
| 2401 | 2339 | "dissimilar", |
| 2402 | 2340 | "expect-test", |
| 2341 | "gen-lsp-types", | |
| 2403 | 2342 | "hir", |
| 2404 | 2343 | "hir-def", |
| 2405 | 2344 | "hir-ty", |
| ... | ... | @@ -2409,10 +2348,9 @@ dependencies = [ |
| 2409 | 2348 | "ide-ssr", |
| 2410 | 2349 | "indexmap", |
| 2411 | 2350 | "intern", |
| 2412 | "itertools 0.14.0", | |
| 2351 | "itertools 0.15.0", | |
| 2413 | 2352 | "load-cargo", |
| 2414 | "lsp-server 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", | |
| 2415 | "lsp-types", | |
| 2353 | "lsp-server 0.7.9", | |
| 2416 | 2354 | "memchr", |
| 2417 | 2355 | "mimalloc", |
| 2418 | 2356 | "num_cpus", |
| ... | ... | @@ -2490,26 +2428,17 @@ version = "0.2.3+llvm-462a31f5a5ab" |
| 2490 | 2428 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2491 | 2429 | checksum = "486c2179b4796f65bfe2ee33679acf0927ac83ecf583ad6c91c3b4570911b9ad" |
| 2492 | 2430 | dependencies = [ |
| 2493 | "bitflags 2.12.1", | |
| 2431 | "bitflags", | |
| 2494 | 2432 | "smallvec", |
| 2495 | 2433 | ] |
| 2496 | 2434 | |
| 2497 | [[package]] | |
| 2498 | name = "rustc_version" | |
| 2499 | version = "0.4.1" | |
| 2500 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2501 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" | |
| 2502 | dependencies = [ | |
| 2503 | "semver", | |
| 2504 | ] | |
| 2505 | ||
| 2506 | 2435 | [[package]] |
| 2507 | 2436 | name = "rustix" |
| 2508 | 2437 | version = "1.1.4" |
| 2509 | 2438 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2510 | 2439 | checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" |
| 2511 | 2440 | dependencies = [ |
| 2512 | "bitflags 2.12.1", | |
| 2441 | "bitflags", | |
| 2513 | 2442 | "errno", |
| 2514 | 2443 | "libc", |
| 2515 | 2444 | "linux-raw-sys", |
| ... | ... | @@ -2536,9 +2465,9 @@ dependencies = [ |
| 2536 | 2465 | |
| 2537 | 2466 | [[package]] |
| 2538 | 2467 | name = "salsa" |
| 2539 | version = "0.27.0" | |
| 2468 | version = "0.27.2" | |
| 2540 | 2469 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2541 | checksum = "adfc1e32b8d1a486e3a45a5480fb5dca7912f49262a8916a67378064da4fe1ab" | |
| 2470 | checksum = "ffbaab832e2ea754afda4a738f987dd1e8bd30c9e5d8c981ee6a3934386095e2" | |
| 2542 | 2471 | dependencies = [ |
| 2543 | 2472 | "boxcar", |
| 2544 | 2473 | "crossbeam-queue", |
| ... | ... | @@ -2562,15 +2491,15 @@ dependencies = [ |
| 2562 | 2491 | |
| 2563 | 2492 | [[package]] |
| 2564 | 2493 | name = "salsa-macro-rules" |
| 2565 | version = "0.27.0" | |
| 2494 | version = "0.27.2" | |
| 2566 | 2495 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2567 | checksum = "67dad477a3e3a484a7c2311c1d25160fb270214981be24022de7de8a206a3300" | |
| 2496 | checksum = "de6872462ac73d39969a836273c24163e6a26a4e08f5114fcd80e25af30ea9c6" | |
| 2568 | 2497 | |
| 2569 | 2498 | [[package]] |
| 2570 | 2499 | name = "salsa-macros" |
| 2571 | version = "0.27.0" | |
| 2500 | version = "0.27.2" | |
| 2572 | 2501 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2573 | checksum = "943f70e101fb3bd599960e79e719e70d85142730e5b45f3269246086ed218562" | |
| 2502 | checksum = "76bc78ffaf65b1a9175818592c5130aa10b1bb245a905722fd4db87cea8a8457" | |
| 2574 | 2503 | dependencies = [ |
| 2575 | 2504 | "proc-macro2", |
| 2576 | 2505 | "quote", |
| ... | ... | @@ -2644,9 +2573,9 @@ dependencies = [ |
| 2644 | 2573 | |
| 2645 | 2574 | [[package]] |
| 2646 | 2575 | name = "serde_json" |
| 2647 | version = "1.0.150" | |
| 2576 | version = "1.0.149" | |
| 2648 | 2577 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2649 | checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" | |
| 2578 | checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" | |
| 2650 | 2579 | dependencies = [ |
| 2651 | 2580 | "indexmap", |
| 2652 | 2581 | "itoa", |
| ... | ... | @@ -2656,17 +2585,6 @@ dependencies = [ |
| 2656 | 2585 | "zmij", |
| 2657 | 2586 | ] |
| 2658 | 2587 | |
| 2659 | [[package]] | |
| 2660 | name = "serde_repr" | |
| 2661 | version = "0.1.20" | |
| 2662 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2663 | checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" | |
| 2664 | dependencies = [ | |
| 2665 | "proc-macro2", | |
| 2666 | "quote", | |
| 2667 | "syn", | |
| 2668 | ] | |
| 2669 | ||
| 2670 | 2588 | [[package]] |
| 2671 | 2589 | name = "serde_spanned" |
| 2672 | 2590 | version = "1.1.1" |
| ... | ... | @@ -2756,15 +2674,6 @@ dependencies = [ |
| 2756 | 2674 | "vfs", |
| 2757 | 2675 | ] |
| 2758 | 2676 | |
| 2759 | [[package]] | |
| 2760 | name = "spin" | |
| 2761 | version = "0.9.8" | |
| 2762 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2763 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" | |
| 2764 | dependencies = [ | |
| 2765 | "lock_api", | |
| 2766 | ] | |
| 2767 | ||
| 2768 | 2677 | [[package]] |
| 2769 | 2678 | name = "stable_deref_trait" |
| 2770 | 2679 | version = "1.2.1" |
| ... | ... | @@ -2784,7 +2693,7 @@ dependencies = [ |
| 2784 | 2693 | "backtrace", |
| 2785 | 2694 | "crossbeam-channel", |
| 2786 | 2695 | "crossbeam-utils", |
| 2787 | "itertools 0.14.0", | |
| 2696 | "itertools 0.15.0", | |
| 2788 | 2697 | "jod-thread", |
| 2789 | 2698 | "libc", |
| 2790 | 2699 | "miow", |
| ... | ... | @@ -2820,7 +2729,7 @@ version = "0.0.0" |
| 2820 | 2729 | dependencies = [ |
| 2821 | 2730 | "either", |
| 2822 | 2731 | "expect-test", |
| 2823 | "itertools 0.14.0", | |
| 2732 | "itertools 0.15.0", | |
| 2824 | 2733 | "parser", |
| 2825 | 2734 | "rayon", |
| 2826 | 2735 | "rowan", |
| ... | ... | @@ -3427,7 +3336,7 @@ version = "0.244.0" |
| 3427 | 3336 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3428 | 3337 | checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" |
| 3429 | 3338 | dependencies = [ |
| 3430 | "bitflags 2.12.1", | |
| 3339 | "bitflags", | |
| 3431 | 3340 | "hashbrown 0.15.5", |
| 3432 | 3341 | "indexmap", |
| 3433 | 3342 | "semver", |
| ... | ... | @@ -3721,7 +3630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3721 | 3630 | checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" |
| 3722 | 3631 | dependencies = [ |
| 3723 | 3632 | "anyhow", |
| 3724 | "bitflags 2.12.1", | |
| 3633 | "bitflags", | |
| 3725 | 3634 | "indexmap", |
| 3726 | 3635 | "log", |
| 3727 | 3636 | "serde", |
| ... | ... | @@ -3801,7 +3710,7 @@ dependencies = [ |
| 3801 | 3710 | "edition", |
| 3802 | 3711 | "either", |
| 3803 | 3712 | "flate2", |
| 3804 | "itertools 0.14.0", | |
| 3713 | "itertools 0.15.0", | |
| 3805 | 3714 | "proc-macro2", |
| 3806 | 3715 | "quote", |
| 3807 | 3716 | "stdx", |
src/tools/rust-analyzer/Cargo.toml+3-3| ... | ... | @@ -114,16 +114,16 @@ dot = "0.1.4" |
| 114 | 114 | either = "1.15.0" |
| 115 | 115 | expect-test = "1.5.1" |
| 116 | 116 | indexmap = { version = "2.9.0", features = ["serde"] } |
| 117 | itertools = "0.14.0" | |
| 117 | itertools = "0.15.0" | |
| 118 | 118 | libc = "0.2.172" |
| 119 | 119 | nohash-hasher = "0.2.0" |
| 120 | 120 | oorandom = "11.1.5" |
| 121 | postcard = { version = "1.1.3", features = ["alloc"] } | |
| 121 | postcard = { version = "1.1.3", default-features = false, features = ["alloc"] } | |
| 122 | 122 | process-wrap = { version = "9.1.0", features = ["std"] } |
| 123 | 123 | pulldown-cmark-to-cmark = "10.0.4" |
| 124 | 124 | pulldown-cmark = { version = "0.9.6", default-features = false } |
| 125 | 125 | rayon = "1.10.0" |
| 126 | rowan = "=0.15.18" | |
| 126 | rowan = "=0.15.19" | |
| 127 | 127 | # Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work |
| 128 | 128 | # on impls without it |
| 129 | 129 | salsa = { version = "0.27.0", default-features = false, features = [ |
src/tools/rust-analyzer/crates/hir-def/src/db.rs+21-4| ... | ... | @@ -4,6 +4,7 @@ use hir_expand::{ |
| 4 | 4 | EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind, |
| 5 | 5 | db::ExpandDatabase, |
| 6 | 6 | }; |
| 7 | use salsa::{Durability, Setter}; | |
| 7 | 8 | use triomphe::Arc; |
| 8 | 9 | |
| 9 | 10 | use crate::{ |
| ... | ... | @@ -16,10 +17,6 @@ use crate::{ |
| 16 | 17 | |
| 17 | 18 | #[query_group::query_group] |
| 18 | 19 | pub trait DefDatabase: ExpandDatabase + SourceDatabase { |
| 19 | /// Whether to expand procedural macros during name resolution. | |
| 20 | #[salsa::input] | |
| 21 | fn expand_proc_attr_macros(&self) -> bool; | |
| 22 | ||
| 23 | 20 | /// Computes an [`ItemTree`] for the given file or macro expansion. |
| 24 | 21 | #[salsa::invoke(file_item_tree)] |
| 25 | 22 | #[salsa::transparent] |
| ... | ... | @@ -47,6 +44,26 @@ pub trait DefDatabase: ExpandDatabase + SourceDatabase { |
| 47 | 44 | fn include_macro_invoc(&self, crate_id: Crate) -> Arc<[(MacroCallId, EditionedFileId)]>; |
| 48 | 45 | } |
| 49 | 46 | |
| 47 | /// Whether to expand procedural macros during name resolution. | |
| 48 | /// | |
| 49 | /// Note: this struct shouldn't be exposed to ide crates -- consider using | |
| 50 | /// [`set_expand_proc_attr_macros`] instead, if possible. | |
| 51 | #[salsa::input(singleton, debug)] | |
| 52 | pub(crate) struct ExpandProcAttrMacros { | |
| 53 | #[returns(copy)] | |
| 54 | pub(crate) enabled: bool, | |
| 55 | } | |
| 56 | ||
| 57 | pub fn set_expand_proc_attr_macros(db: &mut dyn DefDatabase, enabled: bool) { | |
| 58 | if let Some(expand_proc_attr_macros) = ExpandProcAttrMacros::try_get(db) { | |
| 59 | if expand_proc_attr_macros.enabled(db) != enabled { | |
| 60 | expand_proc_attr_macros.set_enabled(db).with_durability(Durability::HIGH).to(enabled); | |
| 61 | } | |
| 62 | } else { | |
| 63 | _ = ExpandProcAttrMacros::builder(enabled).durability(Durability::HIGH).new(db); | |
| 64 | } | |
| 65 | } | |
| 66 | ||
| 50 | 67 | // return: macro call id and include file id |
| 51 | 68 | fn include_macro_invoc( |
| 52 | 69 | db: &dyn DefDatabase, |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs+26-16| ... | ... | @@ -2,7 +2,6 @@ |
| 2 | 2 | //! consts. |
| 3 | 3 | use std::ops; |
| 4 | 4 | |
| 5 | use arrayvec::ArrayVec; | |
| 6 | 5 | use hir_expand::{InFile, Lookup}; |
| 7 | 6 | use span::Edition; |
| 8 | 7 | use syntax::ast; |
| ... | ... | @@ -18,6 +17,24 @@ use crate::{ |
| 18 | 17 | src::HasSource, |
| 19 | 18 | }; |
| 20 | 19 | |
| 20 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | |
| 21 | pub struct Param<Id> { | |
| 22 | /// The id of the formal parameter. In analysis, you want to use this: it has a special status as a parameter, | |
| 23 | /// while [`user_written`][Self::user_written] is just a local variable. | |
| 24 | pub formal: Id, | |
| 25 | /// The id that corresponds to the pattern the user wrote. In IDE, you usually want to use this. | |
| 26 | /// | |
| 27 | /// It will be different than [`formal`][Self::formal] for coroutine fns (async fn etc.), because we apply | |
| 28 | /// a desugaring for those that copies the parameter into a local variable. | |
| 29 | pub user_written: Id, | |
| 30 | } | |
| 31 | ||
| 32 | impl<Id: Copy> Param<Id> { | |
| 33 | pub(crate) fn new(id: Id) -> Self { | |
| 34 | Self { formal: id, user_written: id } | |
| 35 | } | |
| 36 | } | |
| 37 | ||
| 21 | 38 | /// The body of an item (function, const etc.). |
| 22 | 39 | #[derive(Debug, Eq, PartialEq)] |
| 23 | 40 | pub struct Body { |
| ... | ... | @@ -28,13 +45,8 @@ pub struct Body { |
| 28 | 45 | /// |
| 29 | 46 | /// If this `Body` is for the body of a constant, this will just be |
| 30 | 47 | /// empty. |
| 31 | pub params: Box<[PatId]>, | |
| 32 | /// The first element, if it exists, is the real `self` binding. | |
| 33 | /// | |
| 34 | /// The second element is used for `async fn` (or `gen fn` etc.). These functions | |
| 35 | /// have to put a `let self = self` inside the returned coroutine, and the second element | |
| 36 | /// points at it. | |
| 37 | pub self_params: ArrayVec<BindingId, 2>, | |
| 48 | pub params: Box<[Param<PatId>]>, | |
| 49 | pub self_param: Option<Param<BindingId>>, | |
| 38 | 50 | } |
| 39 | 51 | |
| 40 | 52 | impl ops::Deref for Body { |
| ... | ... | @@ -128,14 +140,12 @@ impl Body { |
| 128 | 140 | self.store.expr_roots().next_back().unwrap() |
| 129 | 141 | } |
| 130 | 142 | |
| 131 | pub fn self_param(&self) -> Option<BindingId> { | |
| 132 | self.self_params.first().copied() | |
| 133 | } | |
| 134 | ||
| 135 | /// `async fn` (or `gen fn` etc.), have to put a `let self = self` inside the returned coroutine. | |
| 136 | /// This function returns it. | |
| 137 | pub fn coroutine_self_binding(&self) -> Option<BindingId> { | |
| 138 | self.self_params.get(1).copied() | |
| 143 | /// Returns `true` if this is the formal or user-written self param. | |
| 144 | #[inline] | |
| 145 | pub fn is_any_self_param(&self, binding: BindingId) -> bool { | |
| 146 | self.self_param.is_some_and(|self_param| { | |
| 147 | self_param.formal == binding || self_param.user_written == binding | |
| 148 | }) | |
| 139 | 149 | } |
| 140 | 150 | |
| 141 | 151 | pub fn pretty_print( |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs+113-101| ... | ... | @@ -8,7 +8,6 @@ mod path; |
| 8 | 8 | |
| 9 | 9 | use std::{cell::OnceCell, mem}; |
| 10 | 10 | |
| 11 | use arrayvec::ArrayVec; | |
| 12 | 11 | use base_db::FxIndexSet; |
| 13 | 12 | use cfg::CfgOptions; |
| 14 | 13 | use either::Either; |
| ... | ... | @@ -19,6 +18,7 @@ use hir_expand::{ |
| 19 | 18 | span_map::SpanMap, |
| 20 | 19 | }; |
| 21 | 20 | use intern::{Symbol, sym}; |
| 21 | use itertools::Itertools; | |
| 22 | 22 | use rustc_abi::ExternAbi; |
| 23 | 23 | use rustc_hash::FxHashMap; |
| 24 | 24 | use smallvec::SmallVec; |
| ... | ... | @@ -43,6 +43,7 @@ use crate::{ |
| 43 | 43 | Body, BodySourceMap, ExprPtr, ExprRoot, ExpressionStore, ExpressionStoreBuilder, |
| 44 | 44 | ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, LifetimePtr, |
| 45 | 45 | PatPtr, TypePtr, |
| 46 | body::Param, | |
| 46 | 47 | expander::Expander, |
| 47 | 48 | lower::generics::ImplTraitLowerFn, |
| 48 | 49 | path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path}, |
| ... | ... | @@ -82,7 +83,7 @@ pub(super) fn lower_body( |
| 82 | 83 | // even though they should be the same. Also, when the body comes from multiple expansions, their |
| 83 | 84 | // hygiene is different. |
| 84 | 85 | |
| 85 | let mut self_params = ArrayVec::new(); | |
| 86 | let mut self_param = None; | |
| 86 | 87 | let mut source_map_self_param = None; |
| 87 | 88 | let mut params = vec![]; |
| 88 | 89 | let mut collector = ExprCollector::new(db, module, current_file_id); |
| ... | ... | @@ -100,9 +101,43 @@ pub(super) fn lower_body( |
| 100 | 101 | // If #[rust_analyzer::skip] annotated, only construct enough information for the signature |
| 101 | 102 | // and skip the body. |
| 102 | 103 | if skip_body { |
| 104 | collector.with_expr_root(|collector| { | |
| 105 | if let Some(param_list) = parameters { | |
| 106 | if let Some(self_param_syn) = | |
| 107 | param_list.self_param().filter(|self_param| collector.check_cfg(self_param)) | |
| 108 | { | |
| 109 | let is_mutable = self_param_syn.mut_token().is_some() | |
| 110 | && self_param_syn.amp_token().is_none(); | |
| 111 | let hygiene = self_param_syn | |
| 112 | .name() | |
| 113 | .map(|name| collector.hygiene_id_for(name.syntax().text_range())) | |
| 114 | .unwrap_or(HygieneId::ROOT); | |
| 115 | let binding_id: la_arena::Idx<Binding> = collector.alloc_binding( | |
| 116 | Name::new_symbol_root(sym::self_), | |
| 117 | BindingAnnotation::new(is_mutable, false), | |
| 118 | hygiene, | |
| 119 | ); | |
| 120 | self_param = Some(Param::new(binding_id)); | |
| 121 | source_map_self_param = | |
| 122 | Some(collector.expander.in_file(AstPtr::new(&self_param_syn))); | |
| 123 | } | |
| 124 | let count = param_list.params().filter(|it| collector.check_cfg(it)).count(); | |
| 125 | params = (0..count).map(|_| Param::new(collector.missing_pat())).collect(); | |
| 126 | }; | |
| 127 | ||
| 128 | collector.missing_expr() | |
| 129 | }); | |
| 130 | let (store, source_map) = collector.store.finish(); | |
| 131 | return ( | |
| 132 | Body { store, params: params.into_boxed_slice(), self_param }, | |
| 133 | BodySourceMap { self_param: source_map_self_param, store: source_map }, | |
| 134 | ); | |
| 135 | } | |
| 136 | ||
| 137 | collector.with_expr_root(|collector| { | |
| 103 | 138 | if let Some(param_list) = parameters { |
| 104 | 139 | if let Some(self_param_syn) = |
| 105 | param_list.self_param().filter(|self_param| collector.check_cfg(self_param)) | |
| 140 | param_list.self_param().filter(|it| collector.check_cfg(it)) | |
| 106 | 141 | { |
| 107 | 142 | let is_mutable = |
| 108 | 143 | self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none(); |
| ... | ... | @@ -115,59 +150,31 @@ pub(super) fn lower_body( |
| 115 | 150 | BindingAnnotation::new(is_mutable, false), |
| 116 | 151 | hygiene, |
| 117 | 152 | ); |
| 118 | self_params.push(binding_id); | |
| 153 | self_param = Some(Param::new(binding_id)); | |
| 119 | 154 | source_map_self_param = |
| 120 | 155 | Some(collector.expander.in_file(AstPtr::new(&self_param_syn))); |
| 121 | 156 | } |
| 122 | let count = param_list.params().filter(|it| collector.check_cfg(it)).count(); | |
| 123 | params = (0..count).map(|_| collector.missing_pat()).collect(); | |
| 124 | }; | |
| 125 | collector.with_expr_root(|collector| collector.missing_expr()); | |
| 126 | let (store, source_map) = collector.store.finish(); | |
| 127 | return ( | |
| 128 | Body { store, params: params.into_boxed_slice(), self_params }, | |
| 129 | BodySourceMap { self_param: source_map_self_param, store: source_map }, | |
| 130 | ); | |
| 131 | } | |
| 132 | 157 | |
| 133 | if let Some(param_list) = parameters { | |
| 134 | if let Some(self_param_syn) = param_list.self_param().filter(|it| collector.check_cfg(it)) { | |
| 135 | let is_mutable = | |
| 136 | self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none(); | |
| 137 | let hygiene = self_param_syn | |
| 138 | .name() | |
| 139 | .map(|name| collector.hygiene_id_for(name.syntax().text_range())) | |
| 140 | .unwrap_or(HygieneId::ROOT); | |
| 141 | let binding_id: la_arena::Idx<Binding> = collector.alloc_binding( | |
| 142 | Name::new_symbol_root(sym::self_), | |
| 143 | BindingAnnotation::new(is_mutable, false), | |
| 144 | hygiene, | |
| 158 | let is_extern = matches!( | |
| 159 | owner, | |
| 160 | DefWithBodyId::FunctionId(id) | |
| 161 | if matches!(id.loc(db).container, ItemContainerId::ExternBlockId(_)), | |
| 145 | 162 | ); |
| 146 | self_params.push(binding_id); | |
| 147 | source_map_self_param = Some(collector.expander.in_file(AstPtr::new(&self_param_syn))); | |
| 148 | } | |
| 149 | ||
| 150 | let is_extern = matches!( | |
| 151 | owner, | |
| 152 | DefWithBodyId::FunctionId(id) | |
| 153 | if matches!(id.loc(db).container, ItemContainerId::ExternBlockId(_)), | |
| 154 | ); | |
| 155 | 163 | |
| 156 | for param in param_list.params() { | |
| 157 | if collector.check_cfg(&param) { | |
| 158 | let param_pat = if is_extern { | |
| 159 | collector.collect_extern_fn_param(param.pat()) | |
| 160 | } else { | |
| 161 | collector.collect_pat_top(param.pat()) | |
| 162 | }; | |
| 163 | params.push(param_pat); | |
| 164 | for param in param_list.params() { | |
| 165 | if collector.check_cfg(&param) { | |
| 166 | let param_pat = if is_extern { | |
| 167 | collector.collect_extern_fn_param(param.pat()) | |
| 168 | } else { | |
| 169 | collector.collect_pat_top(param.pat()) | |
| 170 | }; | |
| 171 | params.push(Param::new(param_pat)); | |
| 172 | } | |
| 164 | 173 | } |
| 165 | } | |
| 166 | }; | |
| 174 | }; | |
| 167 | 175 | |
| 168 | collector.with_expr_root(|collector| { | |
| 169 | 176 | collector.collect( |
| 170 | &mut self_params, | |
| 177 | &mut self_param, | |
| 171 | 178 | &mut params, |
| 172 | 179 | body, |
| 173 | 180 | if is_async_fn { |
| ... | ... | @@ -187,7 +194,7 @@ pub(super) fn lower_body( |
| 187 | 194 | |
| 188 | 195 | let (store, source_map) = collector.store.finish(); |
| 189 | 196 | ( |
| 190 | Body { store, params: params.into_boxed_slice(), self_params }, | |
| 197 | Body { store, params: params.into_boxed_slice(), self_param }, | |
| 191 | 198 | BodySourceMap { self_param: source_map_self_param, store: source_map }, |
| 192 | 199 | ) |
| 193 | 200 | } |
| ... | ... | @@ -952,8 +959,8 @@ impl<'db> ExprCollector<'db> { |
| 952 | 959 | /// drop order are stable. |
| 953 | 960 | fn lower_coroutine_body_with_moved_arguments( |
| 954 | 961 | &mut self, |
| 955 | self_params: &mut ArrayVec<BindingId, 2>, | |
| 956 | params: &mut [PatId], | |
| 962 | self_param: &mut Option<Param<BindingId>>, | |
| 963 | params: &mut [Param<PatId>], | |
| 957 | 964 | body: ExprId, |
| 958 | 965 | kind: CoroutineKind, |
| 959 | 966 | coroutine_source: CoroutineSource, |
| ... | ... | @@ -984,10 +991,11 @@ impl<'db> ExprCollector<'db> { |
| 984 | 991 | // If `<pattern>` is a simple ident, then it is lowered to a single |
| 985 | 992 | // `let <pattern> = <pattern>;` statement as an optimization. |
| 986 | 993 | |
| 987 | let mut statements = Vec::new(); | |
| 994 | let mut statements = | |
| 995 | Vec::with_capacity(usize::from(self_param.is_some()) + (params.len() * 2)); | |
| 988 | 996 | |
| 989 | if let Some(&self_param) = self_params.first() { | |
| 990 | let Binding { ref name, mode, hygiene, .. } = self.store.bindings[self_param]; | |
| 997 | if let Some(self_param) = self_param { | |
| 998 | let Binding { ref name, mode, hygiene, .. } = self.store.bindings[self_param.formal]; | |
| 991 | 999 | let name = name.clone(); |
| 992 | 1000 | let child_binding_id = self.alloc_binding(name.clone(), mode, hygiene); |
| 993 | 1001 | let child_pat_id = |
| ... | ... | @@ -1003,11 +1011,11 @@ impl<'db> ExprCollector<'db> { |
| 1003 | 1011 | initializer: Some(expr), |
| 1004 | 1012 | else_branch: None, |
| 1005 | 1013 | }); |
| 1006 | self_params.push(child_binding_id); | |
| 1014 | self_param.user_written = child_binding_id; | |
| 1007 | 1015 | } |
| 1008 | 1016 | |
| 1009 | 1017 | for param in params { |
| 1010 | let (name, hygiene, is_simple_parameter) = match self.store.pats[*param] { | |
| 1018 | let (name, hygiene, is_simple_parameter) = match self.store.pats[param.formal] { | |
| 1011 | 1019 | // Check if this is a binding pattern, if so, we can optimize and avoid adding a |
| 1012 | 1020 | // `let <pat> = __argN;` statement. In this case, we do not rename the parameter. |
| 1013 | 1021 | Pat::Bind { id, subpat: None, .. } |
| ... | ... | @@ -1016,55 +1024,57 @@ impl<'db> ExprCollector<'db> { |
| 1016 | 1024 | BindingAnnotation::Unannotated | BindingAnnotation::Mutable |
| 1017 | 1025 | ) => |
| 1018 | 1026 | { |
| 1019 | (self.store.bindings[id].name.clone(), self.store.bindings[id].hygiene, true) | |
| 1027 | let binding = &self.store.bindings[id]; | |
| 1028 | (binding.name.clone(), binding.hygiene, true) | |
| 1020 | 1029 | } |
| 1021 | 1030 | Pat::Bind { id, .. } => { |
| 1022 | 1031 | // If this is a `ref` binding, we can't leave it as is but we can at least reuse the name, for better display. |
| 1023 | (self.store.bindings[id].name.clone(), self.store.bindings[id].hygiene, false) | |
| 1032 | let binding = &self.store.bindings[id]; | |
| 1033 | (binding.name.clone(), binding.hygiene, false) | |
| 1024 | 1034 | } |
| 1025 | 1035 | _ => (self.generate_new_name(), HygieneId::ROOT, false), |
| 1026 | 1036 | }; |
| 1027 | let pat_syntax = self.store.pat_map_back.get(*param).copied(); | |
| 1028 | let child_binding_id = | |
| 1029 | self.alloc_binding(name.clone(), BindingAnnotation::Mutable, hygiene); | |
| 1030 | let child_pat_id = | |
| 1031 | self.alloc_pat_desugared(Pat::Bind { id: child_binding_id, subpat: None }); | |
| 1032 | self.add_definition_to_binding(child_binding_id, child_pat_id); | |
| 1033 | if let Some(pat_syntax) = pat_syntax { | |
| 1034 | self.store.pat_map_back.insert(child_pat_id, pat_syntax); | |
| 1035 | } | |
| 1036 | let expr = self.alloc_expr_desugared(Expr::Path(name.clone().into())); | |
| 1037 | if !hygiene.is_root() { | |
| 1038 | self.store.ident_hygiene.insert(expr.into(), hygiene); | |
| 1039 | } | |
| 1040 | statements.push(Statement::Let { | |
| 1041 | pat: child_pat_id, | |
| 1042 | type_ref: None, | |
| 1043 | initializer: Some(expr), | |
| 1044 | else_branch: None, | |
| 1045 | }); | |
| 1037 | let pat_syntax = self.store.pat_map_back.get(param.formal).copied(); | |
| 1046 | 1038 | if !is_simple_parameter { |
| 1039 | // It needs to be mutable so the inner patterns can borrow it mutably (`ref mut`). | |
| 1040 | let child_binding_id = | |
| 1041 | self.alloc_binding(name.clone(), BindingAnnotation::Mutable, hygiene); | |
| 1042 | let child_pat_id = | |
| 1043 | self.alloc_pat_desugared(Pat::Bind { id: child_binding_id, subpat: None }); | |
| 1044 | self.add_definition_to_binding(child_binding_id, child_pat_id); | |
| 1045 | if let Some(pat_syntax) = pat_syntax { | |
| 1046 | self.store.pat_map_back.insert(child_pat_id, pat_syntax); | |
| 1047 | } | |
| 1047 | 1048 | let expr = self.alloc_expr_desugared(Expr::Path(name.clone().into())); |
| 1048 | 1049 | if !hygiene.is_root() { |
| 1049 | 1050 | self.store.ident_hygiene.insert(expr.into(), hygiene); |
| 1050 | 1051 | } |
| 1051 | 1052 | statements.push(Statement::Let { |
| 1052 | pat: *param, | |
| 1053 | pat: child_pat_id, | |
| 1053 | 1054 | type_ref: None, |
| 1054 | 1055 | initializer: Some(expr), |
| 1055 | 1056 | else_branch: None, |
| 1056 | 1057 | }); |
| 1058 | } | |
| 1059 | let expr = self.alloc_expr_desugared(Expr::Path(name.clone().into())); | |
| 1060 | if !hygiene.is_root() { | |
| 1061 | self.store.ident_hygiene.insert(expr.into(), hygiene); | |
| 1062 | } | |
| 1063 | statements.push(Statement::Let { | |
| 1064 | pat: param.formal, | |
| 1065 | type_ref: None, | |
| 1066 | initializer: Some(expr), | |
| 1067 | else_branch: None, | |
| 1068 | }); | |
| 1057 | 1069 | |
| 1058 | let parent_binding_id = | |
| 1059 | self.alloc_binding(name.clone(), BindingAnnotation::Mutable, hygiene); | |
| 1060 | let parent_pat_id = | |
| 1061 | self.alloc_pat_desugared(Pat::Bind { id: parent_binding_id, subpat: None }); | |
| 1062 | self.add_definition_to_binding(parent_binding_id, parent_pat_id); | |
| 1063 | if let Some(pat_syntax) = pat_syntax { | |
| 1064 | self.store.pat_map_back.insert(parent_pat_id, pat_syntax); | |
| 1065 | } | |
| 1066 | *param = parent_pat_id; | |
| 1070 | let parent_binding_id = self.alloc_binding(name, BindingAnnotation::Mutable, hygiene); | |
| 1071 | let parent_pat_id = | |
| 1072 | self.alloc_pat_desugared(Pat::Bind { id: parent_binding_id, subpat: None }); | |
| 1073 | self.add_definition_to_binding(parent_binding_id, parent_pat_id); | |
| 1074 | if let Some(pat_syntax) = pat_syntax { | |
| 1075 | self.store.pat_map_back.insert(parent_pat_id, pat_syntax); | |
| 1067 | 1076 | } |
| 1077 | *param = Param { formal: parent_pat_id, user_written: param.formal }; | |
| 1068 | 1078 | } |
| 1069 | 1079 | |
| 1070 | 1080 | let coroutine = self.desugared_coroutine_expr( |
| ... | ... | @@ -1105,8 +1115,8 @@ impl<'db> ExprCollector<'db> { |
| 1105 | 1115 | |
| 1106 | 1116 | fn collect( |
| 1107 | 1117 | &mut self, |
| 1108 | self_params: &mut ArrayVec<BindingId, 2>, | |
| 1109 | params: &mut [PatId], | |
| 1118 | self_param: &mut Option<Param<BindingId>>, | |
| 1119 | params: &mut [Param<PatId>], | |
| 1110 | 1120 | expr: Option<ast::Expr>, |
| 1111 | 1121 | awaitable: Awaitable, |
| 1112 | 1122 | is_async_fn: bool, |
| ... | ... | @@ -1123,7 +1133,7 @@ impl<'db> ExprCollector<'db> { |
| 1123 | 1133 | (false, false) => unreachable!(), |
| 1124 | 1134 | }; |
| 1125 | 1135 | this.lower_coroutine_body_with_moved_arguments( |
| 1126 | self_params, | |
| 1136 | self_param, | |
| 1127 | 1137 | params, |
| 1128 | 1138 | body, |
| 1129 | 1139 | kind, |
| ... | ... | @@ -1562,6 +1572,10 @@ impl<'db> ExprCollector<'db> { |
| 1562 | 1572 | args.reserve_exact(num_params); |
| 1563 | 1573 | arg_types.reserve_exact(num_params); |
| 1564 | 1574 | for param in pl.params() { |
| 1575 | if !this.check_cfg(&param) { | |
| 1576 | continue; | |
| 1577 | } | |
| 1578 | ||
| 1565 | 1579 | let pat = this.collect_pat_top(param.pat()); |
| 1566 | 1580 | let type_ref = |
| 1567 | 1581 | param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it)); |
| ... | ... | @@ -1599,13 +1613,15 @@ impl<'db> ExprCollector<'db> { |
| 1599 | 1613 | let closure_kind = if let Some(kind) = kind { |
| 1600 | 1614 | // It's important that this expr is allocated immediately before the closure. |
| 1601 | 1615 | // We rely on it for `coroutine_for_closure()`. |
| 1616 | let mut args_with_user_written = args.iter().copied().map(Param::new).collect::<Vec<_>>(); | |
| 1602 | 1617 | body = this.lower_coroutine_body_with_moved_arguments( |
| 1603 | &mut ArrayVec::new(), | |
| 1604 | &mut args, | |
| 1618 | &mut None, | |
| 1619 | &mut args_with_user_written, | |
| 1605 | 1620 | body, |
| 1606 | 1621 | kind, |
| 1607 | 1622 | CoroutineSource::Closure, |
| 1608 | 1623 | ); |
| 1624 | args.iter_mut().set_from(args_with_user_written.iter().map(|arg| arg.formal)); | |
| 1609 | 1625 | is_coroutine_closure = true; |
| 1610 | 1626 | |
| 1611 | 1627 | ClosureKind::CoroutineClosure(kind) |
| ... | ... | @@ -1666,7 +1682,7 @@ impl<'db> ExprCollector<'db> { |
| 1666 | 1682 | } |
| 1667 | 1683 | } |
| 1668 | 1684 | ast::Expr::TupleExpr(e) => { |
| 1669 | let mut exprs: Vec<_> = e.fields().map(|expr| self.collect_expr(expr)).collect(); | |
| 1685 | let mut exprs: Vec<_> = e.fields().filter_map(|expr| self.maybe_collect_expr(expr)).collect(); | |
| 1670 | 1686 | // if there is a leading comma, the user is most likely to type out a leading expression |
| 1671 | 1687 | // so we insert a missing expression at the beginning for IDE features |
| 1672 | 1688 | if comma_follows_token(e.l_paren_token()) { |
| ... | ... | @@ -1681,13 +1697,7 @@ impl<'db> ExprCollector<'db> { |
| 1681 | 1697 | match kind { |
| 1682 | 1698 | ArrayExprKind::ElementList(e) => { |
| 1683 | 1699 | let elements = e |
| 1684 | .filter_map(|expr| { | |
| 1685 | if self.check_cfg(&expr) { | |
| 1686 | Some(self.collect_expr(expr)) | |
| 1687 | } else { | |
| 1688 | None | |
| 1689 | } | |
| 1690 | }) | |
| 1700 | .filter_map(|expr| self.maybe_collect_expr(expr)) | |
| 1691 | 1701 | .collect(); |
| 1692 | 1702 | self.alloc_expr(Expr::Array(Array::ElementList { elements }), syntax_ptr) |
| 1693 | 1703 | } |
| ... | ... | @@ -1728,16 +1738,18 @@ impl<'db> ExprCollector<'db> { |
| 1728 | 1738 | let e = e.macro_call()?; |
| 1729 | 1739 | let macro_ptr = AstPtr::new(&e); |
| 1730 | 1740 | let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| { |
| 1731 | expansion.map(|it| this.collect_expr(it)) | |
| 1741 | expansion.map(|it| this.maybe_collect_expr(it)) | |
| 1732 | 1742 | }); |
| 1733 | 1743 | match id { |
| 1734 | Some(id) => { | |
| 1744 | Some(Some(id)) => { | |
| 1735 | 1745 | // Make the macro-call point to its expanded expression so we can query |
| 1736 | 1746 | // semantics on syntax pointers to the macro |
| 1737 | 1747 | let src = self.expander.in_file(syntax_ptr); |
| 1738 | 1748 | self.store.expr_map.insert(src, id.into()); |
| 1739 | 1749 | id |
| 1740 | 1750 | } |
| 1751 | // Macro expanded into a disabled cfg (yes, there is such thing, see the weird_cfgs test). | |
| 1752 | Some(None) => return None, | |
| 1741 | 1753 | None => self.alloc_expr(Expr::Missing, syntax_ptr), |
| 1742 | 1754 | } |
| 1743 | 1755 | } |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs+4| ... | ... | @@ -27,6 +27,10 @@ impl ExprCollector<'_> { |
| 27 | 27 | let mut named_args: FxHashMap<Symbol, usize> = Default::default(); |
| 28 | 28 | let mut reg_args: FxHashSet<usize> = Default::default(); |
| 29 | 29 | for piece in asm.asm_pieces() { |
| 30 | if !self.check_cfg(&piece) { | |
| 31 | continue; | |
| 32 | } | |
| 33 | ||
| 30 | 34 | let slot = operands.len(); |
| 31 | 35 | let mut lower_reg = |reg: Option<ast::AsmRegSpec>| { |
| 32 | 36 | let reg = reg?; |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs+3-3| ... | ... | @@ -92,12 +92,12 @@ pub fn print_body_hir( |
| 92 | 92 | }; |
| 93 | 93 | if let DefWithBodyId::FunctionId(_) = owner { |
| 94 | 94 | p.buf.push('('); |
| 95 | if let Some(self_param) = body.self_param() { | |
| 96 | p.print_binding(self_param); | |
| 95 | if let Some(self_param) = body.self_param { | |
| 96 | p.print_binding(self_param.formal); | |
| 97 | 97 | p.buf.push_str(", "); |
| 98 | 98 | } |
| 99 | 99 | body.params.iter().for_each(|param| { |
| 100 | p.print_pat(*param); | |
| 100 | p.print_pat(param.formal); | |
| 101 | 101 | p.buf.push_str(", "); |
| 102 | 102 | }); |
| 103 | 103 | // remove the last ", " in param list |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs+4-8| ... | ... | @@ -5,7 +5,7 @@ use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx}; |
| 5 | 5 | use crate::{ |
| 6 | 6 | BlockId, DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, VariantId, |
| 7 | 7 | db::DefDatabase, |
| 8 | expr_store::{Body, ExpressionStore, HygieneId}, | |
| 8 | expr_store::{Body, ExpressionStore, HygieneId, body::Param}, | |
| 9 | 9 | hir::{ |
| 10 | 10 | Array, Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement, |
| 11 | 11 | generics::GenericParams, |
| ... | ... | @@ -147,10 +147,10 @@ impl ExprScopes { |
| 147 | 147 | ), |
| 148 | 148 | }; |
| 149 | 149 | let mut root = scopes.root_scope(); |
| 150 | if let Some(self_param) = body.self_param() { | |
| 150 | if let Some(Param { formal: self_param, user_written: _ }) = body.self_param { | |
| 151 | 151 | scopes.add_bindings(body, root, self_param, body.binding_hygiene(self_param)); |
| 152 | 152 | } |
| 153 | scopes.add_params_bindings(body, root, &body.params); | |
| 153 | body.params.iter().for_each(|param| scopes.add_pat_bindings(body, root, param.formal)); | |
| 154 | 154 | compute_expr_scopes(body.root_expr(), body, &mut scopes, &mut { root }, &mut root); |
| 155 | 155 | scopes |
| 156 | 156 | } |
| ... | ... | @@ -248,10 +248,6 @@ impl ExprScopes { |
| 248 | 248 | pattern.walk_child_pats(|pat| self.add_pat_bindings(store, scope, pat)); |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | fn add_params_bindings(&mut self, store: &ExpressionStore, scope: ScopeId, params: &[PatId]) { | |
| 252 | params.iter().for_each(|pat| self.add_pat_bindings(store, scope, *pat)); | |
| 253 | } | |
| 254 | ||
| 255 | 251 | fn set_scope(&mut self, node: ExprId, scope: ScopeId) { |
| 256 | 252 | self.scope_by_expr.insert(node, scope); |
| 257 | 253 | } |
| ... | ... | @@ -356,7 +352,7 @@ fn compute_expr_scopes( |
| 356 | 352 | } |
| 357 | 353 | Expr::Closure { args, body: body_expr, .. } => { |
| 358 | 354 | let mut scope = scopes.new_scope(*scope); |
| 359 | scopes.add_params_bindings(store, scope, args); | |
| 355 | args.iter().for_each(|arg| scopes.add_pat_bindings(store, scope, *arg)); | |
| 360 | 356 | compute_expr_scopes(scopes, *body_expr, &mut scope, const_scope); |
| 361 | 357 | } |
| 362 | 358 | Expr::Match { expr, arms } => { |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs+48-3| ... | ... | @@ -652,9 +652,9 @@ fn async_fn_weird_param_patterns() { |
| 652 | 652 | async fn main(&self, param1: i32, ref mut param2: i32, _: i32, param4 @ _: i32, 123: i32) {} |
| 653 | 653 | "#, |
| 654 | 654 | expect![[r#" |
| 655 | fn main(self, param1, mut param2, mut <ra@gennew>0, mut param4, mut <ra@gennew>1) async { | |
| 655 | fn main(self, mut param1, mut param2, mut <ra@gennew>0, mut param4, mut <ra@gennew>1) async { | |
| 656 | 656 | let self = self; |
| 657 | let mut param1 = param1; | |
| 657 | let param1 = param1; | |
| 658 | 658 | let mut param2 = param2; |
| 659 | 659 | let ref mut param2 = param2; |
| 660 | 660 | let mut <ra@gennew>0 = <ra@gennew>0; |
| ... | ... | @@ -690,7 +690,7 @@ fn foo() { |
| 690 | 690 | } |
| 691 | 691 | |
| 692 | 692 | #[test] |
| 693 | fn foo() { | |
| 693 | fn block_tail_cfg() { | |
| 694 | 694 | pretty_print( |
| 695 | 695 | r#" |
| 696 | 696 | macro_rules! foo { |
| ... | ... | @@ -716,3 +716,48 @@ fn foo() -> i64 { |
| 716 | 716 | }"#]], |
| 717 | 717 | ); |
| 718 | 718 | } |
| 719 | ||
| 720 | #[test] | |
| 721 | fn weird_cfgs() { | |
| 722 | pretty_print( | |
| 723 | r#" | |
| 724 | macro_rules! falsify { | |
| 725 | ( $($t:tt)* ) => { #[cfg(false)] $($t)* }; | |
| 726 | } | |
| 727 | ||
| 728 | struct Foo(); | |
| 729 | ||
| 730 | fn foo() { | |
| 731 | foo(falsify!(1)); | |
| 732 | (falsify!(1),); | |
| 733 | [falsify!(1)]; | |
| 734 | Foo(falsify!(1)); | |
| 735 | foo(#[cfg(false)] 1); | |
| 736 | (#[cfg(false)] 1,); | |
| 737 | [#[cfg(false)] 1]; | |
| 738 | Foo(#[cfg(false)] 1); | |
| 739 | (|#[cfg(false)] a| {})(); | |
| 740 | ||
| 741 | builtin # asm( | |
| 742 | "", | |
| 743 | #[cfg(false)] x = const 4, | |
| 744 | #[cfg(false)] options(), | |
| 745 | #[cfg(false)] clobber_abi("C"), | |
| 746 | ); | |
| 747 | } | |
| 748 | "#, | |
| 749 | expect![[r#" | |
| 750 | fn foo() { | |
| 751 | foo(); | |
| 752 | (); | |
| 753 | []; | |
| 754 | Foo(); | |
| 755 | foo(); | |
| 756 | (); | |
| 757 | []; | |
| 758 | Foo(); | |
| 759 | (|| {})(); | |
| 760 | builtin#asm(_); | |
| 761 | }"#]], | |
| 762 | ); | |
| 763 | } |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs+3-3| ... | ... | @@ -190,13 +190,13 @@ fn f() { |
| 190 | 190 | "#, |
| 191 | 191 | expect![[r#" |
| 192 | 192 | ModuleIdLt { |
| 193 | [salsa id]: Id(3403), | |
| 193 | [salsa id]: Id(2c03), | |
| 194 | 194 | krate: Crate( |
| 195 | Id(2000), | |
| 195 | Id(1c00), | |
| 196 | 196 | ), |
| 197 | 197 | block: Some( |
| 198 | 198 | BlockId( |
| 199 | 4401, | |
| 199 | 3c01, | |
| 200 | 200 | ), |
| 201 | 201 | ), |
| 202 | 202 | containing_module_inside_def_map: None, |
src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs+8-8| ... | ... | @@ -35,9 +35,9 @@ macro_rules! f { |
| 35 | 35 | }; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | struct#0:MacroRules[BE8F, 0]@58..64#17408# MyTraitMap2#0:MacroCall[BE8F, 0]@31..42#ROOT2024# {#0:MacroRules[BE8F, 0]@72..73#17408# | |
| 39 | map#0:MacroRules[BE8F, 0]@86..89#17408#:#0:MacroRules[BE8F, 0]@89..90#17408# #0:MacroRules[BE8F, 0]@89..90#17408#::#0:MacroRules[BE8F, 0]@91..93#17408#std#0:MacroRules[BE8F, 0]@93..96#17408#::#0:MacroRules[BE8F, 0]@96..98#17408#collections#0:MacroRules[BE8F, 0]@98..109#17408#::#0:MacroRules[BE8F, 0]@109..111#17408#HashSet#0:MacroRules[BE8F, 0]@111..118#17408#<#0:MacroRules[BE8F, 0]@118..119#17408#(#0:MacroRules[BE8F, 0]@119..120#17408#)#0:MacroRules[BE8F, 0]@120..121#17408#>#0:MacroRules[BE8F, 0]@121..122#17408#,#0:MacroRules[BE8F, 0]@122..123#17408# | |
| 40 | }#0:MacroRules[BE8F, 0]@132..133#17408# | |
| 38 | struct#0:MacroRules[BE8F, 0]@58..64#15360# MyTraitMap2#0:MacroCall[BE8F, 0]@31..42#ROOT2024# {#0:MacroRules[BE8F, 0]@72..73#15360# | |
| 39 | map#0:MacroRules[BE8F, 0]@86..89#15360#:#0:MacroRules[BE8F, 0]@89..90#15360# #0:MacroRules[BE8F, 0]@89..90#15360#::#0:MacroRules[BE8F, 0]@91..93#15360#std#0:MacroRules[BE8F, 0]@93..96#15360#::#0:MacroRules[BE8F, 0]@96..98#15360#collections#0:MacroRules[BE8F, 0]@98..109#15360#::#0:MacroRules[BE8F, 0]@109..111#15360#HashSet#0:MacroRules[BE8F, 0]@111..118#15360#<#0:MacroRules[BE8F, 0]@118..119#15360#(#0:MacroRules[BE8F, 0]@119..120#15360#)#0:MacroRules[BE8F, 0]@120..121#15360#>#0:MacroRules[BE8F, 0]@121..122#15360#,#0:MacroRules[BE8F, 0]@122..123#15360# | |
| 40 | }#0:MacroRules[BE8F, 0]@132..133#15360# | |
| 41 | 41 | "#]], |
| 42 | 42 | ); |
| 43 | 43 | } |
| ... | ... | @@ -197,7 +197,7 @@ macro_rules! mk_struct { |
| 197 | 197 | #[macro_use] |
| 198 | 198 | mod foo; |
| 199 | 199 | |
| 200 | struct#1:MacroRules[DB0C, 0]@59..65#17408# Foo#0:MacroCall[DB0C, 0]@32..35#ROOT2024#(#1:MacroRules[DB0C, 0]@70..71#17408#u32#0:MacroCall[DB0C, 0]@41..44#ROOT2024#)#1:MacroRules[DB0C, 0]@74..75#17408#;#1:MacroRules[DB0C, 0]@75..76#17408# | |
| 200 | struct#1:MacroRules[DB0C, 0]@59..65#15360# Foo#0:MacroCall[DB0C, 0]@32..35#ROOT2024#(#1:MacroRules[DB0C, 0]@70..71#15360#u32#0:MacroCall[DB0C, 0]@41..44#ROOT2024#)#1:MacroRules[DB0C, 0]@74..75#15360#;#1:MacroRules[DB0C, 0]@75..76#15360# | |
| 201 | 201 | "#]], |
| 202 | 202 | ); |
| 203 | 203 | } |
| ... | ... | @@ -423,10 +423,10 @@ m! { foo, bar } |
| 423 | 423 | macro_rules! m { |
| 424 | 424 | ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); |
| 425 | 425 | } |
| 426 | impl#\17408# Bar#\17408# {#\17408# | |
| 427 | fn#\17408# foo#\ROOT2024#(#\17408#)#\17408# {#\17408#}#\17408# | |
| 428 | fn#\17408# bar#\ROOT2024#(#\17408#)#\17408# {#\17408#}#\17408# | |
| 429 | }#\17408# | |
| 426 | impl#\15360# Bar#\15360# {#\15360# | |
| 427 | fn#\15360# foo#\ROOT2024#(#\15360#)#\15360# {#\15360#}#\15360# | |
| 428 | fn#\15360# bar#\ROOT2024#(#\15360#)#\15360# {#\15360#}#\15360# | |
| 429 | }#\15360# | |
| 430 | 430 | "#]], |
| 431 | 431 | ); |
| 432 | 432 | } |
src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs+6-13| ... | ... | @@ -15,7 +15,7 @@ use hir_expand::{ |
| 15 | 15 | builtin::{BuiltinDeriveExpander, find_builtin_attr, find_builtin_derive, find_builtin_macro}, |
| 16 | 16 | mod_path::{ModPath, PathKind}, |
| 17 | 17 | name::{AsName, Name}, |
| 18 | proc_macro::CustomProcMacroExpander, | |
| 18 | proc_macro::{CustomProcMacroExpander, ProcMacros}, | |
| 19 | 19 | }; |
| 20 | 20 | use intern::{Interned, Symbol, sym}; |
| 21 | 21 | use itertools::izip; |
| ... | ... | @@ -79,9 +79,9 @@ pub(super) fn collect_defs( |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | let proc_macros = if krate.is_proc_macro { |
| 82 | db.proc_macros_for_crate(def_map.krate) | |
| 82 | ProcMacros::get_for_crate(db, def_map.krate) | |
| 83 | 83 | .and_then(|proc_macros| { |
| 84 | proc_macros.list(db.syntax_context(tree_id.file_id(), krate.edition)) | |
| 84 | proc_macros.list(tree_id.file_id().syntax_context(db, krate.edition)) | |
| 85 | 85 | }) |
| 86 | 86 | .unwrap_or_default() |
| 87 | 87 | } else { |
| ... | ... | @@ -616,7 +616,7 @@ impl<'db> DefCollector<'db> { |
| 616 | 616 | let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) { |
| 617 | 617 | Some(_) |
| 618 | 618 | if kind == hir_expand::proc_macro::ProcMacroKind::Attr |
| 619 | && !self.db.expand_proc_attr_macros() => | |
| 619 | && !crate::db::ExpandProcAttrMacros::get(self.db).enabled(self.db) => | |
| 620 | 620 | { |
| 621 | 621 | (CustomProcMacroExpander::disabled_proc_attr(), kind) |
| 622 | 622 | } |
| ... | ... | @@ -2531,12 +2531,8 @@ impl ModCollector<'_, '_> { |
| 2531 | 2531 | // Case 1: builtin macros |
| 2532 | 2532 | let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() { |
| 2533 | 2533 | // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name. |
| 2534 | let name; | |
| 2535 | 2534 | let name = match attrs.by_key(sym::rustc_builtin_macro).string_value_with_span() { |
| 2536 | Some((it, span)) => { | |
| 2537 | name = Name::new_symbol(Symbol::intern(it), span.ctx); | |
| 2538 | &name | |
| 2539 | } | |
| 2535 | Some((it, span)) => &Name::new_symbol(Symbol::intern(it), span.ctx), | |
| 2540 | 2536 | None => { |
| 2541 | 2537 | let explicit_name = |
| 2542 | 2538 | attrs.by_key(sym::rustc_builtin_macro).tt_values().next().and_then(|tt| { |
| ... | ... | @@ -2546,10 +2542,7 @@ impl ModCollector<'_, '_> { |
| 2546 | 2542 | } |
| 2547 | 2543 | }); |
| 2548 | 2544 | match explicit_name { |
| 2549 | Some(ident) => { | |
| 2550 | name = ident.as_name(); | |
| 2551 | &name | |
| 2552 | } | |
| 2545 | Some(ident) => &ident.as_name(), | |
| 2553 | 2546 | None => &mac.name, |
| 2554 | 2547 | } |
| 2555 | 2548 | } |
src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs+4-4| ... | ... | @@ -286,7 +286,7 @@ fn f() { foo } |
| 286 | 286 | "parse", |
| 287 | 287 | "real_span_map", |
| 288 | 288 | "crate_local_def_map", |
| 289 | "proc_macros_for_crate_shim", | |
| 289 | "ProcMacros::get_for_crate_", | |
| 290 | 290 | "file_item_tree_query", |
| 291 | 291 | "ast_id_map", |
| 292 | 292 | "parse", |
| ... | ... | @@ -305,7 +305,7 @@ fn f() { foo } |
| 305 | 305 | "parse_macro_expansion", |
| 306 | 306 | "expand_proc_macro", |
| 307 | 307 | "macro_arg", |
| 308 | "proc_macro_span_shim", | |
| 308 | "proc_macro_span", | |
| 309 | 309 | ] |
| 310 | 310 | "#]], |
| 311 | 311 | expect![[r#" |
| ... | ... | @@ -410,7 +410,7 @@ pub struct S {} |
| 410 | 410 | "parse", |
| 411 | 411 | "real_span_map", |
| 412 | 412 | "crate_local_def_map", |
| 413 | "proc_macros_for_crate_shim", | |
| 413 | "ProcMacros::get_for_crate_", | |
| 414 | 414 | "file_item_tree_query", |
| 415 | 415 | "ast_id_map", |
| 416 | 416 | "parse", |
| ... | ... | @@ -441,7 +441,7 @@ pub struct S {} |
| 441 | 441 | "parse_macro_expansion", |
| 442 | 442 | "expand_proc_macro", |
| 443 | 443 | "macro_arg", |
| 444 | "proc_macro_span_shim", | |
| 444 | "proc_macro_span", | |
| 445 | 445 | ] |
| 446 | 446 | "#]], |
| 447 | 447 | expect![[r#" |
src/tools/rust-analyzer/crates/hir-def/src/test_db.rs+1-2| ... | ... | @@ -15,7 +15,6 @@ use triomphe::Arc; |
| 15 | 15 | |
| 16 | 16 | use crate::{ |
| 17 | 17 | Lookup, ModuleDefId, ModuleId, |
| 18 | db::DefDatabase, | |
| 19 | 18 | expr_store::{Body, scope::ExprScopes}, |
| 20 | 19 | nameres::{DefMap, ModuleSource, block_def_map, crate_def_map}, |
| 21 | 20 | src::HasSource, |
| ... | ... | @@ -48,7 +47,7 @@ impl Default for TestDB { |
| 48 | 47 | crates_map: Default::default(), |
| 49 | 48 | nonce: Nonce::new(), |
| 50 | 49 | }; |
| 51 | this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); | |
| 50 | crate::db::set_expand_proc_attr_macros(&mut this, true); | |
| 52 | 51 | // This needs to be here otherwise `CrateGraphBuilder` panics. |
| 53 | 52 | set_all_crates_with_durability(&mut this, std::iter::empty(), Durability::HIGH); |
| 54 | 53 | _ = base_db::LibraryRoots::builder(Default::default()) |
src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs+18-4| ... | ... | @@ -375,12 +375,28 @@ impl AttrId { |
| 375 | 375 | |
| 376 | 376 | /// Returns the containing `ast::Attr` (note that it may contain other attributes as well due |
| 377 | 377 | /// to `cfg_attr`) and its [`ast::Meta`]. |
| 378 | /// | |
| 379 | /// Assumes that the attribute syntax node was present in the | |
| 380 | /// original file (not speculatively expanded macro output). | |
| 378 | 381 | pub fn find_attr_range_with_source( |
| 379 | 382 | self, |
| 380 | 383 | db: &dyn ExpandDatabase, |
| 381 | 384 | krate: Crate, |
| 382 | 385 | owner: &dyn ast::HasAttrs, |
| 383 | 386 | ) -> (ast::Attr, ast::Meta) { |
| 387 | self.find_attr_range_with_source_opt(db, krate, owner).unwrap_or_else(|| { | |
| 388 | panic!("used an incorrect `AttrId`; crate={krate:?}, attr_id={self:?}"); | |
| 389 | }) | |
| 390 | } | |
| 391 | ||
| 392 | /// Returns the containing `ast::Attr` (note that it may contain other attributes as well due | |
| 393 | /// to `cfg_attr`) and its [`ast::Meta`]. | |
| 394 | pub(crate) fn find_attr_range_with_source_opt( | |
| 395 | self, | |
| 396 | db: &dyn ExpandDatabase, | |
| 397 | krate: Crate, | |
| 398 | owner: &dyn ast::HasAttrs, | |
| 399 | ) -> Option<(ast::Attr, ast::Meta)> { | |
| 384 | 400 | let cfg_options = OnceCell::new(); |
| 385 | 401 | let mut index = 0; |
| 386 | 402 | let result = collect_item_tree_attrs( |
| ... | ... | @@ -395,10 +411,8 @@ impl AttrId { |
| 395 | 411 | }, |
| 396 | 412 | ); |
| 397 | 413 | match result { |
| 398 | Some(Either::Left(it)) => it, | |
| 399 | _ => { | |
| 400 | panic!("used an incorrect `AttrId`; crate={krate:?}, attr_id={self:?}"); | |
| 401 | } | |
| 414 | Some(Either::Left(it)) => Some(it), | |
| 415 | _ => None, | |
| 402 | 416 | } |
| 403 | 417 | } |
| 404 | 418 |
src/tools/rust-analyzer/crates/hir-expand/src/change.rs+3-4| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | //! Defines a unit of change that can applied to the database to get the next |
| 2 | 2 | //! state. Changes are transactional. |
| 3 | use base_db::{CrateGraphBuilder, FileChange, SourceRoot, salsa::Durability}; | |
| 3 | use base_db::{CrateGraphBuilder, FileChange, SourceRoot}; | |
| 4 | 4 | use span::FileId; |
| 5 | use triomphe::Arc; | |
| 6 | 5 | |
| 7 | 6 | use crate::{db::ExpandDatabase, proc_macro::ProcMacrosBuilder}; |
| 8 | 7 | |
| ... | ... | @@ -16,12 +15,12 @@ impl ChangeWithProcMacros { |
| 16 | 15 | pub fn apply(self, db: &mut impl ExpandDatabase) { |
| 17 | 16 | let crates_id_map = self.source_change.apply(db); |
| 18 | 17 | if let Some(proc_macros) = self.proc_macros { |
| 19 | let proc_macros = proc_macros.build( | |
| 18 | proc_macros.build_in( | |
| 19 | db, | |
| 20 | 20 | crates_id_map |
| 21 | 21 | .as_ref() |
| 22 | 22 | .expect("cannot set proc macros without setting the crate graph too"), |
| 23 | 23 | ); |
| 24 | db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH); | |
| 25 | 24 | } |
| 26 | 25 | } |
| 27 | 26 |
src/tools/rust-analyzer/crates/hir-expand/src/db.rs+32-56| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | use base_db::{Crate, SourceDatabase}; |
| 4 | 4 | use mbe::MatchedArmIndex; |
| 5 | use span::{AstIdMap, Edition, Span, SyntaxContext}; | |
| 5 | use span::{AstIdMap, Span}; | |
| 6 | 6 | use std::borrow::Cow; |
| 7 | 7 | use syntax::{AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, ast}; |
| 8 | 8 | use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree}; |
| ... | ... | @@ -17,7 +17,7 @@ use crate::{ |
| 17 | 17 | declarative::DeclarativeMacroExpander, |
| 18 | 18 | fixup::{self, SyntaxFixupUndoInfo}, |
| 19 | 19 | hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt}, |
| 20 | proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros}, | |
| 20 | proc_macro::CustomProcMacroExpander, | |
| 21 | 21 | span_map::{ExpansionSpanMap, RealSpanMap, SpanMap}, |
| 22 | 22 | tt, |
| 23 | 23 | }; |
| ... | ... | @@ -50,14 +50,6 @@ pub enum TokenExpander<'db> { |
| 50 | 50 | |
| 51 | 51 | #[query_group::query_group] |
| 52 | 52 | pub trait ExpandDatabase: SourceDatabase { |
| 53 | /// The proc macros. Do not use this! Use `proc_macros_for_crate()` instead. | |
| 54 | #[salsa::input] | |
| 55 | fn proc_macros(&self) -> Arc<ProcMacros>; | |
| 56 | ||
| 57 | /// Incrementality query to prevent queries from directly depending on `ExpandDatabase::proc_macros`. | |
| 58 | #[salsa::invoke(crate::proc_macro::proc_macros_for_crate)] | |
| 59 | fn proc_macros_for_crate(&self, krate: Crate) -> Option<Arc<CrateProcMacros>>; | |
| 60 | ||
| 61 | 53 | #[salsa::invoke(ast_id_map)] |
| 62 | 54 | #[salsa::transparent] |
| 63 | 55 | fn ast_id_map(&self, file_id: HirFileId) -> &AstIdMap; |
| ... | ... | @@ -115,40 +107,12 @@ pub trait ExpandDatabase: SourceDatabase { |
| 115 | 107 | id: AstId<ast::Macro>, |
| 116 | 108 | ) -> &DeclarativeMacroExpander; |
| 117 | 109 | |
| 118 | /// Special case of the previous query for procedural macros. We can't LRU | |
| 119 | /// proc macros, since they are not deterministic in general, and | |
| 120 | /// non-determinism breaks salsa in a very, very, very bad way. | |
| 121 | /// @edwin0cheng heroically debugged this once! See #4315 for details | |
| 122 | #[salsa::invoke(expand_proc_macro)] | |
| 123 | #[salsa::transparent] | |
| 124 | fn expand_proc_macro(&self, call: MacroCallId) -> &ExpandResult<tt::TopSubtree>; | |
| 125 | /// Retrieves the span to be used for a proc-macro expansions spans. | |
| 126 | /// This is a firewall query as it requires parsing the file, which we don't want proc-macros to | |
| 127 | /// directly depend on as that would cause to frequent invalidations, mainly because of the | |
| 128 | /// parse queries being LRU cached. If they weren't the invalidations would only happen if the | |
| 129 | /// user wrote in the file that defines the proc-macro. | |
| 130 | #[salsa::invoke_interned(proc_macro_span)] | |
| 131 | fn proc_macro_span(&self, fun: AstId<ast::Fn>) -> Span; | |
| 132 | ||
| 133 | 110 | #[salsa::invoke(parse_macro_expansion_error)] |
| 134 | 111 | #[salsa::transparent] |
| 135 | 112 | fn parse_macro_expansion_error( |
| 136 | 113 | &self, |
| 137 | 114 | macro_call: MacroCallId, |
| 138 | 115 | ) -> Option<ExpandResult<Arc<[SyntaxError]>>>; |
| 139 | ||
| 140 | #[salsa::transparent] | |
| 141 | fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext; | |
| 142 | } | |
| 143 | ||
| 144 | fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContext { | |
| 145 | match file { | |
| 146 | HirFileId::FileId(_) => SyntaxContext::root(edition), | |
| 147 | HirFileId::MacroFile(m) => { | |
| 148 | let kind = &m.loc(db).kind; | |
| 149 | db.macro_arg_considering_derives(m, kind).2.ctx | |
| 150 | } | |
| 151 | } | |
| 152 | 116 | } |
| 153 | 117 | |
| 154 | 118 | fn resolve_span(db: &dyn ExpandDatabase, Span { range, anchor, ctx: _ }: Span) -> FileRange { |
| ... | ... | @@ -253,7 +217,7 @@ pub fn expand_speculative( |
| 253 | 217 | // then try finding a token id for our token if it is inside this input subtree. |
| 254 | 218 | let item = ast::Item::cast(speculative_args.clone())?; |
| 255 | 219 | let (_, meta) = |
| 256 | attr_ids.invoc_attr().find_attr_range_with_source(db, loc.krate, &item); | |
| 220 | attr_ids.invoc_attr().find_attr_range_with_source_opt(db, loc.krate, &item)?; | |
| 257 | 221 | if let ast::Meta::TokenTreeMeta(meta) = meta |
| 258 | 222 | && let Some(tt) = meta.token_tree() |
| 259 | 223 | { |
| ... | ... | @@ -277,7 +241,7 @@ pub fn expand_speculative( |
| 277 | 241 | // Otherwise the expand query will fetch the non speculative attribute args and pass those instead. |
| 278 | 242 | let mut speculative_expansion = match loc.def.kind { |
| 279 | 243 | MacroDefKind::ProcMacro(ast, expander, _) => { |
| 280 | let span = db.proc_macro_span(ast); | |
| 244 | let span = proc_macro_span(db, ast); | |
| 281 | 245 | tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); |
| 282 | 246 | tt.set_top_subtree_delimiter_span(tt::DelimSpan::from_single(span)); |
| 283 | 247 | expander.expand( |
| ... | ... | @@ -296,7 +260,7 @@ pub fn expand_speculative( |
| 296 | 260 | } |
| 297 | 261 | MacroDefKind::Declarative(it, _) => db |
| 298 | 262 | .decl_macro_expander(loc.krate, it) |
| 299 | .expand_unhygienic(db, tt, loc.kind.call_style(), span), | |
| 263 | .expand_unhygienic(db, &tt, loc.kind.call_style(), span), | |
| 300 | 264 | MacroDefKind::BuiltIn(_, it) => { |
| 301 | 265 | it.expand(db, actual_macro_call, &tt, span).map_err(Into::into) |
| 302 | 266 | } |
| ... | ... | @@ -556,8 +520,7 @@ fn macro_expand<'db>( |
| 556 | 520 | |
| 557 | 521 | let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind { |
| 558 | 522 | MacroDefKind::ProcMacro(..) => { |
| 559 | return db | |
| 560 | .expand_proc_macro(macro_call_id) | |
| 523 | return expand_proc_macro(db, macro_call_id) | |
| 561 | 524 | .as_ref() |
| 562 | 525 | .map(|it| (Cow::Borrowed(it), None)); |
| 563 | 526 | } |
| ... | ... | @@ -568,9 +531,9 @@ fn macro_expand<'db>( |
| 568 | 531 | |
| 569 | 532 | let arg = macro_arg; |
| 570 | 533 | let res = match loc.def.kind { |
| 571 | MacroDefKind::Declarative(id, _) => db | |
| 572 | .decl_macro_expander(loc.def.krate, id) | |
| 573 | .expand(db, arg.clone(), macro_call_id, span), | |
| 534 | MacroDefKind::Declarative(id, _) => { | |
| 535 | db.decl_macro_expander(loc.def.krate, id).expand(db, arg, macro_call_id, span) | |
| 536 | } | |
| 574 | 537 | MacroDefKind::BuiltIn(_, it) => { |
| 575 | 538 | it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None) |
| 576 | 539 | } |
| ... | ... | @@ -610,7 +573,7 @@ fn macro_expand<'db>( |
| 610 | 573 | } |
| 611 | 574 | MacroDefKind::ProcMacro(_, _, _) => unreachable!(), |
| 612 | 575 | }; |
| 613 | (ExpandResult { value: res.value, err: res.err }, span) | |
| 576 | (res, span) | |
| 614 | 577 | } |
| 615 | 578 | }; |
| 616 | 579 | |
| ... | ... | @@ -627,17 +590,30 @@ fn macro_expand<'db>( |
| 627 | 590 | ExpandResult { value: (Cow::Owned(tt), matched_arm), err } |
| 628 | 591 | } |
| 629 | 592 | |
| 593 | /// Retrieves the span to be used for a proc-macro expansions spans. | |
| 594 | /// This is a firewall query as it requires parsing the file, which we don't want proc-macros to | |
| 595 | /// directly depend on as that would cause to frequent invalidations, mainly because of the | |
| 596 | /// parse queries being LRU cached. If they weren't the invalidations would only happen if the | |
| 597 | /// user wrote in the file that defines the proc-macro. | |
| 630 | 598 | fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span { |
| 631 | let root = db.parse_or_expand(ast.file_id); | |
| 632 | let ast_id_map = &db.ast_id_map(ast.file_id); | |
| 633 | let span_map = &db.span_map(ast.file_id); | |
| 634 | ||
| 635 | let node = ast_id_map.get(ast.value).to_node(&root); | |
| 636 | let range = ast::HasName::name(&node) | |
| 637 | .map_or_else(|| node.syntax().text_range(), |name| name.syntax().text_range()); | |
| 638 | span_map.span_for_range(range) | |
| 599 | #[salsa::tracked] | |
| 600 | fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>, _: ()) -> Span { | |
| 601 | let root = db.parse_or_expand(ast.file_id); | |
| 602 | let ast_id_map = db.ast_id_map(ast.file_id); | |
| 603 | let span_map = db.span_map(ast.file_id); | |
| 604 | ||
| 605 | let node = ast_id_map.get(ast.value).to_node(&root); | |
| 606 | let range = ast::HasName::name(&node) | |
| 607 | .map_or_else(|| node.syntax().text_range(), |name| name.syntax().text_range()); | |
| 608 | span_map.span_for_range(range) | |
| 609 | } | |
| 610 | proc_macro_span(db, ast, ()) | |
| 639 | 611 | } |
| 640 | 612 | |
| 613 | /// Special case of [`macro_expand`] for procedural macros. We can't LRU | |
| 614 | /// proc macros, since they are not deterministic in general, and | |
| 615 | /// non-determinism breaks salsa in a very, very, very bad way. | |
| 616 | /// @edwin0cheng heroically debugged this once! See #4315 for details | |
| 641 | 617 | #[salsa_macros::tracked(returns(ref))] |
| 642 | 618 | fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<tt::TopSubtree> { |
| 643 | 619 | let loc = id.loc(db); |
| ... | ... | @@ -654,7 +630,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<t |
| 654 | 630 | }; |
| 655 | 631 | |
| 656 | 632 | let ExpandResult { value: mut tt, err } = { |
| 657 | let span = db.proc_macro_span(ast); | |
| 633 | let span = proc_macro_span(db, ast); | |
| 658 | 634 | expander.expand( |
| 659 | 635 | db, |
| 660 | 636 | loc.def.krate, |
src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs+7-7| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //! Compiled declarative macro expanders (`macro_rules!` and `macro`) |
| 2 | 2 | |
| 3 | use std::{cell::OnceCell, ops::ControlFlow}; | |
| 3 | use std::ops::ControlFlow; | |
| 4 | 4 | |
| 5 | 5 | use base_db::Crate; |
| 6 | 6 | use span::{Edition, Span, SyntaxContext}; |
| ... | ... | @@ -32,7 +32,7 @@ impl DeclarativeMacroExpander { |
| 32 | 32 | pub fn expand( |
| 33 | 33 | &self, |
| 34 | 34 | db: &dyn ExpandDatabase, |
| 35 | tt: tt::TopSubtree, | |
| 35 | tt: &tt::TopSubtree, | |
| 36 | 36 | call_id: MacroCallId, |
| 37 | 37 | span: Span, |
| 38 | 38 | ) -> ExpandResult<(tt::TopSubtree, Option<u32>)> { |
| ... | ... | @@ -46,7 +46,7 @@ impl DeclarativeMacroExpander { |
| 46 | 46 | .mac |
| 47 | 47 | .expand( |
| 48 | 48 | db, |
| 49 | &tt, | |
| 49 | tt, | |
| 50 | 50 | |s| { |
| 51 | 51 | s.ctx = |
| 52 | 52 | apply_mark(db, s.ctx, call_id.into(), self.transparency, self.edition) |
| ... | ... | @@ -61,7 +61,7 @@ impl DeclarativeMacroExpander { |
| 61 | 61 | pub fn expand_unhygienic( |
| 62 | 62 | &self, |
| 63 | 63 | db: &dyn ExpandDatabase, |
| 64 | tt: tt::TopSubtree, | |
| 64 | tt: &tt::TopSubtree, | |
| 65 | 65 | call_style: MacroCallStyle, |
| 66 | 66 | call_site: Span, |
| 67 | 67 | ) -> ExpandResult<tt::TopSubtree> { |
| ... | ... | @@ -72,7 +72,7 @@ impl DeclarativeMacroExpander { |
| 72 | 72 | ), |
| 73 | 73 | None => self |
| 74 | 74 | .mac |
| 75 | .expand(db, &tt, |_| (), call_style, call_site) | |
| 75 | .expand(db, tt, |_| (), call_style, call_site) | |
| 76 | 76 | .map(TupleExt::head) |
| 77 | 77 | .map_err(Into::into), |
| 78 | 78 | } |
| ... | ... | @@ -91,10 +91,10 @@ impl DeclarativeMacroExpander { |
| 91 | 91 | let root = root.syntax_node(); |
| 92 | 92 | |
| 93 | 93 | let transparency = |node: ast::AnyHasAttrs| { |
| 94 | let cfg_options = OnceCell::new(); | |
| 94 | let mut cfg_options = None; | |
| 95 | 95 | expand_cfg_attr( |
| 96 | 96 | node.attrs(), |
| 97 | || cfg_options.get_or_init(|| def_crate.cfg_options(db)), | |
| 97 | || cfg_options.get_or_insert_with(|| def_crate.cfg_options(db)), | |
| 98 | 98 | |attr, _| { |
| 99 | 99 | if let ast::Meta::KeyValueMeta(attr) = attr |
| 100 | 100 | && attr.path().is1("rustc_macro_transparency") |
src/tools/rust-analyzer/crates/hir-expand/src/lib.rs+12-2| ... | ... | @@ -53,7 +53,7 @@ use crate::{ |
| 53 | 53 | }, |
| 54 | 54 | db::ExpandDatabase, |
| 55 | 55 | mod_path::ModPath, |
| 56 | proc_macro::{CustomProcMacroExpander, ProcMacroKind}, | |
| 56 | proc_macro::{CustomProcMacroExpander, ProcMacroKind, ProcMacros}, | |
| 57 | 57 | span_map::{ExpansionSpanMap, SpanMap}, |
| 58 | 58 | }; |
| 59 | 59 | |
| ... | ... | @@ -176,7 +176,7 @@ impl ExpandErrorKind { |
| 176 | 176 | kind: RenderedExpandError::DISABLED, |
| 177 | 177 | }, |
| 178 | 178 | &ExpandErrorKind::MissingProcMacroExpander(def_crate) => { |
| 179 | match db.proc_macros_for_crate(def_crate).as_ref().and_then(|it| it.get_error()) { | |
| 179 | match ProcMacros::get_for_crate(db, def_crate).and_then(|it| it.get_error()) { | |
| 180 | 180 | Some(e) => RenderedExpandError { |
| 181 | 181 | message: e.to_string(), |
| 182 | 182 | error: e.is_hard_error(), |
| ... | ... | @@ -1128,6 +1128,16 @@ impl HirFileId { |
| 1128 | 1128 | HirFileId::MacroFile(_) => None, |
| 1129 | 1129 | } |
| 1130 | 1130 | } |
| 1131 | ||
| 1132 | pub fn syntax_context(self, db: &dyn ExpandDatabase, edition: Edition) -> SyntaxContext { | |
| 1133 | match self { | |
| 1134 | HirFileId::FileId(_) => SyntaxContext::root(edition), | |
| 1135 | HirFileId::MacroFile(m) => { | |
| 1136 | let kind = &m.loc(db).kind; | |
| 1137 | db.macro_arg_considering_derives(m, kind).2.ctx | |
| 1138 | } | |
| 1139 | } | |
| 1140 | } | |
| 1131 | 1141 | } |
| 1132 | 1142 | |
| 1133 | 1143 | impl PartialEq<EditionedFileId> for HirFileId { |
src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs+27-14| ... | ... | @@ -7,6 +7,7 @@ use std::{panic::RefUnwindSafe, sync}; |
| 7 | 7 | use base_db::{Crate, CrateBuilderId, CratesIdMap, Env, ProcMacroLoadingError}; |
| 8 | 8 | use intern::Symbol; |
| 9 | 9 | use rustc_hash::FxHashMap; |
| 10 | use salsa::{Durability, Setter}; | |
| 10 | 11 | use span::Span; |
| 11 | 12 | use triomphe::Arc; |
| 12 | 13 | |
| ... | ... | @@ -83,14 +84,19 @@ impl ProcMacrosBuilder { |
| 83 | 84 | ); |
| 84 | 85 | } |
| 85 | 86 | |
| 86 | pub(crate) fn build(self, crates_id_map: &CratesIdMap) -> ProcMacros { | |
| 87 | /// Builds [`ProcMacros`] and adds id to `db` | |
| 88 | pub(crate) fn build_in(self, db: &mut dyn ExpandDatabase, crates_id_map: &CratesIdMap) { | |
| 87 | 89 | let mut map = self |
| 88 | 90 | .0 |
| 89 | 91 | .into_iter() |
| 90 | 92 | .map(|(krate, proc_macro)| (crates_id_map[&krate], proc_macro)) |
| 91 | 93 | .collect::<FxHashMap<_, _>>(); |
| 92 | 94 | map.shrink_to_fit(); |
| 93 | ProcMacros(map) | |
| 95 | ProcMacros::try_get(db) | |
| 96 | .unwrap_or_else(|| ProcMacros::new(db, Default::default())) | |
| 97 | .set_by_crate(db) | |
| 98 | .with_durability(Durability::HIGH) | |
| 99 | .to(map); | |
| 94 | 100 | } |
| 95 | 101 | } |
| 96 | 102 | |
| ... | ... | @@ -107,11 +113,25 @@ impl FromIterator<(CrateBuilderId, ProcMacroLoadResult)> for ProcMacrosBuilder { |
| 107 | 113 | #[derive(Debug, PartialEq, Eq)] |
| 108 | 114 | pub struct CrateProcMacros(StoredProcMacroLoadResult); |
| 109 | 115 | |
| 110 | #[derive(Default, Debug)] | |
| 111 | pub struct ProcMacros(FxHashMap<Crate, Arc<CrateProcMacros>>); | |
| 116 | /// The proc macros. Do not use [`Self::get`]! Use [`Self::get_for_crate`] instead. | |
| 117 | #[salsa::input(singleton, debug)] | |
| 118 | pub struct ProcMacros { | |
| 119 | #[returns(ref)] | |
| 120 | pub by_crate: FxHashMap<Crate, Arc<CrateProcMacros>>, | |
| 121 | } | |
| 122 | ||
| 112 | 123 | impl ProcMacros { |
| 113 | fn get(&self, krate: Crate) -> Option<Arc<CrateProcMacros>> { | |
| 114 | self.0.get(&krate).cloned() | |
| 124 | pub fn init_default(db: &dyn ExpandDatabase, durability: Durability) { | |
| 125 | _ = Self::builder(Default::default()).durability(durability).new(db); | |
| 126 | } | |
| 127 | } | |
| 128 | ||
| 129 | #[salsa::tracked] | |
| 130 | impl ProcMacros { | |
| 131 | /// Incrementality query to prevent queries from directly depending on [`Self::get`]. | |
| 132 | #[salsa::tracked(returns(as_ref))] | |
| 133 | pub fn get_for_crate(db: &dyn ExpandDatabase, krate: Crate) -> Option<Arc<CrateProcMacros>> { | |
| 134 | Self::get(db).by_crate(db).get(&krate).cloned() | |
| 115 | 135 | } |
| 116 | 136 | } |
| 117 | 137 | |
| ... | ... | @@ -276,7 +296,7 @@ impl CustomProcMacroExpander { |
| 276 | 296 | ExpandError::new(call_site, ExpandErrorKind::MacroDisabled), |
| 277 | 297 | ), |
| 278 | 298 | id => { |
| 279 | let proc_macros = match db.proc_macros_for_crate(def_crate) { | |
| 299 | let proc_macros = match ProcMacros::get_for_crate(db, def_crate) { | |
| 280 | 300 | Some(it) => it, |
| 281 | 301 | None => { |
| 282 | 302 | return ExpandResult::new( |
| ... | ... | @@ -347,10 +367,3 @@ impl CustomProcMacroExpander { |
| 347 | 367 | } |
| 348 | 368 | } |
| 349 | 369 | } |
| 350 | ||
| 351 | pub(crate) fn proc_macros_for_crate( | |
| 352 | db: &dyn ExpandDatabase, | |
| 353 | krate: Crate, | |
| 354 | ) -> Option<Arc<CrateProcMacros>> { | |
| 355 | db.proc_macros().get(krate) | |
| 356 | } |
src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs+4-4| ... | ... | @@ -63,8 +63,8 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe |
| 63 | 63 | // Unsafety in function parameter patterns (that can only be union destructuring) |
| 64 | 64 | // cannot be inserted into an unsafe block, so even with `unsafe_op_in_unsafe_fn` |
| 65 | 65 | // it is turned off for unsafe functions. |
| 66 | for &param in &body.params { | |
| 67 | visitor.walk_pat(param); | |
| 66 | for param in &body.params { | |
| 67 | visitor.walk_pat(param.formal); | |
| 68 | 68 | } |
| 69 | 69 | } |
| 70 | 70 | |
| ... | ... | @@ -112,8 +112,8 @@ pub fn unsafe_operations_for_body( |
| 112 | 112 | }; |
| 113 | 113 | let mut visitor = UnsafeVisitor::new(db, infer, body, def.into(), &mut visitor_callback); |
| 114 | 114 | visitor.walk_expr(body.root_expr()); |
| 115 | for &param in &body.params { | |
| 116 | visitor.walk_pat(param); | |
| 115 | for param in &body.params { | |
| 116 | visitor.walk_pat(param.formal); | |
| 117 | 117 | } |
| 118 | 118 | } |
| 119 | 119 |
src/tools/rust-analyzer/crates/hir-ty/src/display.rs+17-10| ... | ... | @@ -746,26 +746,33 @@ impl<'db> HirDisplay<'db> for Const<'db> { |
| 746 | 746 | ConstKind::Value(value) => render_const_scalar_from_valtree(f, value.ty, value.value), |
| 747 | 747 | ConstKind::Unevaluated(unev) => { |
| 748 | 748 | let c = unev.def.0; |
| 749 | match c { | |
| 750 | GeneralConstId::ConstId(id) => match &ConstSignature::of(f.db, id).name { | |
| 751 | Some(name) => { | |
| 752 | f.start_location_link(id.into()); | |
| 753 | write!(f, "{}", name.display(f.db, f.edition()))?; | |
| 754 | f.end_location_link(); | |
| 749 | let generic_def = match c { | |
| 750 | GeneralConstId::ConstId(id) => { | |
| 751 | match &ConstSignature::of(f.db, id).name { | |
| 752 | Some(name) => { | |
| 753 | f.start_location_link(id.into()); | |
| 754 | write!(f, "{}", name.display(f.db, f.edition()))?; | |
| 755 | f.end_location_link(); | |
| 756 | } | |
| 757 | None => f.write_str("_")?, | |
| 755 | 758 | } |
| 756 | None => f.write_str("_")?, | |
| 757 | }, | |
| 759 | Some(id.into()) | |
| 760 | } | |
| 758 | 761 | GeneralConstId::StaticId(id) => { |
| 759 | 762 | let name = &StaticSignature::of(f.db, id).name; |
| 760 | 763 | f.start_location_link(id.into()); |
| 761 | 764 | write!(f, "{}", name.display(f.db, f.edition()))?; |
| 762 | 765 | f.end_location_link(); |
| 766 | Some(id.into()) | |
| 763 | 767 | } |
| 764 | 768 | GeneralConstId::AnonConstId(_) => { |
| 765 | f.write_str(if f.display_kind.is_source_code() { "_" } else { "{const}" })? | |
| 769 | f.write_str(if f.display_kind.is_source_code() { "_" } else { "{const}" })?; | |
| 770 | None | |
| 766 | 771 | } |
| 767 | 772 | }; |
| 768 | hir_fmt_generics(f, unev.args.as_slice(), c.generic_def(f.db), None)?; | |
| 773 | if let Some(generic_def) = generic_def { | |
| 774 | hir_fmt_generics(f, unev.args.as_slice(), Some(generic_def), None)?; | |
| 775 | } | |
| 769 | 776 | Ok(()) |
| 770 | 777 | } |
| 771 | 778 | ConstKind::Error(..) => f.write_char('_'), |
src/tools/rust-analyzer/crates/hir-ty/src/generics.rs+1-1| ... | ... | @@ -143,7 +143,7 @@ impl<'db> Generics<'db> { |
| 143 | 143 | self.chain.iter() |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | fn owner(&self) -> &SingleGenerics<'db> { | |
| 146 | pub(crate) fn owner(&self) -> &SingleGenerics<'db> { | |
| 147 | 147 | self.chain.last().expect("must have an owner params") |
| 148 | 148 | } |
| 149 | 149 |
src/tools/rust-analyzer/crates/hir-ty/src/infer.rs+27-4| ... | ... | @@ -44,7 +44,7 @@ use hir_def::{ |
| 44 | 44 | FunctionId, GenericDefId, GenericParamId, HasModule, LocalFieldId, Lookup, StaticId, TraitId, |
| 45 | 45 | TupleFieldId, TupleId, VariantId, |
| 46 | 46 | attrs::AttrFlags, |
| 47 | expr_store::{Body, ExpressionStore, HygieneId, path::Path}, | |
| 47 | expr_store::{Body, ExpressionStore, HygieneId, body::Param, path::Path}, | |
| 48 | 48 | hir::{BindingId, ExprId, ExprOrPatId, LabelId, PatId}, |
| 49 | 49 | lang_item::LangItems, |
| 50 | 50 | layout::Integer, |
| ... | ... | @@ -145,7 +145,9 @@ pub fn infer_query_with_inspect<'db>( |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | match def { |
| 148 | DefWithBodyId::FunctionId(f) => ctx.collect_fn(f, body.self_param(), &body.params), | |
| 148 | DefWithBodyId::FunctionId(f) => { | |
| 149 | ctx.collect_fn(f, body.self_param.map(|param| param.formal), &body.params) | |
| 150 | } | |
| 149 | 151 | DefWithBodyId::ConstId(c) => ctx.collect_const(c, ConstSignature::of(db, c)), |
| 150 | 152 | DefWithBodyId::StaticId(s) => ctx.collect_static(s, StaticSignature::of(db, s)), |
| 151 | 153 | DefWithBodyId::VariantId(v) => { |
| ... | ... | @@ -379,6 +381,14 @@ pub enum InferenceDiagnostic { |
| 379 | 381 | #[type_visitable(ignore)] |
| 380 | 382 | variant: VariantId, |
| 381 | 383 | }, |
| 384 | UnionPatMustHaveExactlyOneField { | |
| 385 | #[type_visitable(ignore)] | |
| 386 | pat: PatId, | |
| 387 | }, | |
| 388 | UnionPatHasRest { | |
| 389 | #[type_visitable(ignore)] | |
| 390 | pat: PatId, | |
| 391 | }, | |
| 382 | 392 | FunctionalRecordUpdateOnNonStruct { |
| 383 | 393 | #[type_visitable(ignore)] |
| 384 | 394 | base_expr: ExprId, |
| ... | ... | @@ -409,6 +419,10 @@ pub enum InferenceDiagnostic { |
| 409 | 419 | expr: ExprId, |
| 410 | 420 | found: StoredTy, |
| 411 | 421 | }, |
| 422 | MutRefInImmRefPat { | |
| 423 | #[type_visitable(ignore)] | |
| 424 | pat: PatId, | |
| 425 | }, | |
| 412 | 426 | CannotImplicitlyDerefTraitObject { |
| 413 | 427 | #[type_visitable(ignore)] |
| 414 | 428 | pat: PatId, |
| ... | ... | @@ -504,6 +518,10 @@ pub enum InferenceDiagnostic { |
| 504 | 518 | #[type_visitable(ignore)] |
| 505 | 519 | pat: PatId, |
| 506 | 520 | }, |
| 521 | YieldOutsideCoroutine { | |
| 522 | #[type_visitable(ignore)] | |
| 523 | expr: ExprId, | |
| 524 | }, | |
| 507 | 525 | } |
| 508 | 526 | |
| 509 | 527 | #[derive(Debug, PartialEq, Eq, Clone)] |
| ... | ... | @@ -1691,7 +1709,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> { |
| 1691 | 1709 | self.return_ty = return_ty; |
| 1692 | 1710 | } |
| 1693 | 1711 | |
| 1694 | fn collect_fn(&mut self, func: FunctionId, self_param: Option<BindingId>, params: &[PatId]) { | |
| 1712 | fn collect_fn( | |
| 1713 | &mut self, | |
| 1714 | func: FunctionId, | |
| 1715 | self_param: Option<BindingId>, | |
| 1716 | params: &[Param<PatId>], | |
| 1717 | ) { | |
| 1695 | 1718 | let data = FunctionSignature::of(self.db, func); |
| 1696 | 1719 | let mut param_tys = self.with_ty_lowering( |
| 1697 | 1720 | &data.store, |
| ... | ... | @@ -1730,7 +1753,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { |
| 1730 | 1753 | let ty = param_tys.next().unwrap_or_else(|| self.table.next_ty_var(Span::Dummy)); |
| 1731 | 1754 | let ty = self.process_user_written_ty(ty); |
| 1732 | 1755 | |
| 1733 | self.infer_top_pat(*pat, ty, PatOrigin::Param); | |
| 1756 | self.infer_top_pat(pat.formal, ty, PatOrigin::Param); | |
| 1734 | 1757 | } |
| 1735 | 1758 | self.return_ty = match data.ret_type { |
| 1736 | 1759 | Some(return_ty) => { |
src/tools/rust-analyzer/crates/hir-ty/src/infer/callee.rs+1-7| ... | ... | @@ -585,13 +585,7 @@ impl<'a, 'db> DeferredCallResolution<'db> { |
| 585 | 585 | method_callee.args, |
| 586 | 586 | ); |
| 587 | 587 | } |
| 588 | None => { | |
| 589 | assert!( | |
| 590 | ctx.lang_items.FnOnce.is_none(), | |
| 591 | "Expected to find a suitable `Fn`/`FnMut`/`FnOnce` implementation for `{:?}`", | |
| 592 | self.closure_ty | |
| 593 | ) | |
| 594 | } | |
| 588 | None => {} | |
| 595 | 589 | } |
| 596 | 590 | } |
| 597 | 591 | } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs+3-1| ... | ... | @@ -597,7 +597,9 @@ impl<'db> InferenceContext<'_, 'db> { |
| 597 | 597 | } |
| 598 | 598 | resume_ty |
| 599 | 599 | } else { |
| 600 | // FIXME: report error (yield expr in non-coroutine) | |
| 600 | self.push_diagnostic(InferenceDiagnostic::YieldOutsideCoroutine { | |
| 601 | expr: tgt_expr, | |
| 602 | }); | |
| 601 | 603 | self.types.types.error |
| 602 | 604 | } |
| 603 | 605 | } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs+3-3| ... | ... | @@ -916,7 +916,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { |
| 916 | 916 | if matches!(bm.0, ByRef::Yes(Mutability::Mut)) |
| 917 | 917 | && let MutblCap::WeaklyNot = pat_info.max_ref_mutbl |
| 918 | 918 | { |
| 919 | // FIXME: Emit an error: cannot borrow as mutable inside an `&` pattern. | |
| 919 | self.push_diagnostic(InferenceDiagnostic::MutRefInImmRefPat { pat }); | |
| 920 | 920 | } |
| 921 | 921 | |
| 922 | 922 | // ...and store it in a side table: |
| ... | ... | @@ -1242,10 +1242,10 @@ impl<'a, 'db> InferenceContext<'a, 'db> { |
| 1242 | 1242 | // Report an error if an incorrect number of fields was specified. |
| 1243 | 1243 | if matches!(variant, VariantId::UnionId(_)) { |
| 1244 | 1244 | if fields.len() != 1 { |
| 1245 | // FIXME: Emit an error, unions can't have more than one field. | |
| 1245 | self.push_diagnostic(InferenceDiagnostic::UnionPatMustHaveExactlyOneField { pat }); | |
| 1246 | 1246 | } |
| 1247 | 1247 | if has_rest_pat { |
| 1248 | // FIXME: Emit an error, unions can't have a rest pat. | |
| 1248 | self.push_diagnostic(InferenceDiagnostic::UnionPatHasRest { pat }); | |
| 1249 | 1249 | } |
| 1250 | 1250 | } else if !unmentioned_fields.is_empty() && !has_rest_pat { |
| 1251 | 1251 | // FIXME: Emit an error. |
src/tools/rust-analyzer/crates/hir-ty/src/lower.rs+9-4| ... | ... | @@ -290,6 +290,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 290 | 290 | self.lifetime_elision = lifetime_elision; |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | pub(crate) fn set_owner(&mut self, owner: &'a SingleGenerics<'db>) { | |
| 294 | self.store = owner.store(); | |
| 295 | self.def = ExpressionStoreOwnerId::Signature(owner.def()); | |
| 296 | } | |
| 297 | ||
| 293 | 298 | pub(crate) fn with_interning_mode(mut self, interning_mode: LoweringMode) -> Self { |
| 294 | 299 | self.interning_mode = interning_mode; |
| 295 | 300 | self |
| ... | ... | @@ -1948,7 +1953,7 @@ fn resolve_type_param_assoc_type_shorthand( |
| 1948 | 1953 | |
| 1949 | 1954 | let mut supertraits_resolution = None; |
| 1950 | 1955 | for maybe_parent_generics in generics.iter_owners().rev() { |
| 1951 | ctx.store = maybe_parent_generics.store(); | |
| 1956 | ctx.set_owner(maybe_parent_generics); | |
| 1952 | 1957 | for pred in maybe_parent_generics.where_predicates() { |
| 1953 | 1958 | let (WherePredicate::TypeBound { target, bound } |
| 1954 | 1959 | | WherePredicate::ForLifetime { lifetimes: _, target, bound }) = pred |
| ... | ... | @@ -2366,7 +2371,7 @@ fn generic_predicates( |
| 2366 | 2371 | // Collect only diagnostics from the child, not including parents. |
| 2367 | 2372 | ctx.diagnostics.clear(); |
| 2368 | 2373 | |
| 2369 | ctx.store = maybe_parent_generics.store(); | |
| 2374 | ctx.set_owner(maybe_parent_generics); | |
| 2370 | 2375 | for pred in maybe_parent_generics.where_predicates() { |
| 2371 | 2376 | tracing::debug!(?pred); |
| 2372 | 2377 | for (pred, source) in ctx.lower_where_predicate(pred, false) { |
| ... | ... | @@ -2568,14 +2573,14 @@ pub(crate) fn generic_defaults_with_diagnostics( |
| 2568 | 2573 | let generics = generics.get().unwrap(); |
| 2569 | 2574 | let mut defaults = ThinVec::new(); |
| 2570 | 2575 | if let Some(parent) = generics.parent() { |
| 2571 | ctx.store = parent.store(); | |
| 2576 | ctx.set_owner(parent); | |
| 2572 | 2577 | defaults.extend( |
| 2573 | 2578 | parent.iter_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)), |
| 2574 | 2579 | ); |
| 2575 | 2580 | } |
| 2576 | 2581 | ctx.diagnostics.clear(); // Don't include diagnostics from the parent. |
| 2577 | 2582 | ctx.defined_anon_consts.clear(); |
| 2578 | ctx.store = store_for_self; | |
| 2583 | ctx.set_owner(generics.owner()); | |
| 2579 | 2584 | defaults.extend( |
| 2580 | 2585 | generics.iter_self_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)), |
| 2581 | 2586 | ); |
src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs+25| ... | ... | @@ -728,7 +728,13 @@ impl TraitImpls { |
| 728 | 728 | { |
| 729 | 729 | continue; |
| 730 | 730 | } |
| 731 | ||
| 731 | 732 | let self_ty = trait_ref.self_ty(); |
| 733 | if self_ty_has_error_constructor(self_ty) { | |
| 734 | // If we see `impl Foo for NoSuchType`, just ignore it. | |
| 735 | continue; | |
| 736 | } | |
| 737 | ||
| 732 | 738 | let interner = DbInterner::new_no_crate(db); |
| 733 | 739 | let entry = map.entry(trait_ref.def_id.0).or_default(); |
| 734 | 740 | match simplify_type(interner, self_ty, TreatParams::InstantiateWithInfer) { |
| ... | ... | @@ -864,3 +870,22 @@ impl TraitImpls { |
| 864 | 870 | } |
| 865 | 871 | } |
| 866 | 872 | } |
| 873 | ||
| 874 | fn self_ty_has_error_constructor<'db>(mut self_ty: Ty<'db>) -> bool { | |
| 875 | if !self_ty.references_non_lt_error() { | |
| 876 | return false; | |
| 877 | } | |
| 878 | ||
| 879 | loop { | |
| 880 | self_ty = match self_ty.kind() { | |
| 881 | TyKind::Error(_) => return true, | |
| 882 | TyKind::Ref(_, inner, _) | |
| 883 | | TyKind::RawPtr(inner, _) | |
| 884 | | TyKind::Array(inner, _) | |
| 885 | | TyKind::Slice(inner) | |
| 886 | | TyKind::Pat(inner, _) => inner, | |
| 887 | TyKind::UnsafeBinder(inner) => inner.skip_binder(), | |
| 888 | _ => return false, | |
| 889 | }; | |
| 890 | } | |
| 891 | } |
src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs+20-5| ... | ... | @@ -3046,7 +3046,7 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { |
| 3046 | 3046 | ty: Ty<'db>, |
| 3047 | 3047 | locals: &Locals<'a>, |
| 3048 | 3048 | addr: Address, |
| 3049 | _metadata: &[u8], | |
| 3049 | metadata: &[u8], | |
| 3050 | 3050 | span: MirSpan, |
| 3051 | 3051 | ) -> Result<'db, ()> { |
| 3052 | 3052 | let Some(drop_fn) = self.lang_items().Drop_drop else { |
| ... | ... | @@ -3056,13 +3056,23 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { |
| 3056 | 3056 | }; |
| 3057 | 3057 | |
| 3058 | 3058 | let generic_args = GenericArgs::new_from_slice(&[ty.into()]); |
| 3059 | if let Ok(MirOrDynIndex::Mir(body)) = | |
| 3060 | self.get_mir_or_dyn_index(drop_fn, generic_args, locals, span) | |
| 3059 | let (drop_impl, drop_args) = self.db.lookup_impl_method( | |
| 3060 | ParamEnvAndCrate { param_env: self.param_env.param_env, krate: self.crate_id }, | |
| 3061 | drop_fn, | |
| 3062 | generic_args, | |
| 3063 | ); | |
| 3064 | if let Either::Left(drop_impl) = drop_impl | |
| 3065 | && matches!(drop_impl.lookup(self.db).container, ItemContainerId::ImplId(_)) | |
| 3066 | && let Ok(body) = self.db.monomorphized_mir_body( | |
| 3067 | drop_impl.into(), | |
| 3068 | drop_args.store(), | |
| 3069 | self.param_env.store(), | |
| 3070 | ) | |
| 3061 | 3071 | { |
| 3062 | 3072 | self.exec_looked_up_function( |
| 3063 | 3073 | body, |
| 3064 | 3074 | locals, |
| 3065 | drop_fn, | |
| 3075 | drop_impl, | |
| 3066 | 3076 | iter::once(IntervalOrOwned::Owned(addr.to_bytes().to_vec())), |
| 3067 | 3077 | span, |
| 3068 | 3078 | Interval { addr: Address::Invalid(0), size: 0 }, |
| ... | ... | @@ -3103,6 +3113,12 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { |
| 3103 | 3113 | AdtId::EnumId(_) => (), |
| 3104 | 3114 | } |
| 3105 | 3115 | } |
| 3116 | TyKind::Dynamic(..) => { | |
| 3117 | if !metadata.is_empty() { | |
| 3118 | let concrete_ty = self.vtable_map.ty_of_bytes(metadata)?; | |
| 3119 | self.run_drop_glue_deep(concrete_ty, locals, addr, &[], span)?; | |
| 3120 | } | |
| 3121 | } | |
| 3106 | 3122 | TyKind::Bool |
| 3107 | 3123 | | TyKind::Char |
| 3108 | 3124 | | TyKind::Int(_) |
| ... | ... | @@ -3125,7 +3141,6 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { |
| 3125 | 3141 | | TyKind::Error(_) |
| 3126 | 3142 | | TyKind::Param(_) |
| 3127 | 3143 | | TyKind::Placeholder(_) |
| 3128 | | TyKind::Dynamic(..) | |
| 3129 | 3144 | | TyKind::FnPtr(..) |
| 3130 | 3145 | | TyKind::Bound(..) |
| 3131 | 3146 | | TyKind::Infer(..) |
src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs+51| ... | ... | @@ -229,6 +229,28 @@ fn main() { |
| 229 | 229 | ); |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | #[test] | |
| 233 | fn drop_glue_for_type_without_drop_impl_does_not_recurse() { | |
| 234 | check_pass( | |
| 235 | r#" | |
| 236 | //- minicore: drop, pin | |
| 237 | ||
| 238 | struct HasDrop; | |
| 239 | impl Drop for HasDrop { | |
| 240 | fn drop(&mut self) {} | |
| 241 | } | |
| 242 | ||
| 243 | struct WithDropGlue { | |
| 244 | field: HasDrop, | |
| 245 | } | |
| 246 | ||
| 247 | fn main() { | |
| 248 | let _c = WithDropGlue { field: HasDrop }; | |
| 249 | } | |
| 250 | "#, | |
| 251 | ); | |
| 252 | } | |
| 253 | ||
| 232 | 254 | #[test] |
| 233 | 255 | fn drop_if_let() { |
| 234 | 256 | check_pass( |
| ... | ... | @@ -358,6 +380,35 @@ fn main() { |
| 358 | 380 | ); |
| 359 | 381 | } |
| 360 | 382 | |
| 383 | #[test] | |
| 384 | fn drop_glue_for_trait_object() { | |
| 385 | check_panic( | |
| 386 | r#" | |
| 387 | //- minicore: manually_drop, coerce_unsized, fmt, panic, drop, pin | |
| 388 | use core::mem::ManuallyDrop; | |
| 389 | use core::ptr::drop_in_place; | |
| 390 | ||
| 391 | struct X; | |
| 392 | impl Drop for X { | |
| 393 | fn drop(&mut self) { | |
| 394 | panic!("concrete drop ran"); | |
| 395 | } | |
| 396 | } | |
| 397 | ||
| 398 | trait T {} | |
| 399 | impl T for X {} | |
| 400 | ||
| 401 | fn main() { | |
| 402 | let mut x = ManuallyDrop::new(X); | |
| 403 | let p = &mut x as *mut ManuallyDrop<X> as *mut X; | |
| 404 | let obj: &mut dyn T = unsafe { &mut *p }; | |
| 405 | drop_in_place(obj); | |
| 406 | } | |
| 407 | "#, | |
| 408 | "concrete drop ran", | |
| 409 | ); | |
| 410 | } | |
| 411 | ||
| 361 | 412 | #[test] |
| 362 | 413 | fn manually_drop() { |
| 363 | 414 | check_pass( |
src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs+4-4| ... | ... | @@ -6,7 +6,7 @@ use base_db::Crate; |
| 6 | 6 | use hir_def::{ |
| 7 | 7 | AdtId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId, GenericParamId, HasModule, |
| 8 | 8 | ItemContainerId, LocalFieldId, Lookup, TraitId, |
| 9 | expr_store::{Body, ExpressionStore, HygieneId, path::Path}, | |
| 9 | expr_store::{Body, ExpressionStore, HygieneId, body::Param, path::Path}, | |
| 10 | 10 | hir::{ |
| 11 | 11 | ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ClosureKind, ExprId, ExprOrPatId, |
| 12 | 12 | LabelId, Literal, MatchArm, Pat, PatId, RecordLitField, RecordSpread, |
| ... | ... | @@ -2312,7 +2312,7 @@ pub fn mir_body_query<'db>(db: &'db dyn HirDatabase, def: InferBodyId) -> Result |
| 2312 | 2312 | let (store, root_expr, self_param, params) = match def { |
| 2313 | 2313 | InferBodyId::DefWithBodyId(def) => { |
| 2314 | 2314 | let body = Body::of(db, def); |
| 2315 | (&**body, body.root_expr(), body.self_param(), &*body.params) | |
| 2315 | (&**body, body.root_expr(), body.self_param.map(|param| param.formal), &*body.params) | |
| 2316 | 2316 | } |
| 2317 | 2317 | InferBodyId::AnonConstId(def) => { |
| 2318 | 2318 | let loc = def.loc(db); |
| ... | ... | @@ -2351,7 +2351,7 @@ pub fn lower_body_to_mir<'db>( |
| 2351 | 2351 | infer: &InferenceResult, |
| 2352 | 2352 | root_expr: ExprId, |
| 2353 | 2353 | self_param: Option<BindingId>, |
| 2354 | params: &[PatId], | |
| 2354 | params: &[Param<PatId>], | |
| 2355 | 2355 | ) -> Result<'db, MirBody> { |
| 2356 | 2356 | // Extract params and self_param only when lowering the body's root expression for a function. |
| 2357 | 2357 | if let Some(fid) = owner.as_function() { |
| ... | ... | @@ -2366,7 +2366,7 @@ pub fn lower_body_to_mir<'db>( |
| 2366 | 2366 | store, |
| 2367 | 2367 | infer, |
| 2368 | 2368 | root_expr, |
| 2369 | params.iter().copied().zip(param_tys), | |
| 2369 | params.iter().map(|param| param.formal).zip(param_tys), | |
| 2370 | 2370 | self_param, |
| 2371 | 2371 | ) |
| 2372 | 2372 | } else { |
src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs+2-2| ... | ... | @@ -7,7 +7,7 @@ use base_db::{ |
| 7 | 7 | SourceRootId, SourceRootInput, all_crates, relevant_crates, set_all_crates_with_durability, |
| 8 | 8 | }; |
| 9 | 9 | |
| 10 | use hir_def::{ModuleId, db::DefDatabase, nameres::crate_def_map}; | |
| 10 | use hir_def::{ModuleId, nameres::crate_def_map}; | |
| 11 | 11 | use hir_expand::EditionedFileId; |
| 12 | 12 | use rustc_hash::FxHashMap; |
| 13 | 13 | use salsa::Durability; |
| ... | ... | @@ -43,7 +43,7 @@ impl Default for TestDB { |
| 43 | 43 | crates_map: Default::default(), |
| 44 | 44 | nonce: Nonce::new(), |
| 45 | 45 | }; |
| 46 | this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); | |
| 46 | hir_def::db::set_expand_proc_attr_macros(&mut this, true); | |
| 47 | 47 | // This needs to be here otherwise `CrateGraphBuilder` panics. |
| 48 | 48 | set_all_crates_with_durability(&mut this, std::iter::empty(), Durability::HIGH); |
| 49 | 49 | _ = base_db::LibraryRoots::builder(Default::default()) |
src/tools/rust-analyzer/crates/hir-ty/src/tests.rs+2-1| ... | ... | @@ -514,7 +514,8 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { |
| 514 | 514 | for (def, krate) in defs { |
| 515 | 515 | let (body, source_map) = Body::with_source_map(&db, def); |
| 516 | 516 | let infer = InferenceResult::of(&db, def); |
| 517 | let self_param = body.self_param().map(|id| (id, source_map.self_param_syntax())); | |
| 517 | let self_param = | |
| 518 | body.self_param.map(|param| (param.formal, source_map.self_param_syntax())); | |
| 518 | 519 | infer_def(infer, body, source_map, self_param, krate); |
| 519 | 520 | } |
| 520 | 521 |
src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs+1-1| ... | ... | @@ -102,7 +102,7 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec |
| 102 | 102 | |
| 103 | 103 | // FIXME: Deduplicate this with hir::Local::sources(). |
| 104 | 104 | let captured_local = capture.captured_local(); |
| 105 | let local_text_range = if body.self_params.contains(&captured_local) | |
| 105 | let local_text_range = if body.is_any_self_param(captured_local) | |
| 106 | 106 | && let Some(source) = source_map.self_param_syntax() |
| 107 | 107 | { |
| 108 | 108 | format!("{:?}", text_range(db, source)) |
src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs+27| ... | ... | @@ -2258,3 +2258,30 @@ fn main() { |
| 2258 | 2258 | "#, |
| 2259 | 2259 | ); |
| 2260 | 2260 | } |
| 2261 | ||
| 2262 | #[test] | |
| 2263 | fn trait_impl_with_error_self_ty_does_not_match_arbitrary_receiver() { | |
| 2264 | check_types( | |
| 2265 | r#" | |
| 2266 | //- minicore: sized | |
| 2267 | trait UnrelatedTrait { | |
| 2268 | fn take(self) {} | |
| 2269 | } | |
| 2270 | ||
| 2271 | struct MyOption<T>(T); | |
| 2272 | ||
| 2273 | impl<T> MyOption<T> { | |
| 2274 | fn take(&mut self) -> MyOption<T> { | |
| 2275 | loop {} | |
| 2276 | } | |
| 2277 | } | |
| 2278 | ||
| 2279 | fn f<T>(mut o: MyOption<T>) { | |
| 2280 | let value = o.take(); | |
| 2281 | //^^^^^ MyOption<T> | |
| 2282 | } | |
| 2283 | ||
| 2284 | impl UnrelatedTrait for &'_ MissingType {} | |
| 2285 | "#, | |
| 2286 | ); | |
| 2287 | } |
src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs+32| ... | ... | @@ -43,6 +43,26 @@ fn no_panic_on_field_of_enum() { |
| 43 | 43 | ); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | #[test] | |
| 47 | fn anon_const_projection_in_impl_predicate() { | |
| 48 | check_no_mismatches( | |
| 49 | r#" | |
| 50 | trait Trait { | |
| 51 | type Assoc; | |
| 52 | } | |
| 53 | ||
| 54 | struct S<const N: usize>; | |
| 55 | ||
| 56 | impl<const N: usize> S<N> | |
| 57 | where | |
| 58 | S<{ N }>: Trait, | |
| 59 | { | |
| 60 | fn new(_: <S<N> as Trait>::Assoc) {} | |
| 61 | } | |
| 62 | "#, | |
| 63 | ); | |
| 64 | } | |
| 65 | ||
| 46 | 66 | #[test] |
| 47 | 67 | fn bug_585() { |
| 48 | 68 | check_infer( |
| ... | ... | @@ -2915,3 +2935,15 @@ impl Foo for Bar { |
| 2915 | 2935 | "#, |
| 2916 | 2936 | ); |
| 2917 | 2937 | } |
| 2938 | ||
| 2939 | #[test] | |
| 2940 | fn regression_unresolved_deferred_closure_call_resolution() { | |
| 2941 | check_no_mismatches( | |
| 2942 | r#" | |
| 2943 | //- minicore: fn | |
| 2944 | fn caller() { | |
| 2945 | let _: &[u8] = &(|| encode_fn())(); | |
| 2946 | } | |
| 2947 | "#, | |
| 2948 | ); | |
| 2949 | } |
src/tools/rust-analyzer/crates/hir/src/db.rs+1-1| ... | ... | @@ -3,6 +3,6 @@ |
| 3 | 3 | //! we didn't do that. |
| 4 | 4 | //! |
| 5 | 5 | //! But we need this for at least LRU caching at the query level. |
| 6 | pub use hir_def::db::DefDatabase; | |
| 6 | pub use hir_def::db::{DefDatabase, set_expand_proc_attr_macros}; | |
| 7 | 7 | pub use hir_expand::db::ExpandDatabase; |
| 8 | 8 | pub use hir_ty::db::HirDatabase; |
src/tools/rust-analyzer/crates/hir/src/diagnostics.rs+39| ... | ... | @@ -135,6 +135,7 @@ diagnostics![AnyDiagnostic<'db> -> |
| 135 | 135 | MissingMatchArms, |
| 136 | 136 | MissingUnsafe, |
| 137 | 137 | MovedOutOfRef<'db>, |
| 138 | MutRefInImmRefPat, | |
| 138 | 139 | MutableRefBinding, |
| 139 | 140 | NeedMut, |
| 140 | 141 | NonExhaustiveLet, |
| ... | ... | @@ -176,7 +177,10 @@ diagnostics![AnyDiagnostic<'db> -> |
| 176 | 177 | ElidedLifetimesInPath, |
| 177 | 178 | TypeMustBeKnown<'db>, |
| 178 | 179 | UnionExprMustHaveExactlyOneField, |
| 180 | UnionPatMustHaveExactlyOneField, | |
| 181 | UnionPatHasRest, | |
| 179 | 182 | UnimplementedTrait<'db>, |
| 183 | YieldOutsideCoroutine, | |
| 180 | 184 | ]; |
| 181 | 185 | |
| 182 | 186 | #[derive(Debug)] |
| ... | ... | @@ -337,6 +341,11 @@ pub struct CannotBeDereferenced<'db> { |
| 337 | 341 | pub found: Type<'db>, |
| 338 | 342 | } |
| 339 | 343 | |
| 344 | #[derive(Debug)] | |
| 345 | pub struct MutRefInImmRefPat { | |
| 346 | pub pat: InFile<ExprOrPatPtr>, | |
| 347 | } | |
| 348 | ||
| 340 | 349 | #[derive(Debug)] |
| 341 | 350 | pub struct CannotImplicitlyDerefTraitObject<'db> { |
| 342 | 351 | pub pat: InFile<ExprOrPatPtr>, |
| ... | ... | @@ -638,6 +647,16 @@ pub struct UnionExprMustHaveExactlyOneField { |
| 638 | 647 | pub expr: InFile<ExprOrPatPtr>, |
| 639 | 648 | } |
| 640 | 649 | |
| 650 | #[derive(Debug)] | |
| 651 | pub struct UnionPatMustHaveExactlyOneField { | |
| 652 | pub pat: InFile<ExprOrPatPtr>, | |
| 653 | } | |
| 654 | ||
| 655 | #[derive(Debug)] | |
| 656 | pub struct UnionPatHasRest { | |
| 657 | pub pat: InFile<ExprOrPatPtr>, | |
| 658 | } | |
| 659 | ||
| 641 | 660 | #[derive(Debug)] |
| 642 | 661 | pub struct InvalidLhsOfAssignment { |
| 643 | 662 | pub lhs: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>, |
| ... | ... | @@ -665,6 +684,11 @@ pub struct MutableRefBinding { |
| 665 | 684 | pub pat: InFile<ExprOrPatPtr>, |
| 666 | 685 | } |
| 667 | 686 | |
| 687 | #[derive(Debug)] | |
| 688 | pub struct YieldOutsideCoroutine { | |
| 689 | pub expr: InFile<ExprOrPatPtr>, | |
| 690 | } | |
| 691 | ||
| 668 | 692 | impl<'db> AnyDiagnostic<'db> { |
| 669 | 693 | pub(crate) fn body_validation_diagnostic( |
| 670 | 694 | db: &'db dyn HirDatabase, |
| ... | ... | @@ -932,6 +956,14 @@ impl<'db> AnyDiagnostic<'db> { |
| 932 | 956 | let pat = pat_syntax(pat)?.map(Into::into); |
| 933 | 957 | NonExhaustiveRecordPat { pat, variant: variant.into() }.into() |
| 934 | 958 | } |
| 959 | &InferenceDiagnostic::UnionPatMustHaveExactlyOneField { pat } => { | |
| 960 | let pat = pat_syntax(pat)?.map(Into::into); | |
| 961 | UnionPatMustHaveExactlyOneField { pat }.into() | |
| 962 | } | |
| 963 | &InferenceDiagnostic::UnionPatHasRest { pat } => { | |
| 964 | let pat = pat_syntax(pat)?.map(Into::into); | |
| 965 | UnionPatHasRest { pat }.into() | |
| 966 | } | |
| 935 | 967 | &InferenceDiagnostic::FunctionalRecordUpdateOnNonStruct { base_expr } => { |
| 936 | 968 | FunctionalRecordUpdateOnNonStruct { base_expr: expr_syntax(base_expr)? }.into() |
| 937 | 969 | } |
| ... | ... | @@ -960,6 +992,10 @@ impl<'db> AnyDiagnostic<'db> { |
| 960 | 992 | let expr = expr_syntax(*expr)?; |
| 961 | 993 | CannotBeDereferenced { expr, found: new_ty(found.as_ref()) }.into() |
| 962 | 994 | } |
| 995 | InferenceDiagnostic::MutRefInImmRefPat { pat } => { | |
| 996 | let pat = pat_syntax(*pat)?.map(Into::into); | |
| 997 | MutRefInImmRefPat { pat }.into() | |
| 998 | } | |
| 963 | 999 | InferenceDiagnostic::CannotImplicitlyDerefTraitObject { pat, found } => { |
| 964 | 1000 | let pat = pat_syntax(*pat)?.map(Into::into); |
| 965 | 1001 | CannotImplicitlyDerefTraitObject { pat, found: new_ty(found.as_ref()) }.into() |
| ... | ... | @@ -1092,6 +1128,9 @@ impl<'db> AnyDiagnostic<'db> { |
| 1092 | 1128 | let pat = pat_syntax(*pat)?.map(Into::into); |
| 1093 | 1129 | MutableRefBinding { pat }.into() |
| 1094 | 1130 | } |
| 1131 | &InferenceDiagnostic::YieldOutsideCoroutine { expr } => { | |
| 1132 | YieldOutsideCoroutine { expr: expr_syntax(expr)? }.into() | |
| 1133 | } | |
| 1095 | 1134 | }) |
| 1096 | 1135 | } |
| 1097 | 1136 |
src/tools/rust-analyzer/crates/hir/src/display.rs+1-1| ... | ... | @@ -217,7 +217,7 @@ fn write_function<'db>(f: &mut HirFormatter<'_, 'db>, func_id: FunctionId) -> Re |
| 217 | 217 | first = false; |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | let pat_id = body.params[param.idx - body.self_param().is_some() as usize]; | |
| 220 | let pat_id = body.params[param.idx - body.self_param.is_some() as usize].user_written; | |
| 221 | 221 | let pat_str = body.pretty_print_pat(db, owner, pat_id, true, f.edition()); |
| 222 | 222 | f.write_str(&pat_str)?; |
| 223 | 223 |
src/tools/rust-analyzer/crates/hir/src/lib.rs+14-17| ... | ... | @@ -1188,21 +1188,18 @@ fn emit_macro_def_diagnostics<'db>( |
| 1188 | 1188 | m: Macro, |
| 1189 | 1189 | ) { |
| 1190 | 1190 | let id = db.macro_def(m.id); |
| 1191 | if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) | |
| 1191 | let krate = id.krate; | |
| 1192 | if let hir_expand::MacroDefKind::Declarative(ast, _) = id.kind | |
| 1193 | && let expander = db.decl_macro_expander(krate, ast) | |
| 1192 | 1194 | && let Some(e) = expander.mac.err() |
| 1193 | 1195 | { |
| 1194 | let Some(ast) = id.ast_id().left() else { | |
| 1195 | never!("declarative expander for non decl-macro: {:?}", e); | |
| 1196 | return; | |
| 1197 | }; | |
| 1198 | let krate = HasModule::krate(&m.id, db); | |
| 1199 | 1196 | let edition = krate.data(db).edition; |
| 1200 | 1197 | emit_def_diagnostic_( |
| 1201 | 1198 | db, |
| 1202 | 1199 | acc, |
| 1203 | 1200 | &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() }, |
| 1204 | 1201 | edition, |
| 1205 | m.krate(db).id, | |
| 1202 | krate, | |
| 1206 | 1203 | ); |
| 1207 | 1204 | } |
| 1208 | 1205 | } |
| ... | ... | @@ -2737,14 +2734,14 @@ impl<'db> Param<'db> { |
| 2737 | 2734 | Callee::Def(CallableDefId::FunctionId(it)) => { |
| 2738 | 2735 | let parent = DefWithBodyId::FunctionId(it); |
| 2739 | 2736 | let body = Body::of(db, parent); |
| 2740 | if let Some(self_param) = body.self_param().filter(|_| self.idx == 0) { | |
| 2737 | if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) { | |
| 2741 | 2738 | Some(Local { |
| 2742 | 2739 | parent: parent.into(), |
| 2743 | 2740 | parent_infer: parent.into(), |
| 2744 | binding_id: self_param, | |
| 2741 | binding_id: self_param.user_written, | |
| 2745 | 2742 | }) |
| 2746 | 2743 | } else if let Pat::Bind { id, .. } = |
| 2747 | &body[body.params[self.idx - body.self_param().is_some() as usize]] | |
| 2744 | &body[body.params[self.idx - body.self_param.is_some() as usize].user_written] | |
| 2748 | 2745 | { |
| 2749 | 2746 | Some(Local { |
| 2750 | 2747 | parent: parent.into(), |
| ... | ... | @@ -4193,7 +4190,7 @@ impl Local { |
| 4193 | 4190 | } |
| 4194 | 4191 | ExpressionStoreOwnerId::Body(def_with_body_id) => { |
| 4195 | 4192 | b = Body::with_source_map(db, def_with_body_id); |
| 4196 | if b.0.self_params.contains(&self.binding_id) | |
| 4193 | if b.0.is_any_self_param(self.binding_id) | |
| 4197 | 4194 | && let Some(source) = b.1.self_param_syntax() |
| 4198 | 4195 | { |
| 4199 | 4196 | let root = source.file_syntax(db); |
| ... | ... | @@ -4234,7 +4231,7 @@ impl Local { |
| 4234 | 4231 | } |
| 4235 | 4232 | ExpressionStoreOwnerId::Body(def_with_body_id) => { |
| 4236 | 4233 | b = Body::with_source_map(db, def_with_body_id); |
| 4237 | if b.0.self_params.contains(&self.binding_id) | |
| 4234 | if b.0.is_any_self_param(self.binding_id) | |
| 4238 | 4235 | && let Some(source) = b.1.self_param_syntax() |
| 4239 | 4236 | { |
| 4240 | 4237 | let root = source.file_syntax(db); |
| ... | ... | @@ -6849,8 +6846,8 @@ impl<'db> Layout<'db> { |
| 6849 | 6846 | .into_iter() |
| 6850 | 6847 | .flatten() |
| 6851 | 6848 | .chain(iter::once((0, self.0.size.bytes()))) |
| 6852 | .tuple_windows() | |
| 6853 | .filter_map(|((i, start), (_, end))| { | |
| 6849 | .array_windows() | |
| 6850 | .filter_map(|[(i, start), (_, end)]| { | |
| 6854 | 6851 | let size = field_size(i)?; |
| 6855 | 6852 | end.checked_sub(start)?.checked_sub(size) |
| 6856 | 6853 | }) |
| ... | ... | @@ -7381,9 +7378,9 @@ pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>( |
| 7381 | 7378 | let mut def_map = crate_def_map(db, krate); |
| 7382 | 7379 | let mut module = &def_map[def_map.root_module_id()]; |
| 7383 | 7380 | let mut segments = segments.with_position().peekable(); |
| 7384 | while let Some((_, segment)) = segments.next_if(|&(position, _)| { | |
| 7385 | !matches!(position, itertools::Position::Last | itertools::Position::Only) | |
| 7386 | }) { | |
| 7381 | while let Some((_, segment)) = | |
| 7382 | segments.next_if(|&(position, _)| !position.is_last) | |
| 7383 | { | |
| 7387 | 7384 | let res = module |
| 7388 | 7385 | .scope |
| 7389 | 7386 | .get(&Name::new_symbol_root(segment)) |
src/tools/rust-analyzer/crates/hir/src/semantics.rs+10-13| ... | ... | @@ -522,7 +522,7 @@ impl<'db> SemanticsImpl<'db> { |
| 522 | 522 | let file_id = declaration_tree_id.file_id(); |
| 523 | 523 | let in_file = InFile::new(file_id, declaration); |
| 524 | 524 | let node = in_file.to_node(self.db); |
| 525 | let root = find_root(node.syntax()); | |
| 525 | let root = node.syntax().tree_top(); | |
| 526 | 526 | self.cache(root, file_id); |
| 527 | 527 | Some(in_file.with_value(node.syntax().clone())) |
| 528 | 528 | } |
| ... | ... | @@ -531,7 +531,7 @@ impl<'db> SemanticsImpl<'db> { |
| 531 | 531 | } |
| 532 | 532 | HirFileId::MacroFile(macro_file) => { |
| 533 | 533 | let node = macro_file.loc(self.db).to_node(self.db); |
| 534 | let root = find_root(&node.value); | |
| 534 | let root = node.value.tree_top(); | |
| 535 | 535 | self.cache(root, node.file_id); |
| 536 | 536 | Some(node) |
| 537 | 537 | } |
| ... | ... | @@ -544,7 +544,7 @@ impl<'db> SemanticsImpl<'db> { |
| 544 | 544 | let def_map = module.id.def_map(self.db); |
| 545 | 545 | let definition = def_map[module.id].origin.definition_source(self.db); |
| 546 | 546 | let definition = definition.map(|it| it.node()); |
| 547 | let root_node = find_root(&definition.value); | |
| 547 | let root_node = definition.value.tree_top(); | |
| 548 | 548 | self.cache(root_node, definition.file_id); |
| 549 | 549 | definition |
| 550 | 550 | } |
| ... | ... | @@ -1067,7 +1067,8 @@ impl<'db> SemanticsImpl<'db> { |
| 1067 | 1067 | && let Some(p) = first.parent() |
| 1068 | 1068 | { |
| 1069 | 1069 | let range = first.text_range().cover(last.text_range()); |
| 1070 | let node = find_root(&p) | |
| 1070 | let node = p | |
| 1071 | .tree_top() | |
| 1071 | 1072 | .covering_element(range) |
| 1072 | 1073 | .ancestors() |
| 1073 | 1074 | .take_while(|it| it.text_range() == range) |
| ... | ... | @@ -1577,7 +1578,7 @@ impl<'db> SemanticsImpl<'db> { |
| 1577 | 1578 | pub fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> { |
| 1578 | 1579 | self.wrap_node_infile(node).original_ast_node_rooted(self.db).map( |
| 1579 | 1580 | |InRealFile { file_id, value }| { |
| 1580 | self.cache(find_root(value.syntax()), file_id.into()); | |
| 1581 | self.cache(value.syntax().tree_top(), file_id.into()); | |
| 1581 | 1582 | value |
| 1582 | 1583 | }, |
| 1583 | 1584 | ) |
| ... | ... | @@ -1589,7 +1590,7 @@ impl<'db> SemanticsImpl<'db> { |
| 1589 | 1590 | let InFile { file_id, .. } = self.find_file(node); |
| 1590 | 1591 | InFile::new(file_id, node).original_syntax_node_rooted(self.db).map( |
| 1591 | 1592 | |InRealFile { file_id, value }| { |
| 1592 | self.cache(find_root(&value), file_id.into()); | |
| 1593 | self.cache(value.tree_top(), file_id.into()); | |
| 1593 | 1594 | value |
| 1594 | 1595 | }, |
| 1595 | 1596 | ) |
| ... | ... | @@ -2171,7 +2172,7 @@ impl<'db> SemanticsImpl<'db> { |
| 2171 | 2172 | pub fn source<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>> { |
| 2172 | 2173 | // FIXME: source call should go through the parse cache |
| 2173 | 2174 | let res = def.source(self.db)?; |
| 2174 | self.cache(find_root(res.value.syntax()), res.file_id); | |
| 2175 | self.cache(res.value.syntax().tree_top(), res.file_id); | |
| 2175 | 2176 | Some(res) |
| 2176 | 2177 | } |
| 2177 | 2178 | |
| ... | ... | @@ -2375,7 +2376,7 @@ impl<'db> SemanticsImpl<'db> { |
| 2375 | 2376 | |
| 2376 | 2377 | /// Wraps the node in a [`InFile`] with the file id it belongs to. |
| 2377 | 2378 | fn find_file<'node>(&self, node: &'node SyntaxNode) -> InFile<&'node SyntaxNode> { |
| 2378 | let root_node = find_root(node); | |
| 2379 | let root_node = node.tree_top(); | |
| 2379 | 2380 | let file_id = self.lookup(&root_node).unwrap_or_else(|| { |
| 2380 | 2381 | panic!( |
| 2381 | 2382 | "\n\nFailed to lookup {:?} in this Semantics.\n\ |
| ... | ... | @@ -2461,7 +2462,7 @@ impl<'db> SemanticsImpl<'db> { |
| 2461 | 2462 | } |
| 2462 | 2463 | }; |
| 2463 | 2464 | let adt_source = adt_ast_id.to_in_file_node(self.db); |
| 2464 | self.cache(adt_source.value.syntax().ancestors().last().unwrap(), adt_source.file_id); | |
| 2465 | self.cache(adt_source.value.syntax().tree_top(), adt_source.file_id); | |
| 2465 | 2466 | ToDef::to_def(self, adt_source.as_ref()) |
| 2466 | 2467 | } |
| 2467 | 2468 | |
| ... | ... | @@ -2702,10 +2703,6 @@ impl ToDef for ast::IdentPat { |
| 2702 | 2703 | } |
| 2703 | 2704 | } |
| 2704 | 2705 | |
| 2705 | fn find_root(node: &SyntaxNode) -> SyntaxNode { | |
| 2706 | node.ancestors().last().unwrap() | |
| 2707 | } | |
| 2708 | ||
| 2709 | 2706 | /// `SemanticsScope` encapsulates the notion of a scope (the set of visible |
| 2710 | 2707 | /// names) at a particular program point. |
| 2711 | 2708 | /// |
src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs+1-1| ... | ... | @@ -371,7 +371,7 @@ impl SourceToDefCtx<'_, '_> { |
| 371 | 371 | .as_expression_store_owner()? |
| 372 | 372 | .as_def_with_body()?; |
| 373 | 373 | let body = Body::of(self.db, container); |
| 374 | Some((container, body.self_param()?)) | |
| 374 | Some((container, body.self_param?.user_written)) | |
| 375 | 375 | } |
| 376 | 376 | pub(super) fn label_to_def( |
| 377 | 377 | &mut self, |
src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs+2-2| ... | ... | @@ -580,7 +580,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 580 | 580 | ) -> Option<Type<'db>> { |
| 581 | 581 | let binding = match self.body_or_sig.as_ref()? { |
| 582 | 582 | BodyOrSig::Sig { .. } | BodyOrSig::VariantFields { .. } => return None, |
| 583 | BodyOrSig::Body { body, .. } => body.self_param()?, | |
| 583 | BodyOrSig::Body { body, .. } => body.self_param?.formal, | |
| 584 | 584 | }; |
| 585 | 585 | let ty = self.infer()?.binding_ty(binding); |
| 586 | 586 | Some(self.ty(ty)) |
| ... | ... | @@ -1155,7 +1155,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 1155 | 1155 | let parent = path.syntax().parent(); |
| 1156 | 1156 | let parent = || parent.clone(); |
| 1157 | 1157 | |
| 1158 | let mut prefer_value_ns = false; | |
| 1158 | let mut prefer_value_ns = parent().and_then(ast::PathExpr::cast).is_some(); | |
| 1159 | 1159 | let resolved = (|| { |
| 1160 | 1160 | let infer = self.infer()?; |
| 1161 | 1161 | if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) { |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs+108-42| ... | ... | @@ -5,6 +5,7 @@ use ide_db::{ |
| 5 | 5 | }; |
| 6 | 6 | use syntax::{ |
| 7 | 7 | SyntaxKind, T, |
| 8 | algo::{next_non_trivia_token, previous_non_trivia_token}, | |
| 8 | 9 | ast::{ |
| 9 | 10 | self, AstNode, HasArgList, HasAttrs, HasGenericParams, HasVisibility, |
| 10 | 11 | syntax_factory::SyntaxFactory, |
| ... | ... | @@ -186,12 +187,39 @@ fn process_struct_name_reference( |
| 186 | 187 | match_ast! { |
| 187 | 188 | match parent { |
| 188 | 189 | ast::TupleStructPat(tuple_struct_pat) => { |
| 189 | let range = ctx.sema.original_range_opt(tuple_struct_pat.syntax())?.range; | |
| 190 | let new = make.record_pat_with_fields( | |
| 191 | full_path, | |
| 192 | generate_record_pat_list(&tuple_struct_pat, names, make), | |
| 193 | ); | |
| 194 | editor.replace_all(cover_edit_range(source.syntax(), range), vec![new.syntax().clone().into()]); | |
| 190 | let (targets, rest_pat) = tuple_pat_field_targets(&tuple_struct_pat, names); | |
| 191 | ||
| 192 | let mut first_insert = vec![]; | |
| 193 | for (pat, name) in targets { | |
| 194 | let range = ctx.sema.original_range_opt(pat.syntax())?.range; | |
| 195 | let place = cover_edit_range(source.syntax(), range); | |
| 196 | let elements = vec![ | |
| 197 | make.name_ref(&name.text()).syntax().clone().into(), | |
| 198 | make.token(T![:]).into(), | |
| 199 | make.whitespace(" ").into(), | |
| 200 | ]; | |
| 201 | if first_insert.is_empty() { | |
| 202 | // XXX: SyntaxEditor cannot insert after deleted element | |
| 203 | first_insert = elements; | |
| 204 | } else { | |
| 205 | editor.insert_all(Position::before(place.start()), elements); | |
| 206 | } | |
| 207 | } | |
| 208 | ||
| 209 | // Record patterns only allow `..` as the trailing field, so it can't stay | |
| 210 | // in place like the other fields; relocate it to just before the closing brace. | |
| 211 | let mut trailing_insert = vec![]; | |
| 212 | if let Some(rest_pat) = rest_pat { | |
| 213 | if !first_insert.is_empty() { | |
| 214 | trailing_insert.push(make.token(T![,]).into()); | |
| 215 | trailing_insert.push(make.whitespace(" ").into()); | |
| 216 | } | |
| 217 | trailing_insert.push(make.rest_pat().syntax().clone().into()); | |
| 218 | delete_rest_pat(ctx, source, editor, &rest_pat); | |
| 219 | } | |
| 220 | ||
| 221 | let (l_paren, r_paren) = tuple_struct_pat_parens(ctx, source, &tuple_struct_pat)?; | |
| 222 | process_delimiter(editor, l_paren, r_paren, first_insert, trailing_insert); | |
| 195 | 223 | }, |
| 196 | 224 | ast::PathExpr(path_expr) => { |
| 197 | 225 | let call_expr = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?; |
| ... | ... | @@ -220,7 +248,11 @@ fn process_struct_name_reference( |
| 220 | 248 | editor.insert_all(Position::before(place.start()), elements); |
| 221 | 249 | } |
| 222 | 250 | } |
| 223 | process_delimiter(ctx, source, editor, &arg_list, first_insert); | |
| 251 | let range = ctx.sema.original_range_opt(arg_list.syntax())?.range; | |
| 252 | let place = cover_edit_range(source.syntax(), range); | |
| 253 | let l_paren = first_token_of(place.start().clone())?; | |
| 254 | let r_paren = last_token_of(place.end().clone())?; | |
| 255 | process_delimiter(editor, l_paren, r_paren, first_insert, vec![]); | |
| 224 | 256 | }, |
| 225 | 257 | _ => {} |
| 226 | 258 | } |
| ... | ... | @@ -229,28 +261,14 @@ fn process_struct_name_reference( |
| 229 | 261 | } |
| 230 | 262 | |
| 231 | 263 | fn process_delimiter( |
| 232 | ctx: &AssistContext<'_, '_>, | |
| 233 | source: &ast::SourceFile, | |
| 234 | 264 | editor: &SyntaxEditor, |
| 235 | list: &impl AstNode, | |
| 265 | l_paren: syntax::SyntaxToken, | |
| 266 | r_paren: syntax::SyntaxToken, | |
| 236 | 267 | first_insert: Vec<syntax::SyntaxElement>, |
| 268 | trailing_insert: Vec<syntax::SyntaxElement>, | |
| 237 | 269 | ) { |
| 238 | 270 | let make = editor.make(); |
| 239 | let Some(range) = ctx.sema.original_range_opt(list.syntax()) else { return }; | |
| 240 | let place = cover_edit_range(source.syntax(), range.range); | |
| 241 | ||
| 242 | let l_paren = match place.start() { | |
| 243 | syntax::NodeOrToken::Node(node) => node.first_token(), | |
| 244 | syntax::NodeOrToken::Token(t) => Some(t.clone()), | |
| 245 | }; | |
| 246 | let r_paren = match place.end() { | |
| 247 | syntax::NodeOrToken::Node(node) => node.last_token(), | |
| 248 | syntax::NodeOrToken::Token(t) => Some(t.clone()), | |
| 249 | }; | |
| 250 | ||
| 251 | if let Some(l_paren) = l_paren | |
| 252 | && l_paren.kind() == T!['('] | |
| 253 | { | |
| 271 | if l_paren.kind() == T!['('] { | |
| 254 | 272 | let mut open_delim = vec![ |
| 255 | 273 | make.whitespace(" ").into(), |
| 256 | 274 | make.token(T!['{']).into(), |
| ... | ... | @@ -259,16 +277,67 @@ fn process_delimiter( |
| 259 | 277 | open_delim.extend(first_insert); |
| 260 | 278 | editor.replace_with_many(l_paren, open_delim); |
| 261 | 279 | } |
| 262 | if let Some(r_paren) = r_paren | |
| 263 | && r_paren.kind() == T![')'] | |
| 264 | { | |
| 265 | editor.replace_with_many( | |
| 266 | r_paren, | |
| 267 | vec![make.whitespace(" ").into(), make.token(T!['}']).into()], | |
| 268 | ); | |
| 280 | if r_paren.kind() == T![')'] { | |
| 281 | let mut close_delim = trailing_insert; | |
| 282 | close_delim.push(make.whitespace(" ").into()); | |
| 283 | close_delim.push(make.token(T!['}']).into()); | |
| 284 | editor.replace_with_many(r_paren, close_delim); | |
| 269 | 285 | } |
| 270 | 286 | } |
| 271 | 287 | |
| 288 | fn first_token_of(elem: syntax::SyntaxElement) -> Option<syntax::SyntaxToken> { | |
| 289 | match elem { | |
| 290 | syntax::NodeOrToken::Node(node) => node.first_token(), | |
| 291 | syntax::NodeOrToken::Token(t) => Some(t), | |
| 292 | } | |
| 293 | } | |
| 294 | ||
| 295 | fn last_token_of(elem: syntax::SyntaxElement) -> Option<syntax::SyntaxToken> { | |
| 296 | match elem { | |
| 297 | syntax::NodeOrToken::Node(node) => node.last_token(), | |
| 298 | syntax::NodeOrToken::Token(t) => Some(t), | |
| 299 | } | |
| 300 | } | |
| 301 | ||
| 302 | /// Locates the `(` and `)` delimiting `pat`'s fields, skipping over its path. Unlike | |
| 303 | /// [`ast::ArgList`], a [`ast::TupleStructPat`] has no dedicated field-list node to anchor on. | |
| 304 | fn tuple_struct_pat_parens( | |
| 305 | ctx: &AssistContext<'_, '_>, | |
| 306 | source: &ast::SourceFile, | |
| 307 | pat: &ast::TupleStructPat, | |
| 308 | ) -> Option<(syntax::SyntaxToken, syntax::SyntaxToken)> { | |
| 309 | let path_range = ctx.sema.original_range_opt(pat.path()?.syntax())?.range; | |
| 310 | let l_paren = | |
| 311 | next_non_trivia_token(cover_edit_range(source.syntax(), path_range).end().clone())?; | |
| 312 | ||
| 313 | let pat_range = ctx.sema.original_range_opt(pat.syntax())?.range; | |
| 314 | let r_paren = last_token_of(cover_edit_range(source.syntax(), pat_range).end().clone())?; | |
| 315 | Some((l_paren, r_paren)) | |
| 316 | } | |
| 317 | ||
| 318 | /// Deletes `rest_pat` along with exactly one neighboring comma, so the surviving fields | |
| 319 | /// keep a single separator between them (the caller re-inserts `..` at the new position). | |
| 320 | fn delete_rest_pat( | |
| 321 | ctx: &AssistContext<'_, '_>, | |
| 322 | source: &ast::SourceFile, | |
| 323 | editor: &SyntaxEditor, | |
| 324 | rest_pat: &ast::RestPat, | |
| 325 | ) -> Option<()> { | |
| 326 | let range = ctx.sema.original_range_opt(rest_pat.syntax())?.range; | |
| 327 | let place = cover_edit_range(source.syntax(), range); | |
| 328 | editor.delete_all(place.clone()); | |
| 329 | ||
| 330 | let following = next_non_trivia_token(place.end().clone()).filter(|t| t.kind() == T![,]); | |
| 331 | let preceding = previous_non_trivia_token(place.start().clone()).filter(|t| t.kind() == T![,]); | |
| 332 | if let Some(comma) = following.or(preceding) { | |
| 333 | if let Some(ws) = comma.next_token().filter(|t| t.kind() == SyntaxKind::WHITESPACE) { | |
| 334 | editor.delete(ws); | |
| 335 | } | |
| 336 | editor.delete(comma); | |
| 337 | } | |
| 338 | Some(()) | |
| 339 | } | |
| 340 | ||
| 272 | 341 | fn edit_field_references( |
| 273 | 342 | ctx: &AssistContext<'_, '_>, |
| 274 | 343 | edit: &mut SourceChangeBuilder, |
| ... | ... | @@ -313,23 +382,21 @@ fn generate_names( |
| 313 | 382 | .collect() |
| 314 | 383 | } |
| 315 | 384 | |
| 316 | fn generate_record_pat_list( | |
| 385 | /// Pairs each non-`..` field with its generated name. The `..` rest pattern (if any) has | |
| 386 | /// no name and is returned separately, since it needs different handling (see [`delete_rest_pat`]). | |
| 387 | fn tuple_pat_field_targets( | |
| 317 | 388 | pat: &ast::TupleStructPat, |
| 318 | 389 | names: &[ast::Name], |
| 319 | make: &SyntaxFactory, | |
| 320 | ) -> ast::RecordPatFieldList { | |
| 390 | ) -> (Vec<(ast::Pat, ast::Name)>, Option<ast::RestPat>) { | |
| 321 | 391 | let pure_fields = pat.fields().filter(|p| !matches!(p, ast::Pat::RestPat(_))); |
| 322 | 392 | let rest_len = names.len().saturating_sub(pure_fields.clone().count()); |
| 323 | 393 | let rest_pat = pat.fields().find_map(|p| ast::RestPat::cast(p.syntax().clone())); |
| 324 | 394 | let rest_idx = |
| 325 | 395 | pat.fields().position(|p| ast::RestPat::can_cast(p.syntax().kind())).unwrap_or(names.len()); |
| 326 | let before_rest = pat.fields().zip(names).take(rest_idx); | |
| 327 | let after_rest = pure_fields.zip(names.iter().skip(rest_len)).skip(rest_idx); | |
| 396 | let before_rest = pat.fields().zip(names.iter().cloned()).take(rest_idx); | |
| 397 | let after_rest = pure_fields.zip(names.iter().skip(rest_len).cloned()).skip(rest_idx); | |
| 328 | 398 | |
| 329 | let fields = before_rest | |
| 330 | .chain(after_rest) | |
| 331 | .map(|(pat, name)| make.record_pat_field(make.name_ref(&name.text()), pat)); | |
| 332 | make.record_pat_field_list(fields, rest_pat) | |
| 399 | (before_rest.chain(after_rest).collect(), rest_pat) | |
| 333 | 400 | } |
| 334 | 401 | |
| 335 | 402 | #[cfg(test)] |
| ... | ... | @@ -803,7 +870,6 @@ fn test(t: T) { |
| 803 | 870 | } |
| 804 | 871 | |
| 805 | 872 | #[test] |
| 806 | #[ignore = "FIXME overlap edits in nested uses self"] | |
| 807 | 873 | fn convert_pat_uses_self() { |
| 808 | 874 | check_assist( |
| 809 | 875 | convert_tuple_struct_to_named_struct, |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs+15-8| ... | ... | @@ -101,7 +101,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_, '_>) - |
| 101 | 101 | let last_descend = ctx.sema.descend_into_macros_single_exact(last.clone()); |
| 102 | 102 | let range = first_descend.text_range().cover(last_descend.text_range()); |
| 103 | 103 | |
| 104 | if first_descend.parent_ancestors().last() != last_descend.parent_ancestors().last() { | |
| 104 | if first_descend.tree_top() != last_descend.tree_top() { | |
| 105 | 105 | return None; |
| 106 | 106 | } |
| 107 | 107 | |
| ... | ... | @@ -110,6 +110,9 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_, '_>) - |
| 110 | 110 | .skip_while(|it| !it.text_range().contains_range(range)) |
| 111 | 111 | .find_map(valid_target_expr(ctx))?; |
| 112 | 112 | let original_range = ctx.sema.original_range(expr.syntax()); |
| 113 | if !node.text_range().contains_range(original_range.range) { | |
| 114 | return None; | |
| 115 | } | |
| 113 | 116 | (cover_edit_range(&node, original_range.range), expr) |
| 114 | 117 | } else { |
| 115 | 118 | let expr = node |
| ... | ... | @@ -198,13 +201,12 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_, '_>) - |
| 198 | 201 | |edit| { |
| 199 | 202 | let (var_name, expr_replace) = kind.get_name_and_expr(ctx, &analysis); |
| 200 | 203 | |
| 201 | let to_replace = | |
| 202 | if expr_replace.ancestors().last() == to_replace.start().ancestors().last() { | |
| 203 | let element = expr_replace.clone().syntax_element(); | |
| 204 | element.clone()..=element | |
| 205 | } else { | |
| 206 | to_replace.clone() | |
| 207 | }; | |
| 204 | let to_replace = if expr_replace.tree_top() == to_replace.start().tree_top() { | |
| 205 | let element = expr_replace.clone().syntax_element(); | |
| 206 | element.clone()..=element | |
| 207 | } else { | |
| 208 | to_replace.clone() | |
| 209 | }; | |
| 208 | 210 | |
| 209 | 211 | let editor = edit.make_editor(&place); |
| 210 | 212 | let make = editor.make(); |
| ... | ... | @@ -3027,4 +3029,9 @@ fn main() { |
| 3027 | 3029 | "Extract into variable", |
| 3028 | 3030 | ); |
| 3029 | 3031 | } |
| 3032 | ||
| 3033 | #[test] | |
| 3034 | fn repro_bad_range_unresolved_macro_paren() { | |
| 3035 | check_assist_not_applicable(extract_variable, "fn f() { m!$0($0 }"); | |
| 3036 | } | |
| 3030 | 3037 | } |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs+52-10| ... | ... | @@ -15,7 +15,7 @@ use syntax::{ |
| 15 | 15 | self, AssocItem, GenericParam, HasAttrs, HasGenericParams, HasName, HasTypeBounds, |
| 16 | 16 | HasVisibility, edit::AstNodeEdit, syntax_factory::SyntaxFactory, |
| 17 | 17 | }, |
| 18 | syntax_editor::Position, | |
| 18 | syntax_editor::{Position, Removable}, | |
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | 21 | // Assist: generate_blanket_trait_impl |
| ... | ... | @@ -99,10 +99,15 @@ pub(crate) fn generate_blanket_trait_impl( |
| 99 | 99 | ast::AssocItem::Fn(method) if method.body().is_none() => { |
| 100 | 100 | todo_fn(make, &method, ctx.config).into() |
| 101 | 101 | } |
| 102 | ast::AssocItem::Const(_) | ast::AssocItem::TypeAlias(_) => item, | |
| 102 | ast::AssocItem::Const(it) if it.body().is_none() => { | |
| 103 | ast::AssocItem::Const(it.reset_indent()) | |
| 104 | } | |
| 105 | ast::AssocItem::TypeAlias(it) if it.ty().is_none() => { | |
| 106 | remove_bounds(it.reset_indent()).into() | |
| 107 | } | |
| 103 | 108 | _ => return None, |
| 104 | 109 | }; |
| 105 | Some(item.reset_indent().indent(1.into())) | |
| 110 | Some(item.indent(1.into())) | |
| 106 | 111 | }) |
| 107 | 112 | .collect::<Vec<_>>(); |
| 108 | 113 | (!items.is_empty()).then(|| make.assoc_item_list(items)) |
| ... | ... | @@ -284,6 +289,16 @@ fn todo_fn(make: &SyntaxFactory, f: &ast::Fn, config: &AssistConfig) -> ast::Fn |
| 284 | 289 | ) |
| 285 | 290 | } |
| 286 | 291 | |
| 292 | fn remove_bounds(alias: ast::TypeAlias) -> ast::TypeAlias { | |
| 293 | let (editor, alias) = syntax::syntax_editor::SyntaxEditor::with_ast_node(&alias); | |
| 294 | ||
| 295 | if let Some(type_bound_list) = alias.type_bound_list() { | |
| 296 | type_bound_list.remove(&editor); | |
| 297 | } | |
| 298 | ||
| 299 | ast::TypeAlias::cast(editor.finish().new_root().clone()).unwrap() | |
| 300 | } | |
| 301 | ||
| 287 | 302 | fn cfg_attrs(node: &impl HasAttrs) -> impl Iterator<Item = ast::Attr> { |
| 288 | 303 | node.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))) |
| 289 | 304 | } |
| ... | ... | @@ -533,6 +548,33 @@ impl<T: ?Sized> Foo for $0T { |
| 533 | 548 | ); |
| 534 | 549 | } |
| 535 | 550 | |
| 551 | #[test] | |
| 552 | fn test_gen_blanket_assoc_items_with_default() { | |
| 553 | check_assist( | |
| 554 | generate_blanket_trait_impl, | |
| 555 | r#" | |
| 556 | trait $0Foo { | |
| 557 | type Item = (); | |
| 558 | ||
| 559 | const N: usize = 3; | |
| 560 | ||
| 561 | fn foo(&self) {} | |
| 562 | } | |
| 563 | "#, | |
| 564 | r#" | |
| 565 | trait Foo { | |
| 566 | type Item = (); | |
| 567 | ||
| 568 | const N: usize = 3; | |
| 569 | ||
| 570 | fn foo(&self) {} | |
| 571 | } | |
| 572 | ||
| 573 | impl<T: ?Sized> Foo for $0T {} | |
| 574 | "#, | |
| 575 | ); | |
| 576 | } | |
| 577 | ||
| 536 | 578 | #[test] |
| 537 | 579 | fn test_gen_blanket_indent() { |
| 538 | 580 | check_assist( |
| ... | ... | @@ -775,7 +817,7 @@ mod foo { |
| 775 | 817 | mod foo { |
| 776 | 818 | mod bar { |
| 777 | 819 | trait $0Foo { |
| 778 | type Item: Bar< | |
| 820 | type Item where Self: Bar< | |
| 779 | 821 | Self, |
| 780 | 822 | >; |
| 781 | 823 | |
| ... | ... | @@ -790,7 +832,7 @@ mod foo { |
| 790 | 832 | mod foo { |
| 791 | 833 | mod bar { |
| 792 | 834 | trait Foo { |
| 793 | type Item: Bar< | |
| 835 | type Item where Self: Bar< | |
| 794 | 836 | Self, |
| 795 | 837 | >; |
| 796 | 838 | |
| ... | ... | @@ -800,7 +842,7 @@ mod foo { |
| 800 | 842 | } |
| 801 | 843 | |
| 802 | 844 | impl<T: ?Sized> Foo for $0T { |
| 803 | type Item: Bar< | |
| 845 | type Item where Self: Bar< | |
| 804 | 846 | Self, |
| 805 | 847 | >; |
| 806 | 848 | |
| ... | ... | @@ -894,7 +936,7 @@ impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 |
| 894 | 936 | where |
| 895 | 937 | Self::Owned: Default, |
| 896 | 938 | { |
| 897 | type X: Sync; | |
| 939 | type X; | |
| 898 | 940 | |
| 899 | 941 | fn foo(&self, x: Self::X) -> T { |
| 900 | 942 | todo!() |
| ... | ... | @@ -943,7 +985,7 @@ where |
| 943 | 985 | Self: ToOwned, |
| 944 | 986 | Self::Owned: Default, |
| 945 | 987 | { |
| 946 | type X: Sync; | |
| 988 | type X; | |
| 947 | 989 | |
| 948 | 990 | fn foo(&self, x: Self::X) -> T { |
| 949 | 991 | todo!() |
| ... | ... | @@ -980,7 +1022,7 @@ trait Foo<T: Send> { |
| 980 | 1022 | } |
| 981 | 1023 | |
| 982 | 1024 | impl<T: Send, T1: ?Sized> Foo<T> for $0T1 { |
| 983 | type X: Sync; | |
| 1025 | type X; | |
| 984 | 1026 | |
| 985 | 1027 | fn foo(&self, x: Self::X) -> T { |
| 986 | 1028 | todo!() |
| ... | ... | @@ -1017,7 +1059,7 @@ trait Foo { |
| 1017 | 1059 | } |
| 1018 | 1060 | |
| 1019 | 1061 | impl<T: ?Sized> Foo for $0T { |
| 1020 | type X: Sync; | |
| 1062 | type X; | |
| 1021 | 1063 | |
| 1022 | 1064 | fn foo(&self, x: Self::X) -> i32 { |
| 1023 | 1065 | todo!() |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs+75-13| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | use ide_db::{RootDatabase, famous_defs::FamousDefs}; |
| 2 | use syntax::ast::{self, AstNode, HasName}; | |
| 2 | use syntax::{ | |
| 3 | ast::{self, AstNode, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory}, | |
| 4 | syntax_editor::{Position, SyntaxEditor}, | |
| 5 | }; | |
| 3 | 6 | |
| 4 | use crate::{AssistContext, AssistId, Assists}; | |
| 7 | use crate::{AssistContext, AssistId, Assists, utils}; | |
| 5 | 8 | |
| 6 | 9 | // Assist: generate_default_from_enum_variant |
| 7 | 10 | // |
| ... | ... | @@ -34,7 +37,7 @@ pub(crate) fn generate_default_from_enum_variant( |
| 34 | 37 | ) -> Option<()> { |
| 35 | 38 | let variant = ctx.find_node_at_offset::<ast::Variant>()?; |
| 36 | 39 | let variant_name = variant.name()?; |
| 37 | let enum_name = variant.parent_enum().name()?; | |
| 40 | let adt = ast::Adt::Enum(variant.parent_enum()); | |
| 38 | 41 | if !matches!(variant.kind(), ast::StructKind::Unit) { |
| 39 | 42 | cov_mark::hit!(test_gen_default_on_non_unit_variant_not_implemented); |
| 40 | 43 | return None; |
| ... | ... | @@ -54,21 +57,54 @@ pub(crate) fn generate_default_from_enum_variant( |
| 54 | 57 | "Generate `Default` impl from this enum variant", |
| 55 | 58 | target, |
| 56 | 59 | |edit| { |
| 57 | let start_offset = variant.parent_enum().syntax().text_range().end(); | |
| 58 | let buf = format!( | |
| 59 | r#" | |
| 60 | ||
| 61 | impl Default for {enum_name} {{ | |
| 62 | fn default() -> Self {{ | |
| 63 | Self::{variant_name} | |
| 64 | }} | |
| 65 | }}"#, | |
| 60 | let editor = edit.make_editor(adt.syntax()); | |
| 61 | let make = editor.make(); | |
| 62 | let indent = adt.indent_level(); | |
| 63 | let impl_ = default_impl(variant_name, &adt, make); | |
| 64 | ||
| 65 | editor.insert_all( | |
| 66 | Position::after(adt.syntax()), | |
| 67 | vec![ | |
| 68 | make.whitespace(&format!("\n\n{indent}")).into(), | |
| 69 | impl_.indent(indent).syntax().clone().into(), | |
| 70 | ], | |
| 66 | 71 | ); |
| 67 | edit.insert(start_offset, buf); | |
| 72 | edit.add_file_edits(ctx.vfs_file_id(), editor); | |
| 68 | 73 | }, |
| 69 | 74 | ) |
| 70 | 75 | } |
| 71 | 76 | |
| 77 | fn default_impl(variant_name: ast::Name, adt: &ast::Adt, make: &SyntaxFactory) -> ast::Impl { | |
| 78 | let impl_ = utils::generate_trait_impl_intransitive(make, adt, make.ty("Default")); | |
| 79 | let fn_ = default_fn(&variant_name.text(), make); | |
| 80 | let (impl_editor, impl_) = SyntaxEditor::with_ast_node(&impl_); | |
| 81 | ||
| 82 | impl_ | |
| 83 | .get_or_create_assoc_item_list_with_editor(&impl_editor) | |
| 84 | .add_items(&impl_editor, vec![fn_.into()]); | |
| 85 | ast::Impl::cast(impl_editor.finish().new_root().clone()).unwrap() | |
| 86 | } | |
| 87 | ||
| 88 | fn default_fn(variant_name: &str, make: &SyntaxFactory) -> ast::Fn { | |
| 89 | let path = make.path_from_idents(["Self", variant_name]).unwrap(); | |
| 90 | let body = make.block_expr(None, Some(make.expr_path(path))); | |
| 91 | make.fn_( | |
| 92 | None, | |
| 93 | None, | |
| 94 | make.name("default"), | |
| 95 | None, | |
| 96 | None, | |
| 97 | make.param_list(None, None), | |
| 98 | body, | |
| 99 | Some(make.ret_type(make.ty("Self"))), | |
| 100 | false, | |
| 101 | false, | |
| 102 | false, | |
| 103 | false, | |
| 104 | ) | |
| 105 | .indent(1.into()) | |
| 106 | } | |
| 107 | ||
| 72 | 108 | fn existing_default_impl( |
| 73 | 109 | sema: &'_ hir::Semantics<'_, RootDatabase>, |
| 74 | 110 | variant: &ast::Variant, |
| ... | ... | @@ -214,6 +250,32 @@ impl Default for Variant { |
| 214 | 250 | Self::Undefined |
| 215 | 251 | } |
| 216 | 252 | } |
| 253 | "#, | |
| 254 | ); | |
| 255 | } | |
| 256 | ||
| 257 | #[test] | |
| 258 | fn test_generate_default_from_variant_with_generics() { | |
| 259 | check_assist( | |
| 260 | generate_default_from_enum_variant, | |
| 261 | r#" | |
| 262 | //- minicore: default | |
| 263 | enum Variant<T> { | |
| 264 | Defined(T), | |
| 265 | Undefi$0ned, | |
| 266 | } | |
| 267 | "#, | |
| 268 | r#" | |
| 269 | enum Variant<T> { | |
| 270 | Defined(T), | |
| 271 | Undefined, | |
| 272 | } | |
| 273 | ||
| 274 | impl<T> Default for Variant<T> { | |
| 275 | fn default() -> Self { | |
| 276 | Self::Undefined | |
| 277 | } | |
| 278 | } | |
| 217 | 279 | "#, |
| 218 | 280 | ); |
| 219 | 281 | } |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs+8-15| ... | ... | @@ -79,7 +79,7 @@ pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext<'_, '_> |
| 79 | 79 | |
| 80 | 80 | let function = ctx.sema.to_def(&ast_func)?; |
| 81 | 81 | |
| 82 | let def_file_editor = SyntaxEditor::new(ast_func.syntax().ancestors().last().unwrap()).0; | |
| 82 | let def_file_editor = SyntaxEditor::new(ast_func.syntax().tree_top()).0; | |
| 83 | 83 | let params = get_fn_params(ctx.sema.db, function, &param_list, def_file_editor.make())?; |
| 84 | 84 | |
| 85 | 85 | let mut file_editors = FxHashMap::default(); |
| ... | ... | @@ -255,7 +255,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Opt |
| 255 | 255 | return None; |
| 256 | 256 | } |
| 257 | 257 | let syntax = call_info.node.syntax().clone(); |
| 258 | let editor = SyntaxEditor::new(syntax.ancestors().last().unwrap()).0; | |
| 258 | let editor = SyntaxEditor::new(syntax.tree_top()).0; | |
| 259 | 259 | let params = get_fn_params(ctx.sema.db, function, &param_list, editor.make())?; |
| 260 | 260 | |
| 261 | 261 | if call_info.arguments.len() != params.len() { |
| ... | ... | @@ -1570,11 +1570,8 @@ async fn foo(arg: u32) -> u32 { |
| 1570 | 1570 | } |
| 1571 | 1571 | fn spawn<T>(_: T) {} |
| 1572 | 1572 | fn main() { |
| 1573 | spawn({ | |
| 1574 | let arg = 42; | |
| 1575 | async move { | |
| 1576 | bar(arg).await * 2 | |
| 1577 | } | |
| 1573 | spawn(async move { | |
| 1574 | bar(42).await * 2 | |
| 1578 | 1575 | }); |
| 1579 | 1576 | } |
| 1580 | 1577 | "#, |
| ... | ... | @@ -1605,12 +1602,9 @@ async fn foo(arg: u32) -> u32 { |
| 1605 | 1602 | } |
| 1606 | 1603 | fn spawn<T>(_: T) {} |
| 1607 | 1604 | fn main() { |
| 1608 | spawn({ | |
| 1609 | let arg = 42; | |
| 1610 | async move { | |
| 1611 | bar(arg).await; | |
| 1612 | 42 | |
| 1613 | } | |
| 1605 | spawn(async move { | |
| 1606 | bar(42).await; | |
| 1607 | 42 | |
| 1614 | 1608 | }); |
| 1615 | 1609 | } |
| 1616 | 1610 | "#, |
| ... | ... | @@ -1645,11 +1639,10 @@ fn spawn<T>(_: T) {} |
| 1645 | 1639 | fn main() { |
| 1646 | 1640 | let var = 42; |
| 1647 | 1641 | spawn({ |
| 1648 | let x = var; | |
| 1649 | 1642 | let y = var + 1; |
| 1650 | 1643 | let z: &u32 = &var; |
| 1651 | 1644 | async move { |
| 1652 | bar(x).await; | |
| 1645 | bar(var).await; | |
| 1653 | 1646 | y + y + *z |
| 1654 | 1647 | } |
| 1655 | 1648 | }); |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs+2-2| ... | ... | @@ -36,7 +36,7 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> O |
| 36 | 36 | |
| 37 | 37 | let use_item = tree.syntax().parent().and_then(ast::Use::cast)?; |
| 38 | 38 | let neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir))?; |
| 39 | let (editor, _) = SyntaxEditor::new(use_item.syntax().parent()?.ancestors().last()?); | |
| 39 | let (editor, _) = SyntaxEditor::new(use_item.syntax().parent()?.tree_top()); | |
| 40 | 40 | merge_uses(use_item, vec![neighbor], &ctx.config.insert_use, &editor)?; |
| 41 | 41 | (target, editor) |
| 42 | 42 | } else { |
| ... | ... | @@ -51,7 +51,7 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> O |
| 51 | 51 | }); |
| 52 | 52 | |
| 53 | 53 | let first_selected = selected_nodes.next()?; |
| 54 | let (editor, _) = SyntaxEditor::new(parent_node.ancestors().last().unwrap()); | |
| 54 | let (editor, _) = SyntaxEditor::new(parent_node.tree_top()); | |
| 55 | 55 | match_ast! { |
| 56 | 56 | match first_selected { |
| 57 | 57 | ast::Use(use_item) => { |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs+1-1| ... | ... | @@ -25,7 +25,7 @@ pub(crate) fn normalize_import(acc: &mut Assists, ctx: &AssistContext<'_, '_>) - |
| 25 | 25 | }; |
| 26 | 26 | |
| 27 | 27 | let target = use_item.syntax().text_range(); |
| 28 | let (editor, _) = SyntaxEditor::new(use_item.syntax().ancestors().last().unwrap()); | |
| 28 | let (editor, _) = SyntaxEditor::new(use_item.syntax().tree_top()); | |
| 29 | 29 | let normalized_use_item = |
| 30 | 30 | try_normalize_import(editor.make(), &use_item, ctx.config.insert_use.granularity.into())?; |
| 31 | 31 | editor.replace(use_item.syntax(), normalized_use_item.syntax()); |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs+22-4| ... | ... | @@ -63,6 +63,11 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_, |
| 63 | 63 | return None; |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | let const_name = to_upper_snake_case(&name.to_string()); | |
| 67 | if const_name.is_empty() || const_name.chars().all(|c| c == '_') { | |
| 68 | return None; | |
| 69 | } | |
| 70 | ||
| 66 | 71 | acc.add( |
| 67 | 72 | AssistId::refactor("promote_local_to_const"), |
| 68 | 73 | "Promote local to constant", |
| ... | ... | @@ -70,15 +75,14 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_, |
| 70 | 75 | |edit| { |
| 71 | 76 | let editor = edit.make_editor(let_stmt.syntax()); |
| 72 | 77 | let make = editor.make(); |
| 73 | let name = to_upper_snake_case(&name.to_string()); | |
| 74 | 78 | let usages = Definition::Local(local).usages(&ctx.sema).all(); |
| 75 | 79 | if let Some(usages) = usages.references.get(&ctx.file_id()) { |
| 76 | let name_ref = make.name_ref(&name); | |
| 80 | let name_ref = make.name_ref(&const_name); | |
| 77 | 81 | |
| 78 | 82 | for usage in usages { |
| 79 | 83 | let Some(usage_name) = usage.name.as_name_ref().cloned() else { continue }; |
| 80 | 84 | if let Some(record_field) = ast::RecordExprField::for_name_ref(&usage_name) { |
| 81 | let path = make.ident_path(&name); | |
| 85 | let path = make.ident_path(&const_name); | |
| 82 | 86 | let name_expr = make.expr_path(path); |
| 83 | 87 | utils::replace_record_field_expr(ctx, edit, record_field, name_expr); |
| 84 | 88 | } else { |
| ... | ... | @@ -88,7 +92,8 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_, |
| 88 | 92 | } |
| 89 | 93 | } |
| 90 | 94 | |
| 91 | let item = make.item_const(None, None, make.name(&name), make.ty(&ty), initializer); | |
| 95 | let item = | |
| 96 | make.item_const(None, None, make.name(&const_name), make.ty(&ty), initializer); | |
| 92 | 97 | |
| 93 | 98 | if let Some((cap, name)) = ctx.config.snippet_cap.zip(item.name()) { |
| 94 | 99 | let tabstop = edit.make_tabstop_before(cap); |
| ... | ... | @@ -292,6 +297,19 @@ fn foo() { |
| 292 | 297 | ); |
| 293 | 298 | } |
| 294 | 299 | |
| 300 | #[test] | |
| 301 | fn not_applicable_when_name_converts_to_all_underscores() { | |
| 302 | check_assist_not_applicable( | |
| 303 | promote_local_to_const, | |
| 304 | r" | |
| 305 | fn foo() { | |
| 306 | let _$0_ = 0; | |
| 307 | __; | |
| 308 | } | |
| 309 | ", | |
| 310 | ); | |
| 311 | } | |
| 312 | ||
| 295 | 313 | #[test] |
| 296 | 314 | fn not_applicable_non_simple_ident() { |
| 297 | 315 | cov_mark::check!(promote_local_non_simple_ident); |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_underscore.rs+32-3| ... | ... | @@ -57,14 +57,17 @@ pub(crate) fn remove_underscore(acc: &mut Assists, ctx: &AssistContext<'_, '_>) |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | let new_name = text.trim_start_matches('_'); |
| 60 | if new_name.is_empty() { | |
| 61 | return None; | |
| 62 | } | |
| 63 | let changes = | |
| 64 | def.rename(&ctx.sema, new_name, RenameDefinition::Yes, &ctx.config.rename_config()).ok()?; | |
| 65 | ||
| 60 | 66 | acc.add( |
| 61 | 67 | AssistId::refactor("remove_underscore_from_used_variables"), |
| 62 | 68 | "Remove underscore from a used variable", |
| 63 | 69 | text_range, |
| 64 | 70 | |builder| { |
| 65 | let changes = def | |
| 66 | .rename(&ctx.sema, new_name, RenameDefinition::Yes, &ctx.config.rename_config()) | |
| 67 | .unwrap(); | |
| 68 | 71 | builder.source_change = changes; |
| 69 | 72 | }, |
| 70 | 73 | ) |
| ... | ... | @@ -175,6 +178,32 @@ fn foo(foo: i32) { |
| 175 | 178 | ) |
| 176 | 179 | } |
| 177 | 180 | |
| 181 | #[test] | |
| 182 | fn not_applicable_when_result_is_keyword() { | |
| 183 | check_assist_not_applicable( | |
| 184 | remove_underscore, | |
| 185 | r#" | |
| 186 | fn main() { | |
| 187 | let _$0crate = 1; | |
| 188 | _crate; | |
| 189 | } | |
| 190 | "#, | |
| 191 | ); | |
| 192 | } | |
| 193 | ||
| 194 | #[test] | |
| 195 | fn not_applicable_when_result_is_empty() { | |
| 196 | check_assist_not_applicable( | |
| 197 | remove_underscore, | |
| 198 | r#" | |
| 199 | fn main() { | |
| 200 | let _$0_ = 1; | |
| 201 | __; | |
| 202 | } | |
| 203 | "#, | |
| 204 | ); | |
| 205 | } | |
| 206 | ||
| 178 | 207 | #[test] |
| 179 | 208 | fn remove_underscore_in_function_parameter() { |
| 180 | 209 | check_assist( |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs+130-74| ... | ... | @@ -4,7 +4,7 @@ use std::iter::successors; |
| 4 | 4 | |
| 5 | 5 | use ide_db::{RootDatabase, defs::NameClass, ty_filter::TryEnum}; |
| 6 | 6 | use syntax::{ |
| 7 | AstNode, Edition, SyntaxKind, T, TextRange, | |
| 7 | AstNode, SyntaxKind, T, TextRange, | |
| 8 | 8 | ast::{ |
| 9 | 9 | self, HasName, |
| 10 | 10 | edit::{AstNodeEdit, IndentLevel}, |
| ... | ... | @@ -241,28 +241,19 @@ pub(crate) fn replace_match_with_if_let( |
| 241 | 241 | return None; |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | let mut arms = match_arm_list.arms(); | |
| 245 | let (first_arm, second_arm) = (arms.next()?, arms.next()?); | |
| 246 | if arms.next().is_some() || second_arm.guard().is_some() { | |
| 247 | return None; | |
| 248 | } | |
| 249 | if first_arm.guard().is_some() && ctx.edition() < Edition::Edition2024 { | |
| 244 | let arms = match_arm_list | |
| 245 | .arms() | |
| 246 | .map(|arm| Some((arm.pat()?, arm.expr()?, arm.guard()))) | |
| 247 | .collect::<Option<Vec<_>>>()?; | |
| 248 | ||
| 249 | if arms.len() < 2 { | |
| 250 | 250 | return None; |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | let (if_let_pat, guard, then_expr, else_expr) = pick_pattern_and_expr_order( | |
| 254 | &ctx.sema, | |
| 255 | first_arm.pat()?, | |
| 256 | second_arm.pat()?, | |
| 257 | first_arm.expr()?, | |
| 258 | second_arm.expr()?, | |
| 259 | first_arm.guard(), | |
| 260 | second_arm.guard(), | |
| 261 | )?; | |
| 253 | let (if_exprs, else_expr) = pick_pattern_and_expr_order(&ctx.sema, arms)?; | |
| 262 | 254 | let scrutinee = match_expr.expr()?.reset_indent(); |
| 263 | let guard = guard.and_then(|it| it.condition()); | |
| 264 | 255 | |
| 265 | let let_ = match &if_let_pat { | |
| 256 | let let_ = match &if_exprs.first()?.0 { | |
| 266 | 257 | ast::Pat::LiteralPat(p) |
| 267 | 258 | if p.literal() |
| 268 | 259 | .map(|it| it.token().kind()) |
| ... | ... | @@ -289,36 +280,51 @@ pub(crate) fn replace_match_with_if_let( |
| 289 | 280 | } |
| 290 | 281 | }; |
| 291 | 282 | |
| 292 | let condition = match if_let_pat { | |
| 293 | ast::Pat::LiteralPat(p) | |
| 294 | if p.literal().is_some_and(|it| it.token().kind() == T![true]) => | |
| 295 | { | |
| 296 | scrutinee | |
| 297 | } | |
| 298 | ast::Pat::LiteralPat(p) | |
| 299 | if p.literal().is_some_and(|it| it.token().kind() == T![false]) => | |
| 283 | let if_branches = if_exprs.into_iter().map(|(pat, then_expr, guard)| { | |
| 284 | let guard = guard.and_then(|it| it.condition()); | |
| 285 | ||
| 286 | let condition = match pat { | |
| 287 | ast::Pat::LiteralPat(p) | |
| 288 | if p.literal().is_some_and(|it| it.token().kind() == T![true]) => | |
| 289 | { | |
| 290 | scrutinee.clone() | |
| 291 | } | |
| 292 | ast::Pat::LiteralPat(p) | |
| 293 | if p.literal().is_some_and(|it| it.token().kind() == T![false]) => | |
| 294 | { | |
| 295 | make.expr_prefix(T![!], scrutinee.clone()).into() | |
| 296 | } | |
| 297 | ast::Pat::WildcardPat(_) => make.expr_literal("true").into(), | |
| 298 | _ => make.expr_let(pat, scrutinee.clone()).into(), | |
| 299 | }; | |
| 300 | let condition = if condition.syntax().text() == "true" | |
| 301 | && let Some(guard) = guard | |
| 300 | 302 | { |
| 301 | make.expr_prefix(T![!], scrutinee).into() | |
| 302 | } | |
| 303 | _ => make.expr_let(if_let_pat, scrutinee).into(), | |
| 304 | }; | |
| 305 | let condition = if let Some(guard) = guard { | |
| 306 | let guard = wrap_paren_in_guard_chain(guard, make); | |
| 307 | make.expr_bin(condition, ast::BinaryOp::LogicOp(ast::LogicOp::And), guard).into() | |
| 308 | } else { | |
| 309 | condition | |
| 310 | }; | |
| 311 | let then_expr = then_expr.reset_indent(); | |
| 303 | guard | |
| 304 | } else if let Some(guard) = guard { | |
| 305 | let guard = wrap_paren_in_guard_chain(guard, make); | |
| 306 | make.expr_bin(condition, ast::BinaryOp::LogicOp(ast::LogicOp::And), guard) | |
| 307 | .into() | |
| 308 | } else { | |
| 309 | condition | |
| 310 | }; | |
| 311 | ||
| 312 | let then_expr = then_expr.reset_indent(); | |
| 313 | let then_block = make_block_expr(then_expr); | |
| 314 | ||
| 315 | (condition, then_block) | |
| 316 | }); | |
| 317 | ||
| 312 | 318 | let else_expr = else_expr.reset_indent(); |
| 313 | let then_block = make_block_expr(then_expr); | |
| 314 | 319 | let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) }; |
| 315 | let if_let_expr = make | |
| 316 | .expr_if( | |
| 317 | condition, | |
| 318 | then_block, | |
| 319 | else_expr.map(make_block_expr).map(ast::ElseBranch::Block), | |
| 320 | ) | |
| 321 | .indent(IndentLevel::from_node(match_expr.syntax())); | |
| 320 | let else_branch = else_expr.map(make_block_expr).map(ast::ElseBranch::Block); | |
| 321 | ||
| 322 | let if_let_expr = | |
| 323 | if_branches.rfold(else_branch, |else_branch, (condition, then_branch)| { | |
| 324 | Some(make.expr_if(condition, then_branch, else_branch).into()) | |
| 325 | }); | |
| 326 | let Some(ast::ElseBranch::IfExpr(if_let_expr)) = if_let_expr else { unreachable!() }; | |
| 327 | let if_let_expr = if_let_expr.indent(match_expr.indent_level()); | |
| 322 | 328 | |
| 323 | 329 | editor.replace(match_expr.syntax(), if_let_expr.syntax()); |
| 324 | 330 | builder.add_file_edits(ctx.vfs_file_id(), editor); |
| ... | ... | @@ -329,37 +335,33 @@ pub(crate) fn replace_match_with_if_let( |
| 329 | 335 | /// Pick the pattern for the if let condition and return the expressions for the `then` body and `else` body in that order. |
| 330 | 336 | fn pick_pattern_and_expr_order( |
| 331 | 337 | sema: &hir::Semantics<'_, RootDatabase>, |
| 332 | pat: ast::Pat, | |
| 333 | pat2: ast::Pat, | |
| 334 | expr: ast::Expr, | |
| 335 | expr2: ast::Expr, | |
| 336 | guard: Option<ast::MatchGuard>, | |
| 337 | guard2: Option<ast::MatchGuard>, | |
| 338 | ) -> Option<(ast::Pat, Option<ast::MatchGuard>, ast::Expr, ast::Expr)> { | |
| 339 | if guard.is_some() && guard2.is_some() { | |
| 338 | mut arms: Vec<(ast::Pat, ast::Expr, Option<ast::MatchGuard>)>, | |
| 339 | ) -> Option<(Vec<(ast::Pat, ast::Expr, Option<ast::MatchGuard>)>, ast::Expr)> { | |
| 340 | if arms.last()?.2.is_some() { | |
| 340 | 341 | return None; |
| 341 | 342 | } |
| 342 | let res = match (pat, pat2) { | |
| 343 | (ast::Pat::WildcardPat(_), _) => return None, | |
| 344 | (pat, ast::Pat::WildcardPat(_)) => (pat, guard, expr, expr2), | |
| 345 | (pat, _) if is_empty_expr(&expr2) => (pat, guard, expr, expr2), | |
| 346 | (_, pat) if is_empty_expr(&expr) => (pat, guard, expr2, expr), | |
| 347 | (pat, pat2) => match (binds_name(sema, &pat), binds_name(sema, &pat2)) { | |
| 348 | (true, true) => return None, | |
| 349 | (true, false) => (pat, guard, expr, expr2), | |
| 350 | (false, true) => { | |
| 351 | // This pattern triggers an invalid transformation. | |
| 352 | // See issues #11373, #19443 | |
| 353 | if let ast::Pat::IdentPat(_) = pat2 { | |
| 354 | return None; | |
| 355 | } | |
| 356 | (pat2, guard2, expr2, expr) | |
| 357 | } | |
| 358 | _ if is_sad_pat(sema, &pat) => (pat2, guard2, expr2, expr), | |
| 359 | (false, false) => (pat, guard, expr, expr2), | |
| 360 | }, | |
| 361 | }; | |
| 362 | Some(res) | |
| 343 | ||
| 344 | if matches!(arms.last()?.0, ast::Pat::WildcardPat(_)) { | |
| 345 | let (_, last, _) = arms.pop()?; | |
| 346 | return Some((arms, last)); | |
| 347 | } | |
| 348 | ||
| 349 | if let Some(sad_arm) = arms.iter().rposition(|arm| { | |
| 350 | matches!(arm, (_, expr, None) if is_empty_expr(expr)) || is_sad_pat(sema, &arm.0) | |
| 351 | }) { | |
| 352 | let (_, sad_arm, _) = arms.remove(sad_arm); | |
| 353 | return Some((arms, sad_arm)); | |
| 354 | } | |
| 355 | ||
| 356 | // This pattern triggers an invalid transformation. | |
| 357 | // See issues #11373, #19443 | |
| 358 | // XXX: Perhaps we can extract a let statement to improve | |
| 359 | if !binds_name(sema, &arms.last()?.0) { | |
| 360 | let (_, last, _) = arms.pop()?; | |
| 361 | return Some((arms, last)); | |
| 362 | } | |
| 363 | ||
| 364 | None | |
| 363 | 365 | } |
| 364 | 366 | |
| 365 | 367 | fn is_empty_expr(expr: &ast::Expr) -> bool { |
| ... | ... | @@ -2565,6 +2567,60 @@ fn main() { |
| 2565 | 2567 | ); |
| 2566 | 2568 | } |
| 2567 | 2569 | |
| 2570 | #[test] | |
| 2571 | fn test_replace_match_multi_arms_with_if_let() { | |
| 2572 | check_assist( | |
| 2573 | replace_match_with_if_let, | |
| 2574 | r#" | |
| 2575 | fn main() { | |
| 2576 | match$0 Some(0) { | |
| 2577 | Some(n) if n % 2 == 0 && n != 6 => (), | |
| 2578 | Some(n) if valided(n) => foo(), | |
| 2579 | _ => code(), | |
| 2580 | } | |
| 2581 | } | |
| 2582 | "#, | |
| 2583 | r#" | |
| 2584 | fn main() { | |
| 2585 | if let Some(n) = Some(0) && (n % 2 == 0 && n != 6) { | |
| 2586 | () | |
| 2587 | } else if let Some(n) = Some(0) && valided(n) { | |
| 2588 | foo() | |
| 2589 | } else { | |
| 2590 | code() | |
| 2591 | } | |
| 2592 | } | |
| 2593 | "#, | |
| 2594 | ); | |
| 2595 | } | |
| 2596 | ||
| 2597 | #[test] | |
| 2598 | fn test_replace_match_with_if_let_other_guards() { | |
| 2599 | check_assist( | |
| 2600 | replace_match_with_if_let, | |
| 2601 | r#" | |
| 2602 | fn main() { | |
| 2603 | match$0 Some(0) { | |
| 2604 | Some(n) if n % 2 == 0 && n != 6 => (), | |
| 2605 | _ if cond => foo(), | |
| 2606 | _ => code(), | |
| 2607 | } | |
| 2608 | } | |
| 2609 | "#, | |
| 2610 | r#" | |
| 2611 | fn main() { | |
| 2612 | if let Some(n) = Some(0) && (n % 2 == 0 && n != 6) { | |
| 2613 | () | |
| 2614 | } else if cond { | |
| 2615 | foo() | |
| 2616 | } else { | |
| 2617 | code() | |
| 2618 | } | |
| 2619 | } | |
| 2620 | "#, | |
| 2621 | ); | |
| 2622 | } | |
| 2623 | ||
| 2568 | 2624 | #[test] |
| 2569 | 2625 | fn test_replace_match_with_if_let_not_applicable_pat2_is_ident_pat() { |
| 2570 | 2626 | check_assist_not_applicable( |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs+1-1| ... | ... | @@ -86,7 +86,7 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_, '_>) |
| 86 | 86 | // - After the arm. In this case we always want to insert a comma after the newly |
| 87 | 87 | // inserted arm. |
| 88 | 88 | // - Missing after the arm, with no arms after. In this case we want to insert a |
| 89 | // comma before the newly inserted arm. It can not be necessary if there arm | |
| 89 | // comma before the newly inserted arm. It can not be necessary if the arm | |
| 90 | 90 | // body is a block, but we don't bother to check that. |
| 91 | 91 | // - Missing after the arm with arms after, if the arm body is a block. In this case |
| 92 | 92 | // we don't want to insert a comma at all. |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs+113-8| ... | ... | @@ -113,16 +113,21 @@ pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_, '_>) |
| 113 | 113 | |
| 114 | 114 | let arg_list = call_expr.arg_list().unwrap(); |
| 115 | 115 | if is_unit_type { |
| 116 | let tail_parent = tail_expr | |
| 117 | .syntax() | |
| 118 | .parent() | |
| 119 | .and_then(Either::<ast::ReturnExpr, ast::StmtList>::cast) | |
| 120 | .unwrap(); | |
| 116 | let tail_parent = tail_expr.syntax().parent().and_then( | |
| 117 | Either::<Either<ast::ReturnExpr, ast::BreakExpr>, ast::StmtList>::cast, | |
| 118 | ); | |
| 121 | 119 | match tail_parent { |
| 122 | Either::Left(ret_expr) => { | |
| 123 | editor.replace(ret_expr.syntax(), make.expr_return(None).syntax()) | |
| 120 | Some(Either::Left(_expr)) => { | |
| 121 | if let Some(ws) = tail_expr | |
| 122 | .syntax() | |
| 123 | .prev_sibling_or_token() | |
| 124 | .filter(|e| e.kind() == SyntaxKind::WHITESPACE) | |
| 125 | { | |
| 126 | editor.delete(ws); | |
| 127 | } | |
| 128 | editor.delete(tail_expr.syntax()); | |
| 124 | 129 | } |
| 125 | Either::Right(stmt_list) => { | |
| 130 | Some(Either::Right(stmt_list)) => { | |
| 126 | 131 | let new_block = if stmt_list.statements().next().is_none() { |
| 127 | 132 | make.expr_empty_block() |
| 128 | 133 | } else { |
| ... | ... | @@ -133,6 +138,10 @@ pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_, '_>) |
| 133 | 138 | new_block.stmt_list().unwrap().syntax(), |
| 134 | 139 | ); |
| 135 | 140 | } |
| 141 | // Parent is a match arm or similar — replace with () | |
| 142 | None => { | |
| 143 | editor.replace(tail_expr.syntax(), make.expr_unit().syntax()); | |
| 144 | } | |
| 136 | 145 | } |
| 137 | 146 | } else if let Some(first_arg) = arg_list.args().next() { |
| 138 | 147 | editor.replace(tail_expr.syntax(), first_arg.syntax()); |
| ... | ... | @@ -2245,6 +2254,102 @@ fn foo(the_field: u32) -> u32 { |
| 2245 | 2254 | ); |
| 2246 | 2255 | } |
| 2247 | 2256 | |
| 2257 | #[test] | |
| 2258 | fn unwrap_option_return_type_unit_type_match_arm() { | |
| 2259 | check_assist_by_label( | |
| 2260 | unwrap_return_type, | |
| 2261 | r#" | |
| 2262 | //- minicore: option | |
| 2263 | fn foo(flag: bool) -> Option<()$0> { | |
| 2264 | match flag { | |
| 2265 | true => Some(()), | |
| 2266 | false => None, | |
| 2267 | } | |
| 2268 | } | |
| 2269 | "#, | |
| 2270 | r#" | |
| 2271 | fn foo(flag: bool) { | |
| 2272 | match flag { | |
| 2273 | true => (), | |
| 2274 | false => ${1:()}$0, | |
| 2275 | } | |
| 2276 | } | |
| 2277 | "#, | |
| 2278 | "Unwrap Option return type", | |
| 2279 | ); | |
| 2280 | } | |
| 2281 | ||
| 2282 | #[test] | |
| 2283 | fn unwrap_option_return_type_unit_type_break() { | |
| 2284 | check_assist_by_label( | |
| 2285 | unwrap_return_type, | |
| 2286 | r#" | |
| 2287 | //- minicore: option | |
| 2288 | fn foo() -> Option<()$0> { | |
| 2289 | loop { | |
| 2290 | break Some(()); | |
| 2291 | } | |
| 2292 | } | |
| 2293 | "#, | |
| 2294 | r#" | |
| 2295 | fn foo() { | |
| 2296 | loop { | |
| 2297 | break; | |
| 2298 | } | |
| 2299 | } | |
| 2300 | "#, | |
| 2301 | "Unwrap Option return type", | |
| 2302 | ); | |
| 2303 | } | |
| 2304 | ||
| 2305 | #[test] | |
| 2306 | fn unwrap_option_return_type_unit_type_break_with_label() { | |
| 2307 | check_assist_by_label( | |
| 2308 | unwrap_return_type, | |
| 2309 | r#" | |
| 2310 | //- minicore: option | |
| 2311 | fn foo() -> Option<()$0> { | |
| 2312 | 'outer: loop { | |
| 2313 | break 'outer Some(()); | |
| 2314 | } | |
| 2315 | } | |
| 2316 | "#, | |
| 2317 | r#" | |
| 2318 | fn foo() { | |
| 2319 | 'outer: loop { | |
| 2320 | break 'outer; | |
| 2321 | } | |
| 2322 | } | |
| 2323 | "#, | |
| 2324 | "Unwrap Option return type", | |
| 2325 | ); | |
| 2326 | } | |
| 2327 | ||
| 2328 | #[test] | |
| 2329 | fn unwrap_result_return_type_unit_type_match_arm() { | |
| 2330 | check_assist_by_label( | |
| 2331 | unwrap_return_type, | |
| 2332 | r#" | |
| 2333 | //- minicore: result | |
| 2334 | fn foo(flag: bool) -> Result<(), ()$0> { | |
| 2335 | match flag { | |
| 2336 | true => Ok(()), | |
| 2337 | false => Err(()), | |
| 2338 | } | |
| 2339 | } | |
| 2340 | "#, | |
| 2341 | r#" | |
| 2342 | fn foo(flag: bool) { | |
| 2343 | match flag { | |
| 2344 | true => (), | |
| 2345 | false => (), | |
| 2346 | } | |
| 2347 | } | |
| 2348 | "#, | |
| 2349 | "Unwrap Result return type", | |
| 2350 | ); | |
| 2351 | } | |
| 2352 | ||
| 2248 | 2353 | #[test] |
| 2249 | 2354 | fn unwrap_result_return_type_nested_type() { |
| 2250 | 2355 | check_assist_by_label( |
src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs+2-2| ... | ... | @@ -127,6 +127,7 @@ pub(crate) fn complete_attribute_path( |
| 127 | 127 | } |
| 128 | 128 | let qualifier_path = |
| 129 | 129 | if let Qualified::With { path, .. } = qualified { Some(path) } else { None }; |
| 130 | let qualifier_segments = qualifier_path.iter().flat_map(|q| q.segments()).collect::<Vec<_>>(); | |
| 130 | 131 | |
| 131 | 132 | let attributes = annotated_item_kind.and_then(|kind| { |
| 132 | 133 | if ast::Expr::can_cast(kind) { |
| ... | ... | @@ -141,9 +142,8 @@ pub(crate) fn complete_attribute_path( |
| 141 | 142 | // add the missing parts to the label and snippet |
| 142 | 143 | let mut label = attr_completion.label.to_owned(); |
| 143 | 144 | let mut snippet = attr_completion.snippet.map(|s| s.to_owned()); |
| 144 | let segments = qualifier_path.iter().flat_map(|q| q.segments()).collect::<Vec<_>>(); | |
| 145 | 145 | let qualifiers = attr_completion.qualifiers; |
| 146 | let matching_qualifiers = segments | |
| 146 | let matching_qualifiers = qualifier_segments | |
| 147 | 147 | .iter() |
| 148 | 148 | .zip(qualifiers) |
| 149 | 149 | .take_while(|(s, q)| s.name_ref().is_some_and(|t| t.text() == **q)) |
src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs+19| ... | ... | @@ -1046,6 +1046,25 @@ mod cfg { |
| 1046 | 1046 | ); |
| 1047 | 1047 | } |
| 1048 | 1048 | |
| 1049 | #[test] | |
| 1050 | fn inside_cfg_attr_gating_attr_macro() { | |
| 1051 | check( | |
| 1052 | r#" | |
| 1053 | //- proc_macros: identity | |
| 1054 | //- /main.rs cfg:feature=on | |
| 1055 | #[cfg_attr(feat$0ure = "on", proc_macros::identity)] | |
| 1056 | fn f() {} | |
| 1057 | "#, | |
| 1058 | expect![[r#" | |
| 1059 | ba all | |
| 1060 | ba any | |
| 1061 | ba feature | |
| 1062 | ba not | |
| 1063 | ba true | |
| 1064 | "#]], | |
| 1065 | ); | |
| 1066 | } | |
| 1067 | ||
| 1049 | 1068 | #[test] |
| 1050 | 1069 | fn complete_key_attr() { |
| 1051 | 1070 | check_edit( |
src/tools/rust-analyzer/crates/ide-db/src/lib.rs+4-7| ... | ... | @@ -63,10 +63,7 @@ use base_db::{ |
| 63 | 63 | CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, Nonce, SourceDatabase, |
| 64 | 64 | SourceRoot, SourceRootId, SourceRootInput, set_all_crates_with_durability, |
| 65 | 65 | }; |
| 66 | use hir::{ | |
| 67 | FilePositionWrapper, FileRangeWrapper, | |
| 68 | db::{DefDatabase, ExpandDatabase, HirDatabase}, | |
| 69 | }; | |
| 66 | use hir::{FilePositionWrapper, FileRangeWrapper, db::HirDatabase}; | |
| 70 | 67 | use triomphe::Arc; |
| 71 | 68 | |
| 72 | 69 | use crate::line_index::LineIndex; |
| ... | ... | @@ -203,20 +200,20 @@ impl RootDatabase { |
| 203 | 200 | // This needs to be here otherwise `CrateGraphBuilder` will panic. |
| 204 | 201 | set_all_crates_with_durability(&mut db, std::iter::empty(), Durability::HIGH); |
| 205 | 202 | CrateGraphBuilder::default().set_in_db(&mut db); |
| 206 | db.set_proc_macros_with_durability(Default::default(), Durability::MEDIUM); | |
| 203 | hir::ProcMacros::init_default(&db, Durability::MEDIUM); | |
| 207 | 204 | _ = base_db::LibraryRoots::builder(Default::default()) |
| 208 | 205 | .durability(Durability::MEDIUM) |
| 209 | 206 | .new(&db); |
| 210 | 207 | _ = base_db::LocalRoots::builder(Default::default()) |
| 211 | 208 | .durability(Durability::MEDIUM) |
| 212 | 209 | .new(&db); |
| 213 | db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH); | |
| 210 | hir::db::set_expand_proc_attr_macros(&mut db, false); | |
| 214 | 211 | db.update_base_query_lru_capacities(lru_capacity); |
| 215 | 212 | db |
| 216 | 213 | } |
| 217 | 214 | |
| 218 | 215 | pub fn enable_proc_attr_macros(&mut self) { |
| 219 | self.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); | |
| 216 | hir::db::set_expand_proc_attr_macros(self, true); | |
| 220 | 217 | } |
| 221 | 218 | |
| 222 | 219 | pub fn update_base_query_lru_capacities(&mut self, _lru_capacity: Option<u16>) { |
src/tools/rust-analyzer/crates/ide-db/src/source_change.rs+4-8| ... | ... | @@ -164,13 +164,9 @@ impl SnippetEdit { |
| 164 | 164 | .into_iter() |
| 165 | 165 | .zip(1..) |
| 166 | 166 | .with_position() |
| 167 | .flat_map(|pos| { | |
| 168 | let (snippet, index) = match pos { | |
| 169 | (itertools::Position::First, it) | (itertools::Position::Middle, it) => it, | |
| 170 | // last/only snippet gets index 0 | |
| 171 | (itertools::Position::Last, (snippet, _)) | |
| 172 | | (itertools::Position::Only, (snippet, _)) => (snippet, 0), | |
| 173 | }; | |
| 167 | .flat_map(|(position, (snippet, index))| { | |
| 168 | // The last/only snippet gets index 0. | |
| 169 | let index = if position.is_last { 0 } else { index }; | |
| 174 | 170 | |
| 175 | 171 | match snippet { |
| 176 | 172 | Snippet::Tabstop(pos) => vec![(index, TextRange::empty(pos))], |
| ... | ... | @@ -264,7 +260,7 @@ impl SourceChangeBuilder { |
| 264 | 260 | } |
| 265 | 261 | |
| 266 | 262 | pub fn make_editor(&self, node: &SyntaxNode) -> SyntaxEditor { |
| 267 | SyntaxEditor::new(node.ancestors().last().unwrap_or_else(|| node.clone())).0 | |
| 263 | SyntaxEditor::new(node.tree_top()).0 | |
| 268 | 264 | } |
| 269 | 265 | |
| 270 | 266 | pub fn add_file_edits(&mut self, file_id: impl Into<FileId>, editor: SyntaxEditor) { |
src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt+15-15| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | ( |
| 3 | 3 | Module { |
| 4 | 4 | id: ModuleIdLt { |
| 5 | [salsa id]: Id(3000), | |
| 5 | [salsa id]: Id(2800), | |
| 6 | 6 | }, |
| 7 | 7 | }, |
| 8 | 8 | [ |
| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | Struct( |
| 13 | 13 | Struct { |
| 14 | 14 | id: StructId( |
| 15 | 3801, | |
| 15 | 3001, | |
| 16 | 16 | ), |
| 17 | 17 | }, |
| 18 | 18 | ), |
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | loc: DeclarationLocation { |
| 21 | 21 | hir_file_id: FileId( |
| 22 | 22 | EditionedFileId( |
| 23 | Id(2c00), | |
| 23 | Id(2400), | |
| 24 | 24 | ), |
| 25 | 25 | ), |
| 26 | 26 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -49,7 +49,7 @@ |
| 49 | 49 | Struct( |
| 50 | 50 | Struct { |
| 51 | 51 | id: StructId( |
| 52 | 3800, | |
| 52 | 3000, | |
| 53 | 53 | ), |
| 54 | 54 | }, |
| 55 | 55 | ), |
| ... | ... | @@ -57,7 +57,7 @@ |
| 57 | 57 | loc: DeclarationLocation { |
| 58 | 58 | hir_file_id: FileId( |
| 59 | 59 | EditionedFileId( |
| 60 | Id(2c00), | |
| 60 | Id(2400), | |
| 61 | 61 | ), |
| 62 | 62 | ), |
| 63 | 63 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -86,7 +86,7 @@ |
| 86 | 86 | Struct( |
| 87 | 87 | Struct { |
| 88 | 88 | id: StructId( |
| 89 | 3800, | |
| 89 | 3000, | |
| 90 | 90 | ), |
| 91 | 91 | }, |
| 92 | 92 | ), |
| ... | ... | @@ -94,7 +94,7 @@ |
| 94 | 94 | loc: DeclarationLocation { |
| 95 | 95 | hir_file_id: FileId( |
| 96 | 96 | EditionedFileId( |
| 97 | Id(2c00), | |
| 97 | Id(2400), | |
| 98 | 98 | ), |
| 99 | 99 | ), |
| 100 | 100 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -123,7 +123,7 @@ |
| 123 | 123 | Struct( |
| 124 | 124 | Struct { |
| 125 | 125 | id: StructId( |
| 126 | 3800, | |
| 126 | 3000, | |
| 127 | 127 | ), |
| 128 | 128 | }, |
| 129 | 129 | ), |
| ... | ... | @@ -131,7 +131,7 @@ |
| 131 | 131 | loc: DeclarationLocation { |
| 132 | 132 | hir_file_id: FileId( |
| 133 | 133 | EditionedFileId( |
| 134 | Id(2c00), | |
| 134 | Id(2400), | |
| 135 | 135 | ), |
| 136 | 136 | ), |
| 137 | 137 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -160,7 +160,7 @@ |
| 160 | 160 | Struct( |
| 161 | 161 | Struct { |
| 162 | 162 | id: StructId( |
| 163 | 3800, | |
| 163 | 3000, | |
| 164 | 164 | ), |
| 165 | 165 | }, |
| 166 | 166 | ), |
| ... | ... | @@ -168,7 +168,7 @@ |
| 168 | 168 | loc: DeclarationLocation { |
| 169 | 169 | hir_file_id: FileId( |
| 170 | 170 | EditionedFileId( |
| 171 | Id(2c00), | |
| 171 | Id(2400), | |
| 172 | 172 | ), |
| 173 | 173 | ), |
| 174 | 174 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -197,7 +197,7 @@ |
| 197 | 197 | Struct( |
| 198 | 198 | Struct { |
| 199 | 199 | id: StructId( |
| 200 | 3801, | |
| 200 | 3001, | |
| 201 | 201 | ), |
| 202 | 202 | }, |
| 203 | 203 | ), |
| ... | ... | @@ -205,7 +205,7 @@ |
| 205 | 205 | loc: DeclarationLocation { |
| 206 | 206 | hir_file_id: FileId( |
| 207 | 207 | EditionedFileId( |
| 208 | Id(2c00), | |
| 208 | Id(2400), | |
| 209 | 209 | ), |
| 210 | 210 | ), |
| 211 | 211 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -234,7 +234,7 @@ |
| 234 | 234 | Struct( |
| 235 | 235 | Struct { |
| 236 | 236 | id: StructId( |
| 237 | 3800, | |
| 237 | 3000, | |
| 238 | 238 | ), |
| 239 | 239 | }, |
| 240 | 240 | ), |
| ... | ... | @@ -242,7 +242,7 @@ |
| 242 | 242 | loc: DeclarationLocation { |
| 243 | 243 | hir_file_id: FileId( |
| 244 | 244 | EditionedFileId( |
| 245 | Id(2c00), | |
| 245 | Id(2400), | |
| 246 | 246 | ), |
| 247 | 247 | ), |
| 248 | 248 | ptr: SyntaxNodePtr { |
src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt+69-69| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | ( |
| 3 | 3 | Module { |
| 4 | 4 | id: ModuleIdLt { |
| 5 | [salsa id]: Id(3000), | |
| 5 | [salsa id]: Id(2800), | |
| 6 | 6 | }, |
| 7 | 7 | }, |
| 8 | 8 | [ |
| ... | ... | @@ -11,14 +11,14 @@ |
| 11 | 11 | def: EnumVariant( |
| 12 | 12 | EnumVariant { |
| 13 | 13 | id: EnumVariantId( |
| 14 | 7800, | |
| 14 | 7000, | |
| 15 | 15 | ), |
| 16 | 16 | }, |
| 17 | 17 | ), |
| 18 | 18 | loc: DeclarationLocation { |
| 19 | 19 | hir_file_id: FileId( |
| 20 | 20 | EditionedFileId( |
| 21 | Id(2c00), | |
| 21 | Id(2400), | |
| 22 | 22 | ), |
| 23 | 23 | ), |
| 24 | 24 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -48,14 +48,14 @@ |
| 48 | 48 | def: TypeAlias( |
| 49 | 49 | TypeAlias { |
| 50 | 50 | id: TypeAliasId( |
| 51 | 6c00, | |
| 51 | 6400, | |
| 52 | 52 | ), |
| 53 | 53 | }, |
| 54 | 54 | ), |
| 55 | 55 | loc: DeclarationLocation { |
| 56 | 56 | hir_file_id: FileId( |
| 57 | 57 | EditionedFileId( |
| 58 | Id(2c00), | |
| 58 | Id(2400), | |
| 59 | 59 | ), |
| 60 | 60 | ), |
| 61 | 61 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -83,14 +83,14 @@ |
| 83 | 83 | def: EnumVariant( |
| 84 | 84 | EnumVariant { |
| 85 | 85 | id: EnumVariantId( |
| 86 | 7801, | |
| 86 | 7001, | |
| 87 | 87 | ), |
| 88 | 88 | }, |
| 89 | 89 | ), |
| 90 | 90 | loc: DeclarationLocation { |
| 91 | 91 | hir_file_id: FileId( |
| 92 | 92 | EditionedFileId( |
| 93 | Id(2c00), | |
| 93 | Id(2400), | |
| 94 | 94 | ), |
| 95 | 95 | ), |
| 96 | 96 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -120,14 +120,14 @@ |
| 120 | 120 | def: Const( |
| 121 | 121 | Const { |
| 122 | 122 | id: ConstId( |
| 123 | 6400, | |
| 123 | 5c00, | |
| 124 | 124 | ), |
| 125 | 125 | }, |
| 126 | 126 | ), |
| 127 | 127 | loc: DeclarationLocation { |
| 128 | 128 | hir_file_id: FileId( |
| 129 | 129 | EditionedFileId( |
| 130 | Id(2c00), | |
| 130 | Id(2400), | |
| 131 | 131 | ), |
| 132 | 132 | ), |
| 133 | 133 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -155,14 +155,14 @@ |
| 155 | 155 | def: Const( |
| 156 | 156 | Const { |
| 157 | 157 | id: ConstId( |
| 158 | 6402, | |
| 158 | 5c02, | |
| 159 | 159 | ), |
| 160 | 160 | }, |
| 161 | 161 | ), |
| 162 | 162 | loc: DeclarationLocation { |
| 163 | 163 | hir_file_id: FileId( |
| 164 | 164 | EditionedFileId( |
| 165 | Id(2c00), | |
| 165 | Id(2400), | |
| 166 | 166 | ), |
| 167 | 167 | ), |
| 168 | 168 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -191,7 +191,7 @@ |
| 191 | 191 | Enum( |
| 192 | 192 | Enum { |
| 193 | 193 | id: EnumId( |
| 194 | 5000, | |
| 194 | 4800, | |
| 195 | 195 | ), |
| 196 | 196 | }, |
| 197 | 197 | ), |
| ... | ... | @@ -199,7 +199,7 @@ |
| 199 | 199 | loc: DeclarationLocation { |
| 200 | 200 | hir_file_id: FileId( |
| 201 | 201 | EditionedFileId( |
| 202 | Id(2c00), | |
| 202 | Id(2400), | |
| 203 | 203 | ), |
| 204 | 204 | ), |
| 205 | 205 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -228,7 +228,7 @@ |
| 228 | 228 | Macro { |
| 229 | 229 | id: Macro2Id( |
| 230 | 230 | Macro2Id( |
| 231 | 4c00, | |
| 231 | 4400, | |
| 232 | 232 | ), |
| 233 | 233 | ), |
| 234 | 234 | }, |
| ... | ... | @@ -236,7 +236,7 @@ |
| 236 | 236 | loc: DeclarationLocation { |
| 237 | 237 | hir_file_id: FileId( |
| 238 | 238 | EditionedFileId( |
| 239 | Id(2c00), | |
| 239 | Id(2400), | |
| 240 | 240 | ), |
| 241 | 241 | ), |
| 242 | 242 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -265,7 +265,7 @@ |
| 265 | 265 | Macro { |
| 266 | 266 | id: Macro2Id( |
| 267 | 267 | Macro2Id( |
| 268 | 4c00, | |
| 268 | 4400, | |
| 269 | 269 | ), |
| 270 | 270 | ), |
| 271 | 271 | }, |
| ... | ... | @@ -273,7 +273,7 @@ |
| 273 | 273 | loc: DeclarationLocation { |
| 274 | 274 | hir_file_id: FileId( |
| 275 | 275 | EditionedFileId( |
| 276 | Id(2c00), | |
| 276 | Id(2400), | |
| 277 | 277 | ), |
| 278 | 278 | ), |
| 279 | 279 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -301,14 +301,14 @@ |
| 301 | 301 | def: Static( |
| 302 | 302 | Static { |
| 303 | 303 | id: StaticId( |
| 304 | 6800, | |
| 304 | 6000, | |
| 305 | 305 | ), |
| 306 | 306 | }, |
| 307 | 307 | ), |
| 308 | 308 | loc: DeclarationLocation { |
| 309 | 309 | hir_file_id: FileId( |
| 310 | 310 | EditionedFileId( |
| 311 | Id(2c00), | |
| 311 | Id(2400), | |
| 312 | 312 | ), |
| 313 | 313 | ), |
| 314 | 314 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -337,7 +337,7 @@ |
| 337 | 337 | Struct( |
| 338 | 338 | Struct { |
| 339 | 339 | id: StructId( |
| 340 | 4801, | |
| 340 | 4001, | |
| 341 | 341 | ), |
| 342 | 342 | }, |
| 343 | 343 | ), |
| ... | ... | @@ -345,7 +345,7 @@ |
| 345 | 345 | loc: DeclarationLocation { |
| 346 | 346 | hir_file_id: FileId( |
| 347 | 347 | EditionedFileId( |
| 348 | Id(2c00), | |
| 348 | Id(2400), | |
| 349 | 349 | ), |
| 350 | 350 | ), |
| 351 | 351 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -374,7 +374,7 @@ |
| 374 | 374 | Struct( |
| 375 | 375 | Struct { |
| 376 | 376 | id: StructId( |
| 377 | 4800, | |
| 377 | 4000, | |
| 378 | 378 | ), |
| 379 | 379 | }, |
| 380 | 380 | ), |
| ... | ... | @@ -382,7 +382,7 @@ |
| 382 | 382 | loc: DeclarationLocation { |
| 383 | 383 | hir_file_id: MacroFile( |
| 384 | 384 | MacroCallId( |
| 385 | Id(4000), | |
| 385 | Id(3800), | |
| 386 | 386 | ), |
| 387 | 387 | ), |
| 388 | 388 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -411,7 +411,7 @@ |
| 411 | 411 | Struct( |
| 412 | 412 | Struct { |
| 413 | 413 | id: StructId( |
| 414 | 4805, | |
| 414 | 4005, | |
| 415 | 415 | ), |
| 416 | 416 | }, |
| 417 | 417 | ), |
| ... | ... | @@ -419,7 +419,7 @@ |
| 419 | 419 | loc: DeclarationLocation { |
| 420 | 420 | hir_file_id: FileId( |
| 421 | 421 | EditionedFileId( |
| 422 | Id(2c00), | |
| 422 | Id(2400), | |
| 423 | 423 | ), |
| 424 | 424 | ), |
| 425 | 425 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -450,7 +450,7 @@ |
| 450 | 450 | Struct( |
| 451 | 451 | Struct { |
| 452 | 452 | id: StructId( |
| 453 | 4806, | |
| 453 | 4006, | |
| 454 | 454 | ), |
| 455 | 455 | }, |
| 456 | 456 | ), |
| ... | ... | @@ -458,7 +458,7 @@ |
| 458 | 458 | loc: DeclarationLocation { |
| 459 | 459 | hir_file_id: FileId( |
| 460 | 460 | EditionedFileId( |
| 461 | Id(2c00), | |
| 461 | Id(2400), | |
| 462 | 462 | ), |
| 463 | 463 | ), |
| 464 | 464 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -489,7 +489,7 @@ |
| 489 | 489 | Struct( |
| 490 | 490 | Struct { |
| 491 | 491 | id: StructId( |
| 492 | 4807, | |
| 492 | 4007, | |
| 493 | 493 | ), |
| 494 | 494 | }, |
| 495 | 495 | ), |
| ... | ... | @@ -497,7 +497,7 @@ |
| 497 | 497 | loc: DeclarationLocation { |
| 498 | 498 | hir_file_id: FileId( |
| 499 | 499 | EditionedFileId( |
| 500 | Id(2c00), | |
| 500 | Id(2400), | |
| 501 | 501 | ), |
| 502 | 502 | ), |
| 503 | 503 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -526,7 +526,7 @@ |
| 526 | 526 | Struct( |
| 527 | 527 | Struct { |
| 528 | 528 | id: StructId( |
| 529 | 4802, | |
| 529 | 4002, | |
| 530 | 530 | ), |
| 531 | 531 | }, |
| 532 | 532 | ), |
| ... | ... | @@ -534,7 +534,7 @@ |
| 534 | 534 | loc: DeclarationLocation { |
| 535 | 535 | hir_file_id: FileId( |
| 536 | 536 | EditionedFileId( |
| 537 | Id(2c00), | |
| 537 | Id(2400), | |
| 538 | 538 | ), |
| 539 | 539 | ), |
| 540 | 540 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -562,14 +562,14 @@ |
| 562 | 562 | def: Trait( |
| 563 | 563 | Trait { |
| 564 | 564 | id: TraitId( |
| 565 | 5c00, | |
| 565 | 5400, | |
| 566 | 566 | ), |
| 567 | 567 | }, |
| 568 | 568 | ), |
| 569 | 569 | loc: DeclarationLocation { |
| 570 | 570 | hir_file_id: FileId( |
| 571 | 571 | EditionedFileId( |
| 572 | Id(2c00), | |
| 572 | Id(2400), | |
| 573 | 573 | ), |
| 574 | 574 | ), |
| 575 | 575 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -598,7 +598,7 @@ |
| 598 | 598 | Macro { |
| 599 | 599 | id: Macro2Id( |
| 600 | 600 | Macro2Id( |
| 601 | 4c00, | |
| 601 | 4400, | |
| 602 | 602 | ), |
| 603 | 603 | ), |
| 604 | 604 | }, |
| ... | ... | @@ -606,7 +606,7 @@ |
| 606 | 606 | loc: DeclarationLocation { |
| 607 | 607 | hir_file_id: FileId( |
| 608 | 608 | EditionedFileId( |
| 609 | Id(2c00), | |
| 609 | Id(2400), | |
| 610 | 610 | ), |
| 611 | 611 | ), |
| 612 | 612 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -635,7 +635,7 @@ |
| 635 | 635 | Union( |
| 636 | 636 | Union { |
| 637 | 637 | id: UnionId( |
| 638 | 5400, | |
| 638 | 4c00, | |
| 639 | 639 | ), |
| 640 | 640 | }, |
| 641 | 641 | ), |
| ... | ... | @@ -643,7 +643,7 @@ |
| 643 | 643 | loc: DeclarationLocation { |
| 644 | 644 | hir_file_id: FileId( |
| 645 | 645 | EditionedFileId( |
| 646 | Id(2c00), | |
| 646 | Id(2400), | |
| 647 | 647 | ), |
| 648 | 648 | ), |
| 649 | 649 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -671,14 +671,14 @@ |
| 671 | 671 | def: Module( |
| 672 | 672 | Module { |
| 673 | 673 | id: ModuleIdLt { |
| 674 | [salsa id]: Id(3001), | |
| 674 | [salsa id]: Id(2801), | |
| 675 | 675 | }, |
| 676 | 676 | }, |
| 677 | 677 | ), |
| 678 | 678 | loc: DeclarationLocation { |
| 679 | 679 | hir_file_id: FileId( |
| 680 | 680 | EditionedFileId( |
| 681 | Id(2c00), | |
| 681 | Id(2400), | |
| 682 | 682 | ), |
| 683 | 683 | ), |
| 684 | 684 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -706,14 +706,14 @@ |
| 706 | 706 | def: Module( |
| 707 | 707 | Module { |
| 708 | 708 | id: ModuleIdLt { |
| 709 | [salsa id]: Id(3002), | |
| 709 | [salsa id]: Id(2802), | |
| 710 | 710 | }, |
| 711 | 711 | }, |
| 712 | 712 | ), |
| 713 | 713 | loc: DeclarationLocation { |
| 714 | 714 | hir_file_id: FileId( |
| 715 | 715 | EditionedFileId( |
| 716 | Id(2c00), | |
| 716 | Id(2400), | |
| 717 | 717 | ), |
| 718 | 718 | ), |
| 719 | 719 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -742,7 +742,7 @@ |
| 742 | 742 | Macro { |
| 743 | 743 | id: MacroRulesId( |
| 744 | 744 | MacroRulesId( |
| 745 | 3c01, | |
| 745 | 3401, | |
| 746 | 746 | ), |
| 747 | 747 | ), |
| 748 | 748 | }, |
| ... | ... | @@ -750,7 +750,7 @@ |
| 750 | 750 | loc: DeclarationLocation { |
| 751 | 751 | hir_file_id: FileId( |
| 752 | 752 | EditionedFileId( |
| 753 | Id(2c00), | |
| 753 | Id(2400), | |
| 754 | 754 | ), |
| 755 | 755 | ), |
| 756 | 756 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -778,14 +778,14 @@ |
| 778 | 778 | def: Function( |
| 779 | 779 | FunctionId( |
| 780 | 780 | FunctionId( |
| 781 | 6002, | |
| 781 | 5802, | |
| 782 | 782 | ), |
| 783 | 783 | ), |
| 784 | 784 | ), |
| 785 | 785 | loc: DeclarationLocation { |
| 786 | 786 | hir_file_id: FileId( |
| 787 | 787 | EditionedFileId( |
| 788 | Id(2c00), | |
| 788 | Id(2400), | |
| 789 | 789 | ), |
| 790 | 790 | ), |
| 791 | 791 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -815,14 +815,14 @@ |
| 815 | 815 | def: Function( |
| 816 | 816 | FunctionId( |
| 817 | 817 | FunctionId( |
| 818 | 6001, | |
| 818 | 5801, | |
| 819 | 819 | ), |
| 820 | 820 | ), |
| 821 | 821 | ), |
| 822 | 822 | loc: DeclarationLocation { |
| 823 | 823 | hir_file_id: FileId( |
| 824 | 824 | EditionedFileId( |
| 825 | Id(2c00), | |
| 825 | Id(2400), | |
| 826 | 826 | ), |
| 827 | 827 | ), |
| 828 | 828 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -853,7 +853,7 @@ |
| 853 | 853 | Macro { |
| 854 | 854 | id: MacroRulesId( |
| 855 | 855 | MacroRulesId( |
| 856 | 3c00, | |
| 856 | 3400, | |
| 857 | 857 | ), |
| 858 | 858 | ), |
| 859 | 859 | }, |
| ... | ... | @@ -861,7 +861,7 @@ |
| 861 | 861 | loc: DeclarationLocation { |
| 862 | 862 | hir_file_id: FileId( |
| 863 | 863 | EditionedFileId( |
| 864 | Id(2c00), | |
| 864 | Id(2400), | |
| 865 | 865 | ), |
| 866 | 866 | ), |
| 867 | 867 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -889,14 +889,14 @@ |
| 889 | 889 | def: Function( |
| 890 | 890 | FunctionId( |
| 891 | 891 | FunctionId( |
| 892 | 6000, | |
| 892 | 5800, | |
| 893 | 893 | ), |
| 894 | 894 | ), |
| 895 | 895 | ), |
| 896 | 896 | loc: DeclarationLocation { |
| 897 | 897 | hir_file_id: FileId( |
| 898 | 898 | EditionedFileId( |
| 899 | Id(2c00), | |
| 899 | Id(2400), | |
| 900 | 900 | ), |
| 901 | 901 | ), |
| 902 | 902 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -925,7 +925,7 @@ |
| 925 | 925 | Macro { |
| 926 | 926 | id: MacroRulesId( |
| 927 | 927 | MacroRulesId( |
| 928 | 3c01, | |
| 928 | 3401, | |
| 929 | 929 | ), |
| 930 | 930 | ), |
| 931 | 931 | }, |
| ... | ... | @@ -933,7 +933,7 @@ |
| 933 | 933 | loc: DeclarationLocation { |
| 934 | 934 | hir_file_id: FileId( |
| 935 | 935 | EditionedFileId( |
| 936 | Id(2c00), | |
| 936 | Id(2400), | |
| 937 | 937 | ), |
| 938 | 938 | ), |
| 939 | 939 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -961,14 +961,14 @@ |
| 961 | 961 | def: Function( |
| 962 | 962 | FunctionId( |
| 963 | 963 | FunctionId( |
| 964 | 6003, | |
| 964 | 5803, | |
| 965 | 965 | ), |
| 966 | 966 | ), |
| 967 | 967 | ), |
| 968 | 968 | loc: DeclarationLocation { |
| 969 | 969 | hir_file_id: FileId( |
| 970 | 970 | EditionedFileId( |
| 971 | Id(2c00), | |
| 971 | Id(2400), | |
| 972 | 972 | ), |
| 973 | 973 | ), |
| 974 | 974 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -998,7 +998,7 @@ |
| 998 | 998 | ( |
| 999 | 999 | Module { |
| 1000 | 1000 | id: ModuleIdLt { |
| 1001 | [salsa id]: Id(3001), | |
| 1001 | [salsa id]: Id(2801), | |
| 1002 | 1002 | }, |
| 1003 | 1003 | }, |
| 1004 | 1004 | [ |
| ... | ... | @@ -1008,7 +1008,7 @@ |
| 1008 | 1008 | Struct( |
| 1009 | 1009 | Struct { |
| 1010 | 1010 | id: StructId( |
| 1011 | 4803, | |
| 1011 | 4003, | |
| 1012 | 1012 | ), |
| 1013 | 1013 | }, |
| 1014 | 1014 | ), |
| ... | ... | @@ -1016,7 +1016,7 @@ |
| 1016 | 1016 | loc: DeclarationLocation { |
| 1017 | 1017 | hir_file_id: FileId( |
| 1018 | 1018 | EditionedFileId( |
| 1019 | Id(2c00), | |
| 1019 | Id(2400), | |
| 1020 | 1020 | ), |
| 1021 | 1021 | ), |
| 1022 | 1022 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -1044,7 +1044,7 @@ |
| 1044 | 1044 | ( |
| 1045 | 1045 | Module { |
| 1046 | 1046 | id: ModuleIdLt { |
| 1047 | [salsa id]: Id(3002), | |
| 1047 | [salsa id]: Id(2802), | |
| 1048 | 1048 | }, |
| 1049 | 1049 | }, |
| 1050 | 1050 | [ |
| ... | ... | @@ -1053,14 +1053,14 @@ |
| 1053 | 1053 | def: Trait( |
| 1054 | 1054 | Trait { |
| 1055 | 1055 | id: TraitId( |
| 1056 | 5c00, | |
| 1056 | 5400, | |
| 1057 | 1057 | ), |
| 1058 | 1058 | }, |
| 1059 | 1059 | ), |
| 1060 | 1060 | loc: DeclarationLocation { |
| 1061 | 1061 | hir_file_id: FileId( |
| 1062 | 1062 | EditionedFileId( |
| 1063 | Id(2c01), | |
| 1063 | Id(2401), | |
| 1064 | 1064 | ), |
| 1065 | 1065 | ), |
| 1066 | 1066 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -1089,7 +1089,7 @@ |
| 1089 | 1089 | Macro { |
| 1090 | 1090 | id: Macro2Id( |
| 1091 | 1091 | Macro2Id( |
| 1092 | 4c00, | |
| 1092 | 4400, | |
| 1093 | 1093 | ), |
| 1094 | 1094 | ), |
| 1095 | 1095 | }, |
| ... | ... | @@ -1097,7 +1097,7 @@ |
| 1097 | 1097 | loc: DeclarationLocation { |
| 1098 | 1098 | hir_file_id: FileId( |
| 1099 | 1099 | EditionedFileId( |
| 1100 | Id(2c01), | |
| 1100 | Id(2401), | |
| 1101 | 1101 | ), |
| 1102 | 1102 | ), |
| 1103 | 1103 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -1126,7 +1126,7 @@ |
| 1126 | 1126 | Struct( |
| 1127 | 1127 | Struct { |
| 1128 | 1128 | id: StructId( |
| 1129 | 4804, | |
| 1129 | 4004, | |
| 1130 | 1130 | ), |
| 1131 | 1131 | }, |
| 1132 | 1132 | ), |
| ... | ... | @@ -1134,7 +1134,7 @@ |
| 1134 | 1134 | loc: DeclarationLocation { |
| 1135 | 1135 | hir_file_id: FileId( |
| 1136 | 1136 | EditionedFileId( |
| 1137 | Id(2c01), | |
| 1137 | Id(2401), | |
| 1138 | 1138 | ), |
| 1139 | 1139 | ), |
| 1140 | 1140 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -1163,7 +1163,7 @@ |
| 1163 | 1163 | Macro { |
| 1164 | 1164 | id: Macro2Id( |
| 1165 | 1165 | Macro2Id( |
| 1166 | 4c00, | |
| 1166 | 4400, | |
| 1167 | 1167 | ), |
| 1168 | 1168 | ), |
| 1169 | 1169 | }, |
| ... | ... | @@ -1171,7 +1171,7 @@ |
| 1171 | 1171 | loc: DeclarationLocation { |
| 1172 | 1172 | hir_file_id: FileId( |
| 1173 | 1173 | EditionedFileId( |
| 1174 | Id(2c01), | |
| 1174 | Id(2401), | |
| 1175 | 1175 | ), |
| 1176 | 1176 | ), |
| 1177 | 1177 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -1200,7 +1200,7 @@ |
| 1200 | 1200 | Struct( |
| 1201 | 1201 | Struct { |
| 1202 | 1202 | id: StructId( |
| 1203 | 4804, | |
| 1203 | 4004, | |
| 1204 | 1204 | ), |
| 1205 | 1205 | }, |
| 1206 | 1206 | ), |
| ... | ... | @@ -1208,7 +1208,7 @@ |
| 1208 | 1208 | loc: DeclarationLocation { |
| 1209 | 1209 | hir_file_id: FileId( |
| 1210 | 1210 | EditionedFileId( |
| 1211 | Id(2c01), | |
| 1211 | Id(2401), | |
| 1212 | 1212 | ), |
| 1213 | 1213 | ), |
| 1214 | 1214 | ptr: SyntaxNodePtr { |
src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_exclude_imports.txt+2-2| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | Struct( |
| 6 | 6 | Struct { |
| 7 | 7 | id: StructId( |
| 8 | 3c00, | |
| 8 | 3400, | |
| 9 | 9 | ), |
| 10 | 10 | }, |
| 11 | 11 | ), |
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | loc: DeclarationLocation { |
| 14 | 14 | hir_file_id: FileId( |
| 15 | 15 | EditionedFileId( |
| 16 | Id(2c01), | |
| 16 | Id(2401), | |
| 17 | 17 | ), |
| 18 | 18 | ), |
| 19 | 19 | ptr: SyntaxNodePtr { |
src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_with_imports.txt+4-4| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | Struct( |
| 6 | 6 | Struct { |
| 7 | 7 | id: StructId( |
| 8 | 3c00, | |
| 8 | 3400, | |
| 9 | 9 | ), |
| 10 | 10 | }, |
| 11 | 11 | ), |
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | loc: DeclarationLocation { |
| 14 | 14 | hir_file_id: FileId( |
| 15 | 15 | EditionedFileId( |
| 16 | Id(2c01), | |
| 16 | Id(2401), | |
| 17 | 17 | ), |
| 18 | 18 | ), |
| 19 | 19 | ptr: SyntaxNodePtr { |
| ... | ... | @@ -42,7 +42,7 @@ |
| 42 | 42 | Struct( |
| 43 | 43 | Struct { |
| 44 | 44 | id: StructId( |
| 45 | 3c00, | |
| 45 | 3400, | |
| 46 | 46 | ), |
| 47 | 47 | }, |
| 48 | 48 | ), |
| ... | ... | @@ -50,7 +50,7 @@ |
| 50 | 50 | loc: DeclarationLocation { |
| 51 | 51 | hir_file_id: FileId( |
| 52 | 52 | EditionedFileId( |
| 53 | Id(2c00), | |
| 53 | Id(2400), | |
| 54 | 54 | ), |
| 55 | 55 | ), |
| 56 | 56 | ptr: SyntaxNodePtr { |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs+17| ... | ... | @@ -539,4 +539,21 @@ pub fn repro<T: A>() { |
| 539 | 539 | "#, |
| 540 | 540 | ); |
| 541 | 541 | } |
| 542 | ||
| 543 | #[test] | |
| 544 | fn cfg_inside_macro_inside_arg() { | |
| 545 | check_diagnostics( | |
| 546 | r#" | |
| 547 | fn foo() {} | |
| 548 | ||
| 549 | macro_rules! make_X { | |
| 550 | () => { #[cfg(false)] X }; | |
| 551 | } | |
| 552 | ||
| 553 | fn main() { | |
| 554 | foo(make_X!()); | |
| 555 | } | |
| 556 | "#, | |
| 557 | ); | |
| 558 | } | |
| 542 | 559 | } |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs+2-2| ... | ... | @@ -117,7 +117,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::MissingFields) -> Option<Vec |
| 117 | 117 | }); |
| 118 | 118 | |
| 119 | 119 | let old_field_list = field_list_parent.record_expr_field_list()?; |
| 120 | let root = old_field_list.syntax().ancestors().last()?; | |
| 120 | let root = old_field_list.syntax().tree_top(); | |
| 121 | 121 | let (editor, _) = SyntaxEditor::new(root); |
| 122 | 122 | let make = editor.make(); |
| 123 | 123 | |
| ... | ... | @@ -178,7 +178,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::MissingFields) -> Option<Vec |
| 178 | 178 | let missing_fields = ctx.sema.record_pattern_missing_fields(field_list_parent); |
| 179 | 179 | |
| 180 | 180 | let old_field_list = field_list_parent.record_pat_field_list()?; |
| 181 | let root = old_field_list.syntax().ancestors().last()?; | |
| 181 | let root = old_field_list.syntax().tree_top(); | |
| 182 | 182 | let (editor, _) = SyntaxEditor::new(root); |
| 183 | 183 | let make = editor.make(); |
| 184 | 184 |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mut_ref_in_imm_ref_pat.rs created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; | |
| 2 | ||
| 3 | // Diagnostic: mut-ref-in-imm-ref-pat | |
| 4 | // | |
| 5 | // This diagnostic is triggered when a binding tries to mutably borrow through | |
| 6 | // an `&` pattern. | |
| 7 | pub(crate) fn mut_ref_in_imm_ref_pat( | |
| 8 | ctx: &DiagnosticsContext<'_, '_>, | |
| 9 | d: &hir::MutRefInImmRefPat, | |
| 10 | ) -> Diagnostic { | |
| 11 | Diagnostic::new_with_syntax_node_ptr( | |
| 12 | ctx, | |
| 13 | DiagnosticCode::RustcHardError("E0596"), | |
| 14 | "cannot borrow as mutable inside an `&` pattern", | |
| 15 | d.pat.map(Into::into), | |
| 16 | ) | |
| 17 | .stable() | |
| 18 | } | |
| 19 | ||
| 20 | #[cfg(test)] | |
| 21 | mod tests { | |
| 22 | use crate::tests::check_diagnostics; | |
| 23 | ||
| 24 | #[test] | |
| 25 | fn mut_ref_in_imm_ref_pat() { | |
| 26 | check_diagnostics( | |
| 27 | r#" | |
| 28 | #![feature(ref_pat_eat_one_layer_2024)] | |
| 29 | ||
| 30 | fn main() { | |
| 31 | let &ref mut _x = &mut 0; | |
| 32 | //^^^^^^^^^^ error: cannot borrow as mutable inside an `&` pattern | |
| 33 | } | |
| 34 | "#, | |
| 35 | ); | |
| 36 | } | |
| 37 | } |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs+66| ... | ... | @@ -74,6 +74,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::TypeMismatch<'_>) -> Option< |
| 74 | 74 | remove_unnecessary_wrapper(ctx, d, expr_ptr, &mut fixes); |
| 75 | 75 | remove_semicolon(ctx, d, expr_ptr, &mut fixes); |
| 76 | 76 | str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); |
| 77 | add_await(ctx, d, expr_ptr, &mut fixes); | |
| 77 | 78 | } |
| 78 | 79 | |
| 79 | 80 | if fixes.is_empty() { None } else { Some(fixes) } |
| ... | ... | @@ -377,6 +378,30 @@ fn str_ref_to_owned( |
| 377 | 378 | Some(()) |
| 378 | 379 | } |
| 379 | 380 | |
| 381 | fn add_await( | |
| 382 | ctx: &DiagnosticsContext<'_, '_>, | |
| 383 | d: &hir::TypeMismatch<'_>, | |
| 384 | expr_ptr: &InFile<AstPtr<ast::Expr>>, | |
| 385 | acc: &mut Vec<Assist>, | |
| 386 | ) -> Option<()> { | |
| 387 | let output = d.actual.clone().future_output(ctx.db())?; | |
| 388 | // XXX: maybe should check if ctx is async | |
| 389 | let is_applicable = output.could_coerce_to(ctx.db(), &d.expected); | |
| 390 | if !is_applicable { | |
| 391 | return None; | |
| 392 | } | |
| 393 | ||
| 394 | let root = ctx.db().parse_or_expand(expr_ptr.file_id); | |
| 395 | let expr = expr_ptr.value.to_node(&root); | |
| 396 | let hir::FileRange { file_id, range } = ctx.sema.original_range_opt(expr.syntax())?; | |
| 397 | ||
| 398 | let edit = TextEdit::insert(range.end(), ".await".to_owned()); | |
| 399 | let source_change = SourceChange::from_text_edit(file_id.file_id(ctx.db()), edit); | |
| 400 | acc.push(fix("add_await", "Add .await here", source_change, range)); | |
| 401 | ||
| 402 | Some(()) | |
| 403 | } | |
| 404 | ||
| 380 | 405 | #[cfg(test)] |
| 381 | 406 | mod tests { |
| 382 | 407 | use crate::tests::{ |
| ... | ... | @@ -1394,6 +1419,47 @@ identity! { |
| 1394 | 1419 | ); |
| 1395 | 1420 | } |
| 1396 | 1421 | |
| 1422 | #[test] | |
| 1423 | fn add_await() { | |
| 1424 | check_fix( | |
| 1425 | r#" | |
| 1426 | //- minicore: future | |
| 1427 | async fn foo() -> u32 { 2 } | |
| 1428 | async fn test() { | |
| 1429 | let x: u32 = foo()$0; | |
| 1430 | } | |
| 1431 | "#, | |
| 1432 | r#" | |
| 1433 | async fn foo() -> u32 { 2 } | |
| 1434 | async fn test() { | |
| 1435 | let x: u32 = foo().await; | |
| 1436 | } | |
| 1437 | "#, | |
| 1438 | ); | |
| 1439 | ||
| 1440 | check_fix( | |
| 1441 | r#" | |
| 1442 | //- minicore: future | |
| 1443 | macro_rules! identity { ($($t:tt)*) => ($($t)*) } | |
| 1444 | async fn foo() -> u32 { 2 } | |
| 1445 | identity! { | |
| 1446 | async fn test() { | |
| 1447 | let x: u32 = foo()$0; | |
| 1448 | } | |
| 1449 | } | |
| 1450 | "#, | |
| 1451 | r#" | |
| 1452 | macro_rules! identity { ($($t:tt)*) => ($($t)*) } | |
| 1453 | async fn foo() -> u32 { 2 } | |
| 1454 | identity! { | |
| 1455 | async fn test() { | |
| 1456 | let x: u32 = foo().await; | |
| 1457 | } | |
| 1458 | } | |
| 1459 | "#, | |
| 1460 | ); | |
| 1461 | } | |
| 1462 | ||
| 1397 | 1463 | #[test] |
| 1398 | 1464 | fn type_mismatch_range_adjustment() { |
| 1399 | 1465 | cov_mark::check!(type_mismatch_range_adjustment); |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/union_pat_has_rest.rs created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; | |
| 2 | ||
| 3 | // Diagnostic: union-pat-has-rest | |
| 4 | // | |
| 5 | // A union pattern uses `..`. | |
| 6 | pub(crate) fn union_pat_has_rest( | |
| 7 | ctx: &DiagnosticsContext<'_, '_>, | |
| 8 | d: &hir::UnionPatHasRest, | |
| 9 | ) -> Diagnostic { | |
| 10 | Diagnostic::new_with_syntax_node_ptr( | |
| 11 | ctx, | |
| 12 | DiagnosticCode::RustcHardError("E0784"), | |
| 13 | "union patterns cannot use `..`", | |
| 14 | d.pat.map(Into::into), | |
| 15 | ) | |
| 16 | .stable() | |
| 17 | } | |
| 18 | ||
| 19 | #[cfg(test)] | |
| 20 | mod tests { | |
| 21 | use crate::tests::check_diagnostics; | |
| 22 | ||
| 23 | #[test] | |
| 24 | fn union_pat_has_rest() { | |
| 25 | check_diagnostics( | |
| 26 | r#" | |
| 27 | union Bird { | |
| 28 | pigeon: u8, | |
| 29 | turtledove: u16, | |
| 30 | } | |
| 31 | ||
| 32 | fn main(bird: Bird) { | |
| 33 | unsafe { | |
| 34 | let Bird { pigeon: 0, .. } = bird; | |
| 35 | //^^^^^^^^^^^^^^^^^^^^^^ error: union patterns cannot use `..` | |
| 36 | } | |
| 37 | } | |
| 38 | "#, | |
| 39 | ); | |
| 40 | } | |
| 41 | } |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/union_pat_must_have_exactly_one_field.rs created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; | |
| 2 | ||
| 3 | // Diagnostic: union-pat-must-have-exactly-one-field | |
| 4 | // | |
| 5 | // A union pattern does not have exactly one field. | |
| 6 | pub(crate) fn union_pat_must_have_exactly_one_field( | |
| 7 | ctx: &DiagnosticsContext<'_, '_>, | |
| 8 | d: &hir::UnionPatMustHaveExactlyOneField, | |
| 9 | ) -> Diagnostic { | |
| 10 | Diagnostic::new_with_syntax_node_ptr( | |
| 11 | ctx, | |
| 12 | DiagnosticCode::RustcHardError("E0784"), | |
| 13 | "union patterns should have exactly one field", | |
| 14 | d.pat.map(Into::into), | |
| 15 | ) | |
| 16 | .stable() | |
| 17 | } | |
| 18 | ||
| 19 | #[cfg(test)] | |
| 20 | mod tests { | |
| 21 | use crate::tests::check_diagnostics; | |
| 22 | ||
| 23 | #[test] | |
| 24 | fn union_pat_must_have_exactly_one_field() { | |
| 25 | check_diagnostics( | |
| 26 | r#" | |
| 27 | union Bird { | |
| 28 | pigeon: u8, | |
| 29 | turtledove: u16, | |
| 30 | } | |
| 31 | ||
| 32 | fn main(bird: Bird) { | |
| 33 | unsafe { | |
| 34 | let Bird {} = bird; | |
| 35 | //^^^^^^^ error: union patterns should have exactly one field | |
| 36 | let Bird { pigeon: 0, turtledove: 1 } = bird; | |
| 37 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: union patterns should have exactly one field | |
| 38 | } | |
| 39 | } | |
| 40 | "#, | |
| 41 | ); | |
| 42 | } | |
| 43 | } |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/yield_outside_coroutine.rs created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; | |
| 2 | ||
| 3 | // Diagnostic: yield-outside-of-coroutine | |
| 4 | // | |
| 5 | // This diagnostic is triggered if the `yield` keyword is used outside of a coroutine. | |
| 6 | pub(crate) fn yield_outside_coroutine( | |
| 7 | ctx: &DiagnosticsContext<'_, '_>, | |
| 8 | d: &hir::YieldOutsideCoroutine, | |
| 9 | ) -> Diagnostic { | |
| 10 | Diagnostic::new_with_syntax_node_ptr( | |
| 11 | ctx, | |
| 12 | DiagnosticCode::RustcHardError("E0627"), | |
| 13 | "yield expression outside of coroutine", | |
| 14 | d.expr.map(|it| it.into()), | |
| 15 | ) | |
| 16 | } | |
| 17 | ||
| 18 | #[cfg(test)] | |
| 19 | mod tests { | |
| 20 | use crate::tests::check_diagnostics; | |
| 21 | ||
| 22 | #[test] | |
| 23 | fn yield_in_regular_function() { | |
| 24 | check_diagnostics( | |
| 25 | r#" | |
| 26 | //- minicore: coroutine | |
| 27 | fn foo() { | |
| 28 | yield 1; | |
| 29 | //^^^^^^^ error: yield expression outside of coroutine | |
| 30 | } | |
| 31 | "#, | |
| 32 | ); | |
| 33 | } | |
| 34 | } |
src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs+12| ... | ... | @@ -65,6 +65,7 @@ mod handlers { |
| 65 | 65 | pub(crate) mod missing_match_arms; |
| 66 | 66 | pub(crate) mod missing_unsafe; |
| 67 | 67 | pub(crate) mod moved_out_of_ref; |
| 68 | pub(crate) mod mut_ref_in_imm_ref_pat; | |
| 68 | 69 | pub(crate) mod mutability_errors; |
| 69 | 70 | pub(crate) mod mutable_ref; |
| 70 | 71 | pub(crate) mod no_such_field; |
| ... | ... | @@ -89,6 +90,8 @@ mod handlers { |
| 89 | 90 | pub(crate) mod unimplemented_builtin_macro; |
| 90 | 91 | pub(crate) mod unimplemented_trait; |
| 91 | 92 | pub(crate) mod union_expr_must_have_exactly_one_field; |
| 93 | pub(crate) mod union_pat_has_rest; | |
| 94 | pub(crate) mod union_pat_must_have_exactly_one_field; | |
| 92 | 95 | pub(crate) mod unreachable_label; |
| 93 | 96 | pub(crate) mod unresolved_assoc_item; |
| 94 | 97 | pub(crate) mod unresolved_extern_crate; |
| ... | ... | @@ -100,6 +103,7 @@ mod handlers { |
| 100 | 103 | pub(crate) mod unresolved_module; |
| 101 | 104 | pub(crate) mod unused_must_use; |
| 102 | 105 | pub(crate) mod unused_variables; |
| 106 | pub(crate) mod yield_outside_coroutine; | |
| 103 | 107 | |
| 104 | 108 | // The handlers below are unusual, the implement the diagnostics as well. |
| 105 | 109 | pub(crate) mod field_shorthand; |
| ... | ... | @@ -479,6 +483,7 @@ pub fn semantic_diagnostics( |
| 479 | 483 | AnyDiagnostic::MissingMatchArms(d) => handlers::missing_match_arms::missing_match_arms(&ctx, &d), |
| 480 | 484 | AnyDiagnostic::MissingUnsafe(d) => handlers::missing_unsafe::missing_unsafe(&ctx, &d), |
| 481 | 485 | AnyDiagnostic::MovedOutOfRef(d) => handlers::moved_out_of_ref::moved_out_of_ref(&ctx, &d), |
| 486 | AnyDiagnostic::MutRefInImmRefPat(d) => handlers::mut_ref_in_imm_ref_pat::mut_ref_in_imm_ref_pat(&ctx, &d), | |
| 482 | 487 | AnyDiagnostic::MutableRefBinding(d) => handlers::mutable_ref::mutable_ref_binding(&ctx, &d), |
| 483 | 488 | AnyDiagnostic::NeedMut(d) => match handlers::mutability_errors::need_mut(&ctx, &d) { |
| 484 | 489 | Some(it) => it, |
| ... | ... | @@ -548,9 +553,16 @@ pub fn semantic_diagnostics( |
| 548 | 553 | AnyDiagnostic::TypeMustBeKnown(d) => handlers::type_must_be_known::type_must_be_known(&ctx, &d), |
| 549 | 554 | AnyDiagnostic::PatternArgInExternFn(d) => handlers::pattern_arg_in_extern_fn::pattern_arg_in_extern_fn(&ctx, &d), |
| 550 | 555 | AnyDiagnostic::UnionExprMustHaveExactlyOneField(d) => handlers::union_expr_must_have_exactly_one_field::union_expr_must_have_exactly_one_field(&ctx, &d), |
| 556 | AnyDiagnostic::UnionPatMustHaveExactlyOneField(d) => { | |
| 557 | handlers::union_pat_must_have_exactly_one_field::union_pat_must_have_exactly_one_field(&ctx, &d) | |
| 558 | } | |
| 559 | AnyDiagnostic::UnionPatHasRest(d) => { | |
| 560 | handlers::union_pat_has_rest::union_pat_has_rest(&ctx, &d) | |
| 561 | } | |
| 551 | 562 | AnyDiagnostic::UnimplementedTrait(d) => handlers::unimplemented_trait::unimplemented_trait(&ctx, &d), |
| 552 | 563 | AnyDiagnostic::FruInDestructuringAssignment(d) => handlers::fru_in_destructuring_assignment::fru_in_destructuring_assignment(&ctx, &d), |
| 553 | 564 | AnyDiagnostic::ExplicitDropMethodUse(d) => handlers::explicit_drop_method_use::explicit_drop_method_use(&ctx, &d), |
| 565 | AnyDiagnostic::YieldOutsideCoroutine(d) => handlers::yield_outside_coroutine::yield_outside_coroutine(&ctx, &d), | |
| 554 | 566 | }; |
| 555 | 567 | res.push(d) |
| 556 | 568 | } |
src/tools/rust-analyzer/crates/ide-ssr/src/fragments.rs+14-11| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | //! needs to determine it somehow. We do this in a stupid way -- by pasting SSR |
| 7 | 7 | //! rule into different contexts and checking what works. |
| 8 | 8 | |
| 9 | use syntax::{AstNode, SyntaxNode, ast}; | |
| 9 | use syntax::{AstNode, SyntaxNode, ast, syntax_editor::SyntaxEditor}; | |
| 10 | 10 | |
| 11 | 11 | pub(crate) fn ty(s: &str) -> Result<SyntaxNode, ()> { |
| 12 | 12 | fragment::<ast::Type>("type T = {};", s) |
| ... | ... | @@ -31,18 +31,20 @@ pub(crate) fn stmt(s: &str) -> Result<SyntaxNode, ()> { |
| 31 | 31 | if !parse.errors().is_empty() { |
| 32 | 32 | return Err(()); |
| 33 | 33 | } |
| 34 | let mut node = | |
| 35 | parse.tree().syntax().descendants().skip(2).find_map(ast::Stmt::cast).ok_or(())?; | |
| 36 | if !s.ends_with(';') && node.to_string().ends_with(';') { | |
| 37 | node = node.clone_for_update(); | |
| 38 | if let Some(it) = node.syntax().last_token() { | |
| 39 | it.detach() | |
| 40 | } | |
| 34 | let node = parse.tree().syntax().descendants().skip(2).find_map(ast::Stmt::cast).ok_or(())?; | |
| 35 | let (editor, node) = SyntaxEditor::new(node.syntax().clone()); | |
| 36 | let node = ast::Stmt::cast(node).ok_or(())?; | |
| 37 | if !s.ends_with(';') | |
| 38 | && node.to_string().ends_with(';') | |
| 39 | && let Some(token) = node.syntax().last_token() | |
| 40 | { | |
| 41 | editor.delete(token); | |
| 41 | 42 | } |
| 43 | let node = editor.finish().new_root().clone(); | |
| 42 | 44 | if node.to_string() != s { |
| 43 | 45 | return Err(()); |
| 44 | 46 | } |
| 45 | Ok(node.syntax().clone_subtree()) | |
| 47 | Ok(node) | |
| 46 | 48 | } |
| 47 | 49 | |
| 48 | 50 | fn fragment<T: AstNode>(template: &str, s: &str) -> Result<SyntaxNode, ()> { |
| ... | ... | @@ -53,8 +55,9 @@ fn fragment<T: AstNode>(template: &str, s: &str) -> Result<SyntaxNode, ()> { |
| 53 | 55 | return Err(()); |
| 54 | 56 | } |
| 55 | 57 | let node = parse.tree().syntax().descendants().find_map(T::cast).ok_or(())?; |
| 56 | if node.syntax().text() != s { | |
| 58 | let (_, node) = SyntaxEditor::new(node.syntax().clone()); | |
| 59 | if node.text() != s { | |
| 57 | 60 | return Err(()); |
| 58 | 61 | } |
| 59 | Ok(node.syntax().clone_subtree()) | |
| 62 | Ok(node) | |
| 60 | 63 | } |
src/tools/rust-analyzer/crates/ide/src/goto_definition.rs+30| ... | ... | @@ -40,6 +40,21 @@ pub struct GotoDefinitionConfig<'a> { |
| 40 | 40 | // | VS Code | <kbd>F12</kbd> | |
| 41 | 41 | // |
| 42 | 42 | //  |
| 43 | // | |
| 44 | // #### Special Go to Definitions | |
| 45 | // | |
| 46 | // You can go to definition on operators and keywords as well. The behavior goes as follows: | |
| 47 | // | |
| 48 | // - On overloadable operators, this will take you to the `impl` of the operator's trait for this type, or to the trait if | |
| 49 | // the impl cannot be determined. | |
| 50 | // - For `?` on `Result` that goes through a non-trivial `From` (i.e. not the blanket `impl<T> From<T> for T`), it'll take | |
| 51 | // you to the `From` impl. | |
| 52 | // - On control flow keywords (loops, conditions, etc.) and `fn`, it'll take you to all exit points for this construct | |
| 53 | // or its entrance, the opposite of the keyword you're at (e.g. on `fn` it'll take you to all exit points, and on `return` | |
| 54 | // it'll take you to the `fn`). | |
| 55 | // - It'll skip known blanket impls from the standard library where possible. For example, on a `try_into()` that comes | |
| 56 | // from the blanket `impl<T: TryFrom<U>, U> TryInto<T> for U`, it'll take you to the `TryFrom` impl, and if it also | |
| 57 | // comes from the blanket `impl<T: From<U>, U> TryFrom<U> for T`, it'll take you to the `From` impl. | |
| 43 | 58 | pub(crate) fn goto_definition( |
| 44 | 59 | db: &RootDatabase, |
| 45 | 60 | FilePosition { file_id, offset }: FilePosition, |
| ... | ... | @@ -984,6 +999,21 @@ impl Trait for T { |
| 984 | 999 | }"#, |
| 985 | 1000 | ); |
| 986 | 1001 | } |
| 1002 | ||
| 1003 | #[test] | |
| 1004 | fn goto_def_array_length_prefers_value_namespace() { | |
| 1005 | check( | |
| 1006 | r#" | |
| 1007 | struct N; | |
| 1008 | ||
| 1009 | trait Trait {} | |
| 1010 | ||
| 1011 | impl<const N: usize> Trait for [N; N$0] {} | |
| 1012 | //^ | |
| 1013 | "#, | |
| 1014 | ); | |
| 1015 | } | |
| 1016 | ||
| 987 | 1017 | #[test] |
| 988 | 1018 | fn goto_def_in_mac_call_in_attr_invoc() { |
| 989 | 1019 | check( |
src/tools/rust-analyzer/crates/ide/src/highlight_related.rs+22| ... | ... | @@ -2545,6 +2545,28 @@ fn main() { |
| 2545 | 2545 | }; |
| 2546 | 2546 | unsafe { *(1 as *const u8) }; |
| 2547 | 2547 | unsafe { *(2 as *const u8) }; |
| 2548 | } | |
| 2549 | "#, | |
| 2550 | ); | |
| 2551 | } | |
| 2552 | ||
| 2553 | #[test] | |
| 2554 | fn async_fn_param() { | |
| 2555 | check( | |
| 2556 | r#" | |
| 2557 | async fn get_double_async(num$0: u32) -> u32 { | |
| 2558 | // ^^^ | |
| 2559 | num | |
| 2560 | // ^^^ read | |
| 2561 | } | |
| 2562 | "#, | |
| 2563 | ); | |
| 2564 | check( | |
| 2565 | r#" | |
| 2566 | async fn get_double_async((num$0,): (u32,)) -> u32 { | |
| 2567 | // ^^^ | |
| 2568 | num | |
| 2569 | // ^^^ read | |
| 2548 | 2570 | } |
| 2549 | 2571 | "#, |
| 2550 | 2572 | ); |
src/tools/rust-analyzer/crates/ide/src/hover/tests.rs+21| ... | ... | @@ -9421,6 +9421,27 @@ fn main(a$0: impl T) {} |
| 9421 | 9421 | ); |
| 9422 | 9422 | } |
| 9423 | 9423 | |
| 9424 | #[test] | |
| 9425 | fn hover_impl_trait_arg_with_anon_const_arg_does_not_recurse() { | |
| 9426 | check( | |
| 9427 | r#" | |
| 9428 | trait Tr<const N: usize> {} | |
| 9429 | pub fn f(x$0: impl Tr<{ 0 }>) {} | |
| 9430 | "#, | |
| 9431 | expect![[r#" | |
| 9432 | *x* | |
| 9433 | ||
| 9434 | ```rust | |
| 9435 | x: impl Tr<{const}> + ?Sized | |
| 9436 | ``` | |
| 9437 | ||
| 9438 | --- | |
| 9439 | ||
| 9440 | type param may need Drop | |
| 9441 | "#]], | |
| 9442 | ); | |
| 9443 | } | |
| 9444 | ||
| 9424 | 9445 | #[test] |
| 9425 | 9446 | fn hover_struct_default_arg_self() { |
| 9426 | 9447 | check( |
src/tools/rust-analyzer/crates/ide/src/move_item.rs+2-2| ... | ... | @@ -119,12 +119,12 @@ fn swap_sibling_in_list<A: AstNode + Clone, I: Iterator<Item = A>>( |
| 119 | 119 | range: TextRange, |
| 120 | 120 | direction: Direction, |
| 121 | 121 | ) -> Option<TextEdit> { |
| 122 | let list_lookup = list.tuple_windows().find(|(l, r)| match direction { | |
| 122 | let list_lookup = list.array_windows().find(|[l, r]| match direction { | |
| 123 | 123 | Direction::Up => r.syntax().text_range().contains_range(range), |
| 124 | 124 | Direction::Down => l.syntax().text_range().contains_range(range), |
| 125 | 125 | }); |
| 126 | 126 | |
| 127 | if let Some((l, r)) = list_lookup { | |
| 127 | if let Some([l, r]) = list_lookup { | |
| 128 | 128 | Some(replace_nodes(range, l.syntax(), r.syntax())) |
| 129 | 129 | } else { |
| 130 | 130 | // Cursor is beyond any movable list item (for example, on curly brace in enum). |
src/tools/rust-analyzer/crates/ide/src/references.rs+1-1| ... | ... | @@ -79,8 +79,8 @@ pub struct Declaration { |
| 79 | 79 | // |
| 80 | 80 | // Special handling for constructors: |
| 81 | 81 | // - When the cursor is on `{`, `(`, or `;` in a struct/enum definition |
| 82 | // - When the cursor is on the type name in a struct/enum definition | |
| 83 | 82 | // These cases will show only constructor/initialization usages of the type |
| 83 | // (for example, `S { .. }`, `S(..)`, or `S`) instead of every type reference. | |
| 84 | 84 | // |
| 85 | 85 | // | Editor | Shortcut | |
| 86 | 86 | // |---------|----------| |
src/tools/rust-analyzer/crates/ide/src/rename.rs+12-1| ... | ... | @@ -121,6 +121,17 @@ pub(crate) fn prepare_rename( |
| 121 | 121 | // | VS Code | <kbd>F2</kbd> | |
| 122 | 122 | // |
| 123 | 123 | //  |
| 124 | // | |
| 125 | // #### Magic Renames | |
| 126 | // | |
| 127 | // rust-analyzer supports some special renames that do additional magic: | |
| 128 | // | |
| 129 | // - **Anonymous lifetime renames**. You can rename `'_` to any lifetime name (the new name must start with `'`), | |
| 130 | // and rust-analyzer will automatically add the new lifetime to the list of generic parameters. | |
| 131 | // - **`self` renames**. You can rename parameters to/from `self`. Renaming `self` into another name will update | |
| 132 | // all callers using method syntax to call the function like an associated function. Renaming to `self` is only | |
| 133 | // supported for the first parameter inside an `impl` and when the `Self` type matches the type of the parameter, | |
| 134 | // and will update callers to use method call syntax. | |
| 124 | 135 | pub(crate) fn rename( |
| 125 | 136 | db: &RootDatabase, |
| 126 | 137 | position: FilePosition, |
| ... | ... | @@ -813,7 +824,7 @@ fn rename_elided_lifetime( |
| 813 | 824 | new_name: &str, |
| 814 | 825 | ) -> RenameResult<SourceChange> { |
| 815 | 826 | let parent = lifetime_token.parent().unwrap(); |
| 816 | let root = parent.ancestors().last().unwrap(); | |
| 827 | let root = parent.tree_top(); | |
| 817 | 828 | |
| 818 | 829 | let mut builder = SourceChangeBuilder::new(position.file_id); |
| 819 | 830 |
src/tools/rust-analyzer/crates/ide/src/static_index.rs+81-54| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | //! read-only code browsers and emitting LSIF |
| 3 | 3 | |
| 4 | 4 | use arrayvec::ArrayVec; |
| 5 | use either::Either; | |
| 5 | 6 | use hir::{Crate, Module, Semantics, db::HirDatabase}; |
| 6 | 7 | use ide_db::{ |
| 7 | 8 | FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, |
| ... | ... | @@ -11,13 +12,12 @@ use ide_db::{ |
| 11 | 12 | famous_defs::FamousDefs, |
| 12 | 13 | ra_fixture::RaFixtureConfig, |
| 13 | 14 | }; |
| 14 | use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange}; | |
| 15 | use syntax::{AstNode, AstToken, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, ast}; | |
| 15 | 16 | |
| 16 | 17 | use crate::navigation_target::UpmappingResult; |
| 17 | 18 | use crate::{ |
| 18 | Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav, | |
| 19 | Analysis, Fold, HoverConfig, HoverResult, TryToNav, | |
| 19 | 20 | hover::{SubstTyLen, hover_for_definition}, |
| 20 | inlay_hints::{AdjustmentHintsMode, InlayFieldsToResolve, TypeHintsPlacement}, | |
| 21 | 21 | moniker::{MonikerResult, SymbolInformationKind, def_to_kind, def_to_moniker}, |
| 22 | 22 | parent_module::crates_for, |
| 23 | 23 | }; |
| ... | ... | @@ -53,6 +53,22 @@ pub struct TokenStaticData { |
| 53 | 53 | /// |
| 54 | 54 | /// For example, in `fn foo() {}` this is the position from `fn` |
| 55 | 55 | /// to the closing brace. |
| 56 | /// | |
| 57 | /// This excludes trivia (whitespace/comments) other than doc | |
| 58 | /// comments. This differs from LSP, which includes trivia. | |
| 59 | /// | |
| 60 | /// SCIP: | |
| 61 | /// | |
| 62 | /// > source range of the nearest non-trivial enclosing AST node. | |
| 63 | /// | |
| 64 | /// <https://github.com/scip-code/scip/blob/20459645420419b3c2a10d6a9f57436abeeb273b/scip.proto#L747-L796> | |
| 65 | /// | |
| 66 | /// LSP: | |
| 67 | /// | |
| 68 | /// > range enclosing this symbol not including leading/trailing | |
| 69 | /// > whitespace but everything else like comments. | |
| 70 | /// | |
| 71 | /// <https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#locationLink> | |
| 56 | 72 | pub definition_body: Option<FileRange>, |
| 57 | 73 | pub references: Vec<ReferenceData>, |
| 58 | 74 | pub moniker: Option<MonikerResult>, |
| ... | ... | @@ -97,7 +113,6 @@ impl TokenStore { |
| 97 | 113 | pub struct StaticIndexedFile { |
| 98 | 114 | pub file_id: FileId, |
| 99 | 115 | pub folds: Vec<Fold>, |
| 100 | pub inlay_hints: Vec<InlayHint>, | |
| 101 | 116 | pub tokens: Vec<(TextRange, TokenId)>, |
| 102 | 117 | } |
| 103 | 118 | |
| ... | ... | @@ -153,49 +168,6 @@ impl StaticIndex<'_> { |
| 153 | 168 | fn add_file(&mut self, file_id: FileId) { |
| 154 | 169 | let current_crate = crates_for(self.db, file_id).pop().map(Into::into); |
| 155 | 170 | let folds = self.analysis.folding_ranges(file_id, true).unwrap(); |
| 156 | let inlay_hints = self | |
| 157 | .analysis | |
| 158 | .inlay_hints( | |
| 159 | &InlayHintsConfig { | |
| 160 | render_colons: true, | |
| 161 | discriminant_hints: crate::DiscriminantHints::Fieldless, | |
| 162 | type_hints: true, | |
| 163 | type_hints_placement: TypeHintsPlacement::Inline, | |
| 164 | sized_bound: false, | |
| 165 | parameter_hints: true, | |
| 166 | parameter_hints_for_missing_arguments: false, | |
| 167 | generic_parameter_hints: crate::GenericParameterHints { | |
| 168 | type_hints: false, | |
| 169 | lifetime_hints: false, | |
| 170 | const_hints: true, | |
| 171 | }, | |
| 172 | chaining_hints: true, | |
| 173 | closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock, | |
| 174 | lifetime_elision_hints: crate::LifetimeElisionHints::Never, | |
| 175 | adjustment_hints: crate::AdjustmentHints::Never, | |
| 176 | adjustment_hints_disable_reborrows: true, | |
| 177 | adjustment_hints_mode: AdjustmentHintsMode::Prefix, | |
| 178 | adjustment_hints_hide_outside_unsafe: false, | |
| 179 | implicit_drop_hints: false, | |
| 180 | implied_dyn_trait_hints: false, | |
| 181 | hide_inferred_type_hints: false, | |
| 182 | hide_named_constructor_hints: false, | |
| 183 | hide_closure_initialization_hints: false, | |
| 184 | hide_closure_parameter_hints: false, | |
| 185 | closure_style: hir::ClosureStyle::ImplFn, | |
| 186 | param_names_for_lifetime_elision_hints: false, | |
| 187 | binding_mode_hints: false, | |
| 188 | max_length: Some(25), | |
| 189 | closure_capture_hints: false, | |
| 190 | closing_brace_hints_min_lines: Some(25), | |
| 191 | fields_to_resolve: InlayFieldsToResolve::empty(), | |
| 192 | range_exclusive_hints: false, | |
| 193 | ra_fixture: RaFixtureConfig::default(), | |
| 194 | }, | |
| 195 | file_id, | |
| 196 | None, | |
| 197 | ) | |
| 198 | .unwrap(); | |
| 199 | 171 | // hovers |
| 200 | 172 | let sema = hir::Semantics::new(self.db); |
| 201 | 173 | let root = sema.parse_guess_edition(file_id).syntax().clone(); |
| ... | ... | @@ -221,12 +193,13 @@ impl StaticIndex<'_> { |
| 221 | 193 | show_drop_glue: true, |
| 222 | 194 | ra_fixture: RaFixtureConfig::default(), |
| 223 | 195 | }; |
| 224 | let mut result = StaticIndexedFile { file_id, inlay_hints, folds, tokens: vec![] }; | |
| 196 | let mut result = StaticIndexedFile { file_id, folds, tokens: vec![] }; | |
| 225 | 197 | |
| 226 | 198 | let mut add_token = |def: Definition, range: TextRange, scope_node: &SyntaxNode| { |
| 227 | 199 | let id = if let Some(it) = self.def_map.get(&def) { |
| 228 | 200 | *it |
| 229 | 201 | } else { |
| 202 | let nav = def.try_to_nav(&sema).map(UpmappingResult::call_site); | |
| 230 | 203 | let it = self.tokens.insert(TokenStaticData { |
| 231 | 204 | documentation: documentation_for_definition(&sema, def, scope_node), |
| 232 | 205 | hover: Some(hover_for_definition( |
| ... | ... | @@ -241,13 +214,14 @@ impl StaticIndex<'_> { |
| 241 | 214 | edition, |
| 242 | 215 | display_target, |
| 243 | 216 | )), |
| 244 | definition: def.try_to_nav(&sema).map(UpmappingResult::call_site).map(|it| { | |
| 245 | FileRange { file_id: it.file_id, range: it.focus_or_full_range() } | |
| 217 | definition: nav.as_ref().map(|it| FileRange { | |
| 218 | file_id: it.file_id, | |
| 219 | range: it.focus_or_full_range(), | |
| 220 | }), | |
| 221 | definition_body: nav.as_ref().map(|it| FileRange { | |
| 222 | file_id: it.file_id, | |
| 223 | range: definition_range_excluding_trivia(&sema, it.file_id, it.full_range), | |
| 246 | 224 | }), |
| 247 | definition_body: def | |
| 248 | .try_to_nav(&sema) | |
| 249 | .map(UpmappingResult::call_site) | |
| 250 | .map(|it| FileRange { file_id: it.file_id, range: it.full_range }), | |
| 251 | 225 | references: vec![], |
| 252 | 226 | moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)), |
| 253 | 227 | display_name: def |
| ... | ... | @@ -333,6 +307,59 @@ impl StaticIndex<'_> { |
| 333 | 307 | } |
| 334 | 308 | } |
| 335 | 309 | |
| 310 | fn definition_range_excluding_trivia( | |
| 311 | sema: &Semantics<'_, RootDatabase>, | |
| 312 | file_id: FileId, | |
| 313 | range: TextRange, | |
| 314 | ) -> TextRange { | |
| 315 | let root = sema.parse_guess_edition(file_id).syntax().clone(); | |
| 316 | if range == root.text_range() { | |
| 317 | return range; | |
| 318 | } | |
| 319 | if !root.text_range().contains_range(range) { | |
| 320 | return range; | |
| 321 | } | |
| 322 | ||
| 323 | let element = root.covering_element(range); | |
| 324 | let tokens = match element { | |
| 325 | NodeOrToken::Node(node) => Either::Left(node.descendants_with_tokens().filter_map(|it| { | |
| 326 | let token = it.into_token()?; | |
| 327 | range.contains_range(token.text_range()).then_some(token) | |
| 328 | })), | |
| 329 | NodeOrToken::Token(token) => Either::Right(std::iter::once(token)), | |
| 330 | }; | |
| 331 | ||
| 332 | let mut first = None; | |
| 333 | let mut last = None; | |
| 334 | for token in tokens { | |
| 335 | if first.is_none() && !is_leading_trivia_excluding_docs(&token) { | |
| 336 | first = Some(token.clone()); | |
| 337 | } | |
| 338 | if !is_trailing_trivia(&token) { | |
| 339 | last = Some(token); | |
| 340 | } | |
| 341 | } | |
| 342 | ||
| 343 | match (first, last) { | |
| 344 | (Some(first), Some(last)) => { | |
| 345 | TextRange::new(first.text_range().start(), last.text_range().end()) | |
| 346 | } | |
| 347 | _ => range, | |
| 348 | } | |
| 349 | } | |
| 350 | ||
| 351 | fn is_leading_trivia_excluding_docs(token: &SyntaxToken) -> bool { | |
| 352 | match token.kind() { | |
| 353 | SyntaxKind::WHITESPACE => true, | |
| 354 | SyntaxKind::COMMENT => ast::Comment::cast(token.clone()).is_none_or(|it| !it.is_outer()), | |
| 355 | _ => false, | |
| 356 | } | |
| 357 | } | |
| 358 | ||
| 359 | fn is_trailing_trivia(token: &SyntaxToken) -> bool { | |
| 360 | matches!(token.kind(), SyntaxKind::WHITESPACE | SyntaxKind::COMMENT) | |
| 361 | } | |
| 362 | ||
| 336 | 363 | #[cfg(test)] |
| 337 | 364 | mod tests { |
| 338 | 365 | use crate::{StaticIndex, fixture}; |
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/async_fn_non_mut_param.html created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | ||
| 2 | <style> | |
| 3 | body { margin: 0; } | |
| 4 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } | |
| 5 | ||
| 6 | .lifetime { color: #DFAF8F; font-style: italic; } | |
| 7 | .label { color: #DFAF8F; font-style: italic; } | |
| 8 | .comment { color: #7F9F7F; } | |
| 9 | .documentation { color: #629755; } | |
| 10 | .intra_doc_link { font-style: italic; } | |
| 11 | .injected { opacity: 0.65 ; } | |
| 12 | .struct, .enum { color: #7CB8BB; } | |
| 13 | .enum_variant { color: #BDE0F3; } | |
| 14 | .string_literal { color: #CC9393; } | |
| 15 | .field { color: #94BFF3; } | |
| 16 | .function { color: #93E0E3; } | |
| 17 | .parameter { color: #94BFF3; } | |
| 18 | .text { color: #DCDCCC; } | |
| 19 | .type { color: #7CB8BB; } | |
| 20 | .builtin_type { color: #8CD0D3; } | |
| 21 | .type_param { color: #DFAF8F; } | |
| 22 | .attribute { color: #94BFF3; } | |
| 23 | .numeric_literal { color: #BFEBBF; } | |
| 24 | .bool_literal { color: #BFE6EB; } | |
| 25 | .macro { color: #94BFF3; } | |
| 26 | .proc_macro { color: #94BFF3; text-decoration: underline; } | |
| 27 | .derive { color: #94BFF3; font-style: italic; } | |
| 28 | .module { color: #AFD8AF; } | |
| 29 | .value_param { color: #DCDCCC; } | |
| 30 | .variable { color: #DCDCCC; } | |
| 31 | .format_specifier { color: #CC696B; } | |
| 32 | .mutable { text-decoration: underline; } | |
| 33 | .escape_sequence { color: #94BFF3; } | |
| 34 | .keyword { color: #F0DFAF; font-weight: bold; } | |
| 35 | .control { font-style: italic; } | |
| 36 | .reference { font-style: italic; font-weight: bold; } | |
| 37 | .const { font-weight: bolder; } | |
| 38 | .unsafe { color: #BC8383; } | |
| 39 | .deprecated { text-decoration: line-through; } | |
| 40 | ||
| 41 | .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } | |
| 42 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | |
| 43 | </style> | |
| 44 | <pre><code><span class="keyword async">async</span> <span class="keyword">fn</span> <span class="function async declaration">get_double_async</span><span class="parenthesis">(</span><span class="value_param declaration">num</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span> | |
| 45 | <span class="value_param">num</span> | |
| 46 | <span class="brace">}</span></code></pre> | |
| \ No newline at end of file |
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs+13| ... | ... | @@ -1584,3 +1584,16 @@ static STATIC: () = (); |
| 1584 | 1584 | false, |
| 1585 | 1585 | ); |
| 1586 | 1586 | } |
| 1587 | ||
| 1588 | #[test] | |
| 1589 | fn async_fn_non_mut_param() { | |
| 1590 | check_highlighting( | |
| 1591 | r#" | |
| 1592 | async fn get_double_async(num: u32) -> u32 { | |
| 1593 | num | |
| 1594 | } | |
| 1595 | "#, | |
| 1596 | expect_file!["./test_data/async_fn_non_mut_param.html"], | |
| 1597 | false, | |
| 1598 | ); | |
| 1599 | } |
src/tools/rust-analyzer/crates/load-cargo/src/lib.rs+1-1| ... | ... | @@ -171,7 +171,7 @@ pub fn load_workspace_into_db( |
| 171 | 171 | .map(|(crate_id, path)| { |
| 172 | 172 | ( |
| 173 | 173 | crate_id, |
| 174 | path.map_or_else(Err, |(_, path)| { | |
| 174 | path.and_then(|(_, path)| { | |
| 175 | 175 | proc_macro_server.as_ref().map_err(Clone::clone).and_then( |
| 176 | 176 | |proc_macro_server| load_proc_macro(proc_macro_server, &path, &[]), |
| 177 | 177 | ) |
src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs+4| ... | ... | @@ -355,6 +355,10 @@ pub(crate) fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedM |
| 355 | 355 | } |
| 356 | 356 | |
| 357 | 357 | let op_n = p.start(); |
| 358 | // test asm_piece_attr | |
| 359 | // builtin # global_asm("", #[cfg(false)] options()) | |
| 360 | attributes::outer_attrs(p); | |
| 361 | ||
| 358 | 362 | // Parse clobber_abi |
| 359 | 363 | if p.eat_contextual_kw(T![clobber_abi]) { |
| 360 | 364 | parse_clobber_abi(p); |
src/tools/rust-analyzer/crates/parser/src/input.rs+1-1| ... | ... | @@ -27,7 +27,7 @@ impl Input { |
| 27 | 27 | pub fn with_capacity(capacity: usize) -> Self { |
| 28 | 28 | Self { |
| 29 | 29 | kind: Vec::with_capacity(capacity), |
| 30 | joint: Vec::with_capacity(capacity / size_of::<bits>()), | |
| 30 | joint: Vec::with_capacity(capacity.div_ceil(bits::BITS as usize)), | |
| 31 | 31 | contextual_kind: Vec::with_capacity(capacity), |
| 32 | 32 | edition: Vec::with_capacity(capacity), |
| 33 | 33 | } |
src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs+4| ... | ... | @@ -25,6 +25,10 @@ mod ok { |
| 25 | 25 | #[test] |
| 26 | 26 | fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); } |
| 27 | 27 | #[test] |
| 28 | fn asm_piece_attr() { | |
| 29 | run_and_expect_no_errors("test_data/parser/inline/ok/asm_piece_attr.rs"); | |
| 30 | } | |
| 31 | #[test] | |
| 28 | 32 | fn asm_sym_paren() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_sym_paren.rs"); } |
| 29 | 33 | #[test] |
| 30 | 34 | fn assoc_const_eq() { |
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rast created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | SOURCE_FILE | |
| 2 | ASM_EXPR | |
| 3 | BUILTIN_KW "builtin" | |
| 4 | WHITESPACE " " | |
| 5 | POUND "#" | |
| 6 | WHITESPACE " " | |
| 7 | GLOBAL_ASM_KW "global_asm" | |
| 8 | L_PAREN "(" | |
| 9 | LITERAL | |
| 10 | STRING "\"\"" | |
| 11 | COMMA "," | |
| 12 | WHITESPACE " " | |
| 13 | ASM_OPTIONS | |
| 14 | ATTR | |
| 15 | POUND "#" | |
| 16 | L_BRACK "[" | |
| 17 | CFG_META | |
| 18 | CFG_KW "cfg" | |
| 19 | L_PAREN "(" | |
| 20 | CFG_ATOM | |
| 21 | FALSE_KW "false" | |
| 22 | R_PAREN ")" | |
| 23 | R_BRACK "]" | |
| 24 | WHITESPACE " " | |
| 25 | OPTIONS_KW "options" | |
| 26 | L_PAREN "(" | |
| 27 | R_PAREN ")" | |
| 28 | R_PAREN ")" | |
| 29 | WHITESPACE "\n" |
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rs created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | builtin # global_asm("", #[cfg(false)] options()) |
src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs+3| ... | ... | @@ -450,6 +450,9 @@ impl WorkspaceBuildScripts { |
| 450 | 450 | |
| 451 | 451 | cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]); |
| 452 | 452 | cmd.args(&config.extra_args); |
| 453 | if let Some(config_path) = &config.config_path { | |
| 454 | cmd.arg("--config").arg(config_path); | |
| 455 | } | |
| 453 | 456 | |
| 454 | 457 | cmd.arg("--manifest-path"); |
| 455 | 458 | cmd.arg(manifest_path); |
src/tools/rust-analyzer/crates/project-model/src/cargo_config_file.rs+4| ... | ... | @@ -17,11 +17,15 @@ impl CargoConfigFile { |
| 17 | 17 | manifest: &ManifestPath, |
| 18 | 18 | extra_env: &FxHashMap<String, Option<String>>, |
| 19 | 19 | sysroot: &Sysroot, |
| 20 | config_path: Option<&AbsPath>, | |
| 20 | 21 | ) -> Option<Self> { |
| 21 | 22 | let mut cargo_config = sysroot.tool(Tool::Cargo, manifest.parent(), extra_env); |
| 22 | 23 | cargo_config |
| 23 | 24 | .args(["-Z", "unstable-options", "config", "get", "--format", "toml", "--show-origin"]) |
| 24 | 25 | .env("RUSTC_BOOTSTRAP", "1"); |
| 26 | if let Some(config_path) = config_path { | |
| 27 | cargo_config.arg("--config").arg(config_path); | |
| 28 | } | |
| 25 | 29 | if manifest.is_rust_manifest() { |
| 26 | 30 | cargo_config.arg("-Zscript"); |
| 27 | 31 | } |
src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs+8| ... | ... | @@ -133,6 +133,8 @@ pub struct CargoConfig { |
| 133 | 133 | pub extra_args: Vec<String>, |
| 134 | 134 | /// Extra args passed only to `cargo metadata`, not other cargo commands. |
| 135 | 135 | pub metadata_extra_args: Vec<String>, |
| 136 | /// Path to an extra config file passed to every cargo invocation via `--config`. | |
| 137 | pub config_path: Option<AbsPathBuf>, | |
| 136 | 138 | /// Extra env vars to set when invoking the cargo command |
| 137 | 139 | pub extra_env: FxHashMap<String, Option<String>>, |
| 138 | 140 | pub invocation_strategy: InvocationStrategy, |
| ... | ... | @@ -324,6 +326,8 @@ pub struct CargoMetadataConfig { |
| 324 | 326 | pub extra_args: Vec<String>, |
| 325 | 327 | /// Extra args passed directly to `cargo metadata` without filtering. |
| 326 | 328 | pub metadata_extra_args: Vec<String>, |
| 329 | /// Path to an extra config file passed to `cargo metadata` via `--config`. | |
| 330 | pub config_path: Option<AbsPathBuf>, | |
| 327 | 331 | /// Extra env vars to set when invoking the cargo command |
| 328 | 332 | pub extra_env: FxHashMap<String, Option<String>>, |
| 329 | 333 | /// What kind of metadata are we fetching: workspace, rustc, or sysroot. |
| ... | ... | @@ -684,6 +688,10 @@ impl FetchMetadata { |
| 684 | 688 | } |
| 685 | 689 | } |
| 686 | 690 | other_options.extend(config.metadata_extra_args.iter().cloned()); |
| 691 | if let Some(config_path) = &config.config_path { | |
| 692 | other_options.push("--config".to_owned()); | |
| 693 | other_options.push(config_path.to_string()); | |
| 694 | } | |
| 687 | 695 | |
| 688 | 696 | let mut lockfile_copy = None; |
| 689 | 697 | if cargo_toml.is_rust_manifest() { |
src/tools/rust-analyzer/crates/project-model/src/workspace.rs+20-3| ... | ... | @@ -217,6 +217,7 @@ impl ProjectWorkspace { |
| 217 | 217 | rustc_source, |
| 218 | 218 | extra_args, |
| 219 | 219 | metadata_extra_args, |
| 220 | config_path, | |
| 220 | 221 | extra_env, |
| 221 | 222 | set_test, |
| 222 | 223 | cfg_overrides, |
| ... | ... | @@ -269,7 +270,8 @@ impl ProjectWorkspace { |
| 269 | 270 | |
| 270 | 271 | tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot"); |
| 271 | 272 | progress("querying project metadata".to_owned()); |
| 272 | let config_file = CargoConfigFile::load(cargo_toml, extra_env, &sysroot); | |
| 273 | let config_file = | |
| 274 | CargoConfigFile::load(cargo_toml, extra_env, &sysroot, config_path.as_deref()); | |
| 273 | 275 | let config_file_ = config_file.clone(); |
| 274 | 276 | let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml, &config_file_); |
| 275 | 277 | let targets = |
| ... | ... | @@ -291,6 +293,7 @@ impl ProjectWorkspace { |
| 291 | 293 | targets: targets.clone(), |
| 292 | 294 | extra_args: extra_args.clone(), |
| 293 | 295 | metadata_extra_args: metadata_extra_args.clone(), |
| 296 | config_path: config_path.clone(), | |
| 294 | 297 | extra_env: extra_env.clone(), |
| 295 | 298 | toolchain_version: toolchain.clone(), |
| 296 | 299 | kind: "workspace", |
| ... | ... | @@ -346,6 +349,7 @@ impl ProjectWorkspace { |
| 346 | 349 | targets: targets.clone(), |
| 347 | 350 | extra_args: extra_args.clone(), |
| 348 | 351 | metadata_extra_args: metadata_extra_args.clone(), |
| 352 | config_path: config_path.clone(), | |
| 349 | 353 | extra_env: extra_env.clone(), |
| 350 | 354 | toolchain_version: toolchain.clone(), |
| 351 | 355 | kind: "rustc-dev" |
| ... | ... | @@ -549,7 +553,12 @@ impl ProjectWorkspace { |
| 549 | 553 | None => Sysroot::empty(), |
| 550 | 554 | }; |
| 551 | 555 | |
| 552 | let config_file = CargoConfigFile::load(detached_file, &config.extra_env, &sysroot); | |
| 556 | let config_file = CargoConfigFile::load( | |
| 557 | detached_file, | |
| 558 | &config.extra_env, | |
| 559 | &sysroot, | |
| 560 | config.config_path.as_deref(), | |
| 561 | ); | |
| 553 | 562 | let query_config = QueryConfig::Cargo(&sysroot, detached_file, &config_file); |
| 554 | 563 | let toolchain = version::get(query_config, &config.extra_env).ok().flatten(); |
| 555 | 564 | let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env) |
| ... | ... | @@ -579,6 +588,7 @@ impl ProjectWorkspace { |
| 579 | 588 | targets, |
| 580 | 589 | extra_args: config.extra_args.clone(), |
| 581 | 590 | metadata_extra_args: config.metadata_extra_args.clone(), |
| 591 | config_path: config.config_path.clone(), | |
| 582 | 592 | extra_env: config.extra_env.clone(), |
| 583 | 593 | toolchain_version: toolchain.clone(), |
| 584 | 594 | kind: "detached-file", |
| ... | ... | @@ -1952,8 +1962,15 @@ fn sysroot_metadata_config( |
| 1952 | 1962 | CargoMetadataConfig { |
| 1953 | 1963 | features: Default::default(), |
| 1954 | 1964 | targets, |
| 1965 | // NOTE: Not passing extra_args / metadata_extra_args / config_path here is very | |
| 1966 | // intentional. The sysroot config has nothing to do with the workspace's config, so it's | |
| 1967 | // very unlikely to do the right thing (e.g. it'd could try to use vendored dependencies in | |
| 1968 | // the project's config for libstd or what not). | |
| 1955 | 1969 | extra_args: Default::default(), |
| 1956 | metadata_extra_args: config.metadata_extra_args.clone(), | |
| 1970 | metadata_extra_args: Default::default(), | |
| 1971 | config_path: Default::default(), | |
| 1972 | // FIXME: Passing extra_env is somewhat dubious here, for the same reason we don't pass | |
| 1973 | // extra_args. | |
| 1957 | 1974 | extra_env: config.extra_env.clone(), |
| 1958 | 1975 | toolchain_version, |
| 1959 | 1976 | kind: "sysroot", |
src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs+4-141| ... | ... | @@ -1,14 +1,10 @@ |
| 1 | 1 | //! A macro that mimics the old Salsa-style `#[query_group]` macro. |
| 2 | 2 | |
| 3 | use core::fmt; | |
| 4 | 3 | use std::vec; |
| 5 | 4 | |
| 6 | 5 | use proc_macro::TokenStream; |
| 7 | 6 | use proc_macro2::Span; |
| 8 | use queries::{ | |
| 9 | GeneratedInputStruct, InputQuery, InputSetter, InputSetterWithDurability, Queries, SetterKind, | |
| 10 | TrackedQuery, Transparent, | |
| 11 | }; | |
| 7 | use queries::{Queries, TrackedQuery, Transparent}; | |
| 12 | 8 | use quote::{ToTokens, format_ident, quote}; |
| 13 | 9 | use syn::parse::{Parse, ParseStream}; |
| 14 | 10 | use syn::punctuated::Punctuated; |
| ... | ... | @@ -26,18 +22,6 @@ pub fn query_group(args: TokenStream, input: TokenStream) -> TokenStream { |
| 26 | 22 | } |
| 27 | 23 | } |
| 28 | 24 | |
| 29 | #[derive(Debug)] | |
| 30 | struct InputStructField { | |
| 31 | name: proc_macro2::TokenStream, | |
| 32 | ty: proc_macro2::TokenStream, | |
| 33 | } | |
| 34 | ||
| 35 | impl fmt::Display for InputStructField { | |
| 36 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| 37 | write!(f, "{}", self.name) | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | 25 | struct SalsaAttr { |
| 42 | 26 | name: String, |
| 43 | 27 | tts: TokenStream, |
| ... | ... | @@ -99,8 +83,6 @@ fn filter_attrs(attrs: Vec<Attribute>) -> (Vec<Attribute>, Vec<SalsaAttr>) { |
| 99 | 83 | |
| 100 | 84 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 101 | 85 | enum QueryKind { |
| 102 | Input, | |
| 103 | Tracked, | |
| 104 | 86 | TrackedWithSalsaStruct, |
| 105 | 87 | Transparent, |
| 106 | 88 | } |
| ... | ... | @@ -182,14 +164,10 @@ pub(crate) fn query_group_impl( |
| 182 | 164 | let input_struct_name = format_ident!("{}Data", trait_name_ident); |
| 183 | 165 | let create_data_ident = format_ident!("create_data_{}", trait_name_ident); |
| 184 | 166 | |
| 185 | let mut input_struct_fields: Vec<InputStructField> = vec![]; | |
| 186 | 167 | let mut trait_methods = vec![]; |
| 187 | let mut setter_trait_methods = vec![]; | |
| 188 | let mut lookup_signatures = vec![]; | |
| 189 | 168 | |
| 190 | 169 | for item in &mut item_trait.items { |
| 191 | 170 | if let syn::TraitItem::Fn(method) = item { |
| 192 | let method_name = &method.sig.ident; | |
| 193 | 171 | let signature = &method.sig; |
| 194 | 172 | |
| 195 | 173 | let (_attrs, salsa_attrs) = filter_attrs(method.attrs.clone()); |
| ... | ... | @@ -197,7 +175,6 @@ pub(crate) fn query_group_impl( |
| 197 | 175 | let mut query_kind = QueryKind::TrackedWithSalsaStruct; |
| 198 | 176 | let mut invoke = None; |
| 199 | 177 | let mut cycle = None; |
| 200 | let mut lru = None; | |
| 201 | 178 | |
| 202 | 179 | let params: Vec<FnArg> = signature.inputs.clone().into_iter().collect(); |
| 203 | 180 | let pat_and_tys = params |
| ... | ... | @@ -215,20 +192,6 @@ pub(crate) fn query_group_impl( |
| 215 | 192 | let c = syn::parse::<Parenthesized<Cycle>>(tts)?; |
| 216 | 193 | cycle = Some(c.0); |
| 217 | 194 | } |
| 218 | "input" => { | |
| 219 | if !pat_and_tys.is_empty() { | |
| 220 | return Err(syn::Error::new( | |
| 221 | span, | |
| 222 | "input methods cannot have a parameter", | |
| 223 | )); | |
| 224 | } | |
| 225 | query_kind = QueryKind::Input; | |
| 226 | } | |
| 227 | "invoke_interned" => { | |
| 228 | let path = syn::parse::<Parenthesized<Path>>(tts)?; | |
| 229 | invoke = Some(path.0.clone()); | |
| 230 | query_kind = QueryKind::Tracked; | |
| 231 | } | |
| 232 | 195 | "invoke" => { |
| 233 | 196 | let path = syn::parse::<Parenthesized<Path>>(tts)?; |
| 234 | 197 | invoke = Some(path.0.clone()); |
| ... | ... | @@ -239,12 +202,6 @@ pub(crate) fn query_group_impl( |
| 239 | 202 | "tracked" if method.default.is_some() => { |
| 240 | 203 | query_kind = QueryKind::TrackedWithSalsaStruct; |
| 241 | 204 | } |
| 242 | "lru" => { | |
| 243 | let lru_count = syn::parse::<Parenthesized<syn::LitInt>>(tts)?; | |
| 244 | let lru_count = lru_count.0.base10_parse::<u32>()?; | |
| 245 | ||
| 246 | lru = Some(lru_count); | |
| 247 | } | |
| 248 | 205 | "transparent" => { |
| 249 | 206 | query_kind = QueryKind::Transparent; |
| 250 | 207 | } |
| ... | ... | @@ -252,76 +209,22 @@ pub(crate) fn query_group_impl( |
| 252 | 209 | } |
| 253 | 210 | } |
| 254 | 211 | |
| 255 | let syn::ReturnType::Type(_, return_ty) = signature.output.clone() else { | |
| 212 | let syn::ReturnType::Type(_, _) = signature.output.clone() else { | |
| 256 | 213 | return Err(syn::Error::new(signature.span(), "Queries must have a return type")); |
| 257 | 214 | }; |
| 258 | 215 | |
| 259 | if let syn::Type::Path(ref ty_path) = *return_ty | |
| 260 | && matches!(query_kind, QueryKind::Input) | |
| 261 | { | |
| 262 | let field = InputStructField { | |
| 263 | name: method_name.to_token_stream(), | |
| 264 | ty: ty_path.path.to_token_stream(), | |
| 265 | }; | |
| 266 | ||
| 267 | input_struct_fields.push(field); | |
| 268 | } | |
| 269 | ||
| 270 | 216 | if let Some(block) = &mut method.default { |
| 271 | 217 | SelfToDbRewriter.visit_block_mut(block); |
| 272 | 218 | } |
| 273 | 219 | |
| 274 | 220 | match (query_kind, invoke) { |
| 275 | // input | |
| 276 | (QueryKind::Input, None) => { | |
| 277 | let query = InputQuery { | |
| 278 | signature: method.sig.clone(), | |
| 279 | create_data_ident: create_data_ident.clone(), | |
| 280 | }; | |
| 281 | let value = Queries::InputQuery(query); | |
| 282 | trait_methods.push(value); | |
| 283 | ||
| 284 | let setter = InputSetter { | |
| 285 | signature: method.sig.clone(), | |
| 286 | return_type: *return_ty.clone(), | |
| 287 | create_data_ident: create_data_ident.clone(), | |
| 288 | }; | |
| 289 | setter_trait_methods.push(SetterKind::Plain(setter)); | |
| 290 | ||
| 291 | let setter = InputSetterWithDurability { | |
| 292 | signature: method.sig.clone(), | |
| 293 | return_type: *return_ty.clone(), | |
| 294 | create_data_ident: create_data_ident.clone(), | |
| 295 | }; | |
| 296 | setter_trait_methods.push(SetterKind::WithDurability(setter)); | |
| 297 | } | |
| 298 | // tracked function. it might have an invoke, or might not. | |
| 299 | (QueryKind::Tracked, invoke) => { | |
| 300 | let method = TrackedQuery { | |
| 301 | trait_name: trait_name_ident.clone(), | |
| 302 | generated_struct: Some(GeneratedInputStruct { | |
| 303 | input_struct_name: input_struct_name.clone(), | |
| 304 | create_data_ident: create_data_ident.clone(), | |
| 305 | }), | |
| 306 | signature: signature.clone(), | |
| 307 | pat_and_tys: pat_and_tys.clone(), | |
| 308 | invoke, | |
| 309 | cycle, | |
| 310 | lru, | |
| 311 | default: method.default.take(), | |
| 312 | }; | |
| 313 | ||
| 314 | trait_methods.push(Queries::TrackedQuery(method)); | |
| 315 | } | |
| 316 | 221 | (QueryKind::TrackedWithSalsaStruct, invoke) => { |
| 317 | 222 | let method = TrackedQuery { |
| 318 | 223 | trait_name: trait_name_ident.clone(), |
| 319 | generated_struct: None, | |
| 320 | 224 | signature: signature.clone(), |
| 321 | 225 | pat_and_tys: pat_and_tys.clone(), |
| 322 | 226 | invoke, |
| 323 | 227 | cycle, |
| 324 | lru, | |
| 325 | 228 | default: method.default.take(), |
| 326 | 229 | }; |
| 327 | 230 | |
| ... | ... | @@ -336,61 +239,23 @@ pub(crate) fn query_group_impl( |
| 336 | 239 | }; |
| 337 | 240 | trait_methods.push(Queries::Transparent(method)); |
| 338 | 241 | } |
| 339 | (QueryKind::Input, Some(path)) => { | |
| 340 | return Err(syn::Error::new( | |
| 341 | path.span(), | |
| 342 | "Inputs cannot be used with an `#[invoke]`".to_string(), | |
| 343 | )); | |
| 344 | } | |
| 345 | 242 | } |
| 346 | 243 | } |
| 347 | 244 | } |
| 348 | 245 | |
| 349 | let fields = input_struct_fields | |
| 350 | .into_iter() | |
| 351 | .map(|input| { | |
| 352 | let name = input.name; | |
| 353 | let ret = input.ty; | |
| 354 | quote! { #name: Option<#ret> } | |
| 355 | }) | |
| 356 | .collect::<Vec<proc_macro2::TokenStream>>(); | |
| 357 | ||
| 358 | 246 | let input_struct = quote! { |
| 359 | 247 | #[salsa_macros::input] |
| 360 | pub(crate) struct #input_struct_name { | |
| 361 | #(#fields),* | |
| 362 | } | |
| 248 | pub(crate) struct #input_struct_name {} | |
| 363 | 249 | }; |
| 364 | 250 | |
| 365 | let field_params = std::iter::repeat_n(quote! { None }, fields.len()) | |
| 366 | .collect::<Vec<proc_macro2::TokenStream>>(); | |
| 367 | ||
| 368 | 251 | let create_data_method = quote! { |
| 369 | 252 | #[allow(non_snake_case)] |
| 370 | 253 | #[salsa_macros::tracked] |
| 371 | 254 | fn #create_data_ident(db: &dyn #trait_name_ident) -> #input_struct_name { |
| 372 | #input_struct_name::new(db, #(#field_params),*) | |
| 255 | #input_struct_name::new(db) | |
| 373 | 256 | } |
| 374 | 257 | }; |
| 375 | 258 | |
| 376 | let mut setter_signatures = vec![]; | |
| 377 | let mut setter_methods = vec![]; | |
| 378 | for trait_item in setter_trait_methods | |
| 379 | .iter() | |
| 380 | .map(|method| method.to_token_stream()) | |
| 381 | .map(|tokens| syn::parse2::<syn::TraitItemFn>(tokens).unwrap()) | |
| 382 | { | |
| 383 | let mut methods_sans_body = trait_item.clone(); | |
| 384 | methods_sans_body.default = None; | |
| 385 | methods_sans_body.semi_token = Some(syn::Token)); | |
| 386 | ||
| 387 | setter_signatures.push(TraitItem::Fn(methods_sans_body)); | |
| 388 | setter_methods.push(TraitItem::Fn(trait_item)); | |
| 389 | } | |
| 390 | ||
| 391 | item_trait.items.append(&mut setter_signatures); | |
| 392 | item_trait.items.append(&mut lookup_signatures); | |
| 393 | ||
| 394 | 259 | let trait_impl = quote! { |
| 395 | 260 | #[salsa_macros::db] |
| 396 | 261 | impl<DB> #trait_name_ident for DB |
| ... | ... | @@ -398,8 +263,6 @@ pub(crate) fn query_group_impl( |
| 398 | 263 | DB: #supertraits, |
| 399 | 264 | { |
| 400 | 265 | #(#trait_methods)* |
| 401 | ||
| 402 | #(#setter_methods)* | |
| 403 | 266 | } |
| 404 | 267 | }; |
| 405 | 268 | RemoveAttrsFromTraitMethods.visit_item_trait_mut(&mut item_trait); |
src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs+10-167| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //! The IR of the `#[query_group]` macro. |
| 2 | 2 | |
| 3 | 3 | use quote::{ToTokens, format_ident, quote, quote_spanned}; |
| 4 | use syn::{FnArg, Ident, PatType, Path, Receiver, ReturnType, parse_quote, spanned::Spanned}; | |
| 4 | use syn::{Ident, PatType, Path, spanned::Spanned}; | |
| 5 | 5 | |
| 6 | 6 | use crate::Cycle; |
| 7 | 7 | |
| ... | ... | @@ -12,13 +12,6 @@ pub(crate) struct TrackedQuery { |
| 12 | 12 | pub(crate) invoke: Option<Path>, |
| 13 | 13 | pub(crate) default: Option<syn::Block>, |
| 14 | 14 | pub(crate) cycle: Option<Cycle>, |
| 15 | pub(crate) lru: Option<u32>, | |
| 16 | pub(crate) generated_struct: Option<GeneratedInputStruct>, | |
| 17 | } | |
| 18 | ||
| 19 | pub(crate) struct GeneratedInputStruct { | |
| 20 | pub(crate) input_struct_name: Ident, | |
| 21 | pub(crate) create_data_ident: Ident, | |
| 22 | 15 | } |
| 23 | 16 | |
| 24 | 17 | impl ToTokens for TrackedQuery { |
| ... | ... | @@ -47,8 +40,7 @@ impl ToTokens for TrackedQuery { |
| 47 | 40 | let options = cycle_fn.into_iter().chain(cycle_initial).chain(cycle_result); |
| 48 | 41 | quote!(#(#options),*) |
| 49 | 42 | }) |
| 50 | .into_iter() | |
| 51 | .chain(self.lru.map(|lru| quote!(lru = #lru))); | |
| 43 | .into_iter(); | |
| 52 | 44 | let annotation = quote!(#[salsa_macros::tracked( #(#options),* )]); |
| 53 | 45 | |
| 54 | 46 | let pat_and_tys = &self.pat_and_tys; |
| ... | ... | @@ -66,170 +58,23 @@ impl ToTokens for TrackedQuery { |
| 66 | 58 | } |
| 67 | 59 | }; |
| 68 | 60 | |
| 69 | let method = match &self.generated_struct { | |
| 70 | Some(generated_struct) => { | |
| 71 | let input_struct_name = &generated_struct.input_struct_name; | |
| 72 | let create_data_ident = &generated_struct.create_data_ident; | |
| 73 | ||
| 74 | quote! { | |
| 75 | #sig { | |
| 76 | #annotation | |
| 77 | fn #shim<'db>( | |
| 78 | db: &'db dyn #trait_name, | |
| 79 | _input: #input_struct_name, | |
| 80 | #(#pat_and_tys),* | |
| 81 | ) #ret | |
| 82 | #invoke_block | |
| 83 | #shim(self, #create_data_ident(self), #(#params),*) | |
| 84 | } | |
| 85 | } | |
| 86 | } | |
| 87 | None => { | |
| 88 | quote! { | |
| 89 | #sig { | |
| 90 | #annotation | |
| 91 | fn #shim<'db>( | |
| 92 | db: &'db dyn #trait_name, | |
| 93 | #(#pat_and_tys),* | |
| 94 | ) #ret | |
| 95 | #invoke_block | |
| 96 | ||
| 97 | #shim(self, #(#params),*) | |
| 98 | } | |
| 99 | } | |
| 100 | } | |
| 101 | }; | |
| 102 | ||
| 103 | method.to_tokens(tokens); | |
| 104 | } | |
| 105 | } | |
| 106 | ||
| 107 | pub(crate) struct InputQuery { | |
| 108 | pub(crate) signature: syn::Signature, | |
| 109 | pub(crate) create_data_ident: Ident, | |
| 110 | } | |
| 111 | ||
| 112 | impl ToTokens for InputQuery { | |
| 113 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { | |
| 114 | let sig = &self.signature; | |
| 115 | let fn_ident = &sig.ident; | |
| 116 | let create_data_ident = &self.create_data_ident; | |
| 117 | ||
| 118 | let method = quote! { | |
| 119 | #sig { | |
| 120 | let data = #create_data_ident(self); | |
| 121 | data.#fn_ident(self).unwrap() | |
| 122 | } | |
| 123 | }; | |
| 124 | method.to_tokens(tokens); | |
| 125 | } | |
| 126 | } | |
| 127 | ||
| 128 | pub(crate) struct InputSetter { | |
| 129 | pub(crate) signature: syn::Signature, | |
| 130 | pub(crate) return_type: syn::Type, | |
| 131 | pub(crate) create_data_ident: Ident, | |
| 132 | } | |
| 133 | ||
| 134 | impl ToTokens for InputSetter { | |
| 135 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { | |
| 136 | let sig = &mut self.signature.clone(); | |
| 137 | ||
| 138 | let ty = &self.return_type; | |
| 139 | let fn_ident = &sig.ident; | |
| 140 | let create_data_ident = &self.create_data_ident; | |
| 141 | ||
| 142 | let setter_ident = format_ident!("set_{}", fn_ident); | |
| 143 | sig.ident = setter_ident.clone(); | |
| 144 | ||
| 145 | let value_argument: PatType = parse_quote!(__value: #ty); | |
| 146 | sig.inputs.push(FnArg::Typed(value_argument.clone())); | |
| 147 | ||
| 148 | // make `&self` `&mut self` instead. | |
| 149 | let mut_receiver: Receiver = parse_quote!(&mut self); | |
| 150 | if let Some(og) = sig.inputs.first_mut() { | |
| 151 | *og = FnArg::Receiver(mut_receiver) | |
| 152 | } | |
| 153 | ||
| 154 | // remove the return value. | |
| 155 | sig.output = ReturnType::Default; | |
| 156 | ||
| 157 | let value = &value_argument.pat; | |
| 158 | 61 | let method = quote! { |
| 159 | 62 | #sig { |
| 160 | use salsa::Setter; | |
| 161 | let data = #create_data_ident(self); | |
| 162 | data.#setter_ident(self).to(Some(#value)); | |
| 63 | #annotation | |
| 64 | fn #shim<'db>( | |
| 65 | db: &'db dyn #trait_name, | |
| 66 | #(#pat_and_tys),* | |
| 67 | ) #ret | |
| 68 | #invoke_block | |
| 69 | ||
| 70 | #shim(self, #(#params),*) | |
| 163 | 71 | } |
| 164 | 72 | }; |
| 165 | method.to_tokens(tokens); | |
| 166 | } | |
| 167 | } | |
| 168 | ||
| 169 | pub(crate) struct InputSetterWithDurability { | |
| 170 | pub(crate) signature: syn::Signature, | |
| 171 | pub(crate) return_type: syn::Type, | |
| 172 | pub(crate) create_data_ident: Ident, | |
| 173 | } | |
| 174 | ||
| 175 | impl ToTokens for InputSetterWithDurability { | |
| 176 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { | |
| 177 | let sig = &mut self.signature.clone(); | |
| 178 | ||
| 179 | let ty = &self.return_type; | |
| 180 | let fn_ident = &sig.ident; | |
| 181 | let setter_ident = format_ident!("set_{}", fn_ident); | |
| 182 | ||
| 183 | let create_data_ident = &self.create_data_ident; | |
| 184 | ||
| 185 | sig.ident = format_ident!("set_{}_with_durability", fn_ident); | |
| 186 | 73 | |
| 187 | let value_argument: PatType = parse_quote!(__value: #ty); | |
| 188 | sig.inputs.push(FnArg::Typed(value_argument.clone())); | |
| 189 | ||
| 190 | let durability_argument: PatType = parse_quote!(durability: salsa::Durability); | |
| 191 | sig.inputs.push(FnArg::Typed(durability_argument.clone())); | |
| 192 | ||
| 193 | // make `&self` `&mut self` instead. | |
| 194 | let mut_receiver: Receiver = parse_quote!(&mut self); | |
| 195 | if let Some(og) = sig.inputs.first_mut() { | |
| 196 | *og = FnArg::Receiver(mut_receiver) | |
| 197 | } | |
| 198 | ||
| 199 | // remove the return value. | |
| 200 | sig.output = ReturnType::Default; | |
| 201 | ||
| 202 | let value = &value_argument.pat; | |
| 203 | let durability = &durability_argument.pat; | |
| 204 | let method = quote! { | |
| 205 | #sig { | |
| 206 | use salsa::Setter; | |
| 207 | let data = #create_data_ident(self); | |
| 208 | data.#setter_ident(self) | |
| 209 | .with_durability(#durability) | |
| 210 | .to(Some(#value)); | |
| 211 | } | |
| 212 | }; | |
| 213 | 74 | method.to_tokens(tokens); |
| 214 | 75 | } |
| 215 | 76 | } |
| 216 | 77 | |
| 217 | pub(crate) enum SetterKind { | |
| 218 | Plain(InputSetter), | |
| 219 | WithDurability(InputSetterWithDurability), | |
| 220 | } | |
| 221 | ||
| 222 | impl ToTokens for SetterKind { | |
| 223 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { | |
| 224 | match self { | |
| 225 | SetterKind::Plain(input_setter) => input_setter.to_tokens(tokens), | |
| 226 | SetterKind::WithDurability(input_setter_with_durability) => { | |
| 227 | input_setter_with_durability.to_tokens(tokens) | |
| 228 | } | |
| 229 | } | |
| 230 | } | |
| 231 | } | |
| 232 | ||
| 233 | 78 | pub(crate) struct Transparent { |
| 234 | 79 | pub(crate) signature: syn::Signature, |
| 235 | 80 | pub(crate) pat_and_tys: Vec<PatType>, |
| ... | ... | @@ -270,7 +115,6 @@ impl ToTokens for Transparent { |
| 270 | 115 | #[allow(clippy::large_enum_variant)] |
| 271 | 116 | pub(crate) enum Queries { |
| 272 | 117 | TrackedQuery(TrackedQuery), |
| 273 | InputQuery(InputQuery), | |
| 274 | 118 | Transparent(Transparent), |
| 275 | 119 | } |
| 276 | 120 | |
| ... | ... | @@ -278,7 +122,6 @@ impl ToTokens for Queries { |
| 278 | 122 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { |
| 279 | 123 | match self { |
| 280 | 124 | Queries::TrackedQuery(tracked_query) => tracked_query.to_tokens(tokens), |
| 281 | Queries::InputQuery(input_query) => input_query.to_tokens(tokens), | |
| 282 | 125 | Queries::Transparent(transparent) => transparent.to_tokens(tokens), |
| 283 | 126 | } |
| 284 | 127 | } |
src/tools/rust-analyzer/crates/query-group-macro/tests/arity.rs deleted-32| ... | ... | @@ -1,32 +0,0 @@ |
| 1 | use query_group_macro::query_group; | |
| 2 | ||
| 3 | #[query_group] | |
| 4 | pub trait ArityDb: salsa::Database { | |
| 5 | #[salsa::invoke_interned(one)] | |
| 6 | fn one(&self, a: ()) -> String; | |
| 7 | ||
| 8 | #[salsa::invoke_interned(two)] | |
| 9 | fn two(&self, a: (), b: ()) -> String; | |
| 10 | ||
| 11 | #[salsa::invoke_interned(three)] | |
| 12 | fn three(&self, a: (), b: (), c: ()) -> String; | |
| 13 | ||
| 14 | #[salsa::invoke_interned(none)] | |
| 15 | fn none(&self) -> String; | |
| 16 | } | |
| 17 | ||
| 18 | fn one(_db: &dyn ArityDb, _a: ()) -> String { | |
| 19 | String::new() | |
| 20 | } | |
| 21 | ||
| 22 | fn two(_db: &dyn ArityDb, _a: (), _b: ()) -> String { | |
| 23 | String::new() | |
| 24 | } | |
| 25 | ||
| 26 | fn three(_db: &dyn ArityDb, _a: (), _b: (), _c: ()) -> String { | |
| 27 | String::new() | |
| 28 | } | |
| 29 | ||
| 30 | fn none(_db: &dyn ArityDb) -> String { | |
| 31 | String::new() | |
| 32 | } |
src/tools/rust-analyzer/crates/query-group-macro/tests/hello_world.rs+14-89| ... | ... | @@ -4,126 +4,51 @@ use query_group_macro::query_group; |
| 4 | 4 | mod logger_db; |
| 5 | 5 | use logger_db::LoggerDb; |
| 6 | 6 | |
| 7 | #[salsa::input(singleton)] | |
| 8 | struct InputString { | |
| 9 | inner: String, | |
| 10 | } | |
| 11 | ||
| 7 | 12 | #[query_group] |
| 8 | 13 | pub trait HelloWorldDatabase: salsa::Database { |
| 9 | // input | |
| 10 | // // input with no params | |
| 11 | #[salsa::input] | |
| 12 | fn input_string(&self) -> String; | |
| 13 | ||
| 14 | // unadorned query | |
| 15 | #[salsa::invoke_interned(length_query)] | |
| 16 | fn length_query(&self, key: ()) -> usize; | |
| 17 | ||
| 18 | 14 | // unadorned query |
| 19 | 15 | fn length_query_with_no_params(&self) -> usize; |
| 20 | 16 | |
| 21 | // renamed/invoke query | |
| 22 | #[salsa::invoke_interned(invoke_length_query_actual)] | |
| 23 | fn invoke_length_query(&self, key: ()) -> usize; | |
| 24 | ||
| 25 | 17 | // not a query. should not invoked |
| 26 | 18 | #[salsa::transparent] |
| 27 | 19 | fn transparent_length(&self, key: ()) -> usize; |
| 28 | ||
| 29 | #[salsa::transparent] | |
| 30 | #[salsa::invoke_interned(transparent_and_invoke_length_actual)] | |
| 31 | fn transparent_and_invoke_length(&self, key: ()) -> usize; | |
| 32 | } | |
| 33 | ||
| 34 | fn length_query(db: &dyn HelloWorldDatabase, _key: ()) -> usize { | |
| 35 | db.input_string().len() | |
| 36 | 20 | } |
| 37 | 21 | |
| 38 | 22 | fn length_query_with_no_params(db: &dyn HelloWorldDatabase) -> usize { |
| 39 | db.input_string().len() | |
| 40 | } | |
| 41 | ||
| 42 | fn invoke_length_query_actual(db: &dyn HelloWorldDatabase, _key: ()) -> usize { | |
| 43 | db.input_string().len() | |
| 23 | InputString::get(db).inner(db).len() | |
| 44 | 24 | } |
| 45 | 25 | |
| 46 | 26 | fn transparent_length(db: &dyn HelloWorldDatabase, _key: ()) -> usize { |
| 47 | db.input_string().len() | |
| 48 | } | |
| 49 | ||
| 50 | fn transparent_and_invoke_length_actual(db: &dyn HelloWorldDatabase, _key: ()) -> usize { | |
| 51 | db.input_string().len() | |
| 27 | InputString::get(db).inner(db).len() | |
| 52 | 28 | } |
| 53 | 29 | |
| 54 | 30 | #[test] |
| 55 | 31 | fn unadorned_query() { |
| 56 | let mut db = LoggerDb::default(); | |
| 57 | ||
| 58 | db.set_input_string(String::from("Hello, world!")); | |
| 59 | let len = db.length_query(()); | |
| 60 | ||
| 61 | assert_eq!(len, 13); | |
| 62 | db.assert_logs(expect![[r#" | |
| 63 | [ | |
| 64 | "salsa_event(WillCheckCancellation)", | |
| 65 | "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 66 | "salsa_event(WillCheckCancellation)", | |
| 67 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 68 | "salsa_event(WillCheckCancellation)", | |
| 69 | "salsa_event(WillExecute { database_key: length_query_shim(Id(800)) })", | |
| 70 | "salsa_event(WillCheckCancellation)", | |
| 71 | ]"#]]); | |
| 72 | } | |
| 73 | ||
| 74 | #[test] | |
| 75 | fn invoke_query() { | |
| 76 | let mut db = LoggerDb::default(); | |
| 32 | let db = LoggerDb::default(); | |
| 77 | 33 | |
| 78 | db.set_input_string(String::from("Hello, world!")); | |
| 79 | let len = db.invoke_length_query(()); | |
| 34 | InputString::new(&db, String::from("Hello, world!")); | |
| 35 | let len = db.length_query_with_no_params(); | |
| 80 | 36 | |
| 81 | 37 | assert_eq!(len, 13); |
| 82 | 38 | db.assert_logs(expect![[r#" |
| 83 | 39 | [ |
| 84 | 40 | "salsa_event(WillCheckCancellation)", |
| 85 | "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 86 | "salsa_event(WillCheckCancellation)", | |
| 87 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 88 | "salsa_event(WillCheckCancellation)", | |
| 89 | "salsa_event(WillExecute { database_key: invoke_length_query_shim(Id(800)) })", | |
| 90 | "salsa_event(WillCheckCancellation)", | |
| 41 | "salsa_event(WillExecute { database_key: length_query_with_no_params_shim(Id(400)) })", | |
| 91 | 42 | ]"#]]); |
| 92 | 43 | } |
| 93 | 44 | |
| 94 | 45 | #[test] |
| 95 | 46 | fn transparent() { |
| 96 | let mut db = LoggerDb::default(); | |
| 47 | let db = LoggerDb::default(); | |
| 97 | 48 | |
| 98 | db.set_input_string(String::from("Hello, world!")); | |
| 49 | InputString::new(&db, String::from("Hello, world!")); | |
| 99 | 50 | let len = db.transparent_length(()); |
| 100 | 51 | |
| 101 | 52 | assert_eq!(len, 13); |
| 102 | db.assert_logs(expect![[r#" | |
| 103 | [ | |
| 104 | "salsa_event(WillCheckCancellation)", | |
| 105 | "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 106 | "salsa_event(WillCheckCancellation)", | |
| 107 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 108 | ]"#]]); | |
| 109 | } | |
| 110 | ||
| 111 | #[test] | |
| 112 | fn transparent_invoke() { | |
| 113 | let mut db = LoggerDb::default(); | |
| 114 | ||
| 115 | db.set_input_string(String::from("Hello, world!")); | |
| 116 | let len = db.transparent_and_invoke_length(()); | |
| 117 | ||
| 118 | assert_eq!(len, 13); | |
| 119 | db.assert_logs(expect![[r#" | |
| 120 | [ | |
| 121 | "salsa_event(WillCheckCancellation)", | |
| 122 | "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 123 | "salsa_event(WillCheckCancellation)", | |
| 124 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 125 | "salsa_event(WillCheckCancellation)", | |
| 126 | "salsa_event(WillExecute { database_key: transparent_and_invoke_length_shim(Id(800)) })", | |
| 127 | "salsa_event(WillCheckCancellation)", | |
| 128 | ]"#]]); | |
| 53 | db.assert_logs(expect!["[]"]); | |
| 129 | 54 | } |
src/tools/rust-analyzer/crates/query-group-macro/tests/lru.rs deleted-68| ... | ... | @@ -1,68 +0,0 @@ |
| 1 | use expect_test::expect; | |
| 2 | ||
| 3 | mod logger_db; | |
| 4 | use logger_db::LoggerDb; | |
| 5 | use query_group_macro::query_group; | |
| 6 | ||
| 7 | #[query_group] | |
| 8 | pub trait LruDB: salsa::Database { | |
| 9 | // // input with no params | |
| 10 | #[salsa::input] | |
| 11 | fn input_string(&self) -> String; | |
| 12 | ||
| 13 | #[salsa::lru(16)] | |
| 14 | #[salsa::invoke_interned(length_query)] | |
| 15 | fn length_query(&self, key: ()) -> usize; | |
| 16 | ||
| 17 | #[salsa::lru(16)] | |
| 18 | #[salsa::invoke_interned(invoked_query)] | |
| 19 | fn length_query_invoke(&self, key: ()) -> usize; | |
| 20 | } | |
| 21 | ||
| 22 | fn length_query(db: &dyn LruDB, _key: ()) -> usize { | |
| 23 | db.input_string().len() | |
| 24 | } | |
| 25 | ||
| 26 | fn invoked_query(db: &dyn LruDB, _key: ()) -> usize { | |
| 27 | db.input_string().len() | |
| 28 | } | |
| 29 | ||
| 30 | #[test] | |
| 31 | fn plain_lru() { | |
| 32 | let mut db = LoggerDb::default(); | |
| 33 | ||
| 34 | db.set_input_string(String::from("Hello, world!")); | |
| 35 | let len = db.length_query(()); | |
| 36 | ||
| 37 | assert_eq!(len, 13); | |
| 38 | db.assert_logs(expect![[r#" | |
| 39 | [ | |
| 40 | "salsa_event(WillCheckCancellation)", | |
| 41 | "salsa_event(WillExecute { database_key: create_data_LruDB(Id(0)) })", | |
| 42 | "salsa_event(WillCheckCancellation)", | |
| 43 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_LruDB(Id(0)) })", | |
| 44 | "salsa_event(WillCheckCancellation)", | |
| 45 | "salsa_event(WillExecute { database_key: length_query_shim(Id(800)) })", | |
| 46 | "salsa_event(WillCheckCancellation)", | |
| 47 | ]"#]]); | |
| 48 | } | |
| 49 | ||
| 50 | #[test] | |
| 51 | fn invoke_lru() { | |
| 52 | let mut db = LoggerDb::default(); | |
| 53 | ||
| 54 | db.set_input_string(String::from("Hello, world!")); | |
| 55 | let len = db.length_query_invoke(()); | |
| 56 | ||
| 57 | assert_eq!(len, 13); | |
| 58 | db.assert_logs(expect![[r#" | |
| 59 | [ | |
| 60 | "salsa_event(WillCheckCancellation)", | |
| 61 | "salsa_event(WillExecute { database_key: create_data_LruDB(Id(0)) })", | |
| 62 | "salsa_event(WillCheckCancellation)", | |
| 63 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_LruDB(Id(0)) })", | |
| 64 | "salsa_event(WillCheckCancellation)", | |
| 65 | "salsa_event(WillExecute { database_key: length_query_invoke_shim(Id(800)) })", | |
| 66 | "salsa_event(WillCheckCancellation)", | |
| 67 | ]"#]]); | |
| 68 | } |
src/tools/rust-analyzer/crates/query-group-macro/tests/multiple_dbs.rs+9-7| ... | ... | @@ -1,25 +1,27 @@ |
| 1 | 1 | use query_group_macro::query_group; |
| 2 | 2 | |
| 3 | #[salsa::input(singleton)] | |
| 4 | struct InputString { | |
| 5 | inner: String, | |
| 6 | } | |
| 7 | ||
| 3 | 8 | #[query_group] |
| 4 | 9 | pub trait DatabaseOne: salsa::Database { |
| 5 | #[salsa::input] | |
| 6 | fn input_string(&self) -> String; | |
| 7 | ||
| 8 | 10 | // unadorned query |
| 9 | #[salsa::invoke_interned(length)] | |
| 11 | #[salsa::transparent] | |
| 10 | 12 | fn length(&self, key: ()) -> usize; |
| 11 | 13 | } |
| 12 | 14 | |
| 13 | 15 | #[query_group] |
| 14 | 16 | pub trait DatabaseTwo: DatabaseOne { |
| 15 | #[salsa::invoke_interned(second_length)] | |
| 17 | #[salsa::transparent] | |
| 16 | 18 | fn second_length(&self, key: ()) -> usize; |
| 17 | 19 | } |
| 18 | 20 | |
| 19 | 21 | fn length(db: &dyn DatabaseOne, _key: ()) -> usize { |
| 20 | db.input_string().len() | |
| 22 | InputString::get(db).inner(db).len() | |
| 21 | 23 | } |
| 22 | 24 | |
| 23 | 25 | fn second_length(db: &dyn DatabaseTwo, _key: ()) -> usize { |
| 24 | db.input_string().len() | |
| 26 | InputString::get(db).inner(db).len() | |
| 25 | 27 | } |
src/tools/rust-analyzer/crates/query-group-macro/tests/result.rs+12-23| ... | ... | @@ -7,46 +7,35 @@ use query_group_macro::query_group; |
| 7 | 7 | #[derive(Clone, Debug, PartialEq, Eq)] |
| 8 | 8 | pub struct Error; |
| 9 | 9 | |
| 10 | #[salsa::input(singleton)] | |
| 11 | struct InputString { | |
| 12 | inner: String, | |
| 13 | } | |
| 14 | ||
| 10 | 15 | #[query_group] |
| 11 | 16 | pub trait ResultDatabase: salsa::Database { |
| 12 | #[salsa::input] | |
| 13 | fn input_string(&self) -> String; | |
| 14 | ||
| 15 | #[salsa::invoke_interned(length)] | |
| 17 | #[salsa::transparent] | |
| 16 | 18 | fn length(&self, key: ()) -> Result<usize, Error>; |
| 17 | 19 | |
| 18 | #[salsa::invoke_interned(length2)] | |
| 20 | #[salsa::transparent] | |
| 19 | 21 | fn length2(&self, key: ()) -> Result<usize, Error>; |
| 20 | 22 | } |
| 21 | 23 | |
| 22 | 24 | fn length(db: &dyn ResultDatabase, _key: ()) -> Result<usize, Error> { |
| 23 | Ok(db.input_string().len()) | |
| 25 | Ok(InputString::get(db).inner(db).len()) | |
| 24 | 26 | } |
| 25 | 27 | |
| 26 | 28 | fn length2(db: &dyn ResultDatabase, _key: ()) -> Result<usize, Error> { |
| 27 | Ok(db.input_string().len()) | |
| 29 | Ok(InputString::get(db).inner(db).len()) | |
| 28 | 30 | } |
| 29 | 31 | |
| 30 | 32 | #[test] |
| 31 | 33 | fn test_queries_with_results() { |
| 32 | let mut db = LoggerDb::default(); | |
| 34 | let db = LoggerDb::default(); | |
| 33 | 35 | let input = "hello"; |
| 34 | db.set_input_string(input.to_owned()); | |
| 36 | _ = InputString::new(&db, input.to_owned()); | |
| 35 | 37 | assert_eq!(db.length(()), Ok(input.len())); |
| 36 | 38 | assert_eq!(db.length2(()), Ok(input.len())); |
| 37 | 39 | |
| 38 | db.assert_logs(expect![[r#" | |
| 39 | [ | |
| 40 | "salsa_event(WillCheckCancellation)", | |
| 41 | "salsa_event(WillExecute { database_key: create_data_ResultDatabase(Id(0)) })", | |
| 42 | "salsa_event(WillCheckCancellation)", | |
| 43 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_ResultDatabase(Id(0)) })", | |
| 44 | "salsa_event(WillCheckCancellation)", | |
| 45 | "salsa_event(WillExecute { database_key: length_shim(Id(800)) })", | |
| 46 | "salsa_event(WillCheckCancellation)", | |
| 47 | "salsa_event(WillCheckCancellation)", | |
| 48 | "salsa_event(WillCheckCancellation)", | |
| 49 | "salsa_event(WillExecute { database_key: length2_shim(Id(c00)) })", | |
| 50 | "salsa_event(WillCheckCancellation)", | |
| 51 | ]"#]]); | |
| 40 | db.assert_logs(expect!["[]"]); | |
| 52 | 41 | } |
src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs+1-1| ... | ... | @@ -8,7 +8,7 @@ pub trait SourceDb: salsa::Database { |
| 8 | 8 | |
| 9 | 9 | #[query_group] |
| 10 | 10 | pub trait RootDb: SourceDb { |
| 11 | #[salsa::invoke_interned(parse)] | |
| 11 | #[salsa::transparent] | |
| 12 | 12 | fn parse(&self, id: usize) -> String; |
| 13 | 13 | } |
| 14 | 14 |
src/tools/rust-analyzer/crates/query-group-macro/tests/tuples.rs+10-17| ... | ... | @@ -4,36 +4,29 @@ mod logger_db; |
| 4 | 4 | use expect_test::expect; |
| 5 | 5 | use logger_db::LoggerDb; |
| 6 | 6 | |
| 7 | #[salsa::input(singleton)] | |
| 8 | struct InputString { | |
| 9 | inner: String, | |
| 10 | } | |
| 11 | ||
| 7 | 12 | #[query_group] |
| 8 | 13 | pub trait HelloWorldDatabase: salsa::Database { |
| 9 | #[salsa::input] | |
| 10 | fn input_string(&self) -> String; | |
| 11 | ||
| 12 | #[salsa::invoke_interned(length_query)] | |
| 14 | #[salsa::transparent] | |
| 13 | 15 | fn length_query(&self, key: ()) -> (usize, usize); |
| 14 | 16 | } |
| 15 | 17 | |
| 16 | 18 | fn length_query(db: &dyn HelloWorldDatabase, _key: ()) -> (usize, usize) { |
| 17 | let len = db.input_string().len(); | |
| 19 | let len = InputString::get(db).inner(db).len(); | |
| 18 | 20 | (len, len) |
| 19 | 21 | } |
| 20 | 22 | |
| 21 | 23 | #[test] |
| 22 | 24 | fn query() { |
| 23 | let mut db = LoggerDb::default(); | |
| 25 | let db = LoggerDb::default(); | |
| 24 | 26 | |
| 25 | db.set_input_string(String::from("Hello, world!")); | |
| 27 | _ = InputString::new(&db, String::from("Hello, world!")); | |
| 26 | 28 | let len = db.length_query(()); |
| 27 | 29 | |
| 28 | 30 | assert_eq!(len, (13, 13)); |
| 29 | db.assert_logs(expect![[r#" | |
| 30 | [ | |
| 31 | "salsa_event(WillCheckCancellation)", | |
| 32 | "salsa_event(WillExecute { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 33 | "salsa_event(WillCheckCancellation)", | |
| 34 | "salsa_event(DidValidateMemoizedValue { database_key: create_data_HelloWorldDatabase(Id(0)) })", | |
| 35 | "salsa_event(WillCheckCancellation)", | |
| 36 | "salsa_event(WillExecute { database_key: length_query_shim(Id(800)) })", | |
| 37 | "salsa_event(WillCheckCancellation)", | |
| 38 | ]"#]]); | |
| 31 | db.assert_logs(expect!["[]"]); | |
| 39 | 32 | } |
src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml+1-1| ... | ... | @@ -29,7 +29,7 @@ ide-completion.workspace = true |
| 29 | 29 | indexmap.workspace = true |
| 30 | 30 | itertools.workspace = true |
| 31 | 31 | scip = "0.7.1" |
| 32 | lsp-types = { version = "=0.95.0", features = ["proposed"] } | |
| 32 | lsp-types = { version = "0.4.0", package = "gen-lsp-types", features=["url"] } | |
| 33 | 33 | parking_lot = "0.12.4" |
| 34 | 34 | xflags = "0.3.2" |
| 35 | 35 | oorandom = "11.1.5" |
src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs+14-19| ... | ... | @@ -207,25 +207,15 @@ fn run_server() -> anyhow::Result<()> { |
| 207 | 207 | |
| 208 | 208 | tracing::info!("InitializeParams: {}", initialize_params); |
| 209 | 209 | let lsp_types::InitializeParams { |
| 210 | #[expect(deprecated, reason = "compatibility with old clients")] | |
| 210 | 211 | root_uri, |
| 211 | mut capabilities, | |
| 212 | workspace_folders, | |
| 212 | capabilities, | |
| 213 | workspace_folders_initialize_params, | |
| 213 | 214 | initialization_options, |
| 214 | 215 | client_info, |
| 215 | 216 | .. |
| 216 | 217 | } = from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?; |
| 217 | 218 | |
| 218 | // lsp-types has a typo in the `/capabilities/workspace/diagnostics` field, its typoed as `diagnostic` | |
| 219 | if let Some(val) = initialize_params.pointer("/capabilities/workspace/diagnostics") | |
| 220 | && let Ok(diag_caps) = from_json::<lsp_types::DiagnosticWorkspaceClientCapabilities>( | |
| 221 | "DiagnosticWorkspaceClientCapabilities", | |
| 222 | val, | |
| 223 | ) | |
| 224 | { | |
| 225 | tracing::info!("Patching lsp-types workspace diagnostics capabilities: {diag_caps:#?}"); | |
| 226 | capabilities.workspace.get_or_insert_default().diagnostic.get_or_insert(diag_caps); | |
| 227 | } | |
| 228 | ||
| 229 | 219 | let root_path = match root_uri |
| 230 | 220 | .and_then(|it| it.to_file_path().ok()) |
| 231 | 221 | .map(patch_path_prefix) |
| ... | ... | @@ -247,7 +237,14 @@ fn run_server() -> anyhow::Result<()> { |
| 247 | 237 | ); |
| 248 | 238 | } |
| 249 | 239 | |
| 250 | let workspace_roots = workspace_folders | |
| 240 | let workspace_roots = workspace_folders_initialize_params | |
| 241 | .workspace_folders | |
| 242 | .and_then(|workspaces| match workspaces { | |
| 243 | lsp_types::WorkspaceFolders::WorkspaceFolderList(workspace_folders) => { | |
| 244 | Some(workspace_folders) | |
| 245 | } | |
| 246 | lsp_types::WorkspaceFolders::Null => None, | |
| 247 | }) | |
| 251 | 248 | .map(|workspaces| { |
| 252 | 249 | workspaces |
| 253 | 250 | .into_iter() |
| ... | ... | @@ -269,12 +266,11 @@ fn run_server() -> anyhow::Result<()> { |
| 269 | 266 | |
| 270 | 267 | if !error_sink.is_empty() { |
| 271 | 268 | use lsp_types::{ |
| 272 | MessageType, ShowMessageParams, | |
| 273 | notification::{Notification, ShowMessage}, | |
| 269 | MessageType, Notification as _, ShowMessageNotification, ShowMessageParams, | |
| 274 | 270 | }; |
| 275 | 271 | let not = lsp_server::Notification::new( |
| 276 | ShowMessage::METHOD.to_owned(), | |
| 277 | ShowMessageParams { typ: MessageType::WARNING, message: error_sink.to_string() }, | |
| 272 | ShowMessageNotification::METHOD.into(), | |
| 273 | ShowMessageParams { kind: MessageType::Warning, message: error_sink.to_string() }, | |
| 278 | 274 | ); |
| 279 | 275 | connection.sender.send(lsp_server::Message::Notification(not)).unwrap(); |
| 280 | 276 | } |
| ... | ... | @@ -288,7 +284,6 @@ fn run_server() -> anyhow::Result<()> { |
| 288 | 284 | name: String::from("rust-analyzer"), |
| 289 | 285 | version: Some(rust_analyzer::version().to_string()), |
| 290 | 286 | }), |
| 291 | offset_encoding: None, | |
| 292 | 287 | }; |
| 293 | 288 | |
| 294 | 289 | let initialize_result = serde_json::to_value(initialize_result).unwrap(); |
src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs+10-9| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | //! LSIF (language server index format) generator |
| 2 | ||
| 3 | 2 | use std::env; |
| 4 | 3 | use std::time::Instant; |
| 5 | 4 | |
| ... | ... | @@ -10,12 +9,14 @@ use ide::{ |
| 10 | 9 | }; |
| 11 | 10 | use ide_db::{line_index, line_index::WideEncoding}; |
| 12 | 11 | use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace}; |
| 13 | use lsp_types::lsif; | |
| 14 | 12 | use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource}; |
| 15 | 13 | use rustc_hash::FxHashMap; |
| 16 | 14 | use stdx::format_to; |
| 15 | use vendored as lsif; | |
| 17 | 16 | use vfs::{AbsPathBuf, Vfs}; |
| 18 | 17 | |
| 18 | mod vendored; | |
| 19 | ||
| 19 | 20 | use crate::{ |
| 20 | 21 | cli::flags, |
| 21 | 22 | line_index::{LineEndings, LineIndex, PositionEncoding}, |
| ... | ... | @@ -38,9 +39,9 @@ struct LsifManager<'a, 'w> { |
| 38 | 39 | #[derive(Clone, Copy)] |
| 39 | 40 | struct Id(i32); |
| 40 | 41 | |
| 41 | impl From<Id> for lsp_types::NumberOrString { | |
| 42 | impl From<Id> for lsp_types::Code { | |
| 42 | 43 | fn from(Id(it): Id) -> Self { |
| 43 | lsp_types::NumberOrString::Number(it) | |
| 44 | lsp_types::Code::Int(it) | |
| 44 | 45 | } |
| 45 | 46 | } |
| 46 | 47 | |
| ... | ... | @@ -145,7 +146,7 @@ impl LsifManager<'_, '_> { |
| 145 | 146 | let path = path.as_path().unwrap(); |
| 146 | 147 | let doc_id = self.add_vertex(lsif::Vertex::Document(lsif::Document { |
| 147 | 148 | language_id: "rust".to_owned(), |
| 148 | uri: lsp_types::Url::from_file_path(path).unwrap(), | |
| 149 | uri: lsp_types::Uri::from_file_path(path).unwrap(), | |
| 149 | 150 | })); |
| 150 | 151 | self.file_map.insert(id, doc_id); |
| 151 | 152 | doc_id |
| ... | ... | @@ -156,7 +157,7 @@ impl LsifManager<'_, '_> { |
| 156 | 157 | if let Some(hover) = token.hover { |
| 157 | 158 | let hover_id = self.add_vertex(lsif::Vertex::HoverResult { |
| 158 | 159 | result: lsp_types::Hover { |
| 159 | contents: lsp_types::HoverContents::Markup(to_proto::markup_content( | |
| 160 | contents: lsp_types::Contents::MarkupContent(to_proto::markup_content( | |
| 160 | 161 | hover.markup, |
| 161 | 162 | ide::HoverDocFormat::Markdown, |
| 162 | 163 | )), |
| ... | ... | @@ -211,7 +212,7 @@ impl LsifManager<'_, '_> { |
| 211 | 212 | out_v: result_set_id.into(), |
| 212 | 213 | })); |
| 213 | 214 | let mut edges = token.references.iter().fold( |
| 214 | FxHashMap::<_, Vec<lsp_types::NumberOrString>>::default(), | |
| 215 | FxHashMap::<_, Vec<lsp_types::Code>>::default(), | |
| 215 | 216 | |mut edges, it| { |
| 216 | 217 | let entry = edges.entry((it.range.file_id, it.is_definition)).or_default(); |
| 217 | 218 | entry.push((*self.range_map.get(&it.range).unwrap()).into()); |
| ... | ... | @@ -321,9 +322,9 @@ impl flags::Lsif { |
| 321 | 322 | let mut lsif = LsifManager::new(&analysis, db, &vfs, out); |
| 322 | 323 | lsif.add_vertex(lsif::Vertex::MetaData(lsif::MetaData { |
| 323 | 324 | version: String::from("0.5.0"), |
| 324 | project_root: lsp_types::Url::from_file_path(path).unwrap(), | |
| 325 | project_root: lsp_types::Uri::from_file_path(path).unwrap(), | |
| 325 | 326 | position_encoding: lsif::Encoding::Utf16, |
| 326 | tool_info: Some(lsp_types::lsif::ToolInfo { | |
| 327 | tool_info: Some(lsif::ToolInfo { | |
| 327 | 328 | name: "rust-analyzer".to_owned(), |
| 328 | 329 | args: vec![], |
| 329 | 330 | version: Some(version().to_string()), |
src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif/vendored.rs created+338| ... | ... | @@ -0,0 +1,338 @@ |
| 1 | //! Types of Language Server Index Format (LSIF). LSIF is a standard format | |
| 2 | //! for language servers or other programming tools to dump their knowledge | |
| 3 | //! about a workspace. | |
| 4 | //! | |
| 5 | //! Based on <https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/> | |
| 6 | ||
| 7 | #![allow(unused, unreachable_pub, reason = "implementing the full spec is fine")] | |
| 8 | ||
| 9 | use lsp_types::{Range, Uri}; | |
| 10 | use serde::{Deserialize, Serialize}; | |
| 11 | ||
| 12 | pub type Id = lsp_types::Code; | |
| 13 | ||
| 14 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 15 | #[serde(untagged)] | |
| 16 | pub enum LocationOrRangeId { | |
| 17 | Location(lsp_types::Location), | |
| 18 | RangeId(Id), | |
| 19 | } | |
| 20 | ||
| 21 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 22 | #[serde(rename_all = "camelCase")] | |
| 23 | pub struct Entry { | |
| 24 | pub id: Id, | |
| 25 | #[serde(flatten)] | |
| 26 | pub data: Element, | |
| 27 | } | |
| 28 | ||
| 29 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 30 | #[serde(rename_all = "camelCase")] | |
| 31 | #[serde(tag = "type")] | |
| 32 | pub enum Element { | |
| 33 | Vertex(Vertex), | |
| 34 | Edge(Edge), | |
| 35 | } | |
| 36 | ||
| 37 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 38 | pub struct ToolInfo { | |
| 39 | pub name: String, | |
| 40 | #[serde(default = "Default::default")] | |
| 41 | #[serde(skip_serializing_if = "Vec::is_empty")] | |
| 42 | pub args: Vec<String>, | |
| 43 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 44 | pub version: Option<String>, | |
| 45 | } | |
| 46 | ||
| 47 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)] | |
| 48 | pub enum Encoding { | |
| 49 | /// Currently only 'utf-16' is supported due to the limitations in LSP. | |
| 50 | #[serde(rename = "utf-16")] | |
| 51 | Utf16, | |
| 52 | } | |
| 53 | ||
| 54 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 55 | pub struct RangeBasedDocumentSymbol { | |
| 56 | pub id: Id, | |
| 57 | #[serde(default = "Default::default")] | |
| 58 | #[serde(skip_serializing_if = "Vec::is_empty")] | |
| 59 | pub children: Vec<RangeBasedDocumentSymbol>, | |
| 60 | } | |
| 61 | ||
| 62 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 63 | #[serde(rename_all = "camelCase")] | |
| 64 | #[serde(untagged)] | |
| 65 | pub enum DocumentSymbolOrRangeBasedVec { | |
| 66 | DocumentSymbol(Vec<lsp_types::DocumentSymbol>), | |
| 67 | RangeBased(Vec<RangeBasedDocumentSymbol>), | |
| 68 | } | |
| 69 | ||
| 70 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 71 | #[serde(rename_all = "camelCase")] | |
| 72 | pub struct DefinitionTag { | |
| 73 | /// The text covered by the range | |
| 74 | text: String, | |
| 75 | /// The symbol kind. | |
| 76 | kind: lsp_types::SymbolKind, | |
| 77 | /// Indicates if this symbol is deprecated. | |
| 78 | #[serde(default)] | |
| 79 | #[serde(skip_serializing_if = "std::ops::Not::not")] | |
| 80 | deprecated: bool, | |
| 81 | /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code. | |
| 82 | /// The range must be included in fullRange. | |
| 83 | full_range: Range, | |
| 84 | /// Optional detail information for the definition. | |
| 85 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 86 | detail: Option<String>, | |
| 87 | } | |
| 88 | ||
| 89 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 90 | #[serde(rename_all = "camelCase")] | |
| 91 | pub struct DeclarationTag { | |
| 92 | /// The text covered by the range | |
| 93 | text: String, | |
| 94 | /// The symbol kind. | |
| 95 | kind: lsp_types::SymbolKind, | |
| 96 | /// Indicates if this symbol is deprecated. | |
| 97 | #[serde(default)] | |
| 98 | deprecated: bool, | |
| 99 | /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code. | |
| 100 | /// The range must be included in fullRange. | |
| 101 | full_range: Range, | |
| 102 | /// Optional detail information for the definition. | |
| 103 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 104 | detail: Option<String>, | |
| 105 | } | |
| 106 | ||
| 107 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 108 | #[serde(rename_all = "camelCase")] | |
| 109 | pub struct ReferenceTag { | |
| 110 | text: String, | |
| 111 | } | |
| 112 | ||
| 113 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 114 | #[serde(rename_all = "camelCase")] | |
| 115 | pub struct UnknownTag { | |
| 116 | text: String, | |
| 117 | } | |
| 118 | ||
| 119 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 120 | #[serde(rename_all = "camelCase")] | |
| 121 | #[serde(tag = "type")] | |
| 122 | pub enum RangeTag { | |
| 123 | Definition(DefinitionTag), | |
| 124 | Declaration(DeclarationTag), | |
| 125 | Reference(ReferenceTag), | |
| 126 | Unknown(UnknownTag), | |
| 127 | } | |
| 128 | ||
| 129 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 130 | #[serde(rename_all = "camelCase")] | |
| 131 | #[serde(tag = "label")] | |
| 132 | pub enum Vertex { | |
| 133 | MetaData(MetaData), | |
| 134 | /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex> | |
| 135 | Project(Project), | |
| 136 | Document(Document), | |
| 137 | /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#ranges> | |
| 138 | Range { | |
| 139 | #[serde(flatten)] | |
| 140 | range: Range, | |
| 141 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 142 | tag: Option<RangeTag>, | |
| 143 | }, | |
| 144 | /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set> | |
| 145 | ResultSet(ResultSet), | |
| 146 | Moniker(lsp_types::Moniker), | |
| 147 | PackageInformation(PackageInformation), | |
| 148 | ||
| 149 | #[serde(rename = "$event")] | |
| 150 | Event(Event), | |
| 151 | ||
| 152 | DefinitionResult, | |
| 153 | DeclarationResult, | |
| 154 | TypeDefinitionResult, | |
| 155 | ReferenceResult, | |
| 156 | ImplementationResult, | |
| 157 | FoldingRangeResult { | |
| 158 | result: Vec<lsp_types::FoldingRange>, | |
| 159 | }, | |
| 160 | HoverResult { | |
| 161 | result: lsp_types::Hover, | |
| 162 | }, | |
| 163 | DocumentSymbolResult { | |
| 164 | result: DocumentSymbolOrRangeBasedVec, | |
| 165 | }, | |
| 166 | DocumentLinkResult { | |
| 167 | result: Vec<lsp_types::DocumentLink>, | |
| 168 | }, | |
| 169 | DiagnosticResult { | |
| 170 | result: Vec<lsp_types::Diagnostic>, | |
| 171 | }, | |
| 172 | } | |
| 173 | ||
| 174 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 175 | #[serde(rename_all = "camelCase")] | |
| 176 | pub enum EventKind { | |
| 177 | Begin, | |
| 178 | End, | |
| 179 | } | |
| 180 | ||
| 181 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 182 | #[serde(rename_all = "camelCase")] | |
| 183 | pub enum EventScope { | |
| 184 | Document, | |
| 185 | Project, | |
| 186 | } | |
| 187 | ||
| 188 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 189 | pub struct Event { | |
| 190 | pub kind: EventKind, | |
| 191 | pub scope: EventScope, | |
| 192 | pub data: Id, | |
| 193 | } | |
| 194 | ||
| 195 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 196 | #[serde(rename_all = "camelCase")] | |
| 197 | #[serde(tag = "label")] | |
| 198 | pub enum Edge { | |
| 199 | Contains(EdgeDataMultiIn), | |
| 200 | Moniker(EdgeData), | |
| 201 | NextMoniker(EdgeData), | |
| 202 | Next(EdgeData), | |
| 203 | PackageInformation(EdgeData), | |
| 204 | Item(Item), | |
| 205 | ||
| 206 | // Methods | |
| 207 | #[serde(rename = "textDocument/definition")] | |
| 208 | Definition(EdgeData), | |
| 209 | #[serde(rename = "textDocument/declaration")] | |
| 210 | Declaration(EdgeData), | |
| 211 | #[serde(rename = "textDocument/hover")] | |
| 212 | Hover(EdgeData), | |
| 213 | #[serde(rename = "textDocument/references")] | |
| 214 | References(EdgeData), | |
| 215 | #[serde(rename = "textDocument/implementation")] | |
| 216 | Implementation(EdgeData), | |
| 217 | #[serde(rename = "textDocument/typeDefinition")] | |
| 218 | TypeDefinition(EdgeData), | |
| 219 | #[serde(rename = "textDocument/foldingRange")] | |
| 220 | FoldingRange(EdgeData), | |
| 221 | #[serde(rename = "textDocument/documentLink")] | |
| 222 | DocumentLink(EdgeData), | |
| 223 | #[serde(rename = "textDocument/documentSymbol")] | |
| 224 | DocumentSymbol(EdgeData), | |
| 225 | #[serde(rename = "textDocument/diagnostic")] | |
| 226 | Diagnostic(EdgeData), | |
| 227 | } | |
| 228 | ||
| 229 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 230 | #[serde(rename_all = "camelCase")] | |
| 231 | pub struct EdgeData { | |
| 232 | pub in_v: Id, | |
| 233 | pub out_v: Id, | |
| 234 | } | |
| 235 | ||
| 236 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 237 | #[serde(rename_all = "camelCase")] | |
| 238 | pub struct EdgeDataMultiIn { | |
| 239 | pub in_vs: Vec<Id>, | |
| 240 | pub out_v: Id, | |
| 241 | } | |
| 242 | ||
| 243 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 244 | #[serde(untagged)] | |
| 245 | pub enum DefinitionResultType { | |
| 246 | Scalar(LocationOrRangeId), | |
| 247 | Array(LocationOrRangeId), | |
| 248 | } | |
| 249 | ||
| 250 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 251 | #[serde(rename_all = "camelCase")] | |
| 252 | pub enum ItemKind { | |
| 253 | Declarations, | |
| 254 | Definitions, | |
| 255 | References, | |
| 256 | ReferenceResults, | |
| 257 | ImplementationResults, | |
| 258 | } | |
| 259 | ||
| 260 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 261 | #[serde(rename_all = "camelCase")] | |
| 262 | pub struct Item { | |
| 263 | pub document: Id, | |
| 264 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 265 | pub property: Option<ItemKind>, | |
| 266 | #[serde(flatten)] | |
| 267 | pub edge_data: EdgeDataMultiIn, | |
| 268 | } | |
| 269 | ||
| 270 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 271 | #[serde(rename_all = "camelCase")] | |
| 272 | pub struct Document { | |
| 273 | pub uri: Uri, | |
| 274 | pub language_id: String, | |
| 275 | } | |
| 276 | ||
| 277 | /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set> | |
| 278 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 279 | #[serde(rename_all = "camelCase")] | |
| 280 | pub struct ResultSet { | |
| 281 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 282 | pub key: Option<String>, | |
| 283 | } | |
| 284 | ||
| 285 | /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex> | |
| 286 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 287 | #[serde(rename_all = "camelCase")] | |
| 288 | pub struct Project { | |
| 289 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 290 | pub resource: Option<Uri>, | |
| 291 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 292 | pub content: Option<String>, | |
| 293 | pub kind: String, | |
| 294 | } | |
| 295 | ||
| 296 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 297 | #[serde(rename_all = "camelCase")] | |
| 298 | pub struct MetaData { | |
| 299 | /// The version of the LSIF format using semver notation. See <https://semver.org/>. Please note | |
| 300 | /// the version numbers starting with 0 don't adhere to semver and adopters have to assume | |
| 301 | /// that each new version is breaking. | |
| 302 | pub version: String, | |
| 303 | ||
| 304 | /// The project root (in form of an URI) used to compute this dump. | |
| 305 | pub project_root: Uri, | |
| 306 | ||
| 307 | /// The string encoding used to compute line and character values in | |
| 308 | /// positions and ranges. | |
| 309 | pub position_encoding: Encoding, | |
| 310 | ||
| 311 | /// Information about the tool that created the dump | |
| 312 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 313 | pub tool_info: Option<ToolInfo>, | |
| 314 | } | |
| 315 | ||
| 316 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 317 | #[serde(rename_all = "camelCase")] | |
| 318 | pub struct Repository { | |
| 319 | pub r#type: String, | |
| 320 | pub url: String, | |
| 321 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 322 | pub commit_id: Option<String>, | |
| 323 | } | |
| 324 | ||
| 325 | #[derive(Debug, PartialEq, Serialize, Deserialize)] | |
| 326 | #[serde(rename_all = "camelCase")] | |
| 327 | pub struct PackageInformation { | |
| 328 | pub name: String, | |
| 329 | pub manager: String, | |
| 330 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 331 | pub uri: Option<Uri>, | |
| 332 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 333 | pub content: Option<String>, | |
| 334 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 335 | pub repository: Option<Repository>, | |
| 336 | #[serde(skip_serializing_if = "Option::is_none")] | |
| 337 | pub version: Option<String>, | |
| 338 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs+64| ... | ... | @@ -948,4 +948,68 @@ pub mod example_mod { |
| 948 | 948 | |
| 949 | 949 | assert_eq!(token.definition_body, Some(expected_range)); |
| 950 | 950 | } |
| 951 | ||
| 952 | #[test] | |
| 953 | fn function_enclosing_range_trivia() { | |
| 954 | let s = "fn first() {}\n// belongs to first\n/// second docs\nfn second() {}"; | |
| 955 | ||
| 956 | let mut host = AnalysisHost::default(); | |
| 957 | let change_fixture = ChangeFixture::parse(s); | |
| 958 | host.raw_database_mut().apply_change(change_fixture.change); | |
| 959 | ||
| 960 | let analysis = host.analysis(); | |
| 961 | let si = StaticIndex::compute( | |
| 962 | &analysis, | |
| 963 | VendoredLibrariesConfig::Included { | |
| 964 | workspace_root: &VfsPath::new_virtual_path("/workspace".to_owned()), | |
| 965 | }, | |
| 966 | ); | |
| 967 | ||
| 968 | let file = si.files.first().unwrap(); | |
| 969 | let token = file | |
| 970 | .tokens | |
| 971 | .iter() | |
| 972 | .filter_map(|(_, token_id)| si.tokens.get(*token_id)) | |
| 973 | .find(|token| token.display_name.as_deref() == Some("second")) | |
| 974 | .unwrap(); | |
| 975 | ||
| 976 | let definition_body = token.definition_body.unwrap(); | |
| 977 | assert_eq!( | |
| 978 | definition_body.range.start(), | |
| 979 | TextSize::new(s.find("/// second docs").unwrap() as u32) | |
| 980 | ); | |
| 981 | assert_eq!(definition_body.range.end(), TextSize::of(s)); | |
| 982 | } | |
| 983 | ||
| 984 | #[test] | |
| 985 | fn const_enclosing_range_trivia() { | |
| 986 | let s = "const FOO_ONE: i32 = 123; // one\nconst FOO_TWO: i32 = 123; // two"; | |
| 987 | ||
| 988 | let mut host = AnalysisHost::default(); | |
| 989 | let change_fixture = ChangeFixture::parse(s); | |
| 990 | host.raw_database_mut().apply_change(change_fixture.change); | |
| 991 | ||
| 992 | let analysis = host.analysis(); | |
| 993 | let si = StaticIndex::compute( | |
| 994 | &analysis, | |
| 995 | VendoredLibrariesConfig::Included { | |
| 996 | workspace_root: &VfsPath::new_virtual_path("/workspace".to_owned()), | |
| 997 | }, | |
| 998 | ); | |
| 999 | ||
| 1000 | let file = si.files.first().unwrap(); | |
| 1001 | let token = file | |
| 1002 | .tokens | |
| 1003 | .iter() | |
| 1004 | .filter_map(|(_, token_id)| si.tokens.get(*token_id)) | |
| 1005 | .find(|token| token.display_name.as_deref() == Some("FOO_TWO")) | |
| 1006 | .unwrap(); | |
| 1007 | ||
| 1008 | let definition_body = token.definition_body.unwrap(); | |
| 1009 | assert_eq!( | |
| 1010 | definition_body.range.start(), | |
| 1011 | TextSize::new(s.find("const FOO_TWO").unwrap() as u32) | |
| 1012 | ); | |
| 1013 | assert_eq!(definition_body.range.end(), TextSize::new(s.find(" // two").unwrap() as u32)); | |
| 1014 | } | |
| 951 | 1015 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs+20-4| ... | ... | @@ -833,6 +833,10 @@ config_data! { |
| 833 | 833 | cargo_cfgs: Vec<String> = { |
| 834 | 834 | vec!["debug_assertions".into(), "miri".into()] |
| 835 | 835 | }, |
| 836 | /// Path to a `.cargo/config.toml` style file to pass to cargo via `--config` | |
| 837 | /// for every cargo invocation (metadata, build scripts, config discovery). | |
| 838 | /// Useful to give rust-analyzer a consistent view of the project configuration. | |
| 839 | cargo_configPath: Option<Utf8PathBuf> = None, | |
| 836 | 840 | /// Extra arguments that are passed to every cargo invocation. |
| 837 | 841 | cargo_extraArgs: Vec<String> = vec![], |
| 838 | 842 | /// Extra environment variables that will be set when running cargo, rustc |
| ... | ... | @@ -1127,7 +1131,7 @@ pub struct Config { |
| 1127 | 1131 | |
| 1128 | 1132 | default_config: &'static DefaultConfigData, |
| 1129 | 1133 | /// Config node that obtains its initial value during the server initialization and |
| 1130 | /// by receiving a `lsp_types::notification::DidChangeConfiguration`. | |
| 1134 | /// by receiving a [`lsp_types::DidChangeConfigurationNotification`]. | |
| 1131 | 1135 | client_config: (FullConfigInput, ConfigErrors), |
| 1132 | 1136 | |
| 1133 | 1137 | /// Config node whose values apply to **every** Rust project. |
| ... | ... | @@ -1684,6 +1688,8 @@ pub struct RunnablesConfig { |
| 1684 | 1688 | pub override_cargo: Option<String>, |
| 1685 | 1689 | /// Additional arguments for the `cargo`, e.g. `--release`. |
| 1686 | 1690 | pub cargo_extra_args: Vec<String>, |
| 1691 | /// Path to an extra config file passed to cargo via `--config`. | |
| 1692 | pub config_path: Option<AbsPathBuf>, | |
| 1687 | 1693 | /// Additional arguments for the binary being run, if it is a test or benchmark. |
| 1688 | 1694 | pub extra_test_binary_args: Vec<String>, |
| 1689 | 1695 | /// Subcommand used for doctest runnables instead of `test`. |
| ... | ... | @@ -2418,6 +2424,7 @@ impl Config { |
| 2418 | 2424 | }); |
| 2419 | 2425 | let sysroot_src = |
| 2420 | 2426 | self.cargo_sysrootSrc(source_root).as_ref().map(|sysroot| self.root_path.join(sysroot)); |
| 2427 | let config_path = self.cargo_config_path(source_root); | |
| 2421 | 2428 | let extra_includes = self |
| 2422 | 2429 | .vfs_extraIncludes(source_root) |
| 2423 | 2430 | .iter() |
| ... | ... | @@ -2484,6 +2491,7 @@ impl Config { |
| 2484 | 2491 | set_test: *self.cfg_setTest(source_root), |
| 2485 | 2492 | no_deps: *self.cargo_noDeps(source_root), |
| 2486 | 2493 | metadata_extra_args: self.cargo_metadataExtraArgs(source_root).clone(), |
| 2494 | config_path, | |
| 2487 | 2495 | } |
| 2488 | 2496 | } |
| 2489 | 2497 | |
| ... | ... | @@ -2573,6 +2581,7 @@ impl Config { |
| 2573 | 2581 | extra_env: self.extra_env(source_root).clone(), |
| 2574 | 2582 | target_dir_config: self.target_dir_from_config(source_root), |
| 2575 | 2583 | set_test: true, |
| 2584 | config_path: self.cargo_config_path(source_root), | |
| 2576 | 2585 | } |
| 2577 | 2586 | } |
| 2578 | 2587 | |
| ... | ... | @@ -2629,6 +2638,7 @@ impl Config { |
| 2629 | 2638 | extra_args: self.check_extra_args(source_root), |
| 2630 | 2639 | extra_test_bin_args: self.runnables_extraTestBinaryArgs(source_root).clone(), |
| 2631 | 2640 | extra_env: self.check_extra_env(source_root), |
| 2641 | config_path: self.cargo_config_path(source_root), | |
| 2632 | 2642 | target_dir_config: self.target_dir_from_config(source_root), |
| 2633 | 2643 | set_test: *self.cfg_setTest(source_root), |
| 2634 | 2644 | }, |
| ... | ... | @@ -2637,6 +2647,10 @@ impl Config { |
| 2637 | 2647 | } |
| 2638 | 2648 | } |
| 2639 | 2649 | |
| 2650 | fn cargo_config_path(&self, source_root: Option<SourceRootId>) -> Option<AbsPathBuf> { | |
| 2651 | self.cargo_configPath(source_root).as_ref().map(|path| self.root_path.join(path)) | |
| 2652 | } | |
| 2653 | ||
| 2640 | 2654 | fn target_dir_from_config(&self, source_root: Option<SourceRootId>) -> TargetDirectoryConfig { |
| 2641 | 2655 | match &self.cargo_targetDir(source_root) { |
| 2642 | 2656 | Some(TargetDirectory::UseSubdirectory(true)) => TargetDirectoryConfig::UseSubdirectory, |
| ... | ... | @@ -2657,6 +2671,7 @@ impl Config { |
| 2657 | 2671 | RunnablesConfig { |
| 2658 | 2672 | override_cargo: self.runnables_command(source_root).clone(), |
| 2659 | 2673 | cargo_extra_args: self.runnables_extraArgs(source_root).clone(), |
| 2674 | config_path: self.cargo_config_path(source_root), | |
| 2660 | 2675 | extra_test_binary_args: self.runnables_extraTestBinaryArgs(source_root).clone(), |
| 2661 | 2676 | test_command: self.runnables_test_command(source_root).clone(), |
| 2662 | 2677 | test_override_command: self.runnables_test_overrideCommand(source_root).clone(), |
| ... | ... | @@ -3501,8 +3516,8 @@ impl FullConfigInput { |
| 3501 | 3516 | fields.sort_by_key(|&(x, ..)| x); |
| 3502 | 3517 | fields |
| 3503 | 3518 | .iter() |
| 3504 | .tuple_windows() | |
| 3505 | .for_each(|(a, b)| assert!(a.0 != b.0, "{a:?} duplicate field")); | |
| 3519 | .array_windows() | |
| 3520 | .for_each(|[a, b]| assert!(a.0 != b.0, "{a:?} duplicate field")); | |
| 3506 | 3521 | fields |
| 3507 | 3522 | } |
| 3508 | 3523 | |
| ... | ... | @@ -4146,7 +4161,8 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json |
| 4146 | 4161 | "enumDescriptions": [ |
| 4147 | 4162 | "Do not show this item or its methods (if it is a trait) in auto-import completions.", |
| 4148 | 4163 | "Do not show this trait's methods in auto-import completions.", |
| 4149 | "Do not show this module's all items in it in auto-import completions." | |
| 4164 | "Do not show this module's all items in it in auto-import completions.", | |
| 4165 | "Do not show this enum's variants in auto-import completions." | |
| 4150 | 4166 | ], |
| 4151 | 4167 | }, |
| 4152 | 4168 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs+3-3| ... | ... | @@ -357,14 +357,14 @@ pub(crate) fn convert_diagnostic( |
| 357 | 357 | lsp_types::Diagnostic { |
| 358 | 358 | range: lsp::to_proto::range(line_index, d.range.range), |
| 359 | 359 | severity: Some(lsp::to_proto::diagnostic_severity(d.severity)), |
| 360 | code: Some(lsp_types::NumberOrString::String(d.code.as_str().to_owned())), | |
| 360 | code: Some(lsp_types::Code::String(d.code.as_str().to_owned())), | |
| 361 | 361 | code_description: Some(lsp_types::CodeDescription { |
| 362 | href: lsp_types::Url::parse(&d.code.url()).unwrap(), | |
| 362 | href: lsp_types::Uri::parse(&d.code.url()).unwrap(), | |
| 363 | 363 | }), |
| 364 | 364 | source: Some("rust-analyzer".to_owned()), |
| 365 | 365 | message: d.message, |
| 366 | 366 | related_information: None, |
| 367 | tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::UNNECESSARY]), | |
| 367 | tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::Unnecessary]), | |
| 368 | 368 | data: None, |
| 369 | 369 | } |
| 370 | 370 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs+21-21| ... | ... | @@ -22,8 +22,8 @@ fn diagnostic_severity( |
| 22 | 22 | code: Option<&crate::flycheck::DiagnosticCode>, |
| 23 | 23 | ) -> Option<lsp_types::DiagnosticSeverity> { |
| 24 | 24 | let res = match level { |
| 25 | DiagnosticLevel::Ice => lsp_types::DiagnosticSeverity::ERROR, | |
| 26 | DiagnosticLevel::Error => lsp_types::DiagnosticSeverity::ERROR, | |
| 25 | DiagnosticLevel::Ice => lsp_types::DiagnosticSeverity::Error, | |
| 26 | DiagnosticLevel::Error => lsp_types::DiagnosticSeverity::Error, | |
| 27 | 27 | DiagnosticLevel::Warning => match code { |
| 28 | 28 | // HACK: special case for `warnings` rustc lint. |
| 29 | 29 | Some(code) |
| ... | ... | @@ -31,7 +31,7 @@ fn diagnostic_severity( |
| 31 | 31 | lint == "warnings" || ide_db::helpers::lint_eq_or_in_group(&code.code, lint) |
| 32 | 32 | }) => |
| 33 | 33 | { |
| 34 | lsp_types::DiagnosticSeverity::HINT | |
| 34 | lsp_types::DiagnosticSeverity::Hint | |
| 35 | 35 | } |
| 36 | 36 | // HACK: special case for `warnings` rustc lint. |
| 37 | 37 | Some(code) |
| ... | ... | @@ -39,12 +39,12 @@ fn diagnostic_severity( |
| 39 | 39 | lint == "warnings" || ide_db::helpers::lint_eq_or_in_group(&code.code, lint) |
| 40 | 40 | }) => |
| 41 | 41 | { |
| 42 | lsp_types::DiagnosticSeverity::INFORMATION | |
| 42 | lsp_types::DiagnosticSeverity::Information | |
| 43 | 43 | } |
| 44 | _ => lsp_types::DiagnosticSeverity::WARNING, | |
| 44 | _ => lsp_types::DiagnosticSeverity::Warning, | |
| 45 | 45 | }, |
| 46 | DiagnosticLevel::Note => lsp_types::DiagnosticSeverity::INFORMATION, | |
| 47 | DiagnosticLevel::Help => lsp_types::DiagnosticSeverity::HINT, | |
| 46 | DiagnosticLevel::Note => lsp_types::DiagnosticSeverity::Information, | |
| 47 | DiagnosticLevel::Help => lsp_types::DiagnosticSeverity::Hint, | |
| 48 | 48 | _ => return None, |
| 49 | 49 | }; |
| 50 | 50 | Some(res) |
| ... | ... | @@ -192,7 +192,7 @@ fn map_rust_child_diagnostic( |
| 192 | 192 | return MappedRustChildDiagnostic::MessageLine(rd.message.clone()); |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | let mut edit_map: FxHashMap<lsp_types::Url, Vec<lsp_types::TextEdit>> = FxHashMap::default(); | |
| 195 | let mut edit_map: FxHashMap<lsp_types::Uri, Vec<lsp_types::TextEdit>> = FxHashMap::default(); | |
| 196 | 196 | let mut suggested_replacements = Vec::new(); |
| 197 | 197 | let mut is_preferred = true; |
| 198 | 198 | for &span in &spans { |
| ... | ... | @@ -239,7 +239,7 @@ fn map_rust_child_diagnostic( |
| 239 | 239 | action: lsp_ext::CodeAction { |
| 240 | 240 | title: message.clone(), |
| 241 | 241 | group: None, |
| 242 | kind: Some(lsp_types::CodeActionKind::QUICKFIX), | |
| 242 | kind: Some(lsp_types::CodeActionKind::QuickFix), | |
| 243 | 243 | edit: Some(lsp_ext::SnippetWorkspaceEdit { |
| 244 | 244 | // FIXME: there's no good reason to use edit_map here.... |
| 245 | 245 | changes: Some(edit_map), |
| ... | ... | @@ -263,7 +263,7 @@ fn map_rust_child_diagnostic( |
| 263 | 263 | |
| 264 | 264 | #[derive(Debug)] |
| 265 | 265 | pub(crate) struct MappedRustDiagnostic { |
| 266 | pub(crate) url: lsp_types::Url, | |
| 266 | pub(crate) url: lsp_types::Uri, | |
| 267 | 267 | pub(crate) diagnostic: lsp_types::Diagnostic, |
| 268 | 268 | pub(crate) fix: Option<Box<Fix>>, |
| 269 | 269 | } |
| ... | ... | @@ -351,10 +351,10 @@ pub(crate) fn map_rust_diagnostic_to_lsp( |
| 351 | 351 | match &*code.code { |
| 352 | 352 | "dead_code" | "unknown_lints" | "unreachable_code" | "unused_attributes" |
| 353 | 353 | | "unused_imports" | "unused_macros" | "unused_variables" => { |
| 354 | tag = Some(lsp_types::DiagnosticTag::UNNECESSARY); | |
| 354 | tag = Some(lsp_types::DiagnosticTag::Unnecessary); | |
| 355 | 355 | } |
| 356 | 356 | "deprecated" => { |
| 357 | tag = Some(lsp_types::DiagnosticTag::DEPRECATED); | |
| 357 | tag = Some(lsp_types::DiagnosticTag::Deprecated); | |
| 358 | 358 | } |
| 359 | 359 | _ => {} |
| 360 | 360 | } |
| ... | ... | @@ -418,13 +418,13 @@ pub(crate) fn map_rust_diagnostic_to_lsp( |
| 418 | 418 | let diagnostic = lsp_types::Diagnostic { |
| 419 | 419 | range: secondary_location.range, |
| 420 | 420 | // downgrade to hint if we're pointing at the macro |
| 421 | severity: Some(lsp_types::DiagnosticSeverity::HINT), | |
| 422 | code: code.map(ToOwned::to_owned).map(lsp_types::NumberOrString::String), | |
| 421 | severity: Some(lsp_types::DiagnosticSeverity::Hint), | |
| 422 | code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), | |
| 423 | 423 | code_description: code_description.clone(), |
| 424 | 424 | source: Some(source.to_owned()), |
| 425 | 425 | message: message.clone(), |
| 426 | 426 | related_information: Some(information_for_additional_diagnostic), |
| 427 | tags: tag.clone().map(|tag| vec![tag]), | |
| 427 | tags: tag.map(|tag| vec![tag]), | |
| 428 | 428 | data: Some(serde_json::json!({ "rendered": rendered })), |
| 429 | 429 | }; |
| 430 | 430 | diagnostics.push(MappedRustDiagnostic { |
| ... | ... | @@ -440,7 +440,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( |
| 440 | 440 | diagnostic: lsp_types::Diagnostic { |
| 441 | 441 | range: primary_location.range, |
| 442 | 442 | severity, |
| 443 | code: code.map(ToOwned::to_owned).map(lsp_types::NumberOrString::String), | |
| 443 | code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), | |
| 444 | 444 | code_description: code_description.clone(), |
| 445 | 445 | source: Some(source.to_owned()), |
| 446 | 446 | message, |
| ... | ... | @@ -452,7 +452,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( |
| 452 | 452 | .collect::<Vec<_>>(); |
| 453 | 453 | if info.is_empty() { None } else { Some(info) } |
| 454 | 454 | }, |
| 455 | tags: tag.clone().map(|tag| vec![tag]), | |
| 455 | tags: tag.map(|tag| vec![tag]), | |
| 456 | 456 | data: Some(serde_json::json!({ "rendered": rendered })), |
| 457 | 457 | }, |
| 458 | 458 | fix: None, |
| ... | ... | @@ -471,8 +471,8 @@ pub(crate) fn map_rust_diagnostic_to_lsp( |
| 471 | 471 | fix: sub.suggested_fix.clone(), |
| 472 | 472 | diagnostic: lsp_types::Diagnostic { |
| 473 | 473 | range: sub.related.location.range, |
| 474 | severity: Some(lsp_types::DiagnosticSeverity::HINT), | |
| 475 | code: code.map(ToOwned::to_owned).map(lsp_types::NumberOrString::String), | |
| 474 | severity: Some(lsp_types::DiagnosticSeverity::Hint), | |
| 475 | code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), | |
| 476 | 476 | code_description: code_description.clone(), |
| 477 | 477 | source: Some(source.to_owned()), |
| 478 | 478 | message: sub.related.message.clone(), |
| ... | ... | @@ -494,7 +494,7 @@ fn rustc_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescripti |
| 494 | 494 | && chars.next().is_none() |
| 495 | 495 | }) |
| 496 | 496 | .and_then(|code| { |
| 497 | lsp_types::Url::parse(&format!("https://doc.rust-lang.org/error-index.html#{code}")) | |
| 497 | lsp_types::Uri::parse(&format!("https://doc.rust-lang.org/error-index.html#{code}")) | |
| 498 | 498 | .ok() |
| 499 | 499 | .map(|href| lsp_types::CodeDescription { href }) |
| 500 | 500 | }) |
| ... | ... | @@ -502,7 +502,7 @@ fn rustc_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescripti |
| 502 | 502 | |
| 503 | 503 | fn clippy_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescription> { |
| 504 | 504 | code.and_then(|code| { |
| 505 | lsp_types::Url::parse(&format!( | |
| 505 | lsp_types::Uri::parse(&format!( | |
| 506 | 506 | "https://rust-lang.github.io/rust-clippy/master/index.html#{code}" |
| 507 | 507 | )) |
| 508 | 508 | .ok() |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt+3-3| ... | ... | @@ -55,6 +55,7 @@ |
| 55 | 55 | "clippy", |
| 56 | 56 | ), |
| 57 | 57 | message: "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref", |
| 58 | tags: None, | |
| 58 | 59 | related_information: Some( |
| 59 | 60 | [ |
| 60 | 61 | DiagnosticRelatedInformation { |
| ... | ... | @@ -111,7 +112,6 @@ |
| 111 | 112 | }, |
| 112 | 113 | ], |
| 113 | 114 | ), |
| 114 | tags: None, | |
| 115 | 115 | data: None, |
| 116 | 116 | }, |
| 117 | 117 | fix: None, |
| ... | ... | @@ -172,6 +172,7 @@ |
| 172 | 172 | "clippy", |
| 173 | 173 | ), |
| 174 | 174 | message: "lint level defined here", |
| 175 | tags: None, | |
| 175 | 176 | related_information: Some( |
| 176 | 177 | [ |
| 177 | 178 | DiagnosticRelatedInformation { |
| ... | ... | @@ -202,7 +203,6 @@ |
| 202 | 203 | }, |
| 203 | 204 | ], |
| 204 | 205 | ), |
| 205 | tags: None, | |
| 206 | 206 | data: None, |
| 207 | 207 | }, |
| 208 | 208 | fix: None, |
| ... | ... | @@ -263,6 +263,7 @@ |
| 263 | 263 | "clippy", |
| 264 | 264 | ), |
| 265 | 265 | message: "consider passing by value instead: `self`", |
| 266 | tags: None, | |
| 266 | 267 | related_information: Some( |
| 267 | 268 | [ |
| 268 | 269 | DiagnosticRelatedInformation { |
| ... | ... | @@ -293,7 +294,6 @@ |
| 293 | 294 | }, |
| 294 | 295 | ], |
| 295 | 296 | ), |
| 296 | tags: None, | |
| 297 | 297 | data: None, |
| 298 | 298 | }, |
| 299 | 299 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt+1-1| ... | ... | @@ -55,8 +55,8 @@ |
| 55 | 55 | "rustc", |
| 56 | 56 | ), |
| 57 | 57 | message: "can't compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", |
| 58 | related_information: None, | |
| 59 | 58 | tags: None, |
| 59 | related_information: None, | |
| 60 | 60 | data: None, |
| 61 | 61 | }, |
| 62 | 62 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt+3-3| ... | ... | @@ -31,6 +31,7 @@ |
| 31 | 31 | "rustc", |
| 32 | 32 | ), |
| 33 | 33 | message: "Please register your known path in the path module", |
| 34 | tags: None, | |
| 34 | 35 | related_information: Some( |
| 35 | 36 | [ |
| 36 | 37 | DiagnosticRelatedInformation { |
| ... | ... | @@ -61,7 +62,6 @@ |
| 61 | 62 | }, |
| 62 | 63 | ], |
| 63 | 64 | ), |
| 64 | tags: None, | |
| 65 | 65 | data: None, |
| 66 | 66 | }, |
| 67 | 67 | fix: None, |
| ... | ... | @@ -98,6 +98,7 @@ |
| 98 | 98 | "rustc", |
| 99 | 99 | ), |
| 100 | 100 | message: "Please register your known path in the path module", |
| 101 | tags: None, | |
| 101 | 102 | related_information: Some( |
| 102 | 103 | [ |
| 103 | 104 | DiagnosticRelatedInformation { |
| ... | ... | @@ -128,7 +129,6 @@ |
| 128 | 129 | }, |
| 129 | 130 | ], |
| 130 | 131 | ), |
| 131 | tags: None, | |
| 132 | 132 | data: None, |
| 133 | 133 | }, |
| 134 | 134 | fix: None, |
| ... | ... | @@ -165,6 +165,7 @@ |
| 165 | 165 | "rustc", |
| 166 | 166 | ), |
| 167 | 167 | message: "Please register your known path in the path module", |
| 168 | tags: None, | |
| 168 | 169 | related_information: Some( |
| 169 | 170 | [ |
| 170 | 171 | DiagnosticRelatedInformation { |
| ... | ... | @@ -221,7 +222,6 @@ |
| 221 | 222 | }, |
| 222 | 223 | ], |
| 223 | 224 | ), |
| 224 | tags: None, | |
| 225 | 225 | data: None, |
| 226 | 226 | }, |
| 227 | 227 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt+1-1| ... | ... | @@ -55,8 +55,8 @@ |
| 55 | 55 | "rustc", |
| 56 | 56 | ), |
| 57 | 57 | message: "`main` function not found in crate `current`\nconsider adding a `main` function to `src/bin/current.rs`", |
| 58 | related_information: None, | |
| 59 | 58 | tags: None, |
| 59 | related_information: None, | |
| 60 | 60 | data: None, |
| 61 | 61 | }, |
| 62 | 62 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt+1-1| ... | ... | @@ -55,8 +55,8 @@ |
| 55 | 55 | "rustc", |
| 56 | 56 | ), |
| 57 | 57 | message: "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`", |
| 58 | related_information: None, | |
| 59 | 58 | tags: None, |
| 59 | related_information: None, | |
| 60 | 60 | data: None, |
| 61 | 61 | }, |
| 62 | 62 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt+1-1| ... | ... | @@ -55,8 +55,8 @@ |
| 55 | 55 | "rustc", |
| 56 | 56 | ), |
| 57 | 57 | message: "mismatched types\nexpected usize, found u32", |
| 58 | related_information: None, | |
| 59 | 58 | tags: None, |
| 59 | related_information: None, | |
| 60 | 60 | data: None, |
| 61 | 61 | }, |
| 62 | 62 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt+2-2| ... | ... | @@ -55,6 +55,7 @@ |
| 55 | 55 | "rustc", |
| 56 | 56 | ), |
| 57 | 57 | message: "mismatched types\nexpected `u32`, found `&str`", |
| 58 | tags: None, | |
| 58 | 59 | related_information: Some( |
| 59 | 60 | [ |
| 60 | 61 | DiagnosticRelatedInformation { |
| ... | ... | @@ -85,7 +86,6 @@ |
| 85 | 86 | }, |
| 86 | 87 | ], |
| 87 | 88 | ), |
| 88 | tags: None, | |
| 89 | 89 | data: None, |
| 90 | 90 | }, |
| 91 | 91 | fix: None, |
| ... | ... | @@ -146,6 +146,7 @@ |
| 146 | 146 | "rustc", |
| 147 | 147 | ), |
| 148 | 148 | message: "expected due to this", |
| 149 | tags: None, | |
| 149 | 150 | related_information: Some( |
| 150 | 151 | [ |
| 151 | 152 | DiagnosticRelatedInformation { |
| ... | ... | @@ -176,7 +177,6 @@ |
| 176 | 177 | }, |
| 177 | 178 | ], |
| 178 | 179 | ), |
| 179 | tags: None, | |
| 180 | 180 | data: None, |
| 181 | 181 | }, |
| 182 | 182 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt+7-9| ... | ... | @@ -35,6 +35,11 @@ |
| 35 | 35 | "rustc", |
| 36 | 36 | ), |
| 37 | 37 | message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", |
| 38 | tags: Some( | |
| 39 | [ | |
| 40 | Unnecessary, | |
| 41 | ], | |
| 42 | ), | |
| 38 | 43 | related_information: Some( |
| 39 | 44 | [ |
| 40 | 45 | DiagnosticRelatedInformation { |
| ... | ... | @@ -65,11 +70,6 @@ |
| 65 | 70 | }, |
| 66 | 71 | ], |
| 67 | 72 | ), |
| 68 | tags: Some( | |
| 69 | [ | |
| 70 | Unnecessary, | |
| 71 | ], | |
| 72 | ), | |
| 73 | 73 | data: None, |
| 74 | 74 | }, |
| 75 | 75 | fix: None, |
| ... | ... | @@ -110,6 +110,7 @@ |
| 110 | 110 | "rustc", |
| 111 | 111 | ), |
| 112 | 112 | message: "consider prefixing with an underscore: `_foo`", |
| 113 | tags: None, | |
| 113 | 114 | related_information: Some( |
| 114 | 115 | [ |
| 115 | 116 | DiagnosticRelatedInformation { |
| ... | ... | @@ -140,7 +141,6 @@ |
| 140 | 141 | }, |
| 141 | 142 | ], |
| 142 | 143 | ), |
| 143 | tags: None, | |
| 144 | 144 | data: None, |
| 145 | 145 | }, |
| 146 | 146 | fix: Some( |
| ... | ... | @@ -161,9 +161,7 @@ |
| 161 | 161 | title: "consider prefixing with an underscore: `_foo`", |
| 162 | 162 | group: None, |
| 163 | 163 | kind: Some( |
| 164 | CodeActionKind( | |
| 165 | "quickfix", | |
| 166 | ), | |
| 164 | QuickFix, | |
| 167 | 165 | ), |
| 168 | 166 | command: None, |
| 169 | 167 | edit: Some( |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt+7-9| ... | ... | @@ -35,6 +35,11 @@ |
| 35 | 35 | "rustc", |
| 36 | 36 | ), |
| 37 | 37 | message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", |
| 38 | tags: Some( | |
| 39 | [ | |
| 40 | Unnecessary, | |
| 41 | ], | |
| 42 | ), | |
| 38 | 43 | related_information: Some( |
| 39 | 44 | [ |
| 40 | 45 | DiagnosticRelatedInformation { |
| ... | ... | @@ -65,11 +70,6 @@ |
| 65 | 70 | }, |
| 66 | 71 | ], |
| 67 | 72 | ), |
| 68 | tags: Some( | |
| 69 | [ | |
| 70 | Unnecessary, | |
| 71 | ], | |
| 72 | ), | |
| 73 | 73 | data: None, |
| 74 | 74 | }, |
| 75 | 75 | fix: None, |
| ... | ... | @@ -110,6 +110,7 @@ |
| 110 | 110 | "rustc", |
| 111 | 111 | ), |
| 112 | 112 | message: "consider prefixing with an underscore: `_foo`", |
| 113 | tags: None, | |
| 113 | 114 | related_information: Some( |
| 114 | 115 | [ |
| 115 | 116 | DiagnosticRelatedInformation { |
| ... | ... | @@ -140,7 +141,6 @@ |
| 140 | 141 | }, |
| 141 | 142 | ], |
| 142 | 143 | ), |
| 143 | tags: None, | |
| 144 | 144 | data: None, |
| 145 | 145 | }, |
| 146 | 146 | fix: Some( |
| ... | ... | @@ -161,9 +161,7 @@ |
| 161 | 161 | title: "consider prefixing with an underscore: `_foo`", |
| 162 | 162 | group: None, |
| 163 | 163 | kind: Some( |
| 164 | CodeActionKind( | |
| 165 | "quickfix", | |
| 166 | ), | |
| 164 | QuickFix, | |
| 167 | 165 | ), |
| 168 | 166 | command: None, |
| 169 | 167 | edit: Some( |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt+7-9| ... | ... | @@ -35,6 +35,11 @@ |
| 35 | 35 | "rustc", |
| 36 | 36 | ), |
| 37 | 37 | message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", |
| 38 | tags: Some( | |
| 39 | [ | |
| 40 | Unnecessary, | |
| 41 | ], | |
| 42 | ), | |
| 38 | 43 | related_information: Some( |
| 39 | 44 | [ |
| 40 | 45 | DiagnosticRelatedInformation { |
| ... | ... | @@ -65,11 +70,6 @@ |
| 65 | 70 | }, |
| 66 | 71 | ], |
| 67 | 72 | ), |
| 68 | tags: Some( | |
| 69 | [ | |
| 70 | Unnecessary, | |
| 71 | ], | |
| 72 | ), | |
| 73 | 73 | data: None, |
| 74 | 74 | }, |
| 75 | 75 | fix: None, |
| ... | ... | @@ -110,6 +110,7 @@ |
| 110 | 110 | "rustc", |
| 111 | 111 | ), |
| 112 | 112 | message: "consider prefixing with an underscore: `_foo`", |
| 113 | tags: None, | |
| 113 | 114 | related_information: Some( |
| 114 | 115 | [ |
| 115 | 116 | DiagnosticRelatedInformation { |
| ... | ... | @@ -140,7 +141,6 @@ |
| 140 | 141 | }, |
| 141 | 142 | ], |
| 142 | 143 | ), |
| 143 | tags: None, | |
| 144 | 144 | data: None, |
| 145 | 145 | }, |
| 146 | 146 | fix: Some( |
| ... | ... | @@ -161,9 +161,7 @@ |
| 161 | 161 | title: "consider prefixing with an underscore: `_foo`", |
| 162 | 162 | group: None, |
| 163 | 163 | kind: Some( |
| 164 | CodeActionKind( | |
| 165 | "quickfix", | |
| 166 | ), | |
| 164 | QuickFix, | |
| 167 | 165 | ), |
| 168 | 166 | command: None, |
| 169 | 167 | edit: Some( |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt+2-2| ... | ... | @@ -55,6 +55,7 @@ |
| 55 | 55 | "rustc", |
| 56 | 56 | ), |
| 57 | 57 | message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters", |
| 58 | tags: None, | |
| 58 | 59 | related_information: Some( |
| 59 | 60 | [ |
| 60 | 61 | DiagnosticRelatedInformation { |
| ... | ... | @@ -85,7 +86,6 @@ |
| 85 | 86 | }, |
| 86 | 87 | ], |
| 87 | 88 | ), |
| 88 | tags: None, | |
| 89 | 89 | data: None, |
| 90 | 90 | }, |
| 91 | 91 | fix: None, |
| ... | ... | @@ -146,6 +146,7 @@ |
| 146 | 146 | "rustc", |
| 147 | 147 | ), |
| 148 | 148 | message: "defined here", |
| 149 | tags: None, | |
| 149 | 150 | related_information: Some( |
| 150 | 151 | [ |
| 151 | 152 | DiagnosticRelatedInformation { |
| ... | ... | @@ -176,7 +177,6 @@ |
| 176 | 177 | }, |
| 177 | 178 | ], |
| 178 | 179 | ), |
| 179 | tags: None, | |
| 180 | 180 | data: None, |
| 181 | 181 | }, |
| 182 | 182 | fix: None, |
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt+4-6| ... | ... | @@ -55,6 +55,7 @@ |
| 55 | 55 | "clippy", |
| 56 | 56 | ), |
| 57 | 57 | message: "returning the result of a let binding from a block\n`#[warn(clippy::let_and_return)]` on by default\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return", |
| 58 | tags: None, | |
| 58 | 59 | related_information: Some( |
| 59 | 60 | [ |
| 60 | 61 | DiagnosticRelatedInformation { |
| ... | ... | @@ -111,7 +112,6 @@ |
| 111 | 112 | }, |
| 112 | 113 | ], |
| 113 | 114 | ), |
| 114 | tags: None, | |
| 115 | 115 | data: None, |
| 116 | 116 | }, |
| 117 | 117 | fix: None, |
| ... | ... | @@ -172,6 +172,7 @@ |
| 172 | 172 | "clippy", |
| 173 | 173 | ), |
| 174 | 174 | message: "unnecessary let binding", |
| 175 | tags: None, | |
| 175 | 176 | related_information: Some( |
| 176 | 177 | [ |
| 177 | 178 | DiagnosticRelatedInformation { |
| ... | ... | @@ -202,7 +203,6 @@ |
| 202 | 203 | }, |
| 203 | 204 | ], |
| 204 | 205 | ), |
| 205 | tags: None, | |
| 206 | 206 | data: None, |
| 207 | 207 | }, |
| 208 | 208 | fix: None, |
| ... | ... | @@ -263,6 +263,7 @@ |
| 263 | 263 | "clippy", |
| 264 | 264 | ), |
| 265 | 265 | message: "return the expression directly: `(0..10).collect()`", |
| 266 | tags: None, | |
| 266 | 267 | related_information: Some( |
| 267 | 268 | [ |
| 268 | 269 | DiagnosticRelatedInformation { |
| ... | ... | @@ -293,7 +294,6 @@ |
| 293 | 294 | }, |
| 294 | 295 | ], |
| 295 | 296 | ), |
| 296 | tags: None, | |
| 297 | 297 | data: None, |
| 298 | 298 | }, |
| 299 | 299 | fix: Some( |
| ... | ... | @@ -324,9 +324,7 @@ |
| 324 | 324 | title: "return the expression directly: `(0..10).collect()`", |
| 325 | 325 | group: None, |
| 326 | 326 | kind: Some( |
| 327 | CodeActionKind( | |
| 328 | "quickfix", | |
| 329 | ), | |
| 327 | QuickFix, | |
| 330 | 328 | ), |
| 331 | 329 | command: None, |
| 332 | 330 | edit: Some( |
src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs+5| ... | ... | @@ -51,6 +51,7 @@ pub(crate) struct CargoOptions { |
| 51 | 51 | pub(crate) extra_args: Vec<String>, |
| 52 | 52 | pub(crate) extra_test_bin_args: Vec<String>, |
| 53 | 53 | pub(crate) extra_env: FxHashMap<String, Option<String>>, |
| 54 | pub(crate) config_path: Option<AbsPathBuf>, | |
| 54 | 55 | pub(crate) target_dir_config: TargetDirectoryConfig, |
| 55 | 56 | } |
| 56 | 57 | |
| ... | ... | @@ -108,6 +109,9 @@ impl CargoOptions { |
| 108 | 109 | cmd.arg(features); |
| 109 | 110 | } |
| 110 | 111 | } |
| 112 | if let Some(config_path) = &self.config_path { | |
| 113 | cmd.arg("--config").arg(config_path); | |
| 114 | } | |
| 111 | 115 | if let Some(target_dir) = self.target_dir_config.target_dir(ws_target_dir) { |
| 112 | 116 | cmd.arg("--target-dir").arg(target_dir.as_ref()); |
| 113 | 117 | } |
| ... | ... | @@ -1169,6 +1173,7 @@ mod tests { |
| 1169 | 1173 | extra_args: vec![], |
| 1170 | 1174 | extra_test_bin_args: vec![], |
| 1171 | 1175 | extra_env: FxHashMap::default(), |
| 1176 | config_path: None, | |
| 1172 | 1177 | target_dir_config: TargetDirectoryConfig::default(), |
| 1173 | 1178 | }, |
| 1174 | 1179 | ansi_color_output: true, |
src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs+15-18| ... | ... | @@ -18,7 +18,7 @@ use ide_db::{ |
| 18 | 18 | }; |
| 19 | 19 | use itertools::Itertools; |
| 20 | 20 | use load_cargo::SourceRootConfig; |
| 21 | use lsp_types::{SemanticTokens, Url}; | |
| 21 | use lsp_types::{Notification, SemanticTokens, Uri}; | |
| 22 | 22 | use parking_lot::{ |
| 23 | 23 | MappedRwLockReadGuard, Mutex, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard, |
| 24 | 24 | RwLockWriteGuard, |
| ... | ... | @@ -97,7 +97,7 @@ pub(crate) struct GlobalState { |
| 97 | 97 | pub(crate) source_root_config: SourceRootConfig, |
| 98 | 98 | /// A mapping that maps a local source root's `SourceRootId` to it parent's `SourceRootId`, if it has one. |
| 99 | 99 | pub(crate) local_roots_parent_map: Arc<FxHashMap<SourceRootId, SourceRootId>>, |
| 100 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, | |
| 100 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Uri, SemanticTokens>>>, | |
| 101 | 101 | |
| 102 | 102 | // status |
| 103 | 103 | pub(crate) shutdown_requested: bool, |
| ... | ... | @@ -209,7 +209,7 @@ pub(crate) struct GlobalStateSnapshot { |
| 209 | 209 | pub(crate) analysis: Analysis, |
| 210 | 210 | pub(crate) check_fixes: CheckFixes, |
| 211 | 211 | mem_docs: MemDocs, |
| 212 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, | |
| 212 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Uri, SemanticTokens>>>, | |
| 213 | 213 | vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
| 214 | 214 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, |
| 215 | 215 | // used to signal semantic highlighting to fall back to syntax based highlighting until |
| ... | ... | @@ -580,12 +580,12 @@ impl GlobalState { |
| 580 | 580 | } |
| 581 | 581 | } |
| 582 | 582 | |
| 583 | pub(crate) fn send_request<R: lsp_types::request::Request>( | |
| 583 | pub(crate) fn send_request<R: lsp_types::Request>( | |
| 584 | 584 | &mut self, |
| 585 | 585 | params: R::Params, |
| 586 | 586 | handler: ReqHandler, |
| 587 | 587 | ) { |
| 588 | let request = self.req_queue.outgoing.register(R::METHOD.to_owned(), params, handler); | |
| 588 | let request = self.req_queue.outgoing.register(R::METHOD.into(), params, handler); | |
| 589 | 589 | self.send(request.into()); |
| 590 | 590 | } |
| 591 | 591 | |
| ... | ... | @@ -598,11 +598,8 @@ impl GlobalState { |
| 598 | 598 | handler(self, response) |
| 599 | 599 | } |
| 600 | 600 | |
| 601 | pub(crate) fn send_notification<N: lsp_types::notification::Notification>( | |
| 602 | &self, | |
| 603 | params: N::Params, | |
| 604 | ) { | |
| 605 | let not = lsp_server::Notification::new(N::METHOD.to_owned(), params); | |
| 601 | pub(crate) fn send_notification<N: lsp_types::Notification>(&self, params: N::Params) { | |
| 602 | let not = lsp_server::Notification::new(N::METHOD.into(), params); | |
| 606 | 603 | self.send(not.into()); |
| 607 | 604 | } |
| 608 | 605 | |
| ... | ... | @@ -647,7 +644,7 @@ impl GlobalState { |
| 647 | 644 | |
| 648 | 645 | pub(crate) fn publish_diagnostics( |
| 649 | 646 | &mut self, |
| 650 | uri: Url, | |
| 647 | uri: Uri, | |
| 651 | 648 | version: Option<i32>, |
| 652 | 649 | mut diagnostics: Vec<lsp_types::Diagnostic>, |
| 653 | 650 | ) { |
| ... | ... | @@ -680,7 +677,7 @@ impl GlobalState { |
| 680 | 677 | } |
| 681 | 678 | |
| 682 | 679 | let not = lsp_server::Notification::new( |
| 683 | <lsp_types::notification::PublishDiagnostics as lsp_types::notification::Notification>::METHOD.to_owned(), | |
| 680 | lsp_types::PublishDiagnosticsNotification::METHOD.into(), | |
| 684 | 681 | lsp_types::PublishDiagnosticsParams { uri, diagnostics, version }, |
| 685 | 682 | ); |
| 686 | 683 | _ = sender.send(not.into()); |
| ... | ... | @@ -744,11 +741,11 @@ impl GlobalStateSnapshot { |
| 744 | 741 | } |
| 745 | 742 | |
| 746 | 743 | /// Returns `None` if the file was excluded. |
| 747 | pub(crate) fn url_to_file_id(&self, url: &Url) -> anyhow::Result<Option<FileId>> { | |
| 744 | pub(crate) fn url_to_file_id(&self, url: &Uri) -> anyhow::Result<Option<FileId>> { | |
| 748 | 745 | url_to_file_id(&self.vfs_read(), url) |
| 749 | 746 | } |
| 750 | 747 | |
| 751 | pub(crate) fn file_id_to_url(&self, id: FileId) -> Url { | |
| 748 | pub(crate) fn file_id_to_url(&self, id: FileId) -> Uri { | |
| 752 | 749 | file_id_to_url(&self.vfs_read(), id) |
| 753 | 750 | } |
| 754 | 751 | |
| ... | ... | @@ -768,12 +765,12 @@ impl GlobalStateSnapshot { |
| 768 | 765 | Some(self.mem_docs.get(self.vfs_read().file_path(file_id))?.version) |
| 769 | 766 | } |
| 770 | 767 | |
| 771 | pub(crate) fn url_file_version(&self, url: &Url) -> Option<i32> { | |
| 768 | pub(crate) fn url_file_version(&self, url: &Uri) -> Option<i32> { | |
| 772 | 769 | let path = from_proto::vfs_path(url).ok()?; |
| 773 | 770 | Some(self.mem_docs.get(&path)?.version) |
| 774 | 771 | } |
| 775 | 772 | |
| 776 | pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url { | |
| 773 | pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Uri { | |
| 777 | 774 | let mut base = self.vfs_read().file_path(path.anchor).clone(); |
| 778 | 775 | base.pop(); |
| 779 | 776 | let path = base.join(&path.path).unwrap(); |
| ... | ... | @@ -898,14 +895,14 @@ impl GlobalStateSnapshot { |
| 898 | 895 | } |
| 899 | 896 | } |
| 900 | 897 | |
| 901 | pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url { | |
| 898 | pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Uri { | |
| 902 | 899 | let path = vfs.file_path(id); |
| 903 | 900 | let path = path.as_path().unwrap(); |
| 904 | 901 | url_from_abs_path(path) |
| 905 | 902 | } |
| 906 | 903 | |
| 907 | 904 | /// Returns `None` if the file was excluded. |
| 908 | pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result<Option<FileId>> { | |
| 905 | pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Uri) -> anyhow::Result<Option<FileId>> { | |
| 909 | 906 | let path = from_proto::vfs_path(url)?; |
| 910 | 907 | vfs_path_to_file_id(vfs, &path) |
| 911 | 908 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs+18-18| ... | ... | @@ -47,7 +47,7 @@ impl RequestDispatcher<'_> { |
| 47 | 47 | f: fn(&mut GlobalState, R::Params) -> anyhow::Result<R::Result>, |
| 48 | 48 | ) -> &mut Self |
| 49 | 49 | where |
| 50 | R: lsp_types::request::Request, | |
| 50 | R: lsp_types::Request, | |
| 51 | 51 | R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug, |
| 52 | 52 | R::Result: Serialize, |
| 53 | 53 | { |
| ... | ... | @@ -75,7 +75,7 @@ impl RequestDispatcher<'_> { |
| 75 | 75 | f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>, |
| 76 | 76 | ) -> &mut Self |
| 77 | 77 | where |
| 78 | R: lsp_types::request::Request, | |
| 78 | R: lsp_types::Request, | |
| 79 | 79 | R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug, |
| 80 | 80 | R::Result: Serialize, |
| 81 | 81 | { |
| ... | ... | @@ -107,14 +107,14 @@ impl RequestDispatcher<'_> { |
| 107 | 107 | f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>, |
| 108 | 108 | ) -> &mut Self |
| 109 | 109 | where |
| 110 | R: lsp_types::request::Request< | |
| 110 | R: lsp_types::Request< | |
| 111 | 111 | Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, |
| 112 | 112 | Result: Serialize + Default, |
| 113 | 113 | > + 'static, |
| 114 | 114 | { |
| 115 | 115 | if !self.global_state.vfs_done { |
| 116 | 116 | if let Some(lsp_server::Request { id, .. }) = |
| 117 | self.req.take_if(|it| it.method == R::METHOD) | |
| 117 | self.req.take_if(|it| it.method.as_str() == R::METHOD.as_str()) | |
| 118 | 118 | { |
| 119 | 119 | self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default())); |
| 120 | 120 | } |
| ... | ... | @@ -136,14 +136,14 @@ impl RequestDispatcher<'_> { |
| 136 | 136 | on_cancelled: fn() -> ResponseError, |
| 137 | 137 | ) -> &mut Self |
| 138 | 138 | where |
| 139 | R: lsp_types::request::Request< | |
| 139 | R: lsp_types::Request< | |
| 140 | 140 | Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, |
| 141 | 141 | Result: Serialize, |
| 142 | 142 | > + 'static, |
| 143 | 143 | { |
| 144 | 144 | if !self.global_state.vfs_done || self.global_state.incomplete_crate_graph { |
| 145 | 145 | if let Some(lsp_server::Request { id, .. }) = |
| 146 | self.req.take_if(|it| it.method == R::METHOD) | |
| 146 | self.req.take_if(|it| it.method.as_str() == R::METHOD.as_str()) | |
| 147 | 147 | { |
| 148 | 148 | self.global_state.respond(lsp_server::Response::new_ok(id, default())); |
| 149 | 149 | } |
| ... | ... | @@ -159,7 +159,7 @@ impl RequestDispatcher<'_> { |
| 159 | 159 | f: fn(GlobalStateSnapshot, Params) -> anyhow::Result<R::Result>, |
| 160 | 160 | ) -> &mut Self |
| 161 | 161 | where |
| 162 | R: lsp_types::request::Request<Params = Params, Result = Params> + 'static, | |
| 162 | R: lsp_types::Request<Params = Params, Result = Params> + 'static, | |
| 163 | 163 | Params: Serialize + DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, |
| 164 | 164 | { |
| 165 | 165 | if !self.global_state.vfs_done { |
| ... | ... | @@ -182,14 +182,14 @@ impl RequestDispatcher<'_> { |
| 182 | 182 | f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>, |
| 183 | 183 | ) -> &mut Self |
| 184 | 184 | where |
| 185 | R: lsp_types::request::Request< | |
| 185 | R: lsp_types::Request< | |
| 186 | 186 | Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, |
| 187 | 187 | Result: Serialize + Default, |
| 188 | 188 | > + 'static, |
| 189 | 189 | { |
| 190 | 190 | if !self.global_state.vfs_done { |
| 191 | 191 | if let Some(lsp_server::Request { id, .. }) = |
| 192 | self.req.take_if(|it| it.method == R::METHOD) | |
| 192 | self.req.take_if(|it| it.method.as_str() == R::METHOD.as_str()) | |
| 193 | 193 | { |
| 194 | 194 | self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default())); |
| 195 | 195 | } |
| ... | ... | @@ -210,7 +210,7 @@ impl RequestDispatcher<'_> { |
| 210 | 210 | f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>, |
| 211 | 211 | ) -> &mut Self |
| 212 | 212 | where |
| 213 | R: lsp_types::request::Request + 'static, | |
| 213 | R: lsp_types::Request + 'static, | |
| 214 | 214 | R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, |
| 215 | 215 | R::Result: Serialize, |
| 216 | 216 | { |
| ... | ... | @@ -240,7 +240,7 @@ impl RequestDispatcher<'_> { |
| 240 | 240 | on_cancelled: fn() -> ResponseError, |
| 241 | 241 | ) -> &mut Self |
| 242 | 242 | where |
| 243 | R: lsp_types::request::Request + 'static, | |
| 243 | R: lsp_types::Request + 'static, | |
| 244 | 244 | R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, |
| 245 | 245 | R::Result: Serialize, |
| 246 | 246 | { |
| ... | ... | @@ -278,11 +278,11 @@ impl RequestDispatcher<'_> { |
| 278 | 278 | |
| 279 | 279 | fn parse<R>(&mut self) -> Option<(lsp_server::Request, R::Params, String)> |
| 280 | 280 | where |
| 281 | R: lsp_types::request::Request, | |
| 281 | R: lsp_types::Request, | |
| 282 | 282 | R::Params: DeserializeOwned + fmt::Debug, |
| 283 | 283 | { |
| 284 | let req = self.req.take_if(|it| it.method == R::METHOD)?; | |
| 285 | let res = crate::from_json(R::METHOD, &req.params); | |
| 284 | let req = self.req.take_if(|it| it.method.as_str() == R::METHOD.as_str())?; | |
| 285 | let res = crate::from_json(R::METHOD.as_str(), &req.params); | |
| 286 | 286 | match res { |
| 287 | 287 | Ok(params) => { |
| 288 | 288 | let panic_context = |
| ... | ... | @@ -334,7 +334,7 @@ fn thread_result_to_response<R>( |
| 334 | 334 | result: thread::Result<anyhow::Result<R::Result>>, |
| 335 | 335 | ) -> Result<lsp_server::Response, HandlerCancelledError> |
| 336 | 336 | where |
| 337 | R: lsp_types::request::Request, | |
| 337 | R: lsp_types::Request, | |
| 338 | 338 | R::Params: DeserializeOwned, |
| 339 | 339 | R::Result: Serialize, |
| 340 | 340 | { |
| ... | ... | @@ -369,7 +369,7 @@ fn result_to_response<R>( |
| 369 | 369 | result: anyhow::Result<R::Result>, |
| 370 | 370 | ) -> Result<lsp_server::Response, HandlerCancelledError> |
| 371 | 371 | where |
| 372 | R: lsp_types::request::Request, | |
| 372 | R: lsp_types::Request, | |
| 373 | 373 | R::Params: DeserializeOwned, |
| 374 | 374 | R::Result: Serialize, |
| 375 | 375 | { |
| ... | ... | @@ -401,7 +401,7 @@ impl NotificationDispatcher<'_> { |
| 401 | 401 | f: fn(&mut GlobalState, N::Params) -> anyhow::Result<()>, |
| 402 | 402 | ) -> &mut Self |
| 403 | 403 | where |
| 404 | N: lsp_types::notification::Notification, | |
| 404 | N: lsp_types::Notification, | |
| 405 | 405 | N::Params: DeserializeOwned + Send + Debug, |
| 406 | 406 | { |
| 407 | 407 | let not = match self.not.take() { |
| ... | ... | @@ -411,7 +411,7 @@ impl NotificationDispatcher<'_> { |
| 411 | 411 | |
| 412 | 412 | let _guard = tracing::info_span!("notification", method = ?not.method).entered(); |
| 413 | 413 | |
| 414 | let params = match not.extract::<N::Params>(N::METHOD) { | |
| 414 | let params = match not.extract::<N::Params>(N::METHOD.as_str()) { | |
| 415 | 415 | Ok(it) => it, |
| 416 | 416 | Err(ExtractError::JsonError { method, error }) => { |
| 417 | 417 | tracing::error!(method = %method, error = %error, "invalid notification"); |
src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs+6-6| ... | ... | @@ -30,8 +30,8 @@ use crate::{ |
| 30 | 30 | |
| 31 | 31 | pub(crate) fn handle_cancel(state: &mut GlobalState, params: CancelParams) -> anyhow::Result<()> { |
| 32 | 32 | let id: lsp_server::RequestId = match params.id { |
| 33 | lsp_types::NumberOrString::Number(id) => id.into(), | |
| 34 | lsp_types::NumberOrString::String(id) => id.into(), | |
| 33 | lsp_types::Id::Int(id) => id.into(), | |
| 34 | lsp_types::Id::String(id) => id.into(), | |
| 35 | 35 | }; |
| 36 | 36 | state.cancel(id); |
| 37 | 37 | Ok(()) |
| ... | ... | @@ -41,7 +41,7 @@ pub(crate) fn handle_work_done_progress_cancel( |
| 41 | 41 | state: &mut GlobalState, |
| 42 | 42 | params: WorkDoneProgressCancelParams, |
| 43 | 43 | ) -> anyhow::Result<()> { |
| 44 | if let lsp_types::NumberOrString::String(s) = &params.token | |
| 44 | if let lsp_types::ProgressToken::String(s) = &params.token | |
| 45 | 45 | && let Some(id) = s.strip_prefix("rust-analyzer/flycheck/") |
| 46 | 46 | && let Ok(id) = id.parse::<u32>() |
| 47 | 47 | && let Some(flycheck) = state.flycheck.get(id as usize) |
| ... | ... | @@ -103,7 +103,7 @@ pub(crate) fn handle_did_change_text_document( |
| 103 | 103 | ) -> anyhow::Result<()> { |
| 104 | 104 | let _p = tracing::info_span!("handle_did_change_text_document").entered(); |
| 105 | 105 | |
| 106 | if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) { | |
| 106 | if let Ok(path) = from_proto::vfs_path(&params.text_document.text_document_identifier.uri) { | |
| 107 | 107 | let Some(DocumentData { version, data }) = state.mem_docs.get_mut(&path) else { |
| 108 | 108 | tracing::error!(?path, "unexpected DidChangeTextDocument"); |
| 109 | 109 | return Ok(()); |
| ... | ... | @@ -215,7 +215,7 @@ pub(crate) fn handle_did_change_configuration( |
| 215 | 215 | ) -> anyhow::Result<()> { |
| 216 | 216 | // As stated in https://github.com/microsoft/language-server-protocol/issues/676, |
| 217 | 217 | // this notification's parameters should be ignored and the actual config queried separately. |
| 218 | state.send_request::<lsp_types::request::WorkspaceConfiguration>( | |
| 218 | state.send_request::<lsp_types::ConfigurationRequest>( | |
| 219 | 219 | lsp_types::ConfigurationParams { |
| 220 | 220 | items: vec![lsp_types::ConfigurationItem { |
| 221 | 221 | scope_uri: None, |
| ... | ... | @@ -553,7 +553,7 @@ pub(crate) fn handle_run_flycheck( |
| 553 | 553 | |
| 554 | 554 | pub(crate) fn handle_abort_run_test(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { |
| 555 | 555 | if state.test_run_session.take().is_some() { |
| 556 | state.send_notification::<lsp_ext::EndRunTest>(()); | |
| 556 | state.send_notification::<lsp_ext::EndRunTestNotification>(()); | |
| 557 | 557 | } |
| 558 | 558 | Ok(()) |
| 559 | 559 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs+189-145| ... | ... | @@ -18,11 +18,11 @@ use lsp_server::ErrorCode; |
| 18 | 18 | use lsp_types::{ |
| 19 | 19 | CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, |
| 20 | 20 | CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, |
| 21 | CodeLens, CompletionItem, FoldingRange, FoldingRangeParams, HoverContents, InlayHint, | |
| 22 | InlayHintParams, Location, LocationLink, Position, PrepareRenameResponse, Range, RenameParams, | |
| 23 | ResourceOp, ResourceOperationKind, SemanticTokensDeltaParams, SemanticTokensFullDeltaResult, | |
| 24 | SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult, | |
| 25 | SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit, | |
| 21 | CodeLens, CompletionItem, Contents, DocumentChange, FoldingRange, FoldingRangeParams, | |
| 22 | InlayHint, InlayHintParams, Location, LocationLink, Position, PrepareRenameResult, Range, | |
| 23 | RenameParams, ResourceOperationKind, SemanticTokens, SemanticTokensDeltaParams, | |
| 24 | SemanticTokensDeltaResponse, SemanticTokensParams, SemanticTokensRangeParams, | |
| 25 | SymbolInformation, SymbolTag, TextDocumentIdentifier, Uri, WorkspaceEdit, | |
| 26 | 26 | }; |
| 27 | 27 | use paths::Utf8PathBuf; |
| 28 | 28 | use project_model::{CargoWorkspace, ManifestPath, ProjectWorkspaceKind, TargetKind}; |
| ... | ... | @@ -172,7 +172,7 @@ pub(crate) fn handle_view_hir( |
| 172 | 172 | params: lsp_types::TextDocumentPositionParams, |
| 173 | 173 | ) -> anyhow::Result<String> { |
| 174 | 174 | let _p = tracing::info_span!("handle_view_hir").entered(); |
| 175 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 175 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 176 | 176 | let res = snap.analysis.view_hir(position)?; |
| 177 | 177 | Ok(res) |
| 178 | 178 | } |
| ... | ... | @@ -182,7 +182,7 @@ pub(crate) fn handle_view_mir( |
| 182 | 182 | params: lsp_types::TextDocumentPositionParams, |
| 183 | 183 | ) -> anyhow::Result<String> { |
| 184 | 184 | let _p = tracing::info_span!("handle_view_mir").entered(); |
| 185 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 185 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 186 | 186 | let res = snap.analysis.view_mir(position)?; |
| 187 | 187 | Ok(res) |
| 188 | 188 | } |
| ... | ... | @@ -192,7 +192,7 @@ pub(crate) fn handle_interpret_function( |
| 192 | 192 | params: lsp_types::TextDocumentPositionParams, |
| 193 | 193 | ) -> anyhow::Result<String> { |
| 194 | 194 | let _p = tracing::info_span!("handle_interpret_function").entered(); |
| 195 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 195 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 196 | 196 | let res = snap.analysis.interpret_function(position)?; |
| 197 | 197 | Ok(res) |
| 198 | 198 | } |
| ... | ... | @@ -252,7 +252,7 @@ pub(crate) fn handle_run_test( |
| 252 | 252 | params: lsp_ext::RunTestParams, |
| 253 | 253 | ) -> anyhow::Result<()> { |
| 254 | 254 | if let Some(_session) = state.test_run_session.take() { |
| 255 | state.send_notification::<lsp_ext::EndRunTest>(()); | |
| 255 | state.send_notification::<lsp_ext::EndRunTestNotification>(()); | |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | 258 | let mut handles = vec![]; |
| ... | ... | @@ -358,9 +358,9 @@ pub(crate) fn handle_selection_range( |
| 358 | 358 | let line_index = snap.file_line_index(file_id)?; |
| 359 | 359 | let res: anyhow::Result<Vec<lsp_types::SelectionRange>> = params |
| 360 | 360 | .positions |
| 361 | .into_iter() | |
| 361 | .iter() | |
| 362 | 362 | .map(|position| { |
| 363 | let offset = from_proto::offset(&line_index, position)?; | |
| 363 | let offset = from_proto::offset(&line_index, *position)?; | |
| 364 | 364 | let mut ranges = Vec::new(); |
| 365 | 365 | { |
| 366 | 366 | let mut range = TextRange::new(offset, offset); |
| ... | ... | @@ -401,9 +401,9 @@ pub(crate) fn handle_matching_brace( |
| 401 | 401 | let line_index = snap.file_line_index(file_id)?; |
| 402 | 402 | params |
| 403 | 403 | .positions |
| 404 | .into_iter() | |
| 404 | .iter() | |
| 405 | 405 | .map(|position| { |
| 406 | let offset = from_proto::offset(&line_index, position); | |
| 406 | let offset = from_proto::offset(&line_index, *position); | |
| 407 | 407 | offset.map(|offset| { |
| 408 | 408 | let offset = match snap.analysis.matching_brace(FilePosition { file_id, offset }) { |
| 409 | 409 | Ok(Some(matching_brace_offset)) => matching_brace_offset, |
| ... | ... | @@ -445,7 +445,7 @@ pub(crate) fn handle_on_enter( |
| 445 | 445 | params: lsp_types::TextDocumentPositionParams, |
| 446 | 446 | ) -> anyhow::Result<Option<Vec<lsp_ext::SnippetTextEdit>>> { |
| 447 | 447 | let _p = tracing::info_span!("handle_on_enter").entered(); |
| 448 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 448 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 449 | 449 | let edit = match snap.analysis.on_enter(position)? { |
| 450 | 450 | None => return Ok(None), |
| 451 | 451 | Some(it) => it, |
| ... | ... | @@ -469,9 +469,11 @@ pub(crate) fn handle_on_type_formatting( |
| 469 | 469 | if !snap.config.typing_trigger_chars().contains(char_typed) { |
| 470 | 470 | return Ok(None); |
| 471 | 471 | } |
| 472 | ||
| 473 | let mut position = | |
| 474 | try_default!(from_proto::file_position(&snap, params.text_document_position)?); | |
| 472 | let tdpp = lsp_types::TextDocumentPositionParams { | |
| 473 | text_document: params.text_document, | |
| 474 | position: params.position, | |
| 475 | }; | |
| 476 | let mut position = try_default!(from_proto::file_position(&snap, &tdpp)?); | |
| 475 | 477 | let line_index = snap.file_line_index(position.file_id)?; |
| 476 | 478 | |
| 477 | 479 | // in `ide`, the `on_type` invariant is that |
| ... | ... | @@ -502,8 +504,8 @@ pub(crate) fn handle_on_type_formatting( |
| 502 | 504 | Ok(Some(change)) |
| 503 | 505 | } |
| 504 | 506 | |
| 505 | pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportResult { | |
| 506 | lsp_types::DocumentDiagnosticReportResult::Report(lsp_types::DocumentDiagnosticReport::Full( | |
| 507 | pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReport { | |
| 508 | lsp_types::DocumentDiagnosticReport::RelatedFullDocumentDiagnosticReport( | |
| 507 | 509 | lsp_types::RelatedFullDocumentDiagnosticReport { |
| 508 | 510 | related_documents: None, |
| 509 | 511 | full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport { |
| ... | ... | @@ -511,13 +513,13 @@ pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportRe |
| 511 | 513 | items: vec![], |
| 512 | 514 | }, |
| 513 | 515 | }, |
| 514 | )) | |
| 516 | ) | |
| 515 | 517 | } |
| 516 | 518 | |
| 517 | 519 | pub(crate) fn handle_document_diagnostics( |
| 518 | 520 | snap: GlobalStateSnapshot, |
| 519 | 521 | params: lsp_types::DocumentDiagnosticParams, |
| 520 | ) -> anyhow::Result<lsp_types::DocumentDiagnosticReportResult> { | |
| 522 | ) -> anyhow::Result<lsp_types::DocumentDiagnosticReport> { | |
| 521 | 523 | let file_id = match from_proto::file_id(&snap, &params.text_document.uri)? { |
| 522 | 524 | Some(it) => it, |
| 523 | 525 | None => return Ok(empty_diagnostic_report()), |
| ... | ... | @@ -554,8 +556,8 @@ pub(crate) fn handle_document_diagnostics( |
| 554 | 556 | } |
| 555 | 557 | None |
| 556 | 558 | }); |
| 557 | Ok(lsp_types::DocumentDiagnosticReportResult::Report( | |
| 558 | lsp_types::DocumentDiagnosticReport::Full(lsp_types::RelatedFullDocumentDiagnosticReport { | |
| 559 | Ok(lsp_types::DocumentDiagnosticReport::RelatedFullDocumentDiagnosticReport( | |
| 560 | lsp_types::RelatedFullDocumentDiagnosticReport { | |
| 559 | 561 | full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport { |
| 560 | 562 | result_id: Some("rust-analyzer".to_owned()), |
| 561 | 563 | items: diagnostics.collect(), |
| ... | ... | @@ -566,7 +568,7 @@ pub(crate) fn handle_document_diagnostics( |
| 566 | 568 | .map(|(id, (items, _))| { |
| 567 | 569 | ( |
| 568 | 570 | to_proto::url(&snap, id), |
| 569 | lsp_types::DocumentDiagnosticReportKind::Full( | |
| 571 | lsp_types::RelatedDocument::FullDocumentDiagnosticReport( | |
| 570 | 572 | lsp_types::FullDocumentDiagnosticReport { |
| 571 | 573 | result_id: Some("rust-analyzer".to_owned()), |
| 572 | 574 | items, |
| ... | ... | @@ -576,7 +578,7 @@ pub(crate) fn handle_document_diagnostics( |
| 576 | 578 | }) |
| 577 | 579 | .collect() |
| 578 | 580 | }), |
| 579 | }), | |
| 581 | }, | |
| 580 | 582 | )) |
| 581 | 583 | } |
| 582 | 584 | |
| ... | ... | @@ -600,7 +602,7 @@ pub(crate) fn handle_document_symbol( |
| 600 | 602 | for node in structure_nodes { |
| 601 | 603 | let mut tags = Vec::new(); |
| 602 | 604 | if node.deprecated { |
| 603 | tags.push(SymbolTag::DEPRECATED) | |
| 605 | tags.push(SymbolTag::Deprecated) | |
| 604 | 606 | }; |
| 605 | 607 | |
| 606 | 608 | #[allow(deprecated)] |
| ... | ... | @@ -649,17 +651,19 @@ pub(crate) fn handle_document_symbol( |
| 649 | 651 | fn flatten_document_symbol( |
| 650 | 652 | symbol: &lsp_types::DocumentSymbol, |
| 651 | 653 | container_name: Option<String>, |
| 652 | url: &Url, | |
| 654 | url: &Uri, | |
| 653 | 655 | res: &mut Vec<SymbolInformation>, |
| 654 | 656 | ) { |
| 655 | 657 | #[allow(deprecated)] |
| 656 | 658 | res.push(SymbolInformation { |
| 657 | name: symbol.name.clone(), | |
| 658 | kind: symbol.kind, | |
| 659 | tags: symbol.tags.clone(), | |
| 660 | 659 | deprecated: symbol.deprecated, |
| 661 | 660 | location: Location::new(url.clone(), symbol.range), |
| 662 | container_name, | |
| 661 | base_symbol_information: lsp_types::BaseSymbolInformation { | |
| 662 | name: symbol.name.clone(), | |
| 663 | kind: symbol.kind, | |
| 664 | tags: symbol.tags.clone(), | |
| 665 | container_name, | |
| 666 | }, | |
| 663 | 667 | }); |
| 664 | 668 | |
| 665 | 669 | for child in symbol.children.iter().flatten() { |
| ... | ... | @@ -696,7 +700,7 @@ pub(crate) fn handle_workspace_symbol( |
| 696 | 700 | res = exec_query(&snap, Query::new(params.query), config.search_limit)?; |
| 697 | 701 | } |
| 698 | 702 | |
| 699 | return Ok(Some(lsp_types::WorkspaceSymbolResponse::Nested(res))); | |
| 703 | return Ok(Some(lsp_types::WorkspaceSymbolResponse::WorkspaceSymbolList(res))); | |
| 700 | 704 | |
| 701 | 705 | fn decide_search_kind_and_scope( |
| 702 | 706 | params: &WorkspaceSymbolParams, |
| ... | ... | @@ -743,19 +747,23 @@ pub(crate) fn handle_workspace_symbol( |
| 743 | 747 | let container_name = nav.container_name.as_ref().map(|v| v.to_string()); |
| 744 | 748 | |
| 745 | 749 | let info = lsp_types::WorkspaceSymbol { |
| 746 | name: match &nav.alias { | |
| 747 | Some(alias) => format!("{} (alias for {})", alias, nav.name), | |
| 748 | None => format!("{}", nav.name), | |
| 749 | }, | |
| 750 | kind: nav | |
| 751 | .kind | |
| 752 | .map(to_proto::symbol_kind) | |
| 753 | .unwrap_or(lsp_types::SymbolKind::VARIABLE), | |
| 754 | // FIXME: Set deprecation | |
| 755 | tags: None, | |
| 756 | container_name, | |
| 757 | location: lsp_types::OneOf::Left(to_proto::location_from_nav(snap, nav)?), | |
| 750 | location: lsp_types::WorkspaceSymbolLocation::Location( | |
| 751 | to_proto::location_from_nav(snap, &nav)?, | |
| 752 | ), | |
| 758 | 753 | data: None, |
| 754 | base_symbol_information: lsp_types::BaseSymbolInformation { | |
| 755 | name: match &nav.alias { | |
| 756 | Some(alias) => format!("{} (alias for {})", alias, nav.name), | |
| 757 | None => nav.name.to_string(), | |
| 758 | }, | |
| 759 | kind: nav | |
| 760 | .kind | |
| 761 | .map(to_proto::symbol_kind) | |
| 762 | .unwrap_or(lsp_types::SymbolKind::Variable), | |
| 763 | // FIXME: Set deprecation | |
| 764 | tags: None, | |
| 765 | container_name, | |
| 766 | }, | |
| 759 | 767 | }; |
| 760 | 768 | res.push(info); |
| 761 | 769 | } |
| ... | ... | @@ -773,8 +781,8 @@ pub(crate) fn handle_will_rename_files( |
| 773 | 781 | .files |
| 774 | 782 | .into_iter() |
| 775 | 783 | .filter_map(|file_rename| { |
| 776 | let from = Url::parse(&file_rename.old_uri).ok()?; | |
| 777 | let to = Url::parse(&file_rename.new_uri).ok()?; | |
| 784 | let from = Uri::parse(&file_rename.old_uri).ok()?; | |
| 785 | let to = Uri::parse(&file_rename.new_uri).ok()?; | |
| 778 | 786 | |
| 779 | 787 | let from_path = from.to_file_path().ok()?; |
| 780 | 788 | let to_path = to.to_file_path().ok()?; |
| ... | ... | @@ -831,11 +839,11 @@ pub(crate) fn handle_will_rename_files( |
| 831 | 839 | |
| 832 | 840 | pub(crate) fn handle_goto_definition( |
| 833 | 841 | snap: GlobalStateSnapshot, |
| 834 | params: lsp_types::GotoDefinitionParams, | |
| 835 | ) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> { | |
| 842 | params: lsp_types::DefinitionParams, | |
| 843 | ) -> anyhow::Result<Option<lsp_types::DefinitionResponse>> { | |
| 836 | 844 | let _p = tracing::info_span!("handle_goto_definition").entered(); |
| 837 | 845 | let position = |
| 838 | try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); | |
| 846 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 839 | 847 | let config = snap.config.goto_definition(snap.minicore()); |
| 840 | 848 | let nav_info = match snap.analysis.goto_definition(position, &config)? { |
| 841 | 849 | None => return Ok(None), |
| ... | ... | @@ -848,60 +856,84 @@ pub(crate) fn handle_goto_definition( |
| 848 | 856 | |
| 849 | 857 | pub(crate) fn handle_goto_declaration( |
| 850 | 858 | snap: GlobalStateSnapshot, |
| 851 | params: lsp_types::request::GotoDeclarationParams, | |
| 852 | ) -> anyhow::Result<Option<lsp_types::request::GotoDeclarationResponse>> { | |
| 859 | params: lsp_types::DeclarationParams, | |
| 860 | ) -> anyhow::Result<Option<lsp_types::DeclarationResponse>> { | |
| 853 | 861 | let _p = tracing::info_span!("handle_goto_declaration").entered(); |
| 854 | let position = try_default!(from_proto::file_position( | |
| 855 | &snap, | |
| 856 | params.text_document_position_params.clone() | |
| 857 | )?); | |
| 862 | let position = | |
| 863 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 858 | 864 | let config = snap.config.goto_definition(snap.minicore()); |
| 859 | 865 | let nav_info = match snap.analysis.goto_declaration(position, &config)? { |
| 860 | None => return handle_goto_definition(snap, params), | |
| 866 | None => { | |
| 867 | // fallback to goto definition | |
| 868 | let params = lsp_types::DefinitionParams { | |
| 869 | work_done_progress_params: params.work_done_progress_params, | |
| 870 | partial_result_params: params.partial_result_params, | |
| 871 | text_document_position_params: params.text_document_position_params, | |
| 872 | }; | |
| 873 | return match handle_goto_definition(snap, params) { | |
| 874 | Ok(Some(x)) => match x { | |
| 875 | lsp_types::DefinitionResponse::Definition(definition) => { | |
| 876 | Ok(Some(lsp_types::DeclarationResponse::Declaration(match definition { | |
| 877 | lsp_types::Definition::Location(location) => { | |
| 878 | lsp_types::Declaration::Location(location) | |
| 879 | } | |
| 880 | lsp_types::Definition::LocationList(locations) => { | |
| 881 | lsp_types::Declaration::LocationList(locations) | |
| 882 | } | |
| 883 | }))) | |
| 884 | } | |
| 885 | lsp_types::DefinitionResponse::DefinitionLinkList(location_links) => Ok(Some( | |
| 886 | lsp_types::DeclarationResponse::DeclarationLinkList(location_links), | |
| 887 | )), | |
| 888 | }, | |
| 889 | Ok(None) => Ok(None), | |
| 890 | Err(error) => Err(error), | |
| 891 | }; | |
| 892 | } | |
| 861 | 893 | Some(it) => it, |
| 862 | 894 | }; |
| 863 | 895 | let src = FileRange { file_id: position.file_id, range: nav_info.range }; |
| 864 | let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?; | |
| 896 | let res = to_proto::goto_declaration_response(&snap, Some(src), nav_info.info)?; | |
| 865 | 897 | Ok(Some(res)) |
| 866 | 898 | } |
| 867 | 899 | |
| 868 | 900 | pub(crate) fn handle_goto_implementation( |
| 869 | 901 | snap: GlobalStateSnapshot, |
| 870 | params: lsp_types::request::GotoImplementationParams, | |
| 871 | ) -> anyhow::Result<Option<lsp_types::request::GotoImplementationResponse>> { | |
| 902 | params: lsp_types::ImplementationParams, | |
| 903 | ) -> anyhow::Result<Option<lsp_types::ImplementationResponse>> { | |
| 872 | 904 | let _p = tracing::info_span!("handle_goto_implementation").entered(); |
| 873 | 905 | let position = |
| 874 | try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); | |
| 906 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 875 | 907 | let nav_info = |
| 876 | 908 | match snap.analysis.goto_implementation(&snap.config.goto_implementation(), position)? { |
| 877 | 909 | None => return Ok(None), |
| 878 | 910 | Some(it) => it, |
| 879 | 911 | }; |
| 880 | 912 | let src = FileRange { file_id: position.file_id, range: nav_info.range }; |
| 881 | let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?; | |
| 913 | let res = to_proto::goto_implementation_response(&snap, Some(src), nav_info.info)?; | |
| 882 | 914 | Ok(Some(res)) |
| 883 | 915 | } |
| 884 | 916 | |
| 885 | 917 | pub(crate) fn handle_goto_type_definition( |
| 886 | 918 | snap: GlobalStateSnapshot, |
| 887 | params: lsp_types::request::GotoTypeDefinitionParams, | |
| 888 | ) -> anyhow::Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> { | |
| 919 | params: lsp_types::TypeDefinitionParams, | |
| 920 | ) -> anyhow::Result<Option<lsp_types::TypeDefinitionResponse>> { | |
| 889 | 921 | let _p = tracing::info_span!("handle_goto_type_definition").entered(); |
| 890 | 922 | let position = |
| 891 | try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); | |
| 923 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 892 | 924 | let nav_info = match snap.analysis.goto_type_definition(position)? { |
| 893 | 925 | None => return Ok(None), |
| 894 | 926 | Some(it) => it, |
| 895 | 927 | }; |
| 896 | 928 | let src = FileRange { file_id: position.file_id, range: nav_info.range }; |
| 897 | let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?; | |
| 929 | let res = to_proto::goto_type_definition_response(&snap, Some(src), nav_info.info)?; | |
| 898 | 930 | Ok(Some(res)) |
| 899 | 931 | } |
| 900 | 932 | |
| 901 | 933 | pub(crate) fn handle_parent_module( |
| 902 | 934 | snap: GlobalStateSnapshot, |
| 903 | 935 | params: lsp_types::TextDocumentPositionParams, |
| 904 | ) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> { | |
| 936 | ) -> anyhow::Result<Option<lsp_types::DefinitionResponse>> { | |
| 905 | 937 | let _p = tracing::info_span!("handle_parent_module").entered(); |
| 906 | 938 | if let Ok(file_path) = &params.text_document.uri.to_file_path() { |
| 907 | 939 | if file_path.file_name().unwrap_or_default() == "Cargo.toml" { |
| ... | ... | @@ -965,7 +997,7 @@ pub(crate) fn handle_parent_module( |
| 965 | 997 | } |
| 966 | 998 | |
| 967 | 999 | // locate parent module by semantics |
| 968 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 1000 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 969 | 1001 | let navs = snap.analysis.parent_module(position)?; |
| 970 | 1002 | let res = to_proto::goto_definition_response(&snap, None, navs)?; |
| 971 | 1003 | Ok(Some(res)) |
| ... | ... | @@ -974,10 +1006,10 @@ pub(crate) fn handle_parent_module( |
| 974 | 1006 | pub(crate) fn handle_child_modules( |
| 975 | 1007 | snap: GlobalStateSnapshot, |
| 976 | 1008 | params: lsp_types::TextDocumentPositionParams, |
| 977 | ) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> { | |
| 1009 | ) -> anyhow::Result<Option<lsp_types::DefinitionResponse>> { | |
| 978 | 1010 | let _p = tracing::info_span!("handle_child_modules").entered(); |
| 979 | 1011 | // locate child module by semantics |
| 980 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 1012 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 981 | 1013 | let navs = snap.analysis.child_modules(position)?; |
| 982 | 1014 | let res = to_proto::goto_definition_response(&snap, None, navs)?; |
| 983 | 1015 | Ok(Some(res)) |
| ... | ... | @@ -1042,6 +1074,10 @@ pub(crate) fn handle_runnables( |
| 1042 | 1074 | cargo_args.push("--all-targets".to_owned()); |
| 1043 | 1075 | } |
| 1044 | 1076 | cargo_args.extend(config.cargo_extra_args.iter().cloned()); |
| 1077 | if let Some(config_path) = &config.config_path { | |
| 1078 | cargo_args.push("--config".to_owned()); | |
| 1079 | cargo_args.push(config_path.to_string()); | |
| 1080 | } | |
| 1045 | 1081 | res.push(lsp_ext::Runnable { |
| 1046 | 1082 | label: format!( |
| 1047 | 1083 | "cargo {cmd} -p {}{all_targets}", |
| ... | ... | @@ -1072,6 +1108,10 @@ pub(crate) fn handle_runnables( |
| 1072 | 1108 | { |
| 1073 | 1109 | let mut cargo_args = vec!["check".to_owned(), "--workspace".to_owned()]; |
| 1074 | 1110 | cargo_args.extend(config.cargo_extra_args.iter().cloned()); |
| 1111 | if let Some(config_path) = &config.config_path { | |
| 1112 | cargo_args.push("--config".to_owned()); | |
| 1113 | cargo_args.push(config_path.to_string()); | |
| 1114 | } | |
| 1075 | 1115 | res.push(lsp_ext::Runnable { |
| 1076 | 1116 | label: "cargo check --workspace".to_owned(), |
| 1077 | 1117 | location: None, |
| ... | ... | @@ -1103,7 +1143,7 @@ pub(crate) fn handle_related_tests( |
| 1103 | 1143 | params: lsp_types::TextDocumentPositionParams, |
| 1104 | 1144 | ) -> anyhow::Result<Vec<lsp_ext::TestInfo>> { |
| 1105 | 1145 | let _p = tracing::info_span!("handle_related_tests").entered(); |
| 1106 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 1146 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 1107 | 1147 | |
| 1108 | 1148 | let tests = snap.analysis.related_tests(position, None)?; |
| 1109 | 1149 | let mut res = Vec::new(); |
| ... | ... | @@ -1119,14 +1159,14 @@ pub(crate) fn handle_related_tests( |
| 1119 | 1159 | pub(crate) fn handle_completion( |
| 1120 | 1160 | snap: GlobalStateSnapshot, |
| 1121 | 1161 | lsp_types::CompletionParams { |
| 1122 | text_document_position, | |
| 1162 | text_document_position_params, | |
| 1123 | 1163 | context, |
| 1124 | 1164 | .. |
| 1125 | 1165 | }: lsp_types::CompletionParams, |
| 1126 | 1166 | ) -> anyhow::Result<Option<lsp_types::CompletionResponse>> { |
| 1127 | 1167 | let _p = tracing::info_span!("handle_completion").entered(); |
| 1128 | 1168 | let mut position = |
| 1129 | try_default!(from_proto::file_position(&snap, text_document_position.clone())?); | |
| 1169 | try_default!(from_proto::file_position(&snap, &text_document_position_params)?); | |
| 1130 | 1170 | let line_index = snap.file_line_index(position.file_id)?; |
| 1131 | 1171 | let completion_trigger_character = |
| 1132 | 1172 | context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next()); |
| ... | ... | @@ -1149,12 +1189,17 @@ pub(crate) fn handle_completion( |
| 1149 | 1189 | &completion_config.fields_to_resolve, |
| 1150 | 1190 | &line_index, |
| 1151 | 1191 | snap.file_version(position.file_id), |
| 1152 | text_document_position, | |
| 1192 | &text_document_position_params, | |
| 1153 | 1193 | completion_trigger_character, |
| 1154 | 1194 | items, |
| 1155 | 1195 | ); |
| 1156 | 1196 | |
| 1157 | let completion_list = lsp_types::CompletionList { is_incomplete: true, items }; | |
| 1197 | let completion_list = lsp_types::CompletionList { | |
| 1198 | is_incomplete: true, | |
| 1199 | items, | |
| 1200 | item_defaults: None, | |
| 1201 | apply_kind: None, | |
| 1202 | }; | |
| 1158 | 1203 | Ok(Some(completion_list.into())) |
| 1159 | 1204 | } |
| 1160 | 1205 | |
| ... | ... | @@ -1217,7 +1262,7 @@ pub(crate) fn handle_completion_resolve( |
| 1217 | 1262 | &forced_resolve_completions_config.fields_to_resolve, |
| 1218 | 1263 | &line_index, |
| 1219 | 1264 | snap.file_version(position.file_id), |
| 1220 | resolve_data.position, | |
| 1265 | &resolve_data.position, | |
| 1221 | 1266 | resolve_data.trigger_character, |
| 1222 | 1267 | vec![corresponding_completion], |
| 1223 | 1268 | ); |
| ... | ... | @@ -1287,7 +1332,7 @@ pub(crate) fn handle_signature_help( |
| 1287 | 1332 | ) -> anyhow::Result<Option<lsp_types::SignatureHelp>> { |
| 1288 | 1333 | let _p = tracing::info_span!("handle_signature_help").entered(); |
| 1289 | 1334 | let position = |
| 1290 | try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); | |
| 1335 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 1291 | 1336 | let help = match snap.analysis.signature_help(position)? { |
| 1292 | 1337 | Some(it) => it, |
| 1293 | 1338 | None => return Ok(None), |
| ... | ... | @@ -1319,7 +1364,7 @@ pub(crate) fn handle_hover( |
| 1319 | 1364 | let markup_kind = hover.format; |
| 1320 | 1365 | let hover = lsp_ext::Hover { |
| 1321 | 1366 | hover: lsp_types::Hover { |
| 1322 | contents: HoverContents::Markup(to_proto::markup_content( | |
| 1367 | contents: Contents::MarkupContent(to_proto::markup_content( | |
| 1323 | 1368 | info.info.markup, |
| 1324 | 1369 | markup_kind, |
| 1325 | 1370 | )), |
| ... | ... | @@ -1337,16 +1382,17 @@ pub(crate) fn handle_hover( |
| 1337 | 1382 | |
| 1338 | 1383 | pub(crate) fn handle_prepare_rename( |
| 1339 | 1384 | snap: GlobalStateSnapshot, |
| 1340 | params: lsp_types::TextDocumentPositionParams, | |
| 1341 | ) -> anyhow::Result<Option<PrepareRenameResponse>> { | |
| 1385 | params: lsp_types::PrepareRenameParams, | |
| 1386 | ) -> anyhow::Result<Option<PrepareRenameResult>> { | |
| 1342 | 1387 | let _p = tracing::info_span!("handle_prepare_rename").entered(); |
| 1343 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 1388 | let position = | |
| 1389 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 1344 | 1390 | |
| 1345 | 1391 | let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?; |
| 1346 | 1392 | |
| 1347 | 1393 | let line_index = snap.file_line_index(position.file_id)?; |
| 1348 | 1394 | let range = to_proto::range(&line_index, change.range); |
| 1349 | Ok(Some(PrepareRenameResponse::Range(range))) | |
| 1395 | Ok(Some(PrepareRenameResult::Range(range))) | |
| 1350 | 1396 | } |
| 1351 | 1397 | |
| 1352 | 1398 | pub(crate) fn handle_rename( |
| ... | ... | @@ -1354,7 +1400,8 @@ pub(crate) fn handle_rename( |
| 1354 | 1400 | params: RenameParams, |
| 1355 | 1401 | ) -> anyhow::Result<Option<WorkspaceEdit>> { |
| 1356 | 1402 | let _p = tracing::info_span!("handle_rename").entered(); |
| 1357 | let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?); | |
| 1403 | let position = | |
| 1404 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 1358 | 1405 | |
| 1359 | 1406 | let source_root = snap.analysis.source_root_id(position.file_id).ok(); |
| 1360 | 1407 | let config = snap.config.rename(source_root); |
| ... | ... | @@ -1375,13 +1422,9 @@ pub(crate) fn handle_rename( |
| 1375 | 1422 | |
| 1376 | 1423 | let workspace_edit = to_proto::workspace_edit(&snap, change)?; |
| 1377 | 1424 | |
| 1378 | if let Some(lsp_types::DocumentChanges::Operations(ops)) = | |
| 1379 | workspace_edit.document_changes.as_ref() | |
| 1380 | { | |
| 1381 | for op in ops { | |
| 1382 | if let lsp_types::DocumentChangeOperation::Op(doc_change_op) = op { | |
| 1383 | resource_ops_supported(&snap.config, resolve_resource_op(doc_change_op))? | |
| 1384 | } | |
| 1425 | if let Some(changes) = workspace_edit.document_changes.as_ref() { | |
| 1426 | for change in changes { | |
| 1427 | resource_ops_supported(&snap.config, change)?; | |
| 1385 | 1428 | } |
| 1386 | 1429 | } |
| 1387 | 1430 | |
| ... | ... | @@ -1393,7 +1436,8 @@ pub(crate) fn handle_references( |
| 1393 | 1436 | params: lsp_types::ReferenceParams, |
| 1394 | 1437 | ) -> anyhow::Result<Option<Vec<Location>>> { |
| 1395 | 1438 | let _p = tracing::info_span!("handle_references").entered(); |
| 1396 | let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?); | |
| 1439 | let position = | |
| 1440 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 1397 | 1441 | |
| 1398 | 1442 | let exclude_imports = snap.config.find_all_refs_exclude_imports(); |
| 1399 | 1443 | let exclude_tests = snap.config.find_all_refs_exclude_tests(); |
| ... | ... | @@ -1442,7 +1486,7 @@ pub(crate) fn handle_formatting( |
| 1442 | 1486 | ) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> { |
| 1443 | 1487 | let _p = tracing::info_span!("handle_formatting").entered(); |
| 1444 | 1488 | |
| 1445 | run_rustfmt(&snap, params.text_document, None) | |
| 1489 | run_rustfmt(&snap, &params.text_document, None) | |
| 1446 | 1490 | } |
| 1447 | 1491 | |
| 1448 | 1492 | pub(crate) fn handle_range_formatting( |
| ... | ... | @@ -1451,7 +1495,7 @@ pub(crate) fn handle_range_formatting( |
| 1451 | 1495 | ) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> { |
| 1452 | 1496 | let _p = tracing::info_span!("handle_range_formatting").entered(); |
| 1453 | 1497 | |
| 1454 | run_rustfmt(&snap, params.text_document, Some(params.range)) | |
| 1498 | run_rustfmt(&snap, &params.text_document, Some(params.range)) | |
| 1455 | 1499 | } |
| 1456 | 1500 | |
| 1457 | 1501 | pub(crate) fn handle_code_action( |
| ... | ... | @@ -1506,8 +1550,8 @@ pub(crate) fn handle_code_action( |
| 1506 | 1550 | let changes = code_action.edit.as_ref().and_then(|it| it.document_changes.as_ref()); |
| 1507 | 1551 | if let Some(changes) = changes { |
| 1508 | 1552 | for change in changes { |
| 1509 | if let lsp_ext::SnippetDocumentChangeOperation::Op(res_op) = change { | |
| 1510 | resource_ops_supported(&snap.config, resolve_resource_op(res_op))? | |
| 1553 | if let lsp_ext::SnippetDocumentChangeOperation::Change(change) = change { | |
| 1554 | resource_ops_supported(&snap.config, change)? | |
| 1511 | 1555 | } |
| 1512 | 1556 | } |
| 1513 | 1557 | } |
| ... | ... | @@ -1609,8 +1653,8 @@ pub(crate) fn handle_code_action_resolve( |
| 1609 | 1653 | && let Some(changes) = edit.document_changes.as_ref() |
| 1610 | 1654 | { |
| 1611 | 1655 | for change in changes { |
| 1612 | if let lsp_ext::SnippetDocumentChangeOperation::Op(res_op) = change { | |
| 1613 | resource_ops_supported(&snap.config, resolve_resource_op(res_op))? | |
| 1656 | if let lsp_ext::SnippetDocumentChangeOperation::Change(change) = change { | |
| 1657 | resource_ops_supported(&snap.config, change)? | |
| 1614 | 1658 | } |
| 1615 | 1659 | } |
| 1616 | 1660 | } |
| ... | ... | @@ -1717,7 +1761,7 @@ pub(crate) fn handle_document_highlight( |
| 1717 | 1761 | ) -> anyhow::Result<Option<Vec<lsp_types::DocumentHighlight>>> { |
| 1718 | 1762 | let _p = tracing::info_span!("handle_document_highlight").entered(); |
| 1719 | 1763 | let position = |
| 1720 | try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); | |
| 1764 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 1721 | 1765 | let line_index = snap.file_line_index(position.file_id)?; |
| 1722 | 1766 | let source_root = snap.analysis.source_root_id(position.file_id)?; |
| 1723 | 1767 | |
| ... | ... | @@ -1750,7 +1794,7 @@ pub(crate) fn handle_ssr( |
| 1750 | 1794 | .map(|range| from_proto::file_range(&snap, &params.position.text_document, *range)) |
| 1751 | 1795 | .collect::<Result<Option<Vec<_>>, _>>()? |
| 1752 | 1796 | ); |
| 1753 | let position = try_default!(from_proto::file_position(&snap, params.position)?); | |
| 1797 | let position = try_default!(from_proto::file_position(&snap, &params.position)?); | |
| 1754 | 1798 | let source_change = snap.analysis.structural_search_replace( |
| 1755 | 1799 | &params.query, |
| 1756 | 1800 | params.parse_only, |
| ... | ... | @@ -1855,7 +1899,7 @@ pub(crate) fn handle_call_hierarchy_prepare( |
| 1855 | 1899 | ) -> anyhow::Result<Option<Vec<CallHierarchyItem>>> { |
| 1856 | 1900 | let _p = tracing::info_span!("handle_call_hierarchy_prepare").entered(); |
| 1857 | 1901 | let position = |
| 1858 | try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); | |
| 1902 | try_default!(from_proto::file_position(&snap, &params.text_document_position_params)?); | |
| 1859 | 1903 | |
| 1860 | 1904 | let config = snap.config.call_hierarchy(snap.minicore()); |
| 1861 | 1905 | let nav_info = match snap.analysis.call_hierarchy(position, &config)? { |
| ... | ... | @@ -1890,25 +1934,26 @@ pub(crate) fn handle_call_hierarchy_incoming( |
| 1890 | 1934 | Some(it) => it, |
| 1891 | 1935 | }; |
| 1892 | 1936 | |
| 1893 | let mut res = vec![]; | |
| 1894 | ||
| 1895 | for call_item in call_items.into_iter() { | |
| 1896 | let file_id = call_item.target.file_id; | |
| 1897 | let line_index = snap.file_line_index(file_id)?; | |
| 1898 | let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; | |
| 1899 | res.push(CallHierarchyIncomingCall { | |
| 1900 | from: item, | |
| 1901 | from_ranges: call_item | |
| 1902 | .ranges | |
| 1903 | .into_iter() | |
| 1904 | // This is the range relative to the item | |
| 1905 | .filter(|it| it.file_id == file_id) | |
| 1906 | .map(|it| to_proto::range(&line_index, it.range)) | |
| 1907 | .collect(), | |
| 1908 | }); | |
| 1909 | } | |
| 1910 | ||
| 1911 | Ok(Some(res)) | |
| 1937 | Ok(Some( | |
| 1938 | call_items | |
| 1939 | .into_iter() | |
| 1940 | .map(|call_item| { | |
| 1941 | let file_id = call_item.target.file_id; | |
| 1942 | let line_index = snap.file_line_index(file_id)?; | |
| 1943 | let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; | |
| 1944 | Ok(CallHierarchyIncomingCall { | |
| 1945 | from: item, | |
| 1946 | from_ranges: call_item | |
| 1947 | .ranges | |
| 1948 | .iter() | |
| 1949 | // This is the range relative to the item | |
| 1950 | .filter(|it| it.file_id == file_id) | |
| 1951 | .map(|it| to_proto::range(&line_index, it.range)) | |
| 1952 | .collect(), | |
| 1953 | }) | |
| 1954 | }) | |
| 1955 | .collect::<anyhow::Result<_>>()?, | |
| 1956 | )) | |
| 1912 | 1957 | } |
| 1913 | 1958 | |
| 1914 | 1959 | pub(crate) fn handle_call_hierarchy_outgoing( |
| ... | ... | @@ -1951,7 +1996,7 @@ pub(crate) fn handle_call_hierarchy_outgoing( |
| 1951 | 1996 | pub(crate) fn handle_semantic_tokens_full( |
| 1952 | 1997 | snap: GlobalStateSnapshot, |
| 1953 | 1998 | params: SemanticTokensParams, |
| 1954 | ) -> anyhow::Result<Option<SemanticTokensResult>> { | |
| 1999 | ) -> anyhow::Result<Option<SemanticTokens>> { | |
| 1955 | 2000 | let _p = tracing::info_span!("handle_semantic_tokens_full").entered(); |
| 1956 | 2001 | |
| 1957 | 2002 | let file_id = try_default!(from_proto::file_id(&snap, &params.text_document.uri)?); |
| ... | ... | @@ -1975,13 +2020,13 @@ pub(crate) fn handle_semantic_tokens_full( |
| 1975 | 2020 | // Unconditionally cache the tokens |
| 1976 | 2021 | snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens.clone()); |
| 1977 | 2022 | |
| 1978 | Ok(Some(semantic_tokens.into())) | |
| 2023 | Ok(Some(semantic_tokens)) | |
| 1979 | 2024 | } |
| 1980 | 2025 | |
| 1981 | 2026 | pub(crate) fn handle_semantic_tokens_full_delta( |
| 1982 | 2027 | snap: GlobalStateSnapshot, |
| 1983 | 2028 | params: SemanticTokensDeltaParams, |
| 1984 | ) -> anyhow::Result<Option<SemanticTokensFullDeltaResult>> { | |
| 2029 | ) -> anyhow::Result<Option<SemanticTokensDeltaResponse>> { | |
| 1985 | 2030 | let _p = tracing::info_span!("handle_semantic_tokens_full_delta").entered(); |
| 1986 | 2031 | |
| 1987 | 2032 | let file_id = try_default!(from_proto::file_id(&snap, &params.text_document.uri)?); |
| ... | ... | @@ -2023,7 +2068,7 @@ pub(crate) fn handle_semantic_tokens_full_delta( |
| 2023 | 2068 | pub(crate) fn handle_semantic_tokens_range( |
| 2024 | 2069 | snap: GlobalStateSnapshot, |
| 2025 | 2070 | params: SemanticTokensRangeParams, |
| 2026 | ) -> anyhow::Result<Option<SemanticTokensRangeResult>> { | |
| 2071 | ) -> anyhow::Result<Option<SemanticTokens>> { | |
| 2027 | 2072 | let _p = tracing::info_span!("handle_semantic_tokens_range").entered(); |
| 2028 | 2073 | |
| 2029 | 2074 | let frange = try_default!(from_proto::file_range(&snap, &params.text_document, params.range)?); |
| ... | ... | @@ -2043,7 +2088,7 @@ pub(crate) fn handle_semantic_tokens_range( |
| 2043 | 2088 | snap.config.semantics_tokens_augments_syntax_tokens(), |
| 2044 | 2089 | snap.config.highlighting_non_standard_tokens(), |
| 2045 | 2090 | ); |
| 2046 | Ok(Some(semantic_tokens.into())) | |
| 2091 | Ok(Some(semantic_tokens)) | |
| 2047 | 2092 | } |
| 2048 | 2093 | |
| 2049 | 2094 | pub(crate) fn handle_open_docs( |
| ... | ... | @@ -2051,7 +2096,7 @@ pub(crate) fn handle_open_docs( |
| 2051 | 2096 | params: lsp_types::TextDocumentPositionParams, |
| 2052 | 2097 | ) -> anyhow::Result<ExternalDocsResponse> { |
| 2053 | 2098 | let _p = tracing::info_span!("handle_open_docs").entered(); |
| 2054 | let position = try_default!(from_proto::file_position(&snap, params)?); | |
| 2099 | let position = try_default!(from_proto::file_position(&snap, &params)?); | |
| 2055 | 2100 | |
| 2056 | 2101 | let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind { |
| 2057 | 2102 | ProjectWorkspaceKind::Cargo { cargo, .. } |
| ... | ... | @@ -2078,8 +2123,8 @@ pub(crate) fn handle_open_docs( |
| 2078 | 2123 | }; |
| 2079 | 2124 | }; |
| 2080 | 2125 | |
| 2081 | let web = remote_urls.web_url.and_then(|it| Url::parse(&it).ok()); | |
| 2082 | let local = remote_urls.local_url.and_then(|it| Url::parse(&it).ok()); | |
| 2126 | let web = remote_urls.web_url.and_then(|it| Uri::parse(&it).ok()); | |
| 2127 | let local = remote_urls.local_url.and_then(|it| Uri::parse(&it).ok()); | |
| 2083 | 2128 | |
| 2084 | 2129 | if snap.config.local_docs() { |
| 2085 | 2130 | Ok(ExternalDocsResponse::WithLocal(ExternalDocsPair { web, local })) |
| ... | ... | @@ -2091,7 +2136,7 @@ pub(crate) fn handle_open_docs( |
| 2091 | 2136 | pub(crate) fn handle_open_cargo_toml( |
| 2092 | 2137 | snap: GlobalStateSnapshot, |
| 2093 | 2138 | params: lsp_ext::OpenCargoTomlParams, |
| 2094 | ) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> { | |
| 2139 | ) -> anyhow::Result<Option<lsp_types::DefinitionResponse>> { | |
| 2095 | 2140 | let _p = tracing::info_span!("handle_open_cargo_toml").entered(); |
| 2096 | 2141 | let file_id = try_default!(from_proto::file_id(&snap, &params.text_document.uri)?); |
| 2097 | 2142 | |
| ... | ... | @@ -2101,8 +2146,9 @@ pub(crate) fn handle_open_cargo_toml( |
| 2101 | 2146 | }; |
| 2102 | 2147 | |
| 2103 | 2148 | let cargo_toml_url = to_proto::url_from_abs_path(&cargo_spec.cargo_toml); |
| 2104 | let res: lsp_types::GotoDefinitionResponse = | |
| 2105 | Location::new(cargo_toml_url, Range::default()).into(); | |
| 2149 | let res = lsp_types::DefinitionResponse::Definition(lsp_types::Definition::Location( | |
| 2150 | Location::new(cargo_toml_url, Range::default()), | |
| 2151 | )); | |
| 2106 | 2152 | Ok(Some(res)) |
| 2107 | 2153 | } |
| 2108 | 2154 | |
| ... | ... | @@ -2184,7 +2230,7 @@ fn show_impl_command_link( |
| 2184 | 2230 | let locations: Vec<_> = nav_data |
| 2185 | 2231 | .info |
| 2186 | 2232 | .into_iter() |
| 2187 | .filter_map(|nav| to_proto::location_from_nav(snap, nav).ok()) | |
| 2233 | .filter_map(|nav| to_proto::location_from_nav(snap, &nav).ok()) | |
| 2188 | 2234 | .collect(); |
| 2189 | 2235 | let title = to_proto::implementation_title(locations.len()); |
| 2190 | 2236 | let command = to_proto::command::show_references(title, &uri, position, locations); |
| ... | ... | @@ -2359,7 +2405,7 @@ fn should_skip_target(runnable: &Runnable, cargo_spec: Option<&TargetSpec>) -> b |
| 2359 | 2405 | |
| 2360 | 2406 | fn run_rustfmt( |
| 2361 | 2407 | snap: &GlobalStateSnapshot, |
| 2362 | text_document: TextDocumentIdentifier, | |
| 2408 | text_document: &TextDocumentIdentifier, | |
| 2363 | 2409 | range: Option<lsp_types::Range>, |
| 2364 | 2410 | ) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> { |
| 2365 | 2411 | let file_id = try_default!(from_proto::file_id(snap, &text_document.uri)?); |
| ... | ... | @@ -2425,7 +2471,7 @@ fn run_rustfmt( |
| 2425 | 2471 | .into()); |
| 2426 | 2472 | } |
| 2427 | 2473 | |
| 2428 | let frange = try_default!(from_proto::file_range(snap, &text_document, range)?); | |
| 2474 | let frange = try_default!(from_proto::file_range(snap, text_document, range)?); | |
| 2429 | 2475 | let start_line = line_index.index.line_col(frange.range.start()).line; |
| 2430 | 2476 | let end_line = line_index.index.line_col(frange.range.end()).line; |
| 2431 | 2477 | |
| ... | ... | @@ -2656,20 +2702,26 @@ fn crate_path(root_file_path: &VfsPath) -> Option<VfsPath> { |
| 2656 | 2702 | None |
| 2657 | 2703 | } |
| 2658 | 2704 | |
| 2659 | fn to_url(path: VfsPath) -> Option<Url> { | |
| 2705 | fn to_url(path: VfsPath) -> Option<Uri> { | |
| 2660 | 2706 | let path = path.as_path()?; |
| 2661 | 2707 | let str_path = path.as_os_str().to_str()?; |
| 2662 | Url::from_file_path(str_path).ok() | |
| 2708 | Uri::from_file_path(str_path).ok() | |
| 2663 | 2709 | } |
| 2664 | 2710 | |
| 2665 | fn resource_ops_supported(config: &Config, kind: ResourceOperationKind) -> anyhow::Result<()> { | |
| 2666 | if !matches!(config.workspace_edit_resource_operations(), Some(resops) if resops.contains(&kind)) | |
| 2711 | fn resource_ops_supported(config: &Config, kind: &DocumentChange) -> anyhow::Result<()> { | |
| 2712 | let op = match kind { | |
| 2713 | lsp_types::DocumentChange::CreateFile(_) => ResourceOperationKind::Create, | |
| 2714 | lsp_types::DocumentChange::RenameFile(_) => ResourceOperationKind::Rename, | |
| 2715 | lsp_types::DocumentChange::DeleteFile(_) => ResourceOperationKind::Delete, | |
| 2716 | lsp_types::DocumentChange::TextDocumentEdit(_) => return Ok(()), | |
| 2717 | }; | |
| 2718 | if !matches!(config.workspace_edit_resource_operations(), Some(resops) if resops.contains(&op)) | |
| 2667 | 2719 | { |
| 2668 | 2720 | return Err(LspError::new( |
| 2669 | 2721 | ErrorCode::RequestFailed as i32, |
| 2670 | 2722 | format!( |
| 2671 | 2723 | "Client does not support {} capability.", |
| 2672 | match kind { | |
| 2724 | match op { | |
| 2673 | 2725 | ResourceOperationKind::Create => "create", |
| 2674 | 2726 | ResourceOperationKind::Rename => "rename", |
| 2675 | 2727 | ResourceOperationKind::Delete => "delete", |
| ... | ... | @@ -2682,14 +2734,6 @@ fn resource_ops_supported(config: &Config, kind: ResourceOperationKind) -> anyho |
| 2682 | 2734 | Ok(()) |
| 2683 | 2735 | } |
| 2684 | 2736 | |
| 2685 | fn resolve_resource_op(op: &ResourceOp) -> ResourceOperationKind { | |
| 2686 | match op { | |
| 2687 | ResourceOp::Create(_) => ResourceOperationKind::Create, | |
| 2688 | ResourceOp::Rename(_) => ResourceOperationKind::Rename, | |
| 2689 | ResourceOp::Delete(_) => ResourceOperationKind::Delete, | |
| 2690 | } | |
| 2691 | } | |
| 2692 | ||
| 2693 | 2737 | pub(crate) fn diff(left: &str, right: &str) -> TextEdit { |
| 2694 | 2738 | use dissimilar::Chunk; |
| 2695 | 2739 |
src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs+2-4| ... | ... | @@ -60,6 +60,7 @@ pub mod tracing { |
| 60 | 60 | pub mod config; |
| 61 | 61 | mod global_state; |
| 62 | 62 | pub mod lsp; |
| 63 | ||
| 63 | 64 | use self::lsp::ext as lsp_ext; |
| 64 | 65 | |
| 65 | 66 | #[cfg(test)] |
| ... | ... | @@ -72,10 +73,7 @@ pub use crate::{ |
| 72 | 73 | version::version, |
| 73 | 74 | }; |
| 74 | 75 | |
| 75 | pub fn from_json<T: DeserializeOwned>( | |
| 76 | what: &'static str, | |
| 77 | json: &serde_json::Value, | |
| 78 | ) -> anyhow::Result<T> { | |
| 76 | pub fn from_json<T: DeserializeOwned>(what: &str, json: &serde_json::Value) -> anyhow::Result<T> { | |
| 79 | 77 | serde_json::from_value(json.clone()) |
| 80 | 78 | .map_err(|e| anyhow::format_err!("Failed to deserialize {what}: {e}; {json}")) |
| 81 | 79 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs+82-68| ... | ... | @@ -2,17 +2,18 @@ |
| 2 | 2 | use ide::{CompletionFieldsToResolve, InlayFieldsToResolve}; |
| 3 | 3 | use ide_db::{FxHashSet, line_index::WideEncoding}; |
| 4 | 4 | use lsp_types::{ |
| 5 | CallHierarchyServerCapability, CodeActionKind, CodeActionOptions, CodeActionProviderCapability, | |
| 6 | CodeLensOptions, CompletionOptions, CompletionOptionsCompletionItem, DeclarationCapability, | |
| 7 | DocumentOnTypeFormattingOptions, FileOperationFilter, FileOperationPattern, | |
| 8 | FileOperationPatternKind, FileOperationRegistrationOptions, FoldingRangeProviderCapability, | |
| 9 | HoverProviderCapability, ImplementationProviderCapability, InlayHintOptions, | |
| 10 | InlayHintServerCapabilities, OneOf, PositionEncodingKind, RenameOptions, SaveOptions, | |
| 11 | SelectionRangeProviderCapability, SemanticTokensFullOptions, SemanticTokensLegend, | |
| 12 | SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, | |
| 13 | TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, | |
| 14 | WorkDoneProgressOptions, WorkspaceFileOperationsServerCapabilities, | |
| 15 | WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, | |
| 5 | CallHierarchyProvider, ChangeNotifications, CodeActionKind, CodeActionOptions, | |
| 6 | CodeActionProvider, CodeLensOptions, CompletionOptions, DeclarationProvider, | |
| 7 | DefinitionProvider, DocumentFormattingProvider, DocumentHighlightProvider, | |
| 8 | DocumentOnTypeFormattingOptions, DocumentRangeFormattingProvider, DocumentSymbolProvider, | |
| 9 | FileOperationFilter, FileOperationOptions, FileOperationPattern, FileOperationPatternKind, | |
| 10 | FileOperationRegistrationOptions, FoldingRangeProvider, Full, HoverProvider, | |
| 11 | ImplementationProvider, InlayHintOptions, InlayHintProvider, PositionEncodingKind, | |
| 12 | ReferencesProvider, RenameOptions, RenameProvider, SaveOptions, SelectionRangeProvider, | |
| 13 | SemanticTokensLegend, SemanticTokensOptions, ServerCapabilities, ServerCompletionItemOptions, | |
| 14 | SignatureHelpOptions, TextDocumentSync, TextDocumentSyncKind, TextDocumentSyncOptions, | |
| 15 | TypeDefinitionProvider, WorkDoneProgressOptions, WorkspaceFoldersServerCapabilities, | |
| 16 | WorkspaceOptions, WorkspaceSymbolProvider, | |
| 16 | 17 | }; |
| 17 | 18 | use serde_json::json; |
| 18 | 19 | |
| ... | ... | @@ -32,9 +33,9 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { |
| 32 | 33 | _ => None, |
| 33 | 34 | }, |
| 34 | 35 | }, |
| 35 | text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { | |
| 36 | text_document_sync: Some(TextDocumentSync::Options(TextDocumentSyncOptions { | |
| 36 | 37 | open_close: Some(true), |
| 37 | change: Some(TextDocumentSyncKind::INCREMENTAL), | |
| 38 | change: Some(TextDocumentSyncKind::Incremental), | |
| 38 | 39 | will_save: None, |
| 39 | 40 | will_save_wait_until: None, |
| 40 | 41 | save: if config.caps().did_save_text_document_dynamic_registration() { |
| ... | ... | @@ -43,7 +44,9 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { |
| 43 | 44 | Some(SaveOptions::default().into()) |
| 44 | 45 | }, |
| 45 | 46 | })), |
| 46 | hover_provider: Some(HoverProviderCapability::Simple(true)), | |
| 47 | notebook_document_sync: None, | |
| 48 | selection_range_provider: Some(SelectionRangeProvider::Bool(true)), | |
| 49 | hover_provider: Some(HoverProvider::Bool(true)), | |
| 47 | 50 | completion_provider: Some(CompletionOptions { |
| 48 | 51 | resolve_provider: if config.client_is_neovim() { |
| 49 | 52 | config.has_completion_item_resolve_additionalTextEdits().then_some(true) |
| ... | ... | @@ -65,20 +68,24 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { |
| 65 | 68 | retrigger_characters: None, |
| 66 | 69 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, |
| 67 | 70 | }), |
| 68 | declaration_provider: Some(DeclarationCapability::Simple(true)), | |
| 69 | definition_provider: Some(OneOf::Left(true)), | |
| 70 | type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), | |
| 71 | implementation_provider: Some(ImplementationProviderCapability::Simple(true)), | |
| 72 | references_provider: Some(OneOf::Left(true)), | |
| 73 | document_highlight_provider: Some(OneOf::Left(true)), | |
| 74 | document_symbol_provider: Some(OneOf::Left(true)), | |
| 75 | workspace_symbol_provider: Some(OneOf::Left(true)), | |
| 71 | definition_provider: Some(DefinitionProvider::Bool(true)), | |
| 72 | type_definition_provider: Some(TypeDefinitionProvider::Bool(true)), | |
| 73 | implementation_provider: Some(ImplementationProvider::Bool(true)), | |
| 74 | references_provider: Some(ReferencesProvider::Bool(true)), | |
| 75 | document_highlight_provider: Some(DocumentHighlightProvider::Bool(true)), | |
| 76 | document_symbol_provider: Some(DocumentSymbolProvider::Bool(true)), | |
| 77 | workspace_symbol_provider: Some(WorkspaceSymbolProvider::Bool(true)), | |
| 76 | 78 | code_action_provider: Some(config.caps().code_action_capabilities()), |
| 77 | code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), | |
| 78 | document_formatting_provider: Some(OneOf::Left(true)), | |
| 79 | code_lens_provider: Some(CodeLensOptions { | |
| 80 | resolve_provider: Some(true), | |
| 81 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, | |
| 82 | }), | |
| 83 | document_formatting_provider: Some(DocumentFormattingProvider::Bool(true)), | |
| 79 | 84 | document_range_formatting_provider: match config.rustfmt(None) { |
| 80 | RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)), | |
| 81 | _ => Some(OneOf::Left(false)), | |
| 85 | RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => { | |
| 86 | Some(DocumentRangeFormattingProvider::Bool(true)) | |
| 87 | } | |
| 88 | _ => Some(DocumentRangeFormattingProvider::Bool(false)), | |
| 82 | 89 | }, |
| 83 | 90 | document_on_type_formatting_provider: Some({ |
| 84 | 91 | let mut chars = ide::Analysis::SUPPORTED_TRIGGER_CHARS.iter(); |
| ... | ... | @@ -87,22 +94,21 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { |
| 87 | 94 | more_trigger_character: Some(chars.map(|c| c.to_string()).collect()), |
| 88 | 95 | } |
| 89 | 96 | }), |
| 90 | selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), | |
| 91 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), | |
| 92 | rename_provider: Some(OneOf::Right(RenameOptions { | |
| 97 | rename_provider: Some(RenameProvider::RenameOptions(RenameOptions { | |
| 93 | 98 | prepare_provider: Some(true), |
| 94 | 99 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, |
| 95 | 100 | })), |
| 96 | linked_editing_range_provider: None, | |
| 97 | 101 | document_link_provider: None, |
| 98 | 102 | color_provider: None, |
| 103 | folding_range_provider: Some(FoldingRangeProvider::Bool(true)), | |
| 104 | declaration_provider: Some(DeclarationProvider::Bool(true)), | |
| 99 | 105 | execute_command_provider: None, |
| 100 | workspace: Some(WorkspaceServerCapabilities { | |
| 106 | workspace: Some(WorkspaceOptions { | |
| 101 | 107 | workspace_folders: Some(WorkspaceFoldersServerCapabilities { |
| 102 | 108 | supported: Some(true), |
| 103 | change_notifications: Some(OneOf::Left(true)), | |
| 109 | change_notifications: Some(ChangeNotifications::Bool(true)), | |
| 104 | 110 | }), |
| 105 | file_operations: Some(WorkspaceFileOperationsServerCapabilities { | |
| 111 | file_operations: Some(FileOperationOptions { | |
| 106 | 112 | did_create: None, |
| 107 | 113 | will_create: None, |
| 108 | 114 | did_rename: None, |
| ... | ... | @@ -129,29 +135,45 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { |
| 129 | 135 | did_delete: None, |
| 130 | 136 | will_delete: None, |
| 131 | 137 | }), |
| 138 | text_document_content: None, | |
| 132 | 139 | }), |
| 133 | call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)), | |
| 140 | call_hierarchy_provider: Some(CallHierarchyProvider::Bool(true)), | |
| 134 | 141 | semantic_tokens_provider: Some( |
| 135 | 142 | SemanticTokensOptions { |
| 136 | 143 | legend: SemanticTokensLegend { |
| 137 | token_types: semantic_tokens::SUPPORTED_TYPES.to_vec(), | |
| 138 | token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(), | |
| 144 | token_types: semantic_tokens::SupportedType::iter() | |
| 145 | .map(|semantic_token_type| semantic_token_type.to_string()) | |
| 146 | .collect(), | |
| 147 | token_modifiers: semantic_tokens::SupportedModifiers::iter() | |
| 148 | .map(|semantic_token_type| semantic_token_type.to_string()) | |
| 149 | .collect(), | |
| 139 | 150 | }, |
| 140 | 151 | |
| 141 | full: Some(SemanticTokensFullOptions::Delta { delta: Some(true) }), | |
| 142 | range: Some(true), | |
| 152 | full: Some(Full::SemanticTokensFullDelta(lsp_types::SemanticTokensFullDelta { | |
| 153 | delta: Some(true), | |
| 154 | })), | |
| 155 | range: Some(lsp_types::SemanticTokensOptionsRange::Bool(true)), | |
| 143 | 156 | work_done_progress_options: Default::default(), |
| 144 | 157 | } |
| 145 | 158 | .into(), |
| 146 | 159 | ), |
| 147 | 160 | moniker_provider: None, |
| 148 | inlay_hint_provider: Some(OneOf::Right(InlayHintServerCapabilities::Options( | |
| 149 | InlayHintOptions { | |
| 150 | work_done_progress_options: Default::default(), | |
| 151 | resolve_provider: Some(config.caps().inlay_hints_resolve_provider()), | |
| 152 | }, | |
| 153 | ))), | |
| 161 | linked_editing_range_provider: None, | |
| 154 | 162 | inline_value_provider: None, |
| 163 | inlay_hint_provider: Some(InlayHintProvider::InlayHintOptions(InlayHintOptions { | |
| 164 | work_done_progress_options: Default::default(), | |
| 165 | resolve_provider: Some(config.caps().inlay_hints_resolve_provider()), | |
| 166 | })), | |
| 167 | diagnostic_provider: Some(lsp_types::DiagnosticProvider::DiagnosticOptions( | |
| 168 | lsp_types::DiagnosticOptions { | |
| 169 | identifier: Some("rust-analyzer".to_owned()), | |
| 170 | inter_file_dependencies: true, | |
| 171 | // FIXME | |
| 172 | workspace_diagnostics: false, | |
| 173 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, | |
| 174 | }, | |
| 175 | )), | |
| 176 | inline_completion_provider: None, | |
| 155 | 177 | experimental: Some(json!({ |
| 156 | 178 | "externalDocs": true, |
| 157 | 179 | "hoverRange": true, |
| ... | ... | @@ -168,16 +190,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { |
| 168 | 190 | "ssr": true, |
| 169 | 191 | "workspaceSymbolScopeKindFiltering": true, |
| 170 | 192 | })), |
| 171 | diagnostic_provider: Some(lsp_types::DiagnosticServerCapabilities::Options( | |
| 172 | lsp_types::DiagnosticOptions { | |
| 173 | identifier: Some("rust-analyzer".to_owned()), | |
| 174 | inter_file_dependencies: true, | |
| 175 | // FIXME | |
| 176 | workspace_diagnostics: false, | |
| 177 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, | |
| 178 | }, | |
| 179 | )), | |
| 180 | inline_completion_provider: None, | |
| 193 | type_hierarchy_provider: None, | |
| 181 | 194 | } |
| 182 | 195 | } |
| 183 | 196 | |
| ... | ... | @@ -244,33 +257,34 @@ impl ClientCapabilities { |
| 244 | 257 | })() == Some(true) |
| 245 | 258 | } |
| 246 | 259 | |
| 247 | fn completion_item(&self) -> Option<CompletionOptionsCompletionItem> { | |
| 248 | Some(CompletionOptionsCompletionItem { | |
| 260 | fn completion_item(&self) -> Option<ServerCompletionItemOptions> { | |
| 261 | Some(ServerCompletionItemOptions { | |
| 249 | 262 | label_details_support: Some(self.completion_label_details_support()), |
| 250 | 263 | }) |
| 251 | 264 | } |
| 252 | 265 | |
| 253 | fn code_action_capabilities(&self) -> CodeActionProviderCapability { | |
| 266 | fn code_action_capabilities(&self) -> CodeActionProvider { | |
| 254 | 267 | self.0 |
| 255 | 268 | .text_document |
| 256 | 269 | .as_ref() |
| 257 | 270 | .and_then(|it| it.code_action.as_ref()) |
| 258 | 271 | .and_then(|it| it.code_action_literal_support.as_ref()) |
| 259 | .map_or(CodeActionProviderCapability::Simple(true), |_| { | |
| 260 | CodeActionProviderCapability::Options(CodeActionOptions { | |
| 272 | .map_or(CodeActionProvider::Bool(true), |_| { | |
| 273 | CodeActionProvider::CodeActionOptions(CodeActionOptions { | |
| 261 | 274 | // Advertise support for all built-in CodeActionKinds. |
| 262 | 275 | // Ideally we would base this off of the client capabilities |
| 263 | 276 | // but the client is supposed to fall back gracefully for unknown values. |
| 264 | 277 | code_action_kinds: Some(vec![ |
| 265 | CodeActionKind::EMPTY, | |
| 266 | CodeActionKind::QUICKFIX, | |
| 267 | CodeActionKind::REFACTOR, | |
| 268 | CodeActionKind::REFACTOR_EXTRACT, | |
| 269 | CodeActionKind::REFACTOR_INLINE, | |
| 270 | CodeActionKind::REFACTOR_REWRITE, | |
| 278 | CodeActionKind::Empty, | |
| 279 | CodeActionKind::QuickFix, | |
| 280 | CodeActionKind::Refactor, | |
| 281 | CodeActionKind::RefactorExtract, | |
| 282 | CodeActionKind::RefactorInline, | |
| 283 | CodeActionKind::RefactorRewrite, | |
| 271 | 284 | ]), |
| 272 | 285 | resolve_provider: Some(true), |
| 273 | 286 | work_done_progress_options: Default::default(), |
| 287 | documentation: None, | |
| 274 | 288 | }) |
| 275 | 289 | }) |
| 276 | 290 | } |
| ... | ... | @@ -307,8 +321,8 @@ impl ClientCapabilities { |
| 307 | 321 | } |
| 308 | 322 | |
| 309 | 323 | pub fn did_save_text_document_dynamic_registration(&self) -> bool { |
| 310 | let caps = (|| -> _ { self.0.text_document.as_ref()?.synchronization.clone() })() | |
| 311 | .unwrap_or_default(); | |
| 324 | let caps = | |
| 325 | (|| -> _ { self.0.text_document.as_ref()?.synchronization })().unwrap_or_default(); | |
| 312 | 326 | caps.did_save == Some(true) && caps.dynamic_registration == Some(true) |
| 313 | 327 | } |
| 314 | 328 | |
| ... | ... | @@ -501,7 +515,7 @@ impl ClientCapabilities { |
| 501 | 515 | } |
| 502 | 516 | |
| 503 | 517 | pub fn diagnostics_refresh(&self) -> bool { |
| 504 | (|| -> _ { self.0.workspace.as_ref()?.diagnostic.as_ref()?.refresh_support })() | |
| 518 | (|| -> _ { self.0.workspace.as_ref()?.diagnostics.as_ref()?.refresh_support })() | |
| 505 | 519 | .unwrap_or_default() |
| 506 | 520 | } |
| 507 | 521 |
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs+193-142| ... | ... | @@ -8,17 +8,16 @@ |
| 8 | 8 | |
| 9 | 9 | use std::ops; |
| 10 | 10 | |
| 11 | use lsp_types::Url; | |
| 12 | use lsp_types::request::Request; | |
| 13 | 11 | use lsp_types::{ |
| 14 | CodeActionKind, DocumentOnTypeFormattingParams, PartialResultParams, Position, Range, | |
| 15 | TextDocumentIdentifier, WorkDoneProgressParams, notification::Notification, | |
| 12 | CodeActionKind, DocumentOnTypeFormattingParams, LspNotificationMethod, LspRequestMethod, | |
| 13 | MessageDirection, Notification, PartialResultParams, Position, Range, Request, | |
| 14 | TextDocumentIdentifier, Uri, WorkDoneProgressParams, | |
| 16 | 15 | }; |
| 17 | 16 | use paths::Utf8PathBuf; |
| 18 | 17 | use rustc_hash::FxHashMap; |
| 19 | 18 | use serde::{Deserialize, Serialize}; |
| 20 | 19 | |
| 21 | pub enum InternalTestingFetchConfig {} | |
| 20 | pub enum InternalTestingFetchConfigRequest {} | |
| 22 | 21 | |
| 23 | 22 | #[derive(Deserialize, Serialize, Debug)] |
| 24 | 23 | pub enum InternalTestingFetchConfigOption { |
| ... | ... | @@ -32,11 +31,13 @@ pub enum InternalTestingFetchConfigResponse { |
| 32 | 31 | CheckWorkspace(bool), |
| 33 | 32 | } |
| 34 | 33 | |
| 35 | impl Request for InternalTestingFetchConfig { | |
| 34 | impl Request for InternalTestingFetchConfigRequest { | |
| 36 | 35 | type Params = InternalTestingFetchConfigParams; |
| 37 | 36 | // Option is solely to circumvent Default bound. |
| 38 | 37 | type Result = Option<InternalTestingFetchConfigResponse>; |
| 39 | const METHOD: &'static str = "rust-analyzer-internal/internalTestingFetchConfig"; | |
| 38 | const METHOD: LspRequestMethod = | |
| 39 | LspRequestMethod::new("rust-analyzer-internal/internalTestingFetchConfig"); | |
| 40 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 40 | 41 | } |
| 41 | 42 | |
| 42 | 43 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -45,12 +46,13 @@ pub struct InternalTestingFetchConfigParams { |
| 45 | 46 | pub text_document: Option<TextDocumentIdentifier>, |
| 46 | 47 | pub config: InternalTestingFetchConfigOption, |
| 47 | 48 | } |
| 48 | pub enum AnalyzerStatus {} | |
| 49 | pub enum AnalyzerStatusRequest {} | |
| 49 | 50 | |
| 50 | impl Request for AnalyzerStatus { | |
| 51 | impl Request for AnalyzerStatusRequest { | |
| 51 | 52 | type Params = AnalyzerStatusParams; |
| 52 | 53 | type Result = String; |
| 53 | const METHOD: &'static str = "rust-analyzer/analyzerStatus"; | |
| 54 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/analyzerStatus"); | |
| 55 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 54 | 56 | } |
| 55 | 57 | |
| 56 | 58 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -64,14 +66,15 @@ pub struct AnalyzerStatusParams { |
| 64 | 66 | pub struct CrateInfoResult { |
| 65 | 67 | pub name: Option<String>, |
| 66 | 68 | pub version: Option<String>, |
| 67 | pub path: Url, | |
| 69 | pub path: Uri, | |
| 68 | 70 | } |
| 69 | pub enum FetchDependencyList {} | |
| 71 | pub enum FetchDependencyListRequest {} | |
| 70 | 72 | |
| 71 | impl Request for FetchDependencyList { | |
| 73 | impl Request for FetchDependencyListRequest { | |
| 72 | 74 | type Params = FetchDependencyListParams; |
| 73 | 75 | type Result = FetchDependencyListResult; |
| 74 | const METHOD: &'static str = "rust-analyzer/fetchDependencyList"; | |
| 76 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/fetchDependencyList"); | |
| 77 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 75 | 78 | } |
| 76 | 79 | |
| 77 | 80 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -84,36 +87,40 @@ pub struct FetchDependencyListResult { |
| 84 | 87 | pub crates: Vec<CrateInfoResult>, |
| 85 | 88 | } |
| 86 | 89 | |
| 87 | pub enum MemoryUsage {} | |
| 90 | pub enum MemoryUsageRequest {} | |
| 88 | 91 | |
| 89 | impl Request for MemoryUsage { | |
| 92 | impl Request for MemoryUsageRequest { | |
| 90 | 93 | type Params = (); |
| 91 | 94 | type Result = String; |
| 92 | const METHOD: &'static str = "rust-analyzer/memoryUsage"; | |
| 95 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/memoryUsage"); | |
| 96 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 93 | 97 | } |
| 94 | 98 | |
| 95 | pub enum ReloadWorkspace {} | |
| 99 | pub enum ReloadWorkspaceRequest {} | |
| 96 | 100 | |
| 97 | impl Request for ReloadWorkspace { | |
| 101 | impl Request for ReloadWorkspaceRequest { | |
| 98 | 102 | type Params = (); |
| 99 | 103 | type Result = (); |
| 100 | const METHOD: &'static str = "rust-analyzer/reloadWorkspace"; | |
| 104 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/reloadWorkspace"); | |
| 105 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 101 | 106 | } |
| 102 | 107 | |
| 103 | pub enum RebuildProcMacros {} | |
| 108 | pub enum RebuildProcMacrosRequest {} | |
| 104 | 109 | |
| 105 | impl Request for RebuildProcMacros { | |
| 110 | impl Request for RebuildProcMacrosRequest { | |
| 106 | 111 | type Params = (); |
| 107 | 112 | type Result = (); |
| 108 | const METHOD: &'static str = "rust-analyzer/rebuildProcMacros"; | |
| 113 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/rebuildProcMacros"); | |
| 114 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 109 | 115 | } |
| 110 | 116 | |
| 111 | pub enum ViewSyntaxTree {} | |
| 117 | pub enum ViewSyntaxTreeRequest {} | |
| 112 | 118 | |
| 113 | impl Request for ViewSyntaxTree { | |
| 119 | impl Request for ViewSyntaxTreeRequest { | |
| 114 | 120 | type Params = ViewSyntaxTreeParams; |
| 115 | 121 | type Result = String; |
| 116 | const METHOD: &'static str = "rust-analyzer/viewSyntaxTree"; | |
| 122 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewSyntaxTree"); | |
| 123 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 117 | 124 | } |
| 118 | 125 | |
| 119 | 126 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -122,36 +129,40 @@ pub struct ViewSyntaxTreeParams { |
| 122 | 129 | pub text_document: TextDocumentIdentifier, |
| 123 | 130 | } |
| 124 | 131 | |
| 125 | pub enum ViewHir {} | |
| 132 | pub enum ViewHirRequest {} | |
| 126 | 133 | |
| 127 | impl Request for ViewHir { | |
| 134 | impl Request for ViewHirRequest { | |
| 128 | 135 | type Params = lsp_types::TextDocumentPositionParams; |
| 129 | 136 | type Result = String; |
| 130 | const METHOD: &'static str = "rust-analyzer/viewHir"; | |
| 137 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewHir"); | |
| 138 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 131 | 139 | } |
| 132 | 140 | |
| 133 | pub enum ViewMir {} | |
| 141 | pub enum ViewMirRequest {} | |
| 134 | 142 | |
| 135 | impl Request for ViewMir { | |
| 143 | impl Request for ViewMirRequest { | |
| 136 | 144 | type Params = lsp_types::TextDocumentPositionParams; |
| 137 | 145 | type Result = String; |
| 138 | const METHOD: &'static str = "rust-analyzer/viewMir"; | |
| 146 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewMir"); | |
| 147 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 139 | 148 | } |
| 140 | 149 | |
| 141 | pub enum InterpretFunction {} | |
| 150 | pub enum InterpretFunctionRequest {} | |
| 142 | 151 | |
| 143 | impl Request for InterpretFunction { | |
| 152 | impl Request for InterpretFunctionRequest { | |
| 144 | 153 | type Params = lsp_types::TextDocumentPositionParams; |
| 145 | 154 | type Result = String; |
| 146 | const METHOD: &'static str = "rust-analyzer/interpretFunction"; | |
| 155 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/interpretFunction"); | |
| 156 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 147 | 157 | } |
| 148 | 158 | |
| 149 | pub enum ViewFileText {} | |
| 159 | pub enum ViewFileTextRequest {} | |
| 150 | 160 | |
| 151 | impl Request for ViewFileText { | |
| 161 | impl Request for ViewFileTextRequest { | |
| 152 | 162 | type Params = lsp_types::TextDocumentIdentifier; |
| 153 | 163 | type Result = String; |
| 154 | const METHOD: &'static str = "rust-analyzer/viewFileText"; | |
| 164 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewFileText"); | |
| 165 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 155 | 166 | } |
| 156 | 167 | |
| 157 | 168 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -161,12 +172,13 @@ pub struct ViewCrateGraphParams { |
| 161 | 172 | pub full: bool, |
| 162 | 173 | } |
| 163 | 174 | |
| 164 | pub enum ViewCrateGraph {} | |
| 175 | pub enum ViewCrateGraphRequest {} | |
| 165 | 176 | |
| 166 | impl Request for ViewCrateGraph { | |
| 177 | impl Request for ViewCrateGraphRequest { | |
| 167 | 178 | type Params = ViewCrateGraphParams; |
| 168 | 179 | type Result = String; |
| 169 | const METHOD: &'static str = "rust-analyzer/viewCrateGraph"; | |
| 180 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewCrateGraph"); | |
| 181 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 170 | 182 | } |
| 171 | 183 | |
| 172 | 184 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -175,12 +187,13 @@ pub struct ViewItemTreeParams { |
| 175 | 187 | pub text_document: TextDocumentIdentifier, |
| 176 | 188 | } |
| 177 | 189 | |
| 178 | pub enum ViewItemTree {} | |
| 190 | pub enum ViewItemTreeRequest {} | |
| 179 | 191 | |
| 180 | impl Request for ViewItemTree { | |
| 192 | impl Request for ViewItemTreeRequest { | |
| 181 | 193 | type Params = ViewItemTreeParams; |
| 182 | 194 | type Result = String; |
| 183 | const METHOD: &'static str = "rust-analyzer/viewItemTree"; | |
| 195 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewItemTree"); | |
| 196 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 184 | 197 | } |
| 185 | 198 | |
| 186 | 199 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -218,19 +231,22 @@ pub struct DiscoverTestResults { |
| 218 | 231 | pub scope_file: Option<Vec<TextDocumentIdentifier>>, |
| 219 | 232 | } |
| 220 | 233 | |
| 221 | pub enum DiscoverTest {} | |
| 234 | pub enum DiscoverTestRequest {} | |
| 222 | 235 | |
| 223 | impl Request for DiscoverTest { | |
| 236 | impl Request for DiscoverTestRequest { | |
| 224 | 237 | type Params = DiscoverTestParams; |
| 225 | 238 | type Result = DiscoverTestResults; |
| 226 | const METHOD: &'static str = "experimental/discoverTest"; | |
| 239 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/discoverTest"); | |
| 240 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 227 | 241 | } |
| 228 | 242 | |
| 229 | pub enum DiscoveredTests {} | |
| 243 | pub enum DiscoveredTestsNotification {} | |
| 230 | 244 | |
| 231 | impl Notification for DiscoveredTests { | |
| 245 | impl Notification for DiscoveredTestsNotification { | |
| 232 | 246 | type Params = DiscoverTestResults; |
| 233 | const METHOD: &'static str = "experimental/discoveredTests"; | |
| 247 | const METHOD: LspNotificationMethod = | |
| 248 | LspNotificationMethod::new("experimental/discoveredTests"); | |
| 249 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 234 | 250 | } |
| 235 | 251 | |
| 236 | 252 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -240,33 +256,38 @@ pub struct RunTestParams { |
| 240 | 256 | pub exclude: Option<Vec<String>>, |
| 241 | 257 | } |
| 242 | 258 | |
| 243 | pub enum RunTest {} | |
| 259 | pub enum RunTestRequest {} | |
| 244 | 260 | |
| 245 | impl Request for RunTest { | |
| 261 | impl Request for RunTestRequest { | |
| 246 | 262 | type Params = RunTestParams; |
| 247 | 263 | type Result = (); |
| 248 | const METHOD: &'static str = "experimental/runTest"; | |
| 264 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/runTest"); | |
| 265 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 249 | 266 | } |
| 250 | 267 | |
| 251 | pub enum EndRunTest {} | |
| 268 | pub enum EndRunTestNotification {} | |
| 252 | 269 | |
| 253 | impl Notification for EndRunTest { | |
| 270 | impl Notification for EndRunTestNotification { | |
| 254 | 271 | type Params = (); |
| 255 | const METHOD: &'static str = "experimental/endRunTest"; | |
| 272 | const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/endRunTest"); | |
| 273 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 256 | 274 | } |
| 257 | 275 | |
| 258 | pub enum AppendOutputToRunTest {} | |
| 276 | pub enum AppendOutputToRunTestNotification {} | |
| 259 | 277 | |
| 260 | impl Notification for AppendOutputToRunTest { | |
| 278 | impl Notification for AppendOutputToRunTestNotification { | |
| 261 | 279 | type Params = String; |
| 262 | const METHOD: &'static str = "experimental/appendOutputToRunTest"; | |
| 280 | const METHOD: LspNotificationMethod = | |
| 281 | LspNotificationMethod::new("experimental/appendOutputToRunTest"); | |
| 282 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 263 | 283 | } |
| 264 | 284 | |
| 265 | pub enum AbortRunTest {} | |
| 285 | pub enum AbortRunTestNotification {} | |
| 266 | 286 | |
| 267 | impl Notification for AbortRunTest { | |
| 287 | impl Notification for AbortRunTestNotification { | |
| 268 | 288 | type Params = (); |
| 269 | const METHOD: &'static str = "experimental/abortRunTest"; | |
| 289 | const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/abortRunTest"); | |
| 290 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 270 | 291 | } |
| 271 | 292 | |
| 272 | 293 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -286,19 +307,22 @@ pub struct ChangeTestStateParams { |
| 286 | 307 | pub state: TestState, |
| 287 | 308 | } |
| 288 | 309 | |
| 289 | pub enum ChangeTestState {} | |
| 310 | pub enum ChangeTestStateNotification {} | |
| 290 | 311 | |
| 291 | impl Notification for ChangeTestState { | |
| 312 | impl Notification for ChangeTestStateNotification { | |
| 292 | 313 | type Params = ChangeTestStateParams; |
| 293 | const METHOD: &'static str = "experimental/changeTestState"; | |
| 314 | const METHOD: LspNotificationMethod = | |
| 315 | LspNotificationMethod::new("experimental/changeTestState"); | |
| 316 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 294 | 317 | } |
| 295 | 318 | |
| 296 | pub enum ExpandMacro {} | |
| 319 | pub enum ExpandMacroRequest {} | |
| 297 | 320 | |
| 298 | impl Request for ExpandMacro { | |
| 321 | impl Request for ExpandMacroRequest { | |
| 299 | 322 | type Params = ExpandMacroParams; |
| 300 | 323 | type Result = Option<ExpandedMacro>; |
| 301 | const METHOD: &'static str = "rust-analyzer/expandMacro"; | |
| 324 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/expandMacro"); | |
| 325 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 302 | 326 | } |
| 303 | 327 | |
| 304 | 328 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -315,12 +339,14 @@ pub struct ExpandedMacro { |
| 315 | 339 | pub expansion: String, |
| 316 | 340 | } |
| 317 | 341 | |
| 318 | pub enum ViewRecursiveMemoryLayout {} | |
| 342 | pub enum ViewRecursiveMemoryLayoutRequest {} | |
| 319 | 343 | |
| 320 | impl Request for ViewRecursiveMemoryLayout { | |
| 344 | impl Request for ViewRecursiveMemoryLayoutRequest { | |
| 321 | 345 | type Params = lsp_types::TextDocumentPositionParams; |
| 322 | 346 | type Result = Option<RecursiveMemoryLayout>; |
| 323 | const METHOD: &'static str = "rust-analyzer/viewRecursiveMemoryLayout"; | |
| 347 | const METHOD: LspRequestMethod = | |
| 348 | LspRequestMethod::new("rust-analyzer/viewRecursiveMemoryLayout"); | |
| 349 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 324 | 350 | } |
| 325 | 351 | |
| 326 | 352 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -342,32 +368,38 @@ pub struct MemoryLayoutNode { |
| 342 | 368 | pub children_len: u64, |
| 343 | 369 | } |
| 344 | 370 | |
| 345 | pub enum CancelFlycheck {} | |
| 371 | pub enum CancelFlycheckNotification {} | |
| 346 | 372 | |
| 347 | impl Notification for CancelFlycheck { | |
| 373 | impl Notification for CancelFlycheckNotification { | |
| 348 | 374 | type Params = (); |
| 349 | const METHOD: &'static str = "rust-analyzer/cancelFlycheck"; | |
| 375 | const METHOD: LspNotificationMethod = | |
| 376 | LspNotificationMethod::new("rust-analyzer/cancelFlycheck"); | |
| 377 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 350 | 378 | } |
| 351 | 379 | |
| 352 | pub enum RunFlycheck {} | |
| 380 | pub enum RunFlycheckNotification {} | |
| 353 | 381 | |
| 354 | impl Notification for RunFlycheck { | |
| 382 | impl Notification for RunFlycheckNotification { | |
| 355 | 383 | type Params = RunFlycheckParams; |
| 356 | const METHOD: &'static str = "rust-analyzer/runFlycheck"; | |
| 384 | const METHOD: LspNotificationMethod = LspNotificationMethod::new("rust-analyzer/runFlycheck"); | |
| 385 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 357 | 386 | } |
| 358 | 387 | |
| 359 | pub enum ClearFlycheck {} | |
| 388 | pub enum ClearFlycheckNotification {} | |
| 360 | 389 | |
| 361 | impl Notification for ClearFlycheck { | |
| 390 | impl Notification for ClearFlycheckNotification { | |
| 362 | 391 | type Params = (); |
| 363 | const METHOD: &'static str = "rust-analyzer/clearFlycheck"; | |
| 392 | const METHOD: LspNotificationMethod = LspNotificationMethod::new("rust-analyzer/clearFlycheck"); | |
| 393 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 364 | 394 | } |
| 365 | 395 | |
| 366 | pub enum OpenServerLogs {} | |
| 396 | pub enum OpenServerLogsNotification {} | |
| 367 | 397 | |
| 368 | impl Notification for OpenServerLogs { | |
| 398 | impl Notification for OpenServerLogsNotification { | |
| 369 | 399 | type Params = (); |
| 370 | const METHOD: &'static str = "rust-analyzer/openServerLogs"; | |
| 400 | const METHOD: LspNotificationMethod = | |
| 401 | LspNotificationMethod::new("rust-analyzer/openServerLogs"); | |
| 402 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 371 | 403 | } |
| 372 | 404 | |
| 373 | 405 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -376,12 +408,13 @@ pub struct RunFlycheckParams { |
| 376 | 408 | pub text_document: Option<TextDocumentIdentifier>, |
| 377 | 409 | } |
| 378 | 410 | |
| 379 | pub enum MatchingBrace {} | |
| 411 | pub enum MatchingBraceRequest {} | |
| 380 | 412 | |
| 381 | impl Request for MatchingBrace { | |
| 413 | impl Request for MatchingBraceRequest { | |
| 382 | 414 | type Params = MatchingBraceParams; |
| 383 | 415 | type Result = Vec<Position>; |
| 384 | const METHOD: &'static str = "experimental/matchingBrace"; | |
| 416 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/matchingBrace"); | |
| 417 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 385 | 418 | } |
| 386 | 419 | |
| 387 | 420 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -391,28 +424,31 @@ pub struct MatchingBraceParams { |
| 391 | 424 | pub positions: Vec<Position>, |
| 392 | 425 | } |
| 393 | 426 | |
| 394 | pub enum ParentModule {} | |
| 427 | pub enum ParentModuleRequest {} | |
| 395 | 428 | |
| 396 | impl Request for ParentModule { | |
| 429 | impl Request for ParentModuleRequest { | |
| 397 | 430 | type Params = lsp_types::TextDocumentPositionParams; |
| 398 | type Result = Option<lsp_types::GotoDefinitionResponse>; | |
| 399 | const METHOD: &'static str = "experimental/parentModule"; | |
| 431 | type Result = Option<lsp_types::DefinitionResponse>; | |
| 432 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/parentModule"); | |
| 433 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 400 | 434 | } |
| 401 | 435 | |
| 402 | pub enum ChildModules {} | |
| 436 | pub enum ChildModulesRequest {} | |
| 403 | 437 | |
| 404 | impl Request for ChildModules { | |
| 438 | impl Request for ChildModulesRequest { | |
| 405 | 439 | type Params = lsp_types::TextDocumentPositionParams; |
| 406 | type Result = Option<lsp_types::GotoDefinitionResponse>; | |
| 407 | const METHOD: &'static str = "experimental/childModules"; | |
| 440 | type Result = Option<lsp_types::DefinitionResponse>; | |
| 441 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/childModules"); | |
| 442 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 408 | 443 | } |
| 409 | 444 | |
| 410 | pub enum JoinLines {} | |
| 445 | pub enum JoinLinesRequest {} | |
| 411 | 446 | |
| 412 | impl Request for JoinLines { | |
| 447 | impl Request for JoinLinesRequest { | |
| 413 | 448 | type Params = JoinLinesParams; |
| 414 | 449 | type Result = Vec<lsp_types::TextEdit>; |
| 415 | const METHOD: &'static str = "experimental/joinLines"; | |
| 450 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/joinLines"); | |
| 451 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 416 | 452 | } |
| 417 | 453 | |
| 418 | 454 | #[derive(Deserialize, Serialize, Debug)] |
| ... | ... | @@ -422,20 +458,22 @@ pub struct JoinLinesParams { |
| 422 | 458 | pub ranges: Vec<Range>, |
| 423 | 459 | } |
| 424 | 460 | |
| 425 | pub enum OnEnter {} | |
| 461 | pub enum OnEnterRequest {} | |
| 426 | 462 | |
| 427 | impl Request for OnEnter { | |
| 463 | impl Request for OnEnterRequest { | |
| 428 | 464 | type Params = lsp_types::TextDocumentPositionParams; |
| 429 | 465 | type Result = Option<Vec<SnippetTextEdit>>; |
| 430 | const METHOD: &'static str = "experimental/onEnter"; | |
| 466 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/onEnter"); | |
| 467 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 431 | 468 | } |
| 432 | 469 | |
| 433 | pub enum Runnables {} | |
| 470 | pub enum RunnablesRequest {} | |
| 434 | 471 | |
| 435 | impl Request for Runnables { | |
| 472 | impl Request for RunnablesRequest { | |
| 436 | 473 | type Params = RunnablesParams; |
| 437 | 474 | type Result = Vec<Runnable>; |
| 438 | const METHOD: &'static str = "experimental/runnables"; | |
| 475 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/runnables"); | |
| 476 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 439 | 477 | } |
| 440 | 478 | |
| 441 | 479 | #[derive(Serialize, Deserialize, Debug, Clone)] |
| ... | ... | @@ -488,12 +526,13 @@ pub struct ShellRunnableArgs { |
| 488 | 526 | pub args: Vec<String>, |
| 489 | 527 | } |
| 490 | 528 | |
| 491 | pub enum RelatedTests {} | |
| 529 | pub enum RelatedTestsRequest {} | |
| 492 | 530 | |
| 493 | impl Request for RelatedTests { | |
| 531 | impl Request for RelatedTestsRequest { | |
| 494 | 532 | type Params = lsp_types::TextDocumentPositionParams; |
| 495 | 533 | type Result = Vec<TestInfo>; |
| 496 | const METHOD: &'static str = "rust-analyzer/relatedTests"; | |
| 534 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/relatedTests"); | |
| 535 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 497 | 536 | } |
| 498 | 537 | |
| 499 | 538 | #[derive(Debug, Deserialize, Serialize)] |
| ... | ... | @@ -501,12 +540,13 @@ pub struct TestInfo { |
| 501 | 540 | pub runnable: Runnable, |
| 502 | 541 | } |
| 503 | 542 | |
| 504 | pub enum Ssr {} | |
| 543 | pub enum SsrRequest {} | |
| 505 | 544 | |
| 506 | impl Request for Ssr { | |
| 545 | impl Request for SsrRequest { | |
| 507 | 546 | type Params = SsrParams; |
| 508 | 547 | type Result = lsp_types::WorkspaceEdit; |
| 509 | const METHOD: &'static str = "experimental/ssr"; | |
| 548 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/ssr"); | |
| 549 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 510 | 550 | } |
| 511 | 551 | |
| 512 | 552 | #[derive(Debug, Deserialize, Serialize)] |
| ... | ... | @@ -528,7 +568,8 @@ pub enum ServerStatusNotification {} |
| 528 | 568 | |
| 529 | 569 | impl Notification for ServerStatusNotification { |
| 530 | 570 | type Params = ServerStatusParams; |
| 531 | const METHOD: &'static str = "experimental/serverStatus"; | |
| 571 | const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/serverStatus"); | |
| 572 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 532 | 573 | } |
| 533 | 574 | |
| 534 | 575 | #[derive(Deserialize, Serialize, PartialEq, Eq, Clone)] |
| ... | ... | @@ -562,7 +603,8 @@ pub enum CodeActionRequest {} |
| 562 | 603 | impl Request for CodeActionRequest { |
| 563 | 604 | type Params = lsp_types::CodeActionParams; |
| 564 | 605 | type Result = Option<Vec<CodeAction>>; |
| 565 | const METHOD: &'static str = "textDocument/codeAction"; | |
| 606 | const METHOD: LspRequestMethod = LspRequestMethod::new("textDocument/codeAction"); | |
| 607 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 566 | 608 | } |
| 567 | 609 | |
| 568 | 610 | pub enum CodeActionResolveRequest {} |
| ... | ... | @@ -570,7 +612,8 @@ pub enum CodeActionResolveRequest {} |
| 570 | 612 | impl Request for CodeActionResolveRequest { |
| 571 | 613 | type Params = CodeAction; |
| 572 | 614 | type Result = CodeAction; |
| 573 | const METHOD: &'static str = "codeAction/resolve"; | |
| 615 | const METHOD: LspRequestMethod = LspRequestMethod::new("codeAction/resolve"); | |
| 616 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 574 | 617 | } |
| 575 | 618 | |
| 576 | 619 | #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)] |
| ... | ... | @@ -604,7 +647,7 @@ pub struct CodeActionData { |
| 604 | 647 | #[serde(rename_all = "camelCase")] |
| 605 | 648 | pub struct SnippetWorkspaceEdit { |
| 606 | 649 | #[serde(skip_serializing_if = "Option::is_none")] |
| 607 | pub changes: Option<FxHashMap<lsp_types::Url, Vec<lsp_types::TextEdit>>>, | |
| 650 | pub changes: Option<FxHashMap<Uri, Vec<lsp_types::TextEdit>>>, | |
| 608 | 651 | #[serde(skip_serializing_if = "Option::is_none")] |
| 609 | 652 | pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>, |
| 610 | 653 | #[serde(skip_serializing_if = "Option::is_none")] |
| ... | ... | @@ -619,7 +662,7 @@ pub struct SnippetWorkspaceEdit { |
| 619 | 662 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] |
| 620 | 663 | #[serde(untagged, rename_all = "lowercase")] |
| 621 | 664 | pub enum SnippetDocumentChangeOperation { |
| 622 | Op(lsp_types::ResourceOp), | |
| 665 | Change(lsp_types::DocumentChange), | |
| 623 | 666 | Edit(SnippetTextDocumentEdit), |
| 624 | 667 | } |
| 625 | 668 | |
| ... | ... | @@ -647,7 +690,8 @@ pub enum HoverRequest {} |
| 647 | 690 | impl Request for HoverRequest { |
| 648 | 691 | type Params = HoverParams; |
| 649 | 692 | type Result = Option<Hover>; |
| 650 | const METHOD: &'static str = lsp_types::request::HoverRequest::METHOD; | |
| 693 | const METHOD: LspRequestMethod = lsp_types::HoverRequest::METHOD; | |
| 694 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 651 | 695 | } |
| 652 | 696 | |
| 653 | 697 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] |
| ... | ... | @@ -691,18 +735,19 @@ pub struct CommandLink { |
| 691 | 735 | pub tooltip: Option<String>, |
| 692 | 736 | } |
| 693 | 737 | |
| 694 | pub enum ExternalDocs {} | |
| 738 | pub enum ExternalDocsRequest {} | |
| 695 | 739 | |
| 696 | impl Request for ExternalDocs { | |
| 740 | impl Request for ExternalDocsRequest { | |
| 697 | 741 | type Params = lsp_types::TextDocumentPositionParams; |
| 698 | 742 | type Result = ExternalDocsResponse; |
| 699 | const METHOD: &'static str = "experimental/externalDocs"; | |
| 743 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/externalDocs"); | |
| 744 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 700 | 745 | } |
| 701 | 746 | |
| 702 | 747 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] |
| 703 | 748 | #[serde(untagged)] |
| 704 | 749 | pub enum ExternalDocsResponse { |
| 705 | Simple(Option<lsp_types::Url>), | |
| 750 | Simple(Option<lsp_types::Uri>), | |
| 706 | 751 | WithLocal(ExternalDocsPair), |
| 707 | 752 | } |
| 708 | 753 | |
| ... | ... | @@ -715,16 +760,17 @@ impl Default for ExternalDocsResponse { |
| 715 | 760 | #[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)] |
| 716 | 761 | #[serde(rename_all = "camelCase")] |
| 717 | 762 | pub struct ExternalDocsPair { |
| 718 | pub web: Option<lsp_types::Url>, | |
| 719 | pub local: Option<lsp_types::Url>, | |
| 763 | pub web: Option<lsp_types::Uri>, | |
| 764 | pub local: Option<lsp_types::Uri>, | |
| 720 | 765 | } |
| 721 | 766 | |
| 722 | pub enum OpenCargoToml {} | |
| 767 | pub enum OpenCargoTomlRequest {} | |
| 723 | 768 | |
| 724 | impl Request for OpenCargoToml { | |
| 769 | impl Request for OpenCargoTomlRequest { | |
| 725 | 770 | type Params = OpenCargoTomlParams; |
| 726 | type Result = Option<lsp_types::GotoDefinitionResponse>; | |
| 727 | const METHOD: &'static str = "experimental/openCargoToml"; | |
| 771 | type Result = Option<lsp_types::DefinitionResponse>; | |
| 772 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/openCargoToml"); | |
| 773 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 728 | 774 | } |
| 729 | 775 | |
| 730 | 776 | #[derive(Serialize, Deserialize, Debug)] |
| ... | ... | @@ -744,16 +790,17 @@ pub struct CodeLensResolveData { |
| 744 | 790 | #[derive(Debug, Serialize, Deserialize)] |
| 745 | 791 | #[serde(rename_all = "camelCase")] |
| 746 | 792 | pub enum CodeLensResolveDataKind { |
| 747 | Impls(lsp_types::request::GotoImplementationParams), | |
| 793 | Impls(lsp_types::ImplementationParams), | |
| 748 | 794 | References(lsp_types::TextDocumentPositionParams), |
| 749 | 795 | } |
| 750 | 796 | |
| 751 | pub enum MoveItem {} | |
| 797 | pub enum MoveItemRequest {} | |
| 752 | 798 | |
| 753 | impl Request for MoveItem { | |
| 799 | impl Request for MoveItemRequest { | |
| 754 | 800 | type Params = MoveItemParams; |
| 755 | 801 | type Result = Vec<SnippetTextEdit>; |
| 756 | const METHOD: &'static str = "experimental/moveItem"; | |
| 802 | const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/moveItem"); | |
| 803 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 757 | 804 | } |
| 758 | 805 | |
| 759 | 806 | #[derive(Serialize, Deserialize, Debug)] |
| ... | ... | @@ -771,12 +818,13 @@ pub enum MoveItemDirection { |
| 771 | 818 | } |
| 772 | 819 | |
| 773 | 820 | #[derive(Debug)] |
| 774 | pub enum WorkspaceSymbol {} | |
| 821 | pub enum WorkspaceSymbolRequest {} | |
| 775 | 822 | |
| 776 | impl Request for WorkspaceSymbol { | |
| 823 | impl Request for WorkspaceSymbolRequest { | |
| 777 | 824 | type Params = WorkspaceSymbolParams; |
| 778 | 825 | type Result = Option<lsp_types::WorkspaceSymbolResponse>; |
| 779 | const METHOD: &'static str = "workspace/symbol"; | |
| 826 | const METHOD: LspRequestMethod = LspRequestMethod::new("workspace/symbol"); | |
| 827 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 780 | 828 | } |
| 781 | 829 | |
| 782 | 830 | #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] |
| ... | ... | @@ -812,15 +860,16 @@ pub enum WorkspaceSymbolSearchKind { |
| 812 | 860 | |
| 813 | 861 | /// The document on type formatting request is sent from the client to |
| 814 | 862 | /// the server to format parts of the document during typing. This is |
| 815 | /// almost same as lsp_types::request::OnTypeFormatting, but the | |
| 863 | /// almost same as [`lsp_types::DocumentOnTypeFormattingRequest`], but the | |
| 816 | 864 | /// result has SnippetTextEdit in it instead of TextEdit. |
| 817 | 865 | #[derive(Debug)] |
| 818 | pub enum OnTypeFormatting {} | |
| 866 | pub enum DocumentOnTypeFormattingRequest {} | |
| 819 | 867 | |
| 820 | impl Request for OnTypeFormatting { | |
| 868 | impl Request for DocumentOnTypeFormattingRequest { | |
| 821 | 869 | type Params = DocumentOnTypeFormattingParams; |
| 822 | 870 | type Result = Option<Vec<SnippetTextEdit>>; |
| 823 | const METHOD: &'static str = "textDocument/onTypeFormatting"; | |
| 871 | const METHOD: LspRequestMethod = LspRequestMethod::new("textDocument/onTypeFormatting"); | |
| 872 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 824 | 873 | } |
| 825 | 874 | |
| 826 | 875 | #[derive(Debug, Serialize, Deserialize)] |
| ... | ... | @@ -859,7 +908,7 @@ pub struct ClientCommandOptions { |
| 859 | 908 | pub commands: Vec<String>, |
| 860 | 909 | } |
| 861 | 910 | |
| 862 | pub enum EvaluatePredicate {} | |
| 911 | pub enum EvaluatePredicateRequest {} | |
| 863 | 912 | |
| 864 | 913 | #[derive(Deserialize, Serialize, Debug)] |
| 865 | 914 | #[serde(rename_all = "camelCase")] |
| ... | ... | @@ -886,13 +935,14 @@ pub enum PredicateEvaluationStatus { |
| 886 | 935 | Unsupported, |
| 887 | 936 | } |
| 888 | 937 | |
| 889 | impl Request for EvaluatePredicate { | |
| 938 | impl Request for EvaluatePredicateRequest { | |
| 890 | 939 | type Params = EvaluatePredicateParams; |
| 891 | 940 | type Result = EvaluatePredicateResult; |
| 892 | const METHOD: &'static str = "rust-analyzer/evaluatePredicate"; | |
| 941 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/evaluatePredicate"); | |
| 942 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 893 | 943 | } |
| 894 | 944 | |
| 895 | pub enum GetFailedObligations {} | |
| 945 | pub enum GetFailedObligationsRequest {} | |
| 896 | 946 | |
| 897 | 947 | #[derive(Deserialize, Serialize, Debug)] |
| 898 | 948 | #[serde(rename_all = "camelCase")] |
| ... | ... | @@ -901,10 +951,11 @@ pub struct GetFailedObligationsParams { |
| 901 | 951 | pub position: Position, |
| 902 | 952 | } |
| 903 | 953 | |
| 904 | impl Request for GetFailedObligations { | |
| 954 | impl Request for GetFailedObligationsRequest { | |
| 905 | 955 | type Params = GetFailedObligationsParams; |
| 906 | 956 | type Result = String; |
| 907 | const METHOD: &'static str = "rust-analyzer/getFailedObligations"; | |
| 957 | const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/getFailedObligations"); | |
| 958 | const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; | |
| 908 | 959 | } |
| 909 | 960 | |
| 910 | 961 | #[cfg(test)] |
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs+14-13| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | //! Conversion lsp_types types to rust-analyzer specific ones. |
| 2 | ||
| 2 | 3 | use anyhow::format_err; |
| 3 | 4 | use ide::{Annotation, AnnotationKind, AssistKind, LineCol}; |
| 4 | 5 | use ide_db::{FileId, FilePosition, FileRange, line_index::WideLineCol}; |
| ... | ... | @@ -12,12 +13,12 @@ use crate::{ |
| 12 | 13 | lsp_ext, try_default, |
| 13 | 14 | }; |
| 14 | 15 | |
| 15 | pub(crate) fn abs_path(url: &lsp_types::Url) -> anyhow::Result<AbsPathBuf> { | |
| 16 | pub(crate) fn abs_path(url: &lsp_types::Uri) -> anyhow::Result<AbsPathBuf> { | |
| 16 | 17 | let path = url.to_file_path().map_err(|()| anyhow::format_err!("url is not a file"))?; |
| 17 | 18 | Ok(AbsPathBuf::try_from(Utf8PathBuf::from_path_buf(path).unwrap()).unwrap()) |
| 18 | 19 | } |
| 19 | 20 | |
| 20 | pub(crate) fn vfs_path(url: &lsp_types::Url) -> anyhow::Result<vfs::VfsPath> { | |
| 21 | pub(crate) fn vfs_path(url: &lsp_types::Uri) -> anyhow::Result<vfs::VfsPath> { | |
| 21 | 22 | abs_path(url).map(vfs::VfsPath::from) |
| 22 | 23 | } |
| 23 | 24 | |
| ... | ... | @@ -65,7 +66,7 @@ pub(crate) fn text_range( |
| 65 | 66 | /// Returns `None` if the file was excluded. |
| 66 | 67 | pub(crate) fn file_id( |
| 67 | 68 | snap: &GlobalStateSnapshot, |
| 68 | url: &lsp_types::Url, | |
| 69 | url: &lsp_types::Uri, | |
| 69 | 70 | ) -> anyhow::Result<Option<FileId>> { |
| 70 | 71 | snap.url_to_file_id(url) |
| 71 | 72 | } |
| ... | ... | @@ -73,7 +74,7 @@ pub(crate) fn file_id( |
| 73 | 74 | /// Returns `None` if the file was excluded. |
| 74 | 75 | pub(crate) fn file_position( |
| 75 | 76 | snap: &GlobalStateSnapshot, |
| 76 | tdpp: lsp_types::TextDocumentPositionParams, | |
| 77 | tdpp: &lsp_types::TextDocumentPositionParams, | |
| 77 | 78 | ) -> anyhow::Result<Option<FilePosition>> { |
| 78 | 79 | let file_id = try_default!(file_id(snap, &tdpp.text_document.uri)?); |
| 79 | 80 | let line_index = snap.file_line_index(file_id)?; |
| ... | ... | @@ -93,7 +94,7 @@ pub(crate) fn file_range( |
| 93 | 94 | /// Returns `None` if the file was excluded. |
| 94 | 95 | pub(crate) fn file_range_uri( |
| 95 | 96 | snap: &GlobalStateSnapshot, |
| 96 | document: &lsp_types::Url, | |
| 97 | document: &lsp_types::Uri, | |
| 97 | 98 | range: lsp_types::Range, |
| 98 | 99 | ) -> anyhow::Result<Option<FileRange>> { |
| 99 | 100 | let file_id = try_default!(file_id(snap, document)?); |
| ... | ... | @@ -104,12 +105,12 @@ pub(crate) fn file_range_uri( |
| 104 | 105 | |
| 105 | 106 | pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> { |
| 106 | 107 | let assist_kind = match &kind { |
| 107 | k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::Generate, | |
| 108 | k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix, | |
| 109 | k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor, | |
| 110 | k if k == &lsp_types::CodeActionKind::REFACTOR_EXTRACT => AssistKind::RefactorExtract, | |
| 111 | k if k == &lsp_types::CodeActionKind::REFACTOR_INLINE => AssistKind::RefactorInline, | |
| 112 | k if k == &lsp_types::CodeActionKind::REFACTOR_REWRITE => AssistKind::RefactorRewrite, | |
| 108 | k if k == &lsp_types::CodeActionKind::Empty => AssistKind::Generate, | |
| 109 | k if k == &lsp_types::CodeActionKind::QuickFix => AssistKind::QuickFix, | |
| 110 | k if k == &lsp_types::CodeActionKind::Refactor => AssistKind::Refactor, | |
| 111 | k if k == &lsp_types::CodeActionKind::RefactorExtract => AssistKind::RefactorExtract, | |
| 112 | k if k == &lsp_types::CodeActionKind::RefactorInline => AssistKind::RefactorInline, | |
| 113 | k if k == &lsp_types::CodeActionKind::RefactorRewrite => AssistKind::RefactorRewrite, | |
| 113 | 114 | _ => return None, |
| 114 | 115 | }; |
| 115 | 116 | |
| ... | ... | @@ -130,7 +131,7 @@ pub(crate) fn annotation( |
| 130 | 131 | return Ok(None); |
| 131 | 132 | } |
| 132 | 133 | let pos @ FilePosition { file_id, .. } = |
| 133 | try_default!(file_position(snap, params.text_document_position_params)?); | |
| 134 | try_default!(file_position(snap, &params.text_document_position_params)?); | |
| 134 | 135 | let line_index = snap.file_line_index(file_id)?; |
| 135 | 136 | |
| 136 | 137 | Ok(Annotation { |
| ... | ... | @@ -142,7 +143,7 @@ pub(crate) fn annotation( |
| 142 | 143 | if snap.url_file_version(&params.text_document.uri) != Some(data.version) { |
| 143 | 144 | return Ok(None); |
| 144 | 145 | } |
| 145 | let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, params)?); | |
| 146 | let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, &params)?); | |
| 146 | 147 | let line_index = snap.file_line_index(file_id)?; |
| 147 | 148 | |
| 148 | 149 | Ok(Annotation { |
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/semantic_tokens.rs+249-155| ... | ... | @@ -1,170 +1,261 @@ |
| 1 | 1 | //! Semantic Tokens helpers |
| 2 | 2 | |
| 3 | use std::ops; | |
| 3 | use std::{fmt, ops, slice::Iter}; | |
| 4 | 4 | |
| 5 | use lsp_types::{ | |
| 6 | Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens, | |
| 7 | SemanticTokensEdit, | |
| 8 | }; | |
| 5 | use lsp_types::{Range, SemanticTokenModifiers, SemanticTokens, SemanticTokensEdit}; | |
| 9 | 6 | |
| 10 | macro_rules! define_semantic_token_types { | |
| 7 | macro_rules! declare_enum { | |
| 11 | 8 | ( |
| 12 | standard { | |
| 13 | $($standard:ident),*$(,)? | |
| 9 | $(#[$attrs:meta])* | |
| 10 | $visibility:vis enum $name:ident { | |
| 11 | $($variant:ident),* $(,)? | |
| 14 | 12 | } |
| 15 | custom { | |
| 16 | $(($custom:ident, $string:literal) $(=> $fallback:ident)?),*$(,)? | |
| 17 | } | |
| 18 | ||
| 19 | 13 | ) => { |
| 20 | pub(crate) mod types { | |
| 21 | use super::SemanticTokenType; | |
| 22 | $(pub(crate) const $standard: SemanticTokenType = SemanticTokenType::$standard;)* | |
| 23 | $(pub(crate) const $custom: SemanticTokenType = SemanticTokenType::new($string);)* | |
| 14 | $(#[$attrs])* | |
| 15 | $visibility enum $name { | |
| 16 | $($variant,)* | |
| 24 | 17 | } |
| 25 | 18 | |
| 26 | pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[ | |
| 27 | $(self::types::$standard,)* | |
| 28 | $(self::types::$custom),* | |
| 29 | ]; | |
| 30 | ||
| 31 | pub(crate) fn standard_fallback_type(token: SemanticTokenType) -> Option<SemanticTokenType> { | |
| 32 | use self::types::*; | |
| 33 | $( | |
| 34 | if token == $custom { | |
| 35 | None $(.or(Some(self::types::$fallback)))? | |
| 36 | } else | |
| 37 | )* | |
| 38 | { Some(token )} | |
| 19 | impl $name { | |
| 20 | pub(crate) fn iter() -> Iter<'static, Self> { | |
| 21 | static ITEMS: &[$name] = &[ | |
| 22 | $( | |
| 23 | $name::$variant, | |
| 24 | )* | |
| 25 | ]; | |
| 26 | ITEMS.iter() | |
| 27 | } | |
| 39 | 28 | } |
| 40 | 29 | }; |
| 41 | 30 | } |
| 42 | 31 | |
| 43 | define_semantic_token_types![ | |
| 44 | standard { | |
| 45 | COMMENT, | |
| 46 | DECORATOR, | |
| 47 | ENUM_MEMBER, | |
| 48 | ENUM, | |
| 49 | FUNCTION, | |
| 50 | INTERFACE, | |
| 51 | KEYWORD, | |
| 52 | MACRO, | |
| 53 | METHOD, | |
| 54 | NAMESPACE, | |
| 55 | NUMBER, | |
| 56 | OPERATOR, | |
| 57 | PARAMETER, | |
| 58 | PROPERTY, | |
| 59 | STRING, | |
| 60 | STRUCT, | |
| 61 | TYPE_PARAMETER, | |
| 62 | VARIABLE, | |
| 63 | TYPE, | |
| 32 | declare_enum! { | |
| 33 | #[repr(u32)] | |
| 34 | #[derive(Debug, PartialEq, Clone, Copy)] | |
| 35 | pub(crate) enum SupportedType { | |
| 36 | Comment, | |
| 37 | Decorator, | |
| 38 | EnumMember, | |
| 39 | Enum, | |
| 40 | Function, | |
| 41 | Interface, | |
| 42 | Keyword, | |
| 43 | Macro, | |
| 44 | Method, | |
| 45 | Namespace, | |
| 46 | Number, | |
| 47 | Operator, | |
| 48 | Parameter, | |
| 49 | Property, | |
| 50 | String, | |
| 51 | Struct, | |
| 52 | TypeParameter, | |
| 53 | Variable, | |
| 54 | Type, | |
| 55 | Label, | |
| 56 | Angle, | |
| 57 | Arithmetic, | |
| 58 | AttributeBracket, | |
| 59 | Attribute, | |
| 60 | Bitwise, | |
| 61 | Boolean, | |
| 62 | Brace, | |
| 63 | Bracket, | |
| 64 | BuiltinAttribute, | |
| 65 | BuiltinType, | |
| 66 | Char, | |
| 67 | Colon, | |
| 68 | Comma, | |
| 69 | Comparison, | |
| 70 | ConstParameter, | |
| 71 | Const, | |
| 72 | DeriveHelper, | |
| 73 | Derive, | |
| 74 | Dot, | |
| 75 | EscapeSequence, | |
| 76 | FormatSpecifier, | |
| 77 | Generic, | |
| 78 | InvalidEscapeSequence, | |
| 79 | Lifetime, | |
| 80 | Logical, | |
| 81 | MacroBang, | |
| 82 | Negation, | |
| 83 | Parenthesis, | |
| 84 | ProcMacro, | |
| 85 | Punctuation, | |
| 86 | SelfKeyword, | |
| 87 | SelfTypeKeyword, | |
| 88 | Semicolon, | |
| 89 | Static, | |
| 90 | ToolModule, | |
| 91 | TypeAlias, | |
| 92 | Union, | |
| 93 | UnresolvedReference, | |
| 64 | 94 | } |
| 95 | } | |
| 65 | 96 | |
| 66 | custom { | |
| 67 | (ANGLE, "angle"), | |
| 68 | (ARITHMETIC, "arithmetic") => OPERATOR, | |
| 69 | (ATTRIBUTE_BRACKET, "attributeBracket") => DECORATOR, | |
| 70 | (ATTRIBUTE, "attribute") => DECORATOR, | |
| 71 | (BITWISE, "bitwise") => OPERATOR, | |
| 72 | (BOOLEAN, "boolean"), | |
| 73 | (BRACE, "brace"), | |
| 74 | (BRACKET, "bracket"), | |
| 75 | (BUILTIN_ATTRIBUTE, "builtinAttribute") => DECORATOR, | |
| 76 | (BUILTIN_TYPE, "builtinType") => TYPE, | |
| 77 | (CHAR, "character") => STRING, | |
| 78 | (COLON, "colon"), | |
| 79 | (COMMA, "comma"), | |
| 80 | (COMPARISON, "comparison") => OPERATOR, | |
| 81 | (CONST_PARAMETER, "constParameter"), | |
| 82 | (CONST, "const") => VARIABLE, | |
| 83 | (DERIVE_HELPER, "deriveHelper") => DECORATOR, | |
| 84 | (DERIVE, "derive") => DECORATOR, | |
| 85 | (DOT, "dot"), | |
| 86 | (ESCAPE_SEQUENCE, "escapeSequence") => STRING, | |
| 87 | (FORMAT_SPECIFIER, "formatSpecifier") => STRING, | |
| 88 | (GENERIC, "generic") => TYPE_PARAMETER, | |
| 89 | (INVALID_ESCAPE_SEQUENCE, "invalidEscapeSequence") => STRING, | |
| 90 | (LABEL, "label"), | |
| 91 | (LIFETIME, "lifetime"), | |
| 92 | (LOGICAL, "logical") => OPERATOR, | |
| 93 | (MACRO_BANG, "macroBang") => MACRO, | |
| 94 | (NEGATION, "negation") => OPERATOR, | |
| 95 | (PARENTHESIS, "parenthesis"), | |
| 96 | (PROC_MACRO, "procMacro") => MACRO, | |
| 97 | (PUNCTUATION, "punctuation"), | |
| 98 | (SELF_KEYWORD, "selfKeyword") => KEYWORD, | |
| 99 | (SELF_TYPE_KEYWORD, "selfTypeKeyword") => KEYWORD, | |
| 100 | (SEMICOLON, "semicolon"), | |
| 101 | (STATIC, "static") => VARIABLE, | |
| 102 | (TOOL_MODULE, "toolModule") => DECORATOR, | |
| 103 | (TYPE_ALIAS, "typeAlias") => TYPE, | |
| 104 | (UNION, "union") => TYPE, | |
| 105 | (UNRESOLVED_REFERENCE, "unresolvedReference"), | |
| 97 | declare_enum! { | |
| 98 | #[repr(u32)] | |
| 99 | #[derive(Debug, PartialEq, Clone, Copy)] | |
| 100 | pub(crate) enum SupportedModifiers { | |
| 101 | Async, | |
| 102 | Documentation, | |
| 103 | Declaration, | |
| 104 | Static, | |
| 105 | DefaultLibrary, | |
| 106 | Deprecated, | |
| 107 | Associated, | |
| 108 | AttributeModifier, | |
| 109 | Callable, | |
| 110 | Constant, | |
| 111 | Consuming, | |
| 112 | ControlFlow, | |
| 113 | CrateRoot, | |
| 114 | Injected, | |
| 115 | IntraDocLink, | |
| 116 | Library, | |
| 117 | MacroModifier, | |
| 118 | Mutable, | |
| 119 | ProcMacroModifier, | |
| 120 | Public, | |
| 121 | Reference, | |
| 122 | TraitModifier, | |
| 123 | Unsafe, | |
| 106 | 124 | } |
| 107 | ]; | |
| 108 | ||
| 109 | macro_rules! count_tts { | |
| 110 | () => {0usize}; | |
| 111 | ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)}; | |
| 112 | 125 | } |
| 113 | macro_rules! define_semantic_token_modifiers { | |
| 114 | ( | |
| 115 | standard { | |
| 116 | $($standard:ident),*$(,)? | |
| 117 | } | |
| 118 | custom { | |
| 119 | $(($custom:ident, $string:literal)),*$(,)? | |
| 120 | } | |
| 121 | ||
| 122 | ) => { | |
| 123 | pub(crate) mod modifiers { | |
| 124 | use super::SemanticTokenModifier; | |
| 125 | ||
| 126 | $(pub(crate) const $standard: SemanticTokenModifier = SemanticTokenModifier::$standard;)* | |
| 127 | $(pub(crate) const $custom: SemanticTokenModifier = SemanticTokenModifier::new($string);)* | |
| 128 | } | |
| 129 | 126 | |
| 130 | pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[ | |
| 131 | $(SemanticTokenModifier::$standard,)* | |
| 132 | $(self::modifiers::$custom),* | |
| 133 | ]; | |
| 127 | impl fmt::Display for SupportedType { | |
| 128 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 129 | let string = match self { | |
| 130 | SupportedType::Comment => ::lsp_types::SemanticTokenTypes::Comment.as_str(), | |
| 131 | SupportedType::Decorator => ::lsp_types::SemanticTokenTypes::Decorator.as_str(), | |
| 132 | SupportedType::EnumMember => ::lsp_types::SemanticTokenTypes::EnumMember.as_str(), | |
| 133 | SupportedType::Enum => ::lsp_types::SemanticTokenTypes::Enum.as_str(), | |
| 134 | SupportedType::Function => ::lsp_types::SemanticTokenTypes::Function.as_str(), | |
| 135 | SupportedType::Interface => ::lsp_types::SemanticTokenTypes::Interface.as_str(), | |
| 136 | SupportedType::Keyword => ::lsp_types::SemanticTokenTypes::Keyword.as_str(), | |
| 137 | SupportedType::Macro => ::lsp_types::SemanticTokenTypes::Macro.as_str(), | |
| 138 | SupportedType::Method => ::lsp_types::SemanticTokenTypes::Method.as_str(), | |
| 139 | SupportedType::Namespace => ::lsp_types::SemanticTokenTypes::Namespace.as_str(), | |
| 140 | SupportedType::Number => ::lsp_types::SemanticTokenTypes::Number.as_str(), | |
| 141 | SupportedType::Operator => ::lsp_types::SemanticTokenTypes::Operator.as_str(), | |
| 142 | SupportedType::Parameter => ::lsp_types::SemanticTokenTypes::Parameter.as_str(), | |
| 143 | SupportedType::Property => ::lsp_types::SemanticTokenTypes::Property.as_str(), | |
| 144 | SupportedType::String => ::lsp_types::SemanticTokenTypes::String.as_str(), | |
| 145 | SupportedType::Struct => ::lsp_types::SemanticTokenTypes::Struct.as_str(), | |
| 146 | SupportedType::TypeParameter => ::lsp_types::SemanticTokenTypes::TypeParameter.as_str(), | |
| 147 | SupportedType::Variable => ::lsp_types::SemanticTokenTypes::Variable.as_str(), | |
| 148 | SupportedType::Type => ::lsp_types::SemanticTokenTypes::Type.as_str(), | |
| 149 | SupportedType::Label => ::lsp_types::SemanticTokenTypes::Label.as_str(), | |
| 150 | SupportedType::Angle => "angle", | |
| 151 | SupportedType::Arithmetic => "arithmetic", | |
| 152 | SupportedType::AttributeBracket => "attributeBracket", | |
| 153 | SupportedType::Attribute => "attribute", | |
| 154 | SupportedType::Bitwise => "bitwise", | |
| 155 | SupportedType::Boolean => "boolean", | |
| 156 | SupportedType::Brace => "brace", | |
| 157 | SupportedType::Bracket => "bracket", | |
| 158 | SupportedType::BuiltinAttribute => "builtinAttribute", | |
| 159 | SupportedType::BuiltinType => "builtinType", | |
| 160 | SupportedType::Char => "character", | |
| 161 | SupportedType::Colon => "colon", | |
| 162 | SupportedType::Comma => "comma", | |
| 163 | SupportedType::Comparison => "comparison", | |
| 164 | SupportedType::ConstParameter => "constParameter", | |
| 165 | SupportedType::Const => "const", | |
| 166 | SupportedType::DeriveHelper => "deriveHelper", | |
| 167 | SupportedType::Derive => "derive", | |
| 168 | SupportedType::Dot => "dot", | |
| 169 | SupportedType::EscapeSequence => "escapeSequence", | |
| 170 | SupportedType::FormatSpecifier => "formatSpecifier", | |
| 171 | SupportedType::Generic => "generic", | |
| 172 | SupportedType::InvalidEscapeSequence => "invalidEscapeSequence", | |
| 173 | SupportedType::Lifetime => "lifetime", | |
| 174 | SupportedType::Logical => "logical", | |
| 175 | SupportedType::MacroBang => "macroBang", | |
| 176 | SupportedType::Negation => "negation", | |
| 177 | SupportedType::Parenthesis => "parenthesis", | |
| 178 | SupportedType::ProcMacro => "procMacro", | |
| 179 | SupportedType::Punctuation => "punctuation", | |
| 180 | SupportedType::SelfKeyword => "selfKeyword", | |
| 181 | SupportedType::SelfTypeKeyword => "selfTypeKeyword", | |
| 182 | SupportedType::Semicolon => "semicolon", | |
| 183 | SupportedType::Static => "static", | |
| 184 | SupportedType::ToolModule => "toolModule", | |
| 185 | SupportedType::TypeAlias => "typeAlias", | |
| 186 | SupportedType::Union => "union", | |
| 187 | SupportedType::UnresolvedReference => "unresolvedReference", | |
| 188 | }; | |
| 189 | f.write_str(string) | |
| 190 | } | |
| 191 | } | |
| 134 | 192 | |
| 135 | const LAST_STANDARD_MOD: usize = count_tts!($($standard)*); | |
| 136 | }; | |
| 193 | pub(crate) fn standard_fallback_type(token: SupportedType) -> Option<SupportedType> { | |
| 194 | Some(match token { | |
| 195 | SupportedType::Comment => SupportedType::Comment, | |
| 196 | SupportedType::Decorator => SupportedType::Decorator, | |
| 197 | SupportedType::EnumMember => SupportedType::EnumMember, | |
| 198 | SupportedType::Enum => SupportedType::Enum, | |
| 199 | SupportedType::Function => SupportedType::Function, | |
| 200 | SupportedType::Interface => SupportedType::Interface, | |
| 201 | SupportedType::Keyword => SupportedType::Keyword, | |
| 202 | SupportedType::Macro => SupportedType::Macro, | |
| 203 | SupportedType::Method => SupportedType::Method, | |
| 204 | SupportedType::Namespace => SupportedType::Namespace, | |
| 205 | SupportedType::Number => SupportedType::Number, | |
| 206 | SupportedType::Operator => SupportedType::Operator, | |
| 207 | SupportedType::Parameter => SupportedType::Parameter, | |
| 208 | SupportedType::Property => SupportedType::Property, | |
| 209 | SupportedType::String => SupportedType::String, | |
| 210 | SupportedType::Struct => SupportedType::Struct, | |
| 211 | SupportedType::TypeParameter => SupportedType::TypeParameter, | |
| 212 | SupportedType::Variable => SupportedType::Variable, | |
| 213 | SupportedType::Type => SupportedType::Type, | |
| 214 | SupportedType::Label => SupportedType::Label, | |
| 215 | _ => return None, | |
| 216 | }) | |
| 137 | 217 | } |
| 138 | 218 | |
| 139 | define_semantic_token_modifiers![ | |
| 140 | standard { | |
| 141 | ASYNC, | |
| 142 | DOCUMENTATION, | |
| 143 | DECLARATION, | |
| 144 | STATIC, | |
| 145 | DEFAULT_LIBRARY, | |
| 146 | DEPRECATED, | |
| 147 | } | |
| 148 | custom { | |
| 149 | (ASSOCIATED, "associated"), | |
| 150 | (ATTRIBUTE_MODIFIER, "attribute"), | |
| 151 | (CALLABLE, "callable"), | |
| 152 | (CONSTANT, "constant"), | |
| 153 | (CONSUMING, "consuming"), | |
| 154 | (CONTROL_FLOW, "controlFlow"), | |
| 155 | (CRATE_ROOT, "crateRoot"), | |
| 156 | (INJECTED, "injected"), | |
| 157 | (INTRA_DOC_LINK, "intraDocLink"), | |
| 158 | (LIBRARY, "library"), | |
| 159 | (MACRO_MODIFIER, "macro"), | |
| 160 | (MUTABLE, "mutable"), | |
| 161 | (PROC_MACRO_MODIFIER, "procMacro"), | |
| 162 | (PUBLIC, "public"), | |
| 163 | (REFERENCE, "reference"), | |
| 164 | (TRAIT_MODIFIER, "trait"), | |
| 165 | (UNSAFE, "unsafe"), | |
| 219 | impl fmt::Display for SupportedModifiers { | |
| 220 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 221 | let string = match self { | |
| 222 | SupportedModifiers::Async => SemanticTokenModifiers::Async.as_str(), | |
| 223 | SupportedModifiers::Documentation => SemanticTokenModifiers::Documentation.as_str(), | |
| 224 | SupportedModifiers::Declaration => SemanticTokenModifiers::Declaration.as_str(), | |
| 225 | SupportedModifiers::Static => SemanticTokenModifiers::Static.as_str(), | |
| 226 | SupportedModifiers::DefaultLibrary => SemanticTokenModifiers::DefaultLibrary.as_str(), | |
| 227 | SupportedModifiers::Deprecated => SemanticTokenModifiers::Deprecated.as_str(), | |
| 228 | SupportedModifiers::Associated => "associated", | |
| 229 | SupportedModifiers::AttributeModifier => "attribute", | |
| 230 | SupportedModifiers::Callable => "callable", | |
| 231 | SupportedModifiers::Constant => "constant", | |
| 232 | SupportedModifiers::Consuming => "consuming", | |
| 233 | SupportedModifiers::ControlFlow => "controlFlow", | |
| 234 | SupportedModifiers::CrateRoot => "crateRoot", | |
| 235 | SupportedModifiers::Injected => "injected", | |
| 236 | SupportedModifiers::IntraDocLink => "intraDocLink", | |
| 237 | SupportedModifiers::Library => "library", | |
| 238 | SupportedModifiers::MacroModifier => "macro", | |
| 239 | SupportedModifiers::Mutable => "mutable", | |
| 240 | SupportedModifiers::ProcMacroModifier => "procMacro", | |
| 241 | SupportedModifiers::Public => "public", | |
| 242 | SupportedModifiers::Reference => "reference", | |
| 243 | SupportedModifiers::TraitModifier => "trait", | |
| 244 | SupportedModifiers::Unsafe => "unsafe", | |
| 245 | }; | |
| 246 | f.write_str(string) | |
| 166 | 247 | } |
| 248 | } | |
| 249 | ||
| 250 | const STANDARD_MOD: [SupportedModifiers; 6] = [ | |
| 251 | SupportedModifiers::Async, | |
| 252 | SupportedModifiers::Documentation, | |
| 253 | SupportedModifiers::Declaration, | |
| 254 | SupportedModifiers::Static, | |
| 255 | SupportedModifiers::DefaultLibrary, | |
| 256 | SupportedModifiers::Deprecated, | |
| 167 | 257 | ]; |
| 258 | const LAST_STANDARD_MOD: usize = STANDARD_MOD.len() - 1; | |
| 168 | 259 | |
| 169 | 260 | #[derive(Default)] |
| 170 | 261 | pub(crate) struct ModifierSet(pub(crate) u32); |
| ... | ... | @@ -176,9 +267,9 @@ impl ModifierSet { |
| 176 | 267 | } |
| 177 | 268 | } |
| 178 | 269 | |
| 179 | impl ops::BitOrAssign<SemanticTokenModifier> for ModifierSet { | |
| 180 | fn bitor_assign(&mut self, rhs: SemanticTokenModifier) { | |
| 181 | let idx = SUPPORTED_MODIFIERS.iter().position(|it| it == &rhs).unwrap(); | |
| 270 | impl ops::BitOrAssign<SupportedModifiers> for ModifierSet { | |
| 271 | fn bitor_assign(&mut self, rhs: SupportedModifiers) { | |
| 272 | let idx = SupportedModifiers::iter().position(|it| *it == rhs).unwrap(); | |
| 182 | 273 | self.0 |= 1 << idx; |
| 183 | 274 | } |
| 184 | 275 | } |
| ... | ... | @@ -190,12 +281,12 @@ pub(crate) struct SemanticTokensBuilder { |
| 190 | 281 | id: String, |
| 191 | 282 | prev_line: u32, |
| 192 | 283 | prev_char: u32, |
| 193 | data: Vec<SemanticToken>, | |
| 284 | data: Vec<lsp_types::SemanticToken>, | |
| 194 | 285 | } |
| 195 | 286 | |
| 196 | 287 | impl SemanticTokensBuilder { |
| 197 | 288 | pub(crate) fn new(id: String) -> Self { |
| 198 | SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Default::default() } | |
| 289 | SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Vec::new() } | |
| 199 | 290 | } |
| 200 | 291 | |
| 201 | 292 | /// Push a new token onto the builder |
| ... | ... | @@ -213,7 +304,7 @@ impl SemanticTokensBuilder { |
| 213 | 304 | // A token cannot be multiline |
| 214 | 305 | let token_len = range.end.character - range.start.character; |
| 215 | 306 | |
| 216 | let token = SemanticToken { | |
| 307 | let token = lsp_types::SemanticToken { | |
| 217 | 308 | delta_line: push_line, |
| 218 | 309 | delta_start: push_char, |
| 219 | 310 | length: token_len, |
| ... | ... | @@ -232,7 +323,10 @@ impl SemanticTokensBuilder { |
| 232 | 323 | } |
| 233 | 324 | } |
| 234 | 325 | |
| 235 | pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<SemanticTokensEdit> { | |
| 326 | pub(crate) fn diff_tokens( | |
| 327 | old: &[lsp_types::SemanticToken], | |
| 328 | new: &[lsp_types::SemanticToken], | |
| 329 | ) -> Vec<SemanticTokensEdit> { | |
| 236 | 330 | let offset = new.iter().zip(old.iter()).take_while(|&(n, p)| n == p).count(); |
| 237 | 331 | |
| 238 | 332 | let (_, old) = old.split_at(offset); |
| ... | ... | @@ -258,16 +352,16 @@ pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<S |
| 258 | 352 | } |
| 259 | 353 | } |
| 260 | 354 | |
| 261 | pub(crate) fn type_index(ty: SemanticTokenType) -> u32 { | |
| 262 | SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32 | |
| 355 | pub(crate) fn type_index(kind: SupportedType) -> u32 { | |
| 356 | kind as u32 | |
| 263 | 357 | } |
| 264 | 358 | |
| 265 | 359 | #[cfg(test)] |
| 266 | 360 | mod tests { |
| 267 | 361 | use super::*; |
| 268 | 362 | |
| 269 | fn from(t: (u32, u32, u32, u32, u32)) -> SemanticToken { | |
| 270 | SemanticToken { | |
| 363 | fn from(t: (u32, u32, u32, u32, u32)) -> lsp_types::SemanticToken { | |
| 364 | lsp_types::SemanticToken { | |
| 271 | 365 | delta_line: t.0, |
| 272 | 366 | delta_start: t.1, |
| 273 | 367 | length: t.2, |
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs+319-248| ... | ... | @@ -58,43 +58,43 @@ pub(crate) fn range(line_index: &LineIndex, range: TextRange) -> lsp_types::Rang |
| 58 | 58 | |
| 59 | 59 | pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind { |
| 60 | 60 | match symbol_kind { |
| 61 | SymbolKind::Function => lsp_types::SymbolKind::FUNCTION, | |
| 62 | SymbolKind::Method => lsp_types::SymbolKind::METHOD, | |
| 63 | SymbolKind::Struct => lsp_types::SymbolKind::STRUCT, | |
| 64 | SymbolKind::Enum => lsp_types::SymbolKind::ENUM, | |
| 65 | SymbolKind::Variant => lsp_types::SymbolKind::ENUM_MEMBER, | |
| 66 | SymbolKind::Trait => lsp_types::SymbolKind::INTERFACE, | |
| 61 | SymbolKind::Function => lsp_types::SymbolKind::Function, | |
| 62 | SymbolKind::Method => lsp_types::SymbolKind::Method, | |
| 63 | SymbolKind::Struct => lsp_types::SymbolKind::Struct, | |
| 64 | SymbolKind::Enum => lsp_types::SymbolKind::Enum, | |
| 65 | SymbolKind::Variant => lsp_types::SymbolKind::EnumMember, | |
| 66 | SymbolKind::Trait => lsp_types::SymbolKind::Interface, | |
| 67 | 67 | SymbolKind::Macro |
| 68 | 68 | | SymbolKind::ProcMacro |
| 69 | 69 | | SymbolKind::BuiltinAttr |
| 70 | 70 | | SymbolKind::Attribute |
| 71 | 71 | | SymbolKind::Derive |
| 72 | | SymbolKind::DeriveHelper => lsp_types::SymbolKind::FUNCTION, | |
| 73 | SymbolKind::CrateRoot => lsp_types::SymbolKind::PACKAGE, | |
| 74 | SymbolKind::Module | SymbolKind::ToolModule => lsp_types::SymbolKind::MODULE, | |
| 72 | | SymbolKind::DeriveHelper => lsp_types::SymbolKind::Function, | |
| 73 | SymbolKind::CrateRoot => lsp_types::SymbolKind::Package, | |
| 74 | SymbolKind::Module | SymbolKind::ToolModule => lsp_types::SymbolKind::Module, | |
| 75 | 75 | SymbolKind::TypeAlias | SymbolKind::TypeParam | SymbolKind::SelfType => { |
| 76 | lsp_types::SymbolKind::TYPE_PARAMETER | |
| 76 | lsp_types::SymbolKind::TypeParameter | |
| 77 | 77 | } |
| 78 | SymbolKind::Field => lsp_types::SymbolKind::FIELD, | |
| 79 | SymbolKind::Static => lsp_types::SymbolKind::CONSTANT, | |
| 80 | SymbolKind::Const => lsp_types::SymbolKind::CONSTANT, | |
| 81 | SymbolKind::ConstParam => lsp_types::SymbolKind::CONSTANT, | |
| 82 | SymbolKind::Impl => lsp_types::SymbolKind::OBJECT, | |
| 78 | SymbolKind::Field => lsp_types::SymbolKind::Field, | |
| 79 | SymbolKind::Static => lsp_types::SymbolKind::Constant, | |
| 80 | SymbolKind::Const => lsp_types::SymbolKind::Constant, | |
| 81 | SymbolKind::ConstParam => lsp_types::SymbolKind::Constant, | |
| 82 | SymbolKind::Impl => lsp_types::SymbolKind::Object, | |
| 83 | 83 | SymbolKind::Local |
| 84 | 84 | | SymbolKind::SelfParam |
| 85 | 85 | | SymbolKind::LifetimeParam |
| 86 | 86 | | SymbolKind::ValueParam |
| 87 | | SymbolKind::Label => lsp_types::SymbolKind::VARIABLE, | |
| 88 | SymbolKind::Union => lsp_types::SymbolKind::STRUCT, | |
| 89 | SymbolKind::InlineAsmRegOrRegClass => lsp_types::SymbolKind::VARIABLE, | |
| 87 | | SymbolKind::Label => lsp_types::SymbolKind::Variable, | |
| 88 | SymbolKind::Union => lsp_types::SymbolKind::Struct, | |
| 89 | SymbolKind::InlineAsmRegOrRegClass => lsp_types::SymbolKind::Variable, | |
| 90 | 90 | } |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolKind { |
| 94 | 94 | match kind { |
| 95 | 95 | StructureNodeKind::SymbolKind(symbol) => symbol_kind(symbol), |
| 96 | StructureNodeKind::Region => lsp_types::SymbolKind::NAMESPACE, | |
| 97 | StructureNodeKind::ExternBlock => lsp_types::SymbolKind::NAMESPACE, | |
| 96 | StructureNodeKind::Region => lsp_types::SymbolKind::Namespace, | |
| 97 | StructureNodeKind::ExternBlock => lsp_types::SymbolKind::Namespace, | |
| 98 | 98 | } |
| 99 | 99 | } |
| 100 | 100 | |
| ... | ... | @@ -102,21 +102,21 @@ pub(crate) fn document_highlight_kind( |
| 102 | 102 | category: ReferenceCategory, |
| 103 | 103 | ) -> Option<lsp_types::DocumentHighlightKind> { |
| 104 | 104 | if category.contains(ReferenceCategory::WRITE) { |
| 105 | return Some(lsp_types::DocumentHighlightKind::WRITE); | |
| 105 | return Some(lsp_types::DocumentHighlightKind::Write); | |
| 106 | 106 | } |
| 107 | 107 | if category.contains(ReferenceCategory::READ) { |
| 108 | return Some(lsp_types::DocumentHighlightKind::READ); | |
| 108 | return Some(lsp_types::DocumentHighlightKind::Read); | |
| 109 | 109 | } |
| 110 | 110 | None |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | pub(crate) fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSeverity { |
| 114 | 114 | match severity { |
| 115 | Severity::Error => lsp_types::DiagnosticSeverity::ERROR, | |
| 116 | Severity::Warning => lsp_types::DiagnosticSeverity::WARNING, | |
| 117 | Severity::WeakWarning => lsp_types::DiagnosticSeverity::HINT, | |
| 115 | Severity::Error => lsp_types::DiagnosticSeverity::Error, | |
| 116 | Severity::Warning => lsp_types::DiagnosticSeverity::Warning, | |
| 117 | Severity::WeakWarning => lsp_types::DiagnosticSeverity::Hint, | |
| 118 | 118 | // unreachable |
| 119 | Severity::Allow => lsp_types::DiagnosticSeverity::INFORMATION, | |
| 119 | Severity::Allow => lsp_types::DiagnosticSeverity::Information, | |
| 120 | 120 | } |
| 121 | 121 | } |
| 122 | 122 | |
| ... | ... | @@ -130,44 +130,44 @@ pub(crate) fn completion_item_kind( |
| 130 | 130 | completion_item_kind: CompletionItemKind, |
| 131 | 131 | ) -> lsp_types::CompletionItemKind { |
| 132 | 132 | match completion_item_kind { |
| 133 | CompletionItemKind::Binding => lsp_types::CompletionItemKind::VARIABLE, | |
| 134 | CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::STRUCT, | |
| 135 | CompletionItemKind::InferredType => lsp_types::CompletionItemKind::SNIPPET, | |
| 136 | CompletionItemKind::Keyword => lsp_types::CompletionItemKind::KEYWORD, | |
| 137 | CompletionItemKind::Snippet => lsp_types::CompletionItemKind::SNIPPET, | |
| 138 | CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::REFERENCE, | |
| 139 | CompletionItemKind::Expression => lsp_types::CompletionItemKind::SNIPPET, | |
| 133 | CompletionItemKind::Binding => lsp_types::CompletionItemKind::Variable, | |
| 134 | CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::Struct, | |
| 135 | CompletionItemKind::InferredType => lsp_types::CompletionItemKind::Snippet, | |
| 136 | CompletionItemKind::Keyword => lsp_types::CompletionItemKind::Keyword, | |
| 137 | CompletionItemKind::Snippet => lsp_types::CompletionItemKind::Snippet, | |
| 138 | CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::Reference, | |
| 139 | CompletionItemKind::Expression => lsp_types::CompletionItemKind::Snippet, | |
| 140 | 140 | CompletionItemKind::SymbolKind(symbol) => match symbol { |
| 141 | SymbolKind::Attribute => lsp_types::CompletionItemKind::FUNCTION, | |
| 142 | SymbolKind::Method => lsp_types::CompletionItemKind::METHOD, | |
| 143 | SymbolKind::Const => lsp_types::CompletionItemKind::CONSTANT, | |
| 144 | SymbolKind::ConstParam => lsp_types::CompletionItemKind::TYPE_PARAMETER, | |
| 145 | SymbolKind::CrateRoot => lsp_types::CompletionItemKind::MODULE, | |
| 146 | SymbolKind::Derive => lsp_types::CompletionItemKind::FUNCTION, | |
| 147 | SymbolKind::DeriveHelper => lsp_types::CompletionItemKind::FUNCTION, | |
| 148 | SymbolKind::Enum => lsp_types::CompletionItemKind::ENUM, | |
| 149 | SymbolKind::Field => lsp_types::CompletionItemKind::FIELD, | |
| 150 | SymbolKind::Function => lsp_types::CompletionItemKind::FUNCTION, | |
| 151 | SymbolKind::Impl => lsp_types::CompletionItemKind::TEXT, | |
| 152 | SymbolKind::Label => lsp_types::CompletionItemKind::VARIABLE, | |
| 153 | SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER, | |
| 154 | SymbolKind::Local => lsp_types::CompletionItemKind::VARIABLE, | |
| 155 | SymbolKind::Macro => lsp_types::CompletionItemKind::FUNCTION, | |
| 156 | SymbolKind::ProcMacro => lsp_types::CompletionItemKind::FUNCTION, | |
| 157 | SymbolKind::Module => lsp_types::CompletionItemKind::MODULE, | |
| 158 | SymbolKind::SelfParam => lsp_types::CompletionItemKind::VALUE, | |
| 159 | SymbolKind::SelfType => lsp_types::CompletionItemKind::TYPE_PARAMETER, | |
| 160 | SymbolKind::Static => lsp_types::CompletionItemKind::VALUE, | |
| 161 | SymbolKind::Struct => lsp_types::CompletionItemKind::STRUCT, | |
| 162 | SymbolKind::Trait => lsp_types::CompletionItemKind::INTERFACE, | |
| 163 | SymbolKind::TypeAlias => lsp_types::CompletionItemKind::STRUCT, | |
| 164 | SymbolKind::TypeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER, | |
| 165 | SymbolKind::Union => lsp_types::CompletionItemKind::STRUCT, | |
| 166 | SymbolKind::ValueParam => lsp_types::CompletionItemKind::VALUE, | |
| 167 | SymbolKind::Variant => lsp_types::CompletionItemKind::ENUM_MEMBER, | |
| 168 | SymbolKind::BuiltinAttr => lsp_types::CompletionItemKind::FUNCTION, | |
| 169 | SymbolKind::ToolModule => lsp_types::CompletionItemKind::MODULE, | |
| 170 | SymbolKind::InlineAsmRegOrRegClass => lsp_types::CompletionItemKind::KEYWORD, | |
| 141 | SymbolKind::Attribute => lsp_types::CompletionItemKind::Function, | |
| 142 | SymbolKind::Method => lsp_types::CompletionItemKind::Method, | |
| 143 | SymbolKind::Const => lsp_types::CompletionItemKind::Constant, | |
| 144 | SymbolKind::ConstParam => lsp_types::CompletionItemKind::TypeParameter, | |
| 145 | SymbolKind::CrateRoot => lsp_types::CompletionItemKind::Module, | |
| 146 | SymbolKind::Derive => lsp_types::CompletionItemKind::Function, | |
| 147 | SymbolKind::DeriveHelper => lsp_types::CompletionItemKind::Function, | |
| 148 | SymbolKind::Enum => lsp_types::CompletionItemKind::Enum, | |
| 149 | SymbolKind::Field => lsp_types::CompletionItemKind::Field, | |
| 150 | SymbolKind::Function => lsp_types::CompletionItemKind::Function, | |
| 151 | SymbolKind::Impl => lsp_types::CompletionItemKind::Text, | |
| 152 | SymbolKind::Label => lsp_types::CompletionItemKind::Variable, | |
| 153 | SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TypeParameter, | |
| 154 | SymbolKind::Local => lsp_types::CompletionItemKind::Variable, | |
| 155 | SymbolKind::Macro => lsp_types::CompletionItemKind::Function, | |
| 156 | SymbolKind::ProcMacro => lsp_types::CompletionItemKind::Function, | |
| 157 | SymbolKind::Module => lsp_types::CompletionItemKind::Module, | |
| 158 | SymbolKind::SelfParam => lsp_types::CompletionItemKind::Value, | |
| 159 | SymbolKind::SelfType => lsp_types::CompletionItemKind::TypeParameter, | |
| 160 | SymbolKind::Static => lsp_types::CompletionItemKind::Value, | |
| 161 | SymbolKind::Struct => lsp_types::CompletionItemKind::Struct, | |
| 162 | SymbolKind::Trait => lsp_types::CompletionItemKind::Interface, | |
| 163 | SymbolKind::TypeAlias => lsp_types::CompletionItemKind::Struct, | |
| 164 | SymbolKind::TypeParam => lsp_types::CompletionItemKind::TypeParameter, | |
| 165 | SymbolKind::Union => lsp_types::CompletionItemKind::Struct, | |
| 166 | SymbolKind::ValueParam => lsp_types::CompletionItemKind::Value, | |
| 167 | SymbolKind::Variant => lsp_types::CompletionItemKind::EnumMember, | |
| 168 | SymbolKind::BuiltinAttr => lsp_types::CompletionItemKind::Function, | |
| 169 | SymbolKind::ToolModule => lsp_types::CompletionItemKind::Module, | |
| 170 | SymbolKind::InlineAsmRegOrRegClass => lsp_types::CompletionItemKind::Keyword, | |
| 171 | 171 | }, |
| 172 | 172 | } |
| 173 | 173 | } |
| ... | ... | @@ -185,7 +185,7 @@ pub(crate) fn completion_text_edit( |
| 185 | 185 | line_index: &LineIndex, |
| 186 | 186 | insert_replace_support: Option<lsp_types::Position>, |
| 187 | 187 | indel: Indel, |
| 188 | ) -> lsp_types::CompletionTextEdit { | |
| 188 | ) -> lsp_types::CompletionItemTextEdit { | |
| 189 | 189 | let text_edit = text_edit(line_index, indel); |
| 190 | 190 | match insert_replace_support { |
| 191 | 191 | Some(cursor_pos) => lsp_types::InsertReplaceEdit { |
| ... | ... | @@ -208,7 +208,7 @@ pub(crate) fn snippet_text_edit( |
| 208 | 208 | let annotation_id = annotation.filter(|_| client_supports_annotations).map(|it| it.to_string()); |
| 209 | 209 | let text_edit = text_edit(line_index, indel); |
| 210 | 210 | let insert_text_format = |
| 211 | if is_snippet { Some(lsp_types::InsertTextFormat::SNIPPET) } else { None }; | |
| 211 | if is_snippet { Some(lsp_types::InsertTextFormat::Snippet) } else { None }; | |
| 212 | 212 | lsp_ext::SnippetTextEdit { |
| 213 | 213 | range: text_edit.range, |
| 214 | 214 | new_text: text_edit.new_text, |
| ... | ... | @@ -250,7 +250,7 @@ pub(crate) fn completion_items( |
| 250 | 250 | fields_to_resolve: &CompletionFieldsToResolve, |
| 251 | 251 | line_index: &LineIndex, |
| 252 | 252 | version: Option<i32>, |
| 253 | tdpp: lsp_types::TextDocumentPositionParams, | |
| 253 | tdpp: &lsp_types::TextDocumentPositionParams, | |
| 254 | 254 | completion_trigger_character: Option<char>, |
| 255 | 255 | mut items: Vec<CompletionItem>, |
| 256 | 256 | ) -> Vec<lsp_types::CompletionItem> { |
| ... | ... | @@ -269,7 +269,7 @@ pub(crate) fn completion_items( |
| 269 | 269 | fields_to_resolve, |
| 270 | 270 | line_index, |
| 271 | 271 | version, |
| 272 | &tdpp, | |
| 272 | tdpp, | |
| 273 | 273 | max_relevance, |
| 274 | 274 | completion_trigger_character, |
| 275 | 275 | item, |
| ... | ... | @@ -340,12 +340,12 @@ fn completion_item( |
| 340 | 340 | Some(text_edit.unwrap()) |
| 341 | 341 | }; |
| 342 | 342 | |
| 343 | let insert_text_format = item.is_snippet.then_some(lsp_types::InsertTextFormat::SNIPPET); | |
| 343 | let insert_text_format = item.is_snippet.then_some(lsp_types::InsertTextFormat::Snippet); | |
| 344 | 344 | let tags = if fields_to_resolve.resolve_tags { |
| 345 | 345 | something_to_resolve |= item.deprecated; |
| 346 | 346 | None |
| 347 | 347 | } else { |
| 348 | item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED]) | |
| 348 | item.deprecated.then(|| vec![lsp_types::CompletionItemTag::Deprecated]) | |
| 349 | 349 | }; |
| 350 | 350 | let command = if item.trigger_call_info && client_commands.trigger_parameter_hints { |
| 351 | 351 | if fields_to_resolve.resolve_command { |
| ... | ... | @@ -383,6 +383,7 @@ fn completion_item( |
| 383 | 383 | .not() |
| 384 | 384 | .then_some(additional_text_edits), |
| 385 | 385 | documentation, |
| 386 | #[expect(deprecated, reason = "we do use tags")] | |
| 386 | 387 | deprecated: item.deprecated.then_some(item.deprecated), |
| 387 | 388 | tags, |
| 388 | 389 | command, |
| ... | ... | @@ -491,7 +492,7 @@ pub(crate) fn signature_help( |
| 491 | 492 | let params = call_info |
| 492 | 493 | .parameter_labels() |
| 493 | 494 | .map(|label| lsp_types::ParameterInformation { |
| 494 | label: lsp_types::ParameterLabel::Simple(label.to_owned()), | |
| 495 | label: lsp_types::ParameterInformationLabel::String(label.to_owned()), | |
| 495 | 496 | documentation: None, |
| 496 | 497 | }) |
| 497 | 498 | .collect::<Vec<_>>(); |
| ... | ... | @@ -513,10 +514,10 @@ pub(crate) fn signature_help( |
| 513 | 514 | .chars() |
| 514 | 515 | .map(|c| c.len_utf16()) |
| 515 | 516 | .sum::<usize>() as u32; |
| 516 | [start, end] | |
| 517 | (start, end) | |
| 517 | 518 | }) |
| 518 | 519 | .map(|label_offsets| lsp_types::ParameterInformation { |
| 519 | label: lsp_types::ParameterLabel::LabelOffsets(label_offsets), | |
| 520 | label: lsp_types::ParameterInformationLabel::Tuple(label_offsets), | |
| 520 | 521 | documentation: None, |
| 521 | 522 | }) |
| 522 | 523 | .collect::<Vec<_>>(); |
| ... | ... | @@ -535,7 +536,7 @@ pub(crate) fn signature_help( |
| 535 | 536 | label.push_str(param); |
| 536 | 537 | let end = label.len() as u32; |
| 537 | 538 | params.push(lsp_types::ParameterInformation { |
| 538 | label: lsp_types::ParameterLabel::LabelOffsets([start, end]), | |
| 539 | label: lsp_types::ParameterInformationLabel::Tuple((start, end)), | |
| 539 | 540 | documentation: None, |
| 540 | 541 | }); |
| 541 | 542 | } |
| ... | ... | @@ -551,7 +552,8 @@ pub(crate) fn signature_help( |
| 551 | 552 | }) |
| 552 | 553 | }); |
| 553 | 554 | |
| 554 | let active_parameter = call_info.active_parameter.map(|it| it as u32); | |
| 555 | let active_parameter = | |
| 556 | call_info.active_parameter.map(|it| lsp_types::ActiveParameter::Int(it as u32)); | |
| 555 | 557 | |
| 556 | 558 | let signature = lsp_types::SignatureInformation { |
| 557 | 559 | label, |
| ... | ... | @@ -639,9 +641,9 @@ pub(crate) fn inlay_hint( |
| 639 | 641 | padding_right: Some(inlay_hint.pad_right), |
| 640 | 642 | kind: match inlay_hint.kind { |
| 641 | 643 | InlayKind::Parameter | InlayKind::GenericParameter => { |
| 642 | Some(lsp_types::InlayHintKind::PARAMETER) | |
| 644 | Some(lsp_types::InlayHintKind::Parameter) | |
| 643 | 645 | } |
| 644 | InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::TYPE), | |
| 646 | InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::Type), | |
| 645 | 647 | _ => None, |
| 646 | 648 | }, |
| 647 | 649 | text_edits, |
| ... | ... | @@ -657,7 +659,7 @@ fn inlay_hint_label( |
| 657 | 659 | something_to_resolve: &mut bool, |
| 658 | 660 | needs_resolve: bool, |
| 659 | 661 | mut label: InlayHintLabel, |
| 660 | ) -> Cancellable<(lsp_types::InlayHintLabel, Option<lsp_types::InlayHintTooltip>)> { | |
| 662 | ) -> Cancellable<(lsp_types::Label, Option<lsp_types::Tooltip>)> { | |
| 661 | 663 | let (label, tooltip) = match &*label.parts { |
| 662 | 664 | [InlayHintLabelPart { linked_location: None, .. }] => { |
| 663 | 665 | let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap(); |
| ... | ... | @@ -670,16 +672,16 @@ fn inlay_hint_label( |
| 670 | 672 | } |
| 671 | 673 | }); |
| 672 | 674 | let hint_tooltip = match tooltip { |
| 673 | Some(ide::InlayTooltip::String(s)) => Some(lsp_types::InlayHintTooltip::String(s)), | |
| 675 | Some(ide::InlayTooltip::String(s)) => Some(lsp_types::Tooltip::String(s)), | |
| 674 | 676 | Some(ide::InlayTooltip::Markdown(s)) => { |
| 675 | Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent { | |
| 677 | Some(lsp_types::Tooltip::MarkupContent(lsp_types::MarkupContent { | |
| 676 | 678 | kind: lsp_types::MarkupKind::Markdown, |
| 677 | 679 | value: s, |
| 678 | 680 | })) |
| 679 | 681 | } |
| 680 | 682 | None => None, |
| 681 | 683 | }; |
| 682 | (lsp_types::InlayHintLabel::String(text), hint_tooltip) | |
| 684 | (lsp_types::Label::String(text), hint_tooltip) | |
| 683 | 685 | } |
| 684 | 686 | _ => { |
| 685 | 687 | let parts = label |
| ... | ... | @@ -694,16 +696,12 @@ fn inlay_hint_label( |
| 694 | 696 | } |
| 695 | 697 | }); |
| 696 | 698 | let tooltip = match tooltip { |
| 697 | Some(ide::InlayTooltip::String(s)) => { | |
| 698 | Some(lsp_types::InlayHintLabelPartTooltip::String(s)) | |
| 699 | } | |
| 699 | Some(ide::InlayTooltip::String(s)) => Some(lsp_types::Tooltip::String(s)), | |
| 700 | 700 | Some(ide::InlayTooltip::Markdown(s)) => { |
| 701 | Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent( | |
| 702 | lsp_types::MarkupContent { | |
| 703 | kind: lsp_types::MarkupKind::Markdown, | |
| 704 | value: s, | |
| 705 | }, | |
| 706 | )) | |
| 701 | Some(lsp_types::Tooltip::MarkupContent(lsp_types::MarkupContent { | |
| 702 | kind: lsp_types::MarkupKind::Markdown, | |
| 703 | value: s, | |
| 704 | })) | |
| 707 | 705 | } |
| 708 | 706 | None => None, |
| 709 | 707 | }; |
| ... | ... | @@ -726,7 +724,7 @@ fn inlay_hint_label( |
| 726 | 724 | }) |
| 727 | 725 | }) |
| 728 | 726 | .collect::<Cancellable<_>>()?; |
| 729 | (lsp_types::InlayHintLabel::LabelParts(parts), None) | |
| 727 | (lsp_types::Label::InlayHintLabelPartList(parts), None) | |
| 730 | 728 | } |
| 731 | 729 | }; |
| 732 | 730 | Ok((label, tooltip)) |
| ... | ... | @@ -773,11 +771,11 @@ pub(crate) fn semantic_tokens( |
| 773 | 771 | |
| 774 | 772 | if !non_standard_tokens { |
| 775 | 773 | ty = match standard_fallback_type(ty) { |
| 776 | Some(ty) => ty, | |
| 774 | Some(fallback) => fallback, | |
| 777 | 775 | None => continue, |
| 778 | 776 | }; |
| 779 | 777 | mods.standard_fallback(); |
| 780 | } | |
| 778 | }; | |
| 781 | 779 | let token_index = semantic_tokens::type_index(ty); |
| 782 | 780 | let modifier_bitset = mods.0; |
| 783 | 781 | |
| ... | ... | @@ -805,106 +803,106 @@ pub(crate) fn semantic_token_delta( |
| 805 | 803 | |
| 806 | 804 | fn semantic_token_type_and_modifiers( |
| 807 | 805 | highlight: Highlight, |
| 808 | ) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) { | |
| 809 | use semantic_tokens::{modifiers as mods, types}; | |
| 806 | ) -> (semantic_tokens::SupportedType, semantic_tokens::ModifierSet) { | |
| 807 | use semantic_tokens::{SupportedModifiers, SupportedType}; | |
| 810 | 808 | |
| 811 | 809 | let mut mods = semantic_tokens::ModifierSet::default(); |
| 812 | 810 | let ty = match highlight.tag { |
| 813 | 811 | HlTag::Symbol(symbol) => match symbol { |
| 814 | SymbolKind::Attribute => types::DECORATOR, | |
| 815 | SymbolKind::Derive => types::DERIVE, | |
| 816 | SymbolKind::DeriveHelper => types::DERIVE_HELPER, | |
| 812 | SymbolKind::Attribute => SupportedType::Decorator, | |
| 813 | SymbolKind::Derive => SupportedType::Derive, | |
| 814 | SymbolKind::DeriveHelper => SupportedType::DeriveHelper, | |
| 817 | 815 | SymbolKind::CrateRoot => { |
| 818 | mods |= mods::CRATE_ROOT; | |
| 819 | types::NAMESPACE | |
| 816 | mods |= SupportedModifiers::CrateRoot; | |
| 817 | SupportedType::Namespace | |
| 820 | 818 | } |
| 821 | SymbolKind::Module => types::NAMESPACE, | |
| 822 | SymbolKind::Impl => types::TYPE_ALIAS, | |
| 823 | SymbolKind::Field => types::PROPERTY, | |
| 824 | SymbolKind::TypeParam => types::TYPE_PARAMETER, | |
| 825 | SymbolKind::ConstParam => types::CONST_PARAMETER, | |
| 826 | SymbolKind::LifetimeParam => types::LIFETIME, | |
| 827 | SymbolKind::Label => types::LABEL, | |
| 828 | SymbolKind::ValueParam => types::PARAMETER, | |
| 829 | SymbolKind::SelfParam => types::SELF_KEYWORD, | |
| 830 | SymbolKind::SelfType => types::SELF_TYPE_KEYWORD, | |
| 831 | SymbolKind::Local => types::VARIABLE, | |
| 832 | SymbolKind::Method => types::METHOD, | |
| 833 | SymbolKind::Function => types::FUNCTION, | |
| 834 | SymbolKind::Const => types::CONST, | |
| 835 | SymbolKind::Static => types::STATIC, | |
| 836 | SymbolKind::Struct => types::STRUCT, | |
| 837 | SymbolKind::Enum => types::ENUM, | |
| 838 | SymbolKind::Variant => types::ENUM_MEMBER, | |
| 839 | SymbolKind::Union => types::UNION, | |
| 840 | SymbolKind::TypeAlias => types::TYPE_ALIAS, | |
| 841 | SymbolKind::Trait => types::INTERFACE, | |
| 842 | SymbolKind::Macro => types::MACRO, | |
| 843 | SymbolKind::ProcMacro => types::PROC_MACRO, | |
| 844 | SymbolKind::BuiltinAttr => types::BUILTIN_ATTRIBUTE, | |
| 845 | SymbolKind::ToolModule => types::TOOL_MODULE, | |
| 846 | SymbolKind::InlineAsmRegOrRegClass => types::KEYWORD, | |
| 819 | SymbolKind::Module => SupportedType::Namespace, | |
| 820 | SymbolKind::Impl => SupportedType::TypeAlias, | |
| 821 | SymbolKind::Field => SupportedType::Property, | |
| 822 | SymbolKind::TypeParam => SupportedType::TypeParameter, | |
| 823 | SymbolKind::ConstParam => SupportedType::ConstParameter, | |
| 824 | SymbolKind::LifetimeParam => SupportedType::Lifetime, | |
| 825 | SymbolKind::Label => SupportedType::Label, | |
| 826 | SymbolKind::ValueParam => SupportedType::Parameter, | |
| 827 | SymbolKind::SelfParam => SupportedType::SelfKeyword, | |
| 828 | SymbolKind::SelfType => SupportedType::SelfTypeKeyword, | |
| 829 | SymbolKind::Local => SupportedType::Variable, | |
| 830 | SymbolKind::Method => SupportedType::Method, | |
| 831 | SymbolKind::Function => SupportedType::Function, | |
| 832 | SymbolKind::Const => SupportedType::Const, | |
| 833 | SymbolKind::Static => SupportedType::Static, | |
| 834 | SymbolKind::Struct => SupportedType::Struct, | |
| 835 | SymbolKind::Enum => SupportedType::Enum, | |
| 836 | SymbolKind::Variant => SupportedType::EnumMember, | |
| 837 | SymbolKind::Union => SupportedType::Union, | |
| 838 | SymbolKind::TypeAlias => SupportedType::TypeAlias, | |
| 839 | SymbolKind::Trait => SupportedType::Interface, | |
| 840 | SymbolKind::Macro => SupportedType::Macro, | |
| 841 | SymbolKind::ProcMacro => SupportedType::ProcMacro, | |
| 842 | SymbolKind::BuiltinAttr => SupportedType::BuiltinAttribute, | |
| 843 | SymbolKind::ToolModule => SupportedType::ToolModule, | |
| 844 | SymbolKind::InlineAsmRegOrRegClass => SupportedType::Keyword, | |
| 847 | 845 | }, |
| 848 | HlTag::AttributeBracket => types::ATTRIBUTE_BRACKET, | |
| 849 | HlTag::BoolLiteral => types::BOOLEAN, | |
| 850 | HlTag::BuiltinType => types::BUILTIN_TYPE, | |
| 851 | HlTag::ByteLiteral | HlTag::NumericLiteral => types::NUMBER, | |
| 852 | HlTag::CharLiteral => types::CHAR, | |
| 853 | HlTag::Comment => types::COMMENT, | |
| 854 | HlTag::EscapeSequence => types::ESCAPE_SEQUENCE, | |
| 855 | HlTag::InvalidEscapeSequence => types::INVALID_ESCAPE_SEQUENCE, | |
| 856 | HlTag::FormatSpecifier => types::FORMAT_SPECIFIER, | |
| 857 | HlTag::Keyword => types::KEYWORD, | |
| 858 | HlTag::None => types::GENERIC, | |
| 846 | HlTag::AttributeBracket => SupportedType::AttributeBracket, | |
| 847 | HlTag::BoolLiteral => SupportedType::Boolean, | |
| 848 | HlTag::BuiltinType => SupportedType::BuiltinType, | |
| 849 | HlTag::ByteLiteral | HlTag::NumericLiteral => SupportedType::Number, | |
| 850 | HlTag::CharLiteral => SupportedType::Char, | |
| 851 | HlTag::Comment => SupportedType::Comment, | |
| 852 | HlTag::EscapeSequence => SupportedType::EscapeSequence, | |
| 853 | HlTag::InvalidEscapeSequence => SupportedType::InvalidEscapeSequence, | |
| 854 | HlTag::FormatSpecifier => SupportedType::FormatSpecifier, | |
| 855 | HlTag::Keyword => SupportedType::Keyword, | |
| 856 | HlTag::None => SupportedType::Generic, | |
| 859 | 857 | HlTag::Operator(op) => match op { |
| 860 | HlOperator::Bitwise => types::BITWISE, | |
| 861 | HlOperator::Arithmetic => types::ARITHMETIC, | |
| 862 | HlOperator::Logical => types::LOGICAL, | |
| 863 | HlOperator::Negation => types::NEGATION, | |
| 864 | HlOperator::Comparison => types::COMPARISON, | |
| 865 | HlOperator::Other => types::OPERATOR, | |
| 858 | HlOperator::Bitwise => SupportedType::Bitwise, | |
| 859 | HlOperator::Arithmetic => SupportedType::Arithmetic, | |
| 860 | HlOperator::Logical => SupportedType::Logical, | |
| 861 | HlOperator::Negation => SupportedType::Negation, | |
| 862 | HlOperator::Comparison => SupportedType::Comparison, | |
| 863 | HlOperator::Other => SupportedType::Operator, | |
| 866 | 864 | }, |
| 867 | HlTag::StringLiteral => types::STRING, | |
| 868 | HlTag::UnresolvedReference => types::UNRESOLVED_REFERENCE, | |
| 865 | HlTag::StringLiteral => SupportedType::String, | |
| 866 | HlTag::UnresolvedReference => SupportedType::UnresolvedReference, | |
| 869 | 867 | HlTag::Punctuation(punct) => match punct { |
| 870 | HlPunct::Bracket => types::BRACKET, | |
| 871 | HlPunct::Brace => types::BRACE, | |
| 872 | HlPunct::Parenthesis => types::PARENTHESIS, | |
| 873 | HlPunct::Angle => types::ANGLE, | |
| 874 | HlPunct::Comma => types::COMMA, | |
| 875 | HlPunct::Dot => types::DOT, | |
| 876 | HlPunct::Colon => types::COLON, | |
| 877 | HlPunct::Semi => types::SEMICOLON, | |
| 878 | HlPunct::Other => types::PUNCTUATION, | |
| 879 | HlPunct::MacroBang => types::MACRO_BANG, | |
| 868 | HlPunct::Bracket => SupportedType::Bracket, | |
| 869 | HlPunct::Brace => SupportedType::Brace, | |
| 870 | HlPunct::Parenthesis => SupportedType::Parenthesis, | |
| 871 | HlPunct::Angle => SupportedType::Angle, | |
| 872 | HlPunct::Comma => SupportedType::Comma, | |
| 873 | HlPunct::Dot => SupportedType::Dot, | |
| 874 | HlPunct::Colon => SupportedType::Colon, | |
| 875 | HlPunct::Semi => SupportedType::Semicolon, | |
| 876 | HlPunct::Other => SupportedType::Punctuation, | |
| 877 | HlPunct::MacroBang => SupportedType::MacroBang, | |
| 880 | 878 | }, |
| 881 | 879 | }; |
| 882 | 880 | |
| 883 | 881 | for modifier in highlight.mods.iter() { |
| 884 | 882 | let modifier = match modifier { |
| 885 | HlMod::Associated => mods::ASSOCIATED, | |
| 886 | HlMod::Async => mods::ASYNC, | |
| 887 | HlMod::Attribute => mods::ATTRIBUTE_MODIFIER, | |
| 888 | HlMod::Callable => mods::CALLABLE, | |
| 889 | HlMod::Const => mods::CONSTANT, | |
| 890 | HlMod::Consuming => mods::CONSUMING, | |
| 891 | HlMod::ControlFlow => mods::CONTROL_FLOW, | |
| 892 | HlMod::CrateRoot => mods::CRATE_ROOT, | |
| 893 | HlMod::DefaultLibrary => mods::DEFAULT_LIBRARY, | |
| 894 | HlMod::Deprecated => mods::DEPRECATED, | |
| 895 | HlMod::Definition => mods::DECLARATION, | |
| 896 | HlMod::Documentation => mods::DOCUMENTATION, | |
| 897 | HlMod::Injected => mods::INJECTED, | |
| 898 | HlMod::IntraDocLink => mods::INTRA_DOC_LINK, | |
| 899 | HlMod::Library => mods::LIBRARY, | |
| 900 | HlMod::Macro => mods::MACRO_MODIFIER, | |
| 901 | HlMod::ProcMacro => mods::PROC_MACRO_MODIFIER, | |
| 902 | HlMod::Mutable => mods::MUTABLE, | |
| 903 | HlMod::Public => mods::PUBLIC, | |
| 904 | HlMod::Reference => mods::REFERENCE, | |
| 905 | HlMod::Static => mods::STATIC, | |
| 906 | HlMod::Trait => mods::TRAIT_MODIFIER, | |
| 907 | HlMod::Unsafe => mods::UNSAFE, | |
| 883 | HlMod::Associated => SupportedModifiers::Associated, | |
| 884 | HlMod::Async => SupportedModifiers::Async, | |
| 885 | HlMod::Attribute => SupportedModifiers::AttributeModifier, | |
| 886 | HlMod::Callable => SupportedModifiers::Callable, | |
| 887 | HlMod::Const => SupportedModifiers::Constant, | |
| 888 | HlMod::Consuming => SupportedModifiers::Consuming, | |
| 889 | HlMod::ControlFlow => SupportedModifiers::ControlFlow, | |
| 890 | HlMod::CrateRoot => SupportedModifiers::CrateRoot, | |
| 891 | HlMod::DefaultLibrary => SupportedModifiers::DefaultLibrary, | |
| 892 | HlMod::Deprecated => SupportedModifiers::Deprecated, | |
| 893 | HlMod::Definition => SupportedModifiers::Declaration, | |
| 894 | HlMod::Documentation => SupportedModifiers::Documentation, | |
| 895 | HlMod::Injected => SupportedModifiers::Injected, | |
| 896 | HlMod::IntraDocLink => SupportedModifiers::IntraDocLink, | |
| 897 | HlMod::Library => SupportedModifiers::Library, | |
| 898 | HlMod::Macro => SupportedModifiers::MacroModifier, | |
| 899 | HlMod::ProcMacro => SupportedModifiers::ProcMacroModifier, | |
| 900 | HlMod::Mutable => SupportedModifiers::Mutable, | |
| 901 | HlMod::Public => SupportedModifiers::Public, | |
| 902 | HlMod::Reference => SupportedModifiers::Reference, | |
| 903 | HlMod::Static => SupportedModifiers::Static, | |
| 904 | HlMod::Trait => SupportedModifiers::TraitModifier, | |
| 905 | HlMod::Unsafe => SupportedModifiers::Unsafe, | |
| 908 | 906 | }; |
| 909 | 907 | mods |= modifier; |
| 910 | 908 | } |
| ... | ... | @@ -983,16 +981,16 @@ pub(crate) fn folding_range( |
| 983 | 981 | } |
| 984 | 982 | } |
| 985 | 983 | |
| 986 | pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Url { | |
| 984 | pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Uri { | |
| 987 | 985 | snap.file_id_to_url(file_id) |
| 988 | 986 | } |
| 989 | 987 | |
| 990 | /// Returns a `Url` object from a given path, will lowercase drive letters if present. | |
| 988 | /// Returns a `Uri` object from a given path, will lowercase drive letters if present. | |
| 991 | 989 | /// This will only happen when processing windows paths. |
| 992 | 990 | /// |
| 993 | /// When processing non-windows path, this is essentially the same as `Url::from_file_path`. | |
| 994 | pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url { | |
| 995 | let url = lsp_types::Url::from_file_path(path).unwrap(); | |
| 991 | /// When processing non-windows path, this is essentially the same as [`lsp_types::Uri::from_file_path`]. | |
| 992 | pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Uri { | |
| 993 | let url = lsp_types::Uri::from_file_path(path).unwrap(); | |
| 996 | 994 | match path.components().next() { |
| 997 | 995 | Some(Utf8Component::Prefix(prefix)) |
| 998 | 996 | if matches!(prefix.kind(), Utf8Prefix::Disk(_) | Utf8Prefix::VerbatimDisk(_)) => |
| ... | ... | @@ -1016,16 +1014,19 @@ pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url { |
| 1016 | 1014 | // string in place. |
| 1017 | 1015 | let mut url: String = url.into(); |
| 1018 | 1016 | url[driver_letter_range].make_ascii_lowercase(); |
| 1019 | lsp_types::Url::parse(&url).unwrap() | |
| 1017 | lsp_types::Uri::parse(&url).unwrap() | |
| 1020 | 1018 | } |
| 1021 | 1019 | |
| 1022 | 1020 | pub(crate) fn optional_versioned_text_document_identifier( |
| 1023 | 1021 | snap: &GlobalStateSnapshot, |
| 1024 | 1022 | file_id: FileId, |
| 1025 | 1023 | ) -> lsp_types::OptionalVersionedTextDocumentIdentifier { |
| 1026 | let url = url(snap, file_id); | |
| 1027 | let version = snap.url_file_version(&url); | |
| 1028 | lsp_types::OptionalVersionedTextDocumentIdentifier { uri: url, version } | |
| 1024 | let uri = url(snap, file_id); | |
| 1025 | let version = snap.url_file_version(&uri); | |
| 1026 | lsp_types::OptionalVersionedTextDocumentIdentifier { | |
| 1027 | text_document_identifier: lsp_types::TextDocumentIdentifier { uri }, | |
| 1028 | version, | |
| 1029 | } | |
| 1029 | 1030 | } |
| 1030 | 1031 | |
| 1031 | 1032 | pub(crate) fn location( |
| ... | ... | @@ -1042,7 +1043,7 @@ pub(crate) fn location( |
| 1042 | 1043 | /// Prefer using `location_link`, if the client has the cap. |
| 1043 | 1044 | pub(crate) fn location_from_nav( |
| 1044 | 1045 | snap: &GlobalStateSnapshot, |
| 1045 | nav: NavigationTarget, | |
| 1046 | nav: &NavigationTarget, | |
| 1046 | 1047 | ) -> Cancellable<lsp_types::Location> { |
| 1047 | 1048 | let url = url(snap, nav.file_id); |
| 1048 | 1049 | let line_index = snap.file_line_index(nav.file_id)?; |
| ... | ... | @@ -1077,7 +1078,7 @@ pub(crate) fn location_link( |
| 1077 | 1078 | fn location_info( |
| 1078 | 1079 | snap: &GlobalStateSnapshot, |
| 1079 | 1080 | target: NavigationTarget, |
| 1080 | ) -> Cancellable<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> { | |
| 1081 | ) -> Cancellable<(lsp_types::Uri, lsp_types::Range, lsp_types::Range)> { | |
| 1081 | 1082 | let line_index = snap.file_line_index(target.file_id)?; |
| 1082 | 1083 | |
| 1083 | 1084 | let target_uri = url(snap, target.file_id); |
| ... | ... | @@ -1091,25 +1092,90 @@ pub(crate) fn goto_definition_response( |
| 1091 | 1092 | snap: &GlobalStateSnapshot, |
| 1092 | 1093 | src: Option<FileRange>, |
| 1093 | 1094 | targets: Vec<NavigationTarget>, |
| 1094 | ) -> Cancellable<lsp_types::GotoDefinitionResponse> { | |
| 1095 | ) -> Cancellable<lsp_types::DefinitionResponse> { | |
| 1095 | 1096 | if snap.config.location_link() { |
| 1096 | let links = targets | |
| 1097 | .into_iter() | |
| 1098 | .unique_by(|nav| (nav.file_id, nav.full_range, nav.focus_range)) | |
| 1099 | .map(|nav| location_link(snap, src, nav)) | |
| 1100 | .collect::<Cancellable<Vec<_>>>()?; | |
| 1097 | let links = targets_to_links(snap, src, targets)?; | |
| 1101 | 1098 | Ok(links.into()) |
| 1102 | 1099 | } else { |
| 1103 | let locations = targets | |
| 1104 | .into_iter() | |
| 1105 | .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) | |
| 1106 | .unique() | |
| 1107 | .map(|range| location(snap, range)) | |
| 1108 | .collect::<Cancellable<Vec<_>>>()?; | |
| 1109 | Ok(locations.into()) | |
| 1100 | let locations = targets_to_locations(snap, targets)?; | |
| 1101 | Ok(lsp_types::DefinitionResponse::Definition(lsp_types::Definition::LocationList( | |
| 1102 | locations, | |
| 1103 | ))) | |
| 1104 | } | |
| 1105 | } | |
| 1106 | ||
| 1107 | pub(crate) fn goto_declaration_response( | |
| 1108 | snap: &GlobalStateSnapshot, | |
| 1109 | src: Option<FileRange>, | |
| 1110 | targets: Vec<NavigationTarget>, | |
| 1111 | ) -> Cancellable<lsp_types::DeclarationResponse> { | |
| 1112 | if snap.config.location_link() { | |
| 1113 | let links = targets_to_links(snap, src, targets)?; | |
| 1114 | Ok(links.into()) | |
| 1115 | } else { | |
| 1116 | let locations = targets_to_locations(snap, targets)?; | |
| 1117 | Ok(lsp_types::DeclarationResponse::Declaration(lsp_types::Declaration::LocationList( | |
| 1118 | locations, | |
| 1119 | ))) | |
| 1110 | 1120 | } |
| 1111 | 1121 | } |
| 1112 | 1122 | |
| 1123 | pub(crate) fn goto_implementation_response( | |
| 1124 | snap: &GlobalStateSnapshot, | |
| 1125 | src: Option<FileRange>, | |
| 1126 | targets: Vec<NavigationTarget>, | |
| 1127 | ) -> Cancellable<lsp_types::ImplementationResponse> { | |
| 1128 | if snap.config.location_link() { | |
| 1129 | let links = targets_to_links(snap, src, targets)?; | |
| 1130 | Ok(links.into()) | |
| 1131 | } else { | |
| 1132 | let locations = targets_to_locations(snap, targets)?; | |
| 1133 | Ok(lsp_types::ImplementationResponse::Definition(lsp_types::Definition::LocationList( | |
| 1134 | locations, | |
| 1135 | ))) | |
| 1136 | } | |
| 1137 | } | |
| 1138 | ||
| 1139 | pub(crate) fn goto_type_definition_response( | |
| 1140 | snap: &GlobalStateSnapshot, | |
| 1141 | src: Option<FileRange>, | |
| 1142 | targets: Vec<NavigationTarget>, | |
| 1143 | ) -> Cancellable<lsp_types::TypeDefinitionResponse> { | |
| 1144 | if snap.config.location_link() { | |
| 1145 | let links = targets_to_links(snap, src, targets)?; | |
| 1146 | Ok(links.into()) | |
| 1147 | } else { | |
| 1148 | let locations = targets_to_locations(snap, targets)?; | |
| 1149 | Ok(lsp_types::TypeDefinitionResponse::Definition(lsp_types::Definition::LocationList( | |
| 1150 | locations, | |
| 1151 | ))) | |
| 1152 | } | |
| 1153 | } | |
| 1154 | ||
| 1155 | fn targets_to_links( | |
| 1156 | snap: &GlobalStateSnapshot, | |
| 1157 | src: Option<hir::FileRangeWrapper<FileId>>, | |
| 1158 | targets: Vec<NavigationTarget>, | |
| 1159 | ) -> Result<Vec<lsp_types::LocationLink>, ide_db::base_db::salsa::Cancelled> { | |
| 1160 | targets | |
| 1161 | .into_iter() | |
| 1162 | .unique_by(|nav| (nav.file_id, nav.full_range, nav.focus_range)) | |
| 1163 | .map(|nav| location_link(snap, src, nav)) | |
| 1164 | .collect::<Cancellable<Vec<_>>>() | |
| 1165 | } | |
| 1166 | ||
| 1167 | fn targets_to_locations( | |
| 1168 | snap: &GlobalStateSnapshot, | |
| 1169 | targets: Vec<NavigationTarget>, | |
| 1170 | ) -> Result<Vec<lsp_types::Location>, ide_db::base_db::salsa::Cancelled> { | |
| 1171 | targets | |
| 1172 | .into_iter() | |
| 1173 | .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) | |
| 1174 | .unique() | |
| 1175 | .map(|range| location(snap, range)) | |
| 1176 | .collect::<Cancellable<Vec<_>>>() | |
| 1177 | } | |
| 1178 | ||
| 1113 | 1179 | fn outside_workspace_annotation_id() -> String { |
| 1114 | 1180 | String::from("OutsideWorkspace") |
| 1115 | 1181 | } |
| ... | ... | @@ -1318,19 +1384,21 @@ pub(crate) fn snippet_text_document_ops( |
| 1318 | 1384 | match file_system_edit { |
| 1319 | 1385 | FileSystemEdit::CreateFile { dst, initial_contents } => { |
| 1320 | 1386 | let uri = snap.anchored_path(&dst); |
| 1321 | let create_file = lsp_types::ResourceOp::Create(lsp_types::CreateFile { | |
| 1387 | let create_file = lsp_types::DocumentChange::CreateFile(lsp_types::CreateFile { | |
| 1322 | 1388 | uri: uri.clone(), |
| 1323 | 1389 | options: None, |
| 1324 | 1390 | annotation_id: None, |
| 1325 | 1391 | }); |
| 1326 | ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(create_file)); | |
| 1392 | ops.push(lsp_ext::SnippetDocumentChangeOperation::Change(create_file)); | |
| 1327 | 1393 | if !initial_contents.is_empty() { |
| 1328 | let text_document = | |
| 1329 | lsp_types::OptionalVersionedTextDocumentIdentifier { uri, version: None }; | |
| 1394 | let text_document = lsp_types::OptionalVersionedTextDocumentIdentifier { | |
| 1395 | text_document_identifier: lsp_types::TextDocumentIdentifier { uri }, | |
| 1396 | version: None, | |
| 1397 | }; | |
| 1330 | 1398 | let text_edit = lsp_ext::SnippetTextEdit { |
| 1331 | 1399 | range: lsp_types::Range::default(), |
| 1332 | 1400 | new_text: initial_contents, |
| 1333 | insert_text_format: Some(lsp_types::InsertTextFormat::PLAIN_TEXT), | |
| 1401 | insert_text_format: Some(lsp_types::InsertTextFormat::PlainText), | |
| 1334 | 1402 | annotation_id: None, |
| 1335 | 1403 | }; |
| 1336 | 1404 | let edit_file = |
| ... | ... | @@ -1348,9 +1416,9 @@ pub(crate) fn snippet_text_document_ops( |
| 1348 | 1416 | { |
| 1349 | 1417 | rename_file.annotation_id = Some(outside_workspace_annotation_id()) |
| 1350 | 1418 | } |
| 1351 | ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(lsp_types::ResourceOp::Rename( | |
| 1352 | rename_file, | |
| 1353 | ))) | |
| 1419 | ops.push(lsp_ext::SnippetDocumentChangeOperation::Change( | |
| 1420 | lsp_types::DocumentChange::RenameFile(rename_file), | |
| 1421 | )) | |
| 1354 | 1422 | } |
| 1355 | 1423 | FileSystemEdit::MoveDir { src, src_id, dst } => { |
| 1356 | 1424 | let old_uri = snap.anchored_path(&src); |
| ... | ... | @@ -1362,9 +1430,9 @@ pub(crate) fn snippet_text_document_ops( |
| 1362 | 1430 | { |
| 1363 | 1431 | rename_file.annotation_id = Some(outside_workspace_annotation_id()) |
| 1364 | 1432 | } |
| 1365 | ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(lsp_types::ResourceOp::Rename( | |
| 1366 | rename_file, | |
| 1367 | ))) | |
| 1433 | ops.push(lsp_ext::SnippetDocumentChangeOperation::Change( | |
| 1434 | lsp_types::DocumentChange::RenameFile(rename_file), | |
| 1435 | )) | |
| 1368 | 1436 | } |
| 1369 | 1437 | } |
| 1370 | 1438 | Ok(ops) |
| ... | ... | @@ -1449,42 +1517,38 @@ impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit { |
| 1449 | 1517 | lsp_types::WorkspaceEdit { |
| 1450 | 1518 | changes: None, |
| 1451 | 1519 | document_changes: snippet_workspace_edit.document_changes.map(|changes| { |
| 1452 | lsp_types::DocumentChanges::Operations( | |
| 1453 | changes | |
| 1454 | .into_iter() | |
| 1455 | .map(|change| match change { | |
| 1456 | lsp_ext::SnippetDocumentChangeOperation::Op(op) => { | |
| 1457 | lsp_types::DocumentChangeOperation::Op(op) | |
| 1458 | } | |
| 1459 | lsp_ext::SnippetDocumentChangeOperation::Edit(edit) => { | |
| 1460 | lsp_types::DocumentChangeOperation::Edit( | |
| 1461 | lsp_types::TextDocumentEdit { | |
| 1462 | text_document: edit.text_document, | |
| 1463 | edits: edit.edits.into_iter().map(From::from).collect(), | |
| 1464 | }, | |
| 1465 | ) | |
| 1466 | } | |
| 1467 | }) | |
| 1468 | .collect(), | |
| 1469 | ) | |
| 1520 | changes | |
| 1521 | .into_iter() | |
| 1522 | .map(|change| match change { | |
| 1523 | lsp_ext::SnippetDocumentChangeOperation::Change(op) => op, | |
| 1524 | lsp_ext::SnippetDocumentChangeOperation::Edit(edit) => { | |
| 1525 | lsp_types::DocumentChange::TextDocumentEdit( | |
| 1526 | lsp_types::TextDocumentEdit { | |
| 1527 | text_document: edit.text_document, | |
| 1528 | edits: edit.edits.into_iter().map(From::from).collect(), | |
| 1529 | }, | |
| 1530 | ) | |
| 1531 | } | |
| 1532 | }) | |
| 1533 | .collect() | |
| 1470 | 1534 | }), |
| 1471 | 1535 | change_annotations: snippet_workspace_edit.change_annotations, |
| 1472 | 1536 | } |
| 1473 | 1537 | } |
| 1474 | 1538 | } |
| 1475 | 1539 | |
| 1476 | impl From<lsp_ext::SnippetTextEdit> | |
| 1477 | for lsp_types::OneOf<lsp_types::TextEdit, lsp_types::AnnotatedTextEdit> | |
| 1478 | { | |
| 1540 | impl From<lsp_ext::SnippetTextEdit> for lsp_types::Edit { | |
| 1479 | 1541 | fn from( |
| 1480 | 1542 | lsp_ext::SnippetTextEdit { annotation_id, insert_text_format:_, new_text, range }: lsp_ext::SnippetTextEdit, |
| 1481 | 1543 | ) -> Self { |
| 1482 | 1544 | match annotation_id { |
| 1483 | Some(annotation_id) => lsp_types::OneOf::Right(lsp_types::AnnotatedTextEdit { | |
| 1484 | text_edit: lsp_types::TextEdit { range, new_text }, | |
| 1485 | annotation_id, | |
| 1486 | }), | |
| 1487 | None => lsp_types::OneOf::Left(lsp_types::TextEdit { range, new_text }), | |
| 1545 | Some(annotation_id) => { | |
| 1546 | lsp_types::Edit::AnnotatedTextEdit(lsp_types::AnnotatedTextEdit { | |
| 1547 | text_edit: lsp_types::TextEdit { range, new_text }, | |
| 1548 | annotation_id, | |
| 1549 | }) | |
| 1550 | } | |
| 1551 | None => lsp_types::Edit::TextEdit(lsp_types::TextEdit { range, new_text }), | |
| 1488 | 1552 | } |
| 1489 | 1553 | } |
| 1490 | 1554 | } |
| ... | ... | @@ -1495,7 +1559,7 @@ pub(crate) fn call_hierarchy_item( |
| 1495 | 1559 | ) -> Cancellable<lsp_types::CallHierarchyItem> { |
| 1496 | 1560 | let name = target.name.to_string(); |
| 1497 | 1561 | let detail = target.description.clone(); |
| 1498 | let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::FUNCTION); | |
| 1562 | let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::Function); | |
| 1499 | 1563 | let (uri, range, selection_range) = location_info(snap, target)?; |
| 1500 | 1564 | Ok(lsp_types::CallHierarchyItem { |
| 1501 | 1565 | name, |
| ... | ... | @@ -1511,12 +1575,12 @@ pub(crate) fn call_hierarchy_item( |
| 1511 | 1575 | |
| 1512 | 1576 | pub(crate) fn code_action_kind(kind: AssistKind) -> lsp_types::CodeActionKind { |
| 1513 | 1577 | match kind { |
| 1514 | AssistKind::Generate => lsp_types::CodeActionKind::EMPTY, | |
| 1515 | AssistKind::QuickFix => lsp_types::CodeActionKind::QUICKFIX, | |
| 1516 | AssistKind::Refactor => lsp_types::CodeActionKind::REFACTOR, | |
| 1517 | AssistKind::RefactorExtract => lsp_types::CodeActionKind::REFACTOR_EXTRACT, | |
| 1518 | AssistKind::RefactorInline => lsp_types::CodeActionKind::REFACTOR_INLINE, | |
| 1519 | AssistKind::RefactorRewrite => lsp_types::CodeActionKind::REFACTOR_REWRITE, | |
| 1578 | AssistKind::Generate => lsp_types::CodeActionKind::Empty, | |
| 1579 | AssistKind::QuickFix => lsp_types::CodeActionKind::QuickFix, | |
| 1580 | AssistKind::Refactor => lsp_types::CodeActionKind::Refactor, | |
| 1581 | AssistKind::RefactorExtract => lsp_types::CodeActionKind::RefactorExtract, | |
| 1582 | AssistKind::RefactorInline => lsp_types::CodeActionKind::RefactorInline, | |
| 1583 | AssistKind::RefactorRewrite => lsp_types::CodeActionKind::RefactorRewrite, | |
| 1520 | 1584 | } |
| 1521 | 1585 | } |
| 1522 | 1586 | |
| ... | ... | @@ -1761,7 +1825,7 @@ pub(crate) fn code_lens( |
| 1761 | 1825 | |
| 1762 | 1826 | let doc_pos = lsp_types::TextDocumentPositionParams::new(id, pos); |
| 1763 | 1827 | |
| 1764 | let goto_params = lsp_types::request::GotoImplementationParams { | |
| 1828 | let goto_params = lsp_types::ImplementationParams { | |
| 1765 | 1829 | text_document_position_params: doc_pos, |
| 1766 | 1830 | work_done_progress_params: Default::default(), |
| 1767 | 1831 | partial_result_params: Default::default(), |
| ... | ... | @@ -1891,7 +1955,7 @@ pub(crate) mod command { |
| 1891 | 1955 | |
| 1892 | 1956 | pub(crate) fn show_references( |
| 1893 | 1957 | title: String, |
| 1894 | uri: &lsp_types::Url, | |
| 1958 | uri: &lsp_types::Uri, | |
| 1895 | 1959 | position: lsp_types::Position, |
| 1896 | 1960 | locations: Vec<lsp_types::Location>, |
| 1897 | 1961 | ) -> lsp_types::Command { |
| ... | ... | @@ -1907,6 +1971,7 @@ pub(crate) mod command { |
| 1907 | 1971 | to_value(position).unwrap(), |
| 1908 | 1972 | to_value(locations).unwrap(), |
| 1909 | 1973 | ]), |
| 1974 | tooltip: None, | |
| 1910 | 1975 | } |
| 1911 | 1976 | } |
| 1912 | 1977 | |
| ... | ... | @@ -1915,6 +1980,7 @@ pub(crate) mod command { |
| 1915 | 1980 | title: title.to_owned(), |
| 1916 | 1981 | command: "rust-analyzer.runSingle".into(), |
| 1917 | 1982 | arguments: Some(vec![to_value(runnable).unwrap()]), |
| 1983 | tooltip: None, | |
| 1918 | 1984 | } |
| 1919 | 1985 | } |
| 1920 | 1986 | |
| ... | ... | @@ -1923,6 +1989,7 @@ pub(crate) mod command { |
| 1923 | 1989 | title: "âš™\u{fe0e} Debug".into(), |
| 1924 | 1990 | command: "rust-analyzer.debugSingle".into(), |
| 1925 | 1991 | arguments: Some(vec![to_value(runnable).unwrap()]), |
| 1992 | tooltip: None, | |
| 1926 | 1993 | } |
| 1927 | 1994 | } |
| 1928 | 1995 | |
| ... | ... | @@ -1932,6 +1999,7 @@ pub(crate) mod command { |
| 1932 | 1999 | command: "rust-analyzer.interpretFunction".into(), |
| 1933 | 2000 | // FIXME: use the `_runnable` here. |
| 1934 | 2001 | arguments: Some(vec![]), |
| 2002 | tooltip: None, | |
| 1935 | 2003 | } |
| 1936 | 2004 | } |
| 1937 | 2005 | |
| ... | ... | @@ -1952,6 +2020,7 @@ pub(crate) mod command { |
| 1952 | 2020 | title: nav.name.to_string(), |
| 1953 | 2021 | command: "rust-analyzer.gotoLocation".into(), |
| 1954 | 2022 | arguments: Some(vec![value]), |
| 2023 | tooltip: None, | |
| 1955 | 2024 | }) |
| 1956 | 2025 | } |
| 1957 | 2026 | |
| ... | ... | @@ -1960,6 +2029,7 @@ pub(crate) mod command { |
| 1960 | 2029 | title: "triggerParameterHints".into(), |
| 1961 | 2030 | command: "rust-analyzer.triggerParameterHints".into(), |
| 1962 | 2031 | arguments: None, |
| 2032 | tooltip: None, | |
| 1963 | 2033 | } |
| 1964 | 2034 | } |
| 1965 | 2035 | |
| ... | ... | @@ -1968,6 +2038,7 @@ pub(crate) mod command { |
| 1968 | 2038 | title: "rename".into(), |
| 1969 | 2039 | command: "rust-analyzer.rename".into(), |
| 1970 | 2040 | arguments: None, |
| 2041 | tooltip: None, | |
| 1971 | 2042 | } |
| 1972 | 2043 | } |
| 1973 | 2044 | } |
| ... | ... | @@ -3081,7 +3152,7 @@ struct ProcMacro { |
| 3081 | 3152 | ) |
| 3082 | 3153 | } |
| 3083 | 3154 | |
| 3084 | // `Url` is not able to parse windows paths on unix machines. | |
| 3155 | // `Uri` is not able to parse windows paths on unix machines. | |
| 3085 | 3156 | #[test] |
| 3086 | 3157 | #[cfg(target_os = "windows")] |
| 3087 | 3158 | fn test_lowercase_drive_letter() { |
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs+112-90| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | //! Utilities for LSP-related boilerplate code. |
| 2 | use std::{mem, ops::Range}; | |
| 2 | use std::{mem, ops::Range, vec}; | |
| 3 | 3 | |
| 4 | 4 | use lsp_server::Notification; |
| 5 | use lsp_types::request::Request; | |
| 5 | use lsp_types::{MessageActionItem, Request}; | |
| 6 | 6 | use triomphe::Arc; |
| 7 | 7 | |
| 8 | 8 | use crate::{ |
| ... | ... | @@ -16,10 +16,8 @@ pub(crate) fn invalid_params_error(message: String) -> LspError { |
| 16 | 16 | LspError { code: lsp_server::ErrorCode::InvalidParams as i32, message } |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | pub(crate) fn notification_is<N: lsp_types::notification::Notification>( | |
| 20 | notification: &Notification, | |
| 21 | ) -> bool { | |
| 22 | notification.method == N::METHOD | |
| 19 | pub(crate) fn notification_is<N: lsp_types::Notification>(notification: &Notification) -> bool { | |
| 20 | notification.method.as_str() == N::METHOD.as_str() | |
| 23 | 21 | } |
| 24 | 22 | |
| 25 | 23 | #[derive(Debug, Eq, PartialEq)] |
| ... | ... | @@ -39,37 +37,34 @@ impl Progress { |
| 39 | 37 | impl GlobalState { |
| 40 | 38 | pub(crate) fn show_message( |
| 41 | 39 | &mut self, |
| 42 | typ: lsp_types::MessageType, | |
| 40 | kind: lsp_types::MessageType, | |
| 43 | 41 | message: String, |
| 44 | 42 | show_open_log_button: bool, |
| 45 | 43 | ) { |
| 46 | match self.config.open_server_logs() && show_open_log_button { | |
| 47 | true => self.send_request::<lsp_types::request::ShowMessageRequest>( | |
| 44 | match self.config.open_server_logs() && show_open_log_button { | |
| 45 | true => self.send_request::<lsp_types::ShowMessageRequest>( | |
| 48 | 46 | lsp_types::ShowMessageRequestParams { |
| 49 | typ, | |
| 47 | kind, | |
| 50 | 48 | message, |
| 51 | 49 | actions: Some(vec![lsp_types::MessageActionItem { |
| 52 | 50 | title: "Open server logs".to_owned(), |
| 53 | properties: Default::default(), | |
| 54 | 51 | }]), |
| 55 | 52 | }, |
| 56 | 53 | |this, resp| { |
| 57 | 54 | let lsp_server::Response { error: None, result: Some(result), .. } = resp |
| 58 | else { return }; | |
| 59 | if let Ok(Some(_item)) = crate::from_json::< | |
| 60 | <lsp_types::request::ShowMessageRequest as lsp_types::request::Request>::Result, | |
| 61 | >( | |
| 62 | lsp_types::request::ShowMessageRequest::METHOD, &result | |
| 55 | else { | |
| 56 | return; | |
| 57 | }; | |
| 58 | if let Ok(Some(_item)) = crate::from_json::<Option<MessageActionItem>>( | |
| 59 | lsp_types::ShowMessageRequest::METHOD.as_str(), | |
| 60 | &result, | |
| 63 | 61 | ) { |
| 64 | this.send_notification::<lsp_ext::OpenServerLogs>(()); | |
| 62 | this.send_notification::<lsp_ext::OpenServerLogsNotification>(()); | |
| 65 | 63 | } |
| 66 | 64 | }, |
| 67 | 65 | ), |
| 68 | false => self.send_notification::<lsp_types::notification::ShowMessage>( | |
| 69 | lsp_types::ShowMessageParams { | |
| 70 | typ, | |
| 71 | message, | |
| 72 | }, | |
| 66 | false => self.send_notification::<lsp_types::ShowMessageNotification>( | |
| 67 | lsp_types::ShowMessageParams { kind, message }, | |
| 73 | 68 | ), |
| 74 | 69 | } |
| 75 | 70 | } |
| ... | ... | @@ -81,15 +76,15 @@ impl GlobalState { |
| 81 | 76 | Some(additional_info) => { |
| 82 | 77 | tracing::error!("{message}:\n{additional_info}"); |
| 83 | 78 | self.show_message( |
| 84 | lsp_types::MessageType::ERROR, | |
| 79 | lsp_types::MessageType::Error, | |
| 85 | 80 | message, |
| 86 | 81 | tracing::enabled!(tracing::Level::ERROR), |
| 87 | 82 | ); |
| 88 | 83 | } |
| 89 | 84 | None => { |
| 90 | 85 | tracing::error!("{message}"); |
| 91 | self.send_notification::<lsp_types::notification::ShowMessage>( | |
| 92 | lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message }, | |
| 86 | self.send_notification::<lsp_types::ShowMessageNotification>( | |
| 87 | lsp_types::ShowMessageParams { kind: lsp_types::MessageType::Error, message }, | |
| 93 | 88 | ); |
| 94 | 89 | } |
| 95 | 90 | } |
| ... | ... | @@ -133,35 +128,49 @@ impl GlobalState { |
| 133 | 128 | cancel_token.unwrap_or_else(|| format!("rustAnalyzer/{title}")), |
| 134 | 129 | ); |
| 135 | 130 | tracing::debug!(?token, ?state, "report_progress {message:?}"); |
| 136 | let work_done_progress = match state { | |
| 131 | match state { | |
| 137 | 132 | Progress::Begin => { |
| 138 | self.send_request::<lsp_types::request::WorkDoneProgressCreate>( | |
| 133 | self.send_request::<lsp_types::WorkDoneProgressCreateRequest>( | |
| 139 | 134 | lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, |
| 140 | 135 | |_, _| (), |
| 141 | 136 | ); |
| 142 | 137 | |
| 143 | lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin { | |
| 144 | title: title.into(), | |
| 145 | cancellable, | |
| 146 | message, | |
| 147 | percentage, | |
| 148 | }) | |
| 138 | self.send_notification::<lsp_types::ProgressNotification>( | |
| 139 | lsp_types::ProgressParams { | |
| 140 | token, | |
| 141 | value: serde_json::to_value(lsp_types::WorkDoneProgressBegin { | |
| 142 | title: title.into(), | |
| 143 | cancellable, | |
| 144 | message, | |
| 145 | percentage, | |
| 146 | }) | |
| 147 | .unwrap(), | |
| 148 | }, | |
| 149 | ); | |
| 149 | 150 | } |
| 150 | 151 | Progress::Report => { |
| 151 | lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport { | |
| 152 | cancellable, | |
| 153 | message, | |
| 154 | percentage, | |
| 155 | }) | |
| 152 | self.send_notification::<lsp_types::ProgressNotification>( | |
| 153 | lsp_types::ProgressParams { | |
| 154 | token, | |
| 155 | value: serde_json::to_value(lsp_types::WorkDoneProgressReport { | |
| 156 | cancellable, | |
| 157 | message, | |
| 158 | percentage, | |
| 159 | }) | |
| 160 | .unwrap(), | |
| 161 | }, | |
| 162 | ); | |
| 156 | 163 | } |
| 157 | 164 | Progress::End => { |
| 158 | lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message }) | |
| 165 | self.send_notification::<lsp_types::ProgressNotification>( | |
| 166 | lsp_types::ProgressParams { | |
| 167 | token, | |
| 168 | value: serde_json::to_value(lsp_types::WorkDoneProgressEnd { message }) | |
| 169 | .unwrap(), | |
| 170 | }, | |
| 171 | ); | |
| 159 | 172 | } |
| 160 | }; | |
| 161 | self.send_notification::<lsp_types::notification::Progress>(lsp_types::ProgressParams { | |
| 162 | token, | |
| 163 | value: lsp_types::ProgressParamsValue::WorkDone(work_done_progress), | |
| 164 | }); | |
| 173 | } | |
| 165 | 174 | } |
| 166 | 175 | } |
| 167 | 176 | |
| ... | ... | @@ -172,15 +181,26 @@ pub(crate) fn apply_document_changes( |
| 172 | 181 | ) -> String { |
| 173 | 182 | // If at least one of the changes is a full document change, use the last |
| 174 | 183 | // of them as the starting point and ignore all previous changes. |
| 175 | let (mut text, content_changes) = | |
| 176 | match content_changes.iter().rposition(|change| change.range.is_none()) { | |
| 177 | Some(idx) => { | |
| 178 | let text = mem::take(&mut content_changes[idx].text); | |
| 179 | (text, &content_changes[idx + 1..]) | |
| 180 | } | |
| 181 | None => (file_contents.to_owned(), &content_changes[..]), | |
| 182 | }; | |
| 183 | if content_changes.is_empty() { | |
| 184 | let (mut text, r_partial_changes); | |
| 185 | match content_changes.iter_mut().rev().try_fold(Vec::new(), |mut acc, change| match change { | |
| 186 | lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangePartial(partial) => { | |
| 187 | acc.push(partial); | |
| 188 | Ok(acc) | |
| 189 | } | |
| 190 | lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( | |
| 191 | whole, | |
| 192 | ) => Err((whole, acc)), | |
| 193 | }) { | |
| 194 | Err((whole_document, reversed_partial_changes)) => { | |
| 195 | text = mem::take(&mut whole_document.text); | |
| 196 | r_partial_changes = reversed_partial_changes; | |
| 197 | } | |
| 198 | Ok(partials) => { | |
| 199 | text = file_contents.to_owned(); | |
| 200 | r_partial_changes = partials; | |
| 201 | } | |
| 202 | } | |
| 203 | if r_partial_changes.is_empty() { | |
| 184 | 204 | return text; |
| 185 | 205 | } |
| 186 | 206 | |
| ... | ... | @@ -198,16 +218,13 @@ pub(crate) fn apply_document_changes( |
| 198 | 218 | // remember the last valid line in the index and only rebuild it if needed. |
| 199 | 219 | // The VFS will normalize the end of lines to `\n`. |
| 200 | 220 | let mut index_valid = !0u32; |
| 201 | for change in content_changes { | |
| 202 | // The None case can't happen as we have handled it above already | |
| 203 | if let Some(range) = change.range { | |
| 204 | if index_valid <= range.end.line { | |
| 205 | *Arc::make_mut(&mut line_index.index) = ide::LineIndex::new(&text); | |
| 206 | } | |
| 207 | index_valid = range.start.line; | |
| 208 | if let Ok(range) = from_proto::text_range(&line_index, range) { | |
| 209 | text.replace_range(Range::<usize>::from(range), &change.text); | |
| 210 | } | |
| 221 | for change in r_partial_changes.iter().rev() { | |
| 222 | if index_valid <= change.range.end.line { | |
| 223 | *Arc::make_mut(&mut line_index.index) = ide::LineIndex::new(&text); | |
| 224 | } | |
| 225 | index_valid = change.range.start.line; | |
| 226 | if let Ok(range) = from_proto::text_range(&line_index, change.range) { | |
| 227 | text.replace_range(Range::<usize>::from(range), &change.text); | |
| 211 | 228 | } |
| 212 | 229 | } |
| 213 | 230 | text |
| ... | ... | @@ -221,10 +238,10 @@ pub(crate) fn all_edits_are_disjoint( |
| 221 | 238 | ) -> bool { |
| 222 | 239 | let mut edit_ranges = Vec::new(); |
| 223 | 240 | match completion.text_edit.as_ref() { |
| 224 | Some(lsp_types::CompletionTextEdit::Edit(edit)) => { | |
| 241 | Some(lsp_types::CompletionItemTextEdit::TextEdit(edit)) => { | |
| 225 | 242 | edit_ranges.push(edit.range); |
| 226 | 243 | } |
| 227 | Some(lsp_types::CompletionTextEdit::InsertAndReplace(edit)) => { | |
| 244 | Some(lsp_types::CompletionItemTextEdit::InsertReplaceEdit(edit)) => { | |
| 228 | 245 | let replace = edit.replace; |
| 229 | 246 | let insert = edit.insert; |
| 230 | 247 | if replace.start != insert.start |
| ... | ... | @@ -252,10 +269,7 @@ pub(crate) fn all_edits_are_disjoint( |
| 252 | 269 | #[cfg(test)] |
| 253 | 270 | mod tests { |
| 254 | 271 | use ide_db::line_index::WideEncoding; |
| 255 | use lsp_types::{ | |
| 256 | CompletionItem, CompletionTextEdit, InsertReplaceEdit, Position, Range, | |
| 257 | TextDocumentContentChangeEvent, | |
| 258 | }; | |
| 272 | use lsp_types::{CompletionItem, InsertReplaceEdit, Position, Range}; | |
| 259 | 273 | |
| 260 | 274 | use super::*; |
| 261 | 275 | |
| ... | ... | @@ -263,14 +277,14 @@ mod tests { |
| 263 | 277 | fn test_apply_document_changes() { |
| 264 | 278 | macro_rules! c { |
| 265 | 279 | [$($sl:expr, $sc:expr; $el:expr, $ec:expr => $text:expr),+] => { |
| 266 | vec![$(TextDocumentContentChangeEvent { | |
| 267 | range: Some(Range { | |
| 280 | vec![$(::lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangePartial(lsp_types::TextDocumentContentChangePartial { | |
| 281 | range: Range { | |
| 268 | 282 | start: Position { line: $sl, character: $sc }, |
| 269 | 283 | end: Position { line: $el, character: $ec }, |
| 270 | }), | |
| 271 | range_length: None, | |
| 284 | }, | |
| 272 | 285 | text: String::from($text), |
| 273 | }),+] | |
| 286 | ..Default::default() | |
| 287 | })),+] | |
| 274 | 288 | }; |
| 275 | 289 | } |
| 276 | 290 | |
| ... | ... | @@ -280,11 +294,11 @@ mod tests { |
| 280 | 294 | let text = apply_document_changes( |
| 281 | 295 | encoding, |
| 282 | 296 | &text, |
| 283 | vec![TextDocumentContentChangeEvent { | |
| 284 | range: None, | |
| 285 | range_length: None, | |
| 286 | text: String::from("the"), | |
| 287 | }], | |
| 297 | vec![ | |
| 298 | lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( | |
| 299 | lsp_types::TextDocumentContentChangeWholeDocument { text: String::from("the") }, | |
| 300 | ), | |
| 301 | ], | |
| 288 | 302 | ); |
| 289 | 303 | assert_eq!(text, "the"); |
| 290 | 304 | let text = apply_document_changes(encoding, &text, c![0, 3; 0, 3 => " quick"]); |
| ... | ... | @@ -332,7 +346,11 @@ mod tests { |
| 332 | 346 | |
| 333 | 347 | #[test] |
| 334 | 348 | fn empty_completion_disjoint_tests() { |
| 335 | let empty_completion = CompletionItem::new_simple("label".to_owned(), "detail".to_owned()); | |
| 349 | let empty_completion = CompletionItem { | |
| 350 | label: "label".to_owned(), | |
| 351 | detail: Some("detail".to_owned()), | |
| 352 | ..Default::default() | |
| 353 | }; | |
| 336 | 354 | |
| 337 | 355 | let disjoint_edit_1 = lsp_types::TextEdit::new( |
| 338 | 356 | Range::new(Position::new(2, 2), Position::new(3, 3)), |
| ... | ... | @@ -384,17 +402,19 @@ mod tests { |
| 384 | 402 | "new_text".to_owned(), |
| 385 | 403 | ); |
| 386 | 404 | |
| 387 | let mut completion_with_joint_edits = | |
| 388 | CompletionItem::new_simple("label".to_owned(), "detail".to_owned()); | |
| 389 | completion_with_joint_edits.additional_text_edits = | |
| 390 | Some(vec![disjoint_edit.clone(), joint_edit.clone()]); | |
| 405 | let mut completion_with_joint_edits = CompletionItem { | |
| 406 | label: "label".to_owned(), | |
| 407 | detail: Some("detail".to_owned()), | |
| 408 | additional_text_edits: Some(vec![disjoint_edit.clone(), joint_edit.clone()]), | |
| 409 | ..Default::default() | |
| 410 | }; | |
| 391 | 411 | assert!( |
| 392 | 412 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), |
| 393 | 413 | "Completion with disjoint edits fails the validation even with empty extra edits" |
| 394 | 414 | ); |
| 395 | 415 | |
| 396 | 416 | completion_with_joint_edits.text_edit = |
| 397 | Some(CompletionTextEdit::Edit(disjoint_edit.clone())); | |
| 417 | Some(lsp_types::CompletionItemTextEdit::TextEdit(disjoint_edit.clone())); | |
| 398 | 418 | completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit.clone()]); |
| 399 | 419 | assert!( |
| 400 | 420 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), |
| ... | ... | @@ -402,7 +422,7 @@ mod tests { |
| 402 | 422 | ); |
| 403 | 423 | |
| 404 | 424 | completion_with_joint_edits.text_edit = |
| 405 | Some(CompletionTextEdit::InsertAndReplace(InsertReplaceEdit { | |
| 425 | Some(lsp_types::CompletionItemTextEdit::InsertReplaceEdit(InsertReplaceEdit { | |
| 406 | 426 | new_text: "new_text".to_owned(), |
| 407 | 427 | insert: disjoint_edit.range, |
| 408 | 428 | replace: disjoint_edit_2.range, |
| ... | ... | @@ -429,10 +449,12 @@ mod tests { |
| 429 | 449 | "new_text".to_owned(), |
| 430 | 450 | ); |
| 431 | 451 | |
| 432 | let mut completion_with_disjoint_edits = | |
| 433 | CompletionItem::new_simple("label".to_owned(), "detail".to_owned()); | |
| 434 | completion_with_disjoint_edits.text_edit = Some(CompletionTextEdit::Edit(disjoint_edit)); | |
| 435 | let completion_with_disjoint_edits = completion_with_disjoint_edits; | |
| 452 | let completion_with_disjoint_edits = CompletionItem { | |
| 453 | label: "label".to_owned(), | |
| 454 | detail: Some("detail".to_owned()), | |
| 455 | text_edit: Some(lsp_types::CompletionItemTextEdit::TextEdit(disjoint_edit)), | |
| 456 | ..Default::default() | |
| 457 | }; | |
| 436 | 458 | |
| 437 | 459 | assert!( |
| 438 | 460 | all_edits_are_disjoint(&completion_with_disjoint_edits, &[]), |
src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs+133-121| ... | ... | @@ -11,7 +11,7 @@ use std::{ |
| 11 | 11 | use crossbeam_channel::{Receiver, never, select}; |
| 12 | 12 | use ide_db::base_db::{SourceDatabase, VfsPath}; |
| 13 | 13 | use lsp_server::{Connection, Notification, Request}; |
| 14 | use lsp_types::{TextDocumentIdentifier, notification::Notification as _}; | |
| 14 | use lsp_types::{Notification as _, TextDocumentIdentifier}; | |
| 15 | 15 | use stdx::thread::ThreadIntent; |
| 16 | 16 | use tracing::{Level, error, span}; |
| 17 | 17 | use vfs::{AbsPathBuf, FileId, loader::LoadingProgress}; |
| ... | ... | @@ -99,7 +99,7 @@ impl fmt::Display for Event { |
| 99 | 99 | |
| 100 | 100 | #[derive(Debug)] |
| 101 | 101 | pub(crate) enum DeferredTask { |
| 102 | CheckIfIndexed(lsp_types::Url), | |
| 102 | CheckIfIndexed(lsp_types::Uri), | |
| 103 | 103 | CheckProcMacroSources(Vec<FileId>), |
| 104 | 104 | } |
| 105 | 105 | |
| ... | ... | @@ -145,8 +145,8 @@ impl fmt::Debug for Event { |
| 145 | 145 | |
| 146 | 146 | match self { |
| 147 | 147 | Event::Lsp(lsp_server::Message::Notification(not)) |
| 148 | if (notification_is::<lsp_types::notification::DidOpenTextDocument>(not) | |
| 149 | || notification_is::<lsp_types::notification::DidChangeTextDocument>(not)) => | |
| 148 | if (notification_is::<lsp_types::DidOpenTextDocumentNotification>(not) | |
| 149 | || notification_is::<lsp_types::DidChangeTextDocumentNotification>(not)) => | |
| 150 | 150 | { |
| 151 | 151 | return debug_non_verbose(not, f); |
| 152 | 152 | } |
| ... | ... | @@ -207,7 +207,7 @@ impl GlobalState { |
| 207 | 207 | if matches!( |
| 208 | 208 | &event, |
| 209 | 209 | Event::Lsp(lsp_server::Message::Notification(Notification { method, .. })) |
| 210 | if method == lsp_types::notification::Exit::METHOD | |
| 210 | if method == lsp_types::ExitNotification::METHOD.as_str() | |
| 211 | 211 | ) { |
| 212 | 212 | return Ok(()); |
| 213 | 213 | } |
| ... | ... | @@ -218,33 +218,43 @@ impl GlobalState { |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | 220 | fn register_did_save_capability(&mut self, additional_patterns: impl Iterator<Item = String>) { |
| 221 | let additional_filters = additional_patterns.map(|pattern| lsp_types::DocumentFilter { | |
| 222 | language: None, | |
| 223 | scheme: None, | |
| 224 | pattern: (Some(pattern)), | |
| 221 | let additional_filters = additional_patterns.map(|pattern| { | |
| 222 | lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( | |
| 223 | lsp_types::TextDocumentFilterPattern { | |
| 224 | language: None, | |
| 225 | scheme: None, | |
| 226 | pattern: pattern.into(), | |
| 227 | }, | |
| 228 | )) | |
| 225 | 229 | }); |
| 226 | 230 | |
| 227 | 231 | let mut selectors = vec![ |
| 228 | lsp_types::DocumentFilter { | |
| 229 | language: None, | |
| 230 | scheme: None, | |
| 231 | pattern: Some("**/*.rs".into()), | |
| 232 | }, | |
| 233 | lsp_types::DocumentFilter { | |
| 234 | language: None, | |
| 235 | scheme: None, | |
| 236 | pattern: Some("**/Cargo.toml".into()), | |
| 237 | }, | |
| 238 | lsp_types::DocumentFilter { | |
| 239 | language: None, | |
| 240 | scheme: None, | |
| 241 | pattern: Some("**/Cargo.lock".into()), | |
| 242 | }, | |
| 232 | lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( | |
| 233 | lsp_types::TextDocumentFilterPattern { | |
| 234 | language: None, | |
| 235 | scheme: None, | |
| 236 | pattern: "**/*.rs".to_owned().into(), | |
| 237 | }, | |
| 238 | )), | |
| 239 | lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( | |
| 240 | lsp_types::TextDocumentFilterPattern { | |
| 241 | language: None, | |
| 242 | scheme: None, | |
| 243 | pattern: "**/Cargo.toml".to_owned().into(), | |
| 244 | }, | |
| 245 | )), | |
| 246 | lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( | |
| 247 | lsp_types::TextDocumentFilterPattern { | |
| 248 | language: None, | |
| 249 | scheme: None, | |
| 250 | pattern: "**/Cargo.lock".to_owned().into(), | |
| 251 | }, | |
| 252 | )), | |
| 243 | 253 | ]; |
| 244 | 254 | selectors.extend(additional_filters); |
| 245 | 255 | |
| 246 | 256 | let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions { |
| 247 | include_text: Some(false), | |
| 257 | save_options: lsp_types::SaveOptions { include_text: Some(false) }, | |
| 248 | 258 | text_document_registration_options: lsp_types::TextDocumentRegistrationOptions { |
| 249 | 259 | document_selector: Some(selectors), |
| 250 | 260 | }, |
| ... | ... | @@ -255,7 +265,7 @@ impl GlobalState { |
| 255 | 265 | method: "textDocument/didSave".to_owned(), |
| 256 | 266 | register_options: Some(serde_json::to_value(save_registration_options).unwrap()), |
| 257 | 267 | }; |
| 258 | self.send_request::<lsp_types::request::RegisterCapability>( | |
| 268 | self.send_request::<lsp_types::RegistrationRequest>( | |
| 259 | 269 | lsp_types::RegistrationParams { registrations: vec![registration] }, |
| 260 | 270 | |_, _| (), |
| 261 | 271 | ); |
| ... | ... | @@ -457,10 +467,7 @@ impl GlobalState { |
| 457 | 467 | self.handle_flycheck_msg(message, &mut cargo_finished); |
| 458 | 468 | } |
| 459 | 469 | if cargo_finished { |
| 460 | self.send_request::<lsp_types::request::WorkspaceDiagnosticRefresh>( | |
| 461 | (), | |
| 462 | |_, _| (), | |
| 463 | ); | |
| 470 | self.send_request::<lsp_types::DiagnosticRefreshRequest>((), |_, _| ()); | |
| 464 | 471 | } |
| 465 | 472 | } |
| 466 | 473 | Event::TestResult(message) => { |
| ... | ... | @@ -537,24 +544,21 @@ impl GlobalState { |
| 537 | 544 | // Refresh semantic tokens if the client supports it. |
| 538 | 545 | if self.config.semantic_tokens_refresh() { |
| 539 | 546 | self.semantic_tokens_cache.lock().clear(); |
| 540 | self.send_request::<lsp_types::request::SemanticTokensRefresh>((), |_, _| ()); | |
| 547 | self.send_request::<lsp_types::SemanticTokensRefreshRequest>((), |_, _| ()); | |
| 541 | 548 | } |
| 542 | 549 | |
| 543 | 550 | // Refresh code lens if the client supports it. |
| 544 | 551 | if self.config.code_lens_refresh() { |
| 545 | self.send_request::<lsp_types::request::CodeLensRefresh>((), |_, _| ()); | |
| 552 | self.send_request::<lsp_types::CodeLensRefreshRequest>((), |_, _| ()); | |
| 546 | 553 | } |
| 547 | 554 | |
| 548 | 555 | // Refresh inlay hints if the client supports it. |
| 549 | 556 | if self.config.inlay_hints_refresh() { |
| 550 | self.send_request::<lsp_types::request::InlayHintRefreshRequest>((), |_, _| ()); | |
| 557 | self.send_request::<lsp_types::InlayHintRefreshRequest>((), |_, _| ()); | |
| 551 | 558 | } |
| 552 | 559 | |
| 553 | 560 | if self.config.diagnostics_refresh() { |
| 554 | self.send_request::<lsp_types::request::WorkspaceDiagnosticRefresh>( | |
| 555 | (), | |
| 556 | |_, _| (), | |
| 557 | ); | |
| 561 | self.send_request::<lsp_types::DiagnosticRefreshRequest>((), |_, _| ()); | |
| 558 | 562 | } |
| 559 | 563 | } |
| 560 | 564 | |
| ... | ... | @@ -828,9 +832,9 @@ impl GlobalState { |
| 828 | 832 | || self.fetch_workspace_error().is_err()); |
| 829 | 833 | self.show_message( |
| 830 | 834 | match health { |
| 831 | lsp_ext::Health::Ok => lsp_types::MessageType::INFO, | |
| 832 | lsp_ext::Health::Warning => lsp_types::MessageType::WARNING, | |
| 833 | lsp_ext::Health::Error => lsp_types::MessageType::ERROR, | |
| 835 | lsp_ext::Health::Ok => lsp_types::MessageType::Info, | |
| 836 | lsp_ext::Health::Warning => lsp_types::MessageType::Warning, | |
| 837 | lsp_ext::Health::Error => lsp_types::MessageType::Error, | |
| 834 | 838 | }, |
| 835 | 839 | message.clone(), |
| 836 | 840 | open_log_button, |
| ... | ... | @@ -911,7 +915,7 @@ impl GlobalState { |
| 911 | 915 | self.discover_handles.push(handle) |
| 912 | 916 | } |
| 913 | 917 | Err(e) => self.show_message( |
| 914 | lsp_types::MessageType::ERROR, | |
| 918 | lsp_types::MessageType::Error, | |
| 915 | 919 | format!("Failed to spawn project discovery command: {e:#}"), |
| 916 | 920 | false, |
| 917 | 921 | ), |
| ... | ... | @@ -960,7 +964,7 @@ impl GlobalState { |
| 960 | 964 | } |
| 961 | 965 | Task::BuildDepsHaveChanged => self.build_deps_changed = true, |
| 962 | 966 | Task::DiscoverTest(tests) => { |
| 963 | self.send_notification::<lsp_ext::DiscoveredTests>(tests); | |
| 967 | self.send_notification::<lsp_ext::DiscoveredTestsNotification>(tests); | |
| 964 | 968 | } |
| 965 | 969 | } |
| 966 | 970 | cancellation_time |
| ... | ... | @@ -1174,7 +1178,7 @@ impl GlobalState { |
| 1174 | 1178 | // The notification requires the namespace form (with underscores) of the target |
| 1175 | 1179 | let test_id = format!("{}::{name}", message.target.target.replace('-', "_")); |
| 1176 | 1180 | |
| 1177 | self.send_notification::<lsp_ext::ChangeTestState>( | |
| 1181 | self.send_notification::<lsp_ext::ChangeTestStateNotification>( | |
| 1178 | 1182 | lsp_ext::ChangeTestStateParams { test_id, state }, |
| 1179 | 1183 | ); |
| 1180 | 1184 | } |
| ... | ... | @@ -1182,12 +1186,12 @@ impl GlobalState { |
| 1182 | 1186 | CargoTestOutput::Finished => { |
| 1183 | 1187 | self.test_run_remaining_jobs = self.test_run_remaining_jobs.saturating_sub(1); |
| 1184 | 1188 | if self.test_run_remaining_jobs == 0 { |
| 1185 | self.send_notification::<lsp_ext::EndRunTest>(()); | |
| 1189 | self.send_notification::<lsp_ext::EndRunTestNotification>(()); | |
| 1186 | 1190 | self.test_run_session = None; |
| 1187 | 1191 | } |
| 1188 | 1192 | } |
| 1189 | 1193 | CargoTestOutput::Custom { text } => { |
| 1190 | self.send_notification::<lsp_ext::AppendOutputToRunTest>(text); | |
| 1194 | self.send_notification::<lsp_ext::AppendOutputToRunTestNotification>(text); | |
| 1191 | 1195 | } |
| 1192 | 1196 | } |
| 1193 | 1197 | } |
| ... | ... | @@ -1308,7 +1312,7 @@ impl GlobalState { |
| 1308 | 1312 | /// Handles a request. |
| 1309 | 1313 | fn on_request(&mut self, req: Request) { |
| 1310 | 1314 | let mut dispatcher = RequestDispatcher { req: Some(req), global_state: self }; |
| 1311 | dispatcher.on_sync_mut::<lsp_types::request::Shutdown>(|s, ()| { | |
| 1315 | dispatcher.on_sync_mut::<lsp_types::ShutdownRequest>(|s, ()| { | |
| 1312 | 1316 | s.shutdown_requested = true; |
| 1313 | 1317 | s.proc_macro_clients = |
| 1314 | 1318 | std::iter::repeat_with(|| None).take(s.proc_macro_clients.len()).collect(); |
| ... | ... | @@ -1330,7 +1334,6 @@ impl GlobalState { |
| 1330 | 1334 | } |
| 1331 | 1335 | |
| 1332 | 1336 | use crate::handlers::request as handlers; |
| 1333 | use lsp_types::request as lsp_request; | |
| 1334 | 1337 | |
| 1335 | 1338 | const RETRY: bool = true; |
| 1336 | 1339 | const NO_RETRY: bool = false; |
| ... | ... | @@ -1339,91 +1342,91 @@ impl GlobalState { |
| 1339 | 1342 | dispatcher |
| 1340 | 1343 | // Request handlers that must run on the main thread |
| 1341 | 1344 | // because they mutate GlobalState: |
| 1342 | .on_sync_mut::<lsp_ext::ReloadWorkspace>(handlers::handle_workspace_reload) | |
| 1343 | .on_sync_mut::<lsp_ext::RebuildProcMacros>(handlers::handle_proc_macros_rebuild) | |
| 1344 | .on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage) | |
| 1345 | .on_sync_mut::<lsp_ext::RunTest>(handlers::handle_run_test) | |
| 1345 | .on_sync_mut::<lsp_ext::ReloadWorkspaceRequest>(handlers::handle_workspace_reload) | |
| 1346 | .on_sync_mut::<lsp_ext::RebuildProcMacrosRequest>(handlers::handle_proc_macros_rebuild) | |
| 1347 | .on_sync_mut::<lsp_ext::MemoryUsageRequest>(handlers::handle_memory_usage) | |
| 1348 | .on_sync_mut::<lsp_ext::RunTestRequest>(handlers::handle_run_test) | |
| 1346 | 1349 | // Request handlers which are related to the user typing |
| 1347 | 1350 | // are run on the main thread to reduce latency: |
| 1348 | .on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines) | |
| 1349 | .on_sync::<lsp_ext::OnEnter>(handlers::handle_on_enter) | |
| 1350 | .on_sync::<lsp_request::SelectionRangeRequest>(handlers::handle_selection_range) | |
| 1351 | .on_sync::<lsp_ext::MatchingBrace>(handlers::handle_matching_brace) | |
| 1352 | .on_sync::<lsp_ext::OnTypeFormatting>(handlers::handle_on_type_formatting) | |
| 1351 | .on_sync::<lsp_ext::JoinLinesRequest>(handlers::handle_join_lines) | |
| 1352 | .on_sync::<lsp_ext::OnEnterRequest>(handlers::handle_on_enter) | |
| 1353 | .on_sync::<lsp_types::SelectionRangeRequest>(handlers::handle_selection_range) | |
| 1354 | .on_sync::<lsp_ext::MatchingBraceRequest>(handlers::handle_matching_brace) | |
| 1355 | .on_sync::<lsp_ext::DocumentOnTypeFormattingRequest>(handlers::handle_on_type_formatting) | |
| 1353 | 1356 | // Formatting should be done immediately as the editor might wait on it, but we can't |
| 1354 | 1357 | // put it on the main thread as we do not want the main thread to block on rustfmt. |
| 1355 | 1358 | // So we have an extra thread just for formatting requests to make sure it gets handled |
| 1356 | 1359 | // as fast as possible. |
| 1357 | .on_fmt_thread::<lsp_request::Formatting>(handlers::handle_formatting) | |
| 1358 | .on_fmt_thread::<lsp_request::RangeFormatting>(handlers::handle_range_formatting) | |
| 1360 | .on_fmt_thread::<lsp_types::DocumentFormattingRequest>(handlers::handle_formatting) | |
| 1361 | .on_fmt_thread::<lsp_types::DocumentRangeFormattingRequest>(handlers::handle_range_formatting) | |
| 1359 | 1362 | // We can’t run latency-sensitive request handlers which do semantic |
| 1360 | 1363 | // analysis on the main thread because that would block other |
| 1361 | 1364 | // requests. Instead, we run these request handlers on higher priority |
| 1362 | 1365 | // threads in the threadpool. |
| 1363 | 1366 | // FIXME: Retrying can make the result of this stale? |
| 1364 | .on_latency_sensitive::<RETRY, lsp_request::Completion>(handlers::handle_completion) | |
| 1367 | .on_latency_sensitive::<RETRY, lsp_types::CompletionRequest>(handlers::handle_completion) | |
| 1365 | 1368 | // FIXME: Retrying can make the result of this stale |
| 1366 | .on_latency_sensitive::<RETRY, lsp_request::ResolveCompletionItem>(handlers::handle_completion_resolve) | |
| 1367 | .on_latency_sensitive::<RETRY, lsp_request::SemanticTokensFullRequest>(handlers::handle_semantic_tokens_full) | |
| 1368 | .on_latency_sensitive::<RETRY, lsp_request::SemanticTokensFullDeltaRequest>(handlers::handle_semantic_tokens_full_delta) | |
| 1369 | .on_latency_sensitive::<NO_RETRY, lsp_request::SemanticTokensRangeRequest>(handlers::handle_semantic_tokens_range) | |
| 1369 | .on_latency_sensitive::<RETRY, lsp_types::CompletionResolveRequest>(handlers::handle_completion_resolve) | |
| 1370 | .on_latency_sensitive::<RETRY, lsp_types::SemanticTokensRequest>(handlers::handle_semantic_tokens_full) | |
| 1371 | .on_latency_sensitive::<RETRY, lsp_types::SemanticTokensDeltaRequest>(handlers::handle_semantic_tokens_full_delta) | |
| 1372 | .on_latency_sensitive::<NO_RETRY, lsp_types::SemanticTokensRangeRequest>(handlers::handle_semantic_tokens_range) | |
| 1370 | 1373 | // FIXME: Some of these NO_RETRY could be retries if the file they are interested didn't change. |
| 1371 | 1374 | // All other request handlers |
| 1372 | .on_with_vfs_default::<lsp_request::DocumentDiagnosticRequest>(handlers::handle_document_diagnostics, empty_diagnostic_report, || lsp_server::ResponseError { | |
| 1375 | .on_with_vfs_default::<lsp_types::DocumentDiagnosticRequest>(handlers::handle_document_diagnostics, empty_diagnostic_report, || lsp_server::ResponseError { | |
| 1373 | 1376 | code: lsp_server::ErrorCode::ServerCancelled as i32, |
| 1374 | 1377 | message: "server cancelled the request".to_owned(), |
| 1375 | 1378 | data: serde_json::to_value(lsp_types::DiagnosticServerCancellationData { |
| 1376 | 1379 | retrigger_request: true |
| 1377 | 1380 | }).ok(), |
| 1378 | 1381 | }) |
| 1379 | .on::<RETRY, lsp_request::DocumentSymbolRequest>(handlers::handle_document_symbol) | |
| 1380 | .on::<RETRY, lsp_request::FoldingRangeRequest>(handlers::handle_folding_range) | |
| 1381 | .on::<NO_RETRY, lsp_request::SignatureHelpRequest>(handlers::handle_signature_help) | |
| 1382 | .on::<RETRY, lsp_request::WillRenameFiles>(handlers::handle_will_rename_files) | |
| 1383 | .on::<NO_RETRY, lsp_request::GotoDefinition>(handlers::handle_goto_definition) | |
| 1384 | .on::<NO_RETRY, lsp_request::GotoDeclaration>(handlers::handle_goto_declaration) | |
| 1385 | .on::<NO_RETRY, lsp_request::GotoImplementation>(handlers::handle_goto_implementation) | |
| 1386 | .on::<NO_RETRY, lsp_request::GotoTypeDefinition>(handlers::handle_goto_type_definition) | |
| 1387 | .on::<NO_RETRY, lsp_request::InlayHintRequest>(handlers::handle_inlay_hints) | |
| 1388 | .on_identity::<NO_RETRY, lsp_request::InlayHintResolveRequest, _>(handlers::handle_inlay_hints_resolve) | |
| 1389 | .on::<NO_RETRY, lsp_request::CodeLensRequest>(handlers::handle_code_lens) | |
| 1390 | .on_identity::<NO_RETRY, lsp_request::CodeLensResolve, _>(handlers::handle_code_lens_resolve) | |
| 1391 | .on::<NO_RETRY, lsp_request::PrepareRenameRequest>(handlers::handle_prepare_rename) | |
| 1392 | .on::<NO_RETRY, lsp_request::Rename>(handlers::handle_rename) | |
| 1393 | .on::<NO_RETRY, lsp_request::References>(handlers::handle_references) | |
| 1394 | .on::<NO_RETRY, lsp_request::DocumentHighlightRequest>(handlers::handle_document_highlight) | |
| 1395 | .on::<NO_RETRY, lsp_request::CallHierarchyPrepare>(handlers::handle_call_hierarchy_prepare) | |
| 1396 | .on::<NO_RETRY, lsp_request::CallHierarchyIncomingCalls>(handlers::handle_call_hierarchy_incoming) | |
| 1397 | .on::<NO_RETRY, lsp_request::CallHierarchyOutgoingCalls>(handlers::handle_call_hierarchy_outgoing) | |
| 1382 | .on::<RETRY, lsp_types::DocumentSymbolRequest>(handlers::handle_document_symbol) | |
| 1383 | .on::<RETRY, lsp_types::FoldingRangeRequest>(handlers::handle_folding_range) | |
| 1384 | .on::<NO_RETRY, lsp_types::SignatureHelpRequest>(handlers::handle_signature_help) | |
| 1385 | .on::<RETRY, lsp_types::WillRenameFilesRequest>(handlers::handle_will_rename_files) | |
| 1386 | .on::<NO_RETRY, lsp_types::DefinitionRequest>(handlers::handle_goto_definition) | |
| 1387 | .on::<NO_RETRY, lsp_types::DeclarationRequest>(handlers::handle_goto_declaration) | |
| 1388 | .on::<NO_RETRY, lsp_types::ImplementationRequest>(handlers::handle_goto_implementation) | |
| 1389 | .on::<NO_RETRY, lsp_types::TypeDefinitionRequest>(handlers::handle_goto_type_definition) | |
| 1390 | .on::<NO_RETRY, lsp_types::InlayHintRequest>(handlers::handle_inlay_hints) | |
| 1391 | .on_identity::<NO_RETRY, lsp_types::InlayHintResolveRequest, _>(handlers::handle_inlay_hints_resolve) | |
| 1392 | .on::<NO_RETRY, lsp_types::CodeLensRequest>(handlers::handle_code_lens) | |
| 1393 | .on_identity::<NO_RETRY, lsp_types::CodeLensResolveRequest, _>(handlers::handle_code_lens_resolve) | |
| 1394 | .on::<NO_RETRY, lsp_types::PrepareRenameRequest>(handlers::handle_prepare_rename) | |
| 1395 | .on::<NO_RETRY, lsp_types::RenameRequest>(handlers::handle_rename) | |
| 1396 | .on::<NO_RETRY, lsp_types::ReferencesRequest>(handlers::handle_references) | |
| 1397 | .on::<NO_RETRY, lsp_types::DocumentHighlightRequest>(handlers::handle_document_highlight) | |
| 1398 | .on::<NO_RETRY, lsp_types::CallHierarchyPrepareRequest>(handlers::handle_call_hierarchy_prepare) | |
| 1399 | .on::<NO_RETRY, lsp_types::CallHierarchyIncomingCallsRequest>(handlers::handle_call_hierarchy_incoming) | |
| 1400 | .on::<NO_RETRY, lsp_types::CallHierarchyOutgoingCallsRequest>(handlers::handle_call_hierarchy_outgoing) | |
| 1398 | 1401 | // All other request handlers (lsp extension) |
| 1399 | .on::<RETRY, lsp_ext::FetchDependencyList>(handlers::fetch_dependency_list) | |
| 1400 | .on::<RETRY, lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status) | |
| 1401 | .on::<RETRY, lsp_ext::ViewFileText>(handlers::handle_view_file_text) | |
| 1402 | .on::<RETRY, lsp_ext::ViewCrateGraph>(handlers::handle_view_crate_graph) | |
| 1403 | .on::<RETRY, lsp_ext::ViewItemTree>(handlers::handle_view_item_tree) | |
| 1404 | .on::<RETRY, lsp_ext::DiscoverTest>(handlers::handle_discover_test) | |
| 1405 | .on::<RETRY, lsp_ext::WorkspaceSymbol>(handlers::handle_workspace_symbol) | |
| 1406 | .on::<NO_RETRY, lsp_ext::Ssr>(handlers::handle_ssr) | |
| 1407 | .on::<NO_RETRY, lsp_ext::ViewRecursiveMemoryLayout>(handlers::handle_view_recursive_memory_layout) | |
| 1408 | .on::<NO_RETRY, lsp_ext::ViewSyntaxTree>(handlers::handle_view_syntax_tree) | |
| 1409 | .on::<NO_RETRY, lsp_ext::ViewHir>(handlers::handle_view_hir) | |
| 1410 | .on::<NO_RETRY, lsp_ext::ViewMir>(handlers::handle_view_mir) | |
| 1411 | .on::<NO_RETRY, lsp_ext::InterpretFunction>(handlers::handle_interpret_function) | |
| 1412 | .on::<NO_RETRY, lsp_ext::ExpandMacro>(handlers::handle_expand_macro) | |
| 1413 | .on::<NO_RETRY, lsp_ext::ParentModule>(handlers::handle_parent_module) | |
| 1414 | .on::<NO_RETRY, lsp_ext::ChildModules>(handlers::handle_child_modules) | |
| 1415 | .on::<NO_RETRY, lsp_ext::Runnables>(handlers::handle_runnables) | |
| 1416 | .on::<NO_RETRY, lsp_ext::RelatedTests>(handlers::handle_related_tests) | |
| 1402 | .on::<RETRY, lsp_ext::FetchDependencyListRequest>(handlers::fetch_dependency_list) | |
| 1403 | .on::<RETRY, lsp_ext::AnalyzerStatusRequest>(handlers::handle_analyzer_status) | |
| 1404 | .on::<RETRY, lsp_ext::ViewFileTextRequest>(handlers::handle_view_file_text) | |
| 1405 | .on::<RETRY, lsp_ext::ViewCrateGraphRequest>(handlers::handle_view_crate_graph) | |
| 1406 | .on::<RETRY, lsp_ext::ViewItemTreeRequest>(handlers::handle_view_item_tree) | |
| 1407 | .on::<RETRY, lsp_ext::DiscoverTestRequest>(handlers::handle_discover_test) | |
| 1408 | .on::<RETRY, lsp_ext::WorkspaceSymbolRequest>(handlers::handle_workspace_symbol) | |
| 1409 | .on::<NO_RETRY, lsp_ext::SsrRequest>(handlers::handle_ssr) | |
| 1410 | .on::<NO_RETRY, lsp_ext::ViewRecursiveMemoryLayoutRequest>(handlers::handle_view_recursive_memory_layout) | |
| 1411 | .on::<NO_RETRY, lsp_ext::ViewSyntaxTreeRequest>(handlers::handle_view_syntax_tree) | |
| 1412 | .on::<NO_RETRY, lsp_ext::ViewHirRequest>(handlers::handle_view_hir) | |
| 1413 | .on::<NO_RETRY, lsp_ext::ViewMirRequest>(handlers::handle_view_mir) | |
| 1414 | .on::<NO_RETRY, lsp_ext::InterpretFunctionRequest>(handlers::handle_interpret_function) | |
| 1415 | .on::<NO_RETRY, lsp_ext::ExpandMacroRequest>(handlers::handle_expand_macro) | |
| 1416 | .on::<NO_RETRY, lsp_ext::ParentModuleRequest>(handlers::handle_parent_module) | |
| 1417 | .on::<NO_RETRY, lsp_ext::ChildModulesRequest>(handlers::handle_child_modules) | |
| 1418 | .on::<NO_RETRY, lsp_ext::RunnablesRequest>(handlers::handle_runnables) | |
| 1419 | .on::<NO_RETRY, lsp_ext::RelatedTestsRequest>(handlers::handle_related_tests) | |
| 1417 | 1420 | .on::<NO_RETRY, lsp_ext::CodeActionRequest>(handlers::handle_code_action) |
| 1418 | 1421 | .on_identity::<RETRY, lsp_ext::CodeActionResolveRequest, _>(handlers::handle_code_action_resolve) |
| 1419 | 1422 | .on::<NO_RETRY, lsp_ext::HoverRequest>(handlers::handle_hover) |
| 1420 | .on::<NO_RETRY, lsp_ext::ExternalDocs>(handlers::handle_open_docs) | |
| 1421 | .on::<NO_RETRY, lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml) | |
| 1422 | .on::<NO_RETRY, lsp_ext::MoveItem>(handlers::handle_move_item) | |
| 1423 | .on::<NO_RETRY, lsp_ext::ExternalDocsRequest>(handlers::handle_open_docs) | |
| 1424 | .on::<NO_RETRY, lsp_ext::OpenCargoTomlRequest>(handlers::handle_open_cargo_toml) | |
| 1425 | .on::<NO_RETRY, lsp_ext::MoveItemRequest>(handlers::handle_move_item) | |
| 1423 | 1426 | // |
| 1424 | .on::<NO_RETRY, lsp_ext::InternalTestingFetchConfig>(handlers::internal_testing_fetch_config) | |
| 1425 | .on::<RETRY, lsp_ext::EvaluatePredicate>(handlers::handle_evaluate_predicate) | |
| 1426 | .on::<RETRY, lsp_ext::GetFailedObligations>(handlers::get_failed_obligations) | |
| 1427 | .on::<NO_RETRY, lsp_ext::InternalTestingFetchConfigRequest>(handlers::internal_testing_fetch_config) | |
| 1428 | .on::<RETRY, lsp_ext::EvaluatePredicateRequest>(handlers::handle_evaluate_predicate) | |
| 1429 | .on::<RETRY, lsp_ext::GetFailedObligationsRequest>(handlers::get_failed_obligations) | |
| 1427 | 1430 | .finish(); |
| 1428 | 1431 | } |
| 1429 | 1432 | |
| ... | ... | @@ -1432,28 +1435,37 @@ impl GlobalState { |
| 1432 | 1435 | let _p = |
| 1433 | 1436 | span!(Level::INFO, "GlobalState::on_notification", not.method = ?not.method).entered(); |
| 1434 | 1437 | use crate::handlers::notification as handlers; |
| 1435 | use lsp_types::notification as notifs; | |
| 1436 | 1438 | |
| 1437 | 1439 | NotificationDispatcher { not: Some(not), global_state: self } |
| 1438 | .on_sync_mut::<notifs::Cancel>(handlers::handle_cancel) | |
| 1439 | .on_sync_mut::<notifs::WorkDoneProgressCancel>( | |
| 1440 | .on_sync_mut::<lsp_types::CancelNotification>(handlers::handle_cancel) | |
| 1441 | .on_sync_mut::<lsp_types::WorkDoneProgressCancelNotification>( | |
| 1440 | 1442 | handlers::handle_work_done_progress_cancel, |
| 1441 | 1443 | ) |
| 1442 | .on_sync_mut::<notifs::DidOpenTextDocument>(handlers::handle_did_open_text_document) | |
| 1443 | .on_sync_mut::<notifs::DidChangeTextDocument>(handlers::handle_did_change_text_document) | |
| 1444 | .on_sync_mut::<notifs::DidCloseTextDocument>(handlers::handle_did_close_text_document) | |
| 1445 | .on_sync_mut::<notifs::DidSaveTextDocument>(handlers::handle_did_save_text_document) | |
| 1446 | .on_sync_mut::<notifs::DidChangeConfiguration>( | |
| 1444 | .on_sync_mut::<lsp_types::DidOpenTextDocumentNotification>( | |
| 1445 | handlers::handle_did_open_text_document, | |
| 1446 | ) | |
| 1447 | .on_sync_mut::<lsp_types::DidChangeTextDocumentNotification>( | |
| 1448 | handlers::handle_did_change_text_document, | |
| 1449 | ) | |
| 1450 | .on_sync_mut::<lsp_types::DidCloseTextDocumentNotification>( | |
| 1451 | handlers::handle_did_close_text_document, | |
| 1452 | ) | |
| 1453 | .on_sync_mut::<lsp_types::DidSaveTextDocumentNotification>( | |
| 1454 | handlers::handle_did_save_text_document, | |
| 1455 | ) | |
| 1456 | .on_sync_mut::<lsp_types::DidChangeConfigurationNotification>( | |
| 1447 | 1457 | handlers::handle_did_change_configuration, |
| 1448 | 1458 | ) |
| 1449 | .on_sync_mut::<notifs::DidChangeWorkspaceFolders>( | |
| 1459 | .on_sync_mut::<lsp_types::DidChangeWorkspaceFoldersNotification>( | |
| 1450 | 1460 | handlers::handle_did_change_workspace_folders, |
| 1451 | 1461 | ) |
| 1452 | .on_sync_mut::<notifs::DidChangeWatchedFiles>(handlers::handle_did_change_watched_files) | |
| 1453 | .on_sync_mut::<lsp_ext::CancelFlycheck>(handlers::handle_cancel_flycheck) | |
| 1454 | .on_sync_mut::<lsp_ext::ClearFlycheck>(handlers::handle_clear_flycheck) | |
| 1455 | .on_sync_mut::<lsp_ext::RunFlycheck>(handlers::handle_run_flycheck) | |
| 1456 | .on_sync_mut::<lsp_ext::AbortRunTest>(handlers::handle_abort_run_test) | |
| 1462 | .on_sync_mut::<lsp_types::DidChangeWatchedFilesNotification>( | |
| 1463 | handlers::handle_did_change_watched_files, | |
| 1464 | ) | |
| 1465 | .on_sync_mut::<lsp_ext::CancelFlycheckNotification>(handlers::handle_cancel_flycheck) | |
| 1466 | .on_sync_mut::<lsp_ext::ClearFlycheckNotification>(handlers::handle_clear_flycheck) | |
| 1467 | .on_sync_mut::<lsp_ext::RunFlycheckNotification>(handlers::handle_run_flycheck) | |
| 1468 | .on_sync_mut::<lsp_ext::AbortRunTestNotification>(handlers::handle_abort_run_test) | |
| 1457 | 1469 | .finish(); |
| 1458 | 1470 | } |
| 1459 | 1471 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs+15-19| ... | ... | @@ -15,10 +15,10 @@ |
| 15 | 15 | // FIXME: This is a mess that needs some untangling work |
| 16 | 16 | use std::{iter, mem, sync::atomic::AtomicUsize, time::Duration}; |
| 17 | 17 | |
| 18 | use hir::{ChangeWithProcMacros, ProcMacrosBuilder, db::DefDatabase}; | |
| 18 | use hir::{ChangeWithProcMacros, ProcMacrosBuilder}; | |
| 19 | 19 | use ide_db::{ |
| 20 | 20 | FxHashMap, |
| 21 | base_db::{CrateGraphBuilder, ProcMacroLoadingError, ProcMacroPaths, salsa::Durability}, | |
| 21 | base_db::{CrateGraphBuilder, ProcMacroLoadingError, ProcMacroPaths}, | |
| 22 | 22 | }; |
| 23 | 23 | use itertools::Itertools; |
| 24 | 24 | use load_cargo::{ProjectFolders, load_proc_macro}; |
| ... | ... | @@ -109,14 +109,10 @@ impl GlobalState { |
| 109 | 109 | self.reload_flycheck(); |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | if self.analysis_host.raw_database().expand_proc_attr_macros() | |
| 113 | != self.config.expand_proc_attr_macros() | |
| 114 | { | |
| 115 | self.analysis_host.raw_database_mut().set_expand_proc_attr_macros_with_durability( | |
| 116 | self.config.expand_proc_attr_macros(), | |
| 117 | Durability::HIGH, | |
| 118 | ); | |
| 119 | } | |
| 112 | hir::db::set_expand_proc_attr_macros( | |
| 113 | self.analysis_host.raw_database_mut(), | |
| 114 | self.config.expand_proc_attr_macros(), | |
| 115 | ); | |
| 120 | 116 | |
| 121 | 117 | if self.config.cargo(None) != old_config.cargo(None) { |
| 122 | 118 | let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false }; |
| ... | ... | @@ -544,8 +540,8 @@ impl GlobalState { |
| 544 | 540 | // FIXME: can we abort the build scripts here if they are already running? |
| 545 | 541 | self.workspaces = Arc::new(workspaces); |
| 546 | 542 | self.check_workspaces_msrv().for_each(|message| { |
| 547 | self.send_notification::<lsp_types::notification::ShowMessage>( | |
| 548 | lsp_types::ShowMessageParams { typ: lsp_types::MessageType::WARNING, message }, | |
| 543 | self.send_notification::<lsp_types::ShowMessageNotification>( | |
| 544 | lsp_types::ShowMessageParams { kind: lsp_types::MessageType::Warning, message }, | |
| 549 | 545 | ); |
| 550 | 546 | }); |
| 551 | 547 | |
| ... | ... | @@ -585,10 +581,10 @@ impl GlobalState { |
| 585 | 581 | }) |
| 586 | 582 | }) |
| 587 | 583 | .map(|(base, pat)| lsp_types::FileSystemWatcher { |
| 588 | glob_pattern: lsp_types::GlobPattern::Relative( | |
| 584 | glob_pattern: lsp_types::GlobPattern::RelativePattern( | |
| 589 | 585 | lsp_types::RelativePattern { |
| 590 | base_uri: lsp_types::OneOf::Right( | |
| 591 | lsp_types::Url::from_file_path(base).unwrap(), | |
| 586 | base_uri: lsp_types::BaseUri::Uri( | |
| 587 | lsp_types::Uri::from_file_path(base).unwrap(), | |
| 592 | 588 | ), |
| 593 | 589 | pattern: pat.to_owned(), |
| 594 | 590 | }, |
| ... | ... | @@ -610,7 +606,7 @@ impl GlobalState { |
| 610 | 606 | }) |
| 611 | 607 | }) |
| 612 | 608 | .map(|glob_pattern| lsp_types::FileSystemWatcher { |
| 613 | glob_pattern: lsp_types::GlobPattern::String(glob_pattern), | |
| 609 | glob_pattern: lsp_types::GlobPattern::Pattern(glob_pattern), | |
| 614 | 610 | kind: None, |
| 615 | 611 | }) |
| 616 | 612 | .collect() |
| ... | ... | @@ -624,7 +620,7 @@ impl GlobalState { |
| 624 | 620 | continue; |
| 625 | 621 | }; |
| 626 | 622 | watchers.push(lsp_types::FileSystemWatcher { |
| 627 | glob_pattern: lsp_types::GlobPattern::String( | |
| 623 | glob_pattern: lsp_types::GlobPattern::Pattern( | |
| 628 | 624 | build.build_file.to_string(), |
| 629 | 625 | ), |
| 630 | 626 | kind: None, |
| ... | ... | @@ -638,7 +634,7 @@ impl GlobalState { |
| 638 | 634 | .chain(self.workspaces.iter().map(|ws| ws.manifest().map(ManifestPath::as_ref))) |
| 639 | 635 | .flatten() |
| 640 | 636 | .map(|glob_pattern| lsp_types::FileSystemWatcher { |
| 641 | glob_pattern: lsp_types::GlobPattern::String(glob_pattern.to_string()), | |
| 637 | glob_pattern: lsp_types::GlobPattern::Pattern(glob_pattern.to_string()), | |
| 642 | 638 | kind: None, |
| 643 | 639 | }), |
| 644 | 640 | ); |
| ... | ... | @@ -650,7 +646,7 @@ impl GlobalState { |
| 650 | 646 | method: "workspace/didChangeWatchedFiles".to_owned(), |
| 651 | 647 | register_options: Some(serde_json::to_value(registration_options).unwrap()), |
| 652 | 648 | }; |
| 653 | self.send_request::<lsp_types::request::RegisterCapability>( | |
| 649 | self.send_request::<lsp_types::RegistrationRequest>( | |
| 654 | 650 | lsp_types::RegistrationParams { registrations: vec![registration] }, |
| 655 | 651 | |_, _| (), |
| 656 | 652 | ); |
src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs+4| ... | ... | @@ -204,6 +204,10 @@ impl CargoTargetSpec { |
| 204 | 204 | } |
| 205 | 205 | } |
| 206 | 206 | cargo_args.extend(config.cargo_extra_args.iter().cloned()); |
| 207 | if let Some(config_path) = &config.config_path { | |
| 208 | cargo_args.push("--config".to_owned()); | |
| 209 | cargo_args.push(config_path.to_string()); | |
| 210 | } | |
| 207 | 211 | (cargo_args, executable_args) |
| 208 | 212 | } |
| 209 | 213 |
src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs+47-55| ... | ... | @@ -20,23 +20,19 @@ mod ratoml; |
| 20 | 20 | mod support; |
| 21 | 21 | mod testdir; |
| 22 | 22 | |
| 23 | use std::{collections::HashMap, path::PathBuf, time::Instant}; | |
| 23 | use std::{path::PathBuf, time::Instant}; | |
| 24 | 24 | |
| 25 | 25 | use ide_db::FxHashMap; |
| 26 | 26 | use lsp_types::{ |
| 27 | CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams, | |
| 28 | DocumentFormattingParams, DocumentRangeFormattingParams, FileRename, FormattingOptions, | |
| 29 | GotoDefinitionParams, HoverParams, InlayHint, InlayHintLabel, InlayHintParams, | |
| 30 | PartialResultParams, Position, Range, RenameFilesParams, TextDocumentItem, | |
| 31 | TextDocumentPositionParams, WorkDoneProgressParams, | |
| 32 | notification::DidOpenTextDocument, | |
| 33 | request::{ | |
| 34 | CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest, | |
| 35 | InlayHintRequest, InlayHintResolveRequest, RangeFormatting, WillRenameFiles, | |
| 36 | WorkspaceSymbolRequest, | |
| 37 | }, | |
| 27 | CodeActionContext, CodeActionParams, CodeActionRequest, CompletionParams, CompletionRequest, | |
| 28 | DidOpenTextDocumentNotification, DidOpenTextDocumentParams, DocumentFormattingParams, | |
| 29 | DocumentFormattingRequest, DocumentRangeFormattingParams, DocumentRangeFormattingRequest, | |
| 30 | FileRename, FormattingOptions, HoverParams, HoverRequest, InlayHint, InlayHintParams, | |
| 31 | InlayHintRequest, InlayHintResolveRequest, Label, LanguageKind, PartialResultParams, Position, | |
| 32 | Range, RenameFilesParams, TextDocumentItem, TextDocumentPositionParams, TypeDefinitionParams, | |
| 33 | TypeDefinitionRequest, WillRenameFilesRequest, WorkDoneProgressParams, WorkspaceSymbolRequest, | |
| 38 | 34 | }; |
| 39 | use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams}; | |
| 35 | use rust_analyzer::lsp::ext::{OnEnterRequest, RunnablesParams, RunnablesRequest}; | |
| 40 | 36 | use serde_json::json; |
| 41 | 37 | use stdx::format_to_acc; |
| 42 | 38 | |
| ... | ... | @@ -68,8 +64,8 @@ use std::collections::Spam; |
| 68 | 64 | .server() |
| 69 | 65 | .wait_until_workspace_is_loaded(); |
| 70 | 66 | |
| 71 | let res = server.send_request::<Completion>(CompletionParams { | |
| 72 | text_document_position: TextDocumentPositionParams::new( | |
| 67 | let res = server.send_request::<CompletionRequest>(CompletionParams { | |
| 68 | text_document_position_params: TextDocumentPositionParams::new( | |
| 73 | 69 | server.doc_id("src/lib.rs"), |
| 74 | 70 | Position::new(0, 23), |
| 75 | 71 | ), |
| ... | ... | @@ -112,13 +108,13 @@ fn f() { |
| 112 | 108 | let hint = hints.pop().unwrap(); |
| 113 | 109 | assert!(hint.data.is_some()); |
| 114 | 110 | assert!( |
| 115 | matches!(&hint.label, InlayHintLabel::LabelParts(parts) if parts[1].location.is_none()) | |
| 111 | matches!(&hint.label, Label::InlayHintLabelPartList(parts) if parts[1].location.is_none()) | |
| 116 | 112 | ); |
| 117 | 113 | let res = server.send_request::<InlayHintResolveRequest>(hint); |
| 118 | 114 | let hint = serde_json::from_value::<InlayHint>(res).unwrap(); |
| 119 | 115 | assert!(hint.data.is_none()); |
| 120 | 116 | assert!( |
| 121 | matches!(&hint.label, InlayHintLabel::LabelParts(parts) if parts[1].location.is_some()) | |
| 117 | matches!(&hint.label, Label::InlayHintLabelPartList(parts) if parts[1].location.is_some()) | |
| 122 | 118 | ); |
| 123 | 119 | } |
| 124 | 120 | |
| ... | ... | @@ -160,8 +156,8 @@ use dependency2::Spam; |
| 160 | 156 | .server() |
| 161 | 157 | .wait_until_workspace_is_loaded(); |
| 162 | 158 | |
| 163 | let res = server.send_request::<Completion>(CompletionParams { | |
| 164 | text_document_position: TextDocumentPositionParams::new( | |
| 159 | let res = server.send_request::<CompletionRequest>(CompletionParams { | |
| 160 | text_document_position_params: TextDocumentPositionParams::new( | |
| 165 | 161 | server.doc_id("src/lib.rs"), |
| 166 | 162 | Position::new(5, 18), |
| 167 | 163 | ), |
| ... | ... | @@ -171,8 +167,8 @@ use dependency2::Spam; |
| 171 | 167 | }); |
| 172 | 168 | assert!(res.to_string().contains("SpecialHashMap"), "{}", res.to_string()); |
| 173 | 169 | |
| 174 | let res = server.send_request::<Completion>(CompletionParams { | |
| 175 | text_document_position: TextDocumentPositionParams::new( | |
| 170 | let res = server.send_request::<CompletionRequest>(CompletionParams { | |
| 171 | text_document_position_params: TextDocumentPositionParams::new( | |
| 176 | 172 | server.doc_id("src/lib.rs"), |
| 177 | 173 | Position::new(6, 18), |
| 178 | 174 | ), |
| ... | ... | @@ -199,8 +195,8 @@ use dependency2::Spam; |
| 199 | 195 | |
| 200 | 196 | std::thread::sleep(std::time::Duration::from_secs(3)); |
| 201 | 197 | |
| 202 | let res = server.send_request::<Completion>(CompletionParams { | |
| 203 | text_document_position: TextDocumentPositionParams::new( | |
| 198 | let res = server.send_request::<CompletionRequest>(CompletionParams { | |
| 199 | text_document_position_params: TextDocumentPositionParams::new( | |
| 204 | 200 | server.doc_id("src/lib.rs"), |
| 205 | 201 | Position::new(5, 18), |
| 206 | 202 | ), |
| ... | ... | @@ -210,8 +206,8 @@ use dependency2::Spam; |
| 210 | 206 | }); |
| 211 | 207 | assert!(!res.to_string().contains("SpecialHashMap")); |
| 212 | 208 | |
| 213 | let res = server.send_request::<Completion>(CompletionParams { | |
| 214 | text_document_position: TextDocumentPositionParams::new( | |
| 209 | let res = server.send_request::<CompletionRequest>(CompletionParams { | |
| 210 | text_document_position_params: TextDocumentPositionParams::new( | |
| 215 | 211 | server.doc_id("src/lib.rs"), |
| 216 | 212 | Position::new(6, 18), |
| 217 | 213 | ), |
| ... | ... | @@ -256,7 +252,7 @@ fn main() {} |
| 256 | 252 | .server() |
| 257 | 253 | .wait_until_workspace_is_loaded(); |
| 258 | 254 | |
| 259 | server.request::<Runnables>( | |
| 255 | server.request::<RunnablesRequest>( | |
| 260 | 256 | RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None }, |
| 261 | 257 | json!([ |
| 262 | 258 | { |
| ... | ... | @@ -407,7 +403,7 @@ mod tests { |
| 407 | 403 | .wait_until_workspace_is_loaded(); |
| 408 | 404 | |
| 409 | 405 | for runnable in ["consumer", "dependency", "devdependency"] { |
| 410 | server.request::<Runnables>( | |
| 406 | server.request::<RunnablesRequest>( | |
| 411 | 407 | RunnablesParams { |
| 412 | 408 | text_document: server.doc_id(&format!("{runnable}/src/lib.rs")), |
| 413 | 409 | position: None, |
| ... | ... | @@ -472,7 +468,7 @@ fn otherpkg() {} |
| 472 | 468 | .server() |
| 473 | 469 | .wait_until_workspace_is_loaded(); |
| 474 | 470 | |
| 475 | server.request::<Runnables>( | |
| 471 | server.request::<RunnablesRequest>( | |
| 476 | 472 | RunnablesParams { text_document: server.doc_id("foo/mainpkg/src/main.rs"), position: None }, |
| 477 | 473 | json!([ |
| 478 | 474 | "{...}", |
| ... | ... | @@ -497,7 +493,7 @@ fn otherpkg() {} |
| 497 | 493 | ]), |
| 498 | 494 | ); |
| 499 | 495 | |
| 500 | server.request::<Runnables>( | |
| 496 | server.request::<RunnablesRequest>( | |
| 501 | 497 | RunnablesParams { text_document: server.doc_id("foo/otherpkg/src/lib.rs"), position: None }, |
| 502 | 498 | json!([ |
| 503 | 499 | "{...}", |
| ... | ... | @@ -547,7 +543,7 @@ pub use std::collections::HashMap; |
| 547 | 543 | ) |
| 548 | 544 | .wait_until_workspace_is_loaded(); |
| 549 | 545 | |
| 550 | server.request::<Formatting>( | |
| 546 | server.request::<DocumentFormattingRequest>( | |
| 551 | 547 | DocumentFormattingParams { |
| 552 | 548 | text_document: server.doc_id("src/lib.rs"), |
| 553 | 549 | options: FormattingOptions { |
| ... | ... | @@ -556,7 +552,6 @@ pub use std::collections::HashMap; |
| 556 | 552 | insert_final_newline: None, |
| 557 | 553 | trim_final_newlines: None, |
| 558 | 554 | trim_trailing_whitespace: None, |
| 559 | properties: HashMap::new(), | |
| 560 | 555 | }, |
| 561 | 556 | work_done_progress_params: WorkDoneProgressParams::default(), |
| 562 | 557 | }, |
| ... | ... | @@ -600,13 +595,12 @@ pub use std::collections::HashMap; |
| 600 | 595 | ) |
| 601 | 596 | .wait_until_workspace_is_loaded(); |
| 602 | 597 | |
| 603 | server.request::<Formatting>( | |
| 598 | server.request::<DocumentFormattingRequest>( | |
| 604 | 599 | DocumentFormattingParams { |
| 605 | 600 | text_document: server.doc_id("src/lib.rs"), |
| 606 | 601 | options: FormattingOptions { |
| 607 | 602 | tab_size: 4, |
| 608 | 603 | insert_spaces: false, |
| 609 | properties: HashMap::new(), | |
| 610 | 604 | insert_final_newline: None, |
| 611 | 605 | trim_final_newlines: None, |
| 612 | 606 | trim_trailing_whitespace: None, |
| ... | ... | @@ -651,7 +645,7 @@ fn main() {} |
| 651 | 645 | ) |
| 652 | 646 | .wait_until_workspace_is_loaded(); |
| 653 | 647 | |
| 654 | server.request::<Formatting>( | |
| 648 | server.request::<DocumentFormattingRequest>( | |
| 655 | 649 | DocumentFormattingParams { |
| 656 | 650 | text_document: server.doc_id("src/lib.rs"), |
| 657 | 651 | options: FormattingOptions { |
| ... | ... | @@ -660,7 +654,6 @@ fn main() {} |
| 660 | 654 | insert_final_newline: None, |
| 661 | 655 | trim_final_newlines: None, |
| 662 | 656 | trim_trailing_whitespace: None, |
| 663 | properties: HashMap::new(), | |
| 664 | 657 | }, |
| 665 | 658 | work_done_progress_params: WorkDoneProgressParams::default(), |
| 666 | 659 | }, |
| ... | ... | @@ -707,7 +700,7 @@ fn main() { |
| 707 | 700 | .server() |
| 708 | 701 | .wait_until_workspace_is_loaded(); |
| 709 | 702 | |
| 710 | server.request::<RangeFormatting>( | |
| 703 | server.request::<DocumentRangeFormattingRequest>( | |
| 711 | 704 | DocumentRangeFormattingParams { |
| 712 | 705 | range: Range { |
| 713 | 706 | end: Position { line: 1, character: 0 }, |
| ... | ... | @@ -720,7 +713,6 @@ fn main() { |
| 720 | 713 | insert_final_newline: None, |
| 721 | 714 | trim_final_newlines: None, |
| 722 | 715 | trim_trailing_whitespace: None, |
| 723 | properties: HashMap::new(), | |
| 724 | 716 | }, |
| 725 | 717 | work_done_progress_params: WorkDoneProgressParams::default(), |
| 726 | 718 | }, |
| ... | ... | @@ -928,17 +920,17 @@ fn main() {{}} |
| 928 | 920 | .wait_until_workspace_is_loaded(); |
| 929 | 921 | |
| 930 | 922 | for i in 0..10 { |
| 931 | server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams { | |
| 923 | server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams { | |
| 932 | 924 | text_document: TextDocumentItem { |
| 933 | 925 | uri: server.doc_id(&format!("src/m{i}.rs")).uri, |
| 934 | language_id: "rust".to_owned(), | |
| 926 | language_id: LanguageKind::Rust, | |
| 935 | 927 | version: 0, |
| 936 | 928 | text: "/// Docs\nfn foo() {}".to_owned(), |
| 937 | 929 | }, |
| 938 | 930 | }); |
| 939 | 931 | } |
| 940 | 932 | let start = Instant::now(); |
| 941 | server.request::<OnEnter>( | |
| 933 | server.request::<OnEnterRequest>( | |
| 942 | 934 | TextDocumentPositionParams { |
| 943 | 935 | text_document: server.doc_id("src/m0.rs"), |
| 944 | 936 | position: Position { line: 0, character: 5 }, |
| ... | ... | @@ -976,7 +968,7 @@ version = \"0.0.0\" |
| 976 | 968 | .server() |
| 977 | 969 | .wait_until_workspace_is_loaded(); |
| 978 | 970 | |
| 979 | server.request::<OnEnter>( | |
| 971 | server.request::<OnEnterRequest>( | |
| 980 | 972 | TextDocumentPositionParams { |
| 981 | 973 | text_document: server.doc_id("src/main.rs"), |
| 982 | 974 | position: Position { line: 0, character: 8 }, |
| ... | ... | @@ -1089,8 +1081,8 @@ fn main() { |
| 1089 | 1081 | }); |
| 1090 | 1082 | assert!(res.to_string().contains("&str")); |
| 1091 | 1083 | |
| 1092 | server.request::<GotoTypeDefinition>( | |
| 1093 | GotoDefinitionParams { | |
| 1084 | server.request::<TypeDefinitionRequest>( | |
| 1085 | TypeDefinitionParams { | |
| 1094 | 1086 | text_document_position_params: TextDocumentPositionParams::new( |
| 1095 | 1087 | server.doc_id("src/main.rs"), |
| 1096 | 1088 | Position::new(28, 9), |
| ... | ... | @@ -1115,8 +1107,8 @@ fn main() { |
| 1115 | 1107 | }]), |
| 1116 | 1108 | ); |
| 1117 | 1109 | |
| 1118 | server.request::<GotoTypeDefinition>( | |
| 1119 | GotoDefinitionParams { | |
| 1110 | server.request::<TypeDefinitionRequest>( | |
| 1111 | TypeDefinitionParams { | |
| 1120 | 1112 | text_document_position_params: TextDocumentPositionParams::new( |
| 1121 | 1113 | server.doc_id("src/main.rs"), |
| 1122 | 1114 | Position::new(29, 9), |
| ... | ... | @@ -1308,8 +1300,8 @@ use crate::old_folder::nested::foo as bar; |
| 1308 | 1300 | let server = |
| 1309 | 1301 | Project::with_fixture(code).tmp_dir(tmp_dir).server().wait_until_workspace_is_loaded(); |
| 1310 | 1302 | |
| 1311 | //rename same level file | |
| 1312 | server.request::<WillRenameFiles>( | |
| 1303 | // rename same level file | |
| 1304 | server.request::<WillRenameFilesRequest>( | |
| 1313 | 1305 | RenameFilesParams { |
| 1314 | 1306 | files: vec![FileRename { |
| 1315 | 1307 | old_uri: base_path.join("src/old_file.rs").to_str().unwrap().to_owned(), |
| ... | ... | @@ -1343,8 +1335,8 @@ use crate::old_folder::nested::foo as bar; |
| 1343 | 1335 | }), |
| 1344 | 1336 | ); |
| 1345 | 1337 | |
| 1346 | //rename file from mod.rs to foo.rs | |
| 1347 | server.request::<WillRenameFiles>( | |
| 1338 | // rename file from mod.rs to foo.rs | |
| 1339 | server.request::<WillRenameFilesRequest>( | |
| 1348 | 1340 | RenameFilesParams { |
| 1349 | 1341 | files: vec![FileRename { |
| 1350 | 1342 | old_uri: base_path.join("src/from_mod/mod.rs").to_str().unwrap().to_owned(), |
| ... | ... | @@ -1354,8 +1346,8 @@ use crate::old_folder::nested::foo as bar; |
| 1354 | 1346 | json!(null), |
| 1355 | 1347 | ); |
| 1356 | 1348 | |
| 1357 | //rename file from foo.rs to mod.rs | |
| 1358 | server.request::<WillRenameFiles>( | |
| 1349 | // rename file from foo.rs to mod.rs | |
| 1350 | server.request::<WillRenameFilesRequest>( | |
| 1359 | 1351 | RenameFilesParams { |
| 1360 | 1352 | files: vec![FileRename { |
| 1361 | 1353 | old_uri: base_path.join("src/to_mod/foo.rs").to_str().unwrap().to_owned(), |
| ... | ... | @@ -1365,8 +1357,8 @@ use crate::old_folder::nested::foo as bar; |
| 1365 | 1357 | json!(null), |
| 1366 | 1358 | ); |
| 1367 | 1359 | |
| 1368 | //rename same level file | |
| 1369 | server.request::<WillRenameFiles>( | |
| 1360 | // rename same level file | |
| 1361 | server.request::<WillRenameFilesRequest>( | |
| 1370 | 1362 | RenameFilesParams { |
| 1371 | 1363 | files: vec![FileRename { |
| 1372 | 1364 | old_uri: base_path.join("src/old_folder").to_str().unwrap().to_owned(), |
| ... | ... | @@ -1568,7 +1560,7 @@ fn test<T: Trait>() { |
| 1568 | 1560 | .server() |
| 1569 | 1561 | .wait_until_workspace_is_loaded(); |
| 1570 | 1562 | |
| 1571 | let res = server.send_request::<rust_analyzer::lsp::ext::EvaluatePredicate>( | |
| 1563 | let res = server.send_request::<rust_analyzer::lsp::ext::EvaluatePredicateRequest>( | |
| 1572 | 1564 | rust_analyzer::lsp::ext::EvaluatePredicateParams { |
| 1573 | 1565 | text: "T: Trait".to_owned(), |
| 1574 | 1566 | text_document: server.doc_id("src/lib.rs"), |
| ... | ... | @@ -1607,7 +1599,7 @@ fn test() { |
| 1607 | 1599 | .server() |
| 1608 | 1600 | .wait_until_workspace_is_loaded(); |
| 1609 | 1601 | |
| 1610 | let res = server.send_request::<rust_analyzer::lsp::ext::GetFailedObligations>( | |
| 1602 | let res = server.send_request::<rust_analyzer::lsp::ext::GetFailedObligationsRequest>( | |
| 1611 | 1603 | rust_analyzer::lsp::ext::GetFailedObligationsParams { |
| 1612 | 1604 | text_document: server.doc_id("src/lib.rs"), |
| 1613 | 1605 | position: Position::new(4, 19), |
src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs+47-36| ... | ... | @@ -1,23 +1,24 @@ |
| 1 | 1 | use crate::support::{Project, Server}; |
| 2 | 2 | use crate::testdir::TestDir; |
| 3 | 3 | use lsp_types::{ |
| 4 | DidChangeTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, | |
| 5 | TextDocumentContentChangeEvent, TextDocumentIdentifier, TextDocumentItem, Url, | |
| 4 | DidChangeTextDocumentNotification, DidChangeTextDocumentParams, | |
| 5 | DidOpenTextDocumentNotification, DidOpenTextDocumentParams, DidSaveTextDocumentNotification, | |
| 6 | DidSaveTextDocumentParams, TextDocumentContentChangeEvent, | |
| 7 | TextDocumentContentChangeWholeDocument, TextDocumentIdentifier, TextDocumentItem, Uri, | |
| 6 | 8 | VersionedTextDocumentIdentifier, |
| 7 | notification::{DidChangeTextDocument, DidOpenTextDocument, DidSaveTextDocument}, | |
| 8 | 9 | }; |
| 9 | 10 | use paths::Utf8PathBuf; |
| 10 | 11 | |
| 11 | 12 | use rust_analyzer::config::Config; |
| 12 | 13 | use rust_analyzer::lsp::ext::{ |
| 13 | InternalTestingFetchConfig, InternalTestingFetchConfigOption, InternalTestingFetchConfigParams, | |
| 14 | InternalTestingFetchConfigResponse, | |
| 14 | InternalTestingFetchConfigOption, InternalTestingFetchConfigParams, | |
| 15 | InternalTestingFetchConfigRequest, InternalTestingFetchConfigResponse, | |
| 15 | 16 | }; |
| 16 | 17 | use serde_json::json; |
| 17 | 18 | use test_utils::skip_slow_tests; |
| 18 | 19 | |
| 19 | 20 | struct RatomlTest { |
| 20 | urls: Vec<Url>, | |
| 21 | urls: Vec<Uri>, | |
| 21 | 22 | server: Server, |
| 22 | 23 | tmp_path: Utf8PathBuf, |
| 23 | 24 | } |
| ... | ... | @@ -54,7 +55,7 @@ impl RatomlTest { |
| 54 | 55 | case |
| 55 | 56 | } |
| 56 | 57 | |
| 57 | fn fixture_path(&self, fixture: &str) -> Url { | |
| 58 | fn fixture_path(&self, fixture: &str) -> Uri { | |
| 58 | 59 | let mut lines = fixture.trim().split('\n'); |
| 59 | 60 | |
| 60 | 61 | let mut path = |
| ... | ... | @@ -81,7 +82,7 @@ impl RatomlTest { |
| 81 | 82 | path = path.join(piece); |
| 82 | 83 | } |
| 83 | 84 | |
| 84 | Url::parse( | |
| 85 | Uri::parse( | |
| 85 | 86 | format!("file://{}", path.into_string().replace("C:\\", "/c:/").replace('\\', "/")) |
| 86 | 87 | .as_str(), |
| 87 | 88 | ) |
| ... | ... | @@ -89,65 +90,75 @@ impl RatomlTest { |
| 89 | 90 | } |
| 90 | 91 | |
| 91 | 92 | fn create(&mut self, fixture_path: &str, text: String) { |
| 92 | let url = self.fixture_path(fixture_path); | |
| 93 | let uri = self.fixture_path(fixture_path); | |
| 93 | 94 | |
| 94 | self.server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams { | |
| 95 | self.server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams { | |
| 95 | 96 | text_document: TextDocumentItem { |
| 96 | uri: url.clone(), | |
| 97 | language_id: "rust".to_owned(), | |
| 97 | uri: uri.clone(), | |
| 98 | language_id: lsp_types::LanguageKind::Rust, | |
| 98 | 99 | version: 0, |
| 99 | 100 | text: String::new(), |
| 100 | 101 | }, |
| 101 | 102 | }); |
| 102 | 103 | |
| 103 | self.server.notification::<DidChangeTextDocument>(DidChangeTextDocumentParams { | |
| 104 | text_document: VersionedTextDocumentIdentifier { uri: url, version: 0 }, | |
| 105 | content_changes: vec![TextDocumentContentChangeEvent { | |
| 106 | range: None, | |
| 107 | range_length: None, | |
| 108 | text, | |
| 109 | }], | |
| 110 | }); | |
| 104 | self.server.notification::<DidChangeTextDocumentNotification>( | |
| 105 | DidChangeTextDocumentParams { | |
| 106 | text_document: VersionedTextDocumentIdentifier { | |
| 107 | text_document_identifier: TextDocumentIdentifier { uri }, | |
| 108 | version: 0, | |
| 109 | }, | |
| 110 | ||
| 111 | content_changes: vec![ | |
| 112 | TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( | |
| 113 | TextDocumentContentChangeWholeDocument { text }, | |
| 114 | ), | |
| 115 | ], | |
| 116 | }, | |
| 117 | ); | |
| 111 | 118 | } |
| 112 | 119 | |
| 113 | 120 | fn delete(&mut self, file_idx: usize) { |
| 114 | self.server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams { | |
| 121 | self.server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams { | |
| 115 | 122 | text_document: TextDocumentItem { |
| 116 | 123 | uri: self.urls[file_idx].clone(), |
| 117 | language_id: "rust".to_owned(), | |
| 124 | language_id: lsp_types::LanguageKind::Rust, | |
| 118 | 125 | version: 0, |
| 119 | 126 | text: "".to_owned(), |
| 120 | 127 | }, |
| 121 | 128 | }); |
| 122 | 129 | |
| 123 | 130 | // See if deleting ratoml file will make the config of interest to return to its default value. |
| 124 | self.server.notification::<DidSaveTextDocument>(DidSaveTextDocumentParams { | |
| 131 | self.server.notification::<DidSaveTextDocumentNotification>(DidSaveTextDocumentParams { | |
| 125 | 132 | text_document: TextDocumentIdentifier { uri: self.urls[file_idx].clone() }, |
| 126 | 133 | text: Some("".to_owned()), |
| 127 | 134 | }); |
| 128 | 135 | } |
| 129 | 136 | |
| 130 | 137 | fn edit(&mut self, file_idx: usize, text: String) { |
| 131 | self.server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams { | |
| 138 | self.server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams { | |
| 132 | 139 | text_document: TextDocumentItem { |
| 133 | 140 | uri: self.urls[file_idx].clone(), |
| 134 | language_id: "rust".to_owned(), | |
| 141 | language_id: lsp_types::LanguageKind::Rust, | |
| 135 | 142 | version: 0, |
| 136 | 143 | text: String::new(), |
| 137 | 144 | }, |
| 138 | 145 | }); |
| 139 | 146 | |
| 140 | self.server.notification::<DidChangeTextDocument>(DidChangeTextDocumentParams { | |
| 141 | text_document: VersionedTextDocumentIdentifier { | |
| 142 | uri: self.urls[file_idx].clone(), | |
| 143 | version: 0, | |
| 147 | self.server.notification::<DidChangeTextDocumentNotification>( | |
| 148 | DidChangeTextDocumentParams { | |
| 149 | text_document: VersionedTextDocumentIdentifier { | |
| 150 | text_document_identifier: TextDocumentIdentifier { | |
| 151 | uri: self.urls[file_idx].clone(), | |
| 152 | }, | |
| 153 | version: 0, | |
| 154 | }, | |
| 155 | content_changes: vec![ | |
| 156 | TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( | |
| 157 | TextDocumentContentChangeWholeDocument { text }, | |
| 158 | ), | |
| 159 | ], | |
| 144 | 160 | }, |
| 145 | content_changes: vec![TextDocumentContentChangeEvent { | |
| 146 | range: None, | |
| 147 | range_length: None, | |
| 148 | text, | |
| 149 | }], | |
| 150 | }); | |
| 161 | ); | |
| 151 | 162 | } |
| 152 | 163 | |
| 153 | 164 | fn query( |
| ... | ... | @@ -156,7 +167,7 @@ impl RatomlTest { |
| 156 | 167 | source_file_idx: usize, |
| 157 | 168 | expected: InternalTestingFetchConfigResponse, |
| 158 | 169 | ) { |
| 159 | let res = self.server.send_request::<InternalTestingFetchConfig>( | |
| 170 | let res = self.server.send_request::<InternalTestingFetchConfigRequest>( | |
| 160 | 171 | InternalTestingFetchConfigParams { |
| 161 | 172 | text_document: Some(TextDocumentIdentifier { |
| 162 | 173 | uri: self.urls[source_file_idx].clone(), |
src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs+13-13| ... | ... | @@ -9,7 +9,7 @@ use crossbeam_channel::{Receiver, after, select}; |
| 9 | 9 | use itertools::Itertools; |
| 10 | 10 | use lsp_server::{Connection, Message, Notification, Request}; |
| 11 | 11 | use lsp_types::{ |
| 12 | PublishDiagnosticsParams, TextDocumentIdentifier, Url, notification::Exit, request::Shutdown, | |
| 12 | ExitNotification, PublishDiagnosticsParams, ShutdownRequest, TextDocumentIdentifier, Uri, | |
| 13 | 13 | }; |
| 14 | 14 | use parking_lot::{Mutex, MutexGuard}; |
| 15 | 15 | use paths::{Utf8Path, Utf8PathBuf}; |
| ... | ... | @@ -229,13 +229,13 @@ impl Project<'_> { |
| 229 | 229 | ..Default::default() |
| 230 | 230 | }), |
| 231 | 231 | text_document: Some(lsp_types::TextDocumentClientCapabilities { |
| 232 | definition: Some(lsp_types::GotoCapability { | |
| 232 | definition: Some(lsp_types::DefinitionClientCapabilities { | |
| 233 | 233 | link_support: Some(true), |
| 234 | 234 | ..Default::default() |
| 235 | 235 | }), |
| 236 | 236 | code_action: Some(lsp_types::CodeActionClientCapabilities { |
| 237 | 237 | code_action_literal_support: Some( |
| 238 | lsp_types::CodeActionLiteralSupport::default(), | |
| 238 | lsp_types::ClientCodeActionLiteralOptions::default(), | |
| 239 | 239 | ), |
| 240 | 240 | ..Default::default() |
| 241 | 241 | }), |
| ... | ... | @@ -244,7 +244,7 @@ impl Project<'_> { |
| 244 | 244 | ..Default::default() |
| 245 | 245 | }), |
| 246 | 246 | inlay_hint: Some(lsp_types::InlayHintClientCapabilities { |
| 247 | resolve_support: Some(lsp_types::InlayHintResolveClientCapabilities { | |
| 247 | resolve_support: Some(lsp_types::ClientInlayHintResolveOptions { | |
| 248 | 248 | properties: vec![ |
| 249 | 249 | "textEdits".to_owned(), |
| 250 | 250 | "tooltip".to_owned(), |
| ... | ... | @@ -321,22 +321,22 @@ impl Server { |
| 321 | 321 | |
| 322 | 322 | pub(crate) fn doc_id(&self, rel_path: &str) -> TextDocumentIdentifier { |
| 323 | 323 | let path = self.dir.path().join(rel_path); |
| 324 | TextDocumentIdentifier { uri: Url::from_file_path(path).unwrap() } | |
| 324 | TextDocumentIdentifier { uri: Uri::from_file_path(path).unwrap() } | |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | 327 | pub(crate) fn notification<N>(&self, params: N::Params) |
| 328 | 328 | where |
| 329 | N: lsp_types::notification::Notification, | |
| 329 | N: lsp_types::Notification, | |
| 330 | 330 | N::Params: Serialize, |
| 331 | 331 | { |
| 332 | let r = Notification::new(N::METHOD.to_owned(), params); | |
| 332 | let r = Notification::new(N::METHOD.into(), params); | |
| 333 | 333 | self.send_notification(r) |
| 334 | 334 | } |
| 335 | 335 | |
| 336 | 336 | #[track_caller] |
| 337 | 337 | pub(crate) fn request<R>(&self, params: R::Params, expected_resp: Value) |
| 338 | 338 | where |
| 339 | R: lsp_types::request::Request, | |
| 339 | R: lsp_types::Request, | |
| 340 | 340 | R::Params: Serialize, |
| 341 | 341 | { |
| 342 | 342 | let actual = self.send_request::<R>(params); |
| ... | ... | @@ -354,13 +354,13 @@ impl Server { |
| 354 | 354 | #[track_caller] |
| 355 | 355 | pub(crate) fn send_request<R>(&self, params: R::Params) -> Value |
| 356 | 356 | where |
| 357 | R: lsp_types::request::Request, | |
| 357 | R: lsp_types::Request, | |
| 358 | 358 | R::Params: Serialize, |
| 359 | 359 | { |
| 360 | 360 | let id = self.req_id.get(); |
| 361 | 361 | self.req_id.set(id.wrapping_add(1)); |
| 362 | 362 | |
| 363 | let r = Request::new(id.into(), R::METHOD.to_owned(), params); | |
| 363 | let r = Request::new(id.into(), R::METHOD.into(), params); | |
| 364 | 364 | self.send_request_(r) |
| 365 | 365 | } |
| 366 | 366 | #[track_caller] |
| ... | ... | @@ -494,7 +494,7 @@ impl Server { |
| 494 | 494 | |
| 495 | 495 | pub(crate) fn write_file_and_save(&self, path: &str, text: String) { |
| 496 | 496 | fs::write(self.dir.path().join(path), &text).unwrap(); |
| 497 | self.notification::<lsp_types::notification::DidSaveTextDocument>( | |
| 497 | self.notification::<lsp_types::DidSaveTextDocumentNotification>( | |
| 498 | 498 | lsp_types::DidSaveTextDocumentParams { |
| 499 | 499 | text_document: self.doc_id(path), |
| 500 | 500 | text: Some(text), |
| ... | ... | @@ -505,8 +505,8 @@ impl Server { |
| 505 | 505 | |
| 506 | 506 | impl Drop for Server { |
| 507 | 507 | fn drop(&mut self) { |
| 508 | self.request::<Shutdown>((), Value::Null); | |
| 509 | self.notification::<Exit>(()); | |
| 508 | self.request::<ShutdownRequest>((), Value::Null); | |
| 509 | self.notification::<ExitNotification>(()); | |
| 510 | 510 | } |
| 511 | 511 | } |
| 512 | 512 |
src/tools/rust-analyzer/crates/span/src/map.rs+1-1| ... | ... | @@ -30,7 +30,7 @@ impl SpanMap { |
| 30 | 30 | /// in order. |
| 31 | 31 | pub fn finish(&mut self) { |
| 32 | 32 | always!( |
| 33 | self.spans.iter().tuple_windows().all(|(a, b)| a.0 < b.0), | |
| 33 | self.spans.iter().array_windows().all(|[a, b]| a.0 < b.0), | |
| 34 | 34 | "spans are not in order" |
| 35 | 35 | ); |
| 36 | 36 | self.spans.shrink_to_fit(); |
src/tools/rust-analyzer/crates/syntax/rust.ungram+3-3| ... | ... | @@ -468,17 +468,17 @@ AsmRegSpec = '@string' | NameRef |
| 468 | 468 | // reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr |
| 469 | 469 | AsmRegOperand = AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr |
| 470 | 470 | // clobber_abi := "clobber_abi(" <abi> *("," <abi>) [","] ")" |
| 471 | AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')' | |
| 471 | AsmClobberAbi = Attr* 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')' | |
| 472 | 472 | // option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" |
| 473 | 473 | AsmOption = 'pure' | 'nomem' | 'readonly' | 'preserves_flags' | 'noreturn' | 'nostack' | 'att_syntax' | 'raw' | 'may_unwind' |
| 474 | 474 | // options := "options(" option *("," option) [","] ")" |
| 475 | AsmOptions = 'options' '(' (AsmOption (',' AsmOption)*) ','? ')' | |
| 475 | AsmOptions = Attr* 'options' '(' (AsmOption (',' AsmOption)*) ','? ')' | |
| 476 | 476 | AsmLabel = 'label' BlockExpr |
| 477 | 477 | AsmSym = 'sym' Path |
| 478 | 478 | AsmConst = 'const' Expr |
| 479 | 479 | // operand := reg_operand / clobber_abi / options |
| 480 | 480 | AsmOperand = AsmRegOperand | AsmLabel | AsmSym | AsmConst |
| 481 | AsmOperandNamed = (Name '=')? AsmOperand | |
| 481 | AsmOperandNamed = Attr* (Name '=')? AsmOperand | |
| 482 | 482 | AsmPiece = AsmOperandNamed | AsmClobberAbi | AsmOptions |
| 483 | 483 | |
| 484 | 484 | FormatArgsExpr = |
src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs+19| ... | ... | @@ -59,6 +59,7 @@ impl ArrayType { |
| 59 | 59 | pub struct AsmClobberAbi { |
| 60 | 60 | pub(crate) syntax: SyntaxNode, |
| 61 | 61 | } |
| 62 | impl ast::HasAttrs for AsmClobberAbi {} | |
| 62 | 63 | impl AsmClobberAbi { |
| 63 | 64 | #[inline] |
| 64 | 65 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } |
| ... | ... | @@ -150,6 +151,7 @@ impl AsmOperandExpr { |
| 150 | 151 | pub struct AsmOperandNamed { |
| 151 | 152 | pub(crate) syntax: SyntaxNode, |
| 152 | 153 | } |
| 154 | impl ast::HasAttrs for AsmOperandNamed {} | |
| 153 | 155 | impl ast::HasName for AsmOperandNamed {} |
| 154 | 156 | impl AsmOperandNamed { |
| 155 | 157 | #[inline] |
| ... | ... | @@ -193,6 +195,7 @@ impl AsmOption { |
| 193 | 195 | pub struct AsmOptions { |
| 194 | 196 | pub(crate) syntax: SyntaxNode, |
| 195 | 197 | } |
| 198 | impl ast::HasAttrs for AsmOptions {} | |
| 196 | 199 | impl AsmOptions { |
| 197 | 200 | #[inline] |
| 198 | 201 | pub fn asm_options(&self) -> AstChildren<AsmOption> { support::children(&self.syntax) } |
| ... | ... | @@ -2193,6 +2196,7 @@ pub enum AsmPiece { |
| 2193 | 2196 | AsmOperandNamed(AsmOperandNamed), |
| 2194 | 2197 | AsmOptions(AsmOptions), |
| 2195 | 2198 | } |
| 2199 | impl ast::HasAttrs for AsmPiece {} | |
| 2196 | 2200 | |
| 2197 | 2201 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
| 2198 | 2202 | pub enum AssocItem { |
| ... | ... | @@ -9096,7 +9100,10 @@ impl AstNode for AnyHasAttrs { |
| 9096 | 9100 | matches!( |
| 9097 | 9101 | kind, |
| 9098 | 9102 | ARRAY_EXPR |
| 9103 | | ASM_CLOBBER_ABI | |
| 9099 | 9104 | | ASM_EXPR |
| 9105 | | ASM_OPERAND_NAMED | |
| 9106 | | ASM_OPTIONS | |
| 9100 | 9107 | | ASSOC_ITEM_LIST |
| 9101 | 9108 | | AWAIT_EXPR |
| 9102 | 9109 | | BECOME_EXPR |
| ... | ... | @@ -9194,10 +9201,22 @@ impl From<ArrayExpr> for AnyHasAttrs { |
| 9194 | 9201 | #[inline] |
| 9195 | 9202 | fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } |
| 9196 | 9203 | } |
| 9204 | impl From<AsmClobberAbi> for AnyHasAttrs { | |
| 9205 | #[inline] | |
| 9206 | fn from(node: AsmClobberAbi) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } | |
| 9207 | } | |
| 9197 | 9208 | impl From<AsmExpr> for AnyHasAttrs { |
| 9198 | 9209 | #[inline] |
| 9199 | 9210 | fn from(node: AsmExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } |
| 9200 | 9211 | } |
| 9212 | impl From<AsmOperandNamed> for AnyHasAttrs { | |
| 9213 | #[inline] | |
| 9214 | fn from(node: AsmOperandNamed) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } | |
| 9215 | } | |
| 9216 | impl From<AsmOptions> for AnyHasAttrs { | |
| 9217 | #[inline] | |
| 9218 | fn from(node: AsmOptions) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } | |
| 9219 | } | |
| 9201 | 9220 | impl From<AssocItemList> for AnyHasAttrs { |
| 9202 | 9221 | #[inline] |
| 9203 | 9222 | fn from(node: AssocItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } |
src/tools/rust-analyzer/docs/book/src/configuration_generated.md+9| ... | ... | @@ -142,6 +142,15 @@ To enable a name with a value, use `"key=value"`. |
| 142 | 142 | To disable, prefix the entry with a `!`. |
| 143 | 143 | |
| 144 | 144 | |
| 145 | ## rust-analyzer.cargo.configPath {#cargo.configPath} | |
| 146 | ||
| 147 | Default: `null` | |
| 148 | ||
| 149 | Path to a `.cargo/config.toml` style file to pass to cargo via `--config` | |
| 150 | for every cargo invocation (metadata, build scripts, config discovery). | |
| 151 | Useful to give rust-analyzer a consistent view of the project configuration. | |
| 152 | ||
| 153 | ||
| 145 | 154 | ## rust-analyzer.cargo.extraArgs {#cargo.extraArgs} |
| 146 | 155 | |
| 147 | 156 | Default: `[]` |
src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md+13-13| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | <!--- |
| 2 | lsp/ext.rs hash: cec81c987f189e83 | |
| 2 | lsp/ext.rs hash: ca646d2ad3d38ccd | |
| 3 | 3 | |
| 4 | 4 | If you need to change the above hash to make the test pass, please check if you |
| 5 | 5 | need to adjust this doc as well and ping this issue: |
| ... | ... | @@ -31,9 +31,10 @@ At the same time some essential configuration parameters are needed early on, be |
| 31 | 31 | For this reason, we ask that `initializationOptions` contains the configuration, as if the server did make a `"workspace/configuration"` request. |
| 32 | 32 | |
| 33 | 33 | If a language client does not know about `rust-analyzer`'s configuration options it can get sensible defaults by doing any of the following: |
| 34 | * Not sending `initializationOptions` | |
| 35 | * Sending `"initializationOptions": null` | |
| 36 | * Sending `"initializationOptions": {}` | |
| 34 | ||
| 35 | * Not sending `initializationOptions` | |
| 36 | * Sending `"initializationOptions": null` | |
| 37 | * Sending `"initializationOptions": {}` | |
| 37 | 38 | |
| 38 | 39 | ## Snippet `TextEdit` |
| 39 | 40 | |
| ... | ... | @@ -131,7 +132,6 @@ This request is sent from client to server to handle "Goto Parent Module" editor |
| 131 | 132 | |
| 132 | 133 | **Response:** `Location | Location[] | LocationLink[] | null` |
| 133 | 134 | |
| 134 | ||
| 135 | 135 | ### Example |
| 136 | 136 | |
| 137 | 137 | ```rust |
| ... | ... | @@ -671,7 +671,6 @@ interface RunFlycheckParams { |
| 671 | 671 | |
| 672 | 672 | Triggers the flycheck processes. |
| 673 | 673 | |
| 674 | ||
| 675 | 674 | **Method:** `rust-analyzer/clearFlycheck` |
| 676 | 675 | |
| 677 | 676 | **Notification:** |
| ... | ... | @@ -849,6 +848,7 @@ interface CommandLinkGroup { |
| 849 | 848 | ``` |
| 850 | 849 | |
| 851 | 850 | Such actions on the client side are appended to a hover bottom as command links: |
| 851 | ||
| 852 | 852 | ``` |
| 853 | 853 | +-----------------------------+ |
| 854 | 854 | | Hover content | |
| ... | ... | @@ -875,7 +875,6 @@ This request is sent from client to server to open the current project's Cargo.t |
| 875 | 875 | |
| 876 | 876 | **Response:** `Location | null` |
| 877 | 877 | |
| 878 | ||
| 879 | 878 | ### Example |
| 880 | 879 | |
| 881 | 880 | ```rust |
| ... | ... | @@ -919,6 +918,7 @@ interface HoverParams extends WorkDoneProgressParams { |
| 919 | 918 | position: Range | Position; |
| 920 | 919 | } |
| 921 | 920 | ``` |
| 921 | ||
| 922 | 922 | Whenever the client sends a `Range`, it is understood as the current selection and any hover included in the range will show the type of the expression if possible. |
| 923 | 923 | |
| 924 | 924 | ### Example |
| ... | ... | @@ -965,7 +965,6 @@ export const enum Direction { |
| 965 | 965 | Extends the existing `workspace/symbol` request with ability to filter symbols by broad scope and kind of symbol. |
| 966 | 966 | If this capability is set, `workspace/symbol` parameter gains two new optional fields: |
| 967 | 967 | |
| 968 | ||
| 969 | 968 | ```typescript |
| 970 | 969 | interface WorkspaceSymbolParams { |
| 971 | 970 | /** |
| ... | ... | @@ -1002,7 +1001,6 @@ However, the server doesn't know which commands are available on the client. |
| 1002 | 1001 | |
| 1003 | 1002 | This extensions allows the client to communicate this info. |
| 1004 | 1003 | |
| 1005 | ||
| 1006 | 1004 | ```typescript |
| 1007 | 1005 | export interface ClientCommandOptions { |
| 1008 | 1006 | /** |
| ... | ... | @@ -1050,6 +1048,7 @@ export interface FetchDependencyListParams {} |
| 1050 | 1048 | ``` |
| 1051 | 1049 | |
| 1052 | 1050 | **Response:** |
| 1051 | ||
| 1053 | 1052 | ```typescript |
| 1054 | 1053 | export interface FetchDependencyListResult { |
| 1055 | 1054 | crates: { |
| ... | ... | @@ -1059,6 +1058,7 @@ export interface FetchDependencyListResult { |
| 1059 | 1058 | }[]; |
| 1060 | 1059 | } |
| 1061 | 1060 | ``` |
| 1061 | ||
| 1062 | 1062 | Returns all crates from this workspace, so it can be used create a viewTree to help navigate the dependency tree. |
| 1063 | 1063 | |
| 1064 | 1064 | ## View Recursive Memory Layout |
| ... | ... | @@ -1100,8 +1100,8 @@ If `RecursiveMemoryLayout::nodes::length == 0` we could not find a suitable type |
| 1100 | 1100 | |
| 1101 | 1101 | Generic Types do not give anything because they are incomplete. Fully specified generic types do not give anything if they are selected directly but do work when a child of other types [this is consistent with other behavior](https://github.com/rust-lang/rust-analyzer/issues/15010). |
| 1102 | 1102 | |
| 1103 | ### Unresolved questions: | |
| 1103 | ### Unresolved questions | |
| 1104 | 1104 | |
| 1105 | - How should enums/unions be represented? currently they do not produce any children because they have multiple distinct sets of children. | |
| 1106 | - Should niches be represented? currently they are not reported. | |
| 1107 | - A visual representation of the memory layout is not specified, see the provided implementation for an example, however it may not translate well to terminal based editors or other such things. | |
| 1105 | * How should enums/unions be represented? currently they do not produce any children because they have multiple distinct sets of children. | |
| 1106 | * Should niches be represented? currently they are not reported. | |
| 1107 | * A visual representation of the memory layout is not specified, see the provided implementation for an example, however it may not translate well to terminal based editors or other such things. |
src/tools/rust-analyzer/docs/book/src/other_editors.md+1-1| ... | ... | @@ -146,7 +146,7 @@ still recommended to get the |
| 146 | 146 | for free. |
| 147 | 147 | |
| 148 | 148 | 1. Install [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) |
| 149 | 2. Add `lua vim.lsp.enable('rust-analyzer')` to your `init.vim` | |
| 149 | 2. Add `lua vim.lsp.enable('rust_analyzer')` to your `init.vim` | |
| 150 | 150 | 3. Customize your setup. |
| 151 | 151 | |
| 152 | 152 | ```lua |
src/tools/rust-analyzer/editors/code/.vscodeignore+1-1| ... | ... | @@ -12,4 +12,4 @@ |
| 12 | 12 | !ra_syntax_tree.tmGrammar.json |
| 13 | 13 | !server |
| 14 | 14 | !README.md |
| 15 | !walkthrough-setup-tips.md | |
| 15 | !walkthrough-* |
src/tools/rust-analyzer/editors/code/package.json+15-1| ... | ... | @@ -971,6 +971,19 @@ |
| 971 | 971 | } |
| 972 | 972 | } |
| 973 | 973 | }, |
| 974 | { | |
| 975 | "title": "Cargo", | |
| 976 | "properties": { | |
| 977 | "rust-analyzer.cargo.configPath": { | |
| 978 | "markdownDescription": "Path to a `.cargo/config.toml` style file to pass to cargo via `--config`\nfor every cargo invocation (metadata, build scripts, config discovery).\nUseful to give rust-analyzer a consistent view of the project configuration.", | |
| 979 | "default": null, | |
| 980 | "type": [ | |
| 981 | "null", | |
| 982 | "string" | |
| 983 | ] | |
| 984 | } | |
| 985 | } | |
| 986 | }, | |
| 974 | 987 | { |
| 975 | 988 | "title": "Cargo", |
| 976 | 989 | "properties": { |
| ... | ... | @@ -1389,7 +1402,8 @@ |
| 1389 | 1402 | "enumDescriptions": [ |
| 1390 | 1403 | "Do not show this item or its methods (if it is a trait) in auto-import completions.", |
| 1391 | 1404 | "Do not show this trait's methods in auto-import completions.", |
| 1392 | "Do not show this module's all items in it in auto-import completions." | |
| 1405 | "Do not show this module's all items in it in auto-import completions.", | |
| 1406 | "Do not show this enum's variants in auto-import completions." | |
| 1393 | 1407 | ] |
| 1394 | 1408 | } |
| 1395 | 1409 | } |
src/tools/rust-analyzer/lib/lsp-server/Cargo.toml+4-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | [package] |
| 2 | 2 | name = "lsp-server" |
| 3 | version = "0.7.9" | |
| 3 | version = "0.8.0" | |
| 4 | 4 | description = "Generic LSP server scaffold." |
| 5 | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server" |
| ... | ... | @@ -14,7 +14,9 @@ serde_derive = { version = "1.0.219" } |
| 14 | 14 | crossbeam-channel.workspace = true |
| 15 | 15 | |
| 16 | 16 | [dev-dependencies] |
| 17 | lsp-types = "=0.95" | |
| 17 | lsp-types = { version = "0.4.0", package = "gen-lsp-types", features = [ | |
| 18 | "url", | |
| 19 | ] } | |
| 18 | 20 | ctrlc = "3.4.7" |
| 19 | 21 | anyhow.workspace = true |
| 20 | 22 | rustc-hash.workspace = true |
src/tools/rust-analyzer/lib/lsp-server/examples/minimal_lsp.rs+49-56| ... | ... | @@ -67,6 +67,15 @@ |
| 67 | 67 | |
| 68 | 68 | use std::{error::Error, io::Write}; |
| 69 | 69 | |
| 70 | use lsp_types::{ | |
| 71 | CompletionItem, CompletionItemKind, CompletionOptions, CompletionRequest, CompletionResponse, | |
| 72 | Contents, DefinitionRequest, Diagnostic, DiagnosticSeverity, DidChangeTextDocumentNotification, | |
| 73 | DidChangeTextDocumentParams, DidOpenTextDocumentNotification, DidOpenTextDocumentParams, | |
| 74 | DocumentFormattingParams, DocumentFormattingRequest, Hover, HoverProvider, HoverRequest, | |
| 75 | InitializeParams, LspNotificationMethod, LspRequestMethod, MarkedString, Notification, | |
| 76 | Position, PublishDiagnosticsNotification, PublishDiagnosticsParams, Range, Request, | |
| 77 | ServerCapabilities, TextDocumentSync, TextEdit, Uri, | |
| 78 | }; | |
| 70 | 79 | use rustc_hash::FxHashMap; // fast hash map |
| 71 | 80 | use std::process::Stdio; |
| 72 | 81 | use toolchain::command; // clippy-approved wrapper |
| ... | ... | @@ -74,39 +83,6 @@ use toolchain::command; // clippy-approved wrapper |
| 74 | 83 | #[allow(clippy::print_stderr, clippy::disallowed_types, clippy::disallowed_methods)] |
| 75 | 84 | use anyhow::{Context, Result, anyhow, bail}; |
| 76 | 85 | use lsp_server::{Connection, Message, Request as ServerRequest, RequestId, Response}; |
| 77 | use lsp_types::notification::Notification as _; // for METHOD consts | |
| 78 | use lsp_types::request::Request as _; | |
| 79 | use lsp_types::{ | |
| 80 | CompletionItem, | |
| 81 | CompletionItemKind, | |
| 82 | // capability helpers | |
| 83 | CompletionOptions, | |
| 84 | CompletionResponse, | |
| 85 | Diagnostic, | |
| 86 | DiagnosticSeverity, | |
| 87 | DidChangeTextDocumentParams, | |
| 88 | DidOpenTextDocumentParams, | |
| 89 | DocumentFormattingParams, | |
| 90 | Hover, | |
| 91 | HoverContents, | |
| 92 | HoverProviderCapability, | |
| 93 | // core | |
| 94 | InitializeParams, | |
| 95 | MarkedString, | |
| 96 | OneOf, | |
| 97 | Position, | |
| 98 | PublishDiagnosticsParams, | |
| 99 | Range, | |
| 100 | ServerCapabilities, | |
| 101 | TextDocumentSyncCapability, | |
| 102 | TextDocumentSyncKind, | |
| 103 | TextEdit, | |
| 104 | Url, | |
| 105 | // notifications | |
| 106 | notification::{DidChangeTextDocument, DidOpenTextDocument, PublishDiagnostics}, | |
| 107 | // requests | |
| 108 | request::{Completion, Formatting, GotoDefinition, HoverRequest}, | |
| 109 | }; // for METHOD consts | |
| 110 | 86 | |
| 111 | 87 | // ===================================================================== |
| 112 | 88 | // main |
| ... | ... | @@ -121,11 +97,11 @@ fn main() -> std::result::Result<(), Box<dyn Error + Sync + Send>> { |
| 121 | 97 | |
| 122 | 98 | // advertised capabilities |
| 123 | 99 | let caps = ServerCapabilities { |
| 124 | text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)), | |
| 100 | text_document_sync: Some(TextDocumentSync::Kind(lsp_types::TextDocumentSyncKind::Full)), | |
| 125 | 101 | completion_provider: Some(CompletionOptions::default()), |
| 126 | definition_provider: Some(OneOf::Left(true)), | |
| 127 | hover_provider: Some(HoverProviderCapability::Simple(true)), | |
| 128 | document_formatting_provider: Some(OneOf::Left(true)), | |
| 102 | definition_provider: Some(lsp_types::DefinitionProvider::Bool(true)), | |
| 103 | hover_provider: Some(HoverProvider::Bool(true)), | |
| 104 | document_formatting_provider: Some(lsp_types::DocumentFormattingProvider::Bool(true)), | |
| 129 | 105 | ..Default::default() |
| 130 | 106 | }; |
| 131 | 107 | let init_value = serde_json::json!({ |
| ... | ... | @@ -149,7 +125,7 @@ fn main_loop( |
| 149 | 125 | params: serde_json::Value, |
| 150 | 126 | ) -> std::result::Result<(), Box<dyn Error + Sync + Send>> { |
| 151 | 127 | let _init: InitializeParams = serde_json::from_value(params)?; |
| 152 | let mut docs: FxHashMap<Url, String> = FxHashMap::default(); | |
| 128 | let mut docs: FxHashMap<Uri, String> = FxHashMap::default(); | |
| 153 | 129 | |
| 154 | 130 | for msg in &connection.receiver { |
| 155 | 131 | match msg { |
| ... | ... | @@ -179,20 +155,25 @@ fn main_loop( |
| 179 | 155 | fn handle_notification( |
| 180 | 156 | conn: &Connection, |
| 181 | 157 | note: &lsp_server::Notification, |
| 182 | docs: &mut FxHashMap<Url, String>, | |
| 158 | docs: &mut FxHashMap<Uri, String>, | |
| 183 | 159 | ) -> Result<()> { |
| 184 | match note.method.as_str() { | |
| 185 | DidOpenTextDocument::METHOD => { | |
| 160 | let method: LspNotificationMethod = note.method.clone().into(); | |
| 161 | match method { | |
| 162 | DidOpenTextDocumentNotification::METHOD => { | |
| 186 | 163 | let p: DidOpenTextDocumentParams = serde_json::from_value(note.params.clone())?; |
| 187 | 164 | let uri = p.text_document.uri; |
| 188 | 165 | docs.insert(uri.clone(), p.text_document.text); |
| 189 | 166 | publish_dummy_diag(conn, &uri)?; |
| 190 | 167 | } |
| 191 | DidChangeTextDocument::METHOD => { | |
| 168 | DidChangeTextDocumentNotification::METHOD => { | |
| 192 | 169 | let p: DidChangeTextDocumentParams = serde_json::from_value(note.params.clone())?; |
| 193 | 170 | if let Some(change) = p.content_changes.into_iter().next() { |
| 194 | let uri = p.text_document.uri; | |
| 195 | docs.insert(uri.clone(), change.text); | |
| 171 | let uri = p.text_document.text_document_identifier.uri; | |
| 172 | let text = match change { | |
| 173 | lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangePartial(partial) => partial.text, | |
| 174 | lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument(whole) => whole.text, | |
| 175 | }; | |
| 176 | docs.insert(uri.clone(), text); | |
| 196 | 177 | publish_dummy_diag(conn, &uri)?; |
| 197 | 178 | } |
| 198 | 179 | } |
| ... | ... | @@ -208,31 +189,43 @@ fn handle_notification( |
| 208 | 189 | fn handle_request( |
| 209 | 190 | conn: &Connection, |
| 210 | 191 | req: &ServerRequest, |
| 211 | docs: &mut FxHashMap<Url, String>, | |
| 192 | docs: &mut FxHashMap<Uri, String>, | |
| 212 | 193 | ) -> Result<()> { |
| 213 | match req.method.as_str() { | |
| 214 | GotoDefinition::METHOD => { | |
| 215 | send_ok(conn, req.id.clone(), &lsp_types::GotoDefinitionResponse::Array(Vec::new()))?; | |
| 194 | let parsed: LspRequestMethod = req.method.clone().into(); | |
| 195 | match parsed { | |
| 196 | DefinitionRequest::METHOD => { | |
| 197 | send_ok( | |
| 198 | conn, | |
| 199 | req.id.clone(), | |
| 200 | &lsp_types::DefinitionResponse::DefinitionLinkList(Vec::new()), | |
| 201 | )?; | |
| 216 | 202 | } |
| 217 | Completion::METHOD => { | |
| 203 | CompletionRequest::METHOD => { | |
| 218 | 204 | let item = CompletionItem { |
| 219 | 205 | label: "HelloFromLSP".into(), |
| 220 | kind: Some(CompletionItemKind::FUNCTION), | |
| 206 | kind: Some(CompletionItemKind::Function), | |
| 221 | 207 | detail: Some("dummy completion".into()), |
| 222 | 208 | ..Default::default() |
| 223 | 209 | }; |
| 224 | send_ok(conn, req.id.clone(), &CompletionResponse::Array(vec![item]))?; | |
| 210 | let items = vec![item]; | |
| 211 | let completion_list = CompletionResponse::CompletionList(lsp_types::CompletionList { | |
| 212 | is_incomplete: false, | |
| 213 | item_defaults: None, | |
| 214 | apply_kind: None, | |
| 215 | items, | |
| 216 | }); | |
| 217 | send_ok(conn, req.id.clone(), &completion_list)?; | |
| 225 | 218 | } |
| 226 | 219 | HoverRequest::METHOD => { |
| 227 | 220 | let hover = Hover { |
| 228 | contents: HoverContents::Scalar(MarkedString::String( | |
| 221 | contents: Contents::MarkedString(MarkedString::String( | |
| 229 | 222 | "Hello from *minimal_lsp*".into(), |
| 230 | 223 | )), |
| 231 | 224 | range: None, |
| 232 | 225 | }; |
| 233 | 226 | send_ok(conn, req.id.clone(), &hover)?; |
| 234 | 227 | } |
| 235 | Formatting::METHOD => { | |
| 228 | DocumentFormattingRequest::METHOD => { | |
| 236 | 229 | let p: DocumentFormattingParams = serde_json::from_value(req.params.clone())?; |
| 237 | 230 | let uri = p.text_document.uri; |
| 238 | 231 | let text = docs |
| ... | ... | @@ -255,10 +248,10 @@ fn handle_request( |
| 255 | 248 | // ===================================================================== |
| 256 | 249 | // diagnostics |
| 257 | 250 | // ===================================================================== |
| 258 | fn publish_dummy_diag(conn: &Connection, uri: &Url) -> Result<()> { | |
| 251 | fn publish_dummy_diag(conn: &Connection, uri: &Uri) -> Result<()> { | |
| 259 | 252 | let diag = Diagnostic { |
| 260 | 253 | range: Range::new(Position::new(0, 0), Position::new(0, 1)), |
| 261 | severity: Some(DiagnosticSeverity::INFORMATION), | |
| 254 | severity: Some(DiagnosticSeverity::Information), | |
| 262 | 255 | code: None, |
| 263 | 256 | code_description: None, |
| 264 | 257 | source: Some("minimal_lsp".into()), |
| ... | ... | @@ -270,7 +263,7 @@ fn publish_dummy_diag(conn: &Connection, uri: &Url) -> Result<()> { |
| 270 | 263 | let params = |
| 271 | 264 | PublishDiagnosticsParams { uri: uri.clone(), diagnostics: vec![diag], version: None }; |
| 272 | 265 | conn.sender.send(Message::Notification(lsp_server::Notification::new( |
| 273 | PublishDiagnostics::METHOD.to_owned(), | |
| 266 | PublishDiagnosticsNotification::METHOD.into(), | |
| 274 | 267 | params, |
| 275 | 268 | )))?; |
| 276 | 269 | Ok(()) |
src/tools/rust-analyzer/lib/lsp-server/src/lib.rs+10-7| ... | ... | @@ -376,9 +376,10 @@ impl Connection { |
| 376 | 376 | #[cfg(test)] |
| 377 | 377 | mod tests { |
| 378 | 378 | use crossbeam_channel::unbounded; |
| 379 | use lsp_types::notification::{Exit, Initialized, Notification}; | |
| 380 | use lsp_types::request::{Initialize, Request}; | |
| 381 | use lsp_types::{InitializeParams, InitializedParams}; | |
| 379 | use lsp_types::{ | |
| 380 | ExitNotification, InitializeParams, InitializeRequest, InitializedNotification, | |
| 381 | InitializedParams, Notification as _, Request as _, | |
| 382 | }; | |
| 382 | 383 | use serde_json::to_value; |
| 383 | 384 | |
| 384 | 385 | use crate::{Connection, Message, ProtocolError, RequestId}; |
| ... | ... | @@ -406,7 +407,7 @@ mod tests { |
| 406 | 407 | #[test] |
| 407 | 408 | fn not_exit_notification() { |
| 408 | 409 | let notification = crate::Notification { |
| 409 | method: Initialized::METHOD.to_owned(), | |
| 410 | method: InitializedNotification::METHOD.to_string(), | |
| 410 | 411 | params: to_value(InitializedParams {}).unwrap(), |
| 411 | 412 | }; |
| 412 | 413 | |
| ... | ... | @@ -414,7 +415,7 @@ mod tests { |
| 414 | 415 | let req_id = RequestId::from(234); |
| 415 | 416 | let request = crate::Request { |
| 416 | 417 | id: req_id.clone(), |
| 417 | method: Initialize::METHOD.to_owned(), | |
| 418 | method: InitializeRequest::METHOD.to_string(), | |
| 418 | 419 | params: params_as_value.clone(), |
| 419 | 420 | }; |
| 420 | 421 | |
| ... | ... | @@ -426,8 +427,10 @@ mod tests { |
| 426 | 427 | |
| 427 | 428 | #[test] |
| 428 | 429 | fn exit_notification() { |
| 429 | let notification = | |
| 430 | crate::Notification { method: Exit::METHOD.to_owned(), params: to_value(()).unwrap() }; | |
| 430 | let notification = crate::Notification { | |
| 431 | method: ExitNotification::METHOD.to_string(), | |
| 432 | params: to_value(()).unwrap(), | |
| 433 | }; | |
| 431 | 434 | let notification_msg = Message::from(notification); |
| 432 | 435 | |
| 433 | 436 | initialize_start_test(TestCase { |
src/tools/rust-analyzer/lib/smol_str/src/lib.rs+10-3| ... | ... | @@ -721,7 +721,8 @@ impl StrExt for str { |
| 721 | 721 | fn to_lowercase_smolstr(&self) -> SmolStr { |
| 722 | 722 | let len = self.len(); |
| 723 | 723 | if len <= INLINE_CAP { |
| 724 | let (buf, rest) = inline_convert_while_ascii(self, u8::to_ascii_lowercase); | |
| 724 | // SAFETY: `to_ascii_lowercase` always converts ASCII to ASCII | |
| 725 | let (buf, rest) = unsafe { inline_convert_while_ascii(self, u8::to_ascii_lowercase) }; | |
| 725 | 726 | from_buf_and_chars(buf, len - rest.len(), rest.chars().flat_map(|c| c.to_lowercase())) |
| 726 | 727 | } else { |
| 727 | 728 | self.to_lowercase().into() |
| ... | ... | @@ -732,7 +733,8 @@ impl StrExt for str { |
| 732 | 733 | fn to_uppercase_smolstr(&self) -> SmolStr { |
| 733 | 734 | let len = self.len(); |
| 734 | 735 | if len <= INLINE_CAP { |
| 735 | let (buf, rest) = inline_convert_while_ascii(self, u8::to_ascii_uppercase); | |
| 736 | // SAFETY: `to_ascii_uppercase` always converts ASCII to ASCII | |
| 737 | let (buf, rest) = unsafe { inline_convert_while_ascii(self, u8::to_ascii_uppercase) }; | |
| 736 | 738 | from_buf_and_chars(buf, len - rest.len(), rest.chars().flat_map(|c| c.to_uppercase())) |
| 737 | 739 | } else { |
| 738 | 740 | self.to_uppercase().into() |
| ... | ... | @@ -848,8 +850,13 @@ unsafe fn replacen_1_ascii(src: &str, mut map: impl FnMut(&u8) -> u8) -> SmolStr |
| 848 | 850 | } |
| 849 | 851 | |
| 850 | 852 | /// Inline version of std fn `convert_while_ascii`. `s` must have len <= 23. |
| 853 | /// | |
| 854 | /// # Safety | |
| 855 | /// | |
| 856 | /// If the input to `convert` is valid ASCII (<= 0x7F), | |
| 857 | /// then the output must be as well. | |
| 851 | 858 | #[inline] |
| 852 | fn inline_convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> ([u8; INLINE_CAP], &str) { | |
| 859 | unsafe fn inline_convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> ([u8; INLINE_CAP], &str) { | |
| 853 | 860 | // Process the input in chunks of 16 bytes to enable auto-vectorization. |
| 854 | 861 | // Previously the chunk size depended on the size of `usize`, |
| 855 | 862 | // but on 32-bit platforms with sse or neon is also the better choice. |
src/tools/rust-analyzer/lib/smol_str/tests/test.rs+4-6| ... | ... | @@ -443,11 +443,10 @@ mod borsh_tests { |
| 443 | 443 | } |
| 444 | 444 | #[test] |
| 445 | 445 | fn borsh_non_utf8_stack() { |
| 446 | let invalid_utf8: Vec<u8> = vec![0xF0, 0x9F, 0x8F]; // Incomplete UTF-8 sequence | |
| 446 | let invalid_utf8: &[u8] = &[0xF0, 0x9F, 0x8F]; // Incomplete UTF-8 sequence | |
| 447 | 447 | |
| 448 | let wrong_utf8 = SmolStr::from(unsafe { String::from_utf8_unchecked(invalid_utf8) }); | |
| 449 | 448 | let mut buffer = Vec::new(); |
| 450 | borsh::BorshSerialize::serialize(&wrong_utf8, &mut buffer).unwrap(); | |
| 449 | borsh::BorshSerialize::serialize(invalid_utf8, &mut buffer).unwrap(); | |
| 451 | 450 | let mut cursor = Cursor::new(buffer); |
| 452 | 451 | let result = SmolStr::deserialize_reader(&mut cursor); |
| 453 | 452 | assert!(result.is_err()); |
| ... | ... | @@ -455,14 +454,13 @@ mod borsh_tests { |
| 455 | 454 | |
| 456 | 455 | #[test] |
| 457 | 456 | fn borsh_non_utf8_heap() { |
| 458 | let invalid_utf8: Vec<u8> = vec![ | |
| 457 | let invalid_utf8: &[u8] = &[ | |
| 459 | 458 | 0xC1, 0x8A, 0x5F, 0xE2, 0x3A, 0x9E, 0x3B, 0xAA, 0x01, 0x08, 0x6F, 0x2F, 0xC0, 0x32, |
| 460 | 459 | 0xAB, 0xE1, 0x9A, 0x2F, 0x4A, 0x3F, 0x25, 0x0D, 0x8A, 0x2A, 0x19, 0x11, 0xF0, 0x7F, |
| 461 | 460 | 0x0E, 0x80, |
| 462 | 461 | ]; |
| 463 | let wrong_utf8 = SmolStr::from(unsafe { String::from_utf8_unchecked(invalid_utf8) }); | |
| 464 | 462 | let mut buffer = Vec::new(); |
| 465 | borsh::BorshSerialize::serialize(&wrong_utf8, &mut buffer).unwrap(); | |
| 463 | borsh::BorshSerialize::serialize(invalid_utf8, &mut buffer).unwrap(); | |
| 466 | 464 | let mut cursor = Cursor::new(buffer); |
| 467 | 465 | let result = SmolStr::deserialize_reader(&mut cursor); |
| 468 | 466 | assert!(result.is_err()); |
src/tools/rust-analyzer/rust-version+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | 942ac9ce4116d4ea784c9882659372b34978b1f8 | |
| 1 | 7fb284d9037fa54f6a9b24261c82b394472cbfd7 |
src/tools/rust-analyzer/xtask/src/tidy.rs+2-2| ... | ... | @@ -205,9 +205,9 @@ fn check_test_attrs(path: &Path, text: &str) { |
| 205 | 205 | } |
| 206 | 206 | if let Some((line, _)) = text |
| 207 | 207 | .lines() |
| 208 | .tuple_windows() | |
| 208 | .array_windows() | |
| 209 | 209 | .enumerate() |
| 210 | .find(|(_, (a, b))| b.contains("#[should_panic") && !a.contains("FIXME")) | |
| 210 | .find(|(_, [a, b])| b.contains("#[should_panic") && !a.contains("FIXME")) | |
| 211 | 211 | { |
| 212 | 212 | panic!( |
| 213 | 213 | "\ndon't add `#[should_panic]` tests, see:\n\n {}\n\n {}:{line}\n", |