authorbors <bors@rust-lang.org> 2026-07-07 08:25:59 UTC
committerbors <bors@rust-lang.org> 2026-07-07 08:25:59 UTC
logf10db292a3733b5c67c8da8c7661195ff4b05774
treefd7846c9f264a9adf3d766d0d07e552ebbdcf10c
parentbcd9ae8b77e8a1d03d73b51f1fd9cb99565cfdc5
parent75e1b3d341a2736043062c7b6be17a2bf9b380f1

Auto merge of #158896 - lnicola:sync-from-ra, r=lnicola

`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? @ghost

155 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
2323If you are using AI to edit your comments for this purpose, please take the time to ensure it reflects your own voice and ideas.
2424If using AI for translation, we recommend writing in your native language and including the AI translation in a quote block.
2525
26**AI should not be used to author code for E-easy+E-has-instructions issues**.
27
28E-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
30AI *may* be used to understand the codebase for E-easy+E-has-instructions contributions, but not to write any code.
31
2632This policy was adapted from [uv's AI policy].
2733
2834[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"
6565source = "registry+https://github.com/rust-lang/crates.io-index"
6666checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
6767
68[[package]]
69name = "atomic-polyfill"
70version = "1.0.3"
71source = "registry+https://github.com/rust-lang/crates.io-index"
72checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
73dependencies = [
74 "critical-section",
75]
76
7768[[package]]
7869name = "autocfg"
7970version = "1.5.1"
......@@ -137,12 +128,6 @@ version = "0.8.0"
137128source = "registry+https://github.com/rust-lang/crates.io-index"
138129checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
139130
140[[package]]
141name = "bitflags"
142version = "1.3.2"
143source = "registry+https://github.com/rust-lang/crates.io-index"
144checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
145
146131[[package]]
147132name = "bitflags"
148133version = "2.12.1"
......@@ -180,12 +165,6 @@ version = "3.20.3"
180165source = "registry+https://github.com/rust-lang/crates.io-index"
181166checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
182167
183[[package]]
184name = "byteorder"
185version = "1.5.0"
186source = "registry+https://github.com/rust-lang/crates.io-index"
187checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
188
189168[[package]]
190169name = "bytes"
191170version = "1.11.1"
......@@ -384,12 +363,6 @@ dependencies = [
384363 "itertools 0.13.0",
385364]
386365
387[[package]]
388name = "critical-section"
389version = "1.2.0"
390source = "registry+https://github.com/rust-lang/crates.io-index"
391checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
392
393366[[package]]
394367name = "crossbeam-channel"
395368version = "0.5.15"
......@@ -538,7 +511,7 @@ version = "0.3.1"
538511source = "registry+https://github.com/rust-lang/crates.io-index"
539512checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
540513dependencies = [
541 "bitflags 2.12.1",
514 "bitflags",
542515 "block2",
543516 "libc",
544517 "objc2",
......@@ -724,6 +697,17 @@ dependencies = [
724697 "slab",
725698]
726699
700[[package]]
701name = "gen-lsp-types"
702version = "0.4.0"
703source = "registry+https://github.com/rust-lang/crates.io-index"
704checksum = "c5b8ec601e62362b666a3def1fed667ee87b10a4507402618376d142a05373c6"
705dependencies = [
706 "serde",
707 "serde_json",
708 "url",
709]
710
727711[[package]]
728712name = "getrandom"
729713version = "0.2.17"
......@@ -777,15 +761,6 @@ dependencies = [
777761 "zerocopy",
778762]
779763
780[[package]]
781name = "hash32"
782version = "0.2.1"
783source = "registry+https://github.com/rust-lang/crates.io-index"
784checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
785dependencies = [
786 "byteorder",
787]
788
789764[[package]]
790765name = "hashbrown"
791766version = "0.14.5"
......@@ -801,15 +776,6 @@ dependencies = [
801776 "foldhash 0.1.5",
802777]
803778
804[[package]]
805name = "hashbrown"
806version = "0.16.1"
807source = "registry+https://github.com/rust-lang/crates.io-index"
808checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
809dependencies = [
810 "foldhash 0.2.0",
811]
812
813779[[package]]
814780name = "hashbrown"
815781version = "0.17.1"
......@@ -823,25 +789,11 @@ dependencies = [
823789
824790[[package]]
825791name = "hashlink"
826version = "0.11.0"
792version = "0.12.0"
827793source = "registry+https://github.com/rust-lang/crates.io-index"
828checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230"
794checksum = "a5081f264ed7adee96ea4b4778b6bb9da0a7228b084587aa3bd3ff05da7c5a3b"
829795dependencies = [
830 "hashbrown 0.16.1",
831]
832
833[[package]]
834name = "heapless"
835version = "0.7.17"
836source = "registry+https://github.com/rust-lang/crates.io-index"
837checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
838dependencies = [
839 "atomic-polyfill",
840 "hash32",
841 "rustc_version",
842 "serde",
843 "spin",
844 "stable_deref_trait",
796 "hashbrown 0.17.1",
845797]
846798
847799[[package]]
......@@ -869,7 +821,7 @@ dependencies = [
869821 "hir-expand",
870822 "hir-ty",
871823 "intern",
872 "itertools 0.14.0",
824 "itertools 0.15.0",
873825 "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
874826 "ra-ap-rustc_type_ir",
875827 "rustc-hash 2.1.2",
......@@ -894,7 +846,7 @@ version = "0.0.0"
894846dependencies = [
895847 "arrayvec",
896848 "base-db",
897 "bitflags 2.12.1",
849 "bitflags",
898850 "cfg",
899851 "cov-mark",
900852 "drop_bomb",
......@@ -904,7 +856,7 @@ dependencies = [
904856 "hir-expand",
905857 "indexmap",
906858 "intern",
907 "itertools 0.14.0",
859 "itertools 0.15.0",
908860 "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
909861 "query-group-macro",
910862 "ra-ap-rustc_abi",
......@@ -936,7 +888,7 @@ dependencies = [
936888 "either",
937889 "expect-test",
938890 "intern",
939 "itertools 0.14.0",
891 "itertools 0.15.0",
940892 "mbe",
941893 "parser",
942894 "query-group-macro",
......@@ -960,7 +912,7 @@ version = "0.0.0"
960912dependencies = [
961913 "arrayvec",
962914 "base-db",
963 "bitflags 2.12.1",
915 "bitflags",
964916 "cov-mark",
965917 "either",
966918 "ena",
......@@ -969,7 +921,7 @@ dependencies = [
969921 "hir-expand",
970922 "indexmap",
971923 "intern",
972 "itertools 0.14.0",
924 "itertools 0.15.0",
973925 "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
974926 "macros",
975927 "oorandom",
......@@ -1106,7 +1058,7 @@ dependencies = [
11061058 "ide-db",
11071059 "ide-diagnostics",
11081060 "ide-ssr",
1109 "itertools 0.14.0",
1061 "itertools 0.15.0",
11101062 "macros",
11111063 "nohash-hasher",
11121064 "oorandom",
......@@ -1135,7 +1087,7 @@ dependencies = [
11351087 "expect-test",
11361088 "hir",
11371089 "ide-db",
1138 "itertools 0.14.0",
1090 "itertools 0.15.0",
11391091 "smallvec",
11401092 "stdx",
11411093 "syntax",
......@@ -1153,7 +1105,7 @@ dependencies = [
11531105 "expect-test",
11541106 "hir",
11551107 "ide-db",
1156 "itertools 0.14.0",
1108 "itertools 0.15.0",
11571109 "macros",
11581110 "smallvec",
11591111 "stdx",
......@@ -1169,14 +1121,14 @@ version = "0.0.0"
11691121dependencies = [
11701122 "arrayvec",
11711123 "base-db",
1172 "bitflags 2.12.1",
1124 "bitflags",
11731125 "cov-mark",
11741126 "crossbeam-channel",
11751127 "either",
11761128 "expect-test",
11771129 "fst",
11781130 "hir",
1179 "itertools 0.14.0",
1131 "itertools 0.15.0",
11801132 "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
11811133 "macros",
11821134 "memchr",
......@@ -1208,7 +1160,7 @@ dependencies = [
12081160 "expect-test",
12091161 "hir",
12101162 "ide-db",
1211 "itertools 0.14.0",
1163 "itertools 0.15.0",
12121164 "paths",
12131165 "serde_json",
12141166 "stdx",
......@@ -1226,7 +1178,7 @@ dependencies = [
12261178 "expect-test",
12271179 "hir",
12281180 "ide-db",
1229 "itertools 0.14.0",
1181 "itertools 0.15.0",
12301182 "parser",
12311183 "syntax",
12321184 "test-fixture",
......@@ -1273,7 +1225,7 @@ version = "0.11.2"
12731225source = "registry+https://github.com/rust-lang/crates.io-index"
12741226checksum = "533e68a5842e734946fe159fb03fc9bbbb254f590dd0d8ad321ae5ff7beca2c1"
12751227dependencies = [
1276 "bitflags 2.12.1",
1228 "bitflags",
12771229 "inotify-sys",
12781230 "libc",
12791231]
......@@ -1328,9 +1280,9 @@ dependencies = [
13281280
13291281[[package]]
13301282name = "itertools"
1331version = "0.14.0"
1283version = "0.15.0"
13321284source = "registry+https://github.com/rust-lang/crates.io-index"
1333checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
1285checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc"
13341286dependencies = [
13351287 "either",
13361288]
......@@ -1375,7 +1327,7 @@ version = "1.1.2"
13751327source = "registry+https://github.com/rust-lang/crates.io-index"
13761328checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
13771329dependencies = [
1378 "bitflags 2.12.1",
1330 "bitflags",
13791331 "libc",
13801332]
13811333
......@@ -1465,7 +1417,7 @@ dependencies = [
14651417 "hir-expand",
14661418 "ide-db",
14671419 "intern",
1468 "itertools 0.14.0",
1420 "itertools 0.15.0",
14691421 "proc-macro-api",
14701422 "project-model",
14711423 "span",
......@@ -1493,43 +1445,30 @@ checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f"
14931445[[package]]
14941446name = "lsp-server"
14951447version = "0.7.9"
1448source = "registry+https://github.com/rust-lang/crates.io-index"
1449checksum = "7d6ada348dbc2703cbe7637b2dda05cff84d3da2819c24abcb305dd613e0ba2e"
14961450dependencies = [
1497 "anyhow",
14981451 "crossbeam-channel",
1499 "ctrlc",
15001452 "log",
1501 "lsp-types",
1502 "rustc-hash 2.1.2",
15031453 "serde",
15041454 "serde_derive",
15051455 "serde_json",
1506 "toolchain",
15071456]
15081457
15091458[[package]]
15101459name = "lsp-server"
1511version = "0.7.9"
1512source = "registry+https://github.com/rust-lang/crates.io-index"
1513checksum = "7d6ada348dbc2703cbe7637b2dda05cff84d3da2819c24abcb305dd613e0ba2e"
1460version = "0.8.0"
15141461dependencies = [
1462 "anyhow",
15151463 "crossbeam-channel",
1464 "ctrlc",
1465 "gen-lsp-types",
15161466 "log",
1467 "rustc-hash 2.1.2",
15171468 "serde",
15181469 "serde_derive",
15191470 "serde_json",
1520]
1521
1522[[package]]
1523name = "lsp-types"
1524version = "0.95.0"
1525source = "registry+https://github.com/rust-lang/crates.io-index"
1526checksum = "158c1911354ef73e8fe42da6b10c0484cb65c7f1007f28022e847706c1ab6984"
1527dependencies = [
1528 "bitflags 1.3.2",
1529 "serde",
1530 "serde_json",
1531 "serde_repr",
1532 "url",
1471 "toolchain",
15331472]
15341473
15351474[[package]]
......@@ -1547,7 +1486,7 @@ name = "mbe"
15471486version = "0.0.0"
15481487dependencies = [
15491488 "arrayvec",
1550 "bitflags 2.12.1",
1489 "bitflags",
15511490 "cov-mark",
15521491 "expect-test",
15531492 "intern",
......@@ -1631,7 +1570,7 @@ version = "0.31.3"
16311570source = "registry+https://github.com/rust-lang/crates.io-index"
16321571checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
16331572dependencies = [
1634 "bitflags 2.12.1",
1573 "bitflags",
16351574 "cfg-if",
16361575 "cfg_aliases",
16371576 "libc",
......@@ -1649,7 +1588,7 @@ version = "8.2.0"
16491588source = "registry+https://github.com/rust-lang/crates.io-index"
16501589checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
16511590dependencies = [
1652 "bitflags 2.12.1",
1591 "bitflags",
16531592 "fsevent-sys",
16541593 "inotify",
16551594 "kqueue",
......@@ -1667,7 +1606,7 @@ version = "2.1.0"
16671606source = "registry+https://github.com/rust-lang/crates.io-index"
16681607checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
16691608dependencies = [
1670 "bitflags 2.12.1",
1609 "bitflags",
16711610]
16721611
16731612[[package]]
......@@ -1890,7 +1829,6 @@ dependencies = [
18901829 "cobs",
18911830 "embedded-io 0.4.0",
18921831 "embedded-io 0.6.1",
1893 "heapless",
18941832 "serde",
18951833]
18961834
......@@ -2025,7 +1963,7 @@ dependencies = [
20251963 "cfg",
20261964 "expect-test",
20271965 "intern",
2028 "itertools 0.14.0",
1966 "itertools 0.15.0",
20291967 "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
20301968 "paths",
20311969 "rustc-hash 2.1.2",
......@@ -2050,7 +1988,7 @@ checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744"
20501988dependencies = [
20511989 "bit-set",
20521990 "bit-vec",
2053 "bitflags 2.12.1",
1991 "bitflags",
20541992 "num-traits",
20551993 "rand",
20561994 "rand_chacha",
......@@ -2087,7 +2025,7 @@ version = "0.9.6"
20872025source = "registry+https://github.com/rust-lang/crates.io-index"
20882026checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
20892027dependencies = [
2090 "bitflags 2.12.1",
2028 "bitflags",
20912029 "memchr",
20922030 "unicase",
20932031]
......@@ -2146,7 +2084,7 @@ version = "0.165.0"
21462084source = "registry+https://github.com/rust-lang/crates.io-index"
21472085checksum = "2f25a779e21ca3bba6795193b16508c8ab159f96ee4b07349893fd272065b525"
21482086dependencies = [
2149 "bitflags 2.12.1",
2087 "bitflags",
21502088 "ra-ap-rustc_hashes",
21512089 "ra-ap-rustc_index",
21522090 "tracing",
......@@ -2241,7 +2179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
22412179checksum = "8c5d9a4d3e7bee7313599bc6d794037247ac0165f03857379cf4fc3097199e05"
22422180dependencies = [
22432181 "arrayvec",
2244 "bitflags 2.12.1",
2182 "bitflags",
22452183 "derive-where",
22462184 "ena",
22472185 "indexmap",
......@@ -2331,7 +2269,7 @@ version = "0.5.18"
23312269source = "registry+https://github.com/rust-lang/crates.io-index"
23322270checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
23332271dependencies = [
2334 "bitflags 2.12.1",
2272 "bitflags",
23352273]
23362274
23372275[[package]]
......@@ -2376,9 +2314,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
23762314
23772315[[package]]
23782316name = "rowan"
2379version = "0.15.18"
2317version = "0.15.19"
23802318source = "registry+https://github.com/rust-lang/crates.io-index"
2381checksum = "62f509095fc8cc0c8c8564016771d458079c11a8d857e65861f045145c0d3208"
2319checksum = "a2441aaccb50f4267d4f0f58b21e0138e96a449f361ed57a2673a83c9bca0772"
23822320dependencies = [
23832321 "countme",
23842322 "hashbrown 0.14.5",
......@@ -2400,6 +2338,7 @@ dependencies = [
24002338 "dirs",
24012339 "dissimilar",
24022340 "expect-test",
2341 "gen-lsp-types",
24032342 "hir",
24042343 "hir-def",
24052344 "hir-ty",
......@@ -2409,10 +2348,9 @@ dependencies = [
24092348 "ide-ssr",
24102349 "indexmap",
24112350 "intern",
2412 "itertools 0.14.0",
2351 "itertools 0.15.0",
24132352 "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",
24162354 "memchr",
24172355 "mimalloc",
24182356 "num_cpus",
......@@ -2490,26 +2428,17 @@ version = "0.2.3+llvm-462a31f5a5ab"
24902428source = "registry+https://github.com/rust-lang/crates.io-index"
24912429checksum = "486c2179b4796f65bfe2ee33679acf0927ac83ecf583ad6c91c3b4570911b9ad"
24922430dependencies = [
2493 "bitflags 2.12.1",
2431 "bitflags",
24942432 "smallvec",
24952433]
24962434
2497[[package]]
2498name = "rustc_version"
2499version = "0.4.1"
2500source = "registry+https://github.com/rust-lang/crates.io-index"
2501checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
2502dependencies = [
2503 "semver",
2504]
2505
25062435[[package]]
25072436name = "rustix"
25082437version = "1.1.4"
25092438source = "registry+https://github.com/rust-lang/crates.io-index"
25102439checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
25112440dependencies = [
2512 "bitflags 2.12.1",
2441 "bitflags",
25132442 "errno",
25142443 "libc",
25152444 "linux-raw-sys",
......@@ -2536,9 +2465,9 @@ dependencies = [
25362465
25372466[[package]]
25382467name = "salsa"
2539version = "0.27.0"
2468version = "0.27.2"
25402469source = "registry+https://github.com/rust-lang/crates.io-index"
2541checksum = "adfc1e32b8d1a486e3a45a5480fb5dca7912f49262a8916a67378064da4fe1ab"
2470checksum = "ffbaab832e2ea754afda4a738f987dd1e8bd30c9e5d8c981ee6a3934386095e2"
25422471dependencies = [
25432472 "boxcar",
25442473 "crossbeam-queue",
......@@ -2562,15 +2491,15 @@ dependencies = [
25622491
25632492[[package]]
25642493name = "salsa-macro-rules"
2565version = "0.27.0"
2494version = "0.27.2"
25662495source = "registry+https://github.com/rust-lang/crates.io-index"
2567checksum = "67dad477a3e3a484a7c2311c1d25160fb270214981be24022de7de8a206a3300"
2496checksum = "de6872462ac73d39969a836273c24163e6a26a4e08f5114fcd80e25af30ea9c6"
25682497
25692498[[package]]
25702499name = "salsa-macros"
2571version = "0.27.0"
2500version = "0.27.2"
25722501source = "registry+https://github.com/rust-lang/crates.io-index"
2573checksum = "943f70e101fb3bd599960e79e719e70d85142730e5b45f3269246086ed218562"
2502checksum = "76bc78ffaf65b1a9175818592c5130aa10b1bb245a905722fd4db87cea8a8457"
25742503dependencies = [
25752504 "proc-macro2",
25762505 "quote",
......@@ -2644,9 +2573,9 @@ dependencies = [
26442573
26452574[[package]]
26462575name = "serde_json"
2647version = "1.0.150"
2576version = "1.0.149"
26482577source = "registry+https://github.com/rust-lang/crates.io-index"
2649checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
2578checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
26502579dependencies = [
26512580 "indexmap",
26522581 "itoa",
......@@ -2656,17 +2585,6 @@ dependencies = [
26562585 "zmij",
26572586]
26582587
2659[[package]]
2660name = "serde_repr"
2661version = "0.1.20"
2662source = "registry+https://github.com/rust-lang/crates.io-index"
2663checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
2664dependencies = [
2665 "proc-macro2",
2666 "quote",
2667 "syn",
2668]
2669
26702588[[package]]
26712589name = "serde_spanned"
26722590version = "1.1.1"
......@@ -2756,15 +2674,6 @@ dependencies = [
27562674 "vfs",
27572675]
27582676
2759[[package]]
2760name = "spin"
2761version = "0.9.8"
2762source = "registry+https://github.com/rust-lang/crates.io-index"
2763checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
2764dependencies = [
2765 "lock_api",
2766]
2767
27682677[[package]]
27692678name = "stable_deref_trait"
27702679version = "1.2.1"
......@@ -2784,7 +2693,7 @@ dependencies = [
27842693 "backtrace",
27852694 "crossbeam-channel",
27862695 "crossbeam-utils",
2787 "itertools 0.14.0",
2696 "itertools 0.15.0",
27882697 "jod-thread",
27892698 "libc",
27902699 "miow",
......@@ -2820,7 +2729,7 @@ version = "0.0.0"
28202729dependencies = [
28212730 "either",
28222731 "expect-test",
2823 "itertools 0.14.0",
2732 "itertools 0.15.0",
28242733 "parser",
28252734 "rayon",
28262735 "rowan",
......@@ -3427,7 +3336,7 @@ version = "0.244.0"
34273336source = "registry+https://github.com/rust-lang/crates.io-index"
34283337checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
34293338dependencies = [
3430 "bitflags 2.12.1",
3339 "bitflags",
34313340 "hashbrown 0.15.5",
34323341 "indexmap",
34333342 "semver",
......@@ -3721,7 +3630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
37213630checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
37223631dependencies = [
37233632 "anyhow",
3724 "bitflags 2.12.1",
3633 "bitflags",
37253634 "indexmap",
37263635 "log",
37273636 "serde",
......@@ -3801,7 +3710,7 @@ dependencies = [
38013710 "edition",
38023711 "either",
38033712 "flate2",
3804 "itertools 0.14.0",
3713 "itertools 0.15.0",
38053714 "proc-macro2",
38063715 "quote",
38073716 "stdx",
src/tools/rust-analyzer/Cargo.toml+3-3
......@@ -114,16 +114,16 @@ dot = "0.1.4"
114114either = "1.15.0"
115115expect-test = "1.5.1"
116116indexmap = { version = "2.9.0", features = ["serde"] }
117itertools = "0.14.0"
117itertools = "0.15.0"
118118libc = "0.2.172"
119119nohash-hasher = "0.2.0"
120120oorandom = "11.1.5"
121postcard = { version = "1.1.3", features = ["alloc"] }
121postcard = { version = "1.1.3", default-features = false, features = ["alloc"] }
122122process-wrap = { version = "9.1.0", features = ["std"] }
123123pulldown-cmark-to-cmark = "10.0.4"
124124pulldown-cmark = { version = "0.9.6", default-features = false }
125125rayon = "1.10.0"
126rowan = "=0.15.18"
126rowan = "=0.15.19"
127127# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
128128# on impls without it
129129salsa = { 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::{
44 EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind,
55 db::ExpandDatabase,
66};
7use salsa::{Durability, Setter};
78use triomphe::Arc;
89
910use crate::{
......@@ -16,10 +17,6 @@ use crate::{
1617
1718#[query_group::query_group]
1819pub 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
2320 /// Computes an [`ItemTree`] for the given file or macro expansion.
2421 #[salsa::invoke(file_item_tree)]
2522 #[salsa::transparent]
......@@ -47,6 +44,26 @@ pub trait DefDatabase: ExpandDatabase + SourceDatabase {
4744 fn include_macro_invoc(&self, crate_id: Crate) -> Arc<[(MacroCallId, EditionedFileId)]>;
4845}
4946
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)]
52pub(crate) struct ExpandProcAttrMacros {
53 #[returns(copy)]
54 pub(crate) enabled: bool,
55}
56
57pub 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
5067// return: macro call id and include file id
5168fn include_macro_invoc(
5269 db: &dyn DefDatabase,
src/tools/rust-analyzer/crates/hir-def/src/expr_store/body.rs+26-16
......@@ -2,7 +2,6 @@
22//! consts.
33use std::ops;
44
5use arrayvec::ArrayVec;
65use hir_expand::{InFile, Lookup};
76use span::Edition;
87use syntax::ast;
......@@ -18,6 +17,24 @@ use crate::{
1817 src::HasSource,
1918};
2019
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub 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
32impl<Id: Copy> Param<Id> {
33 pub(crate) fn new(id: Id) -> Self {
34 Self { formal: id, user_written: id }
35 }
36}
37
2138/// The body of an item (function, const etc.).
2239#[derive(Debug, Eq, PartialEq)]
2340pub struct Body {
......@@ -28,13 +45,8 @@ pub struct Body {
2845 ///
2946 /// If this `Body` is for the body of a constant, this will just be
3047 /// 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>>,
3850}
3951
4052impl ops::Deref for Body {
......@@ -128,14 +140,12 @@ impl Body {
128140 self.store.expr_roots().next_back().unwrap()
129141 }
130142
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 })
139149 }
140150
141151 pub fn pretty_print(
src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs+113-101
......@@ -8,7 +8,6 @@ mod path;
88
99use std::{cell::OnceCell, mem};
1010
11use arrayvec::ArrayVec;
1211use base_db::FxIndexSet;
1312use cfg::CfgOptions;
1413use either::Either;
......@@ -19,6 +18,7 @@ use hir_expand::{
1918 span_map::SpanMap,
2019};
2120use intern::{Symbol, sym};
21use itertools::Itertools;
2222use rustc_abi::ExternAbi;
2323use rustc_hash::FxHashMap;
2424use smallvec::SmallVec;
......@@ -43,6 +43,7 @@ use crate::{
4343 Body, BodySourceMap, ExprPtr, ExprRoot, ExpressionStore, ExpressionStoreBuilder,
4444 ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, LifetimePtr,
4545 PatPtr, TypePtr,
46 body::Param,
4647 expander::Expander,
4748 lower::generics::ImplTraitLowerFn,
4849 path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path},
......@@ -82,7 +83,7 @@ pub(super) fn lower_body(
8283 // even though they should be the same. Also, when the body comes from multiple expansions, their
8384 // hygiene is different.
8485
85 let mut self_params = ArrayVec::new();
86 let mut self_param = None;
8687 let mut source_map_self_param = None;
8788 let mut params = vec![];
8889 let mut collector = ExprCollector::new(db, module, current_file_id);
......@@ -100,9 +101,43 @@ pub(super) fn lower_body(
100101 // If #[rust_analyzer::skip] annotated, only construct enough information for the signature
101102 // and skip the body.
102103 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| {
103138 if let Some(param_list) = parameters {
104139 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))
106141 {
107142 let is_mutable =
108143 self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
......@@ -115,59 +150,31 @@ pub(super) fn lower_body(
115150 BindingAnnotation::new(is_mutable, false),
116151 hygiene,
117152 );
118 self_params.push(binding_id);
153 self_param = Some(Param::new(binding_id));
119154 source_map_self_param =
120155 Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
121156 }
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 }
132157
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(_)),
145162 );
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 );
155163
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 }
164173 }
165 }
166 };
174 };
167175
168 collector.with_expr_root(|collector| {
169176 collector.collect(
170 &mut self_params,
177 &mut self_param,
171178 &mut params,
172179 body,
173180 if is_async_fn {
......@@ -187,7 +194,7 @@ pub(super) fn lower_body(
187194
188195 let (store, source_map) = collector.store.finish();
189196 (
190 Body { store, params: params.into_boxed_slice(), self_params },
197 Body { store, params: params.into_boxed_slice(), self_param },
191198 BodySourceMap { self_param: source_map_self_param, store: source_map },
192199 )
193200}
......@@ -952,8 +959,8 @@ impl<'db> ExprCollector<'db> {
952959 /// drop order are stable.
953960 fn lower_coroutine_body_with_moved_arguments(
954961 &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>],
957964 body: ExprId,
958965 kind: CoroutineKind,
959966 coroutine_source: CoroutineSource,
......@@ -984,10 +991,11 @@ impl<'db> ExprCollector<'db> {
984991 // If `<pattern>` is a simple ident, then it is lowered to a single
985992 // `let <pattern> = <pattern>;` statement as an optimization.
986993
987 let mut statements = Vec::new();
994 let mut statements =
995 Vec::with_capacity(usize::from(self_param.is_some()) + (params.len() * 2));
988996
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];
991999 let name = name.clone();
9921000 let child_binding_id = self.alloc_binding(name.clone(), mode, hygiene);
9931001 let child_pat_id =
......@@ -1003,11 +1011,11 @@ impl<'db> ExprCollector<'db> {
10031011 initializer: Some(expr),
10041012 else_branch: None,
10051013 });
1006 self_params.push(child_binding_id);
1014 self_param.user_written = child_binding_id;
10071015 }
10081016
10091017 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] {
10111019 // Check if this is a binding pattern, if so, we can optimize and avoid adding a
10121020 // `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
10131021 Pat::Bind { id, subpat: None, .. }
......@@ -1016,55 +1024,57 @@ impl<'db> ExprCollector<'db> {
10161024 BindingAnnotation::Unannotated | BindingAnnotation::Mutable
10171025 ) =>
10181026 {
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)
10201029 }
10211030 Pat::Bind { id, .. } => {
10221031 // 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)
10241034 }
10251035 _ => (self.generate_new_name(), HygieneId::ROOT, false),
10261036 };
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();
10461038 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 }
10471048 let expr = self.alloc_expr_desugared(Expr::Path(name.clone().into()));
10481049 if !hygiene.is_root() {
10491050 self.store.ident_hygiene.insert(expr.into(), hygiene);
10501051 }
10511052 statements.push(Statement::Let {
1052 pat: *param,
1053 pat: child_pat_id,
10531054 type_ref: None,
10541055 initializer: Some(expr),
10551056 else_branch: None,
10561057 });
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 });
10571069
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);
10671076 }
1077 *param = Param { formal: parent_pat_id, user_written: param.formal };
10681078 }
10691079
10701080 let coroutine = self.desugared_coroutine_expr(
......@@ -1105,8 +1115,8 @@ impl<'db> ExprCollector<'db> {
11051115
11061116 fn collect(
11071117 &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>],
11101120 expr: Option<ast::Expr>,
11111121 awaitable: Awaitable,
11121122 is_async_fn: bool,
......@@ -1123,7 +1133,7 @@ impl<'db> ExprCollector<'db> {
11231133 (false, false) => unreachable!(),
11241134 };
11251135 this.lower_coroutine_body_with_moved_arguments(
1126 self_params,
1136 self_param,
11271137 params,
11281138 body,
11291139 kind,
......@@ -1562,6 +1572,10 @@ impl<'db> ExprCollector<'db> {
15621572 args.reserve_exact(num_params);
15631573 arg_types.reserve_exact(num_params);
15641574 for param in pl.params() {
1575 if !this.check_cfg(&param) {
1576 continue;
1577 }
1578
15651579 let pat = this.collect_pat_top(param.pat());
15661580 let type_ref =
15671581 param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it));
......@@ -1599,13 +1613,15 @@ impl<'db> ExprCollector<'db> {
15991613 let closure_kind = if let Some(kind) = kind {
16001614 // It's important that this expr is allocated immediately before the closure.
16011615 // We rely on it for `coroutine_for_closure()`.
1616 let mut args_with_user_written = args.iter().copied().map(Param::new).collect::<Vec<_>>();
16021617 body = this.lower_coroutine_body_with_moved_arguments(
1603 &mut ArrayVec::new(),
1604 &mut args,
1618 &mut None,
1619 &mut args_with_user_written,
16051620 body,
16061621 kind,
16071622 CoroutineSource::Closure,
16081623 );
1624 args.iter_mut().set_from(args_with_user_written.iter().map(|arg| arg.formal));
16091625 is_coroutine_closure = true;
16101626
16111627 ClosureKind::CoroutineClosure(kind)
......@@ -1666,7 +1682,7 @@ impl<'db> ExprCollector<'db> {
16661682 }
16671683 }
16681684 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();
16701686 // if there is a leading comma, the user is most likely to type out a leading expression
16711687 // so we insert a missing expression at the beginning for IDE features
16721688 if comma_follows_token(e.l_paren_token()) {
......@@ -1681,13 +1697,7 @@ impl<'db> ExprCollector<'db> {
16811697 match kind {
16821698 ArrayExprKind::ElementList(e) => {
16831699 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))
16911701 .collect();
16921702 self.alloc_expr(Expr::Array(Array::ElementList { elements }), syntax_ptr)
16931703 }
......@@ -1728,16 +1738,18 @@ impl<'db> ExprCollector<'db> {
17281738 let e = e.macro_call()?;
17291739 let macro_ptr = AstPtr::new(&e);
17301740 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))
17321742 });
17331743 match id {
1734 Some(id) => {
1744 Some(Some(id)) => {
17351745 // Make the macro-call point to its expanded expression so we can query
17361746 // semantics on syntax pointers to the macro
17371747 let src = self.expander.in_file(syntax_ptr);
17381748 self.store.expr_map.insert(src, id.into());
17391749 id
17401750 }
1751 // Macro expanded into a disabled cfg (yes, there is such thing, see the weird_cfgs test).
1752 Some(None) => return None,
17411753 None => self.alloc_expr(Expr::Missing, syntax_ptr),
17421754 }
17431755 }
src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs+4
......@@ -27,6 +27,10 @@ impl ExprCollector<'_> {
2727 let mut named_args: FxHashMap<Symbol, usize> = Default::default();
2828 let mut reg_args: FxHashSet<usize> = Default::default();
2929 for piece in asm.asm_pieces() {
30 if !self.check_cfg(&piece) {
31 continue;
32 }
33
3034 let slot = operands.len();
3135 let mut lower_reg = |reg: Option<ast::AsmRegSpec>| {
3236 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(
9292 };
9393 if let DefWithBodyId::FunctionId(_) = owner {
9494 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);
9797 p.buf.push_str(", ");
9898 }
9999 body.params.iter().for_each(|param| {
100 p.print_pat(*param);
100 p.print_pat(param.formal);
101101 p.buf.push_str(", ");
102102 });
103103 // 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};
55use crate::{
66 BlockId, DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, VariantId,
77 db::DefDatabase,
8 expr_store::{Body, ExpressionStore, HygieneId},
8 expr_store::{Body, ExpressionStore, HygieneId, body::Param},
99 hir::{
1010 Array, Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement,
1111 generics::GenericParams,
......@@ -147,10 +147,10 @@ impl ExprScopes {
147147 ),
148148 };
149149 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 {
151151 scopes.add_bindings(body, root, self_param, body.binding_hygiene(self_param));
152152 }
153 scopes.add_params_bindings(body, root, &body.params);
153 body.params.iter().for_each(|param| scopes.add_pat_bindings(body, root, param.formal));
154154 compute_expr_scopes(body.root_expr(), body, &mut scopes, &mut { root }, &mut root);
155155 scopes
156156 }
......@@ -248,10 +248,6 @@ impl ExprScopes {
248248 pattern.walk_child_pats(|pat| self.add_pat_bindings(store, scope, pat));
249249 }
250250
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
255251 fn set_scope(&mut self, node: ExprId, scope: ScopeId) {
256252 self.scope_by_expr.insert(node, scope);
257253 }
......@@ -356,7 +352,7 @@ fn compute_expr_scopes(
356352 }
357353 Expr::Closure { args, body: body_expr, .. } => {
358354 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));
360356 compute_expr_scopes(scopes, *body_expr, &mut scope, const_scope);
361357 }
362358 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() {
652652async fn main(&self, param1: i32, ref mut param2: i32, _: i32, param4 @ _: i32, 123: i32) {}
653653"#,
654654 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 {
656656 let self = self;
657 let mut param1 = param1;
657 let param1 = param1;
658658 let mut param2 = param2;
659659 let ref mut param2 = param2;
660660 let mut <ra@gennew>0 = <ra@gennew>0;
......@@ -690,7 +690,7 @@ fn foo() {
690690}
691691
692692#[test]
693fn foo() {
693fn block_tail_cfg() {
694694 pretty_print(
695695 r#"
696696macro_rules! foo {
......@@ -716,3 +716,48 @@ fn foo() -> i64 {
716716 }"#]],
717717 );
718718}
719
720#[test]
721fn weird_cfgs() {
722 pretty_print(
723 r#"
724macro_rules! falsify {
725 ( $($t:tt)* ) => { #[cfg(false)] $($t)* };
726}
727
728struct Foo();
729
730fn 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() {
190190 "#,
191191 expect![[r#"
192192 ModuleIdLt {
193 [salsa id]: Id(3403),
193 [salsa id]: Id(2c03),
194194 krate: Crate(
195 Id(2000),
195 Id(1c00),
196196 ),
197197 block: Some(
198198 BlockId(
199 4401,
199 3c01,
200200 ),
201201 ),
202202 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 {
3535 };
3636}
3737
38struct#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#
38struct#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#
4141"#]],
4242 );
4343}
......@@ -197,7 +197,7 @@ macro_rules! mk_struct {
197197#[macro_use]
198198mod foo;
199199
200struct#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#
200struct#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#
201201"#]],
202202 );
203203}
......@@ -423,10 +423,10 @@ m! { foo, bar }
423423macro_rules! m {
424424 ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
425425}
426impl#\17408# Bar#\17408# {#\17408#
427 fn#\17408# foo#\ROOT2024#(#\17408#)#\17408# {#\17408#}#\17408#
428 fn#\17408# bar#\ROOT2024#(#\17408#)#\17408# {#\17408#}#\17408#
429}#\17408#
426impl#\15360# Bar#\15360# {#\15360#
427 fn#\15360# foo#\ROOT2024#(#\15360#)#\15360# {#\15360#}#\15360#
428 fn#\15360# bar#\ROOT2024#(#\15360#)#\15360# {#\15360#}#\15360#
429}#\15360#
430430"#]],
431431 );
432432}
src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs+6-13
......@@ -15,7 +15,7 @@ use hir_expand::{
1515 builtin::{BuiltinDeriveExpander, find_builtin_attr, find_builtin_derive, find_builtin_macro},
1616 mod_path::{ModPath, PathKind},
1717 name::{AsName, Name},
18 proc_macro::CustomProcMacroExpander,
18 proc_macro::{CustomProcMacroExpander, ProcMacros},
1919};
2020use intern::{Interned, Symbol, sym};
2121use itertools::izip;
......@@ -79,9 +79,9 @@ pub(super) fn collect_defs(
7979 }
8080
8181 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)
8383 .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))
8585 })
8686 .unwrap_or_default()
8787 } else {
......@@ -616,7 +616,7 @@ impl<'db> DefCollector<'db> {
616616 let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) {
617617 Some(_)
618618 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) =>
620620 {
621621 (CustomProcMacroExpander::disabled_proc_attr(), kind)
622622 }
......@@ -2531,12 +2531,8 @@ impl ModCollector<'_, '_> {
25312531 // Case 1: builtin macros
25322532 let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
25332533 // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
2534 let name;
25352534 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),
25402536 None => {
25412537 let explicit_name =
25422538 attrs.by_key(sym::rustc_builtin_macro).tt_values().next().and_then(|tt| {
......@@ -2546,10 +2542,7 @@ impl ModCollector<'_, '_> {
25462542 }
25472543 });
25482544 match explicit_name {
2549 Some(ident) => {
2550 name = ident.as_name();
2551 &name
2552 }
2545 Some(ident) => &ident.as_name(),
25532546 None => &mac.name,
25542547 }
25552548 }
src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs+4-4
......@@ -286,7 +286,7 @@ fn f() { foo }
286286 "parse",
287287 "real_span_map",
288288 "crate_local_def_map",
289 "proc_macros_for_crate_shim",
289 "ProcMacros::get_for_crate_",
290290 "file_item_tree_query",
291291 "ast_id_map",
292292 "parse",
......@@ -305,7 +305,7 @@ fn f() { foo }
305305 "parse_macro_expansion",
306306 "expand_proc_macro",
307307 "macro_arg",
308 "proc_macro_span_shim",
308 "proc_macro_span",
309309 ]
310310 "#]],
311311 expect![[r#"
......@@ -410,7 +410,7 @@ pub struct S {}
410410 "parse",
411411 "real_span_map",
412412 "crate_local_def_map",
413 "proc_macros_for_crate_shim",
413 "ProcMacros::get_for_crate_",
414414 "file_item_tree_query",
415415 "ast_id_map",
416416 "parse",
......@@ -441,7 +441,7 @@ pub struct S {}
441441 "parse_macro_expansion",
442442 "expand_proc_macro",
443443 "macro_arg",
444 "proc_macro_span_shim",
444 "proc_macro_span",
445445 ]
446446 "#]],
447447 expect![[r#"
src/tools/rust-analyzer/crates/hir-def/src/test_db.rs+1-2
......@@ -15,7 +15,6 @@ use triomphe::Arc;
1515
1616use crate::{
1717 Lookup, ModuleDefId, ModuleId,
18 db::DefDatabase,
1918 expr_store::{Body, scope::ExprScopes},
2019 nameres::{DefMap, ModuleSource, block_def_map, crate_def_map},
2120 src::HasSource,
......@@ -48,7 +47,7 @@ impl Default for TestDB {
4847 crates_map: Default::default(),
4948 nonce: Nonce::new(),
5049 };
51 this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
50 crate::db::set_expand_proc_attr_macros(&mut this, true);
5251 // This needs to be here otherwise `CrateGraphBuilder` panics.
5352 set_all_crates_with_durability(&mut this, std::iter::empty(), Durability::HIGH);
5453 _ = base_db::LibraryRoots::builder(Default::default())
src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs+18-4
......@@ -375,12 +375,28 @@ impl AttrId {
375375
376376 /// Returns the containing `ast::Attr` (note that it may contain other attributes as well due
377377 /// 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).
378381 pub fn find_attr_range_with_source(
379382 self,
380383 db: &dyn ExpandDatabase,
381384 krate: Crate,
382385 owner: &dyn ast::HasAttrs,
383386 ) -> (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)> {
384400 let cfg_options = OnceCell::new();
385401 let mut index = 0;
386402 let result = collect_item_tree_attrs(
......@@ -395,10 +411,8 @@ impl AttrId {
395411 },
396412 );
397413 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,
402416 }
403417 }
404418
src/tools/rust-analyzer/crates/hir-expand/src/change.rs+3-4
......@@ -1,8 +1,7 @@
11//! Defines a unit of change that can applied to the database to get the next
22//! state. Changes are transactional.
3use base_db::{CrateGraphBuilder, FileChange, SourceRoot, salsa::Durability};
3use base_db::{CrateGraphBuilder, FileChange, SourceRoot};
44use span::FileId;
5use triomphe::Arc;
65
76use crate::{db::ExpandDatabase, proc_macro::ProcMacrosBuilder};
87
......@@ -16,12 +15,12 @@ impl ChangeWithProcMacros {
1615 pub fn apply(self, db: &mut impl ExpandDatabase) {
1716 let crates_id_map = self.source_change.apply(db);
1817 if let Some(proc_macros) = self.proc_macros {
19 let proc_macros = proc_macros.build(
18 proc_macros.build_in(
19 db,
2020 crates_id_map
2121 .as_ref()
2222 .expect("cannot set proc macros without setting the crate graph too"),
2323 );
24 db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
2524 }
2625 }
2726
src/tools/rust-analyzer/crates/hir-expand/src/db.rs+32-56
......@@ -2,7 +2,7 @@
22
33use base_db::{Crate, SourceDatabase};
44use mbe::MatchedArmIndex;
5use span::{AstIdMap, Edition, Span, SyntaxContext};
5use span::{AstIdMap, Span};
66use std::borrow::Cow;
77use syntax::{AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, ast};
88use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree};
......@@ -17,7 +17,7 @@ use crate::{
1717 declarative::DeclarativeMacroExpander,
1818 fixup::{self, SyntaxFixupUndoInfo},
1919 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,
2121 span_map::{ExpansionSpanMap, RealSpanMap, SpanMap},
2222 tt,
2323};
......@@ -50,14 +50,6 @@ pub enum TokenExpander<'db> {
5050
5151#[query_group::query_group]
5252pub 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
6153 #[salsa::invoke(ast_id_map)]
6254 #[salsa::transparent]
6355 fn ast_id_map(&self, file_id: HirFileId) -> &AstIdMap;
......@@ -115,40 +107,12 @@ pub trait ExpandDatabase: SourceDatabase {
115107 id: AstId<ast::Macro>,
116108 ) -> &DeclarativeMacroExpander;
117109
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
133110 #[salsa::invoke(parse_macro_expansion_error)]
134111 #[salsa::transparent]
135112 fn parse_macro_expansion_error(
136113 &self,
137114 macro_call: MacroCallId,
138115 ) -> Option<ExpandResult<Arc<[SyntaxError]>>>;
139
140 #[salsa::transparent]
141 fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext;
142}
143
144fn 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 }
152116}
153117
154118fn resolve_span(db: &dyn ExpandDatabase, Span { range, anchor, ctx: _ }: Span) -> FileRange {
......@@ -253,7 +217,7 @@ pub fn expand_speculative(
253217 // then try finding a token id for our token if it is inside this input subtree.
254218 let item = ast::Item::cast(speculative_args.clone())?;
255219 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)?;
257221 if let ast::Meta::TokenTreeMeta(meta) = meta
258222 && let Some(tt) = meta.token_tree()
259223 {
......@@ -277,7 +241,7 @@ pub fn expand_speculative(
277241 // Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
278242 let mut speculative_expansion = match loc.def.kind {
279243 MacroDefKind::ProcMacro(ast, expander, _) => {
280 let span = db.proc_macro_span(ast);
244 let span = proc_macro_span(db, ast);
281245 tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible);
282246 tt.set_top_subtree_delimiter_span(tt::DelimSpan::from_single(span));
283247 expander.expand(
......@@ -296,7 +260,7 @@ pub fn expand_speculative(
296260 }
297261 MacroDefKind::Declarative(it, _) => db
298262 .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),
300264 MacroDefKind::BuiltIn(_, it) => {
301265 it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
302266 }
......@@ -556,8 +520,7 @@ fn macro_expand<'db>(
556520
557521 let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind {
558522 MacroDefKind::ProcMacro(..) => {
559 return db
560 .expand_proc_macro(macro_call_id)
523 return expand_proc_macro(db, macro_call_id)
561524 .as_ref()
562525 .map(|it| (Cow::Borrowed(it), None));
563526 }
......@@ -568,9 +531,9 @@ fn macro_expand<'db>(
568531
569532 let arg = macro_arg;
570533 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 }
574537 MacroDefKind::BuiltIn(_, it) => {
575538 it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None)
576539 }
......@@ -610,7 +573,7 @@ fn macro_expand<'db>(
610573 }
611574 MacroDefKind::ProcMacro(_, _, _) => unreachable!(),
612575 };
613 (ExpandResult { value: res.value, err: res.err }, span)
576 (res, span)
614577 }
615578 };
616579
......@@ -627,17 +590,30 @@ fn macro_expand<'db>(
627590 ExpandResult { value: (Cow::Owned(tt), matched_arm), err }
628591}
629592
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.
630598fn 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, ())
639611}
640612
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
641617#[salsa_macros::tracked(returns(ref))]
642618fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<tt::TopSubtree> {
643619 let loc = id.loc(db);
......@@ -654,7 +630,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<t
654630 };
655631
656632 let ExpandResult { value: mut tt, err } = {
657 let span = db.proc_macro_span(ast);
633 let span = proc_macro_span(db, ast);
658634 expander.expand(
659635 db,
660636 loc.def.krate,
src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs+7-7
......@@ -1,6 +1,6 @@
11//! Compiled declarative macro expanders (`macro_rules!` and `macro`)
22
3use std::{cell::OnceCell, ops::ControlFlow};
3use std::ops::ControlFlow;
44
55use base_db::Crate;
66use span::{Edition, Span, SyntaxContext};
......@@ -32,7 +32,7 @@ impl DeclarativeMacroExpander {
3232 pub fn expand(
3333 &self,
3434 db: &dyn ExpandDatabase,
35 tt: tt::TopSubtree,
35 tt: &tt::TopSubtree,
3636 call_id: MacroCallId,
3737 span: Span,
3838 ) -> ExpandResult<(tt::TopSubtree, Option<u32>)> {
......@@ -46,7 +46,7 @@ impl DeclarativeMacroExpander {
4646 .mac
4747 .expand(
4848 db,
49 &tt,
49 tt,
5050 |s| {
5151 s.ctx =
5252 apply_mark(db, s.ctx, call_id.into(), self.transparency, self.edition)
......@@ -61,7 +61,7 @@ impl DeclarativeMacroExpander {
6161 pub fn expand_unhygienic(
6262 &self,
6363 db: &dyn ExpandDatabase,
64 tt: tt::TopSubtree,
64 tt: &tt::TopSubtree,
6565 call_style: MacroCallStyle,
6666 call_site: Span,
6767 ) -> ExpandResult<tt::TopSubtree> {
......@@ -72,7 +72,7 @@ impl DeclarativeMacroExpander {
7272 ),
7373 None => self
7474 .mac
75 .expand(db, &tt, |_| (), call_style, call_site)
75 .expand(db, tt, |_| (), call_style, call_site)
7676 .map(TupleExt::head)
7777 .map_err(Into::into),
7878 }
......@@ -91,10 +91,10 @@ impl DeclarativeMacroExpander {
9191 let root = root.syntax_node();
9292
9393 let transparency = |node: ast::AnyHasAttrs| {
94 let cfg_options = OnceCell::new();
94 let mut cfg_options = None;
9595 expand_cfg_attr(
9696 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)),
9898 |attr, _| {
9999 if let ast::Meta::KeyValueMeta(attr) = attr
100100 && attr.path().is1("rustc_macro_transparency")
src/tools/rust-analyzer/crates/hir-expand/src/lib.rs+12-2
......@@ -53,7 +53,7 @@ use crate::{
5353 },
5454 db::ExpandDatabase,
5555 mod_path::ModPath,
56 proc_macro::{CustomProcMacroExpander, ProcMacroKind},
56 proc_macro::{CustomProcMacroExpander, ProcMacroKind, ProcMacros},
5757 span_map::{ExpansionSpanMap, SpanMap},
5858};
5959
......@@ -176,7 +176,7 @@ impl ExpandErrorKind {
176176 kind: RenderedExpandError::DISABLED,
177177 },
178178 &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()) {
180180 Some(e) => RenderedExpandError {
181181 message: e.to_string(),
182182 error: e.is_hard_error(),
......@@ -1128,6 +1128,16 @@ impl HirFileId {
11281128 HirFileId::MacroFile(_) => None,
11291129 }
11301130 }
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 }
11311141}
11321142
11331143impl 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};
77use base_db::{Crate, CrateBuilderId, CratesIdMap, Env, ProcMacroLoadingError};
88use intern::Symbol;
99use rustc_hash::FxHashMap;
10use salsa::{Durability, Setter};
1011use span::Span;
1112use triomphe::Arc;
1213
......@@ -83,14 +84,19 @@ impl ProcMacrosBuilder {
8384 );
8485 }
8586
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) {
8789 let mut map = self
8890 .0
8991 .into_iter()
9092 .map(|(krate, proc_macro)| (crates_id_map[&krate], proc_macro))
9193 .collect::<FxHashMap<_, _>>();
9294 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);
94100 }
95101}
96102
......@@ -107,11 +113,25 @@ impl FromIterator<(CrateBuilderId, ProcMacroLoadResult)> for ProcMacrosBuilder {
107113#[derive(Debug, PartialEq, Eq)]
108114pub struct CrateProcMacros(StoredProcMacroLoadResult);
109115
110#[derive(Default, Debug)]
111pub 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)]
118pub struct ProcMacros {
119 #[returns(ref)]
120 pub by_crate: FxHashMap<Crate, Arc<CrateProcMacros>>,
121}
122
112123impl 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]
130impl 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()
115135 }
116136}
117137
......@@ -276,7 +296,7 @@ impl CustomProcMacroExpander {
276296 ExpandError::new(call_site, ExpandErrorKind::MacroDisabled),
277297 ),
278298 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) {
280300 Some(it) => it,
281301 None => {
282302 return ExpandResult::new(
......@@ -347,10 +367,3 @@ impl CustomProcMacroExpander {
347367 }
348368 }
349369}
350
351pub(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
6363 // Unsafety in function parameter patterns (that can only be union destructuring)
6464 // cannot be inserted into an unsafe block, so even with `unsafe_op_in_unsafe_fn`
6565 // 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);
6868 }
6969 }
7070
......@@ -112,8 +112,8 @@ pub fn unsafe_operations_for_body(
112112 };
113113 let mut visitor = UnsafeVisitor::new(db, infer, body, def.into(), &mut visitor_callback);
114114 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);
117117 }
118118}
119119
src/tools/rust-analyzer/crates/hir-ty/src/display.rs+17-10
......@@ -746,26 +746,33 @@ impl<'db> HirDisplay<'db> for Const<'db> {
746746 ConstKind::Value(value) => render_const_scalar_from_valtree(f, value.ty, value.value),
747747 ConstKind::Unevaluated(unev) => {
748748 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("_")?,
755758 }
756 None => f.write_str("_")?,
757 },
759 Some(id.into())
760 }
758761 GeneralConstId::StaticId(id) => {
759762 let name = &StaticSignature::of(f.db, id).name;
760763 f.start_location_link(id.into());
761764 write!(f, "{}", name.display(f.db, f.edition()))?;
762765 f.end_location_link();
766 Some(id.into())
763767 }
764768 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
766771 }
767772 };
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 }
769776 Ok(())
770777 }
771778 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> {
143143 self.chain.iter()
144144 }
145145
146 fn owner(&self) -> &SingleGenerics<'db> {
146 pub(crate) fn owner(&self) -> &SingleGenerics<'db> {
147147 self.chain.last().expect("must have an owner params")
148148 }
149149
src/tools/rust-analyzer/crates/hir-ty/src/infer.rs+27-4
......@@ -44,7 +44,7 @@ use hir_def::{
4444 FunctionId, GenericDefId, GenericParamId, HasModule, LocalFieldId, Lookup, StaticId, TraitId,
4545 TupleFieldId, TupleId, VariantId,
4646 attrs::AttrFlags,
47 expr_store::{Body, ExpressionStore, HygieneId, path::Path},
47 expr_store::{Body, ExpressionStore, HygieneId, body::Param, path::Path},
4848 hir::{BindingId, ExprId, ExprOrPatId, LabelId, PatId},
4949 lang_item::LangItems,
5050 layout::Integer,
......@@ -145,7 +145,9 @@ pub fn infer_query_with_inspect<'db>(
145145 }
146146
147147 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 }
149151 DefWithBodyId::ConstId(c) => ctx.collect_const(c, ConstSignature::of(db, c)),
150152 DefWithBodyId::StaticId(s) => ctx.collect_static(s, StaticSignature::of(db, s)),
151153 DefWithBodyId::VariantId(v) => {
......@@ -379,6 +381,14 @@ pub enum InferenceDiagnostic {
379381 #[type_visitable(ignore)]
380382 variant: VariantId,
381383 },
384 UnionPatMustHaveExactlyOneField {
385 #[type_visitable(ignore)]
386 pat: PatId,
387 },
388 UnionPatHasRest {
389 #[type_visitable(ignore)]
390 pat: PatId,
391 },
382392 FunctionalRecordUpdateOnNonStruct {
383393 #[type_visitable(ignore)]
384394 base_expr: ExprId,
......@@ -409,6 +419,10 @@ pub enum InferenceDiagnostic {
409419 expr: ExprId,
410420 found: StoredTy,
411421 },
422 MutRefInImmRefPat {
423 #[type_visitable(ignore)]
424 pat: PatId,
425 },
412426 CannotImplicitlyDerefTraitObject {
413427 #[type_visitable(ignore)]
414428 pat: PatId,
......@@ -504,6 +518,10 @@ pub enum InferenceDiagnostic {
504518 #[type_visitable(ignore)]
505519 pat: PatId,
506520 },
521 YieldOutsideCoroutine {
522 #[type_visitable(ignore)]
523 expr: ExprId,
524 },
507525}
508526
509527#[derive(Debug, PartialEq, Eq, Clone)]
......@@ -1691,7 +1709,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
16911709 self.return_ty = return_ty;
16921710 }
16931711
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 ) {
16951718 let data = FunctionSignature::of(self.db, func);
16961719 let mut param_tys = self.with_ty_lowering(
16971720 &data.store,
......@@ -1730,7 +1753,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
17301753 let ty = param_tys.next().unwrap_or_else(|| self.table.next_ty_var(Span::Dummy));
17311754 let ty = self.process_user_written_ty(ty);
17321755
1733 self.infer_top_pat(*pat, ty, PatOrigin::Param);
1756 self.infer_top_pat(pat.formal, ty, PatOrigin::Param);
17341757 }
17351758 self.return_ty = match data.ret_type {
17361759 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> {
585585 method_callee.args,
586586 );
587587 }
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 => {}
595589 }
596590 }
597591}
src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs+3-1
......@@ -597,7 +597,9 @@ impl<'db> InferenceContext<'_, 'db> {
597597 }
598598 resume_ty
599599 } else {
600 // FIXME: report error (yield expr in non-coroutine)
600 self.push_diagnostic(InferenceDiagnostic::YieldOutsideCoroutine {
601 expr: tgt_expr,
602 });
601603 self.types.types.error
602604 }
603605 }
src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs+3-3
......@@ -916,7 +916,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
916916 if matches!(bm.0, ByRef::Yes(Mutability::Mut))
917917 && let MutblCap::WeaklyNot = pat_info.max_ref_mutbl
918918 {
919 // FIXME: Emit an error: cannot borrow as mutable inside an `&` pattern.
919 self.push_diagnostic(InferenceDiagnostic::MutRefInImmRefPat { pat });
920920 }
921921
922922 // ...and store it in a side table:
......@@ -1242,10 +1242,10 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
12421242 // Report an error if an incorrect number of fields was specified.
12431243 if matches!(variant, VariantId::UnionId(_)) {
12441244 if fields.len() != 1 {
1245 // FIXME: Emit an error, unions can't have more than one field.
1245 self.push_diagnostic(InferenceDiagnostic::UnionPatMustHaveExactlyOneField { pat });
12461246 }
12471247 if has_rest_pat {
1248 // FIXME: Emit an error, unions can't have a rest pat.
1248 self.push_diagnostic(InferenceDiagnostic::UnionPatHasRest { pat });
12491249 }
12501250 } else if !unmentioned_fields.is_empty() && !has_rest_pat {
12511251 // 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> {
290290 self.lifetime_elision = lifetime_elision;
291291 }
292292
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
293298 pub(crate) fn with_interning_mode(mut self, interning_mode: LoweringMode) -> Self {
294299 self.interning_mode = interning_mode;
295300 self
......@@ -1948,7 +1953,7 @@ fn resolve_type_param_assoc_type_shorthand(
19481953
19491954 let mut supertraits_resolution = None;
19501955 for maybe_parent_generics in generics.iter_owners().rev() {
1951 ctx.store = maybe_parent_generics.store();
1956 ctx.set_owner(maybe_parent_generics);
19521957 for pred in maybe_parent_generics.where_predicates() {
19531958 let (WherePredicate::TypeBound { target, bound }
19541959 | WherePredicate::ForLifetime { lifetimes: _, target, bound }) = pred
......@@ -2366,7 +2371,7 @@ fn generic_predicates(
23662371 // Collect only diagnostics from the child, not including parents.
23672372 ctx.diagnostics.clear();
23682373
2369 ctx.store = maybe_parent_generics.store();
2374 ctx.set_owner(maybe_parent_generics);
23702375 for pred in maybe_parent_generics.where_predicates() {
23712376 tracing::debug!(?pred);
23722377 for (pred, source) in ctx.lower_where_predicate(pred, false) {
......@@ -2568,14 +2573,14 @@ pub(crate) fn generic_defaults_with_diagnostics(
25682573 let generics = generics.get().unwrap();
25692574 let mut defaults = ThinVec::new();
25702575 if let Some(parent) = generics.parent() {
2571 ctx.store = parent.store();
2576 ctx.set_owner(parent);
25722577 defaults.extend(
25732578 parent.iter_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
25742579 );
25752580 }
25762581 ctx.diagnostics.clear(); // Don't include diagnostics from the parent.
25772582 ctx.defined_anon_consts.clear();
2578 ctx.store = store_for_self;
2583 ctx.set_owner(generics.owner());
25792584 defaults.extend(
25802585 generics.iter_self_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
25812586 );
src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs+25
......@@ -728,7 +728,13 @@ impl TraitImpls {
728728 {
729729 continue;
730730 }
731
731732 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
732738 let interner = DbInterner::new_no_crate(db);
733739 let entry = map.entry(trait_ref.def_id.0).or_default();
734740 match simplify_type(interner, self_ty, TreatParams::InstantiateWithInfer) {
......@@ -864,3 +870,22 @@ impl TraitImpls {
864870 }
865871 }
866872}
873
874fn 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> {
30463046 ty: Ty<'db>,
30473047 locals: &Locals<'a>,
30483048 addr: Address,
3049 _metadata: &[u8],
3049 metadata: &[u8],
30503050 span: MirSpan,
30513051 ) -> Result<'db, ()> {
30523052 let Some(drop_fn) = self.lang_items().Drop_drop else {
......@@ -3056,13 +3056,23 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
30563056 };
30573057
30583058 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 )
30613071 {
30623072 self.exec_looked_up_function(
30633073 body,
30643074 locals,
3065 drop_fn,
3075 drop_impl,
30663076 iter::once(IntervalOrOwned::Owned(addr.to_bytes().to_vec())),
30673077 span,
30683078 Interval { addr: Address::Invalid(0), size: 0 },
......@@ -3103,6 +3113,12 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
31033113 AdtId::EnumId(_) => (),
31043114 }
31053115 }
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 }
31063122 TyKind::Bool
31073123 | TyKind::Char
31083124 | TyKind::Int(_)
......@@ -3125,7 +3141,6 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
31253141 | TyKind::Error(_)
31263142 | TyKind::Param(_)
31273143 | TyKind::Placeholder(_)
3128 | TyKind::Dynamic(..)
31293144 | TyKind::FnPtr(..)
31303145 | TyKind::Bound(..)
31313146 | TyKind::Infer(..)
src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs+51
......@@ -229,6 +229,28 @@ fn main() {
229229 );
230230}
231231
232#[test]
233fn drop_glue_for_type_without_drop_impl_does_not_recurse() {
234 check_pass(
235 r#"
236//- minicore: drop, pin
237
238struct HasDrop;
239impl Drop for HasDrop {
240 fn drop(&mut self) {}
241}
242
243struct WithDropGlue {
244 field: HasDrop,
245}
246
247fn main() {
248 let _c = WithDropGlue { field: HasDrop };
249}
250 "#,
251 );
252}
253
232254#[test]
233255fn drop_if_let() {
234256 check_pass(
......@@ -358,6 +380,35 @@ fn main() {
358380 );
359381}
360382
383#[test]
384fn drop_glue_for_trait_object() {
385 check_panic(
386 r#"
387//- minicore: manually_drop, coerce_unsized, fmt, panic, drop, pin
388use core::mem::ManuallyDrop;
389use core::ptr::drop_in_place;
390
391struct X;
392impl Drop for X {
393 fn drop(&mut self) {
394 panic!("concrete drop ran");
395 }
396}
397
398trait T {}
399impl T for X {}
400
401fn 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
361412#[test]
362413fn manually_drop() {
363414 check_pass(
src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs+4-4
......@@ -6,7 +6,7 @@ use base_db::Crate;
66use hir_def::{
77 AdtId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId, GenericParamId, HasModule,
88 ItemContainerId, LocalFieldId, Lookup, TraitId,
9 expr_store::{Body, ExpressionStore, HygieneId, path::Path},
9 expr_store::{Body, ExpressionStore, HygieneId, body::Param, path::Path},
1010 hir::{
1111 ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ClosureKind, ExprId, ExprOrPatId,
1212 LabelId, Literal, MatchArm, Pat, PatId, RecordLitField, RecordSpread,
......@@ -2312,7 +2312,7 @@ pub fn mir_body_query<'db>(db: &'db dyn HirDatabase, def: InferBodyId) -> Result
23122312 let (store, root_expr, self_param, params) = match def {
23132313 InferBodyId::DefWithBodyId(def) => {
23142314 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)
23162316 }
23172317 InferBodyId::AnonConstId(def) => {
23182318 let loc = def.loc(db);
......@@ -2351,7 +2351,7 @@ pub fn lower_body_to_mir<'db>(
23512351 infer: &InferenceResult,
23522352 root_expr: ExprId,
23532353 self_param: Option<BindingId>,
2354 params: &[PatId],
2354 params: &[Param<PatId>],
23552355) -> Result<'db, MirBody> {
23562356 // Extract params and self_param only when lowering the body's root expression for a function.
23572357 if let Some(fid) = owner.as_function() {
......@@ -2366,7 +2366,7 @@ pub fn lower_body_to_mir<'db>(
23662366 store,
23672367 infer,
23682368 root_expr,
2369 params.iter().copied().zip(param_tys),
2369 params.iter().map(|param| param.formal).zip(param_tys),
23702370 self_param,
23712371 )
23722372 } else {
src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs+2-2
......@@ -7,7 +7,7 @@ use base_db::{
77 SourceRootId, SourceRootInput, all_crates, relevant_crates, set_all_crates_with_durability,
88};
99
10use hir_def::{ModuleId, db::DefDatabase, nameres::crate_def_map};
10use hir_def::{ModuleId, nameres::crate_def_map};
1111use hir_expand::EditionedFileId;
1212use rustc_hash::FxHashMap;
1313use salsa::Durability;
......@@ -43,7 +43,7 @@ impl Default for TestDB {
4343 crates_map: Default::default(),
4444 nonce: Nonce::new(),
4545 };
46 this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
46 hir_def::db::set_expand_proc_attr_macros(&mut this, true);
4747 // This needs to be here otherwise `CrateGraphBuilder` panics.
4848 set_all_crates_with_durability(&mut this, std::iter::empty(), Durability::HIGH);
4949 _ = 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 {
514514 for (def, krate) in defs {
515515 let (body, source_map) = Body::with_source_map(&db, def);
516516 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()));
518519 infer_def(infer, body, source_map, self_param, krate);
519520 }
520521
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
102102
103103 // FIXME: Deduplicate this with hir::Local::sources().
104104 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)
106106 && let Some(source) = source_map.self_param_syntax()
107107 {
108108 format!("{:?}", text_range(db, source))
src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs+27
......@@ -2258,3 +2258,30 @@ fn main() {
22582258 "#,
22592259 );
22602260}
2261
2262#[test]
2263fn trait_impl_with_error_self_ty_does_not_match_arbitrary_receiver() {
2264 check_types(
2265 r#"
2266//- minicore: sized
2267trait UnrelatedTrait {
2268 fn take(self) {}
2269}
2270
2271struct MyOption<T>(T);
2272
2273impl<T> MyOption<T> {
2274 fn take(&mut self) -> MyOption<T> {
2275 loop {}
2276 }
2277}
2278
2279fn f<T>(mut o: MyOption<T>) {
2280 let value = o.take();
2281 //^^^^^ MyOption<T>
2282}
2283
2284impl 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() {
4343 );
4444}
4545
46#[test]
47fn anon_const_projection_in_impl_predicate() {
48 check_no_mismatches(
49 r#"
50trait Trait {
51 type Assoc;
52}
53
54struct S<const N: usize>;
55
56impl<const N: usize> S<N>
57where
58 S<{ N }>: Trait,
59{
60 fn new(_: <S<N> as Trait>::Assoc) {}
61}
62 "#,
63 );
64}
65
4666#[test]
4767fn bug_585() {
4868 check_infer(
......@@ -2915,3 +2935,15 @@ impl Foo for Bar {
29152935"#,
29162936 );
29172937}
2938
2939#[test]
2940fn regression_unresolved_deferred_closure_call_resolution() {
2941 check_no_mismatches(
2942 r#"
2943//- minicore: fn
2944fn 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 @@
33//! we didn't do that.
44//!
55//! But we need this for at least LRU caching at the query level.
6pub use hir_def::db::DefDatabase;
6pub use hir_def::db::{DefDatabase, set_expand_proc_attr_macros};
77pub use hir_expand::db::ExpandDatabase;
88pub use hir_ty::db::HirDatabase;
src/tools/rust-analyzer/crates/hir/src/diagnostics.rs+39
......@@ -135,6 +135,7 @@ diagnostics![AnyDiagnostic<'db> ->
135135 MissingMatchArms,
136136 MissingUnsafe,
137137 MovedOutOfRef<'db>,
138 MutRefInImmRefPat,
138139 MutableRefBinding,
139140 NeedMut,
140141 NonExhaustiveLet,
......@@ -176,7 +177,10 @@ diagnostics![AnyDiagnostic<'db> ->
176177 ElidedLifetimesInPath,
177178 TypeMustBeKnown<'db>,
178179 UnionExprMustHaveExactlyOneField,
180 UnionPatMustHaveExactlyOneField,
181 UnionPatHasRest,
179182 UnimplementedTrait<'db>,
183 YieldOutsideCoroutine,
180184];
181185
182186#[derive(Debug)]
......@@ -337,6 +341,11 @@ pub struct CannotBeDereferenced<'db> {
337341 pub found: Type<'db>,
338342}
339343
344#[derive(Debug)]
345pub struct MutRefInImmRefPat {
346 pub pat: InFile<ExprOrPatPtr>,
347}
348
340349#[derive(Debug)]
341350pub struct CannotImplicitlyDerefTraitObject<'db> {
342351 pub pat: InFile<ExprOrPatPtr>,
......@@ -638,6 +647,16 @@ pub struct UnionExprMustHaveExactlyOneField {
638647 pub expr: InFile<ExprOrPatPtr>,
639648}
640649
650#[derive(Debug)]
651pub struct UnionPatMustHaveExactlyOneField {
652 pub pat: InFile<ExprOrPatPtr>,
653}
654
655#[derive(Debug)]
656pub struct UnionPatHasRest {
657 pub pat: InFile<ExprOrPatPtr>,
658}
659
641660#[derive(Debug)]
642661pub struct InvalidLhsOfAssignment {
643662 pub lhs: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
......@@ -665,6 +684,11 @@ pub struct MutableRefBinding {
665684 pub pat: InFile<ExprOrPatPtr>,
666685}
667686
687#[derive(Debug)]
688pub struct YieldOutsideCoroutine {
689 pub expr: InFile<ExprOrPatPtr>,
690}
691
668692impl<'db> AnyDiagnostic<'db> {
669693 pub(crate) fn body_validation_diagnostic(
670694 db: &'db dyn HirDatabase,
......@@ -932,6 +956,14 @@ impl<'db> AnyDiagnostic<'db> {
932956 let pat = pat_syntax(pat)?.map(Into::into);
933957 NonExhaustiveRecordPat { pat, variant: variant.into() }.into()
934958 }
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 }
935967 &InferenceDiagnostic::FunctionalRecordUpdateOnNonStruct { base_expr } => {
936968 FunctionalRecordUpdateOnNonStruct { base_expr: expr_syntax(base_expr)? }.into()
937969 }
......@@ -960,6 +992,10 @@ impl<'db> AnyDiagnostic<'db> {
960992 let expr = expr_syntax(*expr)?;
961993 CannotBeDereferenced { expr, found: new_ty(found.as_ref()) }.into()
962994 }
995 InferenceDiagnostic::MutRefInImmRefPat { pat } => {
996 let pat = pat_syntax(*pat)?.map(Into::into);
997 MutRefInImmRefPat { pat }.into()
998 }
963999 InferenceDiagnostic::CannotImplicitlyDerefTraitObject { pat, found } => {
9641000 let pat = pat_syntax(*pat)?.map(Into::into);
9651001 CannotImplicitlyDerefTraitObject { pat, found: new_ty(found.as_ref()) }.into()
......@@ -1092,6 +1128,9 @@ impl<'db> AnyDiagnostic<'db> {
10921128 let pat = pat_syntax(*pat)?.map(Into::into);
10931129 MutableRefBinding { pat }.into()
10941130 }
1131 &InferenceDiagnostic::YieldOutsideCoroutine { expr } => {
1132 YieldOutsideCoroutine { expr: expr_syntax(expr)? }.into()
1133 }
10951134 })
10961135 }
10971136
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
217217 first = false;
218218 }
219219
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;
221221 let pat_str = body.pretty_print_pat(db, owner, pat_id, true, f.edition());
222222 f.write_str(&pat_str)?;
223223
src/tools/rust-analyzer/crates/hir/src/lib.rs+14-17
......@@ -1188,21 +1188,18 @@ fn emit_macro_def_diagnostics<'db>(
11881188 m: Macro,
11891189) {
11901190 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)
11921194 && let Some(e) = expander.mac.err()
11931195 {
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);
11991196 let edition = krate.data(db).edition;
12001197 emit_def_diagnostic_(
12011198 db,
12021199 acc,
12031200 &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
12041201 edition,
1205 m.krate(db).id,
1202 krate,
12061203 );
12071204 }
12081205}
......@@ -2737,14 +2734,14 @@ impl<'db> Param<'db> {
27372734 Callee::Def(CallableDefId::FunctionId(it)) => {
27382735 let parent = DefWithBodyId::FunctionId(it);
27392736 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) {
27412738 Some(Local {
27422739 parent: parent.into(),
27432740 parent_infer: parent.into(),
2744 binding_id: self_param,
2741 binding_id: self_param.user_written,
27452742 })
27462743 } 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]
27482745 {
27492746 Some(Local {
27502747 parent: parent.into(),
......@@ -4193,7 +4190,7 @@ impl Local {
41934190 }
41944191 ExpressionStoreOwnerId::Body(def_with_body_id) => {
41954192 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)
41974194 && let Some(source) = b.1.self_param_syntax()
41984195 {
41994196 let root = source.file_syntax(db);
......@@ -4234,7 +4231,7 @@ impl Local {
42344231 }
42354232 ExpressionStoreOwnerId::Body(def_with_body_id) => {
42364233 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)
42384235 && let Some(source) = b.1.self_param_syntax()
42394236 {
42404237 let root = source.file_syntax(db);
......@@ -6849,8 +6846,8 @@ impl<'db> Layout<'db> {
68496846 .into_iter()
68506847 .flatten()
68516848 .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)]| {
68546851 let size = field_size(i)?;
68556852 end.checked_sub(start)?.checked_sub(size)
68566853 })
......@@ -7381,9 +7378,9 @@ pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>(
73817378 let mut def_map = crate_def_map(db, krate);
73827379 let mut module = &def_map[def_map.root_module_id()];
73837380 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 {
73877384 let res = module
73887385 .scope
73897386 .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> {
522522 let file_id = declaration_tree_id.file_id();
523523 let in_file = InFile::new(file_id, declaration);
524524 let node = in_file.to_node(self.db);
525 let root = find_root(node.syntax());
525 let root = node.syntax().tree_top();
526526 self.cache(root, file_id);
527527 Some(in_file.with_value(node.syntax().clone()))
528528 }
......@@ -531,7 +531,7 @@ impl<'db> SemanticsImpl<'db> {
531531 }
532532 HirFileId::MacroFile(macro_file) => {
533533 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();
535535 self.cache(root, node.file_id);
536536 Some(node)
537537 }
......@@ -544,7 +544,7 @@ impl<'db> SemanticsImpl<'db> {
544544 let def_map = module.id.def_map(self.db);
545545 let definition = def_map[module.id].origin.definition_source(self.db);
546546 let definition = definition.map(|it| it.node());
547 let root_node = find_root(&definition.value);
547 let root_node = definition.value.tree_top();
548548 self.cache(root_node, definition.file_id);
549549 definition
550550 }
......@@ -1067,7 +1067,8 @@ impl<'db> SemanticsImpl<'db> {
10671067 && let Some(p) = first.parent()
10681068 {
10691069 let range = first.text_range().cover(last.text_range());
1070 let node = find_root(&p)
1070 let node = p
1071 .tree_top()
10711072 .covering_element(range)
10721073 .ancestors()
10731074 .take_while(|it| it.text_range() == range)
......@@ -1577,7 +1578,7 @@ impl<'db> SemanticsImpl<'db> {
15771578 pub fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> {
15781579 self.wrap_node_infile(node).original_ast_node_rooted(self.db).map(
15791580 |InRealFile { file_id, value }| {
1580 self.cache(find_root(value.syntax()), file_id.into());
1581 self.cache(value.syntax().tree_top(), file_id.into());
15811582 value
15821583 },
15831584 )
......@@ -1589,7 +1590,7 @@ impl<'db> SemanticsImpl<'db> {
15891590 let InFile { file_id, .. } = self.find_file(node);
15901591 InFile::new(file_id, node).original_syntax_node_rooted(self.db).map(
15911592 |InRealFile { file_id, value }| {
1592 self.cache(find_root(&value), file_id.into());
1593 self.cache(value.tree_top(), file_id.into());
15931594 value
15941595 },
15951596 )
......@@ -2171,7 +2172,7 @@ impl<'db> SemanticsImpl<'db> {
21712172 pub fn source<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>> {
21722173 // FIXME: source call should go through the parse cache
21732174 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);
21752176 Some(res)
21762177 }
21772178
......@@ -2375,7 +2376,7 @@ impl<'db> SemanticsImpl<'db> {
23752376
23762377 /// Wraps the node in a [`InFile`] with the file id it belongs to.
23772378 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();
23792380 let file_id = self.lookup(&root_node).unwrap_or_else(|| {
23802381 panic!(
23812382 "\n\nFailed to lookup {:?} in this Semantics.\n\
......@@ -2461,7 +2462,7 @@ impl<'db> SemanticsImpl<'db> {
24612462 }
24622463 };
24632464 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);
24652466 ToDef::to_def(self, adt_source.as_ref())
24662467 }
24672468
......@@ -2702,10 +2703,6 @@ impl ToDef for ast::IdentPat {
27022703 }
27032704}
27042705
2705fn find_root(node: &SyntaxNode) -> SyntaxNode {
2706 node.ancestors().last().unwrap()
2707}
2708
27092706/// `SemanticsScope` encapsulates the notion of a scope (the set of visible
27102707/// names) at a particular program point.
27112708///
src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs+1-1
......@@ -371,7 +371,7 @@ impl SourceToDefCtx<'_, '_> {
371371 .as_expression_store_owner()?
372372 .as_def_with_body()?;
373373 let body = Body::of(self.db, container);
374 Some((container, body.self_param()?))
374 Some((container, body.self_param?.user_written))
375375 }
376376 pub(super) fn label_to_def(
377377 &mut self,
src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs+2-2
......@@ -580,7 +580,7 @@ impl<'db> SourceAnalyzer<'db> {
580580 ) -> Option<Type<'db>> {
581581 let binding = match self.body_or_sig.as_ref()? {
582582 BodyOrSig::Sig { .. } | BodyOrSig::VariantFields { .. } => return None,
583 BodyOrSig::Body { body, .. } => body.self_param()?,
583 BodyOrSig::Body { body, .. } => body.self_param?.formal,
584584 };
585585 let ty = self.infer()?.binding_ty(binding);
586586 Some(self.ty(ty))
......@@ -1155,7 +1155,7 @@ impl<'db> SourceAnalyzer<'db> {
11551155 let parent = path.syntax().parent();
11561156 let parent = || parent.clone();
11571157
1158 let mut prefer_value_ns = false;
1158 let mut prefer_value_ns = parent().and_then(ast::PathExpr::cast).is_some();
11591159 let resolved = (|| {
11601160 let infer = self.infer()?;
11611161 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::{
55};
66use syntax::{
77 SyntaxKind, T,
8 algo::{next_non_trivia_token, previous_non_trivia_token},
89 ast::{
910 self, AstNode, HasArgList, HasAttrs, HasGenericParams, HasVisibility,
1011 syntax_factory::SyntaxFactory,
......@@ -186,12 +187,39 @@ fn process_struct_name_reference(
186187 match_ast! {
187188 match parent {
188189 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);
195223 },
196224 ast::PathExpr(path_expr) => {
197225 let call_expr = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
......@@ -220,7 +248,11 @@ fn process_struct_name_reference(
220248 editor.insert_all(Position::before(place.start()), elements);
221249 }
222250 }
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![]);
224256 },
225257 _ => {}
226258 }
......@@ -229,28 +261,14 @@ fn process_struct_name_reference(
229261}
230262
231263fn process_delimiter(
232 ctx: &AssistContext<'_, '_>,
233 source: &ast::SourceFile,
234264 editor: &SyntaxEditor,
235 list: &impl AstNode,
265 l_paren: syntax::SyntaxToken,
266 r_paren: syntax::SyntaxToken,
236267 first_insert: Vec<syntax::SyntaxElement>,
268 trailing_insert: Vec<syntax::SyntaxElement>,
237269) {
238270 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!['('] {
254272 let mut open_delim = vec![
255273 make.whitespace(" ").into(),
256274 make.token(T!['{']).into(),
......@@ -259,16 +277,67 @@ fn process_delimiter(
259277 open_delim.extend(first_insert);
260278 editor.replace_with_many(l_paren, open_delim);
261279 }
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);
269285 }
270286}
271287
288fn 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
295fn 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.
304fn 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).
320fn 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
272341fn edit_field_references(
273342 ctx: &AssistContext<'_, '_>,
274343 edit: &mut SourceChangeBuilder,
......@@ -313,23 +382,21 @@ fn generate_names(
313382 .collect()
314383}
315384
316fn 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`]).
387fn tuple_pat_field_targets(
317388 pat: &ast::TupleStructPat,
318389 names: &[ast::Name],
319 make: &SyntaxFactory,
320) -> ast::RecordPatFieldList {
390) -> (Vec<(ast::Pat, ast::Name)>, Option<ast::RestPat>) {
321391 let pure_fields = pat.fields().filter(|p| !matches!(p, ast::Pat::RestPat(_)));
322392 let rest_len = names.len().saturating_sub(pure_fields.clone().count());
323393 let rest_pat = pat.fields().find_map(|p| ast::RestPat::cast(p.syntax().clone()));
324394 let rest_idx =
325395 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);
328398
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)
333400}
334401
335402#[cfg(test)]
......@@ -803,7 +870,6 @@ fn test(t: T) {
803870 }
804871
805872 #[test]
806 #[ignore = "FIXME overlap edits in nested uses self"]
807873 fn convert_pat_uses_self() {
808874 check_assist(
809875 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<'_, '_>) -
101101 let last_descend = ctx.sema.descend_into_macros_single_exact(last.clone());
102102 let range = first_descend.text_range().cover(last_descend.text_range());
103103
104 if first_descend.parent_ancestors().last() != last_descend.parent_ancestors().last() {
104 if first_descend.tree_top() != last_descend.tree_top() {
105105 return None;
106106 }
107107
......@@ -110,6 +110,9 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -
110110 .skip_while(|it| !it.text_range().contains_range(range))
111111 .find_map(valid_target_expr(ctx))?;
112112 let original_range = ctx.sema.original_range(expr.syntax());
113 if !node.text_range().contains_range(original_range.range) {
114 return None;
115 }
113116 (cover_edit_range(&node, original_range.range), expr)
114117 } else {
115118 let expr = node
......@@ -198,13 +201,12 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -
198201 |edit| {
199202 let (var_name, expr_replace) = kind.get_name_and_expr(ctx, &analysis);
200203
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 };
208210
209211 let editor = edit.make_editor(&place);
210212 let make = editor.make();
......@@ -3027,4 +3029,9 @@ fn main() {
30273029 "Extract into variable",
30283030 );
30293031 }
3032
3033 #[test]
3034 fn repro_bad_range_unresolved_macro_paren() {
3035 check_assist_not_applicable(extract_variable, "fn f() { m!$0($0 }");
3036 }
30303037}
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs+52-10
......@@ -15,7 +15,7 @@ use syntax::{
1515 self, AssocItem, GenericParam, HasAttrs, HasGenericParams, HasName, HasTypeBounds,
1616 HasVisibility, edit::AstNodeEdit, syntax_factory::SyntaxFactory,
1717 },
18 syntax_editor::Position,
18 syntax_editor::{Position, Removable},
1919};
2020
2121// Assist: generate_blanket_trait_impl
......@@ -99,10 +99,15 @@ pub(crate) fn generate_blanket_trait_impl(
9999 ast::AssocItem::Fn(method) if method.body().is_none() => {
100100 todo_fn(make, &method, ctx.config).into()
101101 }
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 }
103108 _ => return None,
104109 };
105 Some(item.reset_indent().indent(1.into()))
110 Some(item.indent(1.into()))
106111 })
107112 .collect::<Vec<_>>();
108113 (!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
284289 )
285290}
286291
292fn 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
287302fn cfg_attrs(node: &impl HasAttrs) -> impl Iterator<Item = ast::Attr> {
288303 node.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_))))
289304}
......@@ -533,6 +548,33 @@ impl<T: ?Sized> Foo for $0T {
533548 );
534549 }
535550
551 #[test]
552 fn test_gen_blanket_assoc_items_with_default() {
553 check_assist(
554 generate_blanket_trait_impl,
555 r#"
556trait $0Foo {
557 type Item = ();
558
559 const N: usize = 3;
560
561 fn foo(&self) {}
562}
563"#,
564 r#"
565trait Foo {
566 type Item = ();
567
568 const N: usize = 3;
569
570 fn foo(&self) {}
571}
572
573impl<T: ?Sized> Foo for $0T {}
574"#,
575 );
576 }
577
536578 #[test]
537579 fn test_gen_blanket_indent() {
538580 check_assist(
......@@ -775,7 +817,7 @@ mod foo {
775817mod foo {
776818 mod bar {
777819 trait $0Foo {
778 type Item: Bar<
820 type Item where Self: Bar<
779821 Self,
780822 >;
781823
......@@ -790,7 +832,7 @@ mod foo {
790832mod foo {
791833 mod bar {
792834 trait Foo {
793 type Item: Bar<
835 type Item where Self: Bar<
794836 Self,
795837 >;
796838
......@@ -800,7 +842,7 @@ mod foo {
800842 }
801843
802844 impl<T: ?Sized> Foo for $0T {
803 type Item: Bar<
845 type Item where Self: Bar<
804846 Self,
805847 >;
806848
......@@ -894,7 +936,7 @@ impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1
894936where
895937 Self::Owned: Default,
896938{
897 type X: Sync;
939 type X;
898940
899941 fn foo(&self, x: Self::X) -> T {
900942 todo!()
......@@ -943,7 +985,7 @@ where
943985 Self: ToOwned,
944986 Self::Owned: Default,
945987{
946 type X: Sync;
988 type X;
947989
948990 fn foo(&self, x: Self::X) -> T {
949991 todo!()
......@@ -980,7 +1022,7 @@ trait Foo<T: Send> {
9801022}
9811023
9821024impl<T: Send, T1: ?Sized> Foo<T> for $0T1 {
983 type X: Sync;
1025 type X;
9841026
9851027 fn foo(&self, x: Self::X) -> T {
9861028 todo!()
......@@ -1017,7 +1059,7 @@ trait Foo {
10171059}
10181060
10191061impl<T: ?Sized> Foo for $0T {
1020 type X: Sync;
1062 type X;
10211063
10221064 fn foo(&self, x: Self::X) -> i32 {
10231065 todo!()
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs+75-13
......@@ -1,7 +1,10 @@
11use ide_db::{RootDatabase, famous_defs::FamousDefs};
2use syntax::ast::{self, AstNode, HasName};
2use syntax::{
3 ast::{self, AstNode, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory},
4 syntax_editor::{Position, SyntaxEditor},
5};
36
4use crate::{AssistContext, AssistId, Assists};
7use crate::{AssistContext, AssistId, Assists, utils};
58
69// Assist: generate_default_from_enum_variant
710//
......@@ -34,7 +37,7 @@ pub(crate) fn generate_default_from_enum_variant(
3437) -> Option<()> {
3538 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
3639 let variant_name = variant.name()?;
37 let enum_name = variant.parent_enum().name()?;
40 let adt = ast::Adt::Enum(variant.parent_enum());
3841 if !matches!(variant.kind(), ast::StructKind::Unit) {
3942 cov_mark::hit!(test_gen_default_on_non_unit_variant_not_implemented);
4043 return None;
......@@ -54,21 +57,54 @@ pub(crate) fn generate_default_from_enum_variant(
5457 "Generate `Default` impl from this enum variant",
5558 target,
5659 |edit| {
57 let start_offset = variant.parent_enum().syntax().text_range().end();
58 let buf = format!(
59 r#"
60
61impl 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 ],
6671 );
67 edit.insert(start_offset, buf);
72 edit.add_file_edits(ctx.vfs_file_id(), editor);
6873 },
6974 )
7075}
7176
77fn 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
88fn 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
72108fn existing_default_impl(
73109 sema: &'_ hir::Semantics<'_, RootDatabase>,
74110 variant: &ast::Variant,
......@@ -214,6 +250,32 @@ impl Default for Variant {
214250 Self::Undefined
215251 }
216252}
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
263enum Variant<T> {
264 Defined(T),
265 Undefi$0ned,
266}
267"#,
268 r#"
269enum Variant<T> {
270 Defined(T),
271 Undefined,
272}
273
274impl<T> Default for Variant<T> {
275 fn default() -> Self {
276 Self::Undefined
277 }
278}
217279"#,
218280 );
219281 }
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<'_, '_>
7979
8080 let function = ctx.sema.to_def(&ast_func)?;
8181
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;
8383 let params = get_fn_params(ctx.sema.db, function, &param_list, def_file_editor.make())?;
8484
8585 let mut file_editors = FxHashMap::default();
......@@ -255,7 +255,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Opt
255255 return None;
256256 }
257257 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;
259259 let params = get_fn_params(ctx.sema.db, function, &param_list, editor.make())?;
260260
261261 if call_info.arguments.len() != params.len() {
......@@ -1570,11 +1570,8 @@ async fn foo(arg: u32) -> u32 {
15701570}
15711571fn spawn<T>(_: T) {}
15721572fn 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
15781575 });
15791576}
15801577"#,
......@@ -1605,12 +1602,9 @@ async fn foo(arg: u32) -> u32 {
16051602}
16061603fn spawn<T>(_: T) {}
16071604fn 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
16141608 });
16151609}
16161610"#,
......@@ -1645,11 +1639,10 @@ fn spawn<T>(_: T) {}
16451639fn main() {
16461640 let var = 42;
16471641 spawn({
1648 let x = var;
16491642 let y = var + 1;
16501643 let z: &u32 = &var;
16511644 async move {
1652 bar(x).await;
1645 bar(var).await;
16531646 y + y + *z
16541647 }
16551648 });
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
3636
3737 let use_item = tree.syntax().parent().and_then(ast::Use::cast)?;
3838 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());
4040 merge_uses(use_item, vec![neighbor], &ctx.config.insert_use, &editor)?;
4141 (target, editor)
4242 } else {
......@@ -51,7 +51,7 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> O
5151 });
5252
5353 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());
5555 match_ast! {
5656 match first_selected {
5757 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<'_, '_>) -
2525 };
2626
2727 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());
2929 let normalized_use_item =
3030 try_normalize_import(editor.make(), &use_item, ctx.config.insert_use.granularity.into())?;
3131 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<'_,
6363 return None;
6464 }
6565
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
6671 acc.add(
6772 AssistId::refactor("promote_local_to_const"),
6873 "Promote local to constant",
......@@ -70,15 +75,14 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_,
7075 |edit| {
7176 let editor = edit.make_editor(let_stmt.syntax());
7277 let make = editor.make();
73 let name = to_upper_snake_case(&name.to_string());
7478 let usages = Definition::Local(local).usages(&ctx.sema).all();
7579 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);
7781
7882 for usage in usages {
7983 let Some(usage_name) = usage.name.as_name_ref().cloned() else { continue };
8084 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);
8286 let name_expr = make.expr_path(path);
8387 utils::replace_record_field_expr(ctx, edit, record_field, name_expr);
8488 } else {
......@@ -88,7 +92,8 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_,
8892 }
8993 }
9094
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);
9297
9398 if let Some((cap, name)) = ctx.config.snippet_cap.zip(item.name()) {
9499 let tabstop = edit.make_tabstop_before(cap);
......@@ -292,6 +297,19 @@ fn foo() {
292297 );
293298 }
294299
300 #[test]
301 fn not_applicable_when_name_converts_to_all_underscores() {
302 check_assist_not_applicable(
303 promote_local_to_const,
304 r"
305fn foo() {
306 let _$0_ = 0;
307 __;
308}
309",
310 );
311 }
312
295313 #[test]
296314 fn not_applicable_non_simple_ident() {
297315 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<'_, '_>)
5757 }
5858
5959 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
6066 acc.add(
6167 AssistId::refactor("remove_underscore_from_used_variables"),
6268 "Remove underscore from a used variable",
6369 text_range,
6470 |builder| {
65 let changes = def
66 .rename(&ctx.sema, new_name, RenameDefinition::Yes, &ctx.config.rename_config())
67 .unwrap();
6871 builder.source_change = changes;
6972 },
7073 )
......@@ -175,6 +178,32 @@ fn foo(foo: i32) {
175178 )
176179 }
177180
181 #[test]
182 fn not_applicable_when_result_is_keyword() {
183 check_assist_not_applicable(
184 remove_underscore,
185 r#"
186fn 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#"
199fn main() {
200 let _$0_ = 1;
201 __;
202}
203"#,
204 );
205 }
206
178207 #[test]
179208 fn remove_underscore_in_function_parameter() {
180209 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;
44
55use ide_db::{RootDatabase, defs::NameClass, ty_filter::TryEnum};
66use syntax::{
7 AstNode, Edition, SyntaxKind, T, TextRange,
7 AstNode, SyntaxKind, T, TextRange,
88 ast::{
99 self, HasName,
1010 edit::{AstNodeEdit, IndentLevel},
......@@ -241,28 +241,19 @@ pub(crate) fn replace_match_with_if_let(
241241 return None;
242242 }
243243
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 {
250250 return None;
251251 }
252252
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)?;
262254 let scrutinee = match_expr.expr()?.reset_indent();
263 let guard = guard.and_then(|it| it.condition());
264255
265 let let_ = match &if_let_pat {
256 let let_ = match &if_exprs.first()?.0 {
266257 ast::Pat::LiteralPat(p)
267258 if p.literal()
268259 .map(|it| it.token().kind())
......@@ -289,36 +280,51 @@ pub(crate) fn replace_match_with_if_let(
289280 }
290281 };
291282
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
300302 {
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
312318 let else_expr = else_expr.reset_indent();
313 let then_block = make_block_expr(then_expr);
314319 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());
322328
323329 editor.replace(match_expr.syntax(), if_let_expr.syntax());
324330 builder.add_file_edits(ctx.vfs_file_id(), editor);
......@@ -329,37 +335,33 @@ pub(crate) fn replace_match_with_if_let(
329335/// Pick the pattern for the if let condition and return the expressions for the `then` body and `else` body in that order.
330336fn pick_pattern_and_expr_order(
331337 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() {
340341 return None;
341342 }
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
363365}
364366
365367fn is_empty_expr(expr: &ast::Expr) -> bool {
......@@ -2565,6 +2567,60 @@ fn main() {
25652567 );
25662568 }
25672569
2570 #[test]
2571 fn test_replace_match_multi_arms_with_if_let() {
2572 check_assist(
2573 replace_match_with_if_let,
2574 r#"
2575fn 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#"
2584fn 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#"
2602fn 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#"
2611fn 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
25682624 #[test]
25692625 fn test_replace_match_with_if_let_not_applicable_pat2_is_ident_pat() {
25702626 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<'_, '_>)
8686 // - After the arm. In this case we always want to insert a comma after the newly
8787 // inserted arm.
8888 // - 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
9090 // body is a block, but we don't bother to check that.
9191 // - Missing after the arm with arms after, if the arm body is a block. In this case
9292 // 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<'_, '_>)
113113
114114 let arg_list = call_expr.arg_list().unwrap();
115115 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 );
121119 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());
124129 }
125 Either::Right(stmt_list) => {
130 Some(Either::Right(stmt_list)) => {
126131 let new_block = if stmt_list.statements().next().is_none() {
127132 make.expr_empty_block()
128133 } else {
......@@ -133,6 +138,10 @@ pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_, '_>)
133138 new_block.stmt_list().unwrap().syntax(),
134139 );
135140 }
141 // Parent is a match arm or similar — replace with ()
142 None => {
143 editor.replace(tail_expr.syntax(), make.expr_unit().syntax());
144 }
136145 }
137146 } else if let Some(first_arg) = arg_list.args().next() {
138147 editor.replace(tail_expr.syntax(), first_arg.syntax());
......@@ -2245,6 +2254,102 @@ fn foo(the_field: u32) -> u32 {
22452254 );
22462255 }
22472256
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
2263fn foo(flag: bool) -> Option<()$0> {
2264 match flag {
2265 true => Some(()),
2266 false => None,
2267 }
2268}
2269"#,
2270 r#"
2271fn 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
2288fn foo() -> Option<()$0> {
2289 loop {
2290 break Some(());
2291 }
2292}
2293"#,
2294 r#"
2295fn 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
2311fn foo() -> Option<()$0> {
2312 'outer: loop {
2313 break 'outer Some(());
2314 }
2315}
2316"#,
2317 r#"
2318fn 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
2334fn foo(flag: bool) -> Result<(), ()$0> {
2335 match flag {
2336 true => Ok(()),
2337 false => Err(()),
2338 }
2339}
2340"#,
2341 r#"
2342fn foo(flag: bool) {
2343 match flag {
2344 true => (),
2345 false => (),
2346 }
2347}
2348"#,
2349 "Unwrap Result return type",
2350 );
2351 }
2352
22482353 #[test]
22492354 fn unwrap_result_return_type_nested_type() {
22502355 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(
127127 }
128128 let qualifier_path =
129129 if let Qualified::With { path, .. } = qualified { Some(path) } else { None };
130 let qualifier_segments = qualifier_path.iter().flat_map(|q| q.segments()).collect::<Vec<_>>();
130131
131132 let attributes = annotated_item_kind.and_then(|kind| {
132133 if ast::Expr::can_cast(kind) {
......@@ -141,9 +142,8 @@ pub(crate) fn complete_attribute_path(
141142 // add the missing parts to the label and snippet
142143 let mut label = attr_completion.label.to_owned();
143144 let mut snippet = attr_completion.snippet.map(|s| s.to_owned());
144 let segments = qualifier_path.iter().flat_map(|q| q.segments()).collect::<Vec<_>>();
145145 let qualifiers = attr_completion.qualifiers;
146 let matching_qualifiers = segments
146 let matching_qualifiers = qualifier_segments
147147 .iter()
148148 .zip(qualifiers)
149149 .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 {
10461046 );
10471047 }
10481048
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)]
1056fn f() {}
1057"#,
1058 expect![[r#"
1059 ba all
1060 ba any
1061 ba feature
1062 ba not
1063 ba true
1064 "#]],
1065 );
1066 }
1067
10491068 #[test]
10501069 fn complete_key_attr() {
10511070 check_edit(
src/tools/rust-analyzer/crates/ide-db/src/lib.rs+4-7
......@@ -63,10 +63,7 @@ use base_db::{
6363 CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, Nonce, SourceDatabase,
6464 SourceRoot, SourceRootId, SourceRootInput, set_all_crates_with_durability,
6565};
66use hir::{
67 FilePositionWrapper, FileRangeWrapper,
68 db::{DefDatabase, ExpandDatabase, HirDatabase},
69};
66use hir::{FilePositionWrapper, FileRangeWrapper, db::HirDatabase};
7067use triomphe::Arc;
7168
7269use crate::line_index::LineIndex;
......@@ -203,20 +200,20 @@ impl RootDatabase {
203200 // This needs to be here otherwise `CrateGraphBuilder` will panic.
204201 set_all_crates_with_durability(&mut db, std::iter::empty(), Durability::HIGH);
205202 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);
207204 _ = base_db::LibraryRoots::builder(Default::default())
208205 .durability(Durability::MEDIUM)
209206 .new(&db);
210207 _ = base_db::LocalRoots::builder(Default::default())
211208 .durability(Durability::MEDIUM)
212209 .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);
214211 db.update_base_query_lru_capacities(lru_capacity);
215212 db
216213 }
217214
218215 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);
220217 }
221218
222219 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 {
164164 .into_iter()
165165 .zip(1..)
166166 .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 };
174170
175171 match snippet {
176172 Snippet::Tabstop(pos) => vec![(index, TextRange::empty(pos))],
......@@ -264,7 +260,7 @@ impl SourceChangeBuilder {
264260 }
265261
266262 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
268264 }
269265
270266 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 @@
22 (
33 Module {
44 id: ModuleIdLt {
5 [salsa id]: Id(3000),
5 [salsa id]: Id(2800),
66 },
77 },
88 [
......@@ -12,7 +12,7 @@
1212 Struct(
1313 Struct {
1414 id: StructId(
15 3801,
15 3001,
1616 ),
1717 },
1818 ),
......@@ -20,7 +20,7 @@
2020 loc: DeclarationLocation {
2121 hir_file_id: FileId(
2222 EditionedFileId(
23 Id(2c00),
23 Id(2400),
2424 ),
2525 ),
2626 ptr: SyntaxNodePtr {
......@@ -49,7 +49,7 @@
4949 Struct(
5050 Struct {
5151 id: StructId(
52 3800,
52 3000,
5353 ),
5454 },
5555 ),
......@@ -57,7 +57,7 @@
5757 loc: DeclarationLocation {
5858 hir_file_id: FileId(
5959 EditionedFileId(
60 Id(2c00),
60 Id(2400),
6161 ),
6262 ),
6363 ptr: SyntaxNodePtr {
......@@ -86,7 +86,7 @@
8686 Struct(
8787 Struct {
8888 id: StructId(
89 3800,
89 3000,
9090 ),
9191 },
9292 ),
......@@ -94,7 +94,7 @@
9494 loc: DeclarationLocation {
9595 hir_file_id: FileId(
9696 EditionedFileId(
97 Id(2c00),
97 Id(2400),
9898 ),
9999 ),
100100 ptr: SyntaxNodePtr {
......@@ -123,7 +123,7 @@
123123 Struct(
124124 Struct {
125125 id: StructId(
126 3800,
126 3000,
127127 ),
128128 },
129129 ),
......@@ -131,7 +131,7 @@
131131 loc: DeclarationLocation {
132132 hir_file_id: FileId(
133133 EditionedFileId(
134 Id(2c00),
134 Id(2400),
135135 ),
136136 ),
137137 ptr: SyntaxNodePtr {
......@@ -160,7 +160,7 @@
160160 Struct(
161161 Struct {
162162 id: StructId(
163 3800,
163 3000,
164164 ),
165165 },
166166 ),
......@@ -168,7 +168,7 @@
168168 loc: DeclarationLocation {
169169 hir_file_id: FileId(
170170 EditionedFileId(
171 Id(2c00),
171 Id(2400),
172172 ),
173173 ),
174174 ptr: SyntaxNodePtr {
......@@ -197,7 +197,7 @@
197197 Struct(
198198 Struct {
199199 id: StructId(
200 3801,
200 3001,
201201 ),
202202 },
203203 ),
......@@ -205,7 +205,7 @@
205205 loc: DeclarationLocation {
206206 hir_file_id: FileId(
207207 EditionedFileId(
208 Id(2c00),
208 Id(2400),
209209 ),
210210 ),
211211 ptr: SyntaxNodePtr {
......@@ -234,7 +234,7 @@
234234 Struct(
235235 Struct {
236236 id: StructId(
237 3800,
237 3000,
238238 ),
239239 },
240240 ),
......@@ -242,7 +242,7 @@
242242 loc: DeclarationLocation {
243243 hir_file_id: FileId(
244244 EditionedFileId(
245 Id(2c00),
245 Id(2400),
246246 ),
247247 ),
248248 ptr: SyntaxNodePtr {
src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt+69-69
......@@ -2,7 +2,7 @@
22 (
33 Module {
44 id: ModuleIdLt {
5 [salsa id]: Id(3000),
5 [salsa id]: Id(2800),
66 },
77 },
88 [
......@@ -11,14 +11,14 @@
1111 def: EnumVariant(
1212 EnumVariant {
1313 id: EnumVariantId(
14 7800,
14 7000,
1515 ),
1616 },
1717 ),
1818 loc: DeclarationLocation {
1919 hir_file_id: FileId(
2020 EditionedFileId(
21 Id(2c00),
21 Id(2400),
2222 ),
2323 ),
2424 ptr: SyntaxNodePtr {
......@@ -48,14 +48,14 @@
4848 def: TypeAlias(
4949 TypeAlias {
5050 id: TypeAliasId(
51 6c00,
51 6400,
5252 ),
5353 },
5454 ),
5555 loc: DeclarationLocation {
5656 hir_file_id: FileId(
5757 EditionedFileId(
58 Id(2c00),
58 Id(2400),
5959 ),
6060 ),
6161 ptr: SyntaxNodePtr {
......@@ -83,14 +83,14 @@
8383 def: EnumVariant(
8484 EnumVariant {
8585 id: EnumVariantId(
86 7801,
86 7001,
8787 ),
8888 },
8989 ),
9090 loc: DeclarationLocation {
9191 hir_file_id: FileId(
9292 EditionedFileId(
93 Id(2c00),
93 Id(2400),
9494 ),
9595 ),
9696 ptr: SyntaxNodePtr {
......@@ -120,14 +120,14 @@
120120 def: Const(
121121 Const {
122122 id: ConstId(
123 6400,
123 5c00,
124124 ),
125125 },
126126 ),
127127 loc: DeclarationLocation {
128128 hir_file_id: FileId(
129129 EditionedFileId(
130 Id(2c00),
130 Id(2400),
131131 ),
132132 ),
133133 ptr: SyntaxNodePtr {
......@@ -155,14 +155,14 @@
155155 def: Const(
156156 Const {
157157 id: ConstId(
158 6402,
158 5c02,
159159 ),
160160 },
161161 ),
162162 loc: DeclarationLocation {
163163 hir_file_id: FileId(
164164 EditionedFileId(
165 Id(2c00),
165 Id(2400),
166166 ),
167167 ),
168168 ptr: SyntaxNodePtr {
......@@ -191,7 +191,7 @@
191191 Enum(
192192 Enum {
193193 id: EnumId(
194 5000,
194 4800,
195195 ),
196196 },
197197 ),
......@@ -199,7 +199,7 @@
199199 loc: DeclarationLocation {
200200 hir_file_id: FileId(
201201 EditionedFileId(
202 Id(2c00),
202 Id(2400),
203203 ),
204204 ),
205205 ptr: SyntaxNodePtr {
......@@ -228,7 +228,7 @@
228228 Macro {
229229 id: Macro2Id(
230230 Macro2Id(
231 4c00,
231 4400,
232232 ),
233233 ),
234234 },
......@@ -236,7 +236,7 @@
236236 loc: DeclarationLocation {
237237 hir_file_id: FileId(
238238 EditionedFileId(
239 Id(2c00),
239 Id(2400),
240240 ),
241241 ),
242242 ptr: SyntaxNodePtr {
......@@ -265,7 +265,7 @@
265265 Macro {
266266 id: Macro2Id(
267267 Macro2Id(
268 4c00,
268 4400,
269269 ),
270270 ),
271271 },
......@@ -273,7 +273,7 @@
273273 loc: DeclarationLocation {
274274 hir_file_id: FileId(
275275 EditionedFileId(
276 Id(2c00),
276 Id(2400),
277277 ),
278278 ),
279279 ptr: SyntaxNodePtr {
......@@ -301,14 +301,14 @@
301301 def: Static(
302302 Static {
303303 id: StaticId(
304 6800,
304 6000,
305305 ),
306306 },
307307 ),
308308 loc: DeclarationLocation {
309309 hir_file_id: FileId(
310310 EditionedFileId(
311 Id(2c00),
311 Id(2400),
312312 ),
313313 ),
314314 ptr: SyntaxNodePtr {
......@@ -337,7 +337,7 @@
337337 Struct(
338338 Struct {
339339 id: StructId(
340 4801,
340 4001,
341341 ),
342342 },
343343 ),
......@@ -345,7 +345,7 @@
345345 loc: DeclarationLocation {
346346 hir_file_id: FileId(
347347 EditionedFileId(
348 Id(2c00),
348 Id(2400),
349349 ),
350350 ),
351351 ptr: SyntaxNodePtr {
......@@ -374,7 +374,7 @@
374374 Struct(
375375 Struct {
376376 id: StructId(
377 4800,
377 4000,
378378 ),
379379 },
380380 ),
......@@ -382,7 +382,7 @@
382382 loc: DeclarationLocation {
383383 hir_file_id: MacroFile(
384384 MacroCallId(
385 Id(4000),
385 Id(3800),
386386 ),
387387 ),
388388 ptr: SyntaxNodePtr {
......@@ -411,7 +411,7 @@
411411 Struct(
412412 Struct {
413413 id: StructId(
414 4805,
414 4005,
415415 ),
416416 },
417417 ),
......@@ -419,7 +419,7 @@
419419 loc: DeclarationLocation {
420420 hir_file_id: FileId(
421421 EditionedFileId(
422 Id(2c00),
422 Id(2400),
423423 ),
424424 ),
425425 ptr: SyntaxNodePtr {
......@@ -450,7 +450,7 @@
450450 Struct(
451451 Struct {
452452 id: StructId(
453 4806,
453 4006,
454454 ),
455455 },
456456 ),
......@@ -458,7 +458,7 @@
458458 loc: DeclarationLocation {
459459 hir_file_id: FileId(
460460 EditionedFileId(
461 Id(2c00),
461 Id(2400),
462462 ),
463463 ),
464464 ptr: SyntaxNodePtr {
......@@ -489,7 +489,7 @@
489489 Struct(
490490 Struct {
491491 id: StructId(
492 4807,
492 4007,
493493 ),
494494 },
495495 ),
......@@ -497,7 +497,7 @@
497497 loc: DeclarationLocation {
498498 hir_file_id: FileId(
499499 EditionedFileId(
500 Id(2c00),
500 Id(2400),
501501 ),
502502 ),
503503 ptr: SyntaxNodePtr {
......@@ -526,7 +526,7 @@
526526 Struct(
527527 Struct {
528528 id: StructId(
529 4802,
529 4002,
530530 ),
531531 },
532532 ),
......@@ -534,7 +534,7 @@
534534 loc: DeclarationLocation {
535535 hir_file_id: FileId(
536536 EditionedFileId(
537 Id(2c00),
537 Id(2400),
538538 ),
539539 ),
540540 ptr: SyntaxNodePtr {
......@@ -562,14 +562,14 @@
562562 def: Trait(
563563 Trait {
564564 id: TraitId(
565 5c00,
565 5400,
566566 ),
567567 },
568568 ),
569569 loc: DeclarationLocation {
570570 hir_file_id: FileId(
571571 EditionedFileId(
572 Id(2c00),
572 Id(2400),
573573 ),
574574 ),
575575 ptr: SyntaxNodePtr {
......@@ -598,7 +598,7 @@
598598 Macro {
599599 id: Macro2Id(
600600 Macro2Id(
601 4c00,
601 4400,
602602 ),
603603 ),
604604 },
......@@ -606,7 +606,7 @@
606606 loc: DeclarationLocation {
607607 hir_file_id: FileId(
608608 EditionedFileId(
609 Id(2c00),
609 Id(2400),
610610 ),
611611 ),
612612 ptr: SyntaxNodePtr {
......@@ -635,7 +635,7 @@
635635 Union(
636636 Union {
637637 id: UnionId(
638 5400,
638 4c00,
639639 ),
640640 },
641641 ),
......@@ -643,7 +643,7 @@
643643 loc: DeclarationLocation {
644644 hir_file_id: FileId(
645645 EditionedFileId(
646 Id(2c00),
646 Id(2400),
647647 ),
648648 ),
649649 ptr: SyntaxNodePtr {
......@@ -671,14 +671,14 @@
671671 def: Module(
672672 Module {
673673 id: ModuleIdLt {
674 [salsa id]: Id(3001),
674 [salsa id]: Id(2801),
675675 },
676676 },
677677 ),
678678 loc: DeclarationLocation {
679679 hir_file_id: FileId(
680680 EditionedFileId(
681 Id(2c00),
681 Id(2400),
682682 ),
683683 ),
684684 ptr: SyntaxNodePtr {
......@@ -706,14 +706,14 @@
706706 def: Module(
707707 Module {
708708 id: ModuleIdLt {
709 [salsa id]: Id(3002),
709 [salsa id]: Id(2802),
710710 },
711711 },
712712 ),
713713 loc: DeclarationLocation {
714714 hir_file_id: FileId(
715715 EditionedFileId(
716 Id(2c00),
716 Id(2400),
717717 ),
718718 ),
719719 ptr: SyntaxNodePtr {
......@@ -742,7 +742,7 @@
742742 Macro {
743743 id: MacroRulesId(
744744 MacroRulesId(
745 3c01,
745 3401,
746746 ),
747747 ),
748748 },
......@@ -750,7 +750,7 @@
750750 loc: DeclarationLocation {
751751 hir_file_id: FileId(
752752 EditionedFileId(
753 Id(2c00),
753 Id(2400),
754754 ),
755755 ),
756756 ptr: SyntaxNodePtr {
......@@ -778,14 +778,14 @@
778778 def: Function(
779779 FunctionId(
780780 FunctionId(
781 6002,
781 5802,
782782 ),
783783 ),
784784 ),
785785 loc: DeclarationLocation {
786786 hir_file_id: FileId(
787787 EditionedFileId(
788 Id(2c00),
788 Id(2400),
789789 ),
790790 ),
791791 ptr: SyntaxNodePtr {
......@@ -815,14 +815,14 @@
815815 def: Function(
816816 FunctionId(
817817 FunctionId(
818 6001,
818 5801,
819819 ),
820820 ),
821821 ),
822822 loc: DeclarationLocation {
823823 hir_file_id: FileId(
824824 EditionedFileId(
825 Id(2c00),
825 Id(2400),
826826 ),
827827 ),
828828 ptr: SyntaxNodePtr {
......@@ -853,7 +853,7 @@
853853 Macro {
854854 id: MacroRulesId(
855855 MacroRulesId(
856 3c00,
856 3400,
857857 ),
858858 ),
859859 },
......@@ -861,7 +861,7 @@
861861 loc: DeclarationLocation {
862862 hir_file_id: FileId(
863863 EditionedFileId(
864 Id(2c00),
864 Id(2400),
865865 ),
866866 ),
867867 ptr: SyntaxNodePtr {
......@@ -889,14 +889,14 @@
889889 def: Function(
890890 FunctionId(
891891 FunctionId(
892 6000,
892 5800,
893893 ),
894894 ),
895895 ),
896896 loc: DeclarationLocation {
897897 hir_file_id: FileId(
898898 EditionedFileId(
899 Id(2c00),
899 Id(2400),
900900 ),
901901 ),
902902 ptr: SyntaxNodePtr {
......@@ -925,7 +925,7 @@
925925 Macro {
926926 id: MacroRulesId(
927927 MacroRulesId(
928 3c01,
928 3401,
929929 ),
930930 ),
931931 },
......@@ -933,7 +933,7 @@
933933 loc: DeclarationLocation {
934934 hir_file_id: FileId(
935935 EditionedFileId(
936 Id(2c00),
936 Id(2400),
937937 ),
938938 ),
939939 ptr: SyntaxNodePtr {
......@@ -961,14 +961,14 @@
961961 def: Function(
962962 FunctionId(
963963 FunctionId(
964 6003,
964 5803,
965965 ),
966966 ),
967967 ),
968968 loc: DeclarationLocation {
969969 hir_file_id: FileId(
970970 EditionedFileId(
971 Id(2c00),
971 Id(2400),
972972 ),
973973 ),
974974 ptr: SyntaxNodePtr {
......@@ -998,7 +998,7 @@
998998 (
999999 Module {
10001000 id: ModuleIdLt {
1001 [salsa id]: Id(3001),
1001 [salsa id]: Id(2801),
10021002 },
10031003 },
10041004 [
......@@ -1008,7 +1008,7 @@
10081008 Struct(
10091009 Struct {
10101010 id: StructId(
1011 4803,
1011 4003,
10121012 ),
10131013 },
10141014 ),
......@@ -1016,7 +1016,7 @@
10161016 loc: DeclarationLocation {
10171017 hir_file_id: FileId(
10181018 EditionedFileId(
1019 Id(2c00),
1019 Id(2400),
10201020 ),
10211021 ),
10221022 ptr: SyntaxNodePtr {
......@@ -1044,7 +1044,7 @@
10441044 (
10451045 Module {
10461046 id: ModuleIdLt {
1047 [salsa id]: Id(3002),
1047 [salsa id]: Id(2802),
10481048 },
10491049 },
10501050 [
......@@ -1053,14 +1053,14 @@
10531053 def: Trait(
10541054 Trait {
10551055 id: TraitId(
1056 5c00,
1056 5400,
10571057 ),
10581058 },
10591059 ),
10601060 loc: DeclarationLocation {
10611061 hir_file_id: FileId(
10621062 EditionedFileId(
1063 Id(2c01),
1063 Id(2401),
10641064 ),
10651065 ),
10661066 ptr: SyntaxNodePtr {
......@@ -1089,7 +1089,7 @@
10891089 Macro {
10901090 id: Macro2Id(
10911091 Macro2Id(
1092 4c00,
1092 4400,
10931093 ),
10941094 ),
10951095 },
......@@ -1097,7 +1097,7 @@
10971097 loc: DeclarationLocation {
10981098 hir_file_id: FileId(
10991099 EditionedFileId(
1100 Id(2c01),
1100 Id(2401),
11011101 ),
11021102 ),
11031103 ptr: SyntaxNodePtr {
......@@ -1126,7 +1126,7 @@
11261126 Struct(
11271127 Struct {
11281128 id: StructId(
1129 4804,
1129 4004,
11301130 ),
11311131 },
11321132 ),
......@@ -1134,7 +1134,7 @@
11341134 loc: DeclarationLocation {
11351135 hir_file_id: FileId(
11361136 EditionedFileId(
1137 Id(2c01),
1137 Id(2401),
11381138 ),
11391139 ),
11401140 ptr: SyntaxNodePtr {
......@@ -1163,7 +1163,7 @@
11631163 Macro {
11641164 id: Macro2Id(
11651165 Macro2Id(
1166 4c00,
1166 4400,
11671167 ),
11681168 ),
11691169 },
......@@ -1171,7 +1171,7 @@
11711171 loc: DeclarationLocation {
11721172 hir_file_id: FileId(
11731173 EditionedFileId(
1174 Id(2c01),
1174 Id(2401),
11751175 ),
11761176 ),
11771177 ptr: SyntaxNodePtr {
......@@ -1200,7 +1200,7 @@
12001200 Struct(
12011201 Struct {
12021202 id: StructId(
1203 4804,
1203 4004,
12041204 ),
12051205 },
12061206 ),
......@@ -1208,7 +1208,7 @@
12081208 loc: DeclarationLocation {
12091209 hir_file_id: FileId(
12101210 EditionedFileId(
1211 Id(2c01),
1211 Id(2401),
12121212 ),
12131213 ),
12141214 ptr: SyntaxNodePtr {
src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_exclude_imports.txt+2-2
......@@ -5,7 +5,7 @@
55 Struct(
66 Struct {
77 id: StructId(
8 3c00,
8 3400,
99 ),
1010 },
1111 ),
......@@ -13,7 +13,7 @@
1313 loc: DeclarationLocation {
1414 hir_file_id: FileId(
1515 EditionedFileId(
16 Id(2c01),
16 Id(2401),
1717 ),
1818 ),
1919 ptr: SyntaxNodePtr {
src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_with_imports.txt+4-4
......@@ -5,7 +5,7 @@
55 Struct(
66 Struct {
77 id: StructId(
8 3c00,
8 3400,
99 ),
1010 },
1111 ),
......@@ -13,7 +13,7 @@
1313 loc: DeclarationLocation {
1414 hir_file_id: FileId(
1515 EditionedFileId(
16 Id(2c01),
16 Id(2401),
1717 ),
1818 ),
1919 ptr: SyntaxNodePtr {
......@@ -42,7 +42,7 @@
4242 Struct(
4343 Struct {
4444 id: StructId(
45 3c00,
45 3400,
4646 ),
4747 },
4848 ),
......@@ -50,7 +50,7 @@
5050 loc: DeclarationLocation {
5151 hir_file_id: FileId(
5252 EditionedFileId(
53 Id(2c00),
53 Id(2400),
5454 ),
5555 ),
5656 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>() {
539539"#,
540540 );
541541 }
542
543 #[test]
544 fn cfg_inside_macro_inside_arg() {
545 check_diagnostics(
546 r#"
547fn foo() {}
548
549macro_rules! make_X {
550 () => { #[cfg(false)] X };
551}
552
553fn main() {
554 foo(make_X!());
555}
556 "#,
557 );
558 }
542559}
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
117117 });
118118
119119 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();
121121 let (editor, _) = SyntaxEditor::new(root);
122122 let make = editor.make();
123123
......@@ -178,7 +178,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::MissingFields) -> Option<Vec
178178 let missing_fields = ctx.sema.record_pattern_missing_fields(field_list_parent);
179179
180180 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();
182182 let (editor, _) = SyntaxEditor::new(root);
183183 let make = editor.make();
184184
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mut_ref_in_imm_ref_pat.rs created+37
......@@ -0,0 +1,37 @@
1use 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.
7pub(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)]
21mod 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
30fn 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<
7474 remove_unnecessary_wrapper(ctx, d, expr_ptr, &mut fixes);
7575 remove_semicolon(ctx, d, expr_ptr, &mut fixes);
7676 str_ref_to_owned(ctx, d, expr_ptr, &mut fixes);
77 add_await(ctx, d, expr_ptr, &mut fixes);
7778 }
7879
7980 if fixes.is_empty() { None } else { Some(fixes) }
......@@ -377,6 +378,30 @@ fn str_ref_to_owned(
377378 Some(())
378379}
379380
381fn 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
380405#[cfg(test)]
381406mod tests {
382407 use crate::tests::{
......@@ -1394,6 +1419,47 @@ identity! {
13941419 );
13951420 }
13961421
1422 #[test]
1423 fn add_await() {
1424 check_fix(
1425 r#"
1426//- minicore: future
1427async fn foo() -> u32 { 2 }
1428async fn test() {
1429 let x: u32 = foo()$0;
1430}
1431 "#,
1432 r#"
1433async fn foo() -> u32 { 2 }
1434async fn test() {
1435 let x: u32 = foo().await;
1436}
1437 "#,
1438 );
1439
1440 check_fix(
1441 r#"
1442//- minicore: future
1443macro_rules! identity { ($($t:tt)*) => ($($t)*) }
1444async fn foo() -> u32 { 2 }
1445identity! {
1446 async fn test() {
1447 let x: u32 = foo()$0;
1448 }
1449}
1450 "#,
1451 r#"
1452macro_rules! identity { ($($t:tt)*) => ($($t)*) }
1453async fn foo() -> u32 { 2 }
1454identity! {
1455 async fn test() {
1456 let x: u32 = foo().await;
1457 }
1458}
1459 "#,
1460 );
1461 }
1462
13971463 #[test]
13981464 fn type_mismatch_range_adjustment() {
13991465 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 @@
1use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
2
3// Diagnostic: union-pat-has-rest
4//
5// A union pattern uses `..`.
6pub(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)]
20mod tests {
21 use crate::tests::check_diagnostics;
22
23 #[test]
24 fn union_pat_has_rest() {
25 check_diagnostics(
26 r#"
27union Bird {
28 pigeon: u8,
29 turtledove: u16,
30}
31
32fn 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 @@
1use 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.
6pub(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)]
20mod tests {
21 use crate::tests::check_diagnostics;
22
23 #[test]
24 fn union_pat_must_have_exactly_one_field() {
25 check_diagnostics(
26 r#"
27union Bird {
28 pigeon: u8,
29 turtledove: u16,
30}
31
32fn 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 @@
1use 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.
6pub(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)]
19mod tests {
20 use crate::tests::check_diagnostics;
21
22 #[test]
23 fn yield_in_regular_function() {
24 check_diagnostics(
25 r#"
26//- minicore: coroutine
27fn 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 {
6565 pub(crate) mod missing_match_arms;
6666 pub(crate) mod missing_unsafe;
6767 pub(crate) mod moved_out_of_ref;
68 pub(crate) mod mut_ref_in_imm_ref_pat;
6869 pub(crate) mod mutability_errors;
6970 pub(crate) mod mutable_ref;
7071 pub(crate) mod no_such_field;
......@@ -89,6 +90,8 @@ mod handlers {
8990 pub(crate) mod unimplemented_builtin_macro;
9091 pub(crate) mod unimplemented_trait;
9192 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;
9295 pub(crate) mod unreachable_label;
9396 pub(crate) mod unresolved_assoc_item;
9497 pub(crate) mod unresolved_extern_crate;
......@@ -100,6 +103,7 @@ mod handlers {
100103 pub(crate) mod unresolved_module;
101104 pub(crate) mod unused_must_use;
102105 pub(crate) mod unused_variables;
106 pub(crate) mod yield_outside_coroutine;
103107
104108 // The handlers below are unusual, the implement the diagnostics as well.
105109 pub(crate) mod field_shorthand;
......@@ -479,6 +483,7 @@ pub fn semantic_diagnostics(
479483 AnyDiagnostic::MissingMatchArms(d) => handlers::missing_match_arms::missing_match_arms(&ctx, &d),
480484 AnyDiagnostic::MissingUnsafe(d) => handlers::missing_unsafe::missing_unsafe(&ctx, &d),
481485 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),
482487 AnyDiagnostic::MutableRefBinding(d) => handlers::mutable_ref::mutable_ref_binding(&ctx, &d),
483488 AnyDiagnostic::NeedMut(d) => match handlers::mutability_errors::need_mut(&ctx, &d) {
484489 Some(it) => it,
......@@ -548,9 +553,16 @@ pub fn semantic_diagnostics(
548553 AnyDiagnostic::TypeMustBeKnown(d) => handlers::type_must_be_known::type_must_be_known(&ctx, &d),
549554 AnyDiagnostic::PatternArgInExternFn(d) => handlers::pattern_arg_in_extern_fn::pattern_arg_in_extern_fn(&ctx, &d),
550555 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 }
551562 AnyDiagnostic::UnimplementedTrait(d) => handlers::unimplemented_trait::unimplemented_trait(&ctx, &d),
552563 AnyDiagnostic::FruInDestructuringAssignment(d) => handlers::fru_in_destructuring_assignment::fru_in_destructuring_assignment(&ctx, &d),
553564 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),
554566 };
555567 res.push(d)
556568 }
src/tools/rust-analyzer/crates/ide-ssr/src/fragments.rs+14-11
......@@ -6,7 +6,7 @@
66//! needs to determine it somehow. We do this in a stupid way -- by pasting SSR
77//! rule into different contexts and checking what works.
88
9use syntax::{AstNode, SyntaxNode, ast};
9use syntax::{AstNode, SyntaxNode, ast, syntax_editor::SyntaxEditor};
1010
1111pub(crate) fn ty(s: &str) -> Result<SyntaxNode, ()> {
1212 fragment::<ast::Type>("type T = {};", s)
......@@ -31,18 +31,20 @@ pub(crate) fn stmt(s: &str) -> Result<SyntaxNode, ()> {
3131 if !parse.errors().is_empty() {
3232 return Err(());
3333 }
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);
4142 }
43 let node = editor.finish().new_root().clone();
4244 if node.to_string() != s {
4345 return Err(());
4446 }
45 Ok(node.syntax().clone_subtree())
47 Ok(node)
4648}
4749
4850fn fragment<T: AstNode>(template: &str, s: &str) -> Result<SyntaxNode, ()> {
......@@ -53,8 +55,9 @@ fn fragment<T: AstNode>(template: &str, s: &str) -> Result<SyntaxNode, ()> {
5355 return Err(());
5456 }
5557 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 {
5760 return Err(());
5861 }
59 Ok(node.syntax().clone_subtree())
62 Ok(node)
6063}
src/tools/rust-analyzer/crates/ide/src/goto_definition.rs+30
......@@ -40,6 +40,21 @@ pub struct GotoDefinitionConfig<'a> {
4040// | VS Code | <kbd>F12</kbd> |
4141//
4242// ![Go to Definition](https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif)
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.
4358pub(crate) fn goto_definition(
4459 db: &RootDatabase,
4560 FilePosition { file_id, offset }: FilePosition,
......@@ -984,6 +999,21 @@ impl Trait for T {
984999}"#,
9851000 );
9861001 }
1002
1003 #[test]
1004 fn goto_def_array_length_prefers_value_namespace() {
1005 check(
1006 r#"
1007struct N;
1008
1009trait Trait {}
1010
1011impl<const N: usize> Trait for [N; N$0] {}
1012 //^
1013"#,
1014 );
1015 }
1016
9871017 #[test]
9881018 fn goto_def_in_mac_call_in_attr_invoc() {
9891019 check(
src/tools/rust-analyzer/crates/ide/src/highlight_related.rs+22
......@@ -2545,6 +2545,28 @@ fn main() {
25452545 };
25462546 unsafe { *(1 as *const u8) };
25472547 unsafe { *(2 as *const u8) };
2548}
2549 "#,
2550 );
2551 }
2552
2553 #[test]
2554 fn async_fn_param() {
2555 check(
2556 r#"
2557async fn get_double_async(num$0: u32) -> u32 {
2558 // ^^^
2559 num
2560 // ^^^ read
2561}
2562 "#,
2563 );
2564 check(
2565 r#"
2566async fn get_double_async((num$0,): (u32,)) -> u32 {
2567 // ^^^
2568 num
2569 // ^^^ read
25482570}
25492571 "#,
25502572 );
src/tools/rust-analyzer/crates/ide/src/hover/tests.rs+21
......@@ -9421,6 +9421,27 @@ fn main(a$0: impl T) {}
94219421 );
94229422}
94239423
9424#[test]
9425fn hover_impl_trait_arg_with_anon_const_arg_does_not_recurse() {
9426 check(
9427 r#"
9428trait Tr<const N: usize> {}
9429pub 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
94249445#[test]
94259446fn hover_struct_default_arg_self() {
94269447 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>>(
119119 range: TextRange,
120120 direction: Direction,
121121) -> 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 {
123123 Direction::Up => r.syntax().text_range().contains_range(range),
124124 Direction::Down => l.syntax().text_range().contains_range(range),
125125 });
126126
127 if let Some((l, r)) = list_lookup {
127 if let Some([l, r]) = list_lookup {
128128 Some(replace_nodes(range, l.syntax(), r.syntax()))
129129 } else {
130130 // 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 {
7979//
8080// Special handling for constructors:
8181// - 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
8382// These cases will show only constructor/initialization usages of the type
83// (for example, `S { .. }`, `S(..)`, or `S`) instead of every type reference.
8484//
8585// | Editor | Shortcut |
8686// |---------|----------|
src/tools/rust-analyzer/crates/ide/src/rename.rs+12-1
......@@ -121,6 +121,17 @@ pub(crate) fn prepare_rename(
121121// | VS Code | <kbd>F2</kbd> |
122122//
123123// ![Rename](https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif)
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.
124135pub(crate) fn rename(
125136 db: &RootDatabase,
126137 position: FilePosition,
......@@ -813,7 +824,7 @@ fn rename_elided_lifetime(
813824 new_name: &str,
814825) -> RenameResult<SourceChange> {
815826 let parent = lifetime_token.parent().unwrap();
816 let root = parent.ancestors().last().unwrap();
827 let root = parent.tree_top();
817828
818829 let mut builder = SourceChangeBuilder::new(position.file_id);
819830
src/tools/rust-analyzer/crates/ide/src/static_index.rs+81-54
......@@ -2,6 +2,7 @@
22//! read-only code browsers and emitting LSIF
33
44use arrayvec::ArrayVec;
5use either::Either;
56use hir::{Crate, Module, Semantics, db::HirDatabase};
67use ide_db::{
78 FileId, FileRange, FxHashMap, FxHashSet, RootDatabase,
......@@ -11,13 +12,12 @@ use ide_db::{
1112 famous_defs::FamousDefs,
1213 ra_fixture::RaFixtureConfig,
1314};
14use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange};
15use syntax::{AstNode, AstToken, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, ast};
1516
1617use crate::navigation_target::UpmappingResult;
1718use crate::{
18 Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav,
19 Analysis, Fold, HoverConfig, HoverResult, TryToNav,
1920 hover::{SubstTyLen, hover_for_definition},
20 inlay_hints::{AdjustmentHintsMode, InlayFieldsToResolve, TypeHintsPlacement},
2121 moniker::{MonikerResult, SymbolInformationKind, def_to_kind, def_to_moniker},
2222 parent_module::crates_for,
2323};
......@@ -53,6 +53,22 @@ pub struct TokenStaticData {
5353 ///
5454 /// For example, in `fn foo() {}` this is the position from `fn`
5555 /// 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>
5672 pub definition_body: Option<FileRange>,
5773 pub references: Vec<ReferenceData>,
5874 pub moniker: Option<MonikerResult>,
......@@ -97,7 +113,6 @@ impl TokenStore {
97113pub struct StaticIndexedFile {
98114 pub file_id: FileId,
99115 pub folds: Vec<Fold>,
100 pub inlay_hints: Vec<InlayHint>,
101116 pub tokens: Vec<(TextRange, TokenId)>,
102117}
103118
......@@ -153,49 +168,6 @@ impl StaticIndex<'_> {
153168 fn add_file(&mut self, file_id: FileId) {
154169 let current_crate = crates_for(self.db, file_id).pop().map(Into::into);
155170 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();
199171 // hovers
200172 let sema = hir::Semantics::new(self.db);
201173 let root = sema.parse_guess_edition(file_id).syntax().clone();
......@@ -221,12 +193,13 @@ impl StaticIndex<'_> {
221193 show_drop_glue: true,
222194 ra_fixture: RaFixtureConfig::default(),
223195 };
224 let mut result = StaticIndexedFile { file_id, inlay_hints, folds, tokens: vec![] };
196 let mut result = StaticIndexedFile { file_id, folds, tokens: vec![] };
225197
226198 let mut add_token = |def: Definition, range: TextRange, scope_node: &SyntaxNode| {
227199 let id = if let Some(it) = self.def_map.get(&def) {
228200 *it
229201 } else {
202 let nav = def.try_to_nav(&sema).map(UpmappingResult::call_site);
230203 let it = self.tokens.insert(TokenStaticData {
231204 documentation: documentation_for_definition(&sema, def, scope_node),
232205 hover: Some(hover_for_definition(
......@@ -241,13 +214,14 @@ impl StaticIndex<'_> {
241214 edition,
242215 display_target,
243216 )),
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),
246224 }),
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 }),
251225 references: vec![],
252226 moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
253227 display_name: def
......@@ -333,6 +307,59 @@ impl StaticIndex<'_> {
333307 }
334308}
335309
310fn 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
351fn 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
359fn is_trailing_trivia(token: &SyntaxToken) -> bool {
360 matches!(token.kind(), SyntaxKind::WHITESPACE | SyntaxKind::COMMENT)
361}
362
336363#[cfg(test)]
337364mod tests {
338365 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>
3body { margin: 0; }
4pre { 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: () = ();
15841584 false,
15851585 );
15861586}
1587
1588#[test]
1589fn async_fn_non_mut_param() {
1590 check_highlighting(
1591 r#"
1592async 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(
171171 .map(|(crate_id, path)| {
172172 (
173173 crate_id,
174 path.map_or_else(Err, |(_, path)| {
174 path.and_then(|(_, path)| {
175175 proc_macro_server.as_ref().map_err(Clone::clone).and_then(
176176 |proc_macro_server| load_proc_macro(proc_macro_server, &path, &[]),
177177 )
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
355355 }
356356
357357 let op_n = p.start();
358 // test asm_piece_attr
359 // builtin # global_asm("", #[cfg(false)] options())
360 attributes::outer_attrs(p);
361
358362 // Parse clobber_abi
359363 if p.eat_contextual_kw(T![clobber_abi]) {
360364 parse_clobber_abi(p);
src/tools/rust-analyzer/crates/parser/src/input.rs+1-1
......@@ -27,7 +27,7 @@ impl Input {
2727 pub fn with_capacity(capacity: usize) -> Self {
2828 Self {
2929 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)),
3131 contextual_kind: Vec::with_capacity(capacity),
3232 edition: Vec::with_capacity(capacity),
3333 }
src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs+4
......@@ -25,6 +25,10 @@ mod ok {
2525 #[test]
2626 fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); }
2727 #[test]
28 fn asm_piece_attr() {
29 run_and_expect_no_errors("test_data/parser/inline/ok/asm_piece_attr.rs");
30 }
31 #[test]
2832 fn asm_sym_paren() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_sym_paren.rs"); }
2933 #[test]
3034 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 @@
1SOURCE_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 @@
1builtin # global_asm("", #[cfg(false)] options())
src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs+3
......@@ -450,6 +450,9 @@ impl WorkspaceBuildScripts {
450450
451451 cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]);
452452 cmd.args(&config.extra_args);
453 if let Some(config_path) = &config.config_path {
454 cmd.arg("--config").arg(config_path);
455 }
453456
454457 cmd.arg("--manifest-path");
455458 cmd.arg(manifest_path);
src/tools/rust-analyzer/crates/project-model/src/cargo_config_file.rs+4
......@@ -17,11 +17,15 @@ impl CargoConfigFile {
1717 manifest: &ManifestPath,
1818 extra_env: &FxHashMap<String, Option<String>>,
1919 sysroot: &Sysroot,
20 config_path: Option<&AbsPath>,
2021 ) -> Option<Self> {
2122 let mut cargo_config = sysroot.tool(Tool::Cargo, manifest.parent(), extra_env);
2223 cargo_config
2324 .args(["-Z", "unstable-options", "config", "get", "--format", "toml", "--show-origin"])
2425 .env("RUSTC_BOOTSTRAP", "1");
26 if let Some(config_path) = config_path {
27 cargo_config.arg("--config").arg(config_path);
28 }
2529 if manifest.is_rust_manifest() {
2630 cargo_config.arg("-Zscript");
2731 }
src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs+8
......@@ -133,6 +133,8 @@ pub struct CargoConfig {
133133 pub extra_args: Vec<String>,
134134 /// Extra args passed only to `cargo metadata`, not other cargo commands.
135135 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>,
136138 /// Extra env vars to set when invoking the cargo command
137139 pub extra_env: FxHashMap<String, Option<String>>,
138140 pub invocation_strategy: InvocationStrategy,
......@@ -324,6 +326,8 @@ pub struct CargoMetadataConfig {
324326 pub extra_args: Vec<String>,
325327 /// Extra args passed directly to `cargo metadata` without filtering.
326328 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>,
327331 /// Extra env vars to set when invoking the cargo command
328332 pub extra_env: FxHashMap<String, Option<String>>,
329333 /// What kind of metadata are we fetching: workspace, rustc, or sysroot.
......@@ -684,6 +688,10 @@ impl FetchMetadata {
684688 }
685689 }
686690 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 }
687695
688696 let mut lockfile_copy = None;
689697 if cargo_toml.is_rust_manifest() {
src/tools/rust-analyzer/crates/project-model/src/workspace.rs+20-3
......@@ -217,6 +217,7 @@ impl ProjectWorkspace {
217217 rustc_source,
218218 extra_args,
219219 metadata_extra_args,
220 config_path,
220221 extra_env,
221222 set_test,
222223 cfg_overrides,
......@@ -269,7 +270,8 @@ impl ProjectWorkspace {
269270
270271 tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot");
271272 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());
273275 let config_file_ = config_file.clone();
274276 let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml, &config_file_);
275277 let targets =
......@@ -291,6 +293,7 @@ impl ProjectWorkspace {
291293 targets: targets.clone(),
292294 extra_args: extra_args.clone(),
293295 metadata_extra_args: metadata_extra_args.clone(),
296 config_path: config_path.clone(),
294297 extra_env: extra_env.clone(),
295298 toolchain_version: toolchain.clone(),
296299 kind: "workspace",
......@@ -346,6 +349,7 @@ impl ProjectWorkspace {
346349 targets: targets.clone(),
347350 extra_args: extra_args.clone(),
348351 metadata_extra_args: metadata_extra_args.clone(),
352 config_path: config_path.clone(),
349353 extra_env: extra_env.clone(),
350354 toolchain_version: toolchain.clone(),
351355 kind: "rustc-dev"
......@@ -549,7 +553,12 @@ impl ProjectWorkspace {
549553 None => Sysroot::empty(),
550554 };
551555
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 );
553562 let query_config = QueryConfig::Cargo(&sysroot, detached_file, &config_file);
554563 let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
555564 let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
......@@ -579,6 +588,7 @@ impl ProjectWorkspace {
579588 targets,
580589 extra_args: config.extra_args.clone(),
581590 metadata_extra_args: config.metadata_extra_args.clone(),
591 config_path: config.config_path.clone(),
582592 extra_env: config.extra_env.clone(),
583593 toolchain_version: toolchain.clone(),
584594 kind: "detached-file",
......@@ -1952,8 +1962,15 @@ fn sysroot_metadata_config(
19521962 CargoMetadataConfig {
19531963 features: Default::default(),
19541964 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).
19551969 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.
19571974 extra_env: config.extra_env.clone(),
19581975 toolchain_version,
19591976 kind: "sysroot",
src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs+4-141
......@@ -1,14 +1,10 @@
11//! A macro that mimics the old Salsa-style `#[query_group]` macro.
22
3use core::fmt;
43use std::vec;
54
65use proc_macro::TokenStream;
76use proc_macro2::Span;
8use queries::{
9 GeneratedInputStruct, InputQuery, InputSetter, InputSetterWithDurability, Queries, SetterKind,
10 TrackedQuery, Transparent,
11};
7use queries::{Queries, TrackedQuery, Transparent};
128use quote::{ToTokens, format_ident, quote};
139use syn::parse::{Parse, ParseStream};
1410use syn::punctuated::Punctuated;
......@@ -26,18 +22,6 @@ pub fn query_group(args: TokenStream, input: TokenStream) -> TokenStream {
2622 }
2723}
2824
29#[derive(Debug)]
30struct InputStructField {
31 name: proc_macro2::TokenStream,
32 ty: proc_macro2::TokenStream,
33}
34
35impl fmt::Display for InputStructField {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 write!(f, "{}", self.name)
38 }
39}
40
4125struct SalsaAttr {
4226 name: String,
4327 tts: TokenStream,
......@@ -99,8 +83,6 @@ fn filter_attrs(attrs: Vec<Attribute>) -> (Vec<Attribute>, Vec<SalsaAttr>) {
9983
10084#[derive(Debug, Clone, PartialEq, Eq)]
10185enum QueryKind {
102 Input,
103 Tracked,
10486 TrackedWithSalsaStruct,
10587 Transparent,
10688}
......@@ -182,14 +164,10 @@ pub(crate) fn query_group_impl(
182164 let input_struct_name = format_ident!("{}Data", trait_name_ident);
183165 let create_data_ident = format_ident!("create_data_{}", trait_name_ident);
184166
185 let mut input_struct_fields: Vec<InputStructField> = vec![];
186167 let mut trait_methods = vec![];
187 let mut setter_trait_methods = vec![];
188 let mut lookup_signatures = vec![];
189168
190169 for item in &mut item_trait.items {
191170 if let syn::TraitItem::Fn(method) = item {
192 let method_name = &method.sig.ident;
193171 let signature = &method.sig;
194172
195173 let (_attrs, salsa_attrs) = filter_attrs(method.attrs.clone());
......@@ -197,7 +175,6 @@ pub(crate) fn query_group_impl(
197175 let mut query_kind = QueryKind::TrackedWithSalsaStruct;
198176 let mut invoke = None;
199177 let mut cycle = None;
200 let mut lru = None;
201178
202179 let params: Vec<FnArg> = signature.inputs.clone().into_iter().collect();
203180 let pat_and_tys = params
......@@ -215,20 +192,6 @@ pub(crate) fn query_group_impl(
215192 let c = syn::parse::<Parenthesized<Cycle>>(tts)?;
216193 cycle = Some(c.0);
217194 }
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 }
232195 "invoke" => {
233196 let path = syn::parse::<Parenthesized<Path>>(tts)?;
234197 invoke = Some(path.0.clone());
......@@ -239,12 +202,6 @@ pub(crate) fn query_group_impl(
239202 "tracked" if method.default.is_some() => {
240203 query_kind = QueryKind::TrackedWithSalsaStruct;
241204 }
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 }
248205 "transparent" => {
249206 query_kind = QueryKind::Transparent;
250207 }
......@@ -252,76 +209,22 @@ pub(crate) fn query_group_impl(
252209 }
253210 }
254211
255 let syn::ReturnType::Type(_, return_ty) = signature.output.clone() else {
212 let syn::ReturnType::Type(_, _) = signature.output.clone() else {
256213 return Err(syn::Error::new(signature.span(), "Queries must have a return type"));
257214 };
258215
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
270216 if let Some(block) = &mut method.default {
271217 SelfToDbRewriter.visit_block_mut(block);
272218 }
273219
274220 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 }
316221 (QueryKind::TrackedWithSalsaStruct, invoke) => {
317222 let method = TrackedQuery {
318223 trait_name: trait_name_ident.clone(),
319 generated_struct: None,
320224 signature: signature.clone(),
321225 pat_and_tys: pat_and_tys.clone(),
322226 invoke,
323227 cycle,
324 lru,
325228 default: method.default.take(),
326229 };
327230
......@@ -336,61 +239,23 @@ pub(crate) fn query_group_impl(
336239 };
337240 trait_methods.push(Queries::Transparent(method));
338241 }
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 }
345242 }
346243 }
347244 }
348245
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
358246 let input_struct = quote! {
359247 #[salsa_macros::input]
360 pub(crate) struct #input_struct_name {
361 #(#fields),*
362 }
248 pub(crate) struct #input_struct_name {}
363249 };
364250
365 let field_params = std::iter::repeat_n(quote! { None }, fields.len())
366 .collect::<Vec<proc_macro2::TokenStream>>();
367
368251 let create_data_method = quote! {
369252 #[allow(non_snake_case)]
370253 #[salsa_macros::tracked]
371254 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)
373256 }
374257 };
375258
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![;](trait_item.span()));
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
394259 let trait_impl = quote! {
395260 #[salsa_macros::db]
396261 impl<DB> #trait_name_ident for DB
......@@ -398,8 +263,6 @@ pub(crate) fn query_group_impl(
398263 DB: #supertraits,
399264 {
400265 #(#trait_methods)*
401
402 #(#setter_methods)*
403266 }
404267 };
405268 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 @@
11//! The IR of the `#[query_group]` macro.
22
33use quote::{ToTokens, format_ident, quote, quote_spanned};
4use syn::{FnArg, Ident, PatType, Path, Receiver, ReturnType, parse_quote, spanned::Spanned};
4use syn::{Ident, PatType, Path, spanned::Spanned};
55
66use crate::Cycle;
77
......@@ -12,13 +12,6 @@ pub(crate) struct TrackedQuery {
1212 pub(crate) invoke: Option<Path>,
1313 pub(crate) default: Option<syn::Block>,
1414 pub(crate) cycle: Option<Cycle>,
15 pub(crate) lru: Option<u32>,
16 pub(crate) generated_struct: Option<GeneratedInputStruct>,
17}
18
19pub(crate) struct GeneratedInputStruct {
20 pub(crate) input_struct_name: Ident,
21 pub(crate) create_data_ident: Ident,
2215}
2316
2417impl ToTokens for TrackedQuery {
......@@ -47,8 +40,7 @@ impl ToTokens for TrackedQuery {
4740 let options = cycle_fn.into_iter().chain(cycle_initial).chain(cycle_result);
4841 quote!(#(#options),*)
4942 })
50 .into_iter()
51 .chain(self.lru.map(|lru| quote!(lru = #lru)));
43 .into_iter();
5244 let annotation = quote!(#[salsa_macros::tracked( #(#options),* )]);
5345
5446 let pat_and_tys = &self.pat_and_tys;
......@@ -66,170 +58,23 @@ impl ToTokens for TrackedQuery {
6658 }
6759 };
6860
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
107pub(crate) struct InputQuery {
108 pub(crate) signature: syn::Signature,
109 pub(crate) create_data_ident: Ident,
110}
111
112impl 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
128pub(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
134impl 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;
15861 let method = quote! {
15962 #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),*)
16371 }
16472 };
165 method.to_tokens(tokens);
166 }
167}
168
169pub(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
175impl 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);
18673
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 };
21374 method.to_tokens(tokens);
21475 }
21576}
21677
217pub(crate) enum SetterKind {
218 Plain(InputSetter),
219 WithDurability(InputSetterWithDurability),
220}
221
222impl 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
23378pub(crate) struct Transparent {
23479 pub(crate) signature: syn::Signature,
23580 pub(crate) pat_and_tys: Vec<PatType>,
......@@ -270,7 +115,6 @@ impl ToTokens for Transparent {
270115#[allow(clippy::large_enum_variant)]
271116pub(crate) enum Queries {
272117 TrackedQuery(TrackedQuery),
273 InputQuery(InputQuery),
274118 Transparent(Transparent),
275119}
276120
......@@ -278,7 +122,6 @@ impl ToTokens for Queries {
278122 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
279123 match self {
280124 Queries::TrackedQuery(tracked_query) => tracked_query.to_tokens(tokens),
281 Queries::InputQuery(input_query) => input_query.to_tokens(tokens),
282125 Queries::Transparent(transparent) => transparent.to_tokens(tokens),
283126 }
284127 }
src/tools/rust-analyzer/crates/query-group-macro/tests/arity.rs deleted-32
......@@ -1,32 +0,0 @@
1use query_group_macro::query_group;
2
3#[query_group]
4pub 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
18fn one(_db: &dyn ArityDb, _a: ()) -> String {
19 String::new()
20}
21
22fn two(_db: &dyn ArityDb, _a: (), _b: ()) -> String {
23 String::new()
24}
25
26fn three(_db: &dyn ArityDb, _a: (), _b: (), _c: ()) -> String {
27 String::new()
28}
29
30fn 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;
44mod logger_db;
55use logger_db::LoggerDb;
66
7#[salsa::input(singleton)]
8struct InputString {
9 inner: String,
10}
11
712#[query_group]
813pub 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
1814 // unadorned query
1915 fn length_query_with_no_params(&self) -> usize;
2016
21 // renamed/invoke query
22 #[salsa::invoke_interned(invoke_length_query_actual)]
23 fn invoke_length_query(&self, key: ()) -> usize;
24
2517 // not a query. should not invoked
2618 #[salsa::transparent]
2719 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
34fn length_query(db: &dyn HelloWorldDatabase, _key: ()) -> usize {
35 db.input_string().len()
3620}
3721
3822fn length_query_with_no_params(db: &dyn HelloWorldDatabase) -> usize {
39 db.input_string().len()
40}
41
42fn invoke_length_query_actual(db: &dyn HelloWorldDatabase, _key: ()) -> usize {
43 db.input_string().len()
23 InputString::get(db).inner(db).len()
4424}
4525
4626fn transparent_length(db: &dyn HelloWorldDatabase, _key: ()) -> usize {
47 db.input_string().len()
48}
49
50fn transparent_and_invoke_length_actual(db: &dyn HelloWorldDatabase, _key: ()) -> usize {
51 db.input_string().len()
27 InputString::get(db).inner(db).len()
5228}
5329
5430#[test]
5531fn 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]
75fn invoke_query() {
76 let mut db = LoggerDb::default();
32 let db = LoggerDb::default();
7733
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();
8036
8137 assert_eq!(len, 13);
8238 db.assert_logs(expect![[r#"
8339 [
8440 "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)) })",
9142 ]"#]]);
9243}
9344
9445#[test]
9546fn transparent() {
96 let mut db = LoggerDb::default();
47 let db = LoggerDb::default();
9748
98 db.set_input_string(String::from("Hello, world!"));
49 InputString::new(&db, String::from("Hello, world!"));
9950 let len = db.transparent_length(());
10051
10152 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]
112fn 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!["[]"]);
12954}
src/tools/rust-analyzer/crates/query-group-macro/tests/lru.rs deleted-68
......@@ -1,68 +0,0 @@
1use expect_test::expect;
2
3mod logger_db;
4use logger_db::LoggerDb;
5use query_group_macro::query_group;
6
7#[query_group]
8pub 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
22fn length_query(db: &dyn LruDB, _key: ()) -> usize {
23 db.input_string().len()
24}
25
26fn invoked_query(db: &dyn LruDB, _key: ()) -> usize {
27 db.input_string().len()
28}
29
30#[test]
31fn 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]
51fn 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 @@
11use query_group_macro::query_group;
22
3#[salsa::input(singleton)]
4struct InputString {
5 inner: String,
6}
7
38#[query_group]
49pub trait DatabaseOne: salsa::Database {
5 #[salsa::input]
6 fn input_string(&self) -> String;
7
810 // unadorned query
9 #[salsa::invoke_interned(length)]
11 #[salsa::transparent]
1012 fn length(&self, key: ()) -> usize;
1113}
1214
1315#[query_group]
1416pub trait DatabaseTwo: DatabaseOne {
15 #[salsa::invoke_interned(second_length)]
17 #[salsa::transparent]
1618 fn second_length(&self, key: ()) -> usize;
1719}
1820
1921fn length(db: &dyn DatabaseOne, _key: ()) -> usize {
20 db.input_string().len()
22 InputString::get(db).inner(db).len()
2123}
2224
2325fn second_length(db: &dyn DatabaseTwo, _key: ()) -> usize {
24 db.input_string().len()
26 InputString::get(db).inner(db).len()
2527}
src/tools/rust-analyzer/crates/query-group-macro/tests/result.rs+12-23
......@@ -7,46 +7,35 @@ use query_group_macro::query_group;
77#[derive(Clone, Debug, PartialEq, Eq)]
88pub struct Error;
99
10#[salsa::input(singleton)]
11struct InputString {
12 inner: String,
13}
14
1015#[query_group]
1116pub trait ResultDatabase: salsa::Database {
12 #[salsa::input]
13 fn input_string(&self) -> String;
14
15 #[salsa::invoke_interned(length)]
17 #[salsa::transparent]
1618 fn length(&self, key: ()) -> Result<usize, Error>;
1719
18 #[salsa::invoke_interned(length2)]
20 #[salsa::transparent]
1921 fn length2(&self, key: ()) -> Result<usize, Error>;
2022}
2123
2224fn length(db: &dyn ResultDatabase, _key: ()) -> Result<usize, Error> {
23 Ok(db.input_string().len())
25 Ok(InputString::get(db).inner(db).len())
2426}
2527
2628fn length2(db: &dyn ResultDatabase, _key: ()) -> Result<usize, Error> {
27 Ok(db.input_string().len())
29 Ok(InputString::get(db).inner(db).len())
2830}
2931
3032#[test]
3133fn test_queries_with_results() {
32 let mut db = LoggerDb::default();
34 let db = LoggerDb::default();
3335 let input = "hello";
34 db.set_input_string(input.to_owned());
36 _ = InputString::new(&db, input.to_owned());
3537 assert_eq!(db.length(()), Ok(input.len()));
3638 assert_eq!(db.length2(()), Ok(input.len()));
3739
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!["[]"]);
5241}
src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs+1-1
......@@ -8,7 +8,7 @@ pub trait SourceDb: salsa::Database {
88
99#[query_group]
1010pub trait RootDb: SourceDb {
11 #[salsa::invoke_interned(parse)]
11 #[salsa::transparent]
1212 fn parse(&self, id: usize) -> String;
1313}
1414
src/tools/rust-analyzer/crates/query-group-macro/tests/tuples.rs+10-17
......@@ -4,36 +4,29 @@ mod logger_db;
44use expect_test::expect;
55use logger_db::LoggerDb;
66
7#[salsa::input(singleton)]
8struct InputString {
9 inner: String,
10}
11
712#[query_group]
813pub trait HelloWorldDatabase: salsa::Database {
9 #[salsa::input]
10 fn input_string(&self) -> String;
11
12 #[salsa::invoke_interned(length_query)]
14 #[salsa::transparent]
1315 fn length_query(&self, key: ()) -> (usize, usize);
1416}
1517
1618fn length_query(db: &dyn HelloWorldDatabase, _key: ()) -> (usize, usize) {
17 let len = db.input_string().len();
19 let len = InputString::get(db).inner(db).len();
1820 (len, len)
1921}
2022
2123#[test]
2224fn query() {
23 let mut db = LoggerDb::default();
25 let db = LoggerDb::default();
2426
25 db.set_input_string(String::from("Hello, world!"));
27 _ = InputString::new(&db, String::from("Hello, world!"));
2628 let len = db.length_query(());
2729
2830 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!["[]"]);
3932}
src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml+1-1
......@@ -29,7 +29,7 @@ ide-completion.workspace = true
2929indexmap.workspace = true
3030itertools.workspace = true
3131scip = "0.7.1"
32lsp-types = { version = "=0.95.0", features = ["proposed"] }
32lsp-types = { version = "0.4.0", package = "gen-lsp-types", features=["url"] }
3333parking_lot = "0.12.4"
3434xflags = "0.3.2"
3535oorandom = "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<()> {
207207
208208 tracing::info!("InitializeParams: {}", initialize_params);
209209 let lsp_types::InitializeParams {
210 #[expect(deprecated, reason = "compatibility with old clients")]
210211 root_uri,
211 mut capabilities,
212 workspace_folders,
212 capabilities,
213 workspace_folders_initialize_params,
213214 initialization_options,
214215 client_info,
215216 ..
216217 } = from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?;
217218
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
229219 let root_path = match root_uri
230220 .and_then(|it| it.to_file_path().ok())
231221 .map(patch_path_prefix)
......@@ -247,7 +237,14 @@ fn run_server() -> anyhow::Result<()> {
247237 );
248238 }
249239
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 })
251248 .map(|workspaces| {
252249 workspaces
253250 .into_iter()
......@@ -269,12 +266,11 @@ fn run_server() -> anyhow::Result<()> {
269266
270267 if !error_sink.is_empty() {
271268 use lsp_types::{
272 MessageType, ShowMessageParams,
273 notification::{Notification, ShowMessage},
269 MessageType, Notification as _, ShowMessageNotification, ShowMessageParams,
274270 };
275271 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() },
278274 );
279275 connection.sender.send(lsp_server::Message::Notification(not)).unwrap();
280276 }
......@@ -288,7 +284,6 @@ fn run_server() -> anyhow::Result<()> {
288284 name: String::from("rust-analyzer"),
289285 version: Some(rust_analyzer::version().to_string()),
290286 }),
291 offset_encoding: None,
292287 };
293288
294289 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 @@
11//! LSIF (language server index format) generator
2
32use std::env;
43use std::time::Instant;
54
......@@ -10,12 +9,14 @@ use ide::{
109};
1110use ide_db::{line_index, line_index::WideEncoding};
1211use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
13use lsp_types::lsif;
1412use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource};
1513use rustc_hash::FxHashMap;
1614use stdx::format_to;
15use vendored as lsif;
1716use vfs::{AbsPathBuf, Vfs};
1817
18mod vendored;
19
1920use crate::{
2021 cli::flags,
2122 line_index::{LineEndings, LineIndex, PositionEncoding},
......@@ -38,9 +39,9 @@ struct LsifManager<'a, 'w> {
3839#[derive(Clone, Copy)]
3940struct Id(i32);
4041
41impl From<Id> for lsp_types::NumberOrString {
42impl From<Id> for lsp_types::Code {
4243 fn from(Id(it): Id) -> Self {
43 lsp_types::NumberOrString::Number(it)
44 lsp_types::Code::Int(it)
4445 }
4546}
4647
......@@ -145,7 +146,7 @@ impl LsifManager<'_, '_> {
145146 let path = path.as_path().unwrap();
146147 let doc_id = self.add_vertex(lsif::Vertex::Document(lsif::Document {
147148 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(),
149150 }));
150151 self.file_map.insert(id, doc_id);
151152 doc_id
......@@ -156,7 +157,7 @@ impl LsifManager<'_, '_> {
156157 if let Some(hover) = token.hover {
157158 let hover_id = self.add_vertex(lsif::Vertex::HoverResult {
158159 result: lsp_types::Hover {
159 contents: lsp_types::HoverContents::Markup(to_proto::markup_content(
160 contents: lsp_types::Contents::MarkupContent(to_proto::markup_content(
160161 hover.markup,
161162 ide::HoverDocFormat::Markdown,
162163 )),
......@@ -211,7 +212,7 @@ impl LsifManager<'_, '_> {
211212 out_v: result_set_id.into(),
212213 }));
213214 let mut edges = token.references.iter().fold(
214 FxHashMap::<_, Vec<lsp_types::NumberOrString>>::default(),
215 FxHashMap::<_, Vec<lsp_types::Code>>::default(),
215216 |mut edges, it| {
216217 let entry = edges.entry((it.range.file_id, it.is_definition)).or_default();
217218 entry.push((*self.range_map.get(&it.range).unwrap()).into());
......@@ -321,9 +322,9 @@ impl flags::Lsif {
321322 let mut lsif = LsifManager::new(&analysis, db, &vfs, out);
322323 lsif.add_vertex(lsif::Vertex::MetaData(lsif::MetaData {
323324 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(),
325326 position_encoding: lsif::Encoding::Utf16,
326 tool_info: Some(lsp_types::lsif::ToolInfo {
327 tool_info: Some(lsif::ToolInfo {
327328 name: "rust-analyzer".to_owned(),
328329 args: vec![],
329330 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
9use lsp_types::{Range, Uri};
10use serde::{Deserialize, Serialize};
11
12pub type Id = lsp_types::Code;
13
14#[derive(Debug, PartialEq, Serialize, Deserialize)]
15#[serde(untagged)]
16pub enum LocationOrRangeId {
17 Location(lsp_types::Location),
18 RangeId(Id),
19}
20
21#[derive(Debug, PartialEq, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub 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")]
32pub enum Element {
33 Vertex(Vertex),
34 Edge(Edge),
35}
36
37#[derive(Debug, PartialEq, Serialize, Deserialize)]
38pub 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)]
48pub 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)]
55pub 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)]
65pub 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")]
72pub 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")]
91pub 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")]
109pub struct ReferenceTag {
110 text: String,
111}
112
113#[derive(Debug, PartialEq, Serialize, Deserialize)]
114#[serde(rename_all = "camelCase")]
115pub struct UnknownTag {
116 text: String,
117}
118
119#[derive(Debug, PartialEq, Serialize, Deserialize)]
120#[serde(rename_all = "camelCase")]
121#[serde(tag = "type")]
122pub 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")]
132pub 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")]
176pub enum EventKind {
177 Begin,
178 End,
179}
180
181#[derive(Debug, PartialEq, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183pub enum EventScope {
184 Document,
185 Project,
186}
187
188#[derive(Debug, PartialEq, Serialize, Deserialize)]
189pub 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")]
198pub 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")]
231pub 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")]
238pub struct EdgeDataMultiIn {
239 pub in_vs: Vec<Id>,
240 pub out_v: Id,
241}
242
243#[derive(Debug, PartialEq, Serialize, Deserialize)]
244#[serde(untagged)]
245pub enum DefinitionResultType {
246 Scalar(LocationOrRangeId),
247 Array(LocationOrRangeId),
248}
249
250#[derive(Debug, PartialEq, Serialize, Deserialize)]
251#[serde(rename_all = "camelCase")]
252pub 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")]
262pub 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")]
272pub 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")]
280pub 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")]
288pub 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")]
298pub 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")]
318pub 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")]
327pub 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 {
948948
949949 assert_eq!(token.definition_body, Some(expected_range));
950950 }
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 }
9511015}
src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs+20-4
......@@ -833,6 +833,10 @@ config_data! {
833833 cargo_cfgs: Vec<String> = {
834834 vec!["debug_assertions".into(), "miri".into()]
835835 },
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,
836840 /// Extra arguments that are passed to every cargo invocation.
837841 cargo_extraArgs: Vec<String> = vec![],
838842 /// Extra environment variables that will be set when running cargo, rustc
......@@ -1127,7 +1131,7 @@ pub struct Config {
11271131
11281132 default_config: &'static DefaultConfigData,
11291133 /// 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`].
11311135 client_config: (FullConfigInput, ConfigErrors),
11321136
11331137 /// Config node whose values apply to **every** Rust project.
......@@ -1684,6 +1688,8 @@ pub struct RunnablesConfig {
16841688 pub override_cargo: Option<String>,
16851689 /// Additional arguments for the `cargo`, e.g. `--release`.
16861690 pub cargo_extra_args: Vec<String>,
1691 /// Path to an extra config file passed to cargo via `--config`.
1692 pub config_path: Option<AbsPathBuf>,
16871693 /// Additional arguments for the binary being run, if it is a test or benchmark.
16881694 pub extra_test_binary_args: Vec<String>,
16891695 /// Subcommand used for doctest runnables instead of `test`.
......@@ -2418,6 +2424,7 @@ impl Config {
24182424 });
24192425 let sysroot_src =
24202426 self.cargo_sysrootSrc(source_root).as_ref().map(|sysroot| self.root_path.join(sysroot));
2427 let config_path = self.cargo_config_path(source_root);
24212428 let extra_includes = self
24222429 .vfs_extraIncludes(source_root)
24232430 .iter()
......@@ -2484,6 +2491,7 @@ impl Config {
24842491 set_test: *self.cfg_setTest(source_root),
24852492 no_deps: *self.cargo_noDeps(source_root),
24862493 metadata_extra_args: self.cargo_metadataExtraArgs(source_root).clone(),
2494 config_path,
24872495 }
24882496 }
24892497
......@@ -2573,6 +2581,7 @@ impl Config {
25732581 extra_env: self.extra_env(source_root).clone(),
25742582 target_dir_config: self.target_dir_from_config(source_root),
25752583 set_test: true,
2584 config_path: self.cargo_config_path(source_root),
25762585 }
25772586 }
25782587
......@@ -2629,6 +2638,7 @@ impl Config {
26292638 extra_args: self.check_extra_args(source_root),
26302639 extra_test_bin_args: self.runnables_extraTestBinaryArgs(source_root).clone(),
26312640 extra_env: self.check_extra_env(source_root),
2641 config_path: self.cargo_config_path(source_root),
26322642 target_dir_config: self.target_dir_from_config(source_root),
26332643 set_test: *self.cfg_setTest(source_root),
26342644 },
......@@ -2637,6 +2647,10 @@ impl Config {
26372647 }
26382648 }
26392649
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
26402654 fn target_dir_from_config(&self, source_root: Option<SourceRootId>) -> TargetDirectoryConfig {
26412655 match &self.cargo_targetDir(source_root) {
26422656 Some(TargetDirectory::UseSubdirectory(true)) => TargetDirectoryConfig::UseSubdirectory,
......@@ -2657,6 +2671,7 @@ impl Config {
26572671 RunnablesConfig {
26582672 override_cargo: self.runnables_command(source_root).clone(),
26592673 cargo_extra_args: self.runnables_extraArgs(source_root).clone(),
2674 config_path: self.cargo_config_path(source_root),
26602675 extra_test_binary_args: self.runnables_extraTestBinaryArgs(source_root).clone(),
26612676 test_command: self.runnables_test_command(source_root).clone(),
26622677 test_override_command: self.runnables_test_overrideCommand(source_root).clone(),
......@@ -3501,8 +3516,8 @@ impl FullConfigInput {
35013516 fields.sort_by_key(|&(x, ..)| x);
35023517 fields
35033518 .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"));
35063521 fields
35073522 }
35083523
......@@ -4146,7 +4161,8 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
41464161 "enumDescriptions": [
41474162 "Do not show this item or its methods (if it is a trait) in auto-import completions.",
41484163 "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."
41504166 ],
41514167 },
41524168 }
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs+3-3
......@@ -357,14 +357,14 @@ pub(crate) fn convert_diagnostic(
357357 lsp_types::Diagnostic {
358358 range: lsp::to_proto::range(line_index, d.range.range),
359359 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())),
361361 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(),
363363 }),
364364 source: Some("rust-analyzer".to_owned()),
365365 message: d.message,
366366 related_information: None,
367 tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::UNNECESSARY]),
367 tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::Unnecessary]),
368368 data: None,
369369 }
370370}
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs+21-21
......@@ -22,8 +22,8 @@ fn diagnostic_severity(
2222 code: Option<&crate::flycheck::DiagnosticCode>,
2323) -> Option<lsp_types::DiagnosticSeverity> {
2424 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,
2727 DiagnosticLevel::Warning => match code {
2828 // HACK: special case for `warnings` rustc lint.
2929 Some(code)
......@@ -31,7 +31,7 @@ fn diagnostic_severity(
3131 lint == "warnings" || ide_db::helpers::lint_eq_or_in_group(&code.code, lint)
3232 }) =>
3333 {
34 lsp_types::DiagnosticSeverity::HINT
34 lsp_types::DiagnosticSeverity::Hint
3535 }
3636 // HACK: special case for `warnings` rustc lint.
3737 Some(code)
......@@ -39,12 +39,12 @@ fn diagnostic_severity(
3939 lint == "warnings" || ide_db::helpers::lint_eq_or_in_group(&code.code, lint)
4040 }) =>
4141 {
42 lsp_types::DiagnosticSeverity::INFORMATION
42 lsp_types::DiagnosticSeverity::Information
4343 }
44 _ => lsp_types::DiagnosticSeverity::WARNING,
44 _ => lsp_types::DiagnosticSeverity::Warning,
4545 },
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,
4848 _ => return None,
4949 };
5050 Some(res)
......@@ -192,7 +192,7 @@ fn map_rust_child_diagnostic(
192192 return MappedRustChildDiagnostic::MessageLine(rd.message.clone());
193193 }
194194
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();
196196 let mut suggested_replacements = Vec::new();
197197 let mut is_preferred = true;
198198 for &span in &spans {
......@@ -239,7 +239,7 @@ fn map_rust_child_diagnostic(
239239 action: lsp_ext::CodeAction {
240240 title: message.clone(),
241241 group: None,
242 kind: Some(lsp_types::CodeActionKind::QUICKFIX),
242 kind: Some(lsp_types::CodeActionKind::QuickFix),
243243 edit: Some(lsp_ext::SnippetWorkspaceEdit {
244244 // FIXME: there's no good reason to use edit_map here....
245245 changes: Some(edit_map),
......@@ -263,7 +263,7 @@ fn map_rust_child_diagnostic(
263263
264264#[derive(Debug)]
265265pub(crate) struct MappedRustDiagnostic {
266 pub(crate) url: lsp_types::Url,
266 pub(crate) url: lsp_types::Uri,
267267 pub(crate) diagnostic: lsp_types::Diagnostic,
268268 pub(crate) fix: Option<Box<Fix>>,
269269}
......@@ -351,10 +351,10 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
351351 match &*code.code {
352352 "dead_code" | "unknown_lints" | "unreachable_code" | "unused_attributes"
353353 | "unused_imports" | "unused_macros" | "unused_variables" => {
354 tag = Some(lsp_types::DiagnosticTag::UNNECESSARY);
354 tag = Some(lsp_types::DiagnosticTag::Unnecessary);
355355 }
356356 "deprecated" => {
357 tag = Some(lsp_types::DiagnosticTag::DEPRECATED);
357 tag = Some(lsp_types::DiagnosticTag::Deprecated);
358358 }
359359 _ => {}
360360 }
......@@ -418,13 +418,13 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
418418 let diagnostic = lsp_types::Diagnostic {
419419 range: secondary_location.range,
420420 // 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),
423423 code_description: code_description.clone(),
424424 source: Some(source.to_owned()),
425425 message: message.clone(),
426426 related_information: Some(information_for_additional_diagnostic),
427 tags: tag.clone().map(|tag| vec![tag]),
427 tags: tag.map(|tag| vec![tag]),
428428 data: Some(serde_json::json!({ "rendered": rendered })),
429429 };
430430 diagnostics.push(MappedRustDiagnostic {
......@@ -440,7 +440,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
440440 diagnostic: lsp_types::Diagnostic {
441441 range: primary_location.range,
442442 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),
444444 code_description: code_description.clone(),
445445 source: Some(source.to_owned()),
446446 message,
......@@ -452,7 +452,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
452452 .collect::<Vec<_>>();
453453 if info.is_empty() { None } else { Some(info) }
454454 },
455 tags: tag.clone().map(|tag| vec![tag]),
455 tags: tag.map(|tag| vec![tag]),
456456 data: Some(serde_json::json!({ "rendered": rendered })),
457457 },
458458 fix: None,
......@@ -471,8 +471,8 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
471471 fix: sub.suggested_fix.clone(),
472472 diagnostic: lsp_types::Diagnostic {
473473 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),
476476 code_description: code_description.clone(),
477477 source: Some(source.to_owned()),
478478 message: sub.related.message.clone(),
......@@ -494,7 +494,7 @@ fn rustc_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescripti
494494 && chars.next().is_none()
495495 })
496496 .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}"))
498498 .ok()
499499 .map(|href| lsp_types::CodeDescription { href })
500500 })
......@@ -502,7 +502,7 @@ fn rustc_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescripti
502502
503503fn clippy_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescription> {
504504 code.and_then(|code| {
505 lsp_types::Url::parse(&format!(
505 lsp_types::Uri::parse(&format!(
506506 "https://rust-lang.github.io/rust-clippy/master/index.html#{code}"
507507 ))
508508 .ok()
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt+3-3
......@@ -55,6 +55,7 @@
5555 "clippy",
5656 ),
5757 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,
5859 related_information: Some(
5960 [
6061 DiagnosticRelatedInformation {
......@@ -111,7 +112,6 @@
111112 },
112113 ],
113114 ),
114 tags: None,
115115 data: None,
116116 },
117117 fix: None,
......@@ -172,6 +172,7 @@
172172 "clippy",
173173 ),
174174 message: "lint level defined here",
175 tags: None,
175176 related_information: Some(
176177 [
177178 DiagnosticRelatedInformation {
......@@ -202,7 +203,6 @@
202203 },
203204 ],
204205 ),
205 tags: None,
206206 data: None,
207207 },
208208 fix: None,
......@@ -263,6 +263,7 @@
263263 "clippy",
264264 ),
265265 message: "consider passing by value instead: `self`",
266 tags: None,
266267 related_information: Some(
267268 [
268269 DiagnosticRelatedInformation {
......@@ -293,7 +294,6 @@
293294 },
294295 ],
295296 ),
296 tags: None,
297297 data: None,
298298 },
299299 fix: None,
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt+1-1
......@@ -55,8 +55,8 @@
5555 "rustc",
5656 ),
5757 message: "can't compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
58 related_information: None,
5958 tags: None,
59 related_information: None,
6060 data: None,
6161 },
6262 fix: None,
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt+3-3
......@@ -31,6 +31,7 @@
3131 "rustc",
3232 ),
3333 message: "Please register your known path in the path module",
34 tags: None,
3435 related_information: Some(
3536 [
3637 DiagnosticRelatedInformation {
......@@ -61,7 +62,6 @@
6162 },
6263 ],
6364 ),
64 tags: None,
6565 data: None,
6666 },
6767 fix: None,
......@@ -98,6 +98,7 @@
9898 "rustc",
9999 ),
100100 message: "Please register your known path in the path module",
101 tags: None,
101102 related_information: Some(
102103 [
103104 DiagnosticRelatedInformation {
......@@ -128,7 +129,6 @@
128129 },
129130 ],
130131 ),
131 tags: None,
132132 data: None,
133133 },
134134 fix: None,
......@@ -165,6 +165,7 @@
165165 "rustc",
166166 ),
167167 message: "Please register your known path in the path module",
168 tags: None,
168169 related_information: Some(
169170 [
170171 DiagnosticRelatedInformation {
......@@ -221,7 +222,6 @@
221222 },
222223 ],
223224 ),
224 tags: None,
225225 data: None,
226226 },
227227 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 @@
5555 "rustc",
5656 ),
5757 message: "`main` function not found in crate `current`\nconsider adding a `main` function to `src/bin/current.rs`",
58 related_information: None,
5958 tags: None,
59 related_information: None,
6060 data: None,
6161 },
6262 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 @@
5555 "rustc",
5656 ),
5757 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,
5958 tags: None,
59 related_information: None,
6060 data: None,
6161 },
6262 fix: None,
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt+1-1
......@@ -55,8 +55,8 @@
5555 "rustc",
5656 ),
5757 message: "mismatched types\nexpected usize, found u32",
58 related_information: None,
5958 tags: None,
59 related_information: None,
6060 data: None,
6161 },
6262 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 @@
5555 "rustc",
5656 ),
5757 message: "mismatched types\nexpected `u32`, found `&str`",
58 tags: None,
5859 related_information: Some(
5960 [
6061 DiagnosticRelatedInformation {
......@@ -85,7 +86,6 @@
8586 },
8687 ],
8788 ),
88 tags: None,
8989 data: None,
9090 },
9191 fix: None,
......@@ -146,6 +146,7 @@
146146 "rustc",
147147 ),
148148 message: "expected due to this",
149 tags: None,
149150 related_information: Some(
150151 [
151152 DiagnosticRelatedInformation {
......@@ -176,7 +177,6 @@
176177 },
177178 ],
178179 ),
179 tags: None,
180180 data: None,
181181 },
182182 fix: None,
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt+7-9
......@@ -35,6 +35,11 @@
3535 "rustc",
3636 ),
3737 message: "unused variable: `foo`\n#[warn(unused_variables)] on by default",
38 tags: Some(
39 [
40 Unnecessary,
41 ],
42 ),
3843 related_information: Some(
3944 [
4045 DiagnosticRelatedInformation {
......@@ -65,11 +70,6 @@
6570 },
6671 ],
6772 ),
68 tags: Some(
69 [
70 Unnecessary,
71 ],
72 ),
7373 data: None,
7474 },
7575 fix: None,
......@@ -110,6 +110,7 @@
110110 "rustc",
111111 ),
112112 message: "consider prefixing with an underscore: `_foo`",
113 tags: None,
113114 related_information: Some(
114115 [
115116 DiagnosticRelatedInformation {
......@@ -140,7 +141,6 @@
140141 },
141142 ],
142143 ),
143 tags: None,
144144 data: None,
145145 },
146146 fix: Some(
......@@ -161,9 +161,7 @@
161161 title: "consider prefixing with an underscore: `_foo`",
162162 group: None,
163163 kind: Some(
164 CodeActionKind(
165 "quickfix",
166 ),
164 QuickFix,
167165 ),
168166 command: None,
169167 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 @@
3535 "rustc",
3636 ),
3737 message: "unused variable: `foo`\n#[warn(unused_variables)] on by default",
38 tags: Some(
39 [
40 Unnecessary,
41 ],
42 ),
3843 related_information: Some(
3944 [
4045 DiagnosticRelatedInformation {
......@@ -65,11 +70,6 @@
6570 },
6671 ],
6772 ),
68 tags: Some(
69 [
70 Unnecessary,
71 ],
72 ),
7373 data: None,
7474 },
7575 fix: None,
......@@ -110,6 +110,7 @@
110110 "rustc",
111111 ),
112112 message: "consider prefixing with an underscore: `_foo`",
113 tags: None,
113114 related_information: Some(
114115 [
115116 DiagnosticRelatedInformation {
......@@ -140,7 +141,6 @@
140141 },
141142 ],
142143 ),
143 tags: None,
144144 data: None,
145145 },
146146 fix: Some(
......@@ -161,9 +161,7 @@
161161 title: "consider prefixing with an underscore: `_foo`",
162162 group: None,
163163 kind: Some(
164 CodeActionKind(
165 "quickfix",
166 ),
164 QuickFix,
167165 ),
168166 command: None,
169167 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 @@
3535 "rustc",
3636 ),
3737 message: "unused variable: `foo`\n#[warn(unused_variables)] on by default",
38 tags: Some(
39 [
40 Unnecessary,
41 ],
42 ),
3843 related_information: Some(
3944 [
4045 DiagnosticRelatedInformation {
......@@ -65,11 +70,6 @@
6570 },
6671 ],
6772 ),
68 tags: Some(
69 [
70 Unnecessary,
71 ],
72 ),
7373 data: None,
7474 },
7575 fix: None,
......@@ -110,6 +110,7 @@
110110 "rustc",
111111 ),
112112 message: "consider prefixing with an underscore: `_foo`",
113 tags: None,
113114 related_information: Some(
114115 [
115116 DiagnosticRelatedInformation {
......@@ -140,7 +141,6 @@
140141 },
141142 ],
142143 ),
143 tags: None,
144144 data: None,
145145 },
146146 fix: Some(
......@@ -161,9 +161,7 @@
161161 title: "consider prefixing with an underscore: `_foo`",
162162 group: None,
163163 kind: Some(
164 CodeActionKind(
165 "quickfix",
166 ),
164 QuickFix,
167165 ),
168166 command: None,
169167 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 @@
5555 "rustc",
5656 ),
5757 message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters",
58 tags: None,
5859 related_information: Some(
5960 [
6061 DiagnosticRelatedInformation {
......@@ -85,7 +86,6 @@
8586 },
8687 ],
8788 ),
88 tags: None,
8989 data: None,
9090 },
9191 fix: None,
......@@ -146,6 +146,7 @@
146146 "rustc",
147147 ),
148148 message: "defined here",
149 tags: None,
149150 related_information: Some(
150151 [
151152 DiagnosticRelatedInformation {
......@@ -176,7 +177,6 @@
176177 },
177178 ],
178179 ),
179 tags: None,
180180 data: None,
181181 },
182182 fix: None,
src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt+4-6
......@@ -55,6 +55,7 @@
5555 "clippy",
5656 ),
5757 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,
5859 related_information: Some(
5960 [
6061 DiagnosticRelatedInformation {
......@@ -111,7 +112,6 @@
111112 },
112113 ],
113114 ),
114 tags: None,
115115 data: None,
116116 },
117117 fix: None,
......@@ -172,6 +172,7 @@
172172 "clippy",
173173 ),
174174 message: "unnecessary let binding",
175 tags: None,
175176 related_information: Some(
176177 [
177178 DiagnosticRelatedInformation {
......@@ -202,7 +203,6 @@
202203 },
203204 ],
204205 ),
205 tags: None,
206206 data: None,
207207 },
208208 fix: None,
......@@ -263,6 +263,7 @@
263263 "clippy",
264264 ),
265265 message: "return the expression directly: `(0..10).collect()`",
266 tags: None,
266267 related_information: Some(
267268 [
268269 DiagnosticRelatedInformation {
......@@ -293,7 +294,6 @@
293294 },
294295 ],
295296 ),
296 tags: None,
297297 data: None,
298298 },
299299 fix: Some(
......@@ -324,9 +324,7 @@
324324 title: "return the expression directly: `(0..10).collect()`",
325325 group: None,
326326 kind: Some(
327 CodeActionKind(
328 "quickfix",
329 ),
327 QuickFix,
330328 ),
331329 command: None,
332330 edit: Some(
src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs+5
......@@ -51,6 +51,7 @@ pub(crate) struct CargoOptions {
5151 pub(crate) extra_args: Vec<String>,
5252 pub(crate) extra_test_bin_args: Vec<String>,
5353 pub(crate) extra_env: FxHashMap<String, Option<String>>,
54 pub(crate) config_path: Option<AbsPathBuf>,
5455 pub(crate) target_dir_config: TargetDirectoryConfig,
5556}
5657
......@@ -108,6 +109,9 @@ impl CargoOptions {
108109 cmd.arg(features);
109110 }
110111 }
112 if let Some(config_path) = &self.config_path {
113 cmd.arg("--config").arg(config_path);
114 }
111115 if let Some(target_dir) = self.target_dir_config.target_dir(ws_target_dir) {
112116 cmd.arg("--target-dir").arg(target_dir.as_ref());
113117 }
......@@ -1169,6 +1173,7 @@ mod tests {
11691173 extra_args: vec![],
11701174 extra_test_bin_args: vec![],
11711175 extra_env: FxHashMap::default(),
1176 config_path: None,
11721177 target_dir_config: TargetDirectoryConfig::default(),
11731178 },
11741179 ansi_color_output: true,
src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs+15-18
......@@ -18,7 +18,7 @@ use ide_db::{
1818};
1919use itertools::Itertools;
2020use load_cargo::SourceRootConfig;
21use lsp_types::{SemanticTokens, Url};
21use lsp_types::{Notification, SemanticTokens, Uri};
2222use parking_lot::{
2323 MappedRwLockReadGuard, Mutex, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard,
2424 RwLockWriteGuard,
......@@ -97,7 +97,7 @@ pub(crate) struct GlobalState {
9797 pub(crate) source_root_config: SourceRootConfig,
9898 /// A mapping that maps a local source root's `SourceRootId` to it parent's `SourceRootId`, if it has one.
9999 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>>>,
101101
102102 // status
103103 pub(crate) shutdown_requested: bool,
......@@ -209,7 +209,7 @@ pub(crate) struct GlobalStateSnapshot {
209209 pub(crate) analysis: Analysis,
210210 pub(crate) check_fixes: CheckFixes,
211211 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>>>,
213213 vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
214214 pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
215215 // used to signal semantic highlighting to fall back to syntax based highlighting until
......@@ -580,12 +580,12 @@ impl GlobalState {
580580 }
581581 }
582582
583 pub(crate) fn send_request<R: lsp_types::request::Request>(
583 pub(crate) fn send_request<R: lsp_types::Request>(
584584 &mut self,
585585 params: R::Params,
586586 handler: ReqHandler,
587587 ) {
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);
589589 self.send(request.into());
590590 }
591591
......@@ -598,11 +598,8 @@ impl GlobalState {
598598 handler(self, response)
599599 }
600600
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);
606603 self.send(not.into());
607604 }
608605
......@@ -647,7 +644,7 @@ impl GlobalState {
647644
648645 pub(crate) fn publish_diagnostics(
649646 &mut self,
650 uri: Url,
647 uri: Uri,
651648 version: Option<i32>,
652649 mut diagnostics: Vec<lsp_types::Diagnostic>,
653650 ) {
......@@ -680,7 +677,7 @@ impl GlobalState {
680677 }
681678
682679 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(),
684681 lsp_types::PublishDiagnosticsParams { uri, diagnostics, version },
685682 );
686683 _ = sender.send(not.into());
......@@ -744,11 +741,11 @@ impl GlobalStateSnapshot {
744741 }
745742
746743 /// 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>> {
748745 url_to_file_id(&self.vfs_read(), url)
749746 }
750747
751 pub(crate) fn file_id_to_url(&self, id: FileId) -> Url {
748 pub(crate) fn file_id_to_url(&self, id: FileId) -> Uri {
752749 file_id_to_url(&self.vfs_read(), id)
753750 }
754751
......@@ -768,12 +765,12 @@ impl GlobalStateSnapshot {
768765 Some(self.mem_docs.get(self.vfs_read().file_path(file_id))?.version)
769766 }
770767
771 pub(crate) fn url_file_version(&self, url: &Url) -> Option<i32> {
768 pub(crate) fn url_file_version(&self, url: &Uri) -> Option<i32> {
772769 let path = from_proto::vfs_path(url).ok()?;
773770 Some(self.mem_docs.get(&path)?.version)
774771 }
775772
776 pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url {
773 pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Uri {
777774 let mut base = self.vfs_read().file_path(path.anchor).clone();
778775 base.pop();
779776 let path = base.join(&path.path).unwrap();
......@@ -898,14 +895,14 @@ impl GlobalStateSnapshot {
898895 }
899896}
900897
901pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url {
898pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Uri {
902899 let path = vfs.file_path(id);
903900 let path = path.as_path().unwrap();
904901 url_from_abs_path(path)
905902}
906903
907904/// Returns `None` if the file was excluded.
908pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result<Option<FileId>> {
905pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Uri) -> anyhow::Result<Option<FileId>> {
909906 let path = from_proto::vfs_path(url)?;
910907 vfs_path_to_file_id(vfs, &path)
911908}
src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs+18-18
......@@ -47,7 +47,7 @@ impl RequestDispatcher<'_> {
4747 f: fn(&mut GlobalState, R::Params) -> anyhow::Result<R::Result>,
4848 ) -> &mut Self
4949 where
50 R: lsp_types::request::Request,
50 R: lsp_types::Request,
5151 R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug,
5252 R::Result: Serialize,
5353 {
......@@ -75,7 +75,7 @@ impl RequestDispatcher<'_> {
7575 f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>,
7676 ) -> &mut Self
7777 where
78 R: lsp_types::request::Request,
78 R: lsp_types::Request,
7979 R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug,
8080 R::Result: Serialize,
8181 {
......@@ -107,14 +107,14 @@ impl RequestDispatcher<'_> {
107107 f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>,
108108 ) -> &mut Self
109109 where
110 R: lsp_types::request::Request<
110 R: lsp_types::Request<
111111 Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
112112 Result: Serialize + Default,
113113 > + 'static,
114114 {
115115 if !self.global_state.vfs_done {
116116 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())
118118 {
119119 self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default()));
120120 }
......@@ -136,14 +136,14 @@ impl RequestDispatcher<'_> {
136136 on_cancelled: fn() -> ResponseError,
137137 ) -> &mut Self
138138 where
139 R: lsp_types::request::Request<
139 R: lsp_types::Request<
140140 Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
141141 Result: Serialize,
142142 > + 'static,
143143 {
144144 if !self.global_state.vfs_done || self.global_state.incomplete_crate_graph {
145145 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())
147147 {
148148 self.global_state.respond(lsp_server::Response::new_ok(id, default()));
149149 }
......@@ -159,7 +159,7 @@ impl RequestDispatcher<'_> {
159159 f: fn(GlobalStateSnapshot, Params) -> anyhow::Result<R::Result>,
160160 ) -> &mut Self
161161 where
162 R: lsp_types::request::Request<Params = Params, Result = Params> + 'static,
162 R: lsp_types::Request<Params = Params, Result = Params> + 'static,
163163 Params: Serialize + DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
164164 {
165165 if !self.global_state.vfs_done {
......@@ -182,14 +182,14 @@ impl RequestDispatcher<'_> {
182182 f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>,
183183 ) -> &mut Self
184184 where
185 R: lsp_types::request::Request<
185 R: lsp_types::Request<
186186 Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
187187 Result: Serialize + Default,
188188 > + 'static,
189189 {
190190 if !self.global_state.vfs_done {
191191 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())
193193 {
194194 self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default()));
195195 }
......@@ -210,7 +210,7 @@ impl RequestDispatcher<'_> {
210210 f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>,
211211 ) -> &mut Self
212212 where
213 R: lsp_types::request::Request + 'static,
213 R: lsp_types::Request + 'static,
214214 R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
215215 R::Result: Serialize,
216216 {
......@@ -240,7 +240,7 @@ impl RequestDispatcher<'_> {
240240 on_cancelled: fn() -> ResponseError,
241241 ) -> &mut Self
242242 where
243 R: lsp_types::request::Request + 'static,
243 R: lsp_types::Request + 'static,
244244 R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
245245 R::Result: Serialize,
246246 {
......@@ -278,11 +278,11 @@ impl RequestDispatcher<'_> {
278278
279279 fn parse<R>(&mut self) -> Option<(lsp_server::Request, R::Params, String)>
280280 where
281 R: lsp_types::request::Request,
281 R: lsp_types::Request,
282282 R::Params: DeserializeOwned + fmt::Debug,
283283 {
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);
286286 match res {
287287 Ok(params) => {
288288 let panic_context =
......@@ -334,7 +334,7 @@ fn thread_result_to_response<R>(
334334 result: thread::Result<anyhow::Result<R::Result>>,
335335) -> Result<lsp_server::Response, HandlerCancelledError>
336336where
337 R: lsp_types::request::Request,
337 R: lsp_types::Request,
338338 R::Params: DeserializeOwned,
339339 R::Result: Serialize,
340340{
......@@ -369,7 +369,7 @@ fn result_to_response<R>(
369369 result: anyhow::Result<R::Result>,
370370) -> Result<lsp_server::Response, HandlerCancelledError>
371371where
372 R: lsp_types::request::Request,
372 R: lsp_types::Request,
373373 R::Params: DeserializeOwned,
374374 R::Result: Serialize,
375375{
......@@ -401,7 +401,7 @@ impl NotificationDispatcher<'_> {
401401 f: fn(&mut GlobalState, N::Params) -> anyhow::Result<()>,
402402 ) -> &mut Self
403403 where
404 N: lsp_types::notification::Notification,
404 N: lsp_types::Notification,
405405 N::Params: DeserializeOwned + Send + Debug,
406406 {
407407 let not = match self.not.take() {
......@@ -411,7 +411,7 @@ impl NotificationDispatcher<'_> {
411411
412412 let _guard = tracing::info_span!("notification", method = ?not.method).entered();
413413
414 let params = match not.extract::<N::Params>(N::METHOD) {
414 let params = match not.extract::<N::Params>(N::METHOD.as_str()) {
415415 Ok(it) => it,
416416 Err(ExtractError::JsonError { method, error }) => {
417417 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::{
3030
3131pub(crate) fn handle_cancel(state: &mut GlobalState, params: CancelParams) -> anyhow::Result<()> {
3232 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(),
3535 };
3636 state.cancel(id);
3737 Ok(())
......@@ -41,7 +41,7 @@ pub(crate) fn handle_work_done_progress_cancel(
4141 state: &mut GlobalState,
4242 params: WorkDoneProgressCancelParams,
4343) -> anyhow::Result<()> {
44 if let lsp_types::NumberOrString::String(s) = &params.token
44 if let lsp_types::ProgressToken::String(s) = &params.token
4545 && let Some(id) = s.strip_prefix("rust-analyzer/flycheck/")
4646 && let Ok(id) = id.parse::<u32>()
4747 && let Some(flycheck) = state.flycheck.get(id as usize)
......@@ -103,7 +103,7 @@ pub(crate) fn handle_did_change_text_document(
103103) -> anyhow::Result<()> {
104104 let _p = tracing::info_span!("handle_did_change_text_document").entered();
105105
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) {
107107 let Some(DocumentData { version, data }) = state.mem_docs.get_mut(&path) else {
108108 tracing::error!(?path, "unexpected DidChangeTextDocument");
109109 return Ok(());
......@@ -215,7 +215,7 @@ pub(crate) fn handle_did_change_configuration(
215215) -> anyhow::Result<()> {
216216 // As stated in https://github.com/microsoft/language-server-protocol/issues/676,
217217 // 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>(
219219 lsp_types::ConfigurationParams {
220220 items: vec![lsp_types::ConfigurationItem {
221221 scope_uri: None,
......@@ -553,7 +553,7 @@ pub(crate) fn handle_run_flycheck(
553553
554554pub(crate) fn handle_abort_run_test(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
555555 if state.test_run_session.take().is_some() {
556 state.send_notification::<lsp_ext::EndRunTest>(());
556 state.send_notification::<lsp_ext::EndRunTestNotification>(());
557557 }
558558 Ok(())
559559}
src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs+189-145
......@@ -18,11 +18,11 @@ use lsp_server::ErrorCode;
1818use lsp_types::{
1919 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
2020 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,
2626};
2727use paths::Utf8PathBuf;
2828use project_model::{CargoWorkspace, ManifestPath, ProjectWorkspaceKind, TargetKind};
......@@ -172,7 +172,7 @@ pub(crate) fn handle_view_hir(
172172 params: lsp_types::TextDocumentPositionParams,
173173) -> anyhow::Result<String> {
174174 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)?);
176176 let res = snap.analysis.view_hir(position)?;
177177 Ok(res)
178178}
......@@ -182,7 +182,7 @@ pub(crate) fn handle_view_mir(
182182 params: lsp_types::TextDocumentPositionParams,
183183) -> anyhow::Result<String> {
184184 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)?);
186186 let res = snap.analysis.view_mir(position)?;
187187 Ok(res)
188188}
......@@ -192,7 +192,7 @@ pub(crate) fn handle_interpret_function(
192192 params: lsp_types::TextDocumentPositionParams,
193193) -> anyhow::Result<String> {
194194 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)?);
196196 let res = snap.analysis.interpret_function(position)?;
197197 Ok(res)
198198}
......@@ -252,7 +252,7 @@ pub(crate) fn handle_run_test(
252252 params: lsp_ext::RunTestParams,
253253) -> anyhow::Result<()> {
254254 if let Some(_session) = state.test_run_session.take() {
255 state.send_notification::<lsp_ext::EndRunTest>(());
255 state.send_notification::<lsp_ext::EndRunTestNotification>(());
256256 }
257257
258258 let mut handles = vec![];
......@@ -358,9 +358,9 @@ pub(crate) fn handle_selection_range(
358358 let line_index = snap.file_line_index(file_id)?;
359359 let res: anyhow::Result<Vec<lsp_types::SelectionRange>> = params
360360 .positions
361 .into_iter()
361 .iter()
362362 .map(|position| {
363 let offset = from_proto::offset(&line_index, position)?;
363 let offset = from_proto::offset(&line_index, *position)?;
364364 let mut ranges = Vec::new();
365365 {
366366 let mut range = TextRange::new(offset, offset);
......@@ -401,9 +401,9 @@ pub(crate) fn handle_matching_brace(
401401 let line_index = snap.file_line_index(file_id)?;
402402 params
403403 .positions
404 .into_iter()
404 .iter()
405405 .map(|position| {
406 let offset = from_proto::offset(&line_index, position);
406 let offset = from_proto::offset(&line_index, *position);
407407 offset.map(|offset| {
408408 let offset = match snap.analysis.matching_brace(FilePosition { file_id, offset }) {
409409 Ok(Some(matching_brace_offset)) => matching_brace_offset,
......@@ -445,7 +445,7 @@ pub(crate) fn handle_on_enter(
445445 params: lsp_types::TextDocumentPositionParams,
446446) -> anyhow::Result<Option<Vec<lsp_ext::SnippetTextEdit>>> {
447447 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)?);
449449 let edit = match snap.analysis.on_enter(position)? {
450450 None => return Ok(None),
451451 Some(it) => it,
......@@ -469,9 +469,11 @@ pub(crate) fn handle_on_type_formatting(
469469 if !snap.config.typing_trigger_chars().contains(char_typed) {
470470 return Ok(None);
471471 }
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)?);
475477 let line_index = snap.file_line_index(position.file_id)?;
476478
477479 // in `ide`, the `on_type` invariant is that
......@@ -502,8 +504,8 @@ pub(crate) fn handle_on_type_formatting(
502504 Ok(Some(change))
503505}
504506
505pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportResult {
506 lsp_types::DocumentDiagnosticReportResult::Report(lsp_types::DocumentDiagnosticReport::Full(
507pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReport {
508 lsp_types::DocumentDiagnosticReport::RelatedFullDocumentDiagnosticReport(
507509 lsp_types::RelatedFullDocumentDiagnosticReport {
508510 related_documents: None,
509511 full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport {
......@@ -511,13 +513,13 @@ pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportRe
511513 items: vec![],
512514 },
513515 },
514 ))
516 )
515517}
516518
517519pub(crate) fn handle_document_diagnostics(
518520 snap: GlobalStateSnapshot,
519521 params: lsp_types::DocumentDiagnosticParams,
520) -> anyhow::Result<lsp_types::DocumentDiagnosticReportResult> {
522) -> anyhow::Result<lsp_types::DocumentDiagnosticReport> {
521523 let file_id = match from_proto::file_id(&snap, &params.text_document.uri)? {
522524 Some(it) => it,
523525 None => return Ok(empty_diagnostic_report()),
......@@ -554,8 +556,8 @@ pub(crate) fn handle_document_diagnostics(
554556 }
555557 None
556558 });
557 Ok(lsp_types::DocumentDiagnosticReportResult::Report(
558 lsp_types::DocumentDiagnosticReport::Full(lsp_types::RelatedFullDocumentDiagnosticReport {
559 Ok(lsp_types::DocumentDiagnosticReport::RelatedFullDocumentDiagnosticReport(
560 lsp_types::RelatedFullDocumentDiagnosticReport {
559561 full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport {
560562 result_id: Some("rust-analyzer".to_owned()),
561563 items: diagnostics.collect(),
......@@ -566,7 +568,7 @@ pub(crate) fn handle_document_diagnostics(
566568 .map(|(id, (items, _))| {
567569 (
568570 to_proto::url(&snap, id),
569 lsp_types::DocumentDiagnosticReportKind::Full(
571 lsp_types::RelatedDocument::FullDocumentDiagnosticReport(
570572 lsp_types::FullDocumentDiagnosticReport {
571573 result_id: Some("rust-analyzer".to_owned()),
572574 items,
......@@ -576,7 +578,7 @@ pub(crate) fn handle_document_diagnostics(
576578 })
577579 .collect()
578580 }),
579 }),
581 },
580582 ))
581583}
582584
......@@ -600,7 +602,7 @@ pub(crate) fn handle_document_symbol(
600602 for node in structure_nodes {
601603 let mut tags = Vec::new();
602604 if node.deprecated {
603 tags.push(SymbolTag::DEPRECATED)
605 tags.push(SymbolTag::Deprecated)
604606 };
605607
606608 #[allow(deprecated)]
......@@ -649,17 +651,19 @@ pub(crate) fn handle_document_symbol(
649651 fn flatten_document_symbol(
650652 symbol: &lsp_types::DocumentSymbol,
651653 container_name: Option<String>,
652 url: &Url,
654 url: &Uri,
653655 res: &mut Vec<SymbolInformation>,
654656 ) {
655657 #[allow(deprecated)]
656658 res.push(SymbolInformation {
657 name: symbol.name.clone(),
658 kind: symbol.kind,
659 tags: symbol.tags.clone(),
660659 deprecated: symbol.deprecated,
661660 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 },
663667 });
664668
665669 for child in symbol.children.iter().flatten() {
......@@ -696,7 +700,7 @@ pub(crate) fn handle_workspace_symbol(
696700 res = exec_query(&snap, Query::new(params.query), config.search_limit)?;
697701 }
698702
699 return Ok(Some(lsp_types::WorkspaceSymbolResponse::Nested(res)));
703 return Ok(Some(lsp_types::WorkspaceSymbolResponse::WorkspaceSymbolList(res)));
700704
701705 fn decide_search_kind_and_scope(
702706 params: &WorkspaceSymbolParams,
......@@ -743,19 +747,23 @@ pub(crate) fn handle_workspace_symbol(
743747 let container_name = nav.container_name.as_ref().map(|v| v.to_string());
744748
745749 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 ),
758753 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 },
759767 };
760768 res.push(info);
761769 }
......@@ -773,8 +781,8 @@ pub(crate) fn handle_will_rename_files(
773781 .files
774782 .into_iter()
775783 .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()?;
778786
779787 let from_path = from.to_file_path().ok()?;
780788 let to_path = to.to_file_path().ok()?;
......@@ -831,11 +839,11 @@ pub(crate) fn handle_will_rename_files(
831839
832840pub(crate) fn handle_goto_definition(
833841 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>> {
836844 let _p = tracing::info_span!("handle_goto_definition").entered();
837845 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)?);
839847 let config = snap.config.goto_definition(snap.minicore());
840848 let nav_info = match snap.analysis.goto_definition(position, &config)? {
841849 None => return Ok(None),
......@@ -848,60 +856,84 @@ pub(crate) fn handle_goto_definition(
848856
849857pub(crate) fn handle_goto_declaration(
850858 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>> {
853861 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)?);
858864 let config = snap.config.goto_definition(snap.minicore());
859865 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 }
861893 Some(it) => it,
862894 };
863895 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)?;
865897 Ok(Some(res))
866898}
867899
868900pub(crate) fn handle_goto_implementation(
869901 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>> {
872904 let _p = tracing::info_span!("handle_goto_implementation").entered();
873905 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)?);
875907 let nav_info =
876908 match snap.analysis.goto_implementation(&snap.config.goto_implementation(), position)? {
877909 None => return Ok(None),
878910 Some(it) => it,
879911 };
880912 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)?;
882914 Ok(Some(res))
883915}
884916
885917pub(crate) fn handle_goto_type_definition(
886918 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>> {
889921 let _p = tracing::info_span!("handle_goto_type_definition").entered();
890922 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)?);
892924 let nav_info = match snap.analysis.goto_type_definition(position)? {
893925 None => return Ok(None),
894926 Some(it) => it,
895927 };
896928 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)?;
898930 Ok(Some(res))
899931}
900932
901933pub(crate) fn handle_parent_module(
902934 snap: GlobalStateSnapshot,
903935 params: lsp_types::TextDocumentPositionParams,
904) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> {
936) -> anyhow::Result<Option<lsp_types::DefinitionResponse>> {
905937 let _p = tracing::info_span!("handle_parent_module").entered();
906938 if let Ok(file_path) = &params.text_document.uri.to_file_path() {
907939 if file_path.file_name().unwrap_or_default() == "Cargo.toml" {
......@@ -965,7 +997,7 @@ pub(crate) fn handle_parent_module(
965997 }
966998
967999 // 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)?);
9691001 let navs = snap.analysis.parent_module(position)?;
9701002 let res = to_proto::goto_definition_response(&snap, None, navs)?;
9711003 Ok(Some(res))
......@@ -974,10 +1006,10 @@ pub(crate) fn handle_parent_module(
9741006pub(crate) fn handle_child_modules(
9751007 snap: GlobalStateSnapshot,
9761008 params: lsp_types::TextDocumentPositionParams,
977) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> {
1009) -> anyhow::Result<Option<lsp_types::DefinitionResponse>> {
9781010 let _p = tracing::info_span!("handle_child_modules").entered();
9791011 // 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)?);
9811013 let navs = snap.analysis.child_modules(position)?;
9821014 let res = to_proto::goto_definition_response(&snap, None, navs)?;
9831015 Ok(Some(res))
......@@ -1042,6 +1074,10 @@ pub(crate) fn handle_runnables(
10421074 cargo_args.push("--all-targets".to_owned());
10431075 }
10441076 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 }
10451081 res.push(lsp_ext::Runnable {
10461082 label: format!(
10471083 "cargo {cmd} -p {}{all_targets}",
......@@ -1072,6 +1108,10 @@ pub(crate) fn handle_runnables(
10721108 {
10731109 let mut cargo_args = vec!["check".to_owned(), "--workspace".to_owned()];
10741110 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 }
10751115 res.push(lsp_ext::Runnable {
10761116 label: "cargo check --workspace".to_owned(),
10771117 location: None,
......@@ -1103,7 +1143,7 @@ pub(crate) fn handle_related_tests(
11031143 params: lsp_types::TextDocumentPositionParams,
11041144) -> anyhow::Result<Vec<lsp_ext::TestInfo>> {
11051145 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)?);
11071147
11081148 let tests = snap.analysis.related_tests(position, None)?;
11091149 let mut res = Vec::new();
......@@ -1119,14 +1159,14 @@ pub(crate) fn handle_related_tests(
11191159pub(crate) fn handle_completion(
11201160 snap: GlobalStateSnapshot,
11211161 lsp_types::CompletionParams {
1122 text_document_position,
1162 text_document_position_params,
11231163 context,
11241164 ..
11251165 }: lsp_types::CompletionParams,
11261166) -> anyhow::Result<Option<lsp_types::CompletionResponse>> {
11271167 let _p = tracing::info_span!("handle_completion").entered();
11281168 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)?);
11301170 let line_index = snap.file_line_index(position.file_id)?;
11311171 let completion_trigger_character =
11321172 context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next());
......@@ -1149,12 +1189,17 @@ pub(crate) fn handle_completion(
11491189 &completion_config.fields_to_resolve,
11501190 &line_index,
11511191 snap.file_version(position.file_id),
1152 text_document_position,
1192 &text_document_position_params,
11531193 completion_trigger_character,
11541194 items,
11551195 );
11561196
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 };
11581203 Ok(Some(completion_list.into()))
11591204}
11601205
......@@ -1217,7 +1262,7 @@ pub(crate) fn handle_completion_resolve(
12171262 &forced_resolve_completions_config.fields_to_resolve,
12181263 &line_index,
12191264 snap.file_version(position.file_id),
1220 resolve_data.position,
1265 &resolve_data.position,
12211266 resolve_data.trigger_character,
12221267 vec![corresponding_completion],
12231268 );
......@@ -1287,7 +1332,7 @@ pub(crate) fn handle_signature_help(
12871332) -> anyhow::Result<Option<lsp_types::SignatureHelp>> {
12881333 let _p = tracing::info_span!("handle_signature_help").entered();
12891334 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)?);
12911336 let help = match snap.analysis.signature_help(position)? {
12921337 Some(it) => it,
12931338 None => return Ok(None),
......@@ -1319,7 +1364,7 @@ pub(crate) fn handle_hover(
13191364 let markup_kind = hover.format;
13201365 let hover = lsp_ext::Hover {
13211366 hover: lsp_types::Hover {
1322 contents: HoverContents::Markup(to_proto::markup_content(
1367 contents: Contents::MarkupContent(to_proto::markup_content(
13231368 info.info.markup,
13241369 markup_kind,
13251370 )),
......@@ -1337,16 +1382,17 @@ pub(crate) fn handle_hover(
13371382
13381383pub(crate) fn handle_prepare_rename(
13391384 snap: GlobalStateSnapshot,
1340 params: lsp_types::TextDocumentPositionParams,
1341) -> anyhow::Result<Option<PrepareRenameResponse>> {
1385 params: lsp_types::PrepareRenameParams,
1386) -> anyhow::Result<Option<PrepareRenameResult>> {
13421387 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)?);
13441390
13451391 let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?;
13461392
13471393 let line_index = snap.file_line_index(position.file_id)?;
13481394 let range = to_proto::range(&line_index, change.range);
1349 Ok(Some(PrepareRenameResponse::Range(range)))
1395 Ok(Some(PrepareRenameResult::Range(range)))
13501396}
13511397
13521398pub(crate) fn handle_rename(
......@@ -1354,7 +1400,8 @@ pub(crate) fn handle_rename(
13541400 params: RenameParams,
13551401) -> anyhow::Result<Option<WorkspaceEdit>> {
13561402 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)?);
13581405
13591406 let source_root = snap.analysis.source_root_id(position.file_id).ok();
13601407 let config = snap.config.rename(source_root);
......@@ -1375,13 +1422,9 @@ pub(crate) fn handle_rename(
13751422
13761423 let workspace_edit = to_proto::workspace_edit(&snap, change)?;
13771424
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)?;
13851428 }
13861429 }
13871430
......@@ -1393,7 +1436,8 @@ pub(crate) fn handle_references(
13931436 params: lsp_types::ReferenceParams,
13941437) -> anyhow::Result<Option<Vec<Location>>> {
13951438 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)?);
13971441
13981442 let exclude_imports = snap.config.find_all_refs_exclude_imports();
13991443 let exclude_tests = snap.config.find_all_refs_exclude_tests();
......@@ -1442,7 +1486,7 @@ pub(crate) fn handle_formatting(
14421486) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> {
14431487 let _p = tracing::info_span!("handle_formatting").entered();
14441488
1445 run_rustfmt(&snap, params.text_document, None)
1489 run_rustfmt(&snap, &params.text_document, None)
14461490}
14471491
14481492pub(crate) fn handle_range_formatting(
......@@ -1451,7 +1495,7 @@ pub(crate) fn handle_range_formatting(
14511495) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> {
14521496 let _p = tracing::info_span!("handle_range_formatting").entered();
14531497
1454 run_rustfmt(&snap, params.text_document, Some(params.range))
1498 run_rustfmt(&snap, &params.text_document, Some(params.range))
14551499}
14561500
14571501pub(crate) fn handle_code_action(
......@@ -1506,8 +1550,8 @@ pub(crate) fn handle_code_action(
15061550 let changes = code_action.edit.as_ref().and_then(|it| it.document_changes.as_ref());
15071551 if let Some(changes) = changes {
15081552 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)?
15111555 }
15121556 }
15131557 }
......@@ -1609,8 +1653,8 @@ pub(crate) fn handle_code_action_resolve(
16091653 && let Some(changes) = edit.document_changes.as_ref()
16101654 {
16111655 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)?
16141658 }
16151659 }
16161660 }
......@@ -1717,7 +1761,7 @@ pub(crate) fn handle_document_highlight(
17171761) -> anyhow::Result<Option<Vec<lsp_types::DocumentHighlight>>> {
17181762 let _p = tracing::info_span!("handle_document_highlight").entered();
17191763 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)?);
17211765 let line_index = snap.file_line_index(position.file_id)?;
17221766 let source_root = snap.analysis.source_root_id(position.file_id)?;
17231767
......@@ -1750,7 +1794,7 @@ pub(crate) fn handle_ssr(
17501794 .map(|range| from_proto::file_range(&snap, &params.position.text_document, *range))
17511795 .collect::<Result<Option<Vec<_>>, _>>()?
17521796 );
1753 let position = try_default!(from_proto::file_position(&snap, params.position)?);
1797 let position = try_default!(from_proto::file_position(&snap, &params.position)?);
17541798 let source_change = snap.analysis.structural_search_replace(
17551799 &params.query,
17561800 params.parse_only,
......@@ -1855,7 +1899,7 @@ pub(crate) fn handle_call_hierarchy_prepare(
18551899) -> anyhow::Result<Option<Vec<CallHierarchyItem>>> {
18561900 let _p = tracing::info_span!("handle_call_hierarchy_prepare").entered();
18571901 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)?);
18591903
18601904 let config = snap.config.call_hierarchy(snap.minicore());
18611905 let nav_info = match snap.analysis.call_hierarchy(position, &config)? {
......@@ -1890,25 +1934,26 @@ pub(crate) fn handle_call_hierarchy_incoming(
18901934 Some(it) => it,
18911935 };
18921936
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 ))
19121957}
19131958
19141959pub(crate) fn handle_call_hierarchy_outgoing(
......@@ -1951,7 +1996,7 @@ pub(crate) fn handle_call_hierarchy_outgoing(
19511996pub(crate) fn handle_semantic_tokens_full(
19521997 snap: GlobalStateSnapshot,
19531998 params: SemanticTokensParams,
1954) -> anyhow::Result<Option<SemanticTokensResult>> {
1999) -> anyhow::Result<Option<SemanticTokens>> {
19552000 let _p = tracing::info_span!("handle_semantic_tokens_full").entered();
19562001
19572002 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(
19752020 // Unconditionally cache the tokens
19762021 snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens.clone());
19772022
1978 Ok(Some(semantic_tokens.into()))
2023 Ok(Some(semantic_tokens))
19792024}
19802025
19812026pub(crate) fn handle_semantic_tokens_full_delta(
19822027 snap: GlobalStateSnapshot,
19832028 params: SemanticTokensDeltaParams,
1984) -> anyhow::Result<Option<SemanticTokensFullDeltaResult>> {
2029) -> anyhow::Result<Option<SemanticTokensDeltaResponse>> {
19852030 let _p = tracing::info_span!("handle_semantic_tokens_full_delta").entered();
19862031
19872032 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(
20232068pub(crate) fn handle_semantic_tokens_range(
20242069 snap: GlobalStateSnapshot,
20252070 params: SemanticTokensRangeParams,
2026) -> anyhow::Result<Option<SemanticTokensRangeResult>> {
2071) -> anyhow::Result<Option<SemanticTokens>> {
20272072 let _p = tracing::info_span!("handle_semantic_tokens_range").entered();
20282073
20292074 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(
20432088 snap.config.semantics_tokens_augments_syntax_tokens(),
20442089 snap.config.highlighting_non_standard_tokens(),
20452090 );
2046 Ok(Some(semantic_tokens.into()))
2091 Ok(Some(semantic_tokens))
20472092}
20482093
20492094pub(crate) fn handle_open_docs(
......@@ -2051,7 +2096,7 @@ pub(crate) fn handle_open_docs(
20512096 params: lsp_types::TextDocumentPositionParams,
20522097) -> anyhow::Result<ExternalDocsResponse> {
20532098 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)?);
20552100
20562101 let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind {
20572102 ProjectWorkspaceKind::Cargo { cargo, .. }
......@@ -2078,8 +2123,8 @@ pub(crate) fn handle_open_docs(
20782123 };
20792124 };
20802125
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());
20832128
20842129 if snap.config.local_docs() {
20852130 Ok(ExternalDocsResponse::WithLocal(ExternalDocsPair { web, local }))
......@@ -2091,7 +2136,7 @@ pub(crate) fn handle_open_docs(
20912136pub(crate) fn handle_open_cargo_toml(
20922137 snap: GlobalStateSnapshot,
20932138 params: lsp_ext::OpenCargoTomlParams,
2094) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> {
2139) -> anyhow::Result<Option<lsp_types::DefinitionResponse>> {
20952140 let _p = tracing::info_span!("handle_open_cargo_toml").entered();
20962141 let file_id = try_default!(from_proto::file_id(&snap, &params.text_document.uri)?);
20972142
......@@ -2101,8 +2146,9 @@ pub(crate) fn handle_open_cargo_toml(
21012146 };
21022147
21032148 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 ));
21062152 Ok(Some(res))
21072153}
21082154
......@@ -2184,7 +2230,7 @@ fn show_impl_command_link(
21842230 let locations: Vec<_> = nav_data
21852231 .info
21862232 .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())
21882234 .collect();
21892235 let title = to_proto::implementation_title(locations.len());
21902236 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
23592405
23602406fn run_rustfmt(
23612407 snap: &GlobalStateSnapshot,
2362 text_document: TextDocumentIdentifier,
2408 text_document: &TextDocumentIdentifier,
23632409 range: Option<lsp_types::Range>,
23642410) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> {
23652411 let file_id = try_default!(from_proto::file_id(snap, &text_document.uri)?);
......@@ -2425,7 +2471,7 @@ fn run_rustfmt(
24252471 .into());
24262472 }
24272473
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)?);
24292475 let start_line = line_index.index.line_col(frange.range.start()).line;
24302476 let end_line = line_index.index.line_col(frange.range.end()).line;
24312477
......@@ -2656,20 +2702,26 @@ fn crate_path(root_file_path: &VfsPath) -> Option<VfsPath> {
26562702 None
26572703}
26582704
2659fn to_url(path: VfsPath) -> Option<Url> {
2705fn to_url(path: VfsPath) -> Option<Uri> {
26602706 let path = path.as_path()?;
26612707 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()
26632709}
26642710
2665fn resource_ops_supported(config: &Config, kind: ResourceOperationKind) -> anyhow::Result<()> {
2666 if !matches!(config.workspace_edit_resource_operations(), Some(resops) if resops.contains(&kind))
2711fn 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))
26672719 {
26682720 return Err(LspError::new(
26692721 ErrorCode::RequestFailed as i32,
26702722 format!(
26712723 "Client does not support {} capability.",
2672 match kind {
2724 match op {
26732725 ResourceOperationKind::Create => "create",
26742726 ResourceOperationKind::Rename => "rename",
26752727 ResourceOperationKind::Delete => "delete",
......@@ -2682,14 +2734,6 @@ fn resource_ops_supported(config: &Config, kind: ResourceOperationKind) -> anyho
26822734 Ok(())
26832735}
26842736
2685fn 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
26932737pub(crate) fn diff(left: &str, right: &str) -> TextEdit {
26942738 use dissimilar::Chunk;
26952739
src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs+2-4
......@@ -60,6 +60,7 @@ pub mod tracing {
6060pub mod config;
6161mod global_state;
6262pub mod lsp;
63
6364use self::lsp::ext as lsp_ext;
6465
6566#[cfg(test)]
......@@ -72,10 +73,7 @@ pub use crate::{
7273 version::version,
7374};
7475
75pub fn from_json<T: DeserializeOwned>(
76 what: &'static str,
77 json: &serde_json::Value,
78) -> anyhow::Result<T> {
76pub fn from_json<T: DeserializeOwned>(what: &str, json: &serde_json::Value) -> anyhow::Result<T> {
7977 serde_json::from_value(json.clone())
8078 .map_err(|e| anyhow::format_err!("Failed to deserialize {what}: {e}; {json}"))
8179}
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs+82-68
......@@ -2,17 +2,18 @@
22use ide::{CompletionFieldsToResolve, InlayFieldsToResolve};
33use ide_db::{FxHashSet, line_index::WideEncoding};
44use 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,
1617};
1718use serde_json::json;
1819
......@@ -32,9 +33,9 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
3233 _ => None,
3334 },
3435 },
35 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
36 text_document_sync: Some(TextDocumentSync::Options(TextDocumentSyncOptions {
3637 open_close: Some(true),
37 change: Some(TextDocumentSyncKind::INCREMENTAL),
38 change: Some(TextDocumentSyncKind::Incremental),
3839 will_save: None,
3940 will_save_wait_until: None,
4041 save: if config.caps().did_save_text_document_dynamic_registration() {
......@@ -43,7 +44,9 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
4344 Some(SaveOptions::default().into())
4445 },
4546 })),
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)),
4750 completion_provider: Some(CompletionOptions {
4851 resolve_provider: if config.client_is_neovim() {
4952 config.has_completion_item_resolve_additionalTextEdits().then_some(true)
......@@ -65,20 +68,24 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
6568 retrigger_characters: None,
6669 work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
6770 }),
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)),
7678 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)),
7984 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)),
8289 },
8390 document_on_type_formatting_provider: Some({
8491 let mut chars = ide::Analysis::SUPPORTED_TRIGGER_CHARS.iter();
......@@ -87,22 +94,21 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
8794 more_trigger_character: Some(chars.map(|c| c.to_string()).collect()),
8895 }
8996 }),
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 {
9398 prepare_provider: Some(true),
9499 work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
95100 })),
96 linked_editing_range_provider: None,
97101 document_link_provider: None,
98102 color_provider: None,
103 folding_range_provider: Some(FoldingRangeProvider::Bool(true)),
104 declaration_provider: Some(DeclarationProvider::Bool(true)),
99105 execute_command_provider: None,
100 workspace: Some(WorkspaceServerCapabilities {
106 workspace: Some(WorkspaceOptions {
101107 workspace_folders: Some(WorkspaceFoldersServerCapabilities {
102108 supported: Some(true),
103 change_notifications: Some(OneOf::Left(true)),
109 change_notifications: Some(ChangeNotifications::Bool(true)),
104110 }),
105 file_operations: Some(WorkspaceFileOperationsServerCapabilities {
111 file_operations: Some(FileOperationOptions {
106112 did_create: None,
107113 will_create: None,
108114 did_rename: None,
......@@ -129,29 +135,45 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
129135 did_delete: None,
130136 will_delete: None,
131137 }),
138 text_document_content: None,
132139 }),
133 call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
140 call_hierarchy_provider: Some(CallHierarchyProvider::Bool(true)),
134141 semantic_tokens_provider: Some(
135142 SemanticTokensOptions {
136143 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(),
139150 },
140151
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)),
143156 work_done_progress_options: Default::default(),
144157 }
145158 .into(),
146159 ),
147160 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,
154162 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,
155177 experimental: Some(json!({
156178 "externalDocs": true,
157179 "hoverRange": true,
......@@ -168,16 +190,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
168190 "ssr": true,
169191 "workspaceSymbolScopeKindFiltering": true,
170192 })),
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,
181194 }
182195}
183196
......@@ -244,33 +257,34 @@ impl ClientCapabilities {
244257 })() == Some(true)
245258 }
246259
247 fn completion_item(&self) -> Option<CompletionOptionsCompletionItem> {
248 Some(CompletionOptionsCompletionItem {
260 fn completion_item(&self) -> Option<ServerCompletionItemOptions> {
261 Some(ServerCompletionItemOptions {
249262 label_details_support: Some(self.completion_label_details_support()),
250263 })
251264 }
252265
253 fn code_action_capabilities(&self) -> CodeActionProviderCapability {
266 fn code_action_capabilities(&self) -> CodeActionProvider {
254267 self.0
255268 .text_document
256269 .as_ref()
257270 .and_then(|it| it.code_action.as_ref())
258271 .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 {
261274 // Advertise support for all built-in CodeActionKinds.
262275 // Ideally we would base this off of the client capabilities
263276 // but the client is supposed to fall back gracefully for unknown values.
264277 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,
271284 ]),
272285 resolve_provider: Some(true),
273286 work_done_progress_options: Default::default(),
287 documentation: None,
274288 })
275289 })
276290 }
......@@ -307,8 +321,8 @@ impl ClientCapabilities {
307321 }
308322
309323 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();
312326 caps.did_save == Some(true) && caps.dynamic_registration == Some(true)
313327 }
314328
......@@ -501,7 +515,7 @@ impl ClientCapabilities {
501515 }
502516
503517 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 })()
505519 .unwrap_or_default()
506520 }
507521
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs+193-142
......@@ -8,17 +8,16 @@
88
99use std::ops;
1010
11use lsp_types::Url;
12use lsp_types::request::Request;
1311use 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,
1615};
1716use paths::Utf8PathBuf;
1817use rustc_hash::FxHashMap;
1918use serde::{Deserialize, Serialize};
2019
21pub enum InternalTestingFetchConfig {}
20pub enum InternalTestingFetchConfigRequest {}
2221
2322#[derive(Deserialize, Serialize, Debug)]
2423pub enum InternalTestingFetchConfigOption {
......@@ -32,11 +31,13 @@ pub enum InternalTestingFetchConfigResponse {
3231 CheckWorkspace(bool),
3332}
3433
35impl Request for InternalTestingFetchConfig {
34impl Request for InternalTestingFetchConfigRequest {
3635 type Params = InternalTestingFetchConfigParams;
3736 // Option is solely to circumvent Default bound.
3837 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;
4041}
4142
4243#[derive(Deserialize, Serialize, Debug)]
......@@ -45,12 +46,13 @@ pub struct InternalTestingFetchConfigParams {
4546 pub text_document: Option<TextDocumentIdentifier>,
4647 pub config: InternalTestingFetchConfigOption,
4748}
48pub enum AnalyzerStatus {}
49pub enum AnalyzerStatusRequest {}
4950
50impl Request for AnalyzerStatus {
51impl Request for AnalyzerStatusRequest {
5152 type Params = AnalyzerStatusParams;
5253 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;
5456}
5557
5658#[derive(Deserialize, Serialize, Debug)]
......@@ -64,14 +66,15 @@ pub struct AnalyzerStatusParams {
6466pub struct CrateInfoResult {
6567 pub name: Option<String>,
6668 pub version: Option<String>,
67 pub path: Url,
69 pub path: Uri,
6870}
69pub enum FetchDependencyList {}
71pub enum FetchDependencyListRequest {}
7072
71impl Request for FetchDependencyList {
73impl Request for FetchDependencyListRequest {
7274 type Params = FetchDependencyListParams;
7375 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;
7578}
7679
7780#[derive(Deserialize, Serialize, Debug)]
......@@ -84,36 +87,40 @@ pub struct FetchDependencyListResult {
8487 pub crates: Vec<CrateInfoResult>,
8588}
8689
87pub enum MemoryUsage {}
90pub enum MemoryUsageRequest {}
8891
89impl Request for MemoryUsage {
92impl Request for MemoryUsageRequest {
9093 type Params = ();
9194 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;
9397}
9498
95pub enum ReloadWorkspace {}
99pub enum ReloadWorkspaceRequest {}
96100
97impl Request for ReloadWorkspace {
101impl Request for ReloadWorkspaceRequest {
98102 type Params = ();
99103 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;
101106}
102107
103pub enum RebuildProcMacros {}
108pub enum RebuildProcMacrosRequest {}
104109
105impl Request for RebuildProcMacros {
110impl Request for RebuildProcMacrosRequest {
106111 type Params = ();
107112 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;
109115}
110116
111pub enum ViewSyntaxTree {}
117pub enum ViewSyntaxTreeRequest {}
112118
113impl Request for ViewSyntaxTree {
119impl Request for ViewSyntaxTreeRequest {
114120 type Params = ViewSyntaxTreeParams;
115121 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;
117124}
118125
119126#[derive(Deserialize, Serialize, Debug)]
......@@ -122,36 +129,40 @@ pub struct ViewSyntaxTreeParams {
122129 pub text_document: TextDocumentIdentifier,
123130}
124131
125pub enum ViewHir {}
132pub enum ViewHirRequest {}
126133
127impl Request for ViewHir {
134impl Request for ViewHirRequest {
128135 type Params = lsp_types::TextDocumentPositionParams;
129136 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;
131139}
132140
133pub enum ViewMir {}
141pub enum ViewMirRequest {}
134142
135impl Request for ViewMir {
143impl Request for ViewMirRequest {
136144 type Params = lsp_types::TextDocumentPositionParams;
137145 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;
139148}
140149
141pub enum InterpretFunction {}
150pub enum InterpretFunctionRequest {}
142151
143impl Request for InterpretFunction {
152impl Request for InterpretFunctionRequest {
144153 type Params = lsp_types::TextDocumentPositionParams;
145154 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;
147157}
148158
149pub enum ViewFileText {}
159pub enum ViewFileTextRequest {}
150160
151impl Request for ViewFileText {
161impl Request for ViewFileTextRequest {
152162 type Params = lsp_types::TextDocumentIdentifier;
153163 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;
155166}
156167
157168#[derive(Deserialize, Serialize, Debug)]
......@@ -161,12 +172,13 @@ pub struct ViewCrateGraphParams {
161172 pub full: bool,
162173}
163174
164pub enum ViewCrateGraph {}
175pub enum ViewCrateGraphRequest {}
165176
166impl Request for ViewCrateGraph {
177impl Request for ViewCrateGraphRequest {
167178 type Params = ViewCrateGraphParams;
168179 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;
170182}
171183
172184#[derive(Deserialize, Serialize, Debug)]
......@@ -175,12 +187,13 @@ pub struct ViewItemTreeParams {
175187 pub text_document: TextDocumentIdentifier,
176188}
177189
178pub enum ViewItemTree {}
190pub enum ViewItemTreeRequest {}
179191
180impl Request for ViewItemTree {
192impl Request for ViewItemTreeRequest {
181193 type Params = ViewItemTreeParams;
182194 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;
184197}
185198
186199#[derive(Deserialize, Serialize, Debug)]
......@@ -218,19 +231,22 @@ pub struct DiscoverTestResults {
218231 pub scope_file: Option<Vec<TextDocumentIdentifier>>,
219232}
220233
221pub enum DiscoverTest {}
234pub enum DiscoverTestRequest {}
222235
223impl Request for DiscoverTest {
236impl Request for DiscoverTestRequest {
224237 type Params = DiscoverTestParams;
225238 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;
227241}
228242
229pub enum DiscoveredTests {}
243pub enum DiscoveredTestsNotification {}
230244
231impl Notification for DiscoveredTests {
245impl Notification for DiscoveredTestsNotification {
232246 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;
234250}
235251
236252#[derive(Deserialize, Serialize, Debug)]
......@@ -240,33 +256,38 @@ pub struct RunTestParams {
240256 pub exclude: Option<Vec<String>>,
241257}
242258
243pub enum RunTest {}
259pub enum RunTestRequest {}
244260
245impl Request for RunTest {
261impl Request for RunTestRequest {
246262 type Params = RunTestParams;
247263 type Result = ();
248 const METHOD: &'static str = "experimental/runTest";
264 const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/runTest");
265 const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer;
249266}
250267
251pub enum EndRunTest {}
268pub enum EndRunTestNotification {}
252269
253impl Notification for EndRunTest {
270impl Notification for EndRunTestNotification {
254271 type Params = ();
255 const METHOD: &'static str = "experimental/endRunTest";
272 const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/endRunTest");
273 const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer;
256274}
257275
258pub enum AppendOutputToRunTest {}
276pub enum AppendOutputToRunTestNotification {}
259277
260impl Notification for AppendOutputToRunTest {
278impl Notification for AppendOutputToRunTestNotification {
261279 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;
263283}
264284
265pub enum AbortRunTest {}
285pub enum AbortRunTestNotification {}
266286
267impl Notification for AbortRunTest {
287impl Notification for AbortRunTestNotification {
268288 type Params = ();
269 const METHOD: &'static str = "experimental/abortRunTest";
289 const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/abortRunTest");
290 const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer;
270291}
271292
272293#[derive(Deserialize, Serialize, Debug)]
......@@ -286,19 +307,22 @@ pub struct ChangeTestStateParams {
286307 pub state: TestState,
287308}
288309
289pub enum ChangeTestState {}
310pub enum ChangeTestStateNotification {}
290311
291impl Notification for ChangeTestState {
312impl Notification for ChangeTestStateNotification {
292313 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;
294317}
295318
296pub enum ExpandMacro {}
319pub enum ExpandMacroRequest {}
297320
298impl Request for ExpandMacro {
321impl Request for ExpandMacroRequest {
299322 type Params = ExpandMacroParams;
300323 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;
302326}
303327
304328#[derive(Deserialize, Serialize, Debug)]
......@@ -315,12 +339,14 @@ pub struct ExpandedMacro {
315339 pub expansion: String,
316340}
317341
318pub enum ViewRecursiveMemoryLayout {}
342pub enum ViewRecursiveMemoryLayoutRequest {}
319343
320impl Request for ViewRecursiveMemoryLayout {
344impl Request for ViewRecursiveMemoryLayoutRequest {
321345 type Params = lsp_types::TextDocumentPositionParams;
322346 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;
324350}
325351
326352#[derive(Deserialize, Serialize, Debug)]
......@@ -342,32 +368,38 @@ pub struct MemoryLayoutNode {
342368 pub children_len: u64,
343369}
344370
345pub enum CancelFlycheck {}
371pub enum CancelFlycheckNotification {}
346372
347impl Notification for CancelFlycheck {
373impl Notification for CancelFlycheckNotification {
348374 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;
350378}
351379
352pub enum RunFlycheck {}
380pub enum RunFlycheckNotification {}
353381
354impl Notification for RunFlycheck {
382impl Notification for RunFlycheckNotification {
355383 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;
357386}
358387
359pub enum ClearFlycheck {}
388pub enum ClearFlycheckNotification {}
360389
361impl Notification for ClearFlycheck {
390impl Notification for ClearFlycheckNotification {
362391 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;
364394}
365395
366pub enum OpenServerLogs {}
396pub enum OpenServerLogsNotification {}
367397
368impl Notification for OpenServerLogs {
398impl Notification for OpenServerLogsNotification {
369399 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;
371403}
372404
373405#[derive(Deserialize, Serialize, Debug)]
......@@ -376,12 +408,13 @@ pub struct RunFlycheckParams {
376408 pub text_document: Option<TextDocumentIdentifier>,
377409}
378410
379pub enum MatchingBrace {}
411pub enum MatchingBraceRequest {}
380412
381impl Request for MatchingBrace {
413impl Request for MatchingBraceRequest {
382414 type Params = MatchingBraceParams;
383415 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;
385418}
386419
387420#[derive(Deserialize, Serialize, Debug)]
......@@ -391,28 +424,31 @@ pub struct MatchingBraceParams {
391424 pub positions: Vec<Position>,
392425}
393426
394pub enum ParentModule {}
427pub enum ParentModuleRequest {}
395428
396impl Request for ParentModule {
429impl Request for ParentModuleRequest {
397430 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;
400434}
401435
402pub enum ChildModules {}
436pub enum ChildModulesRequest {}
403437
404impl Request for ChildModules {
438impl Request for ChildModulesRequest {
405439 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;
408443}
409444
410pub enum JoinLines {}
445pub enum JoinLinesRequest {}
411446
412impl Request for JoinLines {
447impl Request for JoinLinesRequest {
413448 type Params = JoinLinesParams;
414449 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;
416452}
417453
418454#[derive(Deserialize, Serialize, Debug)]
......@@ -422,20 +458,22 @@ pub struct JoinLinesParams {
422458 pub ranges: Vec<Range>,
423459}
424460
425pub enum OnEnter {}
461pub enum OnEnterRequest {}
426462
427impl Request for OnEnter {
463impl Request for OnEnterRequest {
428464 type Params = lsp_types::TextDocumentPositionParams;
429465 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;
431468}
432469
433pub enum Runnables {}
470pub enum RunnablesRequest {}
434471
435impl Request for Runnables {
472impl Request for RunnablesRequest {
436473 type Params = RunnablesParams;
437474 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;
439477}
440478
441479#[derive(Serialize, Deserialize, Debug, Clone)]
......@@ -488,12 +526,13 @@ pub struct ShellRunnableArgs {
488526 pub args: Vec<String>,
489527}
490528
491pub enum RelatedTests {}
529pub enum RelatedTestsRequest {}
492530
493impl Request for RelatedTests {
531impl Request for RelatedTestsRequest {
494532 type Params = lsp_types::TextDocumentPositionParams;
495533 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;
497536}
498537
499538#[derive(Debug, Deserialize, Serialize)]
......@@ -501,12 +540,13 @@ pub struct TestInfo {
501540 pub runnable: Runnable,
502541}
503542
504pub enum Ssr {}
543pub enum SsrRequest {}
505544
506impl Request for Ssr {
545impl Request for SsrRequest {
507546 type Params = SsrParams;
508547 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;
510550}
511551
512552#[derive(Debug, Deserialize, Serialize)]
......@@ -528,7 +568,8 @@ pub enum ServerStatusNotification {}
528568
529569impl Notification for ServerStatusNotification {
530570 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;
532573}
533574
534575#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
......@@ -562,7 +603,8 @@ pub enum CodeActionRequest {}
562603impl Request for CodeActionRequest {
563604 type Params = lsp_types::CodeActionParams;
564605 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;
566608}
567609
568610pub enum CodeActionResolveRequest {}
......@@ -570,7 +612,8 @@ pub enum CodeActionResolveRequest {}
570612impl Request for CodeActionResolveRequest {
571613 type Params = CodeAction;
572614 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;
574617}
575618
576619#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
......@@ -604,7 +647,7 @@ pub struct CodeActionData {
604647#[serde(rename_all = "camelCase")]
605648pub struct SnippetWorkspaceEdit {
606649 #[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>>>,
608651 #[serde(skip_serializing_if = "Option::is_none")]
609652 pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>,
610653 #[serde(skip_serializing_if = "Option::is_none")]
......@@ -619,7 +662,7 @@ pub struct SnippetWorkspaceEdit {
619662#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
620663#[serde(untagged, rename_all = "lowercase")]
621664pub enum SnippetDocumentChangeOperation {
622 Op(lsp_types::ResourceOp),
665 Change(lsp_types::DocumentChange),
623666 Edit(SnippetTextDocumentEdit),
624667}
625668
......@@ -647,7 +690,8 @@ pub enum HoverRequest {}
647690impl Request for HoverRequest {
648691 type Params = HoverParams;
649692 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;
651695}
652696
653697#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
......@@ -691,18 +735,19 @@ pub struct CommandLink {
691735 pub tooltip: Option<String>,
692736}
693737
694pub enum ExternalDocs {}
738pub enum ExternalDocsRequest {}
695739
696impl Request for ExternalDocs {
740impl Request for ExternalDocsRequest {
697741 type Params = lsp_types::TextDocumentPositionParams;
698742 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;
700745}
701746
702747#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
703748#[serde(untagged)]
704749pub enum ExternalDocsResponse {
705 Simple(Option<lsp_types::Url>),
750 Simple(Option<lsp_types::Uri>),
706751 WithLocal(ExternalDocsPair),
707752}
708753
......@@ -715,16 +760,17 @@ impl Default for ExternalDocsResponse {
715760#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
716761#[serde(rename_all = "camelCase")]
717762pub 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>,
720765}
721766
722pub enum OpenCargoToml {}
767pub enum OpenCargoTomlRequest {}
723768
724impl Request for OpenCargoToml {
769impl Request for OpenCargoTomlRequest {
725770 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;
728774}
729775
730776#[derive(Serialize, Deserialize, Debug)]
......@@ -744,16 +790,17 @@ pub struct CodeLensResolveData {
744790#[derive(Debug, Serialize, Deserialize)]
745791#[serde(rename_all = "camelCase")]
746792pub enum CodeLensResolveDataKind {
747 Impls(lsp_types::request::GotoImplementationParams),
793 Impls(lsp_types::ImplementationParams),
748794 References(lsp_types::TextDocumentPositionParams),
749795}
750796
751pub enum MoveItem {}
797pub enum MoveItemRequest {}
752798
753impl Request for MoveItem {
799impl Request for MoveItemRequest {
754800 type Params = MoveItemParams;
755801 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;
757804}
758805
759806#[derive(Serialize, Deserialize, Debug)]
......@@ -771,12 +818,13 @@ pub enum MoveItemDirection {
771818}
772819
773820#[derive(Debug)]
774pub enum WorkspaceSymbol {}
821pub enum WorkspaceSymbolRequest {}
775822
776impl Request for WorkspaceSymbol {
823impl Request for WorkspaceSymbolRequest {
777824 type Params = WorkspaceSymbolParams;
778825 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;
780828}
781829
782830#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
......@@ -812,15 +860,16 @@ pub enum WorkspaceSymbolSearchKind {
812860
813861/// The document on type formatting request is sent from the client to
814862/// 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
816864/// result has SnippetTextEdit in it instead of TextEdit.
817865#[derive(Debug)]
818pub enum OnTypeFormatting {}
866pub enum DocumentOnTypeFormattingRequest {}
819867
820impl Request for OnTypeFormatting {
868impl Request for DocumentOnTypeFormattingRequest {
821869 type Params = DocumentOnTypeFormattingParams;
822870 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;
824873}
825874
826875#[derive(Debug, Serialize, Deserialize)]
......@@ -859,7 +908,7 @@ pub struct ClientCommandOptions {
859908 pub commands: Vec<String>,
860909}
861910
862pub enum EvaluatePredicate {}
911pub enum EvaluatePredicateRequest {}
863912
864913#[derive(Deserialize, Serialize, Debug)]
865914#[serde(rename_all = "camelCase")]
......@@ -886,13 +935,14 @@ pub enum PredicateEvaluationStatus {
886935 Unsupported,
887936}
888937
889impl Request for EvaluatePredicate {
938impl Request for EvaluatePredicateRequest {
890939 type Params = EvaluatePredicateParams;
891940 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;
893943}
894944
895pub enum GetFailedObligations {}
945pub enum GetFailedObligationsRequest {}
896946
897947#[derive(Deserialize, Serialize, Debug)]
898948#[serde(rename_all = "camelCase")]
......@@ -901,10 +951,11 @@ pub struct GetFailedObligationsParams {
901951 pub position: Position,
902952}
903953
904impl Request for GetFailedObligations {
954impl Request for GetFailedObligationsRequest {
905955 type Params = GetFailedObligationsParams;
906956 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;
908959}
909960
910961#[cfg(test)]
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs+14-13
......@@ -1,4 +1,5 @@
11//! Conversion lsp_types types to rust-analyzer specific ones.
2
23use anyhow::format_err;
34use ide::{Annotation, AnnotationKind, AssistKind, LineCol};
45use ide_db::{FileId, FilePosition, FileRange, line_index::WideLineCol};
......@@ -12,12 +13,12 @@ use crate::{
1213 lsp_ext, try_default,
1314};
1415
15pub(crate) fn abs_path(url: &lsp_types::Url) -> anyhow::Result<AbsPathBuf> {
16pub(crate) fn abs_path(url: &lsp_types::Uri) -> anyhow::Result<AbsPathBuf> {
1617 let path = url.to_file_path().map_err(|()| anyhow::format_err!("url is not a file"))?;
1718 Ok(AbsPathBuf::try_from(Utf8PathBuf::from_path_buf(path).unwrap()).unwrap())
1819}
1920
20pub(crate) fn vfs_path(url: &lsp_types::Url) -> anyhow::Result<vfs::VfsPath> {
21pub(crate) fn vfs_path(url: &lsp_types::Uri) -> anyhow::Result<vfs::VfsPath> {
2122 abs_path(url).map(vfs::VfsPath::from)
2223}
2324
......@@ -65,7 +66,7 @@ pub(crate) fn text_range(
6566/// Returns `None` if the file was excluded.
6667pub(crate) fn file_id(
6768 snap: &GlobalStateSnapshot,
68 url: &lsp_types::Url,
69 url: &lsp_types::Uri,
6970) -> anyhow::Result<Option<FileId>> {
7071 snap.url_to_file_id(url)
7172}
......@@ -73,7 +74,7 @@ pub(crate) fn file_id(
7374/// Returns `None` if the file was excluded.
7475pub(crate) fn file_position(
7576 snap: &GlobalStateSnapshot,
76 tdpp: lsp_types::TextDocumentPositionParams,
77 tdpp: &lsp_types::TextDocumentPositionParams,
7778) -> anyhow::Result<Option<FilePosition>> {
7879 let file_id = try_default!(file_id(snap, &tdpp.text_document.uri)?);
7980 let line_index = snap.file_line_index(file_id)?;
......@@ -93,7 +94,7 @@ pub(crate) fn file_range(
9394/// Returns `None` if the file was excluded.
9495pub(crate) fn file_range_uri(
9596 snap: &GlobalStateSnapshot,
96 document: &lsp_types::Url,
97 document: &lsp_types::Uri,
9798 range: lsp_types::Range,
9899) -> anyhow::Result<Option<FileRange>> {
99100 let file_id = try_default!(file_id(snap, document)?);
......@@ -104,12 +105,12 @@ pub(crate) fn file_range_uri(
104105
105106pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> {
106107 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,
113114 _ => return None,
114115 };
115116
......@@ -130,7 +131,7 @@ pub(crate) fn annotation(
130131 return Ok(None);
131132 }
132133 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)?);
134135 let line_index = snap.file_line_index(file_id)?;
135136
136137 Ok(Annotation {
......@@ -142,7 +143,7 @@ pub(crate) fn annotation(
142143 if snap.url_file_version(&params.text_document.uri) != Some(data.version) {
143144 return Ok(None);
144145 }
145 let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, params)?);
146 let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, &params)?);
146147 let line_index = snap.file_line_index(file_id)?;
147148
148149 Ok(Annotation {
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/semantic_tokens.rs+249-155
......@@ -1,170 +1,261 @@
11//! Semantic Tokens helpers
22
3use std::ops;
3use std::{fmt, ops, slice::Iter};
44
5use lsp_types::{
6 Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens,
7 SemanticTokensEdit,
8};
5use lsp_types::{Range, SemanticTokenModifiers, SemanticTokens, SemanticTokensEdit};
96
10macro_rules! define_semantic_token_types {
7macro_rules! declare_enum {
118 (
12 standard {
13 $($standard:ident),*$(,)?
9 $(#[$attrs:meta])*
10 $visibility:vis enum $name:ident {
11 $($variant:ident),* $(,)?
1412 }
15 custom {
16 $(($custom:ident, $string:literal) $(=> $fallback:ident)?),*$(,)?
17 }
18
1913 ) => {
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,)*
2417 }
2518
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 }
3928 }
4029 };
4130}
4231
43define_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,
32declare_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,
6494 }
95}
6596
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"),
97declare_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,
106124 }
107];
108
109macro_rules! count_tts {
110 () => {0usize};
111 ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)};
112125}
113macro_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 }
129126
130 pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
131 $(SemanticTokenModifier::$standard,)*
132 $(self::modifiers::$custom),*
133 ];
127impl 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}
134192
135 const LAST_STANDARD_MOD: usize = count_tts!($($standard)*);
136 };
193pub(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 })
137217}
138218
139define_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"),
219impl 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)
166247 }
248}
249
250const STANDARD_MOD: [SupportedModifiers; 6] = [
251 SupportedModifiers::Async,
252 SupportedModifiers::Documentation,
253 SupportedModifiers::Declaration,
254 SupportedModifiers::Static,
255 SupportedModifiers::DefaultLibrary,
256 SupportedModifiers::Deprecated,
167257];
258const LAST_STANDARD_MOD: usize = STANDARD_MOD.len() - 1;
168259
169260#[derive(Default)]
170261pub(crate) struct ModifierSet(pub(crate) u32);
......@@ -176,9 +267,9 @@ impl ModifierSet {
176267 }
177268}
178269
179impl ops::BitOrAssign<SemanticTokenModifier> for ModifierSet {
180 fn bitor_assign(&mut self, rhs: SemanticTokenModifier) {
181 let idx = SUPPORTED_MODIFIERS.iter().position(|it| it == &rhs).unwrap();
270impl ops::BitOrAssign<SupportedModifiers> for ModifierSet {
271 fn bitor_assign(&mut self, rhs: SupportedModifiers) {
272 let idx = SupportedModifiers::iter().position(|it| *it == rhs).unwrap();
182273 self.0 |= 1 << idx;
183274 }
184275}
......@@ -190,12 +281,12 @@ pub(crate) struct SemanticTokensBuilder {
190281 id: String,
191282 prev_line: u32,
192283 prev_char: u32,
193 data: Vec<SemanticToken>,
284 data: Vec<lsp_types::SemanticToken>,
194285}
195286
196287impl SemanticTokensBuilder {
197288 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() }
199290 }
200291
201292 /// Push a new token onto the builder
......@@ -213,7 +304,7 @@ impl SemanticTokensBuilder {
213304 // A token cannot be multiline
214305 let token_len = range.end.character - range.start.character;
215306
216 let token = SemanticToken {
307 let token = lsp_types::SemanticToken {
217308 delta_line: push_line,
218309 delta_start: push_char,
219310 length: token_len,
......@@ -232,7 +323,10 @@ impl SemanticTokensBuilder {
232323 }
233324}
234325
235pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<SemanticTokensEdit> {
326pub(crate) fn diff_tokens(
327 old: &[lsp_types::SemanticToken],
328 new: &[lsp_types::SemanticToken],
329) -> Vec<SemanticTokensEdit> {
236330 let offset = new.iter().zip(old.iter()).take_while(|&(n, p)| n == p).count();
237331
238332 let (_, old) = old.split_at(offset);
......@@ -258,16 +352,16 @@ pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<S
258352 }
259353}
260354
261pub(crate) fn type_index(ty: SemanticTokenType) -> u32 {
262 SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32
355pub(crate) fn type_index(kind: SupportedType) -> u32 {
356 kind as u32
263357}
264358
265359#[cfg(test)]
266360mod tests {
267361 use super::*;
268362
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 {
271365 delta_line: t.0,
272366 delta_start: t.1,
273367 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
5858
5959pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
6060 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,
6767 SymbolKind::Macro
6868 | SymbolKind::ProcMacro
6969 | SymbolKind::BuiltinAttr
7070 | SymbolKind::Attribute
7171 | 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,
7575 SymbolKind::TypeAlias | SymbolKind::TypeParam | SymbolKind::SelfType => {
76 lsp_types::SymbolKind::TYPE_PARAMETER
76 lsp_types::SymbolKind::TypeParameter
7777 }
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,
8383 SymbolKind::Local
8484 | SymbolKind::SelfParam
8585 | SymbolKind::LifetimeParam
8686 | 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,
9090 }
9191}
9292
9393pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolKind {
9494 match kind {
9595 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,
9898 }
9999}
100100
......@@ -102,21 +102,21 @@ pub(crate) fn document_highlight_kind(
102102 category: ReferenceCategory,
103103) -> Option<lsp_types::DocumentHighlightKind> {
104104 if category.contains(ReferenceCategory::WRITE) {
105 return Some(lsp_types::DocumentHighlightKind::WRITE);
105 return Some(lsp_types::DocumentHighlightKind::Write);
106106 }
107107 if category.contains(ReferenceCategory::READ) {
108 return Some(lsp_types::DocumentHighlightKind::READ);
108 return Some(lsp_types::DocumentHighlightKind::Read);
109109 }
110110 None
111111}
112112
113113pub(crate) fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSeverity {
114114 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,
118118 // unreachable
119 Severity::Allow => lsp_types::DiagnosticSeverity::INFORMATION,
119 Severity::Allow => lsp_types::DiagnosticSeverity::Information,
120120 }
121121}
122122
......@@ -130,44 +130,44 @@ pub(crate) fn completion_item_kind(
130130 completion_item_kind: CompletionItemKind,
131131) -> lsp_types::CompletionItemKind {
132132 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,
140140 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,
171171 },
172172 }
173173}
......@@ -185,7 +185,7 @@ pub(crate) fn completion_text_edit(
185185 line_index: &LineIndex,
186186 insert_replace_support: Option<lsp_types::Position>,
187187 indel: Indel,
188) -> lsp_types::CompletionTextEdit {
188) -> lsp_types::CompletionItemTextEdit {
189189 let text_edit = text_edit(line_index, indel);
190190 match insert_replace_support {
191191 Some(cursor_pos) => lsp_types::InsertReplaceEdit {
......@@ -208,7 +208,7 @@ pub(crate) fn snippet_text_edit(
208208 let annotation_id = annotation.filter(|_| client_supports_annotations).map(|it| it.to_string());
209209 let text_edit = text_edit(line_index, indel);
210210 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 };
212212 lsp_ext::SnippetTextEdit {
213213 range: text_edit.range,
214214 new_text: text_edit.new_text,
......@@ -250,7 +250,7 @@ pub(crate) fn completion_items(
250250 fields_to_resolve: &CompletionFieldsToResolve,
251251 line_index: &LineIndex,
252252 version: Option<i32>,
253 tdpp: lsp_types::TextDocumentPositionParams,
253 tdpp: &lsp_types::TextDocumentPositionParams,
254254 completion_trigger_character: Option<char>,
255255 mut items: Vec<CompletionItem>,
256256) -> Vec<lsp_types::CompletionItem> {
......@@ -269,7 +269,7 @@ pub(crate) fn completion_items(
269269 fields_to_resolve,
270270 line_index,
271271 version,
272 &tdpp,
272 tdpp,
273273 max_relevance,
274274 completion_trigger_character,
275275 item,
......@@ -340,12 +340,12 @@ fn completion_item(
340340 Some(text_edit.unwrap())
341341 };
342342
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);
344344 let tags = if fields_to_resolve.resolve_tags {
345345 something_to_resolve |= item.deprecated;
346346 None
347347 } else {
348 item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED])
348 item.deprecated.then(|| vec![lsp_types::CompletionItemTag::Deprecated])
349349 };
350350 let command = if item.trigger_call_info && client_commands.trigger_parameter_hints {
351351 if fields_to_resolve.resolve_command {
......@@ -383,6 +383,7 @@ fn completion_item(
383383 .not()
384384 .then_some(additional_text_edits),
385385 documentation,
386 #[expect(deprecated, reason = "we do use tags")]
386387 deprecated: item.deprecated.then_some(item.deprecated),
387388 tags,
388389 command,
......@@ -491,7 +492,7 @@ pub(crate) fn signature_help(
491492 let params = call_info
492493 .parameter_labels()
493494 .map(|label| lsp_types::ParameterInformation {
494 label: lsp_types::ParameterLabel::Simple(label.to_owned()),
495 label: lsp_types::ParameterInformationLabel::String(label.to_owned()),
495496 documentation: None,
496497 })
497498 .collect::<Vec<_>>();
......@@ -513,10 +514,10 @@ pub(crate) fn signature_help(
513514 .chars()
514515 .map(|c| c.len_utf16())
515516 .sum::<usize>() as u32;
516 [start, end]
517 (start, end)
517518 })
518519 .map(|label_offsets| lsp_types::ParameterInformation {
519 label: lsp_types::ParameterLabel::LabelOffsets(label_offsets),
520 label: lsp_types::ParameterInformationLabel::Tuple(label_offsets),
520521 documentation: None,
521522 })
522523 .collect::<Vec<_>>();
......@@ -535,7 +536,7 @@ pub(crate) fn signature_help(
535536 label.push_str(param);
536537 let end = label.len() as u32;
537538 params.push(lsp_types::ParameterInformation {
538 label: lsp_types::ParameterLabel::LabelOffsets([start, end]),
539 label: lsp_types::ParameterInformationLabel::Tuple((start, end)),
539540 documentation: None,
540541 });
541542 }
......@@ -551,7 +552,8 @@ pub(crate) fn signature_help(
551552 })
552553 });
553554
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));
555557
556558 let signature = lsp_types::SignatureInformation {
557559 label,
......@@ -639,9 +641,9 @@ pub(crate) fn inlay_hint(
639641 padding_right: Some(inlay_hint.pad_right),
640642 kind: match inlay_hint.kind {
641643 InlayKind::Parameter | InlayKind::GenericParameter => {
642 Some(lsp_types::InlayHintKind::PARAMETER)
644 Some(lsp_types::InlayHintKind::Parameter)
643645 }
644 InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::TYPE),
646 InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::Type),
645647 _ => None,
646648 },
647649 text_edits,
......@@ -657,7 +659,7 @@ fn inlay_hint_label(
657659 something_to_resolve: &mut bool,
658660 needs_resolve: bool,
659661 mut label: InlayHintLabel,
660) -> Cancellable<(lsp_types::InlayHintLabel, Option<lsp_types::InlayHintTooltip>)> {
662) -> Cancellable<(lsp_types::Label, Option<lsp_types::Tooltip>)> {
661663 let (label, tooltip) = match &*label.parts {
662664 [InlayHintLabelPart { linked_location: None, .. }] => {
663665 let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
......@@ -670,16 +672,16 @@ fn inlay_hint_label(
670672 }
671673 });
672674 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)),
674676 Some(ide::InlayTooltip::Markdown(s)) => {
675 Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
677 Some(lsp_types::Tooltip::MarkupContent(lsp_types::MarkupContent {
676678 kind: lsp_types::MarkupKind::Markdown,
677679 value: s,
678680 }))
679681 }
680682 None => None,
681683 };
682 (lsp_types::InlayHintLabel::String(text), hint_tooltip)
684 (lsp_types::Label::String(text), hint_tooltip)
683685 }
684686 _ => {
685687 let parts = label
......@@ -694,16 +696,12 @@ fn inlay_hint_label(
694696 }
695697 });
696698 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)),
700700 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 }))
707705 }
708706 None => None,
709707 };
......@@ -726,7 +724,7 @@ fn inlay_hint_label(
726724 })
727725 })
728726 .collect::<Cancellable<_>>()?;
729 (lsp_types::InlayHintLabel::LabelParts(parts), None)
727 (lsp_types::Label::InlayHintLabelPartList(parts), None)
730728 }
731729 };
732730 Ok((label, tooltip))
......@@ -773,11 +771,11 @@ pub(crate) fn semantic_tokens(
773771
774772 if !non_standard_tokens {
775773 ty = match standard_fallback_type(ty) {
776 Some(ty) => ty,
774 Some(fallback) => fallback,
777775 None => continue,
778776 };
779777 mods.standard_fallback();
780 }
778 };
781779 let token_index = semantic_tokens::type_index(ty);
782780 let modifier_bitset = mods.0;
783781
......@@ -805,106 +803,106 @@ pub(crate) fn semantic_token_delta(
805803
806804fn semantic_token_type_and_modifiers(
807805 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};
810808
811809 let mut mods = semantic_tokens::ModifierSet::default();
812810 let ty = match highlight.tag {
813811 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,
817815 SymbolKind::CrateRoot => {
818 mods |= mods::CRATE_ROOT;
819 types::NAMESPACE
816 mods |= SupportedModifiers::CrateRoot;
817 SupportedType::Namespace
820818 }
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,
847845 },
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,
859857 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,
866864 },
867 HlTag::StringLiteral => types::STRING,
868 HlTag::UnresolvedReference => types::UNRESOLVED_REFERENCE,
865 HlTag::StringLiteral => SupportedType::String,
866 HlTag::UnresolvedReference => SupportedType::UnresolvedReference,
869867 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,
880878 },
881879 };
882880
883881 for modifier in highlight.mods.iter() {
884882 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,
908906 };
909907 mods |= modifier;
910908 }
......@@ -983,16 +981,16 @@ pub(crate) fn folding_range(
983981 }
984982}
985983
986pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Url {
984pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Uri {
987985 snap.file_id_to_url(file_id)
988986}
989987
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.
991989/// This will only happen when processing windows paths.
992990///
993/// When processing non-windows path, this is essentially the same as `Url::from_file_path`.
994pub(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`].
992pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Uri {
993 let url = lsp_types::Uri::from_file_path(path).unwrap();
996994 match path.components().next() {
997995 Some(Utf8Component::Prefix(prefix))
998996 if matches!(prefix.kind(), Utf8Prefix::Disk(_) | Utf8Prefix::VerbatimDisk(_)) =>
......@@ -1016,16 +1014,19 @@ pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url {
10161014 // string in place.
10171015 let mut url: String = url.into();
10181016 url[driver_letter_range].make_ascii_lowercase();
1019 lsp_types::Url::parse(&url).unwrap()
1017 lsp_types::Uri::parse(&url).unwrap()
10201018}
10211019
10221020pub(crate) fn optional_versioned_text_document_identifier(
10231021 snap: &GlobalStateSnapshot,
10241022 file_id: FileId,
10251023) -> 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 }
10291030}
10301031
10311032pub(crate) fn location(
......@@ -1042,7 +1043,7 @@ pub(crate) fn location(
10421043/// Prefer using `location_link`, if the client has the cap.
10431044pub(crate) fn location_from_nav(
10441045 snap: &GlobalStateSnapshot,
1045 nav: NavigationTarget,
1046 nav: &NavigationTarget,
10461047) -> Cancellable<lsp_types::Location> {
10471048 let url = url(snap, nav.file_id);
10481049 let line_index = snap.file_line_index(nav.file_id)?;
......@@ -1077,7 +1078,7 @@ pub(crate) fn location_link(
10771078fn location_info(
10781079 snap: &GlobalStateSnapshot,
10791080 target: NavigationTarget,
1080) -> Cancellable<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> {
1081) -> Cancellable<(lsp_types::Uri, lsp_types::Range, lsp_types::Range)> {
10811082 let line_index = snap.file_line_index(target.file_id)?;
10821083
10831084 let target_uri = url(snap, target.file_id);
......@@ -1091,25 +1092,90 @@ pub(crate) fn goto_definition_response(
10911092 snap: &GlobalStateSnapshot,
10921093 src: Option<FileRange>,
10931094 targets: Vec<NavigationTarget>,
1094) -> Cancellable<lsp_types::GotoDefinitionResponse> {
1095) -> Cancellable<lsp_types::DefinitionResponse> {
10951096 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)?;
11011098 Ok(links.into())
11021099 } 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
1107pub(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 )))
11101120 }
11111121}
11121122
1123pub(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
1139pub(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
1155fn 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
1167fn 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
11131179fn outside_workspace_annotation_id() -> String {
11141180 String::from("OutsideWorkspace")
11151181}
......@@ -1318,19 +1384,21 @@ pub(crate) fn snippet_text_document_ops(
13181384 match file_system_edit {
13191385 FileSystemEdit::CreateFile { dst, initial_contents } => {
13201386 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 {
13221388 uri: uri.clone(),
13231389 options: None,
13241390 annotation_id: None,
13251391 });
1326 ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(create_file));
1392 ops.push(lsp_ext::SnippetDocumentChangeOperation::Change(create_file));
13271393 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 };
13301398 let text_edit = lsp_ext::SnippetTextEdit {
13311399 range: lsp_types::Range::default(),
13321400 new_text: initial_contents,
1333 insert_text_format: Some(lsp_types::InsertTextFormat::PLAIN_TEXT),
1401 insert_text_format: Some(lsp_types::InsertTextFormat::PlainText),
13341402 annotation_id: None,
13351403 };
13361404 let edit_file =
......@@ -1348,9 +1416,9 @@ pub(crate) fn snippet_text_document_ops(
13481416 {
13491417 rename_file.annotation_id = Some(outside_workspace_annotation_id())
13501418 }
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 ))
13541422 }
13551423 FileSystemEdit::MoveDir { src, src_id, dst } => {
13561424 let old_uri = snap.anchored_path(&src);
......@@ -1362,9 +1430,9 @@ pub(crate) fn snippet_text_document_ops(
13621430 {
13631431 rename_file.annotation_id = Some(outside_workspace_annotation_id())
13641432 }
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 ))
13681436 }
13691437 }
13701438 Ok(ops)
......@@ -1449,42 +1517,38 @@ impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
14491517 lsp_types::WorkspaceEdit {
14501518 changes: None,
14511519 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()
14701534 }),
14711535 change_annotations: snippet_workspace_edit.change_annotations,
14721536 }
14731537 }
14741538}
14751539
1476impl From<lsp_ext::SnippetTextEdit>
1477 for lsp_types::OneOf<lsp_types::TextEdit, lsp_types::AnnotatedTextEdit>
1478{
1540impl From<lsp_ext::SnippetTextEdit> for lsp_types::Edit {
14791541 fn from(
14801542 lsp_ext::SnippetTextEdit { annotation_id, insert_text_format:_, new_text, range }: lsp_ext::SnippetTextEdit,
14811543 ) -> Self {
14821544 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 }),
14881552 }
14891553 }
14901554}
......@@ -1495,7 +1559,7 @@ pub(crate) fn call_hierarchy_item(
14951559) -> Cancellable<lsp_types::CallHierarchyItem> {
14961560 let name = target.name.to_string();
14971561 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);
14991563 let (uri, range, selection_range) = location_info(snap, target)?;
15001564 Ok(lsp_types::CallHierarchyItem {
15011565 name,
......@@ -1511,12 +1575,12 @@ pub(crate) fn call_hierarchy_item(
15111575
15121576pub(crate) fn code_action_kind(kind: AssistKind) -> lsp_types::CodeActionKind {
15131577 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,
15201584 }
15211585}
15221586
......@@ -1761,7 +1825,7 @@ pub(crate) fn code_lens(
17611825
17621826 let doc_pos = lsp_types::TextDocumentPositionParams::new(id, pos);
17631827
1764 let goto_params = lsp_types::request::GotoImplementationParams {
1828 let goto_params = lsp_types::ImplementationParams {
17651829 text_document_position_params: doc_pos,
17661830 work_done_progress_params: Default::default(),
17671831 partial_result_params: Default::default(),
......@@ -1891,7 +1955,7 @@ pub(crate) mod command {
18911955
18921956 pub(crate) fn show_references(
18931957 title: String,
1894 uri: &lsp_types::Url,
1958 uri: &lsp_types::Uri,
18951959 position: lsp_types::Position,
18961960 locations: Vec<lsp_types::Location>,
18971961 ) -> lsp_types::Command {
......@@ -1907,6 +1971,7 @@ pub(crate) mod command {
19071971 to_value(position).unwrap(),
19081972 to_value(locations).unwrap(),
19091973 ]),
1974 tooltip: None,
19101975 }
19111976 }
19121977
......@@ -1915,6 +1980,7 @@ pub(crate) mod command {
19151980 title: title.to_owned(),
19161981 command: "rust-analyzer.runSingle".into(),
19171982 arguments: Some(vec![to_value(runnable).unwrap()]),
1983 tooltip: None,
19181984 }
19191985 }
19201986
......@@ -1923,6 +1989,7 @@ pub(crate) mod command {
19231989 title: "âš™\u{fe0e} Debug".into(),
19241990 command: "rust-analyzer.debugSingle".into(),
19251991 arguments: Some(vec![to_value(runnable).unwrap()]),
1992 tooltip: None,
19261993 }
19271994 }
19281995
......@@ -1932,6 +1999,7 @@ pub(crate) mod command {
19321999 command: "rust-analyzer.interpretFunction".into(),
19332000 // FIXME: use the `_runnable` here.
19342001 arguments: Some(vec![]),
2002 tooltip: None,
19352003 }
19362004 }
19372005
......@@ -1952,6 +2020,7 @@ pub(crate) mod command {
19522020 title: nav.name.to_string(),
19532021 command: "rust-analyzer.gotoLocation".into(),
19542022 arguments: Some(vec![value]),
2023 tooltip: None,
19552024 })
19562025 }
19572026
......@@ -1960,6 +2029,7 @@ pub(crate) mod command {
19602029 title: "triggerParameterHints".into(),
19612030 command: "rust-analyzer.triggerParameterHints".into(),
19622031 arguments: None,
2032 tooltip: None,
19632033 }
19642034 }
19652035
......@@ -1968,6 +2038,7 @@ pub(crate) mod command {
19682038 title: "rename".into(),
19692039 command: "rust-analyzer.rename".into(),
19702040 arguments: None,
2041 tooltip: None,
19712042 }
19722043 }
19732044}
......@@ -3081,7 +3152,7 @@ struct ProcMacro {
30813152 )
30823153 }
30833154
3084 // `Url` is not able to parse windows paths on unix machines.
3155 // `Uri` is not able to parse windows paths on unix machines.
30853156 #[test]
30863157 #[cfg(target_os = "windows")]
30873158 fn test_lowercase_drive_letter() {
src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs+112-90
......@@ -1,8 +1,8 @@
11//! Utilities for LSP-related boilerplate code.
2use std::{mem, ops::Range};
2use std::{mem, ops::Range, vec};
33
44use lsp_server::Notification;
5use lsp_types::request::Request;
5use lsp_types::{MessageActionItem, Request};
66use triomphe::Arc;
77
88use crate::{
......@@ -16,10 +16,8 @@ pub(crate) fn invalid_params_error(message: String) -> LspError {
1616 LspError { code: lsp_server::ErrorCode::InvalidParams as i32, message }
1717}
1818
19pub(crate) fn notification_is<N: lsp_types::notification::Notification>(
20 notification: &Notification,
21) -> bool {
22 notification.method == N::METHOD
19pub(crate) fn notification_is<N: lsp_types::Notification>(notification: &Notification) -> bool {
20 notification.method.as_str() == N::METHOD.as_str()
2321}
2422
2523#[derive(Debug, Eq, PartialEq)]
......@@ -39,37 +37,34 @@ impl Progress {
3937impl GlobalState {
4038 pub(crate) fn show_message(
4139 &mut self,
42 typ: lsp_types::MessageType,
40 kind: lsp_types::MessageType,
4341 message: String,
4442 show_open_log_button: bool,
4543 ) {
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>(
4846 lsp_types::ShowMessageRequestParams {
49 typ,
47 kind,
5048 message,
5149 actions: Some(vec![lsp_types::MessageActionItem {
5250 title: "Open server logs".to_owned(),
53 properties: Default::default(),
5451 }]),
5552 },
5653 |this, resp| {
5754 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,
6361 ) {
64 this.send_notification::<lsp_ext::OpenServerLogs>(());
62 this.send_notification::<lsp_ext::OpenServerLogsNotification>(());
6563 }
6664 },
6765 ),
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 },
7368 ),
7469 }
7570 }
......@@ -81,15 +76,15 @@ impl GlobalState {
8176 Some(additional_info) => {
8277 tracing::error!("{message}:\n{additional_info}");
8378 self.show_message(
84 lsp_types::MessageType::ERROR,
79 lsp_types::MessageType::Error,
8580 message,
8681 tracing::enabled!(tracing::Level::ERROR),
8782 );
8883 }
8984 None => {
9085 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 },
9388 );
9489 }
9590 }
......@@ -133,35 +128,49 @@ impl GlobalState {
133128 cancel_token.unwrap_or_else(|| format!("rustAnalyzer/{title}")),
134129 );
135130 tracing::debug!(?token, ?state, "report_progress {message:?}");
136 let work_done_progress = match state {
131 match state {
137132 Progress::Begin => {
138 self.send_request::<lsp_types::request::WorkDoneProgressCreate>(
133 self.send_request::<lsp_types::WorkDoneProgressCreateRequest>(
139134 lsp_types::WorkDoneProgressCreateParams { token: token.clone() },
140135 |_, _| (),
141136 );
142137
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 );
149150 }
150151 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 );
156163 }
157164 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 );
159172 }
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 }
165174 }
166175}
167176
......@@ -172,15 +181,26 @@ pub(crate) fn apply_document_changes(
172181) -> String {
173182 // If at least one of the changes is a full document change, use the last
174183 // 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() {
184204 return text;
185205 }
186206
......@@ -198,16 +218,13 @@ pub(crate) fn apply_document_changes(
198218 // remember the last valid line in the index and only rebuild it if needed.
199219 // The VFS will normalize the end of lines to `\n`.
200220 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);
211228 }
212229 }
213230 text
......@@ -221,10 +238,10 @@ pub(crate) fn all_edits_are_disjoint(
221238) -> bool {
222239 let mut edit_ranges = Vec::new();
223240 match completion.text_edit.as_ref() {
224 Some(lsp_types::CompletionTextEdit::Edit(edit)) => {
241 Some(lsp_types::CompletionItemTextEdit::TextEdit(edit)) => {
225242 edit_ranges.push(edit.range);
226243 }
227 Some(lsp_types::CompletionTextEdit::InsertAndReplace(edit)) => {
244 Some(lsp_types::CompletionItemTextEdit::InsertReplaceEdit(edit)) => {
228245 let replace = edit.replace;
229246 let insert = edit.insert;
230247 if replace.start != insert.start
......@@ -252,10 +269,7 @@ pub(crate) fn all_edits_are_disjoint(
252269#[cfg(test)]
253270mod tests {
254271 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};
259273
260274 use super::*;
261275
......@@ -263,14 +277,14 @@ mod tests {
263277 fn test_apply_document_changes() {
264278 macro_rules! c {
265279 [$($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 {
268282 start: Position { line: $sl, character: $sc },
269283 end: Position { line: $el, character: $ec },
270 }),
271 range_length: None,
284 },
272285 text: String::from($text),
273 }),+]
286 ..Default::default()
287 })),+]
274288 };
275289 }
276290
......@@ -280,11 +294,11 @@ mod tests {
280294 let text = apply_document_changes(
281295 encoding,
282296 &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 ],
288302 );
289303 assert_eq!(text, "the");
290304 let text = apply_document_changes(encoding, &text, c![0, 3; 0, 3 => " quick"]);
......@@ -332,7 +346,11 @@ mod tests {
332346
333347 #[test]
334348 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 };
336354
337355 let disjoint_edit_1 = lsp_types::TextEdit::new(
338356 Range::new(Position::new(2, 2), Position::new(3, 3)),
......@@ -384,17 +402,19 @@ mod tests {
384402 "new_text".to_owned(),
385403 );
386404
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 };
391411 assert!(
392412 !all_edits_are_disjoint(&completion_with_joint_edits, &[]),
393413 "Completion with disjoint edits fails the validation even with empty extra edits"
394414 );
395415
396416 completion_with_joint_edits.text_edit =
397 Some(CompletionTextEdit::Edit(disjoint_edit.clone()));
417 Some(lsp_types::CompletionItemTextEdit::TextEdit(disjoint_edit.clone()));
398418 completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit.clone()]);
399419 assert!(
400420 !all_edits_are_disjoint(&completion_with_joint_edits, &[]),
......@@ -402,7 +422,7 @@ mod tests {
402422 );
403423
404424 completion_with_joint_edits.text_edit =
405 Some(CompletionTextEdit::InsertAndReplace(InsertReplaceEdit {
425 Some(lsp_types::CompletionItemTextEdit::InsertReplaceEdit(InsertReplaceEdit {
406426 new_text: "new_text".to_owned(),
407427 insert: disjoint_edit.range,
408428 replace: disjoint_edit_2.range,
......@@ -429,10 +449,12 @@ mod tests {
429449 "new_text".to_owned(),
430450 );
431451
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 };
436458
437459 assert!(
438460 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::{
1111use crossbeam_channel::{Receiver, never, select};
1212use ide_db::base_db::{SourceDatabase, VfsPath};
1313use lsp_server::{Connection, Notification, Request};
14use lsp_types::{TextDocumentIdentifier, notification::Notification as _};
14use lsp_types::{Notification as _, TextDocumentIdentifier};
1515use stdx::thread::ThreadIntent;
1616use tracing::{Level, error, span};
1717use vfs::{AbsPathBuf, FileId, loader::LoadingProgress};
......@@ -99,7 +99,7 @@ impl fmt::Display for Event {
9999
100100#[derive(Debug)]
101101pub(crate) enum DeferredTask {
102 CheckIfIndexed(lsp_types::Url),
102 CheckIfIndexed(lsp_types::Uri),
103103 CheckProcMacroSources(Vec<FileId>),
104104}
105105
......@@ -145,8 +145,8 @@ impl fmt::Debug for Event {
145145
146146 match self {
147147 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)) =>
150150 {
151151 return debug_non_verbose(not, f);
152152 }
......@@ -207,7 +207,7 @@ impl GlobalState {
207207 if matches!(
208208 &event,
209209 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()
211211 ) {
212212 return Ok(());
213213 }
......@@ -218,33 +218,43 @@ impl GlobalState {
218218 }
219219
220220 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 ))
225229 });
226230
227231 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 )),
243253 ];
244254 selectors.extend(additional_filters);
245255
246256 let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions {
247 include_text: Some(false),
257 save_options: lsp_types::SaveOptions { include_text: Some(false) },
248258 text_document_registration_options: lsp_types::TextDocumentRegistrationOptions {
249259 document_selector: Some(selectors),
250260 },
......@@ -255,7 +265,7 @@ impl GlobalState {
255265 method: "textDocument/didSave".to_owned(),
256266 register_options: Some(serde_json::to_value(save_registration_options).unwrap()),
257267 };
258 self.send_request::<lsp_types::request::RegisterCapability>(
268 self.send_request::<lsp_types::RegistrationRequest>(
259269 lsp_types::RegistrationParams { registrations: vec![registration] },
260270 |_, _| (),
261271 );
......@@ -457,10 +467,7 @@ impl GlobalState {
457467 self.handle_flycheck_msg(message, &mut cargo_finished);
458468 }
459469 if cargo_finished {
460 self.send_request::<lsp_types::request::WorkspaceDiagnosticRefresh>(
461 (),
462 |_, _| (),
463 );
470 self.send_request::<lsp_types::DiagnosticRefreshRequest>((), |_, _| ());
464471 }
465472 }
466473 Event::TestResult(message) => {
......@@ -537,24 +544,21 @@ impl GlobalState {
537544 // Refresh semantic tokens if the client supports it.
538545 if self.config.semantic_tokens_refresh() {
539546 self.semantic_tokens_cache.lock().clear();
540 self.send_request::<lsp_types::request::SemanticTokensRefresh>((), |_, _| ());
547 self.send_request::<lsp_types::SemanticTokensRefreshRequest>((), |_, _| ());
541548 }
542549
543550 // Refresh code lens if the client supports it.
544551 if self.config.code_lens_refresh() {
545 self.send_request::<lsp_types::request::CodeLensRefresh>((), |_, _| ());
552 self.send_request::<lsp_types::CodeLensRefreshRequest>((), |_, _| ());
546553 }
547554
548555 // Refresh inlay hints if the client supports it.
549556 if self.config.inlay_hints_refresh() {
550 self.send_request::<lsp_types::request::InlayHintRefreshRequest>((), |_, _| ());
557 self.send_request::<lsp_types::InlayHintRefreshRequest>((), |_, _| ());
551558 }
552559
553560 if self.config.diagnostics_refresh() {
554 self.send_request::<lsp_types::request::WorkspaceDiagnosticRefresh>(
555 (),
556 |_, _| (),
557 );
561 self.send_request::<lsp_types::DiagnosticRefreshRequest>((), |_, _| ());
558562 }
559563 }
560564
......@@ -828,9 +832,9 @@ impl GlobalState {
828832 || self.fetch_workspace_error().is_err());
829833 self.show_message(
830834 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,
834838 },
835839 message.clone(),
836840 open_log_button,
......@@ -911,7 +915,7 @@ impl GlobalState {
911915 self.discover_handles.push(handle)
912916 }
913917 Err(e) => self.show_message(
914 lsp_types::MessageType::ERROR,
918 lsp_types::MessageType::Error,
915919 format!("Failed to spawn project discovery command: {e:#}"),
916920 false,
917921 ),
......@@ -960,7 +964,7 @@ impl GlobalState {
960964 }
961965 Task::BuildDepsHaveChanged => self.build_deps_changed = true,
962966 Task::DiscoverTest(tests) => {
963 self.send_notification::<lsp_ext::DiscoveredTests>(tests);
967 self.send_notification::<lsp_ext::DiscoveredTestsNotification>(tests);
964968 }
965969 }
966970 cancellation_time
......@@ -1174,7 +1178,7 @@ impl GlobalState {
11741178 // The notification requires the namespace form (with underscores) of the target
11751179 let test_id = format!("{}::{name}", message.target.target.replace('-', "_"));
11761180
1177 self.send_notification::<lsp_ext::ChangeTestState>(
1181 self.send_notification::<lsp_ext::ChangeTestStateNotification>(
11781182 lsp_ext::ChangeTestStateParams { test_id, state },
11791183 );
11801184 }
......@@ -1182,12 +1186,12 @@ impl GlobalState {
11821186 CargoTestOutput::Finished => {
11831187 self.test_run_remaining_jobs = self.test_run_remaining_jobs.saturating_sub(1);
11841188 if self.test_run_remaining_jobs == 0 {
1185 self.send_notification::<lsp_ext::EndRunTest>(());
1189 self.send_notification::<lsp_ext::EndRunTestNotification>(());
11861190 self.test_run_session = None;
11871191 }
11881192 }
11891193 CargoTestOutput::Custom { text } => {
1190 self.send_notification::<lsp_ext::AppendOutputToRunTest>(text);
1194 self.send_notification::<lsp_ext::AppendOutputToRunTestNotification>(text);
11911195 }
11921196 }
11931197 }
......@@ -1308,7 +1312,7 @@ impl GlobalState {
13081312 /// Handles a request.
13091313 fn on_request(&mut self, req: Request) {
13101314 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, ()| {
13121316 s.shutdown_requested = true;
13131317 s.proc_macro_clients =
13141318 std::iter::repeat_with(|| None).take(s.proc_macro_clients.len()).collect();
......@@ -1330,7 +1334,6 @@ impl GlobalState {
13301334 }
13311335
13321336 use crate::handlers::request as handlers;
1333 use lsp_types::request as lsp_request;
13341337
13351338 const RETRY: bool = true;
13361339 const NO_RETRY: bool = false;
......@@ -1339,91 +1342,91 @@ impl GlobalState {
13391342 dispatcher
13401343 // Request handlers that must run on the main thread
13411344 // 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)
13461349 // Request handlers which are related to the user typing
13471350 // 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)
13531356 // Formatting should be done immediately as the editor might wait on it, but we can't
13541357 // put it on the main thread as we do not want the main thread to block on rustfmt.
13551358 // So we have an extra thread just for formatting requests to make sure it gets handled
13561359 // 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)
13591362 // We can’t run latency-sensitive request handlers which do semantic
13601363 // analysis on the main thread because that would block other
13611364 // requests. Instead, we run these request handlers on higher priority
13621365 // threads in the threadpool.
13631366 // 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)
13651368 // 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)
13701373 // FIXME: Some of these NO_RETRY could be retries if the file they are interested didn't change.
13711374 // 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 {
13731376 code: lsp_server::ErrorCode::ServerCancelled as i32,
13741377 message: "server cancelled the request".to_owned(),
13751378 data: serde_json::to_value(lsp_types::DiagnosticServerCancellationData {
13761379 retrigger_request: true
13771380 }).ok(),
13781381 })
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)
13981401 // 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)
14171420 .on::<NO_RETRY, lsp_ext::CodeActionRequest>(handlers::handle_code_action)
14181421 .on_identity::<RETRY, lsp_ext::CodeActionResolveRequest, _>(handlers::handle_code_action_resolve)
14191422 .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)
14231426 //
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)
14271430 .finish();
14281431 }
14291432
......@@ -1432,28 +1435,37 @@ impl GlobalState {
14321435 let _p =
14331436 span!(Level::INFO, "GlobalState::on_notification", not.method = ?not.method).entered();
14341437 use crate::handlers::notification as handlers;
1435 use lsp_types::notification as notifs;
14361438
14371439 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>(
14401442 handlers::handle_work_done_progress_cancel,
14411443 )
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>(
14471457 handlers::handle_did_change_configuration,
14481458 )
1449 .on_sync_mut::<notifs::DidChangeWorkspaceFolders>(
1459 .on_sync_mut::<lsp_types::DidChangeWorkspaceFoldersNotification>(
14501460 handlers::handle_did_change_workspace_folders,
14511461 )
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)
14571469 .finish();
14581470 }
14591471}
src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs+15-19
......@@ -15,10 +15,10 @@
1515// FIXME: This is a mess that needs some untangling work
1616use std::{iter, mem, sync::atomic::AtomicUsize, time::Duration};
1717
18use hir::{ChangeWithProcMacros, ProcMacrosBuilder, db::DefDatabase};
18use hir::{ChangeWithProcMacros, ProcMacrosBuilder};
1919use ide_db::{
2020 FxHashMap,
21 base_db::{CrateGraphBuilder, ProcMacroLoadingError, ProcMacroPaths, salsa::Durability},
21 base_db::{CrateGraphBuilder, ProcMacroLoadingError, ProcMacroPaths},
2222};
2323use itertools::Itertools;
2424use load_cargo::{ProjectFolders, load_proc_macro};
......@@ -109,14 +109,10 @@ impl GlobalState {
109109 self.reload_flycheck();
110110 }
111111
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 );
120116
121117 if self.config.cargo(None) != old_config.cargo(None) {
122118 let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
......@@ -544,8 +540,8 @@ impl GlobalState {
544540 // FIXME: can we abort the build scripts here if they are already running?
545541 self.workspaces = Arc::new(workspaces);
546542 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 },
549545 );
550546 });
551547
......@@ -585,10 +581,10 @@ impl GlobalState {
585581 })
586582 })
587583 .map(|(base, pat)| lsp_types::FileSystemWatcher {
588 glob_pattern: lsp_types::GlobPattern::Relative(
584 glob_pattern: lsp_types::GlobPattern::RelativePattern(
589585 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(),
592588 ),
593589 pattern: pat.to_owned(),
594590 },
......@@ -610,7 +606,7 @@ impl GlobalState {
610606 })
611607 })
612608 .map(|glob_pattern| lsp_types::FileSystemWatcher {
613 glob_pattern: lsp_types::GlobPattern::String(glob_pattern),
609 glob_pattern: lsp_types::GlobPattern::Pattern(glob_pattern),
614610 kind: None,
615611 })
616612 .collect()
......@@ -624,7 +620,7 @@ impl GlobalState {
624620 continue;
625621 };
626622 watchers.push(lsp_types::FileSystemWatcher {
627 glob_pattern: lsp_types::GlobPattern::String(
623 glob_pattern: lsp_types::GlobPattern::Pattern(
628624 build.build_file.to_string(),
629625 ),
630626 kind: None,
......@@ -638,7 +634,7 @@ impl GlobalState {
638634 .chain(self.workspaces.iter().map(|ws| ws.manifest().map(ManifestPath::as_ref)))
639635 .flatten()
640636 .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()),
642638 kind: None,
643639 }),
644640 );
......@@ -650,7 +646,7 @@ impl GlobalState {
650646 method: "workspace/didChangeWatchedFiles".to_owned(),
651647 register_options: Some(serde_json::to_value(registration_options).unwrap()),
652648 };
653 self.send_request::<lsp_types::request::RegisterCapability>(
649 self.send_request::<lsp_types::RegistrationRequest>(
654650 lsp_types::RegistrationParams { registrations: vec![registration] },
655651 |_, _| (),
656652 );
src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs+4
......@@ -204,6 +204,10 @@ impl CargoTargetSpec {
204204 }
205205 }
206206 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 }
207211 (cargo_args, executable_args)
208212 }
209213
src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs+47-55
......@@ -20,23 +20,19 @@ mod ratoml;
2020mod support;
2121mod testdir;
2222
23use std::{collections::HashMap, path::PathBuf, time::Instant};
23use std::{path::PathBuf, time::Instant};
2424
2525use ide_db::FxHashMap;
2626use 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,
3834};
39use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams};
35use rust_analyzer::lsp::ext::{OnEnterRequest, RunnablesParams, RunnablesRequest};
4036use serde_json::json;
4137use stdx::format_to_acc;
4238
......@@ -68,8 +64,8 @@ use std::collections::Spam;
6864 .server()
6965 .wait_until_workspace_is_loaded();
7066
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(
7369 server.doc_id("src/lib.rs"),
7470 Position::new(0, 23),
7571 ),
......@@ -112,13 +108,13 @@ fn f() {
112108 let hint = hints.pop().unwrap();
113109 assert!(hint.data.is_some());
114110 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())
116112 );
117113 let res = server.send_request::<InlayHintResolveRequest>(hint);
118114 let hint = serde_json::from_value::<InlayHint>(res).unwrap();
119115 assert!(hint.data.is_none());
120116 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())
122118 );
123119}
124120
......@@ -160,8 +156,8 @@ use dependency2::Spam;
160156 .server()
161157 .wait_until_workspace_is_loaded();
162158
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(
165161 server.doc_id("src/lib.rs"),
166162 Position::new(5, 18),
167163 ),
......@@ -171,8 +167,8 @@ use dependency2::Spam;
171167 });
172168 assert!(res.to_string().contains("SpecialHashMap"), "{}", res.to_string());
173169
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(
176172 server.doc_id("src/lib.rs"),
177173 Position::new(6, 18),
178174 ),
......@@ -199,8 +195,8 @@ use dependency2::Spam;
199195
200196 std::thread::sleep(std::time::Duration::from_secs(3));
201197
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(
204200 server.doc_id("src/lib.rs"),
205201 Position::new(5, 18),
206202 ),
......@@ -210,8 +206,8 @@ use dependency2::Spam;
210206 });
211207 assert!(!res.to_string().contains("SpecialHashMap"));
212208
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(
215211 server.doc_id("src/lib.rs"),
216212 Position::new(6, 18),
217213 ),
......@@ -256,7 +252,7 @@ fn main() {}
256252 .server()
257253 .wait_until_workspace_is_loaded();
258254
259 server.request::<Runnables>(
255 server.request::<RunnablesRequest>(
260256 RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None },
261257 json!([
262258 {
......@@ -407,7 +403,7 @@ mod tests {
407403 .wait_until_workspace_is_loaded();
408404
409405 for runnable in ["consumer", "dependency", "devdependency"] {
410 server.request::<Runnables>(
406 server.request::<RunnablesRequest>(
411407 RunnablesParams {
412408 text_document: server.doc_id(&format!("{runnable}/src/lib.rs")),
413409 position: None,
......@@ -472,7 +468,7 @@ fn otherpkg() {}
472468 .server()
473469 .wait_until_workspace_is_loaded();
474470
475 server.request::<Runnables>(
471 server.request::<RunnablesRequest>(
476472 RunnablesParams { text_document: server.doc_id("foo/mainpkg/src/main.rs"), position: None },
477473 json!([
478474 "{...}",
......@@ -497,7 +493,7 @@ fn otherpkg() {}
497493 ]),
498494 );
499495
500 server.request::<Runnables>(
496 server.request::<RunnablesRequest>(
501497 RunnablesParams { text_document: server.doc_id("foo/otherpkg/src/lib.rs"), position: None },
502498 json!([
503499 "{...}",
......@@ -547,7 +543,7 @@ pub use std::collections::HashMap;
547543 )
548544 .wait_until_workspace_is_loaded();
549545
550 server.request::<Formatting>(
546 server.request::<DocumentFormattingRequest>(
551547 DocumentFormattingParams {
552548 text_document: server.doc_id("src/lib.rs"),
553549 options: FormattingOptions {
......@@ -556,7 +552,6 @@ pub use std::collections::HashMap;
556552 insert_final_newline: None,
557553 trim_final_newlines: None,
558554 trim_trailing_whitespace: None,
559 properties: HashMap::new(),
560555 },
561556 work_done_progress_params: WorkDoneProgressParams::default(),
562557 },
......@@ -600,13 +595,12 @@ pub use std::collections::HashMap;
600595 )
601596 .wait_until_workspace_is_loaded();
602597
603 server.request::<Formatting>(
598 server.request::<DocumentFormattingRequest>(
604599 DocumentFormattingParams {
605600 text_document: server.doc_id("src/lib.rs"),
606601 options: FormattingOptions {
607602 tab_size: 4,
608603 insert_spaces: false,
609 properties: HashMap::new(),
610604 insert_final_newline: None,
611605 trim_final_newlines: None,
612606 trim_trailing_whitespace: None,
......@@ -651,7 +645,7 @@ fn main() {}
651645 )
652646 .wait_until_workspace_is_loaded();
653647
654 server.request::<Formatting>(
648 server.request::<DocumentFormattingRequest>(
655649 DocumentFormattingParams {
656650 text_document: server.doc_id("src/lib.rs"),
657651 options: FormattingOptions {
......@@ -660,7 +654,6 @@ fn main() {}
660654 insert_final_newline: None,
661655 trim_final_newlines: None,
662656 trim_trailing_whitespace: None,
663 properties: HashMap::new(),
664657 },
665658 work_done_progress_params: WorkDoneProgressParams::default(),
666659 },
......@@ -707,7 +700,7 @@ fn main() {
707700 .server()
708701 .wait_until_workspace_is_loaded();
709702
710 server.request::<RangeFormatting>(
703 server.request::<DocumentRangeFormattingRequest>(
711704 DocumentRangeFormattingParams {
712705 range: Range {
713706 end: Position { line: 1, character: 0 },
......@@ -720,7 +713,6 @@ fn main() {
720713 insert_final_newline: None,
721714 trim_final_newlines: None,
722715 trim_trailing_whitespace: None,
723 properties: HashMap::new(),
724716 },
725717 work_done_progress_params: WorkDoneProgressParams::default(),
726718 },
......@@ -928,17 +920,17 @@ fn main() {{}}
928920 .wait_until_workspace_is_loaded();
929921
930922 for i in 0..10 {
931 server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams {
923 server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams {
932924 text_document: TextDocumentItem {
933925 uri: server.doc_id(&format!("src/m{i}.rs")).uri,
934 language_id: "rust".to_owned(),
926 language_id: LanguageKind::Rust,
935927 version: 0,
936928 text: "/// Docs\nfn foo() {}".to_owned(),
937929 },
938930 });
939931 }
940932 let start = Instant::now();
941 server.request::<OnEnter>(
933 server.request::<OnEnterRequest>(
942934 TextDocumentPositionParams {
943935 text_document: server.doc_id("src/m0.rs"),
944936 position: Position { line: 0, character: 5 },
......@@ -976,7 +968,7 @@ version = \"0.0.0\"
976968 .server()
977969 .wait_until_workspace_is_loaded();
978970
979 server.request::<OnEnter>(
971 server.request::<OnEnterRequest>(
980972 TextDocumentPositionParams {
981973 text_document: server.doc_id("src/main.rs"),
982974 position: Position { line: 0, character: 8 },
......@@ -1089,8 +1081,8 @@ fn main() {
10891081 });
10901082 assert!(res.to_string().contains("&str"));
10911083
1092 server.request::<GotoTypeDefinition>(
1093 GotoDefinitionParams {
1084 server.request::<TypeDefinitionRequest>(
1085 TypeDefinitionParams {
10941086 text_document_position_params: TextDocumentPositionParams::new(
10951087 server.doc_id("src/main.rs"),
10961088 Position::new(28, 9),
......@@ -1115,8 +1107,8 @@ fn main() {
11151107 }]),
11161108 );
11171109
1118 server.request::<GotoTypeDefinition>(
1119 GotoDefinitionParams {
1110 server.request::<TypeDefinitionRequest>(
1111 TypeDefinitionParams {
11201112 text_document_position_params: TextDocumentPositionParams::new(
11211113 server.doc_id("src/main.rs"),
11221114 Position::new(29, 9),
......@@ -1308,8 +1300,8 @@ use crate::old_folder::nested::foo as bar;
13081300 let server =
13091301 Project::with_fixture(code).tmp_dir(tmp_dir).server().wait_until_workspace_is_loaded();
13101302
1311 //rename same level file
1312 server.request::<WillRenameFiles>(
1303 // rename same level file
1304 server.request::<WillRenameFilesRequest>(
13131305 RenameFilesParams {
13141306 files: vec![FileRename {
13151307 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;
13431335 }),
13441336 );
13451337
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>(
13481340 RenameFilesParams {
13491341 files: vec![FileRename {
13501342 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;
13541346 json!(null),
13551347 );
13561348
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>(
13591351 RenameFilesParams {
13601352 files: vec![FileRename {
13611353 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;
13651357 json!(null),
13661358 );
13671359
1368 //rename same level file
1369 server.request::<WillRenameFiles>(
1360 // rename same level file
1361 server.request::<WillRenameFilesRequest>(
13701362 RenameFilesParams {
13711363 files: vec![FileRename {
13721364 old_uri: base_path.join("src/old_folder").to_str().unwrap().to_owned(),
......@@ -1568,7 +1560,7 @@ fn test<T: Trait>() {
15681560 .server()
15691561 .wait_until_workspace_is_loaded();
15701562
1571 let res = server.send_request::<rust_analyzer::lsp::ext::EvaluatePredicate>(
1563 let res = server.send_request::<rust_analyzer::lsp::ext::EvaluatePredicateRequest>(
15721564 rust_analyzer::lsp::ext::EvaluatePredicateParams {
15731565 text: "T: Trait".to_owned(),
15741566 text_document: server.doc_id("src/lib.rs"),
......@@ -1607,7 +1599,7 @@ fn test() {
16071599 .server()
16081600 .wait_until_workspace_is_loaded();
16091601
1610 let res = server.send_request::<rust_analyzer::lsp::ext::GetFailedObligations>(
1602 let res = server.send_request::<rust_analyzer::lsp::ext::GetFailedObligationsRequest>(
16111603 rust_analyzer::lsp::ext::GetFailedObligationsParams {
16121604 text_document: server.doc_id("src/lib.rs"),
16131605 position: Position::new(4, 19),
src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs+47-36
......@@ -1,23 +1,24 @@
11use crate::support::{Project, Server};
22use crate::testdir::TestDir;
33use 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,
68 VersionedTextDocumentIdentifier,
7 notification::{DidChangeTextDocument, DidOpenTextDocument, DidSaveTextDocument},
89};
910use paths::Utf8PathBuf;
1011
1112use rust_analyzer::config::Config;
1213use rust_analyzer::lsp::ext::{
13 InternalTestingFetchConfig, InternalTestingFetchConfigOption, InternalTestingFetchConfigParams,
14 InternalTestingFetchConfigResponse,
14 InternalTestingFetchConfigOption, InternalTestingFetchConfigParams,
15 InternalTestingFetchConfigRequest, InternalTestingFetchConfigResponse,
1516};
1617use serde_json::json;
1718use test_utils::skip_slow_tests;
1819
1920struct RatomlTest {
20 urls: Vec<Url>,
21 urls: Vec<Uri>,
2122 server: Server,
2223 tmp_path: Utf8PathBuf,
2324}
......@@ -54,7 +55,7 @@ impl RatomlTest {
5455 case
5556 }
5657
57 fn fixture_path(&self, fixture: &str) -> Url {
58 fn fixture_path(&self, fixture: &str) -> Uri {
5859 let mut lines = fixture.trim().split('\n');
5960
6061 let mut path =
......@@ -81,7 +82,7 @@ impl RatomlTest {
8182 path = path.join(piece);
8283 }
8384
84 Url::parse(
85 Uri::parse(
8586 format!("file://{}", path.into_string().replace("C:\\", "/c:/").replace('\\', "/"))
8687 .as_str(),
8788 )
......@@ -89,65 +90,75 @@ impl RatomlTest {
8990 }
9091
9192 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);
9394
94 self.server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams {
95 self.server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams {
9596 text_document: TextDocumentItem {
96 uri: url.clone(),
97 language_id: "rust".to_owned(),
97 uri: uri.clone(),
98 language_id: lsp_types::LanguageKind::Rust,
9899 version: 0,
99100 text: String::new(),
100101 },
101102 });
102103
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 );
111118 }
112119
113120 fn delete(&mut self, file_idx: usize) {
114 self.server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams {
121 self.server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams {
115122 text_document: TextDocumentItem {
116123 uri: self.urls[file_idx].clone(),
117 language_id: "rust".to_owned(),
124 language_id: lsp_types::LanguageKind::Rust,
118125 version: 0,
119126 text: "".to_owned(),
120127 },
121128 });
122129
123130 // 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 {
125132 text_document: TextDocumentIdentifier { uri: self.urls[file_idx].clone() },
126133 text: Some("".to_owned()),
127134 });
128135 }
129136
130137 fn edit(&mut self, file_idx: usize, text: String) {
131 self.server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams {
138 self.server.notification::<DidOpenTextDocumentNotification>(DidOpenTextDocumentParams {
132139 text_document: TextDocumentItem {
133140 uri: self.urls[file_idx].clone(),
134 language_id: "rust".to_owned(),
141 language_id: lsp_types::LanguageKind::Rust,
135142 version: 0,
136143 text: String::new(),
137144 },
138145 });
139146
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 ],
144160 },
145 content_changes: vec![TextDocumentContentChangeEvent {
146 range: None,
147 range_length: None,
148 text,
149 }],
150 });
161 );
151162 }
152163
153164 fn query(
......@@ -156,7 +167,7 @@ impl RatomlTest {
156167 source_file_idx: usize,
157168 expected: InternalTestingFetchConfigResponse,
158169 ) {
159 let res = self.server.send_request::<InternalTestingFetchConfig>(
170 let res = self.server.send_request::<InternalTestingFetchConfigRequest>(
160171 InternalTestingFetchConfigParams {
161172 text_document: Some(TextDocumentIdentifier {
162173 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};
99use itertools::Itertools;
1010use lsp_server::{Connection, Message, Notification, Request};
1111use lsp_types::{
12 PublishDiagnosticsParams, TextDocumentIdentifier, Url, notification::Exit, request::Shutdown,
12 ExitNotification, PublishDiagnosticsParams, ShutdownRequest, TextDocumentIdentifier, Uri,
1313};
1414use parking_lot::{Mutex, MutexGuard};
1515use paths::{Utf8Path, Utf8PathBuf};
......@@ -229,13 +229,13 @@ impl Project<'_> {
229229 ..Default::default()
230230 }),
231231 text_document: Some(lsp_types::TextDocumentClientCapabilities {
232 definition: Some(lsp_types::GotoCapability {
232 definition: Some(lsp_types::DefinitionClientCapabilities {
233233 link_support: Some(true),
234234 ..Default::default()
235235 }),
236236 code_action: Some(lsp_types::CodeActionClientCapabilities {
237237 code_action_literal_support: Some(
238 lsp_types::CodeActionLiteralSupport::default(),
238 lsp_types::ClientCodeActionLiteralOptions::default(),
239239 ),
240240 ..Default::default()
241241 }),
......@@ -244,7 +244,7 @@ impl Project<'_> {
244244 ..Default::default()
245245 }),
246246 inlay_hint: Some(lsp_types::InlayHintClientCapabilities {
247 resolve_support: Some(lsp_types::InlayHintResolveClientCapabilities {
247 resolve_support: Some(lsp_types::ClientInlayHintResolveOptions {
248248 properties: vec![
249249 "textEdits".to_owned(),
250250 "tooltip".to_owned(),
......@@ -321,22 +321,22 @@ impl Server {
321321
322322 pub(crate) fn doc_id(&self, rel_path: &str) -> TextDocumentIdentifier {
323323 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() }
325325 }
326326
327327 pub(crate) fn notification<N>(&self, params: N::Params)
328328 where
329 N: lsp_types::notification::Notification,
329 N: lsp_types::Notification,
330330 N::Params: Serialize,
331331 {
332 let r = Notification::new(N::METHOD.to_owned(), params);
332 let r = Notification::new(N::METHOD.into(), params);
333333 self.send_notification(r)
334334 }
335335
336336 #[track_caller]
337337 pub(crate) fn request<R>(&self, params: R::Params, expected_resp: Value)
338338 where
339 R: lsp_types::request::Request,
339 R: lsp_types::Request,
340340 R::Params: Serialize,
341341 {
342342 let actual = self.send_request::<R>(params);
......@@ -354,13 +354,13 @@ impl Server {
354354 #[track_caller]
355355 pub(crate) fn send_request<R>(&self, params: R::Params) -> Value
356356 where
357 R: lsp_types::request::Request,
357 R: lsp_types::Request,
358358 R::Params: Serialize,
359359 {
360360 let id = self.req_id.get();
361361 self.req_id.set(id.wrapping_add(1));
362362
363 let r = Request::new(id.into(), R::METHOD.to_owned(), params);
363 let r = Request::new(id.into(), R::METHOD.into(), params);
364364 self.send_request_(r)
365365 }
366366 #[track_caller]
......@@ -494,7 +494,7 @@ impl Server {
494494
495495 pub(crate) fn write_file_and_save(&self, path: &str, text: String) {
496496 fs::write(self.dir.path().join(path), &text).unwrap();
497 self.notification::<lsp_types::notification::DidSaveTextDocument>(
497 self.notification::<lsp_types::DidSaveTextDocumentNotification>(
498498 lsp_types::DidSaveTextDocumentParams {
499499 text_document: self.doc_id(path),
500500 text: Some(text),
......@@ -505,8 +505,8 @@ impl Server {
505505
506506impl Drop for Server {
507507 fn drop(&mut self) {
508 self.request::<Shutdown>((), Value::Null);
509 self.notification::<Exit>(());
508 self.request::<ShutdownRequest>((), Value::Null);
509 self.notification::<ExitNotification>(());
510510 }
511511}
512512
src/tools/rust-analyzer/crates/span/src/map.rs+1-1
......@@ -30,7 +30,7 @@ impl SpanMap {
3030 /// in order.
3131 pub fn finish(&mut self) {
3232 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),
3434 "spans are not in order"
3535 );
3636 self.spans.shrink_to_fit();
src/tools/rust-analyzer/crates/syntax/rust.ungram+3-3
......@@ -468,17 +468,17 @@ AsmRegSpec = '@string' | NameRef
468468// reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr
469469AsmRegOperand = AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr
470470// clobber_abi := "clobber_abi(" <abi> *("," <abi>) [","] ")"
471AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')'
471AsmClobberAbi = Attr* 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')'
472472// option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
473473AsmOption = 'pure' | 'nomem' | 'readonly' | 'preserves_flags' | 'noreturn' | 'nostack' | 'att_syntax' | 'raw' | 'may_unwind'
474474// options := "options(" option *("," option) [","] ")"
475AsmOptions = 'options' '(' (AsmOption (',' AsmOption)*) ','? ')'
475AsmOptions = Attr* 'options' '(' (AsmOption (',' AsmOption)*) ','? ')'
476476AsmLabel = 'label' BlockExpr
477477AsmSym = 'sym' Path
478478AsmConst = 'const' Expr
479479// operand := reg_operand / clobber_abi / options
480480AsmOperand = AsmRegOperand | AsmLabel | AsmSym | AsmConst
481AsmOperandNamed = (Name '=')? AsmOperand
481AsmOperandNamed = Attr* (Name '=')? AsmOperand
482482AsmPiece = AsmOperandNamed | AsmClobberAbi | AsmOptions
483483
484484FormatArgsExpr =
src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs+19
......@@ -59,6 +59,7 @@ impl ArrayType {
5959pub struct AsmClobberAbi {
6060 pub(crate) syntax: SyntaxNode,
6161}
62impl ast::HasAttrs for AsmClobberAbi {}
6263impl AsmClobberAbi {
6364 #[inline]
6465 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
......@@ -150,6 +151,7 @@ impl AsmOperandExpr {
150151pub struct AsmOperandNamed {
151152 pub(crate) syntax: SyntaxNode,
152153}
154impl ast::HasAttrs for AsmOperandNamed {}
153155impl ast::HasName for AsmOperandNamed {}
154156impl AsmOperandNamed {
155157 #[inline]
......@@ -193,6 +195,7 @@ impl AsmOption {
193195pub struct AsmOptions {
194196 pub(crate) syntax: SyntaxNode,
195197}
198impl ast::HasAttrs for AsmOptions {}
196199impl AsmOptions {
197200 #[inline]
198201 pub fn asm_options(&self) -> AstChildren<AsmOption> { support::children(&self.syntax) }
......@@ -2193,6 +2196,7 @@ pub enum AsmPiece {
21932196 AsmOperandNamed(AsmOperandNamed),
21942197 AsmOptions(AsmOptions),
21952198}
2199impl ast::HasAttrs for AsmPiece {}
21962200
21972201#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21982202pub enum AssocItem {
......@@ -9096,7 +9100,10 @@ impl AstNode for AnyHasAttrs {
90969100 matches!(
90979101 kind,
90989102 ARRAY_EXPR
9103 | ASM_CLOBBER_ABI
90999104 | ASM_EXPR
9105 | ASM_OPERAND_NAMED
9106 | ASM_OPTIONS
91009107 | ASSOC_ITEM_LIST
91019108 | AWAIT_EXPR
91029109 | BECOME_EXPR
......@@ -9194,10 +9201,22 @@ impl From<ArrayExpr> for AnyHasAttrs {
91949201 #[inline]
91959202 fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
91969203}
9204impl From<AsmClobberAbi> for AnyHasAttrs {
9205 #[inline]
9206 fn from(node: AsmClobberAbi) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
9207}
91979208impl From<AsmExpr> for AnyHasAttrs {
91989209 #[inline]
91999210 fn from(node: AsmExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
92009211}
9212impl From<AsmOperandNamed> for AnyHasAttrs {
9213 #[inline]
9214 fn from(node: AsmOperandNamed) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
9215}
9216impl From<AsmOptions> for AnyHasAttrs {
9217 #[inline]
9218 fn from(node: AsmOptions) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
9219}
92019220impl From<AssocItemList> for AnyHasAttrs {
92029221 #[inline]
92039222 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"`.
142142To disable, prefix the entry with a `!`.
143143
144144
145## rust-analyzer.cargo.configPath {#cargo.configPath}
146
147Default: `null`
148
149Path to a `.cargo/config.toml` style file to pass to cargo via `--config`
150for every cargo invocation (metadata, build scripts, config discovery).
151Useful to give rust-analyzer a consistent view of the project configuration.
152
153
145154## rust-analyzer.cargo.extraArgs {#cargo.extraArgs}
146155
147156Default: `[]`
src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md+13-13
......@@ -1,5 +1,5 @@
11<!---
2lsp/ext.rs hash: cec81c987f189e83
2lsp/ext.rs hash: ca646d2ad3d38ccd
33
44If you need to change the above hash to make the test pass, please check if you
55need 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
3131For this reason, we ask that `initializationOptions` contains the configuration, as if the server did make a `"workspace/configuration"` request.
3232
3333If 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": {}`
3738
3839## Snippet `TextEdit`
3940
......@@ -131,7 +132,6 @@ This request is sent from client to server to handle "Goto Parent Module" editor
131132
132133**Response:** `Location | Location[] | LocationLink[] | null`
133134
134
135135### Example
136136
137137```rust
......@@ -671,7 +671,6 @@ interface RunFlycheckParams {
671671
672672Triggers the flycheck processes.
673673
674
675674**Method:** `rust-analyzer/clearFlycheck`
676675
677676**Notification:**
......@@ -849,6 +848,7 @@ interface CommandLinkGroup {
849848```
850849
851850Such actions on the client side are appended to a hover bottom as command links:
851
852852```
853853 +-----------------------------+
854854 | Hover content |
......@@ -875,7 +875,6 @@ This request is sent from client to server to open the current project's Cargo.t
875875
876876**Response:** `Location | null`
877877
878
879878### Example
880879
881880```rust
......@@ -919,6 +918,7 @@ interface HoverParams extends WorkDoneProgressParams {
919918 position: Range | Position;
920919}
921920```
921
922922Whenever 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.
923923
924924### Example
......@@ -965,7 +965,6 @@ export const enum Direction {
965965Extends the existing `workspace/symbol` request with ability to filter symbols by broad scope and kind of symbol.
966966If this capability is set, `workspace/symbol` parameter gains two new optional fields:
967967
968
969968```typescript
970969interface WorkspaceSymbolParams {
971970 /**
......@@ -1002,7 +1001,6 @@ However, the server doesn't know which commands are available on the client.
10021001
10031002This extensions allows the client to communicate this info.
10041003
1005
10061004```typescript
10071005export interface ClientCommandOptions {
10081006 /**
......@@ -1050,6 +1048,7 @@ export interface FetchDependencyListParams {}
10501048```
10511049
10521050**Response:**
1051
10531052```typescript
10541053export interface FetchDependencyListResult {
10551054 crates: {
......@@ -1059,6 +1058,7 @@ export interface FetchDependencyListResult {
10591058 }[];
10601059}
10611060```
1061
10621062Returns all crates from this workspace, so it can be used create a viewTree to help navigate the dependency tree.
10631063
10641064## View Recursive Memory Layout
......@@ -1100,8 +1100,8 @@ If `RecursiveMemoryLayout::nodes::length == 0` we could not find a suitable type
11001100
11011101Generic 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).
11021102
1103### Unresolved questions:
1103### Unresolved questions
11041104
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
146146for free.
147147
1481481. Install [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)
1492. Add `lua vim.lsp.enable('rust-analyzer')` to your `init.vim`
1492. Add `lua vim.lsp.enable('rust_analyzer')` to your `init.vim`
1501503. Customize your setup.
151151
152152```lua
src/tools/rust-analyzer/editors/code/.vscodeignore+1-1
......@@ -12,4 +12,4 @@
1212!ra_syntax_tree.tmGrammar.json
1313!server
1414!README.md
15!walkthrough-setup-tips.md
15!walkthrough-*
src/tools/rust-analyzer/editors/code/package.json+15-1
......@@ -971,6 +971,19 @@
971971 }
972972 }
973973 },
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 },
974987 {
975988 "title": "Cargo",
976989 "properties": {
......@@ -1389,7 +1402,8 @@
13891402 "enumDescriptions": [
13901403 "Do not show this item or its methods (if it is a trait) in auto-import completions.",
13911404 "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."
13931407 ]
13941408 }
13951409 }
src/tools/rust-analyzer/lib/lsp-server/Cargo.toml+4-2
......@@ -1,6 +1,6 @@
11[package]
22name = "lsp-server"
3version = "0.7.9"
3version = "0.8.0"
44description = "Generic LSP server scaffold."
55license = "MIT OR Apache-2.0"
66repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server"
......@@ -14,7 +14,9 @@ serde_derive = { version = "1.0.219" }
1414crossbeam-channel.workspace = true
1515
1616[dev-dependencies]
17lsp-types = "=0.95"
17lsp-types = { version = "0.4.0", package = "gen-lsp-types", features = [
18 "url",
19] }
1820ctrlc = "3.4.7"
1921anyhow.workspace = true
2022rustc-hash.workspace = true
src/tools/rust-analyzer/lib/lsp-server/examples/minimal_lsp.rs+49-56
......@@ -67,6 +67,15 @@
6767
6868use std::{error::Error, io::Write};
6969
70use 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};
7079use rustc_hash::FxHashMap; // fast hash map
7180use std::process::Stdio;
7281use toolchain::command; // clippy-approved wrapper
......@@ -74,39 +83,6 @@ use toolchain::command; // clippy-approved wrapper
7483#[allow(clippy::print_stderr, clippy::disallowed_types, clippy::disallowed_methods)]
7584use anyhow::{Context, Result, anyhow, bail};
7685use lsp_server::{Connection, Message, Request as ServerRequest, RequestId, Response};
77use lsp_types::notification::Notification as _; // for METHOD consts
78use lsp_types::request::Request as _;
79use 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
11086
11187// =====================================================================
11288// main
......@@ -121,11 +97,11 @@ fn main() -> std::result::Result<(), Box<dyn Error + Sync + Send>> {
12197
12298 // advertised capabilities
12399 let caps = ServerCapabilities {
124 text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)),
100 text_document_sync: Some(TextDocumentSync::Kind(lsp_types::TextDocumentSyncKind::Full)),
125101 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)),
129105 ..Default::default()
130106 };
131107 let init_value = serde_json::json!({
......@@ -149,7 +125,7 @@ fn main_loop(
149125 params: serde_json::Value,
150126) -> std::result::Result<(), Box<dyn Error + Sync + Send>> {
151127 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();
153129
154130 for msg in &connection.receiver {
155131 match msg {
......@@ -179,20 +155,25 @@ fn main_loop(
179155fn handle_notification(
180156 conn: &Connection,
181157 note: &lsp_server::Notification,
182 docs: &mut FxHashMap<Url, String>,
158 docs: &mut FxHashMap<Uri, String>,
183159) -> Result<()> {
184 match note.method.as_str() {
185 DidOpenTextDocument::METHOD => {
160 let method: LspNotificationMethod = note.method.clone().into();
161 match method {
162 DidOpenTextDocumentNotification::METHOD => {
186163 let p: DidOpenTextDocumentParams = serde_json::from_value(note.params.clone())?;
187164 let uri = p.text_document.uri;
188165 docs.insert(uri.clone(), p.text_document.text);
189166 publish_dummy_diag(conn, &uri)?;
190167 }
191 DidChangeTextDocument::METHOD => {
168 DidChangeTextDocumentNotification::METHOD => {
192169 let p: DidChangeTextDocumentParams = serde_json::from_value(note.params.clone())?;
193170 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);
196177 publish_dummy_diag(conn, &uri)?;
197178 }
198179 }
......@@ -208,31 +189,43 @@ fn handle_notification(
208189fn handle_request(
209190 conn: &Connection,
210191 req: &ServerRequest,
211 docs: &mut FxHashMap<Url, String>,
192 docs: &mut FxHashMap<Uri, String>,
212193) -> 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 )?;
216202 }
217 Completion::METHOD => {
203 CompletionRequest::METHOD => {
218204 let item = CompletionItem {
219205 label: "HelloFromLSP".into(),
220 kind: Some(CompletionItemKind::FUNCTION),
206 kind: Some(CompletionItemKind::Function),
221207 detail: Some("dummy completion".into()),
222208 ..Default::default()
223209 };
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)?;
225218 }
226219 HoverRequest::METHOD => {
227220 let hover = Hover {
228 contents: HoverContents::Scalar(MarkedString::String(
221 contents: Contents::MarkedString(MarkedString::String(
229222 "Hello from *minimal_lsp*".into(),
230223 )),
231224 range: None,
232225 };
233226 send_ok(conn, req.id.clone(), &hover)?;
234227 }
235 Formatting::METHOD => {
228 DocumentFormattingRequest::METHOD => {
236229 let p: DocumentFormattingParams = serde_json::from_value(req.params.clone())?;
237230 let uri = p.text_document.uri;
238231 let text = docs
......@@ -255,10 +248,10 @@ fn handle_request(
255248// =====================================================================
256249// diagnostics
257250// =====================================================================
258fn publish_dummy_diag(conn: &Connection, uri: &Url) -> Result<()> {
251fn publish_dummy_diag(conn: &Connection, uri: &Uri) -> Result<()> {
259252 let diag = Diagnostic {
260253 range: Range::new(Position::new(0, 0), Position::new(0, 1)),
261 severity: Some(DiagnosticSeverity::INFORMATION),
254 severity: Some(DiagnosticSeverity::Information),
262255 code: None,
263256 code_description: None,
264257 source: Some("minimal_lsp".into()),
......@@ -270,7 +263,7 @@ fn publish_dummy_diag(conn: &Connection, uri: &Url) -> Result<()> {
270263 let params =
271264 PublishDiagnosticsParams { uri: uri.clone(), diagnostics: vec![diag], version: None };
272265 conn.sender.send(Message::Notification(lsp_server::Notification::new(
273 PublishDiagnostics::METHOD.to_owned(),
266 PublishDiagnosticsNotification::METHOD.into(),
274267 params,
275268 )))?;
276269 Ok(())
src/tools/rust-analyzer/lib/lsp-server/src/lib.rs+10-7
......@@ -376,9 +376,10 @@ impl Connection {
376376#[cfg(test)]
377377mod tests {
378378 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 };
382383 use serde_json::to_value;
383384
384385 use crate::{Connection, Message, ProtocolError, RequestId};
......@@ -406,7 +407,7 @@ mod tests {
406407 #[test]
407408 fn not_exit_notification() {
408409 let notification = crate::Notification {
409 method: Initialized::METHOD.to_owned(),
410 method: InitializedNotification::METHOD.to_string(),
410411 params: to_value(InitializedParams {}).unwrap(),
411412 };
412413
......@@ -414,7 +415,7 @@ mod tests {
414415 let req_id = RequestId::from(234);
415416 let request = crate::Request {
416417 id: req_id.clone(),
417 method: Initialize::METHOD.to_owned(),
418 method: InitializeRequest::METHOD.to_string(),
418419 params: params_as_value.clone(),
419420 };
420421
......@@ -426,8 +427,10 @@ mod tests {
426427
427428 #[test]
428429 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 };
431434 let notification_msg = Message::from(notification);
432435
433436 initialize_start_test(TestCase {
src/tools/rust-analyzer/lib/smol_str/src/lib.rs+10-3
......@@ -721,7 +721,8 @@ impl StrExt for str {
721721 fn to_lowercase_smolstr(&self) -> SmolStr {
722722 let len = self.len();
723723 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) };
725726 from_buf_and_chars(buf, len - rest.len(), rest.chars().flat_map(|c| c.to_lowercase()))
726727 } else {
727728 self.to_lowercase().into()
......@@ -732,7 +733,8 @@ impl StrExt for str {
732733 fn to_uppercase_smolstr(&self) -> SmolStr {
733734 let len = self.len();
734735 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) };
736738 from_buf_and_chars(buf, len - rest.len(), rest.chars().flat_map(|c| c.to_uppercase()))
737739 } else {
738740 self.to_uppercase().into()
......@@ -848,8 +850,13 @@ unsafe fn replacen_1_ascii(src: &str, mut map: impl FnMut(&u8) -> u8) -> SmolStr
848850}
849851
850852/// 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.
851858#[inline]
852fn inline_convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> ([u8; INLINE_CAP], &str) {
859unsafe fn inline_convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> ([u8; INLINE_CAP], &str) {
853860 // Process the input in chunks of 16 bytes to enable auto-vectorization.
854861 // Previously the chunk size depended on the size of `usize`,
855862 // 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 {
443443 }
444444 #[test]
445445 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
447447
448 let wrong_utf8 = SmolStr::from(unsafe { String::from_utf8_unchecked(invalid_utf8) });
449448 let mut buffer = Vec::new();
450 borsh::BorshSerialize::serialize(&wrong_utf8, &mut buffer).unwrap();
449 borsh::BorshSerialize::serialize(invalid_utf8, &mut buffer).unwrap();
451450 let mut cursor = Cursor::new(buffer);
452451 let result = SmolStr::deserialize_reader(&mut cursor);
453452 assert!(result.is_err());
......@@ -455,14 +454,13 @@ mod borsh_tests {
455454
456455 #[test]
457456 fn borsh_non_utf8_heap() {
458 let invalid_utf8: Vec<u8> = vec![
457 let invalid_utf8: &[u8] = &[
459458 0xC1, 0x8A, 0x5F, 0xE2, 0x3A, 0x9E, 0x3B, 0xAA, 0x01, 0x08, 0x6F, 0x2F, 0xC0, 0x32,
460459 0xAB, 0xE1, 0x9A, 0x2F, 0x4A, 0x3F, 0x25, 0x0D, 0x8A, 0x2A, 0x19, 0x11, 0xF0, 0x7F,
461460 0x0E, 0x80,
462461 ];
463 let wrong_utf8 = SmolStr::from(unsafe { String::from_utf8_unchecked(invalid_utf8) });
464462 let mut buffer = Vec::new();
465 borsh::BorshSerialize::serialize(&wrong_utf8, &mut buffer).unwrap();
463 borsh::BorshSerialize::serialize(invalid_utf8, &mut buffer).unwrap();
466464 let mut cursor = Cursor::new(buffer);
467465 let result = SmolStr::deserialize_reader(&mut cursor);
468466 assert!(result.is_err());
src/tools/rust-analyzer/rust-version+1-1
......@@ -1 +1 @@
1942ac9ce4116d4ea784c9882659372b34978b1f8
17fb284d9037fa54f6a9b24261c82b394472cbfd7
src/tools/rust-analyzer/xtask/src/tidy.rs+2-2
......@@ -205,9 +205,9 @@ fn check_test_attrs(path: &Path, text: &str) {
205205 }
206206 if let Some((line, _)) = text
207207 .lines()
208 .tuple_windows()
208 .array_windows()
209209 .enumerate()
210 .find(|(_, (a, b))| b.contains("#[should_panic") && !a.contains("FIXME"))
210 .find(|(_, [a, b])| b.contains("#[should_panic") && !a.contains("FIXME"))
211211 {
212212 panic!(
213213 "\ndon't add `#[should_panic]` tests, see:\n\n {}\n\n {}:{line}\n",