mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-13 08:31:28 +00:00
Compare commits
567 Commits
kmm/1.4.0
...
rr/mitropo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a4eee7b36 | ||
|
|
e13a38a758 | ||
|
|
9e9ca4953f | ||
|
|
62dcfcde79 | ||
|
|
4739adb6dc | ||
|
|
03651f1dd4 | ||
|
|
650469024e | ||
|
|
2be94d9d2f | ||
|
|
c015463926 | ||
|
|
1bb3f60bad | ||
|
|
36f22dafc5 | ||
|
|
41131e46d7 | ||
|
|
95625d0fae | ||
|
|
2fe222e8e7 | ||
|
|
de6154980d | ||
|
|
d2ea108123 | ||
|
|
388e619d90 | ||
|
|
f3a2ff8646 | ||
|
|
117aae8a6b | ||
|
|
9e37b62f62 | ||
|
|
55595fe2c6 | ||
|
|
db127bb414 | ||
|
|
3d86e92bf5 | ||
|
|
64b1cc7fd4 | ||
|
|
cc95c16ac2 | ||
|
|
bc16fbf438 | ||
|
|
7d31d7f20c | ||
|
|
b9fda902fb | ||
|
|
ce20196006 | ||
|
|
631e68c99a | ||
|
|
ace7ae19b4 | ||
|
|
07654b4c0e | ||
|
|
b2e629dceb | ||
|
|
0234678804 | ||
|
|
caa5aadc98 | ||
|
|
463908f6f4 | ||
|
|
cc67ac631f | ||
|
|
a150014e74 | ||
|
|
b543588ccd | ||
|
|
9096d21fcd | ||
|
|
632e88459e | ||
|
|
de7d82e42b | ||
|
|
6f0bd6c122 | ||
|
|
7384c89ddd | ||
|
|
fd9b14ed29 | ||
|
|
2ed68643cb | ||
|
|
d8892ced9d | ||
|
|
5ed7abd15d | ||
|
|
69dc963f97 | ||
|
|
19cc9c81dc | ||
|
|
7b1b50499d | ||
|
|
a3750b6419 | ||
|
|
c0f4ee7dc9 | ||
|
|
447308dcfc | ||
|
|
1cccceabb9 | ||
|
|
d9821412d0 | ||
|
|
a292eb865b | ||
|
|
1329030281 | ||
|
|
10e5dc1f63 | ||
|
|
d9e5407ecb | ||
|
|
439808952d | ||
|
|
901b794af3 | ||
|
|
02f6a03ff7 | ||
|
|
2656eeb164 | ||
|
|
d385a9b29e | ||
|
|
f64f9c2144 | ||
|
|
6f957c7b31 | ||
|
|
aaacbaaaec | ||
|
|
a035404c96 | ||
|
|
3297237f3d | ||
|
|
175e94c0aa | ||
|
|
fe61530357 | ||
|
|
ab5cb13dae | ||
|
|
cbbb497edf | ||
|
|
c4b24548cb | ||
|
|
293df7bd50 | ||
|
|
63394858ac | ||
|
|
e787dbf374 | ||
|
|
1c2fbb61fe | ||
|
|
7a0f986823 | ||
|
|
67158caf73 | ||
|
|
41306d25fd | ||
|
|
8e8710efec | ||
|
|
982cbf1148 | ||
|
|
d3d3b41dea | ||
|
|
74c697af92 | ||
|
|
8fb41e4562 | ||
|
|
a72eeb800d | ||
|
|
060b2eaf27 | ||
|
|
ca15c33a62 | ||
|
|
9db9e2ad57 | ||
|
|
71f53d49ca | ||
|
|
d9b4e24b29 | ||
|
|
7b89717092 | ||
|
|
aaf3410708 | ||
|
|
48ec104a34 | ||
|
|
4080bd1325 | ||
|
|
8f156f3609 | ||
|
|
e51874d46a | ||
|
|
464c8eb77a | ||
|
|
4a52596344 | ||
|
|
1f5012684b | ||
|
|
aab4fd7225 | ||
|
|
92c224b616 | ||
|
|
1a81f02377 | ||
|
|
d0c0ddd7e5 | ||
|
|
3283a10561 | ||
|
|
db42b5b062 | ||
|
|
49710c9509 | ||
|
|
8f679bf1d3 | ||
|
|
1ab6a9bc84 | ||
|
|
34aff5953f | ||
|
|
791dfb78ab | ||
|
|
99e05b777a | ||
|
|
10c501d474 | ||
|
|
f5db4b12ba | ||
|
|
cf65b1f87a | ||
|
|
9f45ef8df5 | ||
|
|
0f47a38042 | ||
|
|
f285a31a5a | ||
|
|
2ca0e37be7 | ||
|
|
eb6e797001 | ||
|
|
6316949e36 | ||
|
|
85840578ad | ||
|
|
af1dd6251e | ||
|
|
ee455abe52 | ||
|
|
3766dbff69 | ||
|
|
846fc13519 | ||
|
|
b93c49afae | ||
|
|
99c5585790 | ||
|
|
1a7b30c13a | ||
|
|
2f89ba9499 | ||
|
|
cb8addc4cd | ||
|
|
9cac2e1945 | ||
|
|
1b47d538ae | ||
|
|
51d74d78c6 | ||
|
|
d5ae06e7ed | ||
|
|
05f9154bdd | ||
|
|
d7df249480 | ||
|
|
a6feae0fbb | ||
|
|
a22fb2c1ba | ||
|
|
fe4bb24a3e | ||
|
|
db50afeafe | ||
|
|
1186d1affd | ||
|
|
d7ee168dff | ||
|
|
7c57c4a2fb | ||
|
|
535534cf66 | ||
|
|
f0ff8f202c | ||
|
|
c95216dc5d | ||
|
|
01707800c1 | ||
|
|
9d6ea3c073 | ||
|
|
306abc79ed | ||
|
|
d69ce74ca5 | ||
|
|
da5b2cfb64 | ||
|
|
63a0b5bfde | ||
|
|
447549f20d | ||
|
|
145b2c260b | ||
|
|
f833b4fe63 | ||
|
|
cf655a829c | ||
|
|
a8cb6b2ede | ||
|
|
7c99a6fef4 | ||
|
|
acc15e5fad | ||
|
|
7a58a59114 | ||
|
|
e72fb755a0 | ||
|
|
201b115ee0 | ||
|
|
8e7bbf1780 | ||
|
|
c0d7e565bc | ||
|
|
29ceb25f5c | ||
|
|
3a6b9c8d08 | ||
|
|
9d98240272 | ||
|
|
0f10faabbf | ||
|
|
205510863a | ||
|
|
f7ceacb15c | ||
|
|
077853d2ad | ||
|
|
3b4cef1b56 | ||
|
|
cbabb4f76a | ||
|
|
7b61bf9178 | ||
|
|
24948a8b3f | ||
|
|
063c973eaa | ||
|
|
852dcedb86 | ||
|
|
5689a2c67a | ||
|
|
38416e7e30 | ||
|
|
ef48c38eb4 | ||
|
|
07e18654d9 | ||
|
|
3e3afac407 | ||
|
|
a5e9e1e9be | ||
|
|
567aabeced | ||
|
|
b0c9b88485 | ||
|
|
f9ec4f7d5c | ||
|
|
b4df4e5525 | ||
|
|
eeb2f7d3d1 | ||
|
|
da6c2ddb2f | ||
|
|
f4e8c21309 | ||
|
|
e3111730ac | ||
|
|
40dfb2a438 | ||
|
|
e3f1ddefd0 | ||
|
|
4925ca2c9a | ||
|
|
9faf088c96 | ||
|
|
4aa3040550 | ||
|
|
8737168d41 | ||
|
|
94b4f4a91a | ||
|
|
c2589c7d6d | ||
|
|
d711086be2 | ||
|
|
b85b733e42 | ||
|
|
410c5f3e69 | ||
|
|
b43ff7fbf9 | ||
|
|
a79efd0768 | ||
|
|
89aa15c419 | ||
|
|
8037baf307 | ||
|
|
811e8d0f24 | ||
|
|
58a9c0c996 | ||
|
|
c875c30f2c | ||
|
|
2bf31ae3c3 | ||
|
|
d8aee421ac | ||
|
|
3154eca218 | ||
|
|
d24e136ba8 | ||
|
|
8b37a094fe | ||
|
|
66bbd3e102 | ||
|
|
1b1e579cbf | ||
|
|
b8597b48f1 | ||
|
|
01b6142500 | ||
|
|
5d827d9b5c | ||
|
|
032d017c4f | ||
|
|
d528d24f83 | ||
|
|
484d026d2f | ||
|
|
a0efd1e323 | ||
|
|
3da6ff7ec3 | ||
|
|
bf97323301 | ||
|
|
c720fa5793 | ||
|
|
c2ede13d5a | ||
|
|
b74692e96b | ||
|
|
262e21fcbc | ||
|
|
6da22414dc | ||
|
|
4d2caa8e76 | ||
|
|
6e67e1e78d | ||
|
|
d1c88798df | ||
|
|
2d5b50531d | ||
|
|
46907f861a | ||
|
|
232be94738 | ||
|
|
cbbdec5898 | ||
|
|
957a927790 | ||
|
|
5ab05e6e47 | ||
|
|
293f78efe8 | ||
|
|
bea37569e6 | ||
|
|
28627e9754 | ||
|
|
89cbe9bf93 | ||
|
|
6178cb7206 | ||
|
|
72b09ff323 | ||
|
|
0bd2a74542 | ||
|
|
38922a84f1 | ||
|
|
6a1f921a5c | ||
|
|
8447f512b4 | ||
|
|
ab2a2b3a87 | ||
|
|
fd32e918d5 | ||
|
|
2d55b8db07 | ||
|
|
369c08214b | ||
|
|
a63f83ab15 | ||
|
|
801c97f456 | ||
|
|
bc20464bad | ||
|
|
76d819f66d | ||
|
|
e45e491718 | ||
|
|
83087291df | ||
|
|
1539128c3f | ||
|
|
3921a0ed70 | ||
|
|
d61e40e49b | ||
|
|
39e1f03cd1 | ||
|
|
25f0e38c73 | ||
|
|
163bd34172 | ||
|
|
18914ac9a5 | ||
|
|
60d62148e8 | ||
|
|
b72f7c3021 | ||
|
|
2d068a42f4 | ||
|
|
24568058e1 | ||
|
|
84a4644490 | ||
|
|
974e01ec70 | ||
|
|
6babc73320 | ||
|
|
7190b3400f | ||
|
|
ff7576f8e4 | ||
|
|
eb67c4519d | ||
|
|
256bd8d594 | ||
|
|
143cad78bf | ||
|
|
cc709a2ef9 | ||
|
|
8485532856 | ||
|
|
fdbdc5aac7 | ||
|
|
83144d59be | ||
|
|
dc34d355bc | ||
|
|
85e2392fef | ||
|
|
5567033b33 | ||
|
|
e801fad4d4 | ||
|
|
e3a23aed33 | ||
|
|
93e9d3e57d | ||
|
|
21f7cd5d8f | ||
|
|
a6161c6f22 | ||
|
|
3b422377d2 | ||
|
|
fb8acf8c1e | ||
|
|
8ac0466ec2 | ||
|
|
87a65c0e4b | ||
|
|
19043537c1 | ||
|
|
ee22d0b938 | ||
|
|
115327b967 | ||
|
|
71b916ae8f | ||
|
|
52a422350b | ||
|
|
c3f547ec77 | ||
|
|
7ac48f441d | ||
|
|
19d721d262 | ||
|
|
d317ee1197 | ||
|
|
a62c0e8163 | ||
|
|
c1a62e2f05 | ||
|
|
858b053134 | ||
|
|
dbfa43a60a | ||
|
|
1b8ea31172 | ||
|
|
65b22ebfa9 | ||
|
|
918e4ef7d0 | ||
|
|
00a271dd94 | ||
|
|
c6ae916b24 | ||
|
|
ba7e953760 | ||
|
|
72175fc40e | ||
|
|
bd12b37353 | ||
|
|
a4f8c6734c | ||
|
|
66d44162e9 | ||
|
|
3ca317e0ce | ||
|
|
2290c32a83 | ||
|
|
3e25375013 | ||
|
|
2c0e14ba92 | ||
|
|
e06f297499 | ||
|
|
d46088548d | ||
|
|
30eab6c8a3 | ||
|
|
a8b94b1cca | ||
|
|
f37e313705 | ||
|
|
507fc34c22 | ||
|
|
6a4fa8de9d | ||
|
|
77550186ad | ||
|
|
45ef0e1b50 | ||
|
|
003827a4f2 | ||
|
|
418903e9ef | ||
|
|
6adad1055b | ||
|
|
fc1217ba07 | ||
|
|
77e479fda8 | ||
|
|
2793187bda | ||
|
|
261ed46341 | ||
|
|
6f0eeecc64 | ||
|
|
5c6f40b34a | ||
|
|
b2c78e490e | ||
|
|
69d5635aae | ||
|
|
802272a579 | ||
|
|
6478525666 | ||
|
|
3817f7f044 | ||
|
|
9936468a5e | ||
|
|
611946a7c7 | ||
|
|
596363ea23 | ||
|
|
f3b400975e | ||
|
|
d9bfe11ca1 | ||
|
|
e5885e9277 | ||
|
|
d3c6dc362e | ||
|
|
e37a485aaa | ||
|
|
c8ba3fa8ed | ||
|
|
5076f981a6 | ||
|
|
e51c7a79c7 | ||
|
|
3654da8a63 | ||
|
|
be9e25a2e5 | ||
|
|
719d5da641 | ||
|
|
da9e0d3c02 | ||
|
|
50165397c7 | ||
|
|
9319c4c96e | ||
|
|
cd9273028b | ||
|
|
ce1ef6c159 | ||
|
|
89e5e10657 | ||
|
|
6eab6a96cb | ||
|
|
6485869659 | ||
|
|
c3802891fc | ||
|
|
8677d63003 | ||
|
|
ba1172b3ad | ||
|
|
538535c3b7 | ||
|
|
e593c7270f | ||
|
|
0770a6f848 | ||
|
|
3567880303 | ||
|
|
8a456f578d | ||
|
|
5603afbd20 | ||
|
|
21498359e4 | ||
|
|
7bd872b264 | ||
|
|
0c41fcba6a | ||
|
|
55b7cf0dda | ||
|
|
6d8b0f5566 | ||
|
|
dc660e72e5 | ||
|
|
de2980e9e5 | ||
|
|
85801ea62c | ||
|
|
c7041c0f1a | ||
|
|
d4cb6b68c4 | ||
|
|
529c73d58d | ||
|
|
9719391c82 | ||
|
|
0d2552b0b6 | ||
|
|
6a2fed33d3 | ||
|
|
19855c5bd5 | ||
|
|
8216e5cd72 | ||
|
|
b8cbfcbe7e | ||
|
|
571cab305c | ||
|
|
dce19b0ace | ||
|
|
820353ee0e | ||
|
|
4e820edd1f | ||
|
|
094dbf4c2d | ||
|
|
db0788c68f | ||
|
|
8f00344191 | ||
|
|
0f73cdeccb | ||
|
|
bd2a0563ad | ||
|
|
489290263f | ||
|
|
5e33612238 | ||
|
|
f1906bc966 | ||
|
|
f0006f2405 | ||
|
|
a3c881da59 | ||
|
|
b08f501aac | ||
|
|
4c8f9e4e06 | ||
|
|
46caf27e70 | ||
|
|
6461c1b4f1 | ||
|
|
b7a08494ae | ||
|
|
290a824107 | ||
|
|
46297645a4 | ||
|
|
ab02381a83 | ||
|
|
2287435740 | ||
|
|
e4a1c8dcef | ||
|
|
311b2d7969 | ||
|
|
89c87f941f | ||
|
|
a086d9f7df | ||
|
|
6c5806f971 | ||
|
|
f9b3daabd1 | ||
|
|
7d662bf5d1 | ||
|
|
22b558110d | ||
|
|
3634cbe3cb | ||
|
|
991f12bd73 | ||
|
|
c0144d2161 | ||
|
|
4e7901b807 | ||
|
|
fb812301b2 | ||
|
|
e72401c5f4 | ||
|
|
bfa648972f | ||
|
|
6b0a803d14 | ||
|
|
6b58be377e | ||
|
|
71cbe97688 | ||
|
|
f08a45f2d4 | ||
|
|
a4af833d55 | ||
|
|
4bd622c1c5 | ||
|
|
718f23b34f | ||
|
|
3fdf048e51 | ||
|
|
8ca5d3b6f9 | ||
|
|
8ed4424e3e | ||
|
|
80a310540e | ||
|
|
ee3beea327 | ||
|
|
6c5181d8ce | ||
|
|
1f80f35ce6 | ||
|
|
1ffe438fa1 | ||
|
|
514cbc77fc | ||
|
|
b79d6aced4 | ||
|
|
73b738b7ff | ||
|
|
4f1b7b38b2 | ||
|
|
46ab338ea6 | ||
|
|
d27c7ce86f | ||
|
|
8cc5f2abfb | ||
|
|
6d6a228057 | ||
|
|
39a3f5e7d9 | ||
|
|
1f638f52d5 | ||
|
|
e4e70f1b5b | ||
|
|
3291cf7a6e | ||
|
|
52b29b53bc | ||
|
|
6ad37eb7a8 | ||
|
|
802beb49a6 | ||
|
|
88b130308d | ||
|
|
0ce47f2f12 | ||
|
|
5647a935a2 | ||
|
|
47c25982b6 | ||
|
|
c5aa35e016 | ||
|
|
97e4d23d75 | ||
|
|
69b9a2e98a | ||
|
|
4bbead6200 | ||
|
|
a94d2211e4 | ||
|
|
603bae398f | ||
|
|
71a45e56d7 | ||
|
|
de25359a90 | ||
|
|
202bbdf8dd | ||
|
|
8a4521864e | ||
|
|
cce5a9a1ca | ||
|
|
1ea72ec378 | ||
|
|
74e4a817cb | ||
|
|
0d6e309372 | ||
|
|
4f8ad6bdcb | ||
|
|
c023a02884 | ||
|
|
e3fb74b656 | ||
|
|
a4b9e8fdc6 | ||
|
|
0db02926f5 | ||
|
|
77c20066a8 | ||
|
|
80afe42d17 | ||
|
|
986b13c3a1 | ||
|
|
175fe163af | ||
|
|
7fff8f82e2 | ||
|
|
db1210fc67 | ||
|
|
0b2c9ff77a | ||
|
|
822c14814b | ||
|
|
148f49d54a | ||
|
|
3c8ef5749f | ||
|
|
35b1bb05c8 | ||
|
|
a18bfad53a | ||
|
|
1ed4324613 | ||
|
|
0e908b720d | ||
|
|
3fa9ea9bc0 | ||
|
|
ea60b83f16 | ||
|
|
cd0e218a07 | ||
|
|
f247ea7c27 | ||
|
|
99a1ef0460 | ||
|
|
426f164e02 | ||
|
|
01f3e4b083 | ||
|
|
402dfd5da7 | ||
|
|
e27bd04ba2 | ||
|
|
d3260bca27 | ||
|
|
d27ad99daa | ||
|
|
a5e46568ee | ||
|
|
ef63d6f84c | ||
|
|
d4d8495840 | ||
|
|
65db6bb2a5 | ||
|
|
9d8eb65a5e | ||
|
|
ba43ee8410 | ||
|
|
b0445496bb | ||
|
|
af13ae1ef2 | ||
|
|
ebae6332aa | ||
|
|
f2d0d8b422 | ||
|
|
dae2acca88 | ||
|
|
9fa4ff750b | ||
|
|
15d85bdc05 | ||
|
|
0c18cb054d | ||
|
|
eceeacdf61 | ||
|
|
9cc13c8324 | ||
|
|
8acdb39bdd | ||
|
|
1b120c189e | ||
|
|
ed55e84afa | ||
|
|
87f0f123a8 | ||
|
|
bd194686df | ||
|
|
6cb0190fad | ||
|
|
5eae262264 | ||
|
|
a401374ed4 | ||
|
|
f9c2c846f7 | ||
|
|
71da941c8b | ||
|
|
8f80cf5664 | ||
|
|
890da492fb | ||
|
|
bc4d7e0020 | ||
|
|
e9e850ad8f | ||
|
|
19219c37b6 | ||
|
|
7a22827af4 | ||
|
|
4a4dce1766 | ||
|
|
6507656496 | ||
|
|
291afd8448 | ||
|
|
55a4c40970 | ||
|
|
723b275d99 | ||
|
|
409e90e7de | ||
|
|
080565e482 | ||
|
|
ec746e17c9 | ||
|
|
b0b7cf4042 | ||
|
|
7ba1371466 | ||
|
|
755b846877 | ||
|
|
9f793f1486 | ||
|
|
cb1c3f87f0 | ||
|
|
14a41d91f6 | ||
|
|
a3d6c42810 | ||
|
|
233cf13bdc | ||
|
|
93f39d5df9 | ||
|
|
be4d3783a4 | ||
|
|
4d484dd971 | ||
|
|
164b4dd439 | ||
|
|
f8fdb0dc7e | ||
|
|
2ca751a9fc | ||
|
|
695d383ed1 | ||
|
|
f7ed3139ab |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -58,5 +58,4 @@ kotlin-ultimate/
|
||||
node_modules/
|
||||
.rpt2_cache/
|
||||
libraries/tools/kotlin-test-js-runner/lib/
|
||||
libraries/tools/kotlin-source-map-loader/lib/
|
||||
local.properties
|
||||
|
||||
15
.idea/codeStyles/Project.xml
generated
15
.idea/codeStyles/Project.xml
generated
@@ -13,6 +13,21 @@
|
||||
</option>
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<MarkdownNavigatorCodeStyleSettings>
|
||||
|
||||
1
.idea/dictionaries/4u7.xml
generated
1
.idea/dictionaries/4u7.xml
generated
@@ -11,6 +11,7 @@
|
||||
<w>protobuf</w>
|
||||
<w>redirector</w>
|
||||
<w>remapper</w>
|
||||
<w>sonatype</w>
|
||||
<w>unpresent</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
||||
4
.idea/dictionaries/dmitriy_dolovov.xml
generated
4
.idea/dictionaries/dmitriy_dolovov.xml
generated
@@ -1,6 +1,7 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="dmitriy.dolovov">
|
||||
<words>
|
||||
<w>cinterop</w>
|
||||
<w>commonizable</w>
|
||||
<w>commonization</w>
|
||||
<w>commonize</w>
|
||||
@@ -8,8 +9,11 @@
|
||||
<w>commonizer</w>
|
||||
<w>commonizers</w>
|
||||
<w>commonizes</w>
|
||||
<w>commonizing</w>
|
||||
<w>jetbrains</w>
|
||||
<w>konan</w>
|
||||
<w>kotlinx</w>
|
||||
<w>macos</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
21
.idea/runConfigurations/Test__stdlib_js_public_kotlin_api_test__overwrite_results.xml
generated
Normal file
21
.idea/runConfigurations/Test__stdlib_js_public_kotlin_api_test__overwrite_results.xml
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Test: stdlib-js public kotlin api test, overwrite results" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="--tests "org.jetbrains.kotlin.js.test.ApiTest" -Poverwrite.output=true" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value=":js:js.tests:test" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<GradleScriptDebugEnabled>false</GradleScriptDebugEnabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
2
.idea/scopes/Apply_copyright.xml
generated
2
.idea/scopes/Apply_copyright.xml
generated
@@ -1,3 +1,3 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="Apply copyright" pattern="!file[*]:*//testData//*&&!file[*]:testData//*&&!file[*]:*.gradle.kts&&!file[*]:*.gradle" />
|
||||
<scope name="Apply copyright" pattern="!file[*]:*//testData//*&&!file[*]:testData//*&&!file[*]:*.gradle.kts&&!file[*]:*.gradle&&!file[kotlin.kotlin-ultimate]:*/&&!file[kotlin.kotlin-ultimate.*]:*/&&!file[kotlin.libraries]:stdlib/api//*" />
|
||||
</component>
|
||||
461
ChangeLog.md
461
ChangeLog.md
@@ -1,5 +1,466 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 1.4-M2
|
||||
|
||||
### Compiler
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-37432`](https://youtrack.jetbrains.com/issue/KT-37432) Do not include annotations fields into 'visibility must be explicitly specified' check in api mode
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-27362`](https://youtrack.jetbrains.com/issue/KT-27362) Anonymous classes representing function/property references contain rarely used methods
|
||||
- [`KT-35626`](https://youtrack.jetbrains.com/issue/KT-35626) NI: Performance problem with many type parameters
|
||||
- [`KT-36047`](https://youtrack.jetbrains.com/issue/KT-36047) Compiler produces if-chain instead of switch when when subject captured as variable
|
||||
- [`KT-36638`](https://youtrack.jetbrains.com/issue/KT-36638) Use 'java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;' when appending single character in JVM_IR
|
||||
- [`KT-37389`](https://youtrack.jetbrains.com/issue/KT-37389) Avoid type approximation during generation constraints with EQUALITY kind
|
||||
- [`KT-37392`](https://youtrack.jetbrains.com/issue/KT-37392) Avoid substitution and type approximation for simple calls
|
||||
- [`KT-37546`](https://youtrack.jetbrains.com/issue/KT-37546) NI: high memory and CPU consumption due to creating useless captured types (storing in approximated types cache, unneeded computations)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-11265`](https://youtrack.jetbrains.com/issue/KT-11265) Factory pattern and overload resolution ambiguity
|
||||
- [`KT-27524`](https://youtrack.jetbrains.com/issue/KT-27524) Inline class is boxed when used with suspend modifier
|
||||
- [`KT-27586`](https://youtrack.jetbrains.com/issue/KT-27586) ClassCastException occurs if the Result (or any other inline class) is returned from a lambda
|
||||
- [`KT-30419`](https://youtrack.jetbrains.com/issue/KT-30419) Use boxed version of an inline class in return type position for covariant and generic-specialized overrides
|
||||
- [`KT-31163`](https://youtrack.jetbrains.com/issue/KT-31163) FIR: consider replacing comparisons with compareTo calls and some additional intrinsics
|
||||
- [`KT-31585`](https://youtrack.jetbrains.com/issue/KT-31585) ClassCastException with derived class delegated to generic class with inline class type argument
|
||||
- [`KT-31823`](https://youtrack.jetbrains.com/issue/KT-31823) NI: Type mismatch with a star projection and `UnsafeVariance`
|
||||
- [`KT-33119`](https://youtrack.jetbrains.com/issue/KT-33119) Pre-increment for inline class wrapping Int compiles to direct increment instead of inc-impl
|
||||
- [`KT-33715`](https://youtrack.jetbrains.com/issue/KT-33715) Kotlin/Native: metadata compiler
|
||||
- [`KT-34048`](https://youtrack.jetbrains.com/issue/KT-34048) IllegalAccessError when initializing val property in EXACTLY_ONCE lambda
|
||||
- [`KT-34433`](https://youtrack.jetbrains.com/issue/KT-34433) NI: Type mismatch with a star projection and `UnsafeVariance`
|
||||
- [`KT-35133`](https://youtrack.jetbrains.com/issue/KT-35133) FIR Java: don't set 'isOperator' for methods with non-operator names
|
||||
- [`KT-35234`](https://youtrack.jetbrains.com/issue/KT-35234) ClassCastException with creating an inline class from a function reference of covariant or generic-specialized override
|
||||
- [`KT-35406`](https://youtrack.jetbrains.com/issue/KT-35406) Generic type implicitly inferred as Nothing with no warning
|
||||
- [`KT-35587`](https://youtrack.jetbrains.com/issue/KT-35587) Plain namespace strings in JvmNameResolver.PREDEFINED_STRINGS are prone to namespace changes during jar relocation.
|
||||
- [`KT-36044`](https://youtrack.jetbrains.com/issue/KT-36044) NI: premature fixation a type variable if there were nested lambdas (constraint source was the deepest lambda)
|
||||
- [`KT-36057`](https://youtrack.jetbrains.com/issue/KT-36057) [FIR] Incorrect smartcast
|
||||
- [`KT-36069`](https://youtrack.jetbrains.com/issue/KT-36069) NI: TYPE_MISMATCH caused by incorrect inference to Nothing
|
||||
- [`KT-36125`](https://youtrack.jetbrains.com/issue/KT-36125) Callable reference resolution ambiguity error is not displayed properly in the IDE
|
||||
- [`KT-36191`](https://youtrack.jetbrains.com/issue/KT-36191) IDE locks loading packages and editing file containing `try` keyword inside string template
|
||||
- [`KT-36222`](https://youtrack.jetbrains.com/issue/KT-36222) NI: Improve error message about nullability mismatch for a generic call
|
||||
- [`KT-36249`](https://youtrack.jetbrains.com/issue/KT-36249) NI doesn't use upper bound for T of called function during infer return type and as a result infer it to `Any?` if the resulting type was intersection type
|
||||
- [`KT-36345`](https://youtrack.jetbrains.com/issue/KT-36345) FIR: record argument mapping for use in back-end
|
||||
- [`KT-36446`](https://youtrack.jetbrains.com/issue/KT-36446) NI: "UnsupportedOperationException no descriptor for type constructor of IntegerLiteralType[Int,Long,Byte,Short]" with BuilderInference and delegate
|
||||
- [`KT-36758`](https://youtrack.jetbrains.com/issue/KT-36758) [FIR] Unresolved callable reference to member of local class
|
||||
- [`KT-36759`](https://youtrack.jetbrains.com/issue/KT-36759) [FIR] Unsupported callable reference resolution for methods with default parameters
|
||||
- [`KT-36762`](https://youtrack.jetbrains.com/issue/KT-36762) [FIR] Unresolved `array.clone()`
|
||||
- [`KT-36764`](https://youtrack.jetbrains.com/issue/KT-36764) [FIR] Bug in inference with DefinitelyNotNull types
|
||||
- [`KT-36816`](https://youtrack.jetbrains.com/issue/KT-36816) NI: definitely not-null (T!!) types in invariant positions don't approximate to T inside inference process
|
||||
- [`KT-36819`](https://youtrack.jetbrains.com/issue/KT-36819) NI: premature completion of lambdas, which are passed somewhere
|
||||
- [`KT-36850`](https://youtrack.jetbrains.com/issue/KT-36850) Incorrect private visibility of sealed class constructors
|
||||
- [`KT-36856`](https://youtrack.jetbrains.com/issue/KT-36856) Throwing exception when there is inheritance in Kotlin from Java class, which contains methods with the same JVM descriptors
|
||||
- [`KT-36879`](https://youtrack.jetbrains.com/issue/KT-36879) Introduce FIR_IDENTICAL in diagnostic tests
|
||||
- [`KT-36881`](https://youtrack.jetbrains.com/issue/KT-36881) FIR: completion don't runs for return expressions
|
||||
- [`KT-36887`](https://youtrack.jetbrains.com/issue/KT-36887) [FIR] Unresolved member in nested lambda in initializer
|
||||
- [`KT-36905`](https://youtrack.jetbrains.com/issue/KT-36905) [FIR] Unresolved in lambda in default argument position
|
||||
- [`KT-36953`](https://youtrack.jetbrains.com/issue/KT-36953) AssertionError: "Unsigned type expected: null" when there is a range with an unsigned type
|
||||
- [`KT-37009`](https://youtrack.jetbrains.com/issue/KT-37009) FIR: Bound smart-cast lost
|
||||
- [`KT-37027`](https://youtrack.jetbrains.com/issue/KT-37027) FIR: Wrong projection on spread + varargs on non-final types
|
||||
- [`KT-37038`](https://youtrack.jetbrains.com/issue/KT-37038) NI: redundant lambda's arrow breaks CST calculation for extension lambdas
|
||||
- [`KT-37043`](https://youtrack.jetbrains.com/issue/KT-37043) NI: inference T to Any? if there was elvis between Java out-type and reified `materialize` for this type without out projection
|
||||
- [`KT-37066`](https://youtrack.jetbrains.com/issue/KT-37066) [FIR] Wrong type inference for lambdas
|
||||
- [`KT-37070`](https://youtrack.jetbrains.com/issue/KT-37070) [FIR] Unresolved parameters of outer lambda in scope of inner lambda
|
||||
- [`KT-37087`](https://youtrack.jetbrains.com/issue/KT-37087) "IllegalStateException: Can't find method 'invoke()'" for mutable property reference in default value of an inline function parameter
|
||||
- [`KT-37091`](https://youtrack.jetbrains.com/issue/KT-37091) [FIR] Wrong inferred type of when-expression if when-argument is not-null-asserted and type is not specifies explicitly
|
||||
- [`KT-37176`](https://youtrack.jetbrains.com/issue/KT-37176) [FIR] Incorrect resolution mode for statements of block
|
||||
- [`KT-37302`](https://youtrack.jetbrains.com/issue/KT-37302) Unexpected conversion:`Int` constant inferred to `Long` in when expression
|
||||
- [`KT-37327`](https://youtrack.jetbrains.com/issue/KT-37327) FIR: Smartcast problem
|
||||
- [`KT-37343`](https://youtrack.jetbrains.com/issue/KT-37343) NI: definitely not null types pre-approximation is inconsistent with OI
|
||||
- [`KT-37380`](https://youtrack.jetbrains.com/issue/KT-37380) NI: broken some code with def not null types due to skip needed constraints
|
||||
- [`KT-37419`](https://youtrack.jetbrains.com/issue/KT-37419) NI: UNRESOLVED_REFERENCE_WRONG_RECEIVER is reported in case lambda with receiver is returned from `when` expression
|
||||
- [`KT-37434`](https://youtrack.jetbrains.com/issue/KT-37434) Kotlin/JS, Kotlin/Native: fun interfaces: SAM conversion to Kotlin interface is not compiled with RESOLUTION_TO_CLASSIFIER
|
||||
- [`KT-37447`](https://youtrack.jetbrains.com/issue/KT-37447) Expression from annotation entry in value parameter inside value parameter should be marked as USED_AS_EXPRESSION
|
||||
- [`KT-37453`](https://youtrack.jetbrains.com/issue/KT-37453) Type arguments not checked to be empty for candidates with no declared parameters
|
||||
- [`KT-37488`](https://youtrack.jetbrains.com/issue/KT-37488) [FIR] Incorrect exhaustiveness checking for branches with equals to object that implements sealed class
|
||||
- [`KT-37497`](https://youtrack.jetbrains.com/issue/KT-37497) NI: 'super' is not an expression, it can not be used as a receiver for extension functions
|
||||
- [`KT-37530`](https://youtrack.jetbrains.com/issue/KT-37530) NI: instantiation of abstract class via callable reference argument causes run time InstantiationError
|
||||
- [`KT-37531`](https://youtrack.jetbrains.com/issue/KT-37531) NI: callable reference argument with left hand side type parameter causes frontend exception
|
||||
- [`KT-37554`](https://youtrack.jetbrains.com/issue/KT-37554) NI: Nothing is inferred incorrectly with elvis return
|
||||
- [`KT-37579`](https://youtrack.jetbrains.com/issue/KT-37579) NI: inconsistent behaviour with OI around implicit invoke convention after safe call with additional implicit receiver
|
||||
- [`KT-37604`](https://youtrack.jetbrains.com/issue/KT-37604) "VerifyError: Call to wrong <init> method" in 'invoke' for adapted callable reference to constructor with coercion to Unit
|
||||
- [`KT-37621`](https://youtrack.jetbrains.com/issue/KT-37621) NI: type variable is inferred to Nothing if the second branch was Nothing and there was upper bound for a type parameter
|
||||
- [`KT-37626`](https://youtrack.jetbrains.com/issue/KT-37626) NI: builder inference with expected type breaks class references resolution for a class with parameters
|
||||
- [`KT-37627`](https://youtrack.jetbrains.com/issue/KT-37627) NI: wrong order of the type variable fixation (Nothing? against a call with lambda)
|
||||
- [`KT-37628`](https://youtrack.jetbrains.com/issue/KT-37628) NI: wrong approximation of type argument to star projection during common super type calculation
|
||||
- [`KT-37644`](https://youtrack.jetbrains.com/issue/KT-37644) NI: appeared exception during incorporation of a captured type into a type variable for elvis resolve
|
||||
- [`KT-37650`](https://youtrack.jetbrains.com/issue/KT-37650) NI: it's impossible to infer a type variable with the participation of a wrapped covariant type
|
||||
- [`KT-37718`](https://youtrack.jetbrains.com/issue/KT-37718) False positive unused parameter for @JvmStatic main function in object
|
||||
- [`KT-37779`](https://youtrack.jetbrains.com/issue/KT-37779) ClassCastException: Named argument without spread operator for vararg parameter causes code to crash on runtime
|
||||
- [`KT-37832`](https://youtrack.jetbrains.com/issue/KT-37832) In MPP, subtypes of types defined in legacy libraries, like stdlib, cannot properly resolve on the consumer side receviing both
|
||||
- [`KT-37861`](https://youtrack.jetbrains.com/issue/KT-37861) Capturing an outer class instance in a default parameter of inner class constructor causes VerifyError
|
||||
- [`KT-37986`](https://youtrack.jetbrains.com/issue/KT-37986) Return value of function reference returning inline class mapped to 'java.lang.Object' is not boxed properly
|
||||
- [`KT-37998`](https://youtrack.jetbrains.com/issue/KT-37998) '!!' operator on safe call of function returning inline class value causes CCE at runtime
|
||||
- [`KT-38042`](https://youtrack.jetbrains.com/issue/KT-38042) Allow kotlin.Result as a return type only if one enabled inline classes explicitly
|
||||
- [`KT-38134`](https://youtrack.jetbrains.com/issue/KT-38134) NI: Type mismatch with a star projection and `UnsafeVariance`
|
||||
- [`KT-38298`](https://youtrack.jetbrains.com/issue/KT-38298) Inconsistent choice of candidate when both expect/actual are available (affects only `enableGranularSourceSetMetadata`)
|
||||
- [`KT-38661`](https://youtrack.jetbrains.com/issue/KT-38661) NI: "Cannot infer type variable TypeVariable" with lambda with receiver
|
||||
- [`KT-38668`](https://youtrack.jetbrains.com/issue/KT-38668) Project with module dependency in KN, build fails with Kotlin 1.3.71 and associated libs but passes with 1.3.61.
|
||||
- [`KT-38857`](https://youtrack.jetbrains.com/issue/KT-38857) Class versions V1_5 or less must use F_NEW frames.
|
||||
- [`KT-39113`](https://youtrack.jetbrains.com/issue/KT-39113) "AssertionError: Uninitialized value on stack" with EXACTLY_ONCE contract in non-inline function and lambda destructuring
|
||||
|
||||
### Docs & Examples
|
||||
|
||||
- [`KT-35231`](https://youtrack.jetbrains.com/issue/KT-35231) toMutableList documentation is vague
|
||||
|
||||
### IDE
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-30541`](https://youtrack.jetbrains.com/issue/KT-30541) EDT Freeze after new Kotlin Script creation
|
||||
- [`KT-35050`](https://youtrack.jetbrains.com/issue/KT-35050) Significant freezes due to findSdkAcrossDependencies()
|
||||
- [`KT-37301`](https://youtrack.jetbrains.com/issue/KT-37301) Freeze when "Optimize Imports" in KotlinImportOptimizer
|
||||
- [`KT-37466`](https://youtrack.jetbrains.com/issue/KT-37466) Invalidate partialBodyResolveCache on OCB
|
||||
- [`KT-37467`](https://youtrack.jetbrains.com/issue/KT-37467) PerFileAnalysisCache.fetchAnalysisResults
|
||||
- [`KT-37993`](https://youtrack.jetbrains.com/issue/KT-37993) Do not resolve references if paste code is located in the same origin
|
||||
- [`KT-38318`](https://youtrack.jetbrains.com/issue/KT-38318) Freezes in IDEA
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-27935`](https://youtrack.jetbrains.com/issue/KT-27935) Functional typealias with typealias in type parameters causes UnsupportedOperationException in TypeSignatureMappingKt (IDEA analysis)
|
||||
- [`KT-31668`](https://youtrack.jetbrains.com/issue/KT-31668) Complete statement for class declaration: add '()' to supertype
|
||||
- [`KT-33473`](https://youtrack.jetbrains.com/issue/KT-33473) UAST: References to local variable are resolved to UastKotlinPsiVariable
|
||||
- [`KT-34564`](https://youtrack.jetbrains.com/issue/KT-34564) Kotlin USimpleNameReferenceExpression for annotation parameter resolves to null for compiled Kotlin classes
|
||||
- [`KT-34973`](https://youtrack.jetbrains.com/issue/KT-34973) Light class incorrectly claiming ambiguous method call from Java when one overload is synthetic
|
||||
- [`KT-35801`](https://youtrack.jetbrains.com/issue/KT-35801) UAST: UnknownKotlinExpression for valid Kotlin annotated expression
|
||||
- [`KT-35804`](https://youtrack.jetbrains.com/issue/KT-35804) UAST: Annotations missing from catch clause parameters
|
||||
- [`KT-35848`](https://youtrack.jetbrains.com/issue/KT-35848) UAST: ClassCastException when trying to invoke UElement for some wrapped PsiElements
|
||||
- [`KT-36156`](https://youtrack.jetbrains.com/issue/KT-36156) Kotlin annotation attributes have blue color whereas white in Java
|
||||
- [`KT-36275`](https://youtrack.jetbrains.com/issue/KT-36275) UAST: UCallExpression::resolve returns null for local function calls
|
||||
- [`KT-36717`](https://youtrack.jetbrains.com/issue/KT-36717) Fix failing light class tests after switching plugin to language version 1.4
|
||||
- [`KT-36877`](https://youtrack.jetbrains.com/issue/KT-36877) Message bundles for copy paste are missed in 201
|
||||
- [`KT-36907`](https://youtrack.jetbrains.com/issue/KT-36907) IDE: `-Xuse-ir` setting on facet level does not affect highlighting
|
||||
- [`KT-37133`](https://youtrack.jetbrains.com/issue/KT-37133) UAST: Annotating assignment expression sometimes leads to UnknownKotlinExpression
|
||||
- [`KT-37312`](https://youtrack.jetbrains.com/issue/KT-37312) "Implement members" intention put function in the primary constructor if there are unused brackets in class
|
||||
- [`KT-37613`](https://youtrack.jetbrains.com/issue/KT-37613) Uast: no parameters in reified method
|
||||
- [`KT-37933`](https://youtrack.jetbrains.com/issue/KT-37933) Rare NPE in ProjectRootsUtilKt.isKotlinBinary [easy fix]
|
||||
- [`KT-38081`](https://youtrack.jetbrains.com/issue/KT-38081) Configure kotlin in project produces IDE error "heavy operation and should not be call on AWT thread"
|
||||
- [`KT-38354`](https://youtrack.jetbrains.com/issue/KT-38354) HMPP. IDE. Dependency leakage from leaf native to shared native module
|
||||
- [`KT-38634`](https://youtrack.jetbrains.com/issue/KT-38634) IDE: Error on opening MPP project in 1.3.72 after opening it in 1.4-M2
|
||||
|
||||
### IDE. Code Style, Formatting
|
||||
|
||||
- [`KT-37870`](https://youtrack.jetbrains.com/issue/KT-37870) "Remove trailing comma" action stops working after applying and cancelling it
|
||||
|
||||
### IDE. Completion
|
||||
|
||||
- [`KT-36808`](https://youtrack.jetbrains.com/issue/KT-36808) Delete Flow.collect from autocompletion list or make it least prioritized
|
||||
- [`KT-36860`](https://youtrack.jetbrains.com/issue/KT-36860) Provide convenient completion of extension functions from objects
|
||||
- [`KT-37395`](https://youtrack.jetbrains.com/issue/KT-37395) Invalid callable reference completion of member extension
|
||||
|
||||
### IDE. Debugger
|
||||
|
||||
- [`KT-34906`](https://youtrack.jetbrains.com/issue/KT-34906) Implement Coroutine Debugger
|
||||
- [`KT-35392`](https://youtrack.jetbrains.com/issue/KT-35392) Debugger omits meaningful part of the stacktrace even with disabled filter
|
||||
- [`KT-36215`](https://youtrack.jetbrains.com/issue/KT-36215) Coroutines debugger tab is empty in Android Studio
|
||||
- [`KT-37238`](https://youtrack.jetbrains.com/issue/KT-37238) Coroutines Debugger: dump creation fails every time
|
||||
- [`KT-38047`](https://youtrack.jetbrains.com/issue/KT-38047) Coroutines Debugger: Assertion failed: “Should be invoked in manager thread, use DebuggerManagerThreadImpl” on moving to source code from suspended coroutine in project without debugger jar in classpath
|
||||
- [`KT-38049`](https://youtrack.jetbrains.com/issue/KT-38049) Coroutines Debugger: NPE “null cannot be cast to non-null type com.sun.jdi.ObjectReference” is thrown by calling dumpCoroutines
|
||||
- [`KT-38487`](https://youtrack.jetbrains.com/issue/KT-38487) Any Field Watch interaction causes a MissingResourceException
|
||||
|
||||
### IDE. Decompiler, Indexing, Stubs
|
||||
|
||||
- [`KT-37896`](https://youtrack.jetbrains.com/issue/KT-37896) IAE: "Argument for @NotNull parameter 'file' of IndexTodoCacheManagerImpl.getTodoCount must not be null" through KotlinTodoSearcher.processQuery()
|
||||
|
||||
### IDE. Gradle Integration
|
||||
|
||||
- [`KT-33809`](https://youtrack.jetbrains.com/issue/KT-33809) With `kotlin.mpp.enableGranularSourceSetsMetadata=true`, IDE misses dependsOn-relation between kotlin and android sourceSets, leading to issues with expect/actual matching
|
||||
- [`KT-36354`](https://youtrack.jetbrains.com/issue/KT-36354) IDE: Gradle import from non-JVM projects: dependency to output artifact is created instead of module dependency
|
||||
- [`KT-38037`](https://youtrack.jetbrains.com/issue/KT-38037) UnsupportedOperationException on sync gradle Kotlin project with at least two multiplatform modules
|
||||
|
||||
### IDE. Gradle. Script
|
||||
|
||||
- [`KT-36763`](https://youtrack.jetbrains.com/issue/KT-36763) Drop modification stamp for scripts after project import
|
||||
- [`KT-37237`](https://youtrack.jetbrains.com/issue/KT-37237) Script configurations should be loaded during project import in case of errors
|
||||
- [`KT-38041`](https://youtrack.jetbrains.com/issue/KT-38041) Do not request for script configuration after VCS update
|
||||
|
||||
### IDE. Inspections and Intentions
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-3262`](https://youtrack.jetbrains.com/issue/KT-3262) Inspection "Inner class could be nested"
|
||||
- [`KT-15723`](https://youtrack.jetbrains.com/issue/KT-15723) Add 'Convert to value' quickfix for property containing only getter
|
||||
- [`KT-34026`](https://youtrack.jetbrains.com/issue/KT-34026) Add "Remove argument" quick fix for redundant argument in constructor call
|
||||
- [`KT-34332`](https://youtrack.jetbrains.com/issue/KT-34332) Add "Remove argument" quick fix for redundant argument in function call
|
||||
- [`KT-34450`](https://youtrack.jetbrains.com/issue/KT-34450) `Convert function to property` intention should be also displayed on `fun` keyword
|
||||
- [`KT-34593`](https://youtrack.jetbrains.com/issue/KT-34593) Invert 'if' condition: Invert `String.isNotEmpty` should be `String.isEmpty`
|
||||
- [`KT-34819`](https://youtrack.jetbrains.com/issue/KT-34819) Inspection: report useless elvis "?: return null"
|
||||
- [`KT-37849`](https://youtrack.jetbrains.com/issue/KT-37849) Support `ReplaceWith` for supertypes call
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-37515`](https://youtrack.jetbrains.com/issue/KT-37515) Deadlock
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-12329`](https://youtrack.jetbrains.com/issue/KT-12329) "invert if" inserts unnecessary 'continue' for statement inside a loop with 'continue'
|
||||
- [`KT-17615`](https://youtrack.jetbrains.com/issue/KT-17615) "Convert parameter to receiver" changes `this` to `this@ < no name provided >`
|
||||
- [`KT-20868`](https://youtrack.jetbrains.com/issue/KT-20868) IntelliJ says method from anonymous inner class with inferred interface type is not used even though it is
|
||||
- [`KT-20907`](https://youtrack.jetbrains.com/issue/KT-20907) Secondary constructor is marked as unused by IDE when called by typealias
|
||||
- [`KT-22368`](https://youtrack.jetbrains.com/issue/KT-22368) "Convert to block body" intention incorrectly formats closing brace
|
||||
- [`KT-23510`](https://youtrack.jetbrains.com/issue/KT-23510) "Remove parameter" quick fix keeps lambda argument when it's out of parentheses
|
||||
- [`KT-27601`](https://youtrack.jetbrains.com/issue/KT-27601) False positive "Unused import directive" for extension function used in KDoc
|
||||
- [`KT-28085`](https://youtrack.jetbrains.com/issue/KT-28085) "Convert receiver to parameter" introduces incorrect this@class in lambda
|
||||
- [`KT-30028`](https://youtrack.jetbrains.com/issue/KT-30028) "Convert parameter to receiver" introduces wrong 'this' qualifier for extension lambda receiver
|
||||
- [`KT-31601`](https://youtrack.jetbrains.com/issue/KT-31601) "Remove redundant let call" changes semantics by introducing multiple safe calls
|
||||
- [`KT-31800`](https://youtrack.jetbrains.com/issue/KT-31800) False positive "never used" with function in private val object expression
|
||||
- [`KT-31912`](https://youtrack.jetbrains.com/issue/KT-31912) QF “Convert to anonymous object” do nothing on SAM-interfaces
|
||||
- [`KT-32561`](https://youtrack.jetbrains.com/issue/KT-32561) "Property can be declared in constructor" causes another warning
|
||||
- [`KT-32809`](https://youtrack.jetbrains.com/issue/KT-32809) Convert parameter to receiver inserts wrong qualifiers for this (when nothing needs to be changed)
|
||||
- [`KT-34371`](https://youtrack.jetbrains.com/issue/KT-34371) "Surround with lambda" quickfix is not available for suspend lambda parameters.
|
||||
- [`KT-34640`](https://youtrack.jetbrains.com/issue/KT-34640) Replace 'if' with 'when' leads to copy comment line above when from another if
|
||||
- [`KT-36225`](https://youtrack.jetbrains.com/issue/KT-36225) KNPE: CodeInliner.processTypeParameterUsages with `ReplaceWith` for inline reified generic function
|
||||
- [`KT-36266`](https://youtrack.jetbrains.com/issue/KT-36266) NPE when invoking Lift return out of if/when after intention becomes inapplicable but still beeing shown
|
||||
- [`KT-36296`](https://youtrack.jetbrains.com/issue/KT-36296) False negative "Redundant SAM-constructor" with multiple SAM arguments
|
||||
- [`KT-36367`](https://youtrack.jetbrains.com/issue/KT-36367) False negative "Redundant SAM-constructor" for kotlin functions
|
||||
- [`KT-36368`](https://youtrack.jetbrains.com/issue/KT-36368) False negative "Redundant SAM-constructor" for fun interfaces in kotlin
|
||||
- [`KT-36395`](https://youtrack.jetbrains.com/issue/KT-36395) False positive "Redundant SAM-constructor" with two java interfaces extending one another
|
||||
- [`KT-36411`](https://youtrack.jetbrains.com/issue/KT-36411) "Put parameters on separate lines" and "Put parameters on one line" actions do not respect trailing comma
|
||||
- [`KT-36482`](https://youtrack.jetbrains.com/issue/KT-36482) "Add JvmOverloads annotation" intention is still suggested for annotation's parameters
|
||||
- [`KT-36686`](https://youtrack.jetbrains.com/issue/KT-36686) Implement members quickfix puts the implementation *before* the data class if it already has a body
|
||||
- [`KT-36685`](https://youtrack.jetbrains.com/issue/KT-36685) "Convert to a range check" transform hex range to int if it is compared with "Less" or "Greater"
|
||||
- [`KT-36707`](https://youtrack.jetbrains.com/issue/KT-36707) False positive redundant companion object on calling companion object members
|
||||
- [`KT-36735`](https://youtrack.jetbrains.com/issue/KT-36735) Inspection 'Replace 'toString' with string template' miss curly braces and generates wrong code for constructor calls
|
||||
- [`KT-36834`](https://youtrack.jetbrains.com/issue/KT-36834) Convert use-site targets and usages with convert property to fun intention
|
||||
- [`KT-37213`](https://youtrack.jetbrains.com/issue/KT-37213) "Move to top level" intention does not update imports for extension functions
|
||||
- [`KT-37496`](https://youtrack.jetbrains.com/issue/KT-37496) False positive "Remove redundant backticks" for multiple underscores variable name
|
||||
- [`KT-37502`](https://youtrack.jetbrains.com/issue/KT-37502) False positive "redundant lambda arrow" with inline generic function with reified type in object and anonymous parameter name
|
||||
- [`KT-37508`](https://youtrack.jetbrains.com/issue/KT-37508) "Convert receiver to parameter" breaks code in anonymous objects (this@ < no name provided >)
|
||||
- [`KT-37576`](https://youtrack.jetbrains.com/issue/KT-37576) Kotlin InspectionSuppressor not being called for the kotlin's inspections
|
||||
- [`KT-37749`](https://youtrack.jetbrains.com/issue/KT-37749) "Convert to anonymous object" intention is suggested for Java SAM conversion, but not for Kotlin
|
||||
- [`KT-37781`](https://youtrack.jetbrains.com/issue/KT-37781) "Add modifier" intention/quickfix works incorrectly with functional interfaces
|
||||
- [`KT-37893`](https://youtrack.jetbrains.com/issue/KT-37893) i18n: Incorrect quickfix name "Lift return out of '"
|
||||
|
||||
### IDE. KDoc
|
||||
|
||||
- [`KT-37361`](https://youtrack.jetbrains.com/issue/KT-37361) Support for showing rendered doc comments in editor
|
||||
|
||||
### IDE. Libraries
|
||||
|
||||
- [`KT-36276`](https://youtrack.jetbrains.com/issue/KT-36276) IDE: references to declarations in JavaScript KLib dependency are unresolved
|
||||
- [`KT-37562`](https://youtrack.jetbrains.com/issue/KT-37562) IDE: references to JavaScript KLib dependency are unresolved, when project and library are compiled with "both" mode
|
||||
|
||||
### IDE. Navigation
|
||||
|
||||
- [`KT-18472`](https://youtrack.jetbrains.com/issue/KT-18472) UI lockup on find usages
|
||||
- [`KT-18619`](https://youtrack.jetbrains.com/issue/KT-18619) Find Usages of element used via import alias does not show actual usage location
|
||||
- [`KT-34088`](https://youtrack.jetbrains.com/issue/KT-34088) Navigate | Implementations action doesn't show implementations of Java methods in Kotlin files if method has parameters referring to generic type
|
||||
- [`KT-35006`](https://youtrack.jetbrains.com/issue/KT-35006) IDE: "Navigate to inline function call site" from stack trace for nested inline call navigates to outer inline call
|
||||
- [`KT-36138`](https://youtrack.jetbrains.com/issue/KT-36138) 628 second freeze when doing Find Usages on data class property
|
||||
- [`KT-36218`](https://youtrack.jetbrains.com/issue/KT-36218) Show Kotlin file members in navigation bar
|
||||
- [`KT-37494`](https://youtrack.jetbrains.com/issue/KT-37494) AnnotatedElementsSearch unable to find annotated property accessor
|
||||
|
||||
### IDE. Project View
|
||||
|
||||
- [`KT-32886`](https://youtrack.jetbrains.com/issue/KT-32886) Project tool window: Show Visibility Icons does nothing for Kotlin classes
|
||||
- [`KT-37632`](https://youtrack.jetbrains.com/issue/KT-37632) IDE error on project structure opening
|
||||
|
||||
### IDE. Refactorings
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-37801`](https://youtrack.jetbrains.com/issue/KT-37801) Renaming private property with common name is very slow
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-22733`](https://youtrack.jetbrains.com/issue/KT-22733) Refactor / Inline Function: fun with type parameter: KNPE at CodeInliner.processTypeParameterUsages()
|
||||
- [`KT-27389`](https://youtrack.jetbrains.com/issue/KT-27389) MPP: Refactoring "Move Class" does not change the package declaration
|
||||
- [`KT-29870`](https://youtrack.jetbrains.com/issue/KT-29870) Inline variable doesn't handle 'when' subject val correctly
|
||||
- [`KT-33045`](https://youtrack.jetbrains.com/issue/KT-33045) Cover Move Refactoring by statistics (FUS)
|
||||
- [`KT-36071`](https://youtrack.jetbrains.com/issue/KT-36071) Refactoring: Move top declaration implementation refactoring
|
||||
- [`KT-36072`](https://youtrack.jetbrains.com/issue/KT-36072) Empty files are removed on Refactor/Move action with turned off "Delete empty source files" option
|
||||
- [`KT-36114`](https://youtrack.jetbrains.com/issue/KT-36114) java.lang.NoClassDefFoundError exception on Refactor/Move of kotlin function if it is referenced in java
|
||||
- [`KT-36129`](https://youtrack.jetbrains.com/issue/KT-36129) java.lang.Throwable: Invalid file exception occurs on Refactor/Move of class from kotlin script
|
||||
- [`KT-36382`](https://youtrack.jetbrains.com/issue/KT-36382) Move file refactoring breaks ktor application config
|
||||
- [`KT-36504`](https://youtrack.jetbrains.com/issue/KT-36504) "Extract property" suggests potentially invalid name for new property
|
||||
- [`KT-37637`](https://youtrack.jetbrains.com/issue/KT-37637) KotlinChangeSignatureUsageProcessor broke Change Signature in Python plugin
|
||||
- [`KT-37797`](https://youtrack.jetbrains.com/issue/KT-37797) Useless "Value for new paramater" step in 'Update usages to reflect signature changes' for method with default parameter value
|
||||
- [`KT-37822`](https://youtrack.jetbrains.com/issue/KT-37822) Improve message "Inline all references and remove the kind"
|
||||
- [`KT-38348`](https://youtrack.jetbrains.com/issue/KT-38348) UL methods return signature without generic type parameters
|
||||
- [`KT-38527`](https://youtrack.jetbrains.com/issue/KT-38527) Move nested class to upper level fails silently: MissingResourceException
|
||||
|
||||
### IDE. Script
|
||||
|
||||
- [`KT-37765`](https://youtrack.jetbrains.com/issue/KT-37765) NCDFE KJvmCompiledModuleInMemory on running `*.main.kts` script
|
||||
|
||||
### IDE. Tests Support
|
||||
|
||||
- [`KT-36716`](https://youtrack.jetbrains.com/issue/KT-36716) With `kotlin.gradle.testing.enabled=true`, gradle console output gets extra ijLog messages
|
||||
- [`KT-36910`](https://youtrack.jetbrains.com/issue/KT-36910) There are no Run/Debug actions in context menu for non-JVM platform-specific test results
|
||||
- [`KT-37037`](https://youtrack.jetbrains.com/issue/KT-37037) [JS, Debug] Node.JS test debug doesn't stop on breakpoints
|
||||
|
||||
### IDE. Wizards
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-36150`](https://youtrack.jetbrains.com/issue/KT-36150) New Project Wizard: provide a way to connect with "dependsOn" relation the added project modules
|
||||
- [`KT-36179`](https://youtrack.jetbrains.com/issue/KT-36179) New Project Wizard: it's impossible to make a JVM target friendly to Java code in a multiplatform project
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-35583`](https://youtrack.jetbrains.com/issue/KT-35583) New Project wizard: don't suggest build systems which cannot be used
|
||||
- [`KT-35585`](https://youtrack.jetbrains.com/issue/KT-35585) New Project wizard: remember choices which have sense for many projects
|
||||
- [`KT-35691`](https://youtrack.jetbrains.com/issue/KT-35691) New Project wizard: artifact and group values are effectively ignored
|
||||
- [`KT-35693`](https://youtrack.jetbrains.com/issue/KT-35693) New Project wizard creates pom.xml / build.gradle referring to release Kotlin version only
|
||||
- [`KT-36136`](https://youtrack.jetbrains.com/issue/KT-36136) New Project Wizard: generated projects are missing m2 Gradle repository
|
||||
- [`KT-36137`](https://youtrack.jetbrains.com/issue/KT-36137) New Project Wizard: "multiplatform" shall be written as a single word, without the capital P in the middle
|
||||
- [`KT-36155`](https://youtrack.jetbrains.com/issue/KT-36155) New Project Wizard: show warning "Multiplatform project cannot be generated" only for MPP projects
|
||||
- [`KT-36162`](https://youtrack.jetbrains.com/issue/KT-36162) New Project Wizard: make the error messages in modules editor actionable
|
||||
- [`KT-36163`](https://youtrack.jetbrains.com/issue/KT-36163) New Project Wizard: remove trailing spaces in Android SDK Path automatically
|
||||
- [`KT-36166`](https://youtrack.jetbrains.com/issue/KT-36166) New Project Wizard: addition of Android target into a multiplatform project doesn't add a necessary minimal Android configuration
|
||||
- [`KT-36169`](https://youtrack.jetbrains.com/issue/KT-36169) New Project Wizard: Android-related projects failed to build
|
||||
- [`KT-36176`](https://youtrack.jetbrains.com/issue/KT-36176) New Project Wizard: module templates doesn't work for multiplatform projects
|
||||
- [`KT-36177`](https://youtrack.jetbrains.com/issue/KT-36177) New Project Wizard: it's impossible to add more than one target of JVM kind to a multiplatform project
|
||||
- [`KT-36180`](https://youtrack.jetbrains.com/issue/KT-36180) New Project Wizard: it's impossible to set target JVM version for a JVM module
|
||||
- [`KT-36226`](https://youtrack.jetbrains.com/issue/KT-36226) New Project Wizard: add Mobile Android/iOS project template
|
||||
- [`KT-36267`](https://youtrack.jetbrains.com/issue/KT-36267) New Project Wizard: flatten JVM targets list for multiplatform projects
|
||||
- [`KT-36328`](https://youtrack.jetbrains.com/issue/KT-36328) New Project wizard fails for certain templates with AE: "Wrong line separators" at KotlinFormattingModelBuilder.createModel()
|
||||
- [`KT-37599`](https://youtrack.jetbrains.com/issue/KT-37599) New Project Wizard: Open Kotlin Wizard via hyperlink
|
||||
- [`KT-37667`](https://youtrack.jetbrains.com/issue/KT-37667) New project wizard: implement new UI design
|
||||
- [`KT-37674`](https://youtrack.jetbrains.com/issue/KT-37674) Kotlin version in build files includes the IDEA version
|
||||
- [`KT-38061`](https://youtrack.jetbrains.com/issue/KT-38061) New Project wizard 1.4: do not allow choosing build system if corresponding IJ plugin is disabled
|
||||
- [`KT-38567`](https://youtrack.jetbrains.com/issue/KT-38567) New Project wizard 1.4+: Improve processing case when project with required path already exists
|
||||
- [`KT-38579`](https://youtrack.jetbrains.com/issue/KT-38579) New Project wizard 1.4+: multiplatform mobile application: build fails on lint task: Configuration with name 'compileClasspath' not found
|
||||
- [`KT-38929`](https://youtrack.jetbrains.com/issue/KT-38929) New project wizard: update libraries in project template according to kotlin IDE plugin version
|
||||
- [`KT-38417`](https://youtrack.jetbrains.com/issue/KT-38417) Enable new project wizard by-default
|
||||
|
||||
### JS. Tools
|
||||
|
||||
- [`KT-36484`](https://youtrack.jetbrains.com/issue/KT-36484) KotlinJS, MPP: Compilation throws "TypeError: b is not a function" only in production mode
|
||||
|
||||
### JavaScript
|
||||
|
||||
- [`KT-31126`](https://youtrack.jetbrains.com/issue/KT-31126) Invalid JS constructor call (primary ordinary -> secondary external)
|
||||
- [`KT-35966`](https://youtrack.jetbrains.com/issue/KT-35966) Make @JsExport annotation usable in common code
|
||||
- [`KT-37128`](https://youtrack.jetbrains.com/issue/KT-37128) KJS: StackOverflowException when using reified recursive bound for type parameter
|
||||
- [`KT-37163`](https://youtrack.jetbrains.com/issue/KT-37163) KJS: NullPointerException on using intersection type as a reified one
|
||||
- [`KT-37418`](https://youtrack.jetbrains.com/issue/KT-37418) Support `AssociatedObjectKey` and `findAssociatedObject` in JS IR BE
|
||||
|
||||
### Libraries
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-8658`](https://youtrack.jetbrains.com/issue/KT-8658) Add property delegates which call get/set on the given KProperty instance, e.g. a property reference
|
||||
- [`KT-12448`](https://youtrack.jetbrains.com/issue/KT-12448) Make `@Suppress` applicable for type parameters
|
||||
- [`KT-22932`](https://youtrack.jetbrains.com/issue/KT-22932) String.format should support null locale
|
||||
- [`KT-23514`](https://youtrack.jetbrains.com/issue/KT-23514) assertFailsWith should link unexpected exception as cause
|
||||
- [`KT-23737`](https://youtrack.jetbrains.com/issue/KT-23737) JS & MPP: Support exception cause and addSuppressed
|
||||
- [`KT-25651`](https://youtrack.jetbrains.com/issue/KT-25651) Add shuffle() to Array<T>, ByteArray, IntArray, etc to match MutableList
|
||||
- [`KT-26494`](https://youtrack.jetbrains.com/issue/KT-26494) Create an interface with provideDelegate()
|
||||
- [`KT-27729`](https://youtrack.jetbrains.com/issue/KT-27729) Inherit `ReadWriteProperty` from `ReadOnlyProperty`
|
||||
- [`KT-28290`](https://youtrack.jetbrains.com/issue/KT-28290) Add the onEach extension function to the Array
|
||||
- [`KT-29182`](https://youtrack.jetbrains.com/issue/KT-29182) SIZE_BYTES/BITS for Float and Double
|
||||
- [`KT-30372`](https://youtrack.jetbrains.com/issue/KT-30372) Add associateWith to Array<T>
|
||||
- [`KT-33906`](https://youtrack.jetbrains.com/issue/KT-33906) Add vararg overloads for maxOf/minOf functions
|
||||
- [`KT-34161`](https://youtrack.jetbrains.com/issue/KT-34161) Array.contentEquals/contentHashCode/contentToString should allow null array receiver and argument
|
||||
- [`KT-35851`](https://youtrack.jetbrains.com/issue/KT-35851) Add setOfNotNull function
|
||||
- [`KT-36866`](https://youtrack.jetbrains.com/issue/KT-36866) reduceIndexedOrNull
|
||||
- [`KT-36955`](https://youtrack.jetbrains.com/issue/KT-36955) stdlib: Reverse range and sortDescending range
|
||||
- [`KT-37161`](https://youtrack.jetbrains.com/issue/KT-37161) Add #onEachIndexed similar to #forEachIndexed
|
||||
- [`KT-37603`](https://youtrack.jetbrains.com/issue/KT-37603) Throwable.stackTraceToString: string with detailed information about exception
|
||||
- [`KT-37751`](https://youtrack.jetbrains.com/issue/KT-37751) Implement shuffled() method Sequences
|
||||
- [`KT-37804`](https://youtrack.jetbrains.com/issue/KT-37804) Add 'fail' in kotlin-test that allows to specify cause
|
||||
- [`KT-37839`](https://youtrack.jetbrains.com/issue/KT-37839) StringBuilder.appendLine in stdlib-common
|
||||
- [`KT-37910`](https://youtrack.jetbrains.com/issue/KT-37910) Support Media Source Extension (MSE) and Encrypted Media Extensions (EME) in Kotlin/Js
|
||||
- [`KT-38044`](https://youtrack.jetbrains.com/issue/KT-38044) Common Throwable.printStackTrace
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-37416`](https://youtrack.jetbrains.com/issue/KT-37416) readLine() is very slow
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-13887`](https://youtrack.jetbrains.com/issue/KT-13887) Double/Float companion values such as NaN should be constants
|
||||
- [`KT-14119`](https://youtrack.jetbrains.com/issue/KT-14119) `String.toBoolean()` should be `String?.toBoolean()`
|
||||
- [`KT-16529`](https://youtrack.jetbrains.com/issue/KT-16529) Names of KProperty's type parameters are inconsistent with ReadOnlyProperty/ReadWriteProperty
|
||||
- [`KT-36356`](https://youtrack.jetbrains.com/issue/KT-36356) Specify which element Iterable.distinctBy(selector) retains
|
||||
- [`KT-38060`](https://youtrack.jetbrains.com/issue/KT-38060) runningFold and runningReduce instead of scanReduce
|
||||
|
||||
### Reflection
|
||||
|
||||
- [`KT-29969`](https://youtrack.jetbrains.com/issue/KT-29969) Support optional vararg parameter in `KCallable.callBy`
|
||||
- [`KT-37707`](https://youtrack.jetbrains.com/issue/KT-37707) "IllegalStateException: superInterface.classLoader must not be null" on class, which implements "AutoCloaseable" interface, "isAccessible" property changing
|
||||
|
||||
### Tools. CLI
|
||||
|
||||
- [`KT-37090`](https://youtrack.jetbrains.com/issue/KT-37090) file does not exist: `C:\Users\NK\DOWNLO~1\kotlin-compiler-1.3.61\kotlinc\bin\..\lib\kotlin-compiler.jar" from standalone compiler on Windows`
|
||||
|
||||
### Tools. Gradle
|
||||
|
||||
- [`KT-35447`](https://youtrack.jetbrains.com/issue/KT-35447) Warnings should be piped to stderr when using allWarningsAsErrors = true
|
||||
- [`KT-35942`](https://youtrack.jetbrains.com/issue/KT-35942) User test Gradle source set code cannot reach out internal members from the production code
|
||||
- [`KT-36019`](https://youtrack.jetbrains.com/issue/KT-36019) Implement Gradle DSL for explicit API mode
|
||||
|
||||
### Tools. Gradle. JS
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-32017`](https://youtrack.jetbrains.com/issue/KT-32017) Kotlin/JS in MPP: support changing the generated JS file name in Gradle DSL
|
||||
- [`KT-32721`](https://youtrack.jetbrains.com/issue/KT-32721) [Gradle, JS] CSS Support for browser
|
||||
- [`KT-36843`](https://youtrack.jetbrains.com/issue/KT-36843) [Gradle, JS, IR] Configure JS Compiler Type through DSL
|
||||
- [`KT-37207`](https://youtrack.jetbrains.com/issue/KT-37207) Allow to use npm dependency from a local directory
|
||||
- [`KT-38056`](https://youtrack.jetbrains.com/issue/KT-38056) [Gradle, JS] Group tasks by browser and node
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-32466`](https://youtrack.jetbrains.com/issue/KT-32466) kotlinNpmResolve fails in the case of composite build
|
||||
- [`KT-34468`](https://youtrack.jetbrains.com/issue/KT-34468) Consider custom versions while parsing yarn.lock
|
||||
- [`KT-36489`](https://youtrack.jetbrains.com/issue/KT-36489) [Gradle, JS, IR]: Correct naming for both compilers
|
||||
- [`KT-36784`](https://youtrack.jetbrains.com/issue/KT-36784) Kotlin. JS. MPP – Cannot find project :js when using Gradle composite builds
|
||||
- [`KT-36864`](https://youtrack.jetbrains.com/issue/KT-36864) KJS. Composite build require JS plugin in root project
|
||||
- [`KT-37240`](https://youtrack.jetbrains.com/issue/KT-37240) KJS. Nondeterministic execution order for webpack scripts (from folder 'webpack.config.d')
|
||||
- [`KT-37582`](https://youtrack.jetbrains.com/issue/KT-37582) Kotlin/JS: KotlinWebpack non-nullable properties are shown as nullable in Gradle configuration
|
||||
- [`KT-37587`](https://youtrack.jetbrains.com/issue/KT-37587) KJS. Karma ignore dynamically created webpack patches
|
||||
- [`KT-37635`](https://youtrack.jetbrains.com/issue/KT-37635) [Gradle, JS] Webpack devtool provide enum for only 2 variants
|
||||
- [`KT-37636`](https://youtrack.jetbrains.com/issue/KT-37636) [Gradle, JS] Extract package.json from klib
|
||||
- [`KT-37762`](https://youtrack.jetbrains.com/issue/KT-37762) [Gradle, JS] Actualize Node and Yarn versions in 1.4
|
||||
- [`KT-37988`](https://youtrack.jetbrains.com/issue/KT-37988) [Gradle, JS] Bump NPM versions on 1.4-M2
|
||||
- [`KT-38051`](https://youtrack.jetbrains.com/issue/KT-38051) [Gradle, JS] browserDistribution doesn't provide outputs
|
||||
- [`KT-38519`](https://youtrack.jetbrains.com/issue/KT-38519) JS Compiler per project without additional import
|
||||
|
||||
### Tools. Gradle. Multiplatform
|
||||
|
||||
- [`KT-36674`](https://youtrack.jetbrains.com/issue/KT-36674) `allMetadataJar` task fails if there is an empty intermediate source set in a multiplatform project with native targets
|
||||
- [`KT-38746`](https://youtrack.jetbrains.com/issue/KT-38746) In HMPP, compilation of a shared-native source set could be mistakenly disabled
|
||||
- [`KT-39094`](https://youtrack.jetbrains.com/issue/KT-39094) Provide a way to pass custom JVM args to commonizer from Gradle
|
||||
|
||||
### Tools. Gradle. Native
|
||||
|
||||
- [`KT-25887`](https://youtrack.jetbrains.com/issue/KT-25887) Kotlin Native gradle build fail with `endorsed is not supported. Endorsed standards and standalone APIs` on jdk > 8 & CLion
|
||||
- [`KT-36721`](https://youtrack.jetbrains.com/issue/KT-36721) Deduce a fully qualified unique_name in klib manifest from something like group name
|
||||
- [`KT-37730`](https://youtrack.jetbrains.com/issue/KT-37730) Native part of multiplatform build fails with "unresolved reference" errors if there is a local and external module with the same name
|
||||
- [`KT-38174`](https://youtrack.jetbrains.com/issue/KT-38174) Kotlin/Native: Disable platform libraries generation at the user side by default
|
||||
|
||||
### Tools. J2K
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-34965`](https://youtrack.jetbrains.com/issue/KT-34965) Convert function reference copied from function call
|
||||
- [`KT-35593`](https://youtrack.jetbrains.com/issue/KT-35593) New J2K: method's names don't change between functions declared in Number.java and Number.kt
|
||||
- [`KT-35897`](https://youtrack.jetbrains.com/issue/KT-35897) J2K converts private enum constructors to internal constructors and produces NON_PRIVATE_CONSTRUCTOR_IN_ENUM error
|
||||
- [`KT-36088`](https://youtrack.jetbrains.com/issue/KT-36088) J2K: StackOverflowError when trying to convert Java class with recursive type bound
|
||||
- [`KT-36149`](https://youtrack.jetbrains.com/issue/KT-36149) J2K: PsiInvalidElementAccessException: Element class com.intellij.psi.impl.source.tree.CompositeElement of type DOT_QUALIFIED_EXPRESSION
|
||||
- [`KT-36152`](https://youtrack.jetbrains.com/issue/KT-36152) J2K: RuntimeException: Couldn't get containingKtFile for ktElement
|
||||
- [`KT-36159`](https://youtrack.jetbrains.com/issue/KT-36159) J2K: ClassCastException if constructor contains a super() call and class extends from Kotlin class
|
||||
- [`KT-36190`](https://youtrack.jetbrains.com/issue/KT-36190) J2K: Wrong property name generation when getter for non-boolean value starts with 'is'
|
||||
- [`KT-36891`](https://youtrack.jetbrains.com/issue/KT-36891) j2k: Fail with java.lang.NoClassDefFoundError when converting array
|
||||
- [`KT-37052`](https://youtrack.jetbrains.com/issue/KT-37052) new J2K: Java private function is converted to `private open` top-level function
|
||||
- [`KT-37620`](https://youtrack.jetbrains.com/issue/KT-37620) new J2K: IndexOutOfBoundsException (DefaultArgumentsConversion.applyToElement) with overloaded function with vararg parameter
|
||||
- [`KT-37919`](https://youtrack.jetbrains.com/issue/KT-37919) new J2K: Redundant line feeds when converting function
|
||||
|
||||
### Tools. JPS
|
||||
|
||||
- [`KT-37159`](https://youtrack.jetbrains.com/issue/KT-37159) A Typo (forgotten space) in build output in Circular dependencies warning description
|
||||
|
||||
### Tools. Scripts
|
||||
|
||||
- [`KT-30086`](https://youtrack.jetbrains.com/issue/KT-30086) ThreadDeath when running kotlin scripts using jsr223
|
||||
- [`KT-37558`](https://youtrack.jetbrains.com/issue/KT-37558) Scripts: implicit receivers don't work correctly when using CompiledScriptJarsCache
|
||||
- [`KT-37823`](https://youtrack.jetbrains.com/issue/KT-37823) Consecutive invocations of main.kts throw a KotlinReflectionNotSupportedError
|
||||
|
||||
|
||||
## 1.4-M1
|
||||
|
||||
### Compiler
|
||||
|
||||
@@ -23,28 +23,28 @@ open class ManyImplicitReceiversBenchmark : AbstractSimpleFileBenchmark() {
|
||||
|
||||
override fun buildText(): String {
|
||||
return buildString {
|
||||
appendln("inline fun <T, R> with(receiver: T, block: T.() -> R): R = block()")
|
||||
appendLine("inline fun <T, R> with(receiver: T, block: T.() -> R): R = block()")
|
||||
|
||||
for (i in 1..size) {
|
||||
appendln("interface A$i {")
|
||||
appendln(" fun foo$i()")
|
||||
appendln("}")
|
||||
appendln()
|
||||
appendLine("interface A$i {")
|
||||
appendLine(" fun foo$i()")
|
||||
appendLine("}")
|
||||
appendLine()
|
||||
}
|
||||
appendln()
|
||||
appendLine()
|
||||
append("fun test(")
|
||||
append((1..size).joinToString(", ") { "a$it: A$it" })
|
||||
appendln(" {")
|
||||
appendLine(" {")
|
||||
for (i in 1..size) {
|
||||
appendln("with(a$i) {")
|
||||
appendLine("with(a$i) {")
|
||||
}
|
||||
for (i in 1..size) {
|
||||
appendln("foo$i()")
|
||||
appendLine("foo$i()")
|
||||
}
|
||||
for (i in 1..size) {
|
||||
appendln("}")
|
||||
appendLine("}")
|
||||
}
|
||||
appendln("}")
|
||||
appendLine("}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ open class PlusAssignOperatorDesugaringBenchmark : AbstractInferenceBenchmark()
|
||||
}
|
||||
|
||||
override fun buildText(): String = buildString {
|
||||
appendln(
|
||||
appendLine(
|
||||
"""
|
||||
class A {
|
||||
operator fun <T : Number> plus(other: (Int) -> T): A = this
|
||||
@@ -30,19 +30,20 @@ open class PlusAssignOperatorDesugaringBenchmark : AbstractInferenceBenchmark()
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
appendln("fun test() {")
|
||||
appendln("var a = A()")
|
||||
appendLine("fun test() {")
|
||||
appendLine("var a = A()")
|
||||
for (i in 1..size) {
|
||||
appendln("a += {")
|
||||
appendLine("a += {")
|
||||
}
|
||||
for (i in 1..size) {
|
||||
appendln(
|
||||
appendLine(
|
||||
"""
|
||||
it.inc()
|
||||
1
|
||||
}
|
||||
""".trimIndent())
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
appendln()
|
||||
appendLine()
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
@@ -25,7 +25,7 @@ class MessageCollectorToOutputItemsCollectorAdapter(
|
||||
private val delegate: MessageCollector,
|
||||
private val outputCollector: OutputItemsCollector
|
||||
) : MessageCollector by delegate {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
// TODO: consider adding some other way of passing input -> output mapping from compiler, e.g. dedicated service
|
||||
OutputMessageUtil.parseOutputMessage(message)?.let {
|
||||
outputCollector.add(it.sourceFiles, it.outputFile)
|
||||
|
||||
@@ -28,7 +28,6 @@ buildscript {
|
||||
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
|
||||
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
|
||||
classpath("com.gradle.publish:plugin-publish-plugin:0.11.0")
|
||||
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
|
||||
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
|
||||
}
|
||||
@@ -200,7 +199,10 @@ extra["intellijSeparateSdks"] = intellijSeparateSdks
|
||||
|
||||
extra["IntellijCoreDependencies"] =
|
||||
listOf(
|
||||
if (Platform[191].orHigher()) "asm-all-7.0.1" else "asm-all",
|
||||
when {
|
||||
Platform[202].orHigher() -> "asm-all-8.0.1"
|
||||
else -> "asm-all-7.0.1"
|
||||
},
|
||||
"guava",
|
||||
"jdom",
|
||||
"jna",
|
||||
@@ -322,14 +324,10 @@ val coreLibProjects = listOfNotNull(
|
||||
|
||||
val gradlePluginProjects = listOf(
|
||||
":kotlin-gradle-plugin",
|
||||
":kotlin-gradle-plugin:plugin-marker",
|
||||
":kotlin-gradle-plugin-api",
|
||||
// ":kotlin-gradle-plugin-integration-tests", // TODO: build fails
|
||||
":kotlin-allopen",
|
||||
":kotlin-allopen:plugin-marker",
|
||||
":kotlin-annotation-processing-gradle",
|
||||
":kotlin-noarg",
|
||||
":kotlin-noarg:plugin-marker",
|
||||
":kotlin-sam-with-receiver"
|
||||
)
|
||||
|
||||
@@ -359,7 +357,14 @@ val ignoreTestFailures by extra(project.kotlinBuildProperties.ignoreTestFailures
|
||||
|
||||
allprojects {
|
||||
|
||||
configurations.maybeCreate("embedded")
|
||||
configurations.maybeCreate("embedded").apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
|
||||
jvmTarget = defaultJvmTarget
|
||||
javaHome = defaultJavaHome
|
||||
@@ -608,7 +613,6 @@ tasks {
|
||||
":compiler:fir:raw-fir:light-tree2fir:test",
|
||||
":compiler:fir:analysis-tests:test",
|
||||
":compiler:fir:fir2ir:test",
|
||||
":idea:idea-fir:test",
|
||||
":plugins:fir:fir-plugin-prototype:test"
|
||||
)
|
||||
}
|
||||
@@ -705,8 +709,7 @@ tasks {
|
||||
":idea:jvm-debugger:jvm-debugger-evaluation:test",
|
||||
":idea:jvm-debugger:jvm-debugger-sequence:test",
|
||||
":idea:jvm-debugger:eval4j:test",
|
||||
":idea:scripting-support:test",
|
||||
":idea:idea-fir:test"
|
||||
":idea:scripting-support:test"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -800,7 +803,8 @@ tasks {
|
||||
":kotlin-stdlib:publish",
|
||||
":kotlin-stdlib-jdk7:publish",
|
||||
":kotlin-stdlib-jdk8:publish",
|
||||
":kotlin-reflect:publish"
|
||||
":kotlin-reflect:publish",
|
||||
":kotlin-main-kts:publish"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1043,3 +1047,15 @@ val Jar.outputFile: File
|
||||
|
||||
val Project.sourceSetsOrNull: SourceSetContainer?
|
||||
get() = convention.findPlugin(JavaPluginConvention::class.java)?.sourceSets
|
||||
|
||||
val disableVerificationTasks = System.getProperty("disable.verification.tasks") == "true"
|
||||
if (disableVerificationTasks) {
|
||||
gradle.taskGraph.whenReady {
|
||||
allTasks.forEach {
|
||||
if (it is VerificationTask) {
|
||||
logger.info("DISABLED: '$it'")
|
||||
it.enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,7 @@ repositories {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib", embeddedKotlinVersion))
|
||||
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.17")
|
||||
implementation("com.gradle.publish:plugin-publish-plugin:0.11.0")
|
||||
|
||||
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
|
||||
implementation("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
|
||||
@@ -105,7 +106,7 @@ dependencies {
|
||||
|
||||
implementation("com.github.jengelman.gradle.plugins:shadow:${rootProject.extra["versions.shadow"]}")
|
||||
implementation("net.sf.proguard:proguard-gradle:6.2.2")
|
||||
implementation("org.jetbrains.intellij.deps:asm-all:7.0.1")
|
||||
implementation("org.jetbrains.intellij.deps:asm-all:8.0.1")
|
||||
|
||||
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")
|
||||
}
|
||||
|
||||
@@ -6,16 +6,28 @@ import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.ConfigurablePublishArtifact
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import org.gradle.api.artifacts.PublishArtifact
|
||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.attributes.Bundling
|
||||
import org.gradle.api.attributes.Category
|
||||
import org.gradle.api.attributes.LibraryElements
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.component.AdhocComponentWithVariants
|
||||
import org.gradle.api.file.DuplicatesStrategy
|
||||
import org.gradle.api.plugins.BasePluginConvention
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.plugins.JavaPlugin.*
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.tasks.GenerateModuleMetadata
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.Upload
|
||||
import org.gradle.api.tasks.javadoc.Javadoc
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import plugins.KotlinBuildPublishingPlugin
|
||||
|
||||
|
||||
private const val MAGIC_DO_NOT_CHANGE_TEST_JAR_TASK_NAME = "testJar"
|
||||
@@ -28,7 +40,7 @@ fun Project.testsJar(body: Jar.() -> Unit = {}): Jar {
|
||||
pluginManager.withPlugin("java") {
|
||||
from(testSourceSet.output)
|
||||
}
|
||||
classifier = "tests"
|
||||
archiveClassifier.set("tests")
|
||||
body()
|
||||
project.addArtifact(testsJarCfg, this, this)
|
||||
}
|
||||
@@ -58,20 +70,26 @@ fun Project.noDefaultJar() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.runtimeJarArtifactBy(task: Task, artifactRef: Any, body: ConfigurablePublishArtifact.() -> Unit = {}) {
|
||||
fun <T : Task> Project.runtimeJarArtifactBy(
|
||||
task: TaskProvider<T>,
|
||||
artifactRef: Any,
|
||||
body: ConfigurablePublishArtifact.() -> Unit = {}
|
||||
) {
|
||||
addArtifact("archives", task, artifactRef, body)
|
||||
addArtifact("runtimeJar", task, artifactRef, body)
|
||||
configurations.findByName("runtime")?.let {
|
||||
addArtifact(it, task, artifactRef, body)
|
||||
addArtifact(it.name, task, artifactRef, body)
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.runtimeJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> = runtimeJar(getOrCreateTask("jar", body), { })
|
||||
fun Project.runtimeJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> = runtimeJar(getOrCreateTask("jar", body)) { }
|
||||
|
||||
fun <T : Jar> Project.runtimeJar(task: TaskProvider<T>, body: T.() -> Unit = {}): TaskProvider<T> {
|
||||
|
||||
tasks.named<Jar>("jar").configure {
|
||||
removeArtifacts(configurations.getOrCreate("archives"), this)
|
||||
}
|
||||
|
||||
task.configure {
|
||||
configurations.findByName("embedded")?.let { embedded ->
|
||||
dependsOn(embedded)
|
||||
@@ -80,15 +98,37 @@ fun <T : Jar> Project.runtimeJar(task: TaskProvider<T>, body: T.() -> Unit = {})
|
||||
}
|
||||
}
|
||||
setupPublicJar(project.the<BasePluginConvention>().archivesBaseName)
|
||||
setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE)
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
body()
|
||||
project.runtimeJarArtifactBy(this, this)
|
||||
}
|
||||
|
||||
project.runtimeJarArtifactBy(task, task)
|
||||
|
||||
val runtimeJar = configurations.maybeCreate("runtimeJar").apply {
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
attributes {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
|
||||
configurePublishedComponent {
|
||||
withVariantsFromConfiguration(configurations[RUNTIME_ELEMENTS_CONFIGURATION_NAME]) { skip() }
|
||||
addVariantsFromConfiguration(runtimeJar) { }
|
||||
}
|
||||
|
||||
return task
|
||||
}
|
||||
|
||||
fun Project.sourcesJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
|
||||
val task = tasks.register<Jar>("sourcesJar") {
|
||||
configure<JavaPluginExtension> {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
val sourcesJar = getOrCreateTask<Jar>("sourcesJar") {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveClassifier.set("sources")
|
||||
|
||||
@@ -112,13 +152,21 @@ fun Project.sourcesJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
|
||||
body()
|
||||
}
|
||||
|
||||
addArtifact("archives", task)
|
||||
addArtifact("sources", task)
|
||||
addArtifact("archives", sourcesJar)
|
||||
addArtifact("sources", sourcesJar)
|
||||
|
||||
return task
|
||||
configurePublishedComponent {
|
||||
addVariantsFromConfiguration(configurations[SOURCES_ELEMENTS_CONFIGURATION_NAME]) { }
|
||||
}
|
||||
|
||||
return sourcesJar
|
||||
}
|
||||
|
||||
fun Project.javadocJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
|
||||
configure<JavaPluginExtension> {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
val javadocTask = getOrCreateTask<Jar>("javadocJar") {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveClassifier.set("javadoc")
|
||||
@@ -130,9 +178,40 @@ fun Project.javadocJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
|
||||
}
|
||||
|
||||
addArtifact("archives", javadocTask)
|
||||
|
||||
configurePublishedComponent {
|
||||
addVariantsFromConfiguration(configurations[JAVADOC_ELEMENTS_CONFIGURATION_NAME]) { }
|
||||
}
|
||||
|
||||
return javadocTask
|
||||
}
|
||||
|
||||
fun Project.modularJar(body: Jar.() -> Unit): TaskProvider<Jar> {
|
||||
val modularJar = configurations.maybeCreate("modularJar").apply {
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named("modular-jar"))
|
||||
}
|
||||
}
|
||||
|
||||
val modularJarTask = getOrCreateTask<Jar>("modularJar") {
|
||||
archiveClassifier.set("modular")
|
||||
|
||||
body()
|
||||
}
|
||||
|
||||
addArtifact("modularJar", modularJarTask)
|
||||
addArtifact("archives", modularJarTask)
|
||||
|
||||
configurePublishedComponent {
|
||||
addVariantsFromConfiguration(modularJar) { mapToMavenScope("runtime") }
|
||||
}
|
||||
|
||||
return modularJarTask
|
||||
}
|
||||
|
||||
|
||||
fun Project.standardPublicJars() {
|
||||
runtimeJar()
|
||||
@@ -140,7 +219,22 @@ fun Project.standardPublicJars() {
|
||||
javadocJar()
|
||||
}
|
||||
|
||||
fun Project.publish(body: Upload.() -> Unit = {}): Upload {
|
||||
fun Project.publish(moduleMetadata: Boolean = false, configure: MavenPublication.() -> Unit = { }) {
|
||||
apply<KotlinBuildPublishingPlugin>()
|
||||
|
||||
if (!moduleMetadata) {
|
||||
tasks.withType<GenerateModuleMetadata> {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
val publication = extensions.findByType<PublishingExtension>()
|
||||
?.publications
|
||||
?.findByName(KotlinBuildPublishingPlugin.PUBLICATION_NAME) as MavenPublication
|
||||
publication.configure()
|
||||
}
|
||||
|
||||
fun Project.publishWithLegacyMavenPlugin(body: Upload.() -> Unit = {}): Upload {
|
||||
apply<plugins.PublishedKotlinModule>()
|
||||
|
||||
if (artifactsRemovedDiagnosticFlag) {
|
||||
@@ -236,8 +330,8 @@ fun ConfigurationContainer.getOrCreate(name: String): Configuration = findByName
|
||||
|
||||
fun Jar.setupPublicJar(baseName: String, classifier: String = "") {
|
||||
val buildNumber = project.rootProject.extra["buildNumber"] as String
|
||||
this.baseName = baseName
|
||||
this.classifier = classifier
|
||||
this.archiveBaseName.set(baseName)
|
||||
this.archiveClassifier.set(classifier)
|
||||
manifest.attributes.apply {
|
||||
put("Implementation-Vendor", "JetBrains")
|
||||
put("Implementation-Title", baseName)
|
||||
@@ -256,9 +350,26 @@ fun Project.addArtifact(configuration: Configuration, task: Task, artifactRef: A
|
||||
fun Project.addArtifact(configurationName: String, task: Task, artifactRef: Any, body: ConfigurablePublishArtifact.() -> Unit = {}) =
|
||||
addArtifact(configurations.getOrCreate(configurationName), task, artifactRef, body)
|
||||
|
||||
fun <T : Task> Project.addArtifact(configurationName: String, task: TaskProvider<T>, body: ConfigurablePublishArtifact.() -> Unit = {}) {
|
||||
fun <T : Task> Project.addArtifact(
|
||||
configurationName: String,
|
||||
task: TaskProvider<T>,
|
||||
body: ConfigurablePublishArtifact.() -> Unit = {}
|
||||
): PublishArtifact {
|
||||
configurations.maybeCreate(configurationName)
|
||||
artifacts.add(configurationName, task, body)
|
||||
return artifacts.add(configurationName, task, body)
|
||||
}
|
||||
|
||||
fun <T : Task> Project.addArtifact(
|
||||
configurationName: String,
|
||||
task: TaskProvider<T>,
|
||||
artifactRef: Any,
|
||||
body: ConfigurablePublishArtifact.() -> Unit = {}
|
||||
): PublishArtifact {
|
||||
configurations.maybeCreate(configurationName)
|
||||
return artifacts.add(configurationName, artifactRef) {
|
||||
builtBy(task)
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.cleanArtifacts() {
|
||||
@@ -268,3 +379,6 @@ fun Project.cleanArtifacts() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configurePublishedComponent(configure: AdhocComponentWithVariants.() -> Unit) =
|
||||
(components.findByName(KotlinBuildPublishingPlugin.ADHOC_COMPONENT_NAME) as AdhocComponentWithVariants?)?.apply(configure)
|
||||
|
||||
68
buildSrc/src/main/kotlin/pluginMarkers.kt
Normal file
68
buildSrc/src/main/kotlin/pluginMarkers.kt
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import com.gradle.publish.PluginBundleExtension
|
||||
import com.gradle.publish.PluginConfig
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.publish.PublicationContainer
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import plugins.KotlinBuildPublishingPlugin
|
||||
|
||||
internal const val PLUGIN_MARKER_SUFFIX = ".gradle.plugin"
|
||||
|
||||
fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
|
||||
val pluginDevelopment = extensions.getByType<PluginBundleExtension>()
|
||||
val publishingExtension = extensions.getByType<PublishingExtension>()
|
||||
val mainPublication = publishingExtension.publications[KotlinBuildPublishingPlugin.PUBLICATION_NAME] as MavenPublication
|
||||
|
||||
pluginDevelopment.plugins.forEach { declaration ->
|
||||
val markerPublication = createMavenMarkerPublication(declaration, mainPublication, publishingExtension.publications)
|
||||
if (withEmptyJars) {
|
||||
addEmptyJarArtifacts(markerPublication)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.addEmptyJarArtifacts(publication: MavenPublication) {
|
||||
val emptyJar = getOrCreateTask<Jar>("emptyJar") {
|
||||
archiveBaseName.set("empty")
|
||||
}
|
||||
|
||||
publication.artifact(emptyJar.get()) { }
|
||||
publication.artifact(emptyJar.get()) { classifier = "sources" }
|
||||
publication.artifact(emptyJar.get()) { classifier = "javadoc" }
|
||||
}
|
||||
|
||||
// Based on code from `java-gradle-plugin`
|
||||
// https://github.com/gradle/gradle/blob/v6.4.0/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/MavenPluginPublishPlugin.java#L84
|
||||
private fun createMavenMarkerPublication(
|
||||
declaration: PluginConfig,
|
||||
coordinates: MavenPublication,
|
||||
publications: PublicationContainer
|
||||
): MavenPublication {
|
||||
return publications.create<MavenPublication>(declaration.name.toString() + "PluginMarkerMaven") {
|
||||
val pluginId: String = declaration.id
|
||||
artifactId = pluginId + PLUGIN_MARKER_SUFFIX
|
||||
groupId = pluginId
|
||||
pom.withXml {
|
||||
val root = asElement()
|
||||
val document = root.ownerDocument
|
||||
val dependencies = root.appendChild(document.createElement("dependencies"))
|
||||
val dependency = dependencies.appendChild(document.createElement("dependency"))
|
||||
val groupId = dependency.appendChild(document.createElement("groupId"))
|
||||
groupId.textContent = coordinates.groupId
|
||||
val artifactId = dependency.appendChild(document.createElement("artifactId"))
|
||||
artifactId.textContent = coordinates.artifactId
|
||||
val version = dependency.appendChild(document.createElement("version"))
|
||||
version.textContent = coordinates.version
|
||||
}
|
||||
|
||||
pom.name.set(declaration.displayName)
|
||||
pom.description.set(declaration.description)
|
||||
}
|
||||
}
|
||||
155
buildSrc/src/main/kotlin/plugins/KotlinBuildPublishingPlugin.kt
Normal file
155
buildSrc/src/main/kotlin/plugins/KotlinBuildPublishingPlugin.kt
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package plugins
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.component.AdhocComponentWithVariants
|
||||
import org.gradle.api.component.SoftwareComponentFactory
|
||||
import org.gradle.api.plugins.JavaBasePlugin
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
|
||||
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.plugins.signing.SigningExtension
|
||||
import org.gradle.plugins.signing.SigningPlugin
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class KotlinBuildPublishingPlugin @Inject constructor(
|
||||
private val componentFactory: SoftwareComponentFactory
|
||||
) : Plugin<Project> {
|
||||
override fun apply(target: Project): Unit = with(target) {
|
||||
apply<MavenPublishPlugin>()
|
||||
apply<SigningPlugin>()
|
||||
|
||||
val publishedRuntime = configurations.maybeCreate(RUNTIME_CONFIGURATION).apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
}
|
||||
}
|
||||
|
||||
val publishedCompile = configurations.maybeCreate(COMPILE_CONFIGURATION).apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_API))
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinLibraryComponent = componentFactory.adhoc(ADHOC_COMPONENT_NAME) as AdhocComponentWithVariants
|
||||
components.add(kotlinLibraryComponent)
|
||||
kotlinLibraryComponent.addVariantsFromConfiguration(publishedCompile) { mapToMavenScope("compile") }
|
||||
kotlinLibraryComponent.addVariantsFromConfiguration(publishedRuntime) { mapToMavenScope("runtime") }
|
||||
|
||||
pluginManager.withPlugin("java-base") {
|
||||
val runtimeElements by configurations
|
||||
val apiElements by configurations
|
||||
|
||||
publishedRuntime.extendsFrom(runtimeElements)
|
||||
publishedCompile.extendsFrom(apiElements)
|
||||
|
||||
kotlinLibraryComponent.addVariantsFromConfiguration(runtimeElements) {
|
||||
mapToMavenScope("runtime")
|
||||
|
||||
if (configurationVariant.artifacts.any { JavaBasePlugin.UNPUBLISHABLE_VARIANT_ARTIFACTS.contains(it.type) }) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configure<PublishingExtension> {
|
||||
publications {
|
||||
create<MavenPublication>(PUBLICATION_NAME) {
|
||||
from(kotlinLibraryComponent)
|
||||
|
||||
pom {
|
||||
packaging = "jar"
|
||||
name.set(humanReadableName(project))
|
||||
description.set(project.description ?: humanReadableName(project))
|
||||
url.set("https://kotlinlang.org/")
|
||||
licenses {
|
||||
license {
|
||||
name.set("The Apache License, Version 2.0")
|
||||
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url.set("https://github.com/JetBrains/kotlin")
|
||||
connection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
developerConnection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
name.set("Kotlin Team")
|
||||
organization.set("JetBrains")
|
||||
organizationUrl.set("https://www.jetbrains.com")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = REPOSITORY_NAME
|
||||
url = file("${project.rootDir}/build/repo").toURI()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configure<SigningExtension> {
|
||||
setRequired(provider {
|
||||
project.findProperty("signingRequired")?.toString()?.toBoolean()
|
||||
?: project.property("isSonatypeRelease") as Boolean
|
||||
})
|
||||
|
||||
sign(extensions.getByType<PublishingExtension>().publications[PUBLICATION_NAME])
|
||||
}
|
||||
|
||||
tasks.register("install") {
|
||||
dependsOn(tasks.named("publishToMavenLocal"))
|
||||
}
|
||||
|
||||
tasks.named<PublishToMavenRepository>("publish${PUBLICATION_NAME}PublicationTo${REPOSITORY_NAME}Repository") {
|
||||
dependsOn(project.rootProject.tasks.named("preparePublication"))
|
||||
doFirst {
|
||||
val preparePublication = project.rootProject.tasks.named("preparePublication").get()
|
||||
val username: String? by preparePublication.extra
|
||||
val password: String? by preparePublication.extra
|
||||
val repoUrl: String by preparePublication.extra
|
||||
|
||||
repository.apply {
|
||||
url = uri(repoUrl)
|
||||
if (url.scheme != "file" && username != null && password != null) {
|
||||
credentials {
|
||||
this.username = username
|
||||
this.password = password
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PUBLICATION_NAME = "Main"
|
||||
const val REPOSITORY_NAME = "Maven"
|
||||
const val ADHOC_COMPONENT_NAME = "kotlinLibrary"
|
||||
|
||||
const val COMPILE_CONFIGURATION = "publishedCompile"
|
||||
const val RUNTIME_CONFIGURATION = "publishedRuntime"
|
||||
|
||||
@UseExperimental(ExperimentalStdlibApi::class)
|
||||
fun humanReadableName(project: Project) =
|
||||
project.name.split("-").joinToString(separator = " ") { it.capitalize(Locale.ROOT) }
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,18 @@ open class PublishedKotlinModule : Plugin<Project> {
|
||||
|
||||
plugins.apply("maven")
|
||||
|
||||
val publishedRuntime by configurations.creating {
|
||||
configurations.maybeCreate("publishedRuntime").apply {
|
||||
the<MavenPluginConvention>()
|
||||
.conf2ScopeMappings
|
||||
.addMapping(0, this, Conf2ScopeMappingContainer.RUNTIME)
|
||||
}
|
||||
|
||||
configurations.maybeCreate("publishedCompile").apply {
|
||||
the<MavenPluginConvention>()
|
||||
.conf2ScopeMappings
|
||||
.addMapping(0, this, Conf2ScopeMappingContainer.COMPILE)
|
||||
}
|
||||
|
||||
if (!project.hasProperty("prebuiltJar")) {
|
||||
plugins.apply("signing")
|
||||
|
||||
|
||||
@@ -23,3 +23,15 @@ fun DependencyHandler.publishedRuntime(
|
||||
): ExternalModuleDependency =
|
||||
addDependencyTo(this, "publishedRuntime", dependencyNotation, dependencyConfiguration)
|
||||
|
||||
|
||||
val NamedDomainObjectContainer<Configuration>.publishedCompile: NamedDomainObjectProvider<Configuration> get() = named("publishedCompile")
|
||||
|
||||
fun DependencyHandler.publishedCompile(dependencyNotation: Any): Dependency? =
|
||||
add("publishedCompile", dependencyNotation)
|
||||
|
||||
fun DependencyHandler.publishedCompile(
|
||||
dependencyNotation: String,
|
||||
dependencyConfiguration: Action<ExternalModuleDependency>
|
||||
): ExternalModuleDependency =
|
||||
addDependencyTo(this, "publishedCompile", dependencyNotation, dependencyConfiguration)
|
||||
|
||||
|
||||
@@ -79,21 +79,20 @@ fun Project.projectTest(
|
||||
}
|
||||
}
|
||||
|
||||
doFirst {
|
||||
val agent = tasks.findByPath(":test-instrumenter:jar")!!.outputs.files.singleFile
|
||||
|
||||
val args = project.findProperty("kotlin.test.instrumentation.args")?.let { "=$it" }.orEmpty()
|
||||
|
||||
jvmArgs("-javaagent:$agent$args")
|
||||
if (project.findProperty("kotlin.test.instrumentation.disable")?.toString()?.toBoolean() != true) {
|
||||
doFirst {
|
||||
val agent = tasks.findByPath(":test-instrumenter:jar")!!.outputs.files.singleFile
|
||||
val args = project.findProperty("kotlin.test.instrumentation.args")?.let { "=$it" }.orEmpty()
|
||||
jvmArgs("-javaagent:$agent$args")
|
||||
}
|
||||
dependsOn(":test-instrumenter:jar")
|
||||
}
|
||||
|
||||
dependsOn(":test-instrumenter:jar")
|
||||
|
||||
jvmArgs(
|
||||
"-ea",
|
||||
"-XX:+HeapDumpOnOutOfMemoryError",
|
||||
"-XX:+UseCodeCacheFlushing",
|
||||
"-XX:ReservedCodeCacheSize=128m",
|
||||
"-XX:ReservedCodeCacheSize=256m",
|
||||
"-Djna.nosys=true"
|
||||
)
|
||||
|
||||
@@ -108,6 +107,10 @@ fun Project.projectTest(
|
||||
systemProperty("kotlin.ni", if (rootProject.hasProperty("newInferenceTests")) "true" else "false")
|
||||
systemProperty("org.jetbrains.kotlin.skip.muted.tests", if (rootProject.hasProperty("skipMutedTests")) "true" else "false")
|
||||
|
||||
if (Platform[202].orHigher()) {
|
||||
systemProperty("idea.ignore.disabled.plugins", "true")
|
||||
}
|
||||
|
||||
var subProjectTempRoot: Path? = null
|
||||
doFirst {
|
||||
val teamcity = rootProject.findProperty("teamcity") as? Map<Any?, *>
|
||||
|
||||
@@ -29,9 +29,12 @@ dependencies {
|
||||
testCompile(intellijDep()) { includeJars("openapi", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", "groovy-all", rootProject = rootProject) }
|
||||
Platform[191].orLower {
|
||||
testCompile(intellijDep()) { includeJars("jps-builders") }
|
||||
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", rootProject = rootProject) }
|
||||
Platform[202].orHigher {
|
||||
testCompile(intellijDep()) { includeJars("groovy", rootProject = rootProject) }
|
||||
}
|
||||
Platform[201].orLower {
|
||||
testCompile(intellijDep()) { includeJars("groovy-all", rootProject = rootProject) }
|
||||
}
|
||||
Platform[192].orHigher {
|
||||
testCompile(intellijPluginDep("java")) { includeJars("jps-builders") }
|
||||
|
||||
@@ -93,20 +93,18 @@ object CodegenUtil {
|
||||
private fun mapMembers(
|
||||
inherited: CallableMemberDescriptor,
|
||||
traitMember: CallableMemberDescriptor
|
||||
): LinkedHashMap<FunctionDescriptor, FunctionDescriptor> {
|
||||
val result = linkedMapOf<FunctionDescriptor, FunctionDescriptor>()
|
||||
if (traitMember is SimpleFunctionDescriptor) {
|
||||
result[traitMember] = inherited as FunctionDescriptor
|
||||
} else if (traitMember is PropertyDescriptor) {
|
||||
): Map<FunctionDescriptor, FunctionDescriptor> = when (traitMember) {
|
||||
is SimpleFunctionDescriptor -> mapOf(traitMember to inherited as FunctionDescriptor)
|
||||
is PropertyDescriptor -> linkedMapOf<FunctionDescriptor, FunctionDescriptor>().also { result ->
|
||||
for (traitAccessor in traitMember.accessors) {
|
||||
for (inheritedAccessor in (inherited as PropertyDescriptor).accessors) {
|
||||
if (inheritedAccessor::class.java == traitAccessor::class.java) { // same accessor kind
|
||||
result.put(traitAccessor, inheritedAccessor)
|
||||
if ((inheritedAccessor is PropertyGetterDescriptor) == (traitAccessor is PropertyGetterDescriptor)) {
|
||||
result[traitAccessor] = inheritedAccessor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
else -> error("Unexpected member: $inherited")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
|
||||
@@ -219,21 +220,32 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
protected void generateDelegatesToDefaultImpl() {
|
||||
if (isJvmInterface(descriptor)) return;
|
||||
|
||||
boolean isErasedInlineClass = InlineClassesUtilsKt.isInlineClass(descriptor) && kind == OwnerKind.ERASED_INLINE_CLASS;
|
||||
JvmKotlinType receiverType = new JvmKotlinType(typeMapper.mapType(descriptor), descriptor.getDefaultType());
|
||||
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||
FunctionDescriptor interfaceFun = entry.getKey();
|
||||
//skip java 8 default methods
|
||||
if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) &&
|
||||
!JvmAnnotationUtilKt.isCallableMemberCompiledToJvmDefault(
|
||||
DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(interfaceFun), state.getJvmDefaultMode()
|
||||
)
|
||||
) {
|
||||
generateDelegationToDefaultImpl(interfaceFun, entry.getValue());
|
||||
}
|
||||
generateDelegationToDefaultImpl(entry.getKey(), entry.getValue(), receiverType, functionCodegen, state, isErasedInlineClass);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDelegationToDefaultImpl(@NotNull FunctionDescriptor interfaceFun, @NotNull FunctionDescriptor inheritedFun) {
|
||||
public static void generateDelegationToDefaultImpl(
|
||||
@NotNull FunctionDescriptor interfaceFun,
|
||||
@NotNull FunctionDescriptor inheritedFun,
|
||||
@NotNull JvmKotlinType receiverType,
|
||||
@NotNull FunctionCodegen functionCodegen,
|
||||
@NotNull GenerationState state,
|
||||
boolean isErasedInlineClass
|
||||
) {
|
||||
// Skip Java 8 default methods
|
||||
if (CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) ||
|
||||
JvmAnnotationUtilKt.isCallableMemberCompiledToJvmDefault(
|
||||
DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(interfaceFun), state.getJvmDefaultMode()
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotlinTypeMapper typeMapper = state.getTypeMapper();
|
||||
functionCodegen.generateMethod(
|
||||
new JvmDeclarationOrigin(
|
||||
CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL, descriptorToDeclaration(interfaceFun), interfaceFun, null
|
||||
@@ -248,7 +260,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
DeclarationDescriptor declarationInheritedFun = inheritedFun.getContainingDeclaration();
|
||||
PsiElement classForInheritedFun = descriptorToDeclaration(declarationInheritedFun);
|
||||
if (classForInheritedFun instanceof KtDeclaration) {
|
||||
codegen.markLineNumber((KtElement) classForInheritedFun, false);
|
||||
codegen.markLineNumber(classForInheritedFun, false);
|
||||
}
|
||||
|
||||
ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration;
|
||||
@@ -282,18 +294,15 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
InstructionAdapter iv = codegen.v;
|
||||
Type[] myArgTypes = signature.getAsmMethod().getArgumentTypes();
|
||||
Type[] toArgTypes = defaultImplsMethod.getArgumentTypes();
|
||||
boolean isErasedInlineClass =
|
||||
InlineClassesUtilsKt.isInlineClass(descriptor) && kind == OwnerKind.ERASED_INLINE_CLASS;
|
||||
|
||||
int myArgI = 0;
|
||||
int argVar = 0;
|
||||
|
||||
Type receiverType = typeMapper.mapType(descriptor);
|
||||
KotlinType interfaceKotlinType = ((ClassDescriptor) inheritedFun.getContainingDeclaration()).getDefaultType();
|
||||
StackValue.local(argVar, receiverType, descriptor.getDefaultType())
|
||||
StackValue.local(argVar, receiverType.getType(), receiverType.getKotlinType())
|
||||
.put(OBJECT_TYPE, interfaceKotlinType, iv);
|
||||
if (isErasedInlineClass) myArgI++;
|
||||
argVar += receiverType.getSize();
|
||||
argVar += receiverType.getType().getSize();
|
||||
|
||||
int toArgI = 1;
|
||||
|
||||
|
||||
@@ -185,6 +185,12 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
generateBridges();
|
||||
generateClosureBody();
|
||||
|
||||
if (samType != null) {
|
||||
SamWrapperCodegen.generateDelegatesToDefaultImpl(
|
||||
asmType, classDescriptor, samType.getClassDescriptor(), functionCodegen, state
|
||||
);
|
||||
}
|
||||
|
||||
this.constructor = generateConstructor();
|
||||
|
||||
if (isConst(closure)) {
|
||||
|
||||
@@ -52,7 +52,6 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -77,6 +76,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
@@ -1585,7 +1585,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
assert topOfStack == tryWithFinallyBlockStackElement : "Top element of stack doesn't equals processing finally block";
|
||||
|
||||
KtTryExpression jetTryExpression = tryWithFinallyBlockStackElement.expression;
|
||||
Label finallyStart = new Label();
|
||||
Label finallyStart = linkedLabel();
|
||||
v.mark(finallyStart);
|
||||
tryWithFinallyBlockStackElement.addGapLabel(finallyStart);
|
||||
addGapLabelsForNestedTryCatchWithoutFinally(state, nestedTryBlocksWithoutFinally, finallyStart);
|
||||
|
||||
@@ -70,7 +70,6 @@ import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.generateBridgeForMainFunctionIfNecessary;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
||||
@@ -1064,18 +1063,6 @@ public class FunctionCodegen {
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) {
|
||||
String name = descriptor.getName().asString();
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
|
||||
if (parameters.isEmpty()) {
|
||||
return name.equals("hashCode") || name.equals("toString");
|
||||
}
|
||||
else if (parameters.size() == 1 && name.equals("equals")) {
|
||||
return isNullableAny(parameters.get(0).getType());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull KotlinTypeMapper typeMapper) {
|
||||
return ArrayUtil.toStringArray(CollectionsKt.map(
|
||||
|
||||
@@ -422,14 +422,6 @@ public class PropertyCodegen {
|
||||
}
|
||||
modifiers |= getVisibilityForBackingField(propertyDescriptor, isDelegate);
|
||||
|
||||
// If val is initialized in EXACTLY_ONCE closure, other class from the same package initializes it
|
||||
// so, its visibility should be package private and not final
|
||||
if (!propertyDescriptor.isVar() &&
|
||||
bindingContext.get(BindingContext.FIELD_CAPTURED_IN_EXACLY_ONCE_CLOSURE, propertyDescriptor) != null
|
||||
) {
|
||||
modifiers &= ~(ACC_PRIVATE | ACC_FINAL);
|
||||
}
|
||||
|
||||
if (AsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) {
|
||||
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
|
||||
parentBodyCodegen.addCompanionObjectPropertyToCopy(propertyDescriptor, defaultValue);
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils;
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConversionResolverImplKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.KotlinTypeKt;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
|
||||
public class SamType {
|
||||
@@ -46,6 +47,10 @@ public class SamType {
|
||||
originalSingleArgumentType = valueParameter.getOriginal().getType();
|
||||
}
|
||||
|
||||
if (KotlinTypeKt.isError(singleArgumentType) || KotlinTypeKt.isError(originalSingleArgumentType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
KotlinType originalTypeToUse =
|
||||
// This can be true in case when the value parameter is in the method of a generic type with out-projection.
|
||||
// We approximate Inv<Captured#1> to Nothing, while Inv itself can be a SAM interface safe to call here
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
@@ -42,6 +44,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
@@ -87,7 +90,7 @@ public class SamWrapperCodegen {
|
||||
|
||||
boolean isKotlinFunInterface = !(samType.getClassDescriptor() instanceof JavaClassDescriptor);
|
||||
|
||||
ClassDescriptor classDescriptor = new ClassDescriptorImpl(
|
||||
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
|
||||
samType.getClassDescriptor().getContainingDeclaration(),
|
||||
fqName.shortName(),
|
||||
Modality.FINAL,
|
||||
@@ -97,6 +100,8 @@ public class SamWrapperCodegen {
|
||||
/* isExternal = */ false,
|
||||
LockBasedStorageManager.NO_LOCKS
|
||||
);
|
||||
classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.emptySet(), null);
|
||||
|
||||
// e.g. compare(T, T)
|
||||
SimpleFunctionDescriptor erasedInterfaceFunction = samType.getOriginalAbstractMethod().copy(
|
||||
classDescriptor,
|
||||
@@ -135,12 +140,17 @@ public class SamWrapperCodegen {
|
||||
null);
|
||||
|
||||
generateConstructor(asmType, functionAsmType, cv);
|
||||
generateMethod(asmType, functionAsmType, cv, erasedInterfaceFunction, functionType);
|
||||
|
||||
ClassContext context = state.getRootContext().intoClass(classDescriptor, OwnerKind.IMPLEMENTATION, state);
|
||||
FunctionCodegen functionCodegen = new FunctionCodegen(context, cv, state, parentCodegen);
|
||||
generateMethod(asmType, functionAsmType, erasedInterfaceFunction, functionType, functionCodegen);
|
||||
|
||||
if (isKotlinFunInterface) {
|
||||
generateGetFunctionDelegate(cv, asmType, functionAsmType);
|
||||
generateEquals(cv, asmType, functionAsmType, samAsmType);
|
||||
generateHashCode(cv, asmType, functionAsmType);
|
||||
|
||||
generateDelegatesToDefaultImpl(asmType, classDescriptor, samType.getClassDescriptor(), functionCodegen, state);
|
||||
}
|
||||
|
||||
cv.done();
|
||||
@@ -171,25 +181,22 @@ public class SamWrapperCodegen {
|
||||
}
|
||||
|
||||
private void generateMethod(
|
||||
Type ownerType,
|
||||
Type functionType,
|
||||
ClassBuilder cv,
|
||||
SimpleFunctionDescriptor erasedInterfaceFunction,
|
||||
KotlinType functionJetType
|
||||
@NotNull Type ownerType,
|
||||
@NotNull Type functionType,
|
||||
@NotNull SimpleFunctionDescriptor erasedInterfaceFunction,
|
||||
@NotNull KotlinType functionKotlinType,
|
||||
@NotNull FunctionCodegen functionCodegen
|
||||
) {
|
||||
// using root context to avoid creating ClassDescriptor and everything else
|
||||
FunctionCodegen codegen = new FunctionCodegen(state.getRootContext().intoClass(
|
||||
(ClassDescriptor) erasedInterfaceFunction.getContainingDeclaration(), OwnerKind.IMPLEMENTATION, state), cv, state, parentCodegen);
|
||||
|
||||
FunctionDescriptor invokeFunction =
|
||||
functionJetType.getMemberScope().getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).iterator().next().getOriginal();
|
||||
FunctionDescriptor invokeFunction = functionKotlinType.getMemberScope().getContributedFunctions(
|
||||
OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND
|
||||
).iterator().next().getOriginal();
|
||||
StackValue functionField = StackValue.field(functionType, ownerType, FUNCTION_FIELD_NAME, false, StackValue.none());
|
||||
codegen.genSamDelegate(erasedInterfaceFunction, invokeFunction, functionField);
|
||||
functionCodegen.genSamDelegate(erasedInterfaceFunction, invokeFunction, functionField);
|
||||
|
||||
// generate sam bridges
|
||||
// TODO: erasedInterfaceFunction is actually not an interface function, but function in generated class
|
||||
SimpleFunctionDescriptor originalInterfaceErased = samType.getOriginalAbstractMethod();
|
||||
ClosureCodegen.generateBridgesForSAM(originalInterfaceErased, erasedInterfaceFunction, codegen);
|
||||
ClosureCodegen.generateBridgesForSAM(originalInterfaceErased, erasedInterfaceFunction, functionCodegen);
|
||||
}
|
||||
|
||||
private static void generateEquals(
|
||||
@@ -248,6 +255,31 @@ public class SamWrapperCodegen {
|
||||
FunctionCodegen.endVisit(iv, "getFunctionDelegate of SAM wrapper");
|
||||
}
|
||||
|
||||
public static void generateDelegatesToDefaultImpl(
|
||||
@NotNull Type asmType,
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull ClassDescriptor funInterface,
|
||||
@NotNull FunctionCodegen functionCodegen,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
JvmKotlinType receiverType = new JvmKotlinType(asmType, classDescriptor.getDefaultType());
|
||||
|
||||
for (DeclarationDescriptor descriptor : DescriptorUtils.getAllDescriptors(funInterface.getDefaultType().getMemberScope())) {
|
||||
if (!(descriptor instanceof CallableMemberDescriptor)) continue;
|
||||
CallableMemberDescriptor member = (CallableMemberDescriptor) descriptor;
|
||||
if (member.getModality() == Modality.ABSTRACT ||
|
||||
Visibilities.isPrivate(member.getVisibility()) ||
|
||||
member.getVisibility() == Visibilities.INVISIBLE_FAKE ||
|
||||
DescriptorUtils.isMethodOfAny(member)) continue;
|
||||
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.INSTANCE.copyFunctions(
|
||||
member, member, classDescriptor, Modality.OPEN, Visibilities.PUBLIC, CallableMemberDescriptor.Kind.DECLARATION, false
|
||||
).entrySet()) {
|
||||
ClassBodyCodegen.generateDelegationToDefaultImpl(entry.getKey(), entry.getValue(), receiverType, functionCodegen, state, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private FqName getWrapperName(
|
||||
@NotNull KtFile containingFile,
|
||||
|
||||
@@ -60,6 +60,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import java.util.*
|
||||
|
||||
fun generateIsCheck(
|
||||
@@ -666,3 +667,22 @@ private fun generateLambdaForRunSuspend(
|
||||
lambdaBuilder.done()
|
||||
return lambdaBuilder.thisName
|
||||
}
|
||||
|
||||
internal fun LabelNode.linkWithLabel(): LabelNode {
|
||||
// Remember labelNode in label and vise versa.
|
||||
// Before ASM 8 there was JB patch in MethodNode that makes such linking in constructor of LabelNode.
|
||||
//
|
||||
// protected LabelNode getLabelNode(final Label label) {
|
||||
// if (!(label.info instanceof LabelNode)) {
|
||||
// //label.info = new LabelNode(label); //[JB: needed for Coverage agent]
|
||||
// label.info = new LabelNode(); //ASM 8
|
||||
// }
|
||||
// return (LabelNode) label.info;
|
||||
// }
|
||||
if (label.info == null) {
|
||||
label.info = this
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun linkedLabel(): Label = LabelNode().linkWithLabel().label
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen.coroutines
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.cfg.index
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -229,6 +231,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
|
||||
override fun generateClosureBody() {
|
||||
for (parameter in allFunctionParameters()) {
|
||||
if (parameter.isUnused()) continue
|
||||
val fieldInfo = parameter.getFieldInfoForCoroutineLambdaParameter()
|
||||
v.newField(
|
||||
OtherOrigin(parameter),
|
||||
@@ -241,6 +244,10 @@ class CoroutineCodegenForLambda private constructor(
|
||||
generateResumeImpl()
|
||||
}
|
||||
|
||||
private fun ParameterDescriptor.isUnused(): Boolean =
|
||||
originalSuspendFunctionDescriptor is AnonymousFunctionDescriptor &&
|
||||
bindingContext[BindingContext.SUSPEND_LAMBDA_PARAMETER_USED, originalSuspendFunctionDescriptor to index()] != true
|
||||
|
||||
private val generateErasedCreate: Boolean = allFunctionParameters().size <= 1
|
||||
|
||||
private val doNotGenerateInvokeBridge: Boolean = !originalSuspendFunctionDescriptor.isLocalSuspendFunctionNotSuspendLambda()
|
||||
@@ -398,39 +405,41 @@ class CoroutineCodegenForLambda private constructor(
|
||||
var index = 1
|
||||
for (parameter in allFunctionParameters()) {
|
||||
val fieldInfoForCoroutineLambdaParameter = parameter.getFieldInfoForCoroutineLambdaParameter()
|
||||
if (isBigArity) {
|
||||
load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
|
||||
load(1, AsmTypes.OBJECT_TYPE)
|
||||
iconst(index - 1)
|
||||
aload(AsmTypes.OBJECT_TYPE)
|
||||
StackValue.coerce(
|
||||
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
|
||||
this
|
||||
)
|
||||
putfield(
|
||||
fieldInfoForCoroutineLambdaParameter.ownerInternalName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType.descriptor
|
||||
)
|
||||
} else {
|
||||
if (generateErasedCreate) {
|
||||
load(index, AsmTypes.OBJECT_TYPE)
|
||||
if (!parameter.isUnused()) {
|
||||
if (isBigArity) {
|
||||
load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
|
||||
load(1, AsmTypes.OBJECT_TYPE)
|
||||
iconst(index - 1)
|
||||
aload(AsmTypes.OBJECT_TYPE)
|
||||
StackValue.coerce(
|
||||
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
|
||||
this
|
||||
)
|
||||
putfield(
|
||||
fieldInfoForCoroutineLambdaParameter.ownerInternalName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType.descriptor
|
||||
)
|
||||
} else {
|
||||
load(index, fieldInfoForCoroutineLambdaParameter.fieldType)
|
||||
if (generateErasedCreate) {
|
||||
load(index, AsmTypes.OBJECT_TYPE)
|
||||
StackValue.coerce(
|
||||
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
|
||||
this
|
||||
)
|
||||
} else {
|
||||
load(index, fieldInfoForCoroutineLambdaParameter.fieldType)
|
||||
}
|
||||
AsmUtil.genAssignInstanceFieldFromParam(
|
||||
fieldInfoForCoroutineLambdaParameter,
|
||||
index,
|
||||
this,
|
||||
cloneIndex,
|
||||
generateErasedCreate
|
||||
)
|
||||
}
|
||||
AsmUtil.genAssignInstanceFieldFromParam(
|
||||
fieldInfoForCoroutineLambdaParameter,
|
||||
index,
|
||||
this,
|
||||
cloneIndex,
|
||||
generateErasedCreate
|
||||
)
|
||||
}
|
||||
index += if (isBigArity || generateErasedCreate) 1 else fieldInfoForCoroutineLambdaParameter.fieldType.size
|
||||
}
|
||||
@@ -442,6 +451,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
|
||||
private fun ExpressionCodegen.initializeCoroutineParameters() {
|
||||
for (parameter in allFunctionParameters()) {
|
||||
if (parameter.isUnused()) continue
|
||||
val fieldStackValue =
|
||||
StackValue.field(
|
||||
parameter.getFieldInfoForCoroutineLambdaParameter(), generateThisOrOuter(context.thisDescriptor, false)
|
||||
@@ -463,7 +473,11 @@ class CoroutineCodegenForLambda private constructor(
|
||||
v.visitLocalVariable(name, mappedType.descriptor, null, label, endLabel, newIndex)
|
||||
}
|
||||
|
||||
initializeVariablesForDestructuredLambdaParameters(this, originalSuspendFunctionDescriptor.valueParameters, endLabel)
|
||||
initializeVariablesForDestructuredLambdaParameters(
|
||||
this,
|
||||
originalSuspendFunctionDescriptor.valueParameters.filter { !it.isUnused() },
|
||||
endLabel
|
||||
)
|
||||
}
|
||||
|
||||
private fun allFunctionParameters(): List<ParameterDescriptor> =
|
||||
|
||||
@@ -5,23 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
@@ -30,7 +24,6 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.*
|
||||
import kotlin.math.max
|
||||
|
||||
private const val COROUTINES_DEBUG_METADATA_VERSION = 1
|
||||
@@ -92,14 +85,14 @@ class CoroutineTransformerMethodVisitor(
|
||||
)
|
||||
|
||||
FixStackMethodTransformer().transform(containingClassInternalName, methodNode)
|
||||
RedundantLocalsEliminationMethodTransformer(languageVersionSettings).transform(containingClassInternalName, methodNode)
|
||||
val suspensionPoints = collectSuspensionPoints(methodNode)
|
||||
RedundantLocalsEliminationMethodTransformer(suspensionPoints)
|
||||
.transform(containingClassInternalName, methodNode)
|
||||
if (languageVersionSettings.isReleaseCoroutines()) {
|
||||
ChangeBoxingMethodTransformer.transform(containingClassInternalName, methodNode)
|
||||
}
|
||||
updateMaxStack(methodNode)
|
||||
|
||||
val suspensionPoints = collectSuspensionPoints(methodNode)
|
||||
|
||||
checkForSuspensionPointInsideMonitor(methodNode, suspensionPoints)
|
||||
|
||||
// First instruction in the method node may change in case of named function
|
||||
@@ -114,6 +107,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
languageVersionSettings,
|
||||
containingClassInternalName,
|
||||
methodNode,
|
||||
suspensionPoints,
|
||||
disableTailCallOptimizationForFunctionReturningUnit
|
||||
)
|
||||
if (examiner.allSuspensionPointsAreTailCalls(suspensionPoints)) {
|
||||
@@ -577,11 +571,9 @@ class CoroutineTransformerMethodVisitor(
|
||||
return false
|
||||
}
|
||||
|
||||
val starts = methodNode.instructions.asSequence().filter {
|
||||
isBeforeSuspendMarker(it) &&
|
||||
cfg.getPredecessorsIndices(it).isNotEmpty() // Ignore unreachable start markers
|
||||
}.toList()
|
||||
return starts.mapNotNull { start ->
|
||||
return methodNode.instructions.asSequence().filter {
|
||||
isBeforeSuspendMarker(it)
|
||||
}.mapNotNull { start ->
|
||||
val ends = mutableSetOf<AbstractInsnNode>()
|
||||
if (collectSuspensionPointEnds(start, mutableSetOf(), ends)) return@mapNotNull null
|
||||
// Ignore suspension points, if the suspension call begin is alive and suspension call end is dead
|
||||
@@ -590,7 +582,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
// this is an exit point for the corresponding coroutine.
|
||||
val end = ends.find { isAfterSuspendMarker(it) } ?: return@mapNotNull null
|
||||
SuspensionPoint(start.previous, end)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private fun dropSuspensionMarkers(methodNode: MethodNode) {
|
||||
@@ -750,7 +742,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
suspendMarkerVarIndex: Int,
|
||||
suspendPointLineNumber: LineNumberNode?
|
||||
): LabelNode {
|
||||
val continuationLabel = LabelNode()
|
||||
val continuationLabel = LabelNode().linkWithLabel()
|
||||
val continuationLabelAfterLoadedResult = LabelNode()
|
||||
val suspendElementLineNumber = lineNumber
|
||||
var nextLineNumberNode = nextDefinitelyHitLineNumber(suspension)
|
||||
@@ -898,197 +890,6 @@ class CoroutineTransformerMethodVisitor(
|
||||
private data class SpilledVariableDescriptor(val fieldName: String, val variableName: String)
|
||||
}
|
||||
|
||||
// TODO Use this in variable liveness analysis
|
||||
private class MethodNodeExaminer(
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
val containingClassInternalName: String,
|
||||
val methodNode: MethodNode,
|
||||
disableTailCallOptimizationForFunctionReturningUnit: Boolean
|
||||
) {
|
||||
private val sourceFrames: SourceFrames =
|
||||
MethodTransformer.analyze(containingClassInternalName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||
private val controlFlowGraph = ControlFlowGraph.build(methodNode)
|
||||
|
||||
private val safeUnitInstances = mutableSetOf<AbstractInsnNode>()
|
||||
private val popsBeforeSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
|
||||
private val areturnsAfterSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
|
||||
private val meaningfulSuccessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
|
||||
private val meaningfulPredecessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
|
||||
|
||||
init {
|
||||
if (!disableTailCallOptimizationForFunctionReturningUnit) {
|
||||
// retrieve all POP insns
|
||||
val pops = methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }
|
||||
// for each of them check that all successors are PUSH Unit
|
||||
val popsBeforeUnitInstances = pops.map { it to it.meaningfulSuccessors() }
|
||||
.filter { (_, succs) -> succs.all { it.isUnitInstance() } }
|
||||
.map { it.first }.toList()
|
||||
for (pop in popsBeforeUnitInstances) {
|
||||
val units = pop.meaningfulSuccessors()
|
||||
val allUnitsAreSafe = units.all { unit ->
|
||||
// check no other predecessor exists
|
||||
unit.meaningfulPredecessors().all { it in popsBeforeUnitInstances } &&
|
||||
// check they have only returns among successors
|
||||
unit.meaningfulSuccessors().all { it.opcode == Opcodes.ARETURN }
|
||||
}
|
||||
if (!allUnitsAreSafe) continue
|
||||
// save them all to the properties
|
||||
popsBeforeSafeUnitInstances += pop
|
||||
safeUnitInstances += units
|
||||
units.flatMapTo(areturnsAfterSafeUnitInstances) { it.meaningfulSuccessors() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this)
|
||||
|
||||
// GETSTATIC kotlin/Unit.INSTANCE is considered safe iff
|
||||
// it is part of POP, PUSH Unit, ARETURN sequence.
|
||||
private fun AbstractInsnNode.isSafeUnitInstance(): Boolean = this in safeUnitInstances
|
||||
|
||||
private fun AbstractInsnNode.isPopBeforeSafeUnitInstance(): Boolean = this in popsBeforeSafeUnitInstances
|
||||
private fun AbstractInsnNode.isAreturnAfterSafeUnitInstance(): Boolean = this in areturnsAfterSafeUnitInstances
|
||||
|
||||
private fun AbstractInsnNode.meaningfulSuccessors(): List<AbstractInsnNode> = meaningfulSuccessorsCache.getOrPut(this) {
|
||||
meaningfulSuccessorsOrPredecessors(true)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.meaningfulPredecessors(): List<AbstractInsnNode> = meaningfulPredecessorsCache.getOrPut(this) {
|
||||
meaningfulSuccessorsOrPredecessors(false)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.meaningfulSuccessorsOrPredecessors(isSuccessors: Boolean): List<AbstractInsnNode> {
|
||||
fun AbstractInsnNode.isMeaningful() = isMeaningful && opcode != Opcodes.NOP && opcode != Opcodes.GOTO && this !is LineNumberNode
|
||||
|
||||
fun AbstractInsnNode.getIndices() =
|
||||
if (isSuccessors) controlFlowGraph.getSuccessorsIndices(this)
|
||||
else controlFlowGraph.getPredecessorsIndices(this)
|
||||
|
||||
val visited = arrayListOf<AbstractInsnNode>()
|
||||
fun dfs(insn: AbstractInsnNode) {
|
||||
if (insn in visited) return
|
||||
visited += insn
|
||||
if (!insn.isMeaningful()) {
|
||||
for (succIndex in insn.getIndices()) {
|
||||
dfs(methodNode.instructions[succIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (succIndex in getIndices()) {
|
||||
dfs(methodNode.instructions[succIndex])
|
||||
}
|
||||
return visited.filter { it.isMeaningful() }
|
||||
}
|
||||
|
||||
fun replacePopsBeforeSafeUnitInstancesWithCoroutineSuspendedChecks() {
|
||||
val basicAnalyser = Analyzer(BasicInterpreter())
|
||||
basicAnalyser.analyze(containingClassInternalName, methodNode)
|
||||
val typedFrames = basicAnalyser.frames
|
||||
|
||||
val isReferenceMap = popsBeforeSafeUnitInstances
|
||||
.map { it to (!isUnreachable(it.index(), sourceFrames) && typedFrames[it.index()]?.top()?.isReference == true) }
|
||||
.toMap()
|
||||
|
||||
for (pop in popsBeforeSafeUnitInstances) {
|
||||
if (isReferenceMap[pop] == true) {
|
||||
val label = Label()
|
||||
methodNode.instructions.insertBefore(pop, withInstructionAdapter {
|
||||
dup()
|
||||
loadCoroutineSuspendedMarker(languageVersionSettings)
|
||||
ifacmpne(label)
|
||||
areturn(AsmTypes.OBJECT_TYPE)
|
||||
mark(label)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun allSuspensionPointsAreTailCalls(suspensionPoints: List<SuspensionPoint>): Boolean {
|
||||
val safelyReachableReturns = findSafelyReachableReturns()
|
||||
|
||||
val instructions = methodNode.instructions
|
||||
return suspensionPoints.all { suspensionPoint ->
|
||||
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
|
||||
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
|
||||
|
||||
if (isUnreachable(endIndex, sourceFrames)) return@all true
|
||||
|
||||
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
|
||||
val tryBlockStartIndex = instructions.indexOf(block.start)
|
||||
val tryBlockEndIndex = instructions.indexOf(block.end)
|
||||
|
||||
beginIndex in tryBlockStartIndex..tryBlockEndIndex
|
||||
}
|
||||
if (insideTryBlock) return@all false
|
||||
|
||||
safelyReachableReturns[endIndex + 1]?.all { returnIndex ->
|
||||
sourceFrames[returnIndex]?.top().sure {
|
||||
"There must be some value on stack to return"
|
||||
}.insns.any { sourceInsn ->
|
||||
sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex
|
||||
}
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Let's call an instruction safe if its execution is always invisible: stack modifications, branching, variable insns (invisible in debug)
|
||||
*
|
||||
* For some instruction `insn` define the result as following:
|
||||
* - if there is a path leading to the non-safe instruction then result is `null`
|
||||
* - Otherwise result contains all the reachable ARETURN indices
|
||||
*
|
||||
* @return indices of safely reachable returns for each instruction in the method node
|
||||
*/
|
||||
private fun findSafelyReachableReturns(): Array<Set<Int>?> {
|
||||
val insns = methodNode.instructions
|
||||
val reachableReturnsIndices = Array<Set<Int>?>(insns.size()) init@{ index ->
|
||||
val insn = insns[index]
|
||||
|
||||
if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) {
|
||||
if (isUnreachable(index, sourceFrames)) return@init null
|
||||
return@init setOf(index)
|
||||
}
|
||||
|
||||
// Since POP, PUSH Unit, ARETURN behaves like normal return in terms of tail-call optimization, set return index to POP
|
||||
if (insn.isPopBeforeSafeUnitInstance()) {
|
||||
return@init setOf(index)
|
||||
}
|
||||
|
||||
if (!insn.isMeaningful || insn.opcode in SAFE_OPCODES || insn.isInvisibleInDebugVarInsn(methodNode) || isInlineMarker(insn)
|
||||
|| insn.isSafeUnitInstance() || insn.isAreturnAfterSafeUnitInstance()
|
||||
) {
|
||||
setOf<Int>()
|
||||
} else null
|
||||
}
|
||||
|
||||
var changed: Boolean
|
||||
do {
|
||||
changed = false
|
||||
for (index in 0 until insns.size()) {
|
||||
if (insns[index].opcode == Opcodes.ARETURN) continue
|
||||
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
val newResult =
|
||||
controlFlowGraph
|
||||
.getSuccessorsIndices(index).plus(index)
|
||||
.map(reachableReturnsIndices::get)
|
||||
.fold<Set<Int>?, Set<Int>?>(mutableSetOf<Int>()) { acc, successorsResult ->
|
||||
if (acc != null && successorsResult != null) acc + successorsResult else null
|
||||
}
|
||||
|
||||
if (newResult != reachableReturnsIndices[index]) {
|
||||
reachableReturnsIndices[index] = newResult
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
} while (changed)
|
||||
|
||||
return reachableReturnsIndices
|
||||
}
|
||||
}
|
||||
|
||||
internal fun InstructionAdapter.generateContinuationConstructorCall(
|
||||
objectTypeForState: Type?,
|
||||
methodNode: MethodNode,
|
||||
@@ -1169,15 +970,25 @@ private fun Type.normalize() =
|
||||
* ICONST_1
|
||||
* INVOKESTATIC InlineMarker.mark()
|
||||
*/
|
||||
private class SuspensionPoint(
|
||||
internal class SuspensionPoint(
|
||||
// ICONST_0
|
||||
val suspensionCallBegin: AbstractInsnNode,
|
||||
// INVOKESTATIC InlineMarker.mark()
|
||||
val suspensionCallEnd: AbstractInsnNode
|
||||
) {
|
||||
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
||||
|
||||
operator fun contains(insn: AbstractInsnNode): Boolean {
|
||||
for (i in InsnSequence(suspensionCallBegin, suspensionCallEnd.next)) {
|
||||
if (i == insn) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
internal operator fun List<SuspensionPoint>.contains(insn: AbstractInsnNode): Boolean =
|
||||
any { insn in it }
|
||||
|
||||
internal fun getLastParameterIndex(desc: String, access: Int) =
|
||||
Type.getArgumentTypes(desc).dropLast(1).map { it.size }.sum() + (if (!isStatic(access)) 1 else 0)
|
||||
|
||||
@@ -1208,25 +1019,6 @@ private fun getAllParameterTypes(desc: String, hasDispatchReceiver: Boolean, thi
|
||||
listOfNotNull(if (!hasDispatchReceiver) null else Type.getObjectType(thisName)).toTypedArray() +
|
||||
Type.getArgumentTypes(desc)
|
||||
|
||||
internal class IgnoringCopyOperationSourceInterpreter : SourceInterpreter(Opcodes.API_VERSION) {
|
||||
override fun copyOperation(insn: AbstractInsnNode?, value: SourceValue?) = value
|
||||
}
|
||||
|
||||
// Check whether this instruction is unreachable, i.e. there is no path leading to this instruction
|
||||
internal fun <T : Value> isUnreachable(index: Int, sourceFrames: Array<out Frame<out T>?>): Boolean =
|
||||
sourceFrames.size <= index || sourceFrames[index] == null
|
||||
|
||||
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
|
||||
val insns = methodNode.instructions
|
||||
val index = insns.indexOf(this)
|
||||
return (this is VarInsnNode && methodNode.localVariables.none {
|
||||
it.index == `var` && index in it.start.let(insns::indexOf)..it.end.let(insns::indexOf)
|
||||
})
|
||||
}
|
||||
|
||||
private val SAFE_OPCODES =
|
||||
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
||||
|
||||
internal fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continuationIndex: Int) {
|
||||
val fakeContinuations = methodNode.instructions.asSequence().filter(::isFakeContinuationMarker).toList()
|
||||
for (fakeContinuation in fakeContinuations) {
|
||||
|
||||
@@ -5,93 +5,133 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.inline.nodeText
|
||||
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.removeAll
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
|
||||
private class PossibleSpilledValue(val source: AbstractInsnNode, type: Type?) : BasicValue(type) {
|
||||
val usages = mutableSetOf<AbstractInsnNode>()
|
||||
|
||||
override fun toString(): String = when {
|
||||
source.opcode == Opcodes.ALOAD -> "" + (source as VarInsnNode).`var`
|
||||
source.isUnitInstance() -> "U"
|
||||
else -> error("unreachable")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is PossibleSpilledValue && source == other.source
|
||||
|
||||
override fun hashCode(): Int = super.hashCode() xor source.hashCode()
|
||||
}
|
||||
|
||||
private object NonSpillableValue : BasicValue(AsmTypes.OBJECT_TYPE) {
|
||||
override fun equals(other: Any?): Boolean = other is NonSpillableValue
|
||||
|
||||
override fun toString(): String = "N"
|
||||
}
|
||||
|
||||
private object ConstructedValue : BasicValue(AsmTypes.OBJECT_TYPE) {
|
||||
override fun equals(other: Any?): Boolean = other is ConstructedValue
|
||||
|
||||
override fun toString(): String = "C"
|
||||
}
|
||||
|
||||
fun BasicValue?.nonspillable(): BasicValue? = if (this?.type?.sort == Type.OBJECT) NonSpillableValue else this
|
||||
|
||||
private class RedundantSpillingInterpreter : BasicInterpreter(Opcodes.API_VERSION) {
|
||||
val possibleSpilledValues = mutableSetOf<PossibleSpilledValue>()
|
||||
|
||||
override fun newOperation(insn: AbstractInsnNode): BasicValue? {
|
||||
if (insn.opcode == Opcodes.NEW) return ConstructedValue
|
||||
val basicValue = super.newOperation(insn)
|
||||
return if (insn.isUnitInstance())
|
||||
// Unit instances come from inlining suspend functions returning Unit.
|
||||
// They can be spilled before they are eventually popped.
|
||||
// Track them.
|
||||
PossibleSpilledValue(insn, basicValue.type).also { possibleSpilledValues += it }
|
||||
else basicValue.nonspillable()
|
||||
}
|
||||
|
||||
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? =
|
||||
when (value) {
|
||||
is ConstructedValue -> value
|
||||
is PossibleSpilledValue -> {
|
||||
value.usages += insn
|
||||
if (insn.opcode == Opcodes.ALOAD || insn.opcode == Opcodes.ASTORE) value
|
||||
else value.nonspillable()
|
||||
}
|
||||
else -> value?.nonspillable()
|
||||
}
|
||||
|
||||
override fun naryOperation(insn: AbstractInsnNode, values: MutableList<out BasicValue?>): BasicValue? {
|
||||
for (value in values.filterIsInstance<PossibleSpilledValue>()) {
|
||||
value.usages += insn
|
||||
}
|
||||
return super.naryOperation(insn, values)?.nonspillable()
|
||||
}
|
||||
|
||||
override fun merge(v: BasicValue?, w: BasicValue?): BasicValue? =
|
||||
if (v is PossibleSpilledValue && w is PossibleSpilledValue && v.source == w.source) v
|
||||
else v?.nonspillable()
|
||||
}
|
||||
|
||||
// Inliner emits a lot of locals during inlining.
|
||||
// Remove all of them since these locals are
|
||||
// 1) going to be spilled into continuation object
|
||||
// 2) breaking tail-call elimination
|
||||
class RedundantLocalsEliminationMethodTransformer(private val languageVersionSettings: LanguageVersionSettings) : MethodTransformer() {
|
||||
lateinit var internalClassName: String
|
||||
internal class RedundantLocalsEliminationMethodTransformer(private val suspensionPoints: List<SuspensionPoint>) : MethodTransformer() {
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
this.internalClassName = internalClassName
|
||||
do {
|
||||
var changed = false
|
||||
changed = simpleRemove(methodNode) || changed
|
||||
changed = removeWithReplacement(methodNode) || changed
|
||||
changed = removeAloadCheckcastContinuationAstore(methodNode, languageVersionSettings) || changed
|
||||
} while (changed)
|
||||
}
|
||||
val interpreter = RedundantSpillingInterpreter()
|
||||
val frames = MethodAnalyzer<BasicValue>(internalClassName, methodNode, interpreter).analyze()
|
||||
|
||||
// Replace
|
||||
// GETSTATIC kotlin/Unit.INSTANCE
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// GETSTATIC kotlin/Unit.INSTANCE
|
||||
// or
|
||||
// ACONST_NULL
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// ACONST_NULL
|
||||
// or
|
||||
// ALOAD K
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// ALOAD K
|
||||
//
|
||||
// But do not remove several at a time, since the same local (for example, ALOAD 0) might be loaded and stored multiple times in
|
||||
// sequence, like
|
||||
// ALOAD 0
|
||||
// ASTORE 1
|
||||
// ALOAD 1
|
||||
// ASTORE 2
|
||||
// ALOAD 3
|
||||
// Here, it is unsafe to replace ALOAD 3 with ALOAD 1, and then already removed ALOAD 1 with ALOAD 0.
|
||||
private fun removeWithReplacement(
|
||||
methodNode: MethodNode
|
||||
): Boolean {
|
||||
val cfg = ControlFlowGraph.build(methodNode)
|
||||
val insns = findSafeAstorePredecessors(methodNode, cfg, ignoreLocalVariableTable = false) {
|
||||
it.isUnitInstance() || it.opcode == Opcodes.ACONST_NULL || it.opcode == Opcodes.ALOAD
|
||||
val toDelete = mutableSetOf<AbstractInsnNode>()
|
||||
for (spilledValue in interpreter.possibleSpilledValues.filter { it.usages.isNotEmpty() }) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val aloads = spilledValue.usages.filter { it.opcode == Opcodes.ALOAD } as List<VarInsnNode>
|
||||
|
||||
if (aloads.isEmpty()) continue
|
||||
|
||||
val slot = aloads.first().`var`
|
||||
|
||||
if (aloads.any { it.`var` != slot }) continue
|
||||
for (aload in aloads) {
|
||||
methodNode.instructions.set(aload, spilledValue.source.clone())
|
||||
}
|
||||
|
||||
toDelete.addAll(spilledValue.usages.filter { it.opcode == Opcodes.ASTORE })
|
||||
toDelete.add(spilledValue.source)
|
||||
}
|
||||
for ((pred, astore) in insns) {
|
||||
val aload = findSingleLoadFromAstore(astore, cfg, methodNode) ?: continue
|
||||
|
||||
methodNode.instructions.removeAll(listOf(pred, astore))
|
||||
methodNode.instructions.set(aload, pred.clone())
|
||||
return true
|
||||
for (pop in methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }) {
|
||||
val value = (frames[methodNode.instructions.indexOf(pop)]?.top() as? PossibleSpilledValue) ?: continue
|
||||
if (value.usages.isEmpty() && value.source !in suspensionPoints) {
|
||||
toDelete.add(pop)
|
||||
toDelete.add(value.source)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun findSingleLoadFromAstore(
|
||||
astore: AbstractInsnNode,
|
||||
cfg: ControlFlowGraph,
|
||||
methodNode: MethodNode
|
||||
): AbstractInsnNode? {
|
||||
val aload = methodNode.instructions.asSequence()
|
||||
.singleOrNull { it.opcode == Opcodes.ALOAD && it.localIndex() == astore.localIndex() } ?: return null
|
||||
val succ = findImmediateSuccessors(astore, cfg, methodNode).singleOrNull() ?: return null
|
||||
return if (aload == succ) aload else null
|
||||
// Remove unreachable instructions to simplify further analyses
|
||||
for (index in frames.indices) {
|
||||
if (frames[index] == null) {
|
||||
val insn = methodNode.instructions[index]
|
||||
if (insn !is LabelNode) {
|
||||
toDelete.add(insn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
methodNode.instructions.removeAll(toDelete)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.clone() = when (this) {
|
||||
@@ -101,145 +141,41 @@ class RedundantLocalsEliminationMethodTransformer(private val languageVersionSet
|
||||
is TypeInsnNode -> TypeInsnNode(opcode, desc)
|
||||
else -> error("clone of $this is not implemented yet")
|
||||
}
|
||||
}
|
||||
|
||||
// Remove
|
||||
// ALOAD N
|
||||
// POP
|
||||
// or
|
||||
// ACONST_NULL
|
||||
// POP
|
||||
// or
|
||||
// GETSTATIC kotlin/Unit.INSTANCE
|
||||
// POP
|
||||
private fun simpleRemove(methodNode: MethodNode): Boolean {
|
||||
val insns =
|
||||
findPopPredecessors(methodNode) { it.isUnitInstance() || it.opcode == Opcodes.ACONST_NULL || it.opcode == Opcodes.ALOAD }
|
||||
for ((pred, pop) in insns) {
|
||||
methodNode.instructions.insertBefore(pred, InsnNode(Opcodes.NOP))
|
||||
methodNode.instructions.removeAll(listOf(pred, pop))
|
||||
}
|
||||
return insns.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun findPopPredecessors(
|
||||
methodNode: MethodNode,
|
||||
predicate: (AbstractInsnNode) -> Boolean
|
||||
): Map<AbstractInsnNode, AbstractInsnNode> {
|
||||
val insns = methodNode.instructions.asSequence().filter { predicate(it) }.toList()
|
||||
|
||||
val cfg = ControlFlowGraph.build(methodNode)
|
||||
|
||||
val res = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
|
||||
// Handy debugging routing
|
||||
@Suppress("unused")
|
||||
fun MethodNode.nodeTextWithFrames(frames: Array<*>): String {
|
||||
var insns = nodeText.split("\n")
|
||||
val first = insns.indexOfLast { it.trim().startsWith("@") } + 1
|
||||
var last = insns.indexOfFirst { it.trim().startsWith("LOCALVARIABLE") }
|
||||
if (last < 0) last = insns.size
|
||||
val prefix = insns.subList(0, first).joinToString(separator = "\n")
|
||||
val postfix = insns.subList(last, insns.size).joinToString(separator = "\n")
|
||||
insns = insns.subList(first, last)
|
||||
if (insns.any { it.contains("TABLESWITCH") }) {
|
||||
var insideTableSwitch = false
|
||||
var buffer = ""
|
||||
val res = arrayListOf<String>()
|
||||
for (insn in insns) {
|
||||
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
|
||||
if (succ.opcode != Opcodes.POP) continue
|
||||
if (insn.opcode == Opcodes.ALOAD && methodNode.localVariables.firstOrNull { it.index == insn.localIndex() } != null) continue
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
|
||||
if (sources.size != 1) continue
|
||||
res[insn] = succ
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Replace
|
||||
// ALOAD K
|
||||
// CHECKCAST Continuation
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// ALOAD K
|
||||
// CHECKCAST Continuation
|
||||
private fun removeAloadCheckcastContinuationAstore(methodNode: MethodNode, languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||
// Here we ignore the duplicates of continuation in local variable table,
|
||||
// Since it increases performance greatly.
|
||||
val cfg = ControlFlowGraph.build(methodNode)
|
||||
val insns = findSafeAstorePredecessors(methodNode, cfg, ignoreLocalVariableTable = true) {
|
||||
it.opcode == Opcodes.CHECKCAST &&
|
||||
(it as TypeInsnNode).desc == languageVersionSettings.continuationAsmType().internalName &&
|
||||
it.previous?.opcode == Opcodes.ALOAD
|
||||
}
|
||||
|
||||
var changed = false
|
||||
|
||||
for ((checkcast, astore) in insns) {
|
||||
val aloadk = checkcast.previous
|
||||
val aloadn = findSingleLoadFromAstore(astore, cfg, methodNode) ?: continue
|
||||
|
||||
methodNode.instructions.removeAll(listOf(aloadk, checkcast, astore))
|
||||
methodNode.instructions.insertBefore(aloadn, aloadk.clone())
|
||||
methodNode.instructions.set(aloadn, checkcast.clone())
|
||||
changed = true
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun findSafeAstorePredecessors(
|
||||
methodNode: MethodNode,
|
||||
cfg: ControlFlowGraph,
|
||||
ignoreLocalVariableTable: Boolean,
|
||||
predicate: (AbstractInsnNode) -> Boolean
|
||||
): Map<AbstractInsnNode, AbstractInsnNode> {
|
||||
val insns = methodNode.instructions.asSequence().filter { predicate(it) }.toList()
|
||||
val res = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
|
||||
|
||||
for (insn in insns) {
|
||||
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
|
||||
if (succ.opcode != Opcodes.ASTORE) continue
|
||||
if (methodNode.instructions.asSequence().count {
|
||||
it.opcode == Opcodes.ASTORE && it.localIndex() == succ.localIndex()
|
||||
} != 1) continue
|
||||
if (!ignoreLocalVariableTable && methodNode.localVariables.firstOrNull { it.index == succ.localIndex() } != null) continue
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
|
||||
if (sources.size > 1) continue
|
||||
res[insn] = succ
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Find all meaningful successors of insn
|
||||
private fun findImmediateSuccessors(
|
||||
insn: AbstractInsnNode,
|
||||
cfg: ControlFlowGraph,
|
||||
methodNode: MethodNode
|
||||
): Collection<AbstractInsnNode> {
|
||||
val visited = hashSetOf<AbstractInsnNode>()
|
||||
|
||||
fun dfs(current: AbstractInsnNode): Collection<AbstractInsnNode> {
|
||||
if (!visited.add(current)) return emptySet()
|
||||
|
||||
return cfg.getSuccessorsIndices(current).flatMap {
|
||||
val succ = methodNode.instructions[it]
|
||||
if (!succ.isMeaningful || succ is JumpInsnNode || succ.opcode == Opcodes.NOP) dfs(succ)
|
||||
else setOf(succ)
|
||||
if (insn.contains("TABLESWITCH")) {
|
||||
insideTableSwitch = true
|
||||
}
|
||||
if (insideTableSwitch) {
|
||||
buffer += insn
|
||||
if (insn.contains("default")) {
|
||||
insideTableSwitch = false
|
||||
res += buffer
|
||||
buffer = ""
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
res += insn
|
||||
}
|
||||
}
|
||||
|
||||
return dfs(insn)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.localIndex(): Int {
|
||||
assert(this is VarInsnNode)
|
||||
return (this as VarInsnNode).`var`
|
||||
}
|
||||
}
|
||||
|
||||
private fun findSourceInstructions(
|
||||
internalClassName: String,
|
||||
methodNode: MethodNode,
|
||||
insns: Collection<AbstractInsnNode>,
|
||||
ignoreCopy: Boolean
|
||||
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
||||
val frames = MethodTransformer.analyze(
|
||||
internalClassName,
|
||||
methodNode,
|
||||
if (ignoreCopy) IgnoringCopyOperationSourceInterpreter() else SourceInterpreter()
|
||||
)
|
||||
return insns.keysToMap {
|
||||
val index = methodNode.instructions.indexOf(it)
|
||||
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()
|
||||
frames[index].getStack(0).insns
|
||||
insns = res
|
||||
}
|
||||
return prefix + "\n" + insns.withIndex().joinToString(separator = "\n") { (index, insn) ->
|
||||
if (index >= frames.size) "N/A\t$insn" else "${frames[index]}\t$insn"
|
||||
} + "\n" + postfix
|
||||
}
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.inline.isInlineMarker
|
||||
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.LineNumberNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
|
||||
// TODO Use this in variable liveness analysis
|
||||
internal class MethodNodeExaminer(
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
containingClassInternalName: String,
|
||||
val methodNode: MethodNode,
|
||||
suspensionPoints: List<SuspensionPoint>,
|
||||
disableTailCallOptimizationForFunctionReturningUnit: Boolean
|
||||
) {
|
||||
private val frames: Array<Frame<BasicValue>?> =
|
||||
MethodTransformer.analyze(containingClassInternalName, methodNode, TcoInterpreter(suspensionPoints))
|
||||
private val controlFlowGraph = ControlFlowGraph.build(methodNode)
|
||||
|
||||
private val safeUnitInstances = mutableSetOf<AbstractInsnNode>()
|
||||
private val popsBeforeSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
|
||||
private val areturnsAfterSafeUnitInstances = mutableSetOf<AbstractInsnNode>()
|
||||
private val meaningfulSuccessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
|
||||
private val meaningfulPredecessorsCache = hashMapOf<AbstractInsnNode, List<AbstractInsnNode>>()
|
||||
|
||||
init {
|
||||
if (!disableTailCallOptimizationForFunctionReturningUnit) {
|
||||
// retrieve all POP insns
|
||||
val pops = methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }
|
||||
// for each of them check that all successors are PUSH Unit
|
||||
val popsBeforeUnitInstances = pops.map { it to it.meaningfulSuccessors() }
|
||||
.filter { (_, succs) -> succs.all { it.isUnitInstance() } }
|
||||
.map { it.first }.toList()
|
||||
for (pop in popsBeforeUnitInstances) {
|
||||
val units = pop.meaningfulSuccessors()
|
||||
val allUnitsAreSafe = units.all { unit ->
|
||||
// check no other predecessor exists
|
||||
unit.meaningfulPredecessors().all { it in popsBeforeUnitInstances } &&
|
||||
// check they have only returns among successors
|
||||
unit.meaningfulSuccessors().all { it.opcode == Opcodes.ARETURN }
|
||||
}
|
||||
if (!allUnitsAreSafe) continue
|
||||
// save them all to the properties
|
||||
popsBeforeSafeUnitInstances += pop
|
||||
safeUnitInstances += units
|
||||
units.flatMapTo(areturnsAfterSafeUnitInstances) { it.meaningfulSuccessors() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GETSTATIC kotlin/Unit.INSTANCE is considered safe iff
|
||||
// it is part of POP, PUSH Unit, ARETURN sequence.
|
||||
private fun AbstractInsnNode.isSafeUnitInstance(): Boolean = this in safeUnitInstances
|
||||
|
||||
private fun AbstractInsnNode.isPopBeforeSafeUnitInstance(): Boolean = this in popsBeforeSafeUnitInstances
|
||||
private fun AbstractInsnNode.isAreturnAfterSafeUnitInstance(): Boolean = this in areturnsAfterSafeUnitInstances
|
||||
|
||||
private fun AbstractInsnNode.meaningfulSuccessors(): List<AbstractInsnNode> = meaningfulSuccessorsCache.getOrPut(this) {
|
||||
meaningfulSuccessorsOrPredecessors(true)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.meaningfulPredecessors(): List<AbstractInsnNode> = meaningfulPredecessorsCache.getOrPut(this) {
|
||||
meaningfulSuccessorsOrPredecessors(false)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.meaningfulSuccessorsOrPredecessors(isSuccessors: Boolean): List<AbstractInsnNode> {
|
||||
fun AbstractInsnNode.isMeaningful() = isMeaningful && opcode != Opcodes.NOP && opcode != Opcodes.GOTO && this !is LineNumberNode
|
||||
|
||||
fun AbstractInsnNode.getIndices() =
|
||||
if (isSuccessors) controlFlowGraph.getSuccessorsIndices(this)
|
||||
else controlFlowGraph.getPredecessorsIndices(this)
|
||||
|
||||
val visited = mutableSetOf<AbstractInsnNode>()
|
||||
fun dfs(insn: AbstractInsnNode) {
|
||||
if (insn in visited) return
|
||||
visited += insn
|
||||
if (!insn.isMeaningful()) {
|
||||
for (succIndex in insn.getIndices()) {
|
||||
dfs(methodNode.instructions[succIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (succIndex in getIndices()) {
|
||||
dfs(methodNode.instructions[succIndex])
|
||||
}
|
||||
return visited.filter { it.isMeaningful() }
|
||||
}
|
||||
|
||||
fun replacePopsBeforeSafeUnitInstancesWithCoroutineSuspendedChecks() {
|
||||
val isReferenceMap =
|
||||
popsBeforeSafeUnitInstances.associateWith { (frames[methodNode.instructions.indexOf(it)]?.top()?.isReference == true) }
|
||||
|
||||
for (pop in popsBeforeSafeUnitInstances) {
|
||||
if (isReferenceMap[pop] == true) {
|
||||
val label = Label()
|
||||
methodNode.instructions.insertBefore(pop, withInstructionAdapter {
|
||||
dup()
|
||||
loadCoroutineSuspendedMarker(languageVersionSettings)
|
||||
ifacmpne(label)
|
||||
areturn(AsmTypes.OBJECT_TYPE)
|
||||
mark(label)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun allSuspensionPointsAreTailCalls(suspensionPoints: List<SuspensionPoint>): Boolean {
|
||||
val safelyReachableReturns = findSafelyReachableReturns()
|
||||
|
||||
val instructions = methodNode.instructions
|
||||
return suspensionPoints.all { suspensionPoint ->
|
||||
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
|
||||
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
|
||||
|
||||
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
|
||||
val tryBlockStartIndex = instructions.indexOf(block.start)
|
||||
val tryBlockEndIndex = instructions.indexOf(block.end)
|
||||
|
||||
beginIndex in tryBlockStartIndex until tryBlockEndIndex
|
||||
}
|
||||
if (insideTryBlock) return@all false
|
||||
|
||||
safelyReachableReturns[endIndex + 1]?.all { returnIndex ->
|
||||
frames[returnIndex]?.top().sure {
|
||||
"There must be some value on stack to return"
|
||||
} is FromSuspensionPointValue
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Let's call an instruction safe if its execution is always invisible: stack modifications, branching, variable insns (invisible in debug)
|
||||
*
|
||||
* For some instruction `insn` define the result as following:
|
||||
* - if there is a path leading to the non-safe instruction then result is `null`
|
||||
* - Otherwise result contains all the reachable ARETURN indices
|
||||
*
|
||||
* @return indices of safely reachable returns for each instruction in the method node
|
||||
*/
|
||||
private fun findSafelyReachableReturns(): Array<Set<Int>?> {
|
||||
val insns = methodNode.instructions
|
||||
val reachableReturnsIndices = Array(insns.size()) init@{ index ->
|
||||
val insn = insns[index]
|
||||
|
||||
if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) {
|
||||
return@init setOf(index)
|
||||
}
|
||||
|
||||
// Since POP, PUSH Unit, ARETURN behaves like normal return in terms of tail-call optimization, set return index to POP
|
||||
if (insn.isPopBeforeSafeUnitInstance()) {
|
||||
return@init setOf(index)
|
||||
}
|
||||
|
||||
if (!insn.isMeaningful || insn.opcode in SAFE_OPCODES || insn.isInvisibleInDebugVarInsn(methodNode) || isInlineMarker(insn)
|
||||
|| insn.isSafeUnitInstance() || insn.isAreturnAfterSafeUnitInstance()
|
||||
) {
|
||||
setOf()
|
||||
} else null
|
||||
}
|
||||
|
||||
var changed: Boolean
|
||||
do {
|
||||
changed = false
|
||||
for (index in 0 until insns.size()) {
|
||||
if (insns[index].opcode == Opcodes.ARETURN) continue
|
||||
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
val newResult =
|
||||
controlFlowGraph
|
||||
.getSuccessorsIndices(index).plus(index)
|
||||
.map(reachableReturnsIndices::get)
|
||||
.fold<Set<Int>?, Set<Int>?>(mutableSetOf<Int>()) { acc, successorsResult ->
|
||||
if (acc != null && successorsResult != null) acc + successorsResult else null
|
||||
}
|
||||
|
||||
if (newResult != reachableReturnsIndices[index]) {
|
||||
reachableReturnsIndices[index] = newResult
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
} while (changed)
|
||||
|
||||
return reachableReturnsIndices
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
|
||||
val insns = methodNode.instructions
|
||||
val index = insns.indexOf(this)
|
||||
return (this is VarInsnNode && methodNode.localVariables.none {
|
||||
it.index == `var` && index in it.start.let(insns::indexOf)..it.end.let(insns::indexOf)
|
||||
})
|
||||
}
|
||||
|
||||
private val SAFE_OPCODES =
|
||||
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
||||
|
||||
private object FromSuspensionPointValue : BasicValue(AsmTypes.OBJECT_TYPE) {
|
||||
override fun equals(other: Any?): Boolean = other is FromSuspensionPointValue
|
||||
}
|
||||
|
||||
private fun BasicValue?.toFromSuspensionPoint(): BasicValue? = if (this?.type?.sort == Type.OBJECT) FromSuspensionPointValue else this
|
||||
|
||||
private class TcoInterpreter(private val suspensionPoints: List<SuspensionPoint>) : BasicInterpreter(Opcodes.API_VERSION) {
|
||||
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? {
|
||||
return super.copyOperation(insn, value).convert(insn)
|
||||
}
|
||||
|
||||
private fun BasicValue?.convert(insn: AbstractInsnNode): BasicValue? = if (insn in suspensionPoints) toFromSuspensionPoint() else this
|
||||
|
||||
override fun naryOperation(insn: AbstractInsnNode, values: MutableList<out BasicValue?>?): BasicValue? {
|
||||
return super.naryOperation(insn, values).convert(insn)
|
||||
}
|
||||
|
||||
override fun ternaryOperation(insn: AbstractInsnNode, value1: BasicValue?, value2: BasicValue?, value3: BasicValue?): BasicValue? {
|
||||
return super.ternaryOperation(insn, value1, value2, value3).convert(insn)
|
||||
}
|
||||
|
||||
override fun merge(value1: BasicValue?, value2: BasicValue?): BasicValue {
|
||||
return if (value1 is FromSuspensionPointValue || value2 is FromSuspensionPointValue) FromSuspensionPointValue
|
||||
else super.merge(value1, value2)
|
||||
}
|
||||
|
||||
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? {
|
||||
return super.unaryOperation(insn, value).convert(insn)
|
||||
}
|
||||
|
||||
override fun binaryOperation(insn: AbstractInsnNode, value1: BasicValue?, value2: BasicValue?): BasicValue? {
|
||||
return super.binaryOperation(insn, value1, value2).convert(insn)
|
||||
}
|
||||
|
||||
override fun newOperation(insn: AbstractInsnNode): BasicValue? {
|
||||
return super.newOperation(insn).convert(insn)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class InlineCodegenForDefaultBody(
|
||||
@@ -27,7 +29,7 @@ class InlineCodegenForDefaultBody(
|
||||
) : CallGenerator {
|
||||
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
|
||||
|
||||
private val methodStartLabel = Label()
|
||||
private val methodStartLabel = linkedLabel()
|
||||
|
||||
init {
|
||||
assert(InlineUtil.isInline(function)) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.linkedLabel;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.MethodInlinerUtilKt.getNextMeaningful;
|
||||
|
||||
@@ -198,7 +199,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
//Creating temp node for finally block copy with some additional instruction
|
||||
MethodNode finallyBlockCopy = createEmptyMethodNode();
|
||||
Label newFinallyStart = new Label();
|
||||
Label insertedBlockEnd = new Label();
|
||||
Label insertedBlockEnd = linkedLabel();
|
||||
|
||||
boolean generateAloadAstore = nonLocalReturnType != Type.VOID_TYPE && !finallyInfo.isEmpty();
|
||||
if (generateAloadAstore) {
|
||||
|
||||
@@ -102,7 +102,7 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
//substitute returns with "goto end" instruction to keep non local returns in lambdas
|
||||
val end = Label()
|
||||
val end = linkedLabel()
|
||||
val isTransformingAnonymousObject = nodeRemapper is RegeneratedLambdaFieldRemapper
|
||||
transformedNode = doInline(transformedNode)
|
||||
if (!isTransformingAnonymousObject) {
|
||||
|
||||
@@ -66,16 +66,10 @@ class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, val call
|
||||
return mappedLineNumber
|
||||
}
|
||||
|
||||
val newLineNumber = if (lineNumber == 65100) {
|
||||
// TODO This is a compatibility hack for reading bytecode generated by 1.4-M1. Once the bootstrap
|
||||
// compiler is updated to a newer version, it can be removed (as newer bytecode explicitly lists
|
||||
// this range in the SMAP).
|
||||
parent.mapSyntheticLineNumber(InlineOnlySmapSkipper.LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER)
|
||||
} else {
|
||||
val range = lastVisitedRange?.takeIf { lineNumber in it } ?: smap.findRange(lineNumber) ?: return -1
|
||||
lastVisitedRange = range
|
||||
parent.mapLineNumber(range.mapDestToSource(lineNumber), callSite ?: range.callSite)
|
||||
}
|
||||
val range = lastVisitedRange?.takeIf { lineNumber in it } ?: smap.findRange(lineNumber) ?: return -1
|
||||
lastVisitedRange = range
|
||||
val newLineNumber = parent.mapLineNumber(range.mapDestToSource(lineNumber), callSite ?: range.callSite)
|
||||
|
||||
visitedLines.put(lineNumber, newLineNumber)
|
||||
return newLineNumber
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import jdk.internal.org.objectweb.asm.Type
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
@@ -14,12 +15,14 @@ import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
const val FOR_INLINE_SUFFIX = "\$\$forInline"
|
||||
|
||||
@@ -187,8 +190,7 @@ fun markNoinlineLambdaIfSuspend(mv: MethodVisitor, info: FunctionalArgument?) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Frame<SourceValue>.getSource(offset: Int): AbstractInsnNode? =
|
||||
getStack(stackSize - offset - 1)?.insns?.singleOrNull()
|
||||
private fun Frame<BasicValue>.getSource(offset: Int): AbstractInsnNode? = (getStack(stackSize - offset - 1) as? PossibleLambdaLoad)?.insn
|
||||
|
||||
fun surroundInvokesWithSuspendMarkersIfNeeded(node: MethodNode) {
|
||||
val markers = node.instructions.asSequence().filter {
|
||||
@@ -196,14 +198,14 @@ fun surroundInvokesWithSuspendMarkersIfNeeded(node: MethodNode) {
|
||||
}.toList()
|
||||
if (markers.isEmpty()) return
|
||||
|
||||
val sourceFrames = MethodTransformer.analyze("fake", node, SourceInterpreter())
|
||||
val sourceFrames = MethodTransformer.analyze("fake", node, CapturedLambdaInterpreter())
|
||||
val loads = markers.map { marker ->
|
||||
val arity = (marker.next as MethodInsnNode).owner.removePrefix(NUMBERED_FUNCTION_PREFIX).toInt()
|
||||
var receiver = sourceFrames[node.instructions.indexOf(marker) + 1].getSource(arity)
|
||||
// Navigate the ALOAD+GETFIELD+... chain to the first instruction. We need to insert a stack
|
||||
// spilling marker before it starts.
|
||||
while (receiver?.opcode == Opcodes.GETFIELD) {
|
||||
receiver = sourceFrames[node.instructions.indexOf(receiver)].getSource(0)
|
||||
receiver = receiver.previous
|
||||
}
|
||||
receiver
|
||||
}
|
||||
@@ -244,3 +246,39 @@ fun FieldInsnNode.isSuspendLambdaCapturedByOuterObjectOrLambda(inliningContext:
|
||||
}
|
||||
return isCapturedSuspendLambda(container, name, inliningContext.state.bindingContext)
|
||||
}
|
||||
|
||||
// Interpreter, that keeps track of captured functional arguments
|
||||
private class PossibleLambdaLoad(val insn: AbstractInsnNode) : BasicValue(AsmTypes.OBJECT_TYPE)
|
||||
|
||||
private class CapturedLambdaInterpreter : BasicInterpreter(Opcodes.API_VERSION) {
|
||||
override fun newOperation(insn: AbstractInsnNode): BasicValue? {
|
||||
if (insn.opcode == Opcodes.GETSTATIC) {
|
||||
insn.fieldLoad()?.let { return it }
|
||||
}
|
||||
|
||||
return super.newOperation(insn)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.fieldLoad(): PossibleLambdaLoad? {
|
||||
if (this !is FieldInsnNode) return null
|
||||
if (desc.startsWith('L') && Type.getType(desc).internalName.isNumberedFunctionInternalName()) {
|
||||
if ((opcode == Opcodes.GETSTATIC && name.startsWith(CAPTURED_FIELD_FOLD_PREFIX + CAPTURED_FIELD_PREFIX)) ||
|
||||
(opcode == Opcodes.GETFIELD && isCapturedFieldName(name))
|
||||
) return PossibleLambdaLoad(this)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? =
|
||||
if (insn.opcode == Opcodes.ALOAD) PossibleLambdaLoad(insn) else super.copyOperation(insn, value)
|
||||
|
||||
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue?): BasicValue? {
|
||||
if (insn.opcode == Opcodes.GETFIELD) {
|
||||
insn.fieldLoad()?.let { return it }
|
||||
}
|
||||
return super.unaryOperation(insn, value)
|
||||
}
|
||||
|
||||
override fun merge(v: BasicValue?, w: BasicValue?): BasicValue? =
|
||||
if (v is PossibleLambdaLoad && w is PossibleLambdaLoad && v.insn == w.insn) v else super.merge(v, w)
|
||||
}
|
||||
@@ -205,11 +205,12 @@ private fun getInlineName(
|
||||
}
|
||||
|
||||
internal fun isInvokeOnLambda(owner: String, name: String): Boolean {
|
||||
return OperatorNameConventions.INVOKE.asString() == name &&
|
||||
owner.startsWith(NUMBERED_FUNCTION_PREFIX) &&
|
||||
owner.substring(NUMBERED_FUNCTION_PREFIX.length).isInteger()
|
||||
return OperatorNameConventions.INVOKE.asString() == name && owner.isNumberedFunctionInternalName()
|
||||
}
|
||||
|
||||
internal fun String.isNumberedFunctionInternalName(): Boolean =
|
||||
startsWith(NUMBERED_FUNCTION_PREFIX) && substring(NUMBERED_FUNCTION_PREFIX.length).isInteger()
|
||||
|
||||
internal fun isAnonymousConstructorCall(internalName: String, methodName: String): Boolean =
|
||||
isConstructor(methodName) && isAnonymousClass(internalName)
|
||||
|
||||
|
||||
@@ -33,7 +33,11 @@ class TrimMargin : IntrinsicMethod() {
|
||||
val marginPrefix = argument.valueArgument?.getArgumentExpression()
|
||||
?.let { codegen.getCompileTimeConstant(it) as? StringValue }
|
||||
?.value ?: return null
|
||||
literalText.trimMargin(marginPrefix)
|
||||
try {
|
||||
literalText.trimMargin(marginPrefix)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
else -> error("Unknown value argument type ${argument::class}: $argument")
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
|
||||
private class TransformerForMethod(val methodNode: MethodNode) {
|
||||
val instructions = methodNode.instructions
|
||||
val newLabelNodes = SmartIdentityTable<Label, LabelNode>()
|
||||
val newLabelNodes = SmartIdentityTable<LabelNode, LabelNode>()
|
||||
|
||||
fun transform() {
|
||||
if (rewriteLabelInstructions()) {
|
||||
@@ -48,11 +48,11 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
if (thisNode is LabelNode) {
|
||||
val prevNode = thisNode.previous
|
||||
if (prevNode is LabelNode) {
|
||||
newLabelNodes[thisNode.label] = prevNode
|
||||
newLabelNodes[thisNode] = prevNode
|
||||
removedAnyLabels = true
|
||||
thisNode = instructions.removeNodeGetNext(thisNode)
|
||||
} else {
|
||||
newLabelNodes[thisNode.label] = thisNode
|
||||
newLabelNodes[thisNode] = thisNode
|
||||
thisNode = thisNode.next
|
||||
}
|
||||
} else {
|
||||
@@ -145,12 +145,12 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun getNew(oldLabelNode: LabelNode): LabelNode {
|
||||
return newLabelNodes[oldLabelNode.label]
|
||||
return newLabelNodes[oldLabelNode]
|
||||
?: throw IllegalStateException("Label wasn't found during iterating through instructions")
|
||||
}
|
||||
|
||||
private fun getNewOrOld(oldLabelNode: LabelNode): LabelNode =
|
||||
newLabelNodes[oldLabelNode.label] ?: oldLabelNode
|
||||
newLabelNodes[oldLabelNode] ?: oldLabelNode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.optimization.nullCheck
|
||||
import org.jetbrains.kotlin.codegen.coroutines.withInstructionAdapter
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.debugText
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isInsn
|
||||
@@ -269,7 +270,7 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
|
||||
// <...> -- v is null here
|
||||
|
||||
val jumpsIfNull = insn.opcode == Opcodes.IFNULL
|
||||
val originalLabel = insn.label
|
||||
val originalLabel = insn.label.linkWithLabel()
|
||||
originalLabels[insn] = originalLabel
|
||||
insn.label = synthetic(LabelNode(Label()))
|
||||
|
||||
@@ -342,7 +343,7 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
|
||||
val originalLabel: LabelNode?
|
||||
val insertAfterNotNull: AbstractInsnNode
|
||||
if (jumpsIfInstance) {
|
||||
originalLabel = next.label
|
||||
originalLabel = next.label.linkWithLabel()
|
||||
originalLabels[next] = next.label
|
||||
val newLabel = synthetic(LabelNode(Label()))
|
||||
methodNode.instructions.add(newLabel)
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer.Companion.writeVersionRequirement
|
||||
@@ -202,7 +203,10 @@ class JvmSerializerExtension @JvmOverloads constructor(
|
||||
versionRequirementTable?.writeInlineParameterNullCheckRequirement(proto::addVersionRequirement)
|
||||
}
|
||||
|
||||
if (requiresFunctionNameManglingForReturnType(descriptor)) {
|
||||
if (requiresFunctionNameManglingForReturnType(descriptor) &&
|
||||
!DescriptorUtils.hasJvmNameAnnotation(descriptor) &&
|
||||
!requiresFunctionNameManglingForParameterTypes(descriptor)
|
||||
) {
|
||||
versionRequirementTable?.writeFunctionNameManglingForReturnTypeRequirement(proto::addVersionRequirement)
|
||||
}
|
||||
}
|
||||
@@ -267,7 +271,7 @@ class JvmSerializerExtension @JvmOverloads constructor(
|
||||
versionRequirementTable?.writeInlineParameterNullCheckRequirement(proto::addVersionRequirement)
|
||||
}
|
||||
|
||||
if (requiresFunctionNameManglingForReturnType(descriptor)) {
|
||||
if (!DescriptorUtils.hasJvmNameAnnotation(descriptor) && requiresFunctionNameManglingForReturnType(descriptor)) {
|
||||
versionRequirementTable?.writeFunctionNameManglingForReturnTypeRequirement(proto::addVersionRequirement)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
|
||||
@@ -24,10 +25,13 @@ fun getManglingSuffixBasedOnKotlinSignature(
|
||||
if (descriptor is ConstructorDescriptor) return null
|
||||
if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null
|
||||
|
||||
// Don't mangle functions with '@JvmName' annotation.
|
||||
// Some stdlib functions ('Result.success', 'Result.failure') are annotated with '@JvmName' as a workaround for forward compatibility.
|
||||
if (DescriptorUtils.hasJvmNameAnnotation(descriptor)) return null
|
||||
|
||||
// If a function accepts inline class parameters, mangle its name.
|
||||
val actualValueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
|
||||
if (requiresFunctionNameManglingForParameterTypes(actualValueParameterTypes)) {
|
||||
return "-" + md5base64(collectSignatureForMangling(actualValueParameterTypes))
|
||||
if (requiresFunctionNameManglingForParameterTypes(descriptor)) {
|
||||
return "-" + md5base64(collectSignatureForMangling(descriptor))
|
||||
}
|
||||
|
||||
// If a class member function returns inline class value, mangle its name.
|
||||
@@ -42,8 +46,10 @@ fun getManglingSuffixBasedOnKotlinSignature(
|
||||
return null
|
||||
}
|
||||
|
||||
private fun collectSignatureForMangling(types: List<KotlinType>) =
|
||||
types.joinToString { getSignatureElementForMangling(it) }
|
||||
private fun collectSignatureForMangling(descriptor: CallableMemberDescriptor): String {
|
||||
val types = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
|
||||
return types.joinToString { getSignatureElementForMangling(it) }
|
||||
}
|
||||
|
||||
private fun getSignatureElementForMangling(type: KotlinType): String = buildString {
|
||||
val descriptor = type.constructor.declarationDescriptor ?: return ""
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
@@ -99,8 +100,10 @@ abstract class TypeAnnotationCollector<T>(val context: TypeSystemCommonBackendCo
|
||||
abstract fun KotlinTypeMarker.extractAnnotations(): List<T>
|
||||
|
||||
fun isCompiledToJvm8OrHigher(descriptor: ClassDescriptor?): Boolean =
|
||||
(descriptor as? DeserializedClassDescriptor)?.let { classDescriptor ->
|
||||
((classDescriptor.source as? KotlinJvmBinarySourceElement)?.binaryClass as? FileBasedKotlinClass)?.classVersion ?: 0 >= Opcodes.V1_8
|
||||
} ?: true
|
||||
(descriptor as? DeserializedClassDescriptor)?.let { classDescriptor -> isCompiledToJvm8OrHigher(classDescriptor.source) }
|
||||
?: true
|
||||
|
||||
fun isCompiledToJvm8OrHigher(source: SourceElement): Boolean =
|
||||
(source !is KotlinJvmBinarySourceElement ||
|
||||
(source.binaryClass as? FileBasedKotlinClass)?.classVersion ?: 0 >= Opcodes.V1_8)
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(Buil
|
||||
PrintingMessageCollector(System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, false),
|
||||
false
|
||||
) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
// Only report diagnostics without a particular location because there's plenty of errors in built-in sources
|
||||
// (functions without bodies, incorrect combination of modifiers, etc.)
|
||||
if (location == null) {
|
||||
|
||||
@@ -352,6 +352,23 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var noKotlinNothingValueException: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xprofile",
|
||||
valueDescription = "<profilerPath:command:outputDir>",
|
||||
description = "Debug option: Run compiler with async profiler, save snapshots to outputDir, command is passed to async-profiler on start\n" +
|
||||
"You'll have to provide async-profiler.jar on classpath to use this\n" +
|
||||
"profilerPath is a path to libasyncProfiler.so\n" +
|
||||
"Example: -Xprofile=<PATH_TO_ASYNC_PROFILER>/async-profiler/build/libasyncProfiler.so:event=cpu,interval=1ms,threads,start,framebuf=50000000:<SNAPSHOT_DIR_PATH>"
|
||||
)
|
||||
var profileCompilerCommand: String? by NullableStringFreezableVar(null)
|
||||
|
||||
@Argument(
|
||||
value = "-Xrepeat",
|
||||
valueDescription = "<number>",
|
||||
description = "Debug option: Repeats modules compilation <number> times"
|
||||
)
|
||||
var repeatCompileModules: String? by NullableStringFreezableVar(null)
|
||||
|
||||
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
|
||||
val result = super.configureAnalysisFlags(collector)
|
||||
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
|
||||
|
||||
@@ -18,24 +18,61 @@ package org.jetbrains.kotlin.cli.common.messages
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
interface CompilerMessageSourceLocation : Serializable {
|
||||
val path: String
|
||||
val line: Int
|
||||
val column: Int
|
||||
val lineEnd: Int get() = -1
|
||||
val columnEnd: Int get() = -1
|
||||
val lineContent: String?
|
||||
}
|
||||
|
||||
data class CompilerMessageLocation private constructor(
|
||||
val path: String,
|
||||
val line: Int,
|
||||
val column: Int,
|
||||
val lineContent: String?
|
||||
) : Serializable {
|
||||
override val path: String,
|
||||
override val line: Int,
|
||||
override val column: Int,
|
||||
override val lineContent: String?
|
||||
) : CompilerMessageSourceLocation {
|
||||
override fun toString(): String =
|
||||
path + (if (line != -1 || column != -1) " ($line:$column)" else "")
|
||||
path + (if (line != -1 || column != -1) " ($line:$column)" else "")
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun create(path: String?): CompilerMessageLocation? =
|
||||
create(path, -1, -1, null)
|
||||
create(path, -1, -1, null)
|
||||
|
||||
@JvmStatic
|
||||
fun create(path: String?, line: Int, column: Int, lineContent: String?): CompilerMessageLocation? =
|
||||
if (path == null) null else CompilerMessageLocation(path, line, column, lineContent)
|
||||
if (path == null) null else CompilerMessageLocation(path, line, column, lineContent)
|
||||
|
||||
private val serialVersionUID: Long = 8228357578L
|
||||
}
|
||||
}
|
||||
|
||||
data class CompilerMessageLocationWithRange private constructor(
|
||||
override val path: String,
|
||||
override val line: Int,
|
||||
override val column: Int,
|
||||
override val lineEnd: Int,
|
||||
override val columnEnd: Int,
|
||||
override val lineContent: String?
|
||||
) : CompilerMessageSourceLocation {
|
||||
override fun toString(): String =
|
||||
path + (if (line != -1 || column != -1) " ($line:$column)" else "")
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun create(
|
||||
path: String?,
|
||||
lineStart: Int,
|
||||
columnStart: Int,
|
||||
lineEnd: Int?,
|
||||
columnEnd: Int?,
|
||||
lineContent: String?
|
||||
): CompilerMessageLocationWithRange? =
|
||||
if (path == null) null else CompilerMessageLocationWithRange(path, lineStart, columnStart, lineEnd ?: -1, columnEnd ?: -1, lineContent)
|
||||
|
||||
private val serialVersionUID: Long = 8228357578L
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public class FilteringMessageCollector implements MessageCollector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageLocation location) {
|
||||
public void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageSourceLocation location) {
|
||||
if (!decline.test(severity)) {
|
||||
messageCollector.report(severity, message, location);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GroupingMessageCollector implements MessageCollector {
|
||||
@@ -32,7 +31,7 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
private final boolean treatWarningsAsErrors;
|
||||
|
||||
// Note that the key in this map can be null
|
||||
private final Multimap<CompilerMessageLocation, Message> groupedMessages = LinkedHashMultimap.create();
|
||||
private final Multimap<CompilerMessageSourceLocation, Message> groupedMessages = LinkedHashMultimap.create();
|
||||
|
||||
public GroupingMessageCollector(@NotNull MessageCollector delegate, boolean treatWarningsAsErrors) {
|
||||
this.delegate = delegate;
|
||||
@@ -48,7 +47,7 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
public void report(
|
||||
@NotNull CompilerMessageSeverity severity,
|
||||
@NotNull String message,
|
||||
@Nullable CompilerMessageLocation location
|
||||
@Nullable CompilerMessageSourceLocation location
|
||||
) {
|
||||
if (CompilerMessageSeverity.VERBOSE.contains(severity)) {
|
||||
delegate.report(severity, message, location);
|
||||
@@ -78,9 +77,9 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
report(CompilerMessageSeverity.ERROR, "warnings found and -Werror specified", null);
|
||||
}
|
||||
|
||||
List<CompilerMessageLocation> sortedKeys =
|
||||
List<CompilerMessageSourceLocation> sortedKeys =
|
||||
CollectionsKt.sortedWith(groupedMessages.keySet(), Comparator.nullsFirst(CompilerMessageLocationComparator.INSTANCE));
|
||||
for (CompilerMessageLocation location : sortedKeys) {
|
||||
for (CompilerMessageSourceLocation location : sortedKeys) {
|
||||
for (Message message : groupedMessages.get(location)) {
|
||||
if (!hasExplicitErrors || message.severity.isError() || message.severity == CompilerMessageSeverity.STRONG_WARNING) {
|
||||
delegate.report(message.severity, message.message, message.location);
|
||||
@@ -91,7 +90,7 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
groupedMessages.clear();
|
||||
}
|
||||
|
||||
private static class CompilerMessageLocationComparator implements Comparator<CompilerMessageLocation> {
|
||||
private static class CompilerMessageLocationComparator implements Comparator<CompilerMessageSourceLocation> {
|
||||
public static final CompilerMessageLocationComparator INSTANCE = new CompilerMessageLocationComparator();
|
||||
|
||||
// First, output all messages without any location information. Then, only those with the file path.
|
||||
@@ -104,7 +103,7 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
// foo.kt:42: error: bad line
|
||||
// foo.kt:42:43: error: bad character
|
||||
@Override
|
||||
public int compare(CompilerMessageLocation o1, CompilerMessageLocation o2) {
|
||||
public int compare(CompilerMessageSourceLocation o1, CompilerMessageSourceLocation o2) {
|
||||
if (o1.getColumn() == -1 && o2.getColumn() != -1) return -1;
|
||||
if (o1.getColumn() != -1 && o2.getColumn() == -1) return 1;
|
||||
|
||||
@@ -118,9 +117,9 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
private static class Message {
|
||||
private final CompilerMessageSeverity severity;
|
||||
private final String message;
|
||||
private final CompilerMessageLocation location;
|
||||
private final CompilerMessageSourceLocation location;
|
||||
|
||||
private Message(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageLocation location) {
|
||||
private Message(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageSourceLocation location) {
|
||||
this.severity = severity;
|
||||
this.message = message;
|
||||
this.location = location;
|
||||
|
||||
@@ -19,13 +19,13 @@ package org.jetbrains.kotlin.cli.common.messages
|
||||
interface MessageCollector {
|
||||
fun clear()
|
||||
|
||||
fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation? = null)
|
||||
fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation? = null)
|
||||
|
||||
fun hasErrors(): Boolean
|
||||
|
||||
companion object {
|
||||
val NONE: MessageCollector = object : MessageCollector {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ plugins {
|
||||
dependencies {
|
||||
compile(project(":compiler:cli"))
|
||||
compile(project(":compiler:ir.serialization.js"))
|
||||
runtime(project(":kotlin-reflect"))
|
||||
runtimeOnly(project(":kotlin-reflect"))
|
||||
if (Platform[193].orLower()) {
|
||||
compile(intellijDep()) { includeJars("picocontainer", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
|
||||
protected abstract val performanceManager: CommonCompilerPerformanceManager
|
||||
|
||||
protected open fun createPerformanceManager(arguments: A): CommonCompilerPerformanceManager = performanceManager
|
||||
|
||||
// Used in CompilerRunnerUtil#invokeExecMethod, in Eclipse plugin (KotlinCLICompiler) and in kotlin-gradle-plugin (GradleCompilerRunner)
|
||||
fun execAndOutputXml(errStream: PrintStream, services: Services, vararg args: String): ExitCode {
|
||||
return exec(errStream, services, MessageRenderer.XML, args)
|
||||
@@ -56,7 +58,7 @@ abstract class CLICompiler<A : CommonCompilerArguments> : CLITool<A>() {
|
||||
}
|
||||
|
||||
public override fun execImpl(messageCollector: MessageCollector, services: Services, arguments: A): ExitCode {
|
||||
val performanceManager = performanceManager
|
||||
val performanceManager = createPerformanceManager(arguments)
|
||||
if (arguments.reportPerf || arguments.dumpPerf != null) {
|
||||
performanceManager.enableCollectingPerformanceStatistics()
|
||||
}
|
||||
|
||||
@@ -48,6 +48,9 @@ public class CLIConfigurationKeys {
|
||||
public static final CompilerConfigurationKey<PhaseConfig> PHASE_CONFIG =
|
||||
CompilerConfigurationKey.create("phase configuration");
|
||||
|
||||
public static final CompilerConfigurationKey<Integer> REPEAT_COMPILE_MODULES =
|
||||
CompilerConfigurationKey.create("debug key for profiling, repeats compileModules");
|
||||
|
||||
private CLIConfigurationKeys() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,4 +87,6 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str
|
||||
appendln("$presentableName performance report")
|
||||
measurements.map { it.render() }.sorted().forEach { appendln(it) }
|
||||
}.toByteArray()
|
||||
|
||||
open fun notifyRepeat(total: Int, number: Int) {}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,6 @@ interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
||||
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
|
||||
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
|
||||
render,
|
||||
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
|
||||
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumnRange(diagnostic))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.messages
|
||||
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
|
||||
/**
|
||||
* This class behaviour is the same as [MessageCollector.report] in [AnalyzerWithCompilerReport.reportDiagnostic].
|
||||
*/
|
||||
class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
|
||||
|
||||
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
||||
val messageCollector: MessageCollector
|
||||
|
||||
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
|
||||
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
|
||||
render,
|
||||
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
|
||||
)
|
||||
}
|
||||
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.cli.common.messages
|
||||
|
||||
class GradleStyleMessageRenderer : MessageRenderer {
|
||||
|
||||
override fun render(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?): String {
|
||||
override fun render(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?): String {
|
||||
val prefix = when (severity) {
|
||||
CompilerMessageSeverity.WARNING, CompilerMessageSeverity.STRONG_WARNING -> "w"
|
||||
CompilerMessageSeverity.ERROR, CompilerMessageSeverity.EXCEPTION -> "e"
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface MessageRenderer {
|
||||
MessageRenderer WITHOUT_PATHS = new PlainTextMessageRenderer() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getPath(@NotNull CompilerMessageLocation location) {
|
||||
protected String getPath(@NotNull CompilerMessageSourceLocation location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public interface MessageRenderer {
|
||||
MessageRenderer PLAIN_FULL_PATHS = new PlainTextMessageRenderer() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getPath(@NotNull CompilerMessageLocation location) {
|
||||
protected String getPath(@NotNull CompilerMessageSourceLocation location) {
|
||||
return location.getPath();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public interface MessageRenderer {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getPath(@NotNull CompilerMessageLocation location) {
|
||||
protected String getPath(@NotNull CompilerMessageSourceLocation location) {
|
||||
return FileUtilsKt.descendantRelativeTo(new File(location.getPath()), cwd).getPath();
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public interface MessageRenderer {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getPath(@NotNull CompilerMessageLocation location) {
|
||||
protected String getPath(@NotNull CompilerMessageSourceLocation location) {
|
||||
return FileUtil.toSystemIndependentName(
|
||||
FileUtilsKt.descendantRelativeTo(new File(location.getPath()), cwd).getPath()
|
||||
);
|
||||
@@ -91,7 +91,7 @@ public interface MessageRenderer {
|
||||
|
||||
String renderPreamble();
|
||||
|
||||
String render(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageLocation location);
|
||||
String render(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageSourceLocation location);
|
||||
|
||||
String renderUsage(@NotNull String usage);
|
||||
|
||||
|
||||
@@ -32,21 +32,23 @@ public class MessageUtil {
|
||||
private MessageUtil() {}
|
||||
|
||||
@Nullable
|
||||
public static CompilerMessageLocation psiElementToMessageLocation(@Nullable PsiElement element) {
|
||||
public static CompilerMessageSourceLocation psiElementToMessageLocation(@Nullable PsiElement element) {
|
||||
if (element == null) return null;
|
||||
PsiFile file = element.getContainingFile();
|
||||
return psiFileToMessageLocation(file, "<no path>", DiagnosticUtils.getLineAndColumnInPsiFile(file, element.getTextRange()));
|
||||
return psiFileToMessageLocation(file, "<no path>", DiagnosticUtils.getLineAndColumnRangeInPsiFile(file, element.getTextRange()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CompilerMessageLocation psiFileToMessageLocation(
|
||||
public static CompilerMessageSourceLocation psiFileToMessageLocation(
|
||||
@NotNull PsiFile file,
|
||||
@Nullable String defaultValue,
|
||||
@NotNull PsiDiagnosticUtils.LineAndColumn lineAndColumn
|
||||
@NotNull PsiDiagnosticUtils.LineAndColumnRange range
|
||||
) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
String path = virtualFile != null ? virtualFileToPath(virtualFile) : defaultValue;
|
||||
return CompilerMessageLocation.create(path, lineAndColumn.getLine(), lineAndColumn.getColumn(), lineAndColumn.getLineContent());
|
||||
PsiDiagnosticUtils.LineAndColumn start = range.getStart();
|
||||
PsiDiagnosticUtils.LineAndColumn end = range.getEnd();
|
||||
return CompilerMessageLocationWithRange.create(path, start.getLine(), start.getColumn(), end.getLine(), end.getColumn(), start.getLineContent());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.messages;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils;
|
||||
|
||||
import static com.intellij.openapi.util.io.FileUtil.toSystemDependentName;
|
||||
|
||||
public class MessageUtil {
|
||||
private MessageUtil() {}
|
||||
|
||||
@Nullable
|
||||
public static CompilerMessageLocation psiElementToMessageLocation(@Nullable PsiElement element) {
|
||||
if (element == null) return null;
|
||||
PsiFile file = element.getContainingFile();
|
||||
return psiFileToMessageLocation(file, "<no path>", DiagnosticUtils.getLineAndColumnInPsiFile(file, element.getTextRange()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CompilerMessageLocation psiFileToMessageLocation(
|
||||
@NotNull PsiFile file,
|
||||
@Nullable String defaultValue,
|
||||
@NotNull PsiDiagnosticUtils.LineAndColumn lineAndColumn
|
||||
) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
String path = virtualFile != null ? virtualFileToPath(virtualFile) : defaultValue;
|
||||
return CompilerMessageLocation.create(path, lineAndColumn.getLine(), lineAndColumn.getColumn(), lineAndColumn.getLineContent());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String virtualFileToPath(@NotNull VirtualFile virtualFile) {
|
||||
return toSystemDependentName(virtualFile.getPath());
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageLocation location) {
|
||||
public String render(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageSourceLocation location) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
int line = location != null ? location.getLine() : -1;
|
||||
@@ -156,7 +156,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract String getPath(@NotNull CompilerMessageLocation location);
|
||||
protected abstract String getPath(@NotNull CompilerMessageSourceLocation location);
|
||||
|
||||
@Override
|
||||
public String renderUsage(@NotNull String usage) {
|
||||
|
||||
@@ -42,7 +42,7 @@ public class PrintingMessageCollector implements MessageCollector {
|
||||
public void report(
|
||||
@NotNull CompilerMessageSeverity severity,
|
||||
@NotNull String message,
|
||||
@Nullable CompilerMessageLocation location
|
||||
@Nullable CompilerMessageSourceLocation location
|
||||
) {
|
||||
if (!verbose && CompilerMessageSeverity.VERBOSE.contains(severity)) return;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class XmlMessageRenderer implements MessageRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageLocation location) {
|
||||
public String render(@NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageSourceLocation location) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
String tagName = severity.getPresentableName();
|
||||
out.append("<").append(tagName);
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.profiling
|
||||
|
||||
import java.lang.invoke.MethodHandles
|
||||
import java.lang.invoke.MethodType
|
||||
|
||||
interface AsyncProfilerReflected {
|
||||
fun execute(command: String): String
|
||||
fun stop()
|
||||
val version: String
|
||||
}
|
||||
|
||||
|
||||
|
||||
object AsyncProfilerHelper {
|
||||
private val profilerClass = Class.forName("one.profiler.AsyncProfiler")
|
||||
private val getInstanceHandle =
|
||||
MethodHandles.lookup().findStatic(profilerClass, "getInstance", MethodType.methodType(profilerClass, String::class.java))
|
||||
private val executeHandle =
|
||||
MethodHandles.lookup().findVirtual(
|
||||
profilerClass,
|
||||
"execute",
|
||||
MethodType.methodType(String::class.java, String::class.java)
|
||||
)
|
||||
private val stopHandle =
|
||||
MethodHandles.lookup().findVirtual(profilerClass, "stop", MethodType.methodType(Void.TYPE))
|
||||
private val getVersionHandle =
|
||||
MethodHandles.lookup().findVirtual(profilerClass, "getVersion", MethodType.methodType(String::class.java))
|
||||
|
||||
fun getInstance(libPath: String?): AsyncProfilerReflected {
|
||||
val instance = getInstanceHandle.invokeWithArguments(libPath)
|
||||
return object : AsyncProfilerReflected {
|
||||
private val boundExecute = executeHandle.bindTo(instance)
|
||||
private val boundStop = stopHandle.bindTo(instance)
|
||||
private val boundGetVersion = getVersionHandle.bindTo(instance)
|
||||
|
||||
override fun execute(command: String): String {
|
||||
return boundExecute.invokeWithArguments(command) as String
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
boundStop.invokeWithArguments()
|
||||
}
|
||||
|
||||
override val version: String
|
||||
get() = boundGetVersion.invokeWithArguments() as String
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.profiling
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class ProfilingCompilerPerformanceManager(
|
||||
profilerPath: String,
|
||||
val command: String,
|
||||
val outputDir: File
|
||||
) : CommonCompilerPerformanceManager("Profiling") {
|
||||
private val profiler = AsyncProfilerHelper.getInstance(profilerPath)
|
||||
|
||||
private val runDate = Date()
|
||||
private val formatter = SimpleDateFormat("yyyy-MM-dd__HH-mm")
|
||||
private var active = false
|
||||
|
||||
init {
|
||||
startProfiling()
|
||||
}
|
||||
|
||||
private fun startProfiling() {
|
||||
profiler.execute(command)
|
||||
active = true
|
||||
}
|
||||
|
||||
private fun stopProfiling() {
|
||||
if (active) profiler.stop()
|
||||
active = false
|
||||
}
|
||||
|
||||
private fun restartProfiling() {
|
||||
stopProfiling()
|
||||
startProfiling()
|
||||
}
|
||||
|
||||
private fun dumpProfile(postfix: String) {
|
||||
outputDir.mkdirs()
|
||||
val outputFile = outputDir.resolve("snapshot-${formatter.format(runDate)}-$postfix.collapsed")
|
||||
outputFile.writeText(profiler.execute("collapsed"))
|
||||
active = false
|
||||
}
|
||||
|
||||
override fun notifyRepeat(total: Int, number: Int) {
|
||||
dumpProfile("repeat$number")
|
||||
restartProfiling()
|
||||
}
|
||||
|
||||
override fun notifyCompilationFinished() {
|
||||
dumpProfile("final")
|
||||
stopProfiling()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun create(profileCompilerArgument: String): ProfilingCompilerPerformanceManager {
|
||||
val (path, command, outputDir) = profileCompilerArgument.split(":", limit = 3)
|
||||
return ProfilingCompilerPerformanceManager(path, command, File(outputDir))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageUtil
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
import org.jetbrains.kotlin.cli.common.modules.ModuleBuilder
|
||||
import org.jetbrains.kotlin.cli.common.modules.ModuleChunk
|
||||
import org.jetbrains.kotlin.cli.common.profiling.ProfilingCompilerPerformanceManager
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentUtil
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
@@ -50,8 +51,6 @@ import java.io.File
|
||||
|
||||
class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
|
||||
override val performanceManager = K2JVMCompilerPerformanceManager()
|
||||
|
||||
override fun doExecute(
|
||||
arguments: K2JVMCompilerArguments,
|
||||
configuration: CompilerConfiguration,
|
||||
@@ -60,6 +59,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
): ExitCode {
|
||||
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
|
||||
configuration.putIfNotNull(CLIConfigurationKeys.REPEAT_COMPILE_MODULES, arguments.repeatCompileModules?.toIntOrNull())
|
||||
configuration.put(CLIConfigurationKeys.PHASE_CONFIG, createPhaseConfig(jvmPhases, arguments, messageCollector))
|
||||
|
||||
if (!configuration.configureJdkHome(arguments)) return COMPILATION_ERROR
|
||||
@@ -219,7 +219,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
|
||||
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
|
||||
performanceManager.notifyCompilerInitialized()
|
||||
configuration[CLIConfigurationKeys.PERF_MANAGER]?.notifyCompilerInitialized()
|
||||
|
||||
return if (messageCollector.hasErrors()) null else environment
|
||||
}
|
||||
@@ -263,6 +263,14 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override val performanceManager: CommonCompilerPerformanceManager
|
||||
get() = error("Unsupported")
|
||||
|
||||
override fun createPerformanceManager(arguments: K2JVMCompilerArguments): CommonCompilerPerformanceManager {
|
||||
val argument = arguments.profileCompilerCommand ?: return K2JVMCompilerPerformanceManager()
|
||||
return ProfilingCompilerPerformanceManager.create(argument)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -86,5 +86,7 @@ class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) :
|
||||
|
||||
override fun analyze(element: KtElement) = traceHolder.bindingContext
|
||||
|
||||
override fun analyzeAnnotation(element: KtAnnotationEntry) = traceHolder.bindingContext.get(BindingContext.ANNOTATION, element)
|
||||
|
||||
override fun analyzeWithContent(element: KtClassOrObject) = traceHolder.bindingContext
|
||||
}
|
||||
|
||||
@@ -162,9 +162,24 @@ object KotlinToJVMBytecodeCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun compileModules(environment: KotlinCoreEnvironment, buildFile: File?, chunk: List<Module>): Boolean {
|
||||
internal fun compileModules(
|
||||
environment: KotlinCoreEnvironment,
|
||||
buildFile: File?,
|
||||
chunk: List<Module>,
|
||||
repeat: Boolean = false
|
||||
): Boolean {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
|
||||
val repeats = environment.configuration[CLIConfigurationKeys.REPEAT_COMPILE_MODULES]
|
||||
if (repeats != null && !repeat) {
|
||||
val performanceManager = environment.configuration[CLIConfigurationKeys.PERF_MANAGER]
|
||||
return (0 until repeats).map {
|
||||
val result = compileModules(environment, buildFile, chunk, repeat = true)
|
||||
performanceManager?.notifyRepeat(repeats, it)
|
||||
result
|
||||
}.last()
|
||||
}
|
||||
|
||||
val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
|
||||
for (module in chunk) {
|
||||
moduleVisibilityManager.addModule(module)
|
||||
@@ -289,6 +304,8 @@ object KotlinToJVMBytecodeCompiler {
|
||||
|
||||
private fun compileModulesUsingFrontendIR(environment: KotlinCoreEnvironment, buildFile: File?, chunk: List<Module>): Boolean {
|
||||
val project = environment.project
|
||||
val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER)
|
||||
|
||||
Extensions.getArea(project)
|
||||
.getExtensionPoint(PsiElementFinder.EP_NAME)
|
||||
.unregisterExtension(JavaElementFinder::class.java)
|
||||
@@ -297,6 +314,7 @@ object KotlinToJVMBytecodeCompiler {
|
||||
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||
val outputs = newLinkedHashMapWithExpectedSize<Module, GenerationState>(chunk.size)
|
||||
for (module in chunk) {
|
||||
performanceManager?.notifyAnalysisStarted()
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
|
||||
val ktFiles = module.getSourceFiles(environment, localFileSystem, chunk.size > 1, buildFile)
|
||||
@@ -349,6 +367,11 @@ object KotlinToJVMBytecodeCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
val debugTargetDescription = "target " + module.getModuleName() + "-" + module.getModuleType() + " "
|
||||
val codeLines = environment.countLinesOfCode(ktFiles)
|
||||
performanceManager?.notifyAnalysisFinished(ktFiles.size, codeLines, debugTargetDescription)
|
||||
|
||||
performanceManager?.notifyGenerationStarted()
|
||||
val signaturer = IdSignatureDescriptor(JvmManglerDesc())
|
||||
|
||||
val (moduleFragment, symbolTable, sourceManager, components) =
|
||||
@@ -379,8 +402,7 @@ object KotlinToJVMBytecodeCompiler {
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
|
||||
val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER)
|
||||
performanceManager?.notifyGenerationStarted()
|
||||
|
||||
generationState.beforeCompile()
|
||||
codegenFactory.generateModuleInFrontendIRMode(
|
||||
generationState, moduleFragment, symbolTable, sourceManager
|
||||
@@ -391,8 +413,8 @@ object KotlinToJVMBytecodeCompiler {
|
||||
generationState.factory.done()
|
||||
performanceManager?.notifyGenerationFinished(
|
||||
ktFiles.size,
|
||||
environment.countLinesOfCode(ktFiles),
|
||||
additionalDescription = "target " + module.getModuleName() + "-" + module.getModuleType() + " "
|
||||
codeLines,
|
||||
additionalDescription = debugTargetDescription
|
||||
)
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.compiler.plugin.*
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
import java.util.*
|
||||
|
||||
object PluginCliParser {
|
||||
@JvmStatic
|
||||
@@ -78,44 +77,52 @@ object PluginCliParser {
|
||||
configuration: CompilerConfiguration,
|
||||
classLoader: URLClassLoader
|
||||
) {
|
||||
val optionValuesByPlugin = pluginOptions?.map(::parsePluginOption)?.groupBy {
|
||||
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
|
||||
it.pluginId
|
||||
} ?: mapOf()
|
||||
|
||||
// TODO issue a warning on using deprecated command line processors when all official plugin migrate to the newer convention
|
||||
val commandLineProcessors = ServiceLoaderLite.loadImplementations(CommandLineProcessor::class.java, classLoader)
|
||||
|
||||
for (processor in commandLineProcessors) {
|
||||
val declaredOptions = processor.pluginOptions.associateBy { it.optionName }
|
||||
val optionsToValues = MultiMap<AbstractCliOption, CliOptionValue>()
|
||||
processCompilerPluginsOptions(configuration, pluginOptions, commandLineProcessors)
|
||||
}
|
||||
}
|
||||
|
||||
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
|
||||
val option = declaredOptions[optionValue!!.optionName]
|
||||
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
|
||||
optionsToValues.putValue(option, optionValue)
|
||||
fun processCompilerPluginsOptions(
|
||||
configuration: CompilerConfiguration,
|
||||
pluginOptions: Iterable<String>?,
|
||||
commandLineProcessors: List<CommandLineProcessor>
|
||||
) {
|
||||
val optionValuesByPlugin = pluginOptions?.map(::parsePluginOption)?.groupBy {
|
||||
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
|
||||
it.pluginId
|
||||
} ?: mapOf()
|
||||
|
||||
for (processor in commandLineProcessors) {
|
||||
val declaredOptions = processor.pluginOptions.associateBy { it.optionName }
|
||||
val optionsToValues = MultiMap<AbstractCliOption, CliOptionValue>()
|
||||
|
||||
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
|
||||
val option = declaredOptions[optionValue!!.optionName]
|
||||
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
|
||||
optionsToValues.putValue(option, optionValue)
|
||||
}
|
||||
|
||||
for (option in processor.pluginOptions) {
|
||||
val values = optionsToValues[option]
|
||||
if (option.required && values.isEmpty()) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Required plugin option not present: ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
if (!option.allowMultipleOccurrences && values.size > 1) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Multiple values are not allowed for plugin option ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
|
||||
for (option in processor.pluginOptions) {
|
||||
val values = optionsToValues[option]
|
||||
if (option.required && values.isEmpty()) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Required plugin option not present: ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
if (!option.allowMultipleOccurrences && values.size > 1) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Multiple values are not allowed for plugin option ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
|
||||
for (value in values) {
|
||||
processor.processOption(option, value.value, configuration)
|
||||
}
|
||||
for (value in values) {
|
||||
processor.processOption(option, value.value, configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.config.K2MetadataConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
||||
import org.jetbrains.kotlin.codegen.CompilationException
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
description = "Kotlin Daemon"
|
||||
|
||||
plugins {
|
||||
@@ -21,10 +19,10 @@ dependencies {
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeJars("trove4j") }
|
||||
|
||||
runtime(project(":kotlin-reflect"))
|
||||
runtimeOnly(project(":kotlin-reflect"))
|
||||
|
||||
embedded(project(":daemon-common")) { isTransitive = false }
|
||||
compile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) {
|
||||
api(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) {
|
||||
isTransitive = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,21 @@
|
||||
package org.jetbrains.kotlin.daemon.client.experimental
|
||||
|
||||
import io.ktor.network.sockets.Socket
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.daemon.client.CompileServiceSessionAsync
|
||||
import org.jetbrains.kotlin.daemon.client.KotlinCompilerDaemonClient
|
||||
import org.jetbrains.kotlin.daemon.client.DaemonReportMessage
|
||||
import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets
|
||||
import org.jetbrains.kotlin.daemon.client.KotlinCompilerDaemonClient
|
||||
import org.jetbrains.kotlin.daemon.client.launchProcessWithFallback
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.daemon.common.Profiler
|
||||
import org.jetbrains.kotlin.daemon.common.experimental.*
|
||||
import org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure.Server
|
||||
import org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure.ServerSocketWrapper
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
import java.net.SocketException
|
||||
@@ -30,7 +32,6 @@ import java.util.concurrent.Semaphore
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.logging.Logger
|
||||
import kotlin.concurrent.thread
|
||||
import org.jetbrains.kotlin.daemon.client.launchProcessWithFallback
|
||||
|
||||
|
||||
class KotlinCompilerClient : KotlinCompilerDaemonClient {
|
||||
|
||||
@@ -32,8 +32,8 @@ dependencies {
|
||||
nativePlatformVariants.forEach {
|
||||
embedded(commonDep("net.rubygrapefruit", "native-platform", "-$it"))
|
||||
}
|
||||
runtime(project(":kotlin-reflect"))
|
||||
compile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) {
|
||||
runtimeOnly(project(":kotlin-reflect"))
|
||||
api(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) {
|
||||
isTransitive = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.client
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
@@ -66,7 +66,7 @@ fun MessageCollector.reportFromDaemon(outputsCollector: ((File, List<File>) -> U
|
||||
else -> throw IllegalStateException("Unexpected compiler message report severity $severity")
|
||||
}
|
||||
if (message != null) {
|
||||
report(compilerSeverity, message, attachment as? CompilerMessageLocation)
|
||||
report(compilerSeverity, message, attachment as? CompilerMessageSourceLocation)
|
||||
}
|
||||
else {
|
||||
reportUnexpected(category, severity, message, attachment)
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.daemon
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
@@ -181,7 +181,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
||||
}
|
||||
|
||||
class TestMessageCollector : MessageCollector {
|
||||
data class Message(val severity: CompilerMessageSeverity, val message: String, val location: CompilerMessageLocation?)
|
||||
data class Message(val severity: CompilerMessageSeverity, val message: String, val location: CompilerMessageSourceLocation?)
|
||||
|
||||
val messages = arrayListOf<Message>()
|
||||
|
||||
@@ -189,7 +189,7 @@ class TestMessageCollector : MessageCollector {
|
||||
messages.clear()
|
||||
}
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
messages.add(Message(severity, message, location))
|
||||
}
|
||||
|
||||
|
||||
@@ -685,13 +685,13 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
||||
else -> "?"
|
||||
}
|
||||
val compiledPort: Int? = daemonInfo.trim().split(" ").last().toIntOrNull()
|
||||
appendln("#$i\tcompiled on $daemonInfo, session ${daemonInfos[i]?.second}, result ${resultCodes[i]}; started daemon on port ${port2logs[i]?.first}, log: ${logFiles[i]?.canonicalPath}")
|
||||
appendLine("#$i\tcompiled on $daemonInfo, session ${daemonInfos[i]?.second}, result ${resultCodes[i]}; started daemon on port ${port2logs[i]?.first}, log: ${logFiles[i]?.canonicalPath}")
|
||||
if (resultCodes[i] != 0 || electionLogs[i] == null) {
|
||||
appendln("--- out $i, result ${resultCodes[i]}:\n${outStreams[i].toByteArray().toString(Charset.defaultCharset())}\n---")
|
||||
appendLine("--- out $i, result ${resultCodes[i]}:\n${outStreams[i].toByteArray().toString(Charset.defaultCharset())}\n---")
|
||||
compiledPort?.let { port -> port2logs.find { it?.first == port } }?.second?.let { logFile ->
|
||||
appendln("--- log file ${logFile.name}:\n${logFile.readText()}\n---")
|
||||
appendLine("--- log file ${logFile.name}:\n${logFile.readText()}\n---")
|
||||
}
|
||||
?: appendln("--- log not found (port: $compiledPort)")
|
||||
?: appendLine("--- log not found (port: $compiledPort)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -917,20 +917,20 @@ internal fun generateLargeKotlinFile(size: Int): String {
|
||||
return buildString {
|
||||
append("package large\n\n")
|
||||
(0..size).forEach {
|
||||
appendln("class Class$it")
|
||||
appendln("{")
|
||||
appendln("\tfun foo(): Long = $it")
|
||||
appendln("}")
|
||||
appendln("\n")
|
||||
appendLine("class Class$it")
|
||||
appendLine("{")
|
||||
appendLine("\tfun foo(): Long = $it")
|
||||
appendLine("}")
|
||||
appendLine("\n")
|
||||
repeat(2000) {
|
||||
appendln("// kotlin rules ... and stuff")
|
||||
appendLine("// kotlin rules ... and stuff")
|
||||
}
|
||||
}
|
||||
appendln("fun main(args: Array<String>)")
|
||||
appendln("{")
|
||||
appendln("\tval result = Class5().foo() + Class$size().foo()")
|
||||
appendln("\tprintln(result)")
|
||||
appendln("}")
|
||||
appendLine("fun main(args: Array<String>)")
|
||||
appendLine("{")
|
||||
appendLine("\tval result = Class5().foo() + Class$size().foo()")
|
||||
appendLine("\tprintln(result)")
|
||||
appendLine("}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.daemon.experimental.integration
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
@@ -301,7 +301,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
||||
}
|
||||
|
||||
class TestMessageCollector : MessageCollector {
|
||||
data class Message(val severity: CompilerMessageSeverity, val message: String, val location: CompilerMessageLocation?)
|
||||
data class Message(val severity: CompilerMessageSeverity, val message: String, val location: CompilerMessageSourceLocation?)
|
||||
|
||||
val messages = arrayListOf<Message>()
|
||||
|
||||
@@ -309,7 +309,7 @@ class TestMessageCollector : MessageCollector {
|
||||
messages.clear()
|
||||
}
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
messages.add(Message(severity, message, location))
|
||||
}
|
||||
|
||||
|
||||
@@ -980,13 +980,13 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
||||
else -> "?"
|
||||
}
|
||||
val compiledPort: Int? = daemonInfo.trim().split(" ").last().toIntOrNull()
|
||||
appendln("#$i\tcompiled on $daemonInfo, session ${daemonInfos[i]?.second}, result ${resultCodes[i]}; started daemon on port ${port2logs[i]?.first}, log: ${logFiles[i]?.canonicalPath}")
|
||||
appendLine("#$i\tcompiled on $daemonInfo, session ${daemonInfos[i]?.second}, result ${resultCodes[i]}; started daemon on port ${port2logs[i]?.first}, log: ${logFiles[i]?.canonicalPath}")
|
||||
if (resultCodes[i] != 0 || electionLogs[i] == null) {
|
||||
appendln("--- out $i, result ${resultCodes[i]}:\n${outStreams[i].toByteArray().toString(Charset.defaultCharset())}\n---")
|
||||
appendLine("--- out $i, result ${resultCodes[i]}:\n${outStreams[i].toByteArray().toString(Charset.defaultCharset())}\n---")
|
||||
compiledPort?.let { port -> port2logs.find { it?.first == port } }?.second?.let { logFile ->
|
||||
appendln("--- log file ${logFile.name}:\n${logFile.readText()}\n---")
|
||||
appendLine("--- log file ${logFile.name}:\n${logFile.readText()}\n---")
|
||||
}
|
||||
?: appendln("--- log not found (port: $compiledPort)")
|
||||
?: appendLine("--- log not found (port: $compiledPort)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1371,20 +1371,20 @@ internal fun generateLargeKotlinFile(size: Int): String {
|
||||
return buildString {
|
||||
append("package large\n\n")
|
||||
(0..size).forEach {
|
||||
appendln("class Class$it")
|
||||
appendln("{")
|
||||
appendln("\tfun foo(): Long = $it")
|
||||
appendln("}")
|
||||
appendln("\n")
|
||||
appendLine("class Class$it")
|
||||
appendLine("{")
|
||||
appendLine("\tfun foo(): Long = $it")
|
||||
appendLine("}")
|
||||
appendLine("\n")
|
||||
repeat(2000) {
|
||||
appendln("// kotlin rules ... and stuff")
|
||||
appendLine("// kotlin rules ... and stuff")
|
||||
}
|
||||
}
|
||||
appendln("fun main(args: Array<String>)")
|
||||
appendln("{")
|
||||
appendln("\tval result = Class5().foo() + Class$size().foo()")
|
||||
appendln("\tprintln(result)")
|
||||
appendln("}")
|
||||
appendLine("fun main(args: Array<String>)")
|
||||
appendLine("{")
|
||||
appendLine("\tval result = Class5().foo() + Class$size().foo()")
|
||||
appendLine("\tprintln(result)")
|
||||
appendLine("}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -168,9 +168,9 @@ internal class KeepFirstErrorMessageCollector(compilerMessagesStream: PrintStrea
|
||||
private val innerCollector = PrintingMessageCollector(compilerMessagesStream, MessageRenderer.WITHOUT_PATHS, false)
|
||||
|
||||
internal var firstErrorMessage: String? = null
|
||||
internal var firstErrorLocation: CompilerMessageLocation? = null
|
||||
internal var firstErrorLocation: CompilerMessageSourceLocation? = null
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
if (firstErrorMessage == null && severity.isError) {
|
||||
firstErrorMessage = message
|
||||
firstErrorLocation = location
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.report
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
@@ -34,7 +34,7 @@ internal class CompileServicesFacadeMessageCollector(
|
||||
hasErrors = false
|
||||
}
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
log.info("Message: " + MessageRenderer.WITHOUT_PATHS.render(severity, message, location))
|
||||
when (severity) {
|
||||
CompilerMessageSeverity.OUTPUT -> {
|
||||
|
||||
@@ -5,17 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.report.experimental
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.async
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
import org.jetbrains.kotlin.daemon.KotlinCompileDaemon.log
|
||||
import org.jetbrains.kotlin.daemon.common.CompilationOptions
|
||||
import org.jetbrains.kotlin.daemon.common.ReportCategory
|
||||
import org.jetbrains.kotlin.daemon.common.ReportSeverity
|
||||
import org.jetbrains.kotlin.daemon.common.CompilerServicesFacadeBaseAsync
|
||||
import org.jetbrains.kotlin.daemon.common.report
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
|
||||
internal class CompileServicesFacadeMessageCollector(
|
||||
private val servicesFacade: CompilerServicesFacadeBaseAsync,
|
||||
@@ -28,7 +25,7 @@ internal class CompileServicesFacadeMessageCollector(
|
||||
hasErrors = false
|
||||
}
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
GlobalScope.async {
|
||||
log.info("Message: " + MessageRenderer.WITHOUT_PATHS.render(severity, message, location))
|
||||
when (severity) {
|
||||
|
||||
@@ -5,7 +5,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
|
||||
public final class Class : R|kotlin/Any| {
|
||||
public final val property: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
@R|test/Anno|() public get(): R|kotlin/Int|
|
||||
|
||||
public constructor(): R|test/Class|
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public final class Class : R|kotlin/Any| {
|
||||
public final var property: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
@R|test/Anno|() public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/Class|
|
||||
|
||||
|
||||
@@ -16,15 +16,15 @@ public final annotation class B : R|kotlin/Annotation| {
|
||||
|
||||
public abstract interface I : R|kotlin/Any| {
|
||||
public abstract var getterAndSetter: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
@R|test/A|(value = String(getter)) public get(): R|kotlin/Int|
|
||||
@R|test/B|(value = <implicitArrayOf>(String(setter))) public set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public abstract var propertyAndGetter: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
@R|test/B|(value = <implicitArrayOf>(String(getter))) public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public abstract var propertyAndSetter: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
@R|test/B|(value = <implicitArrayOf>(String(setter))) public set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ public final class A : R|kotlin/Any| {
|
||||
|
||||
public final var R|kotlin/String|.myLength3: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(v: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/A|
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public final class Test : R|kotlin/Any| {
|
||||
|
||||
public final var prop2: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
protected set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
protected set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final val prop3: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
@@ -27,7 +27,7 @@ public final class Test : R|kotlin/Any| {
|
||||
|
||||
public final var prop7: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(i: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
private constructor(): R|test/Test.Companion|
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ public abstract interface Test : R|kotlin/Any| {
|
||||
|
||||
public final var prop2: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
protected set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
protected set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final val prop3: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
@@ -25,7 +25,7 @@ public abstract interface Test : R|kotlin/Any| {
|
||||
|
||||
public final var prop7: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(i: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
private constructor(): R|test/Test.Companion|
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public final class ExtPropInClass : R|kotlin/Any| {
|
||||
public final var R|kotlin/Int|.itIs: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(p: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/ExtPropInClass|
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public final class ExtValInClass<P> : R|kotlin/Any| {
|
||||
public final var R|kotlin/Int|.asas: R|P|
|
||||
public get(): R|P|
|
||||
public set(value: R|P|): R|kotlin/Unit|
|
||||
public set(p: R|P|): R|kotlin/Unit|
|
||||
|
||||
public constructor<P>(): R|test/ExtValInClass<P>|
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public final class ExtValInClass<P> : R|kotlin/Any| {
|
||||
public final var R|kotlin/Int|.asas: R|P?|
|
||||
public get(): R|P?|
|
||||
public set(value: R|P?|): R|kotlin/Unit|
|
||||
public set(p: R|P?|): R|kotlin/Unit|
|
||||
|
||||
public constructor<P>(): R|test/ExtValInClass<P>|
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public final class ExtValPIntInClass<P> : R|kotlin/Any| {
|
||||
public final var R|P|.asas: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(p: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor<P>(): R|test/ExtValPIntInClass<P>|
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public final class ExtValPIntInClass<P> : R|kotlin/Any| {
|
||||
public final var R|P?|.asas: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(p: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor<P>(): R|test/ExtValPIntInClass<P>|
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public final class A : R|kotlin/Any| {
|
||||
public final var a: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/A|
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ public open class ClassVarModality : R|kotlin/Any| {
|
||||
|
||||
internal final var property4: R|kotlin/Int|
|
||||
internal get(): R|kotlin/Int|
|
||||
private set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
private set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/ClassVarModality|
|
||||
|
||||
@@ -22,7 +22,7 @@ public open class ClassVarModality : R|kotlin/Any| {
|
||||
public abstract class ClassVarModalityAbstract : R|kotlin/Any| {
|
||||
public abstract var property1: R|java/util/Date|
|
||||
public get(): R|java/util/Date|
|
||||
public set(value: R|java/util/Date|): R|kotlin/Unit|
|
||||
public set(<set-?>: R|java/util/Date|): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/ClassVarModalityAbstract|
|
||||
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
public final class ClassVal : R|kotlin/Any| {
|
||||
public final var property1: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final var property10: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
protected set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
protected set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final var property11: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
internal set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
internal set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final var property2: R|java/lang/Object|
|
||||
public get(): R|java/lang/Object|
|
||||
protected set(value: R|java/lang/Object|): R|kotlin/Unit|
|
||||
protected set(<set-?>: R|java/lang/Object|): R|kotlin/Unit|
|
||||
|
||||
public final var property3: R|java/lang/Object|
|
||||
public get(): R|java/lang/Object|
|
||||
private set(value: R|java/lang/Object|): R|kotlin/Unit|
|
||||
private set(<set-?>: R|java/lang/Object|): R|kotlin/Unit|
|
||||
|
||||
protected final var property4: R|kotlin/String|
|
||||
protected get(): R|kotlin/String|
|
||||
protected set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
protected set(<set-?>: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
protected final var property5: R|kotlin/String|
|
||||
protected get(): R|kotlin/String|
|
||||
private set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
private set(<set-?>: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
public final var property8: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final var property9: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
private set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
private set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/ClassVal|
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ public final class PrivateClassMembers : R|kotlin/Any| {
|
||||
|
||||
private final var r: R|kotlin/Int|
|
||||
private get(): R|kotlin/Int|
|
||||
private set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
private set(<set-?>: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
private final val v: R|kotlin/Int|
|
||||
private get(): R|kotlin/Int|
|
||||
|
||||
@@ -27,10 +27,10 @@ FILE: lambdaInLambda.kt
|
||||
R|/buildString|(<L> = buildString@fun R|StringBuilder|.<anonymous>(): R|kotlin/Unit| {
|
||||
this@R|special/anonymous|.R|/insert|<R|StringBuilder|, R|KDocTemplate|>(R|/KDocTemplate.KDocTemplate|(), <L> = insert@fun R|KDocTemplate|.<anonymous>(): R|kotlin/Unit| {
|
||||
this@R|special/anonymous|.R|/KDocTemplate.definition|(<L> = definition@fun R|StringBuilder|.<anonymous>(): R|kotlin/Unit| {
|
||||
^ R|<local>/ordinal|?.R|kotlin/let|<R|kotlin/Int|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/ordinal|?.{ $subj$.R|kotlin/let|<R|kotlin/Int|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
^@let Unit
|
||||
}
|
||||
)
|
||||
) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ FILE: main.kt
|
||||
}
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
lval processor: R|AdapterProcessor<ft<PsiMethod, PsiMethod?>!, ft<PsiClass, PsiClass?>!>| = R|/AdapterProcessor.AdapterProcessor|<R|ft<PsiMethod, PsiMethod?>!|, R|ft<PsiClass, PsiClass?>!|>(R|/Function|<R|ft<PsiMethod, PsiMethod?>!|, R|PsiClass?|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|PsiClass?| {
|
||||
^ R|<local>/method|?.R|/PsiMethod.containingClass|
|
||||
^ R|<local>/method|?.{ $subj$.R|/PsiMethod.containingClass| }
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ FILE: bareTypes.kt
|
||||
public abstract interface MutableString : R|MutableA<kotlin/String>| {
|
||||
}
|
||||
public final fun test(a: R|A<kotlin/String>|): R|kotlin/Unit| {
|
||||
(R|<local>/a| as? R|MutableA<kotlin/String>|)?.R|FakeOverride</MutableA.add: R|kotlin/Unit|>|(String())
|
||||
(R|<local>/a| as? R|MutableA<kotlin/String>|)?.{ $subj$.R|FakeOverride</MutableA.add: R|kotlin/Unit|>|(String()) }
|
||||
(R|<local>/a| as R|MutableA<kotlin/String>|).R|FakeOverride</MutableA.add: R|kotlin/Unit|>|(String())
|
||||
}
|
||||
public final fun test2(a: R|A<kotlin/String>|): R|kotlin/Unit| {
|
||||
|
||||
19
compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt
vendored
Normal file
19
compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
fun foo(x: Int) {}
|
||||
|
||||
interface A
|
||||
interface B
|
||||
interface C : A, B
|
||||
|
||||
fun bar(x: A) {}
|
||||
fun bar(x: B) {}
|
||||
|
||||
fun test(c: C) {
|
||||
// Argument mapping error
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>("")
|
||||
|
||||
// Ambiguity
|
||||
<!AMBIGUITY!>bar<!>(c)
|
||||
|
||||
// Unresolved reference
|
||||
<!UNRESOLVED_REFERENCE!>baz<!>()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user