mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-16 00:21:26 +00:00
Compare commits
995 Commits
new_infere
...
yan.archiv
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a2457ca58 | ||
|
|
aec1f79217 | ||
|
|
63a02f9247 | ||
|
|
f6e9c2507d | ||
|
|
55a82615c8 | ||
|
|
64230721ae | ||
|
|
72fd50cd69 | ||
|
|
eefe6cdfbc | ||
|
|
a92b58d7ea | ||
|
|
1c7169e6b8 | ||
|
|
8017da80da | ||
|
|
2914b11097 | ||
|
|
95ea14feb1 | ||
|
|
079360a4fe | ||
|
|
047b222240 | ||
|
|
e772054a37 | ||
|
|
8c6ea5135b | ||
|
|
6075927624 | ||
|
|
ba526c91c9 | ||
|
|
1e2de8b113 | ||
|
|
648f9aae52 | ||
|
|
a1d68f4a79 | ||
|
|
08590c676c | ||
|
|
668570e6b0 | ||
|
|
0205c7d153 | ||
|
|
8351567f46 | ||
|
|
c5137be433 | ||
|
|
0238575a36 | ||
|
|
6fbf5a8904 | ||
|
|
d0b232c172 | ||
|
|
68b5dc756c | ||
|
|
29caa00f23 | ||
|
|
bc86f40fd8 | ||
|
|
89a07ded1c | ||
|
|
3e34b95610 | ||
|
|
052be93c97 | ||
|
|
558a2cb8a8 | ||
|
|
3d1e0c3b39 | ||
|
|
ca6889b4c6 | ||
|
|
07b191f460 | ||
|
|
8ab121b373 | ||
|
|
555e9674b2 | ||
|
|
434bbafe58 | ||
|
|
0a95e7b20f | ||
|
|
058ef31d7a | ||
|
|
14e586d5a5 | ||
|
|
e83845ea72 | ||
|
|
b2ca302bf7 | ||
|
|
f4feb71ad2 | ||
|
|
df17f20ec7 | ||
|
|
a58a6290cc | ||
|
|
5dc094d290 | ||
|
|
6f1e6f1f1b | ||
|
|
246f73c879 | ||
|
|
0c35e79283 | ||
|
|
2dc4769c0a | ||
|
|
172a29ba04 | ||
|
|
48cbcbc496 | ||
|
|
acc84d2524 | ||
|
|
7218bd536c | ||
|
|
5f7c783bb2 | ||
|
|
d38b1c361a | ||
|
|
1219572aa0 | ||
|
|
05f0978865 | ||
|
|
fbbece3c86 | ||
|
|
7e21573cf4 | ||
|
|
e23b1529b3 | ||
|
|
4eb557724c | ||
|
|
a418a3ac49 | ||
|
|
6f21c36d68 | ||
|
|
47507ad694 | ||
|
|
eabbebd458 | ||
|
|
59c8f33450 | ||
|
|
46be5e25be | ||
|
|
febab82c7e | ||
|
|
7120fe190a | ||
|
|
587f76251e | ||
|
|
e8494a5371 | ||
|
|
a6f8db5d02 | ||
|
|
7710cc455c | ||
|
|
b5db681e06 | ||
|
|
c153a386ab | ||
|
|
a4f28cd94f | ||
|
|
e76cd802d8 | ||
|
|
b2926a9322 | ||
|
|
0b63e11ea8 | ||
|
|
98204aa2d3 | ||
|
|
90e5558704 | ||
|
|
7f86fb9343 | ||
|
|
69787bd0d1 | ||
|
|
d301938d23 | ||
|
|
12f0f019da | ||
|
|
361d8536ac | ||
|
|
486c3a2aff | ||
|
|
f96153693e | ||
|
|
80ad969f7b | ||
|
|
78d2c655d5 | ||
|
|
4a47fb3ffb | ||
|
|
a952d797f1 | ||
|
|
8f96157d7f | ||
|
|
8bc95295eb | ||
|
|
9766508512 | ||
|
|
713fb9a0e7 | ||
|
|
b490a79d95 | ||
|
|
eb8ef6e803 | ||
|
|
d39d2883e2 | ||
|
|
26369c3cca | ||
|
|
28689f631c | ||
|
|
10732a1bdd | ||
|
|
5d3579c079 | ||
|
|
f0edb602da | ||
|
|
556287f9bb | ||
|
|
06c8cbf7d6 | ||
|
|
9b51a547d8 | ||
|
|
0d264793ce | ||
|
|
3912025e14 | ||
|
|
8266777bd5 | ||
|
|
74411d9b9c | ||
|
|
6614695616 | ||
|
|
743f599262 | ||
|
|
a0d0bc074b | ||
|
|
cefa17f877 | ||
|
|
d88b5746c7 | ||
|
|
7c6a217579 | ||
|
|
6181ba47c8 | ||
|
|
9b1f323118 | ||
|
|
5abb9dd23e | ||
|
|
f46fa263ef | ||
|
|
86f25bff63 | ||
|
|
460688526d | ||
|
|
899da99232 | ||
|
|
404122654f | ||
|
|
c80beea6fd | ||
|
|
0e31162df4 | ||
|
|
2a0bb68e1c | ||
|
|
4cd07f59a0 | ||
|
|
145c04e7e2 | ||
|
|
725704e70f | ||
|
|
2472966749 | ||
|
|
1298ef7fed | ||
|
|
cd9e298e53 | ||
|
|
18de0f75ab | ||
|
|
30acc224ec | ||
|
|
69f3f04fe4 | ||
|
|
0ad3872d1b | ||
|
|
1171fdb14d | ||
|
|
a39aba4269 | ||
|
|
4b70654c7e | ||
|
|
28123eaf7b | ||
|
|
7f97d58970 | ||
|
|
089b34a8a9 | ||
|
|
1f8e2a1057 | ||
|
|
3a81be6cfb | ||
|
|
f28bec0db1 | ||
|
|
3b8f5bce41 | ||
|
|
fad7818bf0 | ||
|
|
5798595206 | ||
|
|
a28bc830f5 | ||
|
|
29eb594309 | ||
|
|
068f520c01 | ||
|
|
be4739e65e | ||
|
|
bd8a4d78fa | ||
|
|
8cbf364457 | ||
|
|
44c15d8311 | ||
|
|
19e38bbc72 | ||
|
|
46b8deedf7 | ||
|
|
8cd7686535 | ||
|
|
4cb5483c13 | ||
|
|
e2def0c60e | ||
|
|
c251386fc3 | ||
|
|
b091500adc | ||
|
|
80643c5603 | ||
|
|
245d1de2a2 | ||
|
|
4d951de616 | ||
|
|
4c76dc7287 | ||
|
|
4d2061d836 | ||
|
|
6d7c779df2 | ||
|
|
7e417272b2 | ||
|
|
cc346aef64 | ||
|
|
8bfd6d7404 | ||
|
|
c4da370b0b | ||
|
|
2340756b88 | ||
|
|
253cd3871b | ||
|
|
b29a6e48fb | ||
|
|
78850087be | ||
|
|
5e34f290ce | ||
|
|
bd25bf14df | ||
|
|
e12deb54d6 | ||
|
|
7b055c2172 | ||
|
|
233376eef0 | ||
|
|
2da9f12bc5 | ||
|
|
923d9f03fc | ||
|
|
31e73e90d6 | ||
|
|
2224f95294 | ||
|
|
4d378912bf | ||
|
|
4232ad8dfe | ||
|
|
c06aaf6128 | ||
|
|
543db380d2 | ||
|
|
a46a2b9b1c | ||
|
|
5947b4eb8e | ||
|
|
c96eb8df85 | ||
|
|
a59fd3bc85 | ||
|
|
32b68ae1d5 | ||
|
|
eda8bbacb3 | ||
|
|
20c4775da0 | ||
|
|
0c78a2c026 | ||
|
|
f516667640 | ||
|
|
3bf5f44b9d | ||
|
|
399282234e | ||
|
|
6b9520ec73 | ||
|
|
510e17246f | ||
|
|
2805371bdc | ||
|
|
72ffbb9825 | ||
|
|
40d1925e19 | ||
|
|
2399a39414 | ||
|
|
9c9e507172 | ||
|
|
08622b0953 | ||
|
|
e07e9c0ea5 | ||
|
|
fb487b31ba | ||
|
|
5c1321a29f | ||
|
|
f77586574f | ||
|
|
21f2b68357 | ||
|
|
6fc5c3325c | ||
|
|
737d7dcc2f | ||
|
|
70cb08bfdb | ||
|
|
2e933a165a | ||
|
|
b701117ffb | ||
|
|
2386cfbd07 | ||
|
|
ff00831109 | ||
|
|
f4ad5182b8 | ||
|
|
40aa2280a5 | ||
|
|
513f50785e | ||
|
|
4b2d281bba | ||
|
|
577c6cde82 | ||
|
|
26c1673da0 | ||
|
|
117c5a29fb | ||
|
|
b1bff24cde | ||
|
|
f675d9fd81 | ||
|
|
3c19af3645 | ||
|
|
9d9b2b2a58 | ||
|
|
1924172189 | ||
|
|
ee3f89df87 | ||
|
|
c4ef95dbf7 | ||
|
|
ac1c40c0e6 | ||
|
|
7f947bed1e | ||
|
|
925e4e0a67 | ||
|
|
a3dda258c8 | ||
|
|
dade8deea6 | ||
|
|
c54dd6385c | ||
|
|
c52fcdde70 | ||
|
|
512e287f3a | ||
|
|
f0b172ca35 | ||
|
|
c8900d672f | ||
|
|
4c1eb21805 | ||
|
|
2623ae714c | ||
|
|
25cd54713b | ||
|
|
d5d49c65b4 | ||
|
|
7b212c5650 | ||
|
|
2a10d8e837 | ||
|
|
44920f42d8 | ||
|
|
b3eeb2f735 | ||
|
|
82574cb570 | ||
|
|
9290d58ed0 | ||
|
|
899002b681 | ||
|
|
907f53e539 | ||
|
|
5e97517c8b | ||
|
|
95f9884799 | ||
|
|
02857dbfdb | ||
|
|
8b3d439d5b | ||
|
|
ae2d67a5b1 | ||
|
|
2637a36e22 | ||
|
|
4a2440ea0f | ||
|
|
7f1cc81d39 | ||
|
|
ef1a3ec32d | ||
|
|
7e6542b8c8 | ||
|
|
1716720604 | ||
|
|
0f74bb4a7a | ||
|
|
72f2406083 | ||
|
|
5deb20543f | ||
|
|
d16883deaa | ||
|
|
c704f2de9a | ||
|
|
e2b83aecd7 | ||
|
|
7b0070ea62 | ||
|
|
ca57309374 | ||
|
|
a752f3f38e | ||
|
|
62580a47dc | ||
|
|
54f4f5ff24 | ||
|
|
af1d6124ce | ||
|
|
c6a9c36275 | ||
|
|
6cb68531ae | ||
|
|
bba8168150 | ||
|
|
1f841e35bc | ||
|
|
432c743771 | ||
|
|
fdd000c94f | ||
|
|
4d54036d21 | ||
|
|
7dc15b15bb | ||
|
|
2f09c51dca | ||
|
|
704ce121bc | ||
|
|
1c7e42f1d4 | ||
|
|
a1b20535b2 | ||
|
|
f86b77083f | ||
|
|
d1d786dffa | ||
|
|
220fab0d3f | ||
|
|
ca09be1411 | ||
|
|
b4db744a9b | ||
|
|
e46f69bb36 | ||
|
|
404f9cc7d8 | ||
|
|
bad76eb5c2 | ||
|
|
5b3ab97b4e | ||
|
|
571b424b33 | ||
|
|
cc90dfa65b | ||
|
|
690c3433d6 | ||
|
|
106e1b8661 | ||
|
|
075541da21 | ||
|
|
564490c9d4 | ||
|
|
1b6f6e8bf7 | ||
|
|
c2b532b167 | ||
|
|
e5f0ffb0c2 | ||
|
|
b567817d1f | ||
|
|
8bc020f31b | ||
|
|
99be75cbfc | ||
|
|
ba0a91d74c | ||
|
|
908bf71ae6 | ||
|
|
d44313876c | ||
|
|
877874978f | ||
|
|
113e9f496e | ||
|
|
f709a382ae | ||
|
|
05b618eec8 | ||
|
|
5892944bfc | ||
|
|
9d5d85a1c5 | ||
|
|
dbd7ceb5fd | ||
|
|
c5982e7ff5 | ||
|
|
b539adf105 | ||
|
|
ca22bc57fd | ||
|
|
28f4cc5b18 | ||
|
|
e58558dffd | ||
|
|
e57efc7233 | ||
|
|
c1a1a7f9fb | ||
|
|
9d7eca1376 | ||
|
|
d62a7cc9d1 | ||
|
|
dfbe92344f | ||
|
|
2b95e6bc0d | ||
|
|
724f3bf714 | ||
|
|
77b93ab7ad | ||
|
|
b2970ef771 | ||
|
|
ab96e0102a | ||
|
|
9a1f484771 | ||
|
|
d7f0695a51 | ||
|
|
c7f8312e1b | ||
|
|
3ed7df506b | ||
|
|
9ce9b434fe | ||
|
|
886d3ef3a6 | ||
|
|
b4e5f8cf1c | ||
|
|
d848238a46 | ||
|
|
60874f29fe | ||
|
|
0b24be9460 | ||
|
|
560dc920e4 | ||
|
|
3a7e4acf22 | ||
|
|
d15fa83749 | ||
|
|
46ac14198c | ||
|
|
adf6ad6283 | ||
|
|
eae79e96ee | ||
|
|
93d40b0492 | ||
|
|
2ca7045228 | ||
|
|
ed11528664 | ||
|
|
25998c1f9b | ||
|
|
2ee23ddd02 | ||
|
|
108e91f2a2 | ||
|
|
283c762b8b | ||
|
|
192489ae66 | ||
|
|
1c5cd1b3a0 | ||
|
|
81aae03b57 | ||
|
|
e7c1d94c0f | ||
|
|
e978c42e52 | ||
|
|
0a3a493f25 | ||
|
|
df19162c8c | ||
|
|
c66947ba40 | ||
|
|
3512675d96 | ||
|
|
a85b4ddb0f | ||
|
|
f4a7ecc1bb | ||
|
|
322ac6340a | ||
|
|
c6d7ffb3eb | ||
|
|
5d6d321fb2 | ||
|
|
ce5b1acfa7 | ||
|
|
b8dded2685 | ||
|
|
b925b6ef9f | ||
|
|
aee7329b89 | ||
|
|
5a6d58a799 | ||
|
|
4c09a6cf06 | ||
|
|
27b3cdf1fa | ||
|
|
254caef0e6 | ||
|
|
f8601479de | ||
|
|
f91f42c253 | ||
|
|
2c81362ce1 | ||
|
|
e7200d16c3 | ||
|
|
e22e466485 | ||
|
|
084da3665a | ||
|
|
260c549cd7 | ||
|
|
f0723a5c07 | ||
|
|
53d6c17417 | ||
|
|
a278e4ccef | ||
|
|
c1cf03d89c | ||
|
|
0a1580159f | ||
|
|
683bbe396d | ||
|
|
b46784ab86 | ||
|
|
cbfd7088bf | ||
|
|
c0582ed732 | ||
|
|
502a6fa9f1 | ||
|
|
5f6e5c5779 | ||
|
|
b51a7c6957 | ||
|
|
1fd8abb0bb | ||
|
|
79abc8743e | ||
|
|
0cad41bb0c | ||
|
|
23bd0b3db5 | ||
|
|
29fd34d1de | ||
|
|
8c27bf98f4 | ||
|
|
f3dad53ad4 | ||
|
|
d37c8397f5 | ||
|
|
ab50ccf995 | ||
|
|
560e2d1ced | ||
|
|
aa43bebbf1 | ||
|
|
3a06b8fe3b | ||
|
|
bef100b46e | ||
|
|
09f31076e6 | ||
|
|
2f30ca3fac | ||
|
|
f4a8a98157 | ||
|
|
6cb556dd6b | ||
|
|
ab0c081897 | ||
|
|
dd45780de9 | ||
|
|
34bdc04fbe | ||
|
|
7758875955 | ||
|
|
0acfce55a8 | ||
|
|
6bfe168dd7 | ||
|
|
8a23a62c90 | ||
|
|
8810e15f08 | ||
|
|
3f9054b28b | ||
|
|
cfcee0a1fe | ||
|
|
6b656d4da5 | ||
|
|
099c1a84ec | ||
|
|
60149e3021 | ||
|
|
f5e3a5faa4 | ||
|
|
9e21744bf5 | ||
|
|
208a986eab | ||
|
|
f1579d01af | ||
|
|
7c3c59de00 | ||
|
|
9fed8f1d24 | ||
|
|
ceaa34201e | ||
|
|
4c775a9516 | ||
|
|
7da9268e10 | ||
|
|
f940c0b86f | ||
|
|
4f97040ce5 | ||
|
|
7eb2d0d185 | ||
|
|
12daf4389e | ||
|
|
53a3d08a0e | ||
|
|
d7fcc69315 | ||
|
|
81b6a61edf | ||
|
|
1435911437 | ||
|
|
743dc80b4d | ||
|
|
70caae4c6f | ||
|
|
defb5a9d10 | ||
|
|
6690f9f1da | ||
|
|
3f15f7a394 | ||
|
|
e6efaaf752 | ||
|
|
92c23aa0ed | ||
|
|
8eddb10870 | ||
|
|
35fa8efbf3 | ||
|
|
8f7a354592 | ||
|
|
2a0b7e293f | ||
|
|
4d6c83b5b9 | ||
|
|
c023831a00 | ||
|
|
5da156e93c | ||
|
|
91a9d3cf80 | ||
|
|
2f817662d5 | ||
|
|
8ade03ac0b | ||
|
|
e710cbb0bb | ||
|
|
2593ce73f1 | ||
|
|
9cb62d66cb | ||
|
|
6197c5bf7f | ||
|
|
8fc83e3ff5 | ||
|
|
17573a3c21 | ||
|
|
4559da9848 | ||
|
|
db607e231c | ||
|
|
1db0e5c23e | ||
|
|
2fc26ba08f | ||
|
|
892e901f35 | ||
|
|
32a94c70e9 | ||
|
|
5dbab2f907 | ||
|
|
3cfe43f83a | ||
|
|
40706de3db | ||
|
|
75ce68197f | ||
|
|
9d1fbbd1c6 | ||
|
|
253c5f2d9b | ||
|
|
258bd1e8c0 | ||
|
|
6f135e89d7 | ||
|
|
c8bd623d69 | ||
|
|
4cb2b12f01 | ||
|
|
31d650a041 | ||
|
|
11696ac4c0 | ||
|
|
86c10b635a | ||
|
|
fd01351740 | ||
|
|
968e6ecde4 | ||
|
|
0c429857de | ||
|
|
4a4bf5635d | ||
|
|
99a9634609 | ||
|
|
5ffd6a737e | ||
|
|
d25ebadf53 | ||
|
|
e80dae1802 | ||
|
|
5ec5807399 | ||
|
|
993db696ec | ||
|
|
da678a4be2 | ||
|
|
ebc9c217c1 | ||
|
|
685d38218d | ||
|
|
0ca2117ac7 | ||
|
|
361824e170 | ||
|
|
8c7f57ca83 | ||
|
|
d79ac58340 | ||
|
|
67897d9b3d | ||
|
|
a5cc9809ac | ||
|
|
54c262c505 | ||
|
|
0104ed7d44 | ||
|
|
63af3c8e03 | ||
|
|
f36f85f55c | ||
|
|
165ac97c4b | ||
|
|
408c753837 | ||
|
|
69c8da7403 | ||
|
|
6f722d647f | ||
|
|
6299e0e941 | ||
|
|
e9ca6a6038 | ||
|
|
599bb878f1 | ||
|
|
78682ac493 | ||
|
|
45282af38b | ||
|
|
d060203896 | ||
|
|
0991dba626 | ||
|
|
6c23d3a220 | ||
|
|
da157fafdc | ||
|
|
e558837214 | ||
|
|
3b212558e2 | ||
|
|
19c35ef48c | ||
|
|
d51dd97156 | ||
|
|
266b40b654 | ||
|
|
06903f803b | ||
|
|
d881efdeb1 | ||
|
|
1be9e04797 | ||
|
|
fd066ea4d5 | ||
|
|
c5a88c5fb7 | ||
|
|
6bea643176 | ||
|
|
67b5527c68 | ||
|
|
97edda44c8 | ||
|
|
c852d0b6cb | ||
|
|
93097014a0 | ||
|
|
57f710c931 | ||
|
|
7ee3b81939 | ||
|
|
4a69d1545b | ||
|
|
14c80baec8 | ||
|
|
26c158cbae | ||
|
|
e46b56acbc | ||
|
|
627fe52858 | ||
|
|
a8ba8fbf77 | ||
|
|
a752d30f12 | ||
|
|
62f2876230 | ||
|
|
6b2c22aff1 | ||
|
|
3529d61a7d | ||
|
|
eb12cfd444 | ||
|
|
16695c1af5 | ||
|
|
de185b79d0 | ||
|
|
640c28ceaf | ||
|
|
84d63051f9 | ||
|
|
f83c5344d7 | ||
|
|
1c7d97289b | ||
|
|
37d2ff2d4d | ||
|
|
429bf5bb98 | ||
|
|
79ff36592d | ||
|
|
e2306ecf94 | ||
|
|
3825187e93 | ||
|
|
a1f67e347f | ||
|
|
4e26ca5659 | ||
|
|
496df371f4 | ||
|
|
03a8ce63b2 | ||
|
|
25ea53457e | ||
|
|
817dadc120 | ||
|
|
50eaca1ac4 | ||
|
|
184651d366 | ||
|
|
84a6ef6ac4 | ||
|
|
247881baf9 | ||
|
|
0df3ffbe36 | ||
|
|
896246a7f5 | ||
|
|
d0e8e176c4 | ||
|
|
9a61abfb9f | ||
|
|
2c4180222a | ||
|
|
4b6efe3eb0 | ||
|
|
7f1dd88600 | ||
|
|
98d26ae59f | ||
|
|
cde84a7923 | ||
|
|
254f766aaf | ||
|
|
768fce4722 | ||
|
|
cc2faa67f9 | ||
|
|
9a156541c1 | ||
|
|
5e765c525e | ||
|
|
5475f99cec | ||
|
|
ec60c92fe9 | ||
|
|
73bca21f94 | ||
|
|
2e71691ab2 | ||
|
|
8e23ca597d | ||
|
|
a65304556c | ||
|
|
e10fa218f5 | ||
|
|
95e7d29743 | ||
|
|
52df70a576 | ||
|
|
d7807b5ae3 | ||
|
|
232ec63121 | ||
|
|
947e853d9e | ||
|
|
d5bb7e457e | ||
|
|
3f00592443 | ||
|
|
fc93e7a727 | ||
|
|
276a6acc3e | ||
|
|
8b7a8f7bef | ||
|
|
fc51673c83 | ||
|
|
efc470df2b | ||
|
|
945da50b61 | ||
|
|
6116b5c497 | ||
|
|
042f81f23b | ||
|
|
a33a3867b8 | ||
|
|
d2eb8b4a3f | ||
|
|
b6595d661d | ||
|
|
824b506abe | ||
|
|
c5c6eed170 | ||
|
|
fb13347864 | ||
|
|
93ef16deaf | ||
|
|
dd32c4e66a | ||
|
|
2df85ae4a9 | ||
|
|
3e0d83b7d1 | ||
|
|
129fad6ade | ||
|
|
613297ad60 | ||
|
|
f3f8db989a | ||
|
|
ac87ad422d | ||
|
|
79359b7bc2 | ||
|
|
3bf8436895 | ||
|
|
b7ff00ec34 | ||
|
|
419abadcda | ||
|
|
f468990f97 | ||
|
|
4827aadcfd | ||
|
|
934b3cc54e | ||
|
|
5d62277fa5 | ||
|
|
685b138f79 | ||
|
|
01931c2ae6 | ||
|
|
953a485fe7 | ||
|
|
2d8e73f3f6 | ||
|
|
d51b17c1b2 | ||
|
|
9d1091cdaa | ||
|
|
7031087a93 | ||
|
|
d62ced3a82 | ||
|
|
72ec55769b | ||
|
|
429c31c010 | ||
|
|
1534488dd1 | ||
|
|
2f987f08fa | ||
|
|
56230420f8 | ||
|
|
3268189215 | ||
|
|
5affb9a25c | ||
|
|
3f1a3dfeb2 | ||
|
|
f44fba746e | ||
|
|
221aac9820 | ||
|
|
5a1a35bb35 | ||
|
|
9e919829c8 | ||
|
|
8ebe16c9b2 | ||
|
|
bc361363d5 | ||
|
|
35d85ddd1f | ||
|
|
c995f70631 | ||
|
|
6b5aeaa9a6 | ||
|
|
ada7287c66 | ||
|
|
6d4b5bc48f | ||
|
|
a8b01a6b00 | ||
|
|
91bcfb97c6 | ||
|
|
756cb32eaf | ||
|
|
33d94cd5e1 | ||
|
|
67b78bce39 | ||
|
|
bf393505a9 | ||
|
|
e66e8bcd07 | ||
|
|
809cc220ed | ||
|
|
976a158ce1 | ||
|
|
449fee74e8 | ||
|
|
f39250c9a2 | ||
|
|
f38a4f509d | ||
|
|
c5886bc7a2 | ||
|
|
10639eaf6a | ||
|
|
d9edc5f221 | ||
|
|
053f3b6ac0 | ||
|
|
ecd42f14b3 | ||
|
|
c030a047aa | ||
|
|
2af0bf4c71 | ||
|
|
6551ee5403 | ||
|
|
149b197b24 | ||
|
|
66d3c94193 | ||
|
|
00d7150944 | ||
|
|
41086f26ae | ||
|
|
93e7e9b28c | ||
|
|
d7edbb8dfc | ||
|
|
a4d122478b | ||
|
|
ee94a64718 | ||
|
|
61cb39a600 | ||
|
|
50bf74b909 | ||
|
|
5b646ba4fa | ||
|
|
0fee7883ed | ||
|
|
3914c1b0e9 | ||
|
|
ff2e3ecfc4 | ||
|
|
7712044146 | ||
|
|
ad1978940b | ||
|
|
a31f503fa5 | ||
|
|
e8162cd99d | ||
|
|
d0ca0dca2b | ||
|
|
91bb57c5a3 | ||
|
|
fec2d08d22 | ||
|
|
123fd64a34 | ||
|
|
e3a9ad5a74 | ||
|
|
dfe176efca | ||
|
|
5a8c0f8f42 | ||
|
|
9fad40b586 | ||
|
|
3178dee759 | ||
|
|
6208c69c72 | ||
|
|
7711f8e3a7 | ||
|
|
d69382f129 | ||
|
|
43ef113b7a | ||
|
|
fa19bd6d9b | ||
|
|
5652fa762f | ||
|
|
06fa61bb6f | ||
|
|
79a509df7b | ||
|
|
640bf22e4f | ||
|
|
44ee228ac9 | ||
|
|
a2175c2ef5 | ||
|
|
57844968b0 | ||
|
|
ea5505f80c | ||
|
|
c9d0ab38cf | ||
|
|
12a8048bf7 | ||
|
|
a88206c5ea | ||
|
|
94a0e508d9 | ||
|
|
8203d1c3fe | ||
|
|
2bb02beb84 | ||
|
|
5e21dc5560 | ||
|
|
c8904b1c7c | ||
|
|
2cdc246a27 | ||
|
|
4ac870500f | ||
|
|
a8ddf03b53 | ||
|
|
e6aeb66875 | ||
|
|
7c73356893 | ||
|
|
50608d0844 | ||
|
|
b65dcf27ee | ||
|
|
f4f7c83eeb | ||
|
|
3513f1a86a | ||
|
|
657123f2c0 | ||
|
|
710c726c9a | ||
|
|
411feab9ae | ||
|
|
1deed28464 | ||
|
|
aec893180e | ||
|
|
78a87ac0cf | ||
|
|
484bf0115f | ||
|
|
7842fa4796 | ||
|
|
74e5a9425a | ||
|
|
d3adf57145 | ||
|
|
52ccfcecfc | ||
|
|
0159d19539 | ||
|
|
94a7673c2d | ||
|
|
b0b69b2ad0 | ||
|
|
c336159b2b | ||
|
|
3e7e01dc4d | ||
|
|
fd7aaa1579 | ||
|
|
cf6b71aa05 | ||
|
|
77c186442a | ||
|
|
6d63dd9d83 | ||
|
|
1a9d2ab4ee | ||
|
|
3cd4d90bf8 | ||
|
|
37351c344f | ||
|
|
41739602bc | ||
|
|
ce441e2163 | ||
|
|
3e1f471121 | ||
|
|
32b90a1cae | ||
|
|
be18cb9b16 | ||
|
|
9365d1d859 | ||
|
|
ef5c3512cd | ||
|
|
aeb74f7e70 | ||
|
|
4657ae06f4 | ||
|
|
a936f75423 | ||
|
|
420b9fdaa9 | ||
|
|
24336113a2 | ||
|
|
224adfabc5 | ||
|
|
5cbfdf6024 | ||
|
|
7da847e943 | ||
|
|
4df0a1bb1f | ||
|
|
0729566458 | ||
|
|
f7968e1b61 | ||
|
|
dde0535c5a | ||
|
|
05b56b0c4a | ||
|
|
665a697093 | ||
|
|
54dc828c8e | ||
|
|
0e2bd46124 | ||
|
|
4711e2f9da | ||
|
|
3432014971 | ||
|
|
06fd996266 | ||
|
|
1f053be289 | ||
|
|
83710a8ed6 | ||
|
|
5032064bf0 | ||
|
|
84e960b3a4 | ||
|
|
039e036e22 | ||
|
|
4017195ff1 | ||
|
|
e16bdd4287 | ||
|
|
f963b8bd42 | ||
|
|
b80403cf13 | ||
|
|
95cc3fe1b7 | ||
|
|
bb4d6d1059 | ||
|
|
4c5cf0f7e7 | ||
|
|
ef433d163e | ||
|
|
819a3a95b3 | ||
|
|
4890979476 | ||
|
|
106f571814 | ||
|
|
4bff0fb338 | ||
|
|
9eca8cd451 | ||
|
|
c6d8b39b4f | ||
|
|
d818af5287 | ||
|
|
8ed8e05a68 | ||
|
|
0ab924a298 | ||
|
|
b5bd5942e7 | ||
|
|
88540360b4 | ||
|
|
4a6cc3913d | ||
|
|
18fae9e16d | ||
|
|
5bffef6de7 | ||
|
|
37b00b91fc | ||
|
|
a4fbe95112 | ||
|
|
eb25ac44e6 | ||
|
|
18cb9593c8 | ||
|
|
48021ce5a1 | ||
|
|
64f01e53af | ||
|
|
94b8614fb8 | ||
|
|
09d27ca61c | ||
|
|
b775b901cc | ||
|
|
ba4cf4dcc6 | ||
|
|
d0a8dd7dc8 | ||
|
|
3e2003e60d | ||
|
|
f83dc0a067 | ||
|
|
1101bb7fb4 | ||
|
|
6e34f57acf | ||
|
|
1cd14f00eb | ||
|
|
0d64ab4846 | ||
|
|
3f082346ae | ||
|
|
17b4d4a973 | ||
|
|
d8cd926a8c | ||
|
|
c55f08a166 | ||
|
|
3a807cb39b | ||
|
|
46a631a654 | ||
|
|
1692d1a087 | ||
|
|
f67eb90dfb | ||
|
|
a3028beca9 | ||
|
|
adfee2086a | ||
|
|
d4be55df0e | ||
|
|
7c5897c1ab | ||
|
|
c2e706db6c | ||
|
|
c5c52dbda5 | ||
|
|
430aad3651 | ||
|
|
3c78156f0f | ||
|
|
fb3cf212ce | ||
|
|
99951db7e3 | ||
|
|
978a7fdfaa | ||
|
|
773fca5245 | ||
|
|
640ce213cf | ||
|
|
697b358293 | ||
|
|
9ab48d8374 | ||
|
|
99af2372c3 | ||
|
|
17106d6546 | ||
|
|
cc139856c8 | ||
|
|
9b1867ce64 | ||
|
|
a19e229a72 | ||
|
|
775eeb75c9 | ||
|
|
ea5a52f918 | ||
|
|
2b5bbf0fdd | ||
|
|
3b4f82c9b9 | ||
|
|
6456f4ed98 | ||
|
|
d6cface66f | ||
|
|
26413acf33 | ||
|
|
5c33e4a32d | ||
|
|
c79386594d | ||
|
|
1688f6fdbd | ||
|
|
7bf071b69f | ||
|
|
c28a7d8f6d | ||
|
|
b133189309 | ||
|
|
d719d06020 | ||
|
|
f68d639c63 | ||
|
|
5680405531 | ||
|
|
df4bf73033 | ||
|
|
0071ca64c7 | ||
|
|
50dc9a14a6 | ||
|
|
7358980cbc | ||
|
|
70b7e5eb68 | ||
|
|
4ec20ad595 | ||
|
|
da98b7e07b | ||
|
|
f9813e3276 | ||
|
|
187182e46f | ||
|
|
db4c441573 | ||
|
|
4d067ab9ce | ||
|
|
1af93b8342 | ||
|
|
6941065e2c | ||
|
|
d58665b5a8 | ||
|
|
4c96453a4b | ||
|
|
c6f922fb64 | ||
|
|
e5a2be4f3c | ||
|
|
fa6285d32a | ||
|
|
d64e8e3b33 | ||
|
|
6ac345df51 | ||
|
|
6bee5699a0 | ||
|
|
40184f053e | ||
|
|
54d626fe7d | ||
|
|
ba21bae653 | ||
|
|
52ccd67ec1 | ||
|
|
9e82ab38f0 | ||
|
|
46fa5cfae0 | ||
|
|
5116f598df | ||
|
|
f7ccc4144c | ||
|
|
1aab4e643c | ||
|
|
65b5cdbb8d | ||
|
|
9fa9a8748b | ||
|
|
bf97b332cf | ||
|
|
54cceac99b | ||
|
|
5f7460a8c7 | ||
|
|
2f0df832c0 | ||
|
|
a4c29b3587 | ||
|
|
df2b8d01d8 | ||
|
|
455a1c0f53 | ||
|
|
64ba811b7f | ||
|
|
7ba73c1635 | ||
|
|
5bcbe25469 | ||
|
|
beff4a1b92 | ||
|
|
1493805f8e | ||
|
|
821843e13f | ||
|
|
1775f294f4 | ||
|
|
83ae34bb29 | ||
|
|
479f293edc | ||
|
|
c453ff01cd | ||
|
|
8f42aa1eda | ||
|
|
c5c4c9cfcc | ||
|
|
3ede503042 | ||
|
|
cc9ebb26de | ||
|
|
dc23a53116 | ||
|
|
38d3362bcb | ||
|
|
5252cd4da4 | ||
|
|
a375500a33 | ||
|
|
db8147bd79 | ||
|
|
e24e711208 | ||
|
|
58123f2103 | ||
|
|
a079b92ea0 | ||
|
|
a978c6be35 | ||
|
|
d9cfdf2f63 | ||
|
|
8dd5c2f895 | ||
|
|
f33255c990 | ||
|
|
df533053f9 | ||
|
|
ae6421476d | ||
|
|
26393d738f | ||
|
|
1702775738 | ||
|
|
c86dc0d7af | ||
|
|
34452f4f4a | ||
|
|
9ed0b49746 | ||
|
|
a1a1972a04 | ||
|
|
0566366895 | ||
|
|
3c98274006 | ||
|
|
5092758acb | ||
|
|
900ec82614 | ||
|
|
87d2d16cda | ||
|
|
eacd010e7e | ||
|
|
d1daca2560 | ||
|
|
ab99bf843a | ||
|
|
947833cad6 | ||
|
|
3394d675e5 | ||
|
|
3038f87105 | ||
|
|
dc4e673fb1 | ||
|
|
1a93d10697 | ||
|
|
3233d650c1 | ||
|
|
ff99b921b7 | ||
|
|
389729cc50 | ||
|
|
67cd4ed17a | ||
|
|
26d47a034e | ||
|
|
4068b3d9b9 | ||
|
|
1ada284a03 | ||
|
|
ab7ba3ae46 | ||
|
|
93f8542fc4 | ||
|
|
25e56874c1 | ||
|
|
c13b2a6bbc | ||
|
|
e1dbb90fdd | ||
|
|
4563cf250d | ||
|
|
846e50dcaa | ||
|
|
270b41dc66 | ||
|
|
ab619c5655 | ||
|
|
0e2bdf8995 | ||
|
|
2be7116b0b | ||
|
|
d65b999c2c | ||
|
|
0b9830248d | ||
|
|
7efaa7cabc | ||
|
|
e503c1d411 | ||
|
|
24bd31457c | ||
|
|
4404439521 | ||
|
|
edefb45585 | ||
|
|
4eb30b6626 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,3 +1,4 @@
|
||||
**/testData/** linguist-vendored
|
||||
*Generated.java linguist-generated=true
|
||||
compiler/cli/bin/* eol=lf
|
||||
compiler/cli/bin/*.bat eol=crlf
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@
|
||||
/confluence/target
|
||||
/dependencies
|
||||
/dist
|
||||
/local
|
||||
/gh-pages
|
||||
/ideaSDK
|
||||
/clionSDK
|
||||
|
||||
5
.idea/ant.xml
generated
5
.idea/ant.xml
generated
@@ -2,10 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="AntConfiguration">
|
||||
<buildFile url="file://$PROJECT_DIR$/compiler/frontend/buildLexer.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/build.xml">
|
||||
<antCommandLine value="-J-ea" />
|
||||
<maximumHeapSize value="1024" />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/update_dependencies.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/TeamCityBuild.xml">
|
||||
<maximumHeapSize value="512" />
|
||||
@@ -18,6 +14,5 @@
|
||||
</properties>
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/TeamCityRelay.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/node_utils.xml" />
|
||||
</component>
|
||||
</project>
|
||||
24
.idea/codeStyles/Project.xml
generated
24
.idea/codeStyles/Project.xml
generated
@@ -55,6 +55,15 @@
|
||||
</value>
|
||||
</option>
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="false" />
|
||||
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_IN_IF_CONDITIONS" value="false" />
|
||||
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="1" />
|
||||
</JetCodeStyleSettings>
|
||||
<MarkdownNavigatorCodeStyleSettings>
|
||||
<option name="RIGHT_MARGIN" value="72" />
|
||||
</MarkdownNavigatorCodeStyleSettings>
|
||||
@@ -228,7 +237,6 @@
|
||||
<option name="WHILE_BRACE_FORCE" value="1" />
|
||||
<option name="FOR_BRACE_FORCE" value="1" />
|
||||
<option name="FIELD_ANNOTATION_WRAP" value="0" />
|
||||
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="TypeScript">
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
@@ -261,12 +269,16 @@
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="WHILE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="5" />
|
||||
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
6
.idea/copyright/apache.xml
generated
6
.idea/copyright/apache.xml
generated
@@ -1,9 +1,7 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright 2010-&#36;today.year 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." />
|
||||
<option name="keyword" value="Copyright" />
|
||||
<option name="allowReplaceKeyword" value="JetBrains" />
|
||||
<option name="allowReplaceRegexp" value="JetBrains" />
|
||||
<option name="myName" value="apache" />
|
||||
<option name="myLocal" value="true" />
|
||||
<option name="notice" value="Copyright 2000-&#36;today.year JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file." />
|
||||
</copyright>
|
||||
</component>
|
||||
2
.idea/dictionaries/Nikolay_Krasko.xml
generated
2
.idea/dictionaries/Nikolay_Krasko.xml
generated
@@ -2,6 +2,7 @@
|
||||
<dictionary name="Nikolay.Krasko">
|
||||
<words>
|
||||
<w>accessors</w>
|
||||
<w>coroutines</w>
|
||||
<w>crossinline</w>
|
||||
<w>fqname</w>
|
||||
<w>goto</w>
|
||||
@@ -12,6 +13,7 @@
|
||||
<w>memoize</w>
|
||||
<w>memoized</w>
|
||||
<w>multiline</w>
|
||||
<w>navigatable</w>
|
||||
<w>preload</w>
|
||||
<w>preloader</w>
|
||||
<w>preloading</w>
|
||||
|
||||
1
.idea/dictionaries/yan.xml
generated
1
.idea/dictionaries/yan.xml
generated
@@ -5,6 +5,7 @@
|
||||
<w>impls</w>
|
||||
<w>kapt</w>
|
||||
<w>parceler</w>
|
||||
<w>repl</w>
|
||||
<w>uast</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
||||
5
.idea/inspectionProfiles/idea_default.xml
generated
5
.idea/inspectionProfiles/idea_default.xml
generated
@@ -56,7 +56,7 @@
|
||||
<option name="ignoreOnVolatileVariables" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="DuplicateCondition" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreMethodCalls" value="false" />
|
||||
<option name="ignoreSideEffectConditions" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="EmptyStatementBody" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="m_reportEmptyBlocks" value="false" />
|
||||
@@ -281,6 +281,7 @@
|
||||
<option name="fromVersion" value="2.4" />
|
||||
<option name="toVersion" value="3.1" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="Reformat" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="ReplaceAssignmentWithOperatorAssignment" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreLazyOperators" value="true" />
|
||||
<option name="ignoreObscureOperators" value="true" />
|
||||
@@ -402,8 +403,10 @@
|
||||
<inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<scope name="IDEA Test Sources" level="WARNING" enabled="false">
|
||||
<option name="m_ignoreJavadoc" value="true" />
|
||||
<option name="ignoreInModuleStatements" value="true" />
|
||||
</scope>
|
||||
<option name="m_ignoreJavadoc" value="true" />
|
||||
<option name="ignoreInModuleStatements" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="UnnecessaryLabelOnBreakStatement" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="UnnecessaryLabelOnContinueStatement" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
|
||||
1155
ChangeLog.md
1155
ChangeLog.md
File diff suppressed because it is too large
Load Diff
@@ -46,11 +46,7 @@ You also can use [Gradle properties](https://docs.gradle.org/current/userguide/b
|
||||
|
||||
## Building
|
||||
|
||||
To build this project, first time you try to build you need to run this:
|
||||
|
||||
ant -f update_dependencies.xml
|
||||
|
||||
which will setup the dependencies on
|
||||
On the first project configuration gradle will download and setup the dependencies on
|
||||
|
||||
* `intellij-core` is a part of command line compiler and contains only necessary APIs.
|
||||
* `idea-full` is a full blown IntelliJ IDEA Community Edition to be used in the plugin module.
|
||||
@@ -85,7 +81,7 @@ Refer to [libraries/ReadMe.md](libraries/ReadMe.md) for details.
|
||||
|
||||
## Working with the project in IntelliJ IDEA
|
||||
|
||||
Working with the Kotlin project requires IntelliJ IDEA 2017.3. You can download an Early Access Preview version of IntelliJ IDEA 2017.3 [here](https://www.jetbrains.com/idea/nextversion/).
|
||||
Working with the Kotlin project requires IntelliJ IDEA 2017.3. You can download IntelliJ IDEA 2017.3 [here](https://www.jetbrains.com/idea/download).
|
||||
|
||||
To import the project in Intellij choose project directory in Open project dialog. Then, after project opened, Select
|
||||
`File` -> `New...` -> `Module from Existing Sources` in the menu, and select `build.gradle.kts` file in the project's root folder.
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<project name="Kotlin CI Steps" default="none">
|
||||
<import file="build.xml" optional="false"/>
|
||||
<import file="common.xml" optional="false"/>
|
||||
<property name="kotlin-home" value="${output}/kotlinc"/>
|
||||
|
||||
<property name="build.number" value="snapshot"/>
|
||||
<property name="fail.on.plugin.verifier.error" value="true"/>
|
||||
|
||||
<property name="version_substitute_dir" value="${basedir}/versions_temp/"/>
|
||||
|
||||
<property name="artifact.output.path" value="${basedir}/dist/artifacts"/>
|
||||
<property name="artifact.output.path" value="${basedir}/dist/artifacts/ideaPlugin"/>
|
||||
<property name="plugin.xml" value="idea/src/META-INF/plugin.xml"/>
|
||||
<property name="plugin.xml.bk" value="${version_substitute_dir}/plugin.xml.bk"/>
|
||||
<property name="plugin.xml.versioned" value="${plugin.xml}.versioned"/>
|
||||
@@ -38,84 +39,49 @@
|
||||
<echoprop prop="user.home"/>
|
||||
<echoprop prop="user.dir"/>
|
||||
|
||||
<target name="cleanupArtifacts">
|
||||
<delete dir="${artifact.output.path}" includes="*"/>
|
||||
</target>
|
||||
|
||||
<macrodef name="substituteVersionInFile">
|
||||
<attribute name="target.file"/>
|
||||
<attribute name="test.string"/>
|
||||
<attribute name="target.file.bk" default="@{target.file}.bk"/>
|
||||
<attribute name="target.file.versioned" default="@{target.file}.versioned"/>
|
||||
<attribute name="token.key" default="snapshot"/>
|
||||
<attribute name="version" default="${build.number}"/>
|
||||
<macrodef name="run-gradle">
|
||||
<attribute name="tasks" />
|
||||
<attribute name="args" default="" />
|
||||
<sequential>
|
||||
<!-- Create backup. Backup will be restored after build end. This will allow to rebuild project without renew
|
||||
plugin.xml from repository. -->
|
||||
<copy file="@{target.file}" tofile="@{target.file.bk}"/>
|
||||
|
||||
<!-- Check that version has correct pattern for substitution -->
|
||||
<copy todir="">
|
||||
<fileset file="@{target.file.bk}">
|
||||
<contains text="@{test.string}"/>
|
||||
</fileset>
|
||||
<filterchain>
|
||||
<replacetokens>
|
||||
<token key="@{token.key}" value="@{version}"/>
|
||||
</replacetokens>
|
||||
</filterchain>
|
||||
<mergemapper to="@{target.file.versioned}"/>
|
||||
</copy>
|
||||
|
||||
<!-- If file doesn't exist - there's a problem with original plugin.xml. Probably there's a bad pattern used for version -->
|
||||
<copy file="@{target.file.versioned}" tofile="@{target.file}" overwrite="true"/>
|
||||
|
||||
<delete file="@{target.file.versioned}" quiet="true"/>
|
||||
<java classname="org.gradle.wrapper.GradleWrapperMain"
|
||||
fork="true"
|
||||
dir="${basedir}"
|
||||
failonerror="true"
|
||||
timeout="4000000"
|
||||
maxmemory="400m"
|
||||
taskname="gradle">
|
||||
<classpath>
|
||||
<pathelement location="${basedir}/gradle/wrapper/gradle-wrapper.jar"/>
|
||||
</classpath>
|
||||
<arg line="--no-daemon" />
|
||||
<arg line="@{tasks}" />
|
||||
<arg line="@{args}" />
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<target name="cleanupArtifacts">
|
||||
<run-gradle tasks="cleanupArtifacts" />
|
||||
</target>
|
||||
|
||||
<target name="zip-compiler">
|
||||
<run-gradle tasks="zipCompiler" args="-PdeployVersion=${build.number}" />
|
||||
</target>
|
||||
|
||||
<target name="zip-test-data">
|
||||
<run-gradle tasks="zipTestData" />
|
||||
</target>
|
||||
|
||||
<target name="writeCompilerVersionToTemplateFile">
|
||||
<!-- empty, version is written in gradle build -->
|
||||
</target>
|
||||
|
||||
<target name="writePluginVersionToTemplateFile">
|
||||
<mkdir dir="${version_substitute_dir}"/>
|
||||
|
||||
<substituteVersionInFile
|
||||
target.file="${plugin.xml}"
|
||||
target.file.bk="${plugin.xml.bk}"
|
||||
target.file.versioned="${plugin.xml.versioned}"
|
||||
test.string="<version>@snapshot@</version>"
|
||||
version="${plugin.xml.version.number}"/>
|
||||
<run-gradle tasks="writePluginVersion" args="-PpluginVersion=${plugin.xml.version.number}" />
|
||||
</target>
|
||||
|
||||
<target name="revertTemplateFiles">
|
||||
<copy file="${plugin.xml.bk}" tofile="${plugin.xml}" overwrite="true"/>
|
||||
<copy file="${compiler.version.java.bk}" tofile="${compiler.version.java}" overwrite="true"/>
|
||||
|
||||
<delete dir="${version_substitute_dir}" quiet="true"/>
|
||||
</target>
|
||||
|
||||
<target name="pre_build" depends="writeCompilerVersionToTemplateFile, writePluginVersionToTemplateFile, cleanupArtifacts"/>
|
||||
|
||||
<target name="zipArtifacts">
|
||||
<macrodef name="zipPlugin">
|
||||
<attribute name="filename"/>
|
||||
<attribute name="prefix" />
|
||||
<attribute name="dir"/>
|
||||
|
||||
<sequential>
|
||||
<zip destfile="@{filename}">
|
||||
<zipfileset prefix="@{prefix}" dir="@{dir}" excludes="kotlinc/bin/*"/>
|
||||
<zipfileset prefix="@{prefix}/kotlinc/bin" dir="@{dir}/kotlinc/bin" includes="*.bat"
|
||||
filemode="644"/>
|
||||
<zipfileset prefix="@{prefix}/kotlinc/bin" dir="@{dir}/kotlinc/bin" excludes="*.bat"
|
||||
filemode="755"/>
|
||||
</zip>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<zipPlugin filename="${plugin.zip}" prefix="Kotlin" dir="${artifact.output.path}/${pluginArtifactDir}"/>
|
||||
<run-gradle tasks="zipPlugin" args="-PpluginArtifactDir=${pluginArtifactDir} -PpluginZipPath=${plugin.zip}"/>
|
||||
</target>
|
||||
|
||||
<macrodef name="print-statistic">
|
||||
@@ -148,42 +114,8 @@
|
||||
<print-file-size-statistic path="${basedir}/libraries/stdlib/js/build/classes/main" file-name="kotlin.meta.js"/>
|
||||
</target>
|
||||
|
||||
<target name="post_build" depends="zipArtifacts, revertTemplateFiles, printStatistics, remove_internal_artifacts, dont_remove_internal_artifacts"/>
|
||||
|
||||
<target name="none">
|
||||
<fail message="Either specify pre_build or post_build"/>
|
||||
</target>
|
||||
|
||||
<property name="teamcity.build.branch" value=""/>
|
||||
|
||||
<condition property="need.remove.artifacts" value="true">
|
||||
<and>
|
||||
<matches pattern="rri?/.*" string="${teamcity.build.branch}"/>
|
||||
<not>
|
||||
<matches pattern="rri?/internal/.*" string="${teamcity.build.branch}"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
|
||||
<target name="remove_internal_artifacts"
|
||||
description="Remove internal artifacts for rri?/* branches, but store them for rri?/internal/*"
|
||||
if="need.remove.artifacts">
|
||||
<echo message="Remove internal artifacts" />
|
||||
|
||||
<delete failonerror="false" verbose="true">
|
||||
<fileset dir="dist">
|
||||
<include name="kotlin-compiler-before-shrink.jar"/>
|
||||
<include name="kotlin-for-upsource.jar"/>
|
||||
<include name="kotlin-for-upsource-sources.jar"/>
|
||||
<include name="kotlin-test-data.zip"/>
|
||||
</fileset>
|
||||
<fileset dir="out/artifacts/internal">
|
||||
<include name="kotlin-ide-common.jar"/>
|
||||
</fileset>
|
||||
</delete>
|
||||
</target>
|
||||
|
||||
<target name="dont_remove_internal_artifacts" unless="need.remove.artifacts">
|
||||
<echo message="Internal artifacts left untouched"/>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
@@ -10,15 +10,17 @@ dependencies {
|
||||
compileOnly(project(":compiler:frontend.java"))
|
||||
compileOnly(project(":js:js.serializer"))
|
||||
compileOnly(project(":js:js.frontend"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeJars("annotations", "asm-all", "trove4j", "util") }
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
compileOnly(ideaSdkDeps("util"))
|
||||
|
||||
testCompileOnly(project(":compiler:cli-common"))
|
||||
testCompile(projectTests(":compiler:tests-common"))
|
||||
testCompile(commonDep("junit:junit"))
|
||||
testCompile(protobufFull())
|
||||
testCompile(projectDist(":kotlin-stdlib"))
|
||||
testCompileOnly(ideaSdkDeps("openapi"))
|
||||
testRuntime(projectDist(":kotlin-compiler"))
|
||||
testCompileOnly(intellijDep()) { includeJars("openapi") }
|
||||
|
||||
testRuntime(projectDist(":kotlin-reflect"))
|
||||
}
|
||||
|
||||
|
||||
@@ -14,17 +14,27 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.configuration;
|
||||
package org.jetbrains.kotlin.serialization.java;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import "core/deserialization/src/descriptors.proto";
|
||||
|
||||
public abstract class KotlinModuleTypeManager {
|
||||
public static KotlinModuleTypeManager getInstance() {
|
||||
return ServiceManager.getService(KotlinModuleTypeManager.class);
|
||||
}
|
||||
option java_outer_classname = "JavaClassProtoBuf";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
public abstract boolean isAndroidGradleModule(@NotNull Module module);
|
||||
public abstract boolean isGradleModule(@NotNull Module module);
|
||||
extend Function {
|
||||
optional bool is_static_method = 1000;
|
||||
optional bool is_package_private_method = 1001;
|
||||
}
|
||||
|
||||
extend Property {
|
||||
optional bool is_static_field = 1000;
|
||||
optional bool is_package_private_field = 1001;
|
||||
}
|
||||
|
||||
extend Class {
|
||||
optional bool is_package_private_class = 1000;
|
||||
}
|
||||
|
||||
extend Constructor {
|
||||
optional bool is_package_private_constructor = 1000;
|
||||
}
|
||||
@@ -72,13 +72,13 @@ class ChangesCollector {
|
||||
}
|
||||
}
|
||||
|
||||
fun collectProtoChanges(oldData: ProtoData?, newData: ProtoData?) {
|
||||
fun collectProtoChanges(oldData: ProtoData?, newData: ProtoData?, collectAllMembersForNewClass: Boolean = false) {
|
||||
if (oldData == null && newData == null) {
|
||||
throw IllegalStateException("Old and new value are null")
|
||||
}
|
||||
|
||||
if (oldData == null) {
|
||||
newData!!.collectAll(isRemoved = false)
|
||||
newData!!.collectAll(isRemoved = false, collectAllMembersForNewClass = collectAllMembersForNewClass)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -120,10 +120,10 @@ class ChangesCollector {
|
||||
private fun <T> T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List<MessageLite>): Set<String> =
|
||||
members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet()
|
||||
|
||||
private fun ProtoData.collectAll(isRemoved: Boolean) =
|
||||
private fun ProtoData.collectAll(isRemoved: Boolean, collectAllMembersForNewClass: Boolean = false) =
|
||||
when (this) {
|
||||
is PackagePartProtoData -> collectAllFromPackage(isRemoved)
|
||||
is ClassProtoData -> collectAllFromClass(isRemoved)
|
||||
is ClassProtoData -> collectAllFromClass(isRemoved, collectAllMembersForNewClass)
|
||||
}
|
||||
|
||||
private fun PackagePartProtoData.collectAllFromPackage(isRemoved: Boolean) {
|
||||
@@ -142,28 +142,36 @@ class ChangesCollector {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassProtoData.collectAllFromClass(isRemoved: Boolean) {
|
||||
private fun ClassProtoData.collectAllFromClass(isRemoved: Boolean, collectAllMembersForNewClass: Boolean = false) {
|
||||
val classFqName = nameResolver.getClassId(proto.fqName).asSingleFqName()
|
||||
val kind = Flags.CLASS_KIND.get(proto.flags)
|
||||
|
||||
if (kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
|
||||
val memberNames =
|
||||
proto.getNonPrivateNames(
|
||||
nameResolver,
|
||||
ProtoBuf.Class::getConstructorList,
|
||||
ProtoBuf.Class::getFunctionList,
|
||||
ProtoBuf.Class::getPropertyList
|
||||
) + proto.enumEntryList.map { nameResolver.getString(it.name) }
|
||||
val memberNames = getNonPrivateMemberNames()
|
||||
|
||||
val collectMember = if (isRemoved) this@ChangesCollector::collectRemovedMember else this@ChangesCollector::collectChangedMember
|
||||
collectMember(classFqName.parent(), classFqName.shortName().asString())
|
||||
memberNames.forEach { collectMember(classFqName, it) }
|
||||
}
|
||||
else {
|
||||
if (!isRemoved && collectAllMembersForNewClass) {
|
||||
val memberNames = getNonPrivateMemberNames()
|
||||
memberNames.forEach { this@ChangesCollector.collectChangedMember(classFqName, it) }
|
||||
}
|
||||
|
||||
collectSignature(classFqName, areSubclassesAffected = true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassProtoData.getNonPrivateMemberNames(): Set<String> {
|
||||
return proto.getNonPrivateNames(
|
||||
nameResolver,
|
||||
ProtoBuf.Class::getConstructorList,
|
||||
ProtoBuf.Class::getFunctionList,
|
||||
ProtoBuf.Class::getPropertyList
|
||||
) + proto.enumEntryList.map { nameResolver.getString(it.name) }
|
||||
}
|
||||
|
||||
fun collectMemberIfValueWasChanged(scope: FqName, name: String, oldValue: Any?, newValue: Any?) {
|
||||
if (oldValue == null && newValue == null) {
|
||||
throw IllegalStateException("Old and new value are null for $scope#$name")
|
||||
@@ -186,4 +194,4 @@ class ChangesCollector {
|
||||
val prevValue = this.areSubclassesAffected[fqName] ?: false
|
||||
this.areSubclassesAffected[fqName] = prevValue || areSubclassesAffected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,18 +28,20 @@ import java.io.File
|
||||
/**
|
||||
* Incremental cache common for JVM and JS
|
||||
*/
|
||||
abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(workingDir) {
|
||||
abstract class IncrementalCacheCommon<ClassName>(workingDir: File) : BasicMapsOwner(workingDir) {
|
||||
companion object {
|
||||
private val SUBTYPES = "subtypes"
|
||||
private val SUPERTYPES = "supertypes"
|
||||
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
||||
@JvmStatic protected val SOURCE_TO_CLASSES = "source-to-classes"
|
||||
@JvmStatic protected val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
||||
}
|
||||
|
||||
private val dependents = arrayListOf<IncrementalCacheCommon>()
|
||||
fun addDependentCache(cache: IncrementalCacheCommon) {
|
||||
private val dependents = arrayListOf<IncrementalCacheCommon<ClassName>>()
|
||||
fun addDependentCache(cache: IncrementalCacheCommon<ClassName>) {
|
||||
dependents.add(cache)
|
||||
}
|
||||
val thisWithDependentCaches: Iterable<IncrementalCacheCommon> by lazy {
|
||||
val thisWithDependentCaches: Iterable<IncrementalCacheCommon<ClassName>> by lazy {
|
||||
val result = arrayListOf(this)
|
||||
result.addAll(dependents)
|
||||
result
|
||||
@@ -48,6 +50,8 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working
|
||||
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
||||
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
||||
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
|
||||
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
|
||||
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
|
||||
|
||||
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||
subtypesMap[className].asSequence()
|
||||
@@ -55,7 +59,16 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working
|
||||
fun getSourceFileIfClass(fqName: FqName): File? =
|
||||
classFqNameToSourceMap[fqName]
|
||||
|
||||
abstract fun markDirty(removedAndCompiledSources: List<File>)
|
||||
open fun markDirty(removedAndCompiledSources: List<File>) {
|
||||
for (sourceFile in removedAndCompiledSources) {
|
||||
val classes = sourceToClassesMap[sourceFile]
|
||||
classes.forEach {
|
||||
dirtyOutputClassesMap.markDirty(it)
|
||||
}
|
||||
|
||||
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun addToClassStorage(proto: ProtoBuf.Class, nameResolver: NameResolver, srcFile: File) {
|
||||
val supertypes = proto.supertypes(TypeTable(proto.typeTable))
|
||||
@@ -73,11 +86,19 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working
|
||||
classFqNameToSourceMap[child] = srcFile
|
||||
}
|
||||
|
||||
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>) {
|
||||
abstract fun clearCacheForRemovedClasses(changesCollector: ChangesCollector)
|
||||
|
||||
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>, changesCollector: ChangesCollector) {
|
||||
if (removedClasses.isEmpty()) return
|
||||
|
||||
val removedFqNames = removedClasses.toSet()
|
||||
|
||||
for (removedClass in removedFqNames) {
|
||||
for (affectedClass in withSubtypes(removedClass, thisWithDependentCaches)) {
|
||||
changesCollector.collectSignature(affectedClass, areSubclassesAffected = false)
|
||||
}
|
||||
}
|
||||
|
||||
for (cache in thisWithDependentCaches) {
|
||||
val parentsFqNames = hashSetOf<FqName>()
|
||||
val childrenFqNames = hashSetOf<FqName>()
|
||||
|
||||
@@ -31,19 +31,20 @@ import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
|
||||
open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDir) {
|
||||
open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon<FqName>(cachesDir) {
|
||||
companion object {
|
||||
private val TRANSLATION_RESULT_MAP = "translation-result"
|
||||
private val SOURCES_TO_CLASSES_FQNS = "sources-to-classes"
|
||||
private val INLINE_FUNCTIONS = "inline-functions"
|
||||
private val HEADER_FILE_NAME = "header.meta"
|
||||
}
|
||||
|
||||
private val dirtySources = arrayListOf<File>()
|
||||
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile))
|
||||
override val dirtyOutputClassesMap = registerMap(DirtyClassesFqNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile))
|
||||
private val sourcesToClasses = registerMap(SourceToClassesMap(SOURCES_TO_CLASSES_FQNS.storageFile))
|
||||
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
||||
|
||||
private val dirtySources = hashSetOf<File>()
|
||||
|
||||
private val headerFile: File
|
||||
get() = File(cachesDir, HEADER_FILE_NAME)
|
||||
|
||||
@@ -55,30 +56,23 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi
|
||||
}
|
||||
|
||||
override fun markDirty(removedAndCompiledSources: List<File>) {
|
||||
super.markDirty(removedAndCompiledSources)
|
||||
dirtySources.addAll(removedAndCompiledSources)
|
||||
}
|
||||
|
||||
fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) {
|
||||
val translatedFiles = incrementalResults.packageParts
|
||||
|
||||
dirtySources.forEach {
|
||||
if (it !in translatedFiles) {
|
||||
translationResults.remove(it, changesCollector)
|
||||
inlineFunctions.remove(it)
|
||||
}
|
||||
|
||||
removeAllFromClassStorage(sourcesToClasses[it])
|
||||
sourcesToClasses.clearOutputsForSource(it)
|
||||
}
|
||||
dirtySources.clear()
|
||||
|
||||
for ((srcFile, data) in translatedFiles) {
|
||||
dirtySources.remove(srcFile)
|
||||
val (binaryMetadata, binaryAst) = data
|
||||
|
||||
val oldProtoMap = translationResults[srcFile]?.metadata?.let { getProtoData(srcFile, it) } ?: emptyMap()
|
||||
val newProtoMap = getProtoData(srcFile, binaryMetadata)
|
||||
|
||||
for (protoData in newProtoMap.values) {
|
||||
for ((classId, protoData) in newProtoMap) {
|
||||
registerOutputForFile(srcFile, classId.asSingleFqName())
|
||||
|
||||
if (protoData is ClassProtoData) {
|
||||
addToClassStorage(protoData.proto, protoData.nameResolver, srcFile)
|
||||
}
|
||||
@@ -96,6 +90,21 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerOutputForFile(srcFile: File, name: FqName) {
|
||||
sourceToClassesMap.add(srcFile, name)
|
||||
dirtyOutputClassesMap.notDirty(name)
|
||||
}
|
||||
|
||||
override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
||||
dirtySources.forEach {
|
||||
translationResults.remove(it, changesCollector)
|
||||
inlineFunctions.remove(it)
|
||||
}
|
||||
removeAllFromClassStorage(dirtyOutputClassesMap.getDirtyOutputClasses(), changesCollector)
|
||||
dirtySources.clear()
|
||||
dirtyOutputClassesMap.clean()
|
||||
}
|
||||
|
||||
fun nonDirtyPackageParts(): Map<File, TranslationResultValue> =
|
||||
hashMapOf<File, TranslationResultValue>().apply {
|
||||
for (path in translationResults.keys()) {
|
||||
@@ -107,25 +116,6 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi
|
||||
}
|
||||
}
|
||||
|
||||
private class SourceToClassesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
fun clearOutputsForSource(sourceFile: File) {
|
||||
remove(sourceFile.canonicalPath)
|
||||
}
|
||||
|
||||
fun add(sourceFile: File, className: FqName) {
|
||||
storage.append(sourceFile.canonicalPath, className.asString())
|
||||
}
|
||||
|
||||
operator fun get(sourceFile: File): Collection<FqName> =
|
||||
storage[sourceFile.canonicalPath].orEmpty().map { FqName(it) }
|
||||
|
||||
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
|
||||
|
||||
private fun remove(path: String) {
|
||||
storage.remove(path)
|
||||
}
|
||||
}
|
||||
|
||||
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
|
||||
override fun save(output: DataOutput, value: TranslationResultValue) {
|
||||
output.writeInt(value.metadata.size)
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
|
||||
@@ -43,46 +44,38 @@ val KOTLIN_CACHE_DIRECTORY_NAME = "kotlin"
|
||||
open class IncrementalJvmCache(
|
||||
private val targetDataRoot: File,
|
||||
targetOutputDir: File?
|
||||
) : IncrementalCacheCommon(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
|
||||
) : IncrementalCacheCommon<JvmClassName>(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
|
||||
companion object {
|
||||
private val PROTO_MAP = "proto"
|
||||
private val CONSTANTS_MAP = "constants"
|
||||
private val PACKAGE_PARTS = "package-parts"
|
||||
private val MULTIFILE_CLASS_FACADES = "multifile-class-facades"
|
||||
private val MULTIFILE_CLASS_PARTS = "multifile-class-parts"
|
||||
private val SOURCE_TO_CLASSES = "source-to-classes"
|
||||
private val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
||||
private val INLINE_FUNCTIONS = "inline-functions"
|
||||
private val INTERNAL_NAME_TO_SOURCE = "internal-name-to-source"
|
||||
private val JAVA_SOURCES_PROTO_MAP = "java-sources-proto-map"
|
||||
|
||||
private val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
|
||||
}
|
||||
|
||||
override val sourceToClassesMap = registerMap(SourceToJvmNameMap(SOURCE_TO_CLASSES.storageFile))
|
||||
override val dirtyOutputClassesMap = registerMap(DirtyClassesJvmNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||
|
||||
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
|
||||
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
|
||||
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
|
||||
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
|
||||
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
|
||||
private val sourceToClassesMap = registerMap(SourceToClassesMap(SOURCE_TO_CLASSES.storageFile))
|
||||
private val dirtyOutputClassesMap = registerMap(DirtyOutputClassesMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
||||
// todo: try to use internal names only?
|
||||
private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile))
|
||||
private val javaSourcesProtoMap = registerMap(JavaSourcesProtoMap(JAVA_SOURCES_PROTO_MAP.storageFile))
|
||||
|
||||
private val outputDir by lazy(LazyThreadSafetyMode.NONE) { requireNotNull(targetOutputDir) { "Target is expected to have output directory" } }
|
||||
|
||||
protected open fun debugLog(message: String) {}
|
||||
|
||||
override fun markDirty(removedAndCompiledSources: List<File>) {
|
||||
for (sourceFile in removedAndCompiledSources) {
|
||||
val classes = sourceToClassesMap[sourceFile]
|
||||
classes.forEach {
|
||||
dirtyOutputClassesMap.markDirty(it.internalName)
|
||||
}
|
||||
|
||||
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
||||
}
|
||||
}
|
||||
fun isTrackedFile(file: File) = sourceToClassesMap.contains(file)
|
||||
|
||||
// used in gradle
|
||||
@Suppress("unused")
|
||||
@@ -93,7 +86,7 @@ open class IncrementalJvmCache(
|
||||
internalNameToSource[internalName]
|
||||
|
||||
fun isMultifileFacade(className: JvmClassName): Boolean =
|
||||
className.internalName in multifileFacadeToParts
|
||||
className in multifileFacadeToParts
|
||||
|
||||
override fun getClassFilePath(internalClassName: String): String {
|
||||
return toSystemIndependentName(File(outputDir, "$internalClassName.class").canonicalPath)
|
||||
@@ -102,7 +95,7 @@ open class IncrementalJvmCache(
|
||||
fun saveModuleMappingToCache(sourceFiles: Collection<File>, file: File) {
|
||||
val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)
|
||||
protoMap.storeModuleMapping(jvmClassName, file.readBytes())
|
||||
dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME)
|
||||
dirtyOutputClassesMap.notDirty(jvmClassName)
|
||||
sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) }
|
||||
}
|
||||
|
||||
@@ -111,7 +104,7 @@ open class IncrementalJvmCache(
|
||||
val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass
|
||||
val className = kotlinClass.className
|
||||
|
||||
dirtyOutputClassesMap.notDirty(className.internalName)
|
||||
dirtyOutputClassesMap.notDirty(className)
|
||||
sourceFiles.forEach {
|
||||
sourceToClassesMap.add(it, className)
|
||||
}
|
||||
@@ -169,22 +162,46 @@ open class IncrementalJvmCache(
|
||||
}
|
||||
}
|
||||
|
||||
fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
||||
val dirtyClasses = dirtyOutputClassesMap
|
||||
.getDirtyOutputClasses()
|
||||
.map(JvmClassName::byInternalName)
|
||||
.toList()
|
||||
fun saveJavaClassProto(source: File, serializedJavaClass: SerializedJavaClass, collector: ChangesCollector) {
|
||||
val jvmClassName = JvmClassName.byClassId(serializedJavaClass.classId)
|
||||
javaSourcesProtoMap.process(jvmClassName, serializedJavaClass, collector)
|
||||
sourceToClassesMap.add(source, jvmClassName)
|
||||
val (proto, nameResolver) = serializedJavaClass.toProtoData()
|
||||
addToClassStorage(proto, nameResolver, source)
|
||||
|
||||
dirtyOutputClassesMap.notDirty(jvmClassName)
|
||||
}
|
||||
|
||||
fun getObsoleteJavaClasses(): Collection<ClassId> =
|
||||
dirtyOutputClassesMap.getDirtyOutputClasses()
|
||||
.mapNotNull {
|
||||
javaSourcesProtoMap[it]?.classId
|
||||
}
|
||||
|
||||
fun isJavaClassToTrack(classId: ClassId): Boolean {
|
||||
val jvmClassName = JvmClassName.byClassId(classId)
|
||||
return dirtyOutputClassesMap.isDirty(jvmClassName) ||
|
||||
jvmClassName !in javaSourcesProtoMap
|
||||
}
|
||||
|
||||
fun isJavaClassAlreadyInCache(classId: ClassId): Boolean {
|
||||
val jvmClassName = JvmClassName.byClassId(classId)
|
||||
return jvmClassName in javaSourcesProtoMap
|
||||
}
|
||||
|
||||
override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
||||
val dirtyClasses = dirtyOutputClassesMap.getDirtyOutputClasses()
|
||||
|
||||
val facadesWithRemovedParts = hashMapOf<JvmClassName, MutableSet<String>>()
|
||||
for (dirtyClass in dirtyClasses) {
|
||||
val facade = partToMultifileFacade.get(dirtyClass.internalName) ?: continue
|
||||
val facade = partToMultifileFacade.get(dirtyClass) ?: continue
|
||||
val facadeClassName = JvmClassName.byInternalName(facade)
|
||||
val removedParts = facadesWithRemovedParts.getOrPut(facadeClassName) { hashSetOf() }
|
||||
removedParts.add(dirtyClass.internalName)
|
||||
}
|
||||
|
||||
for ((facade, removedParts) in facadesWithRemovedParts.entries) {
|
||||
val allParts = multifileFacadeToParts[facade.internalName] ?: continue
|
||||
val allParts = multifileFacadeToParts[facade] ?: continue
|
||||
val notRemovedParts = allParts.filter { it !in removedParts }
|
||||
|
||||
if (notRemovedParts.isEmpty()) {
|
||||
@@ -203,18 +220,17 @@ open class IncrementalJvmCache(
|
||||
constantsMap.remove(it)
|
||||
inlineFunctionsMap.remove(it)
|
||||
internalNameToSource.remove(it.internalName)
|
||||
javaSourcesProtoMap.remove(it, changesCollector)
|
||||
}
|
||||
|
||||
removeAllFromClassStorage(dirtyClasses.map { it.fqNameForClassNameWithoutDollars })
|
||||
|
||||
removeAllFromClassStorage(dirtyClasses.map { it.fqNameForClassNameWithoutDollars }, changesCollector)
|
||||
dirtyOutputClassesMap.clean()
|
||||
}
|
||||
|
||||
override fun getObsoletePackageParts(): Collection<String> {
|
||||
val obsoletePackageParts =
|
||||
dirtyOutputClassesMap.getDirtyOutputClasses().filter { packagePartMap.isPackagePart(JvmClassName.byInternalName(it)) }
|
||||
val obsoletePackageParts = dirtyOutputClassesMap.getDirtyOutputClasses().filter(packagePartMap::isPackagePart)
|
||||
debugLog("Obsolete package parts: $obsoletePackageParts")
|
||||
return obsoletePackageParts
|
||||
return obsoletePackageParts.map { it.internalName }
|
||||
}
|
||||
|
||||
override fun getPackagePartData(partInternalName: String): JvmPackagePartProto? {
|
||||
@@ -234,8 +250,9 @@ open class IncrementalJvmCache(
|
||||
}
|
||||
|
||||
override fun getStableMultifileFacadeParts(facadeInternalName: String): Collection<String>? {
|
||||
val partNames = multifileFacadeToParts.get(facadeInternalName) ?: return null
|
||||
return partNames.filter { !dirtyOutputClassesMap.isDirty(it) }
|
||||
val jvmClassName = JvmClassName.byInternalName(facadeInternalName)
|
||||
val partNames = multifileFacadeToParts[jvmClassName] ?: return null
|
||||
return partNames.filter { !dirtyOutputClassesMap.isDirty(JvmClassName.byInternalName(it)) }
|
||||
}
|
||||
|
||||
override fun getModuleMappingData(): ByteArray? {
|
||||
@@ -298,6 +315,36 @@ open class IncrementalJvmCache(
|
||||
}
|
||||
}
|
||||
|
||||
private inner class JavaSourcesProtoMap(storageFile: File) : BasicStringMap<SerializedJavaClass>(storageFile, JavaClassProtoMapValueExternalizer) {
|
||||
fun process(jvmClassName: JvmClassName, newData: SerializedJavaClass, changesCollector: ChangesCollector) {
|
||||
val key = jvmClassName.internalName
|
||||
val oldData = storage[key]
|
||||
storage[key] = newData
|
||||
|
||||
changesCollector.collectProtoChanges(
|
||||
oldData?.toProtoData(), newData.toProtoData(),
|
||||
collectAllMembersForNewClass = true
|
||||
)
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName, changesCollector: ChangesCollector) {
|
||||
val key = className.internalName
|
||||
val oldValue = storage[key] ?: return
|
||||
storage.remove(key)
|
||||
|
||||
changesCollector.collectProtoChanges(oldValue.toProtoData(), newData = null)
|
||||
}
|
||||
|
||||
operator fun get(className: JvmClassName): SerializedJavaClass? =
|
||||
storage[className.internalName]
|
||||
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
override fun dumpValue(value: SerializedJavaClass): String =
|
||||
java.lang.Long.toHexString(value.proto.toByteArray().md5())
|
||||
}
|
||||
|
||||
// todo: reuse code with InlineFunctionsMap?
|
||||
private inner class ConstantsMap(storageFile: File) : BasicStringMap<Map<String, Any>>(storageFile, ConstantsMapExternalizer) {
|
||||
private fun getConstantsMap(bytes: ByteArray): Map<String, Any> {
|
||||
@@ -360,13 +407,15 @@ open class IncrementalJvmCache(
|
||||
}
|
||||
|
||||
private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
||||
operator fun set(facadeName: JvmClassName, partNames: Collection<String>) {
|
||||
storage[facadeName.internalName] = partNames
|
||||
operator fun set(className: JvmClassName, partNames: Collection<String>) {
|
||||
storage[className.internalName] = partNames
|
||||
}
|
||||
|
||||
operator fun get(internalName: String): Collection<String>? = storage[internalName]
|
||||
operator fun get(className: JvmClassName): Collection<String>? =
|
||||
storage[className.internalName]
|
||||
|
||||
operator fun contains(internalName: String): Boolean = internalName in storage
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
@@ -380,9 +429,8 @@ open class IncrementalJvmCache(
|
||||
storage[partName] = facadeName
|
||||
}
|
||||
|
||||
fun get(partName: String): String? {
|
||||
return storage.get(partName)
|
||||
}
|
||||
fun get(partName: JvmClassName): String? =
|
||||
storage[partName.internalName]
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
@@ -391,25 +439,6 @@ open class IncrementalJvmCache(
|
||||
override fun dumpValue(value: String): String = value
|
||||
}
|
||||
|
||||
inner class SourceToClassesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
fun clearOutputsForSource(sourceFile: File) {
|
||||
remove(sourceFile.absolutePath)
|
||||
}
|
||||
|
||||
fun add(sourceFile: File, className: JvmClassName) {
|
||||
storage.append(sourceFile.absolutePath, className.internalName)
|
||||
}
|
||||
|
||||
operator fun get(sourceFile: File): Collection<JvmClassName> =
|
||||
storage[sourceFile.absolutePath].orEmpty().map { JvmClassName.byInternalName(it) }
|
||||
|
||||
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
|
||||
|
||||
private fun remove(path: String) {
|
||||
storage.remove(path)
|
||||
}
|
||||
}
|
||||
|
||||
inner class InternalNameToSourcesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) {
|
||||
operator fun set(internalName: String, sourceFiles: Iterable<File>) {
|
||||
storage[internalName] = sourceFiles.map { it.canonicalPath }
|
||||
@@ -431,24 +460,6 @@ open class IncrementalJvmCache(
|
||||
addToClassStorage(proto, nameResolver, srcFile)
|
||||
}
|
||||
|
||||
private inner class DirtyOutputClassesMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||
fun markDirty(className: String) {
|
||||
storage[className] = true
|
||||
}
|
||||
|
||||
fun notDirty(className: String) {
|
||||
storage.remove(className)
|
||||
}
|
||||
|
||||
fun getDirtyOutputClasses(): Collection<String> =
|
||||
storage.keys
|
||||
|
||||
fun isDirty(className: String): Boolean =
|
||||
storage.contains(className)
|
||||
|
||||
override fun dumpValue(value: Boolean) = ""
|
||||
}
|
||||
|
||||
private inner class InlineFunctionsMap(storageFile: File) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
||||
private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray): Map<String, Long> {
|
||||
val inlineFunctions = inlineFunctionsJvmNames(header)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.incremental
|
||||
|
||||
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf
|
||||
|
||||
// It uses BuiltInSerializerProtocol for annotations serialization
|
||||
class JavaClassesSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
|
||||
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) {
|
||||
super.serializeClass(descriptor, proto)
|
||||
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
|
||||
proto.setExtension(JavaClassProtoBuf.isPackagePrivateClass, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder) {
|
||||
super.serializeConstructor(descriptor, proto)
|
||||
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
|
||||
proto.setExtension(JavaClassProtoBuf.isPackagePrivateConstructor, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) {
|
||||
super.serializeFunction(descriptor, proto)
|
||||
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
|
||||
proto.setExtension(JavaClassProtoBuf.isPackagePrivateMethod, true)
|
||||
}
|
||||
|
||||
if (descriptor.dispatchReceiverParameter == null) {
|
||||
proto.setExtension(JavaClassProtoBuf.isStaticMethod, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) {
|
||||
super.serializeProperty(descriptor, proto)
|
||||
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
|
||||
proto.setExtension(JavaClassProtoBuf.isPackagePrivateField, true)
|
||||
}
|
||||
|
||||
if (descriptor.dispatchReceiverParameter == null) {
|
||||
proto.setExtension(JavaClassProtoBuf.isStaticField, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun shouldUseNormalizedVisibility() = true
|
||||
|
||||
override val customClassMembersProducer =
|
||||
object : ClassMembersProducer {
|
||||
override fun getCallableMembers(classDescriptor: ClassDescriptor) =
|
||||
arrayListOf<CallableMemberDescriptor>().apply {
|
||||
addAll(classDescriptor.unsubstitutedMemberScope.getSortedCallableDescriptors())
|
||||
addAll(classDescriptor.staticScope.getSortedCallableDescriptors())
|
||||
}
|
||||
}
|
||||
|
||||
private fun MemberScope.getSortedCallableDescriptors(): Collection<CallableMemberDescriptor> =
|
||||
DescriptorUtils.getAllDescriptors(this).filterIsInstance<CallableMemberDescriptor>()
|
||||
.let { DescriptorSerializer.sort(it) }
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.incremental
|
||||
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.load.java.JavaClassesTracker
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf
|
||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
|
||||
val CONVERTING_JAVA_CLASSES_TO_PROTO = PerformanceCounter.create("Converting Java sources to proto")
|
||||
|
||||
class JavaClassesTrackerImpl(
|
||||
private val cache: IncrementalJvmCache,
|
||||
private val untrackedJavaClasses: Set<ClassId>
|
||||
) : JavaClassesTracker {
|
||||
private val classToSourceSerialized: MutableMap<ClassId, SerializedJavaClassWithSource> = hashMapOf()
|
||||
|
||||
val javaClassesUpdates: Collection<SerializedJavaClassWithSource>
|
||||
get() = classToSourceSerialized.values
|
||||
|
||||
private val classDescriptors: MutableList<JavaClassDescriptor> = mutableListOf()
|
||||
|
||||
override fun reportClass(classDescriptor: JavaClassDescriptor) {
|
||||
val classId = classDescriptor.classId!!
|
||||
if (!cache.isJavaClassToTrack(classId) || classDescriptor.javaSourceFile == null) return
|
||||
|
||||
classDescriptors.add(classDescriptor)
|
||||
}
|
||||
|
||||
override fun onCompletedAnalysis(module: ModuleDescriptor) {
|
||||
for (classId in cache.getObsoleteJavaClasses() + untrackedJavaClasses) {
|
||||
// Just force the loading obsolete classes
|
||||
// We assume here that whenever an LazyJavaClassDescriptor instances is created
|
||||
// it's being passed to JavaClassesTracker::reportClass
|
||||
module.findClassAcrossModuleDependencies(classId)
|
||||
}
|
||||
|
||||
for (classDescriptor in classDescriptors.toList()) {
|
||||
val classId = classDescriptor.classId!!
|
||||
if (cache.isJavaClassAlreadyInCache(classId) || classId in untrackedJavaClasses || classDescriptor.wasContentRequested()) {
|
||||
assert(classId !in classToSourceSerialized) {
|
||||
"Duplicated JavaClassDescriptor $classId reported to IC"
|
||||
}
|
||||
classToSourceSerialized[classId] = CONVERTING_JAVA_CLASSES_TO_PROTO.time {
|
||||
classDescriptor.convertToProto()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun JavaClassDescriptor.wasContentRequested() =
|
||||
this.safeAs<LazyJavaClassDescriptor>()?.wasScopeContentRequested() != false
|
||||
}
|
||||
|
||||
private val JavaClassDescriptor.javaSourceFile: File?
|
||||
get() = source.safeAs<PsiSourceElement>()
|
||||
?.psi?.containingFile?.takeIf { it is PsiJavaFile }
|
||||
?.virtualFile?.path?.let(::File)
|
||||
|
||||
fun JavaClassDescriptor.convertToProto(): SerializedJavaClassWithSource {
|
||||
val file = javaSourceFile.sure { "convertToProto should only be called for source based classes" }
|
||||
|
||||
val extension = JavaClassesSerializerExtension()
|
||||
val serializer = DescriptorSerializer.createTopLevel(extension)
|
||||
val classProto = serializer.classProto(this).build()
|
||||
|
||||
val (stringTable, qualifiedNameTable) = extension.stringTable.buildProto()
|
||||
|
||||
return SerializedJavaClassWithSource(file, SerializedJavaClass(classProto, stringTable, qualifiedNameTable))
|
||||
}
|
||||
|
||||
class SerializedJavaClass(
|
||||
val proto: ProtoBuf.Class,
|
||||
val stringTable: ProtoBuf.StringTable,
|
||||
val qualifiedNameTable: ProtoBuf.QualifiedNameTable
|
||||
) {
|
||||
val classId: ClassId
|
||||
get() = NameResolverImpl(stringTable, qualifiedNameTable).getClassId(proto.fqName)
|
||||
}
|
||||
|
||||
data class SerializedJavaClassWithSource(
|
||||
val source: File,
|
||||
val proto: SerializedJavaClass
|
||||
)
|
||||
|
||||
fun SerializedJavaClass.toProtoData() = ClassProtoData(proto, NameResolverImpl(stringTable, qualifiedNameTable))
|
||||
|
||||
val JAVA_CLASS_PROTOBUF_REGISTRY =
|
||||
ExtensionRegistryLite.newInstance()
|
||||
.also(JavaClassProtoBuf::registerAllExtensions)
|
||||
// Built-ins extensions are used for annotations' serialization
|
||||
.also(BuiltInsProtoBuf::registerAllExtensions)
|
||||
|
||||
object JavaClassProtoMapValueExternalizer : DataExternalizer<SerializedJavaClass> {
|
||||
override fun save(output: DataOutput, value: SerializedJavaClass) {
|
||||
output.writeBytesWithSize(value.proto.toByteArray())
|
||||
output.writeBytesWithSize(value.stringTable.toByteArray())
|
||||
output.writeBytesWithSize(value.qualifiedNameTable.toByteArray())
|
||||
}
|
||||
|
||||
private fun DataOutput.writeBytesWithSize(bytes: ByteArray) {
|
||||
writeInt(bytes.size)
|
||||
write(bytes)
|
||||
}
|
||||
|
||||
private fun DataInput.readBytesWithSize(): ByteArray {
|
||||
val bytesLength = readInt()
|
||||
return ByteArray(bytesLength).also {
|
||||
readFully(it, 0, bytesLength)
|
||||
}
|
||||
}
|
||||
|
||||
override fun read(input: DataInput): SerializedJavaClass {
|
||||
val proto = ProtoBuf.Class.parseFrom(input.readBytesWithSize(), JAVA_CLASS_PROTOBUF_REGISTRY)
|
||||
val stringTable = ProtoBuf.StringTable.parseFrom(input.readBytesWithSize(), JAVA_CLASS_PROTOBUF_REGISTRY)
|
||||
val qualifiedNameTable = ProtoBuf.QualifiedNameTable.parseFrom(input.readBytesWithSize(), JAVA_CLASS_PROTOBUF_REGISTRY)
|
||||
|
||||
return SerializedJavaClass(proto, stringTable, qualifiedNameTable)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
* Copyright 2010-2018 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.
|
||||
@@ -19,8 +19,10 @@ package org.jetbrains.kotlin.incremental
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.js.JsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf
|
||||
import org.jetbrains.kotlin.utils.Interner
|
||||
import java.util.*
|
||||
|
||||
@@ -71,6 +73,11 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.getExtension(JsProtoBuf.packageFqName) != new.getExtension(JsProtoBuf.packageFqName)) return false
|
||||
}
|
||||
|
||||
if (old.hasExtension(BuiltInsProtoBuf.packageFqName) != new.hasExtension(BuiltInsProtoBuf.packageFqName)) return false
|
||||
if (old.hasExtension(BuiltInsProtoBuf.packageFqName)) {
|
||||
if (old.getExtension(BuiltInsProtoBuf.packageFqName) != new.getExtension(BuiltInsProtoBuf.packageFqName)) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
enum class ProtoBufPackageKind {
|
||||
@@ -81,7 +88,8 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
VERSION_REQUIREMENT_TABLE,
|
||||
JVM_EXT_PACKAGE_MODULE_NAME,
|
||||
JVM_EXT_PACKAGE_LOCAL_VARIABLE_LIST,
|
||||
JS_EXT_PACKAGE_FQ_NAME
|
||||
JS_EXT_PACKAGE_FQ_NAME,
|
||||
BUILT_INS_EXT_PACKAGE_FQ_NAME
|
||||
}
|
||||
|
||||
fun difference(old: ProtoBuf.Package, new: ProtoBuf.Package): EnumSet<ProtoBufPackageKind> {
|
||||
@@ -122,6 +130,11 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.getExtension(JsProtoBuf.packageFqName) != new.getExtension(JsProtoBuf.packageFqName)) result.add(ProtoBufPackageKind.JS_EXT_PACKAGE_FQ_NAME)
|
||||
}
|
||||
|
||||
if (old.hasExtension(BuiltInsProtoBuf.packageFqName) != new.hasExtension(BuiltInsProtoBuf.packageFqName)) result.add(ProtoBufPackageKind.BUILT_INS_EXT_PACKAGE_FQ_NAME)
|
||||
if (old.hasExtension(BuiltInsProtoBuf.packageFqName)) {
|
||||
if (old.getExtension(BuiltInsProtoBuf.packageFqName) != new.getExtension(BuiltInsProtoBuf.packageFqName)) result.add(ProtoBufPackageKind.BUILT_INS_EXT_PACKAGE_FQ_NAME)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -201,6 +214,20 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.getExtension(JsProtoBuf.classContainingFileId) != new.getExtension(JsProtoBuf.classContainingFileId)) return false
|
||||
}
|
||||
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateClass) != new.hasExtension(JavaClassProtoBuf.isPackagePrivateClass)) return false
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateClass)) {
|
||||
if (old.getExtension(JavaClassProtoBuf.isPackagePrivateClass) != new.getExtension(JavaClassProtoBuf.isPackagePrivateClass)) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.classAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.classAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.classAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.classAnnotation, i), new.getExtension(BuiltInsProtoBuf.classAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
enum class ProtoBufClassKind {
|
||||
@@ -223,7 +250,9 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
JVM_EXT_CLASS_MODULE_NAME,
|
||||
JVM_EXT_CLASS_LOCAL_VARIABLE_LIST,
|
||||
JS_EXT_CLASS_ANNOTATION_LIST,
|
||||
JS_EXT_CLASS_CONTAINING_FILE_ID
|
||||
JS_EXT_CLASS_CONTAINING_FILE_ID,
|
||||
JAVA_EXT_IS_PACKAGE_PRIVATE_CLASS,
|
||||
BUILT_INS_EXT_CLASS_ANNOTATION_LIST
|
||||
}
|
||||
|
||||
fun difference(old: ProtoBuf.Class, new: ProtoBuf.Class): EnumSet<ProtoBufClassKind> {
|
||||
@@ -304,6 +333,20 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.getExtension(JsProtoBuf.classContainingFileId) != new.getExtension(JsProtoBuf.classContainingFileId)) result.add(ProtoBufClassKind.JS_EXT_CLASS_CONTAINING_FILE_ID)
|
||||
}
|
||||
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateClass) != new.hasExtension(JavaClassProtoBuf.isPackagePrivateClass)) result.add(ProtoBufClassKind.JAVA_EXT_IS_PACKAGE_PRIVATE_CLASS)
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateClass)) {
|
||||
if (old.getExtension(JavaClassProtoBuf.isPackagePrivateClass) != new.getExtension(JavaClassProtoBuf.isPackagePrivateClass)) result.add(ProtoBufClassKind.JAVA_EXT_IS_PACKAGE_PRIVATE_CLASS)
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.classAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.classAnnotation)) {
|
||||
result.add(ProtoBufClassKind.BUILT_INS_EXT_CLASS_ANNOTATION_LIST)
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.classAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.classAnnotation, i), new.getExtension(BuiltInsProtoBuf.classAnnotation, i))) result.add(ProtoBufClassKind.BUILT_INS_EXT_CLASS_ANNOTATION_LIST)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -378,6 +421,25 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.getExtension(JsProtoBuf.functionContainingFileId) != new.getExtension(JsProtoBuf.functionContainingFileId)) return false
|
||||
}
|
||||
|
||||
if (old.hasExtension(JavaClassProtoBuf.isStaticMethod) != new.hasExtension(JavaClassProtoBuf.isStaticMethod)) return false
|
||||
if (old.hasExtension(JavaClassProtoBuf.isStaticMethod)) {
|
||||
if (old.getExtension(JavaClassProtoBuf.isStaticMethod) != new.getExtension(JavaClassProtoBuf.isStaticMethod)) return false
|
||||
}
|
||||
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateMethod) != new.hasExtension(JavaClassProtoBuf.isPackagePrivateMethod)) return false
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateMethod)) {
|
||||
if (old.getExtension(JavaClassProtoBuf.isPackagePrivateMethod) != new.getExtension(JavaClassProtoBuf.isPackagePrivateMethod)) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.functionAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.functionAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.functionAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.functionAnnotation, i), new.getExtension(BuiltInsProtoBuf.functionAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -460,6 +522,30 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.getExtension(JsProtoBuf.propertyContainingFileId) != new.getExtension(JsProtoBuf.propertyContainingFileId)) return false
|
||||
}
|
||||
|
||||
if (old.hasExtension(JavaClassProtoBuf.isStaticField) != new.hasExtension(JavaClassProtoBuf.isStaticField)) return false
|
||||
if (old.hasExtension(JavaClassProtoBuf.isStaticField)) {
|
||||
if (old.getExtension(JavaClassProtoBuf.isStaticField) != new.getExtension(JavaClassProtoBuf.isStaticField)) return false
|
||||
}
|
||||
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateField) != new.hasExtension(JavaClassProtoBuf.isPackagePrivateField)) return false
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateField)) {
|
||||
if (old.getExtension(JavaClassProtoBuf.isPackagePrivateField) != new.getExtension(JavaClassProtoBuf.isPackagePrivateField)) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.propertyAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.propertyAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.propertyAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.propertyAnnotation, i), new.getExtension(BuiltInsProtoBuf.propertyAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(BuiltInsProtoBuf.compileTimeValue) != new.hasExtension(BuiltInsProtoBuf.compileTimeValue)) return false
|
||||
if (old.hasExtension(BuiltInsProtoBuf.compileTimeValue)) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.compileTimeValue), new.getExtension(BuiltInsProtoBuf.compileTimeValue))) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -557,6 +643,15 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
}
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.typeParameterAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.typeParameterAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.typeParameterAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.typeParameterAnnotation, i), new.getExtension(BuiltInsProtoBuf.typeParameterAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -651,6 +746,15 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
}
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.typeAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.typeAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.typeAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.typeAnnotation, i), new.getExtension(BuiltInsProtoBuf.typeAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -681,6 +785,20 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateConstructor) != new.hasExtension(JavaClassProtoBuf.isPackagePrivateConstructor)) return false
|
||||
if (old.hasExtension(JavaClassProtoBuf.isPackagePrivateConstructor)) {
|
||||
if (old.getExtension(JavaClassProtoBuf.isPackagePrivateConstructor) != new.getExtension(JavaClassProtoBuf.isPackagePrivateConstructor)) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.constructorAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.constructorAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.constructorAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.constructorAnnotation, i), new.getExtension(BuiltInsProtoBuf.constructorAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -699,6 +817,15 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
}
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.enumEntryAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.enumEntryAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.enumEntryAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.enumEntryAnnotation, i), new.getExtension(BuiltInsProtoBuf.enumEntryAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -747,6 +874,15 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
}
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(BuiltInsProtoBuf.parameterAnnotation) != new.getExtensionCount(BuiltInsProtoBuf.parameterAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(BuiltInsProtoBuf.parameterAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(BuiltInsProtoBuf.parameterAnnotation, i), new.getExtension(BuiltInsProtoBuf.parameterAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1335,6 +1471,10 @@ fun ProtoBuf.Package.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int)
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.packageFqName)
|
||||
}
|
||||
|
||||
if (hasExtension(BuiltInsProtoBuf.packageFqName)) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.packageFqName)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1419,6 +1559,14 @@ fun ProtoBuf.Class.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) ->
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.classContainingFileId)
|
||||
}
|
||||
|
||||
if (hasExtension(JavaClassProtoBuf.isPackagePrivateClass)) {
|
||||
hashCode = 31 * hashCode + getExtension(JavaClassProtoBuf.isPackagePrivateClass).hashCode()
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.classAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.classAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1483,6 +1631,18 @@ fun ProtoBuf.Function.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int)
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.functionContainingFileId)
|
||||
}
|
||||
|
||||
if (hasExtension(JavaClassProtoBuf.isStaticMethod)) {
|
||||
hashCode = 31 * hashCode + getExtension(JavaClassProtoBuf.isStaticMethod).hashCode()
|
||||
}
|
||||
|
||||
if (hasExtension(JavaClassProtoBuf.isPackagePrivateMethod)) {
|
||||
hashCode = 31 * hashCode + getExtension(JavaClassProtoBuf.isPackagePrivateMethod).hashCode()
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.functionAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.functionAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1551,6 +1711,22 @@ fun ProtoBuf.Property.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int)
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.propertyContainingFileId)
|
||||
}
|
||||
|
||||
if (hasExtension(JavaClassProtoBuf.isStaticField)) {
|
||||
hashCode = 31 * hashCode + getExtension(JavaClassProtoBuf.isStaticField).hashCode()
|
||||
}
|
||||
|
||||
if (hasExtension(JavaClassProtoBuf.isPackagePrivateField)) {
|
||||
hashCode = 31 * hashCode + getExtension(JavaClassProtoBuf.isPackagePrivateField).hashCode()
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.propertyAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.propertyAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
if (hasExtension(BuiltInsProtoBuf.compileTimeValue)) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.compileTimeValue).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1649,6 +1825,10 @@ fun ProtoBuf.TypeParameter.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes:
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.typeParameterAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.typeParameterAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.typeParameterAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1723,6 +1903,10 @@ fun ProtoBuf.Type.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) ->
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.typeAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.typeAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.typeAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1749,6 +1933,14 @@ fun ProtoBuf.Constructor.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (I
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.constructorAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
if (hasExtension(JavaClassProtoBuf.isPackagePrivateConstructor)) {
|
||||
hashCode = 31 * hashCode + getExtension(JavaClassProtoBuf.isPackagePrivateConstructor).hashCode()
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.constructorAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.constructorAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1763,6 +1955,10 @@ fun ProtoBuf.EnumEntry.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.enumEntryAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.enumEntryAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.enumEntryAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1807,6 +2003,10 @@ fun ProtoBuf.ValueParameter.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes:
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.parameterAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(BuiltInsProtoBuf.parameterAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(BuiltInsProtoBuf.parameterAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.synthetic.SAM_LOOKUP_NAME
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@@ -79,7 +80,8 @@ fun makeCompileServices(
|
||||
fun updateIncrementalCache(
|
||||
generatedFiles: Iterable<GeneratedFile>,
|
||||
cache: IncrementalJvmCache,
|
||||
changesCollector: ChangesCollector
|
||||
changesCollector: ChangesCollector,
|
||||
javaChangesTracker: JavaClassesTrackerImpl?
|
||||
) {
|
||||
for (generatedFile in generatedFiles) {
|
||||
when {
|
||||
@@ -88,6 +90,11 @@ fun updateIncrementalCache(
|
||||
}
|
||||
}
|
||||
|
||||
javaChangesTracker?.javaClassesUpdates?.forEach {
|
||||
(source, serializedJavaClass) ->
|
||||
cache.saveJavaClassProto(source, serializedJavaClass, changesCollector)
|
||||
}
|
||||
|
||||
cache.clearCacheForRemovedClasses(changesCollector)
|
||||
}
|
||||
|
||||
@@ -109,7 +116,7 @@ data class DirtyData(
|
||||
)
|
||||
|
||||
fun ChangesCollector.getDirtyData(
|
||||
caches: Iterable<IncrementalCacheCommon>,
|
||||
caches: Iterable<IncrementalCacheCommon<*>>,
|
||||
reporter: ICReporter
|
||||
): DirtyData {
|
||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
@@ -135,10 +142,10 @@ fun ChangesCollector.getDirtyData(
|
||||
dirtyClassesFqNames.addAll(fqNames)
|
||||
|
||||
for (name in change.names) {
|
||||
for (fqName in fqNames) {
|
||||
dirtyLookupSymbols.add(LookupSymbol(name, fqName.asString()))
|
||||
}
|
||||
fqNames.mapTo(dirtyLookupSymbols) { LookupSymbol(name, it.asString()) }
|
||||
}
|
||||
|
||||
fqNames.mapTo(dirtyLookupSymbols) { LookupSymbol(SAM_LOOKUP_NAME.asString(), it.asString()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +170,7 @@ fun mapLookupSymbolsToFiles(
|
||||
}
|
||||
|
||||
fun mapClassesFqNamesToFiles(
|
||||
caches: Iterable<IncrementalCacheCommon>,
|
||||
caches: Iterable<IncrementalCacheCommon<*>>,
|
||||
classesFqNames: Iterable<FqName>,
|
||||
reporter: ICReporter,
|
||||
excludes: Set<File> = emptySet()
|
||||
@@ -173,7 +180,7 @@ fun mapClassesFqNamesToFiles(
|
||||
for (cache in caches) {
|
||||
for (dirtyClassFqName in classesFqNames) {
|
||||
val srcFile = cache.getSourceFileIfClass(dirtyClassFqName)
|
||||
if (srcFile == null || srcFile in excludes) continue
|
||||
if (srcFile == null || srcFile in excludes || srcFile.isJavaFile()) continue
|
||||
|
||||
reporter.report { ("Class $dirtyClassFqName caused recompilation of: ${reporter.pathsAsString(srcFile)}") }
|
||||
dirtyFiles.add(srcFile)
|
||||
@@ -185,7 +192,7 @@ fun mapClassesFqNamesToFiles(
|
||||
|
||||
fun withSubtypes(
|
||||
typeFqName: FqName,
|
||||
caches: Iterable<IncrementalCacheCommon>
|
||||
caches: Iterable<IncrementalCacheCommon<*>>
|
||||
): Set<FqName> {
|
||||
val types = LinkedList(listOf(typeFqName))
|
||||
val subtypes = hashSetOf<FqName>()
|
||||
|
||||
@@ -244,6 +244,13 @@ class DifferenceCalculatorForClass(
|
||||
ProtoBufClassKind.JVM_EXT_CLASS_LOCAL_VARIABLE_LIST -> {
|
||||
// Not affected, local variables are not accessible outside of a file
|
||||
}
|
||||
ProtoBufClassKind.JAVA_EXT_IS_PACKAGE_PRIVATE_CLASS -> {
|
||||
isClassAffected = true
|
||||
areSubclassesAffected = true
|
||||
}
|
||||
ProtoBufClassKind.BUILT_INS_EXT_CLASS_ANNOTATION_LIST -> {
|
||||
isClassAffected = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,6 +296,9 @@ class DifferenceCalculatorForPackageFacade(
|
||||
ProtoBufPackageKind.JVM_EXT_PACKAGE_LOCAL_VARIABLE_LIST -> {
|
||||
// Not affected, local variables are not accessible outside of a file
|
||||
}
|
||||
ProtoBufPackageKind.BUILT_INS_EXT_PACKAGE_FQ_NAME -> {
|
||||
// Not affected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.incremental.storage
|
||||
|
||||
import com.intellij.util.io.BooleanDataDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import java.io.File
|
||||
|
||||
internal class DirtyClassesJvmNameMap(storageFile: File) : AbstractDirtyClassesMap<JvmClassName>(JvmClassNameTransformer, storageFile)
|
||||
internal class DirtyClassesFqNameMap(storageFile: File) : AbstractDirtyClassesMap<FqName>(FqNameTransformer, storageFile)
|
||||
|
||||
internal abstract class AbstractDirtyClassesMap<Name>(
|
||||
private val nameTransformer: NameTransformer<Name>,
|
||||
storageFile: File
|
||||
) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||
fun markDirty(className: Name) {
|
||||
storage[nameTransformer.asString(className)] = true
|
||||
}
|
||||
|
||||
fun notDirty(className: Name) {
|
||||
storage.remove(nameTransformer.asString(className))
|
||||
}
|
||||
|
||||
fun getDirtyOutputClasses(): Collection<Name> =
|
||||
storage.keys.map { nameTransformer.asName(it) }
|
||||
|
||||
fun isDirty(className: Name): Boolean =
|
||||
storage.contains(nameTransformer.asString(className))
|
||||
|
||||
override fun dumpValue(value: Boolean) = ""
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.incremental.storage
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
|
||||
internal interface NameTransformer<Name> {
|
||||
fun asString(name: Name): String
|
||||
fun asName(string: String): Name
|
||||
}
|
||||
|
||||
internal object FqNameTransformer : NameTransformer<FqName> {
|
||||
override fun asString(name: FqName): String =
|
||||
name.asString()
|
||||
|
||||
override fun asName(string: String): FqName =
|
||||
FqName(string)
|
||||
}
|
||||
|
||||
internal object JvmClassNameTransformer : NameTransformer<JvmClassName> {
|
||||
override fun asString(name: JvmClassName): String =
|
||||
name.internalName
|
||||
|
||||
override fun asName(string: String): JvmClassName =
|
||||
JvmClassName.byInternalName(string)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.incremental.storage
|
||||
|
||||
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import java.io.File
|
||||
|
||||
internal class SourceToJvmNameMap(storageFile: File) : AbstractSourceToOutputMap<JvmClassName>(JvmClassNameTransformer, storageFile)
|
||||
internal class SourceToFqNameMap(storageFile: File) : AbstractSourceToOutputMap<FqName>(FqNameTransformer, storageFile)
|
||||
|
||||
internal abstract class AbstractSourceToOutputMap<Name>(
|
||||
private val nameTransformer: NameTransformer<Name>,
|
||||
storageFile: File
|
||||
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
fun clearOutputsForSource(sourceFile: File) {
|
||||
remove(sourceFile.absolutePath)
|
||||
}
|
||||
|
||||
fun add(sourceFile: File, className: Name) {
|
||||
storage.append(sourceFile.absolutePath, nameTransformer.asString(className))
|
||||
}
|
||||
|
||||
fun contains(sourceFile: File): Boolean =
|
||||
sourceFile.absolutePath in storage
|
||||
|
||||
operator fun get(sourceFile: File): Collection<Name> =
|
||||
storage[sourceFile.absolutePath].orEmpty().map(nameTransformer::asName)
|
||||
|
||||
override fun dumpValue(value: Collection<String>) =
|
||||
value.dumpCollection()
|
||||
|
||||
private fun remove(path: String) {
|
||||
storage.remove(path)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: build-common/src/java_descriptors.proto
|
||||
|
||||
package org.jetbrains.kotlin.serialization.java;
|
||||
|
||||
public final class JavaClassProtoBuf {
|
||||
private JavaClassProtoBuf() {}
|
||||
public static void registerAllExtensions(
|
||||
org.jetbrains.kotlin.protobuf.ExtensionRegistryLite registry) {
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf.isStaticMethod);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf.isPackagePrivateMethod);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf.isStaticField);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf.isPackagePrivateField);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf.isPackagePrivateClass);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf.isPackagePrivateConstructor);
|
||||
}
|
||||
public static final int IS_STATIC_METHOD_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Function { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Function,
|
||||
java.lang.Boolean> isStaticMethod = org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
.newSingularGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Function.getDefaultInstance(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
1000,
|
||||
org.jetbrains.kotlin.protobuf.WireFormat.FieldType.BOOL,
|
||||
java.lang.Boolean.class);
|
||||
public static final int IS_PACKAGE_PRIVATE_METHOD_FIELD_NUMBER = 1001;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Function { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Function,
|
||||
java.lang.Boolean> isPackagePrivateMethod = org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
.newSingularGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Function.getDefaultInstance(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
1001,
|
||||
org.jetbrains.kotlin.protobuf.WireFormat.FieldType.BOOL,
|
||||
java.lang.Boolean.class);
|
||||
public static final int IS_STATIC_FIELD_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Property { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Property,
|
||||
java.lang.Boolean> isStaticField = org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
.newSingularGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Property.getDefaultInstance(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
1000,
|
||||
org.jetbrains.kotlin.protobuf.WireFormat.FieldType.BOOL,
|
||||
java.lang.Boolean.class);
|
||||
public static final int IS_PACKAGE_PRIVATE_FIELD_FIELD_NUMBER = 1001;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Property { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Property,
|
||||
java.lang.Boolean> isPackagePrivateField = org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
.newSingularGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Property.getDefaultInstance(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
1001,
|
||||
org.jetbrains.kotlin.protobuf.WireFormat.FieldType.BOOL,
|
||||
java.lang.Boolean.class);
|
||||
public static final int IS_PACKAGE_PRIVATE_CLASS_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Class { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Class,
|
||||
java.lang.Boolean> isPackagePrivateClass = org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
.newSingularGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Class.getDefaultInstance(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
1000,
|
||||
org.jetbrains.kotlin.protobuf.WireFormat.FieldType.BOOL,
|
||||
java.lang.Boolean.class);
|
||||
public static final int IS_PACKAGE_PRIVATE_CONSTRUCTOR_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Constructor { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Constructor,
|
||||
java.lang.Boolean> isPackagePrivateConstructor = org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
.newSingularGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.ProtoBuf.Constructor.getDefaultInstance(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
1000,
|
||||
org.jetbrains.kotlin.protobuf.WireFormat.FieldType.BOOL,
|
||||
java.lang.Boolean.class);
|
||||
|
||||
static {
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(outer_class_scope)
|
||||
}
|
||||
@@ -28,6 +28,9 @@ data class BuildLogFinder(
|
||||
private const val GRADLE_LOG = "gradle-build.log"
|
||||
private const val DATA_CONTAINER_LOG = "data-container-version-build.log"
|
||||
private const val SIMPLE_LOG = "build.log"
|
||||
|
||||
fun isJpsLogFile(file: File): Boolean =
|
||||
file.name.let { it == SIMPLE_LOG || it == DATA_CONTAINER_LOG }
|
||||
}
|
||||
|
||||
fun findBuildLog(dir: File): File? {
|
||||
|
||||
@@ -11047,7 +11047,7 @@ public final class DebugProtoBuf {
|
||||
if (((bitField0_ & 0x00000020) == 0x00000020)) {
|
||||
output.writeMessage(32, versionRequirementTable_);
|
||||
}
|
||||
extensionWriter.writeUntil(200, output);
|
||||
extensionWriter.writeUntil(19000, output);
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@@ -17077,7 +17077,7 @@ public final class DebugProtoBuf {
|
||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||
output.writeInt32(31, versionRequirement_);
|
||||
}
|
||||
extensionWriter.writeUntil(200, output);
|
||||
extensionWriter.writeUntil(19000, output);
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@@ -18497,7 +18497,7 @@ public final class DebugProtoBuf {
|
||||
if (((bitField0_ & 0x00000200) == 0x00000200)) {
|
||||
output.writeMessage(32, contract_);
|
||||
}
|
||||
extensionWriter.writeUntil(200, output);
|
||||
extensionWriter.writeUntil(19000, output);
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@@ -20974,7 +20974,7 @@ public final class DebugProtoBuf {
|
||||
if (((bitField0_ & 0x00000400) == 0x00000400)) {
|
||||
output.writeInt32(31, versionRequirement_);
|
||||
}
|
||||
extensionWriter.writeUntil(200, output);
|
||||
extensionWriter.writeUntil(19000, output);
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@@ -33479,7 +33479,7 @@ public final class DebugProtoBuf {
|
||||
"ter.Variance:\003INV\022=\n\013upper_bound\030\005 \003(\0132(" +
|
||||
".org.jetbrains.kotlin.serialization.Type" +
|
||||
"\022\026\n\016upper_bound_id\030\006 \003(\005\"$\n\010Variance\022\006\n\002" +
|
||||
"IN\020\000\022\007\n\003OUT\020\001\022\007\n\003INV\020\002*\005\010d\020\350\007\"\320\007\n\005Class\022" +
|
||||
"IN\020\000\022\007\n\003OUT\020\001\022\007\n\003INV\020\002*\005\010d\020\350\007\"\321\007\n\005Class\022" +
|
||||
"\020\n\005flags\030\001 \001(\005:\0016\022\025\n\007fq_name\030\003 \002(\005B\004\220\265\030\001",
|
||||
"\022#\n\025companion_object_name\030\004 \001(\005B\004\210\265\030\001\022I\n" +
|
||||
"\016type_parameter\030\005 \003(\01321.org.jetbrains.ko" +
|
||||
@@ -33504,118 +33504,118 @@ public final class DebugProtoBuf {
|
||||
"x\n\004Kind\022\t\n\005CLASS\020\000\022\r\n\tINTERFACE\020\001\022\016\n\nENU" +
|
||||
"M_CLASS\020\002\022\016\n\nENUM_ENTRY\020\003\022\024\n\020ANNOTATION_" +
|
||||
"CLASS\020\004\022\n\n\006OBJECT\020\005\022\024\n\020COMPANION_OBJECT\020" +
|
||||
"\006*\005\010d\020\310\001\"\366\002\n\007Package\022>\n\010function\030\003 \003(\0132," +
|
||||
".org.jetbrains.kotlin.serialization.Func" +
|
||||
"tion\022>\n\010property\030\004 \003(\0132,.org.jetbrains.k" +
|
||||
"otlin.serialization.Property\022A\n\ntype_ali" +
|
||||
"as\030\005 \003(\0132-.org.jetbrains.kotlin.serializ" +
|
||||
"ation.TypeAlias\022A\n\ntype_table\030\036 \001(\0132-.or" +
|
||||
"g.jetbrains.kotlin.serialization.TypeTab",
|
||||
"le\022^\n\031version_requirement_table\030 \001(\0132;." +
|
||||
"org.jetbrains.kotlin.serialization.Versi" +
|
||||
"onRequirementTable*\005\010d\020\310\001\"_\n\tTypeTable\0226" +
|
||||
"\n\004type\030\001 \003(\0132(.org.jetbrains.kotlin.seri" +
|
||||
"alization.Type\022\032\n\016first_nullable\030\002 \001(\005:\002" +
|
||||
"-1\"\220\001\n\013Constructor\022\020\n\005flags\030\001 \001(\005:\0016\022K\n\017" +
|
||||
"value_parameter\030\002 \003(\01322.org.jetbrains.ko" +
|
||||
"tlin.serialization.ValueParameter\022\033\n\023ver" +
|
||||
"sion_requirement\030\037 \001(\005*\005\010d\020\310\001\"\267\004\n\010Functi" +
|
||||
"on\022\020\n\005flags\030\t \001(\005:\0016\022\024\n\told_flags\030\001 \001(\005:",
|
||||
"\0016\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\022=\n\013return_type\030\003 " +
|
||||
"\001(\0132(.org.jetbrains.kotlin.serialization" +
|
||||
".Type\022\026\n\016return_type_id\030\007 \001(\005\022I\n\016type_pa" +
|
||||
"rameter\030\004 \003(\01321.org.jetbrains.kotlin.ser" +
|
||||
"ialization.TypeParameter\022?\n\rreceiver_typ" +
|
||||
"e\030\005 \001(\0132(.org.jetbrains.kotlin.serializa" +
|
||||
"tion.Type\022\030\n\020receiver_type_id\030\010 \001(\005\022K\n\017v" +
|
||||
"alue_parameter\030\006 \003(\01322.org.jetbrains.kot" +
|
||||
"lin.serialization.ValueParameter\022A\n\ntype" +
|
||||
"_table\030\036 \001(\0132-.org.jetbrains.kotlin.seri",
|
||||
"alization.TypeTable\022\033\n\023version_requireme" +
|
||||
"nt\030\037 \001(\005\022>\n\010contract\030 \001(\0132,.org.jetbrai" +
|
||||
"ns.kotlin.serialization.Contract*\005\010d\020\310\001\"" +
|
||||
"\354\003\n\010Property\022\022\n\005flags\030\013 \001(\005:\003518\022\027\n\told_" +
|
||||
"flags\030\001 \001(\005:\0042054\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\022=\n" +
|
||||
"\013return_type\030\003 \001(\0132(.org.jetbrains.kotli" +
|
||||
"n.serialization.Type\022\026\n\016return_type_id\030\t" +
|
||||
" \001(\005\022I\n\016type_parameter\030\004 \003(\01321.org.jetbr" +
|
||||
"ains.kotlin.serialization.TypeParameter\022" +
|
||||
"?\n\rreceiver_type\030\005 \001(\0132(.org.jetbrains.k",
|
||||
"otlin.serialization.Type\022\030\n\020receiver_typ" +
|
||||
"e_id\030\n \001(\005\022R\n\026setter_value_parameter\030\006 \001" +
|
||||
"(\01322.org.jetbrains.kotlin.serialization." +
|
||||
"ValueParameter\022\024\n\014getter_flags\030\007 \001(\005\022\024\n\014" +
|
||||
"setter_flags\030\010 \001(\005\022\033\n\023version_requiremen" +
|
||||
"t\030\037 \001(\005*\005\010d\020\310\001\"\355\001\n\016ValueParameter\022\020\n\005fla" +
|
||||
"gs\030\001 \001(\005:\0010\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\0226\n\004type\030" +
|
||||
"\006*\006\010d\020\270\224\001\"\366\002\n\007Package\022>\n\010function\030\003 \003(\0132" +
|
||||
",.org.jetbrains.kotlin.serialization.Fun" +
|
||||
"ction\022>\n\010property\030\004 \003(\0132,.org.jetbrains." +
|
||||
"kotlin.serialization.Property\022A\n\ntype_al" +
|
||||
"ias\030\005 \003(\0132-.org.jetbrains.kotlin.seriali" +
|
||||
"zation.TypeAlias\022A\n\ntype_table\030\036 \001(\0132-.o" +
|
||||
"rg.jetbrains.kotlin.serialization.TypeTa",
|
||||
"ble\022^\n\031version_requirement_table\030 \001(\0132;" +
|
||||
".org.jetbrains.kotlin.serialization.Vers" +
|
||||
"ionRequirementTable*\005\010d\020\310\001\"_\n\tTypeTable\022" +
|
||||
"6\n\004type\030\001 \003(\0132(.org.jetbrains.kotlin.ser" +
|
||||
"ialization.Type\022\032\n\016first_nullable\030\002 \001(\005:" +
|
||||
"\002-1\"\221\001\n\013Constructor\022\020\n\005flags\030\001 \001(\005:\0016\022K\n" +
|
||||
"\017value_parameter\030\002 \003(\01322.org.jetbrains.k" +
|
||||
"otlin.serialization.ValueParameter\022\033\n\023ve" +
|
||||
"rsion_requirement\030\037 \001(\005*\006\010d\020\270\224\001\"\270\004\n\010Func" +
|
||||
"tion\022\020\n\005flags\030\t \001(\005:\0016\022\024\n\told_flags\030\001 \001(",
|
||||
"\005:\0016\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\022=\n\013return_type\030" +
|
||||
"\003 \001(\0132(.org.jetbrains.kotlin.serializati" +
|
||||
"on.Type\022\017\n\007type_id\030\005 \001(\005\022E\n\023vararg_eleme" +
|
||||
"nt_type\030\004 \001(\0132(.org.jetbrains.kotlin.ser",
|
||||
"ialization.Type\022\036\n\026vararg_element_type_i" +
|
||||
"d\030\006 \001(\005*\005\010d\020\310\001\"\236\003\n\tTypeAlias\022\020\n\005flags\030\001 " +
|
||||
"\001(\005:\0016\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\022I\n\016type_param" +
|
||||
"eter\030\003 \003(\01321.org.jetbrains.kotlin.serial" +
|
||||
"ization.TypeParameter\022A\n\017underlying_type" +
|
||||
"\030\004 \001(\0132(.org.jetbrains.kotlin.serializat" +
|
||||
"ion.Type\022\032\n\022underlying_type_id\030\005 \001(\005\022?\n\r" +
|
||||
"expanded_type\030\006 \001(\0132(.org.jetbrains.kotl" +
|
||||
"in.serialization.Type\022\030\n\020expanded_type_i" +
|
||||
"d\030\007 \001(\005\022B\n\nannotation\030\010 \003(\0132..org.jetbra",
|
||||
"ins.kotlin.serialization.Annotation\022\033\n\023v" +
|
||||
"ersion_requirement\030\037 \001(\005*\005\010d\020\310\001\"&\n\tEnumE" +
|
||||
"ntry\022\022\n\004name\030\001 \001(\005B\004\210\265\030\001*\005\010d\020\310\001\"\237\003\n\022Vers" +
|
||||
"ionRequirement\022\017\n\007version\030\001 \001(\005\022\024\n\014versi" +
|
||||
"on_full\030\002 \001(\005\022R\n\005level\030\003 \001(\0162<.org.jetbr" +
|
||||
"ains.kotlin.serialization.VersionRequire" +
|
||||
"ment.Level:\005ERROR\022\022\n\nerror_code\030\004 \001(\005\022\025\n" +
|
||||
"\007message\030\005 \001(\005B\004\230\265\030\001\022j\n\014version_kind\030\006 \001" +
|
||||
"(\0162B.org.jetbrains.kotlin.serialization." +
|
||||
"VersionRequirement.VersionKind:\020LANGUAGE",
|
||||
"_VERSION\"+\n\005Level\022\013\n\007WARNING\020\000\022\t\n\005ERROR\020" +
|
||||
"\001\022\n\n\006HIDDEN\020\002\"J\n\013VersionKind\022\024\n\020LANGUAGE" +
|
||||
"_VERSION\020\000\022\024\n\020COMPILER_VERSION\020\001\022\017\n\013API_" +
|
||||
"VERSION\020\002\"f\n\027VersionRequirementTable\022K\n\013" +
|
||||
"requirement\030\001 \003(\01326.org.jetbrains.kotlin" +
|
||||
".serialization.VersionRequirement\"\243\002\n\017Pa" +
|
||||
"ckageFragment\022@\n\007strings\030\001 \001(\0132/.org.jet" +
|
||||
"brains.kotlin.serialization.StringTable\022" +
|
||||
"O\n\017qualified_names\030\002 \001(\01326.org.jetbrains" +
|
||||
".kotlin.serialization.QualifiedNameTable",
|
||||
"\022<\n\007package\030\003 \001(\0132+.org.jetbrains.kotlin" +
|
||||
".serialization.Package\0228\n\005class\030\004 \003(\0132)." +
|
||||
"org.jetbrains.kotlin.serialization.Class" +
|
||||
"*\005\010d\020\310\001\"F\n\010Contract\022:\n\006effect\030\001 \003(\0132*.or" +
|
||||
"g.jetbrains.kotlin.serialization.Effect\"" +
|
||||
"\332\003\n\006Effect\022J\n\013effect_type\030\001 \001(\01625.org.je" +
|
||||
"tbrains.kotlin.serialization.Effect.Effe" +
|
||||
"ctType\022S\n\033effect_constructor_argument\030\002 " +
|
||||
"\003(\0132..org.jetbrains.kotlin.serialization" +
|
||||
".Expression\022X\n conclusion_of_conditional",
|
||||
"_effect\030\003 \001(\0132..org.jetbrains.kotlin.ser" +
|
||||
"ialization.Expression\022G\n\004kind\030\004 \001(\01629.or" +
|
||||
"on.Type\022\026\n\016return_type_id\030\007 \001(\005\022I\n\016type_" +
|
||||
"parameter\030\004 \003(\01321.org.jetbrains.kotlin.s" +
|
||||
"erialization.TypeParameter\022?\n\rreceiver_t" +
|
||||
"ype\030\005 \001(\0132(.org.jetbrains.kotlin.seriali" +
|
||||
"zation.Type\022\030\n\020receiver_type_id\030\010 \001(\005\022K\n" +
|
||||
"\017value_parameter\030\006 \003(\01322.org.jetbrains.k" +
|
||||
"otlin.serialization.ValueParameter\022A\n\nty" +
|
||||
"pe_table\030\036 \001(\0132-.org.jetbrains.kotlin.se",
|
||||
"rialization.TypeTable\022\033\n\023version_require" +
|
||||
"ment\030\037 \001(\005\022>\n\010contract\030 \001(\0132,.org.jetbr" +
|
||||
"ains.kotlin.serialization.Contract*\006\010d\020\270" +
|
||||
"\224\001\"\355\003\n\010Property\022\022\n\005flags\030\013 \001(\005:\003518\022\027\n\to" +
|
||||
"ld_flags\030\001 \001(\005:\0042054\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001" +
|
||||
"\022=\n\013return_type\030\003 \001(\0132(.org.jetbrains.ko" +
|
||||
"tlin.serialization.Type\022\026\n\016return_type_i" +
|
||||
"d\030\t \001(\005\022I\n\016type_parameter\030\004 \003(\01321.org.je" +
|
||||
"tbrains.kotlin.serialization.TypeParamet" +
|
||||
"er\022?\n\rreceiver_type\030\005 \001(\0132(.org.jetbrain",
|
||||
"s.kotlin.serialization.Type\022\030\n\020receiver_" +
|
||||
"type_id\030\n \001(\005\022R\n\026setter_value_parameter\030" +
|
||||
"\006 \001(\01322.org.jetbrains.kotlin.serializati" +
|
||||
"on.ValueParameter\022\024\n\014getter_flags\030\007 \001(\005\022" +
|
||||
"\024\n\014setter_flags\030\010 \001(\005\022\033\n\023version_require" +
|
||||
"ment\030\037 \001(\005*\006\010d\020\270\224\001\"\355\001\n\016ValueParameter\022\020\n" +
|
||||
"\005flags\030\001 \001(\005:\0010\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\0226\n\004t" +
|
||||
"ype\030\003 \001(\0132(.org.jetbrains.kotlin.seriali" +
|
||||
"zation.Type\022\017\n\007type_id\030\005 \001(\005\022E\n\023vararg_e" +
|
||||
"lement_type\030\004 \001(\0132(.org.jetbrains.kotlin",
|
||||
".serialization.Type\022\036\n\026vararg_element_ty" +
|
||||
"pe_id\030\006 \001(\005*\005\010d\020\310\001\"\236\003\n\tTypeAlias\022\020\n\005flag" +
|
||||
"s\030\001 \001(\005:\0016\022\022\n\004name\030\002 \002(\005B\004\210\265\030\001\022I\n\016type_p" +
|
||||
"arameter\030\003 \003(\01321.org.jetbrains.kotlin.se" +
|
||||
"rialization.TypeParameter\022A\n\017underlying_" +
|
||||
"type\030\004 \001(\0132(.org.jetbrains.kotlin.serial" +
|
||||
"ization.Type\022\032\n\022underlying_type_id\030\005 \001(\005" +
|
||||
"\022?\n\rexpanded_type\030\006 \001(\0132(.org.jetbrains." +
|
||||
"kotlin.serialization.Type\022\030\n\020expanded_ty" +
|
||||
"pe_id\030\007 \001(\005\022B\n\nannotation\030\010 \003(\0132..org.je",
|
||||
"tbrains.kotlin.serialization.Annotation\022" +
|
||||
"\033\n\023version_requirement\030\037 \001(\005*\005\010d\020\310\001\"&\n\tE" +
|
||||
"numEntry\022\022\n\004name\030\001 \001(\005B\004\210\265\030\001*\005\010d\020\310\001\"\237\003\n\022" +
|
||||
"VersionRequirement\022\017\n\007version\030\001 \001(\005\022\024\n\014v" +
|
||||
"ersion_full\030\002 \001(\005\022R\n\005level\030\003 \001(\0162<.org.j" +
|
||||
"etbrains.kotlin.serialization.VersionReq" +
|
||||
"uirement.Level:\005ERROR\022\022\n\nerror_code\030\004 \001(" +
|
||||
"\005\022\025\n\007message\030\005 \001(\005B\004\230\265\030\001\022j\n\014version_kind" +
|
||||
"\030\006 \001(\0162B.org.jetbrains.kotlin.serializat" +
|
||||
"ion.VersionRequirement.VersionKind:\020LANG",
|
||||
"UAGE_VERSION\"+\n\005Level\022\013\n\007WARNING\020\000\022\t\n\005ER" +
|
||||
"ROR\020\001\022\n\n\006HIDDEN\020\002\"J\n\013VersionKind\022\024\n\020LANG" +
|
||||
"UAGE_VERSION\020\000\022\024\n\020COMPILER_VERSION\020\001\022\017\n\013" +
|
||||
"API_VERSION\020\002\"f\n\027VersionRequirementTable" +
|
||||
"\022K\n\013requirement\030\001 \003(\01326.org.jetbrains.ko" +
|
||||
"tlin.serialization.VersionRequirement\"\243\002" +
|
||||
"\n\017PackageFragment\022@\n\007strings\030\001 \001(\0132/.org" +
|
||||
".jetbrains.kotlin.serialization.StringTa" +
|
||||
"ble\022O\n\017qualified_names\030\002 \001(\01326.org.jetbr" +
|
||||
"ains.kotlin.serialization.QualifiedNameT",
|
||||
"able\022<\n\007package\030\003 \001(\0132+.org.jetbrains.ko" +
|
||||
"tlin.serialization.Package\0228\n\005class\030\004 \003(" +
|
||||
"\0132).org.jetbrains.kotlin.serialization.C" +
|
||||
"lass*\005\010d\020\310\001\"F\n\010Contract\022:\n\006effect\030\001 \003(\0132" +
|
||||
"*.org.jetbrains.kotlin.serialization.Eff" +
|
||||
"ect\"\332\003\n\006Effect\022J\n\013effect_type\030\001 \001(\01625.or" +
|
||||
"g.jetbrains.kotlin.serialization.Effect." +
|
||||
"InvocationKind\"C\n\nEffectType\022\024\n\020RETURNS_" +
|
||||
"CONSTANT\020\000\022\t\n\005CALLS\020\001\022\024\n\020RETURNS_NOT_NUL" +
|
||||
"L\020\002\"G\n\016InvocationKind\022\020\n\014AT_MOST_ONCE\020\000\022" +
|
||||
"\020\n\014EXACTLY_ONCE\020\001\022\021\n\rAT_LEAST_ONCE\020\002\"\260\003\n" +
|
||||
"\nExpression\022\r\n\005flags\030\001 \001(\005\022!\n\031value_para" +
|
||||
"meter_reference\030\002 \001(\005\022T\n\016constant_value\030" +
|
||||
"\003 \001(\0162<.org.jetbrains.kotlin.serializati",
|
||||
"on.Expression.ConstantValue\022B\n\020is_instan" +
|
||||
"ce_type\030\004 \001(\0132(.org.jetbrains.kotlin.ser" +
|
||||
"ialization.Type\022\033\n\023is_instance_type_id\030\005" +
|
||||
" \001(\005\022D\n\014and_argument\030\006 \003(\0132..org.jetbrai" +
|
||||
"ns.kotlin.serialization.Expression\022C\n\013or" +
|
||||
"_argument\030\007 \003(\0132..org.jetbrains.kotlin.s" +
|
||||
"erialization.Expression\".\n\rConstantValue" +
|
||||
"\022\010\n\004TRUE\020\000\022\t\n\005FALSE\020\001\022\010\n\004NULL\020\002*9\n\010Modal" +
|
||||
"ity\022\t\n\005FINAL\020\000\022\010\n\004OPEN\020\001\022\014\n\010ABSTRACT\020\002\022\n" +
|
||||
"\n\006SEALED\020\003*b\n\nVisibility\022\014\n\010INTERNAL\020\000\022\013",
|
||||
"\n\007PRIVATE\020\001\022\r\n\tPROTECTED\020\002\022\n\n\006PUBLIC\020\003\022\023" +
|
||||
"\n\017PRIVATE_TO_THIS\020\004\022\t\n\005LOCAL\020\005*Q\n\nMember" +
|
||||
"Kind\022\017\n\013DECLARATION\020\000\022\021\n\rFAKE_OVERRIDE\020\001" +
|
||||
"\022\016\n\nDELEGATION\020\002\022\017\n\013SYNTHESIZED\020\003B\017B\rDeb" +
|
||||
"ugProtoBuf"
|
||||
"EffectType\022S\n\033effect_constructor_argumen" +
|
||||
"t\030\002 \003(\0132..org.jetbrains.kotlin.serializa" +
|
||||
"tion.Expression\022X\n conclusion_of_conditi",
|
||||
"onal_effect\030\003 \001(\0132..org.jetbrains.kotlin" +
|
||||
".serialization.Expression\022G\n\004kind\030\004 \001(\0162" +
|
||||
"9.org.jetbrains.kotlin.serialization.Eff" +
|
||||
"ect.InvocationKind\"C\n\nEffectType\022\024\n\020RETU" +
|
||||
"RNS_CONSTANT\020\000\022\t\n\005CALLS\020\001\022\024\n\020RETURNS_NOT" +
|
||||
"_NULL\020\002\"G\n\016InvocationKind\022\020\n\014AT_MOST_ONC" +
|
||||
"E\020\000\022\020\n\014EXACTLY_ONCE\020\001\022\021\n\rAT_LEAST_ONCE\020\002" +
|
||||
"\"\260\003\n\nExpression\022\r\n\005flags\030\001 \001(\005\022!\n\031value_" +
|
||||
"parameter_reference\030\002 \001(\005\022T\n\016constant_va" +
|
||||
"lue\030\003 \001(\0162<.org.jetbrains.kotlin.seriali",
|
||||
"zation.Expression.ConstantValue\022B\n\020is_in" +
|
||||
"stance_type\030\004 \001(\0132(.org.jetbrains.kotlin" +
|
||||
".serialization.Type\022\033\n\023is_instance_type_" +
|
||||
"id\030\005 \001(\005\022D\n\014and_argument\030\006 \003(\0132..org.jet" +
|
||||
"brains.kotlin.serialization.Expression\022C" +
|
||||
"\n\013or_argument\030\007 \003(\0132..org.jetbrains.kotl" +
|
||||
"in.serialization.Expression\".\n\rConstantV" +
|
||||
"alue\022\010\n\004TRUE\020\000\022\t\n\005FALSE\020\001\022\010\n\004NULL\020\002*9\n\010M" +
|
||||
"odality\022\t\n\005FINAL\020\000\022\010\n\004OPEN\020\001\022\014\n\010ABSTRACT" +
|
||||
"\020\002\022\n\n\006SEALED\020\003*b\n\nVisibility\022\014\n\010INTERNAL",
|
||||
"\020\000\022\013\n\007PRIVATE\020\001\022\r\n\tPROTECTED\020\002\022\n\n\006PUBLIC" +
|
||||
"\020\003\022\023\n\017PRIVATE_TO_THIS\020\004\022\t\n\005LOCAL\020\005*Q\n\nMe" +
|
||||
"mberKind\022\017\n\013DECLARATION\020\000\022\021\n\rFAKE_OVERRI" +
|
||||
"DE\020\001\022\016\n\nDELEGATION\020\002\022\017\n\013SYNTHESIZED\020\003B\017B" +
|
||||
"\rDebugProtoBuf"
|
||||
};
|
||||
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: build-common/src/java_descriptors.debug.proto
|
||||
|
||||
package org.jetbrains.kotlin.serialization.java;
|
||||
|
||||
public final class DebugJavaClassProtoBuf {
|
||||
private DebugJavaClassProtoBuf() {}
|
||||
public static void registerAllExtensions(
|
||||
org.jetbrains.kotlin.protobuf.ExtensionRegistry registry) {
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.DebugJavaClassProtoBuf.isStaticMethod);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.DebugJavaClassProtoBuf.isPackagePrivateMethod);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.DebugJavaClassProtoBuf.isStaticField);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.DebugJavaClassProtoBuf.isPackagePrivateField);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.DebugJavaClassProtoBuf.isPackagePrivateClass);
|
||||
registry.add(org.jetbrains.kotlin.serialization.java.DebugJavaClassProtoBuf.isPackagePrivateConstructor);
|
||||
}
|
||||
public static final int IS_STATIC_METHOD_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Function { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Function,
|
||||
java.lang.Boolean> isStaticMethod = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Boolean.class,
|
||||
null);
|
||||
public static final int IS_PACKAGE_PRIVATE_METHOD_FIELD_NUMBER = 1001;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Function { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Function,
|
||||
java.lang.Boolean> isPackagePrivateMethod = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Boolean.class,
|
||||
null);
|
||||
public static final int IS_STATIC_FIELD_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Property { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Property,
|
||||
java.lang.Boolean> isStaticField = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Boolean.class,
|
||||
null);
|
||||
public static final int IS_PACKAGE_PRIVATE_FIELD_FIELD_NUMBER = 1001;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Property { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Property,
|
||||
java.lang.Boolean> isPackagePrivateField = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Boolean.class,
|
||||
null);
|
||||
public static final int IS_PACKAGE_PRIVATE_CLASS_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Class { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Class,
|
||||
java.lang.Boolean> isPackagePrivateClass = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Boolean.class,
|
||||
null);
|
||||
public static final int IS_PACKAGE_PRIVATE_CONSTRUCTOR_FIELD_NUMBER = 1000;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Constructor { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Constructor,
|
||||
java.lang.Boolean> isPackagePrivateConstructor = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Boolean.class,
|
||||
null);
|
||||
|
||||
public static org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor
|
||||
getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
private static org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor
|
||||
descriptor;
|
||||
static {
|
||||
java.lang.String[] descriptorData = {
|
||||
"\n-build-common/src/java_descriptors.debu" +
|
||||
"g.proto\022\'org.jetbrains.kotlin.serializat" +
|
||||
"ion.java\0320core/deserialization/src/descr" +
|
||||
"iptors.debug.proto:G\n\020is_static_method\022," +
|
||||
".org.jetbrains.kotlin.serialization.Func" +
|
||||
"tion\030\350\007 \001(\010:P\n\031is_package_private_method" +
|
||||
"\022,.org.jetbrains.kotlin.serialization.Fu" +
|
||||
"nction\030\351\007 \001(\010:F\n\017is_static_field\022,.org.j" +
|
||||
"etbrains.kotlin.serialization.Property\030\350" +
|
||||
"\007 \001(\010:O\n\030is_package_private_field\022,.org.",
|
||||
"jetbrains.kotlin.serialization.Property\030" +
|
||||
"\351\007 \001(\010:L\n\030is_package_private_class\022).org" +
|
||||
".jetbrains.kotlin.serialization.Class\030\350\007" +
|
||||
" \001(\010:X\n\036is_package_private_constructor\022/" +
|
||||
".org.jetbrains.kotlin.serialization.Cons" +
|
||||
"tructor\030\350\007 \001(\010B\030B\026DebugJavaClassProtoBuf"
|
||||
};
|
||||
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||
public org.jetbrains.kotlin.protobuf.ExtensionRegistry assignDescriptors(
|
||||
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor root) {
|
||||
descriptor = root;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor
|
||||
.internalBuildGeneratedFileFrom(descriptorData,
|
||||
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor[] {
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.getDescriptor(),
|
||||
}, assigner);
|
||||
isStaticMethod.internalInit(descriptor.getExtensions().get(0));
|
||||
isPackagePrivateMethod.internalInit(descriptor.getExtensions().get(1));
|
||||
isStaticField.internalInit(descriptor.getExtensions().get(2));
|
||||
isPackagePrivateField.internalInit(descriptor.getExtensions().get(3));
|
||||
isPackagePrivateClass.internalInit(descriptor.getExtensions().get(4));
|
||||
isPackagePrivateConstructor.internalInit(descriptor.getExtensions().get(5));
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.getDescriptor();
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(outer_class_scope)
|
||||
}
|
||||
@@ -32582,6 +32582,28 @@ public final class DebugJsAstProtoBuf {
|
||||
*/
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.StatementOrBuilder getStatementOrBuilder(
|
||||
int index);
|
||||
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
boolean hasFileId();
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
int getFileId();
|
||||
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
boolean hasLocation();
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location getLocation();
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.LocationOrBuilder getLocationOrBuilder();
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code org.jetbrains.kotlin.serialization.js.ast.SwitchEntry}
|
||||
@@ -32656,6 +32678,24 @@ public final class DebugJsAstProtoBuf {
|
||||
statement_.add(input.readMessage(org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Statement.PARSER, extensionRegistry));
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
bitField0_ |= 0x00000002;
|
||||
fileId_ = input.readInt32();
|
||||
break;
|
||||
}
|
||||
case 34: {
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.Builder subBuilder = null;
|
||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||
subBuilder = location_.toBuilder();
|
||||
}
|
||||
location_ = input.readMessage(org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.PARSER, extensionRegistry);
|
||||
if (subBuilder != null) {
|
||||
subBuilder.mergeFrom(location_);
|
||||
location_ = subBuilder.buildPartial();
|
||||
}
|
||||
bitField0_ |= 0x00000004;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException e) {
|
||||
@@ -32755,9 +32795,47 @@ public final class DebugJsAstProtoBuf {
|
||||
return statement_.get(index);
|
||||
}
|
||||
|
||||
public static final int FILEID_FIELD_NUMBER = 3;
|
||||
private int fileId_;
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
public boolean hasFileId() {
|
||||
return ((bitField0_ & 0x00000002) == 0x00000002);
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
public int getFileId() {
|
||||
return fileId_;
|
||||
}
|
||||
|
||||
public static final int LOCATION_FIELD_NUMBER = 4;
|
||||
private org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location location_;
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public boolean hasLocation() {
|
||||
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location getLocation() {
|
||||
return location_;
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.LocationOrBuilder getLocationOrBuilder() {
|
||||
return location_;
|
||||
}
|
||||
|
||||
private void initFields() {
|
||||
label_ = org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Expression.getDefaultInstance();
|
||||
statement_ = java.util.Collections.emptyList();
|
||||
fileId_ = 0;
|
||||
location_ = org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.getDefaultInstance();
|
||||
}
|
||||
private byte memoizedIsInitialized = -1;
|
||||
public final boolean isInitialized() {
|
||||
@@ -32777,6 +32855,12 @@ public final class DebugJsAstProtoBuf {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (hasLocation()) {
|
||||
if (!getLocation().isInitialized()) {
|
||||
memoizedIsInitialized = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memoizedIsInitialized = 1;
|
||||
return true;
|
||||
}
|
||||
@@ -32790,6 +32874,12 @@ public final class DebugJsAstProtoBuf {
|
||||
for (int i = 0; i < statement_.size(); i++) {
|
||||
output.writeMessage(2, statement_.get(i));
|
||||
}
|
||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||
output.writeInt32(3, fileId_);
|
||||
}
|
||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||
output.writeMessage(4, location_);
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@@ -32807,6 +32897,14 @@ public final class DebugJsAstProtoBuf {
|
||||
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
|
||||
.computeMessageSize(2, statement_.get(i));
|
||||
}
|
||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
|
||||
.computeInt32Size(3, fileId_);
|
||||
}
|
||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
|
||||
.computeMessageSize(4, location_);
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSerializedSize = size;
|
||||
return size;
|
||||
@@ -32918,6 +33016,7 @@ public final class DebugJsAstProtoBuf {
|
||||
if (org.jetbrains.kotlin.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
|
||||
getLabelFieldBuilder();
|
||||
getStatementFieldBuilder();
|
||||
getLocationFieldBuilder();
|
||||
}
|
||||
}
|
||||
private static Builder create() {
|
||||
@@ -32938,6 +33037,14 @@ public final class DebugJsAstProtoBuf {
|
||||
} else {
|
||||
statementBuilder_.clear();
|
||||
}
|
||||
fileId_ = 0;
|
||||
bitField0_ = (bitField0_ & ~0x00000004);
|
||||
if (locationBuilder_ == null) {
|
||||
location_ = org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.getDefaultInstance();
|
||||
} else {
|
||||
locationBuilder_.clear();
|
||||
}
|
||||
bitField0_ = (bitField0_ & ~0x00000008);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -32983,6 +33090,18 @@ public final class DebugJsAstProtoBuf {
|
||||
} else {
|
||||
result.statement_ = statementBuilder_.build();
|
||||
}
|
||||
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
|
||||
to_bitField0_ |= 0x00000002;
|
||||
}
|
||||
result.fileId_ = fileId_;
|
||||
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
|
||||
to_bitField0_ |= 0x00000004;
|
||||
}
|
||||
if (locationBuilder_ == null) {
|
||||
result.location_ = location_;
|
||||
} else {
|
||||
result.location_ = locationBuilder_.build();
|
||||
}
|
||||
result.bitField0_ = to_bitField0_;
|
||||
onBuilt();
|
||||
return result;
|
||||
@@ -33028,6 +33147,12 @@ public final class DebugJsAstProtoBuf {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (other.hasFileId()) {
|
||||
setFileId(other.getFileId());
|
||||
}
|
||||
if (other.hasLocation()) {
|
||||
mergeLocation(other.getLocation());
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
return this;
|
||||
}
|
||||
@@ -33045,6 +33170,12 @@ public final class DebugJsAstProtoBuf {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (hasLocation()) {
|
||||
if (!getLocation().isInitialized()) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33423,6 +33554,154 @@ public final class DebugJsAstProtoBuf {
|
||||
return statementBuilder_;
|
||||
}
|
||||
|
||||
private int fileId_ ;
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
public boolean hasFileId() {
|
||||
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
public int getFileId() {
|
||||
return fileId_;
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
public Builder setFileId(int value) {
|
||||
bitField0_ |= 0x00000004;
|
||||
fileId_ = value;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 fileId = 3;</code>
|
||||
*/
|
||||
public Builder clearFileId() {
|
||||
bitField0_ = (bitField0_ & ~0x00000004);
|
||||
fileId_ = 0;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
private org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location location_ = org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.getDefaultInstance();
|
||||
private org.jetbrains.kotlin.protobuf.SingleFieldBuilder<
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location, org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.Builder, org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.LocationOrBuilder> locationBuilder_;
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public boolean hasLocation() {
|
||||
return ((bitField0_ & 0x00000008) == 0x00000008);
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location getLocation() {
|
||||
if (locationBuilder_ == null) {
|
||||
return location_;
|
||||
} else {
|
||||
return locationBuilder_.getMessage();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public Builder setLocation(org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location value) {
|
||||
if (locationBuilder_ == null) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
location_ = value;
|
||||
onChanged();
|
||||
} else {
|
||||
locationBuilder_.setMessage(value);
|
||||
}
|
||||
bitField0_ |= 0x00000008;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public Builder setLocation(
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.Builder builderForValue) {
|
||||
if (locationBuilder_ == null) {
|
||||
location_ = builderForValue.build();
|
||||
onChanged();
|
||||
} else {
|
||||
locationBuilder_.setMessage(builderForValue.build());
|
||||
}
|
||||
bitField0_ |= 0x00000008;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public Builder mergeLocation(org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location value) {
|
||||
if (locationBuilder_ == null) {
|
||||
if (((bitField0_ & 0x00000008) == 0x00000008) &&
|
||||
location_ != org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.getDefaultInstance()) {
|
||||
location_ =
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.newBuilder(location_).mergeFrom(value).buildPartial();
|
||||
} else {
|
||||
location_ = value;
|
||||
}
|
||||
onChanged();
|
||||
} else {
|
||||
locationBuilder_.mergeFrom(value);
|
||||
}
|
||||
bitField0_ |= 0x00000008;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public Builder clearLocation() {
|
||||
if (locationBuilder_ == null) {
|
||||
location_ = org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.getDefaultInstance();
|
||||
onChanged();
|
||||
} else {
|
||||
locationBuilder_.clear();
|
||||
}
|
||||
bitField0_ = (bitField0_ & ~0x00000008);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.Builder getLocationBuilder() {
|
||||
bitField0_ |= 0x00000008;
|
||||
onChanged();
|
||||
return getLocationFieldBuilder().getBuilder();
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
public org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.LocationOrBuilder getLocationOrBuilder() {
|
||||
if (locationBuilder_ != null) {
|
||||
return locationBuilder_.getMessageOrBuilder();
|
||||
} else {
|
||||
return location_;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.Location location = 4;</code>
|
||||
*/
|
||||
private org.jetbrains.kotlin.protobuf.SingleFieldBuilder<
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location, org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.Builder, org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.LocationOrBuilder>
|
||||
getLocationFieldBuilder() {
|
||||
if (locationBuilder_ == null) {
|
||||
locationBuilder_ = new org.jetbrains.kotlin.protobuf.SingleFieldBuilder<
|
||||
org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location, org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.Location.Builder, org.jetbrains.kotlin.serialization.js.ast.DebugJsAstProtoBuf.LocationOrBuilder>(
|
||||
getLocation(),
|
||||
getParentForChildren(),
|
||||
isClean());
|
||||
location_ = null;
|
||||
}
|
||||
return locationBuilder_;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:org.jetbrains.kotlin.serialization.js.ast.SwitchEntry)
|
||||
}
|
||||
|
||||
@@ -49474,101 +49753,103 @@ public final class DebugJsAstProtoBuf {
|
||||
"tch\022I\n\nexpression\030\001 \002(\01325.org.jetbrains." +
|
||||
"kotlin.serialization.js.ast.Expression\022E" +
|
||||
"\n\005entry\030\002 \003(\01326.org.jetbrains.kotlin.ser" +
|
||||
"ialization.js.ast.SwitchEntry\"\234\001\n\013Switch" +
|
||||
"ialization.js.ast.SwitchEntry\"\363\001\n\013Switch" +
|
||||
"Entry\022D\n\005label\030\001 \001(\01325.org.jetbrains.kot" +
|
||||
"lin.serialization.js.ast.Expression\022G\n\ts",
|
||||
"tatement\030\002 \003(\01324.org.jetbrains.kotlin.se" +
|
||||
"rialization.js.ast.Statement\"\225\001\n\005While\022H" +
|
||||
"\n\tcondition\030\001 \002(\01325.org.jetbrains.kotlin" +
|
||||
".serialization.js.ast.Expression\022B\n\004body" +
|
||||
"\030\002 \002(\01324.org.jetbrains.kotlin.serializat" +
|
||||
"ion.js.ast.Statement\"\227\001\n\007DoWhile\022H\n\tcond" +
|
||||
"ition\030\001 \002(\01325.org.jetbrains.kotlin.seria" +
|
||||
"lization.js.ast.Expression\022B\n\004body\030\002 \002(\013" +
|
||||
"24.org.jetbrains.kotlin.serialization.js" +
|
||||
".ast.Statement\"\304\003\n\003For\022I\n\tvariables\030\001 \001(",
|
||||
"\01324.org.jetbrains.kotlin.serialization.j" +
|
||||
"s.ast.StatementH\000\022K\n\nexpression\030\002 \001(\01325." +
|
||||
"org.jetbrains.kotlin.serialization.js.as" +
|
||||
"t.ExpressionH\000\022E\n\005empty\030\003 \001(\01324.org.jetb" +
|
||||
"rains.kotlin.serialization.js.ast.EmptyI" +
|
||||
"nitH\000\022H\n\tcondition\030\004 \001(\01325.org.jetbrains" +
|
||||
"rialization.js.ast.Statement\022\016\n\006fileId\030\003" +
|
||||
" \001(\005\022E\n\010location\030\004 \001(\01323.org.jetbrains.k" +
|
||||
"otlin.serialization.js.ast.Location\"\225\001\n\005" +
|
||||
"While\022H\n\tcondition\030\001 \002(\01325.org.jetbrains" +
|
||||
".kotlin.serialization.js.ast.Expression\022" +
|
||||
"H\n\tincrement\030\005 \001(\01325.org.jetbrains.kotli" +
|
||||
"n.serialization.js.ast.Expression\022B\n\004bod" +
|
||||
"y\030\006 \002(\01324.org.jetbrains.kotlin.serializa",
|
||||
"tion.js.ast.StatementB\006\n\004init\"\013\n\tEmptyIn" +
|
||||
"it\"\374\001\n\005ForIn\022\020\n\006nameId\030\001 \001(\005H\000\022K\n\nexpres" +
|
||||
"sion\030\002 \001(\01325.org.jetbrains.kotlin.serial" +
|
||||
"ization.js.ast.ExpressionH\000\022G\n\010iterable\030" +
|
||||
"\003 \002(\01325.org.jetbrains.kotlin.serializati" +
|
||||
"on.js.ast.Expression\022B\n\004body\030\004 \002(\01324.org" +
|
||||
".jetbrains.kotlin.serialization.js.ast.S" +
|
||||
"tatementB\007\n\005value\"\337\001\n\003Try\022F\n\010tryBlock\030\001 " +
|
||||
"\002(\01324.org.jetbrains.kotlin.serialization" +
|
||||
".js.ast.Statement\022D\n\ncatchBlock\030\002 \001(\01320.",
|
||||
"org.jetbrains.kotlin.serialization.js.as" +
|
||||
"t.Catch\022J\n\014finallyBlock\030\003 \001(\01324.org.jetb" +
|
||||
"rains.kotlin.serialization.js.ast.Statem" +
|
||||
"ent\"\224\001\n\005Catch\022G\n\tparameter\030\001 \002(\01324.org.j" +
|
||||
"etbrains.kotlin.serialization.js.ast.Par" +
|
||||
"ameter\022B\n\004body\030\002 \002(\01324.org.jetbrains.kot" +
|
||||
"lin.serialization.js.ast.Statement\"\007\n\005Em" +
|
||||
"pty\"\327\005\n\010Fragment\022R\n\017imported_module\030\001 \003(" +
|
||||
"\01329.org.jetbrains.kotlin.serialization.j" +
|
||||
"s.ast.ImportedModule\022G\n\014import_entry\030\002 \003",
|
||||
"(\01321.org.jetbrains.kotlin.serialization." +
|
||||
"js.ast.Import\022Q\n\021declaration_block\030\003 \001(\013" +
|
||||
"26.org.jetbrains.kotlin.serialization.js" +
|
||||
".ast.GlobalBlock\022L\n\014export_block\030\004 \001(\01326" +
|
||||
".org.jetbrains.kotlin.serialization.js.a" +
|
||||
"st.GlobalBlock\022Q\n\021initializer_block\030\005 \001(" +
|
||||
"\01326.org.jetbrains.kotlin.serialization.j" +
|
||||
"s.ast.GlobalBlock\022L\n\014name_binding\030\006 \003(\0132" +
|
||||
"6.org.jetbrains.kotlin.serialization.js." +
|
||||
"ast.NameBinding\022J\n\013class_model\030\007 \003(\01325.o",
|
||||
"B\n\004body\030\002 \002(\01324.org.jetbrains.kotlin.ser" +
|
||||
"ialization.js.ast.Statement\"\227\001\n\007DoWhile\022" +
|
||||
"H\n\tcondition\030\001 \002(\01325.org.jetbrains.kotli" +
|
||||
"n.serialization.js.ast.Expression\022B\n\004bod",
|
||||
"y\030\002 \002(\01324.org.jetbrains.kotlin.serializa" +
|
||||
"tion.js.ast.Statement\"\304\003\n\003For\022I\n\tvariabl" +
|
||||
"es\030\001 \001(\01324.org.jetbrains.kotlin.serializ" +
|
||||
"ation.js.ast.StatementH\000\022K\n\nexpression\030\002" +
|
||||
" \001(\01325.org.jetbrains.kotlin.serializatio" +
|
||||
"n.js.ast.ExpressionH\000\022E\n\005empty\030\003 \001(\01324.o" +
|
||||
"rg.jetbrains.kotlin.serialization.js.ast" +
|
||||
".ClassModel\022P\n\021module_expression\030\010 \003(\01325" +
|
||||
".org.jetbrains.kotlin.serialization.js.a" +
|
||||
"st.Expression\022N\n\rinline_module\030\t \003(\01327.o" +
|
||||
".EmptyInitH\000\022H\n\tcondition\030\004 \001(\01325.org.je" +
|
||||
"tbrains.kotlin.serialization.js.ast.Expr" +
|
||||
"ession\022H\n\tincrement\030\005 \001(\01325.org.jetbrain",
|
||||
"s.kotlin.serialization.js.ast.Expression" +
|
||||
"\022B\n\004body\030\006 \002(\01324.org.jetbrains.kotlin.se" +
|
||||
"rialization.js.ast.StatementB\006\n\004init\"\013\n\t" +
|
||||
"EmptyInit\"\374\001\n\005ForIn\022\020\n\006nameId\030\001 \001(\005H\000\022K\n" +
|
||||
"\nexpression\030\002 \001(\01325.org.jetbrains.kotlin" +
|
||||
".serialization.js.ast.ExpressionH\000\022G\n\010it" +
|
||||
"erable\030\003 \002(\01325.org.jetbrains.kotlin.seri" +
|
||||
"alization.js.ast.Expression\022B\n\004body\030\004 \002(" +
|
||||
"\01324.org.jetbrains.kotlin.serialization.j" +
|
||||
"s.ast.StatementB\007\n\005value\"\337\001\n\003Try\022F\n\010tryB",
|
||||
"lock\030\001 \002(\01324.org.jetbrains.kotlin.serial" +
|
||||
"ization.js.ast.Statement\022D\n\ncatchBlock\030\002" +
|
||||
" \001(\01320.org.jetbrains.kotlin.serializatio" +
|
||||
"n.js.ast.Catch\022J\n\014finallyBlock\030\003 \001(\01324.o" +
|
||||
"rg.jetbrains.kotlin.serialization.js.ast" +
|
||||
".InlineModule\"\224\001\n\016ImportedModule\022\030\n\020exte" +
|
||||
"rnal_name_id\030\001 \002(\005\022\030\n\020internal_name_id\030\002" +
|
||||
" \002(\005\022N\n\017plain_reference\030\003 \001(\01325.org.jetb" +
|
||||
"rains.kotlin.serialization.js.ast.Expres" +
|
||||
"sion\"i\n\006Import\022\024\n\014signature_id\030\001 \002(\005\022I\n\n",
|
||||
"expression\030\002 \002(\01325.org.jetbrains.kotlin." +
|
||||
"serialization.js.ast.Expression\"3\n\013NameB" +
|
||||
"inding\022\024\n\014signature_id\030\001 \002(\005\022\016\n\006nameId\030\002" +
|
||||
" \002(\005\"\247\001\n\nClassModel\022\017\n\007name_id\030\001 \002(\005\022\025\n\r" +
|
||||
"super_name_id\030\002 \001(\005\022\031\n\021interface_name_id" +
|
||||
"\030\004 \003(\005\022V\n\026post_declaration_block\030\003 \001(\01326" +
|
||||
".org.jetbrains.kotlin.serialization.js.a" +
|
||||
"st.GlobalBlock\";\n\014InlineModule\022\024\n\014signat" +
|
||||
"ure_id\030\001 \002(\005\022\025\n\rexpression_id\030\002 \002(\005\"\034\n\013S" +
|
||||
"tringTable\022\r\n\005entry\030\001 \003(\t\"K\n\tNameTable\022>",
|
||||
"\n\005entry\030\001 \003(\0132/.org.jetbrains.kotlin.ser" +
|
||||
"ialization.js.ast.Name\"\263\001\n\004Name\022\021\n\ttempo" +
|
||||
"rary\030\001 \002(\010\022\022\n\nidentifier\030\002 \001(\005\022\025\n\rlocal_" +
|
||||
"name_id\030\003 \001(\005\022\027\n\010imported\030\004 \001(\010:\005false\022T" +
|
||||
"\n\020special_function\030\005 \001(\0162:.org.jetbrains" +
|
||||
".kotlin.serialization.js.ast.SpecialFunc" +
|
||||
"tion\"\346\001\n\005Chunk\022L\n\014string_table\030\001 \002(\01326.o" +
|
||||
".Statement\"\224\001\n\005Catch\022G\n\tparameter\030\001 \002(\0132" +
|
||||
"4.org.jetbrains.kotlin.serialization.js." +
|
||||
"ast.Parameter\022B\n\004body\030\002 \002(\01324.org.jetbra" +
|
||||
"ins.kotlin.serialization.js.ast.Statemen" +
|
||||
"t\"\007\n\005Empty\"\327\005\n\010Fragment\022R\n\017imported_modu",
|
||||
"le\030\001 \003(\01329.org.jetbrains.kotlin.serializ" +
|
||||
"ation.js.ast.ImportedModule\022G\n\014import_en" +
|
||||
"try\030\002 \003(\01321.org.jetbrains.kotlin.seriali" +
|
||||
"zation.js.ast.Import\022Q\n\021declaration_bloc" +
|
||||
"k\030\003 \001(\01326.org.jetbrains.kotlin.serializa" +
|
||||
"tion.js.ast.GlobalBlock\022L\n\014export_block\030" +
|
||||
"\004 \001(\01326.org.jetbrains.kotlin.serializati" +
|
||||
"on.js.ast.GlobalBlock\022Q\n\021initializer_blo" +
|
||||
"ck\030\005 \001(\01326.org.jetbrains.kotlin.serializ" +
|
||||
"ation.js.ast.GlobalBlock\022L\n\014name_binding",
|
||||
"\030\006 \003(\01326.org.jetbrains.kotlin.serializat" +
|
||||
"ion.js.ast.NameBinding\022J\n\013class_model\030\007 " +
|
||||
"\003(\01325.org.jetbrains.kotlin.serialization" +
|
||||
".js.ast.ClassModel\022P\n\021module_expression\030" +
|
||||
"\010 \003(\01325.org.jetbrains.kotlin.serializati" +
|
||||
"on.js.ast.Expression\022N\n\rinline_module\030\t " +
|
||||
"\003(\01327.org.jetbrains.kotlin.serialization" +
|
||||
".js.ast.InlineModule\"\224\001\n\016ImportedModule\022" +
|
||||
"\030\n\020external_name_id\030\001 \002(\005\022\030\n\020internal_na" +
|
||||
"me_id\030\002 \002(\005\022N\n\017plain_reference\030\003 \001(\01325.o",
|
||||
"rg.jetbrains.kotlin.serialization.js.ast" +
|
||||
".StringTable\022H\n\nname_table\030\002 \002(\01324.org.j" +
|
||||
"etbrains.kotlin.serialization.js.ast.Nam",
|
||||
"eTable\022E\n\010fragment\030\003 \002(\01323.org.jetbrains" +
|
||||
".kotlin.serialization.js.ast.Fragment*@\n" +
|
||||
"\013SideEffects\022\021\n\rAFFECTS_STATE\020\001\022\024\n\020DEPEN" +
|
||||
"DS_ON_STATE\020\002\022\010\n\004PURE\020\003*?\n\016InlineStrateg" +
|
||||
"y\022\017\n\013AS_FUNCTION\020\000\022\014\n\010IN_PLACE\020\001\022\016\n\nNOT_" +
|
||||
"INLINE\020\002*\327\001\n\017SpecialFunction\022\032\n\026DEFINE_I" +
|
||||
"NLINE_FUNCTION\020\001\022\021\n\rWRAP_FUNCTION\020\002\022\021\n\rT" +
|
||||
"O_BOXED_CHAR\020\003\022\016\n\nUNBOX_CHAR\020\004\022\020\n\014SUSPEN" +
|
||||
"D_CALL\020\005\022\024\n\020COROUTINE_RESULT\020\006\022\030\n\024COROUT" +
|
||||
"INE_CONTROLLER\020\007\022\026\n\022COROUTINE_RECEIVER\020\010",
|
||||
"\022\030\n\024SET_COROUTINE_RESULT\020\tB\024B\022DebugJsAst" +
|
||||
"ProtoBuf"
|
||||
".Expression\"i\n\006Import\022\024\n\014signature_id\030\001 " +
|
||||
"\002(\005\022I\n\nexpression\030\002 \002(\01325.org.jetbrains." +
|
||||
"kotlin.serialization.js.ast.Expression\"3" +
|
||||
"\n\013NameBinding\022\024\n\014signature_id\030\001 \002(\005\022\016\n\006n" +
|
||||
"ameId\030\002 \002(\005\"\247\001\n\nClassModel\022\017\n\007name_id\030\001 " +
|
||||
"\002(\005\022\025\n\rsuper_name_id\030\002 \001(\005\022\031\n\021interface_" +
|
||||
"name_id\030\004 \003(\005\022V\n\026post_declaration_block\030" +
|
||||
"\003 \001(\01326.org.jetbrains.kotlin.serializati" +
|
||||
"on.js.ast.GlobalBlock\";\n\014InlineModule\022\024\n",
|
||||
"\014signature_id\030\001 \002(\005\022\025\n\rexpression_id\030\002 \002" +
|
||||
"(\005\"\034\n\013StringTable\022\r\n\005entry\030\001 \003(\t\"K\n\tName" +
|
||||
"Table\022>\n\005entry\030\001 \003(\0132/.org.jetbrains.kot" +
|
||||
"lin.serialization.js.ast.Name\"\263\001\n\004Name\022\021" +
|
||||
"\n\ttemporary\030\001 \002(\010\022\022\n\nidentifier\030\002 \001(\005\022\025\n" +
|
||||
"\rlocal_name_id\030\003 \001(\005\022\027\n\010imported\030\004 \001(\010:\005" +
|
||||
"false\022T\n\020special_function\030\005 \001(\0162:.org.je" +
|
||||
"tbrains.kotlin.serialization.js.ast.Spec" +
|
||||
"ialFunction\"\346\001\n\005Chunk\022L\n\014string_table\030\001 " +
|
||||
"\002(\01326.org.jetbrains.kotlin.serialization",
|
||||
".js.ast.StringTable\022H\n\nname_table\030\002 \002(\0132" +
|
||||
"4.org.jetbrains.kotlin.serialization.js." +
|
||||
"ast.NameTable\022E\n\010fragment\030\003 \002(\01323.org.je" +
|
||||
"tbrains.kotlin.serialization.js.ast.Frag" +
|
||||
"ment*@\n\013SideEffects\022\021\n\rAFFECTS_STATE\020\001\022\024" +
|
||||
"\n\020DEPENDS_ON_STATE\020\002\022\010\n\004PURE\020\003*?\n\016Inline" +
|
||||
"Strategy\022\017\n\013AS_FUNCTION\020\000\022\014\n\010IN_PLACE\020\001\022" +
|
||||
"\016\n\nNOT_INLINE\020\002*\327\001\n\017SpecialFunction\022\032\n\026D" +
|
||||
"EFINE_INLINE_FUNCTION\020\001\022\021\n\rWRAP_FUNCTION" +
|
||||
"\020\002\022\021\n\rTO_BOXED_CHAR\020\003\022\016\n\nUNBOX_CHAR\020\004\022\020\n",
|
||||
"\014SUSPEND_CALL\020\005\022\024\n\020COROUTINE_RESULT\020\006\022\030\n" +
|
||||
"\024COROUTINE_CONTROLLER\020\007\022\026\n\022COROUTINE_REC" +
|
||||
"EIVER\020\010\022\030\n\024SET_COROUTINE_RESULT\020\tB\024B\022Deb" +
|
||||
"ugJsAstProtoBuf"
|
||||
};
|
||||
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||
@@ -49803,7 +50084,7 @@ public final class DebugJsAstProtoBuf {
|
||||
internal_static_org_jetbrains_kotlin_serialization_js_ast_SwitchEntry_fieldAccessorTable = new
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
internal_static_org_jetbrains_kotlin_serialization_js_ast_SwitchEntry_descriptor,
|
||||
new java.lang.String[] { "Label", "Statement", });
|
||||
new java.lang.String[] { "Label", "Statement", "FileId", "Location", });
|
||||
internal_static_org_jetbrains_kotlin_serialization_js_ast_While_descriptor =
|
||||
getDescriptor().getMessageTypes().get(37);
|
||||
internal_static_org_jetbrains_kotlin_serialization_js_ast_While_fieldAccessorTable = new
|
||||
|
||||
191
build.gradle.kts
191
build.gradle.kts
@@ -1,3 +1,4 @@
|
||||
|
||||
import org.gradle.api.Project
|
||||
import java.util.*
|
||||
import java.io.File
|
||||
@@ -9,13 +10,15 @@ import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
|
||||
buildscript {
|
||||
extra["defaultSnapshotVersion"] = "1.2-SNAPSHOT"
|
||||
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.20-dev-524", onlySuccessBootstrap = false))
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.30-dev-672", onlySuccessBootstrap = false))
|
||||
|
||||
val repos = listOfNotNull(
|
||||
bootstrapKotlinRepo,
|
||||
"https://jcenter.bintray.com/",
|
||||
"https://plugins.gradle.org/m2",
|
||||
"http://repository.jetbrains.com/utils/")
|
||||
"http://dl.bintray.com/kotlin/kotlinx",
|
||||
"https://repo.gradle.org/gradle/libs-releases-local", // for native-platform
|
||||
"https://jetbrains.bintray.com/intellij-third-party-dependencies") // for jflex
|
||||
|
||||
extra["repos"] = repos
|
||||
|
||||
@@ -77,16 +80,21 @@ dependencies {
|
||||
}
|
||||
|
||||
val commonBuildDir = File(rootDir, "build")
|
||||
val distDir = "$rootDir/dist"
|
||||
val distKotlinHomeDir = "$distDir/kotlinc"
|
||||
val distDir by extra("$rootDir/dist")
|
||||
val distKotlinHomeDir by extra("$distDir/kotlinc")
|
||||
val distLibDir = "$distKotlinHomeDir/lib"
|
||||
val ideaPluginDir = "$distDir/artifacts/Kotlin"
|
||||
val ideaUltimatePluginDir = "$distDir/artifacts/KotlinUltimate"
|
||||
val commonLocalDataDir = "$rootDir/local"
|
||||
val ideaSandboxDir = "$commonLocalDataDir/ideaSandbox"
|
||||
val ideaUltimateSandboxDir = "$commonLocalDataDir/ideaUltimateSandbox"
|
||||
val ideaPluginDir = "$distDir/artifacts/ideaPlugin/Kotlin"
|
||||
val ideaUltimatePluginDir = "$distDir/artifacts/ideaUltimatePlugin/Kotlin"
|
||||
|
||||
extra["distDir"] = distDir
|
||||
extra["distKotlinHomeDir"] = distKotlinHomeDir
|
||||
// TODO: use "by extra()" syntax where possible
|
||||
extra["distLibDir"] = project.file(distLibDir)
|
||||
extra["libsDir"] = project.file(distLibDir)
|
||||
extra["commonLocalDataDir"] = project.file(commonLocalDataDir)
|
||||
extra["ideaSandboxDir"] = project.file(ideaSandboxDir)
|
||||
extra["ideaUltimateSandboxDir"] = project.file(ideaUltimateSandboxDir)
|
||||
extra["ideaPluginDir"] = project.file(ideaPluginDir)
|
||||
extra["ideaUltimatePluginDir"] = project.file(ideaUltimatePluginDir)
|
||||
extra["isSonatypeRelease"] = false
|
||||
@@ -105,6 +113,10 @@ extra["JDK_17"] = jdkPath("1.7")
|
||||
extra["JDK_18"] = jdkPath("1.8")
|
||||
extra["JDK_9"] = jdkPathIfFound("9")
|
||||
|
||||
rootProject.apply {
|
||||
from(rootProject.file("versions.gradle.kts"))
|
||||
}
|
||||
|
||||
extra["versions.protobuf-java"] = "2.6.1"
|
||||
extra["versions.javax.inject"] = "1"
|
||||
extra["versions.jsr305"] = "1.3.9"
|
||||
@@ -114,9 +126,57 @@ extra["versions.junit"] = "4.12"
|
||||
extra["versions.javaslang"] = "2.0.6"
|
||||
extra["versions.ant"] = "1.8.2"
|
||||
extra["versions.android"] = "2.3.1"
|
||||
extra["versions.kotlinx-coroutines-core"] = "0.20"
|
||||
extra["versions.kotlinx-coroutines-jdk8"] = "0.20"
|
||||
extra["versions.json"] = "20160807"
|
||||
extra["versions.native-platform"] = "0.14"
|
||||
extra["versions.ant-launcher"] = "1.8.0"
|
||||
extra["versions.robolectric"] = "3.1"
|
||||
extra["versions.org.springframework"] = "4.2.0.RELEASE"
|
||||
extra["versions.jflex"] = "1.7.0"
|
||||
|
||||
extra["ideaCoreSdkJars"] = arrayOf("annotations", "asm-all", "guava", "intellij-core", "jdom", "jna", "log4j", "picocontainer",
|
||||
"snappy-in-java", "streamex", "trove4j", "xpp3-1.1.4-min", "xstream")
|
||||
val markdownVer = "4054 - Kotlin 1.0.2-dev-566".replace(" ", "%20") // fixed here, was last with "status:SUCCESS,tag:forKotlin"
|
||||
extra["markdownParserRepo"] = "https://teamcity.jetbrains.com/guestAuth/repository/download/IntelliJMarkdownParser_Build/$markdownVer/([artifact]_[ext]/)[artifact](.[ext])"
|
||||
|
||||
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
|
||||
val v = it.toString()
|
||||
if (v.isBlank()) true
|
||||
else v.toBoolean()
|
||||
}
|
||||
|
||||
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
|
||||
val intellijUltimateEnabled = project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild
|
||||
|
||||
val intellijSeparateSdks = project.getBooleanProperty("intellijSeparateSdks") ?: false
|
||||
|
||||
extra["intellijUltimateEnabled"] = intellijUltimateEnabled
|
||||
extra["intellijSeparateSdks"] = intellijSeparateSdks
|
||||
|
||||
extra["IntellijCoreDependencies"] =
|
||||
listOf("annotations",
|
||||
"asm-all",
|
||||
"guava-21.0",
|
||||
"jdom",
|
||||
"jna",
|
||||
"log4j",
|
||||
"picocontainer",
|
||||
"snappy-in-java-0.5.1",
|
||||
"streamex",
|
||||
"trove4j",
|
||||
"xpp3-1.1.4-min",
|
||||
"xstream-1.4.8")
|
||||
|
||||
extra["nativePlatformVariants"] =
|
||||
listOf("windows-amd64",
|
||||
"windows-i386",
|
||||
"osx-amd64",
|
||||
"osx-i386",
|
||||
"linux-amd64",
|
||||
"linux-i386",
|
||||
"freebsd-amd64-libcpp",
|
||||
"freebsd-amd64-libstdcpp",
|
||||
"freebsd-i386-libcpp",
|
||||
"freebsd-i386-libstdcpp")
|
||||
|
||||
extra["compilerModules"] = arrayOf(
|
||||
":compiler:util",
|
||||
@@ -192,21 +252,6 @@ apply {
|
||||
}
|
||||
}
|
||||
|
||||
val importedAntTasksPrefix = "imported-ant-update-"
|
||||
|
||||
// TODO: check the reasons of import conflict with xerces
|
||||
//ant.importBuild("$rootDir/update_dependencies.xml") { antTaskName -> importedAntTasksPrefix + antTaskName }
|
||||
|
||||
tasks.matching { task ->
|
||||
task.name.startsWith(importedAntTasksPrefix)
|
||||
}.forEach {
|
||||
it.group = "Imported ant"
|
||||
}
|
||||
|
||||
//task("update-dependencies") {
|
||||
// dependsOn(tasks.getByName(importedAntTasksPrefix + "update"))
|
||||
//}
|
||||
|
||||
fun Project.allprojectsRecursive(body: Project.() -> Unit) {
|
||||
this.body()
|
||||
this.subprojects { allprojectsRecursive(body) }
|
||||
@@ -237,11 +282,16 @@ allprojects {
|
||||
for (repo in (rootProject.extra["repos"] as List<String>)) {
|
||||
maven { setUrl(repo) }
|
||||
}
|
||||
ivy {
|
||||
artifactPattern(rootProject.extra["markdownParserRepo"] as String)
|
||||
}
|
||||
intellijSdkRepo(project)
|
||||
androidDxJarRepo(project)
|
||||
}
|
||||
configureJvmProject(javaHome!!, jvmTarget!!)
|
||||
|
||||
val commonCompilerArgs = listOf("-Xallow-kotlin-package")
|
||||
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
|
||||
kotlinOptions {
|
||||
languageVersion = kotlinLanguageVersion
|
||||
@@ -283,6 +333,18 @@ allprojects {
|
||||
if (javaHome != defaultJavaHome || jvmTarget != defaultJvmTarget) {
|
||||
configureJvmProject(javaHome!!, jvmTarget!!)
|
||||
}
|
||||
|
||||
fun File.toProjectRootRelativePathOrSelf() = (relativeToOrNull(rootDir)?.takeUnless { it.startsWith("..") } ?: this).path
|
||||
|
||||
fun FileCollection.printClassPath(role: String) =
|
||||
println("${project.path} $role classpath:\n ${joinToString("\n ") { it.toProjectRootRelativePathOrSelf() } }")
|
||||
|
||||
try { the<JavaPluginConvention>() } catch (_: UnknownDomainObjectException) { null }?.let { javaConvention ->
|
||||
task("printCompileClasspath") { doFirst { javaConvention.sourceSets["main"].compileClasspath.printClassPath("compile") } }
|
||||
task("printRuntimeClasspath") { doFirst { javaConvention.sourceSets["main"].runtimeClasspath.printClassPath("runtime") } }
|
||||
task("printTestCompileClasspath") { doFirst { javaConvention.sourceSets["test"].compileClasspath.printClassPath("test compile") } }
|
||||
task("printTestRuntimeClasspath") { doFirst { javaConvention.sourceSets["test"].runtimeClasspath.printClassPath("test runtime") } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,14 +355,13 @@ task<Copy>("dist") {
|
||||
}
|
||||
|
||||
val compilerCopyTask = task<Copy>("idea-plugin-copy-compiler") {
|
||||
dependsOnTaskIfExistsRec("dist")
|
||||
shouldRunAfter(":dist")
|
||||
into(ideaPluginDir)
|
||||
from(distDir) { include("kotlinc/**") }
|
||||
}
|
||||
|
||||
task<Copy>("ideaPlugin") {
|
||||
dependsOn(compilerCopyTask)
|
||||
dependsOnTaskIfExistsRec("idea-plugin")
|
||||
shouldRunAfter(":prepare:idea-plugin:idea-plugin")
|
||||
into("$ideaPluginDir/lib")
|
||||
}
|
||||
@@ -313,6 +374,13 @@ tasks {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: copied from TeamCityBuild.xml (with ultimate-related modification), consider removing after migrating from it
|
||||
"cleanupArtifacts" {
|
||||
doLast {
|
||||
delete(ideaPluginDir)
|
||||
delete(ideaUltimatePluginDir)
|
||||
}
|
||||
}
|
||||
|
||||
"coreLibsTest" {
|
||||
(coreLibProjects + listOf(
|
||||
@@ -343,6 +411,7 @@ tasks {
|
||||
|
||||
"jsCompilerTest" {
|
||||
dependsOn(":js:js.tests:test")
|
||||
dependsOn(":js:js.tests:runMocha")
|
||||
}
|
||||
|
||||
"scriptingTest" {
|
||||
@@ -356,6 +425,7 @@ tasks {
|
||||
|
||||
dependsOn("scriptingTest")
|
||||
dependsOn(":kotlin-build-common:test")
|
||||
dependsOn(":compiler:incremental-compilation-impl:test")
|
||||
}
|
||||
|
||||
"examplesTest" {
|
||||
@@ -437,19 +507,70 @@ tasks {
|
||||
"check" { dependsOn("test") }
|
||||
}
|
||||
|
||||
fun CopySpec.compilerScriptPermissionsSpec() {
|
||||
filesMatching("bin/*") { mode = 0b111101101 }
|
||||
filesMatching("bin/*.bat") { mode = 0b110100100 }
|
||||
}
|
||||
|
||||
val zipCompiler by task<Zip> {
|
||||
destinationDir = file(distDir)
|
||||
archiveName = "kotlin-compiler-$kotlinVersion.zip"
|
||||
from(distKotlinHomeDir) {
|
||||
into("kotlinc")
|
||||
compilerScriptPermissionsSpec()
|
||||
}
|
||||
doLast {
|
||||
logger.lifecycle("Compiler artifacts packed to $archivePath")
|
||||
}
|
||||
}
|
||||
|
||||
val zipTestData by task<Zip> {
|
||||
destinationDir = file(distDir)
|
||||
archiveName = "kotlin-test-data.zip"
|
||||
from("compiler/testData") { into("compiler") }
|
||||
from("idea/testData") { into("ide") }
|
||||
from("idea/idea-completion/testData") { into("ide/completion") }
|
||||
doLast {
|
||||
logger.lifecycle("Test data packed to $archivePath")
|
||||
}
|
||||
}
|
||||
|
||||
val zipPlugin by task<Zip> {
|
||||
val src = when (project.findProperty("pluginArtifactDir") as String?) {
|
||||
"Kotlin" -> ideaPluginDir
|
||||
"KotlinUltimate" -> ideaUltimatePluginDir
|
||||
null -> if (project.hasProperty("ultimate")) ideaUltimatePluginDir else ideaPluginDir
|
||||
else -> error("Unsupported plugin artifact dir")
|
||||
}
|
||||
val destPath = project.findProperty("pluginZipPath") as String?
|
||||
val dest = File(destPath ?: "$buildDir/kotlin-plugin.zip")
|
||||
destinationDir = dest.parentFile
|
||||
archiveName = dest.name
|
||||
doFirst {
|
||||
if (destPath == null) throw GradleException("Specify target zip path with 'pluginZipPath' property")
|
||||
}
|
||||
into("Kotlin") {
|
||||
from("$src/kotlinc") {
|
||||
into("kotlinc")
|
||||
compilerScriptPermissionsSpec()
|
||||
}
|
||||
from(src) {
|
||||
exclude("kotlinc")
|
||||
}
|
||||
}
|
||||
doLast {
|
||||
logger.lifecycle("Plugin artifacts packed to $archivePath")
|
||||
}
|
||||
}
|
||||
|
||||
configure<IdeaModel> {
|
||||
module {
|
||||
excludeDirs = files(
|
||||
project.buildDir,
|
||||
commonLocalDataDir,
|
||||
".gradle",
|
||||
"dependencies",
|
||||
"dist",
|
||||
"ideaSDK/bin",
|
||||
"ideaSDK/androidSDK",
|
||||
"ideaSDK/config",
|
||||
"ideaSDK/config-idea",
|
||||
"ideaSDK/system",
|
||||
"ideaSDK/system-idea"
|
||||
"dist"
|
||||
).toSet()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ buildscript {
|
||||
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
|
||||
val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?)
|
||||
extra["versions.shadow"] = "2.0.1"
|
||||
extra["versions.intellij-plugin"] = "0.3.0-SNAPSHOT"
|
||||
extra["versions.native-platform"] = "0.14"
|
||||
|
||||
repositories {
|
||||
buildSrcKotlinRepo?.let {
|
||||
@@ -29,19 +31,40 @@ plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
|
||||
val v = it.toString()
|
||||
if (v.isBlank()) true
|
||||
else v.toBoolean()
|
||||
}
|
||||
|
||||
rootProject.apply {
|
||||
from(rootProject.file("../versions.gradle.kts"))
|
||||
}
|
||||
|
||||
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
|
||||
val intellijUltimateEnabled by extra(project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild)
|
||||
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
|
||||
|
||||
extra["intellijRepo"] = "https://www.jetbrains.com/intellij-repository"
|
||||
extra["intellijReleaseType"] = "releases" // or "snapshots"
|
||||
extra["versions.androidDxSources"] = "5.0.0_r2"
|
||||
|
||||
extra["customDepsOrg"] = "kotlin.build.custom.deps"
|
||||
|
||||
repositories {
|
||||
extra["buildSrcKotlinRepo"]?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
maven(url = "https://dl.bintray.com/kotlin/kotlin-dev") // for dex-method-list
|
||||
// maven { setUrl("https://repo.gradle.org/gradle/libs-releases-local") }
|
||||
maven(url = "https://repo.gradle.org/gradle/libs-releases-local") // for native-platform
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(files("../dependencies/native-platform-uberjar.jar"))
|
||||
compile("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
|
||||
compile("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
|
||||
compile("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}")
|
||||
compile("com.jakewharton.dex:dex-method-list:2.0.0-alpha")
|
||||
// compile("net.rubygrapefruit:native-platform:0.14")
|
||||
// TODO: adding the dep to the plugin breaks the build unexpectedly, resolve and uncomment
|
||||
// compile("org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.extra["bootstrap_kotlin_version"]}")
|
||||
compile("com.github.jengelman.gradle.plugins:shadow:${property("versions.shadow")}")
|
||||
@@ -54,3 +77,5 @@ samWithReceiver {
|
||||
|
||||
fun Project.`samWithReceiver`(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit =
|
||||
extensions.configure("samWithReceiver", configure)
|
||||
|
||||
tasks["build"].dependsOn(":prepare-deps:android-dx:build", ":prepare-deps:intellij-sdk:build")
|
||||
|
||||
106
buildSrc/prepare-deps/android-dx/build.gradle.kts
Normal file
106
buildSrc/prepare-deps/android-dx/build.gradle.kts
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
import org.gradle.api.publish.ivy.internal.artifact.DefaultIvyArtifact
|
||||
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyConfiguration
|
||||
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyPublicationIdentity
|
||||
import org.gradle.api.publish.ivy.internal.publisher.IvyDescriptorFileGenerator
|
||||
import java.io.File
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
|
||||
val toolsOs by lazy {
|
||||
when {
|
||||
OperatingSystem.current().isWindows -> "windows"
|
||||
OperatingSystem.current().isMacOsX -> "macosx"
|
||||
OperatingSystem.current().isLinux -> "linux"
|
||||
else -> {
|
||||
logger.error("Unknown operating system for android tools: ${OperatingSystem.current().name}")
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val buildToolsVersion = rootProject.extra["versions.androidBuildTools"] as String
|
||||
val dxSourcesVersion = rootProject.extra["versions.androidDxSources"] as String
|
||||
|
||||
repositories {
|
||||
ivy {
|
||||
artifactPattern("https://dl-ssl.google.com/android/repository/[artifact]_[revision](-[classifier]).[ext]")
|
||||
artifactPattern("https://android.googlesource.com/platform/dalvik/+archive/android-$dxSourcesVersion/[artifact].[ext]")
|
||||
}
|
||||
}
|
||||
|
||||
val customDepsRepoDir = File(buildDir, "repo")
|
||||
val customDepsOrg: String by rootProject.extra
|
||||
val dxModuleName = "android-dx"
|
||||
val dxRevision = buildToolsVersion
|
||||
val dxRepoModuleDir = File(customDepsRepoDir, "$customDepsOrg/$dxModuleName/$dxRevision")
|
||||
|
||||
val buildToolsZip by configurations.creating
|
||||
val dxSourcesTar by configurations.creating
|
||||
|
||||
dependencies {
|
||||
buildToolsZip("google:build-tools:$buildToolsVersion:$toolsOs@zip")
|
||||
dxSourcesTar("google:dx:0@tar.gz")
|
||||
}
|
||||
|
||||
val unzipDxJar by tasks.creating {
|
||||
dependsOn(buildToolsZip)
|
||||
inputs.files(buildToolsZip)
|
||||
outputs.files(File(dxRepoModuleDir, "dx.jar"))
|
||||
doFirst {
|
||||
project.copy {
|
||||
from(zipTree(buildToolsZip.singleFile).files)
|
||||
include("**/dx.jar")
|
||||
into(dxRepoModuleDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val dxSourcesTargetDir = File(buildDir, "dx_src")
|
||||
|
||||
val untarDxSources by tasks.creating {
|
||||
dependsOn(dxSourcesTar)
|
||||
inputs.files(dxSourcesTar)
|
||||
outputs.dir(dxSourcesTargetDir)
|
||||
doFirst {
|
||||
project.copy {
|
||||
from(tarTree(dxSourcesTar.singleFile))
|
||||
include("src/**")
|
||||
includeEmptyDirs = false
|
||||
into(dxSourcesTargetDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val prepareDxSourcesJar by tasks.creating(Jar::class) {
|
||||
dependsOn(untarDxSources)
|
||||
from("$dxSourcesTargetDir/src")
|
||||
destinationDir = dxRepoModuleDir
|
||||
baseName = "dx"
|
||||
classifier = "sources"
|
||||
}
|
||||
|
||||
val prepareIvyXml by tasks.creating {
|
||||
dependsOn(unzipDxJar, prepareDxSourcesJar)
|
||||
inputs.files(unzipDxJar, prepareDxSourcesJar)
|
||||
val ivyFile = File(dxRepoModuleDir, "$dxModuleName.ivy.xml")
|
||||
outputs.file(ivyFile)
|
||||
doLast {
|
||||
with(IvyDescriptorFileGenerator(DefaultIvyPublicationIdentity(customDepsOrg, dxModuleName, dxRevision))) {
|
||||
addConfiguration(DefaultIvyConfiguration("default"))
|
||||
addConfiguration(DefaultIvyConfiguration("sources"))
|
||||
addArtifact(DefaultIvyArtifact(File(dxRepoModuleDir, "dx.jar"), "dx", "jar", "jar", null).also { it.conf = "default" })
|
||||
addArtifact(DefaultIvyArtifact(File(dxRepoModuleDir, "dx-sources.jar"), "dx", "jar", "sources", "sources").also { it.conf = "sources" })
|
||||
writeTo(ivyFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val build by tasks.creating {
|
||||
dependsOn(unzipDxJar, prepareDxSourcesJar, prepareIvyXml)
|
||||
}
|
||||
|
||||
val clean by tasks.creating(Delete::class) {
|
||||
delete(dxRepoModuleDir)
|
||||
delete(buildDir)
|
||||
}
|
||||
223
buildSrc/prepare-deps/intellij-sdk/build.gradle.kts
Normal file
223
buildSrc/prepare-deps/intellij-sdk/build.gradle.kts
Normal file
@@ -0,0 +1,223 @@
|
||||
|
||||
@file:Suppress("PropertyName")
|
||||
|
||||
import org.gradle.api.publish.ivy.internal.artifact.DefaultIvyArtifact
|
||||
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyConfiguration
|
||||
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyPublicationIdentity
|
||||
import org.gradle.api.publish.ivy.internal.publisher.IvyDescriptorFileGenerator
|
||||
import java.io.File
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
val intellijUltimateEnabled: Boolean by rootProject.extra
|
||||
val intellijRepo: String by rootProject.extra
|
||||
val intellijReleaseType: String by rootProject.extra
|
||||
val intellijVersion = rootProject.extra["versions.intellijSdk"] as String
|
||||
val androidStudioRelease = rootProject.findProperty("versions.androidStudioRelease") as String?
|
||||
val androidStudioBuild = rootProject.findProperty("versions.androidStudioBuild") as String?
|
||||
val intellijSeparateSdks: Boolean by rootProject.extra
|
||||
val installIntellijCommunity = !intellijUltimateEnabled || intellijSeparateSdks
|
||||
val installIntellijUltimate = intellijUltimateEnabled
|
||||
|
||||
logger.info("intellijUltimateEnabled: $intellijUltimateEnabled")
|
||||
|
||||
logger.info("intellijVersion: $intellijVersion")
|
||||
logger.info("androidStudioRelease: $androidStudioRelease")
|
||||
logger.info("androidStudioBuild: $androidStudioBuild")
|
||||
|
||||
logger.info("intellijSeparateSdks: $intellijSeparateSdks")
|
||||
logger.info("installIntellijCommunity: $installIntellijCommunity")
|
||||
logger.info("installIntellijUltimate: $installIntellijUltimate")
|
||||
|
||||
val studioOs by lazy {
|
||||
when {
|
||||
OperatingSystem.current().isWindows -> "windows"
|
||||
OperatingSystem.current().isMacOsX -> "mac"
|
||||
OperatingSystem.current().isLinux -> "linux"
|
||||
else -> {
|
||||
logger.error("Unknown operating system for android tools: ${OperatingSystem.current().name}")
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
if (androidStudioRelease != null) {
|
||||
ivy {
|
||||
artifactPattern("https://dl.google.com/dl/android/studio/ide-zips/$androidStudioRelease/[artifact]-[revision]-$studioOs.zip")
|
||||
}
|
||||
}
|
||||
maven { setUrl("$intellijRepo/$intellijReleaseType") }
|
||||
maven { setUrl("https://plugins.jetbrains.com/maven") }
|
||||
}
|
||||
|
||||
val intellij by configurations.creating
|
||||
val intellijUltimate by configurations.creating
|
||||
val sources by configurations.creating
|
||||
val `jps-standalone` by configurations.creating
|
||||
val `jps-build-test` by configurations.creating
|
||||
val `intellij-core` by configurations.creating
|
||||
val `plugins-NodeJS` by configurations.creating
|
||||
|
||||
val customDepsRepoDir = File(buildDir, "repo")
|
||||
val customDepsOrg: String by rootProject.extra
|
||||
val customDepsRevision = intellijVersion
|
||||
val customDepsRepoModulesDir = File(customDepsRepoDir, "$customDepsOrg/$customDepsRevision")
|
||||
val repoDir = customDepsRepoModulesDir
|
||||
|
||||
dependencies {
|
||||
if (androidStudioRelease != null) {
|
||||
intellij("google:android-studio-ide:$androidStudioBuild")
|
||||
} else {
|
||||
if (installIntellijCommunity) {
|
||||
intellij("com.jetbrains.intellij.idea:ideaIC:$intellijVersion")
|
||||
}
|
||||
if (installIntellijUltimate) {
|
||||
intellijUltimate("com.jetbrains.intellij.idea:ideaIU:$intellijVersion")
|
||||
}
|
||||
}
|
||||
sources("com.jetbrains.intellij.idea:ideaIC:$intellijVersion:sources@jar")
|
||||
`jps-standalone`("com.jetbrains.intellij.idea:jps-standalone:$intellijVersion")
|
||||
`jps-build-test`("com.jetbrains.intellij.idea:jps-build-test:$intellijVersion")
|
||||
`intellij-core`("com.jetbrains.intellij.idea:intellij-core:$intellijVersion")
|
||||
if (intellijUltimateEnabled) {
|
||||
`plugins-NodeJS`("com.jetbrains.plugins:NodeJS:${rootProject.extra["versions.idea.NodeJS"]}@zip")
|
||||
}
|
||||
}
|
||||
|
||||
fun Task.configureExtractFromConfigurationTask(sourceConfig: Configuration,
|
||||
pathRemap: (String) -> String = { it },
|
||||
extractor: (Configuration) -> Any) {
|
||||
dependsOn(sourceConfig)
|
||||
inputs.files(sourceConfig)
|
||||
val targetDir = File(repoDir, sourceConfig.name)
|
||||
outputs.dirs(targetDir)
|
||||
doFirst {
|
||||
project.copy {
|
||||
from(extractor(sourceConfig))
|
||||
into(targetDir)
|
||||
eachFile {
|
||||
path = pathRemap(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removePathPrefix(path: String): String {
|
||||
if (androidStudioRelease == null) return path
|
||||
val slashes = if (studioOs == "mac") 2 else 1
|
||||
var result = path
|
||||
repeat(slashes) {
|
||||
result = result.substringAfter('/')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
val unzipIntellijSdk by tasks.creating {
|
||||
configureExtractFromConfigurationTask(intellij, pathRemap = { removePathPrefix(it) }) { zipTree(it.singleFile) }
|
||||
}
|
||||
|
||||
val unzipIntellijUltimateSdk by tasks.creating { configureExtractFromConfigurationTask(intellijUltimate) { zipTree(it.singleFile) } }
|
||||
|
||||
val unzipIntellijCore by tasks.creating { configureExtractFromConfigurationTask(`intellij-core`) { zipTree(it.singleFile) } }
|
||||
|
||||
val unzipJpsStandalone by tasks.creating { configureExtractFromConfigurationTask(`jps-standalone`) { zipTree(it.singleFile) } }
|
||||
|
||||
val copyIntellijSdkSources by tasks.creating {
|
||||
configureExtractFromConfigurationTask(sources) { it.singleFile }
|
||||
}
|
||||
|
||||
val copyJpsBuildTest by tasks.creating { configureExtractFromConfigurationTask(`jps-build-test`) { it.singleFile } }
|
||||
|
||||
val unzipNodeJSPlugin by tasks.creating { configureExtractFromConfigurationTask(`plugins-NodeJS`) { zipTree(it.singleFile) } }
|
||||
|
||||
fun writeIvyXml(moduleName: String, fileName: String, jarFiles: FileCollection, baseDir: File, sourcesJar: File?) {
|
||||
with(IvyDescriptorFileGenerator(DefaultIvyPublicationIdentity(customDepsOrg, moduleName, intellijVersion))) {
|
||||
addConfiguration(DefaultIvyConfiguration("default"))
|
||||
addConfiguration(DefaultIvyConfiguration("sources"))
|
||||
jarFiles.asFileTree.files.forEach {
|
||||
if (it.isFile && it.extension == "jar") {
|
||||
val relativeName = it.toRelativeString(baseDir).removeSuffix(".jar")
|
||||
addArtifact(DefaultIvyArtifact(it, relativeName, "jar", "jar", null).also { it.conf = "default" })
|
||||
}
|
||||
}
|
||||
if (sourcesJar != null) {
|
||||
val sourcesArtifactName = sourcesJar.name.removeSuffix(".jar").substringBefore("-")
|
||||
addArtifact(DefaultIvyArtifact(sourcesJar, sourcesArtifactName, "jar", "sources", "sources").also { it.conf = "sources" })
|
||||
}
|
||||
writeTo(File(customDepsRepoModulesDir, "$fileName.ivy.xml"))
|
||||
}
|
||||
}
|
||||
|
||||
val prepareIvyXmls by tasks.creating {
|
||||
dependsOn(unzipIntellijCore, unzipJpsStandalone, copyIntellijSdkSources, copyJpsBuildTest)
|
||||
|
||||
val intellijSdkDir = File(repoDir, intellij.name)
|
||||
val intellijUltimateSdkDir = File(repoDir, intellijUltimate.name)
|
||||
|
||||
if (installIntellijCommunity) {
|
||||
dependsOn(unzipIntellijSdk)
|
||||
inputs.dir(intellijSdkDir)
|
||||
outputs.file(File(repoDir, "${intellij.name}.ivy.xml"))
|
||||
}
|
||||
|
||||
if (installIntellijUltimate) {
|
||||
dependsOn(unzipIntellijUltimateSdk)
|
||||
inputs.dir(intellijUltimateSdkDir)
|
||||
outputs.file(File(repoDir, "${intellijUltimate.name}.ivy.xml"))
|
||||
}
|
||||
|
||||
val flatDeps = listOf(`intellij-core`, `jps-standalone`, `jps-build-test`)
|
||||
flatDeps.forEach {
|
||||
inputs.dir(File(repoDir, it.name))
|
||||
outputs.file(File(repoDir, "${it.name}.ivy.xml"))
|
||||
}
|
||||
inputs.dir(File(repoDir, sources.name))
|
||||
|
||||
if (intellijUltimateEnabled) {
|
||||
dependsOn(unzipNodeJSPlugin)
|
||||
inputs.dir(File(repoDir, `plugins-NodeJS`.name))
|
||||
outputs.file(File(repoDir, "${`plugins-NodeJS`.name}.ivy.xml"))
|
||||
}
|
||||
|
||||
doFirst {
|
||||
val sourcesFile = if (sources.isEmpty) null else File(repoDir, "${sources.name}/${sources.singleFile.name}")
|
||||
|
||||
if (installIntellijCommunity) {
|
||||
writeIvyXml(intellij.name, intellij.name,
|
||||
files("$intellijSdkDir/lib/").filter { !it.name.startsWith("kotlin-") },
|
||||
File(intellijSdkDir, "lib"),
|
||||
sourcesFile)
|
||||
File(intellijSdkDir, "plugins").listFiles { it: File -> it.isDirectory }.forEach {
|
||||
writeIvyXml(it.name, "intellij.plugin.${it.name}", files("$it/lib/"), File(it, "lib"), sourcesFile)
|
||||
}
|
||||
}
|
||||
|
||||
if (installIntellijUltimate) {
|
||||
writeIvyXml(intellij.name /* important! the module name should be "intellij" */ , intellijUltimate.name,
|
||||
files("$intellijUltimateSdkDir/lib/").filter { !it.name.startsWith("kotlin-") },
|
||||
File(intellijUltimateSdkDir, "lib"),
|
||||
sourcesFile)
|
||||
File(intellijUltimateSdkDir, "plugins").listFiles { it: File -> it.isDirectory }.forEach {
|
||||
writeIvyXml(it.name, "intellijUltimate.plugin.${it.name}", files("$it/lib/"), File(it, "lib"), sourcesFile)
|
||||
}
|
||||
}
|
||||
|
||||
flatDeps.forEach {
|
||||
writeIvyXml(it.name, it.name, files("$repoDir/${it.name}"), File(repoDir, it.name), sourcesFile)
|
||||
}
|
||||
|
||||
if (intellijUltimateEnabled) {
|
||||
val nodeJsBaseDir = "${`plugins-NodeJS`.name}/NodeJS/lib"
|
||||
writeIvyXml("NodeJS", `plugins-NodeJS`.name, files("$repoDir/$nodeJsBaseDir"), File(repoDir, nodeJsBaseDir), sourcesFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val build by tasks.creating {
|
||||
dependsOn(prepareIvyXmls)
|
||||
}
|
||||
|
||||
val clean by tasks.creating(Delete::class) {
|
||||
delete(customDepsRepoModulesDir)
|
||||
delete(buildDir)
|
||||
}
|
||||
3
buildSrc/settings.gradle
Normal file
3
buildSrc/settings.gradle
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
include "prepare-deps:android-dx",
|
||||
"prepare-deps:intellij-sdk"
|
||||
14
buildSrc/src/main/kotlin/AndroidSdkDependencies.kt
Normal file
14
buildSrc/src/main/kotlin/AndroidSdkDependencies.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
|
||||
fun RepositoryHandler.androidDxJarRepo(project: Project): IvyArtifactRepository = ivy {
|
||||
val baseDir = File("${project.rootDir}/buildSrc/prepare-deps/android-dx/build/repo")
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[module]/[revision]/[module].ivy.xml")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[module]/[revision]/[artifact](-[classifier]).jar")
|
||||
}
|
||||
|
||||
fun Project.androidDxJar() = "kotlin.build.custom.deps:android-dx:${rootProject.extra["versions.androidBuildTools"]}"
|
||||
@@ -1,13 +1,17 @@
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import org.gradle.kotlin.dsl.creating
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.gradle.kotlin.dsl.get
|
||||
import org.gradle.kotlin.dsl.the
|
||||
import java.io.File
|
||||
|
||||
inline fun <reified T : Task> Project.task(noinline configuration: T.() -> Unit) = tasks.creating(T::class, configuration)
|
||||
@@ -16,26 +20,6 @@ fun Project.callGroovy(name: String, vararg args: Any?): Any? {
|
||||
return (property(name) as Closure<*>).call(*args)
|
||||
}
|
||||
|
||||
fun AbstractTask.dependsOnTaskIfExists(task: String, project: Project?, parentProject: Project?) {
|
||||
val thisTask = this
|
||||
val p = project ?: this.project
|
||||
p.afterEvaluate {
|
||||
p.tasks.firstOrNull { it.name == task }?.also {
|
||||
if (parentProject != null) {
|
||||
parentProject.evaluationDependsOn(p.path)
|
||||
}
|
||||
thisTask.dependsOn(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun AbstractTask.dependsOnTaskIfExistsRec(task: String, project: Project? = null, parentProject: Project? = null) {
|
||||
dependsOnTaskIfExists(task, project, parentProject)
|
||||
(project ?: this.project).subprojects.forEach {
|
||||
dependsOnTaskIfExistsRec(task, it, this.project)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun<T: Any> Project.withJavaPlugin(crossinline body: () -> T?): T? {
|
||||
var res: T? = null
|
||||
pluginManager.withPlugin("java") {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
@@ -14,14 +13,24 @@ import java.io.File
|
||||
fun Project.commonDep(coord: String): String {
|
||||
val parts = coord.split(':')
|
||||
return when (parts.size) {
|
||||
1 -> "$coord:$coord:${rootProject.extra["versions.$coord"]}"
|
||||
2 -> "${parts[0]}:${parts[1]}:${rootProject.extra["versions.${parts[1]}"]}"
|
||||
1 -> "$coord:$coord:${commonVer(coord, coord)}"
|
||||
2 -> "${parts[0]}:${parts[1]}:${commonVer(parts[0], parts[1])}"
|
||||
3 -> coord
|
||||
else -> throw IllegalArgumentException("Illegal maven coordinates: $coord")
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.commonDep(group: String, artifact: String): String = "$group:$artifact:${rootProject.extra["versions.$artifact"]}"
|
||||
fun Project.commonDep(group: String, artifact: String, vararg suffixesAndClassifiers: String): String {
|
||||
val (classifiers, artifactSuffixes) = suffixesAndClassifiers.partition { it.startsWith(':') }
|
||||
return "$group:$artifact${artifactSuffixes.joinToString("")}:${commonVer(group, artifact)}${classifiers.joinToString("")}"
|
||||
}
|
||||
|
||||
fun Project.commonVer(group: String, artifact: String) =
|
||||
when {
|
||||
rootProject.extra.has("versions.$artifact") -> rootProject.extra["versions.$artifact"]
|
||||
rootProject.extra.has("versions.$group") -> rootProject.extra["versions.$group"]
|
||||
else -> throw GradleException("Neither versions.$artifact nor versions.$group is defined in the root project's extra")
|
||||
}
|
||||
|
||||
fun Project.preloadedDeps(vararg artifactBaseNames: String, baseDir: File = File(rootDir, "dependencies"), subdir: String? = null, optional: Boolean = false): ConfigurableFileCollection {
|
||||
val dir = if (subdir != null) File(baseDir, subdir) else baseDir
|
||||
@@ -44,25 +53,6 @@ fun Project.ideaUltimatePreloadedDeps(vararg artifactBaseNames: String, subdir:
|
||||
else files()
|
||||
}
|
||||
|
||||
fun Project.ideaSdkDeps(vararg artifactBaseNames: String, subdir: String = "lib", optional: Boolean = false): ConfigurableFileCollection =
|
||||
preloadedDeps(*artifactBaseNames, baseDir = File(rootDir, "ideaSDK"), subdir = subdir, optional = optional)
|
||||
|
||||
fun Project.ideaUltimateSdkDeps(vararg artifactBaseNames: String, subdir: String = "lib"): ConfigurableFileCollection {
|
||||
val ultimateSdkDir = File(rootDir, "ultimate", "ideaSDK")
|
||||
return if (ultimateSdkDir.isDirectory) preloadedDeps(*artifactBaseNames, baseDir = ultimateSdkDir, subdir = subdir)
|
||||
else files()
|
||||
}
|
||||
|
||||
fun Project.ideaSdkCoreDeps(vararg artifactBaseNames: String): ConfigurableFileCollection = ideaSdkDeps(*artifactBaseNames, subdir = "core")
|
||||
|
||||
fun Project.ideaUltimateSdkCoreDeps(vararg artifactBaseNames: String): ConfigurableFileCollection = ideaUltimateSdkDeps(*artifactBaseNames, subdir = "core")
|
||||
|
||||
fun Project.ideaPluginDeps(vararg artifactBaseNames: String, plugin: String, subdir: String = "lib", optional: Boolean = false): ConfigurableFileCollection =
|
||||
ideaSdkDeps(*artifactBaseNames, subdir = "plugins/$plugin/$subdir", optional = optional)
|
||||
|
||||
fun Project.ideaUltimatePluginDeps(vararg artifactBaseNames: String, plugin: String, subdir: String = "lib"): ConfigurableFileCollection =
|
||||
ideaUltimateSdkDeps(*artifactBaseNames, subdir = "plugins/$plugin/$subdir")
|
||||
|
||||
fun Project.kotlinDep(artifactBaseName: String, version: String): String = "org.jetbrains.kotlin:kotlin-$artifactBaseName:$version"
|
||||
|
||||
fun DependencyHandler.projectDist(name: String): ProjectDependency = project(name, configuration = "distJar").apply { isTransitive = false }
|
||||
@@ -72,15 +62,15 @@ fun DependencyHandler.projectArchives(name: String): ProjectDependency = project
|
||||
fun DependencyHandler.projectClasses(name: String): ProjectDependency = project(name, configuration = "classes-dirs")
|
||||
|
||||
val protobufLiteProject = ":custom-dependencies:protobuf-lite"
|
||||
val protobufRelocatedProject = ":custom-dependencies:protobuf-relocated"
|
||||
fun DependencyHandler.protobufLite(): ProjectDependency =
|
||||
project(protobufLiteProject, configuration = "default").apply { isTransitive = false }
|
||||
val protobufLiteTask = "$protobufLiteProject:prepare"
|
||||
|
||||
fun DependencyHandler.protobufFull(): ProjectDependency =
|
||||
project(protobufLiteProject, configuration = "relocated").apply { isTransitive = false }
|
||||
val protobufFullTask = "$protobufLiteProject:prepare-relocated-protobuf"
|
||||
project(protobufRelocatedProject, configuration = "default").apply { isTransitive = false }
|
||||
|
||||
private fun File.matchMaybeVersionedArtifact(baseName: String) = name.matches(baseName.toMaybeVersionedJarRegex())
|
||||
fun File.matchMaybeVersionedArtifact(baseName: String) = name.matches(baseName.toMaybeVersionedJarRegex())
|
||||
|
||||
private val wildcardsRe = """[^*?]+|(\*)|(\?)""".toRegex()
|
||||
|
||||
@@ -103,8 +93,8 @@ private fun String.toMaybeVersionedJarRegex(): Regex {
|
||||
|
||||
private val jreHome = System.getProperty("java.home")
|
||||
|
||||
fun firstFromJavaHomeThatExists(vararg paths: String): File =
|
||||
fun firstFromJavaHomeThatExists(vararg paths: String): File? =
|
||||
paths.mapNotNull { File(jreHome, it).takeIf { it.exists() } }.firstOrNull()
|
||||
?: throw GradleException("Cannot find under '$jreHome' neither of: ${paths.joinToString()}")
|
||||
|
||||
fun toolsJar(): File = firstFromJavaHomeThatExists("../lib/tools.jar", "../Classes/tools.jar")
|
||||
fun toolsJar(): File? = firstFromJavaHomeThatExists("../lib/tools.jar", "../Classes/tools.jar")
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.DuplicatesStrategy
|
||||
import org.gradle.api.tasks.bundling.Zip
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.task
|
||||
import org.gradle.kotlin.dsl.*
|
||||
@@ -20,7 +18,8 @@ val packagesToRelocate =
|
||||
"org.picocontainer",
|
||||
"org.jline",
|
||||
"gnu",
|
||||
"org.fusesource")
|
||||
"org.fusesource",
|
||||
"kotlinx.coroutines")
|
||||
|
||||
// The shaded compiler "dummy" is used to rewrite dependencies in projects that are used with the embeddable compiler
|
||||
// on the runtime and use some shaded dependencies from the compiler
|
||||
@@ -104,23 +103,22 @@ fun Project.embeddableCompilerDummyForDependenciesRewriting(taskName: String = "
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.rewriteDepsToShadedJar(originalJarTask: Jar, shadowJarTask: Zip, body: Jar.() -> Unit = {}): Jar {
|
||||
val originalFiles by lazy {
|
||||
val jarContents = zipTree(originalJarTask.outputs.files.singleFile).files
|
||||
val basePath = jarContents.find { it.name == "MANIFEST.MF" }?.parentFile?.parentFile ?: throw GradleException("cannot determine the jar root dir")
|
||||
jarContents.map { it.relativeTo(basePath).path }.toSet()
|
||||
fun Project.rewriteDepsToShadedJar(originalJarTask: Jar, shadowJarTask: Jar, body: Jar.() -> Unit = {}): Jar {
|
||||
originalJarTask.apply {
|
||||
classifier = "original"
|
||||
}
|
||||
return task<Jar>("rewrittenDepsJar") {
|
||||
originalJarTask.apply {
|
||||
classifier = "original"
|
||||
}
|
||||
shadowJarTask.apply {
|
||||
dependsOn(originalJarTask)
|
||||
from(originalJarTask)// { include("**") }
|
||||
classifier = "shadow"
|
||||
}
|
||||
dependsOn(shadowJarTask)
|
||||
from(project.zipTree(shadowJarTask.outputs.files.singleFile)) { include { originalFiles.any { originalFile -> it.file.canonicalPath.endsWith(originalFile) } } }
|
||||
|
||||
val compilerDummyJarFile by lazy { configurations.getAt("compilerDummyJar").singleFile }
|
||||
|
||||
return shadowJarTask.apply {
|
||||
dependsOn(originalJarTask)
|
||||
from(originalJarTask)// { include("**") }
|
||||
|
||||
// When Gradle traverses the inputs, reject the shaded compiler JAR,
|
||||
// which leads to the content of that JAR being excluded as well:
|
||||
exclude { it.file == compilerDummyJarFile }
|
||||
|
||||
classifier = null
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
@@ -51,6 +52,12 @@ fun Project.configureInstrumentation() {
|
||||
}
|
||||
}
|
||||
|
||||
val instrumentationClasspathCfg = configurations.create("instrumentationClasspath")
|
||||
|
||||
dependencies {
|
||||
instrumentationClasspathCfg(intellijDep()) { includeJars("javac2", "jdom", "asm-all", "jgoodies-forms") }
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
the<JavaPluginConvention>().sourceSets.all { sourceSetParam ->
|
||||
// This copy will ignore filters, but they are unlikely to be used.
|
||||
@@ -66,6 +73,7 @@ fun Project.configureInstrumentation() {
|
||||
instrumentTask.apply {
|
||||
dependsOn(sourceSetParam.classesTaskName).onlyIf { !classesDirsCopy.isEmpty }
|
||||
sourceSet = sourceSetParam
|
||||
instrumentationClasspath = instrumentationClasspathCfg
|
||||
originalClassesDirs = classesDirsCopy
|
||||
output = instrumentedClassesDir
|
||||
}
|
||||
@@ -88,6 +96,8 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
|
||||
|
||||
var sourceSet: SourceSet? = null
|
||||
|
||||
var instrumentationClasspath: Configuration? = null
|
||||
|
||||
@Input
|
||||
var originalClassesDirs: FileCollection? = null
|
||||
|
||||
@@ -101,9 +111,10 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
|
||||
@TaskAction
|
||||
fun instrumentClasses() {
|
||||
logger.info("input files are: ${originalClassesDirs?.joinToString("; ", transform = { "'${it.name}'${if (it.exists()) "" else " (does not exists)" }"})}")
|
||||
output?.deleteRecursively()
|
||||
copyOriginalClasses()
|
||||
|
||||
val classpath = project.ideaSdkDeps("javac2.jar", "jdom.jar", "asm-all.jar", "jgoodies-forms.jar")
|
||||
val classpath = instrumentationClasspath!!
|
||||
|
||||
ant.withGroovyBuilder {
|
||||
"taskdef"("name" to "instrumentIdeaExtensions",
|
||||
@@ -113,7 +124,7 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
|
||||
}
|
||||
|
||||
logger.info("Compiling forms and instrumenting code with nullability preconditions")
|
||||
val instrumentNotNull = prepareNotNullInstrumenting(classpath)
|
||||
val instrumentNotNull = prepareNotNullInstrumenting(classpath.asPath)
|
||||
instrumentCode(sourceDirs, instrumentNotNull)
|
||||
}
|
||||
|
||||
@@ -124,10 +135,10 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareNotNullInstrumenting(classpath: ConfigurableFileCollection): Boolean {
|
||||
private fun prepareNotNullInstrumenting(classpath: String): Boolean {
|
||||
ant.withGroovyBuilder {
|
||||
"typedef"("name" to "skip",
|
||||
"classpath" to classpath.asPath,
|
||||
"classpath" to classpath,
|
||||
"loaderref" to LOADER_REF,
|
||||
"classname" to FILTER_ANNOTATION_REGEXP_CLASS)
|
||||
}
|
||||
|
||||
147
buildSrc/src/main/kotlin/intellijDependencies.kt
Normal file
147
buildSrc/src/main/kotlin/intellijDependencies.kt
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import java.io.File
|
||||
|
||||
private fun Project.intellijRepoDir() = File("${project.rootDir.absoluteFile}/buildSrc/prepare-deps/intellij-sdk/build/repo")
|
||||
|
||||
fun RepositoryHandler.intellijSdkRepo(project: Project): IvyArtifactRepository = ivy {
|
||||
val baseDir = project.intellijRepoDir()
|
||||
setUrl(baseDir)
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]Ultimate.ivy.xml")
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module].ivy.xml")
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[revision]/intellijUltimate.plugin.[module].ivy.xml")
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[revision]/intellij.plugin.[module].ivy.xml")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]Ultimate/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/intellijUltimate/plugins/[module]/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/intellij/plugins/[module]/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/plugins-[module]/[module]/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]/[artifact].jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]/[artifact](-[revision])(-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/sources/[artifact]-[revision]-[classifier].[ext]")
|
||||
}
|
||||
|
||||
fun Project.intellijDep(module: String = "intellij") = "kotlin.build.custom.deps:$module:${rootProject.extra["versions.intellijSdk"]}"
|
||||
|
||||
fun Project.intellijCoreDep() = intellijDep("intellij-core")
|
||||
|
||||
fun Project.intellijPluginDep(plugin: String) = intellijDep(plugin)
|
||||
|
||||
fun Project.intellijUltimateDep() = intellijDep("intellij")
|
||||
|
||||
fun Project.intellijUltimatePluginDep(plugin: String) = intellijDep(plugin)
|
||||
|
||||
fun ModuleDependency.includeJars(vararg names: String, rootProject: Project? = null) {
|
||||
names.forEach {
|
||||
var baseName = it.removeSuffix(".jar")
|
||||
if (rootProject != null && rootProject.extra.has("ignore.jar.$baseName")) {
|
||||
return@forEach
|
||||
}
|
||||
if (rootProject != null && rootProject.extra.has("versions.jar.$baseName")) {
|
||||
baseName += "-${rootProject.extra["versions.jar.$baseName"]}"
|
||||
}
|
||||
artifact {
|
||||
name = baseName
|
||||
type = "jar"
|
||||
extension = "jar"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ModuleDependency.includeIntellijCoreJarDependencies(project: Project) =
|
||||
includeJars(*(project.rootProject.extra["IntellijCoreDependencies"] as List<String>).toTypedArray(), rootProject = project.rootProject)
|
||||
|
||||
fun ModuleDependency.includeIntellijCoreJarDependencies(project: Project, jarsFilterPredicate: (String) -> Boolean) =
|
||||
includeJars(*(project.rootProject.extra["IntellijCoreDependencies"] as List<String>).filter { jarsFilterPredicate(it) }.toTypedArray(), rootProject = project.rootProject)
|
||||
|
||||
fun Project.isIntellijCommunityAvailable() = !(rootProject.extra["intellijUltimateEnabled"] as Boolean) || rootProject.extra["intellijSeparateSdks"] as Boolean
|
||||
|
||||
fun Project.isIntellijUltimateSdkAvailable() = (rootProject.extra["intellijUltimateEnabled"] as Boolean)
|
||||
|
||||
fun Project.intellijRootDir() =
|
||||
File(intellijRepoDir(), "kotlin.build.custom.deps/${rootProject.extra["versions.intellijSdk"]}/intellij${if (isIntellijCommunityAvailable()) "" else "Ultimate"}")
|
||||
|
||||
fun Project.intellijUltimateRootDir() =
|
||||
if (isIntellijUltimateSdkAvailable())
|
||||
File(intellijRepoDir(), "kotlin.build.custom.deps/${rootProject.extra["versions.intellijSdk"]}/intellijUltimate")
|
||||
else
|
||||
throw GradleException("intellij ultimate SDK is not available")
|
||||
|
||||
fun DependencyHandlerScope.excludeInAndroidStudio(rootProject: Project, block: DependencyHandlerScope.() -> Unit) {
|
||||
if (!rootProject.extra.has("versions.androidStudioRelease")) {
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File, body: JavaExec.() -> Unit): JavaExec {
|
||||
|
||||
return task<JavaExec>(name) {
|
||||
val ideaSandboxConfigDir = File(ideaSandboxDir, "config")
|
||||
|
||||
classpath = the<JavaPluginConvention>().sourceSets["main"].runtimeClasspath
|
||||
|
||||
main = "com.intellij.idea.Main"
|
||||
|
||||
workingDir = File(intellijRootDir(), "bin")
|
||||
|
||||
jvmArgs(
|
||||
"-Xmx1250m",
|
||||
"-XX:ReservedCodeCacheSize=240m",
|
||||
"-XX:+HeapDumpOnOutOfMemoryError",
|
||||
"-ea",
|
||||
"-Didea.is.internal=true",
|
||||
"-Didea.debug.mode=true",
|
||||
"-Didea.system.path=$ideaSandboxDir",
|
||||
"-Didea.config.path=$ideaSandboxConfigDir",
|
||||
"-Dapple.laf.useScreenMenuBar=true",
|
||||
"-Dapple.awt.graphics.UseQuartz=true",
|
||||
"-Dsun.io.useCanonCaches=false",
|
||||
"-Dplugin.path=${ideaPluginDir.parentFile.absolutePath}",
|
||||
"-Dkotlin.internal.mode.enabled=true",
|
||||
"-Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar"
|
||||
)
|
||||
|
||||
if (project.hasProperty("noPCE")) {
|
||||
jvmArgs("-Didea.ProcessCanceledException=disabled")
|
||||
}
|
||||
|
||||
args()
|
||||
|
||||
doFirst {
|
||||
val disabledPluginsFile = File(ideaSandboxConfigDir, "disabled_plugins.txt")
|
||||
val disabledPluginsContents = disabledPluginsFile.takeIf { it.isFile }?.readLines()
|
||||
val filteredContents = disabledPluginsContents?.filterNot { it.contains("org.jetbrains.kotlin") }
|
||||
if (filteredContents != null && filteredContents.size != disabledPluginsContents.size) {
|
||||
with(disabledPluginsFile.printWriter()) {
|
||||
filteredContents.forEach(this::println)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body()
|
||||
}
|
||||
}
|
||||
@@ -10,18 +10,17 @@ dependencies {
|
||||
compile(project(":compiler:backend"))
|
||||
compile(projectTests(":compiler:tests-common"))
|
||||
compile(commonDep("junit:junit"))
|
||||
compile(ideaSdkDeps("openapi"))
|
||||
compileOnly(intellijDep()) { includeJars("openapi") }
|
||||
|
||||
testCompile(project(":compiler:incremental-compilation-impl"))
|
||||
testCompile(project(":core:descriptors"))
|
||||
testCompile(project(":core:descriptors.jvm"))
|
||||
testCompile(project(":compiler:frontend.java"))
|
||||
testCompile(projectTests(":jps-plugin"))
|
||||
testCompile(ideaSdkDeps("jps-model.jar", subdir = "jps"))
|
||||
testCompile(ideaSdkDeps("groovy-all"))
|
||||
testCompile(ideaSdkDeps("idea", "idea_rt"))
|
||||
testCompile(ideaSdkDeps("jps-build-test", subdir = "jps/test"))
|
||||
testCompile(ideaSdkDeps("jps-builders"))
|
||||
testCompile(commonDep("junit:junit"))
|
||||
testCompile(intellijDep()) { includeJars("openapi", "idea", "idea_rt", "groovy-all", "jps-builders", rootProject = rootProject) }
|
||||
testCompile(intellijDep("jps-standalone")) { includeJars("jps-model") }
|
||||
testCompile(intellijDep("jps-build-test"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -152,7 +152,9 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
private fun parseSingleReportInFolder(reportFolder: String): List<TestCase> {
|
||||
val folder = File(reportFolder)
|
||||
val files = folder.listFiles()!!
|
||||
assert(files.size == 1)
|
||||
assert(files.size == 1) {
|
||||
"Expecting one file but ${files.size}: ${files.joinToString { it.name }}"
|
||||
}
|
||||
val reportFile = files[0]
|
||||
|
||||
val dbFactory = DocumentBuilderFactory.newInstance()
|
||||
|
||||
@@ -31,11 +31,14 @@ private val packagePattern = Pattern.compile("(?m)^\\s*package[ |\t]+([\\w|\\.]*
|
||||
|
||||
private val importPattern = Pattern.compile("import[ |\t]([\\w|]*\\.)")
|
||||
|
||||
internal fun genFiles(file: File, fileContent: String, filesHolder: CodegenTestsOnAndroidGenerator.FilesWriter): FqName? {
|
||||
val testFiles = createTestFiles(file, fileContent)
|
||||
if (testFiles.filter { it.name.endsWith(".java") }.isNotEmpty()) {
|
||||
internal fun patchFiles(
|
||||
file: File,
|
||||
testFiles: List<CodegenTestCase.TestFile>,
|
||||
filesHolder: CodegenTestsOnAndroidGenerator.FilesWriter
|
||||
): FqName? {
|
||||
if (testFiles.any { it.name.endsWith(".java") }) {
|
||||
//TODO support java files
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
val ktFiles = testFiles.filter { it.name.endsWith(".kt") }
|
||||
if (ktFiles.isEmpty()) return null
|
||||
@@ -82,16 +85,6 @@ internal fun genFiles(file: File, fileContent: String, filesHolder: CodegenTests
|
||||
return boxFiles.last().newClassId
|
||||
}
|
||||
|
||||
|
||||
private fun createTestFiles(file: File, expectedText: String): List<CodegenTestCase.TestFile> {
|
||||
val files = KotlinTestUtils.createTestFiles(file.name, expectedText, object : KotlinTestUtils.TestFileFactoryNoModules<CodegenTestCase.TestFile>() {
|
||||
override fun create(fileName: String, text: String, directives: Map<String, String>): CodegenTestCase.TestFile {
|
||||
return CodegenTestCase.TestFile(fileName, text)
|
||||
}
|
||||
})
|
||||
return files
|
||||
}
|
||||
|
||||
private fun hasBoxMethod(text: String): Boolean {
|
||||
return text.contains("fun box()")
|
||||
}
|
||||
|
||||
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
* 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.android.tests;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection;
|
||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestFiles;
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils;
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.NameUtils;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.test.*;
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase;
|
||||
import org.jetbrains.kotlin.utils.Printer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Ignore
|
||||
public class CodegenTestsOnAndroidGenerator extends KtUsefulTestCase {
|
||||
|
||||
private final PathManager pathManager;
|
||||
private static final String testClassPackage = "org.jetbrains.kotlin.android.tests";
|
||||
private static final String testClassName = "CodegenTestCaseOnAndroid";
|
||||
private static final String baseTestClassPackage = "org.jetbrains.kotlin.android.tests";
|
||||
private static final String baseTestClassName = "AbstractCodegenTestCaseOnAndroid";
|
||||
private static final String generatorName = "CodegenTestsOnAndroidGenerator";
|
||||
|
||||
private static int MODULE_INDEX = 1;
|
||||
private int WRITED_FILES_COUNT = 0;
|
||||
|
||||
private final List<String> generatedTestNames = Lists.newArrayList();
|
||||
|
||||
public static void generate(PathManager pathManager) throws Throwable {
|
||||
new CodegenTestsOnAndroidGenerator(pathManager).generateOutputFiles();
|
||||
}
|
||||
|
||||
private CodegenTestsOnAndroidGenerator(PathManager pathManager) {
|
||||
this.pathManager = pathManager;
|
||||
}
|
||||
|
||||
private void generateOutputFiles() throws Throwable {
|
||||
prepareAndroidModule();
|
||||
generateAndSave();
|
||||
}
|
||||
|
||||
private void prepareAndroidModule() throws IOException {
|
||||
System.out.println("Copying kotlin-runtime.jar and kotlin-reflect.jar in android module...");
|
||||
copyKotlinRuntimeJars();
|
||||
|
||||
System.out.println("Check \"libs\" folder in tested android module...");
|
||||
File libsFolderInTestedModule = new File(pathManager.getLibsFolderInAndroidTestedModuleTmpFolder());
|
||||
if (!libsFolderInTestedModule.exists()) {
|
||||
libsFolderInTestedModule.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
private void copyKotlinRuntimeJars() throws IOException {
|
||||
FileUtil.copy(
|
||||
ForTestCompileRuntime.runtimeJarForTests(),
|
||||
new File(pathManager.getLibsFolderInAndroidTmpFolder() + "/kotlin-runtime.jar")
|
||||
);
|
||||
FileUtil.copy(
|
||||
ForTestCompileRuntime.reflectJarForTests(),
|
||||
new File(pathManager.getLibsFolderInAndroidTmpFolder() + "/kotlin-reflect.jar")
|
||||
);
|
||||
|
||||
FileUtil.copy(
|
||||
ForTestCompileRuntime.kotlinTestJarForTests(),
|
||||
new File(pathManager.getLibsFolderInAndroidTmpFolder() + "/kotlin-test.jar")
|
||||
);
|
||||
}
|
||||
|
||||
private void generateAndSave() throws Throwable {
|
||||
System.out.println("Generating test files...");
|
||||
StringBuilder out = new StringBuilder();
|
||||
Printer p = new Printer(out);
|
||||
|
||||
p.print(FileUtil.loadFile(new File("license/LICENSE.txt")));
|
||||
p.println("package " + testClassPackage + ";");
|
||||
p.println();
|
||||
p.println("import ", baseTestClassPackage, ".", baseTestClassName, ";");
|
||||
p.println();
|
||||
p.println("/* This class is generated by " + generatorName + ". DO NOT MODIFY MANUALLY */");
|
||||
p.println("public class ", testClassName, " extends ", baseTestClassName, " {");
|
||||
p.pushIndent();
|
||||
|
||||
generateTestMethodsForDirectories(p, new File("compiler/testData/codegen/box"), new File("compiler/testData/codegen/boxInline"));
|
||||
|
||||
p.popIndent();
|
||||
p.println("}");
|
||||
|
||||
String testSourceFilePath =
|
||||
pathManager.getSrcFolderInAndroidTmpFolder() + "/" + testClassPackage.replace(".", "/") + "/" + testClassName + ".java";
|
||||
FileUtil.writeToFile(new File(testSourceFilePath), out.toString());
|
||||
}
|
||||
|
||||
private void generateTestMethodsForDirectories(Printer p, File... dirs) throws IOException {
|
||||
FilesWriter holderMock = new FilesWriter(false, false);
|
||||
FilesWriter holderFull = new FilesWriter(true, false);
|
||||
FilesWriter holderInheritMFP = new FilesWriter(true, true);
|
||||
|
||||
for (File dir : dirs) {
|
||||
File[] files = dir.listFiles();
|
||||
Assert.assertNotNull("Folder with testData is empty: " + dir.getAbsolutePath(), files);
|
||||
processFiles(p, files, holderFull, holderMock, holderInheritMFP);
|
||||
}
|
||||
|
||||
holderFull.writeFilesOnDisk();
|
||||
holderMock.writeFilesOnDisk();
|
||||
holderInheritMFP.writeFilesOnDisk();
|
||||
}
|
||||
|
||||
class FilesWriter {
|
||||
private final boolean isFullJdkAndRuntime;
|
||||
private final boolean inheritMultifileParts;
|
||||
|
||||
public List<KtFile> files = new ArrayList<>();
|
||||
private KotlinCoreEnvironment environment;
|
||||
private Disposable disposable;
|
||||
|
||||
private FilesWriter(boolean isFullJdkAndRuntime, boolean inheritMultifileParts) {
|
||||
this.isFullJdkAndRuntime = isFullJdkAndRuntime;
|
||||
this.inheritMultifileParts = inheritMultifileParts;
|
||||
this.disposable = new TestDisposable();
|
||||
this.environment = createEnvironment(isFullJdkAndRuntime, disposable);
|
||||
}
|
||||
|
||||
private KotlinCoreEnvironment createEnvironment(boolean isFullJdkAndRuntime, @NotNull Disposable disposable) {
|
||||
ConfigurationKind configurationKind = isFullJdkAndRuntime ? ConfigurationKind.ALL : ConfigurationKind.NO_KOTLIN_REFLECT;
|
||||
TestJdkKind testJdkKind = isFullJdkAndRuntime ? TestJdkKind.FULL_JDK : TestJdkKind.MOCK_JDK;
|
||||
CompilerConfiguration configuration =
|
||||
KotlinTestUtils.newConfiguration(configurationKind, testJdkKind, KotlinTestUtils.getAnnotationsJar());
|
||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, "android-module-" + MODULE_INDEX++);
|
||||
if (inheritMultifileParts) {
|
||||
configuration.put(JVMConfigurationKeys.INHERIT_MULTIFILE_PARTS, true);
|
||||
}
|
||||
return KotlinCoreEnvironment.createForTests(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
}
|
||||
|
||||
public boolean shouldWriteFilesOnDisk() {
|
||||
return files.size() > 300;
|
||||
}
|
||||
|
||||
public void writeFilesOnDiskIfNeeded() {
|
||||
if (shouldWriteFilesOnDisk()) {
|
||||
writeFilesOnDisk();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeFilesOnDisk() {
|
||||
writeFiles(files);
|
||||
files = new ArrayList<>();
|
||||
if (disposable != null) {
|
||||
Disposer.dispose(disposable);
|
||||
disposable = new TestDisposable();
|
||||
}
|
||||
environment = createEnvironment(isFullJdkAndRuntime, disposable);
|
||||
}
|
||||
|
||||
public void addFile(String name, String content) {
|
||||
try {
|
||||
files.add(CodegenTestFiles.create(name, content, environment.getProject()).getPsiFile());
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new RuntimeException("Problem during creating file " + name + ": \n" + content, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeFiles(List<KtFile> filesToCompile) {
|
||||
if (filesToCompile.isEmpty()) return;
|
||||
|
||||
//1000 files per folder, each folder would be jared by build.gradle script
|
||||
// We can't create one big jar with all test cause dex has problem with memory on teamcity
|
||||
WRITED_FILES_COUNT += filesToCompile.size();
|
||||
File outputDir = new File(pathManager.getOutputForCompiledFiles(WRITED_FILES_COUNT / 1000));
|
||||
|
||||
System.out.println("Generating " + filesToCompile.size() + " files" +
|
||||
(inheritMultifileParts
|
||||
? " (JVM.INHERIT_MULTIFILE_PARTS)"
|
||||
: isFullJdkAndRuntime ? " (full jdk and runtime)" : "") + " into " + outputDir.getName() + "...");
|
||||
OutputFileCollection outputFiles;
|
||||
GenerationState state = null;
|
||||
try {
|
||||
state = GenerationUtils.compileFiles(filesToCompile, environment);
|
||||
outputFiles = state.getFactory();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
if (state != null) {
|
||||
state.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
if (!outputDir.exists()) {
|
||||
outputDir.mkdirs();
|
||||
}
|
||||
Assert.assertTrue("Cannot create directory for compiled files", outputDir.exists());
|
||||
|
||||
OutputUtilsKt.writeAllTo(outputFiles, outputDir);
|
||||
}
|
||||
}
|
||||
|
||||
private void processFiles(
|
||||
@NotNull Printer printer,
|
||||
@NotNull File[] files,
|
||||
@NotNull FilesWriter holderFull,
|
||||
@NotNull FilesWriter holderMock,
|
||||
@NotNull FilesWriter holderInheritMFP
|
||||
) throws IOException {
|
||||
holderFull.writeFilesOnDiskIfNeeded();
|
||||
holderMock.writeFilesOnDiskIfNeeded();
|
||||
holderInheritMFP.writeFilesOnDiskIfNeeded();
|
||||
|
||||
for (File file : files) {
|
||||
if (SpecialFiles.getExcludedFiles().contains(file.getName())) {
|
||||
continue;
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
File[] listFiles = file.listFiles();
|
||||
if (listFiles != null) {
|
||||
processFiles(printer, listFiles, holderFull, holderMock, holderInheritMFP);
|
||||
}
|
||||
}
|
||||
else if (!FileUtilRt.getExtension(file.getName()).equals(KotlinFileType.INSTANCE.getDefaultExtension())) {
|
||||
// skip non kotlin files
|
||||
}
|
||||
else {
|
||||
String fullFileText = FileUtil.loadFile(file, true);
|
||||
|
||||
if (!InTextDirectivesUtils.isPassingTarget(TargetBackend.JVM, file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO: support LANGUAGE_VERSION
|
||||
if (InTextDirectivesUtils.isDirectiveDefined(fullFileText, "LANGUAGE_VERSION:")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO: support multifile facades
|
||||
//TODO: support multifile facades hierarchies
|
||||
if (hasBoxMethod(fullFileText)) {
|
||||
FilesWriter filesHolder = InTextDirectivesUtils.isDirectiveDefined(fullFileText, "FULL_JDK") ||
|
||||
InTextDirectivesUtils.isDirectiveDefined(fullFileText, "WITH_RUNTIME") ||
|
||||
InTextDirectivesUtils.isDirectiveDefined(fullFileText, "WITH_REFLECT") ? holderFull : holderMock;
|
||||
filesHolder = fullFileText.contains("+JVM.INHERIT_MULTIFILE_PARTS") ? holderInheritMFP : filesHolder;
|
||||
|
||||
FqName classWithBoxMethod = AndroidTestGeneratorKt.genFiles(file, fullFileText, filesHolder);
|
||||
if (classWithBoxMethod == null)
|
||||
continue;
|
||||
|
||||
String generatedTestName = generateTestName(file.getName());
|
||||
generateTestMethod(printer, generatedTestName, classWithBoxMethod.asString(), StringUtil.escapeStringCharacters(file.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static boolean hasBoxMethod(String text) {
|
||||
return text.contains("fun box()");
|
||||
}
|
||||
|
||||
private static void generateTestMethod(Printer p, String testName, String className, String filePath) {
|
||||
p.println("public void test" + testName + "() throws Exception {");
|
||||
p.pushIndent();
|
||||
p.println("invokeBoxMethod(" + className + ".class, \"" + filePath + "\", \"OK\");");
|
||||
p.popIndent();
|
||||
p.println("}");
|
||||
p.println();
|
||||
}
|
||||
|
||||
private String generateTestName(String fileName) {
|
||||
String result = NameUtils.sanitizeAsJavaIdentifier(FileUtil.getNameWithoutExtension(StringUtil.capitalize(fileName)));
|
||||
|
||||
int i = 0;
|
||||
while (generatedTestNames.contains(result)) {
|
||||
result += "_" + i++;
|
||||
}
|
||||
generatedTestNames.add(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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.android.tests
|
||||
|
||||
import com.google.common.collect.Lists
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
|
||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAllTo
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestCase
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestFiles
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.*
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.junit.Assert
|
||||
import org.junit.Ignore
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
data class ConfigurationKey(val kind: ConfigurationKind, val jdkKind: TestJdkKind, val configuration: String)
|
||||
|
||||
@Ignore
|
||||
class CodegenTestsOnAndroidGenerator private constructor(private val pathManager: PathManager) : CodegenTestCase() {
|
||||
private var writtenFilesCount = 0
|
||||
|
||||
private var currentModuleIndex = 1
|
||||
|
||||
private val generatedTestNames = Lists.newArrayList<String>()
|
||||
|
||||
private fun generateOutputFiles() {
|
||||
prepareAndroidModule()
|
||||
generateAndSave()
|
||||
}
|
||||
|
||||
private fun prepareAndroidModule() {
|
||||
println("Copying kotlin-runtime.jar and kotlin-reflect.jar in android module...")
|
||||
copyKotlinRuntimeJars()
|
||||
|
||||
println("Check 'libs' folder in tested android module...")
|
||||
val libsFolderInTestedModule = File(pathManager.libsFolderInAndroidTestedModuleTmpFolder)
|
||||
if (!libsFolderInTestedModule.exists()) {
|
||||
libsFolderInTestedModule.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyKotlinRuntimeJars() {
|
||||
FileUtil.copy(
|
||||
ForTestCompileRuntime.runtimeJarForTests(),
|
||||
File(pathManager.libsFolderInAndroidTmpFolder + "/kotlin-runtime.jar")
|
||||
)
|
||||
FileUtil.copy(
|
||||
ForTestCompileRuntime.reflectJarForTests(),
|
||||
File(pathManager.libsFolderInAndroidTmpFolder + "/kotlin-reflect.jar")
|
||||
)
|
||||
|
||||
FileUtil.copy(
|
||||
ForTestCompileRuntime.kotlinTestJarForTests(),
|
||||
File(pathManager.libsFolderInAndroidTmpFolder + "/kotlin-test.jar")
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateAndSave() {
|
||||
println("Generating test files...")
|
||||
val testSourceFilePath =
|
||||
pathManager.srcFolderInAndroidTmpFolder + "/" + testClassPackage.replace(".", "/") + "/" + testClassName + ".java"
|
||||
|
||||
FileWriter(File(testSourceFilePath)).use {
|
||||
val p = Printer(it)
|
||||
p.print(FileUtil.loadFile(File("license/LICENSE.txt")))
|
||||
p.println(
|
||||
"""package $testClassPackage;
|
||||
|
|
||||
|import $baseTestClassPackage.$baseTestClassName;
|
||||
|
|
||||
|/* This class is generated by $generatorName. DO NOT MODIFY MANUALLY */
|
||||
|public class $testClassName extends $baseTestClassName {
|
||||
|
|
||||
""".trimMargin()
|
||||
)
|
||||
p.pushIndent()
|
||||
|
||||
generateTestMethodsForDirectories(p, File("compiler/testData/codegen/box"), File("compiler/testData/codegen/boxInline"))
|
||||
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTestMethodsForDirectories(p: Printer, vararg dirs: File) {
|
||||
val holders = mutableMapOf<ConfigurationKey, FilesWriter>()
|
||||
|
||||
for (dir in dirs) {
|
||||
val files = dir.listFiles() ?: error("Folder with testData is empty: ${dir.absolutePath}")
|
||||
processFiles(p, files, holders)
|
||||
}
|
||||
|
||||
holders.values.forEach {
|
||||
it.writeFilesOnDisk()
|
||||
}
|
||||
}
|
||||
|
||||
internal inner class FilesWriter(
|
||||
private val configuration: CompilerConfiguration
|
||||
) {
|
||||
private val rawFiles: MutableList<Pair<String, String>> = ArrayList()
|
||||
|
||||
private fun shouldWriteFilesOnDisk(): Boolean = rawFiles.size > 300
|
||||
|
||||
fun writeFilesOnDiskIfNeeded() {
|
||||
if (shouldWriteFilesOnDisk()) {
|
||||
writeFilesOnDisk()
|
||||
}
|
||||
}
|
||||
|
||||
fun writeFilesOnDisk() {
|
||||
val disposable = TestDisposable()
|
||||
|
||||
val environment = KotlinCoreEnvironment.createForTests(
|
||||
disposable,
|
||||
configuration.copy().apply { put(CommonConfigurationKeys.MODULE_NAME, "android-module-" + currentModuleIndex++) },
|
||||
EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||
)
|
||||
|
||||
writeFiles(
|
||||
rawFiles.map {
|
||||
CodegenTestFiles.create(it.first, it.second, environment.project).psiFile
|
||||
}, environment
|
||||
)
|
||||
Disposer.dispose(disposable)
|
||||
rawFiles.clear()
|
||||
}
|
||||
|
||||
fun addFile(name: String, content: String) {
|
||||
rawFiles.add(name to content)
|
||||
}
|
||||
|
||||
private fun writeFiles(filesToCompile: List<KtFile>, environment: KotlinCoreEnvironment) {
|
||||
if (filesToCompile.isEmpty()) return
|
||||
|
||||
//1000 files per folder, each folder would be jared by build.gradle script
|
||||
// We can't create one big jar with all test cause dex has problem with memory on teamcity
|
||||
writtenFilesCount += filesToCompile.size
|
||||
val outputDir = File(pathManager.getOutputForCompiledFiles(writtenFilesCount / 1000))
|
||||
|
||||
println("Generating ${filesToCompile.size} files into ${outputDir.name}, configuration: '${environment.configuration}'...")
|
||||
|
||||
val outputFiles = GenerationUtils.compileFiles(filesToCompile, environment).run { destroy(); factory }
|
||||
|
||||
if (!outputDir.exists()) {
|
||||
outputDir.mkdirs()
|
||||
}
|
||||
Assert.assertTrue("Cannot create directory for compiled files", outputDir.exists())
|
||||
|
||||
outputFiles.writeAllTo(outputDir)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun processFiles(
|
||||
printer: Printer,
|
||||
files: Array<File>,
|
||||
holders: MutableMap<ConfigurationKey, FilesWriter>
|
||||
) {
|
||||
holders.values.forEach {
|
||||
it.writeFilesOnDiskIfNeeded()
|
||||
}
|
||||
|
||||
for (file in files) {
|
||||
if (SpecialFiles.getExcludedFiles().contains(file.name)) {
|
||||
continue
|
||||
}
|
||||
if (file.isDirectory) {
|
||||
val listFiles = file.listFiles()
|
||||
if (listFiles != null) {
|
||||
processFiles(printer, listFiles, holders)
|
||||
}
|
||||
} else if (FileUtilRt.getExtension(file.name) != KotlinFileType.EXTENSION) {
|
||||
// skip non kotlin files
|
||||
} else {
|
||||
if (!InTextDirectivesUtils.isPassingTarget(TargetBackend.JVM, file)) {
|
||||
continue
|
||||
}
|
||||
|
||||
val fullFileText = FileUtil.loadFile(file, true)
|
||||
//TODO support JvmPackageName
|
||||
if (fullFileText.contains("@file:JvmPackageName(")) continue
|
||||
|
||||
if (hasBoxMethod(fullFileText)) {
|
||||
val testFiles = createTestFiles(file, fullFileText)
|
||||
val kind = extractConfigurationKind(testFiles)
|
||||
val jdkKind = getJdkKind(testFiles)
|
||||
val keyConfiguration = CompilerConfiguration()
|
||||
updateConfigurationByDirectivesInTestFiles(testFiles, keyConfiguration)
|
||||
|
||||
val key = ConfigurationKey(kind, jdkKind, keyConfiguration.toString())
|
||||
val filesHolder = holders.getOrPut(key) {
|
||||
FilesWriter(KotlinTestUtils.newConfiguration(kind, jdkKind, KotlinTestUtils.getAnnotationsJar()).apply {
|
||||
println("Creating new configuration by $key")
|
||||
updateConfigurationByDirectivesInTestFiles(testFiles, this)
|
||||
})
|
||||
}
|
||||
|
||||
val classWithBoxMethod = patchFiles(file, testFiles, filesHolder) ?: continue
|
||||
|
||||
val generatedTestName = generateTestName(file.name)
|
||||
generateTestMethod(
|
||||
printer,
|
||||
generatedTestName,
|
||||
classWithBoxMethod.asString(),
|
||||
StringUtil.escapeStringCharacters(file.path)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTestFiles(file: File, expectedText: String): List<CodegenTestCase.TestFile> =
|
||||
KotlinTestUtils.createTestFiles(
|
||||
file.name,
|
||||
expectedText,
|
||||
object : KotlinTestUtils.TestFileFactoryNoModules<CodegenTestCase.TestFile>() {
|
||||
override fun create(fileName: String, text: String, directives: Map<String, String>): CodegenTestCase.TestFile {
|
||||
return CodegenTestCase.TestFile(fileName, text)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
private fun generateTestName(fileName: String): String {
|
||||
var result = NameUtils.sanitizeAsJavaIdentifier(FileUtil.getNameWithoutExtension(StringUtil.capitalize(fileName)))
|
||||
|
||||
var i = 0
|
||||
while (generatedTestNames.contains(result)) {
|
||||
result += "_" + i++
|
||||
}
|
||||
generatedTestNames.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val testClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
private const val testClassName = "CodegenTestCaseOnAndroid"
|
||||
private const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
private const val baseTestClassName = "AbstractCodegenTestCaseOnAndroid"
|
||||
private const val generatorName = "CodegenTestsOnAndroidGenerator"
|
||||
|
||||
|
||||
@JvmStatic
|
||||
@Throws(Throwable::class)
|
||||
fun generate(pathManager: PathManager) {
|
||||
CodegenTestsOnAndroidGenerator(pathManager).generateOutputFiles()
|
||||
}
|
||||
|
||||
|
||||
private fun hasBoxMethod(text: String): Boolean {
|
||||
return text.contains("fun box()")
|
||||
}
|
||||
|
||||
private fun generateTestMethod(p: Printer, testName: String, className: String, filePath: String) {
|
||||
p.println("public void test$testName() throws Exception {")
|
||||
p.pushIndent()
|
||||
p.println("invokeBoxMethod($className.class, \"$filePath\", \"OK\");")
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
p.println()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,7 @@ public class SpecialFiles {
|
||||
excludedFiles.add("enumKClassAnnotation.kt");
|
||||
excludedFiles.add("primitivesAndArrays.kt");
|
||||
excludedFiles.add("getDelegateWithoutReflection.kt");
|
||||
excludedFiles.add("parameterAnnotationInDefaultImpls.kt");
|
||||
|
||||
// Reflection is used to check full class name
|
||||
excludedFiles.add("native");
|
||||
@@ -127,9 +128,8 @@ public class SpecialFiles {
|
||||
//wrong function resolution after package renaming
|
||||
excludedFiles.add("apiVersionAtLeast1.kt");
|
||||
|
||||
//special flags
|
||||
excludedFiles.add("inlineFunInConstructorCallWithEnabledNormalization.kt");
|
||||
excludedFiles.add("kt9532_lv10.kt");
|
||||
//special symbols in names
|
||||
excludedFiles.add("nameWithWhitespace.kt");
|
||||
}
|
||||
|
||||
private SpecialFiles() {
|
||||
|
||||
@@ -9,6 +9,7 @@ dependencies {
|
||||
compile(project(":compiler:util"))
|
||||
compile(project(":compiler:frontend"))
|
||||
compile(project(":compiler:ir.tree"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -11,6 +11,8 @@ dependencies {
|
||||
compile(project(":compiler:ir.tree"))
|
||||
compile(project(":compiler:ir.psi2ir"))
|
||||
compile(project(":compiler:serialization"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeJars("annotations", "asm-all", "trove4j", "guava", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -45,7 +45,7 @@ public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDe
|
||||
this.nameSuffix = nameSuffix;
|
||||
|
||||
initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()),
|
||||
descriptor instanceof ConstructorDescriptor || CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)
|
||||
descriptor instanceof ConstructorDescriptor || CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)
|
||||
? null
|
||||
: descriptor.getDispatchReceiverParameter(),
|
||||
copyTypeParameters(descriptor),
|
||||
|
||||
@@ -47,7 +47,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
||||
) {
|
||||
this(property, property.getType(), DescriptorUtils.getReceiverParameterType(property.getExtensionReceiverParameter()),
|
||||
/* dispatchReceiverParameter = */
|
||||
CodegenUtilKt.isJvmStaticInObjectOrClass(property) ? null : property.getDispatchReceiverParameter(),
|
||||
CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(property) ? null : property.getDispatchReceiverParameter(),
|
||||
containingDeclaration, superCallTarget, nameSuffix,
|
||||
getterAccessorRequired, setterAccessorRequired);
|
||||
}
|
||||
|
||||
@@ -370,8 +370,9 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
@Override
|
||||
public Void visitEnumValue(EnumValue value, Void data) {
|
||||
String propertyName = value.getValue().getName().asString();
|
||||
annotationVisitor.visitEnum(name, typeMapper.mapType(value.getType()).getDescriptor(), propertyName);
|
||||
String enumClassInternalName = AsmUtil.asmTypeByClassId(value.getEnumClassId()).getDescriptor();
|
||||
String enumEntryName = value.getEnumEntryName().asString();
|
||||
annotationVisitor.visitEnum(name, enumClassInternalName, enumEntryName);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -437,7 +438,7 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Set<ElementType> getJavaTargetList(ClassDescriptor descriptor) {
|
||||
private static Set<ElementType> getJavaTargetList(ClassDescriptor descriptor) {
|
||||
AnnotationDescriptor targetAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Target.class.getName()));
|
||||
if (targetAnnotation != null) {
|
||||
Collection<ConstantValue<?>> valueArguments = targetAnnotation.getAllValueArguments().values();
|
||||
@@ -448,12 +449,9 @@ public abstract class AnnotationCodegen {
|
||||
Set<ElementType> result = EnumSet.noneOf(ElementType.class);
|
||||
for (ConstantValue<?> value : values) {
|
||||
if (value instanceof EnumValue) {
|
||||
ClassDescriptor enumEntry = ((EnumValue) value).getValue();
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
|
||||
if (classObjectType != null) {
|
||||
if ("java/lang/annotation/ElementType".equals(typeMapper.mapType(classObjectType).getInternalName())) {
|
||||
result.add(ElementType.valueOf(enumEntry.getName().asString()));
|
||||
}
|
||||
FqName enumClassFqName = ((EnumValue) value).getEnumClassId().asSingleFqName();
|
||||
if (ElementType.class.getName().equals(enumClassFqName.asString())) {
|
||||
result.add(ElementType.valueOf(((EnumValue) value).getEnumEntryName().asString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,21 +463,18 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) {
|
||||
private static RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) {
|
||||
KotlinRetention retention = DescriptorUtilsKt.getAnnotationRetention(descriptor);
|
||||
if (retention != null) {
|
||||
return annotationRetentionMap.get(retention);
|
||||
}
|
||||
AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName()));
|
||||
if (retentionAnnotation != null) {
|
||||
ConstantValue<?> compileTimeConstant = CollectionsKt.firstOrNull(retentionAnnotation.getAllValueArguments().values());
|
||||
if (compileTimeConstant instanceof EnumValue) {
|
||||
ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue();
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
|
||||
if (classObjectType != null) {
|
||||
if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
|
||||
return RetentionPolicy.valueOf(enumEntry.getName().asString());
|
||||
}
|
||||
ConstantValue<?> value = CollectionsKt.firstOrNull(retentionAnnotation.getAllValueArguments().values());
|
||||
if (value instanceof EnumValue) {
|
||||
FqName enumClassFqName = ((EnumValue) value).getEnumClassId().asSingleFqName();
|
||||
if (RetentionPolicy.class.getName().equals(enumClassFqName.asString())) {
|
||||
return RetentionPolicy.valueOf(((EnumValue) value).getEnumEntryName().asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.codegen.serialization.JvmStringTable;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.config.JvmTarget;
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
@@ -194,7 +193,7 @@ public class AsmUtil {
|
||||
public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) {
|
||||
return isStaticKind(kind) ||
|
||||
KotlinTypeMapper.isStaticAccessor(functionDescriptor) ||
|
||||
CodegenUtilKt.isJvmStaticInObjectOrClass(functionDescriptor);
|
||||
CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
|
||||
}
|
||||
|
||||
public static boolean isStaticKind(OwnerKind kind) {
|
||||
@@ -781,7 +780,7 @@ public class AsmUtil {
|
||||
public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration();
|
||||
return propertyDescriptor.isConst()
|
||||
&& isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration())
|
||||
&& isCompanionObject(propertyContainer) && isJvmInterface(propertyContainer.getContainingDeclaration())
|
||||
&& getVisibilityForBackingField(propertyDescriptor, false) == ACC_PUBLIC;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public class CallReceiver extends StackValue {
|
||||
|
||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||
|
||||
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
|
||||
if (CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)) {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,19 +16,85 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.google.common.collect.Sets
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
interface CodegenFactory {
|
||||
fun generateModule(state: GenerationState, files: Collection<KtFile?>, errorHandler: CompilationErrorHandler)
|
||||
fun createPackageCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry): PackageCodegen
|
||||
fun createMultifileClassCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry): MultifileClassCodegen
|
||||
|
||||
companion object {
|
||||
fun doCheckCancelled(state: GenerationState) {
|
||||
if (state.classBuilderMode.generateBodies) {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DefaultCodegenFactory : CodegenFactory {
|
||||
override fun generateModule(state: GenerationState, files: Collection<KtFile?>, errorHandler: CompilationErrorHandler) {
|
||||
val filesInPackages = MultiMap<FqName, KtFile>()
|
||||
val filesInMultifileClasses = MultiMap<FqName, KtFile>()
|
||||
|
||||
for (file in files) {
|
||||
if (file == null) throw IllegalArgumentException("A null file given for compilation")
|
||||
|
||||
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file)
|
||||
|
||||
if (fileClassInfo.withJvmMultifileClass) {
|
||||
filesInMultifileClasses.putValue(fileClassInfo.facadeClassFqName, file)
|
||||
}
|
||||
else {
|
||||
filesInPackages.putValue(file.packageFqName, file)
|
||||
}
|
||||
}
|
||||
|
||||
val obsoleteMultifileClasses = HashSet(state.obsoleteMultifileClasses)
|
||||
for (multifileClassFqName in filesInMultifileClasses.keySet() + obsoleteMultifileClasses) {
|
||||
CodegenFactory.doCheckCancelled(state)
|
||||
generateMultifileClass(state, multifileClassFqName, filesInMultifileClasses.get(multifileClassFqName), errorHandler)
|
||||
}
|
||||
|
||||
val packagesWithObsoleteParts = HashSet(state.packagesWithObsoleteParts)
|
||||
for (packageFqName in packagesWithObsoleteParts + filesInPackages.keySet()) {
|
||||
CodegenFactory.doCheckCancelled(state)
|
||||
generatePackage(state, packageFqName, filesInPackages.get(packageFqName), errorHandler)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPackageCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry) =
|
||||
PackageCodegenImpl(state, files, fqName, registry)
|
||||
|
||||
override fun createMultifileClassCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName, registry: PackagePartRegistry) =
|
||||
MultifileClassCodegenImpl(state, files, fqName, registry)
|
||||
|
||||
private fun generateMultifileClass(
|
||||
state: GenerationState,
|
||||
multifileClassFqName: FqName,
|
||||
files: Collection<KtFile>,
|
||||
handler: CompilationErrorHandler
|
||||
) {
|
||||
val codegen = state.factory.forMultifileClass(multifileClassFqName, files)
|
||||
codegen.generate(handler)
|
||||
}
|
||||
|
||||
fun generatePackage(
|
||||
state: GenerationState,
|
||||
packageFqName: FqName,
|
||||
jetFiles: Collection<KtFile>,
|
||||
errorHandler: CompilationErrorHandler
|
||||
) {
|
||||
// We do not really generate package class, but use old package fqName to identify package in module-info.
|
||||
//FqName packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
|
||||
val codegen = state.factory.forPackage(packageFqName, jetFiles)
|
||||
codegen.generate(errorHandler)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. 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;
|
||||
@@ -19,14 +8,22 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.util.ExceptionUtilKt;
|
||||
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
|
||||
|
||||
public class CompilationException extends RuntimeException {
|
||||
public class CompilationException extends KotlinExceptionWithAttachments {
|
||||
private final PsiElement element;
|
||||
|
||||
public CompilationException(@NotNull String message, @Nullable Throwable cause, @Nullable PsiElement element) {
|
||||
super(ExceptionUtilKt.getExceptionMessage("Back-end (JVM)", message, cause, element), cause);
|
||||
super(ExceptionUtilKt.getExceptionMessage("Back-end (JVM)", message, cause,
|
||||
element == null ? null : DiagnosticUtils.atLocation(element)),
|
||||
cause);
|
||||
this.element = element;
|
||||
|
||||
if (element != null) {
|
||||
withAttachment("element.kt", element.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,21 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. 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
|
||||
|
||||
import com.intellij.openapi.diagnostic.Attachment
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
@@ -23,7 +13,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
object ExceptionLogger {
|
||||
@JvmStatic
|
||||
fun logDescriptorNotFound(problemDescription: String, psi: PsiElement): AssertionError {
|
||||
LOG.error(problemDescription, psi.getElementTextWithContext())
|
||||
LOG.error(problemDescription, Attachment("psi.kt", psi.getElementTextWithContext()))
|
||||
throw AssertionError(problemDescription)
|
||||
}
|
||||
|
||||
|
||||
@@ -2324,6 +2324,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||
|
||||
if (isSuspendCall) {
|
||||
addReturnsUnitMarkerIfNecessary(v, resolvedCall);
|
||||
|
||||
addSuspendMarker(v, false);
|
||||
addInlineMarker(v, false);
|
||||
}
|
||||
@@ -2525,8 +2527,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
else if (receiverDescriptor instanceof ScriptDescriptor) {
|
||||
return generateScriptReceiver
|
||||
((ScriptDescriptor) receiverDescriptor);
|
||||
return generateScriptReceiver((ScriptDescriptor) receiverDescriptor);
|
||||
}
|
||||
else {
|
||||
return StackValue.thisOrOuter(this, receiverDescriptor, isSuper,
|
||||
@@ -2630,7 +2631,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
if (thisOrOuterClass.equals(context.getThisDescriptor()) &&
|
||||
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getFunctionDescriptor())) {
|
||||
!CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(context.getFunctionDescriptor())) {
|
||||
return StackValue.local(0, typeMapper.mapType(thisOrOuterClass));
|
||||
}
|
||||
else if (shouldGenerateSingletonAsThisOrOuterFromContext(thisOrOuterClass)) {
|
||||
|
||||
@@ -58,6 +58,16 @@ public class FieldInfo {
|
||||
return new FieldInfo(owner, fieldType, fieldName, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FieldInfo createForHiddenField(
|
||||
@NotNull Type owner,
|
||||
@NotNull Type fieldType,
|
||||
@NotNull String fieldName,
|
||||
@NotNull boolean isStatic
|
||||
) {
|
||||
return new FieldInfo(owner, fieldType, fieldName, isStatic);
|
||||
}
|
||||
|
||||
private final Type fieldType;
|
||||
private final Type ownerType;
|
||||
private final String fieldName;
|
||||
|
||||
@@ -223,9 +223,8 @@ public class FunctionCodegen {
|
||||
|
||||
generateMethodAnnotations(functionDescriptor, asmMethod, mv);
|
||||
|
||||
JvmMethodSignature signature = typeMapper.mapSignatureSkipGeneric(functionDescriptor);
|
||||
generateParameterAnnotations(functionDescriptor, mv, signature);
|
||||
GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, signature, state, (flags & ACC_SYNTHETIC) != 0);
|
||||
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
|
||||
GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0);
|
||||
|
||||
generateBridges(functionDescriptor);
|
||||
|
||||
@@ -243,6 +242,7 @@ public class FunctionCodegen {
|
||||
functionDescriptor.isSuspend() &&
|
||||
functionDescriptor.getModality() != Modality.ABSTRACT && isOverridable(functionDescriptor) &&
|
||||
!isInterface(functionDescriptor.getContainingDeclaration()) &&
|
||||
!(functionDescriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor) &&
|
||||
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
||||
|
||||
if (isOpenSuspendInClass) {
|
||||
@@ -558,7 +558,7 @@ public class FunctionCodegen {
|
||||
mv.visitLabel(methodEntry);
|
||||
context.setMethodStartLabel(methodEntry);
|
||||
|
||||
if (!KotlinTypeMapper.isAccessor(functionDescriptor)) {
|
||||
if (!strategy.skipNotNullAssertionsForParameters()) {
|
||||
genNotNullAssertionsForParameters(new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
|
||||
}
|
||||
|
||||
@@ -1383,6 +1383,11 @@ public class FunctionCodegen {
|
||||
|
||||
iv.areturn(delegateMethod.getReturnType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipNotNullAssertionsForParameters() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ public abstract class FunctionGenerationStrategy {
|
||||
@NotNull MemberCodegen<?> parentCodegen
|
||||
);
|
||||
|
||||
public abstract boolean skipNotNullAssertionsForParameters();
|
||||
|
||||
public MethodVisitor wrapMethodVisitor(@NotNull MethodVisitor mv, int access, @NotNull String name, @NotNull String desc) {
|
||||
return mv;
|
||||
}
|
||||
@@ -76,6 +78,12 @@ public abstract class FunctionGenerationStrategy {
|
||||
doGenerateBody(codegen, signature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipNotNullAssertionsForParameters() {
|
||||
// Assume the strategy injects non-null checks for parameters by default
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,8 @@ import org.jetbrains.kotlin.resolve.DelegationResolver;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
@@ -64,7 +65,10 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
@@ -671,6 +675,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
iv.areturn(componentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipNotNullAssertionsForParameters() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -719,6 +728,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.areturn(thisDescriptorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipNotNullAssertionsForParameters() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void pushCapturedFieldsOnStack(InstructionAdapter iv, MutableClosure closure) {
|
||||
ClassDescriptor captureThis = closure.getCaptureThis();
|
||||
if (captureThis != null) {
|
||||
@@ -964,7 +978,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generatePrimaryConstructor(DelegationFieldsInfo delegationFieldsInfo) {
|
||||
if (isInterface(descriptor) || isAnnotationClass(descriptor)) return;
|
||||
if (isJvmInterface(descriptor)) return;
|
||||
|
||||
ClassConstructorDescriptor constructorDescriptor = descriptor.getUnsubstitutedPrimaryConstructor();
|
||||
if (constructorDescriptor == null) return;
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.*;
|
||||
@@ -57,6 +58,7 @@ import static org.jetbrains.kotlin.descriptors.ClassKind.INTERFACE;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.ABSTRACT;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.DELEGATED_PROPERTY_CALL;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
|
||||
public class JvmCodegenUtil {
|
||||
@@ -330,4 +332,10 @@ public class JvmCodegenUtil {
|
||||
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public static boolean isCompanionObjectInInterfaceNotIntrinsic(@NotNull DeclarationDescriptor companionObject) {
|
||||
return isCompanionObject(companionObject) &&
|
||||
isJvmInterface(companionObject.getContainingDeclaration()) &&
|
||||
!JvmAbi.isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ class JvmStaticInCompanionObjectGenerator(
|
||||
Synthetic(originElement, staticFunctionDescriptor),
|
||||
staticFunctionDescriptor,
|
||||
object : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
override fun skipNotNullAssertionsForParameters(): Boolean = true
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
val iv = codegen.v
|
||||
val classDescriptor = descriptor.containingDeclaration as ClassDescriptor
|
||||
|
||||
@@ -16,19 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import kotlin.collections.SetsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class KotlinCodegenFacade {
|
||||
|
||||
@@ -50,64 +44,19 @@ public class KotlinCodegenFacade {
|
||||
@NotNull GenerationState state,
|
||||
@NotNull CompilationErrorHandler errorHandler
|
||||
) {
|
||||
MultiMap<FqName, KtFile> filesInPackages = new MultiMap<>();
|
||||
MultiMap<FqName, KtFile> filesInMultifileClasses = new MultiMap<>();
|
||||
state.getCodegenFactory().generateModule(state, files, errorHandler);
|
||||
|
||||
for (KtFile file : files) {
|
||||
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
|
||||
|
||||
JvmFileClassInfo fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file);
|
||||
|
||||
if (fileClassInfo.getWithJvmMultifileClass()) {
|
||||
filesInMultifileClasses.putValue(fileClassInfo.getFacadeClassFqName(), file);
|
||||
}
|
||||
else {
|
||||
filesInPackages.putValue(file.getPackageFqName(), file);
|
||||
}
|
||||
}
|
||||
|
||||
Set<FqName> obsoleteMultifileClasses = new HashSet<>(state.getObsoleteMultifileClasses());
|
||||
for (FqName multifileClassFqName : SetsKt.plus(filesInMultifileClasses.keySet(), obsoleteMultifileClasses)) {
|
||||
doCheckCancelled(state);
|
||||
generateMultifileClass(state, multifileClassFqName, filesInMultifileClasses.get(multifileClassFqName), errorHandler);
|
||||
}
|
||||
|
||||
Set<FqName> packagesWithObsoleteParts = new HashSet<>(state.getPackagesWithObsoleteParts());
|
||||
for (FqName packageFqName : SetsKt.plus(packagesWithObsoleteParts, filesInPackages.keySet())) {
|
||||
doCheckCancelled(state);
|
||||
generatePackage(state, packageFqName, filesInPackages.get(packageFqName), errorHandler);
|
||||
}
|
||||
|
||||
doCheckCancelled(state);
|
||||
CodegenFactory.Companion.doCheckCancelled(state);
|
||||
state.getFactory().done();
|
||||
}
|
||||
|
||||
private static void doCheckCancelled(GenerationState state) {
|
||||
if (state.getClassBuilderMode().generateBodies) {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
}
|
||||
}
|
||||
|
||||
public static void generatePackage(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull FqName packageFqName,
|
||||
@NotNull Collection<KtFile> jetFiles,
|
||||
@NotNull CompilationErrorHandler errorHandler
|
||||
) {
|
||||
// We do not really generate package class, but use old package fqName to identify package in module-info.
|
||||
//FqName packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
|
||||
PackageCodegen codegen = state.getFactory().forPackage(packageFqName, jetFiles);
|
||||
codegen.generate(errorHandler);
|
||||
}
|
||||
|
||||
private static void generateMultifileClass(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull FqName multifileClassFqName,
|
||||
@NotNull Collection<KtFile> files,
|
||||
@NotNull CompilationErrorHandler handler
|
||||
) {
|
||||
MultifileClassCodegen codegen = state.getFactory().forMultifileClass(multifileClassFqName, files);
|
||||
codegen.generate(handler);
|
||||
DefaultCodegenFactory.INSTANCE.generatePackage(state, packageFqName, jetFiles, errorHandler);
|
||||
}
|
||||
|
||||
private KotlinCodegenFacade() {}
|
||||
|
||||
@@ -719,6 +719,11 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
functionCodegen.generateMethod(
|
||||
Synthetic(null, original), accessor,
|
||||
new FunctionGenerationStrategy.CodegenBased(state) {
|
||||
@Override
|
||||
public boolean skipNotNullAssertionsForParameters() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
markLineNumberForElement(element.getPsiOrParent(), codegen.v);
|
||||
@@ -779,6 +784,11 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
iv.areturn(signature.getReturnType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipNotNullAssertionsForParameters() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (accessor.isWithSyntheticGetterAccessor()) {
|
||||
@@ -812,7 +822,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
|
||||
);
|
||||
|
||||
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClass(functionDescriptor);
|
||||
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) &&
|
||||
!isNonDefaultInterfaceMember(functionDescriptor, state) &&
|
||||
!isJvmStaticInObjectOrClass;
|
||||
|
||||
@@ -312,6 +312,10 @@ class MultifileClassCodegenImpl(
|
||||
}
|
||||
|
||||
object DelegateToCompiledMemberGenerationStrategy : FunctionGenerationStrategy() {
|
||||
override fun skipNotNullAssertionsForParameters(): kotlin.Boolean {
|
||||
throw IllegalStateException("shouldn't be called")
|
||||
}
|
||||
|
||||
override fun generateBody(mv: MethodVisitor, frameMap: FrameMap, signature: JvmMethodSignature, context: MethodContext, parentCodegen: MemberCodegen<*>) {
|
||||
throw IllegalStateException("shouldn't be called")
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns.RANGES_PACKAGE_FQ_NAME
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitiveNumberClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
@@ -32,30 +35,30 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
val supportedRangeTypes = listOf(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG)
|
||||
|
||||
private val RANGE_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
|
||||
supportedRangeTypes.associateBy {
|
||||
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Range"))
|
||||
}
|
||||
supportedRangeTypes.associateBy {
|
||||
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Range"))
|
||||
}
|
||||
|
||||
private val PROGRESSION_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
|
||||
supportedRangeTypes.associateBy {
|
||||
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression"))
|
||||
}
|
||||
supportedRangeTypes.associateBy {
|
||||
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression"))
|
||||
}
|
||||
|
||||
fun isPrimitiveRange(rangeType: KotlinType) =
|
||||
!rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null
|
||||
!rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null
|
||||
|
||||
fun isPrimitiveProgression(rangeType: KotlinType) =
|
||||
!rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null
|
||||
!rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null
|
||||
|
||||
fun getPrimitiveRangeElementType(rangeType: KotlinType): PrimitiveType? =
|
||||
getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE)
|
||||
getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE)
|
||||
|
||||
private fun getPrimitiveProgressionElementType(rangeType: KotlinType) =
|
||||
getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE)
|
||||
getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE)
|
||||
|
||||
private fun getPrimitiveRangeOrProgressionElementType(
|
||||
rangeOrProgression: KotlinType,
|
||||
map: Map<FqName, PrimitiveType>
|
||||
rangeOrProgression: KotlinType,
|
||||
map: Map<FqName, PrimitiveType>
|
||||
): PrimitiveType? {
|
||||
val declarationDescriptor = rangeOrProgression.constructor.declarationDescriptor ?: return null
|
||||
val fqName = DescriptorUtils.getFqName(declarationDescriptor).takeIf { it.isSafe } ?: return null
|
||||
@@ -67,101 +70,117 @@ fun getRangeOrProgressionElementType(rangeType: KotlinType): KotlinType? {
|
||||
val builtIns = rangeTypeDescriptor.builtIns
|
||||
|
||||
return when {
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "CharRange", "kotlin.ranges") -> builtIns.charType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "IntRange", "kotlin.ranges") -> builtIns.intType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "LongRange", "kotlin.ranges") -> builtIns.longType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("CharRange", "kotlin.ranges") -> builtIns.charType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("IntRange", "kotlin.ranges") -> builtIns.intType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("LongRange", "kotlin.ranges") -> builtIns.longType
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "CharProgression", "kotlin.ranges") -> builtIns.charType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "IntProgression", "kotlin.ranges") -> builtIns.intType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "LongProgression", "kotlin.ranges") -> builtIns.longType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("CharProgression", "kotlin.ranges") -> builtIns.charType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("IntProgression", "kotlin.ranges") -> builtIns.intType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("LongProgression", "kotlin.ranges") -> builtIns.longType
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatRange", "kotlin.ranges") -> builtIns.floatType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedDoubleRange", "kotlin.ranges") -> builtIns.doubleType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("ClosedFloatRange", "kotlin.ranges") -> builtIns.floatType
|
||||
rangeTypeDescriptor.isTopLevelInPackage("ClosedDoubleRange", "kotlin.ranges") -> builtIns.doubleType
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
rangeTypeDescriptor.isTopLevelInPackage("ClosedRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatingPointRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
rangeTypeDescriptor.isTopLevelInPackage("ClosedFloatingPointRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ComparableRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
rangeTypeDescriptor.isTopLevelInPackage("ComparableRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun BindingContext.getElementType(forExpression: KtForExpression): KotlinType {
|
||||
val loopRange = forExpression.loopRange!!
|
||||
val nextCall = get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange)
|
||||
?: throw AssertionError("No next() function " + DiagnosticUtils.atLocation(loopRange))
|
||||
return nextCall.resultingDescriptor.returnType!!
|
||||
}
|
||||
|
||||
fun getPrimitiveRangeOrProgressionElementType(rangeOrProgressionName: FqName): PrimitiveType? =
|
||||
RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?:
|
||||
PROGRESSION_TO_ELEMENT_TYPE[rangeOrProgressionName]
|
||||
RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?: PROGRESSION_TO_ELEMENT_TYPE[rangeOrProgressionName]
|
||||
|
||||
fun isRangeOrProgression(className: FqName) =
|
||||
getPrimitiveRangeOrProgressionElementType(className) != null
|
||||
getPrimitiveRangeOrProgressionElementType(className) != null
|
||||
|
||||
fun isPrimitiveNumberRangeTo(rangeTo: CallableDescriptor) =
|
||||
"rangeTo" == rangeTo.name.asString() && isPrimitiveNumberClassDescriptor(rangeTo.containingDeclaration) ||
|
||||
isPrimitiveRangeToExtension(rangeTo)
|
||||
"rangeTo" == rangeTo.name.asString() && isPrimitiveNumberClassDescriptor(rangeTo.containingDeclaration) ||
|
||||
isPrimitiveRangeToExtension(rangeTo)
|
||||
|
||||
private fun isPrimitiveRangeToExtension(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
return KotlinBuiltIns.isPrimitiveType(extensionReceiver.type)
|
||||
private inline fun CallableDescriptor.isTopLevelExtensionOnType(
|
||||
name: String,
|
||||
packageFQN: String,
|
||||
receiverTypePredicate: (KotlinType) -> Boolean
|
||||
): Boolean {
|
||||
if (!this.isTopLevelInPackage(name, packageFQN)) return false
|
||||
val extensionReceiverType = original.extensionReceiverParameter?.type ?: return false
|
||||
return receiverTypePredicate(extensionReceiverType)
|
||||
}
|
||||
|
||||
fun isPrimitiveNumberDownTo(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false
|
||||
private fun isPrimitiveRangeToExtension(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("rangeTo", "kotlin.ranges") {
|
||||
KotlinBuiltIns.isPrimitiveType(it)
|
||||
}
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
|
||||
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
|
||||
}
|
||||
fun isPrimitiveNumberDownTo(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("downTo", "kotlin.ranges") {
|
||||
isPrimitiveNumberClassDescriptor(it.constructor.declarationDescriptor)
|
||||
}
|
||||
|
||||
fun isPrimitiveNumberUntil(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "until", "kotlin.ranges")) return false
|
||||
fun isPrimitiveNumberUntil(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("until", "kotlin.ranges") {
|
||||
isPrimitiveNumberClassDescriptor(it.constructor.declarationDescriptor)
|
||||
}
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
|
||||
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
|
||||
}
|
||||
fun isArrayOrPrimitiveArrayIndices(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("indices", "kotlin.collections") {
|
||||
KotlinBuiltIns.isArray(it) || KotlinBuiltIns.isPrimitiveArray(it)
|
||||
}
|
||||
|
||||
fun isArrayOrPrimitiveArrayIndices(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
|
||||
fun isArrayOrPrimitiveArrayWithIndex(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("withIndex", "kotlin.collections") {
|
||||
KotlinBuiltIns.isArray(it) || KotlinBuiltIns.isPrimitiveArray(it)
|
||||
}
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverType = extensionReceiver.type
|
||||
return KotlinBuiltIns.isArray(extensionReceiverType) || KotlinBuiltIns.isPrimitiveArray(extensionReceiverType)
|
||||
}
|
||||
fun isCollectionIndices(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("indices", "kotlin.collections") {
|
||||
KotlinBuiltIns.isCollectionOrNullableCollection(it)
|
||||
}
|
||||
|
||||
fun isCollectionIndices(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
|
||||
fun isIterableWithIndex(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("withIndex", "kotlin.collections") {
|
||||
KotlinBuiltIns.isIterableOrNullableIterable(it)
|
||||
}
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverType = extensionReceiver.type
|
||||
return KotlinBuiltIns.isCollectionOrNullableCollection(extensionReceiverType)
|
||||
}
|
||||
fun isSequenceWithIndex(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("withIndex", "kotlin.sequences") {
|
||||
val typeDescriptor = it.constructor.declarationDescriptor ?: return false
|
||||
typeDescriptor.isTopLevelInPackage("Sequence", "kotlin.sequences")
|
||||
}
|
||||
|
||||
fun isCharSequenceIndices(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.text")) return false
|
||||
fun isCharSequenceIndices(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("indices", "kotlin.text") {
|
||||
KotlinBuiltIns.isCharSequenceOrNullableCharSequence(it)
|
||||
}
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverType = extensionReceiver.type
|
||||
return KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)
|
||||
}
|
||||
fun isCharSequenceWithIndex(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("withIndex", "kotlin.text") {
|
||||
KotlinBuiltIns.isCharSequenceOrNullableCharSequence(it)
|
||||
}
|
||||
|
||||
fun isComparableRangeTo(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false
|
||||
|
||||
val extensionReceiver = descriptor.original.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverTypeDescriptor = extensionReceiver.type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
||||
val upperBoundType = extensionReceiverTypeDescriptor.upperBounds.singleOrNull() ?: return false
|
||||
val upperBoundClassDescriptor = upperBoundType.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
if (!isTopLevelInPackage(upperBoundClassDescriptor, "Comparable", "kotlin")) return false
|
||||
|
||||
return true
|
||||
}
|
||||
fun isComparableRangeTo(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("rangeTo", "kotlin.ranges") {
|
||||
val extensionReceiverTypeDescriptor = it.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
||||
val upperBoundType = extensionReceiverTypeDescriptor.upperBounds.singleOrNull() ?: return false
|
||||
val upperBoundClassDescriptor = upperBoundType.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
upperBoundClassDescriptor.isTopLevelInPackage("Comparable", "kotlin")
|
||||
}
|
||||
|
||||
fun isClosedRangeContains(descriptor: CallableDescriptor): Boolean {
|
||||
if (descriptor.name.asString() != "contains") return false
|
||||
val containingClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||
if (!isTopLevelInPackage(containingClassDescriptor, "ClosedRange", "kotlin.ranges")) return false
|
||||
if (!containingClassDescriptor.isTopLevelInPackage("ClosedRange", "kotlin.ranges")) return false
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -188,33 +207,38 @@ fun isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(descriptor: CallableD
|
||||
return true
|
||||
}
|
||||
|
||||
fun isPrimitiveProgressionReverse(descriptor: CallableDescriptor) =
|
||||
descriptor.isTopLevelExtensionOnType("reversed", "kotlin.ranges") {
|
||||
isPrimitiveProgression(it)
|
||||
}
|
||||
|
||||
private fun isPrimitiveNumberType(type: KotlinType) =
|
||||
KotlinBuiltIns.isByte(type) ||
|
||||
KotlinBuiltIns.isShort(type) ||
|
||||
KotlinBuiltIns.isInt(type) ||
|
||||
KotlinBuiltIns.isChar(type) ||
|
||||
KotlinBuiltIns.isLong(type) ||
|
||||
KotlinBuiltIns.isFloat(type) ||
|
||||
KotlinBuiltIns.isDouble(type)
|
||||
KotlinBuiltIns.isByte(type) ||
|
||||
KotlinBuiltIns.isShort(type) ||
|
||||
KotlinBuiltIns.isInt(type) ||
|
||||
KotlinBuiltIns.isChar(type) ||
|
||||
KotlinBuiltIns.isLong(type) ||
|
||||
KotlinBuiltIns.isFloat(type) ||
|
||||
KotlinBuiltIns.isDouble(type)
|
||||
|
||||
fun isClosedFloatingPointRangeContains(descriptor: CallableDescriptor): Boolean {
|
||||
if (descriptor.name.asString() != "contains") return false
|
||||
val containingClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||
if (!isTopLevelInPackage(containingClassDescriptor, "ClosedFloatingPointRange", "kotlin.ranges")) return false
|
||||
if (!containingClassDescriptor.isTopLevelInPackage("ClosedFloatingPointRange", "kotlin.ranges")) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun getClosedFloatingPointRangeElementType(rangeType: KotlinType): KotlinType? {
|
||||
val classDescriptor = rangeType.constructor.declarationDescriptor as? ClassDescriptor ?: return null
|
||||
if (!isTopLevelInPackage(classDescriptor, "ClosedFloatingPointRange", "kotlin.ranges")) return null
|
||||
if (!classDescriptor.isTopLevelInPackage("ClosedFloatingPointRange", "kotlin.ranges")) return null
|
||||
return rangeType.arguments.singleOrNull()?.type
|
||||
}
|
||||
|
||||
private fun isTopLevelInPackage(descriptor: DeclarationDescriptor, name: String, packageName: String): Boolean {
|
||||
if (name != descriptor.name.asString()) return false
|
||||
private fun DeclarationDescriptor.isTopLevelInPackage(name: String, packageName: String): Boolean {
|
||||
if (name != this.name.asString()) return false
|
||||
|
||||
val containingDeclaration = descriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false
|
||||
val containingDeclaration = containingDeclaration as? PackageFragmentDescriptor ?: return false
|
||||
val packageFqName = containingDeclaration.fqName.asString()
|
||||
return packageName == packageFqName
|
||||
}
|
||||
@@ -234,7 +258,8 @@ fun getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCallee: CallableDe
|
||||
when {
|
||||
KotlinBuiltIns.isDouble(it) -> return Type.DOUBLE_TYPE
|
||||
KotlinBuiltIns.isFloat(it) -> return Type.FLOAT_TYPE
|
||||
else -> {}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,6 +185,8 @@ public class SamWrapperCodegen {
|
||||
private FqName getWrapperName(@NotNull KtFile containingFile) {
|
||||
FqName fileClassFqName = JvmFileClassUtil.getFileClassInfoNoResolve(containingFile).getFileClassFqName();
|
||||
JavaClassDescriptor descriptor = samType.getJavaClassDescriptor();
|
||||
//Change sam wrapper name template carefully cause it's used in inliner:
|
||||
// see isSamWrapper/isSamWrapperConstructorCall in inlineCodegenUtils.kt
|
||||
int hash = PackagePartClassUtils.getPathHashCode(containingFile.getVirtualFile()) * 31 +
|
||||
DescriptorUtils.getFqNameSafe(descriptor).hashCode();
|
||||
String shortName = String.format(
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.context.ScriptContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
|
||||
public static ScriptCodegen createScriptCodegen(
|
||||
@NotNull KtScript declaration,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull CodegenContext parentContext
|
||||
) {
|
||||
BindingContext bindingContext = state.getBindingContext();
|
||||
ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, declaration);
|
||||
assert scriptDescriptor != null;
|
||||
|
||||
Type classType = state.getTypeMapper().mapType(scriptDescriptor);
|
||||
|
||||
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, scriptDescriptor),
|
||||
classType, declaration.getContainingFile());
|
||||
List<ScriptDescriptor> earlierScripts = state.getReplSpecific().getEarlierScriptsForReplInterpreter();
|
||||
ScriptContext scriptContext = parentContext.intoScript(
|
||||
scriptDescriptor,
|
||||
earlierScripts == null ? Collections.emptyList() : earlierScripts,
|
||||
scriptDescriptor,
|
||||
state.getTypeMapper()
|
||||
);
|
||||
return new ScriptCodegen(declaration, state, scriptContext, builder);
|
||||
}
|
||||
|
||||
private final KtScript scriptDeclaration;
|
||||
private final ScriptContext context;
|
||||
private final ScriptDescriptor scriptDescriptor;
|
||||
private final Type classAsmType;
|
||||
|
||||
private ScriptCodegen(
|
||||
@NotNull KtScript scriptDeclaration,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull ScriptContext context,
|
||||
@NotNull ClassBuilder builder
|
||||
) {
|
||||
super(state, null, context, scriptDeclaration, builder);
|
||||
this.scriptDeclaration = scriptDeclaration;
|
||||
this.context = context;
|
||||
this.scriptDescriptor = context.getScriptDescriptor();
|
||||
classAsmType = typeMapper.mapClass(context.getContextDescriptor());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration() {
|
||||
v.defineClass(scriptDeclaration,
|
||||
state.getClassFileVersion(),
|
||||
ACC_PUBLIC | ACC_SUPER,
|
||||
classAsmType.getInternalName(),
|
||||
null,
|
||||
typeMapper.mapSupertype(DescriptorUtilsKt.getSuperClassOrAny(scriptDescriptor).getDefaultType(), null).getInternalName(),
|
||||
CodegenUtilKt.mapSupertypesNames(typeMapper, DescriptorUtilsKt.getSuperInterfaces(scriptDescriptor), null));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateBody() {
|
||||
genMembers();
|
||||
genFieldsForParameters(v);
|
||||
genConstructor(scriptDescriptor, v,
|
||||
context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticPartsBeforeBody() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticPartsAfterBody() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
generateKotlinClassMetadataAnnotation(scriptDescriptor, true);
|
||||
}
|
||||
|
||||
private void genConstructor(
|
||||
@NotNull ScriptDescriptor scriptDescriptor,
|
||||
@NotNull ClassBuilder classBuilder,
|
||||
@NotNull MethodContext methodContext
|
||||
) {
|
||||
JvmMethodSignature jvmSignature = typeMapper.mapScriptSignature(scriptDescriptor, context.getEarlierScripts());
|
||||
|
||||
if (state.getReplSpecific().getShouldGenerateScriptResultValue()) {
|
||||
FieldInfo resultFieldInfo = context.getResultFieldInfo();
|
||||
classBuilder.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN,
|
||||
ACC_PUBLIC | ACC_FINAL,
|
||||
resultFieldInfo.getFieldName(),
|
||||
resultFieldInfo.getFieldType().getDescriptor(),
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
MethodVisitor mv = classBuilder.newMethod(
|
||||
JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getUnsubstitutedPrimaryConstructor()),
|
||||
ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(),
|
||||
null, null);
|
||||
|
||||
if (state.getClassBuilderMode().generateBodies) {
|
||||
mv.visitCode();
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
Type classType = typeMapper.mapType(scriptDescriptor);
|
||||
|
||||
ClassDescriptor superclass = DescriptorUtilsKt.getSuperClassNotAny(scriptDescriptor);
|
||||
// TODO: throw if class is not found)
|
||||
|
||||
if (superclass == null) {
|
||||
iv.load(0, classType);
|
||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
|
||||
}
|
||||
else {
|
||||
ConstructorDescriptor ctorDesc = superclass.getUnsubstitutedPrimaryConstructor();
|
||||
if (ctorDesc == null) throw new RuntimeException("Primary constructor not found for script template " + superclass.toString());
|
||||
|
||||
iv.load(0, classType);
|
||||
|
||||
int valueParamStart = context.getEarlierScripts().isEmpty() ? 1 : 2; // this + array of earlier scripts if not empty
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters();
|
||||
for (ValueParameterDescriptor superclassParam: ctorDesc.getValueParameters()) {
|
||||
ValueParameterDescriptor valueParam = null;
|
||||
for (ValueParameterDescriptor vpd: valueParameters) {
|
||||
if (vpd.getName().equals(superclassParam.getName())) {
|
||||
valueParam = vpd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert valueParam != null;
|
||||
iv.load(valueParam.getIndex() + valueParamStart, typeMapper.mapType(valueParam.getType()));
|
||||
}
|
||||
|
||||
CallableMethod ctorMethod = typeMapper.mapToCallableMethod(ctorDesc, false);
|
||||
String sig = ctorMethod.getAsmMethod().getDescriptor();
|
||||
|
||||
iv.invokespecial(
|
||||
typeMapper.mapSupertype(superclass.getDefaultType(), null).getInternalName(),
|
||||
"<init>", sig, false);
|
||||
}
|
||||
iv.load(0, classType);
|
||||
|
||||
FrameMap frameMap = new FrameMap();
|
||||
frameMap.enterTemp(OBJECT_TYPE);
|
||||
|
||||
|
||||
if (!context.getEarlierScripts().isEmpty()) {
|
||||
int scriptsParamIndex = frameMap.enterTemp(AsmUtil.getArrayType(OBJECT_TYPE));
|
||||
|
||||
int earlierScriptIndex = 0;
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassType = typeMapper.mapClass(earlierScript);
|
||||
iv.load(0, classType);
|
||||
iv.load(scriptsParamIndex, earlierClassType);
|
||||
iv.aconst(earlierScriptIndex++);
|
||||
iv.aload(OBJECT_TYPE);
|
||||
iv.checkcast(earlierClassType);
|
||||
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, methodContext, state, this);
|
||||
|
||||
generateInitializers(() -> codegen);
|
||||
|
||||
iv.areturn(Type.VOID_TYPE);
|
||||
}
|
||||
|
||||
mv.visitMaxs(-1, -1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void genFieldsForParameters(@NotNull ClassBuilder classBuilder) {
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassName = typeMapper.mapType(earlierScript);
|
||||
int access = ACC_PUBLIC | ACC_FINAL;
|
||||
classBuilder.newField(NO_ORIGIN, access, context.getScriptFieldName(earlierScript), earlierClassName.getDescriptor(), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void genMembers() {
|
||||
for (KtDeclaration declaration : scriptDeclaration.getDeclarations()) {
|
||||
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
|
||||
genSimpleMember(declaration);
|
||||
}
|
||||
else if (declaration instanceof KtClassOrObject) {
|
||||
genClassOrObject((KtClassOrObject) declaration);
|
||||
}
|
||||
else if (declaration instanceof KtDestructuringDeclaration) {
|
||||
for (KtDestructuringDeclarationEntry entry : ((KtDestructuringDeclaration) declaration).getEntries()) {
|
||||
genSimpleMember(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.context.ScriptContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
|
||||
class ScriptCodegen private constructor(
|
||||
private val scriptDeclaration: KtScript,
|
||||
state: GenerationState,
|
||||
private val scriptContext: ScriptContext,
|
||||
builder: ClassBuilder
|
||||
) : MemberCodegen<KtScript>(state, null, scriptContext, scriptDeclaration, builder) {
|
||||
private val scriptDescriptor = scriptContext.scriptDescriptor
|
||||
private val classAsmType = typeMapper.mapClass(scriptContext.contextDescriptor)
|
||||
|
||||
override fun generateDeclaration() {
|
||||
v.defineClass(
|
||||
scriptDeclaration,
|
||||
state.classFileVersion,
|
||||
ACC_PUBLIC or ACC_SUPER,
|
||||
classAsmType.internalName,
|
||||
null,
|
||||
typeMapper.mapSupertype(scriptDescriptor.getSuperClassOrAny().defaultType, null).internalName,
|
||||
mapSupertypesNames(typeMapper, scriptDescriptor.getSuperInterfaces(), null)
|
||||
)
|
||||
}
|
||||
|
||||
override fun generateBody() {
|
||||
genMembers()
|
||||
genFieldsForParameters(v)
|
||||
genConstructor(scriptDescriptor, v, scriptContext.intoFunction(scriptDescriptor.unsubstitutedPrimaryConstructor))
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsBeforeBody() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType)
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsAfterBody() {}
|
||||
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
generateKotlinClassMetadataAnnotation(scriptDescriptor, true)
|
||||
}
|
||||
|
||||
private fun genConstructor(
|
||||
scriptDescriptor: ScriptDescriptor,
|
||||
classBuilder: ClassBuilder,
|
||||
methodContext: MethodContext
|
||||
) {
|
||||
val jvmSignature = typeMapper.mapScriptSignature(scriptDescriptor, scriptContext.earlierScripts)
|
||||
|
||||
if (state.replSpecific.shouldGenerateScriptResultValue) {
|
||||
val resultFieldInfo = scriptContext.resultFieldInfo
|
||||
classBuilder.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN,
|
||||
ACC_PUBLIC or ACC_FINAL,
|
||||
resultFieldInfo.fieldName,
|
||||
resultFieldInfo.fieldType.descriptor,
|
||||
null, null)
|
||||
}
|
||||
|
||||
val mv = classBuilder.newMethod(
|
||||
OtherOrigin(scriptDeclaration, scriptDescriptor.unsubstitutedPrimaryConstructor),
|
||||
ACC_PUBLIC, jvmSignature.asmMethod.name, jvmSignature.asmMethod.descriptor, null, null)
|
||||
|
||||
if (state.classBuilderMode.generateBodies) {
|
||||
mv.visitCode()
|
||||
|
||||
val iv = InstructionAdapter(mv)
|
||||
|
||||
val classType = typeMapper.mapType(scriptDescriptor)
|
||||
|
||||
val superclass = scriptDescriptor.getSuperClassNotAny()
|
||||
// TODO: throw if class is not found)
|
||||
|
||||
if (superclass == null) {
|
||||
iv.load(0, classType)
|
||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false)
|
||||
}
|
||||
else {
|
||||
val ctorDesc = superclass.unsubstitutedPrimaryConstructor
|
||||
?: throw RuntimeException("Primary constructor not found for script template " + superclass.toString())
|
||||
|
||||
iv.load(0, classType)
|
||||
|
||||
val valueParamStart = if (scriptContext.earlierScripts.isEmpty()) 1 else 2 // this + array of earlier scripts if not empty
|
||||
|
||||
val valueParameters = scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters
|
||||
for (superclassParam in ctorDesc.valueParameters) {
|
||||
val valueParam = valueParameters.first { it.name == superclassParam.name }
|
||||
iv.load(valueParam!!.index + valueParamStart, typeMapper.mapType(valueParam.type))
|
||||
}
|
||||
|
||||
val ctorMethod = typeMapper.mapToCallableMethod(ctorDesc, false)
|
||||
val sig = ctorMethod.getAsmMethod().descriptor
|
||||
|
||||
iv.invokespecial(
|
||||
typeMapper.mapSupertype(superclass.defaultType, null).internalName,
|
||||
"<init>", sig, false)
|
||||
}
|
||||
iv.load(0, classType)
|
||||
|
||||
val frameMap = FrameMap()
|
||||
frameMap.enterTemp(OBJECT_TYPE)
|
||||
|
||||
|
||||
if (!scriptContext.earlierScripts.isEmpty()) {
|
||||
val scriptsParamIndex = frameMap.enterTemp(AsmUtil.getArrayType(OBJECT_TYPE))
|
||||
|
||||
var earlierScriptIndex = 0
|
||||
for (earlierScript in scriptContext.earlierScripts) {
|
||||
val earlierClassType = typeMapper.mapClass(earlierScript)
|
||||
iv.load(0, classType)
|
||||
iv.load(scriptsParamIndex, earlierClassType)
|
||||
iv.aconst(earlierScriptIndex++)
|
||||
iv.aload(OBJECT_TYPE)
|
||||
iv.checkcast(earlierClassType)
|
||||
iv.putfield(classType.internalName, scriptContext.getScriptFieldName(earlierScript), earlierClassType.descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
val codegen = ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, methodContext, state, this)
|
||||
|
||||
generateInitializers { codegen }
|
||||
|
||||
iv.areturn(Type.VOID_TYPE)
|
||||
}
|
||||
|
||||
mv.visitMaxs(-1, -1)
|
||||
mv.visitEnd()
|
||||
}
|
||||
|
||||
private fun genFieldsForParameters(classBuilder: ClassBuilder) {
|
||||
for (earlierScript in scriptContext.earlierScripts) {
|
||||
val earlierClassName = typeMapper.mapType(earlierScript)
|
||||
val access = ACC_PUBLIC or ACC_FINAL
|
||||
classBuilder.newField(NO_ORIGIN, access, scriptContext.getScriptFieldName(earlierScript), earlierClassName.descriptor, null, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun genMembers() {
|
||||
for (declaration in scriptDeclaration.declarations) {
|
||||
if (declaration is KtProperty || declaration is KtNamedFunction || declaration is KtTypeAlias) {
|
||||
genSimpleMember(declaration)
|
||||
}
|
||||
else if (declaration is KtClassOrObject) {
|
||||
genClassOrObject(declaration)
|
||||
}
|
||||
else if (declaration is KtDestructuringDeclaration) {
|
||||
for (entry in declaration.entries) {
|
||||
genSimpleMember(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun createScriptCodegen(
|
||||
declaration: KtScript,
|
||||
state: GenerationState,
|
||||
parentContext: CodegenContext<*>
|
||||
): MemberCodegen<KtScript> {
|
||||
val bindingContext = state.bindingContext
|
||||
val scriptDescriptor = bindingContext.get<PsiElement, ScriptDescriptor>(BindingContext.SCRIPT, declaration)!!
|
||||
|
||||
if (scriptDescriptor.isReplSnippet) {
|
||||
return ScriptCodegenForRepl.createScriptCodegen(declaration, state, parentContext)
|
||||
}
|
||||
|
||||
val classType = state.typeMapper.mapType(scriptDescriptor)
|
||||
|
||||
val builder = state.factory.newVisitor(
|
||||
OtherOrigin(declaration, scriptDescriptor), classType, declaration.containingFile)
|
||||
|
||||
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
||||
|
||||
val scriptContext = parentContext.intoScript(
|
||||
scriptDescriptor,
|
||||
earlierScripts ?: emptyList(),
|
||||
scriptDescriptor,
|
||||
state.typeMapper
|
||||
)
|
||||
|
||||
return ScriptCodegen(declaration, state, scriptContext, builder)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.context.ScriptContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
|
||||
class ScriptCodegenForRepl private constructor(
|
||||
private val scriptDeclaration: KtScript,
|
||||
state: GenerationState,
|
||||
private val scriptContext: ScriptContext,
|
||||
builder: ClassBuilder
|
||||
) : MemberCodegen<KtScript>(state, null, scriptContext, scriptDeclaration, builder) {
|
||||
private val scriptDescriptor = scriptContext.scriptDescriptor
|
||||
private val classAsmType = typeMapper.mapClass(scriptContext.contextDescriptor)
|
||||
|
||||
override fun generateDeclaration() {
|
||||
// Do not allow superclasses for REPL line scripts
|
||||
assert(scriptDescriptor.getSuperClassNotAny() == null)
|
||||
|
||||
v.defineClass(
|
||||
scriptDeclaration,
|
||||
state.classFileVersion,
|
||||
ACC_PUBLIC or ACC_SUPER,
|
||||
classAsmType.internalName,
|
||||
null,
|
||||
"java/lang/Object",
|
||||
mapSupertypesNames(typeMapper, scriptDescriptor.getSuperInterfaces(), null)
|
||||
)
|
||||
}
|
||||
|
||||
override fun generateBody() {
|
||||
genMembers()
|
||||
|
||||
genDefaultConstructor(v)
|
||||
genRunMethod(v, scriptContext.intoFunction(scriptDescriptor.unsubstitutedPrimaryConstructor))
|
||||
genResultFieldIfNeeded(v)
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsBeforeBody() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType)
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsAfterBody() {}
|
||||
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
generateKotlinClassMetadataAnnotation(scriptDescriptor, true)
|
||||
}
|
||||
|
||||
private fun genResultFieldIfNeeded(classBuilder: ClassBuilder) {
|
||||
if (state.replSpecific.shouldGenerateScriptResultValue) {
|
||||
val resultFieldInfo = scriptContext.resultFieldInfo
|
||||
classBuilder.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN,
|
||||
ACC_PUBLIC or ACC_FINAL or ACC_STATIC,
|
||||
resultFieldInfo.fieldName,
|
||||
resultFieldInfo.fieldType.descriptor,
|
||||
null, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun genDefaultConstructor(classBuilder: ClassBuilder) {
|
||||
val mv = classBuilder.newMethod(OtherOrigin(scriptDeclaration), ACC_PUBLIC, "<init>", "()V", null, null)
|
||||
|
||||
if (state.classBuilderMode.generateBodies) {
|
||||
mv.visitCode()
|
||||
with (InstructionAdapter(mv)) {
|
||||
load(0, typeMapper.mapType(scriptDescriptor))
|
||||
invokespecial("java/lang/Object", "<init>", "()V", false)
|
||||
areturn(Type.VOID_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
mv.visitMaxs(-1, -1)
|
||||
mv.visitEnd()
|
||||
}
|
||||
|
||||
private fun genRunMethod(classBuilder: ClassBuilder, methodContext: MethodContext) {
|
||||
val mv = classBuilder.newMethod(OtherOrigin(scriptDeclaration), ACC_PUBLIC or ACC_STATIC, RUN_METHOD_NAME, "()V", null, null)
|
||||
|
||||
if (state.classBuilderMode.generateBodies) {
|
||||
mv.visitCode()
|
||||
with (InstructionAdapter(mv)) {
|
||||
val codegen = ExpressionCodegen(mv, FrameMap(), Type.VOID_TYPE, methodContext, state, this@ScriptCodegenForRepl)
|
||||
generateInitializers { codegen }
|
||||
areturn(Type.VOID_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
mv.visitMaxs(-1, -1)
|
||||
mv.visitEnd()
|
||||
}
|
||||
|
||||
private fun genMembers() {
|
||||
for (declaration in scriptDeclaration.declarations) {
|
||||
if (declaration is KtProperty || declaration is KtNamedFunction || declaration is KtTypeAlias) {
|
||||
genSimpleMember(declaration)
|
||||
}
|
||||
else if (declaration is KtClassOrObject) {
|
||||
genClassOrObject(declaration)
|
||||
}
|
||||
else if (declaration is KtDestructuringDeclaration) {
|
||||
for (entry in declaration.entries) {
|
||||
genSimpleMember(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val RUN_METHOD_NAME = "run"
|
||||
|
||||
@JvmStatic
|
||||
fun createScriptCodegen(
|
||||
declaration: KtScript,
|
||||
state: GenerationState,
|
||||
parentContext: CodegenContext<*>
|
||||
): MemberCodegen<KtScript> {
|
||||
val bindingContext = state.bindingContext
|
||||
val scriptDescriptor = bindingContext.get<PsiElement, ScriptDescriptor>(BindingContext.SCRIPT, declaration)!!
|
||||
|
||||
val classType = state.typeMapper.mapType(scriptDescriptor)
|
||||
|
||||
val builder = state.factory.newVisitor(
|
||||
OtherOrigin(declaration, scriptDescriptor), classType, declaration.containingFile)
|
||||
|
||||
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
||||
|
||||
val scriptContext = parentContext.intoScript(
|
||||
scriptDescriptor,
|
||||
earlierScripts ?: emptyList(),
|
||||
scriptDescriptor,
|
||||
state.typeMapper
|
||||
)
|
||||
|
||||
return ScriptCodegenForRepl(declaration, state, scriptContext, builder)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,6 +187,9 @@ public abstract class StackValue {
|
||||
else if (type == Type.BYTE_TYPE || type == Type.SHORT_TYPE || type == Type.INT_TYPE) {
|
||||
return constant(Integer.valueOf(value), type);
|
||||
}
|
||||
else if (type == Type.CHAR_TYPE) {
|
||||
return constant(Character.valueOf((char) value), type);
|
||||
}
|
||||
else {
|
||||
throw new AssertionError("Unexpected integer type: " + type);
|
||||
}
|
||||
@@ -590,7 +593,7 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
|
||||
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
|
||||
if (CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)) {
|
||||
if (resultReceiver.canHaveSideEffects()) {
|
||||
return coercion(resultReceiver, Type.VOID_TYPE);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. 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.binding;
|
||||
@@ -33,6 +22,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice;
|
||||
import org.jetbrains.kotlin.util.slicedMap.Slices;
|
||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
||||
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.*;
|
||||
@@ -124,7 +114,8 @@ public class CodegenBinding {
|
||||
return asmTypeForAnonymousClass(bindingContext, variableDescriptor);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Couldn't compute ASM type for " + PsiUtilsKt.getElementTextWithContext(expression));
|
||||
throw new KotlinExceptionWithAttachments("Couldn't compute ASM type for expression")
|
||||
.withAttachment("expression.kt", PsiUtilsKt.getElementTextWithContext(expression));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -142,7 +133,10 @@ public class CodegenBinding {
|
||||
return false;
|
||||
}
|
||||
|
||||
return classDescriptor.isInner() || !(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor);
|
||||
DeclarationDescriptor containingDeclaration = classDescriptor.getContainingDeclaration();
|
||||
return classDescriptor.isInner()
|
||||
|| containingDeclaration instanceof ScriptDescriptor
|
||||
|| !(containingDeclaration instanceof ClassDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isSubclass
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
@@ -252,12 +253,12 @@ fun reportTarget6InheritanceErrorIfNeeded(
|
||||
}
|
||||
}
|
||||
|
||||
fun CallableDescriptor.isJvmStaticInObjectOrClass(): Boolean =
|
||||
fun CallableDescriptor.isJvmStaticInObjectOrClassOrInterface(): Boolean =
|
||||
isJvmStaticIn {
|
||||
DescriptorUtils.isNonCompanionObject(it) ||
|
||||
// This is necessary because for generation of @JvmStatic methods from companion of class A
|
||||
// we create a synthesized descriptor containing in class A
|
||||
DescriptorUtils.isClassOrEnumClass(it)
|
||||
DescriptorUtils.isClassOrEnumClass(it) || DescriptorUtils.isInterface(it)
|
||||
}
|
||||
|
||||
fun CallableDescriptor.isJvmStaticInCompanionObject(): Boolean =
|
||||
@@ -420,15 +421,15 @@ fun extractReificationArgument(type: KotlinType): Pair<TypeParameterDescriptor,
|
||||
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
|
||||
function.initialSignatureDescriptor ?: function
|
||||
|
||||
fun ExpressionCodegen.generateCallReceiver(rangeCall: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||
generateReceiverValue(rangeCall.extensionReceiver ?: rangeCall.dispatchReceiver!!, false)
|
||||
fun ExpressionCodegen.generateCallReceiver(call: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||
generateReceiverValue(call.extensionReceiver ?: call.dispatchReceiver!!, false)
|
||||
|
||||
fun ExpressionCodegen.generateCallSingleArgument(rangeCall: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||
gen(ExpressionCodegen.getSingleArgumentExpression(rangeCall)!!)
|
||||
fun ExpressionCodegen.generateCallSingleArgument(call: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||
gen(call.getFirstArgumentExpression()!!)
|
||||
|
||||
fun ClassDescriptor.isPossiblyUninitializedSingleton() =
|
||||
DescriptorUtils.isEnumEntry(this) ||
|
||||
DescriptorUtils.isCompanionObject(this) && DescriptorUtils.isInterface(this.containingDeclaration)
|
||||
DescriptorUtils.isCompanionObject(this) && JvmCodegenUtil.isJvmInterface(this.containingDeclaration)
|
||||
|
||||
val CodegenContext<*>.parentContextsWithSelf
|
||||
get() = generateSequence(this) { it.parentContext }
|
||||
@@ -437,4 +438,4 @@ val CodegenContext<*>.parentContexts
|
||||
get() = parentContext?.parentContextsWithSelf ?: emptySequence()
|
||||
|
||||
val CodegenContext<*>.contextStackText
|
||||
get() = parentContextsWithSelf.joinToString(separator = "\n") { it.toString() }
|
||||
get() = parentContextsWithSelf.joinToString(separator = "\n") { it.toString() }
|
||||
|
||||
@@ -57,13 +57,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
private static class AccessorKey {
|
||||
public final DeclarationDescriptor descriptor;
|
||||
public final ClassDescriptor superCallLabelTarget;
|
||||
public final FieldAccessorKind fieldAccessorKind;
|
||||
|
||||
public AccessorKey(
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@Nullable ClassDescriptor superCallLabelTarget
|
||||
@Nullable ClassDescriptor superCallLabelTarget,
|
||||
@NotNull FieldAccessorKind fieldAccessorKind
|
||||
) {
|
||||
this.descriptor = descriptor;
|
||||
this.superCallLabelTarget = superCallLabelTarget;
|
||||
this.fieldAccessorKind = fieldAccessorKind;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,13 +74,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
if (!(obj instanceof AccessorKey)) return false;
|
||||
AccessorKey other = (AccessorKey) obj;
|
||||
return descriptor.equals(other.descriptor) &&
|
||||
fieldAccessorKind == other.fieldAccessorKind &&
|
||||
(superCallLabelTarget == null ? other.superCallLabelTarget == null
|
||||
: superCallLabelTarget.equals(other.superCallLabelTarget));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * descriptor.hashCode() + (superCallLabelTarget == null ? 0 : superCallLabelTarget.hashCode());
|
||||
return 31 * descriptor.hashCode() +
|
||||
fieldAccessorKind.hashCode() +
|
||||
(superCallLabelTarget == null ? 0 : superCallLabelTarget.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -458,7 +464,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
D descriptor = (D) possiblySubstitutedDescriptor.getOriginal();
|
||||
AccessorKey key = new AccessorKey(descriptor, superCallTarget);
|
||||
AccessorKey key = new AccessorKey(descriptor, superCallTarget, accessorKind);
|
||||
|
||||
// NB should check for property accessor factory first (or change property accessor tracking under propertyAccessorFactory creation)
|
||||
if (propertyAccessorFactories.containsKey(key)) {
|
||||
|
||||
@@ -69,9 +69,15 @@ public class ScriptContext extends ClassContext {
|
||||
public FieldInfo getResultFieldInfo() {
|
||||
assert getState().getReplSpecific().getShouldGenerateScriptResultValue() : "Should not be called unless 'scriptResultFieldName' is set";
|
||||
GenerationState state = getState();
|
||||
|
||||
String scriptResultFieldName = state.getReplSpecific().getScriptResultFieldName();
|
||||
assert scriptResultFieldName != null;
|
||||
return FieldInfo.createForHiddenField(state.getTypeMapper().mapClass(scriptDescriptor), AsmTypes.OBJECT_TYPE, scriptResultFieldName);
|
||||
|
||||
return FieldInfo.createForHiddenField(
|
||||
state.getTypeMapper().mapClass(scriptDescriptor),
|
||||
AsmTypes.OBJECT_TYPE,
|
||||
scriptResultFieldName,
|
||||
scriptDescriptor.isReplSnippet());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -531,6 +531,10 @@ class CoroutineCodegenForNamedFunction private constructor(
|
||||
private const val COROUTINE_LAMBDA_PARAMETER_PREFIX = "p$"
|
||||
|
||||
private object FailingFunctionGenerationStrategy : FunctionGenerationStrategy() {
|
||||
override fun skipNotNullAssertionsForParameters(): kotlin.Boolean {
|
||||
error("This functions must not be called")
|
||||
}
|
||||
|
||||
override fun generateBody(
|
||||
mv: MethodVisitor,
|
||||
frameMap: FrameMap,
|
||||
|
||||
@@ -41,25 +41,26 @@ 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.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
class CoroutineTransformerMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?,
|
||||
private val containingClassInternalName: String,
|
||||
obtainClassBuilderForCoroutineState: () -> ClassBuilder,
|
||||
private val isForNamedFunction: Boolean,
|
||||
private val shouldPreserveClassInitialization: Boolean,
|
||||
private val element: KtElement,
|
||||
// It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls
|
||||
private val needDispatchReceiver: Boolean = false,
|
||||
// May differ from containingClassInternalName in case of DefaultImpls
|
||||
private val internalNameForDispatchReceiver: String? = null
|
||||
delegate: MethodVisitor,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?,
|
||||
private val containingClassInternalName: String,
|
||||
obtainClassBuilderForCoroutineState: () -> ClassBuilder,
|
||||
private val isForNamedFunction: Boolean,
|
||||
private val shouldPreserveClassInitialization: Boolean,
|
||||
private val element: KtElement,
|
||||
// It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls
|
||||
private val needDispatchReceiver: Boolean = false,
|
||||
// May differ from containingClassInternalName in case of DefaultImpls
|
||||
private val internalNameForDispatchReceiver: String? = null
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
|
||||
|
||||
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
|
||||
@@ -77,6 +78,8 @@ class CoroutineTransformerMethodVisitor(
|
||||
FixStackMethodTransformer().transform(containingClassInternalName, methodNode)
|
||||
|
||||
if (isForNamedFunction) {
|
||||
ReturnUnitMethodTransformer.transform(containingClassInternalName, methodNode)
|
||||
|
||||
if (allSuspensionPointsAreTailCalls(containingClassInternalName, methodNode, suspensionPoints)) {
|
||||
dropSuspensionMarkers(methodNode, suspensionPoints)
|
||||
return
|
||||
@@ -117,22 +120,24 @@ class CoroutineTransformerMethodVisitor(
|
||||
val lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0
|
||||
|
||||
// tableswitch(this.label)
|
||||
insertBefore(actualCoroutineStart,
|
||||
insnListOf(
|
||||
*withInstructionAdapter { loadCoroutineSuspendedMarker() }.toArray(),
|
||||
tableSwitchLabel,
|
||||
// Allow debugger to stop on enter into suspend function
|
||||
LineNumberNode(lineNumber, tableSwitchLabel),
|
||||
VarInsnNode(Opcodes.ASTORE, suspendMarkerVarIndex),
|
||||
VarInsnNode(Opcodes.ALOAD, continuationIndex),
|
||||
createInsnForReadingLabel(),
|
||||
TableSwitchInsnNode(0,
|
||||
suspensionPoints.size,
|
||||
defaultLabel,
|
||||
startLabel, *suspensionPointLabels.toTypedArray()
|
||||
),
|
||||
startLabel
|
||||
)
|
||||
insertBefore(
|
||||
actualCoroutineStart,
|
||||
insnListOf(
|
||||
*withInstructionAdapter { loadCoroutineSuspendedMarker() }.toArray(),
|
||||
tableSwitchLabel,
|
||||
// Allow debugger to stop on enter into suspend function
|
||||
LineNumberNode(lineNumber, tableSwitchLabel),
|
||||
VarInsnNode(Opcodes.ASTORE, suspendMarkerVarIndex),
|
||||
VarInsnNode(Opcodes.ALOAD, continuationIndex),
|
||||
createInsnForReadingLabel(),
|
||||
TableSwitchInsnNode(
|
||||
0,
|
||||
suspensionPoints.size,
|
||||
defaultLabel,
|
||||
startLabel, *suspensionPointLabels.toTypedArray()
|
||||
),
|
||||
startLabel
|
||||
)
|
||||
)
|
||||
|
||||
insert(startLabel, withInstructionAdapter { generateResumeWithExceptionCheck(exceptionIndex) })
|
||||
@@ -149,48 +154,48 @@ class CoroutineTransformerMethodVisitor(
|
||||
}
|
||||
|
||||
private fun createInsnForReadingLabel() =
|
||||
if (isForNamedFunction)
|
||||
MethodInsnNode(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"getLabel",
|
||||
Type.getMethodDescriptor(Type.INT_TYPE),
|
||||
false
|
||||
)
|
||||
else
|
||||
FieldInsnNode(
|
||||
Opcodes.GETFIELD,
|
||||
COROUTINE_IMPL_ASM_TYPE.internalName,
|
||||
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
||||
)
|
||||
if (isForNamedFunction)
|
||||
MethodInsnNode(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"getLabel",
|
||||
Type.getMethodDescriptor(Type.INT_TYPE),
|
||||
false
|
||||
)
|
||||
else
|
||||
FieldInsnNode(
|
||||
Opcodes.GETFIELD,
|
||||
COROUTINE_IMPL_ASM_TYPE.internalName,
|
||||
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
||||
)
|
||||
|
||||
private fun createInsnForSettingLabel() =
|
||||
if (isForNamedFunction)
|
||||
MethodInsnNode(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"setLabel",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE),
|
||||
false
|
||||
)
|
||||
else
|
||||
FieldInsnNode(
|
||||
Opcodes.PUTFIELD,
|
||||
COROUTINE_IMPL_ASM_TYPE.internalName,
|
||||
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
||||
)
|
||||
if (isForNamedFunction)
|
||||
MethodInsnNode(
|
||||
Opcodes.INVOKEVIRTUAL,
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"setLabel",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE),
|
||||
false
|
||||
)
|
||||
else
|
||||
FieldInsnNode(
|
||||
Opcodes.PUTFIELD,
|
||||
COROUTINE_IMPL_ASM_TYPE.internalName,
|
||||
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
||||
)
|
||||
|
||||
private fun updateMaxStack(methodNode: MethodNode) {
|
||||
methodNode.instructions.resetLabels()
|
||||
methodNode.accept(
|
||||
MaxStackFrameSizeAndLocalsCalculator(
|
||||
Opcodes.ASM5, methodNode.access, methodNode.desc,
|
||||
object : MethodVisitor(Opcodes.ASM5) {
|
||||
override fun visitMaxs(maxStack: Int, maxLocals: Int) {
|
||||
methodNode.maxStack = maxStack
|
||||
}
|
||||
}
|
||||
)
|
||||
MaxStackFrameSizeAndLocalsCalculator(
|
||||
Opcodes.ASM5, methodNode.access, methodNode.desc,
|
||||
object : MethodVisitor(Opcodes.ASM5) {
|
||||
override fun visitMaxs(maxStack: Int, maxLocals: Int) {
|
||||
methodNode.maxStack = maxStack
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -232,10 +237,10 @@ class CoroutineTransformerMethodVisitor(
|
||||
|
||||
visitVarInsn(Opcodes.ALOAD, continuationIndex)
|
||||
invokevirtual(
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"getLabel",
|
||||
Type.getMethodDescriptor(Type.INT_TYPE),
|
||||
false
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"getLabel",
|
||||
Type.getMethodDescriptor(Type.INT_TYPE),
|
||||
false
|
||||
)
|
||||
|
||||
iconst(1 shl 31)
|
||||
@@ -245,19 +250,19 @@ class CoroutineTransformerMethodVisitor(
|
||||
visitVarInsn(Opcodes.ALOAD, continuationIndex)
|
||||
dup()
|
||||
invokevirtual(
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"getLabel",
|
||||
Type.getMethodDescriptor(Type.INT_TYPE),
|
||||
false
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"getLabel",
|
||||
Type.getMethodDescriptor(Type.INT_TYPE),
|
||||
false
|
||||
)
|
||||
|
||||
iconst(1 shl 31)
|
||||
sub(Type.INT_TYPE)
|
||||
invokevirtual(
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"setLabel",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE),
|
||||
false
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"setLabel",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE),
|
||||
false
|
||||
)
|
||||
|
||||
goTo(afterCoroutineStateCreated)
|
||||
@@ -268,26 +273,26 @@ class CoroutineTransformerMethodVisitor(
|
||||
dup()
|
||||
|
||||
val parameterTypesAndIndices =
|
||||
getParameterTypesIndicesForCoroutineConstructor(
|
||||
methodNode.desc,
|
||||
methodNode.access,
|
||||
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
getParameterTypesIndicesForCoroutineConstructor(
|
||||
methodNode.desc,
|
||||
methodNode.access,
|
||||
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
for ((type, index) in parameterTypesAndIndices) {
|
||||
load(index, type)
|
||||
}
|
||||
|
||||
invokespecial(
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"<init>",
|
||||
Type.getMethodDescriptor(
|
||||
Type.VOID_TYPE,
|
||||
*getParameterTypesForCoroutineConstructor(
|
||||
methodNode.desc, needDispatchReceiver,
|
||||
internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
),
|
||||
false
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"<init>",
|
||||
Type.getMethodDescriptor(
|
||||
Type.VOID_TYPE,
|
||||
*getParameterTypesForCoroutineConstructor(
|
||||
methodNode.desc, needDispatchReceiver,
|
||||
internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
),
|
||||
false
|
||||
)
|
||||
|
||||
visitVarInsn(Opcodes.ASTORE, continuationIndex)
|
||||
@@ -391,13 +396,13 @@ class CoroutineTransformerMethodVisitor(
|
||||
// k + 1 - data
|
||||
// k + 2 - exception
|
||||
val variablesToSpill =
|
||||
(0 until localsCount)
|
||||
.filter{ it !in setOf(continuationIndex, dataIndex, exceptionIndex) }
|
||||
.map { Pair(it, frame.getLocal(it)) }
|
||||
.filter { (index, value) ->
|
||||
(index == 0 && needDispatchReceiver && isForNamedFunction) ||
|
||||
(0 until localsCount)
|
||||
.filter { it !in setOf(continuationIndex, dataIndex, exceptionIndex) }
|
||||
.map { Pair(it, frame.getLocal(it)) }
|
||||
.filter { (index, value) ->
|
||||
(index == 0 && needDispatchReceiver && isForNamedFunction) ||
|
||||
(value != StrictBasicValue.UNINITIALIZED_VALUE && livenessFrame.isAlive(index))
|
||||
}
|
||||
}
|
||||
|
||||
for ((index, basicValue) in variablesToSpill) {
|
||||
if (basicValue === StrictBasicValue.NULL_VALUE) {
|
||||
@@ -452,8 +457,9 @@ class CoroutineTransformerMethodVisitor(
|
||||
val (type, maxIndex) = entry
|
||||
for (index in 0..maxIndex) {
|
||||
classBuilderForCoroutineState.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
||||
type.fieldNameForVar(index), type.descriptor, null, null)
|
||||
JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
||||
type.fieldNameForVar(index), type.descriptor, null, null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,17 +471,17 @@ class CoroutineTransformerMethodVisitor(
|
||||
get() {
|
||||
assert(suspensionCallEnd.next is LabelNode) {
|
||||
"Next instruction after ${this} should be a label, but " +
|
||||
"${suspensionCallEnd.next::class.java}/${suspensionCallEnd.next.opcode} was found"
|
||||
"${suspensionCallEnd.next::class.java}/${suspensionCallEnd.next.opcode} was found"
|
||||
}
|
||||
|
||||
return suspensionCallEnd.next as LabelNode
|
||||
}
|
||||
|
||||
private fun transformCallAndReturnContinuationLabel(
|
||||
id: Int,
|
||||
suspension: SuspensionPoint,
|
||||
methodNode: MethodNode,
|
||||
suspendMarkerVarIndex: Int
|
||||
id: Int,
|
||||
suspension: SuspensionPoint,
|
||||
methodNode: MethodNode,
|
||||
suspendMarkerVarIndex: Int
|
||||
): LabelNode {
|
||||
val continuationLabel = LabelNode()
|
||||
val continuationLabelAfterLoadedResult = LabelNode()
|
||||
@@ -483,12 +489,13 @@ class CoroutineTransformerMethodVisitor(
|
||||
val nextLineNumberNode = suspension.suspensionCallEnd.findNextOrNull { it is LineNumberNode } as? LineNumberNode
|
||||
with(methodNode.instructions) {
|
||||
// Save state
|
||||
insertBefore(suspension.suspensionCallBegin,
|
||||
insnListOf(
|
||||
VarInsnNode(Opcodes.ALOAD, continuationIndex),
|
||||
*withInstructionAdapter { iconst(id) }.toArray(),
|
||||
createInsnForSettingLabel()
|
||||
)
|
||||
insertBefore(
|
||||
suspension.suspensionCallBegin,
|
||||
insnListOf(
|
||||
VarInsnNode(Opcodes.ALOAD, continuationIndex),
|
||||
*withInstructionAdapter { iconst(id) }.toArray(),
|
||||
createInsnForSettingLabel()
|
||||
)
|
||||
)
|
||||
|
||||
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
|
||||
@@ -573,16 +580,17 @@ class CoroutineTransformerMethodVisitor(
|
||||
methodNode.tryCatchBlocks =
|
||||
methodNode.tryCatchBlocks.flatMap {
|
||||
val isContainingSuspensionPoint =
|
||||
instructions.indexOf(it.start) < beginIndex && beginIndex < instructions.indexOf(it.end)
|
||||
instructions.indexOf(it.start) < beginIndex && beginIndex < instructions.indexOf(it.end)
|
||||
|
||||
if (isContainingSuspensionPoint) {
|
||||
assert(instructions.indexOf(it.start) < endIndex && endIndex < instructions.indexOf(it.end)) {
|
||||
"Try catch block containing marker before suspension point should also contain the marker after suspension point"
|
||||
}
|
||||
listOf(TryCatchBlockNode(it.start, firstLabel, it.handler, it.type),
|
||||
TryCatchBlockNode(secondLabel, it.end, it.handler, it.type))
|
||||
}
|
||||
else
|
||||
listOf(
|
||||
TryCatchBlockNode(it.start, firstLabel, it.handler, it.type),
|
||||
TryCatchBlockNode(secondLabel, it.end, it.handler, it.type)
|
||||
)
|
||||
} else
|
||||
listOf(it)
|
||||
}
|
||||
|
||||
@@ -630,10 +638,10 @@ private fun Type.normalize() =
|
||||
* INVOKESTATIC InlineMarker.mark()
|
||||
*/
|
||||
private class SuspensionPoint(
|
||||
// ICONST_0
|
||||
val suspensionCallBegin: AbstractInsnNode,
|
||||
// INVOKESTATIC InlineMarker.mark()
|
||||
val suspensionCallEnd: AbstractInsnNode
|
||||
// ICONST_0
|
||||
val suspensionCallBegin: AbstractInsnNode,
|
||||
// INVOKESTATIC InlineMarker.mark()
|
||||
val suspensionCallEnd: AbstractInsnNode
|
||||
) {
|
||||
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
||||
|
||||
@@ -649,59 +657,68 @@ private class SuspensionPoint(
|
||||
}
|
||||
|
||||
private fun getLastParameterIndex(desc: String, access: Int) =
|
||||
Type.getArgumentTypes(desc).dropLast(1).map { it.size }.sum() + (if (!isStatic(access)) 1 else 0)
|
||||
Type.getArgumentTypes(desc).dropLast(1).map { it.size }.sum() + (if (!isStatic(access)) 1 else 0)
|
||||
|
||||
private fun getParameterTypesForCoroutineConstructor(desc: String, hasDispatchReceiver: Boolean, thisName: String) =
|
||||
listOfNotNull(if (!hasDispatchReceiver) null else Type.getObjectType(thisName)).toTypedArray() +
|
||||
Type.getArgumentTypes(desc).last()
|
||||
listOfNotNull(if (!hasDispatchReceiver) null else Type.getObjectType(thisName)).toTypedArray() +
|
||||
Type.getArgumentTypes(desc).last()
|
||||
|
||||
private fun isStatic(access: Int) = access and Opcodes.ACC_STATIC != 0
|
||||
|
||||
private fun getParameterTypesIndicesForCoroutineConstructor(
|
||||
desc: String,
|
||||
containingFunctionAccess: Int,
|
||||
needDispatchReceiver: Boolean,
|
||||
thisName: String
|
||||
desc: String,
|
||||
containingFunctionAccess: Int,
|
||||
needDispatchReceiver: Boolean,
|
||||
thisName: String
|
||||
): Collection<Pair<Type, Int>> {
|
||||
return mutableListOf<Pair<Type, Int>>().apply {
|
||||
if (needDispatchReceiver) {
|
||||
add(Type.getObjectType(thisName) to 0)
|
||||
}
|
||||
val continuationIndex =
|
||||
getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).map(Type::getSize).sum()
|
||||
getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).map(Type::getSize).sum()
|
||||
add(CONTINUATION_ASM_TYPE to continuationIndex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllParameterTypes(desc: String, hasDispatchReceiver: Boolean, thisName: String) =
|
||||
listOfNotNull(if (!hasDispatchReceiver) null else Type.getObjectType(thisName)).toTypedArray() +
|
||||
Type.getArgumentTypes(desc)
|
||||
listOfNotNull(if (!hasDispatchReceiver) null else Type.getObjectType(thisName)).toTypedArray() +
|
||||
Type.getArgumentTypes(desc)
|
||||
|
||||
private fun allSuspensionPointsAreTailCalls(
|
||||
thisName: String,
|
||||
methodNode: MethodNode,
|
||||
suspensionPoints: List<SuspensionPoint>
|
||||
thisName: String,
|
||||
methodNode: MethodNode,
|
||||
suspensionPoints: List<SuspensionPoint>
|
||||
): Boolean {
|
||||
val safelyReachableReturns = findSafelyReachableReturns(methodNode)
|
||||
val sourceFrames = MethodTransformer.analyze(thisName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||
val safelyReachableReturns = findSafelyReachableReturns(methodNode, sourceFrames)
|
||||
|
||||
val instructions = methodNode.instructions
|
||||
return suspensionPoints.all { suspensionPoint ->
|
||||
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
|
||||
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
|
||||
|
||||
safelyReachableReturns[endIndex + 1]?.all { returnIndex ->
|
||||
val sourceInsn =
|
||||
sourceFrames[returnIndex].top().sure {
|
||||
"There must be some value on stack to return"
|
||||
}.insns.singleOrNull()
|
||||
if (isUnreachable(beginIndex, sourceFrames)) return@all true
|
||||
|
||||
sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex
|
||||
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.all { sourceInsn ->
|
||||
sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex
|
||||
}
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
||||
private class IgnoringCopyOperationSourceInterpreter : SourceInterpreter() {
|
||||
internal class IgnoringCopyOperationSourceInterpreter : SourceInterpreter() {
|
||||
override fun copyOperation(insn: AbstractInsnNode?, value: SourceValue?) = value
|
||||
}
|
||||
|
||||
@@ -714,22 +731,22 @@ private class IgnoringCopyOperationSourceInterpreter : SourceInterpreter() {
|
||||
*
|
||||
* @return indices of safely reachable returns for each instruction in the method node
|
||||
*/
|
||||
private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?> {
|
||||
private fun findSafelyReachableReturns(methodNode: MethodNode, sourceFrames: Array<Frame<SourceValue?>?>): Array<Set<Int>?> {
|
||||
val controlFlowGraph = ControlFlowGraph.build(methodNode)
|
||||
|
||||
val insns = methodNode.instructions
|
||||
val reachableReturnsIndices = Array<Set<Int>?>(insns.size()) init@{ index ->
|
||||
val reachableReturnsIndices = Array<Set<Int>?>(insns.size()) init@ { index ->
|
||||
val insn = insns[index]
|
||||
|
||||
if (insn.opcode == Opcodes.ARETURN) {
|
||||
if (isUnreachable(index, sourceFrames)) return@init null
|
||||
return@init setOf(index)
|
||||
}
|
||||
|
||||
if (!insn.isMeaningful || insn.opcode in SAFE_OPCODES || insn.isInvisibleInDebugVarInsn(methodNode) ||
|
||||
isInlineMarker(insn)) {
|
||||
setOf()
|
||||
}
|
||||
else null
|
||||
} else null
|
||||
}
|
||||
|
||||
var changed: Boolean
|
||||
@@ -740,12 +757,12 @@ private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?>
|
||||
|
||||
@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
|
||||
}
|
||||
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
|
||||
@@ -757,6 +774,9 @@ private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?>
|
||||
return reachableReturnsIndices
|
||||
}
|
||||
|
||||
// Check whether this instruction is unreachable, i.e. there is no path leading to this instruction
|
||||
internal fun isUnreachable(index: Int, sourceFrames: Array<Frame<SourceValue?>?>) = sourceFrames[index] == null
|
||||
|
||||
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
|
||||
val insns = methodNode.instructions
|
||||
val index = insns.indexOf(this)
|
||||
@@ -766,4 +786,4 @@ private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode):
|
||||
}
|
||||
|
||||
private val SAFE_OPCODES =
|
||||
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
||||
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.inline.isReturnsUnitMarker
|
||||
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.common.removeAll
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
|
||||
/*
|
||||
* Replace POP with ARETURN iff
|
||||
* 1) It is immediately followed by { GETSTATIC Unit.INSTANCE, ARETURN } sequences
|
||||
* 2) It is poping Unit
|
||||
*/
|
||||
object ReturnUnitMethodTransformer : MethodTransformer() {
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
val unitMarks = findReturnsUnitMarks(methodNode)
|
||||
if (unitMarks.isEmpty()) return
|
||||
|
||||
val units = findReturnUnitSequences(methodNode)
|
||||
if (units.isEmpty()) {
|
||||
cleanUpReturnsUnitMarkers(methodNode, unitMarks)
|
||||
return
|
||||
}
|
||||
|
||||
val pops = methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }.toList()
|
||||
val popSuccessors = findSuccessors(methodNode, pops)
|
||||
val sourceInsns = findSourceInstructions(internalClassName, methodNode, pops)
|
||||
val safePops = filterOutUnsafes(popSuccessors, units, sourceInsns)
|
||||
|
||||
// Replace POP with ARETURN for tail call optimization
|
||||
safePops.forEach { methodNode.instructions.set(it, InsnNode(Opcodes.ARETURN)) }
|
||||
cleanUpReturnsUnitMarkers(methodNode, unitMarks)
|
||||
}
|
||||
|
||||
// Return list of POPs, which can be safely replaced by ARETURNs
|
||||
private fun filterOutUnsafes(
|
||||
popSuccessors: Map<AbstractInsnNode, Collection<AbstractInsnNode>>,
|
||||
units: Collection<AbstractInsnNode>,
|
||||
sourceInsns: Map<AbstractInsnNode, Collection<AbstractInsnNode>>
|
||||
): Collection<AbstractInsnNode> {
|
||||
return popSuccessors.filter { (pop, successors) ->
|
||||
successors.all { it in units } &&
|
||||
sourceInsns[pop].sure { "Sources of $pop cannot be null" }.all(::isSuspendingCallReturningUnit)
|
||||
}.keys
|
||||
}
|
||||
|
||||
// Find instructions which do something on stack, ignoring markers
|
||||
// Return map {insn => list of found instructions}
|
||||
private fun findSuccessors(
|
||||
methodNode: MethodNode,
|
||||
insns: List<AbstractInsnNode>
|
||||
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
||||
val cfg = ControlFlowGraph.build(methodNode)
|
||||
|
||||
return insns.keysToMap { findSuccessorsDFS(it, cfg, methodNode) }
|
||||
}
|
||||
|
||||
// Find all meaningful successors of insn
|
||||
private fun findSuccessorsDFS(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]
|
||||
when {
|
||||
!succ.isMeaningful || succ is JumpInsnNode || succ.opcode == Opcodes.NOP -> dfs(succ)
|
||||
succ.isUnitInstance() -> {
|
||||
// There can be multiple chains of { UnitInstance, POP } after inlining. Ignore them
|
||||
val newSuccessors = dfs(succ)
|
||||
if (newSuccessors.all { it.opcode == Opcodes.POP }) newSuccessors.flatMap { dfs(it) }
|
||||
else setOf(succ)
|
||||
}
|
||||
else -> setOf(succ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dfs(insn)
|
||||
}
|
||||
|
||||
private fun isSuspendingCallReturningUnit(node: AbstractInsnNode): Boolean =
|
||||
node.safeAs<MethodInsnNode>()?.next?.next?.let(::isReturnsUnitMarker) == true
|
||||
|
||||
private fun findSourceInstructions(
|
||||
internalClassName: String,
|
||||
methodNode: MethodNode,
|
||||
pops: Collection<AbstractInsnNode>
|
||||
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
||||
val frames = analyze(internalClassName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||
return pops.keysToMap {
|
||||
val index = methodNode.instructions.indexOf(it)
|
||||
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()
|
||||
frames[index].getStack(0).insns
|
||||
}
|
||||
}
|
||||
|
||||
// Find { GETSTATIC kotlin/Unit.INSTANCE, ARETURN } sequences
|
||||
// Result is list of GETSTATIC kotlin/Unit.INSTANCE instructions
|
||||
private fun findReturnUnitSequences(methodNode: MethodNode): Collection<AbstractInsnNode> =
|
||||
methodNode.instructions.asSequence().filter { it.isUnitInstance() && it.next?.opcode == Opcodes.ARETURN }.toList()
|
||||
|
||||
private fun findReturnsUnitMarks(methodNode: MethodNode): Collection<AbstractInsnNode> =
|
||||
methodNode.instructions.asSequence().filter(::isReturnsUnitMarker).toList()
|
||||
|
||||
private fun cleanUpReturnsUnitMarkers(methodNode: MethodNode, unitMarks: Collection<AbstractInsnNode>) {
|
||||
unitMarks.forEach { methodNode.instructions.removeAll(listOf(it.previous, it)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ open class FieldRemapper(
|
||||
|
||||
val insnNode = capturedFieldAccess[currentInstruction] as FieldInsnNode
|
||||
if (canProcess(insnNode.owner, insnNode.name, true)) {
|
||||
insnNode.name = CAPTURED_FIELD_FOLD_PREFIX + getFieldNameForFolding(insnNode)
|
||||
insnNode.name = Companion.foldName(getFieldNameForFolding(insnNode))
|
||||
insnNode.opcode = Opcodes.GETSTATIC
|
||||
|
||||
node.remove(InsnSequence(capturedFieldAccess[0], insnNode))
|
||||
@@ -95,4 +95,9 @@ open class FieldRemapper(
|
||||
|
||||
open fun getFieldForInline(node: FieldInsnNode, prefix: StackValue?): StackValue? =
|
||||
MethodInliner.findCapturedField(node, this).remapValue
|
||||
|
||||
companion object {
|
||||
fun foldName(fieldName: String) =
|
||||
CAPTURED_FIELD_FOLD_PREFIX + fieldName
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
|
||||
import org.jetbrains.kotlin.types.expressions.LabelResolver
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -157,18 +159,13 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
}
|
||||
|
||||
fun performInline(
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
|
||||
callDefault: Boolean,
|
||||
codegen: BaseExpressionCodegen
|
||||
) {
|
||||
if (!state.inlineCycleReporter.enterIntoInlining(resolvedCall)) {
|
||||
generateStub(resolvedCall, codegen)
|
||||
return
|
||||
}
|
||||
|
||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||
try {
|
||||
nodeAndSmap = createInlineMethodNode(functionDescriptor, jvmSignature, callDefault, resolvedCall, state, sourceCompiler)
|
||||
nodeAndSmap = createInlineMethodNode(functionDescriptor, jvmSignature, callDefault, typeArguments, state, sourceCompiler)
|
||||
endCall(inlineCall(nodeAndSmap, callDefault))
|
||||
}
|
||||
catch (e: CompilationException) {
|
||||
@@ -180,9 +177,6 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
catch (e: Exception) {
|
||||
throw throwCompilationException(nodeAndSmap, e, true)
|
||||
}
|
||||
finally {
|
||||
state.inlineCycleReporter.exitFromInliningOf(resolvedCall)
|
||||
}
|
||||
}
|
||||
|
||||
private fun canSkipStackSpillingOnInline(methodNode: MethodNode): Boolean {
|
||||
@@ -475,17 +469,15 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
callDefault: Boolean,
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
|
||||
state: GenerationState,
|
||||
sourceCompilerForInline: SourceCompilerForInline
|
||||
): SMAPAndMethodNode {
|
||||
when {
|
||||
isSpecialEnumMethod(functionDescriptor) -> {
|
||||
val arguments = resolvedCall!!.typeArguments
|
||||
|
||||
val node = createSpecialEnumMethodBody(
|
||||
functionDescriptor.name.asString(),
|
||||
arguments.keys.single().defaultType,
|
||||
typeArguments!!.keys.single().defaultType,
|
||||
state.typeMapper
|
||||
)
|
||||
return SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1))
|
||||
@@ -674,7 +666,15 @@ class PsiInlineCodegen(
|
||||
callDefault: Boolean,
|
||||
codegen: ExpressionCodegen
|
||||
) {
|
||||
performInline(resolvedCall, callDefault, codegen)
|
||||
if (!state.inlineCycleReporter.enterIntoInlining(resolvedCall)) {
|
||||
generateStub(resolvedCall, codegen)
|
||||
return
|
||||
}
|
||||
try {
|
||||
performInline(resolvedCall?.typeArguments, callDefault, codegen)
|
||||
} finally {
|
||||
state.inlineCycleReporter.exitFromInliningOf(resolvedCall)
|
||||
}
|
||||
}
|
||||
|
||||
override fun processAndPutHiddenParameters(justProcess: Boolean) {
|
||||
@@ -698,7 +698,7 @@ class PsiInlineCodegen(
|
||||
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
|
||||
activeLambda = next
|
||||
when (next) {
|
||||
is ExpressionLambda -> codegen.pushClosureOnStack(next.classDescriptor, true, this, functionReferenceReceiver)
|
||||
is PsiExpressionLambda -> codegen.pushClosureOnStack(next.classDescriptor, true, this, functionReferenceReceiver)
|
||||
is DefaultLambda -> rememberCapturedForDefaultLambda(next)
|
||||
else -> throw RuntimeException("Unknown lambda: $next")
|
||||
}
|
||||
@@ -744,7 +744,7 @@ class PsiInlineCodegen(
|
||||
val ktLambda = KtPsiUtil.deparenthesize(expression)
|
||||
assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
|
||||
|
||||
return ExpressionLambda(
|
||||
return PsiExpressionLambda(
|
||||
ktLambda!!, typeMapper, parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
|
||||
).also { lambda ->
|
||||
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
|
||||
|
||||
@@ -57,6 +57,8 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
|
||||
|
||||
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner)
|
||||
|
||||
open val hasDispatchReceiver = true
|
||||
|
||||
fun addAllParameters(remapper: FieldRemapper): Parameters {
|
||||
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this)
|
||||
|
||||
@@ -164,7 +166,7 @@ class DefaultLambda(
|
||||
classReader.b,
|
||||
invokeMethod.name,
|
||||
invokeMethod.descriptor,
|
||||
lambdaClassType)!!
|
||||
lambdaClassType) ?: error("Can't find method '${invokeMethod.name}${invokeMethod.descriptor}' in '${classReader.className}'")
|
||||
|
||||
if (needReification) {
|
||||
//nested classes could also require reification
|
||||
@@ -175,13 +177,32 @@ class DefaultLambda(
|
||||
|
||||
fun Type.boxReceiverForBoundReference() = AsmUtil.boxType(this)
|
||||
|
||||
abstract class ExpressionLambda(protected val typeMapper: KotlinTypeMapper, isCrossInline: Boolean): LambdaInfo(isCrossInline) {
|
||||
|
||||
class ExpressionLambda(
|
||||
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
|
||||
val asmMethod = jvmMethodSignature.asmMethod
|
||||
val methodNode = MethodNode(
|
||||
API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, sourceCompiler.state),
|
||||
asmMethod.name, asmMethod.descriptor, null, null
|
||||
)
|
||||
|
||||
node = wrapWithMaxLocalCalc(methodNode).let { adapter ->
|
||||
val smap = sourceCompiler.generateLambdaBody(
|
||||
adapter, jvmMethodSignature, this
|
||||
)
|
||||
adapter.visitMaxs(-1, -1)
|
||||
SMAPAndMethodNode(methodNode, smap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PsiExpressionLambda(
|
||||
expression: KtExpression,
|
||||
private val typeMapper: KotlinTypeMapper,
|
||||
typeMapper: KotlinTypeMapper,
|
||||
isCrossInline: Boolean,
|
||||
override val isBoundCallableReference: Boolean
|
||||
) : LambdaInfo(isCrossInline) {
|
||||
) : ExpressionLambda(typeMapper, isCrossInline) {
|
||||
|
||||
override val lambdaClassType: Type
|
||||
|
||||
@@ -268,21 +289,4 @@ class ExpressionLambda(
|
||||
|
||||
val isPropertyReference: Boolean
|
||||
get() = propertyReferenceInfo != null
|
||||
|
||||
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
|
||||
val asmMethod = jvmMethodSignature.asmMethod
|
||||
val methodNode = MethodNode(
|
||||
API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, sourceCompiler.state),
|
||||
asmMethod.name, asmMethod.descriptor, null, null
|
||||
)
|
||||
|
||||
node = wrapWithMaxLocalCalc(methodNode).let { adapter ->
|
||||
val smap = sourceCompiler.generateLambdaBody(
|
||||
adapter, jvmMethodSignature, this
|
||||
)
|
||||
adapter.visitMaxs(-1, -1)
|
||||
SMAPAndMethodNode(methodNode, smap)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,14 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.IrExpressionLambda
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.FixStackWithLabelNormalizationMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
@@ -164,7 +167,9 @@ class MethodInliner(
|
||||
result.merge(transformResult)
|
||||
result.addChangedType(oldClassName, newClassName)
|
||||
|
||||
if (inliningContext.isInliningLambda && transformationInfo!!.canRemoveAfterTransformation()) {
|
||||
if (inliningContext.isInliningLambda &&
|
||||
inliningContext.lambdaInfo !is DefaultLambda && //never delete default lambda classes
|
||||
transformationInfo!!.canRemoveAfterTransformation()) {
|
||||
// this class is transformed and original not used so we should remove original one after inlining
|
||||
result.addClassToRemove(oldClassName)
|
||||
}
|
||||
@@ -180,7 +185,7 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
override fun anew(type: Type) {
|
||||
if (isAnonymousClass(type.internalName)) {
|
||||
if (isSamWrapper(type.internalName) || isAnonymousClass(type.internalName)) {
|
||||
handleAnonymousObjectRegeneration()
|
||||
}
|
||||
|
||||
@@ -220,15 +225,20 @@ class MethodInliner(
|
||||
setLambdaInlining(true)
|
||||
val lambdaSMAP = info.node.classSMAP
|
||||
|
||||
val sourceMapper = if (inliningContext.classRegeneration && !inliningContext.isInliningLambda)
|
||||
NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo)
|
||||
else
|
||||
InlineLambdaSourceMapper(sourceMapper.parent!!, info.node)
|
||||
val childSourceMapper =
|
||||
if (inliningContext.classRegeneration && !inliningContext.isInliningLambda)
|
||||
NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo)
|
||||
else if (info is DefaultLambda) {
|
||||
NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP.intervals, lambdaSMAP.sourceInfo)
|
||||
}
|
||||
else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node)
|
||||
|
||||
val inliner = MethodInliner(
|
||||
info.node.node, lambdaParameters, inliningContext.subInlineLambda(info),
|
||||
newCapturedRemapper, true /*cause all calls in same module as lambda*/,
|
||||
newCapturedRemapper,
|
||||
if (info is DefaultLambda) isSameModule else true /*cause all nested objects in same module as lambda*/,
|
||||
"Lambda inlining " + info.lambdaClassType.internalName,
|
||||
sourceMapper, inlineCallSiteInfo, null
|
||||
childSourceMapper, inlineCallSiteInfo, null
|
||||
)
|
||||
|
||||
val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift)
|
||||
@@ -242,7 +252,7 @@ class MethodInliner(
|
||||
StackValue.onStack(info.invokeMethod.returnType).put(bridge.returnType, this)
|
||||
setLambdaInlining(false)
|
||||
addInlineMarker(this, false)
|
||||
sourceMapper.endMapping()
|
||||
childSourceMapper.endMapping()
|
||||
inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter)
|
||||
}
|
||||
else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
|
||||
@@ -320,17 +330,29 @@ class MethodInliner(
|
||||
|
||||
val capturedParamsSize = parameters.capturedParametersSizeOnStack
|
||||
val realParametersSize = parameters.realParametersSizeOnStack
|
||||
val transformedNode = MethodNode(
|
||||
API, node.access, node.name,
|
||||
Type.getMethodDescriptor(Type.getReturnType(node.desc), *(Type.getArgumentTypes(node.desc) + parameters.capturedTypes)),
|
||||
node.signature, node.exceptions?.toTypedArray()
|
||||
)
|
||||
|
||||
val transformedNode = object : MethodNode(
|
||||
API, node.access, node.name,
|
||||
Type.getMethodDescriptor(Type.getReturnType(node.desc), *(Type.getArgumentTypes(node.desc) + parameters.capturedTypes)),
|
||||
node.signature, node.exceptions?.toTypedArray()
|
||||
) {
|
||||
val transformationVisitor = object : MethodVisitor(API, transformedNode) {
|
||||
private val GENERATE_DEBUG_INFO = GENERATE_SMAP && inlineOnlySmapSkipper == null
|
||||
|
||||
private val isInliningLambda = nodeRemapper.isInsideInliningLambda
|
||||
|
||||
private fun getNewIndex(`var`: Int): Int {
|
||||
if (inliningContext.isInliningLambda && inliningContext.lambdaInfo is IrExpressionLambda) {
|
||||
if (`var` < parameters.argsSizeOnStack) {
|
||||
if (`var` < capturedParamsSize) {
|
||||
return `var` + realParametersSize
|
||||
}
|
||||
else {
|
||||
return `var` - capturedParamsSize
|
||||
}
|
||||
}
|
||||
return `var`
|
||||
}
|
||||
return `var` + if (`var` < realParametersSize) 0 else capturedParamsSize
|
||||
}
|
||||
|
||||
@@ -383,7 +405,7 @@ class MethodInliner(
|
||||
}
|
||||
}
|
||||
|
||||
node.accept(transformedNode)
|
||||
node.accept(transformationVisitor)
|
||||
|
||||
transformCaptured(transformedNode)
|
||||
transformFinallyDeepIndex(transformedNode, finallyDeepShift)
|
||||
@@ -410,82 +432,111 @@ class MethodInliner(
|
||||
val frame = sources[instructions.indexOf(cur)]
|
||||
|
||||
if (frame != null) {
|
||||
if (ReifiedTypeInliner.isNeedClassReificationMarker(cur)) {
|
||||
awaitClassReification = true
|
||||
}
|
||||
else if (cur is MethodInsnNode) {
|
||||
if (isFinallyStart(cur)) {
|
||||
//TODO deep index calc could be more precise
|
||||
currentFinallyDeep = getConstant(cur.previous)
|
||||
}
|
||||
when {
|
||||
ReifiedTypeInliner.isNeedClassReificationMarker(cur) -> awaitClassReification = true
|
||||
|
||||
val owner = cur.owner
|
||||
val name = cur.name
|
||||
//TODO check closure
|
||||
val argTypes = Type.getArgumentTypes(cur.desc)
|
||||
val paramCount = argTypes.size + 1//non static
|
||||
val firstParameterIndex = frame.stackSize - paramCount
|
||||
if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
|
||||
val sourceValue = frame.getStack(firstParameterIndex)
|
||||
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
|
||||
invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep))
|
||||
}
|
||||
else if (isAnonymousConstructorCall(owner, name)) {
|
||||
val lambdaMapping = HashMap<Int, LambdaInfo>()
|
||||
|
||||
var offset = 0
|
||||
var capturesAnonymousObjectThatMustBeRegenerated = false
|
||||
for (i in 0..paramCount - 1) {
|
||||
val sourceValue = frame.getStack(firstParameterIndex + i)
|
||||
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, false, instructions, sources, toDelete
|
||||
)
|
||||
if (lambdaInfo != null) {
|
||||
lambdaMapping.put(offset, lambdaInfo)
|
||||
}
|
||||
else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
|
||||
capturesAnonymousObjectThatMustBeRegenerated = true
|
||||
}
|
||||
|
||||
offset += if (i == 0) 1 else argTypes[i - 1].size
|
||||
cur is MethodInsnNode -> {
|
||||
if (isFinallyStart(cur)) {
|
||||
//TODO deep index calc could be more precise
|
||||
currentFinallyDeep = getConstant(cur.previous)
|
||||
}
|
||||
|
||||
transformations.add(
|
||||
buildConstructorInvocation(
|
||||
owner, cur.desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
|
||||
val owner = cur.owner
|
||||
val name = cur.name
|
||||
//TODO check closure
|
||||
val argTypes = Type.getArgumentTypes(cur.desc)
|
||||
val paramCount = argTypes.size + 1//non static
|
||||
val firstParameterIndex = frame.stackSize - paramCount
|
||||
if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
|
||||
val sourceValue = frame.getStack(firstParameterIndex)
|
||||
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
|
||||
invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep))
|
||||
}
|
||||
else if (isSamWrapperConstructorCall(owner, name)) {
|
||||
transformations.add(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner)))
|
||||
}
|
||||
else if (isAnonymousConstructorCall(owner, name)) {
|
||||
val lambdaMapping = HashMap<Int, LambdaInfo>()
|
||||
|
||||
var offset = 0
|
||||
var capturesAnonymousObjectThatMustBeRegenerated = false
|
||||
for (i in 0 until paramCount) {
|
||||
val sourceValue = frame.getStack(firstParameterIndex + i)
|
||||
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, false, instructions, sources, toDelete
|
||||
)
|
||||
)
|
||||
awaitClassReification = false
|
||||
if (lambdaInfo != null) {
|
||||
lambdaMapping.put(offset, lambdaInfo)
|
||||
}
|
||||
else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
|
||||
capturesAnonymousObjectThatMustBeRegenerated = true
|
||||
}
|
||||
|
||||
offset += if (i == 0) 1 else argTypes[i - 1].size
|
||||
}
|
||||
|
||||
transformations.add(
|
||||
buildConstructorInvocation(
|
||||
owner, cur.desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
|
||||
)
|
||||
)
|
||||
awaitClassReification = false
|
||||
}
|
||||
else if (inliningContext.isInliningLambda && ReifiedTypeInliner.isOperationReifiedMarker(cur)) {
|
||||
val reificationArgument = cur.reificationArgument
|
||||
val parameterName = reificationArgument!!.parameterName
|
||||
result.reifiedTypeParametersUsages.addUsedReifiedParameter(parameterName)
|
||||
}
|
||||
}
|
||||
else if (inliningContext.isInliningLambda && ReifiedTypeInliner.isOperationReifiedMarker(cur)) {
|
||||
val reificationArgument = cur.reificationArgument
|
||||
val parameterName = reificationArgument!!.parameterName
|
||||
result.reifiedTypeParametersUsages.addUsedReifiedParameter(parameterName)
|
||||
|
||||
cur.opcode == Opcodes.GETSTATIC -> {
|
||||
val fieldInsnNode = cur as FieldInsnNode?
|
||||
val className = fieldInsnNode!!.owner
|
||||
if (isAnonymousSingletonLoad(className, fieldInsnNode.name)) {
|
||||
transformations.add(
|
||||
AnonymousObjectTransformationInfo(
|
||||
className, awaitClassReification, isAlreadyRegenerated(className), true,
|
||||
inliningContext.nameGenerator
|
||||
)
|
||||
)
|
||||
awaitClassReification = false
|
||||
}
|
||||
else if (isWhenMappingAccess(className, fieldInsnNode.name)) {
|
||||
transformations.add(
|
||||
WhenMappingTransformationInfo(
|
||||
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cur.opcode == Opcodes.GETSTATIC) {
|
||||
val fieldInsnNode = cur as FieldInsnNode?
|
||||
val className = fieldInsnNode!!.owner
|
||||
if (isAnonymousSingletonLoad(className, fieldInsnNode.name)) {
|
||||
transformations.add(
|
||||
AnonymousObjectTransformationInfo(
|
||||
className, awaitClassReification, isAlreadyRegenerated(className), true,
|
||||
inliningContext.nameGenerator
|
||||
)
|
||||
)
|
||||
awaitClassReification = false
|
||||
}
|
||||
else if (isWhenMappingAccess(className, fieldInsnNode.name)) {
|
||||
transformations.add(
|
||||
WhenMappingTransformationInfo(
|
||||
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
else if (cur.opcode == Opcodes.POP) {
|
||||
getLambdaIfExistsAndMarkInstructions(frame.top()!!, true, instructions, sources, toDelete)?.let {
|
||||
|
||||
cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions(frame.top()!!, true, instructions, sources, toDelete)?.let {
|
||||
toDelete.add(cur)
|
||||
}
|
||||
|
||||
cur.opcode == Opcodes.PUTFIELD -> {
|
||||
//Recognize next contract's pattern in inline lambda
|
||||
// ALOAD 0
|
||||
// SOME_VALUE
|
||||
// PUTFIELD $capturedField
|
||||
// and transform it to
|
||||
// SOME_VALUE
|
||||
// PUTSTATIC $$$$capturedField
|
||||
val fieldInsn = cur as FieldInsnNode
|
||||
if (isCapturedFieldName(fieldInsn.name) &&
|
||||
nodeRemapper is InlinedLambdaRemapper &&
|
||||
nodeRemapper.originalLambdaInternalName == fieldInsn.owner) {
|
||||
val stackTransformations = mutableSetOf<AbstractInsnNode>()
|
||||
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations)
|
||||
if (lambdaInfo != null && stackTransformations.all { it is VarInsnNode }) {
|
||||
assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) {
|
||||
"Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}"
|
||||
}
|
||||
fieldInsn.name = FieldRemapper.foldName(fieldInsn.name)
|
||||
fieldInsn.opcode = Opcodes.PUTSTATIC
|
||||
toDelete.addAll(stackTransformations)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -606,6 +657,33 @@ class MethodInliner(
|
||||
return
|
||||
}
|
||||
|
||||
if (inliningContext.isInliningLambda && inliningContext.lambdaInfo is IrExpressionLambda) {
|
||||
val capturedVars = inliningContext.lambdaInfo!!.capturedVars
|
||||
var offset = parameters.realParametersSizeOnStack
|
||||
val map = capturedVars.map {
|
||||
offset to it.also { offset += it.type.size }
|
||||
}.toMap()
|
||||
|
||||
var cur: AbstractInsnNode? = node.instructions.first
|
||||
while (cur != null) {
|
||||
if (cur is VarInsnNode && cur.opcode == Opcodes.ALOAD && map.contains(cur.`var`)) {
|
||||
val varIndex = cur.`var`
|
||||
val capturedParamDesc = map[varIndex]!!
|
||||
|
||||
val newIns = FieldInsnNode(
|
||||
Opcodes.GETSTATIC,
|
||||
capturedParamDesc.containingLambdaName,
|
||||
foldName(capturedParamDesc.fieldName),
|
||||
capturedParamDesc.type.descriptor
|
||||
)
|
||||
node.instructions.insertBefore(cur, newIns)
|
||||
node.instructions.remove(cur)
|
||||
cur = newIns
|
||||
}
|
||||
cur = cur.next
|
||||
}
|
||||
}
|
||||
|
||||
// Fold all captured variables access chains
|
||||
// ALOAD 0
|
||||
// [ALOAD this$0]*
|
||||
|
||||
@@ -124,8 +124,10 @@ class ParametersBuilder private constructor() {
|
||||
objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null
|
||||
): ParametersBuilder {
|
||||
val builder = newBuilder()
|
||||
//skipped this for inlined lambda cause it will be removed
|
||||
builder.addThis(objectType, inlineLambda != null).lambda = inlineLambda
|
||||
if (inlineLambda?.hasDispatchReceiver != false) {
|
||||
//skipped this for inlined lambda cause it will be removed
|
||||
builder.addThis(objectType, inlineLambda != null).lambda = inlineLambda
|
||||
}
|
||||
|
||||
for (type in Type.getArgumentTypes(descriptor)) {
|
||||
builder.addNextParameter(type, false)
|
||||
|
||||
@@ -261,7 +261,7 @@ val MethodInsnNode.reificationArgument: ReificationArgument?
|
||||
return ReificationArgument(parameterName, nullable, arrayDepth)
|
||||
}
|
||||
|
||||
private val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() =
|
||||
val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() =
|
||||
previous?.previous?.intConstant?.let {
|
||||
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.codegen.inline
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||
|
||||
class SamWrapperTransformationInfo(override val oldClassName: String, private val inliningContext: InliningContext, private val alreadyRegenerated: Boolean): TransformationInfo {
|
||||
override val nameGenerator: NameGenerator
|
||||
get() = object: NameGenerator("stub") {
|
||||
override fun getGeneratorClass(): String {
|
||||
error ("Shouldn't be called on $oldClassName transformation")
|
||||
}
|
||||
|
||||
override fun subGenerator(inliningMethod: String?): NameGenerator {
|
||||
error ("Shouldn't be called on $oldClassName transformation")
|
||||
}
|
||||
|
||||
override fun subGenerator(lambdaNoWhen: Boolean, nameSuffix: String?): NameGenerator {
|
||||
error ("Shouldn't be called on $oldClassName transformation")
|
||||
}
|
||||
}
|
||||
|
||||
//TODO consider to use package class instead of inliningContext.root.callSiteInfo.ownerClassName
|
||||
override val newClassName: String
|
||||
get() = inliningContext.root.callSiteInfo.ownerClassName + "\$inlined" + "\$sam$".run { this + oldClassName.substringAfter(this) }
|
||||
|
||||
override fun shouldRegenerate(sameModule: Boolean) = !sameModule && !alreadyRegenerated
|
||||
|
||||
override fun canRemoveAfterTransformation() = false
|
||||
|
||||
override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean) =
|
||||
SamWrapperTransformer(this, inliningContext)
|
||||
}
|
||||
|
||||
class SamWrapperTransformer(transformationInfo: SamWrapperTransformationInfo, private val inliningContext: InliningContext) :
|
||||
ObjectTransformer<SamWrapperTransformationInfo>(transformationInfo, inliningContext.state) {
|
||||
|
||||
override fun doTransform(parentRemapper: FieldRemapper): InlineResult {
|
||||
val classReader = createClassReader()
|
||||
val classBuilder = createRemappingClassBuilderViaFactory(inliningContext)
|
||||
|
||||
classReader.accept(object : ClassVisitor(API, classBuilder.visitor) {
|
||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
||||
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
|
||||
}
|
||||
|
||||
}, ClassReader.SKIP_FRAMES)
|
||||
classBuilder.done()
|
||||
|
||||
return transformationResult
|
||||
}
|
||||
}
|
||||
@@ -136,6 +136,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
override fun generateLambdaBody(adapter: MethodVisitor,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: ExpressionLambda): SMAP {
|
||||
lambdaInfo as? PsiExpressionLambda ?: error("TODO")
|
||||
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
|
||||
val closureContext =
|
||||
if (lambdaInfo.isPropertyReference)
|
||||
@@ -157,7 +158,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
context: MethodContext,
|
||||
expression: KtExpression,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: ExpressionLambda?
|
||||
lambdaInfo: PsiExpressionLambda?
|
||||
): SMAP {
|
||||
val isLambda = lambdaInfo != null
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil
|
||||
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.classId
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
@@ -43,14 +45,16 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.ENUM_TYPE
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_CLASS_TYPE
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
@@ -87,6 +91,7 @@ private const val INLINE_MARKER_FINALLY_START = "finallyStart"
|
||||
private const val INLINE_MARKER_FINALLY_END = "finallyEnd"
|
||||
private const val INLINE_MARKER_BEFORE_SUSPEND_ID = 0
|
||||
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
|
||||
private const val INLINE_MARKET_RETURNS_UNIT = 2
|
||||
private val INTRINSIC_ARRAY_CONSTRUCTOR_TYPE = AsmUtil.asmTypeByClassId(classId)
|
||||
|
||||
internal fun getMethodNode(
|
||||
@@ -205,56 +210,34 @@ private fun getInlineName(
|
||||
internal fun isInvokeOnLambda(owner: String, name: String): Boolean {
|
||||
return OperatorNameConventions.INVOKE.asString() == name &&
|
||||
owner.startsWith(NUMBERED_FUNCTION_PREFIX) &&
|
||||
isInteger(owner.substring(NUMBERED_FUNCTION_PREFIX.length))
|
||||
owner.substring(NUMBERED_FUNCTION_PREFIX.length).isInteger()
|
||||
}
|
||||
|
||||
internal fun isAnonymousConstructorCall(internalName: String, methodName: String): Boolean {
|
||||
return "<init>" == methodName && isAnonymousClass(internalName)
|
||||
}
|
||||
internal fun isAnonymousConstructorCall(internalName: String, methodName: String): Boolean =
|
||||
isConstructor(methodName) && isAnonymousClass(internalName)
|
||||
|
||||
internal fun isWhenMappingAccess(internalName: String, fieldName: String): Boolean {
|
||||
return fieldName.startsWith(WhenByEnumsMapping.MAPPING_ARRAY_FIELD_PREFIX) && internalName.endsWith(WhenByEnumsMapping.MAPPINGS_CLASS_NAME_POSTFIX)
|
||||
}
|
||||
private fun isConstructor(methodName: String) = "<init>" == methodName
|
||||
|
||||
internal fun isAnonymousSingletonLoad(internalName: String, fieldName: String): Boolean {
|
||||
return JvmAbi.INSTANCE_FIELD == fieldName && isAnonymousClass(internalName)
|
||||
}
|
||||
internal fun isWhenMappingAccess(internalName: String, fieldName: String): Boolean =
|
||||
fieldName.startsWith(WhenByEnumsMapping.MAPPING_ARRAY_FIELD_PREFIX) && internalName.endsWith(WhenByEnumsMapping.MAPPINGS_CLASS_NAME_POSTFIX)
|
||||
|
||||
internal fun isAnonymousClass(internalName: String): Boolean {
|
||||
val shortName = getLastNamePart(internalName)
|
||||
val index = shortName.lastIndexOf("$")
|
||||
internal fun isAnonymousSingletonLoad(internalName: String, fieldName: String): Boolean =
|
||||
JvmAbi.INSTANCE_FIELD == fieldName && isAnonymousClass(internalName)
|
||||
|
||||
if (index < 0) {
|
||||
return false
|
||||
}
|
||||
internal fun isSamWrapper(internalName: String) =
|
||||
internalName.contains("\$sam$") && internalName.substringAfter("\$i$", "").run { length == 8 && toLongOrNull(16) != null }
|
||||
|
||||
val suffix = shortName.substring(index + 1)
|
||||
return isInteger(suffix)
|
||||
}
|
||||
internal fun isSamWrapperConstructorCall(internalName: String, methodName: String) =
|
||||
isConstructor(methodName) && isSamWrapper(internalName)
|
||||
|
||||
private fun getLastNamePart(internalName: String): String {
|
||||
val index = internalName.lastIndexOf("/")
|
||||
return if (index < 0) internalName else internalName.substring(index + 1)
|
||||
}
|
||||
internal fun isAnonymousClass(internalName: String) =
|
||||
!isSamWrapper(internalName) &&
|
||||
internalName.substringAfterLast('/').substringAfterLast("$", "").isInteger()
|
||||
|
||||
fun wrapWithMaxLocalCalc(methodNode: MethodNode): MethodVisitor {
|
||||
return MaxStackFrameSizeAndLocalsCalculator(API, methodNode.access, methodNode.desc, methodNode)
|
||||
}
|
||||
fun wrapWithMaxLocalCalc(methodNode: MethodNode) =
|
||||
MaxStackFrameSizeAndLocalsCalculator(API, methodNode.access, methodNode.desc, methodNode)
|
||||
|
||||
private fun isInteger(string: String): Boolean {
|
||||
string.toIntOrNull() != null
|
||||
if (string.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (i in 0..string.length - 1) {
|
||||
if (!Character.isDigit(string[i])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
private fun String.isInteger(radix: Int = 10) = toIntOrNull(radix) != null
|
||||
|
||||
internal fun isCapturedFieldName(fieldName: String): Boolean {
|
||||
// TODO: improve this heuristic
|
||||
@@ -263,14 +246,10 @@ internal fun isCapturedFieldName(fieldName: String): Boolean {
|
||||
RECEIVER_0 == fieldName
|
||||
}
|
||||
|
||||
internal fun isReturnOpcode(opcode: Int): Boolean {
|
||||
return opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN
|
||||
}
|
||||
internal fun isReturnOpcode(opcode: Int) = opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN
|
||||
|
||||
//marked return could be either non-local or local in case of labeled lambda self-returns
|
||||
internal fun isMarkedReturn(returnIns: AbstractInsnNode): Boolean {
|
||||
return getMarkedReturnLabelOrNull(returnIns) != null
|
||||
}
|
||||
internal fun isMarkedReturn(returnIns: AbstractInsnNode) = getMarkedReturnLabelOrNull(returnIns) != null
|
||||
|
||||
internal fun getMarkedReturnLabelOrNull(returnInsn: AbstractInsnNode): String? {
|
||||
if (!isReturnOpcode(returnInsn.opcode)) {
|
||||
@@ -308,9 +287,7 @@ internal fun insertNodeBefore(from: MethodNode, to: MethodNode, beforeNode: Abst
|
||||
}
|
||||
}
|
||||
|
||||
internal fun createEmptyMethodNode(): MethodNode {
|
||||
return MethodNode(API, 0, "fake", "()V", null, null)
|
||||
}
|
||||
internal fun createEmptyMethodNode() = MethodNode(API, 0, "fake", "()V", null, null)
|
||||
|
||||
internal fun firstLabelInChain(node: LabelNode): LabelNode {
|
||||
var curNode = node
|
||||
@@ -345,9 +322,7 @@ internal val AbstractInsnNode?.insnText: String
|
||||
}
|
||||
|
||||
internal val AbstractInsnNode?.insnOpcodeText: String
|
||||
get() {
|
||||
return if (this == null) "null" else Printer.OPCODES[opcode]
|
||||
}
|
||||
get() = if (this == null) "null" else Printer.OPCODES[opcode]
|
||||
|
||||
internal fun buildClassReaderByInternalName(state: GenerationState, internalName: String): ClassReader {
|
||||
//try to find just compiled classes then in dependencies
|
||||
@@ -367,26 +342,18 @@ internal fun generateFinallyMarker(v: InstructionAdapter, depth: Int, start: Boo
|
||||
v.invokestatic(INLINE_MARKER_CLASS_NAME, if (start) INLINE_MARKER_FINALLY_START else INLINE_MARKER_FINALLY_END, "(I)V", false)
|
||||
}
|
||||
|
||||
internal fun isFinallyEnd(node: AbstractInsnNode): Boolean {
|
||||
return isFinallyMarker(node, INLINE_MARKER_FINALLY_END)
|
||||
}
|
||||
internal fun isFinallyEnd(node: AbstractInsnNode) = isFinallyMarker(node, INLINE_MARKER_FINALLY_END)
|
||||
|
||||
internal fun isFinallyStart(node: AbstractInsnNode): Boolean {
|
||||
return isFinallyMarker(node, INLINE_MARKER_FINALLY_START)
|
||||
}
|
||||
internal fun isFinallyStart(node: AbstractInsnNode) = isFinallyMarker(node, INLINE_MARKER_FINALLY_START)
|
||||
|
||||
internal fun isFinallyMarker(node: AbstractInsnNode?): Boolean {
|
||||
return node != null && (isFinallyStart(node) || isFinallyEnd(node))
|
||||
}
|
||||
internal fun isFinallyMarker(node: AbstractInsnNode?): Boolean = node != null && (isFinallyStart(node) || isFinallyEnd(node))
|
||||
|
||||
private fun isFinallyMarker(node: AbstractInsnNode, name: String): Boolean {
|
||||
if (node !is MethodInsnNode) return false
|
||||
return INLINE_MARKER_CLASS_NAME == node.owner && name == node.name
|
||||
}
|
||||
|
||||
internal fun isFinallyMarkerRequired(context: MethodContext): Boolean {
|
||||
return context.isInlineMethodContext || context is InlineLambdaContext
|
||||
}
|
||||
internal fun isFinallyMarkerRequired(context: MethodContext) = context.isInlineMethodContext || context is InlineLambdaContext
|
||||
|
||||
internal fun getConstant(ins: AbstractInsnNode): Int {
|
||||
val opcode = ins.opcode
|
||||
@@ -424,6 +391,26 @@ internal fun addInlineMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
)
|
||||
}
|
||||
|
||||
internal fun addReturnsUnitMarkerIfNecessary(v: InstructionAdapter, resolvedCall: ResolvedCall<*>) {
|
||||
val wrapperDescriptor = resolvedCall.candidateDescriptor.safeAs<FunctionDescriptor>() ?: return
|
||||
val unsubstitutedDescriptor = wrapperDescriptor.unwrapInitialDescriptorForSuspendFunction()
|
||||
|
||||
val typeSubstitutor = TypeSubstitutor.create(
|
||||
unsubstitutedDescriptor.typeParameters
|
||||
.withIndex()
|
||||
.associateBy({ it.value.typeConstructor }) {
|
||||
TypeProjectionImpl(resolvedCall.typeArguments[wrapperDescriptor.typeParameters[it.index]] ?: return)
|
||||
}
|
||||
)
|
||||
|
||||
val substitutedDescriptor = unsubstitutedDescriptor.substitute(typeSubstitutor) ?: return
|
||||
val returnType = substitutedDescriptor.returnType ?: return
|
||||
|
||||
if (KotlinBuiltIns.isUnit(returnType)) {
|
||||
addReturnsUnitMarker(v)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun addSuspendMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
v.iconst(if (isStartNotEnd) INLINE_MARKER_BEFORE_SUSPEND_ID else INLINE_MARKER_AFTER_SUSPEND_ID)
|
||||
v.visitMethodInsn(
|
||||
@@ -433,8 +420,18 @@ internal fun addSuspendMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun addReturnsUnitMarker(v: InstructionAdapter) {
|
||||
v.iconst(INLINE_MARKET_RETURNS_UNIT)
|
||||
v.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,
|
||||
"mark",
|
||||
"(I)V", false
|
||||
)
|
||||
}
|
||||
|
||||
internal fun isBeforeSuspendMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_BEFORE_SUSPEND_ID)
|
||||
internal fun isAfterSuspendMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_AFTER_SUSPEND_ID)
|
||||
internal fun isReturnsUnitMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKET_RETURNS_UNIT)
|
||||
|
||||
private fun isSuspendMarker(insn: AbstractInsnNode, id: Int) =
|
||||
isInlineMarker(insn, "mark") && insn.previous.intConstant == id
|
||||
@@ -491,9 +488,7 @@ fun isFakeLocalVariableForInline(name: String): Boolean {
|
||||
return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT)
|
||||
}
|
||||
|
||||
internal fun isThis0(name: String): Boolean {
|
||||
return THIS_0 == name
|
||||
}
|
||||
internal fun isThis0(name: String): Boolean = THIS_0 == name
|
||||
|
||||
internal fun isSpecialEnumMethod(functionDescriptor: FunctionDescriptor): Boolean {
|
||||
val containingDeclaration = functionDescriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false
|
||||
|
||||
@@ -46,10 +46,10 @@ class ApiVersionCallsPreprocessingMethodTransformer(private val targetApiVersion
|
||||
val atLeastVersion = MavenComparableVersion("$epic.$major.$minor")
|
||||
|
||||
val replacementInsn =
|
||||
if (targetApiVersion.version >= atLeastVersion)
|
||||
InsnNode(Opcodes.ICONST_1)
|
||||
else
|
||||
InsnNode(Opcodes.ICONST_0)
|
||||
if (targetApiVersion.version >= atLeastVersion)
|
||||
InsnNode(Opcodes.ICONST_1)
|
||||
else
|
||||
InsnNode(Opcodes.ICONST_0)
|
||||
|
||||
methodNode.instructions.run {
|
||||
remove(prev1)
|
||||
@@ -65,29 +65,29 @@ class ApiVersionCallsPreprocessingMethodTransformer(private val targetApiVersion
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.isApiVersionIsAtLeastCall(): Boolean =
|
||||
isMethodInsnWith(Opcodes.INVOKESTATIC) {
|
||||
owner.startsWith("kotlin/internal") &&
|
||||
name == "apiVersionIsAtLeast" &&
|
||||
desc == "(III)Z"
|
||||
}
|
||||
isMethodInsnWith(Opcodes.INVOKESTATIC) {
|
||||
owner.startsWith("kotlin/internal") &&
|
||||
name == "apiVersionIsAtLeast" &&
|
||||
desc == "(III)Z"
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.getIntConstValue(): Int? =
|
||||
when (this) {
|
||||
is InsnNode ->
|
||||
if (opcode in Opcodes.ICONST_M1..Opcodes.ICONST_5)
|
||||
opcode - Opcodes.ICONST_0
|
||||
else
|
||||
null
|
||||
when (this) {
|
||||
is InsnNode ->
|
||||
if (opcode in Opcodes.ICONST_M1..Opcodes.ICONST_5)
|
||||
opcode - Opcodes.ICONST_0
|
||||
else
|
||||
null
|
||||
|
||||
is IntInsnNode ->
|
||||
when (opcode) {
|
||||
Opcodes.BIPUSH -> operand
|
||||
Opcodes.SIPUSH -> operand
|
||||
else -> null
|
||||
}
|
||||
is IntInsnNode ->
|
||||
when (opcode) {
|
||||
Opcodes.BIPUSH -> operand
|
||||
Opcodes.SIPUSH -> operand
|
||||
else -> null
|
||||
}
|
||||
|
||||
is LdcInsnNode -> cst as? Int
|
||||
is LdcInsnNode -> cst as? Int
|
||||
|
||||
else -> null
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen.optimization
|
||||
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ProperTrackedReferenceValue
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ReferenceTrackingInterpreter
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ReferenceValueDescriptor
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.TrackedReferenceValue
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.removeEmptyCatchBlocks
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.removeUnusedLocalVariables
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
@@ -71,10 +65,10 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
|
||||
var cleanVarInstruction: VarInsnNode? = null
|
||||
|
||||
fun canRewrite(): Boolean =
|
||||
!hazard &&
|
||||
initCallInsn != null &&
|
||||
localVar != null &&
|
||||
localVarIndex >= 0
|
||||
!hazard &&
|
||||
initCallInsn != null &&
|
||||
localVar != null &&
|
||||
localVarIndex >= 0
|
||||
|
||||
override fun onUseAsTainted() {
|
||||
hazard = true
|
||||
@@ -118,10 +112,10 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
|
||||
|
||||
private inner class Interpreter : ReferenceTrackingInterpreter() {
|
||||
override fun newOperation(insn: AbstractInsnNode): BasicValue =
|
||||
refValuesByNewInsn[insn]?.let { descriptor ->
|
||||
ProperTrackedReferenceValue(descriptor.refType, descriptor)
|
||||
}
|
||||
?: super.newOperation(insn)
|
||||
refValuesByNewInsn[insn]?.let { descriptor ->
|
||||
ProperTrackedReferenceValue(descriptor.refType, descriptor)
|
||||
}
|
||||
?: super.newOperation(insn)
|
||||
|
||||
override fun processRefValueUsage(value: TrackedReferenceValue, insn: AbstractInsnNode, position: Int) {
|
||||
for (descriptor in value.descriptors) {
|
||||
@@ -179,7 +173,7 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun BasicValue.getCapturedVarOrNull() =
|
||||
safeAs<ProperTrackedReferenceValue>()?.descriptor?.safeAs<CapturedVarDescriptor>()
|
||||
safeAs<ProperTrackedReferenceValue>()?.descriptor?.safeAs<CapturedVarDescriptor>()
|
||||
|
||||
private fun assignLocalVars() {
|
||||
for (localVar in methodNode.localVariables) {
|
||||
@@ -195,8 +189,7 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
|
||||
|
||||
if (descriptor.localVar == null) {
|
||||
descriptor.localVar = localVar
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
descriptor.hazard = true
|
||||
}
|
||||
}
|
||||
@@ -210,8 +203,7 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
|
||||
refValue.localVarIndex = methodNode.maxLocals
|
||||
methodNode.maxLocals += 2
|
||||
localVar.index = refValue.localVarIndex
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
refValue.localVarIndex = localVar.index
|
||||
}
|
||||
|
||||
@@ -223,7 +215,7 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
val cleanInstructions = findCleanInstructions(refValue, oldVarIndex, methodNode.instructions)
|
||||
if (cleanInstructions.size > 1 ) {
|
||||
if (cleanInstructions.size > 1) {
|
||||
refValue.hazard = true
|
||||
continue
|
||||
}
|
||||
@@ -235,12 +227,14 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
|
||||
return InsnSequence(instructions).filterIsInstance<VarInsnNode>().filter {
|
||||
it.opcode == Opcodes.ASTORE && it.`var` == oldVarIndex
|
||||
}.filter {
|
||||
it.previous?.opcode == Opcodes.ACONST_NULL
|
||||
}.filter {
|
||||
val operationIndex = instructions.indexOf(it)
|
||||
val localVariableNode = refValue.localVar!!
|
||||
instructions.indexOf(localVariableNode.start) < operationIndex && operationIndex < instructions.indexOf(localVariableNode.end)
|
||||
}.toList()
|
||||
it.previous?.opcode == Opcodes.ACONST_NULL
|
||||
}.filter {
|
||||
val operationIndex = instructions.indexOf(it)
|
||||
val localVariableNode = refValue.localVar!!
|
||||
instructions.indexOf(localVariableNode.start) < operationIndex && operationIndex < instructions.indexOf(
|
||||
localVariableNode.end
|
||||
)
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private fun rewrite() {
|
||||
|
||||
@@ -48,20 +48,20 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun collectRewriteActions(): List<() -> Unit> =
|
||||
arrayListOf<() -> Unit>().also { actions ->
|
||||
val frames = analyze(internalClassName, methodNode, ConstantPropagationInterpreter())
|
||||
val insns = methodNode.instructions.toArray()
|
||||
for (i in frames.indices) {
|
||||
val frame = frames[i] ?: continue
|
||||
val insn = insns[i] as? JumpInsnNode ?: continue
|
||||
when (insn.opcode) {
|
||||
in Opcodes.IFEQ .. Opcodes.IFLE ->
|
||||
tryRewriteComparisonWithZero(insn, frame, actions)
|
||||
in Opcodes.IF_ICMPEQ .. Opcodes.IF_ICMPLE ->
|
||||
tryRewriteBinaryComparison(insn, frame, actions)
|
||||
}
|
||||
arrayListOf<() -> Unit>().also { actions ->
|
||||
val frames = analyze(internalClassName, methodNode, ConstantPropagationInterpreter())
|
||||
val insns = methodNode.instructions.toArray()
|
||||
for (i in frames.indices) {
|
||||
val frame = frames[i] ?: continue
|
||||
val insn = insns[i] as? JumpInsnNode ?: continue
|
||||
when (insn.opcode) {
|
||||
in Opcodes.IFEQ..Opcodes.IFLE ->
|
||||
tryRewriteComparisonWithZero(insn, frame, actions)
|
||||
in Opcodes.IF_ICMPEQ..Opcodes.IF_ICMPLE ->
|
||||
tryRewriteBinaryComparison(insn, frame, actions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryRewriteComparisonWithZero(insn: JumpInsnNode, frame: Frame<BasicValue>, actions: ArrayList<() -> Unit>) {
|
||||
val top = frame.top()!!.safeAs<IConstValue>() ?: return
|
||||
@@ -93,8 +93,7 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
|
||||
|
||||
if (arg1 is IConstValue && arg2 is IConstValue) {
|
||||
rewriteBinaryComparisonOfConsts(insn, arg1.value, arg2.value, actions)
|
||||
}
|
||||
else if (arg2 is IConstValue && arg2.value == 0) {
|
||||
} else if (arg2 is IConstValue && arg2.value == 0) {
|
||||
rewriteBinaryComparisonWith0(insn, actions)
|
||||
}
|
||||
}
|
||||
@@ -144,8 +143,8 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
|
||||
|
||||
private class IConstValue private constructor(val value: Int) : StrictBasicValue(Type.INT_TYPE) {
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other === this ||
|
||||
other is IConstValue && other.value == this.value
|
||||
other === this ||
|
||||
other is IConstValue && other.value == this.value
|
||||
|
||||
override fun hashCode(): Int = value
|
||||
|
||||
@@ -155,34 +154,34 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
|
||||
private val ICONST_CACHE = Array(7) { IConstValue(it - 1) }
|
||||
|
||||
fun of(value: Int) =
|
||||
if (value in -1 .. 5)
|
||||
ICONST_CACHE[value + 1]
|
||||
else
|
||||
IConstValue(value)
|
||||
if (value in -1..5)
|
||||
ICONST_CACHE[value + 1]
|
||||
else
|
||||
IConstValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
private class ConstantPropagationInterpreter : OptimizationBasicInterpreter() {
|
||||
override fun newOperation(insn: AbstractInsnNode): BasicValue =
|
||||
when (insn.opcode) {
|
||||
in Opcodes.ICONST_M1 .. Opcodes.ICONST_5 ->
|
||||
IConstValue.of(insn.opcode - Opcodes.ICONST_0)
|
||||
Opcodes.BIPUSH, Opcodes.SIPUSH ->
|
||||
IConstValue.of(insn.cast<IntInsnNode>().operand)
|
||||
Opcodes.LDC -> {
|
||||
val operand = insn.cast<LdcInsnNode>().cst
|
||||
if (operand is Int)
|
||||
IConstValue.of(operand)
|
||||
else
|
||||
super.newOperation(insn)
|
||||
}
|
||||
else -> super.newOperation(insn)
|
||||
when (insn.opcode) {
|
||||
in Opcodes.ICONST_M1..Opcodes.ICONST_5 ->
|
||||
IConstValue.of(insn.opcode - Opcodes.ICONST_0)
|
||||
Opcodes.BIPUSH, Opcodes.SIPUSH ->
|
||||
IConstValue.of(insn.cast<IntInsnNode>().operand)
|
||||
Opcodes.LDC -> {
|
||||
val operand = insn.cast<LdcInsnNode>().cst
|
||||
if (operand is Int)
|
||||
IConstValue.of(operand)
|
||||
else
|
||||
super.newOperation(insn)
|
||||
}
|
||||
else -> super.newOperation(insn)
|
||||
}
|
||||
|
||||
override fun merge(v: BasicValue, w: BasicValue): BasicValue =
|
||||
if (v is IConstValue && w is IConstValue && v == w)
|
||||
v
|
||||
else
|
||||
super.merge(v, w)
|
||||
if (v is IConstValue && w is IConstValue && v == w)
|
||||
v
|
||||
else
|
||||
super.merge(v, w)
|
||||
}
|
||||
}
|
||||
@@ -55,15 +55,15 @@ class DeadCodeEliminationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun shouldRemove(insn: AbstractInsnNode, index: Int, frames: Array<out Any?>): Boolean =
|
||||
when (insn) {
|
||||
is LabelNode ->
|
||||
// Do not remove label nodes because they can be referred by try/catch blocks or local variables table
|
||||
false
|
||||
is LineNumberNode ->
|
||||
isDeadLineNumber(insn, index, frames)
|
||||
else ->
|
||||
frames[index] == null
|
||||
}
|
||||
when (insn) {
|
||||
is LabelNode ->
|
||||
// Do not remove label nodes because they can be referred by try/catch blocks or local variables table
|
||||
false
|
||||
is LineNumberNode ->
|
||||
isDeadLineNumber(insn, index, frames)
|
||||
else ->
|
||||
frames[index] == null
|
||||
}
|
||||
|
||||
private fun isDeadLineNumber(insn: LineNumberNode, index: Int, frames: Array<out Any?>): Boolean {
|
||||
// Line number node is "dead" if the corresponding line number interval
|
||||
|
||||
@@ -18,10 +18,8 @@ package org.jetbrains.kotlin.codegen.optimization
|
||||
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.CompositeMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class FixStackWithLabelNormalizationMethodTransformer : CompositeMethodTransformer(
|
||||
LabelNormalizationMethodTransformer(),
|
||||
FixStackMethodTransformer()
|
||||
LabelNormalizationMethodTransformer(),
|
||||
FixStackMethodTransformer()
|
||||
)
|
||||
@@ -49,13 +49,11 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
newLabelNodes[thisNode.label] = prevNode
|
||||
removedAnyLabels = true
|
||||
thisNode = instructions.removeNodeGetNext(thisNode)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newLabelNodes[thisNode.label] = thisNode
|
||||
thisNode = thisNode.next
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
thisNode = thisNode.next
|
||||
}
|
||||
}
|
||||
@@ -83,19 +81,19 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun rewriteLineNumberNode(oldLineNode: LineNumberNode): AbstractInsnNode? =
|
||||
instructions.replaceNodeGetNext(oldLineNode, oldLineNode.rewriteLabels())
|
||||
instructions.replaceNodeGetNext(oldLineNode, oldLineNode.rewriteLabels())
|
||||
|
||||
private fun rewriteJumpInsn(oldJumpNode: JumpInsnNode): AbstractInsnNode? =
|
||||
instructions.replaceNodeGetNext(oldJumpNode, oldJumpNode.rewriteLabels())
|
||||
instructions.replaceNodeGetNext(oldJumpNode, oldJumpNode.rewriteLabels())
|
||||
|
||||
private fun rewriteLookupSwitchInsn(oldSwitchNode: LookupSwitchInsnNode): AbstractInsnNode? =
|
||||
instructions.replaceNodeGetNext(oldSwitchNode, oldSwitchNode.rewriteLabels())
|
||||
instructions.replaceNodeGetNext(oldSwitchNode, oldSwitchNode.rewriteLabels())
|
||||
|
||||
private fun rewriteTableSwitchInsn(oldSwitchNode: TableSwitchInsnNode): AbstractInsnNode? =
|
||||
instructions.replaceNodeGetNext(oldSwitchNode, oldSwitchNode.rewriteLabels())
|
||||
instructions.replaceNodeGetNext(oldSwitchNode, oldSwitchNode.rewriteLabels())
|
||||
|
||||
private fun rewriteFrameNode(oldFrameNode: FrameNode): AbstractInsnNode? =
|
||||
instructions.replaceNodeGetNext(oldFrameNode, oldFrameNode.rewriteLabels())
|
||||
instructions.replaceNodeGetNext(oldFrameNode, oldFrameNode.rewriteLabels())
|
||||
|
||||
private fun rewriteTryCatchBlocks() {
|
||||
methodNode.tryCatchBlocks = methodNode.tryCatchBlocks.map { oldTcb ->
|
||||
@@ -109,21 +107,21 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
private fun rewriteLocalVars() {
|
||||
methodNode.localVariables = methodNode.localVariables.map { oldVar ->
|
||||
LocalVariableNode(
|
||||
oldVar.name,
|
||||
oldVar.desc,
|
||||
oldVar.signature,
|
||||
getNew(oldVar.start),
|
||||
getNew(oldVar.end),
|
||||
oldVar.index
|
||||
oldVar.name,
|
||||
oldVar.desc,
|
||||
oldVar.signature,
|
||||
getNew(oldVar.start),
|
||||
getNew(oldVar.end),
|
||||
oldVar.index
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun LineNumberNode.rewriteLabels(): AbstractInsnNode =
|
||||
LineNumberNode(line, getNewOrOld(start))
|
||||
LineNumberNode(line, getNewOrOld(start))
|
||||
|
||||
private fun JumpInsnNode.rewriteLabels(): AbstractInsnNode =
|
||||
JumpInsnNode(opcode, getNew(label))
|
||||
JumpInsnNode(opcode, getNew(label))
|
||||
|
||||
private fun LookupSwitchInsnNode.rewriteLabels(): AbstractInsnNode {
|
||||
val switchNode = LookupSwitchInsnNode(getNew(dflt), keys.toIntArray(), emptyArray())
|
||||
@@ -145,10 +143,10 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun getNew(oldLabelNode: LabelNode): LabelNode =
|
||||
newLabelNodes[oldLabelNode.label]!!
|
||||
newLabelNodes[oldLabelNode.label]!!
|
||||
|
||||
private fun getNewOrOld(oldLabelNode: LabelNode): LabelNode =
|
||||
newLabelNodes[oldLabelNode.label] ?: oldLabelNode
|
||||
newLabelNodes[oldLabelNode.label] ?: oldLabelNode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ class MethodVerifier(private val checkPoint: String) : MethodTransformer() {
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
try {
|
||||
analyze(internalClassName, methodNode, BasicVerifier())
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
throw AssertionError("$checkPoint: incorrect bytecode", e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,17 +28,17 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class OptimizationMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
private val disableOptimization: Boolean,
|
||||
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<String>?
|
||||
delegate: MethodVisitor,
|
||||
private val disableOptimization: Boolean,
|
||||
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<String>?
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
|
||||
private val constructorCallNormalizationTransformer =
|
||||
UninitializedStoresMethodTransformer(constructorCallNormalizationMode)
|
||||
UninitializedStoresMethodTransformer(constructorCallNormalizationMode)
|
||||
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
normalizationMethodTransformer.transform("fake", methodNode)
|
||||
@@ -55,22 +55,22 @@ class OptimizationMethodVisitor(
|
||||
private val MEMORY_LIMIT_BY_METHOD_MB = 50
|
||||
|
||||
val normalizationMethodTransformer = CompositeMethodTransformer(
|
||||
FixStackWithLabelNormalizationMethodTransformer(),
|
||||
MethodVerifier("AFTER mandatory stack transformations")
|
||||
FixStackWithLabelNormalizationMethodTransformer(),
|
||||
MethodVerifier("AFTER mandatory stack transformations")
|
||||
)
|
||||
|
||||
val optimizationTransformer = CompositeMethodTransformer(
|
||||
CapturedVarsOptimizationMethodTransformer(),
|
||||
RedundantNullCheckMethodTransformer(),
|
||||
RedundantCheckCastEliminationMethodTransformer(),
|
||||
ConstantConditionEliminationMethodTransformer(),
|
||||
RedundantBoxingMethodTransformer(),
|
||||
StackPeepholeOptimizationsTransformer(),
|
||||
PopBackwardPropagationTransformer(),
|
||||
DeadCodeEliminationMethodTransformer(),
|
||||
RedundantGotoMethodTransformer(),
|
||||
RedundantNopsCleanupMethodTransformer(),
|
||||
MethodVerifier("AFTER optimizations")
|
||||
CapturedVarsOptimizationMethodTransformer(),
|
||||
RedundantNullCheckMethodTransformer(),
|
||||
RedundantCheckCastEliminationMethodTransformer(),
|
||||
ConstantConditionEliminationMethodTransformer(),
|
||||
RedundantBoxingMethodTransformer(),
|
||||
StackPeepholeOptimizationsTransformer(),
|
||||
PopBackwardPropagationTransformer(),
|
||||
DeadCodeEliminationMethodTransformer(),
|
||||
RedundantGotoMethodTransformer(),
|
||||
RedundantNopsCleanupMethodTransformer(),
|
||||
MethodVerifier("AFTER optimizations")
|
||||
)
|
||||
|
||||
fun canBeOptimized(node: MethodNode): Boolean {
|
||||
|
||||
@@ -22,7 +22,8 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
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.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode
|
||||
|
||||
class RedundantCheckCastEliminationMethodTransformer : MethodTransformer() {
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
@@ -57,7 +58,7 @@ class RedundantCheckCastEliminationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun isTrivialSubtype(superType: Type, subType: Type) =
|
||||
superType == subType
|
||||
superType == subType
|
||||
|
||||
private fun isMultiArrayType(type: Type) = type.sort == Type.ARRAY && type.dimensions != 1
|
||||
}
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.optimization
|
||||
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class RedundantGotoMethodTransformer : MethodTransformer() {
|
||||
/**
|
||||
@@ -38,7 +38,7 @@ class RedundantGotoMethodTransformer : MethodTransformer() {
|
||||
insn is LabelNode ->
|
||||
currentLabels.add(insn)
|
||||
insn.opcode == Opcodes.GOTO &&
|
||||
(insn as JumpInsnNode).label in currentLabels ->
|
||||
(insn as JumpInsnNode).label in currentLabels ->
|
||||
insnsToRemove.add(insn)
|
||||
insn.isMeaningful ->
|
||||
currentLabels.clear()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user