mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 15:51:01 +00:00
Compare commits
942 Commits
data_flow_
...
script_run
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3f51fabce | ||
|
|
4c7ddbe397 | ||
|
|
f558b4238c | ||
|
|
c9d9a8220d | ||
|
|
fda89e9c72 | ||
|
|
d0c8af5621 | ||
|
|
3f34a97880 | ||
|
|
f079ed949c | ||
|
|
ec5c15f190 | ||
|
|
d8ea3ddcc8 | ||
|
|
f69e96b240 | ||
|
|
b6bd3e15c5 | ||
|
|
7f8e7c66f5 | ||
|
|
ebdf5aa223 | ||
|
|
6ee94dae6f | ||
|
|
d05a525d8d | ||
|
|
dd0cf8219e | ||
|
|
951e8cd91a | ||
|
|
202fb19cf6 | ||
|
|
31bb1cc0f9 | ||
|
|
a7084ceb9b | ||
|
|
f4038f7109 | ||
|
|
436b637282 | ||
|
|
fbe16f7b91 | ||
|
|
1cb6128f2f | ||
|
|
bf3e896464 | ||
|
|
c9d54d7110 | ||
|
|
b4d8337ca5 | ||
|
|
709a7e201f | ||
|
|
e1a55e8dec | ||
|
|
8e9c0294fe | ||
|
|
fa42f202fa | ||
|
|
e440de3494 | ||
|
|
98ee83f4a3 | ||
|
|
4cba600268 | ||
|
|
81609e4c6f | ||
|
|
8aacddb9f0 | ||
|
|
275c758da1 | ||
|
|
051ac44759 | ||
|
|
7ed1669050 | ||
|
|
65e603c1ed | ||
|
|
44790eccaf | ||
|
|
39f1ef390e | ||
|
|
c554bfa20d | ||
|
|
e154e4cf75 | ||
|
|
8f78446bff | ||
|
|
9213c4a1ab | ||
|
|
fbcc519098 | ||
|
|
5128b8a409 | ||
|
|
def3f73fdd | ||
|
|
541b9dab52 | ||
|
|
f39106f75c | ||
|
|
eb205f620c | ||
|
|
cc7ed2ba54 | ||
|
|
41ea0e8ef8 | ||
|
|
1d64b61a8f | ||
|
|
7ec67505c5 | ||
|
|
9ee4b39e1b | ||
|
|
5636318eb4 | ||
|
|
21197b53aa | ||
|
|
c197db9c69 | ||
|
|
bdc44ff4cf | ||
|
|
e38aaf3e07 | ||
|
|
17a189a24b | ||
|
|
904c7f9c64 | ||
|
|
90e894b171 | ||
|
|
99a10d8d63 | ||
|
|
f454858bbb | ||
|
|
f8a12a0ec3 | ||
|
|
d7cee95d95 | ||
|
|
e2ce285ec3 | ||
|
|
4a73fbb70a | ||
|
|
4385ce8828 | ||
|
|
59f2ba98a6 | ||
|
|
8576054788 | ||
|
|
729f20ed81 | ||
|
|
c7e6f200da | ||
|
|
36ab31f2f7 | ||
|
|
fe599463ac | ||
|
|
a59021a25e | ||
|
|
ccfcfd8721 | ||
|
|
4df6db141c | ||
|
|
891799c853 | ||
|
|
951392005b | ||
|
|
050ff03b07 | ||
|
|
7555bb6c3c | ||
|
|
325e950bfe | ||
|
|
4db8639bf8 | ||
|
|
31840fa328 | ||
|
|
366b9d1d79 | ||
|
|
a8da79a130 | ||
|
|
dd2a87dbf7 | ||
|
|
4e76975a52 | ||
|
|
bcbff98382 | ||
|
|
41276c950b | ||
|
|
5faad493b4 | ||
|
|
eb5be038fa | ||
|
|
9eb8cec5cf | ||
|
|
537b1689b7 | ||
|
|
b1ac451959 | ||
|
|
f84cc7fb5b | ||
|
|
bc399444ab | ||
|
|
7aee51fd77 | ||
|
|
c0e08c61ee | ||
|
|
42629d6f8d | ||
|
|
999c3c5e76 | ||
|
|
96db16a988 | ||
|
|
aacb9a437a | ||
|
|
96d8f685e9 | ||
|
|
1b42095dc1 | ||
|
|
1c412b4068 | ||
|
|
008c27d547 | ||
|
|
ee70a64e1c | ||
|
|
beb28a1c7d | ||
|
|
5c18ab750b | ||
|
|
6c3ce7adc1 | ||
|
|
a77cd0ab09 | ||
|
|
8ac17400ae | ||
|
|
75220e145b | ||
|
|
cf57e5a7a1 | ||
|
|
10e14103b6 | ||
|
|
96c2a589c0 | ||
|
|
65dba3615c | ||
|
|
375b058a28 | ||
|
|
1012a24afc | ||
|
|
b6a7d831bf | ||
|
|
581176fa90 | ||
|
|
788eaf8a18 | ||
|
|
ff391628de | ||
|
|
1834721880 | ||
|
|
930d502b12 | ||
|
|
3c511f3f40 | ||
|
|
fb0e0e3767 | ||
|
|
a2aeda7b2c | ||
|
|
b7fc909821 | ||
|
|
e43a145614 | ||
|
|
6ed7eaf546 | ||
|
|
eda747c0bf | ||
|
|
f2b5f37b22 | ||
|
|
9f0810f723 | ||
|
|
c9b14c5a45 | ||
|
|
743278d456 | ||
|
|
aa53fa7e15 | ||
|
|
bc2c958a2e | ||
|
|
36001ff931 | ||
|
|
d1603c4329 | ||
|
|
00225b3de3 | ||
|
|
a6925e0d0f | ||
|
|
904b693571 | ||
|
|
069579fd79 | ||
|
|
4851a83a83 | ||
|
|
77eafb9716 | ||
|
|
83f9835e00 | ||
|
|
b303fa9caa | ||
|
|
7b238e0b21 | ||
|
|
fbfd51e97e | ||
|
|
820f914d35 | ||
|
|
423a09e46a | ||
|
|
a69f9729e0 | ||
|
|
d4b4bc71ee | ||
|
|
6e1dd08fbb | ||
|
|
1a1db5a6f1 | ||
|
|
c9cd1a4d75 | ||
|
|
0494862ce5 | ||
|
|
303b246a49 | ||
|
|
e037cafe18 | ||
|
|
942fa7719a | ||
|
|
f7786a42ab | ||
|
|
f4acf404ca | ||
|
|
8e9a62d553 | ||
|
|
865f9d4c7e | ||
|
|
987c7f5be8 | ||
|
|
9d06a80519 | ||
|
|
5281602381 | ||
|
|
f664ffb06b | ||
|
|
d282f14eac | ||
|
|
a41c9d2476 | ||
|
|
ce4f923ba0 | ||
|
|
fc685aa03f | ||
|
|
179ec84684 | ||
|
|
c0e1b3ef2d | ||
|
|
ab0e734e7d | ||
|
|
9a5b5393f5 | ||
|
|
43f9035d07 | ||
|
|
f8cf0f2ab9 | ||
|
|
d2dbc47454 | ||
|
|
e98af7bfc1 | ||
|
|
95769dc9d3 | ||
|
|
e9bf1d2ab8 | ||
|
|
0365d3a3d6 | ||
|
|
2e76a76088 | ||
|
|
216b28ec55 | ||
|
|
26d6088c82 | ||
|
|
b48feb257c | ||
|
|
a212a1bf72 | ||
|
|
4cdc3fdde9 | ||
|
|
6036c95511 | ||
|
|
bc5872dd8f | ||
|
|
dfef1f4921 | ||
|
|
44ed903303 | ||
|
|
fda097fc3b | ||
|
|
6baa8614e6 | ||
|
|
2c2b64d44a | ||
|
|
4198a5c3ec | ||
|
|
0e6c9a96c7 | ||
|
|
060b8e0025 | ||
|
|
921db30c90 | ||
|
|
0fa09adf17 | ||
|
|
c7e85ea28f | ||
|
|
b8d453eec3 | ||
|
|
608f5892f9 | ||
|
|
902fe1f5ce | ||
|
|
1367e6f303 | ||
|
|
2d1ac69986 | ||
|
|
5f3366d60b | ||
|
|
c185730846 | ||
|
|
ffb3e2fcbc | ||
|
|
1f6788ac31 | ||
|
|
b3e9dfcea9 | ||
|
|
d93e0adc4f | ||
|
|
8c7352e668 | ||
|
|
389c7d03b7 | ||
|
|
cc8933c82b | ||
|
|
3c04ca4397 | ||
|
|
2611c7de7e | ||
|
|
616d575fb6 | ||
|
|
c444c4d10b | ||
|
|
db27a885f1 | ||
|
|
9344f7f42f | ||
|
|
728de91140 | ||
|
|
b97589b33e | ||
|
|
66ea288be7 | ||
|
|
9e98c11114 | ||
|
|
2602216039 | ||
|
|
652676dc71 | ||
|
|
cb494c46d7 | ||
|
|
c767545d4c | ||
|
|
ac06060260 | ||
|
|
0404fbc092 | ||
|
|
178e3e2c98 | ||
|
|
4448637727 | ||
|
|
549e8ba668 | ||
|
|
2bdeef7970 | ||
|
|
1d6ed4ef8e | ||
|
|
2bf252afe6 | ||
|
|
13e8720ddc | ||
|
|
eb7e9196b5 | ||
|
|
0c79949cf1 | ||
|
|
ff8a57dc26 | ||
|
|
6aac67aa7e | ||
|
|
397103f9d0 | ||
|
|
73cc1fdd9c | ||
|
|
6e24b0f89d | ||
|
|
53caa84db9 | ||
|
|
657c332a1f | ||
|
|
0fadf0bf70 | ||
|
|
b4bf534d29 | ||
|
|
c4ddc7a3a6 | ||
|
|
78f8d29a4c | ||
|
|
d67b51e91a | ||
|
|
f5c59b1343 | ||
|
|
5afd3e72d6 | ||
|
|
b012681a53 | ||
|
|
036090be91 | ||
|
|
e8501c7d54 | ||
|
|
1dcdb72a49 | ||
|
|
448dba3f78 | ||
|
|
84a812df19 | ||
|
|
9b37e76b14 | ||
|
|
2d3ce89afc | ||
|
|
a687dea898 | ||
|
|
1cab0d09ab | ||
|
|
f01de3a935 | ||
|
|
b2b492447f | ||
|
|
848edc14cb | ||
|
|
1d46070bd5 | ||
|
|
b2a7fb9534 | ||
|
|
b15cfeb0a0 | ||
|
|
ef003db020 | ||
|
|
0b6ef5f291 | ||
|
|
a288b8d318 | ||
|
|
0935ed41d4 | ||
|
|
da404de51e | ||
|
|
2849e19af5 | ||
|
|
6a673a03e4 | ||
|
|
890c6a9983 | ||
|
|
fd380f7545 | ||
|
|
14890890b1 | ||
|
|
ee173077c0 | ||
|
|
e82c909f75 | ||
|
|
178bb900b4 | ||
|
|
79ee8f452c | ||
|
|
848f7423ee | ||
|
|
f4d63158cc | ||
|
|
efb6756cbc | ||
|
|
8a9707c140 | ||
|
|
b99007961f | ||
|
|
a983137978 | ||
|
|
e56e3d78c8 | ||
|
|
cb19a86c44 | ||
|
|
7634673213 | ||
|
|
cc4e55b829 | ||
|
|
7407083624 | ||
|
|
fc12f37105 | ||
|
|
3da5ba4efe | ||
|
|
0ca5c0fcc6 | ||
|
|
8cc9330e63 | ||
|
|
8f9b680fc6 | ||
|
|
0af3c6542d | ||
|
|
5a9adcca2d | ||
|
|
83ec8aa918 | ||
|
|
a0f11f773b | ||
|
|
68e0727894 | ||
|
|
7f8d6b3008 | ||
|
|
ebdadf30d8 | ||
|
|
8c9ace7d40 | ||
|
|
564cc27a1d | ||
|
|
dfe2c16bc7 | ||
|
|
9269de721e | ||
|
|
03a6488464 | ||
|
|
c94b21edd5 | ||
|
|
4128064f87 | ||
|
|
5b8e58fe36 | ||
|
|
7edb352aeb | ||
|
|
0ce6bac7eb | ||
|
|
dd5bb78178 | ||
|
|
0962aec456 | ||
|
|
aa7db727ba | ||
|
|
ad80c3cd7f | ||
|
|
22e12dc139 | ||
|
|
905a16e1df | ||
|
|
fc3e9318d9 | ||
|
|
6a3ff5ca46 | ||
|
|
850e1b11fc | ||
|
|
64f880ba71 | ||
|
|
9d1901fc7c | ||
|
|
d137b04b0a | ||
|
|
ea95f31f99 | ||
|
|
224848163d | ||
|
|
c855b5c889 | ||
|
|
a3409b46b0 | ||
|
|
b693b54a2c | ||
|
|
4480a9bdfb | ||
|
|
f4ea1a2f41 | ||
|
|
d19eb05382 | ||
|
|
83ff1a2ef3 | ||
|
|
6551fdc695 | ||
|
|
db1dcc68ff | ||
|
|
614d90d6ef | ||
|
|
36cbc0defd | ||
|
|
ec99fa2142 | ||
|
|
05cad83c79 | ||
|
|
5decf65d6a | ||
|
|
4320b63922 | ||
|
|
b9c0ecf2b1 | ||
|
|
7175361c97 | ||
|
|
a3cd4f415a | ||
|
|
fd402cb76c | ||
|
|
bd2021411c | ||
|
|
a7071ae7af | ||
|
|
e3320c53f5 | ||
|
|
e261b8edf8 | ||
|
|
c870eeac2e | ||
|
|
304e4e8dce | ||
|
|
6140f29818 | ||
|
|
811da2e285 | ||
|
|
25c731241b | ||
|
|
21eed9ee78 | ||
|
|
06d27a9efa | ||
|
|
e4ed217a3b | ||
|
|
8542e878f7 | ||
|
|
2c35675fd6 | ||
|
|
e2d2c5ff42 | ||
|
|
2ec2a08753 | ||
|
|
ebcac3dd01 | ||
|
|
bf09d91e80 | ||
|
|
20be924bbb | ||
|
|
127cd1295e | ||
|
|
522f67fda0 | ||
|
|
a960fa78cb | ||
|
|
b0fda5f451 | ||
|
|
41893736df | ||
|
|
a6f0b7c7a4 | ||
|
|
1d2017b0fc | ||
|
|
9c06739594 | ||
|
|
0c41ceea9d | ||
|
|
0fe9030eba | ||
|
|
8273eff1a1 | ||
|
|
1ddaee5b4a | ||
|
|
691b733c55 | ||
|
|
042990dda1 | ||
|
|
398f92dc6f | ||
|
|
9c4dfa3343 | ||
|
|
c0d10264bc | ||
|
|
1010ecca8c | ||
|
|
2deef48b84 | ||
|
|
2d1abda9a1 | ||
|
|
8f33bd0768 | ||
|
|
523cbc6723 | ||
|
|
d08b18f5f8 | ||
|
|
fe9d3f16d3 | ||
|
|
4b92349031 | ||
|
|
33a93e5fc5 | ||
|
|
5f9a33564a | ||
|
|
a379a814ba | ||
|
|
6c62b60147 | ||
|
|
be15ee3c03 | ||
|
|
722cc521a9 | ||
|
|
5c8a90fe85 | ||
|
|
6a96ade02c | ||
|
|
8fe2858c6a | ||
|
|
d8bb0b1023 | ||
|
|
58e5c497d0 | ||
|
|
fae8efdc7f | ||
|
|
8cc9195fae | ||
|
|
9dc4183a16 | ||
|
|
039729908d | ||
|
|
3fed4e6dc7 | ||
|
|
0ae45a2835 | ||
|
|
c853ac95ad | ||
|
|
f5cd8c7e4d | ||
|
|
daa8521729 | ||
|
|
a12594fe27 | ||
|
|
1de685949b | ||
|
|
2f74fd6f90 | ||
|
|
4cef8728d7 | ||
|
|
f59859842a | ||
|
|
ee53e81e8e | ||
|
|
7c6ffff198 | ||
|
|
9810c10f8b | ||
|
|
2ec1a4311a | ||
|
|
2116877991 | ||
|
|
9f340b40c2 | ||
|
|
0f15413d47 | ||
|
|
55468735df | ||
|
|
6200d07808 | ||
|
|
0b399fe7bb | ||
|
|
158afdea2b | ||
|
|
3808ecbd1e | ||
|
|
ec6e4f2469 | ||
|
|
0f06140a3d | ||
|
|
7ab018da7b | ||
|
|
51fb02b2d5 | ||
|
|
e8a8bdc58e | ||
|
|
9199023952 | ||
|
|
c428505d4d | ||
|
|
612e64d8e3 | ||
|
|
5b9ee88b52 | ||
|
|
40d4eeab4f | ||
|
|
0f4684da67 | ||
|
|
4bd9866975 | ||
|
|
ca63717124 | ||
|
|
f873834529 | ||
|
|
d8fe7e55db | ||
|
|
ec2a5bf0ee | ||
|
|
be7f3a787c | ||
|
|
d613124cb1 | ||
|
|
64f335380f | ||
|
|
fa95f78e78 | ||
|
|
1e74325c52 | ||
|
|
4e18ea2d04 | ||
|
|
b5218915f8 | ||
|
|
2122f57f51 | ||
|
|
dea73ebecf | ||
|
|
6a2f3d8065 | ||
|
|
72611d1337 | ||
|
|
a09b31b568 | ||
|
|
2808e45b89 | ||
|
|
4a0e70ad53 | ||
|
|
d97fa604e1 | ||
|
|
5a8546519a | ||
|
|
61e52f0bfe | ||
|
|
994b6d687c | ||
|
|
28c5978d81 | ||
|
|
d69caea725 | ||
|
|
ee200c87ea | ||
|
|
2a53043fef | ||
|
|
33c22b8251 | ||
|
|
16505daeea | ||
|
|
8121c1d3c4 | ||
|
|
08afaca518 | ||
|
|
8666b95dd2 | ||
|
|
01e2f8e32c | ||
|
|
5453f3067c | ||
|
|
55b585f3d0 | ||
|
|
939bacc810 | ||
|
|
e26c210d69 | ||
|
|
5141a88a53 | ||
|
|
a95d3e601b | ||
|
|
57b7b91444 | ||
|
|
f877c82029 | ||
|
|
8812844d43 | ||
|
|
92f9194112 | ||
|
|
f2a55d590c | ||
|
|
b3caa1da34 | ||
|
|
21d1d16e74 | ||
|
|
cbe62f076d | ||
|
|
42b2534c46 | ||
|
|
fc9810182e | ||
|
|
507eccc4ec | ||
|
|
a0268d23bb | ||
|
|
58442e7b8b | ||
|
|
6cd6608281 | ||
|
|
5ca3459a0f | ||
|
|
69e70575f9 | ||
|
|
5c8f2a8ae8 | ||
|
|
79e14f88e4 | ||
|
|
b7ead75947 | ||
|
|
2d1e1cb6ed | ||
|
|
4f678fa85c | ||
|
|
66bd9d63dd | ||
|
|
84418738a7 | ||
|
|
49252f6eec | ||
|
|
fe17c4416e | ||
|
|
a21dbf08a8 | ||
|
|
962958c403 | ||
|
|
ab919886ae | ||
|
|
25109671b1 | ||
|
|
fe17d616b9 | ||
|
|
0cd8ee57b8 | ||
|
|
37982e4bb1 | ||
|
|
9717745b83 | ||
|
|
778a6758a5 | ||
|
|
c4e7f1aa97 | ||
|
|
40a8bbf24d | ||
|
|
9ba868a903 | ||
|
|
6df0c28119 | ||
|
|
8fabb6945e | ||
|
|
61d9a6b9cd | ||
|
|
eb4f322c77 | ||
|
|
09dbb07fb8 | ||
|
|
1174c7bdd9 | ||
|
|
a4be282074 | ||
|
|
4497874f31 | ||
|
|
d1bddb6250 | ||
|
|
a9cad7f112 | ||
|
|
b2cdb0d63d | ||
|
|
351f810797 | ||
|
|
700b162233 | ||
|
|
ae47c59dc9 | ||
|
|
88968807b2 | ||
|
|
e3e4c447fa | ||
|
|
50a38df8b1 | ||
|
|
20969f161c | ||
|
|
2e8b374ce8 | ||
|
|
58addf72ff | ||
|
|
b1637df8df | ||
|
|
392370bb23 | ||
|
|
dd0f8e98e8 | ||
|
|
6060a39494 | ||
|
|
9122f58d5d | ||
|
|
6a5d6854bb | ||
|
|
df393e18fe | ||
|
|
be28c4a48f | ||
|
|
c8a9b5f67a | ||
|
|
840847e47c | ||
|
|
fdca96634e | ||
|
|
2f0159a7ab | ||
|
|
36be1fdaef | ||
|
|
bdb9f00c75 | ||
|
|
f80f41d254 | ||
|
|
0f4ae3b727 | ||
|
|
8c21ff66a4 | ||
|
|
5192f946c5 | ||
|
|
72f37a278c | ||
|
|
f8346d21c2 | ||
|
|
8768500844 | ||
|
|
2d3888c710 | ||
|
|
9274d963aa | ||
|
|
03d83db660 | ||
|
|
e32880d9a3 | ||
|
|
2275068c94 | ||
|
|
4f914fafca | ||
|
|
1fa7193901 | ||
|
|
479148f7e0 | ||
|
|
cfbb9209a7 | ||
|
|
9eefbc2036 | ||
|
|
9f873f869a | ||
|
|
6c274cecff | ||
|
|
3e29f9ed5a | ||
|
|
3a606d13f0 | ||
|
|
44ce5f73f7 | ||
|
|
af53a0ecd5 | ||
|
|
c2707bb81b | ||
|
|
ed04b4debd | ||
|
|
69457ef3f1 | ||
|
|
d7e4350d42 | ||
|
|
7b52300287 | ||
|
|
4037112f28 | ||
|
|
64331ffa40 | ||
|
|
3dc4f8a2ff | ||
|
|
e7e0032cc8 | ||
|
|
d88d1d6189 | ||
|
|
cb95986c36 | ||
|
|
6441c9d913 | ||
|
|
6cd678af06 | ||
|
|
d8d862fa68 | ||
|
|
7d7ef18e99 | ||
|
|
f6964b18db | ||
|
|
f96ef96078 | ||
|
|
e42b151561 | ||
|
|
b67542533b | ||
|
|
288c2b5dc9 | ||
|
|
59b932a815 | ||
|
|
0352bdbca5 | ||
|
|
d5e02f069a | ||
|
|
f1183d98a9 | ||
|
|
a84c2a6f31 | ||
|
|
ae71833a12 | ||
|
|
5e5a1bd686 | ||
|
|
d165ea9ea7 | ||
|
|
8783f7a94e | ||
|
|
20842dcc44 | ||
|
|
3331be9cc8 | ||
|
|
adc04196b1 | ||
|
|
a0e1bde594 | ||
|
|
73c37ecd25 | ||
|
|
0c8ca5f930 | ||
|
|
69efb81a12 | ||
|
|
fd0658e0f4 | ||
|
|
0e2e3b3e65 | ||
|
|
999e4cda1d | ||
|
|
a5a78b8f91 | ||
|
|
2424431e16 | ||
|
|
6d48b1c3fb | ||
|
|
8af923c5ff | ||
|
|
68df1d73e7 | ||
|
|
46a6dc6550 | ||
|
|
884e85653f | ||
|
|
c8a2de0243 | ||
|
|
bc564af2fc | ||
|
|
3158c71c29 | ||
|
|
87889904ee | ||
|
|
247c0497b1 | ||
|
|
c99db11ace | ||
|
|
3358f0ab69 | ||
|
|
502ac80b89 | ||
|
|
e5ce91dc5b | ||
|
|
9681f5ca42 | ||
|
|
895407f5e3 | ||
|
|
31d21a14f2 | ||
|
|
423fb9dfb3 | ||
|
|
1d36c49537 | ||
|
|
6b18ff1d97 | ||
|
|
87a41293e8 | ||
|
|
0579604653 | ||
|
|
0f350f5db8 | ||
|
|
9847278699 | ||
|
|
e40c8fff05 | ||
|
|
7a9e1b2b1d | ||
|
|
16de991b07 | ||
|
|
4b3ffd9418 | ||
|
|
cd1ae7f0f2 | ||
|
|
0f4497256b | ||
|
|
24f1bbfb46 | ||
|
|
2b3043bf9f | ||
|
|
1f34dfabd5 | ||
|
|
4178188e15 | ||
|
|
135f0a136e | ||
|
|
85d1bef351 | ||
|
|
a064b59a7d | ||
|
|
2407f8b9ac | ||
|
|
16c8a092ca | ||
|
|
ad6c84924b | ||
|
|
3ffd63a17c | ||
|
|
233b63469a | ||
|
|
fb60f4ad8f | ||
|
|
6388c1885c | ||
|
|
a25aa2fed8 | ||
|
|
4e51448b66 | ||
|
|
5a25ba199a | ||
|
|
aed5b934f8 | ||
|
|
7bc42f89d3 | ||
|
|
3460a31e3a | ||
|
|
f68689b5e4 | ||
|
|
fe42586c6f | ||
|
|
0570592952 | ||
|
|
2e823a4816 | ||
|
|
1e020644e1 | ||
|
|
837df66c19 | ||
|
|
78b238a05b | ||
|
|
60dd475493 | ||
|
|
49b742ab3d | ||
|
|
cfd3b137d8 | ||
|
|
62fb149f08 | ||
|
|
1d6f01ee6c | ||
|
|
13ab63ae09 | ||
|
|
44d3b8fb1a | ||
|
|
0f3dff44ac | ||
|
|
31b2fffbe1 | ||
|
|
8ef3531c48 | ||
|
|
9471f33c38 | ||
|
|
90f2ea87a6 | ||
|
|
62cd57b0d2 | ||
|
|
786ac46fa6 | ||
|
|
9356c1e0ef | ||
|
|
0a622e4440 | ||
|
|
8ca82c8e99 | ||
|
|
956cc0dbfd | ||
|
|
d888addba0 | ||
|
|
44b7f5a5be | ||
|
|
8ab705a14c | ||
|
|
9f736f2192 | ||
|
|
2507780e19 | ||
|
|
8dc1b8f95f | ||
|
|
3ae214b97a | ||
|
|
d3a5201ecc | ||
|
|
7efb9ddd4e | ||
|
|
8b9fd44bbe | ||
|
|
06cd02f769 | ||
|
|
04c09bedeb | ||
|
|
d07fd52c43 | ||
|
|
db3172a750 | ||
|
|
2a4cac024b | ||
|
|
aeac2ea384 | ||
|
|
b53a3b324f | ||
|
|
d17f31c8b0 | ||
|
|
dbfea9b787 | ||
|
|
0032719ab9 | ||
|
|
7e01ac81ab | ||
|
|
e8b0d47765 | ||
|
|
f51e3ab90c | ||
|
|
f8617f6676 | ||
|
|
011231f2ab | ||
|
|
0adc8d9bfa | ||
|
|
e9e028f987 | ||
|
|
4f8db14e5b | ||
|
|
1f5cc059f9 | ||
|
|
ace3bfbbf9 | ||
|
|
9e85b0c2ba | ||
|
|
c3f3392f0c | ||
|
|
81f5a29526 | ||
|
|
289286c8cd | ||
|
|
0dced8d29c | ||
|
|
cbccf932a7 | ||
|
|
ce55d9e364 | ||
|
|
b9fb7cc3a5 | ||
|
|
5df5a001a1 | ||
|
|
13a2612e20 | ||
|
|
647558c98a | ||
|
|
eaea160f0e | ||
|
|
1544467725 | ||
|
|
ab4eb1dd20 | ||
|
|
09d8c31433 | ||
|
|
d369fa094a | ||
|
|
6e9c0a0fda | ||
|
|
60c8d5dcc0 | ||
|
|
018d4653e8 | ||
|
|
46512f34e4 | ||
|
|
6eb4addb6e | ||
|
|
8cfd6ffae0 | ||
|
|
b12de14482 | ||
|
|
4356795324 | ||
|
|
7949d3209b | ||
|
|
850568b8e9 | ||
|
|
0e8e8ef546 | ||
|
|
6d7ce6cec1 | ||
|
|
49baba017a | ||
|
|
a2427c64a1 | ||
|
|
94dcadbec7 | ||
|
|
81a1f26b1d | ||
|
|
7734ec3bd5 | ||
|
|
2a1c101350 | ||
|
|
0e2bdb8e66 | ||
|
|
4fa75256b7 | ||
|
|
72e8cd7e78 | ||
|
|
2e9a3e6d12 | ||
|
|
f4c75e61ad | ||
|
|
a4916a3c00 | ||
|
|
14edd7e357 | ||
|
|
6c954d7e04 | ||
|
|
fc2a1fce8b | ||
|
|
2ce430d608 | ||
|
|
a0b5a3a8a2 | ||
|
|
487d948ad3 | ||
|
|
1da3c7f577 | ||
|
|
f32dc9e84e | ||
|
|
af941bfdf5 | ||
|
|
b1f84676d1 | ||
|
|
8c6f93b899 | ||
|
|
839141e4f6 | ||
|
|
c6acc4c5be | ||
|
|
c4fc0f3808 | ||
|
|
724ac3cf59 | ||
|
|
e96d2212da | ||
|
|
c8d3553a31 | ||
|
|
bbb2b36794 | ||
|
|
172a9c7e1e | ||
|
|
51d494a271 | ||
|
|
b7b3b3a19c | ||
|
|
63c4794c30 | ||
|
|
e6dbe87ee2 | ||
|
|
7ce980815c | ||
|
|
52cfec5bc1 | ||
|
|
b0c82aac6a | ||
|
|
a4f6b17559 | ||
|
|
6d22e06359 | ||
|
|
75e5dca735 | ||
|
|
fa3f87492c | ||
|
|
8077a71aec | ||
|
|
c6578384fb | ||
|
|
ada697c6b0 | ||
|
|
945859ae4d | ||
|
|
d5e605d5cc | ||
|
|
aa3589004e | ||
|
|
f225d8dea5 | ||
|
|
44e727b75c | ||
|
|
2afe8989df | ||
|
|
a6d80b78de | ||
|
|
6829c5ef8f | ||
|
|
0381018d00 | ||
|
|
c0ee50a693 | ||
|
|
b9cfb6b59b | ||
|
|
2d9bf73049 | ||
|
|
ac03c91dcc | ||
|
|
79493985be | ||
|
|
a371bcb624 | ||
|
|
4798c029de | ||
|
|
d7ad1f3950 | ||
|
|
46d9d296ca | ||
|
|
3b15285a0c | ||
|
|
ff5a52b445 | ||
|
|
49da81f681 | ||
|
|
ea7d535ae7 | ||
|
|
d61ddaccb6 | ||
|
|
3f411fc93b | ||
|
|
0f44dd6ab0 | ||
|
|
858b454138 | ||
|
|
3f104833ba | ||
|
|
0453c4a7bf | ||
|
|
630af6a9c6 | ||
|
|
ca7a0da10f | ||
|
|
4b0cbc61d1 | ||
|
|
c08d862e9e | ||
|
|
cfa442a42a | ||
|
|
b143b1be42 | ||
|
|
4fab29b648 | ||
|
|
a63d631435 | ||
|
|
ba34ed89d3 | ||
|
|
c149e956cc | ||
|
|
e5717d3e96 | ||
|
|
13212f06b4 | ||
|
|
a0629bfc58 | ||
|
|
1ded171720 | ||
|
|
69c315443a | ||
|
|
566e701131 | ||
|
|
9c11c42ec2 | ||
|
|
2f88b6ef9b | ||
|
|
4252d9786b | ||
|
|
09e4775a10 | ||
|
|
cbb6269391 | ||
|
|
ed922deb93 | ||
|
|
bd9dd90649 | ||
|
|
6f22baa0f6 | ||
|
|
2326b5faf3 | ||
|
|
d90cc6f4cf | ||
|
|
5dfe77b7c3 | ||
|
|
5bba5b2fb7 | ||
|
|
514d25bdd4 | ||
|
|
317e24ce69 | ||
|
|
a6e153312c | ||
|
|
e41c027c9a | ||
|
|
1f26353de4 | ||
|
|
682a278cb8 | ||
|
|
558203e2bb | ||
|
|
bb5681fdb5 | ||
|
|
862631b2ec | ||
|
|
4acb95acb5 | ||
|
|
46ce9a6946 | ||
|
|
15e392bbd1 | ||
|
|
c851e9d206 | ||
|
|
96bd8cb3c2 | ||
|
|
534e8a5c50 | ||
|
|
a614419b43 | ||
|
|
4844d720cc | ||
|
|
0e693c39a3 | ||
|
|
5c993ce83f | ||
|
|
2b153d5c10 | ||
|
|
417b430033 | ||
|
|
59240a4bd9 | ||
|
|
bf21cfd6e0 | ||
|
|
9c4ec902b0 | ||
|
|
e43cc65702 | ||
|
|
1dae687e7d | ||
|
|
590954e9a8 | ||
|
|
c5bf76578a | ||
|
|
ca738a9536 | ||
|
|
174068c462 | ||
|
|
e784d1846e | ||
|
|
93ec81d2eb | ||
|
|
1d1da326be | ||
|
|
3a3720db8d | ||
|
|
41ad637bad | ||
|
|
9d186cfc66 | ||
|
|
27a44f3282 | ||
|
|
b70c52e41f | ||
|
|
6f0e4c4deb | ||
|
|
5bc6c07f9e | ||
|
|
c9545f291a | ||
|
|
fdf098d65c | ||
|
|
3f03b05bd3 | ||
|
|
643e3587cc | ||
|
|
15bfd4439a | ||
|
|
33c3ba815f | ||
|
|
e6001f57fa | ||
|
|
cf04157ec8 | ||
|
|
5e6db3d4a6 | ||
|
|
fb520e3040 | ||
|
|
a802e7fb71 | ||
|
|
a67382fdec | ||
|
|
2cad64881d | ||
|
|
21b88995ab | ||
|
|
483218e491 | ||
|
|
f053d79994 | ||
|
|
bdf76f23c4 | ||
|
|
19db4304bd | ||
|
|
f3f2379e5a | ||
|
|
f54267eab4 | ||
|
|
0980446836 | ||
|
|
45958e630d | ||
|
|
cb4c840d3b | ||
|
|
6a4c1b138f | ||
|
|
7febd846e8 | ||
|
|
2ed027219c | ||
|
|
cc2f607be3 | ||
|
|
1df13e0bc9 | ||
|
|
f6c263b54d | ||
|
|
1273ac9647 | ||
|
|
751ff48301 | ||
|
|
1728b77b2c | ||
|
|
cbaa676c3d | ||
|
|
a4931568ba | ||
|
|
2b878f863c | ||
|
|
ea9194e1fb | ||
|
|
a236400785 | ||
|
|
26e3d2cf5d | ||
|
|
b6d12fe7f3 | ||
|
|
67f9474e2e | ||
|
|
fd1866b838 | ||
|
|
e2aa3518df | ||
|
|
ecfc2236a6 | ||
|
|
29f25ebeb9 |
2
.idea/artifacts/KotlinPlugin.xml
generated
2
.idea/artifacts/KotlinPlugin.xml
generated
@@ -72,6 +72,7 @@
|
||||
</element>
|
||||
<element id="archive" name="android-extensions-compiler.jar">
|
||||
<element id="module-output" name="android-extensions-compiler" />
|
||||
<element id="module-output" name="android-extensions-runtime" />
|
||||
</element>
|
||||
<element id="archive" name="android-lint.jar">
|
||||
<element id="module-output" name="uast-kotlin" />
|
||||
@@ -105,6 +106,7 @@
|
||||
<element id="library" level="project" name="uast-java" />
|
||||
<element id="library" level="project" name="kotlinx-coroutines-core" />
|
||||
<element id="library" level="project" name="javaslang" />
|
||||
<element id="library" level="project" name="kotlinx-coroutines-jdk8" />
|
||||
</element>
|
||||
<element id="directory" name="kotlinc">
|
||||
<element id="dir-copy" path="$PROJECT_DIR$/dist/kotlinc" />
|
||||
|
||||
9
.idea/libraries/android_layoutlib.xml
generated
Normal file
9
.idea/libraries/android_layoutlib.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="android-layoutlib">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/layoutlib.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
1
.idea/libraries/android_plugin.xml
generated
1
.idea/libraries/android_plugin.xml
generated
@@ -6,7 +6,6 @@
|
||||
<CLASSES>
|
||||
<root url="file://$PROJECT_DIR$/ideaSDK/plugins/android/lib" />
|
||||
<root url="file://$PROJECT_DIR$/ideaSDK/plugins/android/lib/jps" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/android-common.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
|
||||
1
.idea/libraries/coverage_plugin.xml
generated
1
.idea/libraries/coverage_plugin.xml
generated
@@ -3,7 +3,6 @@
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/coverage/lib/coverage.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/coverage/lib/jacocoant.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/coverage/lib/coverage-agent.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
|
||||
2
.idea/libraries/intellij_core.xml
generated
2
.idea/libraries/intellij_core.xml
generated
@@ -18,12 +18,14 @@
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/util.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/xpp3-1.1.4-min.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/xstream-1.4.8.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/jsr305.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/guava-19.0-sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/asm-src.zip!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/jsr305.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
11
.idea/libraries/jps.xml
generated
11
.idea/libraries/jps.xml
generated
@@ -9,17 +9,6 @@
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/antLayout/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/jps-builders/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/jps-builders/testSrc" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/jps-launcher/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/model-api/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/model-impl/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/model-impl/testSrc" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/model-serialization/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/model-serialization/testSrc" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/plugin-system/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/jps/standalone-builder/src" />
|
||||
</SOURCES>
|
||||
<jarDirectory url="file://$PROJECT_DIR$/ideaSDK/jps" recursive="false" />
|
||||
</library>
|
||||
|
||||
9
.idea/libraries/json_org.xml
generated
Normal file
9
.idea/libraries/json_org.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="json-org">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/json-org.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
5
.idea/libraries/kotlin_reflect.xml
generated
5
.idea/libraries/kotlin_reflect.xml
generated
@@ -4,6 +4,9 @@
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
<SOURCES>
|
||||
<root url="file://$PROJECT_DIR$/core/reflection.jvm/src" />
|
||||
<root url="file://$PROJECT_DIR$/core/descriptors.runtime/src" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
6
.idea/libraries/kotlin_test.xml
generated
6
.idea/libraries/kotlin_test.xml
generated
@@ -1,13 +1,13 @@
|
||||
<component name="libraryTable">
|
||||
<library name="kotlin-test">
|
||||
<CLASSES>
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test.jar!/"/>
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/shared/src/main/kotlin" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/shared/src/main/kotlin.jvm" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/junit/src/main/kotlin" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/common/src/main/kotlin" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/jvm/src/main/kotlin" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
11
.idea/libraries/kotlinx_coroutines_jdk8.xml
generated
Normal file
11
.idea/libraries/kotlinx_coroutines_jdk8.xml
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="kotlinx-coroutines-jdk8">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/kotlinx-coroutines-jdk8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/kotlinx-coroutines-jdk8-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
7
.idea/libraries/trove4j.xml
generated
7
.idea/libraries/trove4j.xml
generated
@@ -7,11 +7,6 @@
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/trove4j.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/src/trove4j_src.jar!/core/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/src/trove4j_src.jar!/generated/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/src/trove4j_src.jar!/test/src" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/src/trove4j_src.jar!/util/src" />
|
||||
</SOURCES>
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
13
.idea/modules.xml
generated
13
.idea/modules.xml
generated
@@ -9,11 +9,11 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/android-extensions/android-extensions-compiler/android-extensions-compiler.iml" filepath="$PROJECT_DIR$/plugins/android-extensions/android-extensions-compiler/android-extensions-compiler.iml" group="plugins/android-extensions" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/android-extensions/android-extensions-idea/android-extensions-idea.iml" filepath="$PROJECT_DIR$/plugins/android-extensions/android-extensions-idea/android-extensions-idea.iml" group="plugins/android-extensions" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/android-extensions/android-extensions-jps/android-extensions-jps.iml" filepath="$PROJECT_DIR$/plugins/android-extensions/android-extensions-jps/android-extensions-jps.iml" group="plugins/android-extensions" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/android-extensions/android-extensions-runtime/android-extensions-runtime.iml" filepath="$PROJECT_DIR$/plugins/android-extensions/android-extensions-runtime/android-extensions-runtime.iml" group="plugins/android-extensions" />
|
||||
<module fileurl="file://$PROJECT_DIR$/android-studio/android-studio.iml" filepath="$PROJECT_DIR$/android-studio/android-studio.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/android-tests/android-tests.iml" filepath="$PROJECT_DIR$/compiler/android-tests/android-tests.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/annotation-based-compiler-plugins-ide-support/annotation-based-compiler-plugins-ide-support.iml" filepath="$PROJECT_DIR$/plugins/annotation-based-compiler-plugins-ide-support/annotation-based-compiler-plugins-ide-support.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/annotation-collector/annotation-collector.iml" filepath="$PROJECT_DIR$/plugins/annotation-collector/annotation-collector.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/annotation-processing/annotation-processing.iml" filepath="$PROJECT_DIR$/plugins/annotation-processing/annotation-processing.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/ant/ant.iml" filepath="$PROJECT_DIR$/ant/ant.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/backend/backend.iml" filepath="$PROJECT_DIR$/compiler/backend/backend.iml" group="compiler/java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/backend-common/backend-common.iml" filepath="$PROJECT_DIR$/compiler/backend-common/backend-common.iml" group="compiler" />
|
||||
@@ -63,7 +63,6 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" group="compiler/ir" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.tree/ir.tree.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.tree/ir.tree.iml" group="compiler/ir" />
|
||||
<module fileurl="file://$PROJECT_DIR$/j2k/j2k.iml" filepath="$PROJECT_DIR$/j2k/j2k.iml" group="j2k" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/java-model-wrappers/java-model-wrappers.iml" filepath="$PROJECT_DIR$/plugins/java-model-wrappers/java-model-wrappers.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/javac-wrapper/javac-wrapper.iml" filepath="$PROJECT_DIR$/compiler/javac-wrapper/javac-wrapper.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps-plugin/jps-plugin.iml" filepath="$PROJECT_DIR$/jps-plugin/jps-plugin.iml" group="ide/jps" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps-plugin/jps-tests/jps-tests.iml" filepath="$PROJECT_DIR$/jps-plugin/jps-tests/jps-tests.iml" group="ide/jps" />
|
||||
@@ -76,14 +75,14 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/js/js.tests/js.tests.iml" filepath="$PROJECT_DIR$/js/js.tests/js.tests.iml" group="compiler/js" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js/js.translator/js.translator.iml" filepath="$PROJECT_DIR$/js/js.translator/js.translator.iml" group="compiler/js" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" filepath="$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" group="ide/jps" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/kapt3/kapt3.iml" filepath="$PROJECT_DIR$/plugins/kapt3/kapt3.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/kapt3/kapt3.iml" filepath="$PROJECT_DIR$/plugins/kapt3/kapt3.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/kotlin-gradle-tooling/kotlin-gradle-tooling.iml" filepath="$PROJECT_DIR$/idea/kotlin-gradle-tooling/kotlin-gradle-tooling.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/light-classes/light-classes.iml" filepath="$PROJECT_DIR$/compiler/light-classes/light-classes.iml" group="compiler/java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/lint/lint-api/lint-api.iml" filepath="$PROJECT_DIR$/plugins/lint/lint-api/lint-api.iml" group="plugins/lint" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/lint/lint-checks/lint-checks.iml" filepath="$PROJECT_DIR$/plugins/lint/lint-checks/lint-checks.iml" group="plugins/lint" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/lint/lint-idea/lint-idea.iml" filepath="$PROJECT_DIR$/plugins/lint/lint-idea/lint-idea.iml" group="plugins/lint" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/noarg/noarg-cli/noarg-cli.iml" filepath="$PROJECT_DIR$/plugins/noarg/noarg-cli/noarg-cli.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/noarg/noarg-ide/noarg-ide.iml" filepath="$PROJECT_DIR$/plugins/noarg/noarg-ide/noarg-ide.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/noarg/noarg-cli/noarg-cli.iml" filepath="$PROJECT_DIR$/plugins/noarg/noarg-cli/noarg-cli.iml" group="plugins/noarg" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/noarg/noarg-ide/noarg-ide.iml" filepath="$PROJECT_DIR$/plugins/noarg/noarg-ide/noarg-ide.iml" group="plugins/noarg" />
|
||||
<module fileurl="file://$PROJECT_DIR$/non-compiler-tests/non-compiler-tests.iml" filepath="$PROJECT_DIR$/non-compiler-tests/non-compiler-tests.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" filepath="$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/plugins-tests/plugins-tests.iml" filepath="$PROJECT_DIR$/plugins/plugins-tests/plugins-tests.iml" group="plugins" />
|
||||
@@ -91,8 +90,8 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/core/reflection.jvm/reflection.jvm.iml" filepath="$PROJECT_DIR$/core/reflection.jvm/reflection.jvm.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/resolution/resolution.iml" filepath="$PROJECT_DIR$/compiler/resolution/resolution.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" filepath="$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-cli/sam-with-receiver-cli.iml" filepath="$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-cli/sam-with-receiver-cli.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-ide/sam-with-receiver-ide.iml" filepath="$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-ide/sam-with-receiver-ide.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-cli/sam-with-receiver-cli.iml" filepath="$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-cli/sam-with-receiver-cli.iml" group="plugins/sam-with-receiver" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-ide/sam-with-receiver-ide.iml" filepath="$PROJECT_DIR$/plugins/sam-with-receiver/sam-with-receiver-ide/sam-with-receiver-ide.iml" group="plugins/sam-with-receiver" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/script.runtime/script.runtime.iml" filepath="$PROJECT_DIR$/core/script.runtime/script.runtime.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/serialization/serialization.iml" filepath="$PROJECT_DIR$/compiler/serialization/serialization.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/source-sections/source-sections-compiler/source-sections-compiler.iml" filepath="$PROJECT_DIR$/plugins/source-sections/source-sections-compiler/source-sections-compiler.iml" group="plugins" />
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="org.jetbrains.kotlin.codegen.CodegenJdkCommonTestSuite" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-Dkotlin.test.default.jvm.target=1.6 -ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED" />
|
||||
<option name="VM_PARAMETERS" value="-Dkotlin.test.default.jvm.target=1.6 -ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="org.jetbrains.kotlin.codegen.CodegenJdkCommonTestSuite" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-Dkotlin.test.default.jvm.target=1.8 -ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED" />
|
||||
<option name="VM_PARAMETERS" value="-Dkotlin.test.default.jvm.target=1.8 -ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="org.jetbrains.kotlin.codegen.CodegenJdkCommonTestSuite" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-Dkotlin.test.default.jvm.target=1.8 -Dkotlin.test.substitute.bytecode.1.8.to.1.9=true -ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED" />
|
||||
<option name="VM_PARAMETERS" value="-Dkotlin.test.default.jvm.target=1.8 -Dkotlin.test.substitute.bytecode.1.8.to.1.9=true -ea -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m -Djna.nosys=true --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
|
||||
2
.idea/runConfigurations/Js_backend_tests.xml
generated
2
.idea/runConfigurations/Js_backend_tests.xml
generated
@@ -8,7 +8,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="package" />
|
||||
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1250m -XX:+UseCodeCacheFlushing -Djna.nosys=true -Dkotlin.js.generateThreshold=true" />
|
||||
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx1250m -XX:+UseCodeCacheFlushing -Djna.nosys=true -Dkotlin.js.skipMinificationTest=false" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
|
||||
736
ChangeLog.md
736
ChangeLog.md
@@ -3,9 +3,400 @@
|
||||
<!-- Find: ([^\`/\[])(KT-\d+) -->
|
||||
<!-- Replace: $1[`$2`](https://youtrack.jetbrains.com/issue/$2) -->
|
||||
|
||||
## 1.1.3
|
||||
## 1.1.4-EAP-11
|
||||
|
||||
### Android
|
||||
|
||||
- [`KT-11048`](https://youtrack.jetbrains.com/issue/KT-11048) Android Extensions: cannot evaluate expression containing generated properties
|
||||
- [`KT-11051`](https://youtrack.jetbrains.com/issue/KT-11051) Android Extensions: completion of generated properties is unclear for ambiguous ids
|
||||
- [`KT-14912`](https://youtrack.jetbrains.com/issue/KT-14912) Lint: "Code contains STOPSHIP marker" ignores suppress annotation
|
||||
- [`KT-15164`](https://youtrack.jetbrains.com/issue/KT-15164) Kotlin Lint: problems in delegate expression are not reported
|
||||
- [`KT-17783`](https://youtrack.jetbrains.com/issue/KT-17783) Kotlin Lint: quick fixes to add inapplicable @RequiresApi and @SuppressLint make code incompilable
|
||||
- [`KT-17786`](https://youtrack.jetbrains.com/issue/KT-17786) Kotlin Lint: "Surround with if()" quick fix is not suggested for single expression `get()`
|
||||
- [`KT-17787`](https://youtrack.jetbrains.com/issue/KT-17787) Kotlin Lint: "Add @TargetApi" quick fix is not suggested for top level property accessor
|
||||
- [`KT-17788`](https://youtrack.jetbrains.com/issue/KT-17788) Kotlin Lint: "Surround with if()" quick fix corrupts code in case of destructuring declaration
|
||||
- [`KT-17890`](https://youtrack.jetbrains.com/issue/KT-17890) [kotlin-android-extensions] Renaming layout file does not rename import
|
||||
|
||||
### Compiler
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-10942`](https://youtrack.jetbrains.com/issue/KT-10942) Support meta-annotations from JSR 305 for nullability qualifiers
|
||||
- [`KT-14187`](https://youtrack.jetbrains.com/issue/KT-14187) Redundant "is" check is not detected
|
||||
- [`KT-16603`](https://youtrack.jetbrains.com/issue/KT-16603) Support `inline suspend` function
|
||||
- [`KT-17585`](https://youtrack.jetbrains.com/issue/KT-17585) Generate state machine for named functions in their bodies
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-3098`](https://youtrack.jetbrains.com/issue/KT-3098) Generate efficient comparisons
|
||||
- [`KT-6247`](https://youtrack.jetbrains.com/issue/KT-6247) Optimization for 'in' and '..'
|
||||
- [`KT-7571`](https://youtrack.jetbrains.com/issue/KT-7571) Don't box Double instance to call hashCode on Java 8
|
||||
- [`KT-9900`](https://youtrack.jetbrains.com/issue/KT-9900) Optimize range operations for 'until' extension from stdlib
|
||||
- [`KT-11959`](https://youtrack.jetbrains.com/issue/KT-11959) Unnceessary boxing/unboxing due to Comparable.compareTo
|
||||
- [`KT-12158`](https://youtrack.jetbrains.com/issue/KT-12158) Optimize away boxing when comparing nullable primitive type value to primitive value
|
||||
- [`KT-13682`](https://youtrack.jetbrains.com/issue/KT-13682) Reuse StringBuilder for concatenation and string interpolation
|
||||
- [`KT-15235`](https://youtrack.jetbrains.com/issue/KT-15235) Escaped characters in template strings are generating inefficient implementations
|
||||
- [`KT-17280`](https://youtrack.jetbrains.com/issue/KT-17280) Inline constant expressions in string templates
|
||||
- [`KT-17903`](https://youtrack.jetbrains.com/issue/KT-17903) Generate 'for-in-indices' as a precondition loop
|
||||
- [`KT-18157`](https://youtrack.jetbrains.com/issue/KT-18157) Optimize out trivial INSTANCEOF checks
|
||||
- [`KT-18162`](https://youtrack.jetbrains.com/issue/KT-18162) Do not check nullability assertions twice for effectively same value
|
||||
- [`KT-18164`](https://youtrack.jetbrains.com/issue/KT-18164) Do not check nullability for values that have been already checked with !!
|
||||
- [`KT-18478`](https://youtrack.jetbrains.com/issue/KT-18478) Unnecessary nullification of bound variables
|
||||
- [`KT-18558`](https://youtrack.jetbrains.com/issue/KT-18558) Flatten nested string concatenation
|
||||
- [`KT-18777`](https://youtrack.jetbrains.com/issue/KT-18777) Unnecessary boolean negation generated for 'if (expr !in range)'
|
||||
#### Fixes
|
||||
|
||||
- [`KT-1809`](https://youtrack.jetbrains.com/issue/KT-1809) Confusing diagnostics when wrong number of type arguments are specified and there are several callee candiates
|
||||
- [`KT-2007`](https://youtrack.jetbrains.com/issue/KT-2007) Improve diagnostics when + in not resolved on a pair of nullable ints
|
||||
- [`KT-5066`](https://youtrack.jetbrains.com/issue/KT-5066) Bad diagnostic message for ABSTRACT_MEMBER_NOT_IMPLEMENTED for (companion) object
|
||||
- [`KT-5511`](https://youtrack.jetbrains.com/issue/KT-5511) Inconsistent handling of inner enum
|
||||
- [`KT-7773`](https://youtrack.jetbrains.com/issue/KT-7773) Disallow to explicitly extend Enum<E> class
|
||||
- [`KT-7975`](https://youtrack.jetbrains.com/issue/KT-7975) Unclear error message when redundant type arguments supplied
|
||||
- [`KT-8340`](https://youtrack.jetbrains.com/issue/KT-8340) vararg in a property setter must be an error
|
||||
- [`KT-8612`](https://youtrack.jetbrains.com/issue/KT-8612) Incorrect error message for var extension property without getter or setter
|
||||
- [`KT-8829`](https://youtrack.jetbrains.com/issue/KT-8829) Type parameter of a class is not resolved in the constructor parameter's default value
|
||||
- [`KT-8845`](https://youtrack.jetbrains.com/issue/KT-8845) Bogus diagnostic on infix operation "in"
|
||||
- [`KT-9282`](https://youtrack.jetbrains.com/issue/KT-9282) Improve diagnostic on overload resolution ambiguity when a nullable argument is passed to non-null parameter
|
||||
- [`KT-10045`](https://youtrack.jetbrains.com/issue/KT-10045) Not specific enough compiler error message in case of trying to call overloaded private methods
|
||||
- [`KT-10164`](https://youtrack.jetbrains.com/issue/KT-10164) Incorrect error message for external inline method
|
||||
- [`KT-10248`](https://youtrack.jetbrains.com/issue/KT-10248) Smart casts: Misleading error on overloaded function call
|
||||
- [`KT-10657`](https://youtrack.jetbrains.com/issue/KT-10657) Confusing diagnostic when trying to invoke value as a function
|
||||
- [`KT-10839`](https://youtrack.jetbrains.com/issue/KT-10839) Weird diagnostics on callable reference of unresolved class
|
||||
- [`KT-11119`](https://youtrack.jetbrains.com/issue/KT-11119) Confusing error message when overloaded method is called on nullable receiver
|
||||
- [`KT-12408`](https://youtrack.jetbrains.com/issue/KT-12408) Generic information lost for override values
|
||||
- [`KT-13749`](https://youtrack.jetbrains.com/issue/KT-13749) Error highlighting range for no 'override' modifier is bigger than needed
|
||||
- [`KT-14598`](https://youtrack.jetbrains.com/issue/KT-14598) Do not report "member is final and cannot be overridden" when overriding something from final class
|
||||
- [`KT-14633`](https://youtrack.jetbrains.com/issue/KT-14633) "If must have both main and else branches" diagnostic range is too high
|
||||
- [`KT-14647`](https://youtrack.jetbrains.com/issue/KT-14647) Confusing error message "'@receiver:' annotations could be applied only to extension function or extension property declarations"
|
||||
- [`KT-14927`](https://youtrack.jetbrains.com/issue/KT-14927) TCE in QualifiedExpressionResolver
|
||||
- [`KT-15243`](https://youtrack.jetbrains.com/issue/KT-15243) Report deprecation on usages of type alias expanded to a deprecated class
|
||||
- [`KT-15804`](https://youtrack.jetbrains.com/issue/KT-15804) Prohibit having duplicate parameter names in functional types
|
||||
- [`KT-15810`](https://youtrack.jetbrains.com/issue/KT-15810) destructuring declarations don't work in scripts on the top level
|
||||
- [`KT-15931`](https://youtrack.jetbrains.com/issue/KT-15931) IllegalStateException: ClassDescriptor of superType should not be null: T by a
|
||||
- [`KT-16016`](https://youtrack.jetbrains.com/issue/KT-16016) Compiler failure with NO_EXPECTED_TYPE
|
||||
- [`KT-16448`](https://youtrack.jetbrains.com/issue/KT-16448) Inline suspend functions with inlined suspend invocations are miscompiled (VerifyError, ClassNotFound)
|
||||
- [`KT-16576`](https://youtrack.jetbrains.com/issue/KT-16576) Wrong code generated with skynet benchmark
|
||||
- [`KT-17007`](https://youtrack.jetbrains.com/issue/KT-17007) Kotlin is not optimizing away unreachable code based on const vals
|
||||
- [`KT-17188`](https://youtrack.jetbrains.com/issue/KT-17188) Do not propose to specify constructor invocation for classes without an accessible constructor
|
||||
- [`KT-17611`](https://youtrack.jetbrains.com/issue/KT-17611) Unnecessary "Name shadowed" warning on parameter of local function or local class member
|
||||
- [`KT-17692`](https://youtrack.jetbrains.com/issue/KT-17692) NPE in compiler when calling KClass.java on function result of type Unit
|
||||
- [`KT-17820`](https://youtrack.jetbrains.com/issue/KT-17820) False "useless cast" when target type is flexible
|
||||
- [`KT-17972`](https://youtrack.jetbrains.com/issue/KT-17972) Anonymous class generated from lambda captures its outer and tries to set nonexistent this$0 field.
|
||||
- [`KT-18029`](https://youtrack.jetbrains.com/issue/KT-18029) typealias not working in .kts files
|
||||
- [`KT-18085`](https://youtrack.jetbrains.com/issue/KT-18085) Compilation Error:Kotlin: [Internal Error] kotlin.TypeCastException: null cannot be cast to non-null type com.intellij.psi.PsiElement
|
||||
- [`KT-18115`](https://youtrack.jetbrains.com/issue/KT-18115) Generic inherited classes in different packages with coroutine causes java.lang.VerifyError: Bad local variable type
|
||||
- [`KT-18189`](https://youtrack.jetbrains.com/issue/KT-18189) Incorrect generic signature generated for implementation methods overriding special built-ins
|
||||
- [`KT-18234`](https://youtrack.jetbrains.com/issue/KT-18234) Top-level variables in script aren't local variables
|
||||
- [`KT-18413`](https://youtrack.jetbrains.com/issue/KT-18413) Strange compiler error - probably incremental compiler
|
||||
- [`KT-18486`](https://youtrack.jetbrains.com/issue/KT-18486) Superfluos generation of suspend function state-machine because of inner suspension of different coroutine
|
||||
- [`KT-18598`](https://youtrack.jetbrains.com/issue/KT-18598) Report error on access to declarations from non-exported packages and from inaccessible modules on Java 9
|
||||
- [`KT-18702`](https://youtrack.jetbrains.com/issue/KT-18702) Proguard warning with Kotlin 1.2-M1
|
||||
- [`KT-18728`](https://youtrack.jetbrains.com/issue/KT-18728) Integer method reference application fails with CompilationException: Back-end (JVM) Internal error
|
||||
- [`KT-18845`](https://youtrack.jetbrains.com/issue/KT-18845) Exception on building gradle project with collection literals
|
||||
|
||||
### IDE
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-2638`](https://youtrack.jetbrains.com/issue/KT-2638) Inline property (with accessors) refactoring
|
||||
- [`KT-7107`](https://youtrack.jetbrains.com/issue/KT-7107) Rename refactoring for labels
|
||||
- [`KT-9818`](https://youtrack.jetbrains.com/issue/KT-9818) Code style for method expression bodies
|
||||
- [`KT-14965`](https://youtrack.jetbrains.com/issue/KT-14965) "Configure Kotlin in project" should support build.gradle.kts
|
||||
- [`KT-15504`](https://youtrack.jetbrains.com/issue/KT-15504) Add code style options to limit number of blank lines
|
||||
- [`KT-16558`](https://youtrack.jetbrains.com/issue/KT-16558) Code Style: Add Options for "Spaces Before Parentheses"
|
||||
- [`KT-18113`](https://youtrack.jetbrains.com/issue/KT-18113) Add new line options to code style for method parameters
|
||||
- [`KT-18605`](https://youtrack.jetbrains.com/issue/KT-18605) Option to not use continuation indent in chained calls
|
||||
- [`KT-18607`](https://youtrack.jetbrains.com/issue/KT-18607) Options to put blank lines between 'when' branches
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-17751`](https://youtrack.jetbrains.com/issue/KT-17751) Kotlin slows down java inspections big time
|
||||
#### Fixes
|
||||
|
||||
- [`KT-6610`](https://youtrack.jetbrains.com/issue/KT-6610) Language injection doesn't work with String Interpolation
|
||||
- [`KT-8893`](https://youtrack.jetbrains.com/issue/KT-8893) Quick documentation shows type for top-level object-type elements, but "no name provided" for local ones
|
||||
- [`KT-9359`](https://youtrack.jetbrains.com/issue/KT-9359) "Accidental override" error message does not mention class (type) names
|
||||
- [`KT-10736`](https://youtrack.jetbrains.com/issue/KT-10736) Highlighting usages doesn't work for synthetic properties created by the Android Extensions
|
||||
- [`KT-11980`](https://youtrack.jetbrains.com/issue/KT-11980) Spring: Generate Constructor, Setter Dependency in XML for Kotlin class: IOE at LightElement.add()
|
||||
- [`KT-12123`](https://youtrack.jetbrains.com/issue/KT-12123) Formatter: always indent after newline in variable initialization
|
||||
- [`KT-12910`](https://youtrack.jetbrains.com/issue/KT-12910) spring: create init-method/destroy-method from usage results in IOE
|
||||
- [`KT-13072`](https://youtrack.jetbrains.com/issue/KT-13072) Kotlin struggles to index JDK 9 classes
|
||||
- [`KT-13099`](https://youtrack.jetbrains.com/issue/KT-13099) formatting in angle brackets ignored and not fixed
|
||||
- [`KT-14271`](https://youtrack.jetbrains.com/issue/KT-14271) Value captured in closure doesn't always get highlighted
|
||||
- [`KT-14974`](https://youtrack.jetbrains.com/issue/KT-14974) "Find Usages" hangs in ExpressionsOfTypeProcessor
|
||||
- [`KT-15270`](https://youtrack.jetbrains.com/issue/KT-15270) Quickfix to migrate from @native***
|
||||
- [`KT-16725`](https://youtrack.jetbrains.com/issue/KT-16725) Formatter does not fix spaces before square brackets
|
||||
- [`KT-16999`](https://youtrack.jetbrains.com/issue/KT-16999) "Parameter info" shows duplicates on toString
|
||||
- [`KT-17357`](https://youtrack.jetbrains.com/issue/KT-17357) BuiltIns for module build with project LV settings, not with facet module settings
|
||||
- [`KT-17759`](https://youtrack.jetbrains.com/issue/KT-17759) Breakpoints not working in JS
|
||||
- [`KT-17849`](https://youtrack.jetbrains.com/issue/KT-17849) Automatically insert trimMargin() or trimIndent() on enter in multi-line strings
|
||||
- [`KT-17855`](https://youtrack.jetbrains.com/issue/KT-17855) Main function is shown as unused
|
||||
- [`KT-17894`](https://youtrack.jetbrains.com/issue/KT-17894) String `trimIndent` support inserts wrong indent in some cases
|
||||
- [`KT-17942`](https://youtrack.jetbrains.com/issue/KT-17942) Enter in multiline string with injection doesn't add a proper indent
|
||||
- [`KT-18006`](https://youtrack.jetbrains.com/issue/KT-18006) Copying part of string literal with escape sequences converts this sequences to special characters
|
||||
- [`KT-18030`](https://youtrack.jetbrains.com/issue/KT-18030) Parameters hints: `kotlin.arrayOf(elements)` should be on the blacklist by default
|
||||
- [`KT-18059`](https://youtrack.jetbrains.com/issue/KT-18059) Kotlin Lint: False positive error "requires api level 24" for interface method with body
|
||||
- [`KT-18149`](https://youtrack.jetbrains.com/issue/KT-18149) PIEAE "Element class CompositeElement of type REFERENCE_EXPRESSION (class KtNameReferenceExpressionElementType)" at PsiInvalidElementAccessException.createByNode()
|
||||
- [`KT-18151`](https://youtrack.jetbrains.com/issue/KT-18151) Do not import jdkHome from Gradle/Maven model
|
||||
- [`KT-18158`](https://youtrack.jetbrains.com/issue/KT-18158) Expand selection should select the comment after expression getter on the same line
|
||||
- [`KT-18221`](https://youtrack.jetbrains.com/issue/KT-18221) AE at org.jetbrains.kotlin.analyzer.ResolverForProjectImpl.descriptorForModule
|
||||
- [`KT-18269`](https://youtrack.jetbrains.com/issue/KT-18269) Find Usages fails to find operator-style usages of `invoke()` defined as extension
|
||||
- [`KT-18298`](https://youtrack.jetbrains.com/issue/KT-18298) spring: strange menu at "Navige to the spring bean" gutter
|
||||
- [`KT-18309`](https://youtrack.jetbrains.com/issue/KT-18309) Join lines breaks code
|
||||
- [`KT-18373`](https://youtrack.jetbrains.com/issue/KT-18373) Facet: can't change target platform between JVM versions
|
||||
- [`KT-18376`](https://youtrack.jetbrains.com/issue/KT-18376) Maven import fails with NPE at ArgumentUtils.convertArgumentsToStringList() if `jvmTarget` setting is absent
|
||||
- [`KT-18418`](https://youtrack.jetbrains.com/issue/KT-18418) Generate equals and hashCode should be available for classes without properties
|
||||
- [`KT-18429`](https://youtrack.jetbrains.com/issue/KT-18429) Android strings resources folding false positives
|
||||
- [`KT-18475`](https://youtrack.jetbrains.com/issue/KT-18475) Gradle/IntelliJ sync can result in IntelliJ modules getting gradle artifacts added to the classpath, breaking compilation
|
||||
- [`KT-18479`](https://youtrack.jetbrains.com/issue/KT-18479) Can't find usages of invoke operator with vararg parameter
|
||||
- [`KT-18566`](https://youtrack.jetbrains.com/issue/KT-18566) Long find usages for operators when there are several operators for the same type
|
||||
- [`KT-18596`](https://youtrack.jetbrains.com/issue/KT-18596) "Generate hashCode" produces poorly formatted code
|
||||
- [`KT-18725`](https://youtrack.jetbrains.com/issue/KT-18725) Android: `kotlin-language` facet disappears on reopening the project
|
||||
|
||||
### IDE. Completion
|
||||
|
||||
- [`KT-8208`](https://youtrack.jetbrains.com/issue/KT-8208) Support static member completion with not-imported-yet classes
|
||||
- [`KT-12104`](https://youtrack.jetbrains.com/issue/KT-12104) Smart completion does not work with "invoke" when receiver is expression
|
||||
- [`KT-18443`](https://youtrack.jetbrains.com/issue/KT-18443) IntelliJ not handling default constructor argument from companion object well
|
||||
|
||||
### IDE. Debugger
|
||||
|
||||
- [`KT-18453`](https://youtrack.jetbrains.com/issue/KT-18453) Support 'Step over' and 'Force step over' action for suspended calls
|
||||
- [`KT-18577`](https://youtrack.jetbrains.com/issue/KT-18577) Debug: Smart Step Into does not enter functions passed as variable or parameter: "Method invoke() has not been called"
|
||||
- [`KT-18632`](https://youtrack.jetbrains.com/issue/KT-18632) Debug: Smart Step Into does not enter functions passed as variable or parameter when signature of lambda and parameter doesn't match
|
||||
|
||||
### IDE. Inspections and Intentions
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-12119`](https://youtrack.jetbrains.com/issue/KT-12119) Intention to replace .addAll() on a mutable collection with +=
|
||||
- [`KT-13436`](https://youtrack.jetbrains.com/issue/KT-13436) Replace 'when' with return: handle case when all branches jump out (return Nothing)
|
||||
- [`KT-13458`](https://youtrack.jetbrains.com/issue/KT-13458) Cascade "replace with return" for if/when expressions
|
||||
- [`KT-13676`](https://youtrack.jetbrains.com/issue/KT-13676) Add better quickfix for 'let' and 'error 'only not null or asserted calls are allowed'
|
||||
- [`KT-14648`](https://youtrack.jetbrains.com/issue/KT-14648) Add quickfix for @receiver annotation being applied to extension member instead of extension type
|
||||
- [`KT-14900`](https://youtrack.jetbrains.com/issue/KT-14900) "Lift return out of when/if" should work with control flow expressions
|
||||
- [`KT-15257`](https://youtrack.jetbrains.com/issue/KT-15257) JS: quickfix to migrate from @native to external
|
||||
- [`KT-15368`](https://youtrack.jetbrains.com/issue/KT-15368) Add intention to convert Boolean? == true to ?: false and vice versa
|
||||
- [`KT-15893`](https://youtrack.jetbrains.com/issue/KT-15893) "Array property in data class" inspection could have a quick fix to generate `equals()` and `hashcode()`
|
||||
- [`KT-16063`](https://youtrack.jetbrains.com/issue/KT-16063) Inspection to suggest converting block body to expression body
|
||||
- [`KT-17198`](https://youtrack.jetbrains.com/issue/KT-17198) Inspection to replace filter calls followed by functions with a predicate variant
|
||||
- [`KT-17580`](https://youtrack.jetbrains.com/issue/KT-17580) Add remaning branches intention should be available for sealed classes
|
||||
- [`KT-17583`](https://youtrack.jetbrains.com/issue/KT-17583) Support "Declaration access can be weaker" inspection for kotlin properties
|
||||
- [`KT-17815`](https://youtrack.jetbrains.com/issue/KT-17815) Quick-fix "Replace with safe call & elvis"
|
||||
- [`KT-17842`](https://youtrack.jetbrains.com/issue/KT-17842) Add quick-fix for NO_CONSTRUCTOR error
|
||||
- [`KT-17895`](https://youtrack.jetbrains.com/issue/KT-17895) Inspection to replace 'a .. b-1' with 'a until b'
|
||||
- [`KT-17920`](https://youtrack.jetbrains.com/issue/KT-17920) Add intention/inspection removing redundant spread operator for arrayOf call
|
||||
- [`KT-17970`](https://youtrack.jetbrains.com/issue/KT-17970) Intention actions to format parameter/argument list placing each on separate line
|
||||
- [`KT-18236`](https://youtrack.jetbrains.com/issue/KT-18236) Add inspection for potentially wrongly placed unary operators
|
||||
- [`KT-18274`](https://youtrack.jetbrains.com/issue/KT-18274) Add inspection to replace map+joinTo with joinTo(transform)
|
||||
- [`KT-18386`](https://youtrack.jetbrains.com/issue/KT-18386) Inspection to detect safe calls of orEmpty()
|
||||
- [`KT-18438`](https://youtrack.jetbrains.com/issue/KT-18438) Add inspection for empty ranges with start > endInclusive
|
||||
- [`KT-18460`](https://youtrack.jetbrains.com/issue/KT-18460) Add intentions to apply De Morgan's laws to conditions
|
||||
- [`KT-18516`](https://youtrack.jetbrains.com/issue/KT-18516) Add inspection to detect & remove redundant Unit
|
||||
- [`KT-18517`](https://youtrack.jetbrains.com/issue/KT-18517) Provide "Remove explicit type" inspection for some obvious cases
|
||||
- [`KT-18534`](https://youtrack.jetbrains.com/issue/KT-18534) Quick-fix to add empty brackets after primary constructor
|
||||
- [`KT-18615`](https://youtrack.jetbrains.com/issue/KT-18615) Inspection to replace if with three or more options with when
|
||||
- [`KT-18749`](https://youtrack.jetbrains.com/issue/KT-18749) Inspection for useless operations on collection with not-null elements
|
||||
#### Fixes
|
||||
|
||||
- [`KT-11906`](https://youtrack.jetbrains.com/issue/KT-11906) Spring: "Create getter / setter" quick fixes cause IOE at LightElement.add()
|
||||
- [`KT-12524`](https://youtrack.jetbrains.com/issue/KT-12524) Wrong "redundant semicolon" for semicolon inside an enum class before the companion object declaration
|
||||
- [`KT-14092`](https://youtrack.jetbrains.com/issue/KT-14092) "Make <modifier>" intention inserts modifier between annotation and class keywords
|
||||
- [`KT-14093`](https://youtrack.jetbrains.com/issue/KT-14093) "Make <modifier>" intention available only on modifier when declaration already have a visibility modifier
|
||||
- [`KT-14643`](https://youtrack.jetbrains.com/issue/KT-14643) "Add non-null asserted call" quickfix should not be offered on literal null constants
|
||||
- [`KT-16069`](https://youtrack.jetbrains.com/issue/KT-16069) "Simplify if statement" doesn't work in specific case
|
||||
- [`KT-17026`](https://youtrack.jetbrains.com/issue/KT-17026) "Replace explicit parameter" should not be shown on destructuring declaration
|
||||
- [`KT-17537`](https://youtrack.jetbrains.com/issue/KT-17537) Create from Usage should suggest Boolean return type if function is used in if condition
|
||||
- [`KT-17623`](https://youtrack.jetbrains.com/issue/KT-17623) "Remove explicit type arguments" is too conservative sometimes
|
||||
- [`KT-17726`](https://youtrack.jetbrains.com/issue/KT-17726) Nullability quick-fixes operate incorrectly with implicit nullable receiver
|
||||
- [`KT-17740`](https://youtrack.jetbrains.com/issue/KT-17740) CME at MakeOverriddenMemberOpenFix.getText()
|
||||
- [`KT-17823`](https://youtrack.jetbrains.com/issue/KT-17823) Intention "Make private" and friends should respect modifier order
|
||||
- [`KT-17917`](https://youtrack.jetbrains.com/issue/KT-17917) Superfluos suggestion to add replaceWith for DeprecationLevel.HIDDEN
|
||||
- [`KT-17954`](https://youtrack.jetbrains.com/issue/KT-17954) Setting error severity on "Kotlin | Function or property has platform type" does not show up as error in IDE
|
||||
- [`KT-17996`](https://youtrack.jetbrains.com/issue/KT-17996) Android Studio Default Constructor Command Removes Custom Setter
|
||||
- [`KT-18033`](https://youtrack.jetbrains.com/issue/KT-18033) Do not suggest to cast expression to non-nullable type when it's the same as !!
|
||||
- [`KT-18035`](https://youtrack.jetbrains.com/issue/KT-18035) Quickfix for "CanBePrimaryConstructorProperty" does not work correctly with vararg constructor properties
|
||||
- [`KT-18044`](https://youtrack.jetbrains.com/issue/KT-18044) "Move to class body" intention: better placement in the body
|
||||
- [`KT-18120`](https://youtrack.jetbrains.com/issue/KT-18120) Recursive property accessor gives false positives
|
||||
- [`KT-18148`](https://youtrack.jetbrains.com/issue/KT-18148) Incorrect, not working quickfix - final and can't be overridden
|
||||
- [`KT-18253`](https://youtrack.jetbrains.com/issue/KT-18253) Wrong location of "Redundant 'toString()' call in string template" quickfix
|
||||
- [`KT-18347`](https://youtrack.jetbrains.com/issue/KT-18347) Nullability quickfixes are not helpful when using invoke operator
|
||||
- [`KT-18375`](https://youtrack.jetbrains.com/issue/KT-18375) Backticked function name is suggested to be renamed to the same name
|
||||
- [`KT-18385`](https://youtrack.jetbrains.com/issue/KT-18385) Spring: Generate Dependency causes Throwable "AWT events are not allowed inside write action"
|
||||
- [`KT-18407`](https://youtrack.jetbrains.com/issue/KT-18407) "Move property to constructor" action should not appear on properties declared in interfaces
|
||||
- [`KT-18425`](https://youtrack.jetbrains.com/issue/KT-18425) Make <modifier> intention inserts modifier at wrong position for sealed class
|
||||
- [`KT-18529`](https://youtrack.jetbrains.com/issue/KT-18529) Add '!!' quick fix applies to wrong expression on operation 'in'
|
||||
- [`KT-18642`](https://youtrack.jetbrains.com/issue/KT-18642) Remove unused parameter intention transfers default value to another parameter
|
||||
- [`KT-18683`](https://youtrack.jetbrains.com/issue/KT-18683) Wrong 'equals' is generated for Kotlin JS project
|
||||
- [`KT-18709`](https://youtrack.jetbrains.com/issue/KT-18709) "Lift assignment out of if" changes semantics
|
||||
- [`KT-18711`](https://youtrack.jetbrains.com/issue/KT-18711) "Lift return out of when" changes semantics for functional type
|
||||
- [`KT-18717`](https://youtrack.jetbrains.com/issue/KT-18717) Report MemberVisibilityCanBePrivate on visibility modifier if present
|
||||
|
||||
### IDE. Refactorings
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-4379`](https://youtrack.jetbrains.com/issue/KT-4379) Support renaming import alias
|
||||
- [`KT-8180`](https://youtrack.jetbrains.com/issue/KT-8180) Copy Class
|
||||
- [`KT-17547`](https://youtrack.jetbrains.com/issue/KT-17547) Refactor / Move: Problems Detected / Conflicts in View: only referencing file is mentioned
|
||||
#### Fixes
|
||||
|
||||
- [`KT-9054`](https://youtrack.jetbrains.com/issue/KT-9054) Copy / pasting a Kotlin file should bring up the Copy Class dialog
|
||||
- [`KT-13437`](https://youtrack.jetbrains.com/issue/KT-13437) Change signature replaces return type with Unit when it's not requested
|
||||
- [`KT-15859`](https://youtrack.jetbrains.com/issue/KT-15859) Renaming variables or functions with backticks removes the backticks
|
||||
- [`KT-17062`](https://youtrack.jetbrains.com/issue/KT-17062) Field/property inline refactoring works incorrectly with Kotlin & Java usages
|
||||
- [`KT-17128`](https://youtrack.jetbrains.com/issue/KT-17128) Refactor / Rename in the last position of label name throws Throwable "PsiElement(IDENTIFIER) by com.intellij.refactoring.rename.inplace.MemberInplaceRenamer" at InplaceRefactoring.buildTemplateAndStart()
|
||||
- [`KT-17489`](https://youtrack.jetbrains.com/issue/KT-17489) Refactor / Inline Property: cannot inline val with the following plusAssign
|
||||
- [`KT-17571`](https://youtrack.jetbrains.com/issue/KT-17571) Refactor / Move warns about using private/internal class from Java, but this is not related to the move
|
||||
- [`KT-17622`](https://youtrack.jetbrains.com/issue/KT-17622) Refactor / Inline Function loses type arguments
|
||||
- [`KT-18034`](https://youtrack.jetbrains.com/issue/KT-18034) Copy Class refactoring replaces all usages of the class with the new one!
|
||||
- [`KT-18076`](https://youtrack.jetbrains.com/issue/KT-18076) Refactor / Rename on alias of Java class suggests to select between refactoring handlers
|
||||
- [`KT-18096`](https://youtrack.jetbrains.com/issue/KT-18096) Refactor / Rename on import alias usage of a class member element tries to rename the element itself
|
||||
- [`KT-18098`](https://youtrack.jetbrains.com/issue/KT-18098) Refactor / Copy can't generate proper import if original code uses import alias of java member
|
||||
- [`KT-18135`](https://youtrack.jetbrains.com/issue/KT-18135) Refactor: no Problems Detected for Copy/Move source using platform type to another platform's module
|
||||
- [`KT-18200`](https://youtrack.jetbrains.com/issue/KT-18200) Refactor / Copy is enabled for Java source selected with Kotlin file, but not for Java source selected with Kotlin class
|
||||
- [`KT-18241`](https://youtrack.jetbrains.com/issue/KT-18241) Refactor / Copy (and Move) fails for chain of lambdas and invoke()'s with IllegalStateException: "No selector for PARENTHESIZED" at KtSimpleNameReference.changeQualifiedName()
|
||||
- [`KT-18325`](https://youtrack.jetbrains.com/issue/KT-18325) Renaming a parameter name in one implementation silently rename it in all implementations
|
||||
- [`KT-18390`](https://youtrack.jetbrains.com/issue/KT-18390) Refactor / Copy called for Java class opens only Copy File dialog
|
||||
- [`KT-18699`](https://youtrack.jetbrains.com/issue/KT-18699) Refactor / Copy, Move loses necessary parentheses
|
||||
|
||||
### JavaScript
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-18331`](https://youtrack.jetbrains.com/issue/KT-18331) JS: compilation performance degrades fast when inlined nested labels are used
|
||||
#### Fixes
|
||||
|
||||
- [`KT-4078`](https://youtrack.jetbrains.com/issue/KT-4078) JS sourcemaps should contain relative path. The relative base & prefix should be set from project/module preferences
|
||||
- [`KT-8020`](https://youtrack.jetbrains.com/issue/KT-8020) JS: String? plus operator crashes on runtime
|
||||
- [`KT-13919`](https://youtrack.jetbrains.com/issue/KT-13919) JS: Source map weirdness
|
||||
- [`KT-15456`](https://youtrack.jetbrains.com/issue/KT-15456) JS: inlining doesn't work for array constructor with size and lambda
|
||||
- [`KT-16984`](https://youtrack.jetbrains.com/issue/KT-16984) KotlinJS - 1 > 2 > false causes unhandled javascript exception
|
||||
- [`KT-17285`](https://youtrack.jetbrains.com/issue/KT-17285) JS: wrong result when call function with default parameter overridden by delegation by function from another interface
|
||||
- [`KT-17445`](https://youtrack.jetbrains.com/issue/KT-17445) JS: minifier for Kotlin JS apps
|
||||
- [`KT-17476`](https://youtrack.jetbrains.com/issue/KT-17476) JS: Some symbols in identifiers compile, but are not legal
|
||||
- [`KT-17871`](https://youtrack.jetbrains.com/issue/KT-17871) JS: spread vararg call doesn't work on functions imported with @JsModule
|
||||
- [`KT-18027`](https://youtrack.jetbrains.com/issue/KT-18027) JS: Illegal symbols are possible in backticked labels, but cause crash in runtime and malformed js code
|
||||
- [`KT-18032`](https://youtrack.jetbrains.com/issue/KT-18032) JS: Illegal symbols are possible in backticked package names, but cause crash in runtime and malformed js code
|
||||
- [`KT-18169`](https://youtrack.jetbrains.com/issue/KT-18169) JS: reified generic backticked type name containing non-identifier symbols causes malformed JS and runtime crash
|
||||
- [`KT-18187`](https://youtrack.jetbrains.com/issue/KT-18187) JS backend does not copy non-abstract method of interface to implementing class in some cases
|
||||
- [`KT-18201`](https://youtrack.jetbrains.com/issue/KT-18201) JS backend generates wrong code for inline function which calls non-inline function from another module
|
||||
- [`KT-18652`](https://youtrack.jetbrains.com/issue/KT-18652) JS: Objects from same package but from different libraries are incorrectly accessed
|
||||
|
||||
### Libraries
|
||||
|
||||
- [`KT-18526`](https://youtrack.jetbrains.com/issue/KT-18526) Small typo in documentation for kotlin-stdlib / kotlin.collections / retainAll
|
||||
- [`KT-18624`](https://youtrack.jetbrains.com/issue/KT-18624) JS: Bad return type for Promise.all
|
||||
- [`KT-18670`](https://youtrack.jetbrains.com/issue/KT-18670) Incorrect documentation of MutableMap.values
|
||||
|
||||
### Reflection
|
||||
|
||||
- [`KT-14094`](https://youtrack.jetbrains.com/issue/KT-14094) IllegalAccessException when try to get members annotated by private annotation with parameter
|
||||
- [`KT-16399`](https://youtrack.jetbrains.com/issue/KT-16399) Embedded Tomcat fails to load Class-Path: kotlin-runtime.jar from kotlin-reflect-1.0.6.jar
|
||||
- [`KT-16810`](https://youtrack.jetbrains.com/issue/KT-16810) Do not include incorrect ExternalOverridabilityCondition service file into kotlin-reflect.jar
|
||||
- [`KT-18404`](https://youtrack.jetbrains.com/issue/KT-18404) “KotlinReflectionInternalError: This callable does not support a default call” when function or constructor has more than 32 parameters
|
||||
- [`KT-18476`](https://youtrack.jetbrains.com/issue/KT-18476) KClass<*>.superclasses does not contain Any::class
|
||||
- [`KT-18480`](https://youtrack.jetbrains.com/issue/KT-18480) Kotlin Reflection unable to call getter of protected read-only val with custom getter from parent class
|
||||
|
||||
### Tools
|
||||
|
||||
- [`KT-18062`](https://youtrack.jetbrains.com/issue/KT-18062) SamWithReceiver compiler plugin not used by IntelliJ for .kt files
|
||||
- [`KT-18874`](https://youtrack.jetbrains.com/issue/KT-18874) Crash during compilation after switching to 1.1.3-release-IJ2017.2-2
|
||||
|
||||
### Tools. CLI
|
||||
|
||||
- [`KT-17297`](https://youtrack.jetbrains.com/issue/KT-17297) Report error when CLI compiler is not being run under Java 8+
|
||||
- [`KT-18599`](https://youtrack.jetbrains.com/issue/KT-18599) Support -Xmodule-path and -Xadd-modules arguments for modular compilation on Java 9
|
||||
- [`KT-18794`](https://youtrack.jetbrains.com/issue/KT-18794) kotlinc-jvm prints an irrelevant error message when a JVM Home directory does not exist
|
||||
- [`KT-3045`](https://youtrack.jetbrains.com/issue/KT-3045) Report error instead of failing with exception on "kotlinc -script foo.kt"
|
||||
- [`KT-18754`](https://youtrack.jetbrains.com/issue/KT-18754) Rename CLI argument "-module" to "-Xbuild-file"
|
||||
- [`KT-18927`](https://youtrack.jetbrains.com/issue/KT-18927) run kotlin app crashes eclipse
|
||||
|
||||
### Tools. Gradle
|
||||
|
||||
- [`KT-10537`](https://youtrack.jetbrains.com/issue/KT-10537) Gradle plugin doesn't pick up changed project.buildDir
|
||||
- [`KT-17031`](https://youtrack.jetbrains.com/issue/KT-17031) JVM crash on in-process compilation in Gradle with debug
|
||||
- [`KT-17618`](https://youtrack.jetbrains.com/issue/KT-17618) Pass freeCompilerArgs to compiler unchanged
|
||||
|
||||
### Tools. J2K
|
||||
|
||||
- [`KT-10762`](https://youtrack.jetbrains.com/issue/KT-10762) J2K removes empty lines from Doc-comments
|
||||
- [`KT-13146`](https://youtrack.jetbrains.com/issue/KT-13146) J2K goes into infinite loop with anonymous inner class that references itself
|
||||
- [`KT-15761`](https://youtrack.jetbrains.com/issue/KT-15761) Converting Java to Kotlin corrupts string which includes escaped backslash
|
||||
- [`KT-16133`](https://youtrack.jetbrains.com/issue/KT-16133) Converting switch statement inserts dead code (possibly as a false positive for fall-through)
|
||||
- [`KT-16142`](https://youtrack.jetbrains.com/issue/KT-16142) Kotlin Konverter produces empty line in Kdoc
|
||||
- [`KT-18038`](https://youtrack.jetbrains.com/issue/KT-18038) Java to Kotlin converter messes up empty lines while converting from JavaDoc to KDoc
|
||||
- [`KT-18051`](https://youtrack.jetbrains.com/issue/KT-18051) Doesn't work the auto-convert Java to Kotlin in Android Studio 3.0
|
||||
- [`KT-18141`](https://youtrack.jetbrains.com/issue/KT-18141) J2K changes semantic when while does not have a body
|
||||
- [`KT-18142`](https://youtrack.jetbrains.com/issue/KT-18142) J2K changes semantics when `if` does not have a body
|
||||
- [`KT-18512`](https://youtrack.jetbrains.com/issue/KT-18512) J2K Incorrect null parameter conversion
|
||||
|
||||
### Tools. JPS
|
||||
|
||||
- [`KT-14848`](https://youtrack.jetbrains.com/issue/KT-14848) JPS: invalid compiler argument causes exception (see also EA-92062)
|
||||
- [`KT-16057`](https://youtrack.jetbrains.com/issue/KT-16057) Provide better error message when the same compiler argument is set twice
|
||||
|
||||
### Tools. Maven
|
||||
|
||||
- [`KT-18224`](https://youtrack.jetbrains.com/issue/KT-18224) Maven compilation with JDK 9 fails with InaccessibleObjectException
|
||||
|
||||
### Tools. REPL
|
||||
|
||||
- [`KT-5620`](https://youtrack.jetbrains.com/issue/KT-5620) REPL: Support destructuring declarations
|
||||
- [`KT-12564`](https://youtrack.jetbrains.com/issue/KT-12564) Kotlin REPL Doesn't Perform Many Checks
|
||||
- [`KT-15172`](https://youtrack.jetbrains.com/issue/KT-15172) REPL: function declarations that contain empty lines throw error
|
||||
- [`KT-18181`](https://youtrack.jetbrains.com/issue/KT-18181) REPL: support non-headless execution for Swing code
|
||||
- [`KT-18349`](https://youtrack.jetbrains.com/issue/KT-18349) REPL: do not show warnings when there are errors
|
||||
|
||||
## 1.1.3-2
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Noarg compiler plugin reverted to 1.1.2 behavior: by default, it will not run any initialization code
|
||||
from the generated default constructor. If you want to run initializers, you need to enable
|
||||
the corresponding option as described in the documentation.
|
||||
Note that if a @noarg class has initializers that depend on constructor parameters, you will get incorrect
|
||||
compiler behavior, so you shouldn't enable this option if you have such classes in your project.
|
||||
This resolves [`KT-18667`](https://youtrack.jetbrains.com/issue/KT-18667) and [`KT-18668`](https://youtrack.jetbrains.com/issue/KT-18668).
|
||||
- [`KT-18689`](https://youtrack.jetbrains.com/issue/KT-18689) Incorrect bytecode generated when passing a bound member reference to an inline function with default argument values
|
||||
- [`KT-18377`](https://youtrack.jetbrains.com/issue/KT-18377) Syntax error while generating kapt stubs
|
||||
- [`KT-18411`](https://youtrack.jetbrains.com/issue/KT-18411) Slow debugger step-in into inlined function
|
||||
- [`KT-18687`](https://youtrack.jetbrains.com/issue/KT-18687) Deadlock in resolve with Kotlin 1.1.3
|
||||
- [`KT-18726`](https://youtrack.jetbrains.com/issue/KT-18726) Frequent UI hangs in 2017.2 EAPs
|
||||
|
||||
## 1.1.3
|
||||
|
||||
### Android
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-12049`](https://youtrack.jetbrains.com/issue/KT-12049) Kotlin Lint: "Missing Parcelable CREATOR field" could suggest "Add implementation" quick fix
|
||||
- [`KT-16712`](https://youtrack.jetbrains.com/issue/KT-16712) Show warning in IDEA when using Java 1.8 api in Android
|
||||
- [`KT-16843`](https://youtrack.jetbrains.com/issue/KT-16843) Android: provide gutter icons for resources like colors and drawables
|
||||
- [`KT-17389`](https://youtrack.jetbrains.com/issue/KT-17389) Implement Intention "Add Activity / BroadcastReceiver / Service to manifest"
|
||||
- [`KT-17465`](https://youtrack.jetbrains.com/issue/KT-17465) Add intentions Add/Remove/Redo parcelable implementation
|
||||
#### Fixes
|
||||
|
||||
- [`KT-14970`](https://youtrack.jetbrains.com/issue/KT-14970) ClassCastException: butterknife.lint.LintRegistry cannot be cast to com.android.tools.klint.client.api.IssueRegistry
|
||||
- [`KT-17287`](https://youtrack.jetbrains.com/issue/KT-17287) Configure kotlin in Android Studio: don't show menu Choose Configurator with single choice
|
||||
- [`KT-17288`](https://youtrack.jetbrains.com/issue/KT-17288) Android Studio: please remove menu item Configure Kotlin (JavaScript) in Project
|
||||
- [`KT-17289`](https://youtrack.jetbrains.com/issue/KT-17289) Android Studio: Hide "Configure Kotlin" balloon if Kotlin is configured from a kt file banner
|
||||
- [`KT-17291`](https://youtrack.jetbrains.com/issue/KT-17291) Android Studio 2.4: Cannot get property 'metaClass' on null object error after Kotlin configuring
|
||||
- [`KT-17610`](https://youtrack.jetbrains.com/issue/KT-17610) "Unknown reference: kotlinx"
|
||||
|
||||
### Compiler
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-11167`](https://youtrack.jetbrains.com/issue/KT-11167) Support compilation against JRE 9
|
||||
- [`KT-17497`](https://youtrack.jetbrains.com/issue/KT-17497) Warn about redundant else branch in exhaustive when
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-7931`](https://youtrack.jetbrains.com/issue/KT-7931) Optimize iteration over strings/charsequences on JVM
|
||||
- [`KT-10848`](https://youtrack.jetbrains.com/issue/KT-10848) Optimize substitution of inline function with default parameters
|
||||
- [`KT-12497`](https://youtrack.jetbrains.com/issue/KT-12497) Optimize inlined bytecode for functions with default parameters
|
||||
- [`KT-17342`](https://youtrack.jetbrains.com/issue/KT-17342) Optimize control-flow for case of many variables
|
||||
- [`KT-17562`](https://youtrack.jetbrains.com/issue/KT-17562) Optimize KtFile::isScript
|
||||
#### Fixes
|
||||
|
||||
- [`KT-4960`](https://youtrack.jetbrains.com/issue/KT-4960) Redeclaration is not reported for type parameters of interfaces
|
||||
- [`KT-5160`](https://youtrack.jetbrains.com/issue/KT-5160) No warning when a lambda parameter hides a variable
|
||||
- [`KT-5246`](https://youtrack.jetbrains.com/issue/KT-5246) is check fails on cyclic type parameter bounds
|
||||
@@ -13,158 +404,236 @@
|
||||
- [`KT-7645`](https://youtrack.jetbrains.com/issue/KT-7645) Prohibit default value for `catch`-block parameter
|
||||
- [`KT-7724`](https://youtrack.jetbrains.com/issue/KT-7724) Can never import private member
|
||||
- [`KT-7796`](https://youtrack.jetbrains.com/issue/KT-7796) Wrong scope for default parameter value resolution
|
||||
- [`KT-7931`](https://youtrack.jetbrains.com/issue/KT-7931) Optimize iteration over strings/charsequences on JVM
|
||||
- [`KT-7984`](https://youtrack.jetbrains.com/issue/KT-7984) Unexpected "Unresolved reference" in a default value expression in a local function
|
||||
- [`KT-7985`](https://youtrack.jetbrains.com/issue/KT-7985) Unexpected "Unresolved reference to a type parameter" in a default value expression in a local function
|
||||
- [`KT-8320`](https://youtrack.jetbrains.com/issue/KT-8320) It should not be possible to catch a type parameter type
|
||||
- [`KT-8877`](https://youtrack.jetbrains.com/issue/KT-8877) Automatic labeling doesn't work for infix calls
|
||||
- [`KT-9251`](https://youtrack.jetbrains.com/issue/KT-9251) Qualified this does not work with labeled function literals
|
||||
- [`KT-9370`](https://youtrack.jetbrains.com/issue/KT-9370) not possible to pass an argument that starts with "-" to a script using kotlinc
|
||||
- [`KT-9551`](https://youtrack.jetbrains.com/issue/KT-9551) False warning "No cast needed"
|
||||
- [`KT-9645`](https://youtrack.jetbrains.com/issue/KT-9645) Incorrect inspection: No cast Needed
|
||||
- [`KT-9986`](https://youtrack.jetbrains.com/issue/KT-9986) 'null as T' should be unchecked cast
|
||||
- [`KT-10397`](https://youtrack.jetbrains.com/issue/KT-10397) java.lang.reflect.GenericSignatureFormatError when generic inner class is mentioned in function signature
|
||||
- [`KT-10848`](https://youtrack.jetbrains.com/issue/KT-10848) Optimize substitution of inline function with default parameters
|
||||
- [`KT-11167`](https://youtrack.jetbrains.com/issue/KT-11167) Support compilation against JRE 9
|
||||
- [`KT-11474`](https://youtrack.jetbrains.com/issue/KT-11474) ISE: Requested A, got foo.A in JavaClassFinderImpl on Java file with package not matching directory
|
||||
- [`KT-11622`](https://youtrack.jetbrains.com/issue/KT-11622) False "No cast needed" when ambiguous call because of smart cast
|
||||
- [`KT-12049`](https://youtrack.jetbrains.com/issue/KT-12049) Kotlin Lint: "Missing Parcelable CREATOR field" could suggest "Add implementation" quick fix
|
||||
- [`KT-12245`](https://youtrack.jetbrains.com/issue/KT-12245) Code with annotation that has an unresolved identifier as a parameter compiles successfully
|
||||
- [`KT-12269`](https://youtrack.jetbrains.com/issue/KT-12269) False "Non-null type is checked for instance of nullable type"
|
||||
- [`KT-12497`](https://youtrack.jetbrains.com/issue/KT-12497) Optimize inlined bytecode for functions with default parameters
|
||||
- [`KT-12683`](https://youtrack.jetbrains.com/issue/KT-12683) A problem with `is` operator and non-reified type-parameters
|
||||
- [`KT-12690`](https://youtrack.jetbrains.com/issue/KT-12690) USELESS_CAST compiler warning may break code when fix is applied
|
||||
- [`KT-13348`](https://youtrack.jetbrains.com/issue/KT-13348) Report useless cast on safe cast from nullable type to the same not null type
|
||||
- [`KT-13597`](https://youtrack.jetbrains.com/issue/KT-13597) No check for accessing final field in local object in constructor
|
||||
- [`KT-13997`](https://youtrack.jetbrains.com/issue/KT-13997) Incorrect "Property must be initialized or be abstract" error for property with external accessors
|
||||
- [`KT-14381`](https://youtrack.jetbrains.com/issue/KT-14381) Possible val reassignment not detected inside init block
|
||||
- [`KT-14564`](https://youtrack.jetbrains.com/issue/KT-14564) java.lang.VerifyError: Bad local variable type
|
||||
- [`KT-14801`](https://youtrack.jetbrains.com/issue/KT-14801) Invoke error message if nested class has the same name as a function from base class
|
||||
- [`KT-14977`](https://youtrack.jetbrains.com/issue/KT-14977) IDE doesn't warn about checking null value of variable that cannot be null
|
||||
- [`KT-15050`](https://youtrack.jetbrains.com/issue/KT-15050) Random build failures using maven 3 (multi-thread) + bamboo
|
||||
- [`KT-15085`](https://youtrack.jetbrains.com/issue/KT-15085) Label and function naming conflict is resolved in unintuitive way
|
||||
- [`KT-15161`](https://youtrack.jetbrains.com/issue/KT-15161) False warning "no cast needed" for array creation
|
||||
- [`KT-15480`](https://youtrack.jetbrains.com/issue/KT-15480) Cannot destruct a list when "if" has an "else" branch
|
||||
- [`KT-15495`](https://youtrack.jetbrains.com/issue/KT-15495) Internal typealiases in the same module are inaccessible on incremental compilation
|
||||
- [`KT-15566`](https://youtrack.jetbrains.com/issue/KT-15566) Object member imported in file scope used in delegation expression in object declaration should be a compiler error
|
||||
- [`KT-16283`](https://youtrack.jetbrains.com/issue/KT-16283) Maven compiler plugin warns, "Source root doesn't exist"
|
||||
- [`KT-16016`](https://youtrack.jetbrains.com/issue/KT-16016) Compiler failure with NO_EXPECTED_TYPE
|
||||
- [`KT-16426`](https://youtrack.jetbrains.com/issue/KT-16426) Return statement resolved to function instead of property getter
|
||||
- [`KT-16712`](https://youtrack.jetbrains.com/issue/KT-16712) Show warning in IDEA when using Java 1.8 api in Android
|
||||
- [`KT-16743`](https://youtrack.jetbrains.com/issue/KT-16743) Update configuration options in Kotlin Maven plugin
|
||||
- [`KT-16754`](https://youtrack.jetbrains.com/issue/KT-16754) J2K: Apply quick-fixes from EDT thread only
|
||||
- [`KT-16762`](https://youtrack.jetbrains.com/issue/KT-16762) Maven: JS compiler option main is missing
|
||||
- [`KT-16813`](https://youtrack.jetbrains.com/issue/KT-16813) Anonymous objects returned from private-in-file members should behave as for private class members
|
||||
- [`KT-16816`](https://youtrack.jetbrains.com/issue/KT-16816) Java To Kotlin bug: if + chained assignment doesn't include brackets
|
||||
- [`KT-16843`](https://youtrack.jetbrains.com/issue/KT-16843) Android: provide gutter icons for resources like colors and drawables
|
||||
- [`KT-16986`](https://youtrack.jetbrains.com/issue/KT-16986) header symbols referring types from standard library are not matched with their implementations in IDE
|
||||
- [`KT-17093`](https://youtrack.jetbrains.com/issue/KT-17093) Import from maven: please provide a special tag for coroutine option
|
||||
- [`KT-17100`](https://youtrack.jetbrains.com/issue/KT-17100) "kotlin" launcher script: do not add current working directory to classpath if explicit "-classpath" is specified
|
||||
- [`KT-17112`](https://youtrack.jetbrains.com/issue/KT-17112) IncompatibleClassChangeError on invoking Kotlin compiler daemon on JDK 9
|
||||
- [`KT-17140`](https://youtrack.jetbrains.com/issue/KT-17140) Warning "classpath entry points to a file that is not a jar file" could just be disabled
|
||||
- [`KT-16864`](https://youtrack.jetbrains.com/issue/KT-16864) Local delegate + ad-hoc object leads to CCE
|
||||
- [`KT-17144`](https://youtrack.jetbrains.com/issue/KT-17144) Breakpoint inside `when`
|
||||
- [`KT-17149`](https://youtrack.jetbrains.com/issue/KT-17149) Incorrect warning "Kotlin: This operation has led to an overflow"
|
||||
- [`KT-17245`](https://youtrack.jetbrains.com/issue/KT-17245) Kapt: Javac compiler arguments can't be specified in Gradle
|
||||
- [`KT-17264`](https://youtrack.jetbrains.com/issue/KT-17264) Change the format of advanced CLI arguments ("-X...") to require value after "=", not a whitespace
|
||||
- [`KT-17287`](https://youtrack.jetbrains.com/issue/KT-17287) Configure kotlin in Android Studio: don't show menu Choose Configurator with single choice
|
||||
- [`KT-17288`](https://youtrack.jetbrains.com/issue/KT-17288) Android Studio: please remove menu item Configure Kotlin (JavaScript) in Project
|
||||
- [`KT-17289`](https://youtrack.jetbrains.com/issue/KT-17289) Android Studio: Hide "Configure Kotlin" balloon if Kotlin is configured from a kt file banner
|
||||
- [`KT-17291`](https://youtrack.jetbrains.com/issue/KT-17291) Android Studio 2.4: Cannot get property 'metaClass' on null object error after Kotlin configuring
|
||||
- [`KT-17156`](https://youtrack.jetbrains.com/issue/KT-17156) No re-parse after lambda was converted to block
|
||||
- [`KT-17318`](https://youtrack.jetbrains.com/issue/KT-17318) Typo in DSL Marker message `cant`
|
||||
- [`KT-17342`](https://youtrack.jetbrains.com/issue/KT-17342) Optimize control-flow for case of many variables
|
||||
- [`KT-17384`](https://youtrack.jetbrains.com/issue/KT-17384) break/continue expression in inlined function parameter argument causes compilation exception
|
||||
- [`KT-17387`](https://youtrack.jetbrains.com/issue/KT-17387) When compiling in the IDE, progress tracker says "configuring the compilation environment" when it clearly isn't
|
||||
- [`KT-17389`](https://youtrack.jetbrains.com/issue/KT-17389) Implement Intention "Add Activity / BroadcastReceiver / Service to manifest"
|
||||
- [`KT-17418`](https://youtrack.jetbrains.com/issue/KT-17418) "The following options were not recognized by any processor: '[kapt.kotlin.generated]'" warning from Javac shouldn't be shown even if no processor supports the generated annotation
|
||||
- [`KT-17448`](https://youtrack.jetbrains.com/issue/KT-17448) Regression: Sample Resolve
|
||||
- [`KT-17456`](https://youtrack.jetbrains.com/issue/KT-17456) kapt3: NoClassDefFound com/sun/tools/javac/util/Context
|
||||
- [`KT-17465`](https://youtrack.jetbrains.com/issue/KT-17465) Add intentions Add/Remove/Redo parcelable implementation
|
||||
- [`KT-17457`](https://youtrack.jetbrains.com/issue/KT-17457) Suspend + LongRange couldn't transform method node issue in Kotlin 1.1.1
|
||||
- [`KT-17479`](https://youtrack.jetbrains.com/issue/KT-17479) val reassign is allowed via explicit this receiver
|
||||
- [`KT-17560`](https://youtrack.jetbrains.com/issue/KT-17560) Overload resolution ambiguity on semi-valid class-files generated by Scala
|
||||
- [`KT-17562`](https://youtrack.jetbrains.com/issue/KT-17562) Optimize KtFile::isScript
|
||||
- [`KT-17572`](https://youtrack.jetbrains.com/issue/KT-17572) try-catch expression in inlined function parameter argument causes compilation exception
|
||||
- [`KT-17573`](https://youtrack.jetbrains.com/issue/KT-17573) try-finally expression in inlined function parameter argument fails with VerifyError
|
||||
- [`KT-17588`](https://youtrack.jetbrains.com/issue/KT-17588) Compiler error while optimizer tries to get rid of captured variable
|
||||
- [`KT-17590`](https://youtrack.jetbrains.com/issue/KT-17590) conditional return in inline function parameter argument causes compilation exception
|
||||
- [`KT-17591`](https://youtrack.jetbrains.com/issue/KT-17591) non-conditional return in inline function parameter argument causes compilation exception
|
||||
- [`KT-17613`](https://youtrack.jetbrains.com/issue/KT-17613) 'this' expression referring to deprecated class instance is highlighted as deprecated in IDE
|
||||
- [`KT-18358`](https://youtrack.jetbrains.com/issue/KT-18358) Keep smart pointers instead of PSI elements in JavaElementImpl and its descendants
|
||||
|
||||
### IDE
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-7810`](https://youtrack.jetbrains.com/issue/KT-7810) Separate icon for abstract class
|
||||
- [`KT-8370`](https://youtrack.jetbrains.com/issue/KT-8370) "Can't move to original file" should not be an error
|
||||
- [`KT-8930`](https://youtrack.jetbrains.com/issue/KT-8930) Refactor / Move preivew: moved element is shown as reference, and its file as subject
|
||||
- [`KT-9158`](https://youtrack.jetbrains.com/issue/KT-9158) Refactor / Move preview mentions the package statement of moved class as a usage
|
||||
- [`KT-10577`](https://youtrack.jetbrains.com/issue/KT-10577) Refactor / Move Kotlin + Java files adds wrong import in very specific case
|
||||
- [`KT-10981`](https://youtrack.jetbrains.com/issue/KT-10981) Quickfix for INAPPLICABLE_JVM_FIELD to replace with 'const' when possible
|
||||
- [`KT-11250`](https://youtrack.jetbrains.com/issue/KT-11250) Auto-completion for convention function names in 'operator fun' definitions
|
||||
- [`KT-12293`](https://youtrack.jetbrains.com/issue/KT-12293) Autocompletion should propose `lateinit var` in addition to `lateinit`
|
||||
- [`KT-8617`](https://youtrack.jetbrains.com/issue/KT-8617) Recognize TODO method usages and highlight them same as TODO-comment
|
||||
- [`KT-12629`](https://youtrack.jetbrains.com/issue/KT-12629) Add rainbow/semantic-highlighting for local variables
|
||||
- [`KT-13192`](https://youtrack.jetbrains.com/issue/KT-13192) Refactor / Move: to another class: "To" field code completion suggests facade and Java classes
|
||||
- [`KT-13466`](https://youtrack.jetbrains.com/issue/KT-13466) Refactor / Move: class to upper level: the package statement is not updated
|
||||
- [`KT-13524`](https://youtrack.jetbrains.com/issue/KT-13524) Completing the keyword 'constructor' before a primary constructor wrongly inserts parentheses
|
||||
- [`KT-13673`](https://youtrack.jetbrains.com/issue/KT-13673) Add 'companion { ... }' code completion opsion
|
||||
- [`KT-14046`](https://youtrack.jetbrains.com/issue/KT-14046) Add intention to add inline keyword if a function has parameter with noinline and/or crossinline modifier
|
||||
- [`KT-14109`](https://youtrack.jetbrains.com/issue/KT-14109) support parameter hints in idea plugin
|
||||
- [`KT-14435`](https://youtrack.jetbrains.com/issue/KT-14435) "Use destructuring declaration" should be available as intention even without usages
|
||||
- [`KT-14601`](https://youtrack.jetbrains.com/issue/KT-14601) Formatter inserts unnecessary indent before 'else'
|
||||
- [`KT-14665`](https://youtrack.jetbrains.com/issue/KT-14665) No completion for "else" keyword
|
||||
- [`KT-14974`](https://youtrack.jetbrains.com/issue/KT-14974) "Find Usages" hangs in ExpressionsOfTypeProcessor
|
||||
- [`KT-15273`](https://youtrack.jetbrains.com/issue/KT-15273) Kotlin IDE plugin adds `import java.lang.String` with "Optimize Imports", making project broken
|
||||
- [`KT-15519`](https://youtrack.jetbrains.com/issue/KT-15519) KDoc comments for data class values get removed by Change Signature
|
||||
- [`KT-15543`](https://youtrack.jetbrains.com/issue/KT-15543) "Convert receiver to parameter" refactoring breaks code
|
||||
- [`KT-15603`](https://youtrack.jetbrains.com/issue/KT-15603) Annoying completion when making a primary constructor private
|
||||
- [`KT-15660`](https://youtrack.jetbrains.com/issue/KT-15660) Quick-fix "Create header interface implementation" chooses wrong source root
|
||||
- [`KT-15680`](https://youtrack.jetbrains.com/issue/KT-15680) Implementations gutter icon for header interface shows duplicates
|
||||
- [`KT-15854`](https://youtrack.jetbrains.com/issue/KT-15854) Debugger not able to evaluate internal member functions
|
||||
- [`KT-15903`](https://youtrack.jetbrains.com/issue/KT-15903) QuickFix to add/remove suspend in hierarchies
|
||||
- [`KT-16025`](https://youtrack.jetbrains.com/issue/KT-16025) Step into suspend functions stops at the function end
|
||||
- [`KT-16136`](https://youtrack.jetbrains.com/issue/KT-16136) Wrong type parameter variance suggested if type parameter is used in nested anonymous object
|
||||
- [`KT-16161`](https://youtrack.jetbrains.com/issue/KT-16161) Completion of 'onEach' inserts unneeded angular brackets
|
||||
- [`KT-16339`](https://youtrack.jetbrains.com/issue/KT-16339) Incorrect warning: 'protected' visibility is effectively 'private' in a final class
|
||||
- [`KT-16392`](https://youtrack.jetbrains.com/issue/KT-16392) Gradle/Maven java module: Add framework support/ Kotlin (Java or JavaScript) adds nothing
|
||||
- [`KT-16645`](https://youtrack.jetbrains.com/issue/KT-16645) Support inlay type hints for implicitly typed vals, properties, and functions
|
||||
- [`KT-17807`](https://youtrack.jetbrains.com/issue/KT-17807) Add Smart Enter processor for object expessions
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-16995`](https://youtrack.jetbrains.com/issue/KT-16995) Typing during in-place refactorings is impossibly laggy
|
||||
- [`KT-17331`](https://youtrack.jetbrains.com/issue/KT-17331) Frequent long editor freezes
|
||||
- [`KT-17383`](https://youtrack.jetbrains.com/issue/KT-17383) Slow editing in Kotlin files If breadcrumbs are enabled in module with many dependencies
|
||||
- [`KT-17495`](https://youtrack.jetbrains.com/issue/KT-17495) Much time spent in LibraryDependenciesCache.getLibrariesAndSdksUsedWith
|
||||
#### Fixes
|
||||
|
||||
- [`KT-7848`](https://youtrack.jetbrains.com/issue/KT-7848) When you paste text into a string literal special symbols should be escaped
|
||||
- [`KT-7954`](https://youtrack.jetbrains.com/issue/KT-7954) 'Go to symbol' doesn't show containing declaration for local symbols
|
||||
- [`KT-9091`](https://youtrack.jetbrains.com/issue/KT-9091) Sometimes backticks of the method name with spaces are highlighted with rose background
|
||||
- [`KT-10577`](https://youtrack.jetbrains.com/issue/KT-10577) Refactor / Move Kotlin + Java files adds wrong import in very specific case
|
||||
- [`KT-12856`](https://youtrack.jetbrains.com/issue/KT-12856) Import fold region is not updated to include imports added while editing file
|
||||
- [`KT-14161`](https://youtrack.jetbrains.com/issue/KT-14161) Navigate to symbol doesn't see local named functions
|
||||
- [`KT-14601`](https://youtrack.jetbrains.com/issue/KT-14601) Formatter inserts unnecessary indent before 'else'
|
||||
- [`KT-14639`](https://youtrack.jetbrains.com/issue/KT-14639) Incorrect name of code style setting: Align in columns 'case' branches
|
||||
- [`KT-15029`](https://youtrack.jetbrains.com/issue/KT-15029) "Go to symbol" action doesn't find properties declared in primary constructors
|
||||
- [`KT-15255`](https://youtrack.jetbrains.com/issue/KT-15255) Move cursor to a better place when creating a new Kotlin file
|
||||
- [`KT-15273`](https://youtrack.jetbrains.com/issue/KT-15273) Kotlin IDE plugin adds `import java.lang.String` with "Optimize Imports", making project broken
|
||||
- [`KT-16159`](https://youtrack.jetbrains.com/issue/KT-16159) Wrong "Constructor call" highlighting if operator is called on newly created object
|
||||
- [`KT-16392`](https://youtrack.jetbrains.com/issue/KT-16392) Gradle/Maven java module: Add framework support/ Kotlin (Java or JavaScript) adds nothing
|
||||
- [`KT-16423`](https://youtrack.jetbrains.com/issue/KT-16423) Show expression type doesn't work when selecting from the middle of expression with "Expand Selection"
|
||||
- [`KT-16635`](https://youtrack.jetbrains.com/issue/KT-16635) Do not show kotlin-specific live templates macros for all context types
|
||||
- [`KT-16755`](https://youtrack.jetbrains.com/issue/KT-16755) No "Is sublassed by" icon for sealed class
|
||||
- [`KT-16775`](https://youtrack.jetbrains.com/issue/KT-16775) Rewrite at slice CLASS key: OBJECT_DECLARATION while writing code in IDE
|
||||
- [`KT-16786`](https://youtrack.jetbrains.com/issue/KT-16786) Intention to add "open" modifier to a non-private method or property in an open class
|
||||
- [`KT-16838`](https://youtrack.jetbrains.com/issue/KT-16838) Navigate from header to impl shows all overloads
|
||||
- [`KT-16850`](https://youtrack.jetbrains.com/issue/KT-16850) UI freeze for several seconds during inserting selected completion variant
|
||||
- [`KT-16803`](https://youtrack.jetbrains.com/issue/KT-16803) Suspending iteration is not marked in the gutter by IDEA as suspending invocation
|
||||
- [`KT-17037`](https://youtrack.jetbrains.com/issue/KT-17037) Editor suggests to import `EmptyCoroutineContext.plus` for any unresolved `+`
|
||||
- [`KT-17046`](https://youtrack.jetbrains.com/issue/KT-17046) Kotlin facet, Compiler plugins: last line is shown empty when not selected
|
||||
- [`KT-17053`](https://youtrack.jetbrains.com/issue/KT-17053) Inspection to detect use of callable reference as a lambda body
|
||||
- [`KT-17088`](https://youtrack.jetbrains.com/issue/KT-17088) Settings: Kotlin Compiler: "Destination directory" should be enabled if "Copy library runtime files" is on on the dialog opening
|
||||
- [`KT-17094`](https://youtrack.jetbrains.com/issue/KT-17094) Kotlin facet, additional command line parameters dialog: please provide a title
|
||||
- [`KT-17138`](https://youtrack.jetbrains.com/issue/KT-17138) Configure Kotlin in Project: Choose Configurator popup: names could be unified
|
||||
- [`KT-17145`](https://youtrack.jetbrains.com/issue/KT-17145) Kotlin facet: IllegalArgumentException on attempt to show settings common for several javascript kotlin facets with different moduleKind
|
||||
- [`KT-17191`](https://youtrack.jetbrains.com/issue/KT-17191) Intention to name anonymous (_) parameter
|
||||
- [`KT-17211`](https://youtrack.jetbrains.com/issue/KT-17211) Refactor / Move several files: superfluous FQN is inserted into reference to same file's element
|
||||
- [`KT-17213`](https://youtrack.jetbrains.com/issue/KT-17213) Refactor / Inline Function: parameters of lambda as call argument turn incompilable
|
||||
- [`KT-17223`](https://youtrack.jetbrains.com/issue/KT-17223) Absolute path to Kotlin compiler plugin in IML
|
||||
- [`KT-17234`](https://youtrack.jetbrains.com/issue/KT-17234) Refactor / Inline on library property is rejected after GUI freeze for a while
|
||||
- [`KT-17272`](https://youtrack.jetbrains.com/issue/KT-17272) Refactor / Inline Function: unused String literal in parameters is kept (while unsed Int is not)
|
||||
- [`KT-17273`](https://youtrack.jetbrains.com/issue/KT-17273) Refactor / Inline Function: PIEAE: "Element: class org.jetbrains.kotlin.psi.KtCallExpression because: different providers" at PsiUtilCore.ensureValid()
|
||||
- [`KT-17293`](https://youtrack.jetbrains.com/issue/KT-17293) Project Structure dialog is opened too slow for a project with a lot of empty gradle modules
|
||||
- [`KT-17296`](https://youtrack.jetbrains.com/issue/KT-17296) Refactor / Inline Function: UOE at ExpressionReplacementPerformer.findOrCreateBlockToInsertStatement() for call of multi-statement function in declaration
|
||||
- [`KT-17330`](https://youtrack.jetbrains.com/issue/KT-17330) Inline kotlin function causes an infinite loop
|
||||
- [`KT-17331`](https://youtrack.jetbrains.com/issue/KT-17331) Frequent long editor freezes
|
||||
- [`KT-17333`](https://youtrack.jetbrains.com/issue/KT-17333) KotlinChangeInfo retains 132MB of the heap
|
||||
- [`KT-17372`](https://youtrack.jetbrains.com/issue/KT-17372) Specify explicit lambda signature handles anonymous parameters incorrectly
|
||||
- [`KT-17383`](https://youtrack.jetbrains.com/issue/KT-17383) Slow editing in Kotlin files If breadcrumbs are enabled in module with many dependencies
|
||||
- [`KT-17395`](https://youtrack.jetbrains.com/issue/KT-17395) Refactor / Inline Function: arguments passed to lambda turns code to incompilable
|
||||
- [`KT-17400`](https://youtrack.jetbrains.com/issue/KT-17400) Navigate to impl: implementations are duplicated
|
||||
- [`KT-17404`](https://youtrack.jetbrains.com/issue/KT-17404) Editor: attempt to pass type parameter as reified argument causes AE "Classifier descriptor of a type should be of type ClassDescriptor" at DescriptorUtils.getClassDescriptorForTypeConstructor()
|
||||
- [`KT-17408`](https://youtrack.jetbrains.com/issue/KT-17408) "Convert to secondary constructor" intention is available for annotation parameters
|
||||
- [`KT-17472`](https://youtrack.jetbrains.com/issue/KT-17472) Refactor / Move: another class: Java class could be reported explicitly
|
||||
- [`KT-17304`](https://youtrack.jetbrains.com/issue/KT-17304) IDEA shows wrong type for expressions
|
||||
- [`KT-17439`](https://youtrack.jetbrains.com/issue/KT-17439) Kotlin: 'autoscroll from source' doesn't work in Structure view
|
||||
- [`KT-17448`](https://youtrack.jetbrains.com/issue/KT-17448) Regression: Sample Resolve
|
||||
- [`KT-17482`](https://youtrack.jetbrains.com/issue/KT-17482) Set jvmTarget to 1.8 by default when configuring a project with JDK 1.8
|
||||
- [`KT-17495`](https://youtrack.jetbrains.com/issue/KT-17495) Much time spent in LibraryDependenciesCache.getLibrariesAndSdksUsedWith
|
||||
- [`KT-17496`](https://youtrack.jetbrains.com/issue/KT-17496) Refactor / Move: calls to moved extension function type properties are updated (incorrectly)
|
||||
- [`KT-17503`](https://youtrack.jetbrains.com/issue/KT-17503) Intention "To raw string literal" should handle string concatenations
|
||||
- [`KT-17515`](https://youtrack.jetbrains.com/issue/KT-17515) Refactor / Move inner class to another class, Move companion object: disabled in editor, but available in Move dialog
|
||||
- [`KT-17492`](https://youtrack.jetbrains.com/issue/KT-17492) -jvm-target is ignored by IntelliJ
|
||||
- [`KT-17505`](https://youtrack.jetbrains.com/issue/KT-17505) LazyLightClassMemberMatchingError from collection implementation
|
||||
- [`KT-17517`](https://youtrack.jetbrains.com/issue/KT-17517) Compiler options specified as properties are not handled by Maven importer
|
||||
- [`KT-17520`](https://youtrack.jetbrains.com/issue/KT-17520) Quickfix to update language/API version should work for Maven projects
|
||||
- [`KT-17521`](https://youtrack.jetbrains.com/issue/KT-17521) Quickfix to enable coroutines should work for Maven projects
|
||||
- [`KT-17525`](https://youtrack.jetbrains.com/issue/KT-17525) IDE: KNPE at KotlinAddImportActionKt.createSingleImportActionForConstructor() on invalid reference to inner class constructor
|
||||
- [`KT-17578`](https://youtrack.jetbrains.com/issue/KT-17578) Throwable: "Reported element PsiIdentifier:AnnotationConfiguration is not from the file 'PsiFile:InSource.kt' the inspection 'ImplicitSubclassInspection'"
|
||||
- [`KT-17638`](https://youtrack.jetbrains.com/issue/KT-17638) ISE in KotlinElementDescriptionProvider.renderShort
|
||||
- [`KT-17698`](https://youtrack.jetbrains.com/issue/KT-17698) Unknown library format - prevents IDEA from configuring Kotlin JS
|
||||
- [`KT-17714`](https://youtrack.jetbrains.com/issue/KT-17714) UAST inspection on non-physical element
|
||||
- [`KT-17722`](https://youtrack.jetbrains.com/issue/KT-17722) IntelliJ plugin uses wrong JVM target when Kotlin Facet is not configured
|
||||
- [`KT-17770`](https://youtrack.jetbrains.com/issue/KT-17770) Kotlin IntelliJ plugin fails to re-index Gradle script classpath after change to the `plugins` block
|
||||
- [`KT-17777`](https://youtrack.jetbrains.com/issue/KT-17777) Logger$EmptyThrowable: "Facet Kotlin (app) [kotlin-language] not found" at FacetModelImpl.removeFacet()
|
||||
- [`KT-17810`](https://youtrack.jetbrains.com/issue/KT-17810) Exception from unused import inspection leads to code analysis hangs
|
||||
- [`KT-17821`](https://youtrack.jetbrains.com/issue/KT-17821) In Kotlin's plugin KotlinJsMetadataVersionIndex loads file with VfsUtilCore.loadText
|
||||
- [`KT-17840`](https://youtrack.jetbrains.com/issue/KT-17840) Show expression type on `this` shows bogus disambiguation
|
||||
- [`KT-17845`](https://youtrack.jetbrains.com/issue/KT-17845) Searching for usages of override property in primary constructor doesn't suggest base property search
|
||||
- [`KT-17847`](https://youtrack.jetbrains.com/issue/KT-17847) Kotlin facet: strange warning if API version = 1.2
|
||||
- [`KT-17857`](https://youtrack.jetbrains.com/issue/KT-17857) Java should see classes affected by "allopen" plugin as open
|
||||
- [`KT-17861`](https://youtrack.jetbrains.com/issue/KT-17861) Setting 'kotlin.experimental.coroutines "enable"' doesn't work for Android projects
|
||||
- [`KT-17875`](https://youtrack.jetbrains.com/issue/KT-17875) New Project/Module with Kotlin: on attempt to use libraries from plugin IDE suggests to rewrite them
|
||||
- [`KT-17876`](https://youtrack.jetbrains.com/issue/KT-17876) New Project/Module with Kotlin: with "Copy to" option only part of jars are copied
|
||||
- [`KT-17899`](https://youtrack.jetbrains.com/issue/KT-17899) Navigate to symbol: vararg signatures are indistinguishable from non-vararg ones
|
||||
- [`KT-18070`](https://youtrack.jetbrains.com/issue/KT-18070) KtLightModifierList.hasExplicitModifier("default") is true for interface method with body
|
||||
|
||||
### IDE. Completion
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-11250`](https://youtrack.jetbrains.com/issue/KT-11250) Auto-completion for convention function names in 'operator fun' definitions
|
||||
- [`KT-12293`](https://youtrack.jetbrains.com/issue/KT-12293) Autocompletion should propose `lateinit var` in addition to `lateinit`
|
||||
- [`KT-13673`](https://youtrack.jetbrains.com/issue/KT-13673) Add 'companion { ... }' code completion opsion
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-10978`](https://youtrack.jetbrains.com/issue/KT-10978) Kotlin + JOOQ + Intellij performance is unusable
|
||||
- [`KT-16715`](https://youtrack.jetbrains.com/issue/KT-16715) Typing is very slow since 1.1
|
||||
- [`KT-16850`](https://youtrack.jetbrains.com/issue/KT-16850) UI freeze for several seconds during inserting selected completion variant
|
||||
#### Fixes
|
||||
|
||||
- [`KT-13524`](https://youtrack.jetbrains.com/issue/KT-13524) Completing the keyword 'constructor' before a primary constructor wrongly inserts parentheses
|
||||
- [`KT-14665`](https://youtrack.jetbrains.com/issue/KT-14665) No completion for "else" keyword
|
||||
- [`KT-15603`](https://youtrack.jetbrains.com/issue/KT-15603) Annoying completion when making a primary constructor private
|
||||
- [`KT-16161`](https://youtrack.jetbrains.com/issue/KT-16161) Completion of 'onEach' inserts unneeded angular brackets
|
||||
- [`KT-16856`](https://youtrack.jetbrains.com/issue/KT-16856) Code completion optimization
|
||||
|
||||
### IDE. Debugger
|
||||
|
||||
- [`KT-15823`](https://youtrack.jetbrains.com/issue/KT-15823) Breakpoints not work inside crossinline from init of object passed into collection
|
||||
- [`KT-15854`](https://youtrack.jetbrains.com/issue/KT-15854) Debugger not able to evaluate internal member functions
|
||||
- [`KT-16025`](https://youtrack.jetbrains.com/issue/KT-16025) Step into suspend functions stops at the function end
|
||||
- [`KT-17295`](https://youtrack.jetbrains.com/issue/KT-17295) Can't stop in kotlin.concurrent.timer lambda parameter
|
||||
|
||||
### IDE. Inspections and Intentions
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-10981`](https://youtrack.jetbrains.com/issue/KT-10981) Quickfix for INAPPLICABLE_JVM_FIELD to replace with 'const' when possible
|
||||
- [`KT-14046`](https://youtrack.jetbrains.com/issue/KT-14046) Add intention to add inline keyword if a function has parameter with noinline and/or crossinline modifier
|
||||
- [`KT-14137`](https://youtrack.jetbrains.com/issue/KT-14137) Add intention to convert top level val with object expression to object
|
||||
- [`KT-15903`](https://youtrack.jetbrains.com/issue/KT-15903) QuickFix to add/remove suspend in hierarchies
|
||||
- [`KT-16786`](https://youtrack.jetbrains.com/issue/KT-16786) Intention to add "open" modifier to a non-private method or property in an open class
|
||||
- [`KT-16851`](https://youtrack.jetbrains.com/issue/KT-16851) Quickfix adding qualifier `@call` to unallowed 'return' in closures
|
||||
- [`KT-17053`](https://youtrack.jetbrains.com/issue/KT-17053) Inspection to detect use of callable reference as a lambda body
|
||||
- [`KT-17054`](https://youtrack.jetbrains.com/issue/KT-17054) Intention/ inspection to convert 'if' with 'is' check to 'as?' with safe call
|
||||
- [`KT-17191`](https://youtrack.jetbrains.com/issue/KT-17191) Intention to name anonymous (_) parameter
|
||||
- [`KT-17221`](https://youtrack.jetbrains.com/issue/KT-17221) Inspection for recursive calls in property accessors
|
||||
- [`KT-17520`](https://youtrack.jetbrains.com/issue/KT-17520) Quickfix to update language/API version should work for Maven projects
|
||||
- [`KT-17650`](https://youtrack.jetbrains.com/issue/KT-17650) Add quickfix inserting 'lateinit' modifier for not-initialized property
|
||||
- [`KT-17660`](https://youtrack.jetbrains.com/issue/KT-17660) Inspection: data class copy without named argument(s)
|
||||
#### Fixes
|
||||
|
||||
- [`KT-10211`](https://youtrack.jetbrains.com/issue/KT-10211) "Replace infix call with ordinary call" appears both as a quickfix and as an intention in the pop-up
|
||||
- [`KT-11003`](https://youtrack.jetbrains.com/issue/KT-11003) Invalid quickfix in companion object for open properties
|
||||
- [`KT-12805`](https://youtrack.jetbrains.com/issue/KT-12805) False positive redundant semicolon after while without block expression
|
||||
- [`KT-14335`](https://youtrack.jetbrains.com/issue/KT-14335) Unexpected range of "convert lambda to reference" intention
|
||||
- [`KT-14435`](https://youtrack.jetbrains.com/issue/KT-14435) "Use destructuring declaration" should be available as intention even without usages
|
||||
- [`KT-14443`](https://youtrack.jetbrains.com/issue/KT-14443) IDEA intention suggest to make a method in an interface final
|
||||
- [`KT-14820`](https://youtrack.jetbrains.com/issue/KT-14820) Convert function to property shouldn't insert explicit type if it was inferred previously
|
||||
- [`KT-15076`](https://youtrack.jetbrains.com/issue/KT-15076) Replace if with elvis inspection should not be reported in some complex cases
|
||||
- [`KT-15543`](https://youtrack.jetbrains.com/issue/KT-15543) "Convert receiver to parameter" refactoring breaks code
|
||||
- [`KT-15942`](https://youtrack.jetbrains.com/issue/KT-15942) "Convert to secondary constructor" intention is available for data class
|
||||
- [`KT-16136`](https://youtrack.jetbrains.com/issue/KT-16136) Wrong type parameter variance suggested if type parameter is used in nested anonymous object
|
||||
- [`KT-16339`](https://youtrack.jetbrains.com/issue/KT-16339) Incorrect warning: 'protected' visibility is effectively 'private' in a final class
|
||||
- [`KT-16577`](https://youtrack.jetbrains.com/issue/KT-16577) "Redundant semicolon" is not reported for semicolon after package statement in file with no imports
|
||||
- [`KT-17079`](https://youtrack.jetbrains.com/issue/KT-17079) Kotlin: Bad conversion of double comparison to range check if bounds have mixed types
|
||||
- [`KT-17372`](https://youtrack.jetbrains.com/issue/KT-17372) Specify explicit lambda signature handles anonymous parameters incorrectly
|
||||
- [`KT-17404`](https://youtrack.jetbrains.com/issue/KT-17404) Editor: attempt to pass type parameter as reified argument causes AE "Classifier descriptor of a type should be of type ClassDescriptor" at DescriptorUtils.getClassDescriptorForTypeConstructor()
|
||||
- [`KT-17408`](https://youtrack.jetbrains.com/issue/KT-17408) "Convert to secondary constructor" intention is available for annotation parameters
|
||||
- [`KT-17503`](https://youtrack.jetbrains.com/issue/KT-17503) Intention "To raw string literal" should handle string concatenations
|
||||
- [`KT-17599`](https://youtrack.jetbrains.com/issue/KT-17599) "Make primary constructor internal" intention is available for annotation class
|
||||
- [`KT-17600`](https://youtrack.jetbrains.com/issue/KT-17600) "Make primary constructor private" intention is available for annotation class
|
||||
- [`KT-17707`](https://youtrack.jetbrains.com/issue/KT-17707) "Final declaration can't be overridden at runtime" inspection reports Kotlin classes non final due to compiler plugin
|
||||
- [`KT-17708`](https://youtrack.jetbrains.com/issue/KT-17708) "Move to class body" intention is available for annotation parameters
|
||||
- [`KT-17762`](https://youtrack.jetbrains.com/issue/KT-17762) 'Convert to range' intention generates inequivalent code for doubles
|
||||
|
||||
### IDE. Refactorings
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-17234`](https://youtrack.jetbrains.com/issue/KT-17234) Refactor / Inline on library property is rejected after GUI freeze for a while
|
||||
- [`KT-17333`](https://youtrack.jetbrains.com/issue/KT-17333) KotlinChangeInfo retains 132MB of the heap
|
||||
#### Fixes
|
||||
|
||||
- [`KT-8370`](https://youtrack.jetbrains.com/issue/KT-8370) "Can't move to original file" should not be an error
|
||||
- [`KT-8930`](https://youtrack.jetbrains.com/issue/KT-8930) Refactor / Move preivew: moved element is shown as reference, and its file as subject
|
||||
- [`KT-9158`](https://youtrack.jetbrains.com/issue/KT-9158) Refactor / Move preview mentions the package statement of moved class as a usage
|
||||
- [`KT-13192`](https://youtrack.jetbrains.com/issue/KT-13192) Refactor / Move: to another class: "To" field code completion suggests facade and Java classes
|
||||
- [`KT-13466`](https://youtrack.jetbrains.com/issue/KT-13466) Refactor / Move: class to upper level: the package statement is not updated
|
||||
- [`KT-15519`](https://youtrack.jetbrains.com/issue/KT-15519) KDoc comments for data class values get removed by Change Signature
|
||||
- [`KT-17211`](https://youtrack.jetbrains.com/issue/KT-17211) Refactor / Move several files: superfluous FQN is inserted into reference to same file's element
|
||||
- [`KT-17213`](https://youtrack.jetbrains.com/issue/KT-17213) Refactor / Inline Function: parameters of lambda as call argument turn incompilable
|
||||
- [`KT-17272`](https://youtrack.jetbrains.com/issue/KT-17272) Refactor / Inline Function: unused String literal in parameters is kept (while unsed Int is not)
|
||||
- [`KT-17273`](https://youtrack.jetbrains.com/issue/KT-17273) Refactor / Inline Function: PIEAE: "Element: class org.jetbrains.kotlin.psi.KtCallExpression because: different providers" at PsiUtilCore.ensureValid()
|
||||
- [`KT-17296`](https://youtrack.jetbrains.com/issue/KT-17296) Refactor / Inline Function: UOE at ExpressionReplacementPerformer.findOrCreateBlockToInsertStatement() for call of multi-statement function in declaration
|
||||
- [`KT-17330`](https://youtrack.jetbrains.com/issue/KT-17330) Inline kotlin function causes an infinite loop
|
||||
- [`KT-17395`](https://youtrack.jetbrains.com/issue/KT-17395) Refactor / Inline Function: arguments passed to lambda turns code to incompilable
|
||||
- [`KT-17496`](https://youtrack.jetbrains.com/issue/KT-17496) Refactor / Move: calls to moved extension function type properties are updated (incorrectly)
|
||||
- [`KT-17515`](https://youtrack.jetbrains.com/issue/KT-17515) Refactor / Move inner class to another class, Move companion object: disabled in editor, but available in Move dialog
|
||||
- [`KT-17526`](https://youtrack.jetbrains.com/issue/KT-17526) Refactor / Move: reference to companion member gets superfluous companion name in certain cases
|
||||
- [`KT-17538`](https://youtrack.jetbrains.com/issue/KT-17538) Refactor / Move: moving file with import alias removes alias usage from code
|
||||
- [`KT-17545`](https://youtrack.jetbrains.com/issue/KT-17545) Refactor / Move: false Problems Detected on moving class using parent's protected class, object
|
||||
- [`KT-17599`](https://youtrack.jetbrains.com/issue/KT-17599) "Make primary constructor internal" intention is available for annotation class
|
||||
- [`KT-17600`](https://youtrack.jetbrains.com/issue/KT-17600) "Make primary constructor private" intention is available for annotation class
|
||||
- [`KT-18018`](https://youtrack.jetbrains.com/issue/KT-18018) F5 (for Copy) does not work for Kotlin files anymore
|
||||
- [`KT-18205`](https://youtrack.jetbrains.com/issue/KT-18205) Moving multiple classes causes imports to be converted to fully qualified class names
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- [`KT-14988`](https://youtrack.jetbrains.com/issue/KT-14988) Support running the Kotlin compiler on Java 9
|
||||
- [`KT-17112`](https://youtrack.jetbrains.com/issue/KT-17112) IncompatibleClassChangeError on invoking Kotlin compiler daemon on JDK 9
|
||||
|
||||
### JavaScript
|
||||
|
||||
#### Fixes
|
||||
|
||||
### JS
|
||||
- [`KT-12926`](https://youtrack.jetbrains.com/issue/KT-12926) JS: use # instead of @ when linking to sourcemap from generated code
|
||||
- [`KT-13577`](https://youtrack.jetbrains.com/issue/KT-13577) Double.hashCode is zero for big numbers
|
||||
- [`KT-15135`](https://youtrack.jetbrains.com/issue/KT-15135) JS: support friend modules
|
||||
- [`KT-15484`](https://youtrack.jetbrains.com/issue/KT-15484) JS: (node): println with object /number argument leads to "TypeError: Invalid data, chunk must be a string or buffer, not object/number"
|
||||
- [`KT-16658`](https://youtrack.jetbrains.com/issue/KT-16658) JS: Suspend function with default param value in interface
|
||||
- [`KT-16717`](https://youtrack.jetbrains.com/issue/KT-16717) KotlinJs - copy() on data class doesn't work with when there is a secondary constructor
|
||||
@@ -176,14 +645,87 @@
|
||||
- [`KT-17281`](https://youtrack.jetbrains.com/issue/KT-17281) JS: wrong code generated for a recursive call in suspend function
|
||||
- [`KT-17446`](https://youtrack.jetbrains.com/issue/KT-17446) JS: incorrect code generated for call to `suspendCoroutineOrReturn` when the same function calls another suspend function
|
||||
- [`KT-17540`](https://youtrack.jetbrains.com/issue/KT-17540) Incorrect inlining optimization of `also`/`apply` function
|
||||
|
||||
### Reflection
|
||||
- [`KT-14988`](https://youtrack.jetbrains.com/issue/KT-14988) Support running the Kotlin compiler on Java 9
|
||||
- [`KT-17055`](https://youtrack.jetbrains.com/issue/KT-17055) NPE in hashCode and equals of kotlin.jvm.internal.FunctionReference (on local functions)
|
||||
- [`KT-17594`](https://youtrack.jetbrains.com/issue/KT-17594) Cache the result of val Class<T>.kotlin: KClass<T>
|
||||
- [`KT-17700`](https://youtrack.jetbrains.com/issue/KT-17700) Wrong code generated for 'str += (nullableChar ?: break)'
|
||||
- [`KT-17966`](https://youtrack.jetbrains.com/issue/KT-17966) JS: Char literal inside of string template
|
||||
|
||||
### Libraries
|
||||
|
||||
- [`KT-17453`](https://youtrack.jetbrains.com/issue/KT-17453) Array iterators throw IndexOutOfBoundsException instead of NoSuchElementException
|
||||
- [`KT-17635`](https://youtrack.jetbrains.com/issue/KT-17635) Document String#toIntOfNull may throw an exception
|
||||
- [`KT-17686`](https://youtrack.jetbrains.com/issue/KT-17686) takeLast(n) incorrectly performs drop(n) for Lists without random access
|
||||
- [`KT-17704`](https://youtrack.jetbrains.com/issue/KT-17704) Update JavaDoc for ReentrantReadWriteLock.write to put more stress on the fact that to upgrade to write lock, read lock is first released.
|
||||
- [`KT-17853`](https://youtrack.jetbrains.com/issue/KT-17853) JS: Confusing parameter names in 'Math.atan2`
|
||||
- [`KT-18092`](https://youtrack.jetbrains.com/issue/KT-18092) Issue using kotlin-reflect with proguard: missing annotations Mutable and ReadOnly
|
||||
- [`KT-18210`](https://youtrack.jetbrains.com/issue/KT-18210) JS String::match(regex) should have nullable return type
|
||||
|
||||
### Reflection
|
||||
|
||||
- [`KT-17055`](https://youtrack.jetbrains.com/issue/KT-17055) NPE in hashCode and equals of kotlin.jvm.internal.FunctionReference (on local functions)
|
||||
- [`KT-17594`](https://youtrack.jetbrains.com/issue/KT-17594) Cache the result of val Class<T>.kotlin: KClass<T>
|
||||
- [`KT-18494`](https://youtrack.jetbrains.com/issue/KT-18494) KNPE from Kotlin reflection (sometimes) in UtilKt.toJavaClass
|
||||
|
||||
### Tools
|
||||
|
||||
- [`KT-16692`](https://youtrack.jetbrains.com/issue/KT-16692) No-Arg-Constructor plugin should generate code to initialize delegates
|
||||
|
||||
### Tools. CLI
|
||||
|
||||
- [`KT-17696`](https://youtrack.jetbrains.com/issue/KT-17696) Allow kotlinc to take friend modules as .jar files
|
||||
- [`KT-17697`](https://youtrack.jetbrains.com/issue/KT-17697) Allow kotlinc to take .java files as arguments
|
||||
- [`KT-9370`](https://youtrack.jetbrains.com/issue/KT-9370) not possible to pass an argument that starts with "-" to a script using kotlinc
|
||||
- [`KT-17100`](https://youtrack.jetbrains.com/issue/KT-17100) "kotlin" launcher script: do not add current working directory to classpath if explicit "-classpath" is specified
|
||||
- [`KT-17140`](https://youtrack.jetbrains.com/issue/KT-17140) Warning "classpath entry points to a file that is not a jar file" could just be disabled
|
||||
- [`KT-17264`](https://youtrack.jetbrains.com/issue/KT-17264) Change the format of advanced CLI arguments ("-X...") to require value after "=", not a whitespace
|
||||
- [`KT-18180`](https://youtrack.jetbrains.com/issue/KT-18180) Modules not exported by java.se are not readable when compiling against JRE 9
|
||||
|
||||
### Tools. Gradle
|
||||
|
||||
- [`KT-15151`](https://youtrack.jetbrains.com/issue/KT-15151) Kapt3: Support incremental compilation of Java stubs
|
||||
- [`KT-16298`](https://youtrack.jetbrains.com/issue/KT-16298) Gradle: IOException "Parent file doesn't exist:/.../artifact-difference.tab.len" on non-incremental clean after incremental build
|
||||
- [`KT-17681`](https://youtrack.jetbrains.com/issue/KT-17681) Support the new API of Android Gradle plugin (2.4.0+)
|
||||
- [`KT-17936`](https://youtrack.jetbrains.com/issue/KT-17936) Circular dependency between gradle tasks dataBindingExportBuildInfoDebug and compileDebugKotlin
|
||||
- [`KT-17960`](https://youtrack.jetbrains.com/issue/KT-17960) Improve test of memory leak with Gradle daemon
|
||||
- [`KT-18047`](https://youtrack.jetbrains.com/issue/KT-18047) Gradle kotlin options should use unset value as default for languageVersion and apiVersion
|
||||
|
||||
### Tools. J2K
|
||||
|
||||
- [`KT-16754`](https://youtrack.jetbrains.com/issue/KT-16754) J2K: Apply quick-fixes from EDT thread only
|
||||
- [`KT-16816`](https://youtrack.jetbrains.com/issue/KT-16816) Java To Kotlin bug: if + chained assignment doesn't include brackets
|
||||
- [`KT-17230`](https://youtrack.jetbrains.com/issue/KT-17230) J2K Deadlock
|
||||
- [`KT-17712`](https://youtrack.jetbrains.com/issue/KT-17712) Exception in J2K during InlineCodegen convertion: com.intellij.psi.impl.source.JavaDummyHolder cannot be cast to com.intellij.psi.PsiJavaFile
|
||||
|
||||
### Tools. JPS
|
||||
|
||||
- [`KT-16568`](https://youtrack.jetbrains.com/issue/KT-16568) modulesWhoseInternalsAreVisible in ModuleDependencies are not filled in for JS projects
|
||||
- [`KT-17387`](https://youtrack.jetbrains.com/issue/KT-17387) When compiling in the IDE, progress tracker says "configuring the compilation environment" when it clearly isn't
|
||||
- [`KT-17665`](https://youtrack.jetbrains.com/issue/KT-17665) JPS: Kotlin: The '-d' option with a directory destination is ignored because '-module' is specified
|
||||
- [`KT-17801`](https://youtrack.jetbrains.com/issue/KT-17801) Unresolved supertypes from JRE on JDK 9 in JPS
|
||||
|
||||
### Tools. Maven
|
||||
|
||||
- [`KT-17093`](https://youtrack.jetbrains.com/issue/KT-17093) Import from maven: please provide a special tag for coroutine option
|
||||
- [`KT-10028`](https://youtrack.jetbrains.com/issue/KT-10028) Support parallel builds in maven
|
||||
- [`KT-15050`](https://youtrack.jetbrains.com/issue/KT-15050) Random build failures using maven 3 (multi-thread) + bamboo
|
||||
- [`KT-15318`](https://youtrack.jetbrains.com/issue/KT-15318) Intermitent Kotlin compilation errors
|
||||
- [`KT-16283`](https://youtrack.jetbrains.com/issue/KT-16283) Maven compiler plugin warns, "Source root doesn't exist"
|
||||
- [`KT-16743`](https://youtrack.jetbrains.com/issue/KT-16743) Update configuration options in Kotlin Maven plugin
|
||||
- [`KT-16762`](https://youtrack.jetbrains.com/issue/KT-16762) Maven: JS compiler option main is missing
|
||||
|
||||
### Tools. REPL
|
||||
|
||||
- [`KT-5822`](https://youtrack.jetbrains.com/issue/KT-5822) Exception on package directive in REPL
|
||||
- [`KT-10060`](https://youtrack.jetbrains.com/issue/KT-10060) REPL: Cannot execute more than 255 lines
|
||||
- [`KT-17365`](https://youtrack.jetbrains.com/issue/KT-17365) REPL crash when referencing a variable whose definition threw an exception
|
||||
|
||||
### Tools. kapt
|
||||
|
||||
- [`KT-17245`](https://youtrack.jetbrains.com/issue/KT-17245) Kapt: Javac compiler arguments can't be specified in Gradle
|
||||
- [`KT-17418`](https://youtrack.jetbrains.com/issue/KT-17418) "The following options were not recognized by any processor: '[kapt.kotlin.generated]'" warning from Javac shouldn't be shown even if no processor supports the generated annotation
|
||||
- [`KT-17456`](https://youtrack.jetbrains.com/issue/KT-17456) kapt3: NoClassDefFound com/sun/tools/javac/util/Context
|
||||
- [`KT-17567`](https://youtrack.jetbrains.com/issue/KT-17567) Kapt (1.1.2-eap-77) generates invalid Java stub for internal class
|
||||
- [`KT-17620`](https://youtrack.jetbrains.com/issue/KT-17620) Kapt3 IC: avoid running AP when API is not changed
|
||||
- [`KT-17959`](https://youtrack.jetbrains.com/issue/KT-17959) Kapt3 doesn't preserve method parameter names for abstract methods
|
||||
- [`KT-17999`](https://youtrack.jetbrains.com/issue/KT-17999) Cannot use KAPT3 1.1.2-4 in Android Studio java libs (null TypeCastException to WrappedVariantData<*> on Gradle Sync)
|
||||
|
||||
## 1.1.2
|
||||
|
||||
|
||||
18
Kotlin.iml
18
Kotlin.iml
@@ -16,8 +16,8 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/.idea" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/annotation-processor-example/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/browser-example/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/browser-example-with-library/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/browser-example/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/js-example/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/kotlin-gradle-subplugin-example/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/kotlin-java-example/target" />
|
||||
@@ -26,6 +26,8 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/examples/kotlin-jsr223-local-example/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/kotlin.test/common/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/kotlin.test/js/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/kotlin.test/js/it/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/kotlin.test/js/it/node_modules" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/kotlin.test/junit/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/kotlin.test/jvm/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/build" />
|
||||
@@ -36,20 +38,25 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/js/node_modules" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/.idea" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/binary-compatibility-validator/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/gradle-tools/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/idl2k/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-allopen/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-allopen/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-android-extensions/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-annotation-processing/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-annotation-processing-maven/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-annotation-processing/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-build-common-test/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-compiler/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-compiler-client-embeddable/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-compiler-client-embeddable-test/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-compiler-client-embeddable/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-compiler-embeddable/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-compiler-runner/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-compiler/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-daemon-client/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-gradle-plugin-api/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-gradle-plugin-api/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-gradle-plugin-integration-tests/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-gradle-plugin-integration-tests/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-gradle-plugin/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-gradle-plugin/local-repo" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-gradle-plugin/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-maven-allopen/target" />
|
||||
@@ -58,6 +65,7 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-maven-plugin-test/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-maven-plugin/local-repo" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-maven-plugin/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-noarg/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-noarg/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-osgi-bundle/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/tools/kotlin-reflect/build" />
|
||||
@@ -75,4 +83,4 @@
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
||||
|
||||
13
ReadMe.md
13
ReadMe.md
@@ -1,4 +1,4 @@
|
||||
<a href="https://kotlinslackin.herokuapp.com"><img src="https://kotlinslackin.herokuapp.com/badge.svg" height="20"></a>
|
||||
<a href="http://slack.kotlinlang.org/"><img src="http://slack.kotlinlang.org/badge.svg" height="20"></a>
|
||||
[](https://teamcity.jetbrains.com/viewType.html?buildTypeId=bt345&branch_Kotlin=%3Cdefault%3E&tab=buildTypeStatusDiv)
|
||||
[](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.jetbrains.kotlin%22)
|
||||
[](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
@@ -15,7 +15,7 @@ Welcome to [Kotlin](https://kotlinlang.org/)! Some handy links:
|
||||
* [Forum](https://discuss.kotlinlang.org/)
|
||||
* [Kotlin Blog](https://blog.jetbrains.com/kotlin/)
|
||||
* [Follow Kotlin on Twitter](https://twitter.com/kotlin)
|
||||
* [Public Slack channel](https://kotlinslackin.herokuapp.com/)
|
||||
* [Public Slack channel](http://slack.kotlinlang.org/)
|
||||
* [TeamCity CI build](https://teamcity.jetbrains.com/project.html?tab=projectOverview&projectId=Kotlin)
|
||||
|
||||
## Editing Kotlin
|
||||
@@ -168,12 +168,15 @@ The best way to submit a patch is to [fork the project on github](https://help.g
|
||||
[pull request](https://help.github.com/articles/creating-a-pull-request/) via [github](https://github.com).
|
||||
|
||||
If you create your own fork, it might help to enable rebase by default
|
||||
when you pull by executing `git config --global pull.rebase
|
||||
true`. This will avoid your local repo having too many merge commits
|
||||
when you pull by executing
|
||||
``` bash
|
||||
git config --global pull.rebase true
|
||||
```
|
||||
This will avoid your local repo having too many merge commits
|
||||
which will help keep your pull request simple and easy to apply.
|
||||
|
||||
## Commit comments
|
||||
|
||||
If you include in your comment this text (where KT-1234 is the Issue ID in the [Issue Tracker](https://youtrack.jetbrains.com/issues/KT), the issue will get automatically marked as fixed.
|
||||
If you include in your comment this text (where KT-1234 is the Issue ID in the [Issue Tracker](https://youtrack.jetbrains.com/issues/KT)), the issue will get automatically marked as fixed.
|
||||
|
||||
#KT-1234 Fixed
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.compilerRunner;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.Argument;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt;
|
||||
import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
@@ -32,7 +32,7 @@ public class ArgumentUtils {
|
||||
private ArgumentUtils() {}
|
||||
|
||||
@NotNull
|
||||
public static List<String> convertArgumentsToStringList(@NotNull CommonCompilerArguments arguments)
|
||||
public static List<String> convertArgumentsToStringList(@NotNull CommonToolArguments arguments)
|
||||
throws InstantiationException, IllegalAccessException {
|
||||
List<String> result = new ArrayList<>();
|
||||
convertArgumentsToStringList(arguments, arguments.getClass().newInstance(), arguments.getClass(), result);
|
||||
@@ -41,8 +41,8 @@ public class ArgumentUtils {
|
||||
}
|
||||
|
||||
private static void convertArgumentsToStringList(
|
||||
@NotNull CommonCompilerArguments arguments,
|
||||
@NotNull CommonCompilerArguments defaultArguments,
|
||||
@NotNull CommonToolArguments arguments,
|
||||
@NotNull CommonToolArguments defaultArguments,
|
||||
@NotNull Class<?> clazz,
|
||||
@NotNull List<String> result
|
||||
) throws IllegalAccessException, InstantiationException {
|
||||
@@ -61,7 +61,7 @@ public class ArgumentUtils {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Objects.equals(value, defaultValue)) continue;
|
||||
if (value == null || Objects.equals(value, defaultValue)) continue;
|
||||
|
||||
Class<?> fieldType = field.getType();
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ interface ICReporter {
|
||||
fun reportCompileIteration(sourceFiles: Collection<File>, exitCode: ExitCode) {}
|
||||
|
||||
fun pathsAsString(files: Iterable<File>): String =
|
||||
files.map { it.canonicalPath }.joinToString()
|
||||
files.joinToString { it.canonicalPath }
|
||||
|
||||
fun pathsAsString(vararg files: File): String =
|
||||
pathsAsString(files.toList())
|
||||
|
||||
@@ -197,7 +197,7 @@ open class LookupStorage(private val targetDataDir: File) : BasicMapsOwner() {
|
||||
}
|
||||
|
||||
class LookupTrackerImpl(private val delegate: LookupTracker) : LookupTracker {
|
||||
val lookups = MultiMap<LookupSymbol, String>()
|
||||
val lookups = MultiMap.createSet<LookupSymbol, String>()
|
||||
val pathInterner = StringInterner()
|
||||
private val interner = StringInterner()
|
||||
|
||||
|
||||
@@ -56,6 +56,12 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.packageModuleName), new.getExtension(JvmProtoBuf.packageModuleName))) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.packageLocalVariable) != new.getExtensionCount(JvmProtoBuf.packageLocalVariable)) return false
|
||||
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.packageLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.packageLocalVariable, i), new.getExtension(JvmProtoBuf.packageLocalVariable, i))) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
enum class ProtoBufPackageKind {
|
||||
@@ -64,7 +70,8 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
TYPE_ALIAS_LIST,
|
||||
TYPE_TABLE,
|
||||
SINCE_KOTLIN_INFO_TABLE,
|
||||
PACKAGE_MODULE_NAME
|
||||
PACKAGE_MODULE_NAME,
|
||||
PACKAGE_LOCAL_VARIABLE_LIST
|
||||
}
|
||||
|
||||
fun difference(old: ProtoBuf.Package, new: ProtoBuf.Package): EnumSet<ProtoBufPackageKind> {
|
||||
@@ -91,6 +98,12 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.packageModuleName), new.getExtension(JvmProtoBuf.packageModuleName))) result.add(ProtoBufPackageKind.PACKAGE_MODULE_NAME)
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.packageLocalVariable) != new.getExtensionCount(JvmProtoBuf.packageLocalVariable)) result.add(ProtoBufPackageKind.PACKAGE_LOCAL_VARIABLE_LIST)
|
||||
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.packageLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.packageLocalVariable, i), new.getExtension(JvmProtoBuf.packageLocalVariable, i))) result.add(ProtoBufPackageKind.PACKAGE_LOCAL_VARIABLE_LIST)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -147,6 +160,12 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.classModuleName), new.getExtension(JvmProtoBuf.classModuleName))) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.classLocalVariable) != new.getExtensionCount(JvmProtoBuf.classLocalVariable)) return false
|
||||
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.classLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.classLocalVariable, i), new.getExtension(JvmProtoBuf.classLocalVariable, i))) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
enum class ProtoBufClassKind {
|
||||
@@ -166,7 +185,8 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
TYPE_TABLE,
|
||||
SINCE_KOTLIN_INFO,
|
||||
SINCE_KOTLIN_INFO_TABLE,
|
||||
CLASS_MODULE_NAME
|
||||
CLASS_MODULE_NAME,
|
||||
CLASS_LOCAL_VARIABLE_LIST
|
||||
}
|
||||
|
||||
fun difference(old: ProtoBuf.Class, new: ProtoBuf.Class): EnumSet<ProtoBufClassKind> {
|
||||
@@ -224,6 +244,12 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.classModuleName), new.getExtension(JvmProtoBuf.classModuleName))) result.add(ProtoBufClassKind.CLASS_MODULE_NAME)
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.classLocalVariable) != new.getExtensionCount(JvmProtoBuf.classLocalVariable)) result.add(ProtoBufClassKind.CLASS_LOCAL_VARIABLE_LIST)
|
||||
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.classLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.classLocalVariable, i), new.getExtension(JvmProtoBuf.classLocalVariable, i))) result.add(ProtoBufClassKind.CLASS_LOCAL_VARIABLE_LIST)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1053,6 +1079,10 @@ fun ProtoBuf.Package.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int)
|
||||
hashCode = 31 * hashCode + stringIndexes(getExtension(JvmProtoBuf.packageModuleName))
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JvmProtoBuf.packageLocalVariable) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.packageLocalVariable, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1125,6 +1155,10 @@ fun ProtoBuf.Class.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) ->
|
||||
hashCode = 31 * hashCode + stringIndexes(getExtension(JvmProtoBuf.classModuleName))
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JvmProtoBuf.classLocalVariable) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.classLocalVariable, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +41,7 @@ import java.util.*
|
||||
|
||||
|
||||
fun Iterable<File>.javaSourceRoots(roots: Iterable<File>): Iterable<File> =
|
||||
filter(File::isJavaFile)
|
||||
.map { findSrcDirRoot(it, roots) }
|
||||
.filterNotNull()
|
||||
filter(File::isJavaFile).mapNotNull { findSrcDirRoot(it, roots) }
|
||||
|
||||
fun makeModuleFile(name: String, isTest: Boolean, outputDir: File, sourcesToCompile: Iterable<File>, javaSourceRoots: Iterable<File>, classpath: Iterable<File>, friendDirs: Iterable<File>): File {
|
||||
val builder = KotlinModuleXmlBuilder()
|
||||
@@ -166,7 +164,7 @@ fun<Target> OutputItemsCollectorImpl.generatedFiles(
|
||||
return outputs.map { outputItem ->
|
||||
val target =
|
||||
outputItem.sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?:
|
||||
targets.filter { getOutputDir(it)?.let { outputItem.outputFile.startsWith(it) } ?: false }.singleOrNull() ?:
|
||||
targets.singleOrNull { getOutputDir(it)?.let { outputItem.outputFile.startsWith(it) } ?: false } ?:
|
||||
representativeTarget
|
||||
|
||||
when (outputItem.outputFile.extension) {
|
||||
|
||||
@@ -186,7 +186,8 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
}
|
||||
|
||||
for (kind in diff) {
|
||||
when (kind!!) {
|
||||
@Suppress("UNUSED_VARIABLE") // To make this 'when' exhaustive
|
||||
val unused: Any = when (kind!!) {
|
||||
ProtoBufClassKind.COMPANION_OBJECT_NAME -> {
|
||||
if (oldProto.hasCompanionObjectName()) oldProto.companionObjectName.oldToNames()
|
||||
if (newProto.hasCompanionObjectName()) newProto.companionObjectName.newToNames()
|
||||
@@ -203,10 +204,7 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
}
|
||||
ProtoBufClassKind.CONSTRUCTOR_LIST -> {
|
||||
val differentNonPrivateConstructors = calcDifferenceForNonPrivateMembers(ProtoBuf.Class::getConstructorList)
|
||||
|
||||
if (differentNonPrivateConstructors.isNotEmpty()) {
|
||||
isClassAffected = true
|
||||
}
|
||||
isClassAffected = isClassAffected || differentNonPrivateConstructors.isNotEmpty()
|
||||
}
|
||||
ProtoBufClassKind.FUNCTION_LIST ->
|
||||
names.addAll(calcDifferenceForNonPrivateMembers(ProtoBuf.Class::getFunctionList))
|
||||
@@ -238,6 +236,9 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
ProtoBufClassKind.CLASS_MODULE_NAME -> {
|
||||
// TODO
|
||||
}
|
||||
ProtoBufClassKind.CLASS_LOCAL_VARIABLE_LIST -> {
|
||||
// Not affected, local variables are not accessible outside of a file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +268,8 @@ private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newDa
|
||||
}
|
||||
|
||||
for (kind in diff) {
|
||||
when (kind!!) {
|
||||
@Suppress("UNUSED_VARIABLE") // To make this 'when' exhaustive
|
||||
val unused: Any = when (kind!!) {
|
||||
ProtoBufPackageKind.FUNCTION_LIST ->
|
||||
names.addAll(calcDifferenceForNonPrivateMembers(ProtoBuf.Package::getFunctionList))
|
||||
ProtoBufPackageKind.PROPERTY_LIST ->
|
||||
@@ -279,7 +281,9 @@ private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newDa
|
||||
ProtoBufPackageKind.PACKAGE_MODULE_NAME -> {
|
||||
// TODO
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unsupported kind: $kind")
|
||||
ProtoBufPackageKind.PACKAGE_LOCAL_VARIABLE_LIST -> {
|
||||
// Not affected, local variables are not accessible outside of a file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,5 +42,5 @@ open class BasicMapsOwner {
|
||||
maps.forEach { it.flush(memoryCachesOnly) }
|
||||
}
|
||||
|
||||
@TestOnly fun dump(): String = maps.map { it.dump() }.joinToString("\n\n")
|
||||
@TestOnly fun dump(): String = maps.joinToString("\n\n") { it.dump() }
|
||||
}
|
||||
@@ -22202,8 +22202,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
@@ -22213,8 +22213,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
@@ -22419,8 +22419,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
@@ -22432,8 +22432,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
@@ -22913,8 +22913,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
@@ -22926,8 +22926,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
@@ -22939,8 +22939,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
@@ -22955,8 +22955,8 @@ public final class DebugProtoBuf {
|
||||
* <code>optional int32 flags = 1 [default = 0];</code>
|
||||
*
|
||||
* <pre>
|
||||
*declaresDefault
|
||||
*hasAnnotations
|
||||
*declaresDefault
|
||||
*isCrossinline
|
||||
*isNoinline
|
||||
* </pre>
|
||||
|
||||
@@ -14,7 +14,9 @@ public final class DebugJvmProtoBuf {
|
||||
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.isRaw);
|
||||
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.typeParameterAnnotation);
|
||||
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.classModuleName);
|
||||
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.classLocalVariable);
|
||||
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.packageModuleName);
|
||||
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.packageLocalVariable);
|
||||
}
|
||||
public interface StringTableTypesOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:org.jetbrains.kotlin.serialization.jvm.StringTableTypes)
|
||||
@@ -4586,6 +4588,17 @@ public final class DebugJvmProtoBuf {
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Integer.class,
|
||||
null);
|
||||
public static final int CLASS_LOCAL_VARIABLE_FIELD_NUMBER = 102;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Class { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Class,
|
||||
java.util.List<org.jetbrains.kotlin.serialization.DebugProtoBuf.Property>> classLocalVariable = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Property.class,
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Property.getDefaultInstance());
|
||||
public static final int PACKAGE_MODULE_NAME_FIELD_NUMBER = 101;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Package { ... }</code>
|
||||
@@ -4597,6 +4610,17 @@ public final class DebugJvmProtoBuf {
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Integer.class,
|
||||
null);
|
||||
public static final int PACKAGE_LOCAL_VARIABLE_FIELD_NUMBER = 102;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.kotlin.serialization.Package { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
org.jetbrains.kotlin.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Package,
|
||||
java.util.List<org.jetbrains.kotlin.serialization.DebugProtoBuf.Property>> packageLocalVariable = org.jetbrains.kotlin.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Property.class,
|
||||
org.jetbrains.kotlin.serialization.DebugProtoBuf.Property.getDefaultInstance());
|
||||
private static final org.jetbrains.kotlin.protobuf.Descriptors.Descriptor
|
||||
internal_static_org_jetbrains_kotlin_serialization_jvm_StringTableTypes_descriptor;
|
||||
private static
|
||||
@@ -4678,9 +4702,15 @@ public final class DebugJvmProtoBuf {
|
||||
"g.jetbrains.kotlin.serialization.Annotat" +
|
||||
"ion:J\n\021class_module_name\022).org.jetbrains" +
|
||||
".kotlin.serialization.Class\030e \001(\005B\004\230\265\030\001:" +
|
||||
"N\n\023package_module_name\022+.org.jetbrains.k" +
|
||||
"otlin.serialization.Package\030e \001(\005B\004\230\265\030\001B" +
|
||||
"\022B\020DebugJvmProtoBuf"
|
||||
"u\n\024class_local_variable\022).org.jetbrains." +
|
||||
"kotlin.serialization.Class\030f \003(\0132,.org.j" +
|
||||
"etbrains.kotlin.serialization.Property:N",
|
||||
"\n\023package_module_name\022+.org.jetbrains.ko" +
|
||||
"tlin.serialization.Package\030e \001(\005B\004\230\265\030\001:y" +
|
||||
"\n\026package_local_variable\022+.org.jetbrains" +
|
||||
".kotlin.serialization.Package\030f \003(\0132,.or" +
|
||||
"g.jetbrains.kotlin.serialization.Propert" +
|
||||
"yB\022B\020DebugJvmProtoBuf"
|
||||
};
|
||||
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||
@@ -4733,7 +4763,9 @@ public final class DebugJvmProtoBuf {
|
||||
isRaw.internalInit(descriptor.getExtensions().get(4));
|
||||
typeParameterAnnotation.internalInit(descriptor.getExtensions().get(5));
|
||||
classModuleName.internalInit(descriptor.getExtensions().get(6));
|
||||
packageModuleName.internalInit(descriptor.getExtensions().get(7));
|
||||
classLocalVariable.internalInit(descriptor.getExtensions().get(7));
|
||||
packageModuleName.internalInit(descriptor.getExtensions().get(8));
|
||||
packageLocalVariable.internalInit(descriptor.getExtensions().get(9));
|
||||
org.jetbrains.kotlin.protobuf.ExtensionRegistry registry =
|
||||
org.jetbrains.kotlin.protobuf.ExtensionRegistry.newInstance();
|
||||
registry.add(org.jetbrains.kotlin.serialization.DebugExtOptionsProtoBuf.stringIdInTable);
|
||||
|
||||
37
build.xml
37
build.xml
@@ -26,7 +26,6 @@
|
||||
<property name="tools.jar" value="${env.JDK_18}/lib/tools.jar"/>
|
||||
|
||||
<property name="java.target" value="1.8"/>
|
||||
<property name="java.target.1.6" value="1.6"/>
|
||||
|
||||
<condition property="bootstrap.or.local.build" value="true" else="false">
|
||||
<or>
|
||||
@@ -65,6 +64,8 @@
|
||||
<fileset dir="${dependencies}" includes="jansi.jar"/>
|
||||
<fileset dir="${dependencies}" includes="jline.jar"/>
|
||||
<fileset dir="${dependencies}" includes="javaslang-2.0.6.jar"/>
|
||||
<fileset dir="${dependencies}" includes="json-org.jar"/>
|
||||
<fileset dir="${dependencies}" includes="kotlinx-coroutines-core.jar"/>
|
||||
<fileset dir="${basedir}/ideaSDK/jps" includes="jps-model.jar"/>
|
||||
</path>
|
||||
|
||||
@@ -154,6 +155,7 @@
|
||||
<include name="js.parser/**"/>
|
||||
<include name="js.serializer/**"/>
|
||||
<include name="js.dce/**"/>
|
||||
<exclude name="**/META-INF/services/**"/>
|
||||
</patternset>
|
||||
|
||||
<path id="compilerSources.path">
|
||||
@@ -181,6 +183,9 @@
|
||||
<target name="init">
|
||||
<mkdir dir="${kotlin-home}"/>
|
||||
<mkdir dir="${kotlin-home}/lib"/>
|
||||
|
||||
<fail unless="env.JDK_16" message="JDK_16 environment variable is not set."/>
|
||||
<fail unless="env.JDK_18" message="JDK_18 environment variable is not set."/>
|
||||
</target>
|
||||
|
||||
<target name="prepare-dist">
|
||||
@@ -229,6 +234,15 @@
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="copy-bootstrap-to-dist"
|
||||
depends="clean"
|
||||
description="Use bootstrap compiler instead of building one from sources">
|
||||
<mkdir dir="${kotlin-home}"/>
|
||||
<copy todir="${kotlin-home}">
|
||||
<fileset dir="${bootstrap.compiler.home}"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="compiler-sources">
|
||||
<jar jarfile="${output}/kotlin-compiler-sources.jar">
|
||||
<!-- TODO How to convert it from pathset or dirset ? -->
|
||||
@@ -283,7 +297,7 @@
|
||||
<target name="preloader">
|
||||
<cleandir dir="${output}/classes/preloader"/>
|
||||
<javac destdir="${output}/classes/preloader" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false"
|
||||
source="${java.target}" target="${java.target}">
|
||||
source="1.6" target="1.6">
|
||||
<src location="${basedir}/compiler/preloader/src"/>
|
||||
</javac>
|
||||
|
||||
@@ -304,6 +318,9 @@
|
||||
<cleandir dir="${output}/classes/runner"/>
|
||||
<kotlinc output="${output}/classes/runner">
|
||||
<src location="${basedir}/compiler/cli/cli-runner/src"/>
|
||||
<compilerarg line="-jvm-target 1.6"/>
|
||||
<compilerarg value="-jdk-home"/>
|
||||
<compilerarg value="${env.JDK_16}"/>
|
||||
</kotlinc>
|
||||
|
||||
<local name="runtime.jar"/>
|
||||
@@ -354,6 +371,7 @@
|
||||
<fileset dir="${output}/builtins">
|
||||
<include name="kotlin/**"/>
|
||||
</fileset>
|
||||
<fileset dir="${basedir}/core/deserialization/src" includes="META-INF/services/**"/>
|
||||
<fileset dir="${basedir}/core/descriptor.loader.java/src" includes="META-INF/services/**"/>
|
||||
<fileset dir="${basedir}/compiler/frontend.java/src" includes="META-INF/services/**"/>
|
||||
<fileset dir="${basedir}/compiler/backend/src" includes="META-INF/services/**"/>
|
||||
@@ -371,20 +389,22 @@
|
||||
<zipfileset src="${basedir}/ideaSDK/core/asm-all.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/guava-19.0.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/intellij-core.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/jdom.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/jdom.jar" excludes="META-INF/jb/** META-INF/LICENSE"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/jna.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/log4j.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/log4j.jar" excludes="META-INF/jb/** META-INF/LICENSE"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/picocontainer.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/snappy-in-java-0.5.1.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/trove4j.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/xpp3-1.1.4-min.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/xstream-1.4.8.jar"/>
|
||||
<zipfileset src="${idea.sdk}/lib/jna-platform.jar"/>
|
||||
<zipfileset src="${idea.sdk}/lib/oromatcher.jar"/>
|
||||
<zipfileset src="${idea.sdk}/lib/oromatcher.jar" excludes="META-INF/jb/** META-INF/LICENSE"/>
|
||||
<zipfileset src="${idea.sdk}/jps/jps-model.jar"/>
|
||||
<zipfileset src="${dependencies}/jline.jar"/>
|
||||
<zipfileset src="${dependencies}/javaslang-2.0.6.jar"/>
|
||||
<zipfileset src="${dependencies}/json-org.jar"/>
|
||||
<zipfileset src="${protobuf.jar}"/>
|
||||
<zipfileset src="${dependencies}/kotlinx-coroutines-core.jar"/>
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
|
||||
@@ -395,9 +415,6 @@
|
||||
|
||||
<attribute name="Class-Path" value="${compiler.manifest.class.path}"/>
|
||||
<attribute name="Main-Class" value="org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"/>
|
||||
|
||||
<!-- This is needed if the compiler is run on Java 9 via "java -jar kotlin-compiler.jar" -->
|
||||
<attribute name="Add-Opens" value="java.base/java.lang java.base/java.util java.base/java.util.concurrent.atomic java.base/jdk.internal.misc"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</sequential>
|
||||
@@ -638,9 +655,11 @@
|
||||
<skip pattern="kotlin/Metadata"/>
|
||||
<src>
|
||||
<pathelement path="plugins/android-extensions/android-extensions-compiler/src"/>
|
||||
<pathelement path="plugins/android-extensions/android-extensions-runtime/src"/>
|
||||
</src>
|
||||
<classpath>
|
||||
<pathelement path="${idea.sdk}/core/intellij-core.jar"/>
|
||||
<pathelement path="${idea.sdk}/plugins/android/lib/layoutlib.jar"/>
|
||||
<pathelement path="${kotlin-home}/lib/kotlin-compiler.jar"/>
|
||||
</classpath>
|
||||
</javac2>
|
||||
@@ -859,7 +878,7 @@
|
||||
</java>
|
||||
|
||||
<javac2 srcdir="${toString:src.dirset}" destdir="@{output}" debug="true" debuglevel="lines,vars,source"
|
||||
includeAntRuntime="false" source="${java.target.1.6}" target="${java.target.1.6}">
|
||||
includeAntRuntime="false" source="1.6" target="1.6">
|
||||
<skip pattern="kotlin/Metadata"/>
|
||||
<classpath>
|
||||
<path refid="classpath.path"/>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="intellij-core" level="project" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
|
||||
@@ -158,7 +158,7 @@ object CodegenUtil {
|
||||
@JvmStatic
|
||||
fun constructFakeFunctionCall(project: Project, referencedFunction: FunctionDescriptor): KtCallExpression {
|
||||
val fakeFunctionCall = StringBuilder("callableReferenceFakeCall(")
|
||||
fakeFunctionCall.append(referencedFunction.valueParameters.map { "p${it.index}" }.joinToString(", "))
|
||||
fakeFunctionCall.append(referencedFunction.valueParameters.joinToString(", ") { "p${it.index}" })
|
||||
fakeFunctionCall.append(")")
|
||||
return KtPsiFactory(project, markGenerated = false).createExpression(fakeFunctionCall.toString()) as KtCallExpression
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
* TODO: data class with zero components gets no toString/equals/hashCode methods. This is inconsistent and should be
|
||||
* changed here with the platform backends adopted.
|
||||
*/
|
||||
abstract class DataClassMethodGenerator(private val declaration: KtClassOrObject, private val bindingContext: BindingContext) {
|
||||
abstract class DataClassMethodGenerator(protected val declaration: KtClassOrObject, private val bindingContext: BindingContext) {
|
||||
protected val classDescriptor: ClassDescriptor = BindingContextUtils.getNotNull(bindingContext, BindingContext.CLASS, declaration)
|
||||
|
||||
fun generate() {
|
||||
|
||||
@@ -9,11 +9,8 @@
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" />
|
||||
<orderEntry type="module" module-name="serialization" />
|
||||
<orderEntry type="module" module-name="backend-common" exported="" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="backend.jvm" />
|
||||
<orderEntry type="module" module-name="ir.tree" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.FileMapping;
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAPBuilder;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
@@ -29,6 +28,8 @@ import org.jetbrains.org.objectweb.asm.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
|
||||
|
||||
public abstract class AbstractClassBuilder implements ClassBuilder {
|
||||
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.ASM5) {};
|
||||
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.ASM5) {};
|
||||
@@ -105,7 +106,7 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
if (!fileMappings.isEmpty() && InlineCodegenUtil.GENERATE_SMAP) {
|
||||
if (!fileMappings.isEmpty() && GENERATE_SMAP) {
|
||||
FileMapping origin = fileMappings.get(0);
|
||||
assert sourceName == null || origin.getName().equals(sourceName) : "Error " + origin.getName() + " != " + sourceName;
|
||||
getVisitor().visitSource(origin.getName(), new SMAPBuilder(origin.getName(), origin.getPath(), fileMappings).build());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* 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.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.annotation.WrappedAnnotated;
|
||||
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.annotations.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
@@ -291,32 +293,27 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
@Nullable
|
||||
private String genAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) {
|
||||
ClassifierDescriptor classifierDescriptor = getAnnotationClass(annotationDescriptor);
|
||||
assert classifierDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor;
|
||||
RetentionPolicy rp = getRetentionPolicy(classifierDescriptor);
|
||||
ClassDescriptor classDescriptor = getAnnotationClass(annotationDescriptor);
|
||||
assert classDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor;
|
||||
RetentionPolicy rp = getRetentionPolicy(classDescriptor);
|
||||
if (rp == RetentionPolicy.SOURCE && !typeMapper.getClassBuilderMode().generateSourceRetentionAnnotations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
|
||||
innerClassConsumer.addInnerClassInfoFromAnnotation(classDescriptor);
|
||||
|
||||
if (classifierDescriptor instanceof ClassDescriptor) {
|
||||
innerClassConsumer.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor));
|
||||
}
|
||||
|
||||
AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME);
|
||||
String asmTypeDescriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
|
||||
AnnotationVisitor annotationVisitor = visitAnnotation(asmTypeDescriptor, rp == RetentionPolicy.RUNTIME);
|
||||
|
||||
genAnnotationArguments(annotationDescriptor, annotationVisitor);
|
||||
annotationVisitor.visitEnd();
|
||||
|
||||
return descriptor;
|
||||
return asmTypeDescriptor;
|
||||
}
|
||||
|
||||
private void genAnnotationArguments(AnnotationDescriptor annotationDescriptor, AnnotationVisitor annotationVisitor) {
|
||||
for (Map.Entry<ValueParameterDescriptor, ConstantValue<?>> entry : annotationDescriptor.getAllValueArguments().entrySet()) {
|
||||
ValueParameterDescriptor descriptor = entry.getKey();
|
||||
String name = descriptor.getName().asString();
|
||||
genCompileTimeValue(name, entry.getValue(), annotationVisitor);
|
||||
for (Map.Entry<Name, ConstantValue<?>> entry : annotationDescriptor.getAllValueArguments().entrySet()) {
|
||||
genCompileTimeValue(entry.getKey().asString(), entry.getValue(), annotationVisitor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,16 +472,13 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName()));
|
||||
if (retentionAnnotation != null) {
|
||||
Collection<ConstantValue<?>> valueArguments = retentionAnnotation.getAllValueArguments().values();
|
||||
if (!valueArguments.isEmpty()) {
|
||||
ConstantValue<?> compileTimeConstant = valueArguments.iterator().next();
|
||||
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<?> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,15 +27,18 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.HashCode;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
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;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
@@ -137,10 +140,18 @@ public class AsmUtil {
|
||||
return primitiveTypeByBoxedType.get(boxedType);
|
||||
}
|
||||
|
||||
public static boolean isBoxedTypeOf(@NotNull Type boxedType, @NotNull Type unboxedType) {
|
||||
return unboxPrimitiveTypeOrNull(boxedType) == unboxedType;
|
||||
}
|
||||
|
||||
public static boolean isIntPrimitive(Type type) {
|
||||
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isIntOrLongPrimitive(Type type) {
|
||||
return isIntPrimitive(type) || type == Type.LONG_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isNumberPrimitiveOrBoolean(Type type) {
|
||||
return isNumberPrimitive(type) || type.getSort() == Type.BOOLEAN;
|
||||
}
|
||||
@@ -512,7 +523,7 @@ public class AsmUtil {
|
||||
});
|
||||
}
|
||||
|
||||
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) {
|
||||
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type, JvmTarget jvmTarget) {
|
||||
if (type.getSort() == Type.ARRAY) {
|
||||
Type elementType = correctElementType(type);
|
||||
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
|
||||
@@ -525,16 +536,6 @@ public class AsmUtil {
|
||||
else if (type.getSort() == Type.OBJECT) {
|
||||
iv.invokevirtual("java/lang/Object", "hashCode", "()I", false);
|
||||
}
|
||||
else if (type.getSort() == Type.LONG) {
|
||||
genLongHashCode(mv, iv);
|
||||
}
|
||||
else if (type.getSort() == Type.DOUBLE) {
|
||||
iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J", false);
|
||||
genLongHashCode(mv, iv);
|
||||
}
|
||||
else if (type.getSort() == Type.FLOAT) {
|
||||
iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I", false);
|
||||
}
|
||||
else if (type.getSort() == Type.BOOLEAN) {
|
||||
Label end = new Label();
|
||||
iv.dup();
|
||||
@@ -543,8 +544,24 @@ public class AsmUtil {
|
||||
iv.iconst(1);
|
||||
iv.mark(end);
|
||||
}
|
||||
else { // byte short char int
|
||||
// do nothing
|
||||
else {
|
||||
if (JvmTarget.JVM_1_6 == jvmTarget) {
|
||||
if (type.getSort() == Type.LONG) {
|
||||
genLongHashCode(mv, iv);
|
||||
}
|
||||
else if (type.getSort() == Type.DOUBLE) {
|
||||
iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J", false);
|
||||
genLongHashCode(mv, iv);
|
||||
}
|
||||
else if (type.getSort() == Type.FLOAT) {
|
||||
iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I", false);
|
||||
}
|
||||
else { // byte short char int
|
||||
// do nothing
|
||||
}
|
||||
} else {
|
||||
HashCode.Companion.invokeHashCode(iv, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,7 +717,7 @@ public class AsmUtil {
|
||||
if (innerType.getSort() == Type.OBJECT || innerType.getSort() == Type.ARRAY) {
|
||||
v.dup();
|
||||
v.visitLdcInsn(runtimeAssertionInfo.getMessage());
|
||||
v.invokestatic("kotlin/jvm/internal/Intrinsics", "checkExpressionValueIsNotNull",
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkExpressionValueIsNotNull",
|
||||
"(Ljava/lang/Object;Ljava/lang/String;)V", false);
|
||||
}
|
||||
StackValue.coerce(innerType, type, v);
|
||||
@@ -790,6 +807,16 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void pop2(@NotNull MethodVisitor v, @NotNull Type type) {
|
||||
if (type.getSize() == 2) {
|
||||
v.visitInsn(Opcodes.POP2);
|
||||
v.visitInsn(Opcodes.POP2);
|
||||
}
|
||||
else {
|
||||
v.visitInsn(Opcodes.POP2);
|
||||
}
|
||||
}
|
||||
|
||||
public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) {
|
||||
dup(v, type.getSize());
|
||||
}
|
||||
@@ -806,6 +833,22 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void dupx(@NotNull InstructionAdapter v, @NotNull Type type) {
|
||||
dupx(v, type.getSize());
|
||||
}
|
||||
|
||||
private static void dupx(@NotNull InstructionAdapter v, int size) {
|
||||
if (size == 2) {
|
||||
v.dup2X2();
|
||||
}
|
||||
else if (size == 1) {
|
||||
v.dupX1();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) {
|
||||
if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) {
|
||||
return;
|
||||
@@ -861,6 +904,11 @@ public class AsmUtil {
|
||||
return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type asmTypeByClassId(@NotNull ClassId classId) {
|
||||
return Type.getObjectType(classId.asString().replace('.', '$'));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String internalNameByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
|
||||
return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName();
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.kotlin.codegen.inline.NameGenerator
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
interface BaseExpressionCodegen {
|
||||
|
||||
val frameMap: FrameMap
|
||||
|
||||
val visitor: InstructionAdapter
|
||||
|
||||
val inlineNameGenerator: NameGenerator
|
||||
|
||||
val lastLineNumber: Int
|
||||
|
||||
fun consumeReifiedOperationMarker(typeParameterDescriptor: TypeParameterDescriptor)
|
||||
|
||||
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
|
||||
|
||||
fun pushClosureOnStack(
|
||||
classDescriptor: ClassDescriptor,
|
||||
putThis: Boolean,
|
||||
callGenerator: CallGenerator,
|
||||
functionReferenceReceiver: StackValue?
|
||||
)
|
||||
|
||||
fun markLineNumberAfterInlineIfNeeded()
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* 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.tree.IElementType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
abstract class NumberLikeCompare(
|
||||
left: StackValue,
|
||||
right: StackValue,
|
||||
operandType: Type,
|
||||
private val opToken: IElementType
|
||||
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
|
||||
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
|
||||
NumberCompare.patchOpcode(opcode, v, opToken, operandType)
|
||||
}
|
||||
|
||||
abstract class SafeCallFusedWithPrimitiveEqualityBase(
|
||||
opToken: IElementType,
|
||||
operandType: Type,
|
||||
left: StackValue,
|
||||
right: StackValue
|
||||
) : NumberLikeCompare(left, right, operandType, opToken) {
|
||||
private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ
|
||||
|
||||
protected abstract fun cleanupOnNullReceiver(v: InstructionAdapter)
|
||||
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
val endLabel = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
arg2!!.put(operandType, v)
|
||||
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
|
||||
v.goTo(endLabel)
|
||||
|
||||
cleanupOnNullReceiver(v)
|
||||
if (jumpIfFalse == trueIfEqual) {
|
||||
v.goTo(jumpLabel)
|
||||
}
|
||||
|
||||
v.mark(endLabel)
|
||||
}
|
||||
|
||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||
val falseLabel = Label()
|
||||
val endLabel = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
arg2!!.put(operandType, v)
|
||||
v.visitJumpInsn(patchOpcode(opcode, v), falseLabel)
|
||||
|
||||
if (!trueIfEqual) {
|
||||
val trueLabel = Label()
|
||||
v.goTo(trueLabel)
|
||||
cleanupOnNullReceiver(v)
|
||||
v.mark(trueLabel)
|
||||
}
|
||||
|
||||
v.iconst(1)
|
||||
v.goTo(endLabel)
|
||||
|
||||
if (trueIfEqual) {
|
||||
cleanupOnNullReceiver(v)
|
||||
}
|
||||
|
||||
v.mark(falseLabel)
|
||||
v.iconst(0)
|
||||
|
||||
v.mark(endLabel)
|
||||
coerceTo(type, v)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SafeCallToPrimitiveEquality(
|
||||
opToken: IElementType,
|
||||
operandType: Type,
|
||||
left: StackValue,
|
||||
right: StackValue,
|
||||
private val safeReceiverType: Type,
|
||||
private val safeReceiverIsNull: Label
|
||||
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
||||
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
||||
v.mark(safeReceiverIsNull)
|
||||
AsmUtil.pop(v, safeReceiverType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PrimitiveToSafeCallEquality(
|
||||
opToken: IElementType,
|
||||
operandType: Type,
|
||||
left: StackValue,
|
||||
right: StackValue,
|
||||
private val safeReceiverType: Type,
|
||||
private val safeReceiverIsNull: Label
|
||||
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
||||
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
||||
v.mark(safeReceiverIsNull)
|
||||
AsmUtil.pop(v, safeReceiverType)
|
||||
AsmUtil.pop(v, arg1.type)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class BoxedToPrimitiveEquality private constructor(
|
||||
leftBoxed: StackValue,
|
||||
rightPrimitive: StackValue,
|
||||
primitiveType: Type,
|
||||
private val frameMap: FrameMap
|
||||
) : NumberLikeCompare(leftBoxed, rightPrimitive, primitiveType, KtTokens.EQEQ) {
|
||||
private val boxedType = arg1.type
|
||||
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
if (arg2!!.canHaveSideEffects()) {
|
||||
val tmp = frameMap.enterTemp(operandType)
|
||||
doJump(
|
||||
v, jumpLabel, jumpIfFalse,
|
||||
{
|
||||
arg1.put(boxedType, v)
|
||||
arg2.put(operandType, v)
|
||||
v.store(tmp, operandType)
|
||||
},
|
||||
{ v.load(tmp, operandType) }
|
||||
)
|
||||
frameMap.leaveTemp(operandType)
|
||||
}
|
||||
else {
|
||||
doJump(
|
||||
v, jumpLabel, jumpIfFalse,
|
||||
{ arg1.put(boxedType, v) },
|
||||
{ arg2.put(operandType, v) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun doJump(
|
||||
v: InstructionAdapter,
|
||||
jumpLabel: Label,
|
||||
jumpIfFalse: Boolean,
|
||||
putArg1: () -> Unit,
|
||||
putArg2: () -> Unit
|
||||
) {
|
||||
val notNullLabel = Label()
|
||||
val endLabel = Label()
|
||||
|
||||
putArg1()
|
||||
AsmUtil.dup(v, boxedType)
|
||||
v.ifnonnull(notNullLabel)
|
||||
|
||||
AsmUtil.pop(v, boxedType)
|
||||
if (jumpIfFalse) v.goTo(jumpLabel) else v.goTo(endLabel)
|
||||
|
||||
v.mark(notNullLabel)
|
||||
coerce(boxedType, operandType, v)
|
||||
putArg2()
|
||||
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
|
||||
|
||||
v.mark(endLabel)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun create(
|
||||
opToken: IElementType,
|
||||
left: StackValue,
|
||||
leftType: Type,
|
||||
right: StackValue,
|
||||
rightType: Type,
|
||||
frameMap: FrameMap
|
||||
): BranchedValue =
|
||||
if (!isApplicable(opToken, leftType, rightType))
|
||||
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
||||
else when (opToken) {
|
||||
KtTokens.EQEQ -> BoxedToPrimitiveEquality(left, right, rightType, frameMap)
|
||||
KtTokens.EXCLEQ -> Invert(BoxedToPrimitiveEquality(left, right, rightType, frameMap))
|
||||
else -> throw AssertionError("Unexpected opToken: $opToken")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
||||
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
||||
AsmUtil.isIntOrLongPrimitive(rightType) &&
|
||||
AsmUtil.isBoxedTypeOf(leftType, rightType)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PrimitiveToSomethingEquality
|
||||
protected constructor(
|
||||
leftPrimitive: StackValue,
|
||||
right: StackValue,
|
||||
primitiveType: Type
|
||||
) : NumberLikeCompare(leftPrimitive, right, primitiveType, KtTokens.EQEQ) {
|
||||
protected val primitiveType = leftPrimitive.type
|
||||
protected val rightType = right.type
|
||||
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
val notNullLabel = Label()
|
||||
val endLabel = Label()
|
||||
|
||||
arg1.put(primitiveType, v)
|
||||
arg2!!.put(rightType, v)
|
||||
AsmUtil.dup(v, rightType)
|
||||
jumpIfCanCompareTopWithPrimitive(v, notNullLabel)
|
||||
|
||||
AsmUtil.pop(v, rightType)
|
||||
AsmUtil.pop(v, primitiveType)
|
||||
if (jumpIfFalse) v.goTo(jumpLabel) else v.goTo(endLabel)
|
||||
|
||||
v.mark(notNullLabel)
|
||||
coerceRightToPrimitive(v)
|
||||
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
|
||||
|
||||
v.mark(endLabel)
|
||||
}
|
||||
|
||||
protected abstract fun jumpIfCanCompareTopWithPrimitive(v: InstructionAdapter, label: Label)
|
||||
protected abstract fun coerceRightToPrimitive(v: InstructionAdapter)
|
||||
}
|
||||
|
||||
|
||||
class PrimitiveToBoxedEquality private constructor(
|
||||
leftPrimitive: StackValue,
|
||||
rightBoxed: StackValue,
|
||||
primitiveType: Type
|
||||
) : PrimitiveToSomethingEquality(leftPrimitive, rightBoxed, primitiveType) {
|
||||
private val boxedType = rightBoxed.type
|
||||
|
||||
override fun jumpIfCanCompareTopWithPrimitive(v: InstructionAdapter, label: Label) {
|
||||
v.ifnonnull(label)
|
||||
}
|
||||
|
||||
override fun coerceRightToPrimitive(v: InstructionAdapter) {
|
||||
coerce(boxedType, primitiveType, v)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
|
||||
if (!isApplicable(opToken, leftType, rightType))
|
||||
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
||||
else when (opToken) {
|
||||
KtTokens.EQEQ -> PrimitiveToBoxedEquality(left, right, leftType)
|
||||
KtTokens.EXCLEQ -> Invert(PrimitiveToBoxedEquality(left, right, leftType))
|
||||
else -> throw AssertionError("Unexpected opToken: $opToken")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
||||
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
||||
AsmUtil.isIntOrLongPrimitive(leftType) &&
|
||||
AsmUtil.isBoxedTypeOf(rightType, leftType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PrimitiveToObjectEquality private constructor(
|
||||
leftPrimitive: StackValue,
|
||||
rightObject: StackValue,
|
||||
primitiveType: Type
|
||||
) : PrimitiveToSomethingEquality(leftPrimitive, rightObject, primitiveType) {
|
||||
private val boxedType = AsmUtil.boxType(primitiveType)
|
||||
|
||||
override fun jumpIfCanCompareTopWithPrimitive(v: InstructionAdapter, label: Label) {
|
||||
v.instanceOf(boxedType)
|
||||
v.ifne(label)
|
||||
}
|
||||
|
||||
override fun coerceRightToPrimitive(v: InstructionAdapter) {
|
||||
coerce(rightType, boxedType, v)
|
||||
coerce(boxedType, primitiveType, v)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
|
||||
if (!isApplicable(opToken, leftType, rightType))
|
||||
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
||||
else when (opToken) {
|
||||
KtTokens.EQEQ -> PrimitiveToObjectEquality(left, right, leftType)
|
||||
KtTokens.EXCLEQ -> Invert(PrimitiveToObjectEquality(left, right, leftType))
|
||||
else -> throw AssertionError("Unexpected opToken: $opToken")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
||||
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
||||
AsmUtil.isIntOrLongPrimitive(leftType) &&
|
||||
rightType.sort == Type.OBJECT
|
||||
}
|
||||
}
|
||||
@@ -54,9 +54,7 @@ open class BranchedValue(
|
||||
condJump(jumpLabel, v, jumpIfFalse)
|
||||
}
|
||||
|
||||
protected open fun patchOpcode(opcode: Int, v: InstructionAdapter): Int {
|
||||
return opcode
|
||||
}
|
||||
protected open fun patchOpcode(opcode: Int, v: InstructionAdapter): Int = opcode
|
||||
|
||||
companion object {
|
||||
val negatedOperations = hashMapOf<Int, Int>()
|
||||
@@ -120,13 +118,9 @@ open class BranchedValue(
|
||||
negatedOperations.put(negatedOp, op)
|
||||
}
|
||||
|
||||
fun booleanConstant(value: Boolean): BranchedValue {
|
||||
return if (value) TRUE else FALSE
|
||||
}
|
||||
fun booleanConstant(value: Boolean): BranchedValue = if (value) TRUE else FALSE
|
||||
|
||||
fun createInvertValue(argument: StackValue): StackValue {
|
||||
return Invert(condJump(argument))
|
||||
}
|
||||
fun createInvertValue(argument: StackValue): StackValue = Invert(condJump(argument))
|
||||
|
||||
fun condJump(condition: StackValue, label: Label, jumpIfFalse: Boolean, iv: InstructionAdapter) {
|
||||
condJump(condition).condJump(label, iv, jumpIfFalse)
|
||||
@@ -136,14 +130,11 @@ open class BranchedValue(
|
||||
condJump(condition).loopJump(label, iv, jumpIfFalse)
|
||||
}
|
||||
|
||||
fun condJump(condition: StackValue): CondJump {
|
||||
return CondJump(if (condition is BranchedValue) {
|
||||
condition
|
||||
}
|
||||
else {
|
||||
BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ)
|
||||
}, IFEQ)
|
||||
}
|
||||
fun condJump(condition: StackValue): CondJump =
|
||||
CondJump(
|
||||
condition as? BranchedValue ?: BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ),
|
||||
IFEQ
|
||||
)
|
||||
|
||||
fun cmp(opToken: IElementType, operandType: Type, left: StackValue, right: StackValue): StackValue =
|
||||
if (operandType.sort == Type.OBJECT)
|
||||
@@ -203,7 +194,7 @@ class CondJump(val condition: BranchedValue, op: Int) : BranchedValue(condition,
|
||||
}
|
||||
|
||||
class NumberCompare(
|
||||
val opToken: IElementType,
|
||||
private val opToken: IElementType,
|
||||
operandType: Type,
|
||||
left: StackValue,
|
||||
right: StackValue
|
||||
@@ -213,17 +204,15 @@ class NumberCompare(
|
||||
patchOpcode(opcode, v, opToken, operandType)
|
||||
|
||||
companion object {
|
||||
fun getNumberCompareOpcode(opToken: IElementType): Int {
|
||||
return when (opToken) {
|
||||
KtTokens.EQEQ, KtTokens.EQEQEQ -> IFNE
|
||||
KtTokens.EXCLEQ, KtTokens.EXCLEQEQEQ -> IFEQ
|
||||
KtTokens.GT -> IFLE
|
||||
KtTokens.GTEQ -> IFLT
|
||||
KtTokens.LT -> IFGE
|
||||
KtTokens.LTEQ -> IFGT
|
||||
else -> {
|
||||
throw UnsupportedOperationException("Don't know how to generate this condJump: " + opToken)
|
||||
}
|
||||
fun getNumberCompareOpcode(opToken: IElementType): Int = when (opToken) {
|
||||
KtTokens.EQEQ, KtTokens.EQEQEQ -> IFNE
|
||||
KtTokens.EXCLEQ, KtTokens.EXCLEQEQEQ -> IFEQ
|
||||
KtTokens.GT -> IFLE
|
||||
KtTokens.GTEQ -> IFLT
|
||||
KtTokens.LT -> IFGE
|
||||
KtTokens.LTEQ -> IFGT
|
||||
else -> {
|
||||
throw UnsupportedOperationException("Don't know how to generate this condJump: " + opToken)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,100 +247,11 @@ class ObjectCompare(
|
||||
) : BranchedValue(left, right, operandType, ObjectCompare.getObjectCompareOpcode(opToken)) {
|
||||
|
||||
companion object {
|
||||
fun getObjectCompareOpcode(opToken: IElementType): Int {
|
||||
return when (opToken) {
|
||||
KtTokens.EQEQEQ -> IF_ACMPNE
|
||||
KtTokens.EXCLEQEQEQ -> IF_ACMPEQ
|
||||
else -> throw UnsupportedOperationException("don't know how to generate this condjump")
|
||||
}
|
||||
fun getObjectCompareOpcode(opToken: IElementType): Int = when (opToken) {
|
||||
KtTokens.EQEQEQ -> IF_ACMPNE
|
||||
KtTokens.EXCLEQEQEQ -> IF_ACMPEQ
|
||||
else -> throw UnsupportedOperationException("don't know how to generate this condjump")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SafeCallFusedWithPrimitiveEqualityBase(
|
||||
val opToken: IElementType,
|
||||
operandType: Type,
|
||||
left: StackValue,
|
||||
right: StackValue
|
||||
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
|
||||
private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ
|
||||
|
||||
protected abstract fun cleanupOnNullReceiver(v: InstructionAdapter)
|
||||
|
||||
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
|
||||
NumberCompare.patchOpcode(opcode, v, opToken, operandType)
|
||||
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
val endLabel = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
arg2!!.put(operandType, v)
|
||||
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
|
||||
v.goTo(endLabel)
|
||||
|
||||
cleanupOnNullReceiver(v)
|
||||
if (jumpIfFalse == trueIfEqual) {
|
||||
v.goTo(jumpLabel)
|
||||
}
|
||||
|
||||
v.mark(endLabel)
|
||||
}
|
||||
|
||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||
val falseLabel = Label()
|
||||
val endLabel = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
arg2!!.put(operandType, v)
|
||||
v.visitJumpInsn(patchOpcode(opcode, v), falseLabel)
|
||||
|
||||
if (!trueIfEqual) {
|
||||
val trueLabel = Label()
|
||||
v.goTo(trueLabel)
|
||||
cleanupOnNullReceiver(v)
|
||||
v.mark(trueLabel)
|
||||
}
|
||||
|
||||
v.iconst(1)
|
||||
v.goTo(endLabel)
|
||||
|
||||
if (trueIfEqual) {
|
||||
cleanupOnNullReceiver(v)
|
||||
}
|
||||
|
||||
v.mark(falseLabel)
|
||||
v.iconst(0)
|
||||
|
||||
v.mark(endLabel)
|
||||
coerceTo(type, v)
|
||||
}
|
||||
}
|
||||
|
||||
class SafeCallToPrimitiveEquality(
|
||||
opToken: IElementType,
|
||||
operandType: Type,
|
||||
left: StackValue,
|
||||
right: StackValue,
|
||||
val safeReceiverType: Type,
|
||||
val safeReceiverIsNull: Label
|
||||
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
||||
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
||||
v.mark(safeReceiverIsNull)
|
||||
AsmUtil.pop(v, safeReceiverType)
|
||||
}
|
||||
}
|
||||
|
||||
class PrimitiveToSafeCallEquality(
|
||||
opToken: IElementType,
|
||||
operandType: Type,
|
||||
left: StackValue,
|
||||
right: StackValue,
|
||||
val safeReceiverType: Type,
|
||||
val safeReceiverIsNull: Label
|
||||
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
||||
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
||||
v.mark(safeReceiverIsNull)
|
||||
AsmUtil.pop(v, safeReceiverType)
|
||||
AsmUtil.pop(v, arg1.type)
|
||||
}
|
||||
}
|
||||
@@ -31,9 +31,9 @@ enum class ValueKind {
|
||||
DEFAULT_LAMBDA_CAPTURED_PARAMETER
|
||||
}
|
||||
|
||||
abstract class CallGenerator {
|
||||
interface CallGenerator {
|
||||
|
||||
internal class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator() {
|
||||
class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator {
|
||||
|
||||
override fun genCallInner(
|
||||
callableMethod: Callable,
|
||||
@@ -106,9 +106,9 @@ abstract class CallGenerator {
|
||||
genCallInner(callableMethod, resolvedCall, callDefault, codegen)
|
||||
}
|
||||
|
||||
abstract fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen)
|
||||
fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen)
|
||||
|
||||
abstract fun genValueAndPut(
|
||||
fun genValueAndPut(
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
argumentExpression: KtExpression,
|
||||
parameterType: Type,
|
||||
@@ -120,20 +120,20 @@ abstract class CallGenerator {
|
||||
putValueIfNeeded(parameterType, value, ValueKind.GENERAL)
|
||||
}
|
||||
|
||||
abstract fun putValueIfNeeded(
|
||||
fun putValueIfNeeded(
|
||||
parameterType: Type,
|
||||
value: StackValue,
|
||||
kind: ValueKind = ValueKind.GENERAL,
|
||||
parameterIndex: Int = -1)
|
||||
|
||||
abstract fun putCapturedValueOnStack(
|
||||
fun putCapturedValueOnStack(
|
||||
stackValue: StackValue,
|
||||
valueType: Type, paramIndex: Int)
|
||||
|
||||
abstract fun processAndPutHiddenParameters(justProcess: Boolean)
|
||||
fun processAndPutHiddenParameters(justProcess: Boolean)
|
||||
|
||||
/*should be called if justProcess = true in processAndPutHiddenParameters*/
|
||||
abstract fun putHiddenParamsIntoLocals()
|
||||
fun putHiddenParamsIntoLocals()
|
||||
|
||||
abstract fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>)
|
||||
fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
public class CallReceiver extends StackValue {
|
||||
private final StackValue dispatchReceiver;
|
||||
private final StackValue extensionReceiver;
|
||||
private final Type secondReceiverType;
|
||||
|
||||
private CallReceiver(
|
||||
@NotNull StackValue dispatchReceiver,
|
||||
@NotNull StackValue extensionReceiver,
|
||||
@NotNull Type type,
|
||||
@Nullable Type secondReceiverType
|
||||
) {
|
||||
super(type, dispatchReceiver.canHaveSideEffects() || extensionReceiver.canHaveSideEffects());
|
||||
this.dispatchReceiver = dispatchReceiver;
|
||||
this.extensionReceiver = extensionReceiver;
|
||||
this.secondReceiverType = secondReceiverType;
|
||||
}
|
||||
|
||||
public StackValue withoutReceiverArgument() {
|
||||
return new CallReceiver(dispatchReceiver, none(), type, secondReceiverType);
|
||||
}
|
||||
|
||||
public static StackValue generateCallReceiver(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@Nullable Callable callableMethod,
|
||||
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
||||
@NotNull StackValue dispatchReceiver,
|
||||
@Nullable ReceiverParameterDescriptor extensionReceiverParameter,
|
||||
@NotNull StackValue extensionReceiver
|
||||
) {
|
||||
KotlinTypeMapper typeMapper = codegen.typeMapper;
|
||||
GenerationState state = codegen.getState();
|
||||
|
||||
Type type;
|
||||
Type secondReceiverType = null;
|
||||
if (extensionReceiverParameter != null) {
|
||||
type = calcExtensionReceiverType(resolvedCall, extensionReceiverParameter, typeMapper, callableMethod, state);
|
||||
if (dispatchReceiverParameter != null) {
|
||||
secondReceiverType = calcDispatchReceiverType(resolvedCall, dispatchReceiverParameter, typeMapper, callableMethod);
|
||||
}
|
||||
}
|
||||
else if (dispatchReceiverParameter != null) {
|
||||
type = calcDispatchReceiverType(resolvedCall, dispatchReceiverParameter, typeMapper, callableMethod);
|
||||
}
|
||||
else if (isLocalFunCall(callableMethod)) {
|
||||
type = callableMethod.getGenerateCalleeType();
|
||||
}
|
||||
else {
|
||||
type = Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
assert type != null : "Could not map receiver type for " + resolvedCall;
|
||||
|
||||
return new CallReceiver(dispatchReceiver, extensionReceiver, type, secondReceiverType);
|
||||
}
|
||||
|
||||
private static Type calcDispatchReceiverType(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@Nullable ReceiverParameterDescriptor dispatchReceiver,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@Nullable Callable callableMethod
|
||||
) {
|
||||
if (dispatchReceiver == null) return null;
|
||||
|
||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||
|
||||
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
if (callableMethod != null) {
|
||||
return callableMethod.getDispatchReceiverType();
|
||||
}
|
||||
|
||||
// Extract the receiver from the resolved call, workarounding the fact that ResolvedCall#dispatchReceiver doesn't have
|
||||
// all the needed information, for example there's no way to find out whether or not a smart cast was applied to the receiver.
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
if (container instanceof ClassDescriptor) {
|
||||
return typeMapper.mapClass((ClassDescriptor) container);
|
||||
}
|
||||
|
||||
return typeMapper.mapType(dispatchReceiver);
|
||||
}
|
||||
|
||||
private static Type calcExtensionReceiverType(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@Nullable ReceiverParameterDescriptor extensionReceiver,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@Nullable Callable callableMethod,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
if (extensionReceiver == null) return null;
|
||||
|
||||
CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor();
|
||||
|
||||
if (descriptor instanceof PropertyDescriptor &&
|
||||
// hackaround: boxing changes behaviour of T.javaClass intrinsic
|
||||
state.getIntrinsics().getIntrinsic((PropertyDescriptor) descriptor) != JavaClassProperty.INSTANCE
|
||||
) {
|
||||
ReceiverParameterDescriptor receiverCandidate = descriptor.getExtensionReceiverParameter();
|
||||
assert receiverCandidate != null;
|
||||
return typeMapper.mapType(receiverCandidate.getType());
|
||||
}
|
||||
|
||||
return callableMethod != null ? callableMethod.getExtensionReceiverType() : typeMapper.mapType(extensionReceiver.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
StackValue currentExtensionReceiver = extensionReceiver;
|
||||
boolean hasExtensionReceiver = extensionReceiver != none();
|
||||
if (extensionReceiver instanceof SafeCall) {
|
||||
currentExtensionReceiver.put(currentExtensionReceiver.type, v);
|
||||
currentExtensionReceiver = StackValue.onStack(currentExtensionReceiver.type);
|
||||
}
|
||||
|
||||
Type dispatchReceiverType = secondReceiverType != null ? secondReceiverType :
|
||||
hasExtensionReceiver ? dispatchReceiver.type :
|
||||
type;
|
||||
dispatchReceiver.put(dispatchReceiverType, v);
|
||||
|
||||
currentExtensionReceiver
|
||||
.moveToTopOfStack(hasExtensionReceiver ? type : currentExtensionReceiver.type, v, dispatchReceiverType.getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
|
||||
AsmUtil.dup(v, extensionReceiver.type, dispatchReceiver.type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue getDispatchReceiver() {
|
||||
return dispatchReceiver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue getExtensionReceiver() {
|
||||
return extensionReceiver;
|
||||
}
|
||||
}
|
||||
@@ -24,16 +24,17 @@ import kotlin.collections.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext;
|
||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
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.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
@@ -60,6 +61,7 @@ import java.util.List;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtils2Kt.initDefaultSourceMappingIfNeeded;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
@@ -158,7 +160,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
superInterfaceAsmTypes
|
||||
);
|
||||
|
||||
InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);
|
||||
initDefaultSourceMappingIfNeeded(context, this, state);
|
||||
|
||||
v.visitSource(element.getContainingFile().getName(), null);
|
||||
}
|
||||
@@ -229,9 +231,10 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
@Override
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
|
||||
FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
|
||||
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
|
||||
assert method != null : "No method for " + frontendFunDescriptor;
|
||||
|
||||
FunctionDescriptor freeLambdaDescriptor = FakeDescriptorsForReferencesKt.createFreeFakeLambdaDescriptor(frontendFunDescriptor);
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
|
||||
|
||||
DescriptorSerializer serializer =
|
||||
@@ -245,30 +248,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a function descriptor, creates another function descriptor with type parameters copied from outer context(s).
|
||||
* This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
|
||||
*/
|
||||
@NotNull
|
||||
private static FunctionDescriptor createFreeLambdaDescriptor(@NotNull FunctionDescriptor descriptor) {
|
||||
FunctionDescriptor.CopyBuilder<? extends FunctionDescriptor> builder = descriptor.newCopyBuilder();
|
||||
List<TypeParameterDescriptor> typeParameters = new ArrayList<>(0);
|
||||
builder.setTypeParameters(typeParameters);
|
||||
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
while (container != null) {
|
||||
if (container instanceof ClassDescriptor) {
|
||||
typeParameters.addAll(((ClassDescriptor) container).getDeclaredTypeParameters());
|
||||
}
|
||||
else if (container instanceof CallableDescriptor && !(container instanceof ConstructorDescriptor)) {
|
||||
typeParameters.addAll(((CallableDescriptor) container).getTypeParameters());
|
||||
}
|
||||
container = container.getContainingDeclaration();
|
||||
}
|
||||
|
||||
return typeParameters.isEmpty() ? descriptor : builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
writeOuterClassAndEnclosingMethod();
|
||||
@@ -381,13 +360,30 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
|
||||
if (container instanceof ClassDescriptor) {
|
||||
// TODO: getDefaultType() here is wrong and won't work for arrays
|
||||
putJavaLangClassInstance(iv, state.getTypeMapper().mapType(((ClassDescriptor) container).getDefaultType()));
|
||||
wrapJavaClassIntoKClass(iv);
|
||||
}
|
||||
else if (container instanceof PackageFragmentDescriptor) {
|
||||
iv.aconst(state.getTypeMapper().mapOwner(descriptor));
|
||||
}
|
||||
else if (descriptor instanceof VariableDescriptorWithAccessors) {
|
||||
iv.aconst(state.getBindingContext().get(
|
||||
CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, ((VariableDescriptorWithAccessors) descriptor)
|
||||
));
|
||||
}
|
||||
else {
|
||||
iv.aconst(null);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isContainerPackage =
|
||||
descriptor instanceof LocalVariableDescriptor
|
||||
? DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class) == null
|
||||
: container instanceof PackageFragmentDescriptor;
|
||||
|
||||
if (isContainerPackage) {
|
||||
// Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead,
|
||||
// but there's no nice API to obtain that name here yet
|
||||
// TODO: write the referenced declaration's module name and use it in reflection
|
||||
@@ -396,7 +392,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false);
|
||||
}
|
||||
else {
|
||||
iv.aconst(null);
|
||||
wrapJavaClassIntoKClass(iv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import java.util.*
|
||||
|
||||
class DefaultCallArgs(val size: Int) {
|
||||
@@ -32,7 +31,7 @@ class DefaultCallArgs(val size: Int) {
|
||||
bits.set(index)
|
||||
}
|
||||
|
||||
private fun toInts(): List<Int> {
|
||||
fun toInts(): List<Int> {
|
||||
if (bits.isEmpty || size == 0) {
|
||||
return emptyList()
|
||||
}
|
||||
@@ -64,17 +63,4 @@ class DefaultCallArgs(val size: Int) {
|
||||
}
|
||||
return toInts.isNotEmpty()
|
||||
}
|
||||
|
||||
fun generateOnStackIfNeeded(iv: InstructionAdapter, isConstructor: Boolean): Boolean {
|
||||
val toInts = toInts()
|
||||
if (!toInts.isEmpty()) {
|
||||
for (mask in toInts) {
|
||||
iv.iconst(mask)
|
||||
}
|
||||
|
||||
val parameterType = if (isConstructor) AsmTypes.DEFAULT_CONSTRUCTOR_MARKER else AsmTypes.OBJECT_TYPE
|
||||
iv.aconst(null)
|
||||
}
|
||||
return toInts.isNotEmpty()
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOriginFromPure
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -136,7 +137,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0) or
|
||||
(if (remainingParameters.lastOrNull()?.varargElementType != null) Opcodes.ACC_VARARGS else 0)
|
||||
val signature = typeMapper.mapSignatureWithCustomParameters(functionDescriptor, contextKind, remainingParameters, false)
|
||||
val mv = classBuilder.newMethod(OtherOrigin(methodElement, functionDescriptor), flags,
|
||||
val mv = classBuilder.newMethod(OtherOriginFromPure(methodElement, functionDescriptor), flags,
|
||||
signature.asmMethod.name,
|
||||
signature.asmMethod.descriptor,
|
||||
signature.genericsSignature,
|
||||
|
||||
@@ -39,11 +39,12 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenForLambda;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.ResolvedCallWithRealDescriptor;
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
||||
import org.jetbrains.kotlin.codegen.forLoop.AbstractForLoopGenerator;
|
||||
import org.jetbrains.kotlin.codegen.forLoop.ForLoopGeneratorsKt;
|
||||
import org.jetbrains.kotlin.codegen.inline.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.*;
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt;
|
||||
import org.jetbrains.kotlin.codegen.range.RangeValue;
|
||||
import org.jetbrains.kotlin.codegen.range.RangeValuesKt;
|
||||
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -59,7 +60,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
@@ -74,8 +75,7 @@ import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
@@ -105,9 +105,11 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.extractReificationArgument;
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.unwrapInitialSignatureDescriptor;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||
@@ -118,7 +120,7 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFun
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> implements LocalLookup {
|
||||
public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> implements LocalLookup, BaseExpressionCodegen {
|
||||
private final GenerationState state;
|
||||
final KotlinTypeMapper typeMapper;
|
||||
private final BindingContext bindingContext;
|
||||
@@ -598,7 +600,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private void generateFor(@NotNull KtForExpression forExpression) {
|
||||
generateForLoop(ForLoopGeneratorsKt.getForLoopGenerator(this, forExpression));
|
||||
KtExpression range = forExpression.getLoopRange();
|
||||
assert range != null : "No loop range in for expression";
|
||||
RangeValue rangeValue = RangeValuesKt.createRangeValueForExpression(this, range);
|
||||
generateForLoop(rangeValue.createForLoopGenerator(this, forExpression));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -622,7 +627,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return context.getContextKind();
|
||||
}
|
||||
|
||||
private void generateForLoop(AbstractForLoopGenerator generator) {
|
||||
private void generateForLoop(ForLoopGenerator generator) {
|
||||
Label loopExit = new Label();
|
||||
Label loopEntry = new Label();
|
||||
Label continueLabel = new Label();
|
||||
@@ -824,14 +829,76 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@Override
|
||||
public StackValue visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, StackValue receiver) {
|
||||
StringBuilder constantValue = new StringBuilder("");
|
||||
KtStringTemplateEntry[] entries = expression.getEntries();
|
||||
List<StringTemplateEntry> entries = preprocessStringTemplate(expression);
|
||||
|
||||
if (entries.length == 1 && entries[0] instanceof KtStringTemplateEntryWithExpression) {
|
||||
KtExpression expr = entries[0].getExpression();
|
||||
return genToString(gen(expr), expressionType(expr));
|
||||
Type type = expressionType(expression);
|
||||
|
||||
if (entries.size() == 0) {
|
||||
return StackValue.constant("", type);
|
||||
}
|
||||
else if (entries.size() == 1) {
|
||||
StringTemplateEntry entry = entries.get(0);
|
||||
if (entry instanceof StringTemplateEntry.Expression) {
|
||||
KtExpression expr = ((StringTemplateEntry.Expression) entry).expression;
|
||||
return genToString(gen(expr), type);
|
||||
}
|
||||
else {
|
||||
return StackValue.constant(((StringTemplateEntry.Constant) entry).value, type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return StackValue.operation(type, v -> {
|
||||
genStringBuilderConstructor(v);
|
||||
invokeAppendForEntries(v, entries);
|
||||
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void invokeAppendForEntries(InstructionAdapter v, List<StringTemplateEntry> entries) {
|
||||
for (StringTemplateEntry entry : entries) {
|
||||
if (entry instanceof StringTemplateEntry.Expression) {
|
||||
invokeAppend(v, ((StringTemplateEntry.Expression) entry).expression);
|
||||
}
|
||||
else {
|
||||
String value = ((StringTemplateEntry.Constant) entry).value;
|
||||
if (value.length() == 1) {
|
||||
v.iconst(value.charAt(0));
|
||||
genInvokeAppendMethod(v, Type.CHAR_TYPE);
|
||||
}
|
||||
else {
|
||||
v.aconst(value);
|
||||
genInvokeAppendMethod(v, JAVA_STRING_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class StringTemplateEntry {
|
||||
static class Constant extends StringTemplateEntry {
|
||||
final String value;
|
||||
|
||||
Constant(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
static class Expression extends StringTemplateEntry {
|
||||
final KtExpression expression;
|
||||
|
||||
Expression(KtExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull List<StringTemplateEntry> preprocessStringTemplate(@NotNull KtStringTemplateExpression expression) {
|
||||
KtStringTemplateEntry[] entries = expression.getEntries();
|
||||
|
||||
List<StringTemplateEntry> result = new ArrayList<>(entries.length);
|
||||
|
||||
StringBuilder constantValue = new StringBuilder("");
|
||||
for (KtStringTemplateEntry entry : entries) {
|
||||
if (entry instanceof KtLiteralStringTemplateEntry) {
|
||||
constantValue.append(entry.getText());
|
||||
@@ -839,36 +906,46 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
else if (entry instanceof KtEscapeStringTemplateEntry) {
|
||||
constantValue.append(((KtEscapeStringTemplateEntry) entry).getUnescapedValue());
|
||||
}
|
||||
else if (entry instanceof KtStringTemplateEntryWithExpression) {
|
||||
KtExpression entryExpression = entry.getExpression();
|
||||
if (entryExpression == null) throw new AssertionError("No expression in " + entry);
|
||||
|
||||
ConstantValue<?> compileTimeConstant =
|
||||
getPrimitiveOrStringCompileTimeConstant(entryExpression, bindingContext, state.getShouldInlineConstVals());
|
||||
|
||||
if (compileTimeConstant != null && isConstantValueInlinableInStringTemplate(compileTimeConstant)) {
|
||||
constantValue.append(String.valueOf(compileTimeConstant.getValue()));
|
||||
}
|
||||
else {
|
||||
result.add(new StringTemplateEntry.Constant(constantValue.toString()));
|
||||
constantValue.setLength(0);
|
||||
|
||||
result.add(new StringTemplateEntry.Expression(entryExpression));
|
||||
}
|
||||
}
|
||||
else {
|
||||
constantValue = null;
|
||||
break;
|
||||
throw new AssertionError("Unexpected string template entry: " + entry);
|
||||
}
|
||||
}
|
||||
if (constantValue != null) {
|
||||
Type type = expressionType(expression);
|
||||
return StackValue.constant(constantValue.toString(), type);
|
||||
}
|
||||
else {
|
||||
return StackValue.operation(JAVA_STRING_TYPE, v -> {
|
||||
genStringBuilderConstructor(v);
|
||||
for (KtStringTemplateEntry entry : entries) {
|
||||
if (entry instanceof KtStringTemplateEntryWithExpression) {
|
||||
invokeAppend(entry.getExpression());
|
||||
}
|
||||
else {
|
||||
String text = entry instanceof KtEscapeStringTemplateEntry
|
||||
? ((KtEscapeStringTemplateEntry) entry).getUnescapedValue()
|
||||
: entry.getText();
|
||||
v.aconst(text);
|
||||
genInvokeAppendMethod(v, JAVA_STRING_TYPE);
|
||||
}
|
||||
}
|
||||
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
||||
String leftoverConstantValue = constantValue.toString();
|
||||
if (leftoverConstantValue.length() > 0) {
|
||||
result.add(new StringTemplateEntry.Constant(leftoverConstantValue));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isConstantValueInlinableInStringTemplate(@NotNull ConstantValue<?> constant) {
|
||||
return constant instanceof StringValue ||
|
||||
constant instanceof BooleanValue ||
|
||||
constant instanceof DoubleValue ||
|
||||
constant instanceof FloatValue ||
|
||||
constant instanceof IntegerValueConstant ||
|
||||
constant instanceof NullValue;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public StackValue visitBlockExpression(@NotNull KtBlockExpression expression, StackValue receiver) {
|
||||
return generateBlock(expression, false);
|
||||
@@ -1294,10 +1371,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
int index = myFrameMap.leave(variableDescriptor);
|
||||
|
||||
if (isSharedVarType(type)) {
|
||||
v.aconst(null);
|
||||
v.store(index, OBJECT_TYPE);
|
||||
}
|
||||
v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd, index);
|
||||
return null;
|
||||
});
|
||||
@@ -1352,6 +1425,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
//we should generate additional linenumber info after inline call only if it used as argument
|
||||
@Override
|
||||
public void markLineNumberAfterInlineIfNeeded() {
|
||||
if (!shouldMarkLineNumbers) {
|
||||
//if it used as general argument
|
||||
@@ -1366,6 +1440,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastLineNumber() {
|
||||
return myLastLineNumber;
|
||||
}
|
||||
@@ -1414,14 +1489,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Label finallyStart = new Label();
|
||||
v.mark(finallyStart);
|
||||
finallyBlockStackElement.addGapLabel(finallyStart);
|
||||
if (InlineCodegenUtil.isFinallyMarkerRequired(context)) {
|
||||
InlineCodegenUtil.generateFinallyMarker(v, finallyDepth, true);
|
||||
if (isFinallyMarkerRequired(context)) {
|
||||
generateFinallyMarker(v, finallyDepth, true);
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
|
||||
|
||||
if (InlineCodegenUtil.isFinallyMarkerRequired(context)) {
|
||||
InlineCodegenUtil.generateFinallyMarker(v, finallyDepth, false);
|
||||
if (isFinallyMarkerRequired(context)) {
|
||||
generateFinallyMarker(v, finallyDepth, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,7 +1539,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel);
|
||||
|
||||
if (isNonLocalReturn) {
|
||||
InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName);
|
||||
generateGlobalReturnFlag(v, nonLocalReturn.labelName);
|
||||
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
|
||||
}
|
||||
else {
|
||||
@@ -1502,7 +1577,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor containingFunction =
|
||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
||||
//FIRST_FUN_LABEL to prevent clashing with existing labels
|
||||
return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL);
|
||||
return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), FIRST_FUN_LABEL);
|
||||
} else {
|
||||
//local
|
||||
return null;
|
||||
@@ -1538,11 +1613,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
// If it does not end with return we should return something
|
||||
// because if we don't there can be VerifyError (specific cases with Nothing-typed expressions)
|
||||
if (!endsWithReturn(expr)) {
|
||||
markLineNumber(expr, true);
|
||||
|
||||
if (isLambdaVoidBody(expr, typeForExpression)) {
|
||||
markLineNumber((KtFunctionLiteral) expr.getParent(), true);
|
||||
}
|
||||
else {
|
||||
markLineNumber(expr, true);
|
||||
}
|
||||
|
||||
if (typeForExpression.getSort() == Type.VOID) {
|
||||
StackValue.none().put(returnType, v);
|
||||
@@ -1706,31 +1782,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return lookupCapturedValueInConstructorParameters(descriptor);
|
||||
}
|
||||
|
||||
return lookupValuaAndLocalVariableMetadata(descriptor, StackValue.LOCAL_0, state, false, context, this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static StackValue lookupValuaAndLocalVariableMetadata(
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@NotNull StackValue prefix,
|
||||
@NotNull GenerationState state,
|
||||
boolean ignoreNoOuter,
|
||||
@NotNull CodegenContext context,
|
||||
@Nullable ExpressionCodegen codegen
|
||||
) {
|
||||
StackValue value = context.lookupInContext(descriptor, prefix, state, ignoreNoOuter);
|
||||
if(!isDelegatedLocalVariable(descriptor) || value == null) {
|
||||
return value;
|
||||
StackValue value = context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false);
|
||||
if (isDelegatedLocalVariable(descriptor) && value != null) {
|
||||
VariableDescriptor metadata = getDelegatedLocalVariableMetadata((VariableDescriptor) descriptor, bindingContext);
|
||||
StackValue metadataValue = context.lookupInContext(metadata, StackValue.LOCAL_0, state, false);
|
||||
assert metadataValue != null : "Metadata stack value should be non-null for local delegated property: " + descriptor;
|
||||
return delegatedVariableValue(value, metadataValue, (VariableDescriptorWithAccessors) descriptor, typeMapper);
|
||||
}
|
||||
|
||||
|
||||
VariableDescriptor metadata = getDelegatedLocalVariableMetadata((VariableDescriptor) descriptor, state.getBindingContext());
|
||||
StackValue metadataValue = context.lookupInContext(metadata, prefix, state, ignoreNoOuter);
|
||||
assert metadataValue != null : "Metadata stack value should be non-null for local delegated property";
|
||||
//required for ImplementationBodyCodegen.lookupConstructorExpressionsInClosureIfPresent
|
||||
if (codegen == null) return null;
|
||||
return codegen.delegatedVariableValue(value, metadataValue, (VariableDescriptorWithAccessors) descriptor,
|
||||
state.getTypeMapper());
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1741,7 +1801,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
int parameterOffsetInConstructor = context.closure.getCapturedParameterOffsetInConstructor(descriptor);
|
||||
// when captured parameter is singleton
|
||||
// see compiler/testData/codegen/box/objects/objectInLocalAnonymousObject.kt (fun local() captured in A)
|
||||
if (parameterOffsetInConstructor == -1) return adjustVariableValue(parentResult , descriptor);
|
||||
if (parameterOffsetInConstructor == -1) return adjustVariableValue(parentResult, descriptor);
|
||||
|
||||
assert parentResult instanceof StackValue.Field || parentResult instanceof StackValue.FieldForSharedVar
|
||||
: "Part of closure should be either Field or FieldForSharedVar";
|
||||
@@ -1978,32 +2038,27 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return genClosure((KtNamedFunction) expression, samType);
|
||||
}
|
||||
|
||||
Type asmType =
|
||||
state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), this);
|
||||
Type asmType = state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), this);
|
||||
|
||||
return StackValue.operation(asmType, v -> {
|
||||
v.anew(asmType);
|
||||
v.dup();
|
||||
Label afterAll = new Label();
|
||||
|
||||
Type functionType = typeMapper.mapType(samType.getKotlinFunctionType());
|
||||
expression.accept(visitor, StackValue.none()).put(functionType, v);
|
||||
|
||||
Label ifNonNull = new Label();
|
||||
Label afterAll = new Label();
|
||||
|
||||
v.dup();
|
||||
v.ifnonnull(ifNonNull);
|
||||
v.ifnull(afterAll);
|
||||
|
||||
// if null: pop function value and wrapper objects, put null
|
||||
v.pop();
|
||||
v.pop2();
|
||||
v.aconst(null);
|
||||
v.goTo(afterAll);
|
||||
|
||||
v.mark(ifNonNull);
|
||||
int tmp = myFrameMap.enterTemp(functionType);
|
||||
v.store(tmp, functionType);
|
||||
v.anew(asmType);
|
||||
v.dup();
|
||||
v.load(tmp, functionType);
|
||||
v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), false);
|
||||
myFrameMap.leaveTemp(functionType);
|
||||
|
||||
v.mark(afterAll);
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
@@ -2172,19 +2227,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
if (isSuspendCall) {
|
||||
v.invokestatic(
|
||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
||||
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
|
||||
"()V", false
|
||||
);
|
||||
addSuspendMarker(v, true);
|
||||
}
|
||||
|
||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||
|
||||
if (isSuspendCall) {
|
||||
v.invokestatic(
|
||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
||||
CoroutineCodegenUtilKt.AFTER_SUSPENSION_POINT_MARKER_NAME, "()V", false);
|
||||
addSuspendMarker(v, false);
|
||||
addInlineMarker(v, false);
|
||||
}
|
||||
|
||||
@@ -2233,12 +2282,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
// But the problem is that we should leave the receiver itself on the stack, so we store it in a temporary variable.
|
||||
if (isSuspendCall && isSafeCallOrOnStack) {
|
||||
boolean bothReceivers =
|
||||
receiver instanceof StackValue.CallReceiver
|
||||
&& ((StackValue.CallReceiver) receiver).getDispatchReceiver().type.getSort() != Type.VOID
|
||||
&& ((StackValue.CallReceiver) receiver).getExtensionReceiver().type.getSort() != Type.VOID;
|
||||
receiver instanceof CallReceiver
|
||||
&& ((CallReceiver) receiver).getDispatchReceiver().type.getSort() != Type.VOID
|
||||
&& ((CallReceiver) receiver).getExtensionReceiver().type.getSort() != Type.VOID;
|
||||
Type firstReceiverType =
|
||||
bothReceivers
|
||||
? ((StackValue.CallReceiver) receiver).getDispatchReceiver().type
|
||||
? ((CallReceiver) receiver).getDispatchReceiver().type
|
||||
: receiver.type;
|
||||
|
||||
Type secondReceiverType = bothReceivers ? receiver.type : null;
|
||||
@@ -2286,19 +2335,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor original =
|
||||
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()));
|
||||
if (isDefaultCompilation) {
|
||||
return new InlineCodegenForDefaultBody(original, this, state);
|
||||
return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement));
|
||||
}
|
||||
else {
|
||||
return new InlineCodegen(this, state, original, callElement, typeParameterMappings);
|
||||
return new PsiInlineCodegen(this, state, original, typeParameterMappings, new PsiSourceCompilerForInline(this, callElement));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FunctionDescriptor unwrapInitialSignatureDescriptor(@NotNull FunctionDescriptor function) {
|
||||
if (function.getInitialSignatureDescriptor() != null) return function.getInitialSignatureDescriptor();
|
||||
return function;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected CallGenerator getOrCreateCallGeneratorForDefaultImplBody(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) {
|
||||
return getOrCreateCallGenerator(descriptor, function, null, true);
|
||||
@@ -2368,22 +2411,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return typeArgumentsMap;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static Pair<TypeParameterDescriptor, ReificationArgument> extractReificationArgument(@NotNull KotlinType type) {
|
||||
int arrayDepth = 0;
|
||||
boolean isNullable = type.isMarkedNullable();
|
||||
while (KotlinBuiltIns.isArray(type)) {
|
||||
arrayDepth++;
|
||||
type = type.getArguments().get(0).getType();
|
||||
}
|
||||
|
||||
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type);
|
||||
if (parameterDescriptor == null) return null;
|
||||
|
||||
return new Pair<>(parameterDescriptor, new ReificationArgument(parameterDescriptor.getName().asString(), isNullable, arrayDepth));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateReceiverValue(@Nullable ReceiverValue receiverValue, boolean isSuper) {
|
||||
if (receiverValue instanceof ImplicitClassReceiver) {
|
||||
@@ -2828,76 +2855,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
private StackValue generateIn(StackValue leftValue, KtExpression rangeExpression, KtSimpleNameExpression operationReference) {
|
||||
KtExpression deparenthesized = KtPsiUtil.deparenthesize(rangeExpression);
|
||||
|
||||
assert deparenthesized != null : "For with empty range expression";
|
||||
boolean isInverted = operationReference.getReferencedNameElementType() == KtTokens.NOT_IN;
|
||||
return StackValue.operation(Type.BOOLEAN_TYPE, v -> {
|
||||
if (RangeCodegenUtil.isPrimitiveRangeSpecializationOfType(leftValue.type, deparenthesized, bindingContext) ||
|
||||
RangeCodegenUtil.isPrimitiveRangeToExtension(operationReference, bindingContext)) {
|
||||
generateInPrimitiveRange(leftValue, (KtBinaryExpression) deparenthesized, isInverted);
|
||||
}
|
||||
else {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt
|
||||
.getResolvedCallWithAssert(operationReference, bindingContext);
|
||||
StackValue result = invokeFunction(resolvedCall.getCall(), resolvedCall, StackValue.none());
|
||||
result.put(result.type, v);
|
||||
if (isInverted) {
|
||||
genInvertBoolean(v);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Translates x in a..b to a <= x && x <= b
|
||||
* and x !in a..b to a > x || x > b for any primitive type
|
||||
*/
|
||||
private void generateInPrimitiveRange(StackValue argument, KtBinaryExpression rangeExpression, boolean isInverted) {
|
||||
Type rangeType = argument.type;
|
||||
int localVarIndex = myFrameMap.enterTemp(rangeType);
|
||||
// Load left bound
|
||||
gen(rangeExpression.getLeft(), rangeType);
|
||||
// Load x into local variable to avoid StackValue#put side-effects
|
||||
argument.put(rangeType, v);
|
||||
v.store(localVarIndex, rangeType);
|
||||
v.load(localVarIndex, rangeType);
|
||||
|
||||
// If (x < left) goto L1
|
||||
Label l1 = new Label();
|
||||
emitGreaterThan(rangeType, l1);
|
||||
|
||||
// If (x > right) goto L1
|
||||
v.load(localVarIndex, rangeType);
|
||||
gen(rangeExpression.getRight(), rangeType);
|
||||
emitGreaterThan(rangeType, l1);
|
||||
|
||||
Label l2 = new Label();
|
||||
v.iconst(isInverted ? 0 : 1);
|
||||
v.goTo(l2);
|
||||
|
||||
v.mark(l1);
|
||||
v.iconst(isInverted ? 1 : 0);
|
||||
v.mark(l2);
|
||||
myFrameMap.leaveTemp(rangeType);
|
||||
}
|
||||
|
||||
private void emitGreaterThan(Type type, Label label) {
|
||||
if (AsmUtil.isIntPrimitive(type)) {
|
||||
v.ificmpgt(label);
|
||||
}
|
||||
else if (type == Type.LONG_TYPE) {
|
||||
v.lcmp();
|
||||
v.ifgt(label);
|
||||
}
|
||||
// '>' != 'compareTo' for NaN and +/- 0.0
|
||||
else if (type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE) {
|
||||
v.cmpg(type);
|
||||
v.ifgt(label);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unexpected type: " + type);
|
||||
}
|
||||
RangeValue rangeValue = RangeValuesKt.createRangeValueForExpression(this, deparenthesized);
|
||||
return rangeValue.createInExpressionGenerator(this, operationReference).generate(leftValue);
|
||||
}
|
||||
|
||||
private StackValue generateBooleanAnd(KtBinaryExpression expression) {
|
||||
@@ -2935,6 +2895,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken);
|
||||
}
|
||||
|
||||
if (BoxedToPrimitiveEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return BoxedToPrimitiveEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType,
|
||||
myFrameMap);
|
||||
}
|
||||
|
||||
if (PrimitiveToBoxedEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return PrimitiveToBoxedEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType);
|
||||
}
|
||||
|
||||
if (PrimitiveToObjectEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return PrimitiveToObjectEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType);
|
||||
}
|
||||
|
||||
|
||||
if (isPrimitive(leftType) != isPrimitive(rightType)) {
|
||||
leftType = boxType(leftType);
|
||||
rightType = boxType(rightType);
|
||||
@@ -3272,22 +3246,31 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
public void invokeAppend(KtExpression expr) {
|
||||
public void invokeAppend(InstructionAdapter v, KtExpression expr) {
|
||||
expr = KtPsiUtil.safeDeparenthesize(expr);
|
||||
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expr, bindingContext, state.getShouldInlineConstVals());
|
||||
|
||||
if (compileTimeConstant == null && expr instanceof KtBinaryExpression) {
|
||||
KtBinaryExpression binaryExpression = (KtBinaryExpression) expr;
|
||||
if (binaryExpression.getOperationToken() == KtTokens.PLUS) {
|
||||
KtExpression left = binaryExpression.getLeft();
|
||||
KtExpression right = binaryExpression.getRight();
|
||||
Type leftType = expressionType(left);
|
||||
if (compileTimeConstant == null) {
|
||||
if (expr instanceof KtBinaryExpression) {
|
||||
KtBinaryExpression binaryExpression = (KtBinaryExpression) expr;
|
||||
if (binaryExpression.getOperationToken() == KtTokens.PLUS) {
|
||||
KtExpression left = binaryExpression.getLeft();
|
||||
KtExpression right = binaryExpression.getRight();
|
||||
Type leftType = expressionType(left);
|
||||
|
||||
if (leftType.equals(JAVA_STRING_TYPE)) {
|
||||
invokeAppend(left);
|
||||
invokeAppend(right);
|
||||
return;
|
||||
if (leftType.equals(JAVA_STRING_TYPE)) {
|
||||
invokeAppend(v, left);
|
||||
invokeAppend(v, right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (expr instanceof KtStringTemplateExpression) {
|
||||
List<StringTemplateEntry> entries = preprocessStringTemplate((KtStringTemplateExpression) expr);
|
||||
invokeAppendForEntries(v, entries);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Type exprType = expressionType(expr);
|
||||
@@ -3517,7 +3500,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue getVariableMetadataValue(VariableDescriptor variableDescriptor) {
|
||||
private StackValue getVariableMetadataValue(@NotNull VariableDescriptorWithAccessors variableDescriptor) {
|
||||
StackValue value = findLocalOrCapturedValue(getDelegatedLocalVariableMetadata(variableDescriptor, bindingContext));
|
||||
assert value != null : "Can't find stack value for local delegated variable metadata: " + variableDescriptor;
|
||||
return value;
|
||||
@@ -3563,14 +3546,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
StackValue metadataValue = getVariableMetadataValue(variableDescriptor);
|
||||
initializePropertyMetadata((KtProperty) variableDeclaration, variableDescriptor, metadataValue);
|
||||
|
||||
ResolvedCall<FunctionDescriptor> provideDelegateResolvedCall = bindingContext.get(PROVIDE_DELEGATE_RESOLVED_CALL, variableDescriptor);
|
||||
if (provideDelegateResolvedCall != null) {
|
||||
resultType = generateProvideDelegateCallForLocalVariable(initializer, metadataValue, provideDelegateResolvedCall);
|
||||
ResolvedCall<FunctionDescriptor> provideDelegateCall = bindingContext.get(PROVIDE_DELEGATE_RESOLVED_CALL, variableDescriptor);
|
||||
if (provideDelegateCall != null) {
|
||||
resultType = generateProvideDelegateCallForLocalVariable(initializer, metadataValue, provideDelegateCall);
|
||||
}
|
||||
}
|
||||
|
||||
storeTo.storeSelector(resultType, v);
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -3617,10 +3599,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull LocalVariableDescriptor variableDescriptor,
|
||||
@NotNull StackValue metadataVar
|
||||
) {
|
||||
// TODO: do not generate anonymous classes for local delegated properties in inline functions
|
||||
// We can use the $$delegatedProperties array as in non-inline functions and upon inlining, detect elements at what indices
|
||||
// of that array are used in the inline function body, load the corresponding initializing bytecode from <clinit> of the
|
||||
// container class (where the PropertyReferenceNImpl instance is created), copy and adapt it at the call site
|
||||
//noinspection ConstantConditions
|
||||
StackValue value = generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null, null);
|
||||
value.put(K_PROPERTY0_TYPE, v);
|
||||
metadataVar.storeSelector(K_PROPERTY0_TYPE, v);
|
||||
StackValue value = context.getFunctionDescriptor().isInline()
|
||||
? generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null, null)
|
||||
: PropertyCodegen.getDelegatedPropertyMetadata(variableDescriptor, bindingContext);
|
||||
value.put(K_PROPERTY_TYPE, v);
|
||||
metadataVar.storeSelector(K_PROPERTY_TYPE, v);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -4060,19 +4048,17 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind
|
||||
) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, operationKind, v);
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, operationKind, v, this);
|
||||
}
|
||||
|
||||
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v
|
||||
public static void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v,
|
||||
@NotNull BaseExpressionCodegen codegen
|
||||
) {
|
||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
||||
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = typeParameterAndReificationArgument.getFirst();
|
||||
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
||||
parentCodegen.getReifiedTypeParametersUsages().
|
||||
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||
}
|
||||
codegen.consumeReifiedOperationMarker(typeParameterDescriptor);
|
||||
v.iconst(operationKind.getId());
|
||||
v.visitLdcInsn(typeParameterAndReificationArgument.getSecond().asString());
|
||||
v.invokestatic(
|
||||
@@ -4082,6 +4068,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
|
||||
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context);
|
||||
}
|
||||
@@ -4203,6 +4190,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
return context.getContextDescriptor().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public FrameMap getFrameMap() {
|
||||
return myFrameMap;
|
||||
@@ -4213,12 +4201,13 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public NameGenerator getInlineNameGenerator() {
|
||||
NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator();
|
||||
Name name = context.getContextDescriptor().getName();
|
||||
String inlinedName = name.isSpecial() ? InlineCodegenUtil.SPECIAL_TRANSFORMATION_NAME : name.asString();
|
||||
return nameGenerator.subGenerator(inlinedName + InlineCodegenUtil.INLINE_CALL_TRANSFORMATION_SUFFIX);
|
||||
String inlinedName = name.isSpecial() ? SPECIAL_TRANSFORMATION_NAME : name.asString();
|
||||
return nameGenerator.subGenerator(inlinedName + INLINE_CALL_TRANSFORMATION_SUFFIX);
|
||||
}
|
||||
|
||||
public Type getReturnType() {
|
||||
@@ -4255,4 +4244,18 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
) {
|
||||
return StackValue.delegate(typeMapper.mapType(variableDescriptor.getType()), delegateValue, metadataValue, variableDescriptor, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public InstructionAdapter getVisitor() {
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumeReifiedOperationMarker(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
|
||||
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
||||
parentCodegen.getReifiedTypeParametersUsages().
|
||||
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,6 +229,13 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
asmMethod = CoroutineCodegenUtilKt.getImplForOpenMethod(asmMethod, v.getThisName());
|
||||
// remove generic signature as it's unnecessary for synthetic methods
|
||||
jvmSignature =
|
||||
new JvmMethodGenericSignature(
|
||||
asmMethod,
|
||||
jvmSignature.getValueParameters(),
|
||||
null
|
||||
);
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
@@ -995,12 +1002,19 @@ public class FunctionCodegen {
|
||||
capturedArgumentsCount++;
|
||||
}
|
||||
|
||||
int maskIndex = 0;
|
||||
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
|
||||
for (int index = 0; index < valueParameters.size(); index++) {
|
||||
assert valueParameters.size() > 0 : "Expecting value parameters to generate default function " + functionDescriptor;
|
||||
int firstMaskIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
for (int index = 1; index < valueParameters.size(); index++) {
|
||||
if (index % Integer.SIZE == 0) {
|
||||
maskIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
frameMap.enterTemp(Type.INT_TYPE);
|
||||
}
|
||||
}
|
||||
//default handler or constructor marker
|
||||
frameMap.enterTemp(AsmTypes.OBJECT_TYPE);
|
||||
|
||||
for (int index = 0; index < valueParameters.size(); index++) {
|
||||
int maskIndex = firstMaskIndex + index / Integer.SIZE;
|
||||
ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
|
||||
Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();
|
||||
|
||||
|
||||
@@ -31,11 +31,11 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
@@ -65,10 +65,7 @@ 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.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.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
@@ -79,6 +76,7 @@ import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isGenericToArray;
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtils2Kt.initDefaultSourceMappingIfNeeded;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
@@ -217,7 +215,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
v.visitSource(myClass.getContainingKtFile().getName(), null);
|
||||
|
||||
InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);
|
||||
initDefaultSourceMappingIfNeeded(context, this, state);
|
||||
|
||||
writeEnclosingMethod();
|
||||
|
||||
@@ -348,9 +346,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
protected void generateSyntheticPartsBeforeBody() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticPartsAfterBody() {
|
||||
generateFieldForSingleton();
|
||||
|
||||
generateCompanionObjectBackingFieldCopies();
|
||||
@@ -573,7 +574,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.ifnull(ifNull);
|
||||
}
|
||||
|
||||
genHashCode(mv, iv, asmType);
|
||||
genHashCode(mv, iv, asmType, state.getTarget());
|
||||
|
||||
if (ifNull != null) {
|
||||
Label end = new Label();
|
||||
@@ -678,7 +679,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
) {
|
||||
Type thisDescriptorType = typeMapper.mapType(descriptor);
|
||||
|
||||
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, function), function, new FunctionGenerationStrategy() {
|
||||
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOriginFromPure(myClass, function), function, new FunctionGenerationStrategy() {
|
||||
@Override
|
||||
public void generateBody(
|
||||
@NotNull MethodVisitor mv,
|
||||
@@ -778,7 +779,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
FunctionDescriptor valuesFunction =
|
||||
CollectionsKt.single(descriptor.getStaticScope().getContributedFunctions(ENUM_VALUES, NoLookupLocation.FROM_BACKEND));
|
||||
MethodVisitor mv = v.newMethod(
|
||||
JvmDeclarationOriginKt.OtherOrigin(myClass, valuesFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUES.asString(),
|
||||
JvmDeclarationOriginKt.OtherOriginFromPure(myClass, valuesFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUES.asString(),
|
||||
"()" + type.getDescriptor(), null, null
|
||||
);
|
||||
if (!state.getClassBuilderMode().generateBodies) return;
|
||||
@@ -796,7 +797,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
CollectionsKt.single(descriptor.getStaticScope().getContributedFunctions(ENUM_VALUE_OF, NoLookupLocation.FROM_BACKEND),
|
||||
DescriptorUtilsKt::isEnumValueOfMethod);
|
||||
MethodVisitor mv =
|
||||
v.newMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, valueOfFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUE_OF.asString(),
|
||||
v.newMethod(JvmDeclarationOriginKt.OtherOriginFromPure(myClass, valueOfFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUE_OF.asString(),
|
||||
"(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null);
|
||||
if (!state.getClassBuilderMode().generateBodies) return;
|
||||
|
||||
@@ -814,7 +815,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
if (isNonCompanionObject(descriptor)) {
|
||||
StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper);
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass),
|
||||
v.newField(JvmDeclarationOriginKt.OtherOriginFromPure(myClass),
|
||||
ACC_PUBLIC | ACC_STATIC | ACC_FINAL,
|
||||
field.name, field.type.getDescriptor(), null, null);
|
||||
|
||||
@@ -835,9 +836,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Nullable KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(myClass.getCompanionObjects());
|
||||
|
||||
int properFieldVisibilityFlag = getVisibilityAccessFlag(companionObjectDescriptor);
|
||||
boolean fieldShouldBeDeprecated =
|
||||
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.DeprecatedFieldForInvisibleCompanionObject) &&
|
||||
(properFieldVisibilityFlag & (ACC_PRIVATE | ACC_PROTECTED)) != 0;
|
||||
// TODO generate field with proper visibility in language version 1.3
|
||||
int fieldAccessFlags = ACC_PUBLIC | ACC_STATIC | ACC_FINAL;
|
||||
if (fieldShouldBeDeprecated) {
|
||||
fieldAccessFlags |= ACC_DEPRECATED;
|
||||
}
|
||||
StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper);
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject),
|
||||
ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
|
||||
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject),
|
||||
fieldAccessFlags, field.name, field.type.getDescriptor(), null, null);
|
||||
if (fieldShouldBeDeprecated) {
|
||||
AnnotationCodegen.forField(fv, this, typeMapper).visitAnnotation("Ljava/lang/Deprecated;", true).visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void generateCompanionObjectBackingFieldCopies() {
|
||||
@@ -1105,9 +1118,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
private final Map<KtDelegatedSuperTypeEntry, Field> fields = new HashMap<>();
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
public Field getInfo(KtDelegatedSuperTypeEntry specifier) {
|
||||
return fields.get(specifier);
|
||||
Field field = fields.get(specifier);
|
||||
assert field != null || state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES : "No field for " + specifier.getText();
|
||||
return field;
|
||||
}
|
||||
|
||||
private void addField(KtDelegatedSuperTypeEntry specifier, PropertyDescriptor propertyDescriptor) {
|
||||
@@ -1127,22 +1142,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
for (KtSuperTypeListEntry specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
KtExpression expression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
PropertyDescriptor propertyDescriptor = expression != null
|
||||
? CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext)
|
||||
: null;
|
||||
if (expression == null) continue;
|
||||
|
||||
PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext);
|
||||
|
||||
|
||||
if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) {
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, propertyDescriptor);
|
||||
}
|
||||
else {
|
||||
KotlinType expressionType = expression != null
|
||||
? bindingContext.getType(expression)
|
||||
: null;
|
||||
KotlinType expressionType = bindingContext.getType(expression);
|
||||
ClassDescriptor superClass = getSuperClass(specifier);
|
||||
if (superClass != null) {
|
||||
Type asmType = expressionType != null ? typeMapper.mapType(expressionType) : typeMapper.mapType(superClass);
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n);
|
||||
}
|
||||
Type asmType =
|
||||
expressionType != null ? typeMapper.mapType(expressionType) :
|
||||
superClass != null ? typeMapper.mapType(superClass) : null;
|
||||
|
||||
if (asmType == null) continue;
|
||||
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
@@ -1152,7 +1169,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getSuperClass(@NotNull KtSuperTypeListEntry specifier) {
|
||||
return CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
|
||||
ClassDescriptor superClass = CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
|
||||
|
||||
assert superClass != null || state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES
|
||||
: "ClassDescriptor should not be null:" + specifier.getText();
|
||||
return superClass;
|
||||
}
|
||||
|
||||
private void genCallToDelegatorByExpressionSpecifier(
|
||||
@@ -1164,6 +1185,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
KtExpression expression = specifier.getDelegateExpression();
|
||||
|
||||
DelegationFieldsInfo.Field fieldInfo = fieldsInfo.getInfo(specifier);
|
||||
if (fieldInfo == null) return;
|
||||
|
||||
if (fieldInfo.generateField) {
|
||||
iv.load(0, classAsmType);
|
||||
fieldInfo.getStackValue().store(codegen.gen(expression), iv);
|
||||
@@ -1224,9 +1247,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void lookupInContext(@NotNull DeclarationDescriptor toLookup) {
|
||||
ExpressionCodegen.lookupValuaAndLocalVariableMetadata(toLookup, StackValue.LOCAL_0, state, true, context, null);
|
||||
context.lookupInContext(toLookup, StackValue.LOCAL_0, state, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1550,7 +1572,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
Type arrayAsmType = typeMapper.mapType(DescriptorUtilsKt.getBuiltIns(descriptor).getArrayType(INVARIANT, descriptor.getDefaultType()));
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, ENUM_VALUES_FIELD_NAME,
|
||||
v.newField(JvmDeclarationOriginKt.OtherOriginFromPure(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, ENUM_VALUES_FIELD_NAME,
|
||||
arrayAsmType.getDescriptor(), null, null);
|
||||
|
||||
iv.iconst(enumEntries.size());
|
||||
@@ -1609,10 +1631,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatedSuperTypeEntry) specifier);
|
||||
if (field == null) continue;
|
||||
|
||||
generateDelegateField(field);
|
||||
KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
KotlinType delegateExpressionType = delegateExpression != null ? bindingContext.getType(delegateExpression) : null;
|
||||
generateDelegates(getSuperClass(specifier), delegateExpressionType, field);
|
||||
ClassDescriptor superClass = getSuperClass(specifier);
|
||||
if (superClass == null) continue;
|
||||
|
||||
generateDelegates(superClass, delegateExpressionType, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class InterfaceImplBodyCodegen(
|
||||
return classDescriptorImpl
|
||||
}
|
||||
|
||||
override fun generateSyntheticParts() {
|
||||
override fun generateSyntheticPartsAfterBody() {
|
||||
for (memberDescriptor in descriptor.defaultType.memberScope.getContributedDescriptors()) {
|
||||
if (memberDescriptor !is CallableMemberDescriptor) continue
|
||||
|
||||
|
||||
@@ -94,8 +94,7 @@ class JvmStaticInCompanionObjectGenerator(
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
false
|
||||
)
|
||||
val staticFunctionDescriptor = copies[descriptor]!!
|
||||
return staticFunctionDescriptor
|
||||
return copies[descriptor]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,19 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.inline.*;
|
||||
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.inline.NameGenerator;
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
@@ -44,8 +49,8 @@ import org.jetbrains.kotlin.name.SpecialNames;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
@@ -66,11 +71,15 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isNonDefaultInterfaceMember;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getInlineName;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
@@ -127,11 +136,18 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
public void generate() {
|
||||
generateDeclaration();
|
||||
|
||||
boolean shouldGenerateSyntheticParts =
|
||||
!(element instanceof KtClassOrObject) ||
|
||||
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) element);
|
||||
|
||||
if (shouldGenerateSyntheticParts) {
|
||||
generateSyntheticPartsBeforeBody();
|
||||
}
|
||||
|
||||
generateBody();
|
||||
|
||||
if (!(element instanceof KtClassOrObject) ||
|
||||
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) element)) {
|
||||
generateSyntheticParts();
|
||||
if (shouldGenerateSyntheticParts) {
|
||||
generateSyntheticPartsAfterBody();
|
||||
}
|
||||
|
||||
if (state.getClassBuilderMode().generateMetadata) {
|
||||
@@ -143,9 +159,12 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
protected abstract void generateDeclaration();
|
||||
|
||||
protected void generateSyntheticPartsBeforeBody() {
|
||||
}
|
||||
|
||||
protected abstract void generateBody();
|
||||
|
||||
protected void generateSyntheticParts() {
|
||||
protected void generateSyntheticPartsAfterBody() {
|
||||
}
|
||||
|
||||
protected abstract void generateKotlinMetadataAnnotation();
|
||||
@@ -296,7 +315,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
Type classType = state.getTypeMapper().mapClass(descriptor);
|
||||
ClassBuilder classBuilder = state.getFactory().newVisitor(
|
||||
JvmDeclarationOriginKt.OtherOrigin(aClass, descriptor),
|
||||
JvmDeclarationOriginKt.OtherOriginFromPure(aClass, descriptor),
|
||||
classType, aClass.getContainingKtFile());
|
||||
ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
|
||||
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen, false).generate();
|
||||
@@ -437,7 +456,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
@NotNull
|
||||
public NameGenerator getInlineNameGenerator() {
|
||||
if (inlineNameGenerator == null) {
|
||||
String prefix = InlineCodegenUtil.getInlineName(context, typeMapper, fileClassesProvider);
|
||||
String prefix = getInlineName(context, typeMapper, fileClassesProvider);
|
||||
inlineNameGenerator = new NameGenerator(prefix);
|
||||
}
|
||||
return inlineNameGenerator;
|
||||
@@ -510,11 +529,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
StackValue provideDelegateReceiver = codegen.gen(initializer);
|
||||
|
||||
int indexOfDelegatedProperty = PropertyCodegen.indexOfDelegatedProperty(property);
|
||||
|
||||
StackValue delegateValue = PropertyCodegen.invokeDelegatedPropertyConventionMethodWithReceiver(
|
||||
codegen, typeMapper, provideDelegateResolvedCall, indexOfDelegatedProperty, 1,
|
||||
provideDelegateReceiver, propertyDescriptor
|
||||
StackValue delegateValue = PropertyCodegen.invokeDelegatedPropertyConventionMethod(
|
||||
codegen, provideDelegateResolvedCall, provideDelegateReceiver, propertyDescriptor
|
||||
);
|
||||
|
||||
propValue.store(delegateValue, codegen.v);
|
||||
@@ -594,16 +610,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
|
||||
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
|
||||
List<KtProperty> delegatedProperties = new ArrayList<>();
|
||||
for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
|
||||
if (declaration instanceof KtProperty) {
|
||||
KtProperty property = (KtProperty) declaration;
|
||||
if (property.hasDelegate()) {
|
||||
delegatedProperties.add(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (delegatedProperties.isEmpty()) return;
|
||||
List<VariableDescriptorWithAccessors> delegatedProperties = bindingContext.get(CodegenBinding.DELEGATED_PROPERTIES, thisAsmType);
|
||||
if (delegatedProperties == null || delegatedProperties.isEmpty()) return;
|
||||
|
||||
v.newField(NO_ORIGIN, ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
|
||||
"[" + K_PROPERTY_TYPE, null, null);
|
||||
@@ -615,8 +623,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
iv.newarray(K_PROPERTY_TYPE);
|
||||
|
||||
for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
|
||||
PropertyDescriptor property =
|
||||
(PropertyDescriptor) BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));
|
||||
VariableDescriptorWithAccessors property = delegatedProperties.get(i);
|
||||
|
||||
iv.dup();
|
||||
iv.iconst(i);
|
||||
@@ -626,10 +633,12 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount];
|
||||
iv.anew(implType);
|
||||
iv.dup();
|
||||
|
||||
// TODO: generate the container once and save to a local field instead (KT-10495)
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
|
||||
iv.aconst(property.getName().asString());
|
||||
PropertyReferenceCodegen.generateCallableReferenceSignature(iv, property, state);
|
||||
|
||||
iv.invokespecial(
|
||||
implType.getInternalName(), "<init>",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false
|
||||
@@ -679,7 +688,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
protected void generateConstInstance(@NotNull Type thisAsmType, @NotNull Type fieldAsmType) {
|
||||
v.newField(
|
||||
JvmDeclarationOriginKt.OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD,
|
||||
JvmDeclarationOriginKt.OtherOriginFromPure(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD,
|
||||
fieldAsmType.getDescriptor(), null, null
|
||||
);
|
||||
|
||||
|
||||
@@ -205,11 +205,8 @@ class MultifileClassCodegenImpl(
|
||||
val packageFragment = this.packageFragment
|
||||
?: throw AssertionError("File part $file of $facadeFqName: no package fragment")
|
||||
|
||||
val partClassFqName = file.getFileClassFqName()
|
||||
val partInitializerClassFqName = FqName(partClassFqName.asString() + "__Init")
|
||||
val partType = partClassFqName.toAsmType()
|
||||
val partInitializerType = partInitializerClassFqName.toAsmType()
|
||||
val partContext = state.rootContext.intoMultifileClassPart(packageFragment, facadeClassType, partType, partInitializerType, file)
|
||||
val partType = file.getFileClassFqName().toAsmType()
|
||||
val partContext = state.rootContext.intoMultifileClassPart(packageFragment, facadeClassType, partType, file)
|
||||
|
||||
generateNonPartClassDeclarations(file, partContext)
|
||||
|
||||
|
||||
@@ -175,8 +175,11 @@ class MultifileClassPartCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
val serializer = DescriptorSerializer.createTopLevel(JvmSerializerExtension(v.serializationBindings, state))
|
||||
val packageProto = serializer.packagePartProto(packageFragment.fqName, members).build()
|
||||
val extension = JvmSerializerExtension(v.serializationBindings, state)
|
||||
val serializer = DescriptorSerializer.createTopLevel(extension)
|
||||
val builder = serializer.packagePartProto(packageFragment.fqName, members)
|
||||
extension.serializeJvmPackage(builder, partType)
|
||||
val packageProto = builder.build()
|
||||
|
||||
val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0
|
||||
|
||||
@@ -186,7 +189,7 @@ class MultifileClassPartCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateSyntheticParts() {
|
||||
override fun generateSyntheticPartsAfterBody() {
|
||||
generateSyntheticAccessors()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
|
||||
enum class OwnerKind {
|
||||
PACKAGE,
|
||||
IMPLEMENTATION,
|
||||
DEFAULT_IMPLS;
|
||||
|
||||
companion object {
|
||||
fun getMemberOwnerKind(descriptor: DeclarationDescriptor): OwnerKind = when (descriptor) {
|
||||
is FileClassDescriptor, is PackageFragmentDescriptor -> OwnerKind.PACKAGE
|
||||
is ClassDescriptor -> OwnerKind.IMPLEMENTATION
|
||||
else -> throw AssertionError("Unexpected declaration container: $this")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,9 +119,11 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorSerializer serializer =
|
||||
DescriptorSerializer.createTopLevel(new JvmSerializerExtension(v.getSerializationBindings(), state));
|
||||
ProtoBuf.Package packageProto = serializer.packagePartProto(element.getPackageFqName(), members).build();
|
||||
JvmSerializerExtension extension = new JvmSerializerExtension(v.getSerializationBindings(), state);
|
||||
DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(extension);
|
||||
ProtoBuf.Package.Builder builder = serializer.packagePartProto(element.getPackageFqName(), members);
|
||||
extension.serializeJvmPackage(builder, packagePartType);
|
||||
ProtoBuf.Package packageProto = builder.build();
|
||||
|
||||
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.FILE_FACADE, 0, av -> {
|
||||
writeAnnotationData(av, serializer, packageProto);
|
||||
@@ -130,7 +132,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
protected void generateSyntheticPartsAfterBody() {
|
||||
generateSyntheticAccessors();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithFakeAnnotations;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
|
||||
import org.jetbrains.kotlin.codegen.context.MultifileClassFacadeContext;
|
||||
import org.jetbrains.kotlin.codegen.context.MultifileClassPartContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -32,7 +35,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtilKt;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
@@ -60,6 +62,8 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.getDeprecatedAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTIES;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.FIELD_FOR_PROPERTY;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
@@ -478,7 +482,7 @@ public class PropertyCodegen {
|
||||
FunctionGenerationStrategy strategy;
|
||||
if (accessor == null || !accessor.hasBody()) {
|
||||
if (p instanceof KtProperty && ((KtProperty) p).hasDelegate()) {
|
||||
strategy = new DelegatedPropertyAccessorStrategy(state, accessorDescriptor, indexOfDelegatedProperty((KtProperty) p));
|
||||
strategy = new DelegatedPropertyAccessorStrategy(state, accessorDescriptor);
|
||||
}
|
||||
else {
|
||||
strategy = new DefaultPropertyAccessorStrategy(state, accessorDescriptor);
|
||||
@@ -491,39 +495,9 @@ public class PropertyCodegen {
|
||||
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(accessor != null ? accessor : p, accessorDescriptor), accessorDescriptor, strategy);
|
||||
}
|
||||
|
||||
public static int indexOfDelegatedProperty(@NotNull KtProperty property) {
|
||||
PsiElement parent = property.getParent();
|
||||
KtDeclarationContainer container;
|
||||
if (parent instanceof KtClassBody) {
|
||||
container = ((KtClassOrObject) parent.getParent());
|
||||
}
|
||||
else if (parent instanceof KtFile) {
|
||||
container = (KtFile) parent;
|
||||
}
|
||||
else if (KtPsiUtil.isScriptDeclaration(property)) {
|
||||
container = KtPsiUtil.getScript(property);
|
||||
assert container != null : "Script declaration for property '" + property.getText() + "' should be not null!";
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unknown delegated property container: " + parent);
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (KtDeclaration declaration : container.getDeclarations()) {
|
||||
if (declaration instanceof KtProperty && ((KtProperty) declaration).hasDelegate()) {
|
||||
if (declaration == property) {
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Delegated property not found in its parent: " + PsiUtilsKt.getElementTextWithContext(property));
|
||||
}
|
||||
|
||||
|
||||
private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
|
||||
private final PropertyAccessorDescriptor propertyAccessorDescriptor;
|
||||
|
||||
public DefaultPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
|
||||
super(state);
|
||||
propertyAccessorDescriptor = descriptor;
|
||||
@@ -561,75 +535,45 @@ public class PropertyCodegen {
|
||||
}
|
||||
|
||||
public static StackValue invokeDelegatedPropertyConventionMethod(
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
|
||||
int indexInPropertyMetadataArray,
|
||||
int propertyMetadataArgumentIndex
|
||||
) {
|
||||
StackValue.Property receiver = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
|
||||
return invokeDelegatedPropertyConventionMethodWithReceiver(
|
||||
codegen, typeMapper, resolvedCall, indexInPropertyMetadataArray, propertyMetadataArgumentIndex,
|
||||
receiver, propertyDescriptor
|
||||
);
|
||||
}
|
||||
|
||||
public static StackValue invokeDelegatedPropertyConventionMethodWithReceiver(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
|
||||
int indexInPropertyMetadataArray,
|
||||
int propertyMetadataArgumentIndex,
|
||||
@Nullable StackValue receiver,
|
||||
@NotNull PropertyDescriptor propertyDescriptor
|
||||
) {
|
||||
Type owner = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor) ?
|
||||
codegen.getState().getTypeMapper().mapOwner(propertyDescriptor) :
|
||||
getDelegatedPropertyMetadataOwner(codegen, typeMapper);
|
||||
|
||||
codegen.tempVariables.put(
|
||||
resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(),
|
||||
new StackValue(K_PROPERTY_TYPE) {
|
||||
@Override
|
||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
Field array = StackValue.field(
|
||||
Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none()
|
||||
);
|
||||
StackValue.arrayElement(
|
||||
K_PROPERTY_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)
|
||||
).put(type, v);
|
||||
}
|
||||
}
|
||||
resolvedCall.getCall().getValueArguments().get(1).asElement(),
|
||||
getDelegatedPropertyMetadata(propertyDescriptor, codegen.getBindingContext())
|
||||
);
|
||||
|
||||
return codegen.invokeFunction(resolvedCall, receiver);
|
||||
}
|
||||
|
||||
private static Type getDelegatedPropertyMetadataOwner(@NotNull ExpressionCodegen codegen, @NotNull KotlinTypeMapper typeMapper) {
|
||||
CodegenContext<? extends ClassOrPackageFragmentDescriptor> ownerContext = codegen.getContext().getClassOrPackageParentContext();
|
||||
if (ownerContext instanceof ClassContext) {
|
||||
return typeMapper.mapClass(((ClassContext) ownerContext).getContextDescriptor());
|
||||
}
|
||||
else if (ownerContext instanceof PackageContext) {
|
||||
return ((PackageContext) ownerContext).getPackagePartType();
|
||||
}
|
||||
else if (ownerContext instanceof MultifileClassContextBase) {
|
||||
return ((MultifileClassContextBase) ownerContext).getFilePartType();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unknown context: " + ownerContext);
|
||||
@NotNull
|
||||
public static StackValue getDelegatedPropertyMetadata(
|
||||
@NotNull VariableDescriptorWithAccessors descriptor,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
Type owner = bindingContext.get(DELEGATED_PROPERTY_METADATA_OWNER, descriptor);
|
||||
assert owner != null : "Delegated property owner not found: " + descriptor;
|
||||
|
||||
List<VariableDescriptorWithAccessors> allDelegatedProperties = bindingContext.get(DELEGATED_PROPERTIES, owner);
|
||||
int index = allDelegatedProperties == null ? -1 : allDelegatedProperties.indexOf(descriptor);
|
||||
if (index < 0) {
|
||||
throw new AssertionError("Delegated property not found in " + owner + ": " + descriptor);
|
||||
}
|
||||
|
||||
StackValue.Field array = StackValue.field(
|
||||
Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none()
|
||||
);
|
||||
return StackValue.arrayElement(K_PROPERTY_TYPE, array, StackValue.constant(index, Type.INT_TYPE));
|
||||
}
|
||||
|
||||
private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
|
||||
private final int index;
|
||||
private final PropertyAccessorDescriptor propertyAccessorDescriptor;
|
||||
|
||||
public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor, int index) {
|
||||
public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
|
||||
super(state);
|
||||
this.index = index;
|
||||
propertyAccessorDescriptor = descriptor;
|
||||
this.propertyAccessorDescriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -641,8 +585,9 @@ public class PropertyCodegen {
|
||||
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, propertyAccessorDescriptor);
|
||||
assert resolvedCall != null : "Resolve call should be recorded for delegate call " + signature.toString();
|
||||
|
||||
StackValue lastValue = invokeDelegatedPropertyConventionMethod(propertyAccessorDescriptor.getCorrespondingProperty(),
|
||||
codegen, state.getTypeMapper(), resolvedCall, index, 1);
|
||||
PropertyDescriptor propertyDescriptor = propertyAccessorDescriptor.getCorrespondingProperty();
|
||||
StackValue.Property receiver = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
|
||||
StackValue lastValue = invokeDelegatedPropertyConventionMethod(codegen, resolvedCall, receiver, propertyDescriptor);
|
||||
Type asmType = signature.getReturnType();
|
||||
lastValue.put(asmType, v);
|
||||
v.areturn(asmType);
|
||||
|
||||
@@ -116,10 +116,11 @@ class PropertyReferenceCodegen(
|
||||
generateCallableReferenceSignature(this, target, state)
|
||||
}
|
||||
|
||||
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(this, target, state)
|
||||
}
|
||||
|
||||
if (!isLocalDelegatedProperty) {
|
||||
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(this, target, state)
|
||||
}
|
||||
generateAccessors()
|
||||
}
|
||||
}
|
||||
@@ -194,6 +195,17 @@ class PropertyReferenceCodegen(
|
||||
|
||||
@JvmStatic
|
||||
fun generateCallableReferenceSignature(iv: InstructionAdapter, callable: CallableDescriptor, state: GenerationState) {
|
||||
if (callable is LocalVariableDescriptor) {
|
||||
val asmType = state.bindingContext.get(CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, callable)
|
||||
val allDelegatedProperties = state.bindingContext.get(CodegenBinding.DELEGATED_PROPERTIES, asmType)
|
||||
val index = allDelegatedProperties?.indexOf(callable) ?: -1
|
||||
if (index < 0) {
|
||||
throw AssertionError("Local delegated property is not found in $asmType: $callable")
|
||||
}
|
||||
iv.aconst("<v#$index>") // v = "variable"
|
||||
return
|
||||
}
|
||||
|
||||
val accessor = when (callable) {
|
||||
is FunctionDescriptor -> callable
|
||||
is VariableDescriptorWithAccessors ->
|
||||
|
||||
@@ -1,241 +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.codegen;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.RANGES_PACKAGE_FQ_NAME;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitiveNumberClassDescriptor;
|
||||
|
||||
public class RangeCodegenUtil {
|
||||
private static final ImmutableMap<FqName, PrimitiveType> RANGE_TO_ELEMENT_TYPE;
|
||||
private static final ImmutableMap<FqName, PrimitiveType> PROGRESSION_TO_ELEMENT_TYPE;
|
||||
|
||||
@NotNull
|
||||
public static List<PrimitiveType> supportedRangeTypes() {
|
||||
return Arrays.asList(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG);
|
||||
}
|
||||
|
||||
static {
|
||||
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
|
||||
ImmutableMap.Builder<FqName, PrimitiveType> progressionBuilder = ImmutableMap.builder();
|
||||
for (PrimitiveType primitiveType : supportedRangeTypes()) {
|
||||
FqName rangeClassFqName = RANGES_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Range"));
|
||||
FqName progressionClassFqName = RANGES_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Progression"));
|
||||
rangeBuilder.put(rangeClassFqName, primitiveType);
|
||||
progressionBuilder.put(progressionClassFqName, primitiveType);
|
||||
}
|
||||
RANGE_TO_ELEMENT_TYPE = rangeBuilder.build();
|
||||
PROGRESSION_TO_ELEMENT_TYPE = progressionBuilder.build();
|
||||
}
|
||||
|
||||
private RangeCodegenUtil() {}
|
||||
|
||||
public static boolean isRange(KotlinType rangeType) {
|
||||
return !rangeType.isMarkedNullable() && getPrimitiveRangeElementType(rangeType) != null;
|
||||
}
|
||||
|
||||
public static boolean isProgression(KotlinType rangeType) {
|
||||
return !rangeType.isMarkedNullable() && getPrimitiveProgressionElementType(rangeType) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PrimitiveType getPrimitiveRangeElementType(KotlinType rangeType) {
|
||||
return getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PrimitiveType getPrimitiveProgressionElementType(KotlinType rangeType) {
|
||||
return getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PrimitiveType getPrimitiveRangeOrProgressionElementType(
|
||||
@NotNull KotlinType rangeOrProgression,
|
||||
@NotNull ImmutableMap<FqName, PrimitiveType> map
|
||||
) {
|
||||
ClassifierDescriptor declarationDescriptor = rangeOrProgression.getConstructor().getDeclarationDescriptor();
|
||||
if (declarationDescriptor == null) return null;
|
||||
FqNameUnsafe fqName = DescriptorUtils.getFqName(declarationDescriptor);
|
||||
if (!fqName.isSafe()) return null;
|
||||
return map.get(fqName.toSafe());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PrimitiveType getPrimitiveRangeOrProgressionElementType(@NotNull FqName rangeOrProgressionName) {
|
||||
PrimitiveType result = RANGE_TO_ELEMENT_TYPE.get(rangeOrProgressionName);
|
||||
return result != null ? result : PROGRESSION_TO_ELEMENT_TYPE.get(rangeOrProgressionName);
|
||||
}
|
||||
|
||||
public static boolean isRangeOrProgression(@NotNull FqName className) {
|
||||
return getPrimitiveRangeOrProgressionElementType(className) != null;
|
||||
}
|
||||
|
||||
public static boolean isPrimitiveNumberRangeTo(CallableDescriptor rangeTo) {
|
||||
if (!"rangeTo".equals(rangeTo.getName().asString())) return false;
|
||||
|
||||
if (!isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isPrimitiveRangeToExtension(@NotNull CallableDescriptor descriptor) {
|
||||
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false;
|
||||
|
||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||
if (extensionReceiver == null) return false;
|
||||
|
||||
return KotlinBuiltIns.isPrimitiveType(extensionReceiver.getType());
|
||||
}
|
||||
|
||||
public static boolean isPrimitiveNumberDownTo(@NotNull CallableDescriptor descriptor) {
|
||||
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false;
|
||||
|
||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||
if (extensionReceiver == null) return false;
|
||||
ClassifierDescriptor extensionReceiverClassifier = extensionReceiver.getType().getConstructor().getDeclarationDescriptor();
|
||||
if (!isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isPrimitiveNumberUntil(@NotNull CallableDescriptor descriptor) {
|
||||
if (!isTopLevelInPackage(descriptor, "until", "kotlin.ranges")) return false;
|
||||
|
||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||
if (extensionReceiver == null) return false;
|
||||
ClassifierDescriptor extensionReceiverClassifier = extensionReceiver.getType().getConstructor().getDeclarationDescriptor();
|
||||
if (!isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isArrayOrPrimitiveArrayIndices(@NotNull CallableDescriptor descriptor) {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false;
|
||||
|
||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||
if (extensionReceiver == null) return false;
|
||||
KotlinType extensionReceiverType = extensionReceiver.getType();
|
||||
if (!KotlinBuiltIns.isArray(extensionReceiverType) && !KotlinBuiltIns.isPrimitiveArray(extensionReceiverType)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isCollectionIndices(@NotNull CallableDescriptor descriptor) {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false;
|
||||
|
||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||
if (extensionReceiver == null) return false;
|
||||
KotlinType extensionReceiverType = extensionReceiver.getType();
|
||||
if (!KotlinBuiltIns.isCollectionOrNullableCollection(extensionReceiverType)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isCharSequenceIndices(@NotNull CallableDescriptor descriptor) {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.text")) return false;
|
||||
|
||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||
if (extensionReceiver == null) return false;
|
||||
KotlinType extensionReceiverType = extensionReceiver.getType();
|
||||
if (!KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isPrimitiveRangeToExtension(@NotNull KtSimpleNameExpression operationReference, @NotNull BindingContext bindingContext) {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt
|
||||
.getResolvedCallWithAssert(operationReference, bindingContext);
|
||||
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
|
||||
|
||||
/*
|
||||
* Range is optimizable if
|
||||
* 'in' receiver is expression 'rangeTo' from stdlib package
|
||||
* and its argument has same primitive type as generic range parameter.
|
||||
* For non-matching primitive types (e.g. int in double range)
|
||||
* dispatch receiver will be null, because extension method will be called.
|
||||
*/
|
||||
if (!(receiver instanceof ExpressionReceiver)) return false;
|
||||
ExpressionReceiver e = (ExpressionReceiver) receiver;
|
||||
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedReceiver =
|
||||
CallUtilKt.getResolvedCall(e.getExpression(), bindingContext);
|
||||
if (resolvedReceiver == null) return false;
|
||||
|
||||
return isPrimitiveRangeToExtension(resolvedReceiver.getResultingDescriptor());
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether for expression 'x in a..b' a..b is primitive integral range
|
||||
* with same type as x.
|
||||
*/
|
||||
public static boolean isPrimitiveRangeSpecializationOfType(
|
||||
@NotNull Type argumentType,
|
||||
@NotNull KtExpression rangeExpression,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
if (rangeExpression instanceof KtBinaryExpression &&
|
||||
((KtBinaryExpression) rangeExpression).getOperationReference().getReferencedNameElementType() == KtTokens.RANGE) {
|
||||
KotlinType kotlinType = bindingContext.getType(rangeExpression);
|
||||
assert kotlinType != null;
|
||||
DeclarationDescriptor descriptor = kotlinType.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor != null) {
|
||||
FqNameUnsafe fqName = DescriptorUtils.getFqName(descriptor);
|
||||
if (fqName.equals(KotlinBuiltIns.FQ_NAMES.longRange)) {
|
||||
return argumentType == Type.LONG_TYPE;
|
||||
}
|
||||
if (fqName.equals(KotlinBuiltIns.FQ_NAMES.charRange) || fqName.equals(KotlinBuiltIns.FQ_NAMES.intRange)) {
|
||||
return AsmUtil.isIntPrimitive(argumentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isTopLevelInPackage(@NotNull CallableDescriptor descriptor, @NotNull String name, @NotNull String packageName) {
|
||||
if (!name.equals(descriptor.getName().asString())) return false;
|
||||
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (!(containingDeclaration instanceof PackageFragmentDescriptor)) return false;
|
||||
String packageFqName = ((PackageFragmentDescriptor) containingDeclaration).getFqName().asString();
|
||||
if (!packageName.equals(packageFqName)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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.kotlin.builtins.KotlinBuiltIns
|
||||
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.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
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"))
|
||||
}
|
||||
|
||||
private val PROGRESSION_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
|
||||
supportedRangeTypes.associateBy {
|
||||
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression"))
|
||||
}
|
||||
|
||||
fun isPrimitiveRange(rangeType: KotlinType) =
|
||||
!rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null
|
||||
|
||||
fun isPrimitiveProgression(rangeType: KotlinType) =
|
||||
!rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null
|
||||
|
||||
fun getPrimitiveRangeElementType(rangeType: KotlinType): PrimitiveType? =
|
||||
getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE)
|
||||
|
||||
private fun getPrimitiveProgressionElementType(rangeType: KotlinType) =
|
||||
getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE)
|
||||
|
||||
private fun getPrimitiveRangeOrProgressionElementType(
|
||||
rangeOrProgression: KotlinType,
|
||||
map: Map<FqName, PrimitiveType>
|
||||
): PrimitiveType? {
|
||||
val declarationDescriptor = rangeOrProgression.constructor.declarationDescriptor ?: return null
|
||||
val fqName = DescriptorUtils.getFqName(declarationDescriptor).takeIf { it.isSafe } ?: return null
|
||||
return map[fqName.toSafe()]
|
||||
}
|
||||
|
||||
fun getRangeOrProgressionElementType(rangeType: KotlinType): KotlinType? {
|
||||
val rangeTypeDescriptor = rangeType.constructor.declarationDescriptor ?: return null
|
||||
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
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "CharProgression", "kotlin.ranges") -> builtIns.charType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "IntProgression", "kotlin.ranges") -> builtIns.intType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "LongProgression", "kotlin.ranges") -> builtIns.longType
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatRange", "kotlin.ranges") -> builtIns.floatType
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedDoubleRange", "kotlin.ranges") -> builtIns.doubleType
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatingPointRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
|
||||
isTopLevelInPackage(rangeTypeDescriptor, "ComparableRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun getPrimitiveRangeOrProgressionElementType(rangeOrProgressionName: FqName): PrimitiveType? =
|
||||
RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?:
|
||||
PROGRESSION_TO_ELEMENT_TYPE[rangeOrProgressionName]
|
||||
|
||||
fun isRangeOrProgression(className: FqName) =
|
||||
getPrimitiveRangeOrProgressionElementType(className) != null
|
||||
|
||||
fun isPrimitiveNumberRangeTo(rangeTo: CallableDescriptor) =
|
||||
"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)
|
||||
}
|
||||
|
||||
fun isPrimitiveNumberDownTo(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
|
||||
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
|
||||
}
|
||||
|
||||
fun isPrimitiveNumberUntil(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "until", "kotlin.ranges")) return false
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
|
||||
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
|
||||
}
|
||||
|
||||
fun isArrayOrPrimitiveArrayIndices(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverType = extensionReceiver.type
|
||||
return KotlinBuiltIns.isArray(extensionReceiverType) || KotlinBuiltIns.isPrimitiveArray(extensionReceiverType)
|
||||
}
|
||||
|
||||
fun isCollectionIndices(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverType = extensionReceiver.type
|
||||
return KotlinBuiltIns.isCollectionOrNullableCollection(extensionReceiverType)
|
||||
}
|
||||
|
||||
fun isCharSequenceIndices(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.text")) return false
|
||||
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverType = extensionReceiver.type
|
||||
return KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)
|
||||
}
|
||||
|
||||
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 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
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun isPrimitiveRangeContains(descriptor: CallableDescriptor): Boolean {
|
||||
if (descriptor.name.asString() != "contains") return false
|
||||
val dispatchReceiverType = descriptor.dispatchReceiverParameter?.type ?: return false
|
||||
if (!isPrimitiveRange(dispatchReceiverType)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(descriptor: CallableDescriptor): Boolean {
|
||||
if (descriptor.name.asString() != "contains") return false
|
||||
|
||||
val extensionReceiverType = descriptor.extensionReceiverParameter?.type ?: return false
|
||||
|
||||
val rangeElementType = getRangeOrProgressionElementType(extensionReceiverType) ?: return false
|
||||
if (!isPrimitiveNumberType(rangeElementType)) return false
|
||||
|
||||
val argumentType = descriptor.valueParameters.singleOrNull()?.type ?: return false
|
||||
if (!isPrimitiveNumberType(argumentType)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun getClosedFloatingPointRangeElementType(rangeType: KotlinType): KotlinType? {
|
||||
val classDescriptor = rangeType.constructor.declarationDescriptor as? ClassDescriptor ?: return null
|
||||
if (!isTopLevelInPackage(classDescriptor, "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
|
||||
|
||||
val containingDeclaration = descriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false
|
||||
val packageFqName = containingDeclaration.fqName.asString()
|
||||
return packageName == packageFqName
|
||||
}
|
||||
|
||||
fun getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCallee: CallableDescriptor): Type {
|
||||
val rangeType = rangeCallee.returnType!!
|
||||
|
||||
getPrimitiveRangeElementType(rangeType)?.let {
|
||||
return AsmTypes.valueTypeForPrimitive(it)
|
||||
}
|
||||
|
||||
getPrimitiveProgressionElementType(rangeType)?.let {
|
||||
return AsmTypes.valueTypeForPrimitive(it)
|
||||
}
|
||||
|
||||
getClosedFloatingPointRangeElementType(rangeType)?.let {
|
||||
when {
|
||||
KotlinBuiltIns.isDouble(it) -> return Type.DOUBLE_TYPE
|
||||
KotlinBuiltIns.isFloat(it) -> return Type.FLOAT_TYPE
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
throw AssertionError("Unexpected range type: $rangeType")
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor;
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor;
|
||||
|
||||
public class SamCodegenUtil {
|
||||
|
||||
@@ -105,10 +105,14 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
protected void generateSyntheticPartsBeforeBody() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticPartsAfterBody() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
generateKotlinClassMetadataAnnotation(scriptDescriptor, true);
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,8 +26,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty;
|
||||
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.SyntheticFieldDescriptor;
|
||||
@@ -518,9 +515,11 @@ public abstract class StackValue {
|
||||
descriptor
|
||||
);
|
||||
StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, callExtensionReceiver, true);
|
||||
Type type = CallReceiver.calcType(resolvedCall, dispatchReceiverParameter, extensionReceiverParameter, codegen.typeMapper, callableMethod, codegen.getState());
|
||||
assert type != null : "Could not map receiver type for " + resolvedCall;
|
||||
return new CallReceiver(dispatchReceiver, extensionReceiver, type);
|
||||
return CallReceiver.generateCallReceiver(
|
||||
resolvedCall, codegen, callableMethod,
|
||||
dispatchReceiverParameter, dispatchReceiver,
|
||||
extensionReceiverParameter, extensionReceiver
|
||||
);
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
@@ -569,14 +568,13 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Contract("null -> false")
|
||||
private static boolean isLocalFunCall(@Nullable Callable callableMethod) {
|
||||
static boolean isLocalFunCall(@Nullable Callable callableMethod) {
|
||||
return callableMethod != null && callableMethod.getGenerateCalleeType() != null;
|
||||
}
|
||||
|
||||
public static StackValue receiverWithoutReceiverArgument(StackValue receiverWithParameter) {
|
||||
if (receiverWithParameter instanceof CallReceiver) {
|
||||
CallReceiver callReceiver = (CallReceiver) receiverWithParameter;
|
||||
return new CallReceiver(callReceiver.dispatchReceiver, none(), callReceiver.type);
|
||||
return ((CallReceiver) receiverWithParameter).withoutReceiverArgument();
|
||||
}
|
||||
return receiverWithParameter;
|
||||
}
|
||||
@@ -1517,101 +1515,6 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class CallReceiver extends StackValue {
|
||||
private final StackValue dispatchReceiver;
|
||||
private final StackValue extensionReceiver;
|
||||
|
||||
public CallReceiver(
|
||||
@NotNull StackValue dispatchReceiver,
|
||||
@NotNull StackValue extensionReceiver,
|
||||
@NotNull Type type
|
||||
) {
|
||||
super(type, dispatchReceiver.canHaveSideEffects() || extensionReceiver.canHaveSideEffects());
|
||||
this.dispatchReceiver = dispatchReceiver;
|
||||
this.extensionReceiver = extensionReceiver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Type calcType(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@Nullable ReceiverParameterDescriptor dispatchReceiver,
|
||||
@Nullable ReceiverParameterDescriptor extensionReceiver,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@Nullable Callable callableMethod,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
if (extensionReceiver != null) {
|
||||
CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor();
|
||||
|
||||
if (descriptor instanceof PropertyDescriptor &&
|
||||
// hackaround: boxing changes behaviour of T.javaClass intrinsic
|
||||
state.getIntrinsics().getIntrinsic((PropertyDescriptor) descriptor) != JavaClassProperty.INSTANCE
|
||||
) {
|
||||
ReceiverParameterDescriptor receiverCandidate = descriptor.getExtensionReceiverParameter();
|
||||
assert receiverCandidate != null;
|
||||
return typeMapper.mapType(receiverCandidate.getType());
|
||||
}
|
||||
|
||||
return callableMethod != null ? callableMethod.getExtensionReceiverType() : typeMapper.mapType(extensionReceiver.getType());
|
||||
}
|
||||
else if (dispatchReceiver != null) {
|
||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||
|
||||
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
if (callableMethod != null) {
|
||||
return callableMethod.getDispatchReceiverType();
|
||||
}
|
||||
|
||||
// Extract the receiver from the resolved call, workarounding the fact that ResolvedCall#dispatchReceiver doesn't have
|
||||
// all the needed information, for example there's no way to find out whether or not a smart cast was applied to the receiver.
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
if (container instanceof ClassDescriptor) {
|
||||
return typeMapper.mapClass((ClassDescriptor) container);
|
||||
}
|
||||
|
||||
return typeMapper.mapType(dispatchReceiver);
|
||||
}
|
||||
else if (isLocalFunCall(callableMethod)) {
|
||||
return callableMethod.getGenerateCalleeType();
|
||||
}
|
||||
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
StackValue currentExtensionReceiver = extensionReceiver;
|
||||
boolean hasExtensionReceiver = extensionReceiver != none();
|
||||
if (extensionReceiver instanceof StackValue.SafeCall) {
|
||||
currentExtensionReceiver.put(currentExtensionReceiver.type, v);
|
||||
currentExtensionReceiver = StackValue.onStack(currentExtensionReceiver.type);
|
||||
}
|
||||
|
||||
dispatchReceiver.put(hasExtensionReceiver ? dispatchReceiver.type : type, v);
|
||||
|
||||
currentExtensionReceiver
|
||||
.moveToTopOfStack(hasExtensionReceiver ? type : currentExtensionReceiver.type, v, dispatchReceiver.type.getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
|
||||
AsmUtil.dup(v, extensionReceiver.type, dispatchReceiver.type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue getDispatchReceiver() {
|
||||
return dispatchReceiver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue getExtensionReceiver() {
|
||||
return extensionReceiver;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class StackValueWithSimpleReceiver extends StackValue {
|
||||
|
||||
public final boolean isStaticPut;
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.tree.LocalVariableNode;
|
||||
@@ -29,6 +28,9 @@ import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getNodeText;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.wrapWithMaxLocalCalc;
|
||||
|
||||
public abstract class TransformationMethodVisitor extends MethodVisitor {
|
||||
|
||||
private final MethodNode methodNode;
|
||||
@@ -46,7 +48,7 @@ public abstract class TransformationMethodVisitor extends MethodVisitor {
|
||||
this.delegate = delegate;
|
||||
this.methodNode = new MethodNode(access, name, desc, signature, exceptions);
|
||||
this.methodNode.localVariables = new ArrayList<>(5);
|
||||
this.mv = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode);
|
||||
this.mv = wrapWithMaxLocalCalc(methodNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,7 +85,7 @@ public abstract class TransformationMethodVisitor extends MethodVisitor {
|
||||
delegate.visitEnd();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new CompilationException("Couldn't transform method node: " + InlineCodegenUtil.getNodeText(methodNode), t, null);
|
||||
throw new CompilationException("Couldn't transform method node: " + getNodeText(methodNode), t, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
interface WrappedAnnotated : Annotated {
|
||||
val originalAnnotated: Annotated
|
||||
@@ -34,10 +33,6 @@ class AnnotatedWithOnlyTargetedAnnotations(original: Annotated) : Annotated {
|
||||
private class UseSiteTargetedAnnotations(private val additionalAnnotations: Annotations) : Annotations {
|
||||
override fun isEmpty() = true
|
||||
|
||||
override fun findAnnotation(fqName: FqName) = null
|
||||
|
||||
override fun findExternalAnnotation(fqName: FqName) = null
|
||||
|
||||
override fun getUseSiteTargetedAnnotations() = getAdditionalTargetedAnnotations()
|
||||
|
||||
override fun getAllAnnotations() = getAdditionalTargetedAnnotations()
|
||||
@@ -48,4 +43,4 @@ class AnnotatedWithOnlyTargetedAnnotations(original: Annotated) : Annotated {
|
||||
}
|
||||
}
|
||||
|
||||
class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations)
|
||||
class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations)
|
||||
|
||||
@@ -38,8 +38,9 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingConfiguration;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -370,26 +371,13 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
@NotNull
|
||||
private MutableClosure recordClosure(@NotNull ClassDescriptor classDescriptor, @NotNull String name) {
|
||||
return CodegenBinding.recordClosure(
|
||||
bindingTrace, classDescriptor, peekFromStack(classStack), Type.getObjectType(name), fileClassesProvider
|
||||
);
|
||||
return CodegenBinding.recordClosure(bindingTrace, classDescriptor, peekFromStack(classStack), Type.getObjectType(name));
|
||||
}
|
||||
|
||||
private void recordLocalVariablePropertyMetadata(LocalVariableDescriptor variableDescriptor) {
|
||||
KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType(variableDescriptor, bindingContext);
|
||||
if (delegateType == null) return;
|
||||
|
||||
LocalVariableDescriptor delegateVariableDescriptor = new LocalVariableDescriptor(
|
||||
variableDescriptor.getContainingDeclaration(),
|
||||
Annotations.Companion.getEMPTY(),
|
||||
variableDescriptor.getName(),
|
||||
delegateType,
|
||||
false,
|
||||
false,
|
||||
SourceElement.NO_SOURCE
|
||||
);
|
||||
bindingTrace.record(LOCAL_VARIABLE_DELEGATE, variableDescriptor, delegateVariableDescriptor);
|
||||
|
||||
LocalVariableDescriptor metadataVariableDescriptor = new LocalVariableDescriptor(
|
||||
variableDescriptor.getContainingDeclaration(),
|
||||
Annotations.Companion.getEMPTY(),
|
||||
@@ -428,12 +416,38 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
runtimeTypes.getSupertypeForPropertyReference(variableDescriptor, variableDescriptor.isVar(), /* bound = */ false);
|
||||
ClassDescriptor classDescriptor = recordClassForCallable(delegate, variableDescriptor, Collections.singleton(supertype), name);
|
||||
recordClosure(classDescriptor, name);
|
||||
|
||||
Type containerType = getMetadataOwner(property);
|
||||
List<VariableDescriptorWithAccessors> descriptors = bindingTrace.get(DELEGATED_PROPERTIES, containerType);
|
||||
if (descriptors == null) {
|
||||
descriptors = new ArrayList<>(1);
|
||||
bindingTrace.record(DELEGATED_PROPERTIES, containerType, descriptors);
|
||||
}
|
||||
descriptors.add(variableDescriptor);
|
||||
|
||||
bindingTrace.record(DELEGATED_PROPERTY_METADATA_OWNER, variableDescriptor, containerType);
|
||||
}
|
||||
|
||||
super.visitProperty(property);
|
||||
nameStack.pop();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type getMetadataOwner(@NotNull KtProperty property) {
|
||||
for (int i = classStack.size() - 1; i >= 0; i--) {
|
||||
ClassDescriptor descriptor = classStack.get(i);
|
||||
// The first "real" containing class (not a synthetic class for lambda) is the owner of the delegated property metadata
|
||||
if (!(descriptor instanceof SyntheticClassDescriptorForLambda)) {
|
||||
ClassId classId = DescriptorUtilsKt.getClassId(descriptor);
|
||||
return classId != null
|
||||
? AsmUtil.asmTypeByClassId(classId)
|
||||
: CodegenBinding.getAsmType(bindingContext, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return Type.getObjectType(FileClasses.getFileClassInternalName(fileClassesProvider, property.getContainingKtFile()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedFunction(@NotNull KtNamedFunction function) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function);
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.codegen.SamType;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
@@ -49,7 +48,7 @@ public class CodegenBinding {
|
||||
|
||||
public static final WritableSlice<ClassDescriptor, Boolean> ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice();
|
||||
|
||||
public static final WritableSlice<ClassDescriptor, Collection<ClassDescriptor>> INNER_CLASSES = Slices.createSimpleSlice();
|
||||
private static final WritableSlice<ClassDescriptor, Collection<ClassDescriptor>> INNER_CLASSES = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<KtExpression, SamType> SAM_VALUE = Slices.createSimpleSlice();
|
||||
|
||||
@@ -60,18 +59,19 @@ public class CodegenBinding {
|
||||
public static final WritableSlice<String, List<WhenByEnumsMapping>> MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<VariableDescriptor, VariableDescriptor> LOCAL_VARIABLE_DELEGATE =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<VariableDescriptor, VariableDescriptor> LOCAL_VARIABLE_PROPERTY_METADATA =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<FunctionDescriptor, FunctionDescriptor> SUSPEND_FUNCTION_TO_JVM_VIEW =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ValueParameterDescriptor, ValueParameterDescriptor> PARAMETER_SYNONYM =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<Type, List<VariableDescriptorWithAccessors>> DELEGATED_PROPERTIES =
|
||||
Slices.createSimpleSlice();
|
||||
public static final WritableSlice<VariableDescriptorWithAccessors, Type> DELEGATED_PROPERTY_METADATA_OWNER =
|
||||
Slices.createSimpleSlice();
|
||||
public static final WritableSlice<VariableDescriptor, VariableDescriptor> LOCAL_VARIABLE_PROPERTY_METADATA =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
static {
|
||||
BasicWritableSlice.initSliceDebugNames(CodegenBinding.class);
|
||||
}
|
||||
@@ -150,8 +150,7 @@ public class CodegenBinding {
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@Nullable ClassDescriptor enclosing,
|
||||
@NotNull Type asmType,
|
||||
@NotNull JvmFileClassesProvider fileClassesManager
|
||||
@NotNull Type asmType
|
||||
) {
|
||||
KtElement element = (KtElement) DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor);
|
||||
assert element != null : "No source element for " + classDescriptor;
|
||||
@@ -227,32 +226,6 @@ public class CodegenBinding {
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<ClassDescriptor> getAllInnerClasses(
|
||||
@NotNull BindingContext bindingContext, @NotNull ClassDescriptor outermostClass
|
||||
) {
|
||||
Collection<ClassDescriptor> innerClasses = bindingContext.get(INNER_CLASSES, outermostClass);
|
||||
if (innerClasses == null || innerClasses.isEmpty()) return Collections.emptySet();
|
||||
|
||||
Set<ClassDescriptor> allInnerClasses = new HashSet<>();
|
||||
|
||||
Deque<ClassDescriptor> stack = new ArrayDeque<>(innerClasses);
|
||||
do {
|
||||
ClassDescriptor currentClass = stack.pop();
|
||||
if (allInnerClasses.add(currentClass)) {
|
||||
Collection<ClassDescriptor> nextClasses = bindingContext.get(INNER_CLASSES, currentClass);
|
||||
if (nextClasses != null) {
|
||||
for (ClassDescriptor nextClass : nextClasses) {
|
||||
stack.push(nextClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!stack.isEmpty());
|
||||
|
||||
return allInnerClasses;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static VariableDescriptor getDelegatedLocalVariableMetadata(
|
||||
@NotNull VariableDescriptor variableDescriptor,
|
||||
|
||||
@@ -17,16 +17,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.google.common.collect.Maps
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
|
||||
import org.jetbrains.kotlin.codegen.context.PackageContext
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext
|
||||
@@ -43,13 +47,13 @@ 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.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -239,8 +243,9 @@ fun reportTarget6InheritanceErrorIfNeeded(
|
||||
state.diagnostics.report(
|
||||
ErrorsJvm.TARGET6_INTERFACE_INHERITANCE.on(
|
||||
classElement, classDescriptor, key,
|
||||
value.map { Renderers.COMPACT.render(JvmCodegenUtil.getDirectMember(it), RenderingContext.Empty) }.
|
||||
joinToString(separator = "\n", prefix = "\n")
|
||||
value.joinToString(separator = "\n", prefix = "\n") {
|
||||
Renderers.COMPACT.render(JvmCodegenUtil.getDirectMember(it), RenderingContext.Empty)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -287,14 +292,10 @@ fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingConte
|
||||
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression!!, ktType, bindingContext, descriptor)
|
||||
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow)
|
||||
return stableTypes.firstNotNullResult {
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(it)) {
|
||||
TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it))
|
||||
}
|
||||
else if (KotlinBuiltIns.isFloatOrNullableFloat(it)) {
|
||||
TypeAndNullability(Type.FLOAT_TYPE, TypeUtils.isNullableType(it))
|
||||
}
|
||||
else {
|
||||
null
|
||||
when {
|
||||
KotlinBuiltIns.isDoubleOrNullableDouble(it) -> TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it))
|
||||
KotlinBuiltIns.isFloatOrNullableFloat(it) -> TypeAndNullability(Type.FLOAT_TYPE, TypeUtils.isNullableType(it))
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,3 +397,26 @@ fun InstructionAdapter.generateNewInstanceDupAndPlaceBeforeStackTop(
|
||||
load(index, topStackType)
|
||||
}
|
||||
}
|
||||
|
||||
fun extractReificationArgument(type: KotlinType): Pair<TypeParameterDescriptor, ReificationArgument>? {
|
||||
var type = type
|
||||
var arrayDepth = 0
|
||||
val isNullable = type.isMarkedNullable
|
||||
while (KotlinBuiltIns.isArray(type)) {
|
||||
arrayDepth++
|
||||
type = type.arguments[0].type
|
||||
}
|
||||
|
||||
val parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type) ?: return null
|
||||
|
||||
return Pair(parameterDescriptor, ReificationArgument(parameterDescriptor.name.asString(), isNullable, arrayDepth))
|
||||
}
|
||||
|
||||
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
|
||||
function.initialSignatureDescriptor ?: function
|
||||
|
||||
fun ExpressionCodegen.generateCallReceiver(rangeCall: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||
generateReceiverValue(rangeCall.extensionReceiver ?: rangeCall.dispatchReceiver!!, false)
|
||||
|
||||
fun ExpressionCodegen.generateCallSingleArgument(rangeCall: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||
gen(ExpressionCodegen.getSingleArgumentExpression(rangeCall)!!)
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
@@ -248,10 +248,9 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@NotNull PackageFragmentDescriptor descriptor,
|
||||
@NotNull Type multifileClassType,
|
||||
@NotNull Type filePartType,
|
||||
@NotNull Type filePartInitializerType,
|
||||
@NotNull KtFile sourceFile
|
||||
) {
|
||||
return new MultifileClassPartContext(descriptor, this, multifileClassType, filePartType, filePartInitializerType, sourceFile);
|
||||
return new MultifileClassPartContext(descriptor, this, multifileClassType, filePartType, sourceFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -55,9 +55,12 @@ public interface LocalLookup {
|
||||
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
||||
if (!idx) return null;
|
||||
|
||||
VariableDescriptor delegateVariableDescriptor = state.getBindingContext().get(LOCAL_VARIABLE_DELEGATE, vd);
|
||||
KotlinType delegateType =
|
||||
vd instanceof VariableDescriptorWithAccessors
|
||||
? JvmCodegenUtil.getPropertyDelegateType((VariableDescriptorWithAccessors) vd, state.getBindingContext())
|
||||
: null;
|
||||
Type sharedVarType = state.getTypeMapper().getSharedVarType(vd);
|
||||
Type localType = state.getTypeMapper().mapType(delegateVariableDescriptor != null ? delegateVariableDescriptor : vd);
|
||||
Type localType = state.getTypeMapper().mapType(delegateType != null ? delegateType : vd.getType());
|
||||
Type type = sharedVarType != null ? sharedVarType : localType;
|
||||
|
||||
String fieldName = "$" + vd.getName();
|
||||
|
||||
@@ -24,19 +24,16 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class MultifileClassPartContext extends MultifileClassContextBase implements DelegatingToPartContext, FacadePartWithSourceFile {
|
||||
private final KtFile sourceFile;
|
||||
private final Type partInitializerType;
|
||||
|
||||
public MultifileClassPartContext(
|
||||
PackageFragmentDescriptor descriptor,
|
||||
CodegenContext parent,
|
||||
Type multifileClassType,
|
||||
Type filePartType,
|
||||
Type partInitializerType,
|
||||
@NotNull KtFile sourceFile
|
||||
) {
|
||||
super(descriptor, parent, multifileClassType, filePartType);
|
||||
this.sourceFile = sourceFile;
|
||||
this.partInitializerType = partInitializerType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -45,11 +42,6 @@ public class MultifileClassPartContext extends MultifileClassContextBase impleme
|
||||
return getFilePartType();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type getPartInitializerType() {
|
||||
return partInitializerType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public KtFile getSourceFile() {
|
||||
|
||||
@@ -43,11 +43,6 @@ public class PackageContext extends FieldOwnerContext<PackageFragmentDescriptor>
|
||||
return "Package: " + getContextDescriptor().getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Type getPackagePartType() {
|
||||
return packagePartType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Type getImplementationOwnerClassType() {
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||
import org.jetbrains.kotlin.coroutines.isSuspendLambda
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -39,6 +40,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -192,7 +194,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
if (allFunctionParameters().size <= 1) {
|
||||
val delegate = typeMapper.mapSignatureSkipGeneric(createCoroutineDescriptor).asmMethod
|
||||
|
||||
val bridgeParameters = (1..delegate.argumentTypes.size - 1).map { AsmTypes.OBJECT_TYPE } + delegate.argumentTypes.last()
|
||||
val bridgeParameters = (1 until delegate.argumentTypes.size).map { AsmTypes.OBJECT_TYPE } + delegate.argumentTypes.last()
|
||||
val bridge = Method(delegate.name, delegate.returnType, bridgeParameters.toTypedArray())
|
||||
|
||||
generateBridge(bridge, delegate)
|
||||
@@ -288,7 +290,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
|
||||
private fun allFunctionParameters() =
|
||||
originalSuspendFunctionDescriptor.extensionReceiverParameter.let(::listOfNotNull) +
|
||||
originalSuspendFunctionDescriptor.valueParameters.orEmpty()
|
||||
originalSuspendFunctionDescriptor.valueParameters
|
||||
|
||||
private fun ParameterDescriptor.getFieldInfoForCoroutineLambdaParameter() =
|
||||
createHiddenFieldInfo(type, COROUTINE_LAMBDA_PARAMETER_PREFIX + (this.safeAs<ValueParameterDescriptor>()?.index ?: ""))
|
||||
@@ -310,6 +312,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { v },
|
||||
element = element,
|
||||
containingClassInternalName = v.thisName,
|
||||
isForNamedFunction = false
|
||||
)
|
||||
@@ -474,8 +477,10 @@ class CoroutineCodegenForNamedFunction private constructor(
|
||||
}
|
||||
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) {
|
||||
// Do not write method metadata for raw coroutine state machines
|
||||
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { av ->
|
||||
val serializer = DescriptorSerializer.createForLambda(JvmSerializerExtension(v.serializationBindings, state))
|
||||
val functionProto = serializer.functionProto(createFreeFakeLambdaDescriptor(suspendFunctionJvmView)).build()
|
||||
AsmUtil.writeAnnotationData(av, serializer, functionProto)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,17 +17,21 @@
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import com.intellij.util.containers.Stack
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.inline.MaxStackFrameSizeAndLocalsCalculator
|
||||
import org.jetbrains.kotlin.codegen.inline.isAfterSuspendMarker
|
||||
import org.jetbrains.kotlin.codegen.inline.isBeforeSuspendMarker
|
||||
import org.jetbrains.kotlin.codegen.inline.isInlineMarker
|
||||
import org.jetbrains.kotlin.codegen.optimization.DeadCodeEliminationMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
@@ -50,6 +54,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
private val containingClassInternalName: String,
|
||||
obtainClassBuilderForCoroutineState: () -> ClassBuilder,
|
||||
private val isForNamedFunction: 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
|
||||
@@ -59,8 +64,8 @@ class CoroutineTransformerMethodVisitor(
|
||||
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
|
||||
|
||||
private val continuationIndex = if (isForNamedFunction) getLastParameterIndex(desc, access) else 0
|
||||
var dataIndex = if (isForNamedFunction) -1 else 1
|
||||
var exceptionIndex = if (isForNamedFunction) -1 else 2
|
||||
private var dataIndex = if (isForNamedFunction) -1 else 1
|
||||
private var exceptionIndex = if (isForNamedFunction) -1 else 2
|
||||
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
val suspensionPoints = collectSuspensionPoints(methodNode)
|
||||
@@ -106,11 +111,16 @@ class CoroutineTransformerMethodVisitor(
|
||||
methodNode.instructions.apply {
|
||||
val startLabel = LabelNode()
|
||||
val defaultLabel = LabelNode()
|
||||
val firstToInsertBefore = actualCoroutineStart
|
||||
val tableSwitchLabel = LabelNode()
|
||||
val lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0
|
||||
|
||||
// tableswitch(this.label)
|
||||
insertBefore(firstToInsertBefore,
|
||||
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(),
|
||||
@@ -293,7 +303,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
// It doesn't introduce an additional state to the corresponding coroutine's FSM.
|
||||
suspensionPoints.forEach {
|
||||
if (dceResult.isAlive(it.suspensionCallBegin) && dceResult.isRemoved(it.suspensionCallEnd)) {
|
||||
methodNode.instructions.remove(it.suspensionCallBegin)
|
||||
it.removeBeforeSuspendMarker(methodNode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,17 +312,15 @@ class CoroutineTransformerMethodVisitor(
|
||||
|
||||
private fun collectSuspensionPoints(methodNode: MethodNode): MutableList<SuspensionPoint> {
|
||||
val suspensionPoints = mutableListOf<SuspensionPoint>()
|
||||
val beforeSuspensionPointMarkerStack = Stack<MethodInsnNode>()
|
||||
val beforeSuspensionPointMarkerStack = Stack<AbstractInsnNode>()
|
||||
|
||||
for (methodInsn in methodNode.instructions.toArray().filterIsInstance<MethodInsnNode>()) {
|
||||
if (methodInsn.owner != COROUTINE_MARKER_OWNER) continue
|
||||
|
||||
when (methodInsn.name) {
|
||||
BEFORE_SUSPENSION_POINT_MARKER_NAME -> {
|
||||
beforeSuspensionPointMarkerStack.add(methodInsn)
|
||||
when {
|
||||
isBeforeSuspendMarker(methodInsn) -> {
|
||||
beforeSuspensionPointMarkerStack.add(methodInsn.previous)
|
||||
}
|
||||
|
||||
AFTER_SUSPENSION_POINT_MARKER_NAME -> {
|
||||
isAfterSuspendMarker(methodInsn) -> {
|
||||
suspensionPoints.add(SuspensionPoint(beforeSuspensionPointMarkerStack.pop(), methodInsn))
|
||||
}
|
||||
}
|
||||
@@ -326,10 +334,8 @@ class CoroutineTransformerMethodVisitor(
|
||||
private fun dropSuspensionMarkers(methodNode: MethodNode, suspensionPoints: List<SuspensionPoint>) {
|
||||
// Drop markers
|
||||
suspensionPoints.forEach {
|
||||
// before-marker
|
||||
methodNode.instructions.remove(it.suspensionCallBegin)
|
||||
// after-marker
|
||||
methodNode.instructions.remove(it.suspensionCallEnd)
|
||||
it.removeBeforeSuspendMarker(methodNode)
|
||||
it.removeAfterSuspendMarker(methodNode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,6 +469,8 @@ class CoroutineTransformerMethodVisitor(
|
||||
): LabelNode {
|
||||
val continuationLabel = LabelNode()
|
||||
val continuationLabelAfterLoadedResult = LabelNode()
|
||||
val suspendElementLineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0
|
||||
val nextLineNumberNode = suspension.suspensionCallEnd.findNextOrNull { it is LineNumberNode } as? LineNumberNode
|
||||
with(methodNode.instructions) {
|
||||
// Save state
|
||||
insertBefore(suspension.suspensionCallBegin,
|
||||
@@ -479,6 +487,10 @@ class CoroutineTransformerMethodVisitor(
|
||||
ifacmpne(continuationLabelAfterLoadedResult.label)
|
||||
|
||||
// Exit
|
||||
val returnLabel = LabelNode()
|
||||
visitLabel(returnLabel.label)
|
||||
// Special line number to stop in debugger before suspend return
|
||||
visitLineNumber(suspendElementLineNumber, returnLabel.label)
|
||||
load(suspendMarkerVarIndex, AsmTypes.OBJECT_TYPE)
|
||||
areturn(AsmTypes.OBJECT_TYPE)
|
||||
// Mark place for continuation
|
||||
@@ -503,7 +515,18 @@ class CoroutineTransformerMethodVisitor(
|
||||
load(dataIndex, AsmTypes.OBJECT_TYPE)
|
||||
|
||||
visitLabel(continuationLabelAfterLoadedResult.label)
|
||||
|
||||
// Extend next instruction linenumber. Can't use line number of suspension point here because both non-suspended execution
|
||||
// and re-entering after suspension passes this label.
|
||||
val afterSuspensionPointLineNumber = nextLineNumberNode?.line ?: suspendElementLineNumber
|
||||
visitLineNumber(afterSuspensionPointLineNumber, continuationLabelAfterLoadedResult.label)
|
||||
})
|
||||
|
||||
if (nextLineNumberNode != null) {
|
||||
// Remove the line number instruction as it now covered with line number on continuation label.
|
||||
// If both linenumber are present in bytecode, debugger will trigger line specific events twice.
|
||||
remove(nextLineNumberNode)
|
||||
}
|
||||
}
|
||||
|
||||
return continuationLabel
|
||||
@@ -589,18 +612,30 @@ private fun Type.normalize() =
|
||||
|
||||
/**
|
||||
* Suspension call may consists of several instructions:
|
||||
* INVOKESTATIC beforeSuspensionMarker
|
||||
* ICONST_0
|
||||
* INVOKESTATIC InlineMarker.mark()
|
||||
* INVOKEVIRTUAL suspensionMethod()Ljava/lang/Object; // actually it could be some inline method instead of plain call
|
||||
* CHECKCAST Type
|
||||
* INVOKESTATIC afterSuspensionMarker
|
||||
* ICONST_1
|
||||
* INVOKESTATIC InlineMarker.mark()
|
||||
*/
|
||||
private class SuspensionPoint(
|
||||
// INVOKESTATIC beforeSuspensionMarker
|
||||
// ICONST_0
|
||||
val suspensionCallBegin: AbstractInsnNode,
|
||||
// INVOKESTATIC afterSuspensionMarker
|
||||
// INVOKESTATIC InlineMarker.mark()
|
||||
val suspensionCallEnd: AbstractInsnNode
|
||||
) {
|
||||
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
||||
|
||||
fun removeBeforeSuspendMarker(methodNode: MethodNode) {
|
||||
methodNode.instructions.remove(suspensionCallBegin.next)
|
||||
methodNode.instructions.remove(suspensionCallBegin)
|
||||
}
|
||||
|
||||
fun removeAfterSuspendMarker(methodNode: MethodNode) {
|
||||
methodNode.instructions.remove(suspensionCallEnd.previous)
|
||||
methodNode.instructions.remove(suspensionCallEnd)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLastParameterIndex(desc: String, access: Int) =
|
||||
@@ -681,7 +716,7 @@ private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?>
|
||||
}
|
||||
|
||||
if (!insn.isMeaningful || insn.opcode in SAFE_OPCODES || insn.isInvisibleInDebugVarInsn(methodNode) ||
|
||||
InlineCodegenUtil.isInlineMarker(insn)) {
|
||||
isInlineMarker(insn)) {
|
||||
setOf()
|
||||
}
|
||||
else null
|
||||
@@ -693,6 +728,7 @@ private fun findSafelyReachableReturns(methodNode: MethodNode): Array<Set<Int>?>
|
||||
for (index in 0 until insns.size()) {
|
||||
if (insns[index].opcode == Opcodes.ARETURN) continue
|
||||
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
val newResult =
|
||||
controlFlowGraph
|
||||
.getSuccessorsIndices(index).plus(index)
|
||||
@@ -720,4 +756,4 @@ private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode):
|
||||
}
|
||||
|
||||
private val SAFE_OPCODES =
|
||||
((Opcodes.DUP..Opcodes.DUP2_X2) + 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()
|
||||
|
||||
@@ -57,6 +57,7 @@ class SuspendFunctionGenerationStrategy(
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
|
||||
isForNamedFunction = true,
|
||||
element = declaration,
|
||||
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
internalNameForDispatchReceiver = containingClassInternalNameOrNull()
|
||||
).also {
|
||||
|
||||
@@ -52,11 +52,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
// These classes do not actually exist at runtime
|
||||
const val COROUTINE_MARKER_OWNER = "kotlin/coroutines/Markers"
|
||||
const val BEFORE_SUSPENSION_POINT_MARKER_NAME = "beforeSuspensionPoint"
|
||||
const val AFTER_SUSPENSION_POINT_MARKER_NAME = "afterSuspensionPoint"
|
||||
|
||||
const val COROUTINE_LABEL_FIELD_NAME = "label"
|
||||
const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create"
|
||||
const val DO_RESUME_METHOD_NAME = "doResume"
|
||||
|
||||
@@ -144,7 +144,7 @@ internal fun performRefinedTypeAnalysis(methodNode: MethodNode, thisName: String
|
||||
}
|
||||
})
|
||||
|
||||
val refinedFrames = Array(basicFrames.size) {
|
||||
return Array(basicFrames.size) {
|
||||
insnIndex ->
|
||||
val current = Frame(basicFrames[insnIndex] ?: return@Array null)
|
||||
|
||||
@@ -158,8 +158,6 @@ internal fun performRefinedTypeAnalysis(methodNode: MethodNode, thisName: String
|
||||
|
||||
current
|
||||
}
|
||||
|
||||
return refinedFrames
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.isIntLoad() = opcode == Opcodes.ILOAD
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -14,10 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.java.model.elements
|
||||
package org.jetbrains.kotlin.codegen.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.java.model.JeElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
|
||||
interface JeElementRenderer {
|
||||
fun render(element: JeElement): String
|
||||
}
|
||||
interface FileClassDescriptor : ClassDescriptor
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Given a function descriptor, creates another function descriptor with type parameters copied from outer context(s).
|
||||
* This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
|
||||
*/
|
||||
fun createFreeFakeLambdaDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
|
||||
return createFreeDescriptor(descriptor)
|
||||
}
|
||||
|
||||
private fun <D : CallableMemberDescriptor> createFreeDescriptor(descriptor: D): D {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val builder = descriptor.newCopyBuilder() as CallableMemberDescriptor.CopyBuilder<D>
|
||||
|
||||
val typeParameters = ArrayList<TypeParameterDescriptor>(0)
|
||||
builder.setTypeParameters(typeParameters)
|
||||
|
||||
var container: DeclarationDescriptor? = descriptor.containingDeclaration
|
||||
while (container != null) {
|
||||
if (container is ClassDescriptor) {
|
||||
typeParameters.addAll(container.declaredTypeParameters)
|
||||
}
|
||||
else if (container is CallableDescriptor && container !is ConstructorDescriptor) {
|
||||
typeParameters.addAll(container.typeParameters)
|
||||
}
|
||||
container = container.containingDeclaration
|
||||
}
|
||||
|
||||
return if (typeParameters.isEmpty()) descriptor else builder.build()!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a local delegated variable descriptor, creates a descriptor of a property that should be observed
|
||||
* when using reflection on that local variable at runtime.
|
||||
* Only members used by [DescriptorSerializer.propertyProto] are implemented correctly in this property descriptor.
|
||||
*/
|
||||
fun createFreeFakeLocalPropertyDescriptor(descriptor: LocalVariableDescriptor): PropertyDescriptor {
|
||||
val property = PropertyDescriptorImpl.create(
|
||||
descriptor.containingDeclaration, descriptor.annotations, Modality.FINAL, descriptor.visibility, descriptor.isVar,
|
||||
descriptor.name, CallableMemberDescriptor.Kind.DECLARATION, descriptor.source, false, descriptor.isConst,
|
||||
false, false, false, @Suppress("DEPRECATION") descriptor.isDelegated
|
||||
)
|
||||
property.setType(descriptor.type, descriptor.typeParameters, descriptor.dispatchReceiverParameter, descriptor.extensionReceiverParameter)
|
||||
|
||||
property.initialize(
|
||||
descriptor.getter?.run {
|
||||
PropertyGetterDescriptorImpl(property, annotations, modality, visibility, true, isExternal, isInline, kind, null, source).apply {
|
||||
initialize(this@run.returnType)
|
||||
}
|
||||
},
|
||||
descriptor.setter?.run {
|
||||
PropertySetterDescriptorImpl(property, annotations, modality, visibility, true, isExternal, isInline, kind, null, source).apply {
|
||||
initialize(this@run.valueParameters.single())
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return createFreeDescriptor(property)
|
||||
}
|
||||
@@ -1,101 +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.forLoop
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.RangeCodegenUtil
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
fun ExpressionCodegen.getForLoopGenerator(forExpression: KtForExpression) : AbstractForLoopGenerator {
|
||||
getLoopRangeResolvedCall(forExpression, bindingContext)?.let { loopRangeCall ->
|
||||
createOptimizedForLoopGeneratorOrNull(forExpression, loopRangeCall)?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
val loopRange = forExpression.loopRange!!
|
||||
val loopRangeType = bindingContext.getType(loopRange)!!
|
||||
val asmLoopRangeType = asmType(loopRangeType)
|
||||
|
||||
return when {
|
||||
asmLoopRangeType.sort == Type.ARRAY ->
|
||||
ForInArrayLoopGenerator(this, forExpression)
|
||||
RangeCodegenUtil.isRange(loopRangeType) ->
|
||||
ForInRangeInstanceLoopGenerator(this, forExpression)
|
||||
RangeCodegenUtil.isProgression(loopRangeType) ->
|
||||
ForInProgressionExpressionLoopGenerator(this, forExpression)
|
||||
isSubtypeOfCharSequence(loopRangeType, state.module.builtIns) ->
|
||||
ForInCharSequenceLoopGenerator(this, forExpression)
|
||||
else ->
|
||||
IteratorForLoopGenerator(this, forExpression)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSubtypeOfCharSequence(type: KotlinType, builtIns: KotlinBuiltIns) =
|
||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.getBuiltInClassByName(Name.identifier("CharSequence")).defaultType)
|
||||
|
||||
private fun ExpressionCodegen.createOptimizedForLoopGeneratorOrNull(
|
||||
forExpression: KtForExpression,
|
||||
loopRangeCall: ResolvedCall<out CallableDescriptor>
|
||||
): AbstractForLoopGenerator? {
|
||||
val loopRangeCallee = loopRangeCall.resultingDescriptor
|
||||
|
||||
return when {
|
||||
RangeCodegenUtil.isPrimitiveNumberRangeTo(loopRangeCallee) ->
|
||||
ForInRangeLiteralLoopGenerator(this, forExpression, loopRangeCall)
|
||||
RangeCodegenUtil.isPrimitiveNumberDownTo(loopRangeCallee) ->
|
||||
ForInDownToProgressionLoopGenerator(this, forExpression, loopRangeCall)
|
||||
RangeCodegenUtil.isPrimitiveNumberUntil(loopRangeCallee) ->
|
||||
ForInUntilRangeLoopGenerator(this, forExpression, loopRangeCall)
|
||||
RangeCodegenUtil.isArrayOrPrimitiveArrayIndices(loopRangeCallee) ->
|
||||
ForInArrayIndicesRangeLoopGenerator(this, forExpression, loopRangeCall)
|
||||
RangeCodegenUtil.isCollectionIndices(loopRangeCallee) ->
|
||||
ForInCollectionIndicesRangeLoopGenerator(this, forExpression, loopRangeCall)
|
||||
RangeCodegenUtil.isCharSequenceIndices(loopRangeCallee) ->
|
||||
ForInCharSequenceIndicesRangeLoopGenerator(this, forExpression, loopRangeCall)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLoopRangeResolvedCall(forExpression: KtForExpression, bindingContext: BindingContext): ResolvedCall<out CallableDescriptor>? {
|
||||
val loopRange = KtPsiUtil.deparenthesize(forExpression.loopRange)
|
||||
|
||||
if (loopRange is KtQualifiedExpression) {
|
||||
val qualifiedExpression = loopRange as KtQualifiedExpression?
|
||||
val selector = qualifiedExpression!!.selectorExpression
|
||||
if (selector is KtCallExpression || selector is KtSimpleNameExpression) {
|
||||
return selector.getResolvedCall(bindingContext)
|
||||
}
|
||||
}
|
||||
else if (loopRange is KtSimpleNameExpression || loopRange is KtCallExpression) {
|
||||
return loopRange.getResolvedCall(bindingContext)
|
||||
}
|
||||
else if (loopRange is KtBinaryExpression) {
|
||||
return loopRange.operationReference.getResolvedCall(bindingContext)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.coroutines.COROUTINE_IMPL_ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
@@ -49,7 +48,7 @@ class AnonymousObjectTransformer(
|
||||
val classBuilder = createRemappingClassBuilderViaFactory(inliningContext)
|
||||
val methodsToTransform = ArrayList<MethodNode>()
|
||||
|
||||
createClassReader().accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) {
|
||||
createClassReader().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)
|
||||
if (COROUTINE_IMPL_ASM_TYPE.internalName == superName) {
|
||||
@@ -79,11 +78,11 @@ class AnonymousObjectTransformer(
|
||||
|
||||
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||
addUniqueField(name)
|
||||
if (InlineCodegenUtil.isCapturedFieldName(name)) {
|
||||
return null
|
||||
return if (isCapturedFieldName(name)) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
return classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value)
|
||||
classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,14 +95,14 @@ class AnonymousObjectTransformer(
|
||||
}, ClassReader.SKIP_FRAMES)
|
||||
|
||||
if (!inliningContext.isInliningLambda) {
|
||||
if (debugInfo != null && !debugInfo!!.isEmpty()) {
|
||||
sourceMapper = SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!))
|
||||
sourceMapper = if (debugInfo != null && !debugInfo!!.isEmpty()) {
|
||||
SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!))
|
||||
}
|
||||
else {
|
||||
//seems we can't do any clever mapping cause we don't know any about original class name
|
||||
sourceMapper = IdenticalSourceMapper
|
||||
IdenticalSourceMapper
|
||||
}
|
||||
if (sourceInfo != null && !InlineCodegenUtil.GENERATE_SMAP) {
|
||||
if (sourceInfo != null && !GENERATE_SMAP) {
|
||||
classBuilder.visitSource(sourceInfo!!, debugInfo)
|
||||
}
|
||||
}
|
||||
@@ -139,7 +138,7 @@ class AnonymousObjectTransformer(
|
||||
}
|
||||
|
||||
deferringMethods.forEach { method ->
|
||||
InlineCodegenUtil.removeFinallyMarkers(method.intermediate)
|
||||
removeFinallyMarkers(method.intermediate)
|
||||
method.visitEnd()
|
||||
}
|
||||
|
||||
@@ -286,7 +285,7 @@ class AnonymousObjectTransformer(
|
||||
|
||||
val intermediateMethodNode = MethodNode(constructor!!.access, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY)
|
||||
inlineMethodAndUpdateGlobalResult(parentRemapper, intermediateMethodNode, constructor!!, constructorInlineBuilder, true)
|
||||
InlineCodegenUtil.removeFinallyMarkers(intermediateMethodNode)
|
||||
removeFinallyMarkers(intermediateMethodNode)
|
||||
|
||||
val first = intermediateMethodNode.instructions.first
|
||||
val oldStartLabel = if (first is LabelNode) first.label else null
|
||||
@@ -429,8 +428,8 @@ class AnonymousObjectTransformer(
|
||||
val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper ?:
|
||||
throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}")
|
||||
val ownerType = Type.getObjectType(parent.originalLambdaInternalName)
|
||||
val desc = CapturedParamDesc(ownerType, InlineCodegenUtil.THIS, ownerType)
|
||||
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.`THIS$0`/*outer lambda/object*/, false)
|
||||
val desc = CapturedParamDesc(ownerType, THIS, ownerType)
|
||||
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, THIS_0/*outer lambda/object*/, false)
|
||||
val composed = StackValue.LOCAL_0
|
||||
recapturedParamInfo.remapValue = composed
|
||||
allRecapturedParameters.add(desc)
|
||||
@@ -458,16 +457,16 @@ class AnonymousObjectTransformer(
|
||||
}
|
||||
|
||||
private fun getNewFieldName(oldName: String, originalField: Boolean): String {
|
||||
if (InlineCodegenUtil.`THIS$0` == oldName) {
|
||||
if (!originalField) {
|
||||
return oldName
|
||||
if (THIS_0 == oldName) {
|
||||
return if (!originalField) {
|
||||
oldName
|
||||
}
|
||||
else {
|
||||
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
|
||||
return addUniqueField(oldName + InlineCodegenUtil.INLINE_FUN_THIS_0_SUFFIX)
|
||||
addUniqueField(oldName + INLINE_FUN_THIS_0_SUFFIX)
|
||||
}
|
||||
}
|
||||
return addUniqueField(oldName + InlineCodegenUtil.INLINE_TRANSFORMATION_SUFFIX)
|
||||
return addUniqueField(oldName + INLINE_TRANSFORMATION_SUFFIX)
|
||||
}
|
||||
|
||||
private fun addUniqueField(name: String): String {
|
||||
|
||||
@@ -38,7 +38,7 @@ abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
|
||||
|
||||
open fun processInstruction(curInstr: AbstractInsnNode, directOrder: Boolean) {
|
||||
if (curInstr is VarInsnNode || curInstr is IincInsnNode) {
|
||||
val argSize = InlineCodegenUtil.getLoadStoreArgSize(curInstr.opcode)
|
||||
val argSize = getLoadStoreArgSize(curInstr.opcode)
|
||||
val varIndex = if (curInstr is VarInsnNode) curInstr.`var` else (curInstr as IincInsnNode).`var`
|
||||
nextFreeLocalIndex = Math.max(nextFreeLocalIndex, varIndex + argSize)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
class DeferredMethodVisitor(
|
||||
val intermediate: MethodNode,
|
||||
val resultNode: () -> MethodVisitor
|
||||
) : MethodVisitor(InlineCodegenUtil.API, intermediate) {
|
||||
) : MethodVisitor(API, intermediate) {
|
||||
|
||||
override fun visitEnd() {
|
||||
super.visitEnd()
|
||||
|
||||
@@ -35,7 +35,7 @@ open class FieldRemapper(
|
||||
protected open fun canProcess(fieldOwner: String, fieldName: String, isFolding: Boolean): Boolean {
|
||||
return fieldOwner == originalLambdaInternalName &&
|
||||
//don't process general field of anonymous objects
|
||||
InlineCodegenUtil.isCapturedFieldName(fieldName)
|
||||
isCapturedFieldName(fieldName)
|
||||
}
|
||||
|
||||
fun foldFieldAccessChainIfNeeded(capturedFieldAccess: List<AbstractInsnNode>, node: MethodNode): AbstractInsnNode? =
|
||||
@@ -68,7 +68,7 @@ open class FieldRemapper(
|
||||
|
||||
val insnNode = capturedFieldAccess[currentInstruction] as FieldInsnNode
|
||||
if (canProcess(insnNode.owner, insnNode.name, true)) {
|
||||
insnNode.name = InlineCodegenUtil.CAPTURED_FIELD_FOLD_PREFIX + getFieldNameForFolding(insnNode)
|
||||
insnNode.name = CAPTURED_FIELD_FOLD_PREFIX + getFieldNameForFolding(insnNode)
|
||||
insnNode.opcode = Opcodes.GETSTATIC
|
||||
|
||||
node.remove(InsnSequence(capturedFieldAccess[0], insnNode))
|
||||
|
||||
@@ -25,7 +25,9 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getLoadStoreArgSize;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.API;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getLoadStoreArgSize;
|
||||
|
||||
public class InlineAdapter extends InstructionAdapter {
|
||||
private final SourceMapper sourceMapper;
|
||||
@@ -36,7 +38,7 @@ public class InlineAdapter extends InstructionAdapter {
|
||||
private int nextLocalIndexBeforeInline = -1;
|
||||
|
||||
public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapper sourceMapper) {
|
||||
super(InlineCodegenUtil.API, mv);
|
||||
super(API, mv);
|
||||
this.nextLocalIndex = localsSize;
|
||||
this.sourceMapper = sourceMapper;
|
||||
}
|
||||
@@ -86,7 +88,7 @@ public class InlineAdapter extends InstructionAdapter {
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(int line, @NotNull Label start) {
|
||||
if (InlineCodegenUtil.GENERATE_SMAP) {
|
||||
if (GENERATE_SMAP) {
|
||||
line = sourceMapper.mapLineNumber(line);
|
||||
}
|
||||
//skip not mapped lines
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,704 @@
|
||||
/*
|
||||
* 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.codegen.inline
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
||||
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCoroutineOrReturn
|
||||
import org.jetbrains.kotlin.codegen.coroutines.isBuiltInSuspendCoroutineOrReturnInJvm
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.bytecode
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.classId
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.isInlineOnly
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
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
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.util.*
|
||||
|
||||
abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
protected val codegen: T,
|
||||
protected val state: GenerationState,
|
||||
function: FunctionDescriptor,
|
||||
private val typeParameterMappings: TypeParameterMappings,
|
||||
protected val sourceCompiler: SourceCompilerForInline
|
||||
) {
|
||||
init {
|
||||
assert(InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function)) {
|
||||
"InlineCodegen can inline only inline functions and array constructors: " + function
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement AS_FUNCTION inline strategy
|
||||
private val asFunctionInline = false
|
||||
|
||||
protected val typeMapper = state.typeMapper
|
||||
|
||||
private val initialFrameSize = codegen.frameMap.currentSize
|
||||
|
||||
private val reifiedTypeInliner = ReifiedTypeInliner(typeParameterMappings)
|
||||
|
||||
protected val functionDescriptor: FunctionDescriptor =
|
||||
if (InlineUtil.isArrayConstructorWithLambda(function))
|
||||
FictitiousArrayConstructor.create(function as ConstructorDescriptor)
|
||||
else
|
||||
function.original
|
||||
|
||||
protected val jvmSignature: JvmMethodGenericSignature
|
||||
|
||||
private val isSameModule: Boolean
|
||||
|
||||
protected val invocationParamBuilder = ParametersBuilder.newBuilder()
|
||||
|
||||
protected val expressionMap = linkedMapOf<Int, LambdaInfo>()
|
||||
|
||||
protected var activeLambda: LambdaInfo? = null
|
||||
|
||||
private val defaultSourceMapper = sourceCompiler.lazySourceMapper
|
||||
|
||||
protected var delayedHiddenWriting: Function0<Unit>? = null
|
||||
|
||||
protected val maskValues = ArrayList<Int>()
|
||||
protected var maskStartIndex = -1
|
||||
protected var methodHandleInDefaultMethodIndex = -1
|
||||
|
||||
init {
|
||||
sourceCompiler.initializeInlineFunctionContext(functionDescriptor)
|
||||
jvmSignature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.contextKind)
|
||||
isSameModule = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor)
|
||||
|
||||
if (functionDescriptor !is FictitiousArrayConstructor) {
|
||||
reportIncrementalInfo(functionDescriptor, sourceCompiler.compilationContextFunctionDescriptor.original, jvmSignature, state)
|
||||
val functionOrAccessorName = typeMapper.mapAsmMethod(function).name
|
||||
//track changes for property accessor and @JvmName inline functions/property accessors
|
||||
if (functionOrAccessorName != functionDescriptor.name.asString()) {
|
||||
val scope = getMemberScope(functionDescriptor)
|
||||
//Fake lookup to track track changes for property accessors and @JvmName functions/property accessors
|
||||
scope?.getContributedFunctions(Name.identifier(functionOrAccessorName), sourceCompiler.lookupLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected fun throwCompilationException(
|
||||
nodeAndSmap: SMAPAndMethodNode?, e: Exception, generateNodeText: Boolean
|
||||
): CompilationException {
|
||||
val contextDescriptor = sourceCompiler.compilationContextDescriptor
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor)
|
||||
val node = nodeAndSmap?.node
|
||||
throw CompilationException(
|
||||
"Couldn't inline method call '" + functionDescriptor.name + "' into\n" +
|
||||
DescriptorRenderer.DEBUG_TEXT.render(contextDescriptor) + "\n" +
|
||||
(element?.text ?: "<no source>") +
|
||||
if (generateNodeText) "\nCause: " + node.nodeText else "",
|
||||
e, sourceCompiler.callElement as? PsiElement
|
||||
)
|
||||
}
|
||||
|
||||
protected fun generateStub(resolvedCall: ResolvedCall<*>?, codegen: BaseExpressionCodegen) {
|
||||
leaveTemps()
|
||||
assert(resolvedCall != null)
|
||||
val message = "Call is part of inline cycle: " + resolvedCall!!.call.callElement.text
|
||||
AsmUtil.genThrow(codegen.v, "java/lang/UnsupportedOperationException", message)
|
||||
}
|
||||
|
||||
protected fun endCall(result: InlineResult) {
|
||||
leaveTemps()
|
||||
|
||||
codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages)
|
||||
|
||||
state.factory.removeClasses(result.calcClassesToRemove())
|
||||
|
||||
codegen.markLineNumberAfterInlineIfNeeded()
|
||||
}
|
||||
|
||||
fun performInline(
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
callDefault: Boolean,
|
||||
codegen: BaseExpressionCodegen
|
||||
) {
|
||||
if (!state.inlineCycleReporter.enterIntoInlining(resolvedCall)) {
|
||||
generateStub(resolvedCall, codegen)
|
||||
return
|
||||
}
|
||||
|
||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||
try {
|
||||
nodeAndSmap = createInlineMethodNode(functionDescriptor, jvmSignature, codegen, callDefault, resolvedCall, state, sourceCompiler)
|
||||
endCall(inlineCall(nodeAndSmap, callDefault))
|
||||
}
|
||||
catch (e: CompilationException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: InlineException) {
|
||||
throw throwCompilationException(nodeAndSmap, e, false)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
throw throwCompilationException(nodeAndSmap, e, true)
|
||||
}
|
||||
finally {
|
||||
state.inlineCycleReporter.exitFromInliningOf(resolvedCall)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, callDefault: Boolean): InlineResult {
|
||||
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
|
||||
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
|
||||
val node = nodeAndSmap.node
|
||||
if (callDefault) {
|
||||
val defaultLambdas = expandMaskConditionsAndUpdateVariableNodes(
|
||||
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
|
||||
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor)
|
||||
)
|
||||
for (lambda in defaultLambdas) {
|
||||
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).lambda = lambda
|
||||
val prev = expressionMap.put(lambda.offset, lambda)
|
||||
assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" }
|
||||
}
|
||||
}
|
||||
val reificationResult = reifiedTypeInliner.reifyInstructions(node)
|
||||
generateClosuresBodies()
|
||||
|
||||
//through generation captured parameters will be added to invocationParamBuilder
|
||||
putClosureParametersOnStack()
|
||||
|
||||
addInlineMarker(codegen.v, true)
|
||||
|
||||
val parameters = invocationParamBuilder.buildParameters()
|
||||
|
||||
val info = RootInliningContext(
|
||||
expressionMap, state, codegen.inlineNameGenerator.subGenerator(jvmSignature.asmMethod.name),
|
||||
sourceCompiler, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings
|
||||
)
|
||||
|
||||
val inliner = MethodInliner(
|
||||
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
|
||||
"Method inlining " + sourceCompiler.callElementText,
|
||||
createNestedSourceMapper(nodeAndSmap, defaultSourceMapper), info.callSiteInfo,
|
||||
if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null
|
||||
) //with captured
|
||||
|
||||
val remapper = LocalVarRemapper(parameters, initialFrameSize)
|
||||
|
||||
val adapter = createEmptyMethodNode()
|
||||
//hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain
|
||||
adapter.visitInsn(Opcodes.NOP)
|
||||
|
||||
val result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL)
|
||||
result.reifiedTypeParametersUsages.mergeAll(reificationResult)
|
||||
|
||||
val labels = sourceCompiler.getContextLabels()
|
||||
|
||||
val infos = MethodInliner.processReturns(adapter, LabelOwner { labels.contains(it) }, true, null)
|
||||
sourceCompiler.generateAndInsertFinallyBlocks(
|
||||
adapter, infos, (remapper.remap(parameters.argsSizeOnStack + 1).value as StackValue.Local).index
|
||||
)
|
||||
removeStaticInitializationTrigger(adapter)
|
||||
if (!sourceCompiler.isFinallyMarkerRequired()) {
|
||||
removeFinallyMarkers(adapter)
|
||||
}
|
||||
|
||||
adapter.accept(MethodBodyVisitor(codegen.v))
|
||||
|
||||
addInlineMarker(codegen.v, false)
|
||||
|
||||
defaultSourceMapper.callSiteMarker = null
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun generateClosuresBodies() {
|
||||
for (info in expressionMap.values) {
|
||||
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun putArgumentOrCapturedToLocalVal(
|
||||
type: Type,
|
||||
stackValue: StackValue,
|
||||
capturedParamIndex: Int,
|
||||
parameterIndex: Int,
|
||||
kind: ValueKind
|
||||
) {
|
||||
val isDefaultParameter = kind === ValueKind.DEFAULT_PARAMETER
|
||||
if (!isDefaultParameter && shouldPutGeneralValue(type, stackValue)) {
|
||||
stackValue.put(type, codegen.v)
|
||||
}
|
||||
|
||||
if (!asFunctionInline && Type.VOID_TYPE !== type) {
|
||||
//TODO remap only inlinable closure => otherwise we could get a lot of problem
|
||||
val couldBeRemapped = !shouldPutGeneralValue(type, stackValue) && kind !== ValueKind.DEFAULT_PARAMETER
|
||||
val remappedValue = if (couldBeRemapped) stackValue else null
|
||||
|
||||
val info: ParameterInfo
|
||||
if (capturedParamIndex >= 0) {
|
||||
val capturedParamInfoInLambda = activeLambda!!.capturedVars[capturedParamIndex]
|
||||
info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.fieldName, false)
|
||||
info.setRemapValue(remappedValue)
|
||||
}
|
||||
else {
|
||||
info = invocationParamBuilder.addNextValueParameter(type, false, remappedValue, parameterIndex)
|
||||
}
|
||||
|
||||
recordParameterValueInLocalVal(
|
||||
false,
|
||||
isDefaultParameter || kind === ValueKind.DEFAULT_LAMBDA_CAPTURED_PARAMETER,
|
||||
info
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun recordParameterValueInLocalVal(delayedWritingToLocals: Boolean, skipStore: Boolean, vararg infos: ParameterInfo): Function0<Unit>? {
|
||||
val index = IntArray(infos.size) { i ->
|
||||
if (!infos[i].isSkippedOrRemapped) {
|
||||
codegen.frameMap.enterTemp(infos[i].getType())
|
||||
}
|
||||
else -1
|
||||
}
|
||||
|
||||
val possibleLazyTask = {
|
||||
for (i in infos.indices.reversed()) {
|
||||
val info = infos[i]
|
||||
if (!info.isSkippedOrRemapped) {
|
||||
val type = info.type
|
||||
val local = StackValue.local(index[i], type)
|
||||
if (!skipStore) {
|
||||
local.store(StackValue.onStack(type), codegen.v)
|
||||
}
|
||||
if (info is CapturedParamInfo) {
|
||||
info.setRemapValue(local)
|
||||
info.isSynthetic = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delayedWritingToLocals) return possibleLazyTask
|
||||
possibleLazyTask()
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
private fun leaveTemps() {
|
||||
invocationParamBuilder.listAllParams().asReversed().forEach {
|
||||
param ->
|
||||
if (!param.isSkippedOrRemapped || CapturedParamInfo.isSynthetic(param)) {
|
||||
codegen.frameMap.leaveTemp(param.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun putClosureParametersOnStack() {
|
||||
for (next in expressionMap.values) {
|
||||
//closure parameters for bounded callable references are generated inplace
|
||||
if (next is ExpressionLambda && next.isBoundCallableReference) continue
|
||||
putClosureParametersOnStack(next, null)
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?)
|
||||
|
||||
protected fun rememberCapturedForDefaultLambda(defaultLambda: DefaultLambda) {
|
||||
for ((paramIndex, captured) in defaultLambda.capturedVars.withIndex()) {
|
||||
putArgumentOrCapturedToLocalVal(
|
||||
captured.type,
|
||||
//HACK: actually parameter would be placed on stack in default function
|
||||
// also see ValueKind.DEFAULT_LAMBDA_CAPTURED_PARAMETER check
|
||||
StackValue.onStack(captured.type),
|
||||
paramIndex,
|
||||
paramIndex,
|
||||
ValueKind.DEFAULT_LAMBDA_CAPTURED_PARAMETER
|
||||
)
|
||||
|
||||
defaultLambda.parameterOffsetsInDefault.add(invocationParamBuilder.nextParameterOffset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected fun processDefaultMaskOrMethodHandler(value: StackValue, kind: ValueKind): Boolean {
|
||||
if (kind !== ValueKind.DEFAULT_MASK && kind !== ValueKind.METHOD_HANDLE_IN_DEFAULT) {
|
||||
return false
|
||||
}
|
||||
assert(value is StackValue.Constant) { "Additional default method argument should be constant, but " + value }
|
||||
val constantValue = (value as StackValue.Constant).value
|
||||
if (kind === ValueKind.DEFAULT_MASK) {
|
||||
assert(constantValue is Int) { "Mask should be of Integer type, but " + constantValue }
|
||||
maskValues.add(constantValue as Int)
|
||||
if (maskStartIndex == -1) {
|
||||
maskStartIndex = invocationParamBuilder.listAllParams().sumBy {
|
||||
if (it is CapturedParamInfo) 0 else it.type.size
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(constantValue == null) { "Additional method handle for default argument should be null, but " + constantValue!! }
|
||||
methodHandleInDefaultMethodIndex = maskStartIndex + maskValues.size
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
private fun getMemberScope(functionOrAccessor: FunctionDescriptor): MemberScope? {
|
||||
val callableMemberDescriptor = JvmCodegenUtil.getDirectMember(functionOrAccessor)
|
||||
val classOrPackageFragment = callableMemberDescriptor.containingDeclaration
|
||||
return when (classOrPackageFragment) {
|
||||
is ClassDescriptor -> classOrPackageFragment.unsubstitutedMemberScope
|
||||
is PackageFragmentDescriptor -> classOrPackageFragment.getMemberScope()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun createInlineMethodNode(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
codegen: BaseExpressionCodegen,
|
||||
callDefault: Boolean,
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
state: GenerationState,
|
||||
sourceCompilerForInline: SourceCompilerForInline
|
||||
): SMAPAndMethodNode {
|
||||
if (isSpecialEnumMethod(functionDescriptor)) {
|
||||
val arguments = resolvedCall!!.typeArguments
|
||||
|
||||
val node = createSpecialEnumMethodBody(
|
||||
codegen,
|
||||
functionDescriptor.name.asString(),
|
||||
arguments.keys.single().defaultType,
|
||||
state.typeMapper
|
||||
)
|
||||
return SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1))
|
||||
}
|
||||
else if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm()) {
|
||||
return SMAPAndMethodNode(
|
||||
createMethodNodeForSuspendCoroutineOrReturn(
|
||||
functionDescriptor, state.typeMapper
|
||||
),
|
||||
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
|
||||
)
|
||||
}
|
||||
|
||||
val asmMethod = if (callDefault)
|
||||
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompilerForInline.contextKind)
|
||||
else
|
||||
jvmSignature.asmMethod
|
||||
|
||||
val methodId = MethodId(DescriptorUtils.getFqNameSafe(functionDescriptor.containingDeclaration), asmMethod)
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DeserializedCallableMemberDescriptor) {
|
||||
return sourceCompilerForInline.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
|
||||
}
|
||||
|
||||
val resultInCache = state.inlineCache.methodNodeById.getOrPut(methodId
|
||||
) {
|
||||
doCreateMethodNodeFromCompiled(directMember, state, asmMethod)
|
||||
?: throw IllegalStateException("Couldn't obtain compiled function body for " + functionDescriptor)
|
||||
}
|
||||
|
||||
return resultInCache.copyWithNewNode(cloneMethodNode(resultInCache.node))
|
||||
}
|
||||
|
||||
private fun getDirectMemberAndCallableFromObject(functionDescriptor: FunctionDescriptor): CallableMemberDescriptor {
|
||||
val directMember = JvmCodegenUtil.getDirectMember(functionDescriptor)
|
||||
return (directMember as? ImportedFromObjectCallableDescriptor<*>)?.callableFromObject ?: directMember
|
||||
}
|
||||
|
||||
private fun cloneMethodNode(methodNode: MethodNode): MethodNode {
|
||||
methodNode.instructions.resetLabels()
|
||||
return MethodNode(
|
||||
API, methodNode.access, methodNode.name, methodNode.desc, methodNode.signature,
|
||||
ArrayUtil.toStringArray(methodNode.exceptions)
|
||||
).also(methodNode::accept)
|
||||
}
|
||||
|
||||
private fun doCreateMethodNodeFromCompiled(
|
||||
callableDescriptor: CallableMemberDescriptor,
|
||||
state: GenerationState,
|
||||
asmMethod: Method
|
||||
): SMAPAndMethodNode? {
|
||||
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
|
||||
val classId = classId
|
||||
val bytes = state.inlineCache.classBytes.getOrPut(classId) { bytecode }
|
||||
return getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classId.asString())
|
||||
}
|
||||
|
||||
assert(callableDescriptor is DeserializedCallableMemberDescriptor) { "Not a deserialized function or proper: " + callableDescriptor }
|
||||
|
||||
val containingClasses = state.typeMapper.getContainingClassesForDeserializedCallable(callableDescriptor as DeserializedCallableMemberDescriptor)
|
||||
|
||||
val containerId = containingClasses.implClassId
|
||||
|
||||
val bytes = state.inlineCache.classBytes.getOrPut(containerId) {
|
||||
findVirtualFile(state, containerId)?.contentsToByteArray() ?:
|
||||
throw IllegalStateException("Couldn't find declaration file for " + containerId)
|
||||
}
|
||||
|
||||
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, containerId.asString()) ?: return null
|
||||
|
||||
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
|
||||
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
|
||||
if (isLegacySuspendInlineFunction(callableDescriptor)) {
|
||||
insertLegacySuspendInlineMarks(methodNode.node)
|
||||
}
|
||||
|
||||
return methodNode
|
||||
}
|
||||
|
||||
private fun isBuiltInArrayIntrinsic(callableDescriptor: CallableMemberDescriptor): Boolean {
|
||||
if (callableDescriptor is FictitiousArrayConstructor) return true
|
||||
val name = callableDescriptor.name.asString()
|
||||
return (name == "arrayOf" || name == "emptyArray") && callableDescriptor.containingDeclaration is BuiltInsPackageFragment
|
||||
}
|
||||
|
||||
private fun removeStaticInitializationTrigger(methodNode: MethodNode) {
|
||||
val insnList = methodNode.instructions
|
||||
var insn: AbstractInsnNode? = insnList.first
|
||||
while (insn != null) {
|
||||
if (MultifileClassPartCodegen.isStaticInitTrigger(insn)) {
|
||||
val clinitTriggerCall = insn
|
||||
insn = insn.next
|
||||
insnList.remove(clinitTriggerCall)
|
||||
}
|
||||
else {
|
||||
insn = insn.next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*descriptor is null for captured vars*/
|
||||
private fun shouldPutGeneralValue(type: Type, stackValue: StackValue): Boolean {
|
||||
//remap only inline functions (and maybe non primitives)
|
||||
//TODO - clean asserion and remapping logic
|
||||
if (isPrimitive(type) != isPrimitive(stackValue.type)) {
|
||||
//don't remap boxing/unboxing primitives - lost identity and perfomance
|
||||
return true
|
||||
}
|
||||
|
||||
if (stackValue is StackValue.Local) {
|
||||
return false
|
||||
}
|
||||
|
||||
var field = stackValue
|
||||
if (stackValue is StackValue.FieldForSharedVar) {
|
||||
field = stackValue.receiver
|
||||
}
|
||||
|
||||
//check that value corresponds to captured inlining parameter
|
||||
if (field is StackValue.Field) {
|
||||
val varDescriptor = field.descriptor
|
||||
//check that variable is inline function parameter
|
||||
return !(varDescriptor is ParameterDescriptor &&
|
||||
InlineUtil.isInlineLambdaParameter(varDescriptor) &&
|
||||
InlineUtil.isInline(varDescriptor.containingDeclaration))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescriptor): Set<String> {
|
||||
val result = HashSet<String>()
|
||||
|
||||
if (lambdaOrFun != null) {
|
||||
val label = LabelResolver.getLabelNameIfAny(lambdaOrFun)
|
||||
if (label != null) {
|
||||
result.add(label.asString())
|
||||
}
|
||||
}
|
||||
|
||||
if (!isFunctionLiteral(descriptor)) {
|
||||
if (!descriptor.name.isSpecial) {
|
||||
result.add(descriptor.name.asString())
|
||||
}
|
||||
result.add(FIRST_FUN_LABEL)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
fun createNestedSourceMapper(nodeAndSmap: SMAPAndMethodNode, parent: SourceMapper): SourceMapper {
|
||||
return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo)
|
||||
}
|
||||
|
||||
internal fun reportIncrementalInfo(
|
||||
sourceDescriptor: FunctionDescriptor,
|
||||
targetDescriptor: FunctionDescriptor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
state: GenerationState
|
||||
) {
|
||||
val incrementalCache = state.incrementalCacheForThisTarget ?: return
|
||||
val classFilePath = sourceDescriptor.getClassFilePath(state.typeMapper, incrementalCache)
|
||||
val sourceFilePath = targetDescriptor.sourceFilePath
|
||||
val method = jvmSignature.asmMethod
|
||||
incrementalCache.registerInline(classFilePath, method.name + method.descriptor, sourceFilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val BaseExpressionCodegen.v: InstructionAdapter
|
||||
get() = visitor
|
||||
|
||||
class PsiInlineCodegen(
|
||||
codegen: ExpressionCodegen,
|
||||
state: GenerationState,
|
||||
function: FunctionDescriptor,
|
||||
typeParameterMappings: TypeParameterMappings,
|
||||
sourceCompiler: SourceCompilerForInline
|
||||
) : InlineCodegen<ExpressionCodegen>(codegen, state, function, typeParameterMappings, sourceCompiler), CallGenerator {
|
||||
|
||||
override fun genCallInner(
|
||||
callableMethod: Callable,
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
callDefault: Boolean,
|
||||
codegen: ExpressionCodegen
|
||||
) {
|
||||
performInline(resolvedCall, callDefault, codegen)
|
||||
}
|
||||
|
||||
override fun processAndPutHiddenParameters(justProcess: Boolean) {
|
||||
if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) {
|
||||
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false)
|
||||
}
|
||||
|
||||
for (param in jvmSignature.valueParameters) {
|
||||
if (param.kind == JvmMethodParameterKind.VALUE) {
|
||||
break
|
||||
}
|
||||
invocationParamBuilder.addNextParameter(param.asmType, false)
|
||||
}
|
||||
|
||||
invocationParamBuilder.markValueParametersStart()
|
||||
val hiddenParameters = invocationParamBuilder.buildParameters().parameters
|
||||
|
||||
delayedHiddenWriting = recordParameterValueInLocalVal(justProcess, false, *hiddenParameters.toTypedArray())
|
||||
}
|
||||
|
||||
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
|
||||
activeLambda = next
|
||||
when (next) {
|
||||
is ExpressionLambda -> codegen.pushClosureOnStack(next.classDescriptor, true, this, functionReferenceReceiver)
|
||||
is DefaultLambda -> rememberCapturedForDefaultLambda(next)
|
||||
else -> throw RuntimeException("Unknown lambda: $next")
|
||||
}
|
||||
activeLambda = null
|
||||
}
|
||||
|
||||
|
||||
private fun getBoundCallableReferenceReceiver(
|
||||
argumentExpression: KtExpression
|
||||
): KtExpression? {
|
||||
val deparenthesized = KtPsiUtil.deparenthesize(argumentExpression)
|
||||
if (deparenthesized is KtCallableReferenceExpression) {
|
||||
val receiverExpression = deparenthesized.receiverExpression
|
||||
if (receiverExpression != null) {
|
||||
val lhs = state.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, receiverExpression)
|
||||
if (lhs is DoubleColonLHS.Expression) return receiverExpression
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/*lambda or callable reference*/
|
||||
private fun isInliningParameter(expression: KtExpression, valueParameterDescriptor: ValueParameterDescriptor): Boolean {
|
||||
//TODO deparenthisise typed
|
||||
val deparenthesized = KtPsiUtil.deparenthesize(expression)
|
||||
|
||||
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) && isInlinableParameterExpression(deparenthesized)
|
||||
}
|
||||
|
||||
override fun genValueAndPut(
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
argumentExpression: KtExpression,
|
||||
parameterType: Type,
|
||||
parameterIndex: Int
|
||||
) {
|
||||
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
|
||||
val lambdaInfo = rememberClosure(argumentExpression, parameterType, valueParameterDescriptor)
|
||||
|
||||
val receiver = getBoundCallableReferenceReceiver(argumentExpression)
|
||||
if (receiver != null) {
|
||||
val receiverValue = codegen.gen(receiver)
|
||||
putClosureParametersOnStack(lambdaInfo, StackValue.coercion(receiverValue, receiverValue.type.boxReceiverForBoundReference()))
|
||||
}
|
||||
}
|
||||
else {
|
||||
val value = codegen.gen(argumentExpression)
|
||||
putValueIfNeeded(parameterType, value, ValueKind.GENERAL, valueParameterDescriptor.index)
|
||||
}
|
||||
}
|
||||
|
||||
private fun rememberClosure(expression: KtExpression, type: Type, parameter: ValueParameterDescriptor): LambdaInfo {
|
||||
val ktLambda = KtPsiUtil.deparenthesize(expression)
|
||||
assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
|
||||
|
||||
return ExpressionLambda(
|
||||
ktLambda!!, typeMapper, parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
|
||||
).also { lambda ->
|
||||
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
|
||||
closureInfo.lambda = lambda
|
||||
expressionMap.put(closureInfo.index, lambda)
|
||||
}
|
||||
}
|
||||
|
||||
override fun putValueIfNeeded(parameterType: Type, value: StackValue, kind: ValueKind, parameterIndex: Int) {
|
||||
if (processDefaultMaskOrMethodHandler(value, kind)) return
|
||||
|
||||
assert(maskValues.isEmpty()) { "Additional default call arguments should be last ones, but " + value }
|
||||
|
||||
putArgumentOrCapturedToLocalVal(parameterType, value, -1, parameterIndex, kind)
|
||||
}
|
||||
|
||||
override fun putCapturedValueOnStack(stackValue: StackValue, valueType: Type, paramIndex: Int) {
|
||||
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex, ValueKind.CAPTURED)
|
||||
}
|
||||
|
||||
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) = Unit
|
||||
|
||||
override fun putHiddenParamsIntoLocals() {
|
||||
assert(delayedHiddenWriting != null) { "processAndPutHiddenParameters(true) should be called before putHiddenParamsIntoLocals" }
|
||||
delayedHiddenWriting!!.invoke()
|
||||
delayedHiddenWriting = null
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,9 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
@@ -33,8 +32,9 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
class InlineCodegenForDefaultBody(
|
||||
function: FunctionDescriptor,
|
||||
codegen: ExpressionCodegen,
|
||||
val state: GenerationState
|
||||
) : CallGenerator() {
|
||||
val state: GenerationState,
|
||||
private val sourceCompilerForInline: SourceCompilerForInline
|
||||
) : CallGenerator {
|
||||
|
||||
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
|
||||
|
||||
@@ -45,12 +45,12 @@ class InlineCodegenForDefaultBody(
|
||||
function.original
|
||||
|
||||
|
||||
private val context = InlineCodegen.getContext(
|
||||
functionDescriptor, state,
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile
|
||||
)
|
||||
init {
|
||||
sourceCompilerForInline.initializeInlineFunctionContext(functionDescriptor)
|
||||
}
|
||||
|
||||
private val jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, context.contextKind)
|
||||
|
||||
private val jvmSignature: JvmMethodGenericSignature
|
||||
|
||||
private val methodStartLabel = Label()
|
||||
|
||||
@@ -58,6 +58,9 @@ class InlineCodegenForDefaultBody(
|
||||
assert(InlineUtil.isInline(function)) {
|
||||
"InlineCodegen can inline only inline functions and array constructors: " + function
|
||||
}
|
||||
sourceCompilerForInline.initializeInlineFunctionContext(functionDescriptor)
|
||||
jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompilerForInline.contextKind)
|
||||
|
||||
InlineCodegen.reportIncrementalInfo(functionDescriptor, codegen.context.functionDescriptor.original, jvmSignature, state)
|
||||
|
||||
//InlineCodegenForDefaultBody created just after visitCode call
|
||||
@@ -65,7 +68,7 @@ class InlineCodegenForDefaultBody(
|
||||
}
|
||||
|
||||
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
|
||||
val nodeAndSmap = InlineCodegen.createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, null)
|
||||
val nodeAndSmap = InlineCodegen.createInlineMethodNode(functionDescriptor, jvmSignature, codegen, callDefault, null, state, sourceCompilerForInline)
|
||||
val childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper)
|
||||
|
||||
val node = nodeAndSmap.node
|
||||
@@ -84,7 +87,7 @@ class InlineCodegenForDefaultBody(
|
||||
}
|
||||
})
|
||||
|
||||
transformedMethod.accept(MethodBodyVisitor(codegen.v))
|
||||
transformedMethod.accept(MethodBodyVisitor(codegen.visitor))
|
||||
}
|
||||
|
||||
override fun genValueAndPut(valueParameterDescriptor: ValueParameterDescriptor, argumentExpression: KtExpression, parameterType: Type, parameterIndex: Int) {
|
||||
|
||||
@@ -1,593 +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.codegen.inline;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil;
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.kotlin.codegen.MemberCodegen;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
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.intrinsics.IntrinsicArrayConstructorsKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.tree.*;
|
||||
import org.jetbrains.org.objectweb.asm.util.Printer;
|
||||
import org.jetbrains.org.objectweb.asm.util.Textifier;
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.ENUM_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_CLASS_TYPE;
|
||||
|
||||
public class InlineCodegenUtil {
|
||||
public static final boolean GENERATE_SMAP = true;
|
||||
public static final int API = Opcodes.ASM5;
|
||||
|
||||
private static final String CAPTURED_FIELD_PREFIX = "$";
|
||||
private static final String NON_CAPTURED_FIELD_PREFIX = "$$";
|
||||
public static final String THIS$0 = "this$0";
|
||||
public static final String THIS = "this";
|
||||
private static final String RECEIVER$0 = "receiver$0";
|
||||
private static final String NON_LOCAL_RETURN = "$$$$$NON_LOCAL_RETURN$$$$$";
|
||||
public static final String FIRST_FUN_LABEL = "$$$$$ROOT$$$$$";
|
||||
public static final String NUMBERED_FUNCTION_PREFIX = "kotlin/jvm/functions/Function";
|
||||
private static final String INLINE_MARKER_CLASS_NAME = "kotlin/jvm/internal/InlineMarker";
|
||||
private static final String INLINE_MARKER_BEFORE_METHOD_NAME = "beforeInlineCall";
|
||||
private static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall";
|
||||
private static final String INLINE_MARKER_FINALLY_START = "finallyStart";
|
||||
private static final String INLINE_MARKER_FINALLY_END = "finallyEnd";
|
||||
public static final String SPECIAL_TRANSFORMATION_NAME = "$special";
|
||||
public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined";
|
||||
public static final String INLINE_CALL_TRANSFORMATION_SUFFIX = "$" + INLINE_TRANSFORMATION_SUFFIX;
|
||||
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
|
||||
public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
|
||||
|
||||
public static final String DEFAULT_LAMBDA_FAKE_CALL = "$$$DEFAULT_LAMBDA_FAKE_CALL$$$";
|
||||
public static final String CAPTURED_FIELD_FOLD_PREFIX = "$$$";
|
||||
|
||||
@Nullable
|
||||
public static SMAPAndMethodNode getMethodNode(
|
||||
byte[] classData,
|
||||
@NotNull String methodName,
|
||||
@NotNull String methodDescriptor,
|
||||
@NotNull String classInternalName
|
||||
) {
|
||||
ClassReader cr = new ClassReader(classData);
|
||||
MethodNode[] node = new MethodNode[1];
|
||||
String[] debugInfo = new String[2];
|
||||
int[] lines = new int[2];
|
||||
lines[0] = Integer.MAX_VALUE;
|
||||
lines[1] = Integer.MIN_VALUE;
|
||||
//noinspection PointlessBitwiseExpression
|
||||
cr.accept(new ClassVisitor(API) {
|
||||
|
||||
@Override
|
||||
public void visitSource(String source, String debug) {
|
||||
super.visitSource(source, debug);
|
||||
debugInfo[0] = source;
|
||||
debugInfo[1] = debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
String signature,
|
||||
String[] exceptions
|
||||
) {
|
||||
if (methodName.equals(name) && methodDescriptor.equals(desc)) {
|
||||
node[0] = new MethodNode(API, access, name, desc, signature, exceptions) {
|
||||
@Override
|
||||
public void visitLineNumber(int line, @NotNull Label start) {
|
||||
super.visitLineNumber(line, start);
|
||||
lines[0] = Math.min(lines[0], line);
|
||||
lines[1] = Math.max(lines[1], line);
|
||||
}
|
||||
};
|
||||
return node[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));
|
||||
|
||||
if (node[0] == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (IntrinsicArrayConstructorsKt.getClassId().asString().equals(classInternalName)) {
|
||||
// Don't load source map for intrinsic array constructors
|
||||
debugInfo[0] = null;
|
||||
}
|
||||
|
||||
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classInternalName, lines[0], lines[1]);
|
||||
return new SMAPAndMethodNode(node[0], smap);
|
||||
}
|
||||
|
||||
public static void initDefaultSourceMappingIfNeeded(
|
||||
@NotNull CodegenContext context, @NotNull MemberCodegen codegen, @NotNull GenerationState state
|
||||
) {
|
||||
if (state.isInlineDisabled()) return;
|
||||
|
||||
CodegenContext<?> parentContext = context.getParentContext();
|
||||
while (parentContext != null) {
|
||||
if (parentContext.isInlineMethodContext()) {
|
||||
//just init default one to one mapping
|
||||
codegen.getOrCreateSourceMapper();
|
||||
break;
|
||||
}
|
||||
parentContext = parentContext.getParentContext();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile findVirtualFile(@NotNull GenerationState state, @NotNull ClassId classId) {
|
||||
return VirtualFileFinder.SERVICE.getInstance(state.getProject()).findVirtualFileWithHeader(classId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile findVirtualFileImprecise(@NotNull GenerationState state, @NotNull String internalClassName) {
|
||||
FqName packageFqName = JvmClassName.byInternalName(internalClassName).getPackageFqName();
|
||||
String classNameWithDollars = StringsKt.substringAfterLast(internalClassName, "/", internalClassName);
|
||||
//TODO: we cannot construct proper classId at this point, we need to read InnerClasses info from class file
|
||||
// we construct valid.package.name/RelativeClassNameAsSingleName that should work in compiler, but fails for inner classes in IDE
|
||||
return findVirtualFile(state, new ClassId(packageFqName, Name.identifier(classNameWithDollars)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getInlineName(
|
||||
@NotNull CodegenContext codegenContext,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull JvmFileClassesProvider fileClassesManager
|
||||
) {
|
||||
return getInlineName(codegenContext, codegenContext.getContextDescriptor(), typeMapper, fileClassesManager);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getInlineName(
|
||||
@NotNull CodegenContext codegenContext,
|
||||
@NotNull DeclarationDescriptor currentDescriptor,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull JvmFileClassesProvider fileClassesProvider
|
||||
) {
|
||||
if (currentDescriptor instanceof PackageFragmentDescriptor) {
|
||||
PsiFile file = DescriptorToSourceUtils.getContainingFile(codegenContext.getContextDescriptor());
|
||||
|
||||
Type implementationOwnerType;
|
||||
if (file == null) {
|
||||
implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(codegenContext);
|
||||
}
|
||||
else {
|
||||
implementationOwnerType = FileClasses.getFileClassType(fileClassesProvider, (KtFile) file);
|
||||
}
|
||||
|
||||
if (implementationOwnerType == null) {
|
||||
DeclarationDescriptor contextDescriptor = codegenContext.getContextDescriptor();
|
||||
//noinspection ConstantConditions
|
||||
throw new RuntimeException(
|
||||
"Couldn't find declaration for " +
|
||||
contextDescriptor.getContainingDeclaration().getName() + "." + contextDescriptor.getName() +
|
||||
"; context: " + codegenContext
|
||||
);
|
||||
}
|
||||
|
||||
return implementationOwnerType.getInternalName();
|
||||
}
|
||||
else if (currentDescriptor instanceof ClassifierDescriptor) {
|
||||
Type type = typeMapper.mapType((ClassifierDescriptor) currentDescriptor);
|
||||
return type.getInternalName();
|
||||
}
|
||||
else if (currentDescriptor instanceof FunctionDescriptor) {
|
||||
ClassDescriptor descriptor =
|
||||
typeMapper.getBindingContext().get(CodegenBinding.CLASS_FOR_CALLABLE, (FunctionDescriptor) currentDescriptor);
|
||||
if (descriptor != null) {
|
||||
return typeMapper.mapType(descriptor).getInternalName();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: add suffix for special case
|
||||
String suffix = currentDescriptor.getName().isSpecial() ? "" : currentDescriptor.getName().asString();
|
||||
|
||||
//noinspection ConstantConditions
|
||||
return getInlineName(codegenContext, currentDescriptor.getContainingDeclaration(), typeMapper, fileClassesProvider) + "$" + suffix;
|
||||
}
|
||||
|
||||
public static boolean isInvokeOnLambda(@NotNull String owner, @NotNull String name) {
|
||||
return OperatorNameConventions.INVOKE.asString().equals(name) &&
|
||||
owner.startsWith(NUMBERED_FUNCTION_PREFIX) &&
|
||||
isInteger(owner.substring(NUMBERED_FUNCTION_PREFIX.length()));
|
||||
}
|
||||
|
||||
public static boolean isAnonymousConstructorCall(@NotNull String internalName, @NotNull String methodName) {
|
||||
return "<init>".equals(methodName) && isAnonymousClass(internalName);
|
||||
}
|
||||
|
||||
public static boolean isWhenMappingAccess(@NotNull String internalName, @NotNull String fieldName) {
|
||||
return fieldName.startsWith(WhenByEnumsMapping.MAPPING_ARRAY_FIELD_PREFIX) &&
|
||||
internalName.endsWith(WhenByEnumsMapping.MAPPINGS_CLASS_NAME_POSTFIX);
|
||||
}
|
||||
|
||||
public static boolean isAnonymousSingletonLoad(@NotNull String internalName, @NotNull String fieldName) {
|
||||
return JvmAbi.INSTANCE_FIELD.equals(fieldName) && isAnonymousClass(internalName);
|
||||
}
|
||||
|
||||
public static boolean isAnonymousClass(@NotNull String internalName) {
|
||||
String shortName = getLastNamePart(internalName);
|
||||
int index = shortName.lastIndexOf("$");
|
||||
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String suffix = shortName.substring(index + 1);
|
||||
return isInteger(suffix);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getLastNamePart(@NotNull String internalName) {
|
||||
int index = internalName.lastIndexOf("/");
|
||||
return index < 0 ? internalName : internalName.substring(index + 1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static MethodVisitor wrapWithMaxLocalCalc(@NotNull MethodNode methodNode) {
|
||||
return new MaxStackFrameSizeAndLocalsCalculator(API, methodNode.access, methodNode.desc, methodNode);
|
||||
}
|
||||
|
||||
private static boolean isInteger(@NotNull String string) {
|
||||
if (string.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < string.length(); i++) {
|
||||
if (!Character.isDigit(string.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isCapturedFieldName(@NotNull String fieldName) {
|
||||
// TODO: improve this heuristic
|
||||
return fieldName.startsWith(CAPTURED_FIELD_PREFIX) &&
|
||||
!fieldName.startsWith(NON_CAPTURED_FIELD_PREFIX) ||
|
||||
THIS$0.equals(fieldName) ||
|
||||
RECEIVER$0.equals(fieldName);
|
||||
}
|
||||
|
||||
public static boolean isReturnOpcode(int opcode) {
|
||||
return opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN;
|
||||
}
|
||||
|
||||
//marked return could be either non-local or local in case of labeled lambda self-returns
|
||||
public static boolean isMarkedReturn(@NotNull AbstractInsnNode returnIns) {
|
||||
return getMarkedReturnLabelOrNull(returnIns) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getMarkedReturnLabelOrNull(@NotNull AbstractInsnNode returnInsn) {
|
||||
if (!isReturnOpcode(returnInsn.getOpcode())) {
|
||||
return null;
|
||||
}
|
||||
AbstractInsnNode previous = returnInsn.getPrevious();
|
||||
if (previous instanceof MethodInsnNode) {
|
||||
MethodInsnNode marker = (MethodInsnNode) previous;
|
||||
if (NON_LOCAL_RETURN.equals(marker.owner)) {
|
||||
return marker.name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void generateGlobalReturnFlag(@NotNull InstructionAdapter iv, @NotNull String labelName) {
|
||||
iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type getReturnType(int opcode) {
|
||||
switch (opcode) {
|
||||
case Opcodes.RETURN:
|
||||
return Type.VOID_TYPE;
|
||||
case Opcodes.IRETURN:
|
||||
return Type.INT_TYPE;
|
||||
case Opcodes.DRETURN:
|
||||
return Type.DOUBLE_TYPE;
|
||||
case Opcodes.FRETURN:
|
||||
return Type.FLOAT_TYPE;
|
||||
case Opcodes.LRETURN:
|
||||
return Type.LONG_TYPE;
|
||||
default:
|
||||
return AsmTypes.OBJECT_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) {
|
||||
ListIterator<AbstractInsnNode> iterator = from.instructions.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
AbstractInsnNode next = iterator.next();
|
||||
to.instructions.insertBefore(beforeNode, next);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static MethodNode createEmptyMethodNode() {
|
||||
return new MethodNode(API, 0, "fake", "()V", null, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LabelNode firstLabelInChain(@NotNull LabelNode node) {
|
||||
LabelNode curNode = node;
|
||||
while (curNode.getPrevious() instanceof LabelNode) {
|
||||
curNode = (LabelNode) curNode.getPrevious();
|
||||
}
|
||||
return curNode;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getNodeText(@Nullable MethodNode node) {
|
||||
Textifier textifier = new Textifier();
|
||||
if (node == null) {
|
||||
return "Not generated";
|
||||
}
|
||||
node.accept(new TraceMethodVisitor(textifier));
|
||||
StringWriter sw = new StringWriter();
|
||||
textifier.print(new PrintWriter(sw));
|
||||
sw.flush();
|
||||
return node.name + " " + node.desc + ":\n" + sw.getBuffer().toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getInsnText(@Nullable AbstractInsnNode node) {
|
||||
if (node == null) return "<null>";
|
||||
Textifier textifier = new Textifier();
|
||||
node.accept(new TraceMethodVisitor(textifier));
|
||||
StringWriter sw = new StringWriter();
|
||||
textifier.print(new PrintWriter(sw));
|
||||
sw.flush();
|
||||
return sw.toString().trim();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getInsnOpcodeText(@Nullable AbstractInsnNode node) {
|
||||
return node == null ? "null" : Printer.OPCODES[node.getOpcode()];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/* package */ static ClassReader buildClassReaderByInternalName(@NotNull GenerationState state, @NotNull String internalName) {
|
||||
//try to find just compiled classes then in dependencies
|
||||
try {
|
||||
OutputFile outputFile = state.getFactory().get(internalName + ".class");
|
||||
if (outputFile != null) {
|
||||
return new ClassReader(outputFile.asByteArray());
|
||||
}
|
||||
VirtualFile file = findVirtualFileImprecise(state, internalName);
|
||||
if (file != null) {
|
||||
return new ClassReader(file.contentsToByteArray());
|
||||
}
|
||||
throw new RuntimeException("Couldn't find virtual file for " + internalName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void generateFinallyMarker(@NotNull InstructionAdapter v, int depth, boolean start) {
|
||||
v.iconst(depth);
|
||||
v.invokestatic(INLINE_MARKER_CLASS_NAME, start ? INLINE_MARKER_FINALLY_START : INLINE_MARKER_FINALLY_END, "(I)V", false);
|
||||
}
|
||||
|
||||
public static boolean isFinallyEnd(@NotNull AbstractInsnNode node) {
|
||||
return isFinallyMarker(node, INLINE_MARKER_FINALLY_END);
|
||||
}
|
||||
|
||||
public static boolean isFinallyStart(@NotNull AbstractInsnNode node) {
|
||||
return isFinallyMarker(node, INLINE_MARKER_FINALLY_START);
|
||||
}
|
||||
|
||||
public static boolean isFinallyMarker(@Nullable AbstractInsnNode node) {
|
||||
return node != null && (isFinallyStart(node) || isFinallyEnd(node));
|
||||
}
|
||||
|
||||
private static boolean isFinallyMarker(@NotNull AbstractInsnNode node, String name) {
|
||||
if (!(node instanceof MethodInsnNode)) return false;
|
||||
MethodInsnNode method = (MethodInsnNode) node;
|
||||
return INLINE_MARKER_CLASS_NAME.equals(method.owner) && name.equals(method.name);
|
||||
}
|
||||
|
||||
public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) {
|
||||
return context.isInlineMethodContext() || context instanceof InlineLambdaContext;
|
||||
}
|
||||
|
||||
public static int getConstant(@NotNull AbstractInsnNode ins) {
|
||||
int opcode = ins.getOpcode();
|
||||
if (opcode >= Opcodes.ICONST_0 && opcode <= Opcodes.ICONST_5) {
|
||||
return opcode - Opcodes.ICONST_0;
|
||||
}
|
||||
else if (opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH) {
|
||||
return ((IntInsnNode) ins).operand;
|
||||
}
|
||||
else {
|
||||
LdcInsnNode index = (LdcInsnNode) ins;
|
||||
return (Integer) index.cst;
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeFinallyMarkers(@NotNull MethodNode intoNode) {
|
||||
InsnList instructions = intoNode.instructions;
|
||||
AbstractInsnNode curInstr = instructions.getFirst();
|
||||
while (curInstr != null) {
|
||||
if (isFinallyMarker(curInstr)) {
|
||||
AbstractInsnNode marker = curInstr;
|
||||
//just to assert
|
||||
getConstant(marker.getPrevious());
|
||||
curInstr = curInstr.getNext();
|
||||
instructions.remove(marker.getPrevious());
|
||||
instructions.remove(marker);
|
||||
continue;
|
||||
}
|
||||
curInstr = curInstr.getNext();
|
||||
}
|
||||
}
|
||||
|
||||
public static void addInlineMarker(@NotNull InstructionAdapter v, boolean isStartNotEnd) {
|
||||
v.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,
|
||||
isStartNotEnd ? INLINE_MARKER_BEFORE_METHOD_NAME : INLINE_MARKER_AFTER_METHOD_NAME,
|
||||
"()V", false
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean isInlineMarker(@NotNull AbstractInsnNode insn) {
|
||||
return isInlineMarker(insn, null);
|
||||
}
|
||||
|
||||
private static boolean isInlineMarker(@NotNull AbstractInsnNode insn, @Nullable String name) {
|
||||
if (!(insn instanceof MethodInsnNode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
|
||||
return insn.getOpcode() == Opcodes.INVOKESTATIC &&
|
||||
methodInsnNode.owner.equals(INLINE_MARKER_CLASS_NAME) &&
|
||||
(name != null ? methodInsnNode.name.equals(name)
|
||||
: methodInsnNode.name.equals(INLINE_MARKER_BEFORE_METHOD_NAME) ||
|
||||
methodInsnNode.name.equals(INLINE_MARKER_AFTER_METHOD_NAME));
|
||||
}
|
||||
|
||||
public static boolean isBeforeInlineMarker(@NotNull AbstractInsnNode insn) {
|
||||
return isInlineMarker(insn, INLINE_MARKER_BEFORE_METHOD_NAME);
|
||||
}
|
||||
|
||||
public static boolean isAfterInlineMarker(@NotNull AbstractInsnNode insn) {
|
||||
return isInlineMarker(insn, INLINE_MARKER_AFTER_METHOD_NAME);
|
||||
}
|
||||
|
||||
public static int getLoadStoreArgSize(int opcode) {
|
||||
return opcode == Opcodes.DSTORE || opcode == Opcodes.LSTORE || opcode == Opcodes.DLOAD || opcode == Opcodes.LLOAD ? 2 : 1;
|
||||
}
|
||||
|
||||
public static boolean isStoreInstruction(int opcode) {
|
||||
return opcode >= Opcodes.ISTORE && opcode <= Opcodes.ASTORE;
|
||||
}
|
||||
|
||||
public static int calcMarkerShift(@NotNull Parameters parameters, @NotNull MethodNode node) {
|
||||
int markerShiftTemp = getIndexAfterLastMarker(node);
|
||||
return markerShiftTemp - parameters.getRealParametersSizeOnStack() + parameters.getArgsSizeOnStack();
|
||||
}
|
||||
|
||||
private static int getIndexAfterLastMarker(@NotNull MethodNode node) {
|
||||
int result = -1;
|
||||
for (LocalVariableNode variable : node.localVariables) {
|
||||
if (isFakeLocalVariableForInline(variable.name)) {
|
||||
result = Math.max(result, variable.index + 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isFakeLocalVariableForInline(@NotNull String name) {
|
||||
return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) ||
|
||||
name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT);
|
||||
}
|
||||
|
||||
public static boolean isThis0(@NotNull String name) {
|
||||
return THIS$0.equals(name);
|
||||
}
|
||||
|
||||
public static boolean isSpecialEnumMethod(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||
if (!(containingDeclaration instanceof PackageFragmentDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
if (!((PackageFragmentDescriptor) containingDeclaration).getFqName().equals(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)) {
|
||||
return false;
|
||||
}
|
||||
if (functionDescriptor.getTypeParameters().size() != 1) {
|
||||
return false;
|
||||
}
|
||||
String name = functionDescriptor.getName().asString();
|
||||
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
|
||||
return "enumValues".equals(name) && parameters.size() == 0 ||
|
||||
"enumValueOf".equals(name) && parameters.size() == 1 && KotlinBuiltIns.isString(parameters.get(0).getType());
|
||||
}
|
||||
|
||||
public static MethodNode createSpecialEnumMethodBody(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull String name,
|
||||
@NotNull KotlinType type,
|
||||
@NotNull KotlinTypeMapper typeMapper
|
||||
) {
|
||||
boolean isValueOf = "enumValueOf".equals(name);
|
||||
Type invokeType = typeMapper.mapType(type);
|
||||
String desc = getSpecialEnumFunDescriptor(invokeType, isValueOf);
|
||||
MethodNode node = new MethodNode(API, Opcodes.ACC_STATIC, "fake", desc, null, null);
|
||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.ENUM_REIFIED, new InstructionAdapter(node));
|
||||
if (isValueOf) {
|
||||
node.visitInsn(Opcodes.ACONST_NULL);
|
||||
node.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
|
||||
node.visitMethodInsn(Opcodes.INVOKESTATIC, ENUM_TYPE.getInternalName(), "valueOf",
|
||||
Type.getMethodDescriptor(ENUM_TYPE, JAVA_CLASS_TYPE, AsmTypes.JAVA_STRING_TYPE), false);
|
||||
}
|
||||
else {
|
||||
node.visitInsn(Opcodes.ICONST_0);
|
||||
node.visitTypeInsn(Opcodes.ANEWARRAY, ENUM_TYPE.getInternalName());
|
||||
}
|
||||
node.visitInsn(Opcodes.ARETURN);
|
||||
node.visitMaxs(isValueOf ? 3 : 2, isValueOf ? 1 : 0);
|
||||
return node;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getSpecialEnumFunDescriptor(@NotNull Type type, boolean isValueOf) {
|
||||
return isValueOf ? Type.getMethodDescriptor(type, AsmTypes.JAVA_STRING_TYPE) : Type.getMethodDescriptor(AsmUtil.getArrayType(type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class RootInliningContext(
|
||||
expressionMap: Map<Int, LambdaInfo>,
|
||||
state: GenerationState,
|
||||
nameGenerator: NameGenerator,
|
||||
val callElement: KtElement,
|
||||
val sourceCompilerForInline: SourceCompilerForInline,
|
||||
override val callSiteInfo: InlineCallSiteInfo,
|
||||
val inlineMethodReifier: ReifiedTypeInliner,
|
||||
typeParameterMappings: TypeParameterMappings
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ReadOnly;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
@@ -34,7 +33,7 @@ import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.MethodInlinerUtilKt.getNextMeaningful;
|
||||
|
||||
public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
@@ -106,7 +105,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
|
||||
private int initAndGetVarIndexForNonLocalReturnValue() {
|
||||
MaxLocalsCalculator tempCalcNode = new MaxLocalsCalculator(
|
||||
InlineCodegenUtil.API,
|
||||
API,
|
||||
inlineFun.access, inlineFun.desc, null
|
||||
);
|
||||
inlineFun.accept(tempCalcNode);
|
||||
@@ -126,8 +125,8 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
processInstruction(curIns, false);
|
||||
|
||||
//At this point only global return is possible, local one already substituted with: goto endLabel
|
||||
if (!InlineCodegenUtil.isReturnOpcode(curIns.getOpcode()) ||
|
||||
!InlineCodegenUtil.isMarkedReturn(curIns)) {
|
||||
if (!isReturnOpcode(curIns.getOpcode()) ||
|
||||
!isMarkedReturn(curIns)) {
|
||||
curIns = curIns.getPrevious();
|
||||
continue;
|
||||
}
|
||||
@@ -147,7 +146,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
AbstractInsnNode nextPrev = instrInsertFinallyBefore.getPrevious();
|
||||
assert markedReturn.getNext() instanceof LabelNode : "Label should be occurred after non-local return";
|
||||
LabelNode newFinallyEnd = (LabelNode) markedReturn.getNext();
|
||||
Type nonLocalReturnType = InlineCodegenUtil.getReturnType(markedReturn.getOpcode());
|
||||
Type nonLocalReturnType = getReturnType(markedReturn.getOpcode());
|
||||
|
||||
//Generally there could be several tryCatch blocks (group) on one code interval (same start and end labels, but maybe different handlers) -
|
||||
// all of them refer to one try/*catches*/finally or try/catches.
|
||||
@@ -216,7 +215,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
finallyBlockCopy.visitLabel(insertedBlockEnd);
|
||||
|
||||
//Copying finally body before non-local return instruction
|
||||
InlineCodegenUtil.insertNodeBefore(finallyBlockCopy, inlineFun, instrInsertFinallyBefore);
|
||||
insertNodeBefore(finallyBlockCopy, inlineFun, instrInsertFinallyBefore);
|
||||
|
||||
updateExceptionTable(clusterBlocks, newFinallyStart, newFinallyEnd,
|
||||
tryCatchBlockInlinedInFinally, labelsInsideFinally, (LabelNode) insertedBlockEnd.info);
|
||||
@@ -251,7 +250,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
int depthShift
|
||||
) {
|
||||
if (isInsOrJumpInsideFinally) {
|
||||
if (InlineCodegenUtil.isFinallyMarker(currentIns.getNext())) {
|
||||
if (isFinallyMarker(currentIns.getNext())) {
|
||||
Integer constant = getConstant(currentIns);
|
||||
finallyBlockCopy.visitLdcInsn(constant + depthShift);
|
||||
} else {
|
||||
@@ -455,7 +454,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
AbstractInsnNode current = meaningful.getNext();
|
||||
while (endFinallyChainExclusive != current) {
|
||||
current = current.getNext();
|
||||
if (InlineCodegenUtil.isFinallyEnd(current)) {
|
||||
if (isFinallyEnd(current)) {
|
||||
Integer currentDepth = getConstant(current.getPrevious());
|
||||
if (currentDepth.equals(finallyDepth)) {
|
||||
endFinallyChainExclusive = current.getNext();
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
|
||||
|
||||
lateinit var node: SMAPAndMethodNode
|
||||
|
||||
abstract fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner)
|
||||
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner)
|
||||
|
||||
fun addAllParameters(remapper: FieldRemapper): Parameters {
|
||||
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this)
|
||||
@@ -105,11 +105,14 @@ class DefaultLambda(
|
||||
|
||||
override fun isMyLabel(name: String): Boolean = false
|
||||
|
||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val classReader = InlineCodegenUtil.buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
|
||||
var originalBoundReceiverType: Type? = null
|
||||
private set
|
||||
|
||||
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val classReader = buildClassReaderByInternalName(sourceCompiler.state, lambdaClassType.internalName)
|
||||
var isPropertyReference = false
|
||||
var isFunctionReference = false
|
||||
classReader.accept(object: ClassVisitor(InlineCodegenUtil.API){
|
||||
classReader.accept(object: ClassVisitor(API){
|
||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array<out String>?) {
|
||||
isPropertyReference = superName?.startsWith("kotlin/jvm/internal/PropertyReference") ?: false
|
||||
isFunctionReference = "kotlin/jvm/internal/FunctionReference" == superName
|
||||
@@ -128,7 +131,7 @@ class DefaultLambda(
|
||||
}
|
||||
|
||||
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
|
||||
val constructor = InlineCodegenUtil.getMethodNode(
|
||||
val constructor = getMethodNode(
|
||||
classReader.b,
|
||||
"<init>",
|
||||
descriptor,
|
||||
@@ -141,7 +144,8 @@ class DefaultLambda(
|
||||
capturedVars =
|
||||
if (isFunctionReference || isPropertyReference)
|
||||
constructor?.desc?.let { Type.getArgumentTypes(it) }?.singleOrNull()?.let {
|
||||
listOf(capturedParamDesc(AsmUtil.RECEIVER_NAME, it))
|
||||
originalBoundReceiverType = it
|
||||
listOf(capturedParamDesc(AsmUtil.RECEIVER_NAME, it.boxReceiverForBoundReference()))
|
||||
} ?: emptyList()
|
||||
else
|
||||
constructor?.findCapturedFieldAssignmentInstructions()?.map {
|
||||
@@ -153,10 +157,10 @@ class DefaultLambda(
|
||||
|
||||
invokeMethod = Method(
|
||||
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
|
||||
codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
||||
sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
||||
)
|
||||
|
||||
node = InlineCodegenUtil.getMethodNode(
|
||||
node = getMethodNode(
|
||||
classReader.b,
|
||||
invokeMethod.name,
|
||||
invokeMethod.descriptor,
|
||||
@@ -169,6 +173,9 @@ class DefaultLambda(
|
||||
}
|
||||
}
|
||||
|
||||
fun Type.boxReceiverForBoundReference() = AsmUtil.boxType(this)
|
||||
|
||||
|
||||
class ExpressionLambda(
|
||||
expression: KtExpression,
|
||||
private val typeMapper: KotlinTypeMapper,
|
||||
@@ -237,7 +244,9 @@ class ExpressionLambda(
|
||||
}
|
||||
|
||||
if (closure.captureReceiverType != null) {
|
||||
val type = typeMapper.mapType(closure.captureReceiverType!!)
|
||||
val type = typeMapper.mapType(closure.captureReceiverType!!).let {
|
||||
if (isBoundCallableReference) it.boxReceiverForBoundReference() else it
|
||||
}
|
||||
val descriptor = EnclosedValueDescriptor(
|
||||
AsmUtil.CAPTURED_RECEIVER_FIELD, null,
|
||||
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0),
|
||||
@@ -260,24 +269,17 @@ class ExpressionLambda(
|
||||
val isPropertyReference: Boolean
|
||||
get() = propertyReferenceInfo != null
|
||||
|
||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val closureContext =
|
||||
if (isPropertyReference)
|
||||
codegen.getContext().intoAnonymousClass(classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
|
||||
else
|
||||
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, typeMapper)
|
||||
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, isCrossInline, isPropertyReference)
|
||||
|
||||
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
|
||||
val asmMethod = jvmMethodSignature.asmMethod
|
||||
val methodNode = MethodNode(
|
||||
InlineCodegenUtil.API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, context.contextKind, codegen.state),
|
||||
API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, sourceCompiler.state),
|
||||
asmMethod.name, asmMethod.descriptor, null, null
|
||||
)
|
||||
|
||||
node = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode).let { adapter ->
|
||||
val smap = InlineCodegen.generateMethodBody(
|
||||
adapter, invokeMethodDescriptor, context, functionWithBodyOrCallableReference, jvmMethodSignature, codegen, this
|
||||
node = wrapWithMaxLocalCalc(methodNode).let { adapter ->
|
||||
val smap = sourceCompiler.generateLambdaBody(
|
||||
adapter, jvmMethodSignature, this
|
||||
)
|
||||
adapter.visitMaxs(-1, -1)
|
||||
SMAPAndMethodNode(methodNode, smap)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 jdk.internal.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
|
||||
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
|
||||
|
||||
fun insertLegacySuspendInlineMarks(node: MethodNode) {
|
||||
with (node.instructions) {
|
||||
// look for return instruction before the end and insert "afterSuspendMarker" there
|
||||
insertBefore(findLastReturn(last) ?: return, produceSuspendMarker(false).instructions)
|
||||
// insert "beforeSuspendMarker" at the beginning
|
||||
insertBefore(first, produceSuspendMarker(true).instructions)
|
||||
}
|
||||
node.maxStack = node.maxStack.coerceAtLeast(2) // min stack need for suspend marker before return
|
||||
}
|
||||
|
||||
fun findLastReturn(node: AbstractInsnNode?): AbstractInsnNode? {
|
||||
var cur = node
|
||||
while (cur != null && cur.opcode != Opcodes.ARETURN) cur = cur.previous
|
||||
return cur
|
||||
}
|
||||
|
||||
private fun produceSuspendMarker(isStartNotEnd: Boolean): MethodNode =
|
||||
MethodNode().also { addSuspendMarker(InstructionAdapter(it), isStartNotEnd) }
|
||||
|
||||
fun isLegacySuspendInlineFunction(descriptor: CallableMemberDescriptor): Boolean {
|
||||
if (descriptor !is FunctionDescriptor) return false
|
||||
if (!descriptor.isSuspend || !descriptor.isInline) return false
|
||||
val jvmBytecodeVersion = descriptor.getContainingKotlinJvmBinaryClass()?.classHeader?.bytecodeVersion ?: return false
|
||||
return !jvmBytecodeVersion.isAtLeast(1, 0, 2)
|
||||
}
|
||||
@@ -103,7 +103,7 @@ class LocalVarRemapper(private val params: Parameters, private val additionalShi
|
||||
val remapInfo = remap(`var`)
|
||||
val value = remapInfo.value
|
||||
if (value is StackValue.Local) {
|
||||
val isStore = InlineCodegenUtil.isStoreInstruction(opcode)
|
||||
val isStore = isStoreInstruction(opcode)
|
||||
if (remapInfo.parameterInfo != null) {
|
||||
//All remapped value parameters can't be rewritten except case of default ones.
|
||||
//On remapping default parameter to actual value there is only one instruction that writes to it according to mask value
|
||||
|
||||
@@ -23,10 +23,12 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.TypePath;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.API;
|
||||
|
||||
public class MethodBodyVisitor extends InstructionAdapter {
|
||||
|
||||
public MethodBodyVisitor(MethodVisitor mv) {
|
||||
super(InlineCodegenUtil.API, mv);
|
||||
super(API, mv);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.FixStackWithLabelNormalizationMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
@@ -87,7 +87,7 @@ class MethodInliner(
|
||||
transformedNode.instructions.resetLabels()
|
||||
|
||||
val resultNode = MethodNode(
|
||||
InlineCodegenUtil.API, transformedNode.access, transformedNode.name, transformedNode.desc,
|
||||
API, transformedNode.access, transformedNode.name, transformedNode.desc,
|
||||
transformedNode.signature, transformedNode.exceptions?.toTypedArray()
|
||||
)
|
||||
val visitor = RemapVisitor(resultNode, remapper, nodeRemapper)
|
||||
@@ -130,7 +130,7 @@ class MethodInliner(
|
||||
AsmTypeRemapper(remapper, result)
|
||||
)
|
||||
|
||||
val markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node)
|
||||
val markerShift = calcMarkerShift(parameters, node)
|
||||
val lambdaInliner = object : InlineAdapter(remappingMethodAdapter, parameters.argsSizeOnStack, sourceMapper) {
|
||||
private var transformationInfo: TransformationInfo? = null
|
||||
|
||||
@@ -312,11 +312,11 @@ class MethodInliner(
|
||||
val realParametersSize = parameters.realParametersSizeOnStack
|
||||
|
||||
val transformedNode = object : MethodNode(
|
||||
InlineCodegenUtil.API, node.access, node.name,
|
||||
API, node.access, node.name,
|
||||
Type.getMethodDescriptor(Type.getReturnType(node.desc), *(Type.getArgumentTypes(node.desc) + parameters.capturedTypes)),
|
||||
node.signature, node.exceptions?.toTypedArray()
|
||||
) {
|
||||
private val GENERATE_DEBUG_INFO = InlineCodegenUtil.GENERATE_SMAP && inlineOnlySmapSkipper == null
|
||||
private val GENERATE_DEBUG_INFO = GENERATE_SMAP && inlineOnlySmapSkipper == null
|
||||
|
||||
private val isInliningLambda = nodeRemapper.isInsideInliningLambda
|
||||
|
||||
@@ -343,11 +343,15 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
|
||||
if (InlineCodegenUtil.DEFAULT_LAMBDA_FAKE_CALL == owner) {
|
||||
val index = name.substringAfter(InlineCodegenUtil.DEFAULT_LAMBDA_FAKE_CALL).toInt()
|
||||
if (DEFAULT_LAMBDA_FAKE_CALL == owner) {
|
||||
val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt()
|
||||
val lambda = getLambdaIfExists(index) as DefaultLambda
|
||||
lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach {
|
||||
(_, captured) ->
|
||||
val originalBoundReceiverType = lambda.originalBoundReceiverType
|
||||
if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) {
|
||||
StackValue.onStack(originalBoundReceiverType!!).put(captured.type, InstructionAdapter(this))
|
||||
}
|
||||
super.visitFieldInsn(
|
||||
Opcodes.PUTSTATIC, captured.containingLambdaName, CAPTURED_FIELD_FOLD_PREFIX + captured.fieldName, captured.type.descriptor
|
||||
)
|
||||
@@ -362,7 +366,7 @@ class MethodInliner(
|
||||
name: String, desc: String, signature: String?, start: Label, end: Label, index: Int
|
||||
) {
|
||||
if (isInliningLambda || GENERATE_DEBUG_INFO) {
|
||||
val varSuffix = if (inliningContext.isRoot && !InlineCodegenUtil.isFakeLocalVariableForInline(name)) INLINE_FUN_VAR_SUFFIX else ""
|
||||
val varSuffix = if (inliningContext.isRoot && !isFakeLocalVariableForInline(name)) INLINE_FUN_VAR_SUFFIX else ""
|
||||
val varName = if (!varSuffix.isEmpty() && name == "this") name + "_" else name
|
||||
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index))
|
||||
}
|
||||
@@ -400,9 +404,9 @@ class MethodInliner(
|
||||
awaitClassReification = true
|
||||
}
|
||||
else if (cur is MethodInsnNode) {
|
||||
if (InlineCodegenUtil.isFinallyStart(cur)) {
|
||||
if (isFinallyStart(cur)) {
|
||||
//TODO deep index calc could be more precise
|
||||
currentFinallyDeep = InlineCodegenUtil.getConstant(cur.previous)
|
||||
currentFinallyDeep = getConstant(cur.previous)
|
||||
}
|
||||
|
||||
val owner = cur.owner
|
||||
@@ -615,11 +619,11 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
private fun wrapException(originalException: Throwable, node: MethodNode, errorSuffix: String): RuntimeException {
|
||||
if (originalException is InlineException) {
|
||||
return InlineException("$errorPrefix: $errorSuffix", originalException)
|
||||
return if (originalException is InlineException) {
|
||||
InlineException("$errorPrefix: $errorSuffix", originalException)
|
||||
}
|
||||
else {
|
||||
return InlineException("$errorPrefix: $errorSuffix\nCause: ${getNodeText(node)}", originalException)
|
||||
InlineException("$errorPrefix: $errorSuffix\nCause: ${node.nodeText}", originalException)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,18 +672,18 @@ class MethodInliner(
|
||||
insertBeforeInsn: AbstractInsnNode,
|
||||
sourceValueFrame: Frame<SourceValue>
|
||||
) {
|
||||
assert(InlineCodegenUtil.isReturnOpcode(returnInsn.opcode)) { "return instruction expected" }
|
||||
assert(isReturnOpcode(returnInsn.opcode)) { "return instruction expected" }
|
||||
assert(returnOpcode < 0 || returnOpcode == returnInsn.opcode) { "Return op should be " + Printer.OPCODES[returnOpcode] + ", got " + Printer.OPCODES[returnInsn.opcode] }
|
||||
returnOpcode = returnInsn.opcode
|
||||
|
||||
localReturns.add(LocalReturn(returnInsn, insertBeforeInsn, sourceValueFrame))
|
||||
|
||||
if (returnInsn.opcode != Opcodes.RETURN) {
|
||||
if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) {
|
||||
returnVariableSize = 2
|
||||
returnVariableSize = if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) {
|
||||
2
|
||||
}
|
||||
else {
|
||||
returnVariableSize = 1
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -712,10 +716,9 @@ class MethodInliner(
|
||||
"Captured field template should start with $CAPTURED_FIELD_FOLD_PREFIX prefix"
|
||||
}
|
||||
val fin = FieldInsnNode(node.opcode, node.owner, node.name.substring(3), node.desc)
|
||||
val field = fieldRemapper.findField(fin) ?: throw IllegalStateException(
|
||||
return fieldRemapper.findField(fin) ?: throw IllegalStateException(
|
||||
"Couldn't find captured field ${node.owner}.${node.name} in ${fieldRemapper.originalLambdaInternalName}"
|
||||
)
|
||||
return field
|
||||
}
|
||||
|
||||
private fun analyzeMethodNodeWithoutMandatoryTransformations(node: MethodNode): Array<Frame<SourceValue>?> {
|
||||
@@ -771,9 +774,9 @@ class MethodInliner(
|
||||
|
||||
var cur: AbstractInsnNode? = node.instructions.first
|
||||
while (cur != null) {
|
||||
if (cur is MethodInsnNode && InlineCodegenUtil.isFinallyMarker(cur)) {
|
||||
if (cur is MethodInsnNode && isFinallyMarker(cur)) {
|
||||
val constant = cur.previous
|
||||
val curDeep = InlineCodegenUtil.getConstant(constant)
|
||||
val curDeep = getConstant(constant)
|
||||
node.instructions.insert(constant, LdcInsnNode(curDeep + finallyDeepShift))
|
||||
node.instructions.remove(constant)
|
||||
}
|
||||
@@ -829,9 +832,9 @@ class MethodInliner(
|
||||
val instructions = node.instructions
|
||||
var insnNode: AbstractInsnNode? = instructions.first
|
||||
while (insnNode != null) {
|
||||
if (InlineCodegenUtil.isReturnOpcode(insnNode.opcode)) {
|
||||
if (isReturnOpcode(insnNode.opcode)) {
|
||||
var isLocalReturn = true
|
||||
val labelName = InlineCodegenUtil.getMarkedReturnLabelOrNull(insnNode)
|
||||
val labelName = getMarkedReturnLabelOrNull(insnNode)
|
||||
|
||||
if (labelName != null) {
|
||||
isLocalReturn = labelOwner.isMyLabel(labelName)
|
||||
@@ -842,9 +845,13 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
if (isLocalReturn && endLabel != null) {
|
||||
val nop = InsnNode(Opcodes.NOP)
|
||||
instructions.insert(insnNode, nop)
|
||||
|
||||
val labelNode = endLabel.info as LabelNode
|
||||
val jumpInsnNode = JumpInsnNode(Opcodes.GOTO, labelNode)
|
||||
instructions.insert(insnNode, jumpInsnNode)
|
||||
instructions.insert(nop, jumpInsnNode)
|
||||
|
||||
instructions.remove(insnNode)
|
||||
insnNode = jumpInsnNode
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ fun MethodNode.findCapturedFieldAssignmentInstructions(): Sequence<FieldInsnNode
|
||||
val prevPrev = fieldNode.previous?.previous as? VarInsnNode
|
||||
|
||||
fieldNode.opcode == Opcodes.PUTFIELD &&
|
||||
InlineCodegenUtil.isCapturedFieldName(fieldNode.name) &&
|
||||
isCapturedFieldName(fieldNode.name) &&
|
||||
fieldNode.previous is VarInsnNode && prevPrev != null && prevPrev.`var` == 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ abstract class ObjectTransformer<out T : TransformationInfo>(@JvmField val trans
|
||||
val classBuilder = state.factory.newVisitor(
|
||||
JvmDeclarationOrigin.NO_ORIGIN,
|
||||
Type.getObjectType(transformationInfo.newClassName),
|
||||
inliningContext.root.callElement.containingFile
|
||||
inliningContext.root.sourceCompilerForInline.callsiteFile!!
|
||||
)
|
||||
|
||||
return RemappingClassBuilder(
|
||||
@@ -47,7 +47,7 @@ abstract class ObjectTransformer<out T : TransformationInfo>(@JvmField val trans
|
||||
}
|
||||
|
||||
fun createClassReader(): ClassReader {
|
||||
return InlineCodegenUtil.buildClassReaderByInternalName(state, transformationInfo.oldClassName)
|
||||
return buildClassReaderByInternalName(state, transformationInfo.oldClassName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ class WhenMappingTransformer(
|
||||
/*MAPPING File could contains mappings for several enum classes, we should filter one*/
|
||||
val methodNodes = arrayListOf<MethodNode>()
|
||||
val fieldNode = transformationInfo.fieldNode
|
||||
classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.inline
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
internal class ParametersBuilder private constructor() {
|
||||
class ParametersBuilder private constructor() {
|
||||
|
||||
private val params = arrayListOf<ParameterInfo>()
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.CAPTURED_FIELD_FOLD_PREFIX
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.THIS
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||
@@ -67,7 +65,7 @@ class RegeneratedLambdaFieldRemapper(
|
||||
val field = findFieldInSuper(fin) ?:
|
||||
//search in parent
|
||||
findFieldInSuper(FieldInsnNode(
|
||||
Opcodes.GETSTATIC, originalLambdaInternalName, InlineCodegenUtil.`THIS$0`,
|
||||
Opcodes.GETSTATIC, originalLambdaInternalName, THIS_0,
|
||||
Type.getObjectType(parent!!.originalLambdaInternalName!!).descriptor
|
||||
))?.also { fromParent = true } ?:
|
||||
throw AssertionError("Couldn't find captured this $originalLambdaInternalName for $fieldName")
|
||||
|
||||
@@ -169,7 +169,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
|
||||
) = rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { stubCheckcast: AbstractInsnNode ->
|
||||
if (stubCheckcast !is TypeInsnNode) return false
|
||||
|
||||
val newMethodNode = MethodNode(InlineCodegenUtil.API)
|
||||
val newMethodNode = MethodNode(API)
|
||||
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe)
|
||||
|
||||
instructions.insert(insn, newMethodNode.instructions)
|
||||
@@ -189,7 +189,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
|
||||
) = rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { stubInstanceOf: AbstractInsnNode ->
|
||||
if (stubInstanceOf !is TypeInsnNode) return false
|
||||
|
||||
val newMethodNode = MethodNode(InlineCodegenUtil.API)
|
||||
val newMethodNode = MethodNode(API)
|
||||
generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType)
|
||||
|
||||
instructions.insert(insn, newMethodNode.instructions)
|
||||
@@ -231,14 +231,14 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
|
||||
if (next3 is MethodInsnNode && next3.name == "valueOf") {
|
||||
instructions.remove(next1)
|
||||
next3.owner = parameter.internalName
|
||||
next3.desc = InlineCodegenUtil.getSpecialEnumFunDescriptor(parameter, true)
|
||||
next3.desc = getSpecialEnumFunDescriptor(parameter, true)
|
||||
return true
|
||||
}
|
||||
}
|
||||
else if (next1.opcode == Opcodes.ICONST_0 && next2.opcode == Opcodes.ANEWARRAY) {
|
||||
instructions.remove(next1)
|
||||
instructions.remove(next2)
|
||||
val desc = InlineCodegenUtil.getSpecialEnumFunDescriptor(parameter, false)
|
||||
val desc = getSpecialEnumFunDescriptor(parameter, false)
|
||||
instructions.insert(insn, MethodInsnNode(Opcodes.INVOKESTATIC, parameter.internalName, "values", desc, false))
|
||||
return true
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user