mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-13 00:21:28 +00:00
Compare commits
1502 Commits
abannykh/j
...
v1.2-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26da9976d2 | ||
|
|
ae135d979f | ||
|
|
2950495c4a | ||
|
|
8cdde268c6 | ||
|
|
00146b383c | ||
|
|
cc244f717e | ||
|
|
27c01598e8 | ||
|
|
6a11584cde | ||
|
|
1a9fc4fdc8 | ||
|
|
610a303bfa | ||
|
|
f831d88259 | ||
|
|
078acbb1a6 | ||
|
|
1333442a96 | ||
|
|
1e85dc3e12 | ||
|
|
6c77a19794 | ||
|
|
a8a0666ea5 | ||
|
|
103b41e90d | ||
|
|
50960a61d0 | ||
|
|
75bd6264f5 | ||
|
|
ad1663ec73 | ||
|
|
6d3a1bb51b | ||
|
|
040de90d14 | ||
|
|
28b4a372d2 | ||
|
|
45be5e971d | ||
|
|
f8b5e276bc | ||
|
|
12cb4ffde5 | ||
|
|
1fd5e25bb3 | ||
|
|
fa06b74440 | ||
|
|
4d2c2c39c2 | ||
|
|
5e6b195551 | ||
|
|
adaa4da502 | ||
|
|
6f98973786 | ||
|
|
e82eb7bc87 | ||
|
|
7c51e305d0 | ||
|
|
eae7e959e8 | ||
|
|
a94843cdd9 | ||
|
|
7e9c487073 | ||
|
|
5919f5e2b3 | ||
|
|
c6511f465b | ||
|
|
e1ae00cdf4 | ||
|
|
17826efbf6 | ||
|
|
fb673c4c9f | ||
|
|
77faa8659d | ||
|
|
d986a20e42 | ||
|
|
39b103ba9c | ||
|
|
7672b65c5f | ||
|
|
2a4c21908b | ||
|
|
018cd25f6d | ||
|
|
774ee74812 | ||
|
|
759bfb5869 | ||
|
|
5516924430 | ||
|
|
24b2dd0166 | ||
|
|
e87cf00d7b | ||
|
|
02d006eafa | ||
|
|
b6a9e6fc0c | ||
|
|
765adaef0a | ||
|
|
cd22050cda | ||
|
|
3dc4bc284a | ||
|
|
cec91bfd47 | ||
|
|
89e0797d63 | ||
|
|
c41cae6264 | ||
|
|
64169a5b02 | ||
|
|
fb10690690 | ||
|
|
4f1a483c22 | ||
|
|
a7d17eb24c | ||
|
|
a035c2beb3 | ||
|
|
be1715cd59 | ||
|
|
03dcbcaf8d | ||
|
|
0e57fa3a82 | ||
|
|
120ab10d79 | ||
|
|
e320104016 | ||
|
|
c5353f97c8 | ||
|
|
dbc3891418 | ||
|
|
f41a48f11a | ||
|
|
81dc100276 | ||
|
|
b68ac868f5 | ||
|
|
43ee2bd9c4 | ||
|
|
3d71fa85be | ||
|
|
e8d42e4dde | ||
|
|
7c26f87b0c | ||
|
|
9b0f15137f | ||
|
|
721889600f | ||
|
|
98e9238763 | ||
|
|
bd3d79d318 | ||
|
|
79308287be | ||
|
|
0722c5c13a | ||
|
|
d312996f3a | ||
|
|
9771a3c66e | ||
|
|
aa35d4ed36 | ||
|
|
6ba0ac1238 | ||
|
|
a66cd8b309 | ||
|
|
1c7d66c803 | ||
|
|
d87c0b164f | ||
|
|
6a1b6d10d8 | ||
|
|
6d26d1fb67 | ||
|
|
91a99b4726 | ||
|
|
481cbd0850 | ||
|
|
7cd5eeb24d | ||
|
|
e12de11ce9 | ||
|
|
2c521727c3 | ||
|
|
c0dd97b40d | ||
|
|
a18e9436a1 | ||
|
|
7982f3489e | ||
|
|
2fe7cc5534 | ||
|
|
77f625bfc8 | ||
|
|
7849452b66 | ||
|
|
bba2d27e82 | ||
|
|
14742a6048 | ||
|
|
6d7c88a2bc | ||
|
|
37a23f0958 | ||
|
|
d3082b0e62 | ||
|
|
fcc84d00c3 | ||
|
|
fc4ff3b760 | ||
|
|
afdd647df1 | ||
|
|
c5c6050baa | ||
|
|
88644001d3 | ||
|
|
8d8f683042 | ||
|
|
956b0aca92 | ||
|
|
194d16176c | ||
|
|
2b186909d4 | ||
|
|
d20ba5d082 | ||
|
|
19b8ecab61 | ||
|
|
6e41bbc2a7 | ||
|
|
32cc619f15 | ||
|
|
85d6a4d1af | ||
|
|
27615209ed | ||
|
|
6766196bd8 | ||
|
|
bc78d672c1 | ||
|
|
e896a1f5ea | ||
|
|
5d25106267 | ||
|
|
dd8bed8b46 | ||
|
|
1a2dc4c96c | ||
|
|
205272f51b | ||
|
|
0640d5618c | ||
|
|
6650340716 | ||
|
|
b909704bb9 | ||
|
|
31f4f2d0c9 | ||
|
|
89c8ee8614 | ||
|
|
280a60af6f | ||
|
|
62ec4b5a31 | ||
|
|
9f02a8b2a8 | ||
|
|
74f81f38ba | ||
|
|
2d0ac0011a | ||
|
|
c4fd1a8e5c | ||
|
|
fba1a2a2db | ||
|
|
810d62bbaf | ||
|
|
eb648e20c6 | ||
|
|
e86d2f00ff | ||
|
|
c8ee424f67 | ||
|
|
fd6eab38e5 | ||
|
|
4dc47c734c | ||
|
|
0bf7dc3e0c | ||
|
|
1ebfe1af43 | ||
|
|
79b2b40289 | ||
|
|
5641909d1d | ||
|
|
11b6382518 | ||
|
|
05dd471404 | ||
|
|
373bd5ff17 | ||
|
|
aa442860c2 | ||
|
|
bbf4c56c06 | ||
|
|
faaddacec6 | ||
|
|
13fc526695 | ||
|
|
a9ece23e63 | ||
|
|
a63495aa0b | ||
|
|
26af128694 | ||
|
|
d9f99971bb | ||
|
|
e6171dc4c5 | ||
|
|
8eeed17b65 | ||
|
|
9984b6f9d1 | ||
|
|
2fb2211a4d | ||
|
|
83bf257666 | ||
|
|
4ac8a98050 | ||
|
|
69051a4764 | ||
|
|
74bda80ec2 | ||
|
|
8e72a1211b | ||
|
|
b574ddfba0 | ||
|
|
68259f7939 | ||
|
|
f905d56b38 | ||
|
|
b1d9abdf83 | ||
|
|
6336ad874b | ||
|
|
24b1f2ed1f | ||
|
|
4d95c30360 | ||
|
|
97fed6336b | ||
|
|
363d345752 | ||
|
|
2ca220d442 | ||
|
|
b744ed0fd3 | ||
|
|
943dd96a87 | ||
|
|
d32e101802 | ||
|
|
92215b41b9 | ||
|
|
cd6201c5df | ||
|
|
0f9d31c9d1 | ||
|
|
04b8f1db6e | ||
|
|
71c2489ade | ||
|
|
94e3a51a45 | ||
|
|
74043089ab | ||
|
|
b9872b7651 | ||
|
|
d20af1133a | ||
|
|
179e720e4a | ||
|
|
773eff1de8 | ||
|
|
a3c4850f0d | ||
|
|
4c2cfd3ea9 | ||
|
|
9ae6feb2c5 | ||
|
|
e8e38d90ff | ||
|
|
2bb437b219 | ||
|
|
70ae1596fb | ||
|
|
d07b628e0c | ||
|
|
234148518e | ||
|
|
7d80afbe63 | ||
|
|
c6263ac8e6 | ||
|
|
08052e63e9 | ||
|
|
2249675e59 | ||
|
|
49bc9249a1 | ||
|
|
497251a6d7 | ||
|
|
11c83ad0fc | ||
|
|
22dc36a596 | ||
|
|
cc8fbf6078 | ||
|
|
296638a7c4 | ||
|
|
cad6fdb323 | ||
|
|
75fa982370 | ||
|
|
1b45e9d517 | ||
|
|
b01a3eb747 | ||
|
|
16c5fb6f6b | ||
|
|
28d785854c | ||
|
|
97fd72a1e0 | ||
|
|
b905ddeac9 | ||
|
|
4eb0f245a6 | ||
|
|
fbdcf45976 | ||
|
|
8753baeab6 | ||
|
|
5bb88b659b | ||
|
|
30c7f633bd | ||
|
|
d7ad973843 | ||
|
|
9a8699a2ab | ||
|
|
7b4e24a454 | ||
|
|
07be1e9d10 | ||
|
|
f84df6381e | ||
|
|
3f4ddb006a | ||
|
|
eefb490a8a | ||
|
|
1b688182cd | ||
|
|
f6d7a17227 | ||
|
|
e0509e8c4d | ||
|
|
033386b47d | ||
|
|
89c5f78a8e | ||
|
|
a03c03c427 | ||
|
|
88138fc420 | ||
|
|
7b96c9a003 | ||
|
|
be3273a933 | ||
|
|
3587a2a08e | ||
|
|
c9ec1a2511 | ||
|
|
32fc340d62 | ||
|
|
e645da64da | ||
|
|
f8ca714c45 | ||
|
|
eee28d8507 | ||
|
|
32c02161cd | ||
|
|
b925df0e14 | ||
|
|
239f88e5d3 | ||
|
|
08103d1cb4 | ||
|
|
e16d16fdb7 | ||
|
|
2048a74302 | ||
|
|
a4766cc293 | ||
|
|
dafb52a44a | ||
|
|
dd1ac5bb6b | ||
|
|
97233448d0 | ||
|
|
7ae722492f | ||
|
|
4b25317ecb | ||
|
|
5eb69e0ae4 | ||
|
|
60c735f2fd | ||
|
|
593d6b7a95 | ||
|
|
ac1c7d9a6a | ||
|
|
b6c32edc43 | ||
|
|
89257e6397 | ||
|
|
26cbcfa1ac | ||
|
|
7fe1e4f83e | ||
|
|
38d1d06e6e | ||
|
|
6b6d1e80f8 | ||
|
|
40e2046e76 | ||
|
|
ea9f5a7200 | ||
|
|
b2e27f9172 | ||
|
|
cd44131f88 | ||
|
|
0caadcd2f1 | ||
|
|
9d2b9df3b4 | ||
|
|
1d05e83401 | ||
|
|
6d30123c21 | ||
|
|
aed01c8475 | ||
|
|
62b3059425 | ||
|
|
0b143e982f | ||
|
|
c90c3e4bf5 | ||
|
|
0acc96c4f3 | ||
|
|
2656a6a513 | ||
|
|
37fa45dc34 | ||
|
|
ae509d5980 | ||
|
|
37d2386a0b | ||
|
|
7e3d3bde74 | ||
|
|
5c4e034171 | ||
|
|
4428798c61 | ||
|
|
66ece54b25 | ||
|
|
26b2f59b86 | ||
|
|
ba2c3136bb | ||
|
|
ea91a0794d | ||
|
|
488a825349 | ||
|
|
dd9ffd10b6 | ||
|
|
d8b46406ab | ||
|
|
24c6f5f0f0 | ||
|
|
c65a79bca4 | ||
|
|
c66bc0b0e9 | ||
|
|
1350e3c4ac | ||
|
|
502c51ccff | ||
|
|
206369c088 | ||
|
|
03ce6d859f | ||
|
|
c149c37ac7 | ||
|
|
c4ebfe8e84 | ||
|
|
13775f8637 | ||
|
|
bdad58cec6 | ||
|
|
8ebc766b5b | ||
|
|
8b64a4c8ea | ||
|
|
6f8503a178 | ||
|
|
6c3620f481 | ||
|
|
69176a146e | ||
|
|
deda5e7eee | ||
|
|
ebd3ac6dc8 | ||
|
|
e9ce5bbb37 | ||
|
|
53144def10 | ||
|
|
d7149a4083 | ||
|
|
6bec17246c | ||
|
|
6b14d15374 | ||
|
|
c479e585ca | ||
|
|
fcab80db96 | ||
|
|
6fd3ce07b3 | ||
|
|
eb7a984843 | ||
|
|
2877314313 | ||
|
|
d2ff821a3b | ||
|
|
ff0efe59f6 | ||
|
|
4779f4fefb | ||
|
|
f2b6644db5 | ||
|
|
980feffffa | ||
|
|
78b1fb2e93 | ||
|
|
dcd966f7c2 | ||
|
|
4f647e84c9 | ||
|
|
5a5a27b983 | ||
|
|
fe0f44da94 | ||
|
|
2fa4c28e0f | ||
|
|
44fd8103d4 | ||
|
|
ddb6e3307e | ||
|
|
529036eb78 | ||
|
|
c327118eac | ||
|
|
d38fd0fdf8 | ||
|
|
ba19931aef | ||
|
|
97e4dbe330 | ||
|
|
e1b79fc316 | ||
|
|
f840d0df41 | ||
|
|
140db74607 | ||
|
|
369f3d6553 | ||
|
|
e392b4a427 | ||
|
|
088800d82f | ||
|
|
03440210ee | ||
|
|
27b8b209e3 | ||
|
|
326111aece | ||
|
|
1cf8ee9433 | ||
|
|
599113b30f | ||
|
|
5bf4540458 | ||
|
|
361d6dfca0 | ||
|
|
187ca71dc6 | ||
|
|
cea891c754 | ||
|
|
fe3413c291 | ||
|
|
04c2e28341 | ||
|
|
c330285fd0 | ||
|
|
84e59601c1 | ||
|
|
4d9a612a64 | ||
|
|
4e4291c586 | ||
|
|
f4b329a055 | ||
|
|
8c5d18c1f2 | ||
|
|
61faa068d4 | ||
|
|
2b27e64fc8 | ||
|
|
160ba0c7c0 | ||
|
|
71663afbfe | ||
|
|
81a1bf3319 | ||
|
|
638cf346aa | ||
|
|
2ce6a0eaee | ||
|
|
385ff3f4eb | ||
|
|
80ffc5cd41 | ||
|
|
e01371b231 | ||
|
|
a3060f1073 | ||
|
|
21cdf9dd5b | ||
|
|
081b732070 | ||
|
|
356f903645 | ||
|
|
0dc29d6d7e | ||
|
|
e7449a3584 | ||
|
|
4a6f35b9c2 | ||
|
|
6d4bb229ac | ||
|
|
ec512d1c8a | ||
|
|
cbe79e94a6 | ||
|
|
e5b290d77f | ||
|
|
a9a52379ee | ||
|
|
653314e671 | ||
|
|
7f361c7579 | ||
|
|
7ca1fe0f55 | ||
|
|
b8aa2f81a2 | ||
|
|
28c9d274ec | ||
|
|
5a984a40e6 | ||
|
|
989cebe79e | ||
|
|
abb254297a | ||
|
|
593aa72439 | ||
|
|
63855af026 | ||
|
|
df7d69b5b4 | ||
|
|
918ce78c5a | ||
|
|
41140d00b1 | ||
|
|
1260146d25 | ||
|
|
7646c2fc72 | ||
|
|
8c256b24dc | ||
|
|
f2b2e20331 | ||
|
|
b90885d1cb | ||
|
|
901346243d | ||
|
|
6bb5d00700 | ||
|
|
834cd1d93d | ||
|
|
61ba6e528a | ||
|
|
df782eaadd | ||
|
|
eb6186b74d | ||
|
|
8e6b1da592 | ||
|
|
aaf3380050 | ||
|
|
445a80c755 | ||
|
|
7c421b0b83 | ||
|
|
29857e48c8 | ||
|
|
be4b86e3d9 | ||
|
|
b0fb3370e3 | ||
|
|
cc6bfcfc7c | ||
|
|
f008736ef7 | ||
|
|
f709bd869a | ||
|
|
f74416a151 | ||
|
|
839f197a1e | ||
|
|
ebef2dc0cf | ||
|
|
80f1a1bde8 | ||
|
|
840fce520c | ||
|
|
2d10df1541 | ||
|
|
81d0445775 | ||
|
|
ad37626af3 | ||
|
|
59976baac2 | ||
|
|
76acd23bd7 | ||
|
|
db840a73a9 | ||
|
|
05290c3ed2 | ||
|
|
f695ff96e8 | ||
|
|
0fa4e1cbaf | ||
|
|
5220dfc0ad | ||
|
|
be900a76d8 | ||
|
|
f4da6c2cc6 | ||
|
|
56a075eab6 | ||
|
|
e0bf438195 | ||
|
|
895d5fda46 | ||
|
|
8b0d606ab5 | ||
|
|
9eace7b295 | ||
|
|
d2972314bc | ||
|
|
92103ff393 | ||
|
|
feeacda12b | ||
|
|
f5cea51d21 | ||
|
|
bf639b1272 | ||
|
|
6fbb370eae | ||
|
|
e781b70170 | ||
|
|
6f9869ae11 | ||
|
|
d8b6bd5cb3 | ||
|
|
982461e207 | ||
|
|
5d44e095c8 | ||
|
|
2427b2cc6c | ||
|
|
dde0efd8ab | ||
|
|
f5222600d8 | ||
|
|
17b4874c37 | ||
|
|
ff1c5ad793 | ||
|
|
a0ddef22ef | ||
|
|
0246b82833 | ||
|
|
4e4bf31016 | ||
|
|
ed79891ee6 | ||
|
|
73c139d250 | ||
|
|
6af91b8c97 | ||
|
|
80a90572d6 | ||
|
|
742fecf69c | ||
|
|
21e3051a78 | ||
|
|
c8d25c587a | ||
|
|
638eb28692 | ||
|
|
b12e20b2a3 | ||
|
|
bbf9bf91fc | ||
|
|
01cce59c35 | ||
|
|
d951e957ea | ||
|
|
78b69cad77 | ||
|
|
d0b0fdd732 | ||
|
|
c5b9d500bc | ||
|
|
53961e8df0 | ||
|
|
3bae430d49 | ||
|
|
f88cd5ed3d | ||
|
|
352071dc4a | ||
|
|
a623fb5312 | ||
|
|
29d2482b62 | ||
|
|
350cea7afd | ||
|
|
be64a6feeb | ||
|
|
a68312379e | ||
|
|
aef5911c7e | ||
|
|
abb07ced6d | ||
|
|
fb4bf4e5b8 | ||
|
|
f47093dc45 | ||
|
|
290deb6ba4 | ||
|
|
09c1115ff9 | ||
|
|
0d7c0d4e5e | ||
|
|
b231bf0207 | ||
|
|
ce0fb60ff4 | ||
|
|
d6fbb084b1 | ||
|
|
84c2e01161 | ||
|
|
68522b9f1e | ||
|
|
dce6cb0cfc | ||
|
|
4ada692421 | ||
|
|
a120130069 | ||
|
|
a6c2135851 | ||
|
|
eefc6ebcc9 | ||
|
|
67fdd9f76e | ||
|
|
2dc0c55e76 | ||
|
|
1b0d7ff5be | ||
|
|
4f180e1292 | ||
|
|
01883a41cb | ||
|
|
8494e54608 | ||
|
|
2224720a90 | ||
|
|
108a40261b | ||
|
|
e1924e0d2f | ||
|
|
0e28d612e7 | ||
|
|
0263919dbd | ||
|
|
843a9871b1 | ||
|
|
106db13a6a | ||
|
|
f37cc9c8ef | ||
|
|
f7f3bacc8e | ||
|
|
cc5d23440e | ||
|
|
ac3beabf43 | ||
|
|
cb1ffdccd7 | ||
|
|
10feac9402 | ||
|
|
8e10a22aab | ||
|
|
66a77c7ec2 | ||
|
|
cf72b14b34 | ||
|
|
141c889a84 | ||
|
|
5f9bad5905 | ||
|
|
73b63bb343 | ||
|
|
44e8ae3571 | ||
|
|
b73d5cbe1f | ||
|
|
2312013c41 | ||
|
|
556c43ae00 | ||
|
|
4a591bf5b6 | ||
|
|
66cb45c202 | ||
|
|
dbe3baf740 | ||
|
|
919daefb0e | ||
|
|
093bbc069a | ||
|
|
b28382b8e7 | ||
|
|
1c4ada2008 | ||
|
|
b54414d628 | ||
|
|
eeb90656dc | ||
|
|
7ecf5abdc7 | ||
|
|
0a5fe3ef7c | ||
|
|
e16c5ddb97 | ||
|
|
23bc907d3f | ||
|
|
166883d847 | ||
|
|
7810da7018 | ||
|
|
71e8f16906 | ||
|
|
52b638ddb3 | ||
|
|
c7775b8d11 | ||
|
|
20551f6c99 | ||
|
|
bb1cba67b7 | ||
|
|
4aea9b349c | ||
|
|
356536d32b | ||
|
|
20b14d4121 | ||
|
|
6fedf07f56 | ||
|
|
d4d684a7f0 | ||
|
|
65529fa866 | ||
|
|
53d911ab99 | ||
|
|
5ddc8d83bb | ||
|
|
60f68266dd | ||
|
|
9727ec401b | ||
|
|
af73082fcc | ||
|
|
508d96836c | ||
|
|
d1fd88fb8e | ||
|
|
a076b4614e | ||
|
|
3ad5e78d77 | ||
|
|
367b9f6664 | ||
|
|
e3b7f6d698 | ||
|
|
6953ae79e2 | ||
|
|
f8f5494d79 | ||
|
|
ceae10f451 | ||
|
|
1814f3172a | ||
|
|
5b8e5fb9aa | ||
|
|
f07d4901ca | ||
|
|
cdda5d39e5 | ||
|
|
c420e2bfa5 | ||
|
|
3d8b15d9db | ||
|
|
fac207ce7c | ||
|
|
38849893b6 | ||
|
|
b87abc9f0f | ||
|
|
d1cff41ce0 | ||
|
|
56b507d141 | ||
|
|
3a2d93f73e | ||
|
|
6cb4916dee | ||
|
|
59c49675b0 | ||
|
|
3bc8ca5913 | ||
|
|
9ecd04f628 | ||
|
|
74ba0080b1 | ||
|
|
472959aca1 | ||
|
|
f01e0ef335 | ||
|
|
e65a62c48c | ||
|
|
2ceb8cef36 | ||
|
|
98eae4e7ee | ||
|
|
d1e52e76f9 | ||
|
|
f31c48017b | ||
|
|
ff4f928420 | ||
|
|
c163e71662 | ||
|
|
b988fb701d | ||
|
|
83a1d6e5ca | ||
|
|
8cf7f7a8f3 | ||
|
|
749a574234 | ||
|
|
e666b87545 | ||
|
|
3f8a685ace | ||
|
|
d18a14b717 | ||
|
|
51be629e13 | ||
|
|
6f397f8512 | ||
|
|
9f2bf066b9 | ||
|
|
1a05df204e | ||
|
|
f0035a7be0 | ||
|
|
0920b2574c | ||
|
|
08e090bf5e | ||
|
|
c142db15fa | ||
|
|
46a1c8ca12 | ||
|
|
91f50c99e7 | ||
|
|
7fecec1141 | ||
|
|
a6b446cc4f | ||
|
|
6eb534fca8 | ||
|
|
c45f86a2fc | ||
|
|
08964006de | ||
|
|
e040a317cc | ||
|
|
55d1130dfc | ||
|
|
f075934697 | ||
|
|
963ab7f27f | ||
|
|
f42be4aea2 | ||
|
|
9f71de5f66 | ||
|
|
74e07b6580 | ||
|
|
d9eef94a8e | ||
|
|
cb1270836c | ||
|
|
76012f6603 | ||
|
|
e011e443cc | ||
|
|
3cf240340c | ||
|
|
ff1e230828 | ||
|
|
da003d48ff | ||
|
|
6b8293ae5b | ||
|
|
aca21c847d | ||
|
|
1ae4ad1598 | ||
|
|
cdaa98fb63 | ||
|
|
2b01b91315 | ||
|
|
e88c1b4f0a | ||
|
|
9bbfac11b4 | ||
|
|
aedb4c0ade | ||
|
|
2e1edaf3d4 | ||
|
|
e06cb1ec39 | ||
|
|
cb3a8d87d0 | ||
|
|
1dfa05fe49 | ||
|
|
ad9fe53ee2 | ||
|
|
fcd7677a3f | ||
|
|
d5f0607cef | ||
|
|
1848bc1840 | ||
|
|
f941186f75 | ||
|
|
c549c63100 | ||
|
|
1e73921200 | ||
|
|
c132f3b0d1 | ||
|
|
6424b6760f | ||
|
|
6f180416b1 | ||
|
|
f0f6a252a5 | ||
|
|
0adf1d210f | ||
|
|
0fd5c6f1ca | ||
|
|
9dc5354f24 | ||
|
|
3623f581b8 | ||
|
|
82fc221470 | ||
|
|
0efdcb59fa | ||
|
|
2b90a67bc1 | ||
|
|
806aa7d4c1 | ||
|
|
8af7a25f8e | ||
|
|
39599fc7c9 | ||
|
|
99a402ee30 | ||
|
|
4d2fbf1801 | ||
|
|
97d46e76f5 | ||
|
|
905b8cc4e9 | ||
|
|
79ecc7fd5c | ||
|
|
1b2e28d467 | ||
|
|
f7a1c71b54 | ||
|
|
770441c212 | ||
|
|
8db736e2b4 | ||
|
|
7601666ec0 | ||
|
|
a24c9a987f | ||
|
|
be664e26f7 | ||
|
|
4092d754c6 | ||
|
|
12eb4ef37a | ||
|
|
a2a018eadb | ||
|
|
f7c17d6a64 | ||
|
|
6a5d8dcc82 | ||
|
|
070e35bc15 | ||
|
|
a641838368 | ||
|
|
226ffb6c7e | ||
|
|
6a4ea8b669 | ||
|
|
a12877e51c | ||
|
|
a086863561 | ||
|
|
b2d931fb1f | ||
|
|
9be5cf89b4 | ||
|
|
80b6aaa802 | ||
|
|
5bd04a6d22 | ||
|
|
787bbe9a4c | ||
|
|
1215b2864b | ||
|
|
2f556e1bea | ||
|
|
537c1fd063 | ||
|
|
f80fcc7146 | ||
|
|
d3a9d122e6 | ||
|
|
cd5c382179 | ||
|
|
4dbde03c3b | ||
|
|
f5c7db8270 | ||
|
|
7f9110b4e6 | ||
|
|
0b44386800 | ||
|
|
8439e15c6e | ||
|
|
e4f70a3568 | ||
|
|
62ca3bab31 | ||
|
|
f455f06a9e | ||
|
|
386b1fc002 | ||
|
|
98eb990f30 | ||
|
|
e3963fccf4 | ||
|
|
57d209f599 | ||
|
|
e5e5b56af0 | ||
|
|
04464024fe | ||
|
|
9bb7ed5e02 | ||
|
|
34681b1459 | ||
|
|
1fe3f84071 | ||
|
|
5b72159967 | ||
|
|
e315249624 | ||
|
|
5501cdf049 | ||
|
|
746de612ad | ||
|
|
5fd8f93b0e | ||
|
|
71bf649b1e | ||
|
|
bf98e26bc2 | ||
|
|
718ee01a48 | ||
|
|
830b543879 | ||
|
|
165707c46c | ||
|
|
88bc74551b | ||
|
|
7986250dbe | ||
|
|
192d569e54 | ||
|
|
4cf2bf6ca5 | ||
|
|
3d6622ae1b | ||
|
|
0226d15d29 | ||
|
|
cd40968b72 | ||
|
|
6cd409d379 | ||
|
|
80131d8359 | ||
|
|
4b2b5dec75 | ||
|
|
f8de17b039 | ||
|
|
a8c82b64a1 | ||
|
|
ce37ab81ba | ||
|
|
9962fc88ca | ||
|
|
8898455352 | ||
|
|
8948023a26 | ||
|
|
964f60d0a4 | ||
|
|
f8f0c0b6d7 | ||
|
|
a82e313d14 | ||
|
|
6d66fb35d6 | ||
|
|
10bf49118a | ||
|
|
46bbf55acd | ||
|
|
eeede71d9d | ||
|
|
2cf4da8564 | ||
|
|
d8c20ed9c0 | ||
|
|
0d6cf19896 | ||
|
|
c2b54c3e8a | ||
|
|
bb7521a142 | ||
|
|
99439620d4 | ||
|
|
2954c41848 | ||
|
|
f94569c995 | ||
|
|
4e868c5232 | ||
|
|
62dc3c8da4 | ||
|
|
384ae8d8b5 | ||
|
|
532560ef43 | ||
|
|
ca19ea8205 | ||
|
|
ce77751349 | ||
|
|
6ae247ba61 | ||
|
|
13349086ac | ||
|
|
a36cbad7cd | ||
|
|
4a15870e59 | ||
|
|
e56f9f6040 | ||
|
|
85ecde6ec9 | ||
|
|
4d72f0ef66 | ||
|
|
11086192bc | ||
|
|
08673bfb0c | ||
|
|
0694f2d0c5 | ||
|
|
548e86285c | ||
|
|
20d0d49cc3 | ||
|
|
48d4f5f5c2 | ||
|
|
c1cfd70ae7 | ||
|
|
b825a8db43 | ||
|
|
23e606d179 | ||
|
|
cf4d0fb977 | ||
|
|
83a8395287 | ||
|
|
282da4cab5 | ||
|
|
298d29a962 | ||
|
|
62e583903e | ||
|
|
c675824c0a | ||
|
|
6336c4ee98 | ||
|
|
be1022db2b | ||
|
|
a142c2f8fa | ||
|
|
c07096c9d7 | ||
|
|
768305adc8 | ||
|
|
e8d2782089 | ||
|
|
b50d5fb998 | ||
|
|
7fffb7b553 | ||
|
|
b938206234 | ||
|
|
84e1e9f8aa | ||
|
|
239943867b | ||
|
|
0d3b882852 | ||
|
|
6354d9d54f | ||
|
|
856276328e | ||
|
|
e0ef08cf18 | ||
|
|
642c5414a3 | ||
|
|
46a3a59b81 | ||
|
|
7e7fcd352c | ||
|
|
82c977f2d2 | ||
|
|
6cfd090b20 | ||
|
|
e2190ea956 | ||
|
|
f3f7ca4b95 | ||
|
|
ab90221a93 | ||
|
|
485e2345a9 | ||
|
|
bb2fab5b5d | ||
|
|
a4c7dbd693 | ||
|
|
61b3c1c429 | ||
|
|
c601890151 | ||
|
|
1cce1ef1f6 | ||
|
|
ed5b6e07aa | ||
|
|
23afaeec2f | ||
|
|
f5e77c740d | ||
|
|
8ffd141d17 | ||
|
|
1921950a1b | ||
|
|
cc24b9f4ad | ||
|
|
5dd4e4cdd4 | ||
|
|
9ab7c92b4b | ||
|
|
8fbab94c5c | ||
|
|
6ca06265cf | ||
|
|
a41e5fff6b | ||
|
|
674d30cd76 | ||
|
|
c180de563f | ||
|
|
223acbcfeb | ||
|
|
e35b262827 | ||
|
|
4e190248cd | ||
|
|
3fd6dd3572 | ||
|
|
022430cb59 | ||
|
|
974dad571c | ||
|
|
2ac7b6a534 | ||
|
|
915f47133b | ||
|
|
f24488915a | ||
|
|
adfc481c7a | ||
|
|
4405021f85 | ||
|
|
73a4da6c56 | ||
|
|
a7bbf3d1f8 | ||
|
|
3415853cac | ||
|
|
ac96c31a7d | ||
|
|
0b45d25bb1 | ||
|
|
bdbe134b60 | ||
|
|
07794c8188 | ||
|
|
dde1f4b8f3 | ||
|
|
36cabf1bfc | ||
|
|
d6a9a49968 | ||
|
|
aafe7e6f1b | ||
|
|
fcc067435e | ||
|
|
194deccd09 | ||
|
|
3debca09ea | ||
|
|
cfbc559a97 | ||
|
|
4a74ca568c | ||
|
|
053b02e0df | ||
|
|
20e105c274 | ||
|
|
82c3637d91 | ||
|
|
46d0ea3eed | ||
|
|
cf3615d279 | ||
|
|
e52c3b4c81 | ||
|
|
998814b1a1 | ||
|
|
9361cd895c | ||
|
|
48246e5f34 | ||
|
|
b6e195128c | ||
|
|
5486f4e612 | ||
|
|
64b722d4f6 | ||
|
|
9c37d0a007 | ||
|
|
60e330b6f3 | ||
|
|
ff0736f09e | ||
|
|
45d5f6a950 | ||
|
|
3ae084b1b3 | ||
|
|
49612063dc | ||
|
|
07c5702861 | ||
|
|
6e4b02a94b | ||
|
|
6305abdf9f | ||
|
|
ca418c727e | ||
|
|
8a17e6c1c9 | ||
|
|
e53b1a1e92 | ||
|
|
5904b7f257 | ||
|
|
15f401a473 | ||
|
|
11ba805181 | ||
|
|
5ecdf2af9e | ||
|
|
fca1500d48 | ||
|
|
e2dcf47b3b | ||
|
|
52f923c5ff | ||
|
|
ae3497c6ce | ||
|
|
8f8143d3ed | ||
|
|
4d4c39939f | ||
|
|
216ab1c6d1 | ||
|
|
7ba073206d | ||
|
|
7693f64dee | ||
|
|
9e018fa094 | ||
|
|
07a4496054 | ||
|
|
a13442b12b | ||
|
|
dc83e5ca3a | ||
|
|
3fb865e07c | ||
|
|
fb72726f08 | ||
|
|
6680f01cfe | ||
|
|
e7cd615450 | ||
|
|
cf75afba66 | ||
|
|
ac507e721c | ||
|
|
21c5187c9e | ||
|
|
0d464f06d1 | ||
|
|
39349abd39 | ||
|
|
5ec8d4920f | ||
|
|
c0d6eff97c | ||
|
|
0bf81aeec0 | ||
|
|
258a5aea28 | ||
|
|
ab2f99542a | ||
|
|
b344865c15 | ||
|
|
93d80c252f | ||
|
|
ef93088a42 | ||
|
|
9378bff65c | ||
|
|
3450340d7f | ||
|
|
1bc68e073d | ||
|
|
4848f8e3da | ||
|
|
85e34163bb | ||
|
|
455c43afa8 | ||
|
|
f1144c9f01 | ||
|
|
c752e1580e | ||
|
|
a5dffafacd | ||
|
|
7802492b08 | ||
|
|
6be726854f | ||
|
|
76d013a33f | ||
|
|
4963580f90 | ||
|
|
17cdbcca03 | ||
|
|
915ac32bfb | ||
|
|
91241a34d1 | ||
|
|
d58c6e245f | ||
|
|
e74a02eb94 | ||
|
|
ffc130f5fb | ||
|
|
5f2cc75718 | ||
|
|
e4b73fcdbd | ||
|
|
756f7d6e9c | ||
|
|
d4e8a30dcf | ||
|
|
e5c87fdad7 | ||
|
|
b336919db3 | ||
|
|
397e04f382 | ||
|
|
5b2e66f0ca | ||
|
|
dc453e6d8b | ||
|
|
ba068c2d65 | ||
|
|
def0816095 | ||
|
|
38d9123a57 | ||
|
|
18961cc5a9 | ||
|
|
8599763cb9 | ||
|
|
fbad16567b | ||
|
|
1ae4278cfd | ||
|
|
bc2a8555a3 | ||
|
|
c0c94910e2 | ||
|
|
9fa3bce73a | ||
|
|
26cc08be65 | ||
|
|
6facdcb7ea | ||
|
|
badbf777df | ||
|
|
5eb56dca60 | ||
|
|
d1263c5dc3 | ||
|
|
cf55674109 | ||
|
|
f578d07b00 | ||
|
|
f637ebe9ff | ||
|
|
b7c894a6d3 | ||
|
|
b6bb171b67 | ||
|
|
8670d2abba | ||
|
|
72d14bfe0d | ||
|
|
a303888e66 | ||
|
|
0136be3500 | ||
|
|
0634025229 | ||
|
|
c6fcbf6172 | ||
|
|
e12eb66572 | ||
|
|
de17604fe7 | ||
|
|
42438bd363 | ||
|
|
85248676d2 | ||
|
|
b9e9243e9d | ||
|
|
af138e7403 | ||
|
|
5bb61d2d02 | ||
|
|
7eabdeffb3 | ||
|
|
b3be21146c | ||
|
|
0f0d834c23 | ||
|
|
55181541af | ||
|
|
58f73bd82a | ||
|
|
30f7396803 | ||
|
|
89ac3bd5cf | ||
|
|
3a25405088 | ||
|
|
ff6a28b64c | ||
|
|
acc6e48172 | ||
|
|
29e2a26ad6 | ||
|
|
ee16a79612 | ||
|
|
55dc2c11f7 | ||
|
|
02f4558683 | ||
|
|
36ea9484a9 | ||
|
|
0b358fb693 | ||
|
|
b24c1bf06c | ||
|
|
d624ed4aff | ||
|
|
a4551fb0fb | ||
|
|
71878b2218 | ||
|
|
13a2de1816 | ||
|
|
0cfac71efe | ||
|
|
94036b7cac | ||
|
|
999db0bc80 | ||
|
|
8fd508566a | ||
|
|
64eeb479aa | ||
|
|
1264ed7c86 | ||
|
|
666c241479 | ||
|
|
2536615e0e | ||
|
|
4c00119f08 | ||
|
|
7d66af6583 | ||
|
|
8d226594ff | ||
|
|
8de6017e53 | ||
|
|
ae6f38e252 | ||
|
|
6194bc10f8 | ||
|
|
656f8bb5cf | ||
|
|
435cfeea0a | ||
|
|
c5772e5549 | ||
|
|
2ed5a5e368 | ||
|
|
20cd748377 | ||
|
|
dbaec43e4d | ||
|
|
0a9e0ddba9 | ||
|
|
97a3d343f7 | ||
|
|
d30461afc6 | ||
|
|
78117b3e7b | ||
|
|
3b4891279e | ||
|
|
d738633981 | ||
|
|
563472e676 | ||
|
|
db9f925bb1 | ||
|
|
aed9d3899e | ||
|
|
41e5840298 | ||
|
|
9ac1a0140c | ||
|
|
61b10ac330 | ||
|
|
1ef5362edc | ||
|
|
3ea4a7fb47 | ||
|
|
0e4089ef8e | ||
|
|
d10fa8f891 | ||
|
|
e38cf54dac | ||
|
|
f0becd0040 | ||
|
|
82c62b4d8e | ||
|
|
88420311cb | ||
|
|
b423d58a14 | ||
|
|
4ca8d3d6cf | ||
|
|
8d5e69b06c | ||
|
|
b56f5593ab | ||
|
|
53d12e6cf7 | ||
|
|
10941ae732 | ||
|
|
0c2ea5d799 | ||
|
|
e6f1a3ccf3 | ||
|
|
3c0a4a0abf | ||
|
|
c5613888eb | ||
|
|
05eee9c173 | ||
|
|
3d7d1b20ab | ||
|
|
9a40e9b96d | ||
|
|
3770786075 | ||
|
|
13868f89e8 | ||
|
|
45681ed9eb | ||
|
|
6002281874 | ||
|
|
3bb7febeb8 | ||
|
|
5ff014f89d | ||
|
|
448fa8495a | ||
|
|
c1600c9841 | ||
|
|
9a5a003d0a | ||
|
|
53e193d130 | ||
|
|
4dddb00aca | ||
|
|
bf2bc1fdc7 | ||
|
|
9e9c4f79f5 | ||
|
|
65ea9290ea | ||
|
|
2ba89b9e68 | ||
|
|
45ec0e364a | ||
|
|
40163868af | ||
|
|
2984a5a19f | ||
|
|
50599c933f | ||
|
|
2e49971989 | ||
|
|
2d8f7419eb | ||
|
|
87cdc7635a | ||
|
|
c5a81691fb | ||
|
|
42f8a3e65b | ||
|
|
4dbb82a789 | ||
|
|
df56ef5e3f | ||
|
|
27365dc4be | ||
|
|
5fcefa28a7 | ||
|
|
c2617e89c9 | ||
|
|
1ed1751b63 | ||
|
|
29dba9edb3 | ||
|
|
b9788bbafd | ||
|
|
050744627d | ||
|
|
69b4d213b7 | ||
|
|
514635e965 | ||
|
|
5ce3a436c7 | ||
|
|
7cccba3b9a | ||
|
|
3f471d1ac6 | ||
|
|
e602903567 | ||
|
|
534db2d45b | ||
|
|
a4a0335b20 | ||
|
|
62fdd91947 | ||
|
|
aea5293288 | ||
|
|
8143ca158b | ||
|
|
e7afb073d9 | ||
|
|
5af9d29cbe | ||
|
|
2bd7d12312 | ||
|
|
50091bfac8 | ||
|
|
840f688bbf | ||
|
|
2e82bb5632 | ||
|
|
4923589b38 | ||
|
|
23ea1a1a60 | ||
|
|
f42808af94 | ||
|
|
e0aca97f9f | ||
|
|
88fa7c2952 | ||
|
|
be0b01a1e6 | ||
|
|
05ea99441f | ||
|
|
b0b2c046b2 | ||
|
|
d7e62937b2 | ||
|
|
9a004ceda2 | ||
|
|
5e032139cb | ||
|
|
4e77897bfd | ||
|
|
ca06d38c5b | ||
|
|
d59a72ea75 | ||
|
|
9e34437447 | ||
|
|
82502e1a8b | ||
|
|
527ccaff16 | ||
|
|
9e6b706a03 | ||
|
|
05919244bd | ||
|
|
7906ac9348 | ||
|
|
c1fd8fc318 | ||
|
|
e115c8b373 | ||
|
|
99555fa843 | ||
|
|
8b149db0ec | ||
|
|
b988582531 | ||
|
|
1e6850f198 | ||
|
|
eb673d6ed3 | ||
|
|
4b42f9e071 | ||
|
|
46a01ec131 | ||
|
|
3beb6a86f7 | ||
|
|
67336653e0 | ||
|
|
c8bc2d9d16 | ||
|
|
5df461c7e0 | ||
|
|
24865ba26a | ||
|
|
53373b66b9 | ||
|
|
1b93e2030f | ||
|
|
142a64e039 | ||
|
|
fabcd6b73c | ||
|
|
e9e81d96a5 | ||
|
|
79921b0206 | ||
|
|
ee7eb3186d | ||
|
|
6ba96b1103 | ||
|
|
7f467f0fdd | ||
|
|
d3ea7c3a14 | ||
|
|
996292264b | ||
|
|
0346b31628 | ||
|
|
44dafc38e5 | ||
|
|
3ff5c95419 | ||
|
|
c41c5f1916 | ||
|
|
68659f5a32 | ||
|
|
b81ca31aae | ||
|
|
c9ad290ad5 | ||
|
|
b867c46f72 | ||
|
|
7450899b87 | ||
|
|
ca8bf395c3 | ||
|
|
ff676c050f | ||
|
|
7da6ff78c1 | ||
|
|
ea1068a822 | ||
|
|
f29cf07fa4 | ||
|
|
92558ad183 | ||
|
|
826672ea1b | ||
|
|
725f51056f | ||
|
|
53fda33499 | ||
|
|
c2be771486 | ||
|
|
5a1a4bd8bd | ||
|
|
84eff43b49 | ||
|
|
98a2506eb0 | ||
|
|
8cdcfc5e67 | ||
|
|
38449caaed | ||
|
|
d0e4b236a7 | ||
|
|
cf607a0f14 | ||
|
|
4200629347 | ||
|
|
19eb30b3ae | ||
|
|
3062e72282 | ||
|
|
aa5f9ee3ec | ||
|
|
96c9bcd820 | ||
|
|
4197380621 | ||
|
|
c23bca6afe | ||
|
|
edd8a0a64e | ||
|
|
5290553184 | ||
|
|
a82f66cf45 | ||
|
|
dc88e1e16c | ||
|
|
c3988ef184 | ||
|
|
9781d1fcdf | ||
|
|
a08f55cf99 | ||
|
|
e6872c52a3 | ||
|
|
7fb78a0372 | ||
|
|
732d1129ab | ||
|
|
5df2698f77 | ||
|
|
224df7a1ea | ||
|
|
2f99f6ad34 | ||
|
|
845de7aa4d | ||
|
|
593f98190d | ||
|
|
0391c24ab2 | ||
|
|
c78ad9c047 | ||
|
|
fa88fb74c4 | ||
|
|
094125c970 | ||
|
|
f313001b2d | ||
|
|
baa6b44567 | ||
|
|
f10ea03173 | ||
|
|
e0dc7a27a0 | ||
|
|
861219f502 | ||
|
|
63c6ba7e31 | ||
|
|
f370d74609 | ||
|
|
0971af803c | ||
|
|
e1f7c91728 | ||
|
|
0f2992ddec | ||
|
|
079f7690a8 | ||
|
|
6dbaec0cc6 | ||
|
|
6eff8c7b4b | ||
|
|
57a501ebce | ||
|
|
8e3f8c4c14 | ||
|
|
d5ca46157a | ||
|
|
f1811e7f0e | ||
|
|
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 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,7 +7,7 @@
|
||||
/gh-pages
|
||||
/ideaSDK
|
||||
/android-studio/sdk
|
||||
/out
|
||||
out/
|
||||
/tmp
|
||||
workspace.xml
|
||||
*.versionsBackup
|
||||
@@ -21,4 +21,5 @@ workspace.xml
|
||||
.gradle/
|
||||
build/
|
||||
!**/src/**/build
|
||||
!**/test/**/build
|
||||
|
||||
|
||||
9
.idea/artifacts/KotlinPlugin.xml
generated
9
.idea/artifacts/KotlinPlugin.xml
generated
@@ -61,6 +61,9 @@
|
||||
<element id="module-output" name="ir.psi2ir" />
|
||||
<element id="module-output" name="annotation-based-compiler-plugins-ide-support" />
|
||||
<element id="module-output" name="frontend.script" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/json-org.jar" path-in-jar="/" />
|
||||
<element id="module-output" name="idea-gradle" />
|
||||
<element id="module-output" name="idea-jvm" />
|
||||
</element>
|
||||
<element id="library" level="project" name="javax.inject" />
|
||||
<element id="directory" name="jps">
|
||||
@@ -72,6 +75,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" />
|
||||
@@ -102,9 +106,12 @@
|
||||
<element id="archive" name="kotlin-gradle-tooling.jar">
|
||||
<element id="module-output" name="kotlin-gradle-tooling" />
|
||||
</element>
|
||||
<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 id="archive" name="kapt-idea.jar">
|
||||
<element id="module-output" name="kapt3-idea" />
|
||||
</element>
|
||||
</element>
|
||||
<element id="directory" name="kotlinc">
|
||||
<element id="dir-copy" path="$PROJECT_DIR$/dist/kotlinc" />
|
||||
|
||||
2
.idea/dictionaries/yan.xml
generated
2
.idea/dictionaries/yan.xml
generated
@@ -1,8 +1,10 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="yan">
|
||||
<words>
|
||||
<w>deserializes</w>
|
||||
<w>impls</w>
|
||||
<w>kapt</w>
|
||||
<w>parceler</w>
|
||||
<w>uast</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
||||
7
.idea/dictionaries/yole.xml
generated
Normal file
7
.idea/dictionaries/yole.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="yole">
|
||||
<words>
|
||||
<w>multiplatform</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
1
.idea/inspectionProfiles/idea_default.xml
generated
1
.idea/inspectionProfiles/idea_default.xml
generated
@@ -235,7 +235,6 @@
|
||||
<scope name="idea openapi" level="WARNING" enabled="true" />
|
||||
<scope name="runtime.classes" level="ERROR" enabled="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="LoopToCallChain" enabled="false" level="INFO" enabled_by_default="false" />
|
||||
<inspection_tool class="MethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="m_onlyPrivateOrFinal" value="false" />
|
||||
<option name="m_ignoreEmptyMethods" value="true" />
|
||||
|
||||
9
.idea/kotlinc.xml
generated
9
.idea/kotlinc.xml
generated
@@ -1,8 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinCommonCompilerArguments">
|
||||
<option name="languageVersion" value="1.1" />
|
||||
<option name="apiVersion" value="1.1" />
|
||||
<component name="Kotlin2JsCompilerArguments">
|
||||
<option name="sourceMapPrefix" value="" />
|
||||
<option name="sourceMapEmbedSources" value="inlining" />
|
||||
</component>
|
||||
<component name="Kotlin2JvmCompilerArguments">
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
</component>
|
||||
<component name="KotlinCompilerSettings">
|
||||
<option name="additionalArguments" value="-version -Xallow-kotlin-package -Xskip-metadata-version-check" />
|
||||
|
||||
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>
|
||||
6
.idea/libraries/intellij_core.xml
generated
6
.idea/libraries/intellij_core.xml
generated
@@ -7,7 +7,7 @@
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/annotations.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/asm-all.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/guava-19.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/guava-21.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/intellij-core.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/jdom.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/core/jna.jar!/" />
|
||||
@@ -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$/dependencies/guava-21.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>
|
||||
4
.idea/libraries/jline.xml
generated
4
.idea/libraries/jline.xml
generated
@@ -4,11 +4,11 @@
|
||||
<root url="file://$PROJECT_DIR$/annotations" />
|
||||
</ANNOTATIONS>
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/jline.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/jline3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/jline-sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/jline3-sources.jar!/" />
|
||||
</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>
|
||||
41
.idea/libraries/robolectric.xml
generated
Normal file
41
.idea/libraries/robolectric.xml
generated
Normal file
@@ -0,0 +1,41 @@
|
||||
<component name="libraryTable">
|
||||
<library name="robolectric">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/accessibility-test-framework-2.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/android-all-6.0.0_r1-robolectric-0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/annotations-12.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/ant-1.8.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/ant-launcher-1.8.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-5.0.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-analysis-5.0.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-commons-5.0.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-tree-5.0.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-util-5.0.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/bcprov-jdk16-1.46.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/guava-19.0-rc2.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/hamcrest-core-1.3.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/hamcrest-library-1.3.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/icu4j-53.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/junit-4.8.2.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-ant-tasks-2.1.3.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/protobuf-java-2.6.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-3.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-annotations-3.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-resources-3.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-utils-3.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/shadows-core-3.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/sqlite4java-0.282.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/vtd-xml-2.11.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/xmlpull-1.1.3.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/xpp3_min-1.1.4c.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/xstream-1.4.8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-3.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-ant-tasks-2.1.3-sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-3.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
10
.idea/libraries/uast_java.xml
generated
10
.idea/libraries/uast_java.xml
generated
@@ -1,15 +1,13 @@
|
||||
<component name="libraryTable">
|
||||
<library name="uast-java">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/uast-common.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/uast-java.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/uast-tests.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/idea.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/openapi.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/uast-common-sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/uast-java-sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/uast-tests-sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
16
.idea/modules.xml
generated
16
.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" />
|
||||
@@ -51,7 +51,9 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-android/idea-android-output-parser/idea-android-output-parser.iml" filepath="$PROJECT_DIR$/idea/idea-android/idea-android-output-parser/idea-android-output-parser.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" filepath="$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-core/idea-core.iml" filepath="$PROJECT_DIR$/idea/idea-core/idea-core.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-gradle/idea-gradle.iml" filepath="$PROJECT_DIR$/idea/idea-gradle/idea-gradle.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" filepath="$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-jvm/idea-jvm.iml" filepath="$PROJECT_DIR$/idea/idea-jvm/idea-jvm.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" filepath="$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-maven/idea-maven.iml" filepath="$PROJECT_DIR$/idea/idea-maven/idea-maven.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" group="ide" />
|
||||
@@ -63,7 +65,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 +77,15 @@
|
||||
<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$/plugins/kapt3-idea/kapt3-idea.iml" filepath="$PROJECT_DIR$/plugins/kapt3-idea/kapt3-idea.iml" />
|
||||
<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 +93,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" />
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</extension>
|
||||
<module name="compiler-tests" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9-ea" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9" />
|
||||
<option name="PACKAGE_NAME" value="org.jetbrains.kotlin.codegen" />
|
||||
<option name="MAIN_CLASS_NAME" value="org.jetbrains.kotlin.codegen.CodegenJdkCommonTestSuite" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</extension>
|
||||
<module name="compiler-tests" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9-ea" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9" />
|
||||
<option name="PACKAGE_NAME" value="org.jetbrains.kotlin.codegen" />
|
||||
<option name="MAIN_CLASS_NAME" value="org.jetbrains.kotlin.codegen.CodegenJdkCommonTestSuite" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</extension>
|
||||
<module name="compiler-tests" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9-ea" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9" />
|
||||
<option name="PACKAGE_NAME" value="org.jetbrains.kotlin.codegen" />
|
||||
<option name="MAIN_CLASS_NAME" value="org.jetbrains.kotlin.codegen.CodegenJdkCommonTestSuite" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
|
||||
2
.idea/runConfigurations/IDEA.xml
generated
2
.idea/runConfigurations/IDEA.xml
generated
@@ -3,7 +3,7 @@
|
||||
<log_file path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" checked="true" skipped="true" show_all="false" alias="idea.log" />
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=128m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/ideaSDK/bin" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<log_file path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" checked="true" skipped="true" show_all="false" alias="idea.log" />
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=128m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Didea.ProcessCanceledException=disabled -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Didea.ProcessCanceledException=disabled -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/ideaSDK/bin" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</extension>
|
||||
<module name="compiler-tests-java8" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9-ea" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="9" />
|
||||
<option name="PACKAGE_NAME" value="org.jetbrains.kotlin" />
|
||||
<option name="MAIN_CLASS_NAME" value="" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
|
||||
2
.idea/runConfigurations/Update_Dist_Run.xml
generated
2
.idea/runConfigurations/Update_Dist_Run.xml
generated
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Update-Dist-Run" type="Application" factoryName="Application" singleton="true">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=64m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/ideaSDK/bin" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
|
||||
3035
ChangeLog.md
3035
ChangeLog.md
File diff suppressed because it is too large
Load Diff
@@ -26,10 +26,14 @@
|
||||
<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" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/common/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/jdk7/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/jdk8/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/jre7/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/jre8/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/libraries/stdlib/js/build" />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
[](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||
<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)
|
||||
@@ -37,6 +38,8 @@ In order to build Kotlin distribution you need to have:
|
||||
JDK_17="path to JDK 1.7"
|
||||
JDK_18="path to JDK 1.8"
|
||||
|
||||
> Note: The JDK 6 for MacOS is not available on Oracle's site. You can [download it here](https://support.apple.com/kb/DL1572).
|
||||
|
||||
## Building
|
||||
|
||||
To build this project, first time you try to build you need to run this:
|
||||
@@ -113,7 +116,7 @@ From this root project there are Run/Debug Configurations for running IDEA or th
|
||||
|
||||
We love contributions! There's [lots to do on Kotlin](https://youtrack.jetbrains.com/issues/KT) and on the
|
||||
[standard library](https://youtrack.jetbrains.com/issues/KT?q=%23Kotlin%20%23Unresolved%20and%20(links:%20KT-2554,%20KT-4089%20or%20%23Libraries)) so why not chat with us
|
||||
about what you're interested in doing? Please join the #kontributors channel in [our Slack chat](http://kotlinslackin.herokuapp.com/)
|
||||
about what you're interested in doing? Please join the #kontributors channel in [our Slack chat](http://slack.kotlinlang.org/)
|
||||
and let us know about your plans.
|
||||
|
||||
If you want to find some issues to start off with, try [this query](https://youtrack.jetbrains.com/issues/KT?q=tag:%20%7BUp%20For%20Grabs%7D%20%23Unresolved) which should find all Kotlin issues that marked as "up-for-grabs".
|
||||
|
||||
@@ -39,9 +39,7 @@ class KotlinCompilerAdapter : Javac13() {
|
||||
return argument
|
||||
}
|
||||
|
||||
override fun getSupportedFileExtensions(): Array<String> {
|
||||
return super.getSupportedFileExtensions() + KOTLIN_EXTENSIONS
|
||||
}
|
||||
override fun getSupportedFileExtensions(): Array<String> = super.getSupportedFileExtensions() + KOTLIN_EXTENSIONS
|
||||
|
||||
@Throws(BuildException::class)
|
||||
override fun execute(): Boolean {
|
||||
|
||||
@@ -15,5 +15,7 @@
|
||||
<orderEntry type="module" module-name="tests-common" scope="TEST" />
|
||||
<orderEntry type="library" scope="TEST" name="idea-full" level="project" />
|
||||
<orderEntry type="library" name="kotlin-reflect" level="project" />
|
||||
<orderEntry type="module" module-name="js.serializer" />
|
||||
<orderEntry type="module" module-name="js.frontend" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -21,17 +21,15 @@ import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import java.io.File
|
||||
|
||||
open class GeneratedFile<Target>(
|
||||
val target: Target,
|
||||
val sourceFiles: Collection<File>,
|
||||
val outputFile: File
|
||||
open class GeneratedFile(
|
||||
val sourceFiles: Collection<File>,
|
||||
val outputFile: File
|
||||
)
|
||||
|
||||
class GeneratedJvmClass<Target> (
|
||||
target: Target,
|
||||
class GeneratedJvmClass (
|
||||
sourceFiles: Collection<File>,
|
||||
outputFile: File
|
||||
) : GeneratedFile<Target>(target, sourceFiles, outputFile) {
|
||||
) : GeneratedFile(sourceFiles, outputFile) {
|
||||
val outputClass = LocalFileKotlinClass.create(outputFile).sure {
|
||||
"Couldn't load KotlinClass from $outputFile; it may happen because class doesn't have valid Kotlin annotations"
|
||||
}
|
||||
|
||||
@@ -16,13 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.compilerRunner;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.jvm.JvmClassMappingKt;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KProperty1;
|
||||
import kotlin.reflect.KVisibility;
|
||||
import kotlin.reflect.full.KClasses;
|
||||
import kotlin.reflect.jvm.ReflectJvmMapping;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.Argument;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt;
|
||||
import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -33,39 +41,35 @@ public class ArgumentUtils {
|
||||
|
||||
@NotNull
|
||||
public static List<String> convertArgumentsToStringList(@NotNull CommonToolArguments arguments)
|
||||
throws InstantiationException, IllegalAccessException {
|
||||
throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
List<String> result = new ArrayList<>();
|
||||
convertArgumentsToStringList(arguments, arguments.getClass().newInstance(), arguments.getClass(), result);
|
||||
result.addAll(arguments.freeArgs);
|
||||
Class<? extends CommonToolArguments> argumentsClass = arguments.getClass();
|
||||
convertArgumentsToStringList(arguments, argumentsClass.newInstance(), JvmClassMappingKt.getKotlinClass(argumentsClass), result);
|
||||
result.addAll(arguments.getFreeArgs());
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void convertArgumentsToStringList(
|
||||
@NotNull CommonToolArguments arguments,
|
||||
@NotNull CommonToolArguments defaultArguments,
|
||||
@NotNull Class<?> clazz,
|
||||
@NotNull KClass<?> clazz,
|
||||
@NotNull List<String> result
|
||||
) throws IllegalAccessException, InstantiationException {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
Argument argument = field.getAnnotation(Argument.class);
|
||||
) throws IllegalAccessException, InstantiationException, InvocationTargetException {
|
||||
for (KProperty1 property : KClasses.getMemberProperties(clazz)) {
|
||||
Argument argument = ContainerUtil.findInstance(property.getAnnotations(), Argument.class);
|
||||
if (argument == null) continue;
|
||||
|
||||
Object value;
|
||||
Object defaultValue;
|
||||
try {
|
||||
value = field.get(arguments);
|
||||
defaultValue = field.get(defaultArguments);
|
||||
}
|
||||
catch (IllegalAccessException ignored) {
|
||||
// skip this field
|
||||
continue;
|
||||
}
|
||||
if (property.getVisibility() != KVisibility.PUBLIC) continue;
|
||||
|
||||
Object value = property.get(arguments);
|
||||
Object defaultValue = property.get(defaultArguments);
|
||||
|
||||
if (value == null || Objects.equals(value, defaultValue)) continue;
|
||||
|
||||
Class<?> fieldType = field.getType();
|
||||
Type propertyJavaType = ReflectJvmMapping.getJavaType(property.getReturnType());
|
||||
|
||||
if (fieldType.isArray()) {
|
||||
if (propertyJavaType instanceof Class && ((Class) propertyJavaType).isArray()) {
|
||||
Object[] values = (Object[]) value;
|
||||
if (values.length == 0) continue;
|
||||
value = StringsKt.join(Arrays.asList(values), ",");
|
||||
@@ -73,7 +77,7 @@ public class ArgumentUtils {
|
||||
|
||||
result.add(argument.value());
|
||||
|
||||
if (fieldType == boolean.class || fieldType == Boolean.class) continue;
|
||||
if (propertyJavaType == boolean.class || propertyJavaType == Boolean.class) continue;
|
||||
|
||||
if (ParseCommandLineArgumentsKt.isAdvanced(argument)) {
|
||||
result.set(result.size() - 1, argument.value() + "=" + value.toString());
|
||||
@@ -82,10 +86,5 @@ public class ArgumentUtils {
|
||||
result.add(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> superClazz = clazz.getSuperclass();
|
||||
if (superClazz != null) {
|
||||
convertArgumentsToStringList(arguments, defaultArguments, superClazz, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.compilerRunner
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
|
||||
class MessageCollectorToOutputItemsCollectorAdapter(
|
||||
private val delegate: MessageCollector,
|
||||
private val outputCollector: OutputItemsCollector
|
||||
) : MessageCollector by delegate {
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
// TODO: consider adding some other way of passing input -> output mapping from compiler, e.g. dedicated service
|
||||
OutputMessageUtil.parseOutputMessage(message)?.let {
|
||||
outputCollector.add(it.sourceFiles, it.outputFile)
|
||||
}
|
||||
delegate.report(severity, message, location)
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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.compilerRunner;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
public class SimpleOutputItem {
|
||||
private final Collection<File> sourceFiles;
|
||||
private final File outputFile;
|
||||
|
||||
public SimpleOutputItem(@NotNull Collection<File> sourceFiles, @NotNull File outputFile) {
|
||||
this.sourceFiles = sourceFiles;
|
||||
this.outputFile = outputFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<File> getSourceFiles() {
|
||||
return sourceFiles;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public File getOutputFile() {
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sourceFiles + " -> " + outputFile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.compilerRunner
|
||||
|
||||
import org.jetbrains.kotlin.build.GeneratedFile
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import java.io.File
|
||||
|
||||
data class SimpleOutputItem(val sourceFiles: Collection<File>, val outputFile: File) {
|
||||
override fun toString(): String =
|
||||
"$sourceFiles->$outputFile"
|
||||
}
|
||||
|
||||
fun SimpleOutputItem.toGeneratedFile(): GeneratedFile =
|
||||
when {
|
||||
outputFile.name.endsWith(".class") -> GeneratedJvmClass(sourceFiles, outputFile)
|
||||
else -> GeneratedFile(sourceFiles, outputFile)
|
||||
}
|
||||
@@ -24,11 +24,9 @@ import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
private val NORMAL_VERSION = 8
|
||||
private val EXPERIMENTAL_VERSION = 4
|
||||
private val DATA_CONTAINER_VERSION = 2
|
||||
|
||||
private val NORMAL_VERSION_FILE_NAME = "format-version.txt"
|
||||
private val EXPERIMENTAL_VERSION_FILE_NAME = "experimental-format-version.txt"
|
||||
private val DATA_CONTAINER_VERSION_FILE_NAME = "data-container-format-version.txt"
|
||||
|
||||
class CacheVersion(
|
||||
@@ -92,32 +90,23 @@ class CacheVersion(
|
||||
REBUILD_ALL_KOTLIN,
|
||||
REBUILD_CHUNK,
|
||||
CLEAN_NORMAL_CACHES,
|
||||
CLEAN_EXPERIMENTAL_CACHES,
|
||||
CLEAN_DATA_CONTAINER,
|
||||
DO_NOTHING
|
||||
}
|
||||
}
|
||||
|
||||
fun normalCacheVersion(dataRoot: File): CacheVersion =
|
||||
fun normalCacheVersion(dataRoot: File, enabled: Boolean? = null): CacheVersion =
|
||||
CacheVersion(ownVersion = NORMAL_VERSION,
|
||||
versionFile = File(dataRoot, NORMAL_VERSION_FILE_NAME),
|
||||
whenVersionChanged = CacheVersion.Action.REBUILD_CHUNK,
|
||||
whenTurnedOn = CacheVersion.Action.REBUILD_CHUNK,
|
||||
whenTurnedOff = CacheVersion.Action.CLEAN_NORMAL_CACHES,
|
||||
isEnabled = { IncrementalCompilation.isEnabled() })
|
||||
isEnabled = { enabled ?: IncrementalCompilation.isEnabled() })
|
||||
|
||||
fun experimentalCacheVersion(dataRoot: File): CacheVersion =
|
||||
CacheVersion(ownVersion = EXPERIMENTAL_VERSION,
|
||||
versionFile = File(dataRoot, EXPERIMENTAL_VERSION_FILE_NAME),
|
||||
whenVersionChanged = CacheVersion.Action.REBUILD_CHUNK,
|
||||
whenTurnedOn = CacheVersion.Action.REBUILD_CHUNK,
|
||||
whenTurnedOff = CacheVersion.Action.CLEAN_EXPERIMENTAL_CACHES,
|
||||
isEnabled = { IncrementalCompilation.isExperimental() })
|
||||
|
||||
fun dataContainerCacheVersion(dataRoot: File): CacheVersion =
|
||||
fun dataContainerCacheVersion(dataRoot: File, enabled: Boolean? = null): CacheVersion =
|
||||
CacheVersion(ownVersion = DATA_CONTAINER_VERSION,
|
||||
versionFile = File(dataRoot, DATA_CONTAINER_VERSION_FILE_NAME),
|
||||
whenVersionChanged = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||
whenTurnedOn = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||
whenTurnedOff = CacheVersion.Action.CLEAN_DATA_CONTAINER,
|
||||
isEnabled = { IncrementalCompilation.isExperimental() })
|
||||
isEnabled = { enabled ?: IncrementalCompilation.isEnabled() })
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.serialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
|
||||
class ChangesCollector {
|
||||
private val removedMembers = hashMapOf<FqName, MutableSet<String>>()
|
||||
private val changedMembers = hashMapOf<FqName, MutableSet<String>>()
|
||||
private val areSubclassesAffected = hashMapOf<FqName, Boolean>()
|
||||
|
||||
fun changes(): List<ChangeInfo> {
|
||||
val changes = arrayListOf<ChangeInfo>()
|
||||
|
||||
for ((fqName, members) in removedMembers) {
|
||||
if (members.isNotEmpty()) {
|
||||
changes.add(ChangeInfo.Removed(fqName, members))
|
||||
}
|
||||
}
|
||||
|
||||
for ((fqName, members) in changedMembers) {
|
||||
if (members.isNotEmpty()) {
|
||||
changes.add(ChangeInfo.MembersChanged(fqName, members))
|
||||
}
|
||||
}
|
||||
|
||||
for ((fqName, areSubclassesAffected) in areSubclassesAffected) {
|
||||
changes.add(ChangeInfo.SignatureChanged(fqName, areSubclassesAffected))
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
private fun <T, R> MutableMap<T, MutableSet<R>>.getSet(key: T) =
|
||||
getOrPut(key) { HashSet() }
|
||||
|
||||
private fun collectChangedMember(scope: FqName, name: String) {
|
||||
changedMembers.getSet(scope).add(name)
|
||||
}
|
||||
|
||||
private fun collectRemovedMember(scope: FqName, name: String) {
|
||||
removedMembers.getSet(scope).add(name)
|
||||
}
|
||||
|
||||
private fun collectChangedMembers(scope: FqName, names: Collection<String>) {
|
||||
if (names.isNotEmpty()) {
|
||||
changedMembers.getSet(scope).addAll(names)
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectRemovedMembers(scope: FqName, names: Collection<String>) {
|
||||
if (names.isNotEmpty()) {
|
||||
removedMembers.getSet(scope).addAll(names)
|
||||
}
|
||||
}
|
||||
|
||||
fun collectProtoChanges(oldData: ProtoData?, newData: ProtoData?) {
|
||||
if (oldData == null && newData == null) {
|
||||
throw IllegalStateException("Old and new value are null")
|
||||
}
|
||||
|
||||
if (oldData == null) {
|
||||
newData!!.collectAll(isRemoved = false)
|
||||
return
|
||||
}
|
||||
|
||||
if (newData == null) {
|
||||
oldData.collectAll(isRemoved = true)
|
||||
return
|
||||
}
|
||||
|
||||
when (oldData) {
|
||||
is ClassProtoData -> {
|
||||
when (newData) {
|
||||
is ClassProtoData -> {
|
||||
val fqName = oldData.nameResolver.getClassId(oldData.proto.fqName).asSingleFqName()
|
||||
val diff = DifferenceCalculatorForClass(oldData, newData).difference()
|
||||
if (diff.isClassAffected) {
|
||||
collectSignature(oldData, diff.areSubclassesAffected)
|
||||
}
|
||||
collectChangedMembers(fqName, diff.changedMembersNames)
|
||||
}
|
||||
is PackagePartProtoData -> {
|
||||
collectSignature(oldData, areSubclassesAffected = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
is PackagePartProtoData -> {
|
||||
when (newData) {
|
||||
is ClassProtoData -> {
|
||||
collectSignature(newData, areSubclassesAffected = false)
|
||||
}
|
||||
is PackagePartProtoData -> {
|
||||
val diff = DifferenceCalculatorForPackageFacade(oldData, newData).difference()
|
||||
collectChangedMembers(oldData.packageFqName, diff.changedMembersNames)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List<MessageLite>): Set<String> =
|
||||
members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet()
|
||||
|
||||
private fun ProtoData.collectAll(isRemoved: Boolean) =
|
||||
when (this) {
|
||||
is PackagePartProtoData -> collectAllFromPackage(isRemoved)
|
||||
is ClassProtoData -> collectAllFromClass(isRemoved)
|
||||
}
|
||||
|
||||
private fun PackagePartProtoData.collectAllFromPackage(isRemoved: Boolean) {
|
||||
val memberNames =
|
||||
proto.getNonPrivateNames(
|
||||
nameResolver,
|
||||
ProtoBuf.Package::getFunctionList,
|
||||
ProtoBuf.Package::getPropertyList
|
||||
)
|
||||
|
||||
if (isRemoved) {
|
||||
collectRemovedMembers(packageFqName, memberNames)
|
||||
}
|
||||
else {
|
||||
collectChangedMembers(packageFqName, memberNames)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassProtoData.collectAllFromClass(isRemoved: Boolean) {
|
||||
val classFqName = nameResolver.getClassId(proto.fqName).asSingleFqName()
|
||||
val kind = Flags.CLASS_KIND.get(proto.flags)
|
||||
|
||||
if (kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
|
||||
val memberNames =
|
||||
proto.getNonPrivateNames(
|
||||
nameResolver,
|
||||
ProtoBuf.Class::getConstructorList,
|
||||
ProtoBuf.Class::getFunctionList,
|
||||
ProtoBuf.Class::getPropertyList
|
||||
) + proto.enumEntryList.map { nameResolver.getString(it.name) }
|
||||
|
||||
val collectMember = if (isRemoved) this@ChangesCollector::collectRemovedMember else this@ChangesCollector::collectChangedMember
|
||||
collectMember(classFqName.parent(), classFqName.shortName().asString())
|
||||
memberNames.forEach { collectMember(classFqName, it) }
|
||||
}
|
||||
else {
|
||||
collectSignature(classFqName, areSubclassesAffected = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun collectMemberIfValueWasChanged(scope: FqName, name: String, oldValue: Any?, newValue: Any?) {
|
||||
if (oldValue == null && newValue == null) {
|
||||
throw IllegalStateException("Old and new value are null for $scope#$name")
|
||||
}
|
||||
|
||||
if (oldValue != null && newValue == null) {
|
||||
collectRemovedMember(scope, name)
|
||||
}
|
||||
else if (oldValue != newValue) {
|
||||
collectChangedMember(scope, name)
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectSignature(classData: ClassProtoData, areSubclassesAffected: Boolean) {
|
||||
val fqName = classData.nameResolver.getClassId(classData.proto.fqName).asSingleFqName()
|
||||
collectSignature(fqName, areSubclassesAffected)
|
||||
}
|
||||
|
||||
fun collectSignature(fqName: FqName, areSubclassesAffected: Boolean) {
|
||||
val prevValue = this.areSubclassesAffected[fqName] ?: false
|
||||
this.areSubclassesAffected[fqName] = prevValue || areSubclassesAffected
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.serialization.deserialization.supertypes
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Incremental cache common for JVM and JS
|
||||
*/
|
||||
abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(workingDir) {
|
||||
companion object {
|
||||
private val SUBTYPES = "subtypes"
|
||||
private val SUPERTYPES = "supertypes"
|
||||
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
||||
}
|
||||
|
||||
private val dependents = arrayListOf<IncrementalCacheCommon>()
|
||||
fun addDependentCache(cache: IncrementalCacheCommon) {
|
||||
dependents.add(cache)
|
||||
}
|
||||
val thisWithDependentCaches: Iterable<IncrementalCacheCommon> by lazy {
|
||||
val result = arrayListOf(this)
|
||||
result.addAll(dependents)
|
||||
result
|
||||
}
|
||||
|
||||
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
||||
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
||||
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
|
||||
|
||||
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||
subtypesMap[className].asSequence()
|
||||
|
||||
fun getSourceFileIfClass(fqName: FqName): File? =
|
||||
classFqNameToSourceMap[fqName]
|
||||
|
||||
abstract fun markDirty(removedAndCompiledSources: List<File>)
|
||||
|
||||
protected fun addToClassStorage(proto: ProtoBuf.Class, nameResolver: NameResolver, srcFile: File) {
|
||||
val supertypes = proto.supertypes(TypeTable(proto.typeTable))
|
||||
val parents = supertypes.map { nameResolver.getClassId(it.className).asSingleFqName() }
|
||||
.filter { it.asString() != "kotlin.Any" }
|
||||
.toSet()
|
||||
val child = nameResolver.getClassId(proto.fqName).asSingleFqName()
|
||||
|
||||
parents.forEach { subtypesMap.add(it, child) }
|
||||
|
||||
val removedSupertypes = supertypesMap[child].filter { it !in parents }
|
||||
removedSupertypes.forEach { subtypesMap.removeValues(it, setOf(child)) }
|
||||
|
||||
supertypesMap[child] = parents
|
||||
classFqNameToSourceMap[child] = srcFile
|
||||
}
|
||||
|
||||
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>) {
|
||||
if (removedClasses.isEmpty()) return
|
||||
|
||||
val removedFqNames = removedClasses.toSet()
|
||||
|
||||
for (cache in thisWithDependentCaches) {
|
||||
val parentsFqNames = hashSetOf<FqName>()
|
||||
val childrenFqNames = hashSetOf<FqName>()
|
||||
|
||||
for (removedFqName in removedFqNames) {
|
||||
parentsFqNames.addAll(cache.supertypesMap[removedFqName])
|
||||
childrenFqNames.addAll(cache.subtypesMap[removedFqName])
|
||||
|
||||
cache.supertypesMap.remove(removedFqName)
|
||||
cache.subtypesMap.remove(removedFqName)
|
||||
}
|
||||
|
||||
for (child in childrenFqNames) {
|
||||
cache.supertypesMap.removeValues(child, removedFqNames)
|
||||
}
|
||||
|
||||
for (parent in parentsFqNames) {
|
||||
cache.subtypesMap.removeValues(parent, removedFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
removedFqNames.forEach { classFqNameToSourceMap.remove(it) }
|
||||
}
|
||||
|
||||
protected class ClassFqNameToSourceMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
|
||||
operator fun set(fqName: FqName, sourceFile: File) {
|
||||
storage[fqName.asString()] = sourceFile.canonicalPath
|
||||
}
|
||||
|
||||
operator fun get(fqName: FqName): File? =
|
||||
storage[fqName.asString()]?.let(::File)
|
||||
|
||||
fun remove(fqName: FqName) {
|
||||
storage.remove(fqName.asString())
|
||||
}
|
||||
|
||||
override fun dumpValue(value: String) = value
|
||||
}
|
||||
}
|
||||
@@ -1,834 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.io.BooleanDataDescriptor
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import gnu.trove.THashSet
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.incremental.ChangeInfo.MembersChanged
|
||||
import org.jetbrains.kotlin.incremental.ChangeInfo.Removed
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.serialization.deserialization.supertypes
|
||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.io.File
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
|
||||
val KOTLIN_CACHE_DIRECTORY_NAME = "kotlin"
|
||||
|
||||
open class IncrementalCacheImpl<Target>(
|
||||
private val targetDataRoot: File,
|
||||
targetOutputDir: File?,
|
||||
target: Target
|
||||
) : BasicMapsOwner(), IncrementalCache {
|
||||
companion object {
|
||||
private val PROTO_MAP = "proto"
|
||||
private val CONSTANTS_MAP = "constants"
|
||||
private val PACKAGE_PARTS = "package-parts"
|
||||
private val MULTIFILE_CLASS_FACADES = "multifile-class-facades"
|
||||
private val MULTIFILE_CLASS_PARTS = "multifile-class-parts"
|
||||
private val SOURCE_TO_CLASSES = "source-to-classes"
|
||||
private val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
||||
private val INLINE_FUNCTIONS = "inline-functions"
|
||||
private val SUBTYPES = "subtypes"
|
||||
private val SUPERTYPES = "supertypes"
|
||||
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
||||
private val INTERNAL_NAME_TO_SOURCE = "internal-name-to-source"
|
||||
|
||||
private val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
|
||||
}
|
||||
|
||||
private val baseDir = File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)
|
||||
private val experimentalMaps = arrayListOf<BasicMap<*, *>>()
|
||||
|
||||
private fun <K, V, M : BasicMap<K, V>> registerExperimentalMap(map: M): M {
|
||||
experimentalMaps.add(map)
|
||||
return registerMap(map)
|
||||
}
|
||||
|
||||
protected val String.storageFile: File
|
||||
get() = File(baseDir, this + "." + CACHE_EXTENSION)
|
||||
|
||||
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
|
||||
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
|
||||
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
|
||||
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
|
||||
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
|
||||
private val sourceToClassesMap = registerMap(SourceToClassesMap(SOURCE_TO_CLASSES.storageFile))
|
||||
private val dirtyOutputClassesMap = registerMap(DirtyOutputClassesMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
||||
private val subtypesMap = registerExperimentalMap(SubtypesMap(SUBTYPES.storageFile))
|
||||
private val supertypesMap = registerExperimentalMap(SupertypesMap(SUPERTYPES.storageFile))
|
||||
private val classFqNameToSourceMap = registerExperimentalMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
|
||||
// todo: try to use internal names only?
|
||||
private val internalNameToSource = registerExperimentalMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile))
|
||||
|
||||
private val dependents = arrayListOf<IncrementalCacheImpl<Target>>()
|
||||
private val outputDir by lazy(LazyThreadSafetyMode.NONE) { requireNotNull(targetOutputDir) { "Target is expected to have output directory: $target" } }
|
||||
|
||||
val thisWithDependentCaches: Iterable<IncrementalCacheImpl<Target>> by lazy {
|
||||
val result = arrayListOf(this)
|
||||
result.addAll(dependents)
|
||||
result
|
||||
}
|
||||
|
||||
override fun registerInline(fromPath: String, jvmSignature: String, toPath: String) {
|
||||
}
|
||||
|
||||
protected open fun debugLog(message: String) {}
|
||||
|
||||
fun addDependentCache(cache: IncrementalCacheImpl<Target>) {
|
||||
dependents.add(cache)
|
||||
}
|
||||
|
||||
fun markOutputClassesDirty(removedAndCompiledSources: List<File>) {
|
||||
for (sourceFile in removedAndCompiledSources) {
|
||||
val classes = sourceToClassesMap[sourceFile]
|
||||
classes.forEach {
|
||||
dirtyOutputClassesMap.markDirty(it.internalName)
|
||||
}
|
||||
|
||||
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
||||
}
|
||||
}
|
||||
|
||||
// used in gradle
|
||||
@Suppress("unused")
|
||||
fun classesBySources(sources: Iterable<File>): Iterable<JvmClassName> =
|
||||
sources.flatMap { sourceToClassesMap[it] }
|
||||
|
||||
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||
subtypesMap[className].asSequence()
|
||||
|
||||
fun getSourceFileIfClass(fqName: FqName): File? =
|
||||
classFqNameToSourceMap[fqName]
|
||||
|
||||
fun sourcesByInternalName(internalName: String): Collection<File> =
|
||||
internalNameToSource[internalName]
|
||||
|
||||
fun isMultifileFacade(className: JvmClassName): Boolean =
|
||||
className.internalName in multifileFacadeToParts
|
||||
|
||||
override fun getClassFilePath(internalClassName: String): String {
|
||||
return toSystemIndependentName(File(outputDir, "$internalClassName.class").canonicalPath)
|
||||
}
|
||||
|
||||
fun saveModuleMappingToCache(sourceFiles: Collection<File>, file: File): CompilationResult {
|
||||
val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)
|
||||
protoMap.process(jvmClassName, file.readBytes(), emptyArray<String>(), isPackage = false, checkChangesIsOpenPart = false)
|
||||
dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME)
|
||||
sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) }
|
||||
return CompilationResult.NO_CHANGES
|
||||
}
|
||||
|
||||
open fun saveFileToCache(generatedClass: GeneratedJvmClass<Target>): CompilationResult {
|
||||
val sourceFiles: Collection<File> = generatedClass.sourceFiles
|
||||
val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass
|
||||
val className = kotlinClass.className
|
||||
|
||||
dirtyOutputClassesMap.notDirty(className.internalName)
|
||||
sourceFiles.forEach {
|
||||
sourceToClassesMap.add(it, className)
|
||||
}
|
||||
|
||||
if (IncrementalCompilation.isExperimental()) {
|
||||
internalNameToSource[className.internalName] = sourceFiles
|
||||
}
|
||||
|
||||
if (kotlinClass.classId.isLocal) {
|
||||
return CompilationResult.NO_CHANGES
|
||||
}
|
||||
|
||||
val header = kotlinClass.classHeader
|
||||
val changesInfo = when (header.kind) {
|
||||
KotlinClassHeader.Kind.FILE_FACADE -> {
|
||||
assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }
|
||||
packagePartMap.addPackagePart(className)
|
||||
|
||||
protoMap.process(kotlinClass, isPackage = true) +
|
||||
constantsMap.process(kotlinClass, isPackage = true) +
|
||||
inlineFunctionsMap.process(kotlinClass, isPackage = true)
|
||||
}
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS -> {
|
||||
val partNames = kotlinClass.classHeader.data?.toList()
|
||||
?: throw AssertionError("Multifile class has no parts: ${kotlinClass.className}")
|
||||
multifileFacadeToParts[className] = partNames
|
||||
// When a class is replaced with a facade with the same name,
|
||||
// the class' proto wouldn't ever be deleted,
|
||||
// because we don't write proto for multifile facades.
|
||||
// As a workaround we can remove proto values for multifile facades.
|
||||
val additionalChangeInfo = if (className in protoMap) {
|
||||
val info = ChangeInfo.SignatureChanged(className.fqNameForClassNameWithoutDollars, areSubclassesAffected = true)
|
||||
CompilationResult(protoChanged = true, changes = sequenceOf(info))
|
||||
}
|
||||
else CompilationResult.NO_CHANGES
|
||||
protoMap.remove(className)
|
||||
classFqNameToSourceMap.remove(className.fqNameForClassNameWithoutDollars)
|
||||
internalNameToSource.remove(className.internalName)
|
||||
|
||||
// TODO NO_CHANGES? (delegates only)
|
||||
constantsMap.process(kotlinClass, isPackage = true) +
|
||||
inlineFunctionsMap.process(kotlinClass, isPackage = true) +
|
||||
additionalChangeInfo
|
||||
}
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
|
||||
assert(sourceFiles.size == 1) { "Multifile class part from several source files: $sourceFiles" }
|
||||
packagePartMap.addPackagePart(className)
|
||||
partToMultifileFacade.set(className.internalName, header.multifileClassName!!)
|
||||
|
||||
protoMap.process(kotlinClass, isPackage = true) +
|
||||
constantsMap.process(kotlinClass, isPackage = true) +
|
||||
inlineFunctionsMap.process(kotlinClass, isPackage = true)
|
||||
}
|
||||
KotlinClassHeader.Kind.CLASS -> {
|
||||
assert(sourceFiles.size == 1) { "Class is expected to have only one source file: $sourceFiles" }
|
||||
addToClassStorage(kotlinClass, sourceFiles.first())
|
||||
|
||||
protoMap.process(kotlinClass, isPackage = false) +
|
||||
constantsMap.process(kotlinClass, isPackage = false) +
|
||||
inlineFunctionsMap.process(kotlinClass, isPackage = false)
|
||||
}
|
||||
else -> CompilationResult.NO_CHANGES
|
||||
}
|
||||
|
||||
changesInfo.logIfSomethingChanged(className)
|
||||
return changesInfo
|
||||
}
|
||||
|
||||
private fun CompilationResult.logIfSomethingChanged(className: JvmClassName) {
|
||||
if (this == CompilationResult.NO_CHANGES) return
|
||||
|
||||
debugLog("$className is changed: $this")
|
||||
}
|
||||
|
||||
private fun computeChanges(className: JvmClassName, createChangeInfo: (FqName, Collection<String>) -> ChangeInfo): List<ChangeInfo> {
|
||||
fun <T> T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List<MessageLite>): Set<String> =
|
||||
members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet()
|
||||
|
||||
if (className.internalName == MODULE_MAPPING_FILE_NAME) return emptyList()
|
||||
|
||||
val mapValue = protoMap[className] ?: return emptyList()
|
||||
|
||||
return when {
|
||||
mapValue.isPackageFacade -> {
|
||||
val packageData = JvmProtoBufUtil.readPackageDataFrom(mapValue.bytes, mapValue.strings)
|
||||
|
||||
val memberNames =
|
||||
packageData.packageProto.getNonPrivateNames(
|
||||
packageData.nameResolver,
|
||||
ProtoBuf.Package::getFunctionList,
|
||||
ProtoBuf.Package::getPropertyList
|
||||
)
|
||||
|
||||
listOf(createChangeInfo(className.packageFqName, memberNames))
|
||||
}
|
||||
else -> {
|
||||
val classData = JvmProtoBufUtil.readClassDataFrom(mapValue.bytes, mapValue.strings)
|
||||
|
||||
val classFqName = className.fqNameForClassNameWithoutDollars
|
||||
val kind = Flags.CLASS_KIND.get(classData.classProto.flags)
|
||||
|
||||
if (kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
|
||||
val memberNames =
|
||||
classData.classProto.getNonPrivateNames(
|
||||
classData.nameResolver,
|
||||
ProtoBuf.Class::getConstructorList,
|
||||
ProtoBuf.Class::getFunctionList,
|
||||
ProtoBuf.Class::getPropertyList
|
||||
) + classData.classProto.enumEntryList.map { classData.nameResolver.getString(it.name) }
|
||||
|
||||
val companionObjectChanged = createChangeInfo(classFqName.parent(), listOfNotNull(classFqName.shortName().asString()))
|
||||
val companionObjectMembersChanged = createChangeInfo(classFqName, memberNames)
|
||||
|
||||
listOf(companionObjectMembersChanged, companionObjectChanged)
|
||||
}
|
||||
else {
|
||||
listOf(ChangeInfo.SignatureChanged(classFqName, areSubclassesAffected = true))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearCacheForRemovedClasses(): CompilationResult {
|
||||
val dirtyClasses = dirtyOutputClassesMap
|
||||
.getDirtyOutputClasses()
|
||||
.map(JvmClassName::byInternalName)
|
||||
.toList()
|
||||
|
||||
val changes =
|
||||
if (IncrementalCompilation.isExperimental())
|
||||
dirtyClasses.flatMap { computeChanges(it, ::Removed) }.asSequence()
|
||||
else
|
||||
emptySequence<ChangeInfo>()
|
||||
|
||||
val changesInfo = dirtyClasses.fold(CompilationResult(changes = changes)) { info, className ->
|
||||
val newInfo = CompilationResult(protoChanged = className in protoMap,
|
||||
constantsChanged = className in constantsMap)
|
||||
newInfo.logIfSomethingChanged(className)
|
||||
info + newInfo
|
||||
}
|
||||
|
||||
val facadesWithRemovedParts = hashMapOf<JvmClassName, MutableSet<String>>()
|
||||
for (dirtyClass in dirtyClasses) {
|
||||
val facade = partToMultifileFacade.get(dirtyClass.internalName) ?: continue
|
||||
val facadeClassName = JvmClassName.byInternalName(facade)
|
||||
val removedParts = facadesWithRemovedParts.getOrPut(facadeClassName) { hashSetOf() }
|
||||
removedParts.add(dirtyClass.internalName)
|
||||
}
|
||||
|
||||
for ((facade, removedParts) in facadesWithRemovedParts.entries) {
|
||||
val allParts = multifileFacadeToParts[facade.internalName] ?: continue
|
||||
val notRemovedParts = allParts.filter { it !in removedParts }
|
||||
|
||||
if (notRemovedParts.isEmpty()) {
|
||||
multifileFacadeToParts.remove(facade)
|
||||
}
|
||||
else {
|
||||
multifileFacadeToParts[facade] = notRemovedParts
|
||||
}
|
||||
}
|
||||
|
||||
dirtyClasses.forEach {
|
||||
protoMap.remove(it)
|
||||
packagePartMap.remove(it)
|
||||
multifileFacadeToParts.remove(it)
|
||||
partToMultifileFacade.remove(it)
|
||||
constantsMap.remove(it)
|
||||
inlineFunctionsMap.remove(it)
|
||||
internalNameToSource.remove(it.internalName)
|
||||
}
|
||||
|
||||
removeAllFromClassStorage(dirtyClasses)
|
||||
|
||||
dirtyOutputClassesMap.clean()
|
||||
return changesInfo
|
||||
}
|
||||
|
||||
override fun getObsoletePackageParts(): Collection<String> {
|
||||
val obsoletePackageParts =
|
||||
dirtyOutputClassesMap.getDirtyOutputClasses().filter { packagePartMap.isPackagePart(JvmClassName.byInternalName(it)) }
|
||||
debugLog("Obsolete package parts: $obsoletePackageParts")
|
||||
return obsoletePackageParts
|
||||
}
|
||||
|
||||
override fun getPackagePartData(partInternalName: String): JvmPackagePartProto? {
|
||||
return protoMap[JvmClassName.byInternalName(partInternalName)]?.let { value ->
|
||||
JvmPackagePartProto(value.bytes, value.strings)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getObsoleteMultifileClasses(): Collection<String> {
|
||||
val obsoleteMultifileClasses = linkedSetOf<String>()
|
||||
for (dirtyClass in dirtyOutputClassesMap.getDirtyOutputClasses()) {
|
||||
val dirtyFacade = partToMultifileFacade.get(dirtyClass) ?: continue
|
||||
obsoleteMultifileClasses.add(dirtyFacade)
|
||||
}
|
||||
debugLog("Obsolete multifile class facades: $obsoleteMultifileClasses")
|
||||
return obsoleteMultifileClasses
|
||||
}
|
||||
|
||||
override fun getStableMultifileFacadeParts(facadeInternalName: String): Collection<String>? {
|
||||
val partNames = multifileFacadeToParts.get(facadeInternalName) ?: return null
|
||||
return partNames.filter { !dirtyOutputClassesMap.isDirty(it) }
|
||||
}
|
||||
|
||||
override fun getModuleMappingData(): ByteArray? {
|
||||
return protoMap[JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)]?.bytes
|
||||
}
|
||||
|
||||
override fun clean() {
|
||||
super.clean()
|
||||
normalCacheVersion(targetDataRoot).clean()
|
||||
experimentalCacheVersion(targetDataRoot).clean()
|
||||
}
|
||||
|
||||
fun cleanExperimental() {
|
||||
experimentalCacheVersion(targetDataRoot).clean()
|
||||
experimentalMaps.forEach { it.clean() }
|
||||
}
|
||||
|
||||
private inner class ProtoMap(storageFile: File) : BasicStringMap<ProtoMapValue>(storageFile, ProtoMapValueExternalizer) {
|
||||
|
||||
fun process(kotlinClass: LocalFileKotlinClass, isPackage: Boolean): CompilationResult {
|
||||
val header = kotlinClass.classHeader
|
||||
val bytes = BitEncoding.decodeBytes(header.data!!)
|
||||
return put(kotlinClass.className, bytes, header.strings!!, isPackage, checkChangesIsOpenPart = true)
|
||||
}
|
||||
|
||||
fun process(className: JvmClassName, data: ByteArray, strings: Array<String>, isPackage: Boolean, checkChangesIsOpenPart: Boolean): CompilationResult {
|
||||
return put(className, data, strings, isPackage, checkChangesIsOpenPart)
|
||||
}
|
||||
|
||||
private fun put(
|
||||
className: JvmClassName, bytes: ByteArray, strings: Array<String>, isPackage: Boolean, checkChangesIsOpenPart: Boolean
|
||||
): CompilationResult {
|
||||
val key = className.internalName
|
||||
val oldData = storage[key]
|
||||
val data = ProtoMapValue(isPackage, bytes, strings)
|
||||
|
||||
if (oldData == null ||
|
||||
!Arrays.equals(bytes, oldData.bytes) ||
|
||||
!Arrays.equals(strings, oldData.strings) ||
|
||||
isPackage != oldData.isPackageFacade
|
||||
) {
|
||||
storage[key] = data
|
||||
}
|
||||
|
||||
if (!checkChangesIsOpenPart) return CompilationResult(protoChanged = true)
|
||||
|
||||
if (oldData == null) {
|
||||
val changes =
|
||||
if (IncrementalCompilation.isExperimental())
|
||||
computeChanges(className, ::MembersChanged).asSequence()
|
||||
else
|
||||
emptySequence<ChangeInfo>()
|
||||
|
||||
return CompilationResult(protoChanged = true, changes = changes)
|
||||
}
|
||||
|
||||
val difference = difference(oldData, data)
|
||||
val fqName = if (isPackage) className.packageFqName else className.fqNameForClassNameWithoutDollars
|
||||
val changeList = SmartList<ChangeInfo>()
|
||||
|
||||
if (difference.isClassAffected) {
|
||||
changeList.add(ChangeInfo.SignatureChanged(fqName, difference.areSubclassesAffected))
|
||||
}
|
||||
|
||||
if (difference.changedMembersNames.isNotEmpty()) {
|
||||
changeList.add(ChangeInfo.MembersChanged(fqName, difference.changedMembersNames))
|
||||
}
|
||||
|
||||
return CompilationResult(protoChanged = changeList.isNotEmpty(), changes = changeList.asSequence())
|
||||
}
|
||||
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
operator fun get(className: JvmClassName): ProtoMapValue? =
|
||||
storage[className.internalName]
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: ProtoMapValue): String {
|
||||
return (if (value.isPackageFacade) "1" else "0") + java.lang.Long.toHexString(value.bytes.md5())
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ConstantsMap(storageFile: File) : BasicStringMap<Map<String, Any>>(storageFile, ConstantsMapExternalizer) {
|
||||
private fun getConstantsMap(bytes: ByteArray): Map<String, Any>? {
|
||||
val result = HashMap<String, Any>()
|
||||
|
||||
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
|
||||
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||
val staticFinal = Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_PRIVATE
|
||||
if (value != null && access and staticFinal == Opcodes.ACC_STATIC or Opcodes.ACC_FINAL) {
|
||||
result[name] = value
|
||||
}
|
||||
return null
|
||||
}
|
||||
}, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES)
|
||||
|
||||
return if (result.isEmpty()) null else result
|
||||
}
|
||||
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
fun process(kotlinClass: LocalFileKotlinClass, isPackage: Boolean): CompilationResult {
|
||||
return put(kotlinClass.className, getConstantsMap(kotlinClass.fileContents), isPackage)
|
||||
}
|
||||
|
||||
private fun put(className: JvmClassName, constantsMap: Map<String, Any>?, isPackage: Boolean): CompilationResult {
|
||||
val key = className.internalName
|
||||
|
||||
val oldMap = storage[key]
|
||||
if (oldMap == constantsMap) return CompilationResult.NO_CHANGES
|
||||
|
||||
if (constantsMap != null) {
|
||||
storage[key] = constantsMap
|
||||
}
|
||||
else {
|
||||
remove(className)
|
||||
}
|
||||
|
||||
val changes =
|
||||
if (!IncrementalCompilation.isExperimental() ||
|
||||
constantsMap == null || constantsMap.isEmpty() ||
|
||||
oldMap == null || oldMap.isEmpty()
|
||||
) {
|
||||
emptySequence<ChangeInfo>()
|
||||
}
|
||||
else {
|
||||
// we need only changed constants everything other should be covered by diff
|
||||
val changedNames = oldMap.filter { constantsMap.containsKey(it.key) && constantsMap[it.key] != it.value }.map { it.key }
|
||||
|
||||
val fqName = if (isPackage) className.packageFqName else className.fqNameForClassNameWithoutDollars
|
||||
|
||||
sequenceOf(ChangeInfo.MembersChanged(fqName, changedNames))
|
||||
}
|
||||
|
||||
return CompilationResult(constantsChanged = true, changes = changes)
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Map<String, Any>): String =
|
||||
value.dumpMap(Any::toString)
|
||||
}
|
||||
|
||||
private inner class PackagePartMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||
fun addPackagePart(className: JvmClassName) {
|
||||
storage[className.internalName] = true
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
fun isPackagePart(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
override fun dumpValue(value: Boolean) = ""
|
||||
}
|
||||
|
||||
private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
||||
operator fun set(facadeName: JvmClassName, partNames: Collection<String>) {
|
||||
storage[facadeName.internalName] = partNames
|
||||
}
|
||||
|
||||
operator fun get(internalName: String): Collection<String>? = storage[internalName]
|
||||
|
||||
operator fun contains(internalName: String): Boolean = internalName in storage
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
||||
}
|
||||
|
||||
private inner class MultifileClassPartMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor.INSTANCE) {
|
||||
fun set(partName: String, facadeName: String) {
|
||||
storage[partName] = facadeName
|
||||
}
|
||||
|
||||
fun get(partName: String): String? {
|
||||
return storage.get(partName)
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: String): String = value
|
||||
}
|
||||
|
||||
inner class SourceToClassesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
fun clearOutputsForSource(sourceFile: File) {
|
||||
remove(sourceFile.absolutePath)
|
||||
}
|
||||
|
||||
fun add(sourceFile: File, className: JvmClassName) {
|
||||
storage.append(sourceFile.absolutePath, className.internalName)
|
||||
}
|
||||
|
||||
operator fun get(sourceFile: File): Collection<JvmClassName> =
|
||||
storage[sourceFile.absolutePath].orEmpty().map { JvmClassName.byInternalName(it) }
|
||||
|
||||
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
|
||||
|
||||
private fun remove(path: String) {
|
||||
storage.remove(path)
|
||||
}
|
||||
}
|
||||
|
||||
inner class ClassFqNameToSourceMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
|
||||
operator fun set(fqName: FqName, sourceFile: File) {
|
||||
storage[fqName.asString()] = sourceFile.canonicalPath
|
||||
}
|
||||
|
||||
operator fun get(fqName: FqName): File? =
|
||||
storage[fqName.asString()]?.let(::File)
|
||||
|
||||
fun remove(fqName: FqName) {
|
||||
storage.remove(fqName.asString())
|
||||
}
|
||||
|
||||
override fun dumpValue(value: String) = value
|
||||
}
|
||||
|
||||
|
||||
inner class InternalNameToSourcesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) {
|
||||
operator fun set(internalName: String, sourceFiles: Iterable<File>) {
|
||||
storage[internalName] = sourceFiles.map { it.canonicalPath }
|
||||
}
|
||||
|
||||
operator fun get(internalName: String): Collection<File> =
|
||||
(storage[internalName] ?: emptyList()).map(::File)
|
||||
|
||||
fun remove(internalName: String) {
|
||||
storage.remove(internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Collection<String>): String =
|
||||
value.dumpCollection()
|
||||
}
|
||||
|
||||
private fun addToClassStorage(kotlinClass: LocalFileKotlinClass, srcFile: File) {
|
||||
if (!IncrementalCompilation.isExperimental()) return
|
||||
|
||||
val classData = JvmProtoBufUtil.readClassDataFrom(kotlinClass.classHeader.data!!, kotlinClass.classHeader.strings!!)
|
||||
val supertypes = classData.classProto.supertypes(TypeTable(classData.classProto.typeTable))
|
||||
val parents = supertypes.map { classData.nameResolver.getClassId(it.className).asSingleFqName() }
|
||||
.filter { it.asString() != "kotlin.Any" }
|
||||
.toSet()
|
||||
val child = kotlinClass.classId.asSingleFqName()
|
||||
|
||||
parents.forEach { subtypesMap.add(it, child) }
|
||||
|
||||
val removedSupertypes = supertypesMap[child].filter { it !in parents }
|
||||
removedSupertypes.forEach { subtypesMap.removeValues(it, setOf(child)) }
|
||||
|
||||
supertypesMap[child] = parents
|
||||
classFqNameToSourceMap[kotlinClass.className.fqNameForClassNameWithoutDollars] = srcFile
|
||||
}
|
||||
|
||||
private fun removeAllFromClassStorage(removedClasses: Collection<JvmClassName>) {
|
||||
if (!IncrementalCompilation.isExperimental() || removedClasses.isEmpty()) return
|
||||
|
||||
val removedFqNames = removedClasses.map { it.fqNameForClassNameWithoutDollars }.toSet()
|
||||
|
||||
for (cache in thisWithDependentCaches) {
|
||||
val parentsFqNames = hashSetOf<FqName>()
|
||||
val childrenFqNames = hashSetOf<FqName>()
|
||||
|
||||
for (removedFqName in removedFqNames) {
|
||||
parentsFqNames.addAll(cache.supertypesMap[removedFqName])
|
||||
childrenFqNames.addAll(cache.subtypesMap[removedFqName])
|
||||
|
||||
cache.supertypesMap.remove(removedFqName)
|
||||
cache.subtypesMap.remove(removedFqName)
|
||||
}
|
||||
|
||||
for (child in childrenFqNames) {
|
||||
cache.supertypesMap.removeValues(child, removedFqNames)
|
||||
}
|
||||
|
||||
for (parent in parentsFqNames) {
|
||||
cache.subtypesMap.removeValues(parent, removedFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
removedFqNames.forEach { classFqNameToSourceMap.remove(it) }
|
||||
}
|
||||
|
||||
private inner class DirtyOutputClassesMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||
fun markDirty(className: String) {
|
||||
storage[className] = true
|
||||
}
|
||||
|
||||
fun notDirty(className: String) {
|
||||
storage.remove(className)
|
||||
}
|
||||
|
||||
fun getDirtyOutputClasses(): Collection<String> =
|
||||
storage.keys
|
||||
|
||||
fun isDirty(className: String): Boolean =
|
||||
storage.contains(className)
|
||||
|
||||
override fun dumpValue(value: Boolean) = ""
|
||||
}
|
||||
|
||||
private inner class InlineFunctionsMap(storageFile: File) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
||||
private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray): Map<String, Long> {
|
||||
val inlineFunctions = inlineFunctionsJvmNames(header)
|
||||
if (inlineFunctions.isEmpty()) return emptyMap()
|
||||
|
||||
val result = HashMap<String, Long>()
|
||||
|
||||
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
||||
val dummyClassWriter = ClassWriter(Opcodes.ASM5)
|
||||
|
||||
return object : MethodVisitor(Opcodes.ASM5, dummyClassWriter.visitMethod(0, name, desc, null, exceptions)) {
|
||||
override fun visitEnd() {
|
||||
val jvmName = name + desc
|
||||
if (jvmName !in inlineFunctions) return
|
||||
|
||||
val dummyBytes = dummyClassWriter.toByteArray()!!
|
||||
val hash = dummyBytes.md5()
|
||||
result[jvmName] = hash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, 0)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun process(kotlinClass: LocalFileKotlinClass, isPackage: Boolean): CompilationResult {
|
||||
return put(kotlinClass.className, getInlineFunctionsMap(kotlinClass.classHeader, kotlinClass.fileContents), isPackage)
|
||||
}
|
||||
|
||||
private fun put(className: JvmClassName, newMap: Map<String, Long>, isPackage: Boolean): CompilationResult {
|
||||
val internalName = className.internalName
|
||||
val oldMap = storage[internalName] ?: emptyMap()
|
||||
|
||||
val added = hashSetOf<String>()
|
||||
val changed = hashSetOf<String>()
|
||||
val allFunctions = oldMap.keys + newMap.keys
|
||||
|
||||
for (fn in allFunctions) {
|
||||
val oldHash = oldMap[fn]
|
||||
val newHash = newMap[fn]
|
||||
|
||||
when {
|
||||
oldHash == null -> added.add(fn)
|
||||
oldHash != newHash -> changed.add(fn)
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
newMap.isNotEmpty() -> storage[internalName] = newMap
|
||||
else -> storage.remove(internalName)
|
||||
}
|
||||
|
||||
val changes =
|
||||
if (IncrementalCompilation.isExperimental()) {
|
||||
val fqName = if (isPackage) className.packageFqName else className.fqNameForClassNameWithoutDollars
|
||||
// TODO get name in better way instead of using substringBefore
|
||||
(added.asSequence() + changed.asSequence()).map { ChangeInfo.MembersChanged(fqName, listOf(it.substringBefore("("))) }
|
||||
}
|
||||
else {
|
||||
emptySequence<ChangeInfo>()
|
||||
}
|
||||
|
||||
processChangedInlineFunctions(className, changed)
|
||||
return CompilationResult(inlineChanged = changed.isNotEmpty(),
|
||||
inlineAdded = added.isNotEmpty(),
|
||||
changes = changes)
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Map<String, Long>): String =
|
||||
value.dumpMap { java.lang.Long.toHexString(it) }
|
||||
}
|
||||
|
||||
protected open fun processChangedInlineFunctions(
|
||||
className: JvmClassName,
|
||||
changedFunctions: Collection<String>
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
private object PathCollectionExternalizer : CollectionExternalizer<String>(PathStringDescriptor, { THashSet(FileUtil.PATH_HASHING_STRATEGY) })
|
||||
|
||||
sealed class ChangeInfo(val fqName: FqName) {
|
||||
open class MembersChanged(fqName: FqName, val names: Collection<String>) : ChangeInfo(fqName) {
|
||||
override fun toStringProperties(): String = super.toStringProperties() + ", names = $names"
|
||||
}
|
||||
|
||||
class Removed(fqName: FqName, names: Collection<String>) : MembersChanged(fqName, names)
|
||||
|
||||
class SignatureChanged(fqName: FqName, val areSubclassesAffected: Boolean) : ChangeInfo(fqName)
|
||||
|
||||
|
||||
protected open fun toStringProperties(): String = "fqName = $fqName"
|
||||
|
||||
override fun toString(): String {
|
||||
return this::class.java.simpleName + "(${toStringProperties()})"
|
||||
}
|
||||
}
|
||||
|
||||
data class CompilationResult(
|
||||
val protoChanged: Boolean = false,
|
||||
val constantsChanged: Boolean = false,
|
||||
val inlineChanged: Boolean = false,
|
||||
val inlineAdded: Boolean = false,
|
||||
val changes: Sequence<ChangeInfo> = emptySequence()
|
||||
) {
|
||||
companion object {
|
||||
val NO_CHANGES: CompilationResult = CompilationResult()
|
||||
}
|
||||
|
||||
operator fun plus(other: CompilationResult): CompilationResult =
|
||||
CompilationResult(protoChanged || other.protoChanged,
|
||||
constantsChanged || other.constantsChanged,
|
||||
inlineChanged || other.inlineChanged,
|
||||
inlineAdded || other.inlineAdded,
|
||||
changes + other.changes)
|
||||
}
|
||||
|
||||
fun ByteArray.md5(): Long {
|
||||
val d = MessageDigest.getInstance("MD5").digest(this)!!
|
||||
return ((d[0].toLong() and 0xFFL)
|
||||
or ((d[1].toLong() and 0xFFL) shl 8)
|
||||
or ((d[2].toLong() and 0xFFL) shl 16)
|
||||
or ((d[3].toLong() and 0xFFL) shl 24)
|
||||
or ((d[4].toLong() and 0xFFL) shl 32)
|
||||
or ((d[5].toLong() and 0xFFL) shl 40)
|
||||
or ((d[6].toLong() and 0xFFL) shl 48)
|
||||
or ((d[7].toLong() and 0xFFL) shl 56)
|
||||
)
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun <K : Comparable<K>, V> Map<K, V>.dumpMap(dumpValue: (V)->String): String =
|
||||
buildString {
|
||||
append("{")
|
||||
for (key in keys.sorted()) {
|
||||
if (length != 1) {
|
||||
append(", ")
|
||||
}
|
||||
|
||||
val value = get(key)?.let(dumpValue) ?: "null"
|
||||
append("$key -> $value")
|
||||
}
|
||||
append("}")
|
||||
}
|
||||
|
||||
@TestOnly fun <T : Comparable<T>> Collection<T>.dumpCollection(): String =
|
||||
"[${sorted().joinToString(", ", transform = Any::toString)}]"
|
||||
@@ -16,17 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
|
||||
class IncrementalCompilationComponentsImpl(
|
||||
private val caches: Map<TargetId, IncrementalCache>,
|
||||
private val lookupTracker: LookupTracker
|
||||
private val caches: Map<TargetId, IncrementalCache>
|
||||
): IncrementalCompilationComponents {
|
||||
override fun getIncrementalCache(target: TargetId): IncrementalCache =
|
||||
caches[target] ?: throw Exception("Incremental cache for target ${target.name} not found")
|
||||
|
||||
override fun getLookupTracker(): LookupTracker = lookupTracker
|
||||
}
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
|
||||
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.serialization.js.JsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
|
||||
open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDir) {
|
||||
companion object {
|
||||
private val TRANSLATION_RESULT_MAP = "translation-result"
|
||||
private val SOURCES_TO_CLASSES_FQNS = "sources-to-classes"
|
||||
private val INLINE_FUNCTIONS = "inline-functions"
|
||||
private val HEADER_FILE_NAME = "header.meta"
|
||||
}
|
||||
|
||||
private val dirtySources = arrayListOf<File>()
|
||||
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile))
|
||||
private val sourcesToClasses = registerMap(SourceToClassesMap(SOURCES_TO_CLASSES_FQNS.storageFile))
|
||||
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
||||
|
||||
private val headerFile: File
|
||||
get() = File(cachesDir, HEADER_FILE_NAME)
|
||||
|
||||
var header: ByteArray
|
||||
get() = headerFile.readBytes()
|
||||
set(value) {
|
||||
cachesDir.mkdirs()
|
||||
headerFile.writeBytes(value)
|
||||
}
|
||||
|
||||
override fun markDirty(removedAndCompiledSources: List<File>) {
|
||||
dirtySources.addAll(removedAndCompiledSources)
|
||||
}
|
||||
|
||||
fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) {
|
||||
val translatedFiles = incrementalResults.packageParts
|
||||
|
||||
dirtySources.forEach {
|
||||
if (it !in translatedFiles) {
|
||||
translationResults.remove(it, changesCollector)
|
||||
inlineFunctions.remove(it)
|
||||
}
|
||||
|
||||
removeAllFromClassStorage(sourcesToClasses[it])
|
||||
sourcesToClasses.clearOutputsForSource(it)
|
||||
}
|
||||
dirtySources.clear()
|
||||
|
||||
for ((srcFile, data) in translatedFiles) {
|
||||
val (binaryMetadata, binaryAst) = data
|
||||
|
||||
val oldProtoMap = translationResults[srcFile]?.metadata?.let { getProtoData(srcFile, it) } ?: emptyMap()
|
||||
val newProtoMap = getProtoData(srcFile, binaryMetadata)
|
||||
|
||||
for (protoData in newProtoMap.values) {
|
||||
if (protoData is ClassProtoData) {
|
||||
addToClassStorage(protoData.proto, protoData.nameResolver, srcFile)
|
||||
}
|
||||
}
|
||||
|
||||
for (classId in oldProtoMap.keys + newProtoMap.keys) {
|
||||
changesCollector.collectProtoChanges(oldProtoMap[classId], newProtoMap[classId])
|
||||
}
|
||||
|
||||
translationResults.put(srcFile, binaryMetadata, binaryAst)
|
||||
}
|
||||
|
||||
for ((srcFile, inlineDeclarations) in incrementalResults.inlineFunctions) {
|
||||
inlineFunctions.process(srcFile, inlineDeclarations, changesCollector)
|
||||
}
|
||||
}
|
||||
|
||||
fun nonDirtyPackageParts(): Map<File, TranslationResultValue> =
|
||||
hashMapOf<File, TranslationResultValue>().apply {
|
||||
for (path in translationResults.keys()) {
|
||||
val file = File(path)
|
||||
if (file !in dirtySources) {
|
||||
put(file, translationResults[path]!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SourceToClassesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
fun clearOutputsForSource(sourceFile: File) {
|
||||
remove(sourceFile.canonicalPath)
|
||||
}
|
||||
|
||||
fun add(sourceFile: File, className: FqName) {
|
||||
storage.append(sourceFile.canonicalPath, className.asString())
|
||||
}
|
||||
|
||||
operator fun get(sourceFile: File): Collection<FqName> =
|
||||
storage[sourceFile.canonicalPath].orEmpty().map { FqName(it) }
|
||||
|
||||
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
|
||||
|
||||
private fun remove(path: String) {
|
||||
storage.remove(path)
|
||||
}
|
||||
}
|
||||
|
||||
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
|
||||
override fun save(output: DataOutput, value: TranslationResultValue) {
|
||||
output.writeInt(value.metadata.size)
|
||||
output.write(value.metadata)
|
||||
|
||||
output.writeInt(value.binaryAst.size)
|
||||
output.write(value.binaryAst)
|
||||
}
|
||||
|
||||
override fun read(input: DataInput): TranslationResultValue {
|
||||
val metadataSize = input.readInt()
|
||||
val metadata = ByteArray(metadataSize)
|
||||
input.readFully(metadata)
|
||||
|
||||
val binaryAstSize = input.readInt()
|
||||
val binaryAst = ByteArray(binaryAstSize)
|
||||
input.readFully(binaryAst)
|
||||
|
||||
return TranslationResultValue(metadata = metadata, binaryAst = binaryAst)
|
||||
}
|
||||
}
|
||||
|
||||
private class TranslationResultMap(storageFile: File) : BasicStringMap<TranslationResultValue>(storageFile, TranslationResultValueExternalizer) {
|
||||
override fun dumpValue(value: TranslationResultValue): String =
|
||||
"Metadata: ${value.metadata.md5()}, Binary AST: ${value.binaryAst.md5()}"
|
||||
|
||||
fun put(file: File, newMetadata: ByteArray, newBinaryAst: ByteArray) {
|
||||
storage[file.canonicalPath] = TranslationResultValue(metadata = newMetadata, binaryAst = newBinaryAst)
|
||||
}
|
||||
|
||||
operator fun get(file: File): TranslationResultValue? =
|
||||
storage[file.canonicalPath]
|
||||
|
||||
operator fun get(key: String): TranslationResultValue? =
|
||||
storage[key]
|
||||
|
||||
fun keys(): Collection<String> =
|
||||
storage.keys
|
||||
|
||||
fun remove(file: File, changesCollector: ChangesCollector) {
|
||||
val protoBytes = storage[file.canonicalPath]!!.metadata
|
||||
val protoMap = getProtoData(file, protoBytes)
|
||||
|
||||
for ((_, protoData) in protoMap) {
|
||||
changesCollector.collectProtoChanges(oldData = protoData, newData = null)
|
||||
}
|
||||
storage.remove(file.canonicalPath)
|
||||
}
|
||||
}
|
||||
|
||||
fun getProtoData(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData> {
|
||||
val classes = hashMapOf<ClassId, ProtoData>()
|
||||
val proto = ProtoBuf.PackageFragment.parseFrom(metadata, JsSerializerProtocol.extensionRegistry)
|
||||
val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
|
||||
|
||||
proto.class_List.forEach {
|
||||
val classId = nameResolver.getClassId(it.fqName)
|
||||
classes[classId] = ClassProtoData(it, nameResolver)
|
||||
}
|
||||
|
||||
proto.`package`.apply {
|
||||
val packageFqName = if (hasExtension(JsProtoBuf.packageFqName)) {
|
||||
nameResolver.getPackageFqName(getExtension(JsProtoBuf.packageFqName))
|
||||
}
|
||||
else FqName.ROOT
|
||||
|
||||
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalize() + "Kt"))
|
||||
classes[packagePartClassId] = PackagePartProtoData(this, nameResolver, packageFqName)
|
||||
}
|
||||
return classes
|
||||
}
|
||||
|
||||
private class InlineFunctionsMap(storageFile: File) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
||||
fun process(srcFile: File, newMap: Map<String, Long>, changesCollector: ChangesCollector) {
|
||||
val key = srcFile.canonicalPath
|
||||
val oldMap = storage[key] ?: emptyMap()
|
||||
|
||||
if (newMap.isNotEmpty()) {
|
||||
storage[key] = newMap
|
||||
}
|
||||
else {
|
||||
storage.remove(key)
|
||||
}
|
||||
|
||||
for (fn in oldMap.keys + newMap.keys) {
|
||||
val fqNameSegments = fn.removePrefix("<get>").removePrefix("<set>").split(".")
|
||||
val fqName = FqName.fromSegments(fqNameSegments)
|
||||
changesCollector.collectMemberIfValueWasChanged(fqName.parent(), fqName.shortName().asString(), oldMap[fn], newMap[fn])
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(sourceFile: File) {
|
||||
storage.remove(sourceFile.canonicalPath)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Map<String, Long>): String =
|
||||
value.dumpMap { java.lang.Long.toHexString(it) }
|
||||
}
|
||||
@@ -0,0 +1,562 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName
|
||||
import com.intellij.util.io.BooleanDataDescriptor
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import gnu.trove.THashSet
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.io.File
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
|
||||
val KOTLIN_CACHE_DIRECTORY_NAME = "kotlin"
|
||||
|
||||
open class IncrementalJvmCache(
|
||||
private val targetDataRoot: File,
|
||||
targetOutputDir: File?
|
||||
) : IncrementalCacheCommon(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
|
||||
companion object {
|
||||
private val PROTO_MAP = "proto"
|
||||
private val CONSTANTS_MAP = "constants"
|
||||
private val PACKAGE_PARTS = "package-parts"
|
||||
private val MULTIFILE_CLASS_FACADES = "multifile-class-facades"
|
||||
private val MULTIFILE_CLASS_PARTS = "multifile-class-parts"
|
||||
private val SOURCE_TO_CLASSES = "source-to-classes"
|
||||
private val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
||||
private val INLINE_FUNCTIONS = "inline-functions"
|
||||
private val INTERNAL_NAME_TO_SOURCE = "internal-name-to-source"
|
||||
|
||||
private val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
|
||||
}
|
||||
|
||||
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
|
||||
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
|
||||
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
|
||||
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
|
||||
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
|
||||
private val sourceToClassesMap = registerMap(SourceToClassesMap(SOURCE_TO_CLASSES.storageFile))
|
||||
private val dirtyOutputClassesMap = registerMap(DirtyOutputClassesMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
||||
// todo: try to use internal names only?
|
||||
private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile))
|
||||
|
||||
private val outputDir by lazy(LazyThreadSafetyMode.NONE) { requireNotNull(targetOutputDir) { "Target is expected to have output directory" } }
|
||||
|
||||
protected open fun debugLog(message: String) {}
|
||||
|
||||
override fun markDirty(removedAndCompiledSources: List<File>) {
|
||||
for (sourceFile in removedAndCompiledSources) {
|
||||
val classes = sourceToClassesMap[sourceFile]
|
||||
classes.forEach {
|
||||
dirtyOutputClassesMap.markDirty(it.internalName)
|
||||
}
|
||||
|
||||
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
||||
}
|
||||
}
|
||||
|
||||
// used in gradle
|
||||
@Suppress("unused")
|
||||
fun classesBySources(sources: Iterable<File>): Iterable<JvmClassName> =
|
||||
sources.flatMap { sourceToClassesMap[it] }
|
||||
|
||||
fun sourcesByInternalName(internalName: String): Collection<File> =
|
||||
internalNameToSource[internalName]
|
||||
|
||||
fun isMultifileFacade(className: JvmClassName): Boolean =
|
||||
className.internalName in multifileFacadeToParts
|
||||
|
||||
override fun getClassFilePath(internalClassName: String): String {
|
||||
return toSystemIndependentName(File(outputDir, "$internalClassName.class").canonicalPath)
|
||||
}
|
||||
|
||||
fun saveModuleMappingToCache(sourceFiles: Collection<File>, file: File) {
|
||||
val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)
|
||||
protoMap.storeModuleMapping(jvmClassName, file.readBytes())
|
||||
dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME)
|
||||
sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) }
|
||||
}
|
||||
|
||||
open fun saveFileToCache(generatedClass: GeneratedJvmClass, changesCollector: ChangesCollector) {
|
||||
val sourceFiles: Collection<File> = generatedClass.sourceFiles
|
||||
val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass
|
||||
val className = kotlinClass.className
|
||||
|
||||
dirtyOutputClassesMap.notDirty(className.internalName)
|
||||
sourceFiles.forEach {
|
||||
sourceToClassesMap.add(it, className)
|
||||
}
|
||||
|
||||
internalNameToSource[className.internalName] = sourceFiles
|
||||
|
||||
if (kotlinClass.classId.isLocal) return
|
||||
|
||||
val header = kotlinClass.classHeader
|
||||
when (header.kind) {
|
||||
KotlinClassHeader.Kind.FILE_FACADE -> {
|
||||
assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }
|
||||
packagePartMap.addPackagePart(className)
|
||||
|
||||
protoMap.process(kotlinClass, changesCollector)
|
||||
constantsMap.process(kotlinClass, changesCollector)
|
||||
inlineFunctionsMap.process(kotlinClass, changesCollector)
|
||||
}
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS -> {
|
||||
val partNames = kotlinClass.classHeader.data?.toList()
|
||||
?: throw AssertionError("Multifile class has no parts: ${kotlinClass.className}")
|
||||
multifileFacadeToParts[className] = partNames
|
||||
// When a class is replaced with a facade with the same name,
|
||||
// the class' proto wouldn't ever be deleted,
|
||||
// because we don't write proto for multifile facades.
|
||||
// As a workaround we can remove proto values for multifile facades.
|
||||
if (className in protoMap) {
|
||||
changesCollector.collectSignature(className.fqNameForClassNameWithoutDollars, areSubclassesAffected = true)
|
||||
}
|
||||
protoMap.remove(className, changesCollector)
|
||||
classFqNameToSourceMap.remove(className.fqNameForClassNameWithoutDollars)
|
||||
internalNameToSource.remove(className.internalName)
|
||||
|
||||
// TODO NO_CHANGES? (delegates only)
|
||||
constantsMap.process(kotlinClass, changesCollector)
|
||||
inlineFunctionsMap.process(kotlinClass, changesCollector)
|
||||
}
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
|
||||
assert(sourceFiles.size == 1) { "Multifile class part from several source files: $sourceFiles" }
|
||||
packagePartMap.addPackagePart(className)
|
||||
partToMultifileFacade.set(className.internalName, header.multifileClassName!!)
|
||||
|
||||
protoMap.process(kotlinClass, changesCollector)
|
||||
constantsMap.process(kotlinClass, changesCollector)
|
||||
inlineFunctionsMap.process(kotlinClass, changesCollector)
|
||||
}
|
||||
KotlinClassHeader.Kind.CLASS -> {
|
||||
assert(sourceFiles.size == 1) { "Class is expected to have only one source file: $sourceFiles" }
|
||||
addToClassStorage(kotlinClass, sourceFiles.first())
|
||||
|
||||
protoMap.process(kotlinClass, changesCollector)
|
||||
constantsMap.process(kotlinClass, changesCollector)
|
||||
inlineFunctionsMap.process(kotlinClass, changesCollector)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
||||
val dirtyClasses = dirtyOutputClassesMap
|
||||
.getDirtyOutputClasses()
|
||||
.map(JvmClassName::byInternalName)
|
||||
.toList()
|
||||
|
||||
val facadesWithRemovedParts = hashMapOf<JvmClassName, MutableSet<String>>()
|
||||
for (dirtyClass in dirtyClasses) {
|
||||
val facade = partToMultifileFacade.get(dirtyClass.internalName) ?: continue
|
||||
val facadeClassName = JvmClassName.byInternalName(facade)
|
||||
val removedParts = facadesWithRemovedParts.getOrPut(facadeClassName) { hashSetOf() }
|
||||
removedParts.add(dirtyClass.internalName)
|
||||
}
|
||||
|
||||
for ((facade, removedParts) in facadesWithRemovedParts.entries) {
|
||||
val allParts = multifileFacadeToParts[facade.internalName] ?: continue
|
||||
val notRemovedParts = allParts.filter { it !in removedParts }
|
||||
|
||||
if (notRemovedParts.isEmpty()) {
|
||||
multifileFacadeToParts.remove(facade)
|
||||
}
|
||||
else {
|
||||
multifileFacadeToParts[facade] = notRemovedParts
|
||||
}
|
||||
}
|
||||
|
||||
dirtyClasses.forEach {
|
||||
protoMap.remove(it, changesCollector)
|
||||
packagePartMap.remove(it)
|
||||
multifileFacadeToParts.remove(it)
|
||||
partToMultifileFacade.remove(it)
|
||||
constantsMap.remove(it)
|
||||
inlineFunctionsMap.remove(it)
|
||||
internalNameToSource.remove(it.internalName)
|
||||
}
|
||||
|
||||
removeAllFromClassStorage(dirtyClasses.map { it.fqNameForClassNameWithoutDollars })
|
||||
|
||||
dirtyOutputClassesMap.clean()
|
||||
}
|
||||
|
||||
override fun getObsoletePackageParts(): Collection<String> {
|
||||
val obsoletePackageParts =
|
||||
dirtyOutputClassesMap.getDirtyOutputClasses().filter { packagePartMap.isPackagePart(JvmClassName.byInternalName(it)) }
|
||||
debugLog("Obsolete package parts: $obsoletePackageParts")
|
||||
return obsoletePackageParts
|
||||
}
|
||||
|
||||
override fun getPackagePartData(partInternalName: String): JvmPackagePartProto? {
|
||||
return protoMap[JvmClassName.byInternalName(partInternalName)]?.let { value ->
|
||||
JvmPackagePartProto(value.bytes, value.strings)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getObsoleteMultifileClasses(): Collection<String> {
|
||||
val obsoleteMultifileClasses = linkedSetOf<String>()
|
||||
for (dirtyClass in dirtyOutputClassesMap.getDirtyOutputClasses()) {
|
||||
val dirtyFacade = partToMultifileFacade.get(dirtyClass) ?: continue
|
||||
obsoleteMultifileClasses.add(dirtyFacade)
|
||||
}
|
||||
debugLog("Obsolete multifile class facades: $obsoleteMultifileClasses")
|
||||
return obsoleteMultifileClasses
|
||||
}
|
||||
|
||||
override fun getStableMultifileFacadeParts(facadeInternalName: String): Collection<String>? {
|
||||
val partNames = multifileFacadeToParts.get(facadeInternalName) ?: return null
|
||||
return partNames.filter { !dirtyOutputClassesMap.isDirty(it) }
|
||||
}
|
||||
|
||||
override fun getModuleMappingData(): ByteArray? {
|
||||
return protoMap[JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)]?.bytes
|
||||
}
|
||||
|
||||
override fun clean() {
|
||||
super.clean()
|
||||
normalCacheVersion(targetDataRoot).clean()
|
||||
}
|
||||
|
||||
private inner class ProtoMap(storageFile: File) : BasicStringMap<ProtoMapValue>(storageFile, ProtoMapValueExternalizer) {
|
||||
|
||||
fun process(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
return put(kotlinClass, changesCollector)
|
||||
}
|
||||
|
||||
// A module mapping (.kotlin_module file) is stored in a cache,
|
||||
// because a corresponding file will be deleted on each round
|
||||
// (it is reported as output for each [package part?] source file).
|
||||
// If a mapping is not preserved, a resulting file will only contain data
|
||||
// from files compiled during last round.
|
||||
// However there is no need to compare old and new data in this case
|
||||
// (also that would fail with exception).
|
||||
fun storeModuleMapping(className: JvmClassName, bytes: ByteArray) {
|
||||
storage[className.internalName] = ProtoMapValue(isPackageFacade = false, bytes = bytes, strings = emptyArray())
|
||||
}
|
||||
|
||||
private fun put(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
val header = kotlinClass.classHeader
|
||||
|
||||
val key = kotlinClass.className.internalName
|
||||
val oldData = storage[key]
|
||||
val newData = ProtoMapValue(header.kind != KotlinClassHeader.Kind.CLASS,
|
||||
BitEncoding.decodeBytes(header.data!!),
|
||||
header.strings!!)
|
||||
storage[key] = newData
|
||||
|
||||
val packageFqName = kotlinClass.className.packageFqName
|
||||
changesCollector.collectProtoChanges(oldData?.toProtoData(packageFqName), newData.toProtoData(packageFqName))
|
||||
}
|
||||
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
operator fun get(className: JvmClassName): ProtoMapValue? =
|
||||
storage[className.internalName]
|
||||
|
||||
fun remove(className: JvmClassName, changesCollector: ChangesCollector) {
|
||||
val key = className.internalName
|
||||
val oldValue = storage[key] ?: return
|
||||
changesCollector.collectProtoChanges(oldData = oldValue.toProtoData(className.packageFqName), newData = null)
|
||||
storage.remove(key)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: ProtoMapValue): String {
|
||||
return (if (value.isPackageFacade) "1" else "0") + java.lang.Long.toHexString(value.bytes.md5())
|
||||
}
|
||||
}
|
||||
|
||||
// todo: reuse code with InlineFunctionsMap?
|
||||
private inner class ConstantsMap(storageFile: File) : BasicStringMap<Map<String, Any>>(storageFile, ConstantsMapExternalizer) {
|
||||
private fun getConstantsMap(bytes: ByteArray): Map<String, Any> {
|
||||
val result = HashMap<String, Any>()
|
||||
|
||||
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
|
||||
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||
val staticFinal = Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_PRIVATE
|
||||
if (value != null && access and staticFinal == Opcodes.ACC_STATIC or Opcodes.ACC_FINAL) {
|
||||
result[name] = value
|
||||
}
|
||||
return null
|
||||
}
|
||||
}, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
fun process(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
val key = kotlinClass.className.internalName
|
||||
val oldMap = storage[key] ?: emptyMap()
|
||||
|
||||
val newMap = getConstantsMap(kotlinClass.fileContents)
|
||||
if (newMap.isNotEmpty()) {
|
||||
storage[key] = newMap
|
||||
}
|
||||
else {
|
||||
storage.remove(key)
|
||||
}
|
||||
|
||||
for (const in oldMap.keys + newMap.keys) {
|
||||
changesCollector.collectMemberIfValueWasChanged(kotlinClass.scopeFqName(), const, oldMap[const], newMap[const])
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Map<String, Any>): String =
|
||||
value.dumpMap(Any::toString)
|
||||
}
|
||||
|
||||
private inner class PackagePartMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||
fun addPackagePart(className: JvmClassName) {
|
||||
storage[className.internalName] = true
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
fun isPackagePart(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
override fun dumpValue(value: Boolean) = ""
|
||||
}
|
||||
|
||||
private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
||||
operator fun set(facadeName: JvmClassName, partNames: Collection<String>) {
|
||||
storage[facadeName.internalName] = partNames
|
||||
}
|
||||
|
||||
operator fun get(internalName: String): Collection<String>? = storage[internalName]
|
||||
|
||||
operator fun contains(internalName: String): Boolean = internalName in storage
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
||||
}
|
||||
|
||||
private inner class MultifileClassPartMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor.INSTANCE) {
|
||||
fun set(partName: String, facadeName: String) {
|
||||
storage[partName] = facadeName
|
||||
}
|
||||
|
||||
fun get(partName: String): String? {
|
||||
return storage.get(partName)
|
||||
}
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: String): String = value
|
||||
}
|
||||
|
||||
inner class SourceToClassesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
fun clearOutputsForSource(sourceFile: File) {
|
||||
remove(sourceFile.absolutePath)
|
||||
}
|
||||
|
||||
fun add(sourceFile: File, className: JvmClassName) {
|
||||
storage.append(sourceFile.absolutePath, className.internalName)
|
||||
}
|
||||
|
||||
operator fun get(sourceFile: File): Collection<JvmClassName> =
|
||||
storage[sourceFile.absolutePath].orEmpty().map { JvmClassName.byInternalName(it) }
|
||||
|
||||
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
|
||||
|
||||
private fun remove(path: String) {
|
||||
storage.remove(path)
|
||||
}
|
||||
}
|
||||
|
||||
inner class InternalNameToSourcesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) {
|
||||
operator fun set(internalName: String, sourceFiles: Iterable<File>) {
|
||||
storage[internalName] = sourceFiles.map { it.canonicalPath }
|
||||
}
|
||||
|
||||
operator fun get(internalName: String): Collection<File> =
|
||||
(storage[internalName] ?: emptyList()).map(::File)
|
||||
|
||||
fun remove(internalName: String) {
|
||||
storage.remove(internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Collection<String>): String =
|
||||
value.dumpCollection()
|
||||
}
|
||||
|
||||
private fun addToClassStorage(kotlinClass: LocalFileKotlinClass, srcFile: File) {
|
||||
val (nameResolver, proto) = JvmProtoBufUtil.readClassDataFrom(kotlinClass.classHeader.data!!, kotlinClass.classHeader.strings!!)
|
||||
addToClassStorage(proto, nameResolver, srcFile)
|
||||
}
|
||||
|
||||
private inner class DirtyOutputClassesMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||
fun markDirty(className: String) {
|
||||
storage[className] = true
|
||||
}
|
||||
|
||||
fun notDirty(className: String) {
|
||||
storage.remove(className)
|
||||
}
|
||||
|
||||
fun getDirtyOutputClasses(): Collection<String> =
|
||||
storage.keys
|
||||
|
||||
fun isDirty(className: String): Boolean =
|
||||
storage.contains(className)
|
||||
|
||||
override fun dumpValue(value: Boolean) = ""
|
||||
}
|
||||
|
||||
private inner class InlineFunctionsMap(storageFile: File) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
||||
private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray): Map<String, Long> {
|
||||
val inlineFunctions = inlineFunctionsJvmNames(header)
|
||||
if (inlineFunctions.isEmpty()) return emptyMap()
|
||||
|
||||
val result = HashMap<String, Long>()
|
||||
|
||||
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
||||
val dummyClassWriter = ClassWriter(Opcodes.ASM5)
|
||||
|
||||
return object : MethodVisitor(Opcodes.ASM5, dummyClassWriter.visitMethod(0, name, desc, null, exceptions)) {
|
||||
override fun visitEnd() {
|
||||
val jvmName = name + desc
|
||||
if (jvmName !in inlineFunctions) return
|
||||
|
||||
val dummyBytes = dummyClassWriter.toByteArray()!!
|
||||
val hash = dummyBytes.md5()
|
||||
result[jvmName] = hash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, 0)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun process(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
val key = kotlinClass.className.internalName
|
||||
val oldMap = storage[key] ?: emptyMap()
|
||||
|
||||
val newMap = getInlineFunctionsMap(kotlinClass.classHeader, kotlinClass.fileContents)
|
||||
if (newMap.isNotEmpty()) {
|
||||
storage[key] = newMap
|
||||
}
|
||||
else {
|
||||
storage.remove(key)
|
||||
}
|
||||
|
||||
for (fn in oldMap.keys + newMap.keys) {
|
||||
changesCollector.collectMemberIfValueWasChanged(kotlinClass.scopeFqName(), functionNameBySignature(fn), oldMap[fn], newMap[fn])
|
||||
}
|
||||
}
|
||||
|
||||
// TODO get name in better way instead of using substringBefore
|
||||
private fun functionNameBySignature(signature: String): String =
|
||||
signature.substringBefore("(")
|
||||
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
|
||||
override fun dumpValue(value: Map<String, Long>): String =
|
||||
value.dumpMap { java.lang.Long.toHexString(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private object PathCollectionExternalizer : CollectionExternalizer<String>(PathStringDescriptor, { THashSet(FileUtil.PATH_HASHING_STRATEGY) })
|
||||
|
||||
sealed class ChangeInfo(val fqName: FqName) {
|
||||
open class MembersChanged(fqName: FqName, val names: Collection<String>) : ChangeInfo(fqName) {
|
||||
override fun toStringProperties(): String = super.toStringProperties() + ", names = $names"
|
||||
}
|
||||
|
||||
class Removed(fqName: FqName, names: Collection<String>) : MembersChanged(fqName, names)
|
||||
|
||||
class SignatureChanged(fqName: FqName, val areSubclassesAffected: Boolean) : ChangeInfo(fqName)
|
||||
|
||||
|
||||
protected open fun toStringProperties(): String = "fqName = $fqName"
|
||||
|
||||
override fun toString(): String {
|
||||
return this::class.java.simpleName + "(${toStringProperties()})"
|
||||
}
|
||||
}
|
||||
|
||||
private fun LocalFileKotlinClass.scopeFqName() =
|
||||
when (classHeader.kind) {
|
||||
KotlinClassHeader.Kind.CLASS -> className.fqNameForClassNameWithoutDollars
|
||||
else -> className.packageFqName
|
||||
}
|
||||
|
||||
fun ByteArray.md5(): Long {
|
||||
val d = MessageDigest.getInstance("MD5").digest(this)!!
|
||||
return ((d[0].toLong() and 0xFFL)
|
||||
or ((d[1].toLong() and 0xFFL) shl 8)
|
||||
or ((d[2].toLong() and 0xFFL) shl 16)
|
||||
or ((d[3].toLong() and 0xFFL) shl 24)
|
||||
or ((d[4].toLong() and 0xFFL) shl 32)
|
||||
or ((d[5].toLong() and 0xFFL) shl 40)
|
||||
or ((d[6].toLong() and 0xFFL) shl 48)
|
||||
or ((d[7].toLong() and 0xFFL) shl 56)
|
||||
)
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun <K : Comparable<K>, V> Map<K, V>.dumpMap(dumpValue: (V)->String): String =
|
||||
buildString {
|
||||
append("{")
|
||||
for (key in keys.sorted()) {
|
||||
if (length != 1) {
|
||||
append(", ")
|
||||
}
|
||||
|
||||
val value = get(key)?.let(dumpValue) ?: "null"
|
||||
append("$key -> $value")
|
||||
}
|
||||
append("}")
|
||||
}
|
||||
|
||||
@TestOnly fun <T : Comparable<T>> Collection<T>.dumpCollection(): String =
|
||||
"[${sorted().joinToString(", ", transform = Any::toString)}]"
|
||||
@@ -29,15 +29,12 @@ import java.io.File
|
||||
import java.util.*
|
||||
|
||||
|
||||
open class LookupStorage(private val targetDataDir: File) : BasicMapsOwner() {
|
||||
open class LookupStorage(targetDataDir: File) : BasicMapsOwner(targetDataDir) {
|
||||
companion object {
|
||||
private val DELETED_TO_SIZE_TRESHOLD = 0.5
|
||||
private val MINIMUM_GARBAGE_COLLECTIBLE_SIZE = 10000
|
||||
}
|
||||
|
||||
private val String.storageFile: File
|
||||
get() = File(targetDataDir, this + "." + CACHE_EXTENSION)
|
||||
|
||||
private val countersFile = "counters".storageFile
|
||||
private val idToFile = registerMap(IdToFileMap("id-to-file".storageFile))
|
||||
private val fileToId = registerMap(FileToIdMap("file-to-id".storageFile))
|
||||
@@ -197,7 +194,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()
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.js.JsProtoBuf
|
||||
import org.jetbrains.kotlin.utils.Interner
|
||||
import java.util.*
|
||||
|
||||
@@ -56,6 +57,20 @@ 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
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.packageLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.packageLocalVariable, i), new.getExtension(JvmProtoBuf.packageLocalVariable, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JsProtoBuf.packageFqName) != new.hasExtension(JsProtoBuf.packageFqName)) return false
|
||||
if (old.hasExtension(JsProtoBuf.packageFqName)) {
|
||||
if (old.getExtension(JsProtoBuf.packageFqName) != new.getExtension(JsProtoBuf.packageFqName)) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
enum class ProtoBufPackageKind {
|
||||
@@ -64,7 +79,9 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
TYPE_ALIAS_LIST,
|
||||
TYPE_TABLE,
|
||||
SINCE_KOTLIN_INFO_TABLE,
|
||||
PACKAGE_MODULE_NAME
|
||||
JVM_EXT_PACKAGE_MODULE_NAME,
|
||||
JVM_EXT_PACKAGE_LOCAL_VARIABLE_LIST,
|
||||
JS_EXT_PACKAGE_FQ_NAME
|
||||
}
|
||||
|
||||
fun difference(old: ProtoBuf.Package, new: ProtoBuf.Package): EnumSet<ProtoBufPackageKind> {
|
||||
@@ -86,9 +103,23 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkEquals(old.sinceKotlinInfoTable, new.sinceKotlinInfoTable)) result.add(ProtoBufPackageKind.SINCE_KOTLIN_INFO_TABLE)
|
||||
}
|
||||
|
||||
if (old.hasExtension(JvmProtoBuf.packageModuleName) != new.hasExtension(JvmProtoBuf.packageModuleName)) result.add(ProtoBufPackageKind.PACKAGE_MODULE_NAME)
|
||||
if (old.hasExtension(JvmProtoBuf.packageModuleName) != new.hasExtension(JvmProtoBuf.packageModuleName)) result.add(ProtoBufPackageKind.JVM_EXT_PACKAGE_MODULE_NAME)
|
||||
if (old.hasExtension(JvmProtoBuf.packageModuleName)) {
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.packageModuleName), new.getExtension(JvmProtoBuf.packageModuleName))) result.add(ProtoBufPackageKind.PACKAGE_MODULE_NAME)
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.packageModuleName), new.getExtension(JvmProtoBuf.packageModuleName))) result.add(ProtoBufPackageKind.JVM_EXT_PACKAGE_MODULE_NAME)
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.packageLocalVariable) != new.getExtensionCount(JvmProtoBuf.packageLocalVariable)) {
|
||||
result.add(ProtoBufPackageKind.JVM_EXT_PACKAGE_LOCAL_VARIABLE_LIST)
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.packageLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.packageLocalVariable, i), new.getExtension(JvmProtoBuf.packageLocalVariable, i))) result.add(ProtoBufPackageKind.JVM_EXT_PACKAGE_LOCAL_VARIABLE_LIST)
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JsProtoBuf.packageFqName) != new.hasExtension(JsProtoBuf.packageFqName)) result.add(ProtoBufPackageKind.JS_EXT_PACKAGE_FQ_NAME)
|
||||
if (old.hasExtension(JsProtoBuf.packageFqName)) {
|
||||
if (old.getExtension(JsProtoBuf.packageFqName) != new.getExtension(JsProtoBuf.packageFqName)) result.add(ProtoBufPackageKind.JS_EXT_PACKAGE_FQ_NAME)
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -147,6 +178,29 @@ 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
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.classLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.classLocalVariable, i), new.getExtension(JvmProtoBuf.classLocalVariable, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.classAnnotation) != new.getExtensionCount(JsProtoBuf.classAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.classAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.classAnnotation, i), new.getExtension(JsProtoBuf.classAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JsProtoBuf.classContainingFileId) != new.hasExtension(JsProtoBuf.classContainingFileId)) return false
|
||||
if (old.hasExtension(JsProtoBuf.classContainingFileId)) {
|
||||
if (old.getExtension(JsProtoBuf.classContainingFileId) != new.getExtension(JsProtoBuf.classContainingFileId)) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
enum class ProtoBufClassKind {
|
||||
@@ -166,7 +220,10 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
TYPE_TABLE,
|
||||
SINCE_KOTLIN_INFO,
|
||||
SINCE_KOTLIN_INFO_TABLE,
|
||||
CLASS_MODULE_NAME
|
||||
JVM_EXT_CLASS_MODULE_NAME,
|
||||
JVM_EXT_CLASS_LOCAL_VARIABLE_LIST,
|
||||
JS_EXT_CLASS_ANNOTATION_LIST,
|
||||
JS_EXT_CLASS_CONTAINING_FILE_ID
|
||||
}
|
||||
|
||||
fun difference(old: ProtoBuf.Class, new: ProtoBuf.Class): EnumSet<ProtoBufClassKind> {
|
||||
@@ -219,9 +276,32 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkEquals(old.sinceKotlinInfoTable, new.sinceKotlinInfoTable)) result.add(ProtoBufClassKind.SINCE_KOTLIN_INFO_TABLE)
|
||||
}
|
||||
|
||||
if (old.hasExtension(JvmProtoBuf.classModuleName) != new.hasExtension(JvmProtoBuf.classModuleName)) result.add(ProtoBufClassKind.CLASS_MODULE_NAME)
|
||||
if (old.hasExtension(JvmProtoBuf.classModuleName) != new.hasExtension(JvmProtoBuf.classModuleName)) result.add(ProtoBufClassKind.JVM_EXT_CLASS_MODULE_NAME)
|
||||
if (old.hasExtension(JvmProtoBuf.classModuleName)) {
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.classModuleName), new.getExtension(JvmProtoBuf.classModuleName))) result.add(ProtoBufClassKind.CLASS_MODULE_NAME)
|
||||
if (!checkStringEquals(old.getExtension(JvmProtoBuf.classModuleName), new.getExtension(JvmProtoBuf.classModuleName))) result.add(ProtoBufClassKind.JVM_EXT_CLASS_MODULE_NAME)
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.classLocalVariable) != new.getExtensionCount(JvmProtoBuf.classLocalVariable)) {
|
||||
result.add(ProtoBufClassKind.JVM_EXT_CLASS_LOCAL_VARIABLE_LIST)
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.classLocalVariable) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.classLocalVariable, i), new.getExtension(JvmProtoBuf.classLocalVariable, i))) result.add(ProtoBufClassKind.JVM_EXT_CLASS_LOCAL_VARIABLE_LIST)
|
||||
}
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.classAnnotation) != new.getExtensionCount(JsProtoBuf.classAnnotation)) {
|
||||
result.add(ProtoBufClassKind.JS_EXT_CLASS_ANNOTATION_LIST)
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.classAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.classAnnotation, i), new.getExtension(JsProtoBuf.classAnnotation, i))) result.add(ProtoBufClassKind.JS_EXT_CLASS_ANNOTATION_LIST)
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JsProtoBuf.classContainingFileId) != new.hasExtension(JsProtoBuf.classContainingFileId)) result.add(ProtoBufClassKind.JS_EXT_CLASS_CONTAINING_FILE_ID)
|
||||
if (old.hasExtension(JsProtoBuf.classContainingFileId)) {
|
||||
if (old.getExtension(JsProtoBuf.classContainingFileId) != new.getExtension(JsProtoBuf.classContainingFileId)) result.add(ProtoBufClassKind.JS_EXT_CLASS_CONTAINING_FILE_ID)
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -279,6 +359,20 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.methodSignature), new.getExtension(JvmProtoBuf.methodSignature))) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.functionAnnotation) != new.getExtensionCount(JsProtoBuf.functionAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.functionAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.functionAnnotation, i), new.getExtension(JsProtoBuf.functionAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JsProtoBuf.functionContainingFileId) != new.hasExtension(JsProtoBuf.functionContainingFileId)) return false
|
||||
if (old.hasExtension(JsProtoBuf.functionContainingFileId)) {
|
||||
if (old.getExtension(JsProtoBuf.functionContainingFileId) != new.getExtension(JsProtoBuf.functionContainingFileId)) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -342,6 +436,25 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.propertySignature), new.getExtension(JvmProtoBuf.propertySignature))) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.propertyAnnotation) != new.getExtensionCount(JsProtoBuf.propertyAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.propertyAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.propertyAnnotation, i), new.getExtension(JsProtoBuf.propertyAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JsProtoBuf.compileTimeValue) != new.hasExtension(JsProtoBuf.compileTimeValue)) return false
|
||||
if (old.hasExtension(JsProtoBuf.compileTimeValue)) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.compileTimeValue), new.getExtension(JsProtoBuf.compileTimeValue))) return false
|
||||
}
|
||||
|
||||
if (old.hasExtension(JsProtoBuf.propertyContainingFileId) != new.hasExtension(JsProtoBuf.propertyContainingFileId)) return false
|
||||
if (old.hasExtension(JsProtoBuf.propertyContainingFileId)) {
|
||||
if (old.getExtension(JsProtoBuf.propertyContainingFileId) != new.getExtension(JsProtoBuf.propertyContainingFileId)) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -421,10 +534,22 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
|
||||
if (!checkEqualsTypeParameterUpperBoundId(old, new)) return false
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.typeParameterAnnotation) != new.getExtensionCount(JvmProtoBuf.typeParameterAnnotation)) return false
|
||||
if (old.getExtensionCount(JvmProtoBuf.typeParameterAnnotation) != new.getExtensionCount(JvmProtoBuf.typeParameterAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.typeParameterAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.typeParameterAnnotation, i), new.getExtension(JvmProtoBuf.typeParameterAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.typeParameterAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.typeParameterAnnotation, i), new.getExtension(JvmProtoBuf.typeParameterAnnotation, i))) return false
|
||||
if (old.getExtensionCount(JsProtoBuf.typeParameterAnnotation) != new.getExtensionCount(JsProtoBuf.typeParameterAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.typeParameterAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.typeParameterAnnotation, i), new.getExtension(JsProtoBuf.typeParameterAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
@@ -498,10 +623,13 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.flags != new.flags) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JvmProtoBuf.typeAnnotation) != new.getExtensionCount(JvmProtoBuf.typeAnnotation)) return false
|
||||
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.typeAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.typeAnnotation, i), new.getExtension(JvmProtoBuf.typeAnnotation, i))) return false
|
||||
if (old.getExtensionCount(JvmProtoBuf.typeAnnotation) != new.getExtensionCount(JvmProtoBuf.typeAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JvmProtoBuf.typeAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.typeAnnotation, i), new.getExtension(JvmProtoBuf.typeAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
if (old.hasExtension(JvmProtoBuf.isRaw) != new.hasExtension(JvmProtoBuf.isRaw)) return false
|
||||
@@ -509,6 +637,15 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.getExtension(JvmProtoBuf.isRaw) != new.getExtension(JvmProtoBuf.isRaw)) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.typeAnnotation) != new.getExtensionCount(JsProtoBuf.typeAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.typeAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.typeAnnotation, i), new.getExtension(JsProtoBuf.typeAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -530,6 +667,15 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkEquals(old.getExtension(JvmProtoBuf.constructorSignature), new.getExtension(JvmProtoBuf.constructorSignature))) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.constructorAnnotation) != new.getExtensionCount(JsProtoBuf.constructorAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.constructorAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.constructorAnnotation, i), new.getExtension(JsProtoBuf.constructorAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -539,6 +685,23 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (!checkStringEquals(old.name, new.name)) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.enumEntryAnnotation) != new.getExtensionCount(JsProtoBuf.enumEntryAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.enumEntryAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.enumEntryAnnotation, i), new.getExtension(JsProtoBuf.enumEntryAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
open fun checkEquals(old: ProtoBuf.Annotation, new: ProtoBuf.Annotation): Boolean {
|
||||
if (!checkClassIdEquals(old.id, new.id)) return false
|
||||
|
||||
if (!checkEqualsAnnotationArgument(old, new)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -570,6 +733,15 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
if (old.varargElementTypeId != new.varargElementTypeId) return false
|
||||
}
|
||||
|
||||
if (old.getExtensionCount(JsProtoBuf.parameterAnnotation) != new.getExtensionCount(JsProtoBuf.parameterAnnotation)) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
for(i in 0..old.getExtensionCount(JsProtoBuf.parameterAnnotation) - 1) {
|
||||
if (!checkEquals(old.getExtension(JsProtoBuf.parameterAnnotation, i), new.getExtension(JsProtoBuf.parameterAnnotation, i))) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -611,10 +783,48 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
return true
|
||||
}
|
||||
|
||||
open fun checkEquals(old: ProtoBuf.Annotation, new: ProtoBuf.Annotation): Boolean {
|
||||
if (!checkClassIdEquals(old.id, new.id)) return false
|
||||
open fun checkEquals(old: ProtoBuf.Annotation.Argument.Value, new: ProtoBuf.Annotation.Argument.Value): Boolean {
|
||||
if (old.hasType() != new.hasType()) return false
|
||||
if (old.hasType()) {
|
||||
if (old.type != new.type) return false
|
||||
}
|
||||
|
||||
if (!checkEqualsAnnotationArgument(old, new)) return false
|
||||
if (old.hasIntValue() != new.hasIntValue()) return false
|
||||
if (old.hasIntValue()) {
|
||||
if (old.intValue != new.intValue) return false
|
||||
}
|
||||
|
||||
if (old.hasFloatValue() != new.hasFloatValue()) return false
|
||||
if (old.hasFloatValue()) {
|
||||
if (old.floatValue != new.floatValue) return false
|
||||
}
|
||||
|
||||
if (old.hasDoubleValue() != new.hasDoubleValue()) return false
|
||||
if (old.hasDoubleValue()) {
|
||||
if (old.doubleValue != new.doubleValue) return false
|
||||
}
|
||||
|
||||
if (old.hasStringValue() != new.hasStringValue()) return false
|
||||
if (old.hasStringValue()) {
|
||||
if (!checkStringEquals(old.stringValue, new.stringValue)) return false
|
||||
}
|
||||
|
||||
if (old.hasClassId() != new.hasClassId()) return false
|
||||
if (old.hasClassId()) {
|
||||
if (!checkClassIdEquals(old.classId, new.classId)) return false
|
||||
}
|
||||
|
||||
if (old.hasEnumValueId() != new.hasEnumValueId()) return false
|
||||
if (old.hasEnumValueId()) {
|
||||
if (!checkStringEquals(old.enumValueId, new.enumValueId)) return false
|
||||
}
|
||||
|
||||
if (old.hasAnnotation() != new.hasAnnotation()) return false
|
||||
if (old.hasAnnotation()) {
|
||||
if (!checkEquals(old.annotation, new.annotation)) return false
|
||||
}
|
||||
|
||||
if (!checkEqualsAnnotationArgumentValueArrayElement(old, new)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -667,6 +877,14 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
return true
|
||||
}
|
||||
|
||||
open fun checkEquals(old: ProtoBuf.Annotation.Argument, new: ProtoBuf.Annotation.Argument): Boolean {
|
||||
if (!checkStringEquals(old.nameId, new.nameId)) return false
|
||||
|
||||
if (!checkEquals(old.value, new.value)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
open fun checkEquals(old: JvmProtoBuf.JvmFieldSignature, new: JvmProtoBuf.JvmFieldSignature): Boolean {
|
||||
if (old.hasName() != new.hasName()) return false
|
||||
if (old.hasName()) {
|
||||
@@ -681,60 +899,6 @@ open class ProtoCompareGenerated(val oldNameResolver: NameResolver, val newNameR
|
||||
return true
|
||||
}
|
||||
|
||||
open fun checkEquals(old: ProtoBuf.Annotation.Argument, new: ProtoBuf.Annotation.Argument): Boolean {
|
||||
if (!checkStringEquals(old.nameId, new.nameId)) return false
|
||||
|
||||
if (!checkEquals(old.value, new.value)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
open fun checkEquals(old: ProtoBuf.Annotation.Argument.Value, new: ProtoBuf.Annotation.Argument.Value): Boolean {
|
||||
if (old.hasType() != new.hasType()) return false
|
||||
if (old.hasType()) {
|
||||
if (old.type != new.type) return false
|
||||
}
|
||||
|
||||
if (old.hasIntValue() != new.hasIntValue()) return false
|
||||
if (old.hasIntValue()) {
|
||||
if (old.intValue != new.intValue) return false
|
||||
}
|
||||
|
||||
if (old.hasFloatValue() != new.hasFloatValue()) return false
|
||||
if (old.hasFloatValue()) {
|
||||
if (old.floatValue != new.floatValue) return false
|
||||
}
|
||||
|
||||
if (old.hasDoubleValue() != new.hasDoubleValue()) return false
|
||||
if (old.hasDoubleValue()) {
|
||||
if (old.doubleValue != new.doubleValue) return false
|
||||
}
|
||||
|
||||
if (old.hasStringValue() != new.hasStringValue()) return false
|
||||
if (old.hasStringValue()) {
|
||||
if (!checkStringEquals(old.stringValue, new.stringValue)) return false
|
||||
}
|
||||
|
||||
if (old.hasClassId() != new.hasClassId()) return false
|
||||
if (old.hasClassId()) {
|
||||
if (!checkClassIdEquals(old.classId, new.classId)) return false
|
||||
}
|
||||
|
||||
if (old.hasEnumValueId() != new.hasEnumValueId()) return false
|
||||
if (old.hasEnumValueId()) {
|
||||
if (!checkStringEquals(old.enumValueId, new.enumValueId)) return false
|
||||
}
|
||||
|
||||
if (old.hasAnnotation() != new.hasAnnotation()) return false
|
||||
if (old.hasAnnotation()) {
|
||||
if (!checkEquals(old.annotation, new.annotation)) return false
|
||||
}
|
||||
|
||||
if (!checkEqualsAnnotationArgumentValueArrayElement(old, new)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
open fun checkEqualsPackageFunction(old: ProtoBuf.Package, new: ProtoBuf.Package): Boolean {
|
||||
if (old.functionCount != new.functionCount) return false
|
||||
|
||||
@@ -1053,6 +1217,14 @@ 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)
|
||||
}
|
||||
|
||||
if (hasExtension(JsProtoBuf.packageFqName)) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.packageFqName)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1125,6 +1297,18 @@ 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)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.classAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.classAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
if (hasExtension(JsProtoBuf.classContainingFileId)) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.classContainingFileId)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1177,6 +1361,14 @@ fun ProtoBuf.Function.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int)
|
||||
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.methodSignature).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.functionAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.functionAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
if (hasExtension(JsProtoBuf.functionContainingFileId)) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.functionContainingFileId)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1233,6 +1425,18 @@ fun ProtoBuf.Property.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int)
|
||||
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.propertySignature).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.propertyAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.propertyAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
if (hasExtension(JsProtoBuf.compileTimeValue)) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.compileTimeValue).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
if (hasExtension(JsProtoBuf.propertyContainingFileId)) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.propertyContainingFileId)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1327,6 +1531,10 @@ fun ProtoBuf.TypeParameter.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes:
|
||||
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.typeParameterAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.typeParameterAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.typeParameterAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1397,6 +1605,10 @@ fun ProtoBuf.Type.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) ->
|
||||
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.isRaw).hashCode()
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.typeAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.typeAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1419,6 +1631,10 @@ fun ProtoBuf.Constructor.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (I
|
||||
hashCode = 31 * hashCode + getExtension(JvmProtoBuf.constructorSignature).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.constructorAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.constructorAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1429,6 +1645,22 @@ fun ProtoBuf.EnumEntry.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int
|
||||
hashCode = 31 * hashCode + stringIndexes(name)
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.enumEntryAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.enumEntryAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
fun ProtoBuf.Annotation.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
|
||||
var hashCode = 1
|
||||
|
||||
hashCode = 31 * hashCode + fqNameIndexes(id)
|
||||
|
||||
for(i in 0..argumentCount - 1) {
|
||||
hashCode = 31 * hashCode + getArgument(i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1457,6 +1689,10 @@ fun ProtoBuf.ValueParameter.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes:
|
||||
hashCode = 31 * hashCode + varargElementTypeId
|
||||
}
|
||||
|
||||
for(i in 0..getExtensionCount(JsProtoBuf.parameterAnnotation) - 1) {
|
||||
hashCode = 31 * hashCode + getExtension(JsProtoBuf.parameterAnnotation, i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -1496,13 +1732,43 @@ fun JvmProtoBuf.JvmPropertySignature.hashCode(stringIndexes: (Int) -> Int, fqNam
|
||||
return hashCode
|
||||
}
|
||||
|
||||
fun ProtoBuf.Annotation.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
|
||||
fun ProtoBuf.Annotation.Argument.Value.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
|
||||
var hashCode = 1
|
||||
|
||||
hashCode = 31 * hashCode + fqNameIndexes(id)
|
||||
if (hasType()) {
|
||||
hashCode = 31 * hashCode + type.hashCode()
|
||||
}
|
||||
|
||||
for(i in 0..argumentCount - 1) {
|
||||
hashCode = 31 * hashCode + getArgument(i).hashCode(stringIndexes, fqNameIndexes)
|
||||
if (hasIntValue()) {
|
||||
hashCode = 31 * hashCode + intValue.hashCode()
|
||||
}
|
||||
|
||||
if (hasFloatValue()) {
|
||||
hashCode = 31 * hashCode + floatValue.hashCode()
|
||||
}
|
||||
|
||||
if (hasDoubleValue()) {
|
||||
hashCode = 31 * hashCode + doubleValue.hashCode()
|
||||
}
|
||||
|
||||
if (hasStringValue()) {
|
||||
hashCode = 31 * hashCode + stringIndexes(stringValue)
|
||||
}
|
||||
|
||||
if (hasClassId()) {
|
||||
hashCode = 31 * hashCode + fqNameIndexes(classId)
|
||||
}
|
||||
|
||||
if (hasEnumValueId()) {
|
||||
hashCode = 31 * hashCode + stringIndexes(enumValueId)
|
||||
}
|
||||
|
||||
if (hasAnnotation()) {
|
||||
hashCode = 31 * hashCode + annotation.hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..arrayElementCount - 1) {
|
||||
hashCode = 31 * hashCode + getArrayElement(i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
@@ -1552,6 +1818,16 @@ fun ProtoBuf.Type.Argument.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes:
|
||||
return hashCode
|
||||
}
|
||||
|
||||
fun ProtoBuf.Annotation.Argument.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
|
||||
var hashCode = 1
|
||||
|
||||
hashCode = 31 * hashCode + stringIndexes(nameId)
|
||||
|
||||
hashCode = 31 * hashCode + value.hashCode(stringIndexes, fqNameIndexes)
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
fun JvmProtoBuf.JvmFieldSignature.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
|
||||
var hashCode = 1
|
||||
|
||||
@@ -1565,55 +1841,3 @@ fun JvmProtoBuf.JvmFieldSignature.hashCode(stringIndexes: (Int) -> Int, fqNameIn
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
fun ProtoBuf.Annotation.Argument.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
|
||||
var hashCode = 1
|
||||
|
||||
hashCode = 31 * hashCode + stringIndexes(nameId)
|
||||
|
||||
hashCode = 31 * hashCode + value.hashCode(stringIndexes, fqNameIndexes)
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
fun ProtoBuf.Annotation.Argument.Value.hashCode(stringIndexes: (Int) -> Int, fqNameIndexes: (Int) -> Int): Int {
|
||||
var hashCode = 1
|
||||
|
||||
if (hasType()) {
|
||||
hashCode = 31 * hashCode + type.hashCode()
|
||||
}
|
||||
|
||||
if (hasIntValue()) {
|
||||
hashCode = 31 * hashCode + intValue.hashCode()
|
||||
}
|
||||
|
||||
if (hasFloatValue()) {
|
||||
hashCode = 31 * hashCode + floatValue.hashCode()
|
||||
}
|
||||
|
||||
if (hasDoubleValue()) {
|
||||
hashCode = 31 * hashCode + doubleValue.hashCode()
|
||||
}
|
||||
|
||||
if (hasStringValue()) {
|
||||
hashCode = 31 * hashCode + stringIndexes(stringValue)
|
||||
}
|
||||
|
||||
if (hasClassId()) {
|
||||
hashCode = 31 * hashCode + fqNameIndexes(classId)
|
||||
}
|
||||
|
||||
if (hasEnumValueId()) {
|
||||
hashCode = 31 * hashCode + stringIndexes(enumValueId)
|
||||
}
|
||||
|
||||
if (hasAnnotation()) {
|
||||
hashCode = 31 * hashCode + annotation.hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
for(i in 0..arrayElementCount - 1) {
|
||||
hashCode = 31 * hashCode + getArrayElement(i).hashCode(stringIndexes, fqNameIndexes)
|
||||
}
|
||||
|
||||
return hashCode
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// these functions are used in the kotlin gradle plugin
|
||||
@file:Suppress("unused")
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
@@ -25,8 +22,6 @@ import org.jetbrains.kotlin.build.GeneratedFile
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.build.JvmSourceRoot
|
||||
import org.jetbrains.kotlin.build.isModuleMappingFile
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
@@ -35,21 +30,24 @@ import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
|
||||
fun Iterable<File>.javaSourceRoots(roots: Iterable<File>): Iterable<File> =
|
||||
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 {
|
||||
fun makeModuleFile(
|
||||
name: String,
|
||||
isTest: Boolean,
|
||||
outputDir: File,
|
||||
sourcesToCompile: Iterable<File>,
|
||||
javaSourceRoots: Iterable<JvmSourceRoot>,
|
||||
classpath: Iterable<File>,
|
||||
friendDirs: Iterable<File>
|
||||
): File {
|
||||
val builder = KotlinModuleXmlBuilder()
|
||||
builder.addModule(
|
||||
name,
|
||||
outputDir.absolutePath,
|
||||
sourcesToCompile,
|
||||
javaSourceRoots.map { JvmSourceRoot(it) },
|
||||
javaSourceRoots,
|
||||
classpath,
|
||||
null,
|
||||
"java-production",
|
||||
@@ -70,72 +68,27 @@ fun makeCompileServices(
|
||||
compilationCanceledStatus: CompilationCanceledStatus?
|
||||
): Services =
|
||||
with(Services.Builder()) {
|
||||
register(IncrementalCompilationComponents::class.java,
|
||||
IncrementalCompilationComponentsImpl(incrementalCaches, lookupTracker))
|
||||
register(LookupTracker::class.java, lookupTracker)
|
||||
register(IncrementalCompilationComponents::class.java, IncrementalCompilationComponentsImpl(incrementalCaches))
|
||||
compilationCanceledStatus?.let {
|
||||
register(CompilationCanceledStatus::class.java, it)
|
||||
}
|
||||
build()
|
||||
}
|
||||
|
||||
fun makeLookupTracker(parentLookupTracker: LookupTracker = LookupTracker.DO_NOTHING): LookupTracker =
|
||||
if (IncrementalCompilation.isExperimental()) LookupTrackerImpl(parentLookupTracker)
|
||||
else parentLookupTracker
|
||||
|
||||
fun<Target> makeIncrementalCachesMap(
|
||||
targets: Iterable<Target>,
|
||||
getDependencies: (Target) -> Iterable<Target>,
|
||||
getCache: (Target) -> IncrementalCacheImpl<Target>,
|
||||
getTargetId: Target.() -> TargetId
|
||||
): Map<TargetId, IncrementalCacheImpl<Target>>
|
||||
{
|
||||
val dependents = targets.keysToMap { hashSetOf<Target>() }
|
||||
val targetsWithDependents = targets.toHashSet()
|
||||
|
||||
for (target in targets) {
|
||||
for (dependency in getDependencies(target)) {
|
||||
if (dependency !in targets) continue
|
||||
|
||||
dependents[dependency]!!.add(target)
|
||||
targetsWithDependents.add(target)
|
||||
}
|
||||
}
|
||||
|
||||
val caches = targetsWithDependents.keysToMap { getCache(it) }
|
||||
|
||||
for ((target, cache) in caches) {
|
||||
dependents[target]?.forEach {
|
||||
cache.addDependentCache(caches[it]!!)
|
||||
}
|
||||
}
|
||||
|
||||
return caches.mapKeys { it.key.getTargetId() }
|
||||
}
|
||||
|
||||
fun<Target> updateIncrementalCaches(
|
||||
targets: Iterable<Target>,
|
||||
generatedFiles: List<GeneratedFile<Target>>,
|
||||
compiledWithErrors: Boolean,
|
||||
getIncrementalCache: (Target) -> IncrementalCacheImpl<Target>
|
||||
): CompilationResult {
|
||||
|
||||
var changesInfo = CompilationResult.NO_CHANGES
|
||||
fun updateIncrementalCache(
|
||||
generatedFiles: Iterable<GeneratedFile>,
|
||||
cache: IncrementalJvmCache,
|
||||
changesCollector: ChangesCollector
|
||||
) {
|
||||
for (generatedFile in generatedFiles) {
|
||||
val ic = getIncrementalCache(generatedFile.target)
|
||||
when {
|
||||
generatedFile is GeneratedJvmClass<Target> -> changesInfo += ic.saveFileToCache(generatedFile)
|
||||
generatedFile.outputFile.isModuleMappingFile() -> changesInfo += ic.saveModuleMappingToCache(generatedFile.sourceFiles, generatedFile.outputFile)
|
||||
generatedFile is GeneratedJvmClass -> cache.saveFileToCache(generatedFile, changesCollector)
|
||||
generatedFile.outputFile.isModuleMappingFile() -> cache.saveModuleMappingToCache(generatedFile.sourceFiles, generatedFile.outputFile)
|
||||
}
|
||||
}
|
||||
|
||||
if (!compiledWithErrors) {
|
||||
targets.forEach {
|
||||
val newChangesInfo = getIncrementalCache(it).clearCacheForRemovedClasses()
|
||||
changesInfo += newChangesInfo
|
||||
}
|
||||
}
|
||||
|
||||
return changesInfo
|
||||
cache.clearCacheForRemovedClasses(changesCollector)
|
||||
}
|
||||
|
||||
fun LookupStorage.update(
|
||||
@@ -150,43 +103,19 @@ fun LookupStorage.update(
|
||||
addAll(lookupTracker.lookups.entrySet(), lookupTracker.pathInterner.values)
|
||||
}
|
||||
|
||||
fun<Target> OutputItemsCollectorImpl.generatedFiles(
|
||||
targets: Collection<Target>,
|
||||
representativeTarget: Target,
|
||||
getSources: (Target) -> Iterable<File>,
|
||||
getOutputDir: (Target) -> File?
|
||||
): List<GeneratedFile<Target>> {
|
||||
// If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below
|
||||
val sourceToTarget =
|
||||
if (targets.size >1) targets.flatMap { target -> getSources(target).map { Pair(it, target) } }.toMap()
|
||||
else mapOf<File, Target>()
|
||||
|
||||
return outputs.map { outputItem ->
|
||||
val target =
|
||||
outputItem.sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?:
|
||||
targets.singleOrNull { getOutputDir(it)?.let { outputItem.outputFile.startsWith(it) } ?: false } ?:
|
||||
representativeTarget
|
||||
|
||||
when (outputItem.outputFile.extension) {
|
||||
"class" -> GeneratedJvmClass(target, outputItem.sourceFiles, outputItem.outputFile)
|
||||
else -> GeneratedFile(target, outputItem.sourceFiles, outputItem.outputFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class DirtyData(
|
||||
val dirtyLookupSymbols: Collection<LookupSymbol> = emptyList(),
|
||||
val dirtyClassesFqNames: Collection<FqName> = emptyList()
|
||||
)
|
||||
|
||||
fun <Target> CompilationResult.getDirtyData(
|
||||
caches: Iterable<IncrementalCacheImpl<Target>>,
|
||||
fun ChangesCollector.getDirtyData(
|
||||
caches: Iterable<IncrementalCacheCommon>,
|
||||
reporter: ICReporter
|
||||
): DirtyData {
|
||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
val dirtyClassesFqNames = HashSet<FqName>()
|
||||
|
||||
for (change in changes) {
|
||||
for (change in changes()) {
|
||||
reporter.report { "Process $change" }
|
||||
|
||||
if (change is ChangeInfo.SignatureChanged) {
|
||||
@@ -233,8 +162,8 @@ fun mapLookupSymbolsToFiles(
|
||||
return dirtyFiles
|
||||
}
|
||||
|
||||
fun <Target> mapClassesFqNamesToFiles(
|
||||
caches: Iterable<IncrementalCacheImpl<Target>>,
|
||||
fun mapClassesFqNamesToFiles(
|
||||
caches: Iterable<IncrementalCacheCommon>,
|
||||
classesFqNames: Iterable<FqName>,
|
||||
reporter: ICReporter,
|
||||
excludes: Set<File> = emptySet()
|
||||
@@ -254,12 +183,9 @@ fun <Target> mapClassesFqNamesToFiles(
|
||||
return dirtyFiles
|
||||
}
|
||||
|
||||
private fun findSrcDirRoot(file: File, roots: Iterable<File>): File? =
|
||||
roots.firstOrNull { FileUtil.isAncestor(it, file, false) }
|
||||
|
||||
fun <Target> withSubtypes(
|
||||
fun withSubtypes(
|
||||
typeFqName: FqName,
|
||||
caches: Iterable<IncrementalCacheImpl<Target>>
|
||||
caches: Iterable<IncrementalCacheCommon>
|
||||
): Set<FqName> {
|
||||
val types = LinkedList(listOf(typeFqName))
|
||||
val subtypes = hashSetOf<FqName>()
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.incremental.ProtoCompareGenerated.ProtoBufClassKind
|
||||
import org.jetbrains.kotlin.incremental.ProtoCompareGenerated.ProtoBufPackageKind
|
||||
import org.jetbrains.kotlin.incremental.storage.ProtoMapValue
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.serialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
@@ -34,21 +35,19 @@ data class Difference(
|
||||
val changedMembersNames: Set<String> = emptySet()
|
||||
)
|
||||
|
||||
fun difference(oldData: ProtoMapValue, newData: ProtoMapValue): Difference {
|
||||
if (!oldData.isPackageFacade && newData.isPackageFacade) return Difference(isClassAffected = true, areSubclassesAffected = true)
|
||||
sealed class ProtoData
|
||||
data class ClassProtoData(val proto: ProtoBuf.Class, val nameResolver: NameResolver) : ProtoData()
|
||||
data class PackagePartProtoData(val proto: ProtoBuf.Package, val nameResolver: NameResolver, val packageFqName: FqName) : ProtoData()
|
||||
|
||||
if (oldData.isPackageFacade && !newData.isPackageFacade) return Difference(isClassAffected = true)
|
||||
|
||||
val differenceObject =
|
||||
if (oldData.isPackageFacade) {
|
||||
DifferenceCalculatorForPackageFacade(oldData, newData)
|
||||
}
|
||||
else {
|
||||
DifferenceCalculatorForClass(oldData, newData)
|
||||
}
|
||||
|
||||
return differenceObject.difference()
|
||||
}
|
||||
fun ProtoMapValue.toProtoData(packageFqName: FqName): ProtoData =
|
||||
if (isPackageFacade) {
|
||||
val packageData = JvmProtoBufUtil.readPackageDataFrom(bytes, strings)
|
||||
PackagePartProtoData(packageData.packageProto, packageData.nameResolver, packageFqName)
|
||||
}
|
||||
else {
|
||||
val classData = JvmProtoBufUtil.readClassDataFrom(bytes, strings)
|
||||
ClassProtoData(classData.classProto, classData.nameResolver)
|
||||
}
|
||||
|
||||
internal val MessageLite.isPrivate: Boolean
|
||||
get() = Visibilities.isPrivate(Deserialization.visibility(
|
||||
@@ -72,11 +71,8 @@ private fun MessageLite.name(nameResolver: NameResolver): String {
|
||||
|
||||
internal fun List<MessageLite>.names(nameResolver: NameResolver): List<String> = map { it.name(nameResolver) }
|
||||
|
||||
private abstract class DifferenceCalculator() {
|
||||
protected abstract val oldNameResolver: NameResolver
|
||||
protected abstract val newNameResolver: NameResolver
|
||||
|
||||
protected val compareObject by lazy { ProtoCompareGenerated(oldNameResolver, newNameResolver) }
|
||||
abstract class DifferenceCalculator {
|
||||
protected abstract val compareObject: ProtoCompareGenerated
|
||||
|
||||
abstract fun difference(): Difference
|
||||
|
||||
@@ -158,19 +154,18 @@ private abstract class DifferenceCalculator() {
|
||||
}
|
||||
}
|
||||
|
||||
private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: ProtoMapValue) : DifferenceCalculator() {
|
||||
val oldClassData = JvmProtoBufUtil.readClassDataFrom(oldData.bytes, oldData.strings)
|
||||
val newClassData = JvmProtoBufUtil.readClassDataFrom(newData.bytes, newData.strings)
|
||||
|
||||
val oldProto = oldClassData.classProto
|
||||
val newProto = newClassData.classProto
|
||||
|
||||
override val oldNameResolver = oldClassData.nameResolver
|
||||
override val newNameResolver = newClassData.nameResolver
|
||||
|
||||
val diff = compareObject.difference(oldProto, newProto)
|
||||
class DifferenceCalculatorForClass(
|
||||
private val oldData: ClassProtoData,
|
||||
private val newData: ClassProtoData
|
||||
) : DifferenceCalculator() {
|
||||
override val compareObject = ProtoCompareGenerated(oldData.nameResolver, newData.nameResolver)
|
||||
|
||||
override fun difference(): Difference {
|
||||
val (oldProto, oldNameResolver) = oldData
|
||||
val (newProto, newNameResolver) = newData
|
||||
|
||||
val diff = compareObject.difference(oldProto, newProto)
|
||||
|
||||
var isClassAffected = false
|
||||
var areSubclassesAffected = false
|
||||
val names = hashSetOf<String>()
|
||||
@@ -186,7 +181,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 +199,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))
|
||||
@@ -218,7 +211,15 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
isClassAffected = true
|
||||
}
|
||||
ProtoBufClassKind.SEALED_SUBCLASS_FQ_NAME_LIST -> {
|
||||
// TODO
|
||||
isClassAffected = true
|
||||
// Subclasses are considered to be affected to fix the case where
|
||||
// an implementation is added to an nth-level (n > 1) sealed class.
|
||||
// In case of the following hierarchy:
|
||||
// Base <- Intermediate <- Impl
|
||||
// the change of the SEALED_SUBCLASS_FQ_NAME_LIST will be detected in the Intermediate,
|
||||
// but there can be usages, that should be rebuilt, without direct references to the Intermediate:
|
||||
// when (x as Base) { is Impl -> ... }
|
||||
areSubclassesAffected = true
|
||||
}
|
||||
ProtoBufClassKind.TYPE_TABLE -> {
|
||||
// TODO
|
||||
@@ -231,12 +232,17 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
ProtoBufClassKind.FQ_NAME,
|
||||
ProtoBufClassKind.TYPE_PARAMETER_LIST,
|
||||
ProtoBufClassKind.SUPERTYPE_LIST,
|
||||
ProtoBufClassKind.SUPERTYPE_ID_LIST-> {
|
||||
ProtoBufClassKind.SUPERTYPE_ID_LIST,
|
||||
ProtoBufClassKind.JS_EXT_CLASS_ANNOTATION_LIST -> {
|
||||
isClassAffected = true
|
||||
areSubclassesAffected = true
|
||||
}
|
||||
ProtoBufClassKind.CLASS_MODULE_NAME -> {
|
||||
// TODO
|
||||
ProtoBufClassKind.JVM_EXT_CLASS_MODULE_NAME,
|
||||
ProtoBufClassKind.JS_EXT_CLASS_CONTAINING_FILE_ID -> {
|
||||
// TODO
|
||||
}
|
||||
ProtoBufClassKind.JVM_EXT_CLASS_LOCAL_VARIABLE_LIST -> {
|
||||
// Not affected, local variables are not accessible outside of a file
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,19 +251,18 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
}
|
||||
}
|
||||
|
||||
private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newData: ProtoMapValue) : DifferenceCalculator() {
|
||||
val oldPackageData = JvmProtoBufUtil.readPackageDataFrom(oldData.bytes, oldData.strings)
|
||||
val newPackageData = JvmProtoBufUtil.readPackageDataFrom(newData.bytes, newData.strings)
|
||||
|
||||
val oldProto = oldPackageData.packageProto
|
||||
val newProto = newPackageData.packageProto
|
||||
|
||||
override val oldNameResolver = oldPackageData.nameResolver
|
||||
override val newNameResolver = newPackageData.nameResolver
|
||||
|
||||
val diff = compareObject.difference(oldProto, newProto)
|
||||
class DifferenceCalculatorForPackageFacade(
|
||||
private val oldData: PackagePartProtoData,
|
||||
private val newData: PackagePartProtoData
|
||||
) : DifferenceCalculator() {
|
||||
override val compareObject = ProtoCompareGenerated(oldData.nameResolver, newData.nameResolver)
|
||||
|
||||
override fun difference(): Difference {
|
||||
val oldProto = oldData.proto
|
||||
val newProto = newData.proto
|
||||
|
||||
val diff = compareObject.difference(oldProto, newProto)
|
||||
|
||||
val names = hashSetOf<String>()
|
||||
|
||||
fun calcDifferenceForNonPrivateMembers(members: (ProtoBuf.Package) -> List<MessageLite>): Collection<String> {
|
||||
@@ -267,7 +272,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 ->
|
||||
@@ -276,10 +282,13 @@ private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newDa
|
||||
names.addAll(calcDifferenceForNonPrivateMembers(ProtoBuf.Package::getTypeAliasList))
|
||||
ProtoBufPackageKind.TYPE_TABLE,
|
||||
ProtoBufPackageKind.SINCE_KOTLIN_INFO_TABLE,
|
||||
ProtoBufPackageKind.PACKAGE_MODULE_NAME -> {
|
||||
ProtoBufPackageKind.JVM_EXT_PACKAGE_MODULE_NAME,
|
||||
ProtoBufPackageKind.JS_EXT_PACKAGE_FQ_NAME-> {
|
||||
// TODO
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unsupported kind: $kind")
|
||||
ProtoBufPackageKind.JVM_EXT_PACKAGE_LOCAL_VARIABLE_LIST -> {
|
||||
// Not affected, local variables are not accessible outside of a file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,18 @@
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.io.File
|
||||
|
||||
open class BasicMapsOwner {
|
||||
open class BasicMapsOwner(val cachesDir: File) {
|
||||
private val maps = arrayListOf<BasicMap<*, *>>()
|
||||
|
||||
companion object {
|
||||
val CACHE_EXTENSION = "tab"
|
||||
}
|
||||
|
||||
protected val String.storageFile: File
|
||||
get() = File(cachesDir, this + "." + CACHE_EXTENSION)
|
||||
|
||||
protected fun <K, V, M : BasicMap<K, V>> registerMap(map: M): M {
|
||||
maps.add(map)
|
||||
return map
|
||||
|
||||
@@ -87,7 +87,7 @@ class LazyStorage<K, V>(
|
||||
try {
|
||||
storage?.close()
|
||||
}
|
||||
catch (ignored: IOException) {
|
||||
catch (ignored: Throwable) {
|
||||
}
|
||||
|
||||
PersistentHashMap.deleteFilesStartingWith(storageFile)
|
||||
|
||||
@@ -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.
|
||||
@@ -17,22 +17,25 @@
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import junit.framework.TestCase
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import java.io.File
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
abstract class TestWithWorkingDir {
|
||||
abstract class TestWithWorkingDir : TestCase() {
|
||||
protected var workingDir: File by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Before
|
||||
open fun setUp() {
|
||||
workingDir = FileUtil.createTempDirectory(this::class.java.simpleName, null)
|
||||
public override fun setUp() {
|
||||
super.setUp()
|
||||
workingDir = FileUtil.createTempDirectory(this::class.java.simpleName, null, /* deleteOnExit = */ true)
|
||||
}
|
||||
|
||||
@After
|
||||
open fun tearDown() {
|
||||
public override fun tearDown() {
|
||||
workingDir.deleteRecursively()
|
||||
super.tearDown()
|
||||
}
|
||||
}
|
||||
@@ -18,15 +18,15 @@ package org.jetbrains.kotlin.incremental.testingUtils
|
||||
|
||||
import java.io.File
|
||||
|
||||
class BuildLogFinder(
|
||||
private val isExperimentalEnabled: Boolean = false,
|
||||
data class BuildLogFinder(
|
||||
private val isDataContainerBuildLogEnabled: Boolean = false,
|
||||
private val isGradleEnabled: Boolean = false
|
||||
private val isGradleEnabled: Boolean = false,
|
||||
private val isJsEnabled: Boolean = false
|
||||
) {
|
||||
companion object {
|
||||
private const val JS_LOG = "js-build.log"
|
||||
private const val GRADLE_LOG = "gradle-build.log"
|
||||
private const val DATA_CONTAINER_LOG = "data-container-version-build.log"
|
||||
private const val EXPERIMENTAL_LOG = "experimental-ic-build.log"
|
||||
private const val SIMPLE_LOG = "build.log"
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ class BuildLogFinder(
|
||||
val names = dir.list() ?: arrayOf()
|
||||
val files = names.filter { File(dir, it).isFile }.toSet()
|
||||
val matchedName = when {
|
||||
isJsEnabled && JS_LOG in files -> JS_LOG
|
||||
isGradleEnabled && GRADLE_LOG in files -> GRADLE_LOG
|
||||
isDataContainerBuildLogEnabled && DATA_CONTAINER_LOG in files -> DATA_CONTAINER_LOG
|
||||
isExperimentalEnabled && EXPERIMENTAL_LOG in files -> EXPERIMENTAL_LOG
|
||||
SIMPLE_LOG in files -> SIMPLE_LOG
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -128,13 +128,13 @@ fun getModificationsToPerform(
|
||||
}
|
||||
|
||||
abstract class Modification(val path: String) {
|
||||
abstract fun perform(workDir: File, mapping: MutableMap<File, File>)
|
||||
abstract fun perform(workDir: File, mapping: MutableMap<File, File>): File?
|
||||
|
||||
override fun toString(): String = "${this::class.java.simpleName} $path"
|
||||
}
|
||||
|
||||
class ModifyContent(path: String, val dataFile: File) : Modification(path) {
|
||||
override fun perform(workDir: File, mapping: MutableMap<File, File>) {
|
||||
override fun perform(workDir: File, mapping: MutableMap<File, File>): File? {
|
||||
val file = File(workDir, path)
|
||||
|
||||
val oldLastModified = file.lastModified()
|
||||
@@ -148,11 +148,12 @@ class ModifyContent(path: String, val dataFile: File) : Modification(path) {
|
||||
}
|
||||
|
||||
mapping[file] = dataFile
|
||||
return file
|
||||
}
|
||||
}
|
||||
|
||||
class TouchFile(path: String, private val touchPolicy: TouchPolicy) : Modification(path) {
|
||||
override fun perform(workDir: File, mapping: MutableMap<File, File>) {
|
||||
override fun perform(workDir: File, mapping: MutableMap<File, File>): File? {
|
||||
val file = File(workDir, path)
|
||||
|
||||
when (touchPolicy) {
|
||||
@@ -166,16 +167,18 @@ class TouchFile(path: String, private val touchPolicy: TouchPolicy) : Modificati
|
||||
}
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
}
|
||||
|
||||
class DeleteFile(path: String) : Modification(path) {
|
||||
override fun perform(workDir: File, mapping: MutableMap<File, File>) {
|
||||
override fun perform(workDir: File, mapping: MutableMap<File, File>): File? {
|
||||
val fileToDelete = File(workDir, path)
|
||||
if (!fileToDelete.delete()) {
|
||||
throw AssertionError("Couldn't delete $fileToDelete")
|
||||
}
|
||||
|
||||
mapping.remove(fileToDelete)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9743,7 +9743,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
boolean hasFlags();
|
||||
@@ -9757,7 +9757,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
int getFlags();
|
||||
@@ -10465,7 +10465,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public boolean hasFlags() {
|
||||
@@ -10481,7 +10481,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public int getFlags() {
|
||||
@@ -11826,7 +11826,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public boolean hasFlags() {
|
||||
@@ -11842,7 +11842,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public int getFlags() {
|
||||
@@ -11858,7 +11858,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public Builder setFlags(int value) {
|
||||
@@ -11877,7 +11877,7 @@ public final class DebugProtoBuf {
|
||||
*ClassKind
|
||||
*isInner
|
||||
*isData
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public Builder clearFlags() {
|
||||
@@ -17734,7 +17734,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
boolean hasFlags();
|
||||
@@ -17752,7 +17752,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
int getFlags();
|
||||
@@ -18097,7 +18097,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public boolean hasFlags() {
|
||||
@@ -18117,7 +18117,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public int getFlags() {
|
||||
@@ -18930,7 +18930,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public boolean hasFlags() {
|
||||
@@ -18950,7 +18950,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public int getFlags() {
|
||||
@@ -18970,7 +18970,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public Builder setFlags(int value) {
|
||||
@@ -18993,7 +18993,7 @@ public final class DebugProtoBuf {
|
||||
*isTailrec
|
||||
*isExternal
|
||||
*isSuspend
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public Builder clearFlags() {
|
||||
@@ -20039,7 +20039,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
boolean hasFlags();
|
||||
@@ -20059,7 +20059,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
int getFlags();
|
||||
@@ -20417,7 +20417,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public boolean hasFlags() {
|
||||
@@ -20439,7 +20439,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public int getFlags() {
|
||||
@@ -21239,7 +21239,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public boolean hasFlags() {
|
||||
@@ -21261,7 +21261,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public int getFlags() {
|
||||
@@ -21283,7 +21283,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public Builder setFlags(int value) {
|
||||
@@ -21308,7 +21308,7 @@ public final class DebugProtoBuf {
|
||||
*hasConstant
|
||||
*isExternal
|
||||
*isDelegated
|
||||
*isHeader
|
||||
*isExpect
|
||||
* </pre>
|
||||
*/
|
||||
public Builder clearFlags() {
|
||||
@@ -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>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
40
build.xml
40
build.xml
@@ -61,10 +61,11 @@
|
||||
<pathelement location="${tools.jar}"/>
|
||||
|
||||
<fileset dir="${basedir}/lib" includes="**/*.jar"/>
|
||||
<fileset dir="${dependencies}" includes="jline3.jar"/>
|
||||
<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>
|
||||
|
||||
@@ -386,23 +387,26 @@
|
||||
<zipgroupfileset dir="${basedir}/lib" includes="*.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/annotations.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/asm-all.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/guava-19.0.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/guava-21.0.jar"/>
|
||||
<zipfileset src="${basedir}/ideaSDK/core/intellij-core.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" 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/streamex-0.6.2.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" excludes="META-INF/jb/** META-INF/LICENSE"/>
|
||||
<zipfileset src="${idea.sdk}/jps/jps-model.jar"/>
|
||||
<zipfileset src="${dependencies}/jline.jar"/>
|
||||
<zipfileset src="${idea.sdk}/jps/jps-model.jar" excludes="META-INF/services/**"/>
|
||||
<zipfileset src="${dependencies}/jline3.jar"/>
|
||||
<zipfileset src="${dependencies}/jansi.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}"/>
|
||||
@@ -554,6 +558,8 @@
|
||||
<pathelement path="build-common/test"/>
|
||||
<pathelement path="compiler/incremental-compilation-impl/test"/>
|
||||
</src>
|
||||
<exclude name="**/*Generated.java"/>
|
||||
|
||||
<classpath>
|
||||
<pathelement path="${bootstrap.runtime}"/>
|
||||
<pathelement path="${bootstrap.reflect}"/>
|
||||
@@ -653,9 +659,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>
|
||||
@@ -667,6 +675,28 @@
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="android-extensions-runtime">
|
||||
<cleandir dir="${output}/classes/android-extensions/android-extensions-runtime"/>
|
||||
<javac2 destdir="${output}/classes/android-extensions/android-extensions-runtime" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
|
||||
<withKotlin modulename="kotlin-android-extensions-runtime">
|
||||
<compilerarg value="-version"/>
|
||||
</withKotlin>
|
||||
<skip pattern="kotlin/Metadata"/>
|
||||
<src>
|
||||
<pathelement path="plugins/android-extensions/android-extensions-runtime/src"/>
|
||||
</src>
|
||||
<classpath>
|
||||
<pathelement path="${idea.sdk}/plugins/android/lib/layoutlib.jar"/>
|
||||
</classpath>
|
||||
</javac2>
|
||||
|
||||
<jar destfile="${kotlin-home}/lib/android-extensions-runtime.jar">
|
||||
<fileset dir="${output}/classes/android-extensions/android-extensions-runtime"/>
|
||||
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="allopen-compiler-plugin">
|
||||
<cleandir dir="${output}/classes/allopen-compiler-plugin"/>
|
||||
<javac2 destdir="${output}/classes/allopen-compiler-plugin" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
|
||||
@@ -953,7 +983,7 @@
|
||||
depends="gradle-runtime,mock-runtime-for-test"/>
|
||||
|
||||
<target name="other-artifacts"
|
||||
depends="android-extensions-compiler,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,source-sections-compiler-plugin,annotation-processing,daemon-client,compiler-client-embeddable,kotlin-build-common-test" />
|
||||
depends="android-extensions-compiler,android-extensions-runtime,allopen-compiler-plugin,noarg-compiler-plugin,sam-with-receiver-compiler-plugin,source-sections-compiler-plugin,annotation-processing,daemon-client,compiler-client-embeddable,kotlin-build-common-test" />
|
||||
|
||||
<target name="dist"
|
||||
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler-fork,compiler-sources,ant-tools,runtime,other-artifacts"
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-beta4'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
@@ -15,11 +17,12 @@ apply plugin: 'com.android.application'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "23.0.3"
|
||||
buildToolsVersion "26.0.1"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.jetbrains.kotlin.android.tests"
|
||||
@@ -64,7 +67,7 @@ android {
|
||||
|
||||
dexOptions {
|
||||
dexInProcess false
|
||||
javaMaxHeapSize "300m"
|
||||
javaMaxHeapSize "600m"
|
||||
//default is 4 and Total Memory = maxProcessCount * javaMaxHeapSize
|
||||
maxProcessCount 1
|
||||
additionalParameters "--debug"
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
#don't try to download android specific tools within gradle: licence acceptance will be required
|
||||
android.builder.sdkDownload=false
|
||||
android.builder.sdkDownload=false
|
||||
android.enableAapt2=false
|
||||
android.enableD8=false
|
||||
@@ -41,19 +41,19 @@ public class SDKDownloader {
|
||||
//NOTE: PLATFORM_TOOLS 23.1.0 requires only 64 bit build agents
|
||||
private static final String PLATFORM_TOOLS = "23.0.1";
|
||||
private static final String SDK_TOOLS = "25.1.1";
|
||||
public static final String BUILD_TOOLS = "23.0.3";
|
||||
public static final String BUILD_TOOLS = "26.0.1";
|
||||
private static final int ANDROID_VERSION = 19;
|
||||
public static final String GRADLE_VERSION = "2.14.1";
|
||||
public static final String GRADLE_VERSION = "4.1";
|
||||
|
||||
|
||||
public SDKDownloader(PathManager pathManager) {
|
||||
this.pathManager = pathManager;
|
||||
platformZipPath = pathManager.getRootForDownload() + "/platforms.zip";
|
||||
platformZipPath = pathManager.getRootForDownload() + "/platform" + ANDROID_VERSION + ".zip";
|
||||
armImage = pathManager.getRootForDownload() + "/arm-image.zip";
|
||||
x86Image = pathManager.getRootForDownload() + "/x86-image.zip";
|
||||
platformToolsZipPath = pathManager.getRootForDownload() + "/platform-tools.zip";
|
||||
skdToolsZipPath = pathManager.getRootForDownload() + "/tools.zip";
|
||||
buildToolsZipPath = pathManager.getRootForDownload() + "/build-tools.zip";
|
||||
platformToolsZipPath = pathManager.getRootForDownload() + "/platform-tools" + PLATFORM_TOOLS + ".zip";
|
||||
skdToolsZipPath = pathManager.getRootForDownload() + "/tools" + SDK_TOOLS + ".zip";
|
||||
buildToolsZipPath = pathManager.getRootForDownload() + "/build-tools" + BUILD_TOOLS + ".zip";
|
||||
gradleZipPath = pathManager.getRootForDownload() + "/gradle" + GRADLE_VERSION + ".zip";
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ public class SDKDownloader {
|
||||
String buildToolsFolder = buildTools + BUILD_TOOLS + "/";
|
||||
new File(buildToolsFolder).delete();
|
||||
unzip(buildToolsZipPath, buildTools);
|
||||
new File(buildTools + "/android-6.0").renameTo(new File(buildToolsFolder));
|
||||
new File(buildTools + "/android-8.0.0").renameTo(new File(buildToolsFolder));
|
||||
}
|
||||
|
||||
public void deleteAll() {
|
||||
|
||||
@@ -33,6 +33,7 @@ public class GradleRunner {
|
||||
listOfCommands = new ArrayList<>();
|
||||
String cmdName = SystemInfo.isWindows ? "gradle.bat" : "gradle";
|
||||
listOfCommands.add(pathManager.getGradleBinFolder() + "/" + cmdName);
|
||||
listOfCommands.add("--no-daemon");
|
||||
listOfCommands.add("--build-file");
|
||||
listOfCommands.add(pathManager.getTmpFolder() + "/build.gradle");
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.kotlin.android.tests;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -28,6 +30,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestFiles;
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils;
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
|
||||
@@ -145,14 +148,16 @@ public class CodegenTestsOnAndroidGenerator extends KtUsefulTestCase {
|
||||
|
||||
public List<KtFile> files = new ArrayList<>();
|
||||
private KotlinCoreEnvironment environment;
|
||||
private Disposable disposable;
|
||||
|
||||
private FilesWriter(boolean isFullJdkAndRuntime, boolean inheritMultifileParts) {
|
||||
this.isFullJdkAndRuntime = isFullJdkAndRuntime;
|
||||
this.inheritMultifileParts = inheritMultifileParts;
|
||||
this.environment = createEnvironment(isFullJdkAndRuntime);
|
||||
this.disposable = new TestDisposable();
|
||||
this.environment = createEnvironment(isFullJdkAndRuntime, disposable);
|
||||
}
|
||||
|
||||
private KotlinCoreEnvironment createEnvironment(boolean isFullJdkAndRuntime) {
|
||||
private KotlinCoreEnvironment createEnvironment(boolean isFullJdkAndRuntime, @NotNull Disposable disposable) {
|
||||
ConfigurationKind configurationKind = isFullJdkAndRuntime ? ConfigurationKind.ALL : ConfigurationKind.NO_KOTLIN_REFLECT;
|
||||
TestJdkKind testJdkKind = isFullJdkAndRuntime ? TestJdkKind.FULL_JDK : TestJdkKind.MOCK_JDK;
|
||||
CompilerConfiguration configuration =
|
||||
@@ -161,7 +166,7 @@ public class CodegenTestsOnAndroidGenerator extends KtUsefulTestCase {
|
||||
if (inheritMultifileParts) {
|
||||
configuration.put(JVMConfigurationKeys.INHERIT_MULTIFILE_PARTS, true);
|
||||
}
|
||||
return KotlinCoreEnvironment.createForTests(myTestRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
return KotlinCoreEnvironment.createForTests(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
}
|
||||
|
||||
public boolean shouldWriteFilesOnDisk() {
|
||||
@@ -177,7 +182,11 @@ public class CodegenTestsOnAndroidGenerator extends KtUsefulTestCase {
|
||||
public void writeFilesOnDisk() {
|
||||
writeFiles(files);
|
||||
files = new ArrayList<>();
|
||||
environment = createEnvironment(isFullJdkAndRuntime);
|
||||
if (disposable != null) {
|
||||
Disposer.dispose(disposable);
|
||||
disposable = new TestDisposable();
|
||||
}
|
||||
environment = createEnvironment(isFullJdkAndRuntime, disposable);
|
||||
}
|
||||
|
||||
public void addFile(String name, String content) {
|
||||
@@ -202,12 +211,19 @@ public class CodegenTestsOnAndroidGenerator extends KtUsefulTestCase {
|
||||
? " (JVM.INHERIT_MULTIFILE_PARTS)"
|
||||
: isFullJdkAndRuntime ? " (full jdk and runtime)" : "") + " into " + outputDir.getName() + "...");
|
||||
OutputFileCollection outputFiles;
|
||||
GenerationState state = null;
|
||||
try {
|
||||
outputFiles = GenerationUtils.compileFiles(filesToCompile, environment).getFactory();
|
||||
state = GenerationUtils.compileFiles(filesToCompile, environment);
|
||||
outputFiles = state.getFactory();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
if (state != null) {
|
||||
state.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
if (!outputDir.exists()) {
|
||||
outputDir.mkdirs();
|
||||
|
||||
@@ -122,6 +122,7 @@ public class SpecialFiles {
|
||||
// KT-8120
|
||||
excludedFiles.add("closureOfInnerLocalClass.kt");
|
||||
excludedFiles.add("closureWithSelfInstantiation.kt");
|
||||
excludedFiles.add("quotedClassName.kt");
|
||||
}
|
||||
|
||||
private SpecialFiles() {
|
||||
|
||||
@@ -156,10 +156,9 @@ object CodegenUtil {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun constructFakeFunctionCall(project: Project, referencedFunction: FunctionDescriptor): KtCallExpression {
|
||||
val fakeFunctionCall = StringBuilder("callableReferenceFakeCall(")
|
||||
fakeFunctionCall.append(referencedFunction.valueParameters.joinToString(", ") { "p${it.index}" })
|
||||
fakeFunctionCall.append(")")
|
||||
return KtPsiFactory(project, markGenerated = false).createExpression(fakeFunctionCall.toString()) as KtCallExpression
|
||||
fun constructFakeFunctionCall(project: Project, arity: Int): KtCallExpression {
|
||||
val fakeFunctionCall =
|
||||
(1..arity).joinToString(prefix = "callableReferenceFakeCall(", separator = ", ", postfix = ")") { "p$it" }
|
||||
return KtPsiFactory(project, markGenerated = false).createExpression(fakeFunctionCall) as KtCallExpression
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,22 @@ package org.jetbrains.kotlin.codegen
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
abstract class AccessorForPropertyBackingField(property: PropertyDescriptor,
|
||||
type: KotlinType,
|
||||
receiverType: KotlinType?,
|
||||
dispatchReceiver: ReceiverParameterDescriptor?,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
suffix: String
|
||||
) : AccessorForPropertyDescriptor(property, type, receiverType, dispatchReceiver, containingDeclaration, null, suffix)
|
||||
class AccessorForPropertyBackingField(
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
delegateType: KotlinType?,
|
||||
extensionReceiverParameter: ReceiverParameterDescriptor?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
nameSuffix: String,
|
||||
val fieldAccessorKind: FieldAccessorKind
|
||||
) : AccessorForPropertyDescriptor(
|
||||
property,
|
||||
delegateType ?: property.type,
|
||||
extensionReceiverParameter?.type,
|
||||
dispatchReceiverParameter,
|
||||
containingDeclaration,
|
||||
null,
|
||||
nameSuffix
|
||||
)
|
||||
|
||||
@@ -1,28 +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 org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
class AccessorForPropertyBackingFieldFromLocal(property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
nameSuffix: String
|
||||
) : AccessorForPropertyBackingField(property, property.type,
|
||||
DescriptorUtils.getReceiverParameterType(property.extensionReceiverParameter),
|
||||
property.dispatchReceiverParameter, containingDeclaration, nameSuffix)
|
||||
@@ -1,27 +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 org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class AccessorForPropertyBackingFieldInClassCompanion(property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
delegationType: KotlinType?,
|
||||
nameSuffix: String
|
||||
) : AccessorForPropertyBackingField(property, delegationType ?: property.type, null, null, containingDeclaration, nameSuffix)
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ 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;
|
||||
import org.jetbrains.kotlin.resolve.DeprecationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
@@ -139,16 +139,16 @@ 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 isNumberPrimitiveOrBoolean(Type type) {
|
||||
return isNumberPrimitive(type) || type.getSort() == Type.BOOLEAN;
|
||||
}
|
||||
|
||||
public static boolean isNumberPrimitive(Type type) {
|
||||
return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
|
||||
public static boolean isIntOrLongPrimitive(Type type) {
|
||||
return isIntPrimitive(type) || type == Type.LONG_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isPrimitive(Type type) {
|
||||
@@ -202,7 +202,7 @@ public class AsmUtil {
|
||||
}
|
||||
|
||||
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind, GenerationState state) {
|
||||
int flags = getCommonCallableFlags(functionDescriptor);
|
||||
int flags = getCommonCallableFlags(functionDescriptor, state);
|
||||
|
||||
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.METHOD_FLAGS) {
|
||||
if (flagAnnotation.hasAnnotation(functionDescriptor.getOriginal())) {
|
||||
@@ -243,17 +243,11 @@ public class AsmUtil {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) {
|
||||
public static int getCommonCallableFlags(FunctionDescriptor functionDescriptor, @NotNull GenerationState state) {
|
||||
int flags = getVisibilityAccessFlag(functionDescriptor);
|
||||
flags |= getVarargsFlag(functionDescriptor);
|
||||
flags |= getDeprecatedAccessFlag(functionDescriptor);
|
||||
if (DeprecationUtilKt.isDeprecatedHidden(functionDescriptor, LanguageVersionSettingsImpl.DEFAULT)
|
||||
|| functionDescriptor instanceof PropertyAccessorDescriptor
|
||||
&& DeprecationUtilKt.isDeprecatedHidden(
|
||||
((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(),
|
||||
LanguageVersionSettingsImpl.DEFAULT
|
||||
)
|
||||
) {
|
||||
if (state.getDeprecationProvider().isDeprecatedHidden(functionDescriptor)) {
|
||||
flags |= ACC_SYNTHETIC;
|
||||
}
|
||||
return flags;
|
||||
@@ -353,7 +347,9 @@ public class AsmUtil {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
Visibility memberVisibility = memberDescriptor.getVisibility();
|
||||
|
||||
if (isEffectivelyInlineOnly(memberDescriptor)) return ACC_PRIVATE;
|
||||
if (isEffectivelyInlineOnly(memberDescriptor)) {
|
||||
return ACC_PRIVATE;
|
||||
}
|
||||
|
||||
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
return ACC_PUBLIC;
|
||||
@@ -657,8 +653,23 @@ public class AsmUtil {
|
||||
// currently when resuming a suspend function we pass default values instead of real arguments (i.e. nulls for references)
|
||||
if (descriptor.isSuspend()) return;
|
||||
|
||||
// Private method is not accessible from other classes, no assertions needed
|
||||
if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return;
|
||||
if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) {
|
||||
// Private method is not accessible from other classes, no assertions needed,
|
||||
// unless we have a private operator function, in which we should generate a parameter assertion for an extension receiver.
|
||||
|
||||
// HACK: this provides "fail fast" behavior for operator functions.
|
||||
// Such functions can be invoked in operator conventions desugaring,
|
||||
// which is currently done on ad hoc basis in ExpressionCodegen.
|
||||
|
||||
if (state.isReceiverAssertionsDisabled()) return;
|
||||
if (descriptor.isOperator()) {
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
@@ -674,18 +685,19 @@ public class AsmUtil {
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull FrameMap frameMap,
|
||||
@NotNull CallableDescriptor parameter,
|
||||
@NotNull ParameterDescriptor parameter,
|
||||
@NotNull String name
|
||||
) {
|
||||
KotlinType type = parameter.getReturnType();
|
||||
if (type == null || isNullableType(type)) return;
|
||||
KotlinType type = parameter.getType();
|
||||
if (isNullableType(type)) return;
|
||||
|
||||
int index = frameMap.getIndex(parameter);
|
||||
Type asmType = typeMapper.mapType(type);
|
||||
if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) {
|
||||
v.load(index, asmType);
|
||||
v.visitLdcInsn(name);
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull",
|
||||
String checkMethod = "checkParameterIsNotNull";
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, checkMethod,
|
||||
"(Ljava/lang/Object;Ljava/lang/String;)V", false);
|
||||
}
|
||||
}
|
||||
@@ -708,7 +720,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);
|
||||
@@ -895,6 +907,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,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)
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.StackValue.createDefaulValue;
|
||||
import static org.jetbrains.kotlin.codegen.StackValue.createDefaultValue;
|
||||
|
||||
public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
private final ExpressionCodegen codegen;
|
||||
@@ -64,7 +64,7 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
|
||||
@Override
|
||||
protected void generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
callGenerator.putValueIfNeeded(valueParameterTypes.get(i), createDefaulValue(valueParameterTypes.get(i)), ValueKind.DEFAULT_PARAMETER, i);
|
||||
callGenerator.putValueIfNeeded(valueParameterTypes.get(i), createDefaultValue(valueParameterTypes.get(i)), ValueKind.DEFAULT_PARAMETER, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,11 @@ import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
|
||||
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptorKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -101,6 +104,16 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
|
||||
}
|
||||
|
||||
// Generate synthetic nested classes
|
||||
Collection<DeclarationDescriptor> classifiers = descriptor
|
||||
.getUnsubstitutedMemberScope()
|
||||
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.Companion.getALL_NAME_FILTER());
|
||||
for (DeclarationDescriptor memberDescriptor : classifiers) {
|
||||
if (memberDescriptor instanceof SyntheticClassOrObjectDescriptor) {
|
||||
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) memberDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
if (generateNonClassMembers) {
|
||||
generateBridges();
|
||||
}
|
||||
@@ -182,7 +195,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected List<KtParameter> getPrimaryConstructorParameters() {
|
||||
public List<KtParameter> getPrimaryConstructorParameters() {
|
||||
if (myClass instanceof KtClass) {
|
||||
return myClass.getPrimaryConstructorParameters();
|
||||
}
|
||||
@@ -192,6 +205,6 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
@Nullable
|
||||
@Override
|
||||
protected ClassDescriptor classForInnerClassRecord() {
|
||||
return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
|
||||
return InnerClassConsumer.Companion.classForInnerClassRecord(descriptor, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,19 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.io.FilesKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageParts;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
@@ -143,8 +146,26 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
StringBuilder answer = new StringBuilder();
|
||||
|
||||
for (OutputFile file : asList()) {
|
||||
answer.append("@").append(file.getRelativePath()).append('\n');
|
||||
answer.append(file.asText());
|
||||
File relativePath = new File(file.getRelativePath());
|
||||
answer.append("@").append(relativePath).append('\n');
|
||||
switch (FilesKt.getExtension(relativePath)) {
|
||||
case "class":
|
||||
answer.append(file.asText());
|
||||
break;
|
||||
case "kotlin_module": {
|
||||
ModuleMapping mapping = ModuleMapping.Companion.create(
|
||||
file.asByteArray(), relativePath.getPath(), CompilerDeserializationConfiguration.Default.INSTANCE
|
||||
);
|
||||
for (Map.Entry<String, PackageParts> entry : mapping.getPackageFqName2Parts().entrySet()) {
|
||||
FqName packageFqName = new FqName(entry.getKey());
|
||||
PackageParts packageParts = entry.getValue();
|
||||
answer.append("<package ").append(packageFqName).append(": ").append(packageParts.getParts()).append(">\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown OutputFile: " + file);
|
||||
}
|
||||
}
|
||||
|
||||
return answer.toString();
|
||||
@@ -176,9 +197,9 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
|
||||
private PackagePartRegistry buildNewPackagePartRegistry(@NotNull FqName packageFqName) {
|
||||
String packageFqNameAsString = packageFqName.asString();
|
||||
return (partShortName, facadeShortName) -> {
|
||||
return (partInternalName, facadeInternalName) -> {
|
||||
PackageParts packageParts = partsGroupedByPackage.computeIfAbsent(packageFqNameAsString, PackageParts::new);
|
||||
packageParts.addPart(partShortName, facadeShortName);
|
||||
packageParts.addPart(partInternalName, facadeInternalName);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ 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;
|
||||
@@ -33,6 +34,7 @@ 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;
|
||||
@@ -201,7 +203,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
erasedInterfaceFunction = getErasedInvokeFunction(funDescriptor);
|
||||
}
|
||||
else {
|
||||
erasedInterfaceFunction = samType.getAbstractMethod().getOriginal();
|
||||
erasedInterfaceFunction = samType.getOriginalAbstractMethod();
|
||||
}
|
||||
|
||||
generateBridge(
|
||||
@@ -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
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +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 org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
class CodegenFileClassesProvider : JvmFileClassesProvider {
|
||||
override fun getFileClassInfo(file: KtFile): JvmFileClassInfo =
|
||||
JvmFileClassUtil.getFileClassInfoNoResolve(file)
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import java.util.*
|
||||
|
||||
class DefaultCallArgs(val size: Int) {
|
||||
|
||||
val bits: BitSet = BitSet(size)
|
||||
private val bits: BitSet = BitSet(size)
|
||||
|
||||
fun mark(index: Int) {
|
||||
assert (index < size) {
|
||||
@@ -39,7 +39,7 @@ class DefaultCallArgs(val size: Int) {
|
||||
val masks = ArrayList<Int>(1)
|
||||
|
||||
var mask = 0
|
||||
for (i in 0..size - 1) {
|
||||
for (i in 0 until size) {
|
||||
if (i != 0 && i % Integer.SIZE == 0) {
|
||||
masks.add(mask)
|
||||
mask = 0
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.psi.KtPureElement
|
||||
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
|
||||
@@ -129,7 +128,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
) {
|
||||
val typeMapper = state.typeMapper
|
||||
val isStatic = AsmUtil.isStaticMethod(contextKind, functionDescriptor)
|
||||
val baseMethodFlags = AsmUtil.getCommonCallableFlags(functionDescriptor) and Opcodes.ACC_VARARGS.inv()
|
||||
val baseMethodFlags = AsmUtil.getCommonCallableFlags(functionDescriptor, state) and Opcodes.ACC_VARARGS.inv()
|
||||
val remainingParameters = getRemainingParameters(functionDescriptor.original, substituteCount)
|
||||
val flags =
|
||||
baseMethodFlags or
|
||||
|
||||
@@ -39,18 +39,18 @@ 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.range.forLoop.ForLoopGenerator;
|
||||
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;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
|
||||
import org.jetbrains.kotlin.config.ApiVersion;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
@@ -61,14 +61,12 @@ 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.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
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.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
@@ -106,6 +104,7 @@ 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.isPossiblyUninitializedSingleton;
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.unwrapInitialSignatureDescriptor;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
@@ -134,6 +133,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
private final TailRecursionCodegen tailRecursionCodegen;
|
||||
public final CallGenerator defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this);
|
||||
private final SwitchCodegenProvider switchCodegenProvider;
|
||||
|
||||
private final Stack<BlockStackElement> blockStackElements = new Stack<>();
|
||||
|
||||
@@ -165,6 +165,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
this.parentCodegen = parentCodegen;
|
||||
this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
|
||||
this.switchCodegenProvider = new SwitchCodegenProvider(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -436,11 +437,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return CodegenUtilKt.asmType(expression, typeMapper, bindingContext);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private KotlinType expressionJetType(@Nullable KtExpression expression) {
|
||||
return CodegenUtilKt.kotlinType(expression, bindingContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression, StackValue receiver) {
|
||||
return genQualified(receiver, expression.getExpression());
|
||||
@@ -750,11 +746,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@Override
|
||||
public StackValue visitConstantExpression(@NotNull KtConstantExpression expression, StackValue receiver) {
|
||||
ConstantValue<?> compileTimeValue = getPrimitiveOrStringCompileTimeConstant(expression, bindingContext, state.getShouldInlineConstVals());
|
||||
ConstantValue<?> compileTimeValue = getPrimitiveOrStringCompileTimeConstant(expression);
|
||||
assert compileTimeValue != null;
|
||||
return StackValue.constant(compileTimeValue.getValue(), expressionType(expression));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ConstantValue<?> getCompileTimeConstant(@NotNull KtExpression expression) {
|
||||
return getCompileTimeConstant(expression, bindingContext, state.getShouldInlineConstVals());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ConstantValue<?> getPrimitiveOrStringCompileTimeConstant(@NotNull KtExpression expression) {
|
||||
return getPrimitiveOrStringCompileTimeConstant(expression, bindingContext, state.getShouldInlineConstVals());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ConstantValue<?> getPrimitiveOrStringCompileTimeConstant(
|
||||
@NotNull KtExpression expression,
|
||||
@@ -831,24 +837,29 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public StackValue visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, StackValue receiver) {
|
||||
List<StringTemplateEntry> entries = preprocessStringTemplate(expression);
|
||||
|
||||
if (entries.size() == 1) {
|
||||
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), expressionType(expr));
|
||||
return genToString(gen(expr), type);
|
||||
}
|
||||
else {
|
||||
Type type = expressionType(expression);
|
||||
return StackValue.constant(((StringTemplateEntry.Constant) entry).value, type);
|
||||
}
|
||||
}
|
||||
|
||||
return StackValue.operation(JAVA_STRING_TYPE, v -> {
|
||||
genStringBuilderConstructor(v);
|
||||
invokeAppendForEntries(v, entries);
|
||||
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
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) {
|
||||
@@ -905,8 +916,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
KtExpression entryExpression = entry.getExpression();
|
||||
if (entryExpression == null) throw new AssertionError("No expression in " + entry);
|
||||
|
||||
ConstantValue<?> compileTimeConstant =
|
||||
getPrimitiveOrStringCompileTimeConstant(entryExpression, bindingContext, state.getShouldInlineConstVals());
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(entryExpression);
|
||||
|
||||
if (compileTimeConstant != null && isConstantValueInlinableInStringTemplate(compileTimeConstant)) {
|
||||
constantValue.append(String.valueOf(compileTimeConstant.getValue()));
|
||||
@@ -1062,7 +1072,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
List<ResolvedValueArgument> valueArguments = new ArrayList<>(params);
|
||||
List<ValueParameterDescriptor> valueParameters = new ArrayList<>(params);
|
||||
List<Type> mappedTypes = new ArrayList<>(params);
|
||||
for (ValueParameterDescriptor parameter : superValueParameters) {
|
||||
for (ValueParameterDescriptor parameter : superCall.getValueArguments().keySet()) {
|
||||
ResolvedValueArgument argument = superCall.getValueArguments().get(parameter);
|
||||
if (!(argument instanceof DefaultValueArgument)) {
|
||||
valueArguments.add(argument);
|
||||
@@ -1276,8 +1286,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
KotlinType varType = isDelegatedLocalVariable(variableDescriptor)
|
||||
? JvmCodegenUtil.getPropertyDelegateType((VariableDescriptorWithAccessors) variableDescriptor, bindingContext)
|
||||
: variableDescriptor.getType();
|
||||
//noinspection ConstantConditions
|
||||
return asmType(varType);
|
||||
|
||||
if (variableDescriptor instanceof ValueParameterDescriptor &&
|
||||
MethodSignatureMappingKt.forceSingleValueParameterBoxing(
|
||||
(CallableDescriptor) variableDescriptor.getContainingDeclaration()
|
||||
)
|
||||
) {
|
||||
//noinspection ConstantConditions
|
||||
return asmType(TypeUtils.makeNullable(varType));
|
||||
}
|
||||
else {
|
||||
//noinspection ConstantConditions
|
||||
return asmType(varType);
|
||||
}
|
||||
}
|
||||
|
||||
private void putDescriptorIntoFrameMap(@NotNull KtElement statement) {
|
||||
@@ -1608,11 +1629,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);
|
||||
@@ -1684,7 +1706,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
|
||||
if (!codegenExtensions.isEmpty() && resolvedCall != null) {
|
||||
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
|
||||
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(this, typeMapper, v);
|
||||
KotlinType returnType = propertyDescriptor.getReturnType();
|
||||
for (ExpressionCodegenExtension extension : codegenExtensions) {
|
||||
if (returnType != null) {
|
||||
@@ -1701,7 +1723,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
receiver = StackValue.receiverWithoutReceiverArgument(receiver);
|
||||
}
|
||||
|
||||
return intermediateValueForProperty(propertyDescriptor, directToField, directToField, superCallTarget, false, receiver, resolvedCall);
|
||||
return intermediateValueForProperty(propertyDescriptor, directToField, directToField, superCallTarget, false, receiver,
|
||||
resolvedCall, false);
|
||||
}
|
||||
|
||||
if (descriptor instanceof TypeAliasDescriptor) {
|
||||
@@ -1715,6 +1738,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
|
||||
if (isPossiblyUninitializedSingleton(classDescriptor) && isInsideSingleton(classDescriptor)) {
|
||||
return generateThisOrOuterFromContext(classDescriptor, false, false);
|
||||
}
|
||||
if (isObject(classDescriptor)) {
|
||||
return StackValue.singleton(classDescriptor, typeMapper);
|
||||
}
|
||||
@@ -1776,31 +1802,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
|
||||
@@ -1811,7 +1821,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";
|
||||
@@ -1830,10 +1840,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||
Type varType = getVariableTypeNoSharing(variableDescriptor);
|
||||
if (sharedVarType != null) {
|
||||
return StackValue.shared(index, varType);
|
||||
return StackValue.shared(index, varType, variableDescriptor);
|
||||
}
|
||||
else {
|
||||
return adjustVariableValue(StackValue.local(index, varType), variableDescriptor);
|
||||
return adjustVariableValue(StackValue.local(index, varType, variableDescriptor), variableDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1864,7 +1874,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull StackValue receiver
|
||||
) {
|
||||
return intermediateValueForProperty(propertyDescriptor, forceField, false, superCallTarget, false, receiver, null);
|
||||
return intermediateValueForProperty(propertyDescriptor, forceField, false, superCallTarget, false, receiver, null, false);
|
||||
}
|
||||
|
||||
private CodegenContext getBackingFieldContext(
|
||||
@@ -1872,12 +1882,24 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull DeclarationDescriptor containingDeclaration
|
||||
) {
|
||||
switch (accessorKind) {
|
||||
case NORMAL: return context.getParentContext();
|
||||
case NORMAL:
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
CodegenContext parentWithDescriptor = context.findParentContextWithDescriptor(containingDeclaration);
|
||||
if (parentWithDescriptor != null) {
|
||||
return parentWithDescriptor;
|
||||
}
|
||||
}
|
||||
return context.getParentContext();
|
||||
// For companion object property, backing field lives in object containing class
|
||||
// Otherwise, it lives in its containing declaration
|
||||
case IN_CLASS_COMPANION: return context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
||||
case FIELD_FROM_LOCAL: return context.findParentContextWithDescriptor(containingDeclaration);
|
||||
default: throw new IllegalStateException();
|
||||
case IN_CLASS_COMPANION:
|
||||
return context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
||||
case FIELD_FROM_LOCAL:
|
||||
return context.findParentContextWithDescriptor(containingDeclaration);
|
||||
case LATEINIT_INTRINSIC:
|
||||
return context.findParentContextWithDescriptor(containingDeclaration);
|
||||
default:
|
||||
throw new IllegalStateException("Unknown field accessor kind: " + accessorKind);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1888,22 +1910,35 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
boolean skipAccessorsForPrivateFieldInOuterClass,
|
||||
@NotNull StackValue receiver,
|
||||
@Nullable ResolvedCall resolvedCall
|
||||
@Nullable ResolvedCall resolvedCall,
|
||||
boolean skipLateinitAssertion
|
||||
) {
|
||||
if (propertyDescriptor instanceof SyntheticJavaPropertyDescriptor) {
|
||||
return intermediateValueForSyntheticExtensionProperty((SyntheticJavaPropertyDescriptor) propertyDescriptor, receiver);
|
||||
}
|
||||
|
||||
if (propertyDescriptor instanceof PropertyImportedFromObject) {
|
||||
propertyDescriptor = ((PropertyImportedFromObject) propertyDescriptor).getCallableFromObject();
|
||||
}
|
||||
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
|
||||
FieldAccessorKind fieldAccessorKind = FieldAccessorKind.NORMAL;
|
||||
boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
if (isBackingFieldInClassCompanion && (forceField || propertyDescriptor.isConst() && Visibilities.isPrivate(propertyDescriptor.getVisibility()))) {
|
||||
FieldAccessorKind fieldAccessorKind;
|
||||
if (skipLateinitAssertion) {
|
||||
fieldAccessorKind = FieldAccessorKind.LATEINIT_INTRINSIC;
|
||||
}
|
||||
else if (isBackingFieldInClassCompanion &&
|
||||
(forceField || propertyDescriptor.isConst() && Visibilities.isPrivate(propertyDescriptor.getVisibility()))) {
|
||||
fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION;
|
||||
}
|
||||
else if (syntheticBackingField && context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration) {
|
||||
else if ((syntheticBackingField &&
|
||||
context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration)) {
|
||||
fieldAccessorKind = FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||
}
|
||||
else {
|
||||
fieldAccessorKind = FieldAccessorKind.NORMAL;
|
||||
}
|
||||
boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) ||
|
||||
AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor);
|
||||
boolean isSuper = superCallTarget != null;
|
||||
@@ -1916,15 +1951,26 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
CallableMethod callableSetter = null;
|
||||
|
||||
CodegenContext backingFieldContext = getBackingFieldContext(fieldAccessorKind, containingDeclaration);
|
||||
DeclarationDescriptor ownerDescriptor = containingDeclaration;
|
||||
boolean isPrivateProperty =
|
||||
fieldAccessorKind != FieldAccessorKind.NORMAL &&
|
||||
(AsmUtil.getVisibilityForBackingField(propertyDescriptor, isDelegatedProperty) & ACC_PRIVATE) != 0;
|
||||
DeclarationDescriptor ownerDescriptor;
|
||||
boolean skipPropertyAccessors;
|
||||
|
||||
PropertyDescriptor originalPropertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
|
||||
|
||||
if (fieldAccessorKind != FieldAccessorKind.NORMAL) {
|
||||
int flags = AsmUtil.getVisibilityForBackingField(propertyDescriptor, isDelegatedProperty);
|
||||
if (fieldAccessorKind == FieldAccessorKind.LATEINIT_INTRINSIC) {
|
||||
skipPropertyAccessors = !isPrivateProperty || context.getClassOrPackageParentContext() == backingFieldContext;
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
propertyDescriptor = (AccessorForPropertyBackingField)
|
||||
backingFieldContext.getAccessor(propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget);
|
||||
}
|
||||
ownerDescriptor = propertyDescriptor;
|
||||
}
|
||||
else if (fieldAccessorKind == FieldAccessorKind.IN_CLASS_COMPANION || fieldAccessorKind == FieldAccessorKind.FIELD_FROM_LOCAL) {
|
||||
boolean isInlinedConst = propertyDescriptor.isConst() && state.getShouldInlineConstVals();
|
||||
skipPropertyAccessors = isInlinedConst || (flags & ACC_PRIVATE) == 0 || skipAccessorsForPrivateFieldInOuterClass;
|
||||
skipPropertyAccessors = isInlinedConst || !isPrivateProperty || skipAccessorsForPrivateFieldInOuterClass;
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
//noinspection ConstantConditions
|
||||
@@ -1935,12 +1981,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
"Unexpected accessor descriptor: " + propertyDescriptor;
|
||||
ownerDescriptor = propertyDescriptor;
|
||||
}
|
||||
else {
|
||||
ownerDescriptor = containingDeclaration;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!isBackingFieldInClassCompanion) {
|
||||
ownerDescriptor = propertyDescriptor;
|
||||
}
|
||||
skipPropertyAccessors = forceField;
|
||||
ownerDescriptor = isBackingFieldInClassCompanion ? containingDeclaration : propertyDescriptor;
|
||||
}
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
@@ -1984,10 +2031,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
fieldName = KotlinTypeMapper.mapDefaultFieldName(propertyDescriptor, isDelegatedProperty);
|
||||
}
|
||||
|
||||
return StackValue.property(propertyDescriptor, backingFieldOwner,
|
||||
typeMapper.mapType(
|
||||
isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
|
||||
isStaticBackingField, fieldName, callableGetter, callableSetter, receiver, this, resolvedCall);
|
||||
return StackValue.property(
|
||||
propertyDescriptor, backingFieldOwner,
|
||||
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
|
||||
isStaticBackingField, fieldName, callableGetter, callableSetter, receiver, this, resolvedCall, skipLateinitAssertion
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -2001,7 +2049,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor setMethod = propertyDescriptor.getSetMethod();
|
||||
CallableMethod callableSetter =
|
||||
setMethod != null ? typeMapper.mapToCallableMethod(context.accessibleDescriptor(setMethod, null), false) : null;
|
||||
return StackValue.property(propertyDescriptor, null, type, false, null, callableGetter, callableSetter, receiver, this, null);
|
||||
return StackValue.property(propertyDescriptor, null, type, false, null, callableGetter, callableSetter, receiver, this,
|
||||
null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2120,7 +2169,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
|
||||
if (!codegenExtensions.isEmpty()) {
|
||||
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
|
||||
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(this, typeMapper, v);
|
||||
for (ExpressionCodegenExtension extension : codegenExtensions) {
|
||||
StackValue stackValue = extension.applyFunction(receiver, resolvedCall, context);
|
||||
if (stackValue != null) return stackValue;
|
||||
@@ -2205,7 +2254,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
) {
|
||||
boolean isSuspendCall = CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall);
|
||||
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
|
||||
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, isSuspendCall, isConstructor);
|
||||
if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) {
|
||||
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, isSuspendCall, isConstructor);
|
||||
}
|
||||
|
||||
callGenerator.processAndPutHiddenParameters(false);
|
||||
|
||||
@@ -2292,12 +2343,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;
|
||||
@@ -2335,15 +2386,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
) {
|
||||
if (callElement == null) return defaultCallGenerator;
|
||||
|
||||
boolean isIntrinsic = descriptor instanceof CallableMemberDescriptor &&
|
||||
state.getIntrinsics().getIntrinsic((CallableMemberDescriptor) descriptor) != null;
|
||||
|
||||
boolean isInline = (InlineUtil.isInline(descriptor) && !isIntrinsic) || InlineUtil.isArrayConstructorWithLambda(descriptor);
|
||||
|
||||
// We should inline callable containing reified type parameters even if inline is disabled
|
||||
// because they may contain something to reify and straight call will probably fail at runtime
|
||||
boolean isInline = (!state.isInlineDisabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) &&
|
||||
(InlineUtil.isInline(descriptor) || InlineUtil.isArrayConstructorWithLambda(descriptor));
|
||||
|
||||
if (!isInline) return defaultCallGenerator;
|
||||
boolean shouldInline = isInline && (!state.isInlineDisabled() || InlineUtil.containsReifiedTypeParameters(descriptor));
|
||||
if (!shouldInline) return defaultCallGenerator;
|
||||
|
||||
FunctionDescriptor original =
|
||||
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()));
|
||||
CoroutineCodegenUtilKt.getOriginalSuspendFunctionView(
|
||||
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())),
|
||||
bindingContext
|
||||
);
|
||||
if (isDefaultCompilation) {
|
||||
return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement));
|
||||
}
|
||||
@@ -2430,6 +2487,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) {
|
||||
return StackValue.LOCAL_0;
|
||||
}
|
||||
else if (isPossiblyUninitializedSingleton(receiverDescriptor) && isInsideSingleton(receiverDescriptor)) {
|
||||
return generateThisOrOuterFromContext(receiverDescriptor, false, false);
|
||||
}
|
||||
else {
|
||||
return StackValue.singleton(receiverDescriptor, typeMapper);
|
||||
}
|
||||
@@ -2447,7 +2507,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return generateExtensionReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor());
|
||||
}
|
||||
else if (receiverValue instanceof ExpressionReceiver) {
|
||||
return gen(((ExpressionReceiver) receiverValue).getExpression());
|
||||
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiverValue;
|
||||
StackValue stackValue = gen(expressionReceiver.getExpression());
|
||||
if (!state.isReceiverAssertionsDisabled()) {
|
||||
RuntimeAssertionInfo runtimeAssertionInfo =
|
||||
bindingContext.get(JvmBindingContextSlices.RECEIVER_RUNTIME_ASSERTION_INFO, expressionReceiver);
|
||||
stackValue = genNotNullAssertions(state, stackValue, runtimeAssertionInfo);
|
||||
}
|
||||
return stackValue;
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unsupported receiver value: " + receiverValue);
|
||||
@@ -2507,22 +2574,47 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return generateThisOrOuter(calleeContainingClass, isSuper, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) {
|
||||
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
|
||||
if (isSingleton) {
|
||||
if (calleeContainingClass.equals(context.getThisDescriptor()) &&
|
||||
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getFunctionDescriptor())) {
|
||||
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
|
||||
}
|
||||
else if (isEnumEntry(calleeContainingClass)) {
|
||||
return StackValue.enumEntry(calleeContainingClass, typeMapper);
|
||||
}
|
||||
else {
|
||||
return StackValue.singleton(calleeContainingClass, typeMapper);
|
||||
private boolean isInsideSingleton(@NotNull ClassDescriptor singletonClassDescriptor) {
|
||||
assert singletonClassDescriptor.getKind().isSingleton() :
|
||||
"Singleton expected: " + singletonClassDescriptor;
|
||||
|
||||
DeclarationDescriptor descriptor = context.getContextDescriptor();
|
||||
while (descriptor != null) {
|
||||
if (descriptor == singletonClassDescriptor) return true;
|
||||
|
||||
if (descriptor instanceof ClassDescriptor &&
|
||||
!(((ClassDescriptor) descriptor).isInner() || DescriptorUtils.isAnonymousObject(descriptor))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
descriptor = descriptor.getContainingDeclaration();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) {
|
||||
if (!calleeContainingClass.getKind().isSingleton()) {
|
||||
return generateThisOrOuterFromContext(calleeContainingClass, isSuper, forceOuter);
|
||||
}
|
||||
|
||||
if (calleeContainingClass.equals(context.getThisDescriptor()) &&
|
||||
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getFunctionDescriptor())) {
|
||||
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
|
||||
}
|
||||
else if (CodegenUtilKt.isPossiblyUninitializedSingleton(calleeContainingClass) && isInsideSingleton(calleeContainingClass)) {
|
||||
return generateThisOrOuterFromContext(calleeContainingClass, isSuper, forceOuter);
|
||||
}
|
||||
else if (isEnumEntry(calleeContainingClass)) {
|
||||
return StackValue.enumEntry(calleeContainingClass, typeMapper);
|
||||
}
|
||||
else {
|
||||
return StackValue.singleton(calleeContainingClass, typeMapper);
|
||||
}
|
||||
}
|
||||
|
||||
private StackValue generateThisOrOuterFromContext(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) {
|
||||
CodegenContext cur = context;
|
||||
Type type = asmType(calleeContainingClass.getDefaultType());
|
||||
StackValue result = StackValue.local(0, type);
|
||||
@@ -2683,35 +2775,45 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public StackValue visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, StackValue data) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression.getCallableReference(), bindingContext);
|
||||
|
||||
KotlinType receiverExpressionType = expressionJetType(expression.getReceiverExpression());
|
||||
Type receiverAsmType = receiverExpressionType != null ? asmType(receiverExpressionType) : null;
|
||||
StackValue receiverValue =
|
||||
receiverExpressionType != null ? StackValue.coercion(gen(expression.getReceiverExpression()), receiverAsmType) : null;
|
||||
StackValue receiver = generateCallableReferenceReceiver(resolvedCall);
|
||||
|
||||
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
||||
if (functionDescriptor != null) {
|
||||
FunctionReferenceGenerationStrategy strategy =
|
||||
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null, false);
|
||||
FunctionReferenceGenerationStrategy strategy = new FunctionReferenceGenerationStrategy(
|
||||
state, functionDescriptor, resolvedCall, receiver != null ? receiver.type : null, null, false
|
||||
);
|
||||
|
||||
return genClosure(
|
||||
expression, functionDescriptor, strategy, null,
|
||||
(FunctionDescriptor) resolvedCall.getResultingDescriptor(), receiverValue
|
||||
(FunctionDescriptor) resolvedCall.getResultingDescriptor(), receiver
|
||||
);
|
||||
}
|
||||
|
||||
VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(expression);
|
||||
return generatePropertyReference(
|
||||
expression, variableDescriptor, (VariableDescriptor) resolvedCall.getResultingDescriptor(),
|
||||
receiverAsmType, receiverValue
|
||||
expression, getVariableDescriptorNotNull(expression),
|
||||
(VariableDescriptor) resolvedCall.getResultingDescriptor(), receiver
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StackValue generateCallableReferenceReceiver(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||
if (descriptor.getExtensionReceiverParameter() == null && descriptor.getDispatchReceiverParameter() == null) return null;
|
||||
|
||||
ReceiverValue dispatchReceiver = resolvedCall.getDispatchReceiver();
|
||||
ReceiverValue extensionReceiver = resolvedCall.getExtensionReceiver();
|
||||
assert dispatchReceiver == null || extensionReceiver == null : "Cannot generate reference with both receivers: " + descriptor;
|
||||
ReceiverValue receiver = dispatchReceiver != null ? dispatchReceiver : extensionReceiver;
|
||||
if (receiver == null || receiver instanceof TransientReceiver) return null;
|
||||
|
||||
return StackValue.coercion(generateReceiverValue(receiver, false), asmType(receiver.getType()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue generatePropertyReference(
|
||||
@NotNull KtElement element,
|
||||
@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull VariableDescriptor target,
|
||||
@Nullable Type receiverAsmType,
|
||||
@Nullable StackValue receiverValue
|
||||
) {
|
||||
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||
@@ -2722,17 +2824,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
element.getContainingFile()
|
||||
);
|
||||
|
||||
Type receiverAsmType = receiverValue != null ? receiverValue.type : null;
|
||||
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
||||
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
||||
element, classBuilder, variableDescriptor, target, receiverAsmType
|
||||
);
|
||||
codegen.generate();
|
||||
|
||||
return codegen.putInstanceOnStack(receiverValue == null ? null : () -> {
|
||||
assert receiverAsmType != null : "Receiver type should not be null when receiver value is not null: " + receiverValue;
|
||||
receiverValue.put(receiverAsmType, v);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
return codegen.putInstanceOnStack(receiverValue);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -2833,7 +2932,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
else if (opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ ||
|
||||
opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) {
|
||||
return generateEquals(expression.getLeft(), expression.getRight(), opToken);
|
||||
return generateEquals(expression.getLeft(), expression.getRight(), opToken, null);
|
||||
}
|
||||
else if (opToken == KtTokens.LT || opToken == KtTokens.LTEQ ||
|
||||
opToken == KtTokens.GT || opToken == KtTokens.GTEQ) {
|
||||
@@ -2847,7 +2946,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
expression.getRight(), reference);
|
||||
}
|
||||
else {
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expression, bindingContext, state.getShouldInlineConstVals());
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expression);
|
||||
if (compileTimeConstant != null) {
|
||||
return StackValue.constant(compileTimeConstant.getValue(), expressionType(expression));
|
||||
}
|
||||
@@ -2878,33 +2977,81 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.or(gen(expression.getLeft()), gen(expression.getRight()));
|
||||
}
|
||||
|
||||
private StackValue generateEquals(@Nullable KtExpression left, @Nullable KtExpression right, @NotNull IElementType opToken) {
|
||||
private StackValue genLazyUnlessProvided(@Nullable StackValue pregenerated, @NotNull KtExpression expr, @NotNull Type type) {
|
||||
return pregenerated != null ? StackValue.coercion(pregenerated, type) : genLazy(expr, type);
|
||||
}
|
||||
|
||||
private StackValue genUnlessProvided(@Nullable StackValue pregenerated, @NotNull KtExpression expr, @NotNull Type type) {
|
||||
if (pregenerated != null) {
|
||||
pregenerated.put(type, v);
|
||||
}
|
||||
else {
|
||||
gen(expr, type);
|
||||
}
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
|
||||
private StackValue generateEquals(
|
||||
@Nullable KtExpression left,
|
||||
@Nullable KtExpression right,
|
||||
@NotNull IElementType opToken,
|
||||
@Nullable StackValue pregeneratedLeft
|
||||
) {
|
||||
Type leftType = expressionType(left);
|
||||
Type rightType = expressionType(right);
|
||||
|
||||
if (KtPsiUtil.isNullConstant(left)) {
|
||||
return genCmpWithNull(right, opToken);
|
||||
return genCmpWithNull(right, opToken, null);
|
||||
}
|
||||
|
||||
if (KtPsiUtil.isNullConstant(right)) {
|
||||
return genCmpWithNull(left, opToken);
|
||||
return genCmpWithNull(left, opToken, pregeneratedLeft);
|
||||
}
|
||||
|
||||
if (isIntZero(left, leftType) && isIntPrimitive(rightType)) {
|
||||
return genCmpWithZero(right, opToken);
|
||||
return genCmpWithZero(right, opToken, null);
|
||||
}
|
||||
|
||||
if (isIntZero(right, rightType) && isIntPrimitive(leftType)) {
|
||||
return genCmpWithZero(left, opToken);
|
||||
return genCmpWithZero(left, opToken, pregeneratedLeft);
|
||||
}
|
||||
|
||||
if (left instanceof KtSafeQualifiedExpression && isPrimitive(rightType)) {
|
||||
if (pregeneratedLeft == null && left instanceof KtSafeQualifiedExpression &&
|
||||
isSelectorPureNonNullType((KtSafeQualifiedExpression) left) && isPrimitive(rightType)) {
|
||||
return genCmpSafeCallToPrimitive((KtSafeQualifiedExpression) left, right, rightType, opToken);
|
||||
}
|
||||
if (isPrimitive(leftType) && right instanceof KtSafeQualifiedExpression) {
|
||||
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken);
|
||||
|
||||
if (isPrimitive(leftType) && right instanceof KtSafeQualifiedExpression &&
|
||||
isSelectorPureNonNullType(((KtSafeQualifiedExpression) right))) {
|
||||
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken, pregeneratedLeft);
|
||||
}
|
||||
|
||||
if (BoxedToPrimitiveEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return BoxedToPrimitiveEquality.create(
|
||||
opToken,
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
|
||||
genLazy(right, rightType), rightType,
|
||||
myFrameMap
|
||||
);
|
||||
}
|
||||
|
||||
if (PrimitiveToBoxedEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return PrimitiveToBoxedEquality.create(
|
||||
opToken,
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
|
||||
genLazy(right, rightType), rightType
|
||||
);
|
||||
}
|
||||
|
||||
if (PrimitiveToObjectEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return PrimitiveToObjectEquality.create(
|
||||
opToken,
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
|
||||
genLazy(right, rightType), rightType
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (isPrimitive(leftType) != isPrimitive(rightType)) {
|
||||
leftType = boxType(leftType);
|
||||
rightType = boxType(rightType);
|
||||
@@ -2913,23 +3060,38 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) {
|
||||
// TODO: always casting to the type of the left operand in case of primitives looks wrong
|
||||
Type operandType = isPrimitive(leftType) ? leftType : OBJECT_TYPE;
|
||||
return StackValue.cmp(opToken, operandType, genLazy(left, leftType), genLazy(right, rightType));
|
||||
return StackValue.cmp(
|
||||
opToken,
|
||||
operandType,
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
|
||||
genLazy(right, rightType)
|
||||
);
|
||||
}
|
||||
|
||||
return genEqualsForExpressionsPreferIEEE754Arithmetic(left, right, opToken, leftType, rightType, null);
|
||||
return genEqualsForExpressionsPreferIEEE754Arithmetic(left, right, opToken, leftType, rightType, pregeneratedLeft);
|
||||
}
|
||||
|
||||
private boolean isSelectorPureNonNullType(@NotNull KtSafeQualifiedExpression safeExpression) {
|
||||
KtExpression expression = safeExpression.getSelectorExpression();
|
||||
if (expression == null) return false;
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
|
||||
if (resolvedCall == null) return false;
|
||||
KotlinType returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
||||
return returnType != null && !TypeUtils.isNullableType(returnType);
|
||||
}
|
||||
|
||||
private StackValue genCmpPrimitiveToSafeCall(
|
||||
@NotNull KtExpression left,
|
||||
@NotNull Type leftType,
|
||||
@NotNull KtSafeQualifiedExpression right,
|
||||
@NotNull IElementType opToken
|
||||
@NotNull IElementType opToken,
|
||||
@Nullable StackValue pregeneratedLeft
|
||||
) {
|
||||
Label rightIsNull = new Label();
|
||||
return new PrimitiveToSafeCallEquality(
|
||||
opToken,
|
||||
leftType,
|
||||
genLazy(left, leftType),
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
|
||||
generateSafeQualifiedExpression(right, rightIsNull),
|
||||
expressionType(right.getReceiverExpression()),
|
||||
rightIsNull
|
||||
@@ -2990,7 +3152,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
return genEqualsForExpressionsOnStack(
|
||||
opToken,
|
||||
pregeneratedLeft != null ? StackValue.coercion(pregeneratedLeft, leftType) : genLazy(left, leftType),
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
|
||||
genLazy(right, rightType)
|
||||
);
|
||||
}
|
||||
@@ -3006,12 +3168,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
) {
|
||||
Type leftType = left754Type.isNullable ? AsmUtil.boxType(left754Type.type) : left754Type.type;
|
||||
|
||||
if (pregeneratedLeft != null) {
|
||||
StackValue.coercion(pregeneratedLeft, leftType).put(leftType, v);
|
||||
}
|
||||
else {
|
||||
gen(left, leftType);
|
||||
}
|
||||
genUnlessProvided(pregeneratedLeft, left, leftType);
|
||||
Type rightType = right754Type.isNullable ? AsmUtil.boxType(right754Type.type) : right754Type.type;
|
||||
gen(right, rightType);
|
||||
|
||||
@@ -3116,16 +3273,22 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private boolean isIntZero(KtExpression expr, Type exprType) {
|
||||
ConstantValue<?> exprValue = getPrimitiveOrStringCompileTimeConstant(expr, bindingContext, state.getShouldInlineConstVals());
|
||||
ConstantValue<?> exprValue = getPrimitiveOrStringCompileTimeConstant(expr);
|
||||
return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue());
|
||||
}
|
||||
|
||||
private StackValue genCmpWithZero(KtExpression exp, IElementType opToken) {
|
||||
return StackValue.compareIntWithZero(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNE : IFEQ);
|
||||
private StackValue genCmpWithZero(KtExpression exp, IElementType opToken, @Nullable StackValue pregeneratedExpr) {
|
||||
return StackValue.compareIntWithZero(
|
||||
pregeneratedExpr != null ? pregeneratedExpr : gen(exp),
|
||||
(KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNE : IFEQ
|
||||
);
|
||||
}
|
||||
|
||||
private StackValue genCmpWithNull(KtExpression exp, IElementType opToken) {
|
||||
return StackValue.compareWithNull(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNONNULL : IFNULL);
|
||||
private StackValue genCmpWithNull(KtExpression exp, IElementType opToken, @Nullable StackValue pregeneratedExpr) {
|
||||
return StackValue.compareWithNull(
|
||||
pregeneratedExpr != null ? pregeneratedExpr : gen(exp),
|
||||
(KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNONNULL : IFNULL
|
||||
);
|
||||
}
|
||||
|
||||
private StackValue generateElvis(@NotNull KtBinaryExpression expression) {
|
||||
@@ -3245,7 +3408,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public void invokeAppend(InstructionAdapter v, KtExpression expr) {
|
||||
expr = KtPsiUtil.safeDeparenthesize(expr);
|
||||
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expr, bindingContext, state.getShouldInlineConstVals());
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expr);
|
||||
|
||||
if (compileTimeConstant == null) {
|
||||
if (expr instanceof KtBinaryExpression) {
|
||||
@@ -3295,7 +3458,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@Override
|
||||
public StackValue visitPrefixExpression(@NotNull KtPrefixExpression expression, @NotNull StackValue receiver) {
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expression, bindingContext, state.getShouldInlineConstVals());
|
||||
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expression);
|
||||
if (compileTimeConstant != null) {
|
||||
return StackValue.constant(compileTimeConstant.getValue(), expressionType(expression));
|
||||
}
|
||||
@@ -3413,6 +3576,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
else if (delegateExpression != null) {
|
||||
initializeLocalVariable(property, gen(delegateExpression));
|
||||
}
|
||||
else if (property.hasModifier(KtTokens.LATEINIT_KEYWORD)) {
|
||||
initializeLocalVariable(property, null);
|
||||
}
|
||||
|
||||
return StackValue.none();
|
||||
}
|
||||
@@ -3444,10 +3610,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
initializeDestructuringDeclarationVariables(multiDeclaration, initializerAsReceiver, local, asProperty);
|
||||
|
||||
if (initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) {
|
||||
v.aconst(null);
|
||||
v.store(tempVarIndex, initializerAsmType);
|
||||
}
|
||||
myFrameMap.leaveTemp(initializerAsmType);
|
||||
|
||||
return StackValue.none();
|
||||
@@ -3479,13 +3641,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
if (asProperty && variableDescriptor instanceof PropertyDescriptor) {
|
||||
StackValue.Property propertyValue = intermediateValueForProperty(
|
||||
(PropertyDescriptor) variableDescriptor,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
true,
|
||||
StackValue.LOCAL_0,
|
||||
null);
|
||||
(PropertyDescriptor) variableDescriptor, true, false, null, true, StackValue.LOCAL_0, null, false
|
||||
);
|
||||
|
||||
propertyValue.store(invokeFunction(call, resolvedCall, receiverStackValue), v);
|
||||
}
|
||||
@@ -3496,7 +3653,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;
|
||||
@@ -3513,7 +3670,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
private void initializeLocalVariable(
|
||||
@NotNull KtVariableDeclaration variableDeclaration,
|
||||
@NotNull StackValue initializer
|
||||
@Nullable StackValue initializer
|
||||
) {
|
||||
LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) getVariableDescriptorNotNull(variableDeclaration);
|
||||
|
||||
@@ -3533,6 +3690,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType);
|
||||
|
||||
storeTo.putReceiver(v, false);
|
||||
if (variableDescriptor.isLateInit()) {
|
||||
assert initializer == null : "Initializer should be null for lateinit var " + variableDescriptor + ": " + initializer;
|
||||
v.aconst(null);
|
||||
storeTo.storeSelector(storeTo.type, v);
|
||||
return;
|
||||
}
|
||||
|
||||
assert initializer != null : "Initializer should be not null for " + variableDescriptor;
|
||||
initializer.put(initializer.type, v);
|
||||
|
||||
markLineNumber(variableDeclaration, false);
|
||||
@@ -3542,14 +3707,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
|
||||
@@ -3596,10 +3760,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)
|
||||
: PropertyCodegen.getDelegatedPropertyMetadata(variableDescriptor, bindingContext);
|
||||
value.put(K_PROPERTY_TYPE, v);
|
||||
metadataVar.storeSelector(K_PROPERTY_TYPE, v);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -3988,22 +4158,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
|
||||
private StackValue generateExpressionMatch(StackValue expressionToMatch, KtExpression subjectExpression, KtExpression patternExpression) {
|
||||
if (expressionToMatch != null) {
|
||||
Type subjectType = expressionToMatch.type;
|
||||
markStartLineNumber(patternExpression);
|
||||
KotlinType condJetType = bindingContext.getType(patternExpression);
|
||||
Type condType;
|
||||
if (isNumberPrimitiveOrBoolean(subjectType)) {
|
||||
assert condJetType != null;
|
||||
condType = asmType(condJetType);
|
||||
if (!isNumberPrimitiveOrBoolean(condType)) {
|
||||
subjectType = boxType(subjectType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
condType = OBJECT_TYPE;
|
||||
}
|
||||
|
||||
return genEqualsForExpressionsPreferIEEE754Arithmetic(subjectExpression, patternExpression, KtTokens.EQEQ, subjectType, condType, expressionToMatch);
|
||||
return generateEquals(subjectExpression, patternExpression, KtTokens.EQEQ, expressionToMatch);
|
||||
}
|
||||
else {
|
||||
return gen(patternExpression);
|
||||
@@ -4076,12 +4231,12 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression);
|
||||
|
||||
return StackValue.operation(resultType, v -> {
|
||||
SwitchCodegen switchCodegen = SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, CodegenUtil.isExhaustive(bindingContext, expression, isStatement), this
|
||||
SwitchCodegen switchCodegen = switchCodegenProvider.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, CodegenUtil.isExhaustive(bindingContext, expression, isStatement)
|
||||
);
|
||||
if (switchCodegen != null) {
|
||||
switchCodegen.generate();
|
||||
return Unit.INSTANCE;
|
||||
return null;
|
||||
}
|
||||
|
||||
int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
|
||||
|
||||
@@ -34,7 +34,7 @@ public class FieldInfo {
|
||||
}
|
||||
|
||||
if (isNonCompanionObject(classDescriptor) || CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(classDescriptor)) {
|
||||
return createSingletonViaInstance(classDescriptor, typeMapper);
|
||||
return createSingletonViaInstance(classDescriptor, typeMapper, JvmAbi.INSTANCE_FIELD);
|
||||
}
|
||||
|
||||
ClassDescriptor ownerDescriptor = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class);
|
||||
@@ -46,10 +46,11 @@ public class FieldInfo {
|
||||
@NotNull
|
||||
public static FieldInfo createSingletonViaInstance(
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull KotlinTypeMapper typeMapper
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull String name
|
||||
) {
|
||||
Type type = typeMapper.mapType(classDescriptor);
|
||||
return new FieldInfo(type, type, JvmAbi.INSTANCE_FIELD, true);
|
||||
return new FieldInfo(type, type, name, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -204,53 +204,6 @@ public class FunctionCodegen {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isOpenSuspendInClass =
|
||||
functionDescriptor.isSuspend() &&
|
||||
functionDescriptor.getModality() != Modality.ABSTRACT && isOverridable(functionDescriptor) &&
|
||||
!isInterface(functionDescriptor.getContainingDeclaration()) &&
|
||||
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
||||
|
||||
if (isOpenSuspendInClass) {
|
||||
MethodVisitor mv =
|
||||
v.newMethod(origin,
|
||||
flags,
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
jvmSignature.getGenericsSignature(),
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
);
|
||||
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
int index = 1;
|
||||
for (Type type : asmMethod.getArgumentTypes()) {
|
||||
mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
|
||||
index += type.getSize();
|
||||
}
|
||||
|
||||
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,
|
||||
v.getThisName(), asmMethod.getName(), asmMethod.getDescriptor(),
|
||||
false
|
||||
);
|
||||
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitEnd();
|
||||
|
||||
flags |= Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC;
|
||||
flags &= ~getVisibilityAccessFlag(functionDescriptor);
|
||||
flags |= AsmUtil.NO_FLAG_PACKAGE_PRIVATE;
|
||||
}
|
||||
|
||||
MethodVisitor mv =
|
||||
strategy.wrapMethodVisitor(
|
||||
v.newMethod(origin,
|
||||
@@ -286,6 +239,79 @@ public class FunctionCodegen {
|
||||
parentBodyCodegen.addAdditionalTask(new JvmStaticInCompanionObjectGenerator(functionDescriptor, origin, state, parentBodyCodegen));
|
||||
}
|
||||
|
||||
boolean isOpenSuspendInClass =
|
||||
functionDescriptor.isSuspend() &&
|
||||
functionDescriptor.getModality() != Modality.ABSTRACT && isOverridable(functionDescriptor) &&
|
||||
!isInterface(functionDescriptor.getContainingDeclaration()) &&
|
||||
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
||||
|
||||
if (isOpenSuspendInClass) {
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
int index = 1;
|
||||
for (Type type : asmMethod.getArgumentTypes()) {
|
||||
mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
|
||||
index += type.getSize();
|
||||
}
|
||||
|
||||
Method asmMethodForOpenSuspendImpl = CoroutineCodegenUtilKt.getImplForOpenMethod(asmMethod, v.getThisName());
|
||||
// remove generic signature as it's unnecessary for synthetic methods
|
||||
JvmMethodSignature jvmSignatureForOpenSuspendImpl =
|
||||
new JvmMethodGenericSignature(
|
||||
asmMethodForOpenSuspendImpl,
|
||||
jvmSignature.getValueParameters(),
|
||||
null
|
||||
);
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
v.getThisName(), asmMethodForOpenSuspendImpl.getName(), asmMethodForOpenSuspendImpl.getDescriptor(),
|
||||
false
|
||||
);
|
||||
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitEnd();
|
||||
|
||||
int flagsForOpenSuspendImpl = flags;
|
||||
flagsForOpenSuspendImpl |= Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC;
|
||||
flagsForOpenSuspendImpl &= ~getVisibilityAccessFlag(functionDescriptor);
|
||||
flagsForOpenSuspendImpl |= AsmUtil.NO_FLAG_PACKAGE_PRIVATE;
|
||||
|
||||
MethodVisitor mvForOpenSuspendImpl = strategy.wrapMethodVisitor(
|
||||
v.newMethod(origin,
|
||||
flagsForOpenSuspendImpl,
|
||||
asmMethodForOpenSuspendImpl.getName(),
|
||||
asmMethodForOpenSuspendImpl.getDescriptor(),
|
||||
null,
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
),
|
||||
flagsForOpenSuspendImpl, asmMethodForOpenSuspendImpl.getName(),
|
||||
asmMethodForOpenSuspendImpl.getDescriptor()
|
||||
);
|
||||
|
||||
generateMethodBody(
|
||||
origin, functionDescriptor, methodContext, strategy, mvForOpenSuspendImpl, jvmSignatureForOpenSuspendImpl,
|
||||
staticInCompanionObject
|
||||
);
|
||||
}
|
||||
else {
|
||||
generateMethodBody(
|
||||
origin, functionDescriptor, methodContext, strategy, mv, jvmSignature, staticInCompanionObject
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void generateMethodBody(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodContext methodContext,
|
||||
@NotNull FunctionGenerationStrategy strategy,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmSignature,
|
||||
boolean staticInCompanionObject
|
||||
) {
|
||||
OwnerKind contextKind = methodContext.getContextKind();
|
||||
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind, state)) {
|
||||
generateLocalVariableTable(
|
||||
mv,
|
||||
@@ -595,8 +621,31 @@ public class FunctionCodegen {
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
int shiftForDestructuringVariables
|
||||
) {
|
||||
generateLocalVariablesForParameters(mv, jvmMethodSignature, thisType, methodBegin, methodEnd,
|
||||
functionDescriptor.getValueParameters(),
|
||||
if (functionDescriptor.isSuspend()) {
|
||||
FunctionDescriptor unwrapped = CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(
|
||||
functionDescriptor
|
||||
);
|
||||
|
||||
if (unwrapped != functionDescriptor) {
|
||||
generateLocalVariableTable(
|
||||
mv,
|
||||
new JvmMethodSignature(
|
||||
jvmMethodSignature.getAsmMethod(),
|
||||
jvmMethodSignature.getValueParameters().subList(
|
||||
0,
|
||||
jvmMethodSignature.getValueParameters().size() - 1
|
||||
)
|
||||
),
|
||||
unwrapped,
|
||||
thisType, methodBegin, methodEnd, ownerKind, typeMapper, shiftForDestructuringVariables
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
generateLocalVariablesForParameters(mv,
|
||||
jvmMethodSignature,
|
||||
thisType, methodBegin, methodEnd, functionDescriptor.getValueParameters(),
|
||||
AsmUtil.isStaticMethod(ownerKind, functionDescriptor), typeMapper, shiftForDestructuringVariables
|
||||
);
|
||||
}
|
||||
@@ -786,7 +835,9 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static String renderByteCodeIfAvailable(MethodVisitor mv) {
|
||||
@SuppressWarnings("WeakerAccess") // Useful in debug
|
||||
@Nullable
|
||||
public static String renderByteCodeIfAvailable(@NotNull MethodVisitor mv) {
|
||||
String bytecode = null;
|
||||
|
||||
if (mv instanceof TransformationMethodVisitor) {
|
||||
|
||||
@@ -24,10 +24,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DelegatingResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
@@ -40,8 +37,24 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject;
|
||||
|
||||
/*
|
||||
* Notice the difference between two function descriptors in this class.
|
||||
* - [referencedFunction] is the function declaration which is referenced by the "::" expression. This is a real function present in code.
|
||||
* - [functionDescriptor] is a synthetically created function which has the same signature as the "invoke" of the generated callable
|
||||
* reference subclass. Its parameters include dispatch/extension receiver parameters of the referenced function, and those value
|
||||
* parameters of the referenced function which are required by the expected function type where the callable reference is passed to.
|
||||
* In simple cases, these value parameters are all of the referenced function's value parameters. But in cases when the referenced
|
||||
* function has parameters with default values, or a vararg parameter, functionDescriptor can take fewer parameters than
|
||||
* referencedFunction if the expected function type takes fewer parameters as well. For example:
|
||||
*
|
||||
* fun foo(a: A, b: B = ..., c: C = ..., vararg d: D) {}
|
||||
*
|
||||
* fun bar(f: (A, B) -> Unit) {}
|
||||
*
|
||||
* // referencedFunction: foo(A, B, C, vararg D)
|
||||
* // functionDescriptor: invoke(A, B)
|
||||
* bar(::foo)
|
||||
*/
|
||||
public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased {
|
||||
private final ResolvedCall<?> resolvedCall;
|
||||
private final FunctionDescriptor referencedFunction;
|
||||
@@ -80,20 +93,21 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
every argument boils down to calling LOAD with the corresponding index
|
||||
*/
|
||||
|
||||
KtCallExpression fakeExpression = CodegenUtil.constructFakeFunctionCall(state.getProject(), referencedFunction);
|
||||
int receivers = CallableReferenceUtilKt.computeExpectedNumberOfReceivers(referencedFunction, receiverType != null);
|
||||
KtCallExpression fakeExpression =
|
||||
CodegenUtil.constructFakeFunctionCall(state.getProject(), functionDescriptor.getValueParameters().size() - receivers);
|
||||
List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments();
|
||||
|
||||
ReceiverValue dispatchReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getDispatchReceiverParameter());
|
||||
ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getExtensionReceiverParameter());
|
||||
computeAndSaveArguments(fakeArguments, codegen);
|
||||
computeAndSaveArguments(fakeArguments, codegen, receivers);
|
||||
|
||||
ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {
|
||||
|
||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> argumentMap;
|
||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> argumentMap = new LinkedHashMap<>();
|
||||
{
|
||||
argumentMap = new LinkedHashMap<>(fakeArguments.size());
|
||||
int index = 0;
|
||||
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
|
||||
List<ValueParameterDescriptor> parameters = referencedFunction.getValueParameters();
|
||||
for (ValueArgument argument : fakeArguments) {
|
||||
argumentMap.put(parameters.get(index), new ExpressionValueArgument(argument));
|
||||
index++;
|
||||
@@ -146,20 +160,14 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
v.areturn(returnType);
|
||||
}
|
||||
|
||||
private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) {
|
||||
int receivers = (referencedFunction.getDispatchReceiverParameter() != null ? 1 : 0) +
|
||||
(referencedFunction.getExtensionReceiverParameter() != null ? 1 : 0) -
|
||||
(receiverType != null ? 1 : 0);
|
||||
|
||||
if (receivers < 0 && referencedFunction instanceof ConstructorDescriptor && isObject(referencedFunction.getContainingDeclaration().getContainingDeclaration())) {
|
||||
//reference to object nested class
|
||||
//TODO: seems problem should be fixed on frontend side (note that object instance are captured by generated class)
|
||||
receivers = 0;
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> parameters = CollectionsKt.drop(functionDescriptor.getValueParameters(), receivers);
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
ValueParameterDescriptor parameter = parameters.get(i);
|
||||
private void computeAndSaveArguments(
|
||||
@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen, int receivers
|
||||
) {
|
||||
List<ValueParameterDescriptor> valueParameters = CollectionsKt.drop(functionDescriptor.getValueParameters(), receivers);
|
||||
assert valueParameters.size() == fakeArguments.size()
|
||||
: functionDescriptor + ": " + valueParameters.size() + " != " + fakeArguments.size();
|
||||
for (int i = 0; i < valueParameters.size(); i++) {
|
||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||
ValueArgument fakeArgument = fakeArguments.get(i);
|
||||
|
||||
Type type = state.getTypeMapper().mapType(parameter);
|
||||
|
||||
@@ -35,10 +35,10 @@ 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;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
@@ -64,10 +64,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.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.load.java.JvmAbi.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
@@ -356,6 +354,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
protected void generateSyntheticPartsAfterBody() {
|
||||
generateFieldForSingleton();
|
||||
|
||||
initializeObjects();
|
||||
|
||||
generateCompanionObjectBackingFieldCopies();
|
||||
|
||||
generateTraitMethods();
|
||||
@@ -813,21 +813,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateFieldForSingleton() {
|
||||
if (isCompanionObjectInInterfaceNotIntrinsic(descriptor)) {
|
||||
StackValue.Field field = StackValue.createSingletonViaInstance(descriptor, typeMapper, HIDDEN_INSTANCE_FIELD);
|
||||
//hidden instance in interface companion
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(descriptor),
|
||||
ACC_SYNTHETIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
|
||||
}
|
||||
|
||||
if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) return;
|
||||
|
||||
if (isNonCompanionObject(descriptor)) {
|
||||
StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper);
|
||||
StackValue.Field field = StackValue.createSingletonViaInstance(descriptor, typeMapper, INSTANCE_FIELD);
|
||||
v.newField(JvmDeclarationOriginKt.OtherOriginFromPure(myClass),
|
||||
ACC_PUBLIC | ACC_STATIC | ACC_FINAL,
|
||||
field.name, field.type.getDescriptor(), null, null);
|
||||
|
||||
if (!state.getClassBuilderMode().generateBodies) return;
|
||||
// Invoke the object constructor but ignore the result because INSTANCE will be initialized in the first line of <init>
|
||||
InstructionAdapter v = createOrGetClInitCodegen().v;
|
||||
markLineNumberForElement(element.getPsiOrParent(), v);
|
||||
v.anew(classAsmType);
|
||||
v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -838,9 +838,75 @@ 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 initializeObjects() {
|
||||
if (!DescriptorUtils.isObject(descriptor)) return;
|
||||
if (!state.getClassBuilderMode().generateBodies) return;
|
||||
|
||||
boolean isNonCompanionObject = isNonCompanionObject(descriptor);
|
||||
boolean isInterfaceCompanion = isCompanionObjectInInterfaceNotIntrinsic(descriptor);
|
||||
boolean isMappedIntrinsicCompanionObject = isMappedIntrinsicCompanionObject(descriptor);
|
||||
if (isNonCompanionObject || isInterfaceCompanion || isMappedIntrinsicCompanionObject) {
|
||||
ExpressionCodegen clInitCodegen = createOrGetClInitCodegen();
|
||||
InstructionAdapter v = clInitCodegen.v;
|
||||
markLineNumberForElement(element.getPsiOrParent(), v);
|
||||
v.anew(classAsmType);
|
||||
v.dup();
|
||||
v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
|
||||
|
||||
//local0 emulates this in object constructor
|
||||
int local0Index = clInitCodegen.getFrameMap().enterTemp(classAsmType);
|
||||
assert local0Index == 0 : "Local variable with index 0 in clInit should be used only for singleton instance keeping";
|
||||
StackValue.Local local0 = StackValue.local(0, classAsmType);
|
||||
local0.store(StackValue.onStack(classAsmType), clInitCodegen.v);
|
||||
StackValue.Field singleton =
|
||||
StackValue.createSingletonViaInstance(
|
||||
descriptor, typeMapper, isInterfaceCompanion ? HIDDEN_INSTANCE_FIELD : INSTANCE_FIELD
|
||||
);
|
||||
singleton.store(local0, clInitCodegen.v);
|
||||
|
||||
generateInitializers(clInitCodegen);
|
||||
|
||||
if (isInterfaceCompanion) {
|
||||
//initialize singleton instance in outer by hidden instance
|
||||
StackValue.singleton(descriptor, typeMapper).store(
|
||||
singleton, getParentCodegen().createOrGetClInitCodegen().v, true
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
|
||||
ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
|
||||
ExpressionCodegen parentClInitCodegen = parentCodegen.createOrGetClInitCodegen();
|
||||
InstructionAdapter parentVisitor = parentClInitCodegen.v;
|
||||
|
||||
FunctionDescriptor constructor = (FunctionDescriptor) parentCodegen.context.accessibleDescriptor(
|
||||
CollectionsKt.single(descriptor.getConstructors()), /* superCallExpression = */ null
|
||||
);
|
||||
parentCodegen.generateMethodCallTo(constructor, null, parentVisitor);
|
||||
StackValue instance = StackValue.onStack(parentCodegen.typeMapper.mapClass(descriptor));
|
||||
StackValue.singleton(descriptor, parentCodegen.typeMapper).store(instance, parentVisitor, true);
|
||||
|
||||
generateInitializers(parentClInitCodegen);
|
||||
}
|
||||
else {
|
||||
assert false : "Unknown object type: " + descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateCompanionObjectBackingFieldCopies() {
|
||||
@@ -890,17 +956,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
field.store(property, codegen.v);
|
||||
}
|
||||
|
||||
private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
|
||||
FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor(
|
||||
CollectionsKt.single(companionObject.getConstructors()), /* superCallExpression = */ null
|
||||
);
|
||||
generateMethodCallTo(constructor, null, codegen.v);
|
||||
StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
|
||||
StackValue.singleton(companionObject, typeMapper).store(instance, codegen.v, true);
|
||||
}
|
||||
|
||||
private void generatePrimaryConstructor(DelegationFieldsInfo delegationFieldsInfo) {
|
||||
if (isInterface(descriptor) || isAnnotationClass(descriptor)) return;
|
||||
|
||||
@@ -968,10 +1023,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor,
|
||||
getDelegationConstructorCall(bindingContext, constructorDescriptor));
|
||||
|
||||
if (isNonCompanionObject(descriptor)) {
|
||||
StackValue.singletonViaInstance(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
|
||||
}
|
||||
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatedSuperTypeEntry) specifier, fieldsInfo);
|
||||
@@ -993,18 +1044,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
curParam++;
|
||||
}
|
||||
|
||||
if (isCompanionObject(descriptor)) {
|
||||
ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
|
||||
parentCodegen.generateCompanionObjectInitializer(descriptor);
|
||||
}
|
||||
|
||||
if (JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
|
||||
generateInitializers(((ImplementationBodyCodegen) getParentCodegen())::createOrGetClInitCodegen);
|
||||
}
|
||||
else {
|
||||
//object initialization was moved to initializeObjects()
|
||||
if (!isObject(descriptor)) {
|
||||
generateInitializers(codegen);
|
||||
}
|
||||
|
||||
iv.visitInsn(RETURN);
|
||||
}
|
||||
|
||||
@@ -1149,7 +1192,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
if (asmType == null) continue;
|
||||
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n);
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, DELEGATE_SUPER_FIELD_PREFIX + n);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
@@ -1237,9 +1280,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
|
||||
@@ -1395,7 +1437,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
else {
|
||||
argumentGenerator =
|
||||
generateSuperCallImplicitArguments(iv, codegen, constructorDescriptor, delegateConstructor, delegateConstructorCallable,
|
||||
generateSuperCallImplicitArguments(iv, codegen, constructorDescriptor, delegateConstructor, delegationConstructorCall,
|
||||
delegateConstructorCallable,
|
||||
delegatingParameters,
|
||||
parameters);
|
||||
}
|
||||
@@ -1414,6 +1457,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull ConstructorDescriptor constructorDescriptor,
|
||||
@NotNull ConstructorDescriptor superConstructor,
|
||||
@NotNull ResolvedCall<ConstructorDescriptor> superConstructorCall,
|
||||
@NotNull CallableMethod superCallable,
|
||||
@NotNull List<JvmMethodParameterSignature> superParameters,
|
||||
@NotNull List<JvmMethodParameterSignature> parameters
|
||||
@@ -1456,7 +1500,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
if (isAnonymousObject(descriptor)) {
|
||||
List<JvmMethodParameterSignature> superValues = superParameters.subList(superIndex, superParameters.size());
|
||||
return new ObjectSuperCallArgumentGenerator(superValues, iv, offset);
|
||||
return new ObjectSuperCallArgumentGenerator(superValues, iv, offset, superConstructorCall);
|
||||
}
|
||||
else {
|
||||
return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(),
|
||||
@@ -1497,49 +1541,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
delegatingCallable.getValueParameterTypes());
|
||||
}
|
||||
|
||||
private static class ObjectSuperCallArgumentGenerator extends ArgumentGenerator {
|
||||
private final List<JvmMethodParameterSignature> parameters;
|
||||
private final InstructionAdapter iv;
|
||||
private int offset;
|
||||
|
||||
public ObjectSuperCallArgumentGenerator(
|
||||
@NotNull List<JvmMethodParameterSignature> superParameters,
|
||||
@NotNull InstructionAdapter iv,
|
||||
int firstValueParamOffset
|
||||
) {
|
||||
this.parameters = superParameters;
|
||||
this.iv = iv;
|
||||
this.offset = firstValueParamOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||
generateSuperCallArgument(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
Type type = parameters.get(i).getAsmType();
|
||||
pushDefaultValueOnStack(type, iv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||
generateSuperCallArgument(i);
|
||||
}
|
||||
|
||||
private void generateSuperCallArgument(int i) {
|
||||
Type type = parameters.get(i).getAsmType();
|
||||
iv.load(offset, type);
|
||||
offset += type.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> args) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void generateEnumEntries() {
|
||||
if (descriptor.getKind() != ClassKind.ENUM_CLASS) return;
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class InlineCycleReporter(val diagnostics: DiagnosticSink) {
|
||||
class InlineCycleReporter(private val diagnostics: DiagnosticSink) {
|
||||
|
||||
val processingFunctions = linkedMapOf<PsiElement, CallableDescriptor>()
|
||||
private val processingFunctions = linkedMapOf<PsiElement, CallableDescriptor>()
|
||||
|
||||
fun enterIntoInlining(call: ResolvedCall<*>?): Boolean {
|
||||
//null call for default method inlining
|
||||
|
||||
@@ -17,7 +17,35 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import java.util.*
|
||||
|
||||
interface InnerClassConsumer {
|
||||
fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor)
|
||||
|
||||
companion object {
|
||||
|
||||
fun classForInnerClassRecord(descriptor: ClassDescriptor, defaultImpls: Boolean): ClassDescriptor? {
|
||||
if (defaultImpls) {
|
||||
if (DescriptorUtils.isLocal(descriptor)) return null
|
||||
val classDescriptorImpl = ClassDescriptorImpl(
|
||||
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
||||
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false)
|
||||
|
||||
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
|
||||
return classDescriptorImpl
|
||||
}
|
||||
else {
|
||||
return if (DescriptorUtils.isTopLevelDeclaration(descriptor)) null else descriptor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,20 +22,14 @@ import org.jetbrains.kotlin.backend.common.bridges.firstSuperMethodFromKotlin
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import java.util.*
|
||||
|
||||
class InterfaceImplBodyCodegen(
|
||||
aClass: KtPureClassOrObject,
|
||||
@@ -47,12 +41,14 @@ class InterfaceImplBodyCodegen(
|
||||
private var isAnythingGenerated: Boolean = false
|
||||
get() = (v as InterfaceImplClassBuilder).isAnythingGenerated
|
||||
|
||||
private val defaultImplType = typeMapper.mapDefaultImpls(descriptor)
|
||||
|
||||
override fun generateDeclaration() {
|
||||
val codegenFlags = ACC_PUBLIC or ACC_FINAL or ACC_SUPER
|
||||
val flags = if (state.classBuilderMode == ClassBuilderMode.LIGHT_CLASSES) codegenFlags or ACC_STATIC else codegenFlags
|
||||
v.defineClass(
|
||||
myClass.psiOrParent, state.classFileVersion, flags,
|
||||
typeMapper.mapDefaultImpls(descriptor).internalName,
|
||||
defaultImplType.internalName,
|
||||
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
|
||||
)
|
||||
v.visitSource(myClass.containingKtFile.name, null)
|
||||
@@ -60,14 +56,7 @@ class InterfaceImplBodyCodegen(
|
||||
|
||||
override fun classForInnerClassRecord(): ClassDescriptor? {
|
||||
if (!isAnythingGenerated) return null
|
||||
if (DescriptorUtils.isLocal(descriptor)) return null
|
||||
val classDescriptorImpl = ClassDescriptorImpl(
|
||||
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
||||
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false)
|
||||
|
||||
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
|
||||
return classDescriptorImpl
|
||||
return InnerClassConsumer.classForInnerClassRecord(descriptor, true)
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsAfterBody() {
|
||||
@@ -161,7 +150,7 @@ class InterfaceImplBodyCodegen(
|
||||
override fun done() {
|
||||
super.done()
|
||||
if (!isAnythingGenerated) {
|
||||
state.factory.removeClasses(setOf(typeMapper.mapDefaultImpls(descriptor).internalName))
|
||||
state.factory.removeClasses(setOf(defaultImplType.internalName))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,4 +179,8 @@ class InterfaceImplBodyCodegen(
|
||||
return super.newMethod(origin, access, name, desc, signature, exceptions)
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsBeforeBody() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(defaultImplType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
|
||||
import org.jetbrains.kotlin.coroutines.isSuspendLambda
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
||||
@@ -29,7 +30,6 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
|
||||
class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
private val kotlinJvmInternalPackage = MutablePackageFragmentDescriptor(module, FqName("kotlin.jvm.internal"))
|
||||
@@ -77,7 +77,7 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
descriptor.builtIns,
|
||||
Annotations.EMPTY,
|
||||
actualFunctionDescriptor.extensionReceiverParameter?.type,
|
||||
ExpressionTypingUtils.getValueParametersTypes(actualFunctionDescriptor.valueParameters),
|
||||
actualFunctionDescriptor.valueParameters.map { it.type },
|
||||
null,
|
||||
actualFunctionDescriptor.returnType!!
|
||||
)
|
||||
@@ -94,14 +94,20 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
return listOf(lambda.defaultType, functionType)
|
||||
}
|
||||
|
||||
fun getSupertypesForFunctionReference(descriptor: FunctionDescriptor, isBound: Boolean): Collection<KotlinType> {
|
||||
fun getSupertypesForFunctionReference(
|
||||
referencedFunction: FunctionDescriptor,
|
||||
anonymousFunctionDescriptor: AnonymousFunctionDescriptor,
|
||||
isBound: Boolean
|
||||
): Collection<KotlinType> {
|
||||
val receivers = computeExpectedNumberOfReceivers(referencedFunction, isBound)
|
||||
|
||||
val functionType = createFunctionType(
|
||||
descriptor.builtIns,
|
||||
referencedFunction.builtIns,
|
||||
Annotations.EMPTY,
|
||||
if (isBound) null else descriptor.extensionReceiverParameter?.type ?: descriptor.dispatchReceiverParameter?.type,
|
||||
ExpressionTypingUtils.getValueParametersTypes(descriptor.valueParameters),
|
||||
if (isBound) null else referencedFunction.extensionReceiverParameter?.type ?: referencedFunction.dispatchReceiverParameter?.type,
|
||||
anonymousFunctionDescriptor.valueParameters.drop(receivers).map { it.type },
|
||||
null,
|
||||
descriptor.returnType!!
|
||||
referencedFunction.returnType!!
|
||||
)
|
||||
|
||||
return listOf(functionReference.defaultType, functionType)
|
||||
|
||||
@@ -25,9 +25,9 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
|
||||
class JvmStaticInCompanionObjectGenerator(
|
||||
val descriptor: FunctionDescriptor,
|
||||
val declarationOrigin: JvmDeclarationOrigin,
|
||||
val state: GenerationState,
|
||||
private val descriptor: FunctionDescriptor,
|
||||
private val declarationOrigin: JvmDeclarationOrigin,
|
||||
private val state: GenerationState,
|
||||
parentBodyCodegen: ImplementationBodyCodegen
|
||||
) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> {
|
||||
private val typeMapper = state.typeMapper
|
||||
@@ -94,8 +94,7 @@ class JvmStaticInCompanionObjectGenerator(
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
false
|
||||
)
|
||||
val staticFunctionDescriptor = copies[descriptor]!!
|
||||
return staticFunctionDescriptor
|
||||
return copies[descriptor]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import kotlin.collections.SetsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
@@ -55,7 +56,7 @@ public class KotlinCodegenFacade {
|
||||
for (KtFile file : files) {
|
||||
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
|
||||
|
||||
JvmFileClassInfo fileClassInfo = state.getFileClassesProvider().getFileClassInfo(file);
|
||||
JvmFileClassInfo fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file);
|
||||
|
||||
if (fileClassInfo.getWithJvmMultifileClass()) {
|
||||
filesInMultifileClasses.putValue(fileClassInfo.getFacadeClassFqName(), file);
|
||||
@@ -66,13 +67,13 @@ public class KotlinCodegenFacade {
|
||||
}
|
||||
|
||||
Set<FqName> obsoleteMultifileClasses = new HashSet<>(state.getObsoleteMultifileClasses());
|
||||
for (FqName multifileClassFqName : Sets.union(filesInMultifileClasses.keySet(), obsoleteMultifileClasses)) {
|
||||
for (FqName multifileClassFqName : SetsKt.plus(filesInMultifileClasses.keySet(), obsoleteMultifileClasses)) {
|
||||
doCheckCancelled(state);
|
||||
generateMultifileClass(state, multifileClassFqName, filesInMultifileClasses.get(multifileClassFqName), errorHandler);
|
||||
}
|
||||
|
||||
Set<FqName> packagesWithObsoleteParts = new HashSet<>(state.getPackagesWithObsoleteParts());
|
||||
for (FqName packageFqName : Sets.union(packagesWithObsoleteParts, filesInPackages.keySet())) {
|
||||
for (FqName packageFqName : SetsKt.plus(packagesWithObsoleteParts, filesInPackages.keySet())) {
|
||||
doCheckCancelled(state);
|
||||
generatePackage(state, packageFqName, filesInPackages.get(packageFqName), errorHandler);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ 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.DefaultSourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.inline.NameGenerator;
|
||||
@@ -36,8 +37,7 @@ 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.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
@@ -47,7 +47,6 @@ 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.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
@@ -69,7 +68,10 @@ 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;
|
||||
@@ -95,7 +97,6 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
public final KotlinTypeMapper typeMapper;
|
||||
public final BindingContext bindingContext;
|
||||
|
||||
private final JvmFileClassesProvider fileClassesProvider;
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
|
||||
private final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<>();
|
||||
@@ -115,7 +116,6 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
this.state = state;
|
||||
this.typeMapper = state.getTypeMapper();
|
||||
this.bindingContext = state.getBindingContext();
|
||||
this.fileClassesProvider = state.getFileClassesProvider();
|
||||
this.element = element;
|
||||
this.context = context;
|
||||
this.v = builder;
|
||||
@@ -339,12 +339,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
parentCodegen.innerClasses.add(classDescriptor);
|
||||
}
|
||||
|
||||
for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) {
|
||||
ClassDescriptor outerClass = codegen.classForInnerClassRecord();
|
||||
if (outerClass != null) {
|
||||
innerClasses.add(outerClass);
|
||||
}
|
||||
}
|
||||
addParentsToInnerClassesIfNeeded(innerClasses);
|
||||
}
|
||||
|
||||
for (ClassDescriptor innerClass : innerClasses) {
|
||||
@@ -352,6 +347,18 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
}
|
||||
|
||||
protected void addParentsToInnerClassesIfNeeded(@NotNull Collection<ClassDescriptor> innerClasses) {
|
||||
ClassDescriptor outerClass = classForInnerClassRecord();
|
||||
if (outerClass != null) {
|
||||
innerClasses.add(outerClass);
|
||||
}
|
||||
|
||||
MemberCodegen<?> parentCodegen = getParentCodegen();
|
||||
if (parentCodegen != null) {
|
||||
parentCodegen.addParentsToInnerClassesIfNeeded(innerClasses);
|
||||
}
|
||||
}
|
||||
|
||||
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
||||
// See FileBasedKotlinClass.convertAnnotationVisitor
|
||||
@Override
|
||||
@@ -423,7 +430,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
return implementationOwnerType;
|
||||
}
|
||||
else {
|
||||
return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile());
|
||||
return Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(element.getContainingKtFile()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,7 +458,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
@NotNull
|
||||
public NameGenerator getInlineNameGenerator() {
|
||||
if (inlineNameGenerator == null) {
|
||||
String prefix = getInlineName(context, typeMapper, fileClassesProvider);
|
||||
String prefix = getInlineName(context, typeMapper);
|
||||
inlineNameGenerator = new NameGenerator(prefix);
|
||||
}
|
||||
return inlineNameGenerator;
|
||||
@@ -506,7 +513,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
public void beforeMethodBody(@NotNull MethodVisitor mv) {
|
||||
}
|
||||
|
||||
private void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) {
|
||||
// Requires public access, because it is used by serialization plugin to generate initializer in synthetic constructor
|
||||
public void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
|
||||
assert propertyDescriptor != null;
|
||||
|
||||
@@ -514,7 +522,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
|
||||
|
||||
StackValue.Property propValue = codegen.intermediateValueForProperty(
|
||||
propertyDescriptor, true, false, null, true, StackValue.LOCAL_0, null);
|
||||
propertyDescriptor, true, false, null, true, StackValue.LOCAL_0, null, false
|
||||
);
|
||||
|
||||
ResolvedCall<FunctionDescriptor> provideDelegateResolvedCall = bindingContext.get(PROVIDE_DELEGATE_RESOLVED_CALL, propertyDescriptor);
|
||||
if (provideDelegateResolvedCall == null) {
|
||||
@@ -524,17 +533,15 @@ 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);
|
||||
}
|
||||
|
||||
protected boolean shouldInitializeProperty(@NotNull KtProperty property) {
|
||||
// Public accessible for serialization plugin to check whether call to initializeProperty(..) is legal.
|
||||
public boolean shouldInitializeProperty(@NotNull KtProperty property) {
|
||||
if (!property.hasDelegateExpressionOrInitializer()) return false;
|
||||
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
|
||||
@@ -608,16 +615,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);
|
||||
@@ -629,8 +628,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);
|
||||
@@ -640,10 +638,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
|
||||
@@ -736,6 +736,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
|
||||
private final PropertyAccessorDescriptor callableDescriptor;
|
||||
|
||||
private PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
|
||||
super(MemberCodegen.this.state);
|
||||
this.callableDescriptor = callableDescriptor;
|
||||
@@ -743,7 +744,9 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
|
||||
FieldAccessorKind fieldAccessorKind = accessor instanceof AccessorForPropertyBackingField
|
||||
? ((AccessorForPropertyBackingField) accessor).getFieldAccessorKind() : null;
|
||||
boolean syntheticBackingField = fieldAccessorKind == FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||
boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
!isCompanionObject(accessor.getContainingDeclaration());
|
||||
boolean forceField = forceFieldForCompanionProperty ||
|
||||
@@ -751,7 +754,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
|
||||
StackValue property = codegen.intermediateValueForProperty(
|
||||
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(),
|
||||
forceFieldForCompanionProperty, StackValue.none(), null
|
||||
forceFieldForCompanionProperty, StackValue.none(), null,
|
||||
fieldAccessorKind == FieldAccessorKind.LATEINIT_INTRINSIC
|
||||
);
|
||||
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
@@ -77,9 +77,6 @@ class MultifileClassCodegenImpl(
|
||||
.getContributedDescriptors(DescriptorKindFilter.CALLABLES, MemberScope.ALL_NAME_FILTER)
|
||||
.filterIsInstance<DeserializedCallableMemberDescriptor>()
|
||||
|
||||
private fun KtFile.getFileClassFqName() =
|
||||
state.fileClassesProvider.getFileClassInfo(this).fileClassFqName
|
||||
|
||||
private val shouldGeneratePartHierarchy =
|
||||
state.inheritMultifileParts
|
||||
|
||||
@@ -87,7 +84,7 @@ class MultifileClassCodegenImpl(
|
||||
val partInternalNamesSet = hashSetOf<String>()
|
||||
for (file in files) {
|
||||
if (file.hasDeclarationsForPartClass()) {
|
||||
partInternalNamesSet.add(file.getFileClassFqName().toInternalName())
|
||||
partInternalNamesSet.add(JvmFileClassUtil.getFileClassInternalName(file))
|
||||
}
|
||||
}
|
||||
compiledPackageFragment?.let {
|
||||
@@ -205,17 +202,14 @@ 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 = Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(file))
|
||||
val partContext = state.rootContext.intoMultifileClassPart(packageFragment, facadeClassType, partType, file)
|
||||
|
||||
generateNonPartClassDeclarations(file, partContext)
|
||||
|
||||
if (!state.generateDeclaredClassFilter.shouldGeneratePackagePart(file) || !file.hasDeclarationsForPartClass()) return
|
||||
|
||||
packagePartRegistry.addPart(partType.internalName.substringAfterLast('/'), facadeClassType.internalName.substringAfterLast('/'))
|
||||
packagePartRegistry.addPart(partType.internalName, facadeClassType.internalName)
|
||||
|
||||
val builder = state.factory.newVisitor(MultifileClassPart(file, packageFragment), partType, file)
|
||||
|
||||
@@ -323,7 +317,7 @@ class MultifileClassCodegenImpl(
|
||||
|
||||
private fun writeKotlinMultifileFacadeAnnotationIfNeeded() {
|
||||
if (!state.classBuilderMode.generateMetadata) return
|
||||
if (files.any { it.isScript }) return
|
||||
if (files.any { it.isScript() }) return
|
||||
|
||||
val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0
|
||||
|
||||
@@ -375,12 +369,6 @@ class MultifileClassCodegenImpl(
|
||||
private fun KtFile.hasDeclarationsForPartClass() =
|
||||
declarations.any { it is KtProperty || it is KtFunction }
|
||||
|
||||
private fun FqName.toInternalName() =
|
||||
AsmUtil.internalNameByFqNameWithoutInnerClasses(this)
|
||||
|
||||
private fun FqName.toAsmType() =
|
||||
AsmUtil.asmTypeByFqNameWithoutInnerClasses(this)
|
||||
|
||||
private fun getCompiledPackageFragment(
|
||||
facadeFqName: FqName, state: GenerationState
|
||||
): IncrementalPackageFragmentProvider.IncrementalMultifileClassPackageFragment? {
|
||||
@@ -396,5 +384,4 @@ class MultifileClassCodegenImpl(
|
||||
return incrementalPackageFragment?.getPackageFragmentForMultifileClass(facadeFqName)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.AsmUtil.pushDefaultValueOnStack
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
internal class ObjectSuperCallArgumentGenerator(
|
||||
private val parameters: List<JvmMethodParameterSignature>,
|
||||
private val iv: InstructionAdapter,
|
||||
offset: Int,
|
||||
superConstructorCall: ResolvedCall<ConstructorDescriptor>
|
||||
) : ArgumentGenerator() {
|
||||
|
||||
private val offsets = IntArray(parameters.size) { -1 }
|
||||
|
||||
init {
|
||||
var currentOffset = offset
|
||||
superConstructorCall.valueArguments.forEach {
|
||||
(descriptor, argument) ->
|
||||
if (argument !is DefaultValueArgument) {
|
||||
val index = descriptor.index
|
||||
offsets[index] = currentOffset
|
||||
currentOffset += parameters[index].asmType.size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun generate(
|
||||
valueArgumentsByIndex: List<ResolvedValueArgument>,
|
||||
actualArgs: List<ResolvedValueArgument>,
|
||||
calleeDescriptor: CallableDescriptor?
|
||||
): DefaultCallArgs = super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor)
|
||||
|
||||
public override fun generateExpression(i: Int, argument: ExpressionValueArgument) {
|
||||
generateSuperCallArgument(i)
|
||||
}
|
||||
|
||||
public override fun generateDefault(i: Int, argument: DefaultValueArgument) {
|
||||
val type = parameters[i].asmType
|
||||
pushDefaultValueOnStack(type, iv)
|
||||
}
|
||||
|
||||
public override fun generateVararg(i: Int, argument: VarargValueArgument) {
|
||||
generateSuperCallArgument(i)
|
||||
}
|
||||
|
||||
private fun generateSuperCallArgument(i: Int) {
|
||||
val type = parameters[i].asmType
|
||||
if (offsets[i] == -1) {
|
||||
throw AssertionError("Unknown parameter value at index $i with type $type")
|
||||
}
|
||||
iv.load(offsets[i], type)
|
||||
}
|
||||
|
||||
override fun reorderArgumentsIfNeeded(args: List<ArgumentAndDeclIndex>) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.SmartList;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.context.PackageContext;
|
||||
@@ -28,10 +27,11 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
@@ -88,11 +88,8 @@ public class PackageCodegenImpl implements PackageCodegen {
|
||||
}
|
||||
|
||||
private void generateFile(@NotNull KtFile file) {
|
||||
JvmFileClassInfo fileClassInfo = state.getFileClassesProvider().getFileClassInfo(file);
|
||||
|
||||
if (fileClassInfo.getWithJvmMultifileClass()) {
|
||||
return;
|
||||
}
|
||||
JvmFileClassInfo fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file);
|
||||
if (fileClassInfo.getWithJvmMultifileClass()) return;
|
||||
|
||||
Type fileClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(fileClassInfo.getFileClassFqName());
|
||||
PackageContext packagePartContext = state.getRootContext().intoPackagePart(packageFragment, fileClassType, file);
|
||||
@@ -102,7 +99,7 @@ public class PackageCodegenImpl implements PackageCodegen {
|
||||
List<KtClassOrObject> classOrObjects = new ArrayList<>();
|
||||
|
||||
for (KtDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration.hasModifier(KtTokens.HEADER_KEYWORD)) continue;
|
||||
if (PsiUtilsKt.hasExpectModifier(declaration)) continue;
|
||||
|
||||
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
|
||||
generatePackagePart = true;
|
||||
@@ -125,8 +122,7 @@ public class PackageCodegenImpl implements PackageCodegen {
|
||||
|
||||
if (!generatePackagePart || !state.getGenerateDeclaredClassFilter().shouldGeneratePackagePart(file)) return;
|
||||
|
||||
String name = fileClassType.getInternalName();
|
||||
packagePartRegistry.addPart(StringsKt.substringAfterLast(name, '/', name), null);
|
||||
packagePartRegistry.addPart(fileClassType.getInternalName(), null);
|
||||
|
||||
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.PackagePart(file, packageFragment), fileClassType, file);
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
||||
@@ -89,7 +89,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
@Override
|
||||
protected void generateBody() {
|
||||
for (KtDeclaration declaration : element.getDeclarations()) {
|
||||
if (declaration.hasModifier(KtTokens.HEADER_KEYWORD)) continue;
|
||||
if (PsiUtilsKt.hasExpectModifier(declaration)) continue;
|
||||
|
||||
if (declaration instanceof KtNamedFunction || declaration instanceof KtProperty || declaration instanceof KtTypeAlias) {
|
||||
genSimpleMember(declaration);
|
||||
@@ -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);
|
||||
|
||||
@@ -17,5 +17,5 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
interface PackagePartRegistry {
|
||||
fun addPart(partShortName: String, facadeShortName: String?)
|
||||
fun addPart(partInternalName: String, facadeInternalName: String?)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -62,7 +62,7 @@ class PropertyReferenceCodegen(
|
||||
|
||||
private val isLocalDelegatedProperty = target is LocalVariableDescriptor
|
||||
|
||||
val getFunction =
|
||||
private val getFunction =
|
||||
if (isLocalDelegatedProperty)
|
||||
(localVariableDescriptorForReference as VariableDescriptorWithAccessors).getter!!
|
||||
else
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -164,7 +165,7 @@ class PropertyReferenceCodegen(
|
||||
writeSyntheticClassMetadata(v, state)
|
||||
}
|
||||
|
||||
fun putInstanceOnStack(receiverValue: (() -> Unit)?): StackValue {
|
||||
fun putInstanceOnStack(receiverValue: StackValue?): StackValue {
|
||||
return StackValue.operation(wrapperMethod.returnType) { iv ->
|
||||
if (JvmCodegenUtil.isConst(closure)) {
|
||||
assert(receiverValue == null) { "No receiver expected for unbound property reference: $classDescriptor" }
|
||||
@@ -174,7 +175,7 @@ class PropertyReferenceCodegen(
|
||||
assert(receiverValue != null) { "Receiver expected for bound property reference: $classDescriptor" }
|
||||
iv.anew(asmType)
|
||||
iv.dup()
|
||||
receiverValue!!()
|
||||
receiverValue!!.put(receiverValue.type, iv)
|
||||
iv.invokespecial(asmType.internalName, "<init>", constructor.descriptor, false)
|
||||
}
|
||||
}
|
||||
@@ -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 ->
|
||||
@@ -238,13 +250,13 @@ class PropertyReferenceCodegen(
|
||||
|
||||
class PropertyReferenceGenerationStrategy(
|
||||
val isGetter: Boolean,
|
||||
val originalFunctionDesc: FunctionDescriptor,
|
||||
private val originalFunctionDesc: FunctionDescriptor,
|
||||
val target: VariableDescriptor,
|
||||
val asmType: Type,
|
||||
val receiverType: Type?,
|
||||
val expression: KtElement,
|
||||
state: GenerationState,
|
||||
val isInliningStrategy: Boolean
|
||||
private val isInliningStrategy: Boolean
|
||||
) :
|
||||
FunctionGenerationStrategy.CodegenBased(state) {
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
|
||||
@@ -50,12 +50,12 @@ public class SamType {
|
||||
@NotNull
|
||||
public KotlinType getKotlinFunctionType() {
|
||||
//noinspection ConstantConditions
|
||||
return getJavaClassDescriptor().getFunctionTypeForSamInterface();
|
||||
return getJavaClassDescriptor().getDefaultFunctionTypeForSamInterface();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SimpleFunctionDescriptor getAbstractMethod() {
|
||||
return (SimpleFunctionDescriptor) SingleAbstractMethodUtils.getAbstractMembers(type).get(0);
|
||||
public SimpleFunctionDescriptor getOriginalAbstractMethod() {
|
||||
return (SimpleFunctionDescriptor) SingleAbstractMethodUtils.getAbstractMembers(getJavaClassDescriptor()).get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -88,7 +88,7 @@ public class SamWrapperCodegen {
|
||||
/* isExternal = */ false
|
||||
);
|
||||
// e.g. compare(T, T)
|
||||
SimpleFunctionDescriptor erasedInterfaceFunction = samType.getAbstractMethod().getOriginal().copy(
|
||||
SimpleFunctionDescriptor erasedInterfaceFunction = samType.getOriginalAbstractMethod().copy(
|
||||
classDescriptor,
|
||||
Modality.FINAL,
|
||||
Visibilities.PUBLIC,
|
||||
@@ -167,7 +167,7 @@ public class SamWrapperCodegen {
|
||||
|
||||
// generate sam bridges
|
||||
// TODO: erasedInterfaceFunction is actually not an interface function, but function in generated class
|
||||
SimpleFunctionDescriptor originalInterfaceErased = samType.getAbstractMethod().getOriginal();
|
||||
SimpleFunctionDescriptor originalInterfaceErased = samType.getOriginalAbstractMethod();
|
||||
SimpleFunctionDescriptorImpl descriptorForBridges = SimpleFunctionDescriptorImpl
|
||||
.create(erasedInterfaceFunction.getContainingDeclaration(), erasedInterfaceFunction.getAnnotations(), originalInterfaceErased.getName(),
|
||||
CallableMemberDescriptor.Kind.DECLARATION, erasedInterfaceFunction.getSource());
|
||||
|
||||
@@ -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,12 +26,12 @@ 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.pseudoInsns.PseudoInsnsKt;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.ValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -149,6 +148,11 @@ public abstract class StackValue {
|
||||
return new Local(index, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Local local(int index, @NotNull Type type, @NotNull VariableDescriptor descriptor) {
|
||||
return new Local(index, type, descriptor.isLateInit(), descriptor.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Delegate delegate(
|
||||
@NotNull Type type,
|
||||
@@ -165,6 +169,11 @@ public abstract class StackValue {
|
||||
return new Shared(index, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StackValue shared(int index, @NotNull Type type, @NotNull VariableDescriptor descriptor) {
|
||||
return new Shared(index, type, descriptor.isLateInit(), descriptor.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StackValue onStack(@NotNull Type type) {
|
||||
return type == Type.VOID_TYPE ? none() : new OnStack(type);
|
||||
@@ -181,7 +190,7 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static StackValue createDefaulValue(@NotNull Type type) {
|
||||
public static StackValue createDefaultValue(@NotNull Type type) {
|
||||
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
||||
return constant(null, type);
|
||||
}
|
||||
@@ -297,9 +306,11 @@ public abstract class StackValue {
|
||||
@Nullable CallableMethod setter,
|
||||
@NotNull StackValue receiver,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@Nullable ResolvedCall resolvedCall
|
||||
@Nullable ResolvedCall resolvedCall,
|
||||
boolean skipLateinitAssertion
|
||||
) {
|
||||
return new Property(descriptor, backingFieldOwner, getter, setter, isStaticBackingField, fieldName, type, receiver, codegen, resolvedCall);
|
||||
return new Property(descriptor, backingFieldOwner, getter, setter, isStaticBackingField, fieldName, type, receiver, codegen,
|
||||
resolvedCall, skipLateinitAssertion);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -437,16 +448,18 @@ public abstract class StackValue {
|
||||
@NotNull Type localType,
|
||||
@NotNull Type classType,
|
||||
@NotNull String fieldName,
|
||||
@NotNull Field refWrapper
|
||||
@NotNull Field refWrapper,
|
||||
@NotNull VariableDescriptor variableDescriptor
|
||||
) {
|
||||
return new FieldForSharedVar(localType, classType, fieldName, refWrapper);
|
||||
return new FieldForSharedVar(localType, classType, fieldName, refWrapper,
|
||||
variableDescriptor.isLateInit(), variableDescriptor.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FieldForSharedVar fieldForSharedVar(@NotNull FieldForSharedVar field, @NotNull StackValue newReceiver) {
|
||||
Field oldReceiver = (Field) field.receiver;
|
||||
Field newSharedVarReceiver = field(oldReceiver, newReceiver);
|
||||
return new FieldForSharedVar(field.type, field.owner, field.name, newSharedVarReceiver);
|
||||
return new FieldForSharedVar(field.type, field.owner, field.name, newSharedVarReceiver, field.isLateinit, field.variableName);
|
||||
}
|
||||
|
||||
public static StackValue coercion(@NotNull StackValue value, @NotNull Type castType) {
|
||||
@@ -518,9 +531,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 +584,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;
|
||||
}
|
||||
@@ -594,8 +608,8 @@ public abstract class StackValue {
|
||||
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper), none());
|
||||
}
|
||||
|
||||
public static Field singletonViaInstance(ClassDescriptor classDescriptor, KotlinTypeMapper typeMapper) {
|
||||
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper), none());
|
||||
public static Field createSingletonViaInstance(@NotNull ClassDescriptor classDescriptor, @NotNull KotlinTypeMapper typeMapper, @NotNull String name) {
|
||||
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, name), none());
|
||||
}
|
||||
|
||||
public static StackValue operation(Type type, Function1<InstructionAdapter, Unit> lambda) {
|
||||
@@ -625,19 +639,35 @@ public abstract class StackValue {
|
||||
|
||||
public static class Local extends StackValue {
|
||||
public final int index;
|
||||
private final boolean isLateinit;
|
||||
private final Name name;
|
||||
|
||||
private Local(int index, Type type) {
|
||||
private Local(int index, Type type, boolean isLateinit, Name name) {
|
||||
super(type, false);
|
||||
this.index = index;
|
||||
|
||||
if (index < 0) {
|
||||
throw new IllegalStateException("local variable index must be non-negative");
|
||||
}
|
||||
|
||||
if (isLateinit && name == null) {
|
||||
throw new IllegalArgumentException("Lateinit local variable should have name: #" + index + " " + type.getDescriptor());
|
||||
}
|
||||
|
||||
this.index = index;
|
||||
this.isLateinit = isLateinit;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private Local(int index, Type type) {
|
||||
this(index, type, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
v.load(index, this.type);
|
||||
if (isLateinit) {
|
||||
StackValue.genNonNullAssertForLateinit(v, name.asString());
|
||||
}
|
||||
coerceTo(type, v);
|
||||
// TODO unbox
|
||||
}
|
||||
@@ -646,6 +676,9 @@ public abstract class StackValue {
|
||||
public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) {
|
||||
coerceFrom(topOfStackType, v);
|
||||
v.store(index, this.type);
|
||||
if (isLateinit) {
|
||||
PseudoInsnsKt.storeNotNull(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1156,20 +1189,17 @@ public abstract class StackValue {
|
||||
private final CallableMethod getter;
|
||||
private final CallableMethod setter;
|
||||
private final Type backingFieldOwner;
|
||||
|
||||
private final PropertyDescriptor descriptor;
|
||||
|
||||
private final String fieldName;
|
||||
@NotNull private final ExpressionCodegen codegen;
|
||||
@Nullable private final ResolvedCall resolvedCall;
|
||||
private final ExpressionCodegen codegen;
|
||||
private final ResolvedCall resolvedCall;
|
||||
private final boolean skipLateinitAssertion;
|
||||
|
||||
public Property(
|
||||
@NotNull PropertyDescriptor descriptor, @Nullable Type backingFieldOwner,
|
||||
@Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStaticBackingField,
|
||||
@Nullable String fieldName, @NotNull Type type,
|
||||
@NotNull StackValue receiver,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@Nullable ResolvedCall resolvedCall
|
||||
@NotNull PropertyDescriptor descriptor, @Nullable Type backingFieldOwner, @Nullable CallableMethod getter,
|
||||
@Nullable CallableMethod setter, boolean isStaticBackingField, @Nullable String fieldName, @NotNull Type type,
|
||||
@NotNull StackValue receiver, @NotNull ExpressionCodegen codegen, @Nullable ResolvedCall resolvedCall,
|
||||
boolean skipLateinitAssertion
|
||||
) {
|
||||
super(type, isStatic(isStaticBackingField, getter), isStatic(isStaticBackingField, setter), receiver, true);
|
||||
this.backingFieldOwner = backingFieldOwner;
|
||||
@@ -1179,6 +1209,7 @@ public abstract class StackValue {
|
||||
this.fieldName = fieldName;
|
||||
this.codegen = codegen;
|
||||
this.resolvedCall = resolvedCall;
|
||||
this.skipLateinitAssertion = skipLateinitAssertion;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1190,7 +1221,9 @@ public abstract class StackValue {
|
||||
|
||||
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
|
||||
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||
genNotNullAssertionForLateInitIfNeeded(v);
|
||||
if (!skipLateinitAssertion) {
|
||||
genNotNullAssertionForLateInitIfNeeded(v);
|
||||
}
|
||||
coerceTo(type, v);
|
||||
}
|
||||
else {
|
||||
@@ -1260,12 +1293,7 @@ public abstract class StackValue {
|
||||
private void genNotNullAssertionForLateInitIfNeeded(@NotNull InstructionAdapter v) {
|
||||
if (!descriptor.isLateInit()) return;
|
||||
|
||||
v.dup();
|
||||
Label ok = new Label();
|
||||
v.ifnonnull(ok);
|
||||
v.visitLdcInsn(descriptor.getName().asString());
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwUninitializedPropertyAccessException", "(Ljava/lang/String;)V", false);
|
||||
v.mark(ok);
|
||||
StackValue.genNonNullAssertForLateinit(v, descriptor.getName().asString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1329,6 +1357,15 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
private static void genNonNullAssertForLateinit(@NotNull InstructionAdapter v, @NotNull String name) {
|
||||
v.dup();
|
||||
Label ok = new Label();
|
||||
v.ifnonnull(ok);
|
||||
v.visitLdcInsn(name);
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwUninitializedPropertyAccessException", "(Ljava/lang/String;)V", false);
|
||||
v.mark(ok);
|
||||
}
|
||||
|
||||
private static class Expression extends StackValue {
|
||||
private final KtExpression expression;
|
||||
private final ExpressionCodegen generator;
|
||||
@@ -1347,10 +1384,23 @@ public abstract class StackValue {
|
||||
|
||||
public static class Shared extends StackValueWithSimpleReceiver {
|
||||
private final int index;
|
||||
private final boolean isLateinit;
|
||||
private final Name name;
|
||||
|
||||
public Shared(int index, Type type) {
|
||||
public Shared(int index, Type type, boolean isLateinit, Name name) {
|
||||
super(type, false, false, local(index, OBJECT_TYPE), false);
|
||||
this.index = index;
|
||||
|
||||
if (isLateinit && name == null) {
|
||||
throw new IllegalArgumentException("Lateinit shared local variable should have name: #" + index + " " + type.getDescriptor());
|
||||
}
|
||||
|
||||
this.isLateinit = isLateinit;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Shared(int index, Type type) {
|
||||
this(index, type, false, null);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
@@ -1362,6 +1412,9 @@ public abstract class StackValue {
|
||||
Type refType = refType(this.type);
|
||||
Type sharedType = sharedTypeForType(this.type);
|
||||
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor());
|
||||
if (isLateinit) {
|
||||
StackValue.genNonNullAssertForLateinit(v, name.asString());
|
||||
}
|
||||
coerceFrom(refType, v);
|
||||
coerceTo(type, v);
|
||||
}
|
||||
@@ -1399,11 +1452,23 @@ public abstract class StackValue {
|
||||
public static class FieldForSharedVar extends StackValueWithSimpleReceiver {
|
||||
final Type owner;
|
||||
final String name;
|
||||
final boolean isLateinit;
|
||||
final Name variableName;
|
||||
|
||||
public FieldForSharedVar(Type type, Type owner, String name, StackValue.Field receiver) {
|
||||
public FieldForSharedVar(
|
||||
Type type, Type owner, String name, StackValue.Field receiver,
|
||||
boolean isLateinit, Name variableName
|
||||
) {
|
||||
super(type, false, false, receiver, receiver.canHaveSideEffects());
|
||||
|
||||
if (isLateinit && variableName == null) {
|
||||
throw new IllegalArgumentException("variableName should be non-null for captured lateinit variable " + name);
|
||||
}
|
||||
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.isLateinit = isLateinit;
|
||||
this.variableName = variableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1411,6 +1476,9 @@ public abstract class StackValue {
|
||||
Type sharedType = sharedTypeForType(this.type);
|
||||
Type refType = refType(this.type);
|
||||
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor());
|
||||
if (isLateinit) {
|
||||
StackValue.genNonNullAssertForLateinit(v, variableName.asString());
|
||||
}
|
||||
coerceFrom(refType, v);
|
||||
coerceTo(type, v);
|
||||
}
|
||||
@@ -1517,101 +1585,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;
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class CoercionValue(
|
||||
val value: StackValue,
|
||||
val castType: Type
|
||||
private val castType: Type
|
||||
) : StackValue(castType, value.canHaveSideEffects()) {
|
||||
|
||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -30,16 +30,18 @@ import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
|
||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||
import org.jetbrains.kotlin.coroutines.CoroutineUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
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;
|
||||
@@ -54,7 +56,10 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.*;
|
||||
@@ -79,18 +84,16 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
private final BindingContext bindingContext;
|
||||
private final GenerationState.GenerateClassFilter filter;
|
||||
private final JvmRuntimeTypes runtimeTypes;
|
||||
private final JvmFileClassesProvider fileClassesProvider;
|
||||
private final TypeMappingConfiguration<Type> typeMappingConfiguration;
|
||||
private final boolean shouldInlineConstVals;
|
||||
private final SwitchCodegenProvider switchCodegenProvider;
|
||||
|
||||
public CodegenAnnotatingVisitor(@NotNull GenerationState state) {
|
||||
this.bindingTrace = state.getBindingTrace();
|
||||
this.bindingContext = state.getBindingContext();
|
||||
this.filter = state.getGenerateDeclaredClassFilter();
|
||||
this.runtimeTypes = state.getJvmRuntimeTypes();
|
||||
this.fileClassesProvider = state.getFileClassesProvider();
|
||||
this.typeMappingConfiguration = state.getTypeMapper().getTypeMappingConfiguration();
|
||||
this.shouldInlineConstVals = state.getShouldInlineConstVals();
|
||||
this.switchCodegenProvider = new SwitchCodegenProvider(state);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -328,17 +331,25 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
if (referencedFunction == null) return;
|
||||
CallableDescriptor target = referencedFunction.getResultingDescriptor();
|
||||
|
||||
ReceiverValue extensionReceiver = referencedFunction.getExtensionReceiver();
|
||||
ReceiverValue dispatchReceiver = referencedFunction.getDispatchReceiver();
|
||||
|
||||
// TransientReceiver corresponds to an unbound reference, other receiver values -- to bound references
|
||||
KotlinType receiverType =
|
||||
dispatchReceiver != null && !(dispatchReceiver instanceof TransientReceiver) ? dispatchReceiver.getType() :
|
||||
extensionReceiver != null && !(extensionReceiver instanceof TransientReceiver) ? extensionReceiver.getType() :
|
||||
null;
|
||||
|
||||
CallableDescriptor callableDescriptor;
|
||||
Collection<KotlinType> supertypes;
|
||||
|
||||
KtExpression receiverExpression = expression.getReceiverExpression();
|
||||
KotlinType receiverType = receiverExpression != null ? bindingContext.getType(receiverExpression) : null;
|
||||
|
||||
if (target instanceof FunctionDescriptor) {
|
||||
callableDescriptor = bindingContext.get(FUNCTION, expression);
|
||||
if (callableDescriptor == null) return;
|
||||
|
||||
supertypes = runtimeTypes.getSupertypesForFunctionReference((FunctionDescriptor) target, receiverType != null);
|
||||
supertypes = runtimeTypes.getSupertypesForFunctionReference(
|
||||
(FunctionDescriptor) target, (AnonymousFunctionDescriptor) callableDescriptor, receiverType != null
|
||||
);
|
||||
}
|
||||
else if (target instanceof PropertyDescriptor) {
|
||||
callableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||
@@ -370,33 +381,18 @@ 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(),
|
||||
Name.identifier(variableDescriptor.getName().asString() + "$metadata"),
|
||||
ReflectionTypes.Companion.createKPropertyStarType(DescriptorUtilsKt.getModule(variableDescriptor)),
|
||||
false,
|
||||
false,
|
||||
SourceElement.NO_SOURCE
|
||||
);
|
||||
bindingTrace.record(LOCAL_VARIABLE_PROPERTY_METADATA, variableDescriptor, metadataVariableDescriptor);
|
||||
@@ -428,12 +424,44 @@ 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);
|
||||
if (classId == null) {
|
||||
return CodegenBinding.getAsmType(bindingContext, descriptor);
|
||||
}
|
||||
|
||||
return AsmUtil.asmTypeByClassId(
|
||||
DescriptorUtils.isInterface(descriptor)
|
||||
? classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
|
||||
: classId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(property.getContainingKtFile()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedFunction(@NotNull KtNamedFunction function) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function);
|
||||
@@ -517,7 +545,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
else if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||
KtFile containingFile = DescriptorToSourceUtils.getContainingFile(descriptor);
|
||||
assert containingFile != null : "File not found for " + descriptor;
|
||||
return FileClasses.getFileClassInternalName(fileClassesProvider, containingFile) + '$' + name;
|
||||
return JvmFileClassUtil.getFileClassInternalName(containingFile) + '$' + name;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -545,6 +573,9 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
if (valueArguments == null) return;
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : original.getValueParameters()) {
|
||||
ValueParameterDescriptor adaptedParameter = descriptor.getValueParameters().get(valueParameter.getIndex());
|
||||
if (KotlinTypeChecker.DEFAULT.equalTypes(adaptedParameter.getType(), valueParameter.getType())) continue;
|
||||
|
||||
SamType samType = SamType.create(TypeMapperUtilsKt.removeExternalProjections(valueParameter.getType()));
|
||||
if (samType == null) continue;
|
||||
|
||||
@@ -664,7 +695,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
WhenByEnumsMapping mapping = new WhenByEnumsMapping(classDescriptor, currentClassName, fieldNumber);
|
||||
|
||||
for (ConstantValue<?> constant : SwitchCodegenUtil.getAllConstants(expression, bindingContext, shouldInlineConstVals)) {
|
||||
for (ConstantValue<?> constant : switchCodegenProvider.getAllConstants(expression)) {
|
||||
if (constant instanceof NullValue) continue;
|
||||
|
||||
assert constant instanceof EnumValue : "expression in when should be EnumValue";
|
||||
@@ -678,10 +709,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
private boolean isWhenWithEnums(@NotNull KtWhenExpression expression) {
|
||||
return WhenChecker.isWhenByEnum(expression, bindingContext) &&
|
||||
SwitchCodegenUtil.checkAllItemsAreConstantsSatisfying(
|
||||
switchCodegenProvider.checkAllItemsAreConstantsSatisfying(
|
||||
expression,
|
||||
bindingContext,
|
||||
shouldInlineConstVals,
|
||||
constant -> constant instanceof EnumValue || constant instanceof NullValue
|
||||
);
|
||||
}
|
||||
@@ -696,7 +725,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
}
|
||||
}
|
||||
|
||||
return FileClasses.getFacadeClassInternalName(fileClassesProvider, file);
|
||||
return JvmFileClassUtil.getFacadeClassInternalName(file);
|
||||
}
|
||||
|
||||
private static <T> T peekFromStack(@NotNull Stack<T> stack) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user