mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-11 00:21:31 +00:00
Compare commits
400 Commits
rr/selezne
...
1.3.30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bddfa806c | ||
|
|
b6969cdf2a | ||
|
|
3719ecc1e0 | ||
|
|
e1d48eae88 | ||
|
|
3f47d10730 | ||
|
|
292d2d9deb | ||
|
|
47b38dbd1e | ||
|
|
b3be525f15 | ||
|
|
01e8c7c077 | ||
|
|
0df06f9d7c | ||
|
|
dc08b1d666 | ||
|
|
7774b825bf | ||
|
|
b2f4b410cf | ||
|
|
96bdd3c11e | ||
|
|
3b43276885 | ||
|
|
8c162cb82e | ||
|
|
23c2ea59de | ||
|
|
b6bea36596 | ||
|
|
548266df7c | ||
|
|
e0846e0eef | ||
|
|
fbbc6dfe2e | ||
|
|
b8654651b8 | ||
|
|
643361ce39 | ||
|
|
c5ddda2eb2 | ||
|
|
55e8e94caf | ||
|
|
b8414b430e | ||
|
|
0aa1e55b9a | ||
|
|
c8f11d8a71 | ||
|
|
57137df678 | ||
|
|
c880d79390 | ||
|
|
01b1c77c43 | ||
|
|
6381b3b151 | ||
|
|
7c7da5498e | ||
|
|
384fe15a8e | ||
|
|
6319f56464 | ||
|
|
e975f6f916 | ||
|
|
857c0b5597 | ||
|
|
02144498f1 | ||
|
|
681e8dd968 | ||
|
|
7025adeaea | ||
|
|
0423d49ef2 | ||
|
|
91699471b9 | ||
|
|
8372e917ef | ||
|
|
1ae93dea56 | ||
|
|
4ea3aa2a0a | ||
|
|
5184f35165 | ||
|
|
03a5c26060 | ||
|
|
7fa7e61f0a | ||
|
|
7cf5c28560 | ||
|
|
6f90e9bb08 | ||
|
|
54d75fb73b | ||
|
|
897d51796f | ||
|
|
419a22c1d2 | ||
|
|
45d2662821 | ||
|
|
2782813ef9 | ||
|
|
396d748ef4 | ||
|
|
369fdebbfb | ||
|
|
bce9b9c203 | ||
|
|
321a197d81 | ||
|
|
571c204499 | ||
|
|
533f5012a5 | ||
|
|
505b219b5f | ||
|
|
eb7ef5a8b2 | ||
|
|
ffc27b0bc6 | ||
|
|
bfe9d5d0bb | ||
|
|
28c95272e2 | ||
|
|
c026097bb6 | ||
|
|
39eee9c0af | ||
|
|
a9c28ab4f1 | ||
|
|
2452558ba3 | ||
|
|
75bf9ef0be | ||
|
|
36d2d6607c | ||
|
|
e0792394cc | ||
|
|
2302967bfb | ||
|
|
b8d573b6f4 | ||
|
|
44d1e81c73 | ||
|
|
86500b52e4 | ||
|
|
e88814ff26 | ||
|
|
63b116b188 | ||
|
|
a9bad98772 | ||
|
|
d254c583c1 | ||
|
|
8f1f4cbe96 | ||
|
|
cc1dcf69b4 | ||
|
|
e2505325ad | ||
|
|
57642ff586 | ||
|
|
8fc83b21a7 | ||
|
|
dc9e112844 | ||
|
|
0e525987f6 | ||
|
|
0c4ad4bb86 | ||
|
|
52b5a868e7 | ||
|
|
13f6dbbfd4 | ||
|
|
04948907bb | ||
|
|
c9de6e44fa | ||
|
|
aca62090fe | ||
|
|
00405b3f94 | ||
|
|
24f2b91356 | ||
|
|
e5c5e90dc5 | ||
|
|
3b0b6b14fc | ||
|
|
4fdbf987d7 | ||
|
|
5541bcfac1 | ||
|
|
b5e4e07cca | ||
|
|
e8445b9b98 | ||
|
|
8f49f44cef | ||
|
|
cf699796fc | ||
|
|
f6a1e13bc7 | ||
|
|
348fc18376 | ||
|
|
c34f00e268 | ||
|
|
195cbda7a7 | ||
|
|
0bf335cf1a | ||
|
|
22b1c29ce8 | ||
|
|
8c184481e7 | ||
|
|
91fa42baba | ||
|
|
d239f02afe | ||
|
|
4f97b4672c | ||
|
|
fc8b012aa2 | ||
|
|
a2182d593f | ||
|
|
26256f4112 | ||
|
|
534c9fb05a | ||
|
|
335f979533 | ||
|
|
1f8756227e | ||
|
|
57a55f4929 | ||
|
|
6e09494f20 | ||
|
|
f017b47e0a | ||
|
|
ee293c0ec4 | ||
|
|
2a47e75b8e | ||
|
|
7b3b189d07 | ||
|
|
c4c90d920d | ||
|
|
2c39d1cadc | ||
|
|
43fd33c0aa | ||
|
|
c0d0cd8f5e | ||
|
|
1ceef03bb8 | ||
|
|
b65f777a19 | ||
|
|
8f4a705d09 | ||
|
|
ab07560c1a | ||
|
|
8b8a3f6819 | ||
|
|
a621a22a43 | ||
|
|
64b3519252 | ||
|
|
2c50f37fae | ||
|
|
6d6a320bb9 | ||
|
|
574229dfcc | ||
|
|
e381138e61 | ||
|
|
2a9125b267 | ||
|
|
c9a252729b | ||
|
|
590b81184d | ||
|
|
b463df5a1d | ||
|
|
7b1373053d | ||
|
|
f8f5f8d4d4 | ||
|
|
e2c61e7231 | ||
|
|
669b39d874 | ||
|
|
137a2794bc | ||
|
|
41d8e84593 | ||
|
|
42b7db6507 | ||
|
|
ace0dcaf06 | ||
|
|
da846d27f6 | ||
|
|
922a55b069 | ||
|
|
ec1f57660d | ||
|
|
6b7adfea03 | ||
|
|
a164d8d9d5 | ||
|
|
624fb69d88 | ||
|
|
fd1fe8d68c | ||
|
|
6894d1feeb | ||
|
|
b5f9be5763 | ||
|
|
5f148dad80 | ||
|
|
47423ec5d5 | ||
|
|
a21766f0b0 | ||
|
|
fd8c164fda | ||
|
|
ecdec20d1d | ||
|
|
fa10395235 | ||
|
|
1f1e8ca1b6 | ||
|
|
9c413572af | ||
|
|
b298a3ed1a | ||
|
|
fa87574e90 | ||
|
|
56e67bd7c9 | ||
|
|
6aa1709ae4 | ||
|
|
9a994ab364 | ||
|
|
fb57ec1076 | ||
|
|
f64b76561a | ||
|
|
9d12760b81 | ||
|
|
2baeb67f72 | ||
|
|
abe2db4d84 | ||
|
|
6a1ff34f6f | ||
|
|
2938e2f8cf | ||
|
|
a0d9f8144c | ||
|
|
fa1224ae63 | ||
|
|
b9636aad73 | ||
|
|
7aa65671fc | ||
|
|
2a8d9e6e9e | ||
|
|
37ed69347d | ||
|
|
49e0ad054c | ||
|
|
cda7a2d22d | ||
|
|
633cdf90b7 | ||
|
|
21a25db4f2 | ||
|
|
9625081f13 | ||
|
|
a31b08468b | ||
|
|
22aa4b575e | ||
|
|
191578bafa | ||
|
|
77d41040a0 | ||
|
|
ad2d63426c | ||
|
|
6060df876a | ||
|
|
4910994c2a | ||
|
|
5289218403 | ||
|
|
f3a1f0fa5d | ||
|
|
fce0a1d29d | ||
|
|
dd8209b20d | ||
|
|
fc6f20b6e5 | ||
|
|
be9e3d81e2 | ||
|
|
afc9dcd869 | ||
|
|
831f10b62c | ||
|
|
ab805c5f52 | ||
|
|
1c0562be2a | ||
|
|
f90ff23884 | ||
|
|
990c9de07c | ||
|
|
ec9a780dec | ||
|
|
a205144aa9 | ||
|
|
b3f4327ce8 | ||
|
|
ea7bdf5a6b | ||
|
|
85cfa28d47 | ||
|
|
5654166596 | ||
|
|
0d8057c7c5 | ||
|
|
58395e84b5 | ||
|
|
aa586e7eb0 | ||
|
|
557ec4cc89 | ||
|
|
7c1066f317 | ||
|
|
70c6d34d81 | ||
|
|
070324a67b | ||
|
|
ad043c8378 | ||
|
|
4554cdd54e | ||
|
|
f94311a4a3 | ||
|
|
624332bd6c | ||
|
|
a47fb6e40a | ||
|
|
39ab591679 | ||
|
|
93e5849b8b | ||
|
|
338c11f6d1 | ||
|
|
e5436802b6 | ||
|
|
f8173c07c2 | ||
|
|
017821a01d | ||
|
|
bfb240ee11 | ||
|
|
b84d0e406b | ||
|
|
7066d2cb5d | ||
|
|
d164f0b58c | ||
|
|
b827ddf22f | ||
|
|
60100a337c | ||
|
|
e52f481fcd | ||
|
|
e31104bbde | ||
|
|
cd03c543de | ||
|
|
20361e462d | ||
|
|
62b76fe25d | ||
|
|
8ba3141c1a | ||
|
|
462b25c3a9 | ||
|
|
44518097c5 | ||
|
|
9a485d8bbb | ||
|
|
485f6c62ee | ||
|
|
14b98ab49a | ||
|
|
ceaacc7890 | ||
|
|
29bb3de2a4 | ||
|
|
41824a0b39 | ||
|
|
b7f23aeda5 | ||
|
|
1c2549dce6 | ||
|
|
ced8dee0e9 | ||
|
|
3e17f8d27d | ||
|
|
238a4fbc88 | ||
|
|
5da7ed6dd5 | ||
|
|
425346e8c0 | ||
|
|
36fdd5107a | ||
|
|
29cbf6d42a | ||
|
|
c04e476a7b | ||
|
|
e3c4cded7b | ||
|
|
ff84936aaf | ||
|
|
49f291cb02 | ||
|
|
8153f22236 | ||
|
|
3a0d6097dc | ||
|
|
ee0d9051e2 | ||
|
|
686eb92557 | ||
|
|
5a0dd2206e | ||
|
|
cad8f1826f | ||
|
|
1a73d10f2b | ||
|
|
b7672a5155 | ||
|
|
cdf3d031d8 | ||
|
|
f51feceb01 | ||
|
|
153ce51475 | ||
|
|
8c81b1760f | ||
|
|
dc4e06c6af | ||
|
|
38f6303702 | ||
|
|
b6353524a0 | ||
|
|
2e8d524b19 | ||
|
|
75afa63a79 | ||
|
|
3cd89c71cd | ||
|
|
7e376ff3c6 | ||
|
|
8cc11279d7 | ||
|
|
9a01d323aa | ||
|
|
a84470c124 | ||
|
|
87944cd866 | ||
|
|
ff97e1cea9 | ||
|
|
ff38226b01 | ||
|
|
e934478581 | ||
|
|
39616479ba | ||
|
|
38c5f58be7 | ||
|
|
0fe065ba77 | ||
|
|
4d601d34d0 | ||
|
|
39e22851cd | ||
|
|
d2cf140965 | ||
|
|
b1e2afccb5 | ||
|
|
a1d586cfc5 | ||
|
|
056f99228f | ||
|
|
88bdb7a8b9 | ||
|
|
9e61c7db7d | ||
|
|
572ac40df0 | ||
|
|
276aa903db | ||
|
|
8df4c48be2 | ||
|
|
a62d3812f6 | ||
|
|
2bd835f008 | ||
|
|
e7cf4fd3f2 | ||
|
|
320b0f907b | ||
|
|
7650f63921 | ||
|
|
419195e608 | ||
|
|
a616b79cba | ||
|
|
183eca867e | ||
|
|
7dbd79304d | ||
|
|
6e20d4deec | ||
|
|
068afcacae | ||
|
|
d2d73b5043 | ||
|
|
3391530809 | ||
|
|
4d96bfe089 | ||
|
|
9d37feab72 | ||
|
|
feb8b91075 | ||
|
|
fbe6c72c46 | ||
|
|
04a898dd44 | ||
|
|
8a05e00960 | ||
|
|
a690dbefe5 | ||
|
|
c366433034 | ||
|
|
8be1487429 | ||
|
|
7c62ffa9cd | ||
|
|
10c71ea2f2 | ||
|
|
bb98d95186 | ||
|
|
5098171326 | ||
|
|
e9c071aabc | ||
|
|
ed7b530513 | ||
|
|
65feaf9a4a | ||
|
|
558d1edd39 | ||
|
|
492dd24897 | ||
|
|
710134b4a6 | ||
|
|
c253404622 | ||
|
|
94a88c5c19 | ||
|
|
8ac926d3e2 | ||
|
|
1dcad35f21 | ||
|
|
6df81c5fc7 | ||
|
|
6c0cec151e | ||
|
|
22b2fc0c9f | ||
|
|
48596fe2c7 | ||
|
|
7fcc915fc4 | ||
|
|
7c4e5dbb09 | ||
|
|
4b12826e99 | ||
|
|
fab11884cc | ||
|
|
800ccdcc1d | ||
|
|
0d16f0de42 | ||
|
|
d191510b42 | ||
|
|
536ab732cd | ||
|
|
e100e3ec58 | ||
|
|
e6a560c49c | ||
|
|
f1636cab67 | ||
|
|
15a60b8640 | ||
|
|
86395bc6dc | ||
|
|
a8345c25f0 | ||
|
|
017d99de4c | ||
|
|
bb020202aa | ||
|
|
e111863ee2 | ||
|
|
d940851bdf | ||
|
|
868c22b4cf | ||
|
|
a8755cef36 | ||
|
|
1629c46177 | ||
|
|
3dfd560470 | ||
|
|
f745c84574 | ||
|
|
502a6086d6 | ||
|
|
1050b9d19b | ||
|
|
7954c1fced | ||
|
|
5454bed997 | ||
|
|
c361b184d9 | ||
|
|
4b1c847863 | ||
|
|
1162c1be5f | ||
|
|
b55d69c36b | ||
|
|
0af1dc35a4 | ||
|
|
ef27fe4e0e | ||
|
|
614c68280f | ||
|
|
bfbdd3f2fb | ||
|
|
157ad173ec | ||
|
|
dfbe43fe16 | ||
|
|
3dc42d2525 | ||
|
|
919d527aa7 | ||
|
|
45991a69ff | ||
|
|
a134e568f2 | ||
|
|
3af23f2d3f | ||
|
|
7572ee4122 | ||
|
|
41f3415b4a | ||
|
|
9dbd7269cb | ||
|
|
dd3d2311a8 | ||
|
|
b28e71730b | ||
|
|
5e91bc5697 | ||
|
|
ef209999f7 | ||
|
|
d364505652 | ||
|
|
30d2a1ae2a |
2
.idea/artifacts/kotlin_plugin_jar.xml
generated
2
.idea/artifacts/kotlin_plugin_jar.xml
generated
@@ -17,7 +17,7 @@
|
||||
<element id="module-output" name="kotlin.core.descriptors.jvm.main" />
|
||||
<element id="module-output" name="kotlin.core.descriptors.main" />
|
||||
<element id="module-output" name="kotlin.core.deserialization.main" />
|
||||
<element id="module-output" name="kotlin.eval4j.main" />
|
||||
<element id="module-output" name="kotlin.idea.eval4j.main" />
|
||||
<element id="module-output" name="kotlin.idea.fir-view.main" />
|
||||
<element id="module-output" name="kotlin.compiler.frontend.java.main" />
|
||||
<element id="module-output" name="kotlin.compiler.frontend.script.main" />
|
||||
|
||||
7
.idea/dictionaries/NK.xml
generated
Normal file
7
.idea/dictionaries/NK.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="NK">
|
||||
<words>
|
||||
<w>typealias</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
2
.idea/inspectionProfiles/idea_default.xml
generated
2
.idea/inspectionProfiles/idea_default.xml
generated
@@ -121,6 +121,8 @@
|
||||
<Problem reference="com.intellij.openapi.diagnostic.LoggerKt#debugOrInfoIfTestMode" reason="Absent in 182." />
|
||||
<Problem reference="com.intellij.psi.search.PsiSearchHelper#getInstance" reason="Absent in 181. Use psiSearchHelperInstance() instead." />
|
||||
<Problem reference="com.intellij.psi.search.PsiSearchHelper.SERVICE" reason="Deprecated since 182. Use psiSearchHelperInstance() instead." />
|
||||
<Problem reference="org.jetbrains.kotlin.idea.reporter.ITNReporterCompat#submit" reason="parentComponent is nullable in AS" />
|
||||
<Problem reference="com.intellij.diagnostic.ITNReporter#submit" reason="parentComponent is nullable in AS" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
|
||||
1
.idea/inspectionProfiles/profiles_settings.xml
generated
1
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -1,7 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="idea.default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
19
.idea/runConfigurations/IDEA__Not_Internal_.xml
generated
Normal file
19
.idea/runConfigurations/IDEA__Not_Internal_.xml
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="IDEA (Not Internal)" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="-Pidea.is.internal=false" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runIde" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
</configuration>
|
||||
</component>
|
||||
7841
ChangeLog.md
7841
ChangeLog.md
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,8 @@ sourceSets {
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
publish()
|
||||
|
||||
runtimeJar()
|
||||
sourcesJar()
|
||||
javadocJar()
|
||||
@@ -39,5 +41,3 @@ javadocJar()
|
||||
testsJar()
|
||||
|
||||
projectTest()
|
||||
|
||||
publish()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ import org.gradle.kotlin.dsl.*
|
||||
buildscript {
|
||||
extra["defaultSnapshotVersion"] = "1.3-SNAPSHOT"
|
||||
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.3.30-dev-1945", onlySuccessBootstrap = false))
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.3.30-eap-28", projectExtId = "Kotlin_1330_Compiler", onlySuccessBootstrap = false))
|
||||
|
||||
repositories.withRedirector(project) {
|
||||
bootstrapKotlinRepo?.let(::maven)
|
||||
@@ -531,7 +531,7 @@ tasks {
|
||||
":idea:idea-gradle-native:test",
|
||||
":idea:idea-maven:test",
|
||||
":j2k:test",
|
||||
":eval4j:test")
|
||||
":idea:eval4j:test")
|
||||
}
|
||||
|
||||
create("idea-plugin-tests") {
|
||||
|
||||
8
buildSrc/gradle.properties.as35
Normal file
8
buildSrc/gradle.properties.as35
Normal file
@@ -0,0 +1,8 @@
|
||||
org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m -Dfile.encoding=UTF-8
|
||||
|
||||
cacheRedirectorEnabled=true
|
||||
|
||||
#buildSrc.kotlin.repo=https://jcenter.bintray.com
|
||||
#buildSrc.kotlin.version=1.1.50
|
||||
|
||||
intellijUltimateEnabled=false
|
||||
286
buildSrc/prepare-deps/intellij-sdk/build.gradle.kts.as35
Normal file
286
buildSrc/prepare-deps/intellij-sdk/build.gradle.kts.as35
Normal file
@@ -0,0 +1,286 @@
|
||||
@file:Suppress("PropertyName")
|
||||
|
||||
import org.gradle.api.publish.ivy.internal.artifact.FileBasedIvyArtifact
|
||||
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyConfiguration
|
||||
import org.gradle.api.publish.ivy.internal.publication.DefaultIvyPublicationIdentity
|
||||
import org.gradle.api.publish.ivy.internal.publisher.IvyDescriptorFileGenerator
|
||||
import java.io.File
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
val cacheRedirectorEnabled = findProperty("cacheRedirectorEnabled")?.toString()?.toBoolean() == true
|
||||
|
||||
val intellijUltimateEnabled: Boolean by rootProject.extra
|
||||
val intellijReleaseType: String by rootProject.extra
|
||||
val intellijVersion = rootProject.extra["versions.intellijSdk"] as String
|
||||
val asmVersion = rootProject.findProperty("versions.jar.asm-all") as String?
|
||||
val androidStudioRelease = rootProject.findProperty("versions.androidStudioRelease") as String?
|
||||
val androidStudioBuild = rootProject.findProperty("versions.androidStudioBuild") as String?
|
||||
val intellijSeparateSdks: Boolean by rootProject.extra
|
||||
val installIntellijCommunity = !intellijUltimateEnabled || intellijSeparateSdks
|
||||
val installIntellijUltimate = intellijUltimateEnabled
|
||||
|
||||
val intellijVersionDelimiterIndex = intellijVersion.indexOfAny(charArrayOf('.', '-'))
|
||||
if (intellijVersionDelimiterIndex == -1) {
|
||||
error("Invalid IDEA version $intellijVersion")
|
||||
}
|
||||
|
||||
val platformBaseVersion = intellijVersion.substring(0, intellijVersionDelimiterIndex)
|
||||
|
||||
logger.info("intellijUltimateEnabled: $intellijUltimateEnabled")
|
||||
|
||||
logger.info("intellijVersion: $intellijVersion")
|
||||
logger.info("androidStudioRelease: $androidStudioRelease")
|
||||
logger.info("androidStudioBuild: $androidStudioBuild")
|
||||
|
||||
logger.info("intellijSeparateSdks: $intellijSeparateSdks")
|
||||
logger.info("installIntellijCommunity: $installIntellijCommunity")
|
||||
logger.info("installIntellijUltimate: $installIntellijUltimate")
|
||||
|
||||
val studioOs = "linux"
|
||||
|
||||
repositories {
|
||||
if (androidStudioRelease != null) {
|
||||
ivy {
|
||||
if (cacheRedirectorEnabled) {
|
||||
artifactPattern("https://cache-redirector.jetbrains.com/dl.google.com/dl/android/studio/ide-zips/$androidStudioRelease/[artifact]-[revision]-$studioOs.zip")
|
||||
}
|
||||
|
||||
artifactPattern("https://dl.google.com/dl/android/studio/ide-zips/$androidStudioRelease/[artifact]-[revision]-$studioOs.zip")
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
|
||||
ivy {
|
||||
artifactPattern("https://dl.bintray.com/kotlin/as/[artifact]-[revision].zip")
|
||||
credentials {
|
||||
username = System.getenv("AS_BINTRAY_USER_NAME")
|
||||
password = System.getenv("AS_BINTRAY_API_KEY")
|
||||
}
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cacheRedirectorEnabled) {
|
||||
maven("https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/$intellijReleaseType")
|
||||
maven("https://cache-redirector.jetbrains.com/plugins.jetbrains.com/maven")
|
||||
maven("https://cache-redirector.jetbrains.com/jetbrains.bintray.com/intellij-third-party-dependencies/")
|
||||
}
|
||||
|
||||
maven("https://www.jetbrains.com/intellij-repository/$intellijReleaseType")
|
||||
maven("https://plugins.jetbrains.com/maven")
|
||||
maven("https://jetbrains.bintray.com/intellij-third-party-dependencies/")
|
||||
}
|
||||
|
||||
val intellij by configurations.creating
|
||||
val intellijUltimate by configurations.creating
|
||||
val sources by configurations.creating
|
||||
val `jps-standalone` by configurations.creating
|
||||
val `jps-build-test` by configurations.creating
|
||||
val `intellij-core` by configurations.creating
|
||||
val `plugins-NodeJS` by configurations.creating
|
||||
|
||||
val customDepsRepoDir = File(buildDir, "repo")
|
||||
val customDepsOrg: String by rootProject.extra
|
||||
val customDepsRevision = intellijVersion
|
||||
val customDepsRepoModulesDir = File(customDepsRepoDir, "$customDepsOrg/$customDepsRevision")
|
||||
val repoDir = customDepsRepoModulesDir
|
||||
|
||||
dependencies {
|
||||
if (androidStudioRelease != null) {
|
||||
intellij("google:android-studio-ide:$androidStudioBuild")
|
||||
} else {
|
||||
if (installIntellijCommunity) {
|
||||
intellij("com.jetbrains.intellij.idea:ideaIC:$intellijVersion")
|
||||
}
|
||||
if (installIntellijUltimate) {
|
||||
intellijUltimate("com.jetbrains.intellij.idea:ideaIU:$intellijVersion")
|
||||
}
|
||||
}
|
||||
|
||||
if (asmVersion != null) {
|
||||
sources("org.jetbrains.intellij.deps:asm-all:$asmVersion:sources@jar")
|
||||
}
|
||||
|
||||
sources("com.jetbrains.intellij.idea:ideaIC:$intellijVersion:sources@jar")
|
||||
`jps-standalone`("com.jetbrains.intellij.idea:jps-standalone:$intellijVersion")
|
||||
`jps-build-test`("com.jetbrains.intellij.idea:jps-build-test:$intellijVersion")
|
||||
`intellij-core`("com.jetbrains.intellij.idea:intellij-core:$intellijVersion")
|
||||
if (intellijUltimateEnabled) {
|
||||
`plugins-NodeJS`("com.jetbrains.plugins:NodeJS:${rootProject.extra["versions.idea.NodeJS"]}@zip")
|
||||
}
|
||||
}
|
||||
|
||||
fun Task.configureExtractFromConfigurationTask(sourceConfig: Configuration,
|
||||
pathRemap: (String) -> String = { it },
|
||||
extractor: (Configuration) -> Any) {
|
||||
dependsOn(sourceConfig)
|
||||
inputs.files(sourceConfig)
|
||||
val targetDir = File(repoDir, sourceConfig.name)
|
||||
outputs.dirs(targetDir)
|
||||
doFirst {
|
||||
project.copy {
|
||||
from(extractor(sourceConfig))
|
||||
into(targetDir)
|
||||
eachFile {
|
||||
path = pathRemap(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removePathPrefix(path: String): String {
|
||||
if (androidStudioRelease == null) return path
|
||||
val slashes = if (studioOs == "mac") 2 else 1
|
||||
var result = path
|
||||
repeat(slashes) {
|
||||
result = result.substringAfter('/')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
val unzipIntellijSdk by tasks.creating {
|
||||
configureExtractFromConfigurationTask(intellij, pathRemap = { removePathPrefix(it) }) {
|
||||
zipTree(it.singleFile).matching {
|
||||
exclude("**/plugins/Kotlin/**")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val unzipIntellijUltimateSdk by tasks.creating {
|
||||
configureExtractFromConfigurationTask(intellijUltimate) {
|
||||
zipTree(it.singleFile).matching {
|
||||
exclude("plugins/Kotlin/**")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val unzipIntellijCore by tasks.creating { configureExtractFromConfigurationTask(`intellij-core`) { zipTree(it.singleFile) } }
|
||||
|
||||
val unzipJpsStandalone by tasks.creating { configureExtractFromConfigurationTask(`jps-standalone`) { zipTree(it.singleFile) } }
|
||||
|
||||
val mergeSources by tasks.creating(Jar::class.java) {
|
||||
dependsOn(sources)
|
||||
from(provider { sources.map(::zipTree) })
|
||||
destinationDir = File(repoDir, sources.name)
|
||||
baseName = "intellij"
|
||||
classifier = "sources"
|
||||
version = intellijVersion
|
||||
}
|
||||
|
||||
val copyJpsBuildTest by tasks.creating { configureExtractFromConfigurationTask(`jps-build-test`) { it.singleFile } }
|
||||
|
||||
val unzipNodeJSPlugin by tasks.creating { configureExtractFromConfigurationTask(`plugins-NodeJS`) { zipTree(it.singleFile) } }
|
||||
|
||||
fun writeIvyXml(moduleName: String, fileName: String, jarFiles: FileCollection, baseDir: File, vararg sourcesJar: File) {
|
||||
with(IvyDescriptorFileGenerator(DefaultIvyPublicationIdentity(customDepsOrg, moduleName, intellijVersion))) {
|
||||
addConfiguration(DefaultIvyConfiguration("default"))
|
||||
addConfiguration(DefaultIvyConfiguration("sources"))
|
||||
jarFiles.asFileTree.files.forEach { jarFile ->
|
||||
if (jarFile.isFile && jarFile.extension == "jar") {
|
||||
val relativeName = jarFile.toRelativeString(baseDir).removeSuffix(".jar")
|
||||
addArtifact(
|
||||
FileBasedIvyArtifact(jarFile, DefaultIvyPublicationIdentity(customDepsOrg, relativeName, intellijVersion)).also {
|
||||
it.conf = "default"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
sourcesJar.forEach {
|
||||
val sourcesArtifactName = it.name.substringBeforeLast("-").substringBeforeLast("-")
|
||||
addArtifact(
|
||||
FileBasedIvyArtifact(it, DefaultIvyPublicationIdentity(customDepsOrg, sourcesArtifactName, intellijVersion)).also { artifact ->
|
||||
artifact.conf = "sources"
|
||||
artifact.classifier = "sources"
|
||||
}
|
||||
)
|
||||
}
|
||||
writeTo(File(customDepsRepoModulesDir, "$fileName.ivy.xml"))
|
||||
}
|
||||
}
|
||||
|
||||
val prepareIvyXmls by tasks.creating {
|
||||
dependsOn(unzipIntellijCore, unzipJpsStandalone, mergeSources, copyJpsBuildTest)
|
||||
|
||||
val intellijSdkDir = File(repoDir, intellij.name)
|
||||
val intellijUltimateSdkDir = File(repoDir, intellijUltimate.name)
|
||||
|
||||
if (installIntellijCommunity) {
|
||||
dependsOn(unzipIntellijSdk)
|
||||
inputs.dir(intellijSdkDir)
|
||||
outputs.file(File(repoDir, "${intellij.name}.ivy.xml"))
|
||||
}
|
||||
|
||||
if (installIntellijUltimate) {
|
||||
dependsOn(unzipIntellijUltimateSdk)
|
||||
inputs.dir(intellijUltimateSdkDir)
|
||||
outputs.file(File(repoDir, "${intellijUltimate.name}.ivy.xml"))
|
||||
}
|
||||
|
||||
val flatDeps = listOf(`intellij-core`, `jps-standalone`, `jps-build-test`)
|
||||
flatDeps.forEach {
|
||||
inputs.dir(File(repoDir, it.name))
|
||||
outputs.file(File(repoDir, "${it.name}.ivy.xml"))
|
||||
}
|
||||
inputs.dir(File(repoDir, sources.name))
|
||||
|
||||
if (intellijUltimateEnabled) {
|
||||
dependsOn(unzipNodeJSPlugin)
|
||||
inputs.dir(File(repoDir, `plugins-NodeJS`.name))
|
||||
outputs.file(File(repoDir, "${`plugins-NodeJS`.name}.ivy.xml"))
|
||||
}
|
||||
|
||||
doFirst {
|
||||
val sources = File(repoDir, sources.name).listFiles()
|
||||
|
||||
if (installIntellijCommunity) {
|
||||
val libDir = File(intellijSdkDir, "lib")
|
||||
writeIvyXml(intellij.name,
|
||||
intellij.name,
|
||||
fileTree(libDir).filter {
|
||||
it.parentFile == libDir && !it.name.startsWith("kotlin-")
|
||||
},
|
||||
libDir,
|
||||
*sources)
|
||||
|
||||
File(intellijSdkDir, "plugins").listFiles { file: File -> file.isDirectory }.forEach {
|
||||
writeIvyXml(it.name, "intellij.plugin.${it.name}", files("$it/lib/"), File(it, "lib"), *sources)
|
||||
}
|
||||
}
|
||||
|
||||
if (installIntellijUltimate) {
|
||||
val libDir = File(intellijUltimateSdkDir, "lib")
|
||||
writeIvyXml(intellij.name, // important! the module name should be "intellij"
|
||||
intellijUltimate.name,
|
||||
fileTree(libDir).filter {
|
||||
it.parentFile == libDir && !it.name.startsWith("kotlin-")
|
||||
},
|
||||
libDir,
|
||||
*sources)
|
||||
|
||||
File(intellijUltimateSdkDir, "plugins").listFiles { it: File -> it.isDirectory }.forEach {
|
||||
writeIvyXml(it.name, "intellijUltimate.plugin.${it.name}", files("$it/lib/"), File(it, "lib"), *sources)
|
||||
}
|
||||
}
|
||||
|
||||
flatDeps.forEach {
|
||||
writeIvyXml(it.name, it.name, files("$repoDir/${it.name}"), File(repoDir, it.name), *sources)
|
||||
}
|
||||
|
||||
if (intellijUltimateEnabled) {
|
||||
val nodeJsBaseDir = "${`plugins-NodeJS`.name}/NodeJS/lib"
|
||||
writeIvyXml("NodeJS", `plugins-NodeJS`.name, files("$repoDir/$nodeJsBaseDir"), File(repoDir, nodeJsBaseDir), *sources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val build by tasks.creating {
|
||||
dependsOn(prepareIvyXmls)
|
||||
}
|
||||
|
||||
val clean by tasks.creating(Delete::class) {
|
||||
delete(customDepsRepoModulesDir)
|
||||
delete(buildDir)
|
||||
}
|
||||
@@ -35,14 +35,26 @@ fun Project.testsJar(body: Jar.() -> Unit = {}): Jar {
|
||||
}
|
||||
}
|
||||
|
||||
var Project.artifactsRemovedDiagnosticFlag: Boolean
|
||||
get() = extra.has("artifactsRemovedDiagnosticFlag") && extra["artifactsRemovedDiagnosticFlag"] == true
|
||||
set(value) {
|
||||
extra["artifactsRemovedDiagnosticFlag"] = value
|
||||
}
|
||||
|
||||
fun Project.removeArtifacts(configuration: Configuration, task: Task) {
|
||||
configuration.artifacts.removeAll { artifact ->
|
||||
artifact.file in task.outputs.files
|
||||
}
|
||||
|
||||
artifactsRemovedDiagnosticFlag = true
|
||||
}
|
||||
|
||||
fun Project.noDefaultJar() {
|
||||
tasks.findByName("jar")?.let { defaultJarTask ->
|
||||
defaultJarTask.enabled = false
|
||||
defaultJarTask.actions = emptyList()
|
||||
configurations.forEach { cfg ->
|
||||
cfg.artifacts.removeAll { artifact ->
|
||||
artifact.file in defaultJarTask.outputs.files
|
||||
}
|
||||
removeArtifacts(cfg, defaultJarTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,8 +70,7 @@ fun Project.runtimeJarArtifactBy(task: Task, artifactRef: Any, body: Configurabl
|
||||
fun <T : Jar> Project.runtimeJar(task: T, body: T.() -> Unit = {}): T {
|
||||
extra["runtimeJarTask"] = task
|
||||
tasks.findByName("jar")?.let { defaultJarTask ->
|
||||
configurations.getOrCreate("archives")
|
||||
.artifacts.removeAll { (it as? ArchivePublishArtifact)?.archiveTask?.let { it == defaultJarTask } ?: false }
|
||||
removeArtifacts(configurations.getOrCreate("archives"), defaultJarTask)
|
||||
}
|
||||
return task.apply {
|
||||
setupPublicJar(project.the<BasePluginConvention>().archivesBaseName)
|
||||
@@ -109,6 +120,10 @@ fun Project.standardPublicJars() {
|
||||
fun Project.publish(body: Upload.() -> Unit = {}): Upload {
|
||||
apply<plugins.PublishedKotlinModule>()
|
||||
|
||||
if (artifactsRemovedDiagnosticFlag) {
|
||||
error("`publish()` should be called before removing artifacts typically done in `noDefaultJar()` of `runtimeJar()` calls")
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
if (configurations.findByName("classes-dirs") != null)
|
||||
throw GradleException("classesDirsArtifact() is incompatible with publish(), see sources comments for details")
|
||||
|
||||
@@ -137,7 +137,6 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
|
||||
"-XX:ReservedCodeCacheSize=240m",
|
||||
"-XX:+HeapDumpOnOutOfMemoryError",
|
||||
"-ea",
|
||||
"-Didea.is.internal=true",
|
||||
"-Didea.debug.mode=true",
|
||||
"-Didea.system.path=$ideaSandboxDir",
|
||||
"-Didea.config.path=$ideaSandboxConfigDir",
|
||||
@@ -155,6 +154,12 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
|
||||
jvmArgs("-Didea.ProcessCanceledException=disabled")
|
||||
}
|
||||
|
||||
jvmArgs("-Didea.is.internal=${project.findProperty("idea.is.internal") ?: true}")
|
||||
|
||||
project.findProperty("idea.args")?.let { arguments ->
|
||||
jvmArgs(arguments.toString().split(" "))
|
||||
}
|
||||
|
||||
args()
|
||||
|
||||
doFirst {
|
||||
|
||||
@@ -244,7 +244,7 @@ private fun parseSourceRoots(project: Project): List<PSourceRoot> {
|
||||
|
||||
for (sourceSet in project.sourceSets) {
|
||||
val kotlinCompileTask = kotlinTasksBySourceSet[sourceSet.name]
|
||||
val kind = if (sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME) Kind.TEST else Kind.PRODUCTION
|
||||
val kind = if (sourceSet.isTestSourceSet) Kind.TEST else Kind.PRODUCTION
|
||||
|
||||
fun Any.getKotlin(): SourceDirectorySet {
|
||||
val kotlinMethod = javaClass.getMethod("getKotlin")
|
||||
@@ -298,9 +298,8 @@ private fun parseSourceRoots(project: Project): List<PSourceRoot> {
|
||||
|
||||
private fun parseResourceRootsProcessedByProcessResourcesTask(project: Project, sourceSet: SourceSet): List<PSourceRoot> {
|
||||
val isMainSourceSet = sourceSet.name == SourceSet.MAIN_SOURCE_SET_NAME
|
||||
val isTestSourceSet = sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME
|
||||
|
||||
val resourceRootKind = if (isTestSourceSet) PSourceRoot.Kind.TEST_RESOURCES else PSourceRoot.Kind.RESOURCES
|
||||
val resourceRootKind = if (sourceSet.isTestSourceSet) PSourceRoot.Kind.TEST_RESOURCES else PSourceRoot.Kind.RESOURCES
|
||||
val taskNameBase = "processResources"
|
||||
val taskName = if (isMainSourceSet) taskNameBase else sourceSet.name + taskNameBase.capitalize()
|
||||
val task = project.tasks.findByName(taskName) as? ProcessResources ?: return emptyList()
|
||||
@@ -319,6 +318,11 @@ private fun parseResourceRootsProcessedByProcessResourcesTask(project: Project,
|
||||
return roots.map { PSourceRoot(it, resourceRootKind, null) }
|
||||
}
|
||||
|
||||
private val SourceSet.isTestSourceSet: Boolean
|
||||
get() = name == SourceSet.TEST_SOURCE_SET_NAME
|
||||
|| name.endsWith("Test")
|
||||
|| name.endsWith("Tests")
|
||||
|
||||
private fun getKotlinOptions(kotlinCompileTask: Any): PSourceRootKotlinOptions? {
|
||||
val compileArguments = kotlinCompileTask.invokeInternal("getSerializedCompilerArguments") as List<String>
|
||||
fun parseBoolean(name: String) = compileArguments.contains("-$name")
|
||||
|
||||
@@ -244,6 +244,10 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
annotationTargetMaps.put(JvmTarget.JVM_1_6, jvm6);
|
||||
annotationTargetMaps.put(JvmTarget.JVM_1_8, jvm8);
|
||||
annotationTargetMaps.put(JvmTarget.JVM_9, jvm8);
|
||||
annotationTargetMaps.put(JvmTarget.JVM_10, jvm8);
|
||||
annotationTargetMaps.put(JvmTarget.JVM_11, jvm8);
|
||||
annotationTargetMaps.put(JvmTarget.JVM_12, jvm8);
|
||||
}
|
||||
|
||||
private void generateTargetAnnotation(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,9 @@ enum class ValueKind {
|
||||
DEFAULT_MASK,
|
||||
METHOD_HANDLE_IN_DEFAULT,
|
||||
CAPTURED,
|
||||
DEFAULT_LAMBDA_CAPTURED_PARAMETER
|
||||
DEFAULT_LAMBDA_CAPTURED_PARAMETER,
|
||||
NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND,
|
||||
NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER
|
||||
}
|
||||
|
||||
interface CallGenerator {
|
||||
|
||||
@@ -100,7 +100,8 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isBoxedLocalCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
|
||||
@@ -2900,7 +2901,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
while (cur != null) {
|
||||
ClassDescriptor thisDescriptor = cur.getThisDescriptor();
|
||||
|
||||
if (!isSuper && thisDescriptor == thisOrOuterClass) {
|
||||
// We use equals on type constructors (instead of reference equality on classes) to support the case where default parameter
|
||||
// values of actual functions loaded from the expected function refer to the expected class.
|
||||
if (!isSuper && thisDescriptor.getTypeConstructor().equals(thisOrOuterClass.getTypeConstructor())) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3142,7 +3145,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull VariableDescriptor target,
|
||||
@Nullable StackValue receiverValue
|
||||
) {
|
||||
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, variableDescriptor);
|
||||
if (classDescriptor == null) {
|
||||
throw new IllegalStateException(
|
||||
"Property reference class was not found: " + variableDescriptor +
|
||||
"\nTried to generate: " + element.getText());
|
||||
}
|
||||
|
||||
ClassBuilder classBuilder = state.getFactory().newVisitor(
|
||||
JvmDeclarationOriginKt.OtherOrigin(element),
|
||||
@@ -4858,6 +4866,10 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
KtProperty subjectVariable = expression.getSubjectVariable();
|
||||
KtExpression subjectExpression = expression.getSubjectExpression();
|
||||
|
||||
if (subjectVariable == null && subjectExpression == null) {
|
||||
v.nop();
|
||||
}
|
||||
|
||||
SwitchCodegen switchCodegen = switchCodegenProvider.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, CodegenUtil.isExhaustive(bindingContext, expression, isStatement)
|
||||
);
|
||||
|
||||
@@ -21,10 +21,9 @@ import com.intellij.openapi.util.Trinity
|
||||
import gnu.trove.TObjectIntHashMap
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class FrameMap : FrameMapBase<DeclarationDescriptor>()
|
||||
open class FrameMap : FrameMapBase<DeclarationDescriptor>()
|
||||
|
||||
open class FrameMapBase<T : Any> {
|
||||
private val myVarIndex = TObjectIntHashMap<T>()
|
||||
@@ -61,7 +60,7 @@ open class FrameMapBase<T : Any> {
|
||||
currentSize -= type.size
|
||||
}
|
||||
|
||||
fun getIndex(descriptor: T): Int {
|
||||
open fun getIndex(descriptor: T): Int {
|
||||
return if (myVarIndex.contains(descriptor)) myVarIndex.get(descriptor) else -1
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||
|
||||
/**
|
||||
* This [FrameMap] subclass substitutes values declared in the expected declaration with the corresponding value in the actual declaration,
|
||||
* which is needed for the case when expected function declares parameters with default values, which refer to other parameters.
|
||||
*/
|
||||
class FrameMapWithExpectActualSupport(private val module: ModuleDescriptor) : FrameMap() {
|
||||
override fun getIndex(descriptor: DeclarationDescriptor): Int {
|
||||
val tmp = if (descriptor is ParameterDescriptor) findActualParameter(descriptor) ?: descriptor else descriptor
|
||||
return super.getIndex(tmp)
|
||||
}
|
||||
|
||||
private fun findActualParameter(parameter: ParameterDescriptor): ParameterDescriptor? {
|
||||
val container = parameter.containingDeclaration
|
||||
if (container !is CallableMemberDescriptor || !container.isExpect) return null
|
||||
|
||||
// Generation of value parameters is supported by the fact that FunctionCodegen.generateDefaultImplBody substitutes value parameters
|
||||
// of the generated actual function with the parameters of the expected declaration in the first place.
|
||||
// Generation of dispatch receiver parameters (this and outer receiver values) is supported
|
||||
// in ExpressionCodegen.generateThisOrOuterFromContext by comparing classes by type constructor equality.
|
||||
if (parameter !is ReceiverParameterDescriptor || parameter.value !is ExtensionReceiver) return null
|
||||
|
||||
val actual = with(ExpectedActualResolver) {
|
||||
container.findCompatibleActualForExpected(module).firstOrNull()
|
||||
}
|
||||
|
||||
return (actual as? CallableDescriptor)?.extensionReceiverParameter
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
@@ -125,7 +126,8 @@ public class FunctionCodegen {
|
||||
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
|
||||
function,
|
||||
v.getThisName(),
|
||||
state.getConstructorCallNormalizationMode()
|
||||
state.getConstructorCallNormalizationMode(),
|
||||
this
|
||||
);
|
||||
} else {
|
||||
strategy = new SuspendInlineFunctionGenerationStrategy(
|
||||
@@ -1215,6 +1217,10 @@ public class FunctionCodegen {
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
);
|
||||
|
||||
// Only method annotations are copied to the $default method. Parameter annotations are not copied until there are valid use cases;
|
||||
// enum constructors have two additional synthetic parameters which somewhat complicate this task
|
||||
AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations(functionDescriptor, defaultMethod.getReturnType());
|
||||
|
||||
if (!state.getClassBuilderMode().generateBodies) {
|
||||
if (this.owner instanceof MultifileClassFacadeContext)
|
||||
endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
|
||||
@@ -1360,7 +1366,7 @@ public class FunctionCodegen {
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
boolean isStatic
|
||||
) {
|
||||
FrameMap frameMap = new FrameMap();
|
||||
FrameMap frameMap = new FrameMapWithExpectActualSupport(state.getModule());
|
||||
if (!isStatic) {
|
||||
frameMap.enterTemp(OBJECT_TYPE);
|
||||
}
|
||||
@@ -1686,4 +1692,9 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CalculatedClosure getClosure() {
|
||||
return owner.closure;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.util.ArrayUtil
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
@@ -41,6 +39,7 @@ import org.jetbrains.kotlin.psi.KtTypeAlias
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClassPart
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
@@ -67,20 +66,20 @@ class MultifileClassCodegenImpl(
|
||||
) : MultifileClassCodegen {
|
||||
private val facadeClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(facadeFqName)
|
||||
|
||||
private val packageFragment = getOnlyPackageFragment(facadeFqName.parent(), files, state.module)
|
||||
private val packageFragment = getOnlyPackageFragment(files, state.module)
|
||||
|
||||
private val compiledPackageFragment = getCompiledPackageFragment(facadeFqName, state)
|
||||
|
||||
private val previouslyCompiledCallables =
|
||||
if (compiledPackageFragment == null)
|
||||
emptyList<DeserializedCallableMemberDescriptor>()
|
||||
else
|
||||
getDeserializedCallables(compiledPackageFragment)
|
||||
if (compiledPackageFragment == null)
|
||||
emptyList()
|
||||
else
|
||||
getDeserializedCallables(compiledPackageFragment)
|
||||
|
||||
private fun getDeserializedCallables(compiledPackageFragment: PackageFragmentDescriptor) =
|
||||
compiledPackageFragment.getMemberScope()
|
||||
.getContributedDescriptors(DescriptorKindFilter.CALLABLES, MemberScope.ALL_NAME_FILTER)
|
||||
.filterIsInstance<DeserializedCallableMemberDescriptor>()
|
||||
compiledPackageFragment.getMemberScope()
|
||||
.getContributedDescriptors(DescriptorKindFilter.CALLABLES, MemberScope.ALL_NAME_FILTER)
|
||||
.filterIsInstance<DeserializedCallableMemberDescriptor>()
|
||||
|
||||
private val shouldGeneratePartHierarchy =
|
||||
state.languageVersionSettings.getFlag(JvmAnalysisFlags.inheritMultifileParts)
|
||||
@@ -100,7 +99,7 @@ class MultifileClassCodegenImpl(
|
||||
|
||||
private val superClassForInheritedPart = run {
|
||||
val result = hashMapOf<String, String>()
|
||||
for (i in 1 ..partInternalNamesSorted.size - 1) {
|
||||
for (i in 1 until partInternalNamesSorted.size) {
|
||||
result[partInternalNamesSorted[i]] = partInternalNamesSorted[i - 1]
|
||||
}
|
||||
result
|
||||
@@ -115,29 +114,23 @@ class MultifileClassCodegenImpl(
|
||||
J_L_OBJECT
|
||||
|
||||
private val classBuilder = ClassBuilderOnDemand {
|
||||
val originFile = files.firstOrNull()
|
||||
|
||||
val actualPackageFragment = packageFragment
|
||||
?: compiledPackageFragment
|
||||
?: throw AssertionError("No package fragment for multifile facade $facadeFqName; files: $files")
|
||||
|
||||
val declarationOrigin = MultifileClass(originFile, actualPackageFragment)
|
||||
?: compiledPackageFragment
|
||||
?: throw AssertionError("No package fragment for multifile facade $facadeFqName; files: $files")
|
||||
|
||||
val singleSourceFile =
|
||||
if (previouslyCompiledCallables.isEmpty())
|
||||
files.singleOrNull { it.hasDeclarationsForPartClass() }
|
||||
else
|
||||
null
|
||||
if (previouslyCompiledCallables.isEmpty())
|
||||
files.singleOrNull { it.hasDeclarationsForPartClass() }
|
||||
else
|
||||
null
|
||||
|
||||
val superClassForFacade =
|
||||
if (shouldGeneratePartHierarchy)
|
||||
partInternalNamesSorted.last()
|
||||
else
|
||||
J_L_OBJECT
|
||||
val superClassForFacade = if (shouldGeneratePartHierarchy) partInternalNamesSorted.last() else J_L_OBJECT
|
||||
|
||||
state.factory.newVisitor(declarationOrigin, facadeClassType, files).apply {
|
||||
defineClass(singleSourceFile, state.classFileVersion, FACADE_CLASS_ATTRIBUTES,
|
||||
facadeClassType.internalName, null, superClassForFacade, ArrayUtil.EMPTY_STRING_ARRAY)
|
||||
state.factory.newVisitor(MultifileClass(files.firstOrNull(), actualPackageFragment), facadeClassType, files).apply {
|
||||
defineClass(
|
||||
singleSourceFile, state.classFileVersion, FACADE_CLASS_ATTRIBUTES,
|
||||
facadeClassType.internalName, null, superClassForFacade, emptyArray()
|
||||
)
|
||||
if (singleSourceFile != null) {
|
||||
visitSource(singleSourceFile.name, null)
|
||||
}
|
||||
@@ -162,7 +155,7 @@ class MultifileClassCodegenImpl(
|
||||
|
||||
generateDelegatesToPreviouslyCompiledParts()
|
||||
|
||||
if (!partInternalNamesSorted.isEmpty()) {
|
||||
if (partInternalNamesSorted.isNotEmpty()) {
|
||||
generateMultifileFacadeClass()
|
||||
}
|
||||
|
||||
@@ -175,16 +168,12 @@ class MultifileClassCodegenImpl(
|
||||
try {
|
||||
generatePart(file)
|
||||
state.afterIndependentPart()
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
val vFile = file.virtualFile
|
||||
errorHandler.reportException(e, if (vFile == null) "no file" else vFile.url)
|
||||
} catch (e: Throwable) {
|
||||
errorHandler.reportException(e, file.virtualFile?.url ?: "no file")
|
||||
DiagnosticUtils.throwIfRunningOnServer(e)
|
||||
if (ApplicationManager.getApplication().isInternal) {
|
||||
//noinspection CallToPrintStackTrace
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
@@ -205,7 +194,7 @@ class MultifileClassCodegenImpl(
|
||||
|
||||
private fun generatePart(file: KtFile) {
|
||||
val packageFragment = this.packageFragment
|
||||
?: throw AssertionError("File part $file of $facadeFqName: no package fragment")
|
||||
?: throw AssertionError("File part $file of $facadeFqName: no package fragment")
|
||||
|
||||
val partType = Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(file))
|
||||
val partContext = state.rootContext.intoMultifileClassPart(packageFragment, facadeClassType, partType, file)
|
||||
@@ -219,10 +208,7 @@ class MultifileClassCodegenImpl(
|
||||
val builder = state.factory.newVisitor(MultifileClassPart(file, packageFragment), partType, file)
|
||||
|
||||
MultifileClassPartCodegen(
|
||||
builder, file, packageFragment,
|
||||
getSuperClassForPart(partType.internalName),
|
||||
shouldGeneratePartHierarchy,
|
||||
partContext, state
|
||||
builder, file, packageFragment, getSuperClassForPart(partType.internalName), shouldGeneratePartHierarchy, partContext, state
|
||||
).generate()
|
||||
|
||||
addDelegateGenerationTasksForDeclarationsInFile(file, packageFragment, partType)
|
||||
@@ -284,14 +270,14 @@ class MultifileClassCodegenImpl(
|
||||
val partFqName = JvmFileClassUtil.getPartFqNameForDeserialized(callable)
|
||||
val partType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(partFqName)
|
||||
|
||||
addDelegateGenerationTaskIfNeeded(callable, { generateDelegateToCompiledMember(callable, compiledPackageFragment, partType) })
|
||||
addDelegateGenerationTaskIfNeeded(callable) { generateDelegateToCompiledMember(callable, compiledPackageFragment, partType) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDelegateToCompiledMember(
|
||||
member: CallableMemberDescriptor,
|
||||
compiledPackageFragment: PackageFragmentDescriptor,
|
||||
partType: Type
|
||||
member: CallableMemberDescriptor,
|
||||
compiledPackageFragment: PackageFragmentDescriptor,
|
||||
partType: Type
|
||||
) {
|
||||
val context = state.rootContext.intoMultifileClass(compiledPackageFragment, facadeClassType, partType)
|
||||
|
||||
@@ -302,7 +288,8 @@ class MultifileClassCodegenImpl(
|
||||
memberCodegen.functionCodegen.generateMethod(OtherOrigin(member), member, DelegateToCompiledMemberGenerationStrategy)
|
||||
|
||||
memberCodegen.functionCodegen.generateDefaultIfNeeded(
|
||||
context.intoFunction(member), member, OwnerKind.PACKAGE, DefaultParameterValueLoader.DEFAULT, null)
|
||||
context.intoFunction(member), member, OwnerKind.PACKAGE, DefaultParameterValueLoader.DEFAULT, null
|
||||
)
|
||||
|
||||
memberCodegen.functionCodegen.generateOverloadsWithDefaultValues(null, member, member)
|
||||
}
|
||||
@@ -310,7 +297,7 @@ class MultifileClassCodegenImpl(
|
||||
memberCodegen.propertyCodegen.generateInPackageFacade(member)
|
||||
}
|
||||
else -> {
|
||||
throw IllegalStateException("Unexpected member: " + member)
|
||||
throw IllegalStateException("Unexpected member: $member")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,7 +307,9 @@ class MultifileClassCodegenImpl(
|
||||
throw IllegalStateException("shouldn't be called")
|
||||
}
|
||||
|
||||
override fun generateBody(mv: MethodVisitor, frameMap: FrameMap, signature: JvmMethodSignature, context: MethodContext, parentCodegen: MemberCodegen<*>) {
|
||||
override fun generateBody(
|
||||
mv: MethodVisitor, frameMap: FrameMap, signature: JvmMethodSignature, context: MethodContext, parentCodegen: MemberCodegen<*>
|
||||
) {
|
||||
throw IllegalStateException("shouldn't be called")
|
||||
}
|
||||
}
|
||||
@@ -340,15 +329,29 @@ class MultifileClassCodegenImpl(
|
||||
arv.visit(null, internalName)
|
||||
}
|
||||
arv.visitEnd()
|
||||
|
||||
val kotlinPackageFqName =
|
||||
packageFragment?.fqName ?: compiledPackageFragment?.fqName
|
||||
?: error("Either source package or compiled package should not be null: $facadeClassType ($files)")
|
||||
|
||||
if (files.any { it.packageFqName != kotlinPackageFqName })
|
||||
throw UnsupportedOperationException(
|
||||
"Multi-file parts of a facade with JvmPackageName should all lie in the same Kotlin package:\n " +
|
||||
files.joinToString("\n ") { file -> "$file: package ${file.packageFqName}" }
|
||||
)
|
||||
|
||||
if (kotlinPackageFqName != JvmClassName.byInternalName(facadeClassType.internalName).packageFqName) {
|
||||
av.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, kotlinPackageFqName.asString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCodegenForDelegatesInMultifileFacade(facadeContext: FieldOwnerContext<*>): MemberCodegen<KtFile> =
|
||||
object : MemberCodegen<KtFile>(state, null, facadeContext, null, classBuilder) {
|
||||
override fun generateDeclaration() = throw UnsupportedOperationException()
|
||||
override fun generateBody() = throw UnsupportedOperationException()
|
||||
override fun generateKotlinMetadataAnnotation() = throw UnsupportedOperationException()
|
||||
}
|
||||
object : MemberCodegen<KtFile>(state, null, facadeContext, null, classBuilder) {
|
||||
override fun generateDeclaration() = throw UnsupportedOperationException()
|
||||
override fun generateBody() = throw UnsupportedOperationException()
|
||||
override fun generateKotlinMetadataAnnotation() = throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun done() {
|
||||
classBuilder.done()
|
||||
@@ -359,19 +362,12 @@ class MultifileClassCodegenImpl(
|
||||
|
||||
companion object {
|
||||
private val J_L_OBJECT = AsmTypes.OBJECT_TYPE.internalName
|
||||
private val FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER
|
||||
private const val FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER
|
||||
|
||||
private fun getOnlyPackageFragment(packageFqName: FqName, files: Collection<KtFile>, moduleDescriptor: ModuleDescriptor): PackageFragmentDescriptor? {
|
||||
val fragments = SmartList<PackageFragmentDescriptor>()
|
||||
for (file in files) {
|
||||
val fragment = moduleDescriptor.findPackageFragmentForFile(file)
|
||||
?: throw AssertionError("package fragment is null for " + file + "\n" + file.text)
|
||||
|
||||
assert(packageFqName == fragment.fqName) { "expected package fq name: " + packageFqName + ", actual: " + fragment.fqName }
|
||||
|
||||
if (!fragments.contains(fragment)) {
|
||||
fragments.add(fragment)
|
||||
}
|
||||
private fun getOnlyPackageFragment(files: Collection<KtFile>, moduleDescriptor: ModuleDescriptor): PackageFragmentDescriptor? {
|
||||
val fragments = files.mapTo(linkedSetOf()) { file ->
|
||||
moduleDescriptor.findPackageFragmentForFile(file)
|
||||
?: throw AssertionError("package fragment is null for " + file + "\n" + file.text)
|
||||
}
|
||||
if (fragments.size > 1) {
|
||||
throw IllegalStateException("More than one package fragment, files: $files | fragments: $fragments")
|
||||
@@ -383,16 +379,15 @@ class MultifileClassCodegenImpl(
|
||||
CodegenUtil.getMemberDeclarationsToGenerate(this).isNotEmpty()
|
||||
|
||||
private fun getCompiledPackageFragment(
|
||||
facadeFqName: FqName, state: GenerationState
|
||||
facadeFqName: FqName, state: GenerationState
|
||||
): IncrementalPackageFragmentProvider.IncrementalMultifileClassPackageFragment? {
|
||||
if (!IncrementalCompilation.isEnabledForJvm()) return null
|
||||
|
||||
val packageFqName = facadeFqName.parent()
|
||||
|
||||
val incrementalPackageFragment = state.module.getPackage(packageFqName).fragments.firstOrNull { fragment ->
|
||||
fragment is IncrementalPackageFragmentProvider.IncrementalPackageFragment &&
|
||||
fragment.target == state.targetId
|
||||
} as IncrementalPackageFragmentProvider.IncrementalPackageFragment?
|
||||
fragment is IncrementalPackageFragmentProvider.IncrementalPackageFragment && fragment.target == state.targetId
|
||||
} as IncrementalPackageFragmentProvider.IncrementalPackageFragment?
|
||||
|
||||
return incrementalPackageFragment?.getPackageFragmentForMultifileClass(facadeFqName)
|
||||
}
|
||||
|
||||
@@ -22,20 +22,22 @@ import org.jetbrains.kotlin.codegen.context.MultifileClassPartContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
class MultifileClassPartCodegen(
|
||||
v: ClassBuilder,
|
||||
file: KtFile,
|
||||
private val packageFragment: PackageFragmentDescriptor,
|
||||
private val superClassInternalName: String,
|
||||
private val shouldGeneratePartHierarchy: Boolean,
|
||||
partContext: MultifileClassPartContext,
|
||||
state: GenerationState
|
||||
v: ClassBuilder,
|
||||
file: KtFile,
|
||||
private val packageFragment: PackageFragmentDescriptor,
|
||||
private val superClassInternalName: String,
|
||||
private val shouldGeneratePartHierarchy: Boolean,
|
||||
partContext: MultifileClassPartContext,
|
||||
state: GenerationState
|
||||
) : MemberCodegen<KtFile>(state, null, partContext, file, v) {
|
||||
private val partType = partContext.filePartType
|
||||
private val facadeClassType = partContext.multifileClassType
|
||||
@@ -97,6 +99,11 @@ class MultifileClassPartCodegen(
|
||||
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, extraFlags) { av ->
|
||||
AsmUtil.writeAnnotationData(av, serializer, packageProto)
|
||||
av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassType.internalName)
|
||||
|
||||
val kotlinPackageFqName = element.packageFqName
|
||||
if (kotlinPackageFqName != JvmClassName.byInternalName(partType.internalName).packageFqName) {
|
||||
av.visit(METADATA_PACKAGE_NAME_FIELD_NAME, kotlinPackageFqName.asString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -726,6 +726,9 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
if (variableDescriptor instanceof ValueParameterDescriptor &&
|
||||
((ValueParameterDescriptor) variableDescriptor).isCrossinline()) {
|
||||
DeclarationDescriptor functionWithCrossinlineParameter = variableDescriptor.getContainingDeclaration();
|
||||
if (functionsStack.peek().isSuspend()) {
|
||||
bindingTrace.record(CALL_SITE_IS_SUSPEND_FOR_CROSSINLINE_LAMBDA, (ValueParameterDescriptor) variableDescriptor, true);
|
||||
}
|
||||
for (int i = functionsStack.size() - 1; i >= 0; i--) {
|
||||
Boolean alreadyPutValue = bindingTrace.getBindingContext()
|
||||
.get(CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, functionsStack.get(i));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -60,6 +60,9 @@ public class CodegenBinding {
|
||||
public static final WritableSlice<FunctionDescriptor, Boolean> CAPTURES_CROSSINLINE_LAMBDA =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ValueParameterDescriptor, Boolean> CALL_SITE_IS_SUSPEND_FOR_CROSSINLINE_LAMBDA =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ClassDescriptor, Boolean> RECURSIVE_SUSPEND_CALLABLE_REFERENCE =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
@@ -112,20 +115,12 @@ public class CodegenBinding {
|
||||
return Boolean.TRUE.equals(bindingContext.get(ENUM_ENTRY_CLASS_NEED_SUBCLASS, classDescriptor));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor anonymousClassForCallable(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull CallableDescriptor descriptor
|
||||
) {
|
||||
//noinspection ConstantConditions
|
||||
return bindingContext.get(CLASS_FOR_CALLABLE, descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type asmTypeForAnonymousClass(@NotNull BindingContext bindingContext, @NotNull KtElement expression) {
|
||||
Type result = asmTypeForAnonymousClassOrNull(bindingContext, expression);
|
||||
if (result == null) {
|
||||
throw new IllegalStateException("Type must not be null: " + expression.getText());
|
||||
throw new KotlinExceptionWithAttachments("Couldn't compute ASM type for expression")
|
||||
.withAttachment("expression.kt", PsiUtilsKt.getElementTextWithContext(expression));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -152,8 +147,7 @@ public class CodegenBinding {
|
||||
return asmTypeForAnonymousClassOrNull(bindingContext, variableDescriptor);
|
||||
}
|
||||
|
||||
throw new KotlinExceptionWithAttachments("Couldn't compute ASM type for expression")
|
||||
.withAttachment("expression.kt", PsiUtilsKt.getElementTextWithContext(expression));
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -168,7 +162,11 @@ public class CodegenBinding {
|
||||
|
||||
@Nullable
|
||||
public static Type asmTypeForAnonymousClassOrNull(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor descriptor) {
|
||||
return bindingContext.get(ASM_TYPE, anonymousClassForCallable(bindingContext, descriptor));
|
||||
ClassDescriptor classForCallable = bindingContext.get(CLASS_FOR_CALLABLE, descriptor);
|
||||
if (classForCallable == null) {
|
||||
return null;
|
||||
}
|
||||
return bindingContext.get(ASM_TYPE, classForCallable);
|
||||
}
|
||||
|
||||
public static boolean canHaveOuter(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) {
|
||||
|
||||
@@ -19,11 +19,11 @@ package org.jetbrains.kotlin.codegen.context;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.anonymousClassForCallable;
|
||||
|
||||
public class ClosureContext extends ClassContext {
|
||||
private final FunctionDescriptor functionDescriptor;
|
||||
private final FunctionDescriptor originalSuspendLambdaDescriptor;
|
||||
@@ -37,14 +37,27 @@ public class ClosureContext extends ClassContext {
|
||||
@Nullable FunctionDescriptor originalSuspendLambdaDescriptor
|
||||
) {
|
||||
super(typeMapper,
|
||||
anonymousClassForCallable(
|
||||
typeMapper.getBindingContext(), originalSuspendLambdaDescriptor != null ? originalSuspendLambdaDescriptor : functionDescriptor),
|
||||
getClassForCallable(typeMapper, functionDescriptor, originalSuspendLambdaDescriptor),
|
||||
OwnerKind.IMPLEMENTATION, parentContext, localLookup);
|
||||
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
this.originalSuspendLambdaDescriptor = originalSuspendLambdaDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ClassDescriptor getClassForCallable(
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@Nullable FunctionDescriptor originalSuspendLambdaDescriptor
|
||||
) {
|
||||
FunctionDescriptor callable = originalSuspendLambdaDescriptor != null ? originalSuspendLambdaDescriptor : functionDescriptor;
|
||||
ClassDescriptor classDescriptor = typeMapper.getBindingContext().get(CodegenBinding.CLASS_FOR_CALLABLE, callable);
|
||||
if (classDescriptor == null) {
|
||||
throw new IllegalStateException("Class for callable is not found: " + functionDescriptor);
|
||||
}
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
public ClosureContext(
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
@@ -22,10 +26,8 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
@@ -38,11 +40,13 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
abstract class AbstractCoroutineCodegen(
|
||||
outerExpressionCodegen: ExpressionCodegen,
|
||||
@@ -452,8 +456,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
|
||||
|
||||
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
||||
if (forInline) return super.wrapMethodVisitor(mv, access, name, desc)
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { v },
|
||||
element = element,
|
||||
@@ -464,6 +467,17 @@ class CoroutineCodegenForLambda private constructor(
|
||||
languageVersionSettings = languageVersionSettings,
|
||||
sourceFile = element.containingFile.name
|
||||
)
|
||||
return if (forInline) AddEndLabelMethodVisitor(
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
stateMachineBuilder, access, name, desc, v.thisName,
|
||||
isCapturedSuspendLambda = { isCapturedSuspendLambda(closure, it.name, state.bindingContext) }
|
||||
), access, name, desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
), access, name, desc, Label()
|
||||
) else AddEndLabelMethodVisitor(stateMachineBuilder, access, name, desc, Label())
|
||||
}
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
@@ -503,6 +517,37 @@ class CoroutineCodegenForLambda private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun isCapturedSuspendLambda(closure: CalculatedClosure, name: String, bindingContext: BindingContext): Boolean {
|
||||
for ((param, value) in closure.captureVariables) {
|
||||
if (param !is ValueParameterDescriptor) continue
|
||||
if (value.fieldName != name) continue
|
||||
return param.type.isSuspendFunctionTypeOrSubtype
|
||||
}
|
||||
val classDescriptor = closure.capturedOuterClassDescriptor ?: return false
|
||||
return isCapturedSuspendLambda(classDescriptor, name, bindingContext)
|
||||
}
|
||||
|
||||
fun isCapturedSuspendLambda(classDescriptor: ClassDescriptor, name: String, bindingContext: BindingContext): Boolean {
|
||||
val closure = bindingContext[CLOSURE, classDescriptor] ?: return false
|
||||
return isCapturedSuspendLambda(closure, name, bindingContext)
|
||||
}
|
||||
|
||||
private class AddEndLabelMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
private val endLabel: Label
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
methodNode.instructions.add(
|
||||
withInstructionAdapter {
|
||||
mark(endLabel)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class CoroutineCodegenForNamedFunction private constructor(
|
||||
outerExpressionCodegen: ExpressionCodegen,
|
||||
element: KtElement,
|
||||
|
||||
@@ -47,6 +47,8 @@ private const val COROUTINES_METADATA_CLASS_NAME_JVM_NAME = "c"
|
||||
private const val COROUTINES_METADATA_VERSION_JVM_NAME = "v"
|
||||
|
||||
const val SUSPEND_FUNCTION_CONTINUATION_PARAMETER = "\$completion"
|
||||
const val SUSPEND_CALL_RESULT_NAME = "\$result"
|
||||
const val ILLEGAL_STATE_ERROR_MESSAGE = "call to 'resume' before 'invoke' with coroutine"
|
||||
|
||||
class CoroutineTransformerMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
@@ -177,7 +179,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
insert(last, defaultLabel)
|
||||
|
||||
insert(last, withInstructionAdapter {
|
||||
AsmUtil.genThrow(this, "java/lang/IllegalStateException", "call to 'resume' before 'invoke' with coroutine")
|
||||
AsmUtil.genThrow(this, "java/lang/IllegalStateException", ILLEGAL_STATE_ERROR_MESSAGE)
|
||||
areturn(Type.VOID_TYPE)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
@@ -22,17 +20,19 @@ import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
open class SuspendFunctionGenerationStrategy(
|
||||
state: GenerationState,
|
||||
protected val originalSuspendDescriptor: FunctionDescriptor,
|
||||
protected val declaration: KtFunction,
|
||||
private val containingClassInternalName: String,
|
||||
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode
|
||||
state: GenerationState,
|
||||
protected val originalSuspendDescriptor: FunctionDescriptor,
|
||||
protected val declaration: KtFunction,
|
||||
private val containingClassInternalName: String,
|
||||
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
|
||||
protected val functionCodegen: FunctionCodegen
|
||||
) : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
|
||||
private lateinit var codegen: ExpressionCodegen
|
||||
@@ -45,7 +45,7 @@ open class SuspendFunctionGenerationStrategy(
|
||||
declaration.containingFile
|
||||
).also {
|
||||
val coroutineCodegen =
|
||||
CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration)
|
||||
CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration)
|
||||
coroutineCodegen.generate()
|
||||
}
|
||||
}
|
||||
@@ -53,16 +53,7 @@ open class SuspendFunctionGenerationStrategy(
|
||||
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
||||
if (access and Opcodes.ACC_ABSTRACT != 0) return mv
|
||||
|
||||
if (state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true) {
|
||||
return AddConstructorCallForCoroutineRegeneration(
|
||||
mv, access, name, desc, null, null, this::classBuilderForCoroutineState,
|
||||
containingClassInternalName,
|
||||
originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
containingClassInternalNameOrNull(),
|
||||
languageVersionSettings
|
||||
)
|
||||
}
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
|
||||
isForNamedFunction = true,
|
||||
element = declaration,
|
||||
@@ -73,10 +64,40 @@ open class SuspendFunctionGenerationStrategy(
|
||||
languageVersionSettings = languageVersionSettings,
|
||||
sourceFile = declaration.containingFile.name
|
||||
)
|
||||
|
||||
val forInline = state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true
|
||||
// Both capturing and inline functions share the same suffix, however, inline functions can also be capturing
|
||||
// they are already covered by SuspendInlineFunctionGenerationStrategy, thus, if we generate yet another copy,
|
||||
// we will get name+descriptor clash
|
||||
return if (forInline && !originalSuspendDescriptor.isInline)
|
||||
AddConstructorCallForCoroutineRegeneration(
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
stateMachineBuilder,
|
||||
access, name, desc, containingClassInternalName,
|
||||
isCapturedSuspendLambda = {
|
||||
isCapturedSuspendLambda(
|
||||
functionCodegen.closure.sure {
|
||||
"Anonymous object should have closure"
|
||||
},
|
||||
it.name,
|
||||
state.bindingContext
|
||||
)
|
||||
}
|
||||
), access, name, desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
), access, name, desc, null, null, this::classBuilderForCoroutineState,
|
||||
containingClassInternalName,
|
||||
originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
containingClassInternalNameOrNull(),
|
||||
languageVersionSettings
|
||||
) else stateMachineBuilder
|
||||
}
|
||||
|
||||
private fun containingClassInternalNameOrNull() =
|
||||
originalSuspendDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let(state.typeMapper::mapClass)?.internalName
|
||||
originalSuspendDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let(state.typeMapper::mapClass)?.internalName
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
this.codegen = codegen
|
||||
@@ -116,6 +137,7 @@ open class SuspendFunctionGenerationStrategy(
|
||||
languageVersionSettings
|
||||
)
|
||||
addFakeContinuationConstructorCallMarker(this, false)
|
||||
pop() // Otherwise stack-transformation breaks
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -9,12 +9,12 @@ import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -29,13 +29,14 @@ class SuspendInlineFunctionGenerationStrategy(
|
||||
declaration: KtFunction,
|
||||
containingClassInternalName: String,
|
||||
constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
|
||||
private val codegen: FunctionCodegen
|
||||
codegen: FunctionCodegen
|
||||
) : SuspendFunctionGenerationStrategy(
|
||||
state,
|
||||
originalSuspendDescriptor,
|
||||
declaration,
|
||||
containingClassInternalName,
|
||||
constructorCallNormalizationMode
|
||||
constructorCallNormalizationMode,
|
||||
codegen
|
||||
) {
|
||||
private val defaultStrategy = FunctionGenerationStrategy.FunctionDefault(state, declaration)
|
||||
|
||||
@@ -43,16 +44,10 @@ class SuspendInlineFunctionGenerationStrategy(
|
||||
if (access and Opcodes.ACC_ABSTRACT != 0) return mv
|
||||
|
||||
return MethodNodeCopyingMethodVisitor(
|
||||
super.wrapMethodVisitor(mv, access, name, desc),
|
||||
access,
|
||||
name,
|
||||
desc = desc,
|
||||
signature = null,
|
||||
exceptions = null,
|
||||
codegen = codegen,
|
||||
declaration = declaration,
|
||||
originalSuspendDescriptor = originalSuspendDescriptor,
|
||||
isReleaseCoroutines = state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
super.wrapMethodVisitor(mv, access, name, desc), access, name, desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}, keepAccess = false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -60,46 +55,26 @@ class SuspendInlineFunctionGenerationStrategy(
|
||||
super.doGenerateBody(codegen, signature)
|
||||
defaultStrategy.doGenerateBody(codegen, signature)
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodNodeCopyingMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
private val access: Int,
|
||||
private val name: String,
|
||||
private val desc: String,
|
||||
private val signature: String?,
|
||||
private val exceptions: Array<out String>?,
|
||||
private val codegen: FunctionCodegen,
|
||||
private val declaration: KtFunction,
|
||||
private val originalSuspendDescriptor: FunctionDescriptor,
|
||||
private val isReleaseCoroutines: Boolean
|
||||
) : TransformationMethodVisitor(
|
||||
delegate,
|
||||
calculateAccessForInline(access),
|
||||
"$name\$\$forInline",
|
||||
desc,
|
||||
signature,
|
||||
exceptions
|
||||
) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
val newMethodNode = codegen.newMethod(
|
||||
OtherOrigin(declaration, getOrCreateJvmSuspendFunctionView(originalSuspendDescriptor, isReleaseCoroutines)),
|
||||
calculateAccessForInline(access), "$name\$\$forInline", desc, signature, exceptions
|
||||
)
|
||||
methodNode.instructions.resetLabels()
|
||||
methodNode.accept(newMethodNode)
|
||||
}
|
||||
class MethodNodeCopyingMethodVisitor(
|
||||
delegate: MethodVisitor, private val access: Int, private val name: String, private val desc: String,
|
||||
private val newMethod: (JvmDeclarationOrigin, Int, String, String) -> MethodVisitor,
|
||||
private val keepAccess: Boolean = true
|
||||
) : TransformationMethodVisitor(
|
||||
delegate, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc, null, null
|
||||
) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
val newMethodNode = newMethod(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc
|
||||
)
|
||||
methodNode.instructions.resetLabels()
|
||||
methodNode.accept(newMethodNode)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun calculateAccessForInline(access: Int): Int {
|
||||
var accessForInline = access
|
||||
if (accessForInline and Opcodes.ACC_PUBLIC != 0) {
|
||||
accessForInline = accessForInline xor Opcodes.ACC_PUBLIC
|
||||
}
|
||||
if (accessForInline and Opcodes.ACC_PROTECTED != 0) {
|
||||
accessForInline = accessForInline xor Opcodes.ACC_PROTECTED
|
||||
}
|
||||
return accessForInline or Opcodes.ACC_PRIVATE
|
||||
}
|
||||
private fun calculateAccessForInline(access: Int, keepAccess: Boolean): Int =
|
||||
if (keepAccess) access
|
||||
else access or Opcodes.ACC_PRIVATE and Opcodes.ACC_PUBLIC.inv() and Opcodes.ACC_PROTECTED.inv()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.coroutines.DEBUG_METADATA_ANNOTATION_ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.coroutines.isCapturedSuspendLambda
|
||||
import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
|
||||
@@ -67,6 +69,8 @@ class AnonymousObjectTransformer(
|
||||
// Empty inner class info because no inner classes are used in kotlin.Metadata and its arguments
|
||||
val innerClassesInfo = FileBasedKotlinClass.InnerClassesInfo()
|
||||
return FileBasedKotlinClass.convertAnnotationVisitor(metadataReader, desc, innerClassesInfo)
|
||||
} else if (desc == DEBUG_METADATA_ANNOTATION_ASM_TYPE.descriptor) {
|
||||
return null
|
||||
}
|
||||
return super.visitAnnotation(desc, visible)
|
||||
}
|
||||
@@ -133,14 +137,15 @@ class AnonymousObjectTransformer(
|
||||
val coroutineTransformer = CoroutineTransformer(
|
||||
inliningContext,
|
||||
classBuilder,
|
||||
sourceInfo,
|
||||
methodsToTransform,
|
||||
superClassName
|
||||
superClassName,
|
||||
allCapturedParamBuilder.listCaptured()
|
||||
)
|
||||
for (next in methodsToTransform) {
|
||||
loop@for (next in methodsToTransform) {
|
||||
val deferringVisitor =
|
||||
when {
|
||||
coroutineTransformer.shouldTransform(next) -> coroutineTransformer.newMethod(next)
|
||||
coroutineTransformer.shouldSkip(next) -> continue@loop
|
||||
coroutineTransformer.shouldGenerateStateMachine(next) -> coroutineTransformer.newMethod(next)
|
||||
else -> newMethod(classBuilder, next)
|
||||
}
|
||||
val funResult = inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false)
|
||||
@@ -276,7 +281,8 @@ class AnonymousObjectTransformer(
|
||||
InlineCallSiteInfo(
|
||||
transformationInfo.oldClassName,
|
||||
sourceNode.name,
|
||||
if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc
|
||||
if (isConstructor) transformationInfo.newConstructorDescriptor else sourceNode.desc,
|
||||
inliningContext.callSiteInfo.isInlineOrInsideInline
|
||||
), null
|
||||
)
|
||||
|
||||
@@ -342,7 +348,7 @@ class AnonymousObjectTransformer(
|
||||
for (info in constructorAdditionalFakeParams) {
|
||||
val fake = constructorInlineBuilder.addCapturedParamCopy(info)
|
||||
|
||||
if (fake.lambda != null) {
|
||||
if (fake.functionalArgument is LambdaInfo) {
|
||||
//set remap value to skip this fake (captured with lambda already skipped)
|
||||
val composed = StackValue.field(
|
||||
fake.getType(),
|
||||
@@ -414,7 +420,7 @@ class AnonymousObjectTransformer(
|
||||
): List<CapturedParamInfo> {
|
||||
val capturedLambdas = LinkedHashSet<LambdaInfo>() //captured var of inlined parameter
|
||||
val constructorAdditionalFakeParams = ArrayList<CapturedParamInfo>()
|
||||
val indexToLambda = transformationInfo.lambdasToInline
|
||||
val indexToFunctionalArgument = transformationInfo.functionalArguments
|
||||
val capturedParams = HashSet<Int>()
|
||||
|
||||
//load captured parameters and patch instruction list
|
||||
@@ -424,18 +430,18 @@ class AnonymousObjectTransformer(
|
||||
val fieldName = fieldNode.name
|
||||
val parameterAload = fieldNode.previous as VarInsnNode
|
||||
val varIndex = parameterAload.`var`
|
||||
val lambdaInfo = indexToLambda[varIndex]
|
||||
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values))
|
||||
val functionalArgument = indexToFunctionalArgument[varIndex]
|
||||
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToFunctionalArgument.values))
|
||||
getNewFieldName(fieldName, true)
|
||||
else
|
||||
fieldName
|
||||
val info = capturedParamBuilder.addCapturedParam(
|
||||
Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName,
|
||||
Type.getType(fieldNode.desc), lambdaInfo != null, null
|
||||
Type.getType(fieldNode.desc), functionalArgument is LambdaInfo, null
|
||||
)
|
||||
if (lambdaInfo != null) {
|
||||
info.lambda = lambdaInfo
|
||||
capturedLambdas.add(lambdaInfo)
|
||||
info.functionalArgument = functionalArgument
|
||||
if (functionalArgument is LambdaInfo) {
|
||||
capturedLambdas.add(functionalArgument)
|
||||
}
|
||||
constructorAdditionalFakeParams.add(info)
|
||||
capturedParams.add(varIndex)
|
||||
@@ -450,9 +456,9 @@ class AnonymousObjectTransformer(
|
||||
|
||||
val paramTypes = transformationInfo.constructorDesc?.let { Type.getArgumentTypes(it) } ?: emptyArray()
|
||||
for (type in paramTypes) {
|
||||
val info = indexToLambda[constructorParamBuilder.nextParameterOffset]
|
||||
val parameterInfo = constructorParamBuilder.addNextParameter(type, info != null)
|
||||
parameterInfo.lambda = info
|
||||
val info = indexToFunctionalArgument[constructorParamBuilder.nextParameterOffset]
|
||||
val parameterInfo = constructorParamBuilder.addNextParameter(type, info is LambdaInfo)
|
||||
parameterInfo.functionalArgument = info
|
||||
if (capturedParams.contains(parameterInfo.index)) {
|
||||
parameterInfo.isCaptured = true
|
||||
} else {
|
||||
@@ -478,6 +484,11 @@ class AnonymousObjectTransformer(
|
||||
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
|
||||
alreadyAddedParam != null
|
||||
)
|
||||
if (info is PsiExpressionLambda && info.closure.captureVariables.any { it.value.fieldName == desc.fieldName }) {
|
||||
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend(
|
||||
isCapturedSuspendLambda(info.closure, desc.fieldName, inliningContext.state.bindingContext)
|
||||
)
|
||||
}
|
||||
val composed = StackValue.field(
|
||||
desc.type,
|
||||
oldObjectType, /*TODO owner type*/
|
||||
@@ -518,9 +529,9 @@ class AnonymousObjectTransformer(
|
||||
return constructorAdditionalFakeParams
|
||||
}
|
||||
|
||||
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<LambdaInfo>): Boolean {
|
||||
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<FunctionalArgument>): Boolean {
|
||||
return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
|
||||
values.any { it.capturedVars.any { isThis0(it.fieldName) } }
|
||||
values.any { it is LambdaInfo && it.capturedVars.any { isThis0(it.fieldName) } }
|
||||
} else false
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public class CapturedParamInfo extends ParameterInfo {
|
||||
CapturedParamInfo result = new CapturedParamInfo(
|
||||
desc, newFieldName, isSkipped, getIndex(), getRemapValue(), skipInConstructor, newDeclarationIndex
|
||||
);
|
||||
result.setLambda(getLambda());
|
||||
result.setFunctionalArgument(getFunctionalArgument());
|
||||
result.setSynthetic(synthetic);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
class InlineCallSiteInfo(val ownerClassName: String, val functionName: String?, val functionDesc: String?)
|
||||
class InlineCallSiteInfo(val ownerClassName: String, val functionName: String?, val functionDesc: String?, val isInlineOrInsideInline: Boolean)
|
||||
@@ -9,9 +9,12 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForCoroutineContext
|
||||
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForIntercepted
|
||||
@@ -19,6 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCorouti
|
||||
import org.jetbrains.kotlin.codegen.coroutines.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.bytecode
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.classId
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
@@ -89,7 +93,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
|
||||
protected val invocationParamBuilder = ParametersBuilder.newBuilder()
|
||||
|
||||
protected val expressionMap = linkedMapOf<Int, LambdaInfo>()
|
||||
protected val expressionMap = linkedMapOf<Int, FunctionalArgument>()
|
||||
|
||||
var activeLambda: LambdaInfo? = null
|
||||
protected set
|
||||
@@ -240,7 +244,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
extractDefaultLambdaOffsetAndDescriptor(jvmSignature, functionDescriptor)
|
||||
)
|
||||
for (lambda in defaultLambdas) {
|
||||
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).lambda = lambda
|
||||
invocationParamBuilder.buildParameters().getParameterByDeclarationSlot(lambda.offset).functionalArgument = lambda
|
||||
val prev = expressionMap.put(lambda.offset, lambda)
|
||||
assert(prev == null) { "Lambda with offset ${lambda.offset} already exists: $prev" }
|
||||
}
|
||||
@@ -316,7 +320,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
|
||||
private fun generateClosuresBodies() {
|
||||
for (info in expressionMap.values) {
|
||||
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
|
||||
if (info is LambdaInfo) {
|
||||
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +352,12 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
info.setRemapValue(remappedValue)
|
||||
} else {
|
||||
info = invocationParamBuilder.addNextValueParameter(jvmType, false, remappedValue, parameterIndex)
|
||||
info.functionalArgument = when (kind) {
|
||||
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND ->
|
||||
NonInlineableArgumentForInlineableParameterCalledInSuspend(kotlinType?.isSuspendFunctionTypeOrSubtype == true)
|
||||
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER -> NonInlineableArgumentForInlineableSuspendParameter
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
recordParameterValueInLocalVal(
|
||||
@@ -401,8 +413,10 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
private fun putClosureParametersOnStack() {
|
||||
for (next in expressionMap.values) {
|
||||
//closure parameters for bounded callable references are generated inplace
|
||||
if (next is ExpressionLambda && next.isBoundCallableReference) continue
|
||||
putClosureParametersOnStack(next, null)
|
||||
if (next is LambdaInfo) {
|
||||
if (next is ExpressionLambda && next.isBoundCallableReference) continue
|
||||
putClosureParametersOnStack(next, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,7 +548,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
// 2) for inliner: with mangled name and without state machine
|
||||
private fun mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor: FunctionDescriptor, asmMethod: Method): Method {
|
||||
if (!functionDescriptor.isSuspend) return asmMethod
|
||||
return Method("${asmMethod.name}\$\$forInline", asmMethod.descriptor)
|
||||
return Method("${asmMethod.name}$FOR_INLINE_SUFFIX", asmMethod.descriptor)
|
||||
}
|
||||
|
||||
private fun getDirectMemberAndCallableFromObject(functionDescriptor: FunctionDescriptor): CallableMemberDescriptor {
|
||||
@@ -761,10 +775,21 @@ class PsiInlineCodegen(
|
||||
}
|
||||
} else {
|
||||
val value = codegen.gen(argumentExpression)
|
||||
putValueIfNeeded(parameterType, value, ValueKind.GENERAL, parameterIndex)
|
||||
val kind = when {
|
||||
isCallSiteIsSuspend(valueParameterDescriptor) -> ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND
|
||||
isInlineSuspendParameter(valueParameterDescriptor) -> ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER
|
||||
else -> ValueKind.GENERAL
|
||||
}
|
||||
putValueIfNeeded(parameterType, value, kind, parameterIndex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isInlineSuspendParameter(descriptor: ValueParameterDescriptor): Boolean =
|
||||
functionDescriptor.isInline && !descriptor.isNoinline && descriptor.type.isSuspendFunctionTypeOrSubtype
|
||||
|
||||
private fun isCallSiteIsSuspend(descriptor: ValueParameterDescriptor): Boolean =
|
||||
state.bindingContext[CodegenBinding.CALL_SITE_IS_SUSPEND_FOR_CROSSINLINE_LAMBDA, descriptor] == true
|
||||
|
||||
private fun rememberClosure(expression: KtExpression, type: Type, parameter: ValueParameterDescriptor): LambdaInfo {
|
||||
val ktLambda = KtPsiUtil.deparenthesize(expression)
|
||||
assert(isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
|
||||
@@ -774,7 +799,7 @@ class PsiInlineCodegen(
|
||||
parameter.isCrossinline, getBoundCallableReferenceReceiver(expression) != null
|
||||
).also { lambda ->
|
||||
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
|
||||
closureInfo.lambda = lambda
|
||||
closureInfo.functionalArgument = lambda
|
||||
expressionMap.put(closureInfo.index, lambda)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
|
||||
class RootInliningContext(
|
||||
expressionMap: Map<Int, LambdaInfo>,
|
||||
expressionMap: Map<Int, FunctionalArgument>,
|
||||
state: GenerationState,
|
||||
nameGenerator: NameGenerator,
|
||||
val sourceCompilerForInline: SourceCompilerForInline,
|
||||
@@ -22,7 +22,7 @@ class RootInliningContext(
|
||||
|
||||
class RegeneratedClassContext(
|
||||
parent: InliningContext,
|
||||
expressionMap: Map<Int, LambdaInfo>,
|
||||
expressionMap: Map<Int, FunctionalArgument>,
|
||||
state: GenerationState,
|
||||
nameGenerator: NameGenerator,
|
||||
typeRemapper: TypeRemapper,
|
||||
@@ -36,7 +36,7 @@ class RegeneratedClassContext(
|
||||
|
||||
open class InliningContext(
|
||||
val parent: InliningContext?,
|
||||
val expressionMap: Map<Int, LambdaInfo>,
|
||||
val expressionMap: Map<Int, FunctionalArgument>,
|
||||
val state: GenerationState,
|
||||
val nameGenerator: NameGenerator,
|
||||
val typeRemapper: TypeRemapper,
|
||||
|
||||
@@ -19,11 +19,11 @@ package org.jetbrains.kotlin.codegen.inline;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class InvokeCall {
|
||||
public final LambdaInfo lambdaInfo;
|
||||
public final FunctionalArgument functionalArgument;
|
||||
public final int finallyDepthShift;
|
||||
|
||||
InvokeCall(@Nullable LambdaInfo lambdaInfo, int finallyDepthShift) {
|
||||
this.lambdaInfo = lambdaInfo;
|
||||
InvokeCall(@Nullable FunctionalArgument functionalArgument, int finallyDepthShift) {
|
||||
this.functionalArgument = functionalArgument;
|
||||
this.finallyDepthShift = finallyDepthShift;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.codegen.inline
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.*
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure
|
||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
|
||||
@@ -34,7 +33,9 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
|
||||
interface FunctionalArgument
|
||||
|
||||
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument, LabelOwner {
|
||||
|
||||
abstract val isBoundCallableReference: Boolean
|
||||
|
||||
@@ -76,6 +77,8 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
|
||||
}
|
||||
}
|
||||
|
||||
class NonInlineableArgumentForInlineableParameterCalledInSuspend(val isSuspend: Boolean) : FunctionalArgument
|
||||
object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument
|
||||
|
||||
class DefaultLambda(
|
||||
override val lambdaClassType: Type,
|
||||
@@ -225,7 +228,8 @@ class PsiExpressionLambda(
|
||||
|
||||
private val labels: Set<String>
|
||||
|
||||
private lateinit var closure: CalculatedClosure
|
||||
var closure: CalculatedClosure
|
||||
private set
|
||||
|
||||
init {
|
||||
val bindingContext = typeMapper.bindingContext
|
||||
@@ -234,8 +238,9 @@ class PsiExpressionLambda(
|
||||
if (function == null && expression is KtCallableReferenceExpression) {
|
||||
val variableDescriptor =
|
||||
bindingContext.get(BindingContext.VARIABLE, functionWithBodyOrCallableReference) as? VariableDescriptorWithAccessors
|
||||
?: throw AssertionError("""Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}""")
|
||||
classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor)
|
||||
?: throw AssertionError("Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}")
|
||||
classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, variableDescriptor)
|
||||
?: throw IllegalStateException("Class for callable not found: $variableDescriptor\n${expression.text}")
|
||||
lambdaClassType = typeMapper.mapClass(classDescriptor)
|
||||
val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor)
|
||||
invokeMethodDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor)
|
||||
@@ -246,7 +251,8 @@ class PsiExpressionLambda(
|
||||
} else {
|
||||
propertyReferenceInfo = null
|
||||
invokeMethodDescriptor = function ?: throw AssertionError("Function is not resolved to descriptor: " + expression.text)
|
||||
classDescriptor = anonymousClassForCallable(bindingContext, invokeMethodDescriptor)
|
||||
classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, invokeMethodDescriptor)
|
||||
?: throw IllegalStateException("Class for invoke method not found: $invokeMethodDescriptor\n${expression.text}")
|
||||
lambdaClassType = asmTypeForAnonymousClass(bindingContext, invokeMethodDescriptor)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,14 @@ import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
|
||||
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
|
||||
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.*
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.FixStackWithLabelNormalizationMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
@@ -217,9 +215,12 @@ class MethodInliner(
|
||||
if (/*INLINE_RUNTIME.equals(owner) &&*/ isInvokeOnLambda(owner, name)) { //TODO add method
|
||||
assert(!currentInvokes.isEmpty())
|
||||
val invokeCall = currentInvokes.remove()
|
||||
val info = invokeCall.lambdaInfo
|
||||
val info = invokeCall.functionalArgument
|
||||
|
||||
if (info == null) {
|
||||
if (info !is LambdaInfo) {
|
||||
if (info == NonInlineableArgumentForInlineableSuspendParameter) {
|
||||
super.visitMethodInsn(Opcodes.INVOKESTATIC, NOINLINE_CALL_MARKER, NOINLINE_CALL_MARKER, "()V", false)
|
||||
}
|
||||
//noninlinable lambda
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
||||
return
|
||||
@@ -263,7 +264,7 @@ class MethodInliner(
|
||||
listOf(*info.invokeMethod.argumentTypes), valueParameters, invokeParameters, valueParamShift, this, coroutineDesc
|
||||
)
|
||||
|
||||
if (invokeCall.lambdaInfo.invokeMethodDescriptor.valueParameters.isEmpty()) {
|
||||
if (info.invokeMethodDescriptor.valueParameters.isEmpty()) {
|
||||
// There won't be no parameters processing and line call can be left without actual instructions.
|
||||
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
|
||||
visitInsn(Opcodes.NOP)
|
||||
@@ -366,6 +367,8 @@ class MethodInliner(
|
||||
ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))
|
||||
) {
|
||||
//we shouldn't process here content of inlining lambda it should be reified at external level except default lambdas
|
||||
} else if (owner == NOINLINE_CALL_MARKER && name == NOINLINE_CALL_MARKER) {
|
||||
// do not generate multiple markers on single invoke
|
||||
} else {
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
||||
}
|
||||
@@ -386,7 +389,21 @@ class MethodInliner(
|
||||
|
||||
node.accept(lambdaInliner)
|
||||
|
||||
return resultNode
|
||||
return surroundInvokesWithSuspendMarkersIfNeeded(resultNode)
|
||||
}
|
||||
|
||||
private fun surroundInvokesWithSuspendMarkersIfNeeded(node: MethodNode): MethodNode {
|
||||
val markers = node.instructions.asSequence().filter { it.isNoinlineCallMarker() }.toList()
|
||||
if (markers.isEmpty()) return node
|
||||
val invokes = markers.map { it.next as MethodInsnNode }
|
||||
node.instructions.removeAll(markers)
|
||||
|
||||
val sourceFrames = MethodTransformer.analyze(inlineCallSiteInfo.ownerClassName, node, SourceInterpreter())
|
||||
val toSurround = invokes.mapNotNull { insn ->
|
||||
findReceiverOfInvoke(sourceFrames[node.instructions.indexOf(insn)], insn)?.let { insn to it }
|
||||
}
|
||||
surroundInvokesWithSuspendMarkers(node, toSurround)
|
||||
return node
|
||||
}
|
||||
|
||||
private fun isDefaultLambdaWithReification(lambdaInfo: LambdaInfo) =
|
||||
@@ -447,7 +464,7 @@ class MethodInliner(
|
||||
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
|
||||
if (DEFAULT_LAMBDA_FAKE_CALL == owner) {
|
||||
val index = name.substringAfter(DEFAULT_LAMBDA_FAKE_CALL).toInt()
|
||||
val lambda = getLambdaIfExists(index) as DefaultLambda
|
||||
val lambda = getFunctionalArgumentIfExists(index) as DefaultLambda
|
||||
lambda.parameterOffsetsInDefault.zip(lambda.capturedVars).asReversed().forEach { (_, captured) ->
|
||||
val originalBoundReceiverType = lambda.originalBoundReceiverType
|
||||
if (lambda.isBoundCallableReference && AsmUtil.isPrimitive(originalBoundReceiverType)) {
|
||||
@@ -522,22 +539,23 @@ class MethodInliner(
|
||||
val firstParameterIndex = frame.stackSize - paramCount
|
||||
if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
|
||||
val sourceValue = frame.getStack(firstParameterIndex)
|
||||
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
|
||||
invokeCalls.add(InvokeCall(lambdaInfo, currentFinallyDeep))
|
||||
val functionalArgument =
|
||||
getFunctionalArgumentIfExistsAndMarkInstructions(sourceValue, true, instructions, sources, toDelete)
|
||||
invokeCalls.add(InvokeCall(functionalArgument, currentFinallyDeep))
|
||||
} else if (isSamWrapperConstructorCall(owner, name)) {
|
||||
recordTransformation(SamWrapperTransformationInfo(owner, inliningContext, isAlreadyRegenerated(owner)))
|
||||
} else if (isAnonymousConstructorCall(owner, name)) {
|
||||
val lambdaMapping = HashMap<Int, LambdaInfo>()
|
||||
val functionalArgumentMapping = HashMap<Int, FunctionalArgument>()
|
||||
|
||||
var offset = 0
|
||||
var capturesAnonymousObjectThatMustBeRegenerated = false
|
||||
for (i in 0 until paramCount) {
|
||||
val sourceValue = frame.getStack(firstParameterIndex + i)
|
||||
val lambdaInfo = getLambdaIfExistsAndMarkInstructions(
|
||||
val functionalArgument = getFunctionalArgumentIfExistsAndMarkInstructions(
|
||||
sourceValue, false, instructions, sources, toDelete
|
||||
)
|
||||
if (lambdaInfo != null) {
|
||||
lambdaMapping.put(offset, lambdaInfo)
|
||||
if (functionalArgument != null) {
|
||||
functionalArgumentMapping.put(offset, functionalArgument)
|
||||
} else if (i < argTypes.size && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
|
||||
capturesAnonymousObjectThatMustBeRegenerated = true
|
||||
}
|
||||
@@ -547,7 +565,7 @@ class MethodInliner(
|
||||
|
||||
recordTransformation(
|
||||
buildConstructorInvocation(
|
||||
owner, cur.desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
|
||||
owner, cur.desc, functionalArgumentMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
|
||||
)
|
||||
)
|
||||
awaitClassReification = false
|
||||
@@ -595,14 +613,16 @@ class MethodInliner(
|
||||
}
|
||||
}
|
||||
|
||||
cur.opcode == Opcodes.POP -> getLambdaIfExistsAndMarkInstructions(
|
||||
cur.opcode == Opcodes.POP -> getFunctionalArgumentIfExistsAndMarkInstructions(
|
||||
frame.top()!!,
|
||||
true,
|
||||
instructions,
|
||||
sources,
|
||||
toDelete
|
||||
)?.let {
|
||||
toDelete.add(cur)
|
||||
if (it is LambdaInfo) {
|
||||
toDelete.add(cur)
|
||||
}
|
||||
}
|
||||
|
||||
cur.opcode == Opcodes.PUTFIELD -> {
|
||||
@@ -620,8 +640,8 @@ class MethodInliner(
|
||||
) {
|
||||
val stackTransformations = mutableSetOf<AbstractInsnNode>()
|
||||
val lambdaInfo =
|
||||
getLambdaIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations)
|
||||
if (lambdaInfo != null && stackTransformations.all { it is VarInsnNode }) {
|
||||
getFunctionalArgumentIfExistsAndMarkInstructions(frame.peek(1)!!, false, instructions, sources, stackTransformations)
|
||||
if (lambdaInfo is LambdaInfo && stackTransformations.all { it is VarInsnNode }) {
|
||||
assert(lambdaInfo.lambdaClassType.internalName == nodeRemapper.originalLambdaInternalName) {
|
||||
"Wrong bytecode template for contract template: ${lambdaInfo.lambdaClassType.internalName} != ${nodeRemapper.originalLambdaInternalName}"
|
||||
}
|
||||
@@ -812,7 +832,7 @@ class MethodInliner(
|
||||
private fun buildConstructorInvocation(
|
||||
anonymousType: String,
|
||||
desc: String,
|
||||
lambdaMapping: Map<Int, LambdaInfo>,
|
||||
lambdaMapping: Map<Int, FunctionalArgument>,
|
||||
needReification: Boolean,
|
||||
capturesAnonymousObjectThatMustBeRegenerated: Boolean
|
||||
): AnonymousObjectTransformationInfo {
|
||||
@@ -845,20 +865,20 @@ class MethodInliner(
|
||||
return inliningContext.typeRemapper.hasNoAdditionalMapping(owner)
|
||||
}
|
||||
|
||||
internal fun getLambdaIfExists(insnNode: AbstractInsnNode): LambdaInfo? {
|
||||
internal fun getFunctionalArgumentIfExists(insnNode: AbstractInsnNode): FunctionalArgument? {
|
||||
return when {
|
||||
insnNode.opcode == Opcodes.ALOAD ->
|
||||
getLambdaIfExists((insnNode as VarInsnNode).`var`)
|
||||
getFunctionalArgumentIfExists((insnNode as VarInsnNode).`var`)
|
||||
insnNode is FieldInsnNode && insnNode.name.startsWith(CAPTURED_FIELD_FOLD_PREFIX) ->
|
||||
findCapturedField(insnNode, nodeRemapper).lambda
|
||||
findCapturedField(insnNode, nodeRemapper).functionalArgument
|
||||
else ->
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLambdaIfExists(varIndex: Int): LambdaInfo? {
|
||||
private fun getFunctionalArgumentIfExists(varIndex: Int): FunctionalArgument? {
|
||||
if (varIndex < parameters.argsSizeOnStack) {
|
||||
return parameters.getParameterByDeclarationSlot(varIndex).lambda
|
||||
return parameters.getParameterByDeclarationSlot(varIndex).functionalArgument
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
@@ -26,37 +15,39 @@ import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
||||
fun MethodInliner.getFunctionalArgumentIfExistsAndMarkInstructions(
|
||||
sourceValue: SourceValue,
|
||||
processSwap: Boolean,
|
||||
insnList: InsnList,
|
||||
frames: Array<Frame<SourceValue>?>,
|
||||
toDelete: MutableSet<AbstractInsnNode>
|
||||
): LambdaInfo? {
|
||||
): FunctionalArgument? {
|
||||
val toDeleteInner = SmartSet.create<AbstractInsnNode>()
|
||||
|
||||
val lambdaSet = SmartSet.create<LambdaInfo?>()
|
||||
sourceValue.insns.mapTo(lambdaSet) {
|
||||
getLambdaIfExistsAndMarkInstructions(it, processSwap, insnList, frames, toDeleteInner)
|
||||
val functionalArgumentSet = SmartSet.create<FunctionalArgument?>()
|
||||
sourceValue.insns.mapTo(functionalArgumentSet) {
|
||||
getFunctionalArgumentIfExistsAndMarkInstructions(it, processSwap, insnList, frames, toDeleteInner)
|
||||
}
|
||||
|
||||
return lambdaSet.singleOrNull()?.also {
|
||||
toDelete.addAll(toDeleteInner)
|
||||
return functionalArgumentSet.singleOrNull()?.also {
|
||||
if (it is LambdaInfo) {
|
||||
toDelete.addAll(toDeleteInner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
|
||||
|
||||
private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
||||
private fun MethodInliner.getFunctionalArgumentIfExistsAndMarkInstructions(
|
||||
insnNode: AbstractInsnNode?,
|
||||
processSwap: Boolean,
|
||||
insnList: InsnList,
|
||||
frames: Array<Frame<SourceValue>?>,
|
||||
toDelete: MutableSet<AbstractInsnNode>
|
||||
): LambdaInfo? {
|
||||
): FunctionalArgument? {
|
||||
if (insnNode == null) return null
|
||||
|
||||
getLambdaIfExists(insnNode)?.let {
|
||||
getFunctionalArgumentIfExists(insnNode)?.let {
|
||||
//delete lambda aload instruction
|
||||
toDelete.add(insnNode)
|
||||
return it
|
||||
@@ -69,7 +60,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
||||
if (storeIns is VarInsnNode && storeIns.getOpcode() == Opcodes.ASTORE) {
|
||||
val frame = frames[insnList.indexOf(storeIns)] ?: return null
|
||||
val topOfStack = frame.top()!!
|
||||
getLambdaIfExistsAndMarkInstructions(topOfStack, processSwap, insnList, frames, toDelete)?.let {
|
||||
getFunctionalArgumentIfExistsAndMarkInstructions(topOfStack, processSwap, insnList, frames, toDelete)?.let {
|
||||
//remove intermediate lambda astore, aload instruction: see 'complexStack/simple.1.kt' test
|
||||
toDelete.add(storeIns)
|
||||
toDelete.add(insnNode)
|
||||
@@ -79,7 +70,7 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
||||
} else if (processSwap && insnNode.opcode == Opcodes.SWAP) {
|
||||
val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null
|
||||
val dispatchReceiver = swapFrame.top()!!
|
||||
getLambdaIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete)?.let {
|
||||
getFunctionalArgumentIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete)?.let {
|
||||
//remove swap instruction (dispatch receiver would be deleted on recursion call): see 'complexStack/simpleExtension.1.kt' test
|
||||
toDelete.add(insnNode)
|
||||
return it
|
||||
|
||||
@@ -29,7 +29,7 @@ public class ParameterInfo {
|
||||
public final boolean isSkipped;
|
||||
|
||||
private boolean isCaptured;
|
||||
private LambdaInfo lambda;
|
||||
private FunctionalArgument functionalArgument;
|
||||
//in case when parameter could be extracted from outer context (e.g. from local var)
|
||||
private StackValue remapValue;
|
||||
|
||||
@@ -68,13 +68,13 @@ public class ParameterInfo {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LambdaInfo getLambda() {
|
||||
return lambda;
|
||||
public FunctionalArgument getFunctionalArgument() {
|
||||
return functionalArgument;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ParameterInfo setLambda(@Nullable LambdaInfo lambda) {
|
||||
this.lambda = lambda;
|
||||
public ParameterInfo setFunctionalArgument(@Nullable FunctionalArgument functionalArgument) {
|
||||
this.functionalArgument = functionalArgument;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class ParametersBuilder private constructor() {
|
||||
|
||||
fun addCapturedParam(original: CapturedParamInfo, newFieldName: String): CapturedParamInfo {
|
||||
val info = CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextParameterOffset, original.index)
|
||||
info.lambda = original.lambda
|
||||
info.functionalArgument = original.functionalArgument
|
||||
return addParameter(info)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class ParametersBuilder private constructor() {
|
||||
CapturedParamDesc(containingLambdaType, fieldName, type), newFieldName, skipped, nextParameterOffset, original?.index ?: -1
|
||||
)
|
||||
if (original != null) {
|
||||
info.lambda = original.lambda
|
||||
info.functionalArgument = original.functionalArgument
|
||||
}
|
||||
return addParameter(info)
|
||||
}
|
||||
@@ -116,7 +116,7 @@ class ParametersBuilder private constructor() {
|
||||
val builder = newBuilder()
|
||||
if (inlineLambda?.hasDispatchReceiver != false && !isStatic) {
|
||||
//skipped this for inlined lambda cause it will be removed
|
||||
builder.addThis(objectType, inlineLambda != null).lambda = inlineLambda
|
||||
builder.addThis(objectType, inlineLambda != null).functionalArgument = inlineLambda
|
||||
}
|
||||
|
||||
for (type in Type.getArgumentTypes(descriptor)) {
|
||||
|
||||
@@ -75,7 +75,7 @@ class RegeneratedLambdaFieldRemapper(
|
||||
|
||||
|
||||
val result = StackValue.field(
|
||||
if (field.isSkipped)
|
||||
if (field.isSkipped && field.functionalArgument is LambdaInfo)
|
||||
Type.getObjectType(parent!!.parent!!.newLambdaInternalName)
|
||||
else
|
||||
field.getType(),
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline;
|
||||
@@ -29,9 +18,13 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.commons.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.FieldRemapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RemappingClassBuilder extends DelegatingClassBuilder {
|
||||
private final ClassBuilder builder;
|
||||
private final Remapper remapper;
|
||||
private final Map<String, FieldVisitor> spilledCoroutineVariables = new HashMap<>();
|
||||
|
||||
public RemappingClassBuilder(@NotNull ClassBuilder builder, @NotNull Remapper remapper) {
|
||||
this.builder = builder;
|
||||
@@ -68,9 +61,39 @@ public class RemappingClassBuilder extends DelegatingClassBuilder {
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
return new FieldRemapper(
|
||||
builder.newField(origin, access, name, remapper.mapDesc(desc), remapper.mapSignature(signature, true), value), remapper
|
||||
if (spilledCoroutineVariables.containsKey(name)) return spilledCoroutineVariables.get(name);
|
||||
|
||||
FieldRemapper field = new FieldRemapper(
|
||||
builder.newField(origin, access, name, this.remapper.mapDesc(desc), this.remapper.mapSignature(signature, true), value),
|
||||
this.remapper
|
||||
);
|
||||
if (isSpilledCoroutineVariableName(name)) {
|
||||
spilledCoroutineVariables.put(name, field);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
private static boolean isSpilledCoroutineVariableName(String name) {
|
||||
if (name.length() < 3) return false;
|
||||
switch (name.charAt(0)) {
|
||||
case 'L':
|
||||
case 'Z':
|
||||
case 'C':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'I':
|
||||
case 'F':
|
||||
case 'J':
|
||||
case 'D':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (name.charAt(1) != '$') return false;
|
||||
for (int i = 2; i < name.length(); ++i) {
|
||||
if (!Character.isDigit(name.charAt(i))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.context.*
|
||||
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -120,7 +121,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
|
||||
val signature = codegen.state.typeMapper.mapSignatureSkipGeneric(context.functionDescriptor, context.contextKind)
|
||||
return InlineCallSiteInfo(
|
||||
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor
|
||||
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor, compilationContextFunctionDescriptor.isInlineOrInsideInline()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -134,11 +135,15 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
): SMAP {
|
||||
lambdaInfo as? PsiExpressionLambda ?: error("TODO")
|
||||
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
|
||||
val closureContext =
|
||||
if (lambdaInfo.isPropertyReference)
|
||||
val closureContext = when {
|
||||
lambdaInfo.isPropertyReference ->
|
||||
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
|
||||
else
|
||||
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
|
||||
invokeMethodDescriptor.isSuspend ->
|
||||
codegen.getContext().intoCoroutineClosure(
|
||||
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state), invokeMethodDescriptor, codegen, state.typeMapper
|
||||
)
|
||||
else -> codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
|
||||
}
|
||||
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, lambdaInfo.isCrossInline, lambdaInfo.isPropertyReference)
|
||||
|
||||
return generateMethodBody(
|
||||
@@ -467,4 +472,8 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isInlineOrInsideInline(): Boolean =
|
||||
if (this is FunctionDescriptor && isInline) true
|
||||
else containingDeclaration?.isInlineOrInsideInline() == true
|
||||
|
||||
@@ -67,7 +67,7 @@ class WhenMappingTransformationInfo(
|
||||
class AnonymousObjectTransformationInfo internal constructor(
|
||||
override val oldClassName: String,
|
||||
private val needReification: Boolean,
|
||||
val lambdasToInline: Map<Int, LambdaInfo>,
|
||||
val functionalArguments: Map<Int, FunctionalArgument>,
|
||||
private val capturedOuterRegenerated: Boolean,
|
||||
private val alreadyRegenerated: Boolean,
|
||||
val constructorDesc: String?,
|
||||
@@ -99,7 +99,7 @@ class AnonymousObjectTransformationInfo internal constructor(
|
||||
|
||||
override fun shouldRegenerate(sameModule: Boolean): Boolean =
|
||||
!alreadyRegenerated &&
|
||||
(!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated)
|
||||
(!functionalArguments.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated)
|
||||
|
||||
override fun canRemoveAfterTransformation(): Boolean {
|
||||
// Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda
|
||||
|
||||
@@ -6,47 +6,51 @@
|
||||
package org.jetbrains.kotlin.codegen.inline.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_THIS_FIELD
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.coroutines.getLastParameterIndex
|
||||
import org.jetbrains.kotlin.codegen.coroutines.isResumeImplMethodName
|
||||
import org.jetbrains.kotlin.codegen.coroutines.replaceFakeContinuationsWithRealOnes
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
const val NOINLINE_CALL_MARKER = "NOINLINE_CALL_MARKER"
|
||||
|
||||
const val FOR_INLINE_SUFFIX = "\$\$forInline"
|
||||
|
||||
class CoroutineTransformer(
|
||||
private val inliningContext: InliningContext,
|
||||
private val classBuilder: ClassBuilder,
|
||||
private val sourceFile: String?,
|
||||
private val methods: List<MethodNode>,
|
||||
private val superClassName: String
|
||||
private val superClassName: String,
|
||||
private val capturedParams: List<CapturedParamInfo>
|
||||
) {
|
||||
private val state = inliningContext.state
|
||||
// If we inline into inline function, we should generate both method with state-machine for Java interop and method without
|
||||
// state-machine for further transformation/inlining.
|
||||
private val generateForInline = inliningContext.callSiteInfo.isInlineOrInsideInline
|
||||
|
||||
fun shouldTransform(node: MethodNode): Boolean {
|
||||
fun shouldSkip(node: MethodNode): Boolean = methods.any { it.name == node.name + FOR_INLINE_SUFFIX && it.desc == node.desc }
|
||||
|
||||
fun shouldGenerateStateMachine(node: MethodNode): Boolean {
|
||||
// Continuations are similar to lambdas from bird's view, but we should never generate state machine for them
|
||||
if (isContinuationNotLambda()) return false
|
||||
val crossinlineParam = crossinlineLambda() ?: return false
|
||||
if (inliningContext.isInliningLambda && !inliningContext.isContinuation) return false
|
||||
return when {
|
||||
isSuspendFunction(node) -> true
|
||||
isSuspendLambda(node) -> {
|
||||
if (isStateMachine(node)) return false
|
||||
val functionDescriptor =
|
||||
crossinlineParam.invokeMethodDescriptor.containingDeclaration as? FunctionDescriptor ?: return true
|
||||
!functionDescriptor.isInline
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
// there can be suspend lambdas inside inline functions, which do not
|
||||
// capture crossinline lambdas, thus, there is no need to transform them
|
||||
return isSuspendFunctionWithFakeConstructorCall(node) || (isSuspendLambda(node) && !isStateMachine(node))
|
||||
}
|
||||
|
||||
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation &&
|
||||
@@ -58,14 +62,16 @@ class CoroutineTransformer(
|
||||
}?.cast()
|
||||
|
||||
private fun isStateMachine(node: MethodNode): Boolean =
|
||||
node.instructions.asSequence().any { it.opcode == Opcodes.INVOKESTATIC && (it as MethodInsnNode).name == "getCOROUTINE_SUSPENDED" }
|
||||
node.instructions.asSequence().any { insn -> insn is LdcInsnNode && insn.cst == ILLEGAL_STATE_ERROR_MESSAGE }
|
||||
|
||||
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
|
||||
|
||||
fun newMethod(node: MethodNode): DeferredMethodVisitor {
|
||||
val element = crossinlineLambda()?.functionWithBodyOrCallableReference.sure {
|
||||
"crossinline lambda should have element"
|
||||
}
|
||||
// Find ANY element to report error about suspension point in monitor on.
|
||||
val element = crossinlineLambda()?.functionWithBodyOrCallableReference
|
||||
?: inliningContext.root.sourceCompilerForInline.callElement as? KtElement
|
||||
?: error("crossinline lambda should have element")
|
||||
|
||||
return when {
|
||||
isResumeImpl(node) -> {
|
||||
assert(!isStateMachine(node)) {
|
||||
@@ -73,74 +79,129 @@ class CoroutineTransformer(
|
||||
}
|
||||
newStateMachineForLambda(node, element)
|
||||
}
|
||||
isSuspendFunction(node) -> newStateMachineForNamedFunction(node, element)
|
||||
isSuspendFunctionWithFakeConstructorCall(node) -> newStateMachineForNamedFunction(node, element)
|
||||
else -> error("no need to generate state maching for ${node.name}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun isResumeImpl(node: MethodNode): Boolean =
|
||||
state.languageVersionSettings.isResumeImplMethodName(node.name) &&
|
||||
state.languageVersionSettings.isResumeImplMethodName(node.name.removeSuffix(FOR_INLINE_SUFFIX)) &&
|
||||
inliningContext.isContinuation
|
||||
|
||||
private fun isSuspendFunction(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
|
||||
private fun isSuspendFunctionWithFakeConstructorCall(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
|
||||
|
||||
private fun newStateMachineForLambda(node: MethodNode, element: KtElement): DeferredMethodVisitor {
|
||||
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
|
||||
return DeferredMethodVisitor(
|
||||
MethodNode(
|
||||
node.access, node.name, node.desc, node.signature,
|
||||
node.access, name, node.desc, node.signature,
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
)
|
||||
) {
|
||||
CoroutineTransformerMethodVisitor(
|
||||
classBuilder.newMethod(
|
||||
JvmDeclarationOrigin.NO_ORIGIN,
|
||||
node.access,
|
||||
node.name,
|
||||
node.desc,
|
||||
node.signature,
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
), node.access, node.name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { classBuilder },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
languageVersionSettings = state.languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classBuilder.thisName,
|
||||
isForNamedFunction = false,
|
||||
sourceFile = sourceFile ?: "",
|
||||
isCrossinlineLambda = inliningContext.isContinuation
|
||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkers(
|
||||
node,
|
||||
CoroutineTransformerMethodVisitor(
|
||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { classBuilder },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
languageVersionSettings = state.languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classBuilder.thisName,
|
||||
isForNamedFunction = false,
|
||||
sourceFile = element.containingKtFile.name
|
||||
)
|
||||
)
|
||||
|
||||
if (generateForInline)
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
delegate = stateMachineBuilder,
|
||||
access = node.access,
|
||||
name = name,
|
||||
desc = node.desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
classBuilder.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
)
|
||||
else
|
||||
stateMachineBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private fun newStateMachineForNamedFunction(node: MethodNode, element: KtElement): DeferredMethodVisitor {
|
||||
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
|
||||
val continuationClassName = findFakeContinuationConstructorClassName(node)
|
||||
assert(inliningContext is RegeneratedClassContext)
|
||||
return DeferredMethodVisitor(
|
||||
MethodNode(
|
||||
node.access, node.name, node.desc, node.signature,
|
||||
node.access, name, node.desc, node.signature,
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
)
|
||||
) {
|
||||
CoroutineTransformerMethodVisitor(
|
||||
classBuilder.newMethod(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, node.access, node.name, node.desc, node.signature,
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
), node.access, node.name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
languageVersionSettings = state.languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classBuilder.thisName,
|
||||
isForNamedFunction = true,
|
||||
needDispatchReceiver = true,
|
||||
internalNameForDispatchReceiver = classBuilder.thisName,
|
||||
sourceFile = sourceFile ?: ""
|
||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkers(
|
||||
node,
|
||||
CoroutineTransformerMethodVisitor(
|
||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
languageVersionSettings = state.languageVersionSettings,
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = classBuilder.thisName,
|
||||
isForNamedFunction = true,
|
||||
needDispatchReceiver = true,
|
||||
internalNameForDispatchReceiver = classBuilder.thisName,
|
||||
sourceFile = element.containingKtFile.name
|
||||
)
|
||||
)
|
||||
|
||||
if (generateForInline)
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
stateMachineBuilder, node.access, name, node.desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
classBuilder.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
)
|
||||
else
|
||||
stateMachineBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private fun surroundNoinlineCallsWithMarkers(node: MethodNode, delegate: MethodVisitor): MethodVisitor =
|
||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
delegate, node.access, node.name, node.desc, classBuilder.thisName, this::fieldIsCapturedSuspendLambda
|
||||
)
|
||||
|
||||
private fun fieldIsCapturedSuspendLambda(field: FieldInsnNode): Boolean =
|
||||
capturedParams.find { it.newFieldName == field.name }?.let { it.functionalArgument?.isSuspendLambda() == true }
|
||||
?: isSuspendLambdaCapturedByOuterObjectOrLambda(field)
|
||||
|
||||
// We cannot find the lambda in captured parameters: it came from object outside of the our reach:
|
||||
// this can happen when the lambda capture by non-transformed closure:
|
||||
// inline fun inlineMe(crossinline c: suspend() -> Unit) = suspend { c() }
|
||||
// inline fun inlineMe2(crossinline c: suspend() -> Unit) = suspend { inlineMe { c() }() }
|
||||
// Suppose, we inline inlineMe into inlineMe2: the only knowledge we have about inlineMe$1 is captured receiver (this$0)
|
||||
// Thus, transformed lambda from inlineMe, inlineMe3$$inlined$inlineMe2$1 contains the following bytecode
|
||||
// ALOAD 0
|
||||
// GETFIELD inlineMe2$1$invokeSuspend$$inlined$inlineMe$1.this$0 : LScratchKt$inlineMe2$1;
|
||||
// GETFIELD inlineMe2$1.$c : Lkotlin/jvm/functions/Function1;
|
||||
// Since inlineMe2's lambda is outside of reach of the inliner, find crossinline parameter from compilation context:
|
||||
private fun isSuspendLambdaCapturedByOuterObjectOrLambda(field: FieldInsnNode): Boolean {
|
||||
val functionDescriptor = inliningContext.root.sourceCompilerForInline.compilationContextFunctionDescriptor
|
||||
val classDescriptor = functionDescriptor.findContainingClassOrLambda() ?: return false
|
||||
return isCapturedSuspendLambda(classDescriptor, field.name, inliningContext.state.bindingContext)
|
||||
}
|
||||
|
||||
private tailrec fun DeclarationDescriptor.findContainingClassOrLambda(): ClassDescriptor? =
|
||||
if (containingDeclaration is ClassDescriptor) containingDeclaration as ClassDescriptor
|
||||
else containingDeclaration?.findContainingClassOrLambda()
|
||||
|
||||
private fun createNewMethodFrom(node: MethodNode, name: String): MethodVisitor {
|
||||
return classBuilder.newMethod(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, node.access, name, node.desc, node.signature, ArrayUtil.toStringArray(node.exceptions)
|
||||
)
|
||||
}
|
||||
|
||||
fun replaceFakesWithReals(node: MethodNode) {
|
||||
findFakeContinuationConstructorClassName(node)?.let(::unregisterClassBuilder)?.let(ClassBuilder::done)
|
||||
replaceFakeContinuationsWithRealOnes(
|
||||
@@ -164,4 +225,79 @@ class CoroutineTransformer(
|
||||
return (new as TypeInsnNode).desc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
delegate: MethodVisitor, access: Int, name: String, desc: String,
|
||||
private val thisName: String,
|
||||
private val isCapturedSuspendLambda: (FieldInsnNode) -> Boolean
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this)
|
||||
|
||||
val sourceFrames = MethodTransformer.analyze(thisName, methodNode, SourceInterpreter())
|
||||
|
||||
val noinlineInvokes = arrayListOf<Pair<AbstractInsnNode, AbstractInsnNode>>()
|
||||
|
||||
for (insn in methodNode.instructions.asSequence()) {
|
||||
if (insn.opcode != Opcodes.INVOKEINTERFACE) continue
|
||||
insn as MethodInsnNode
|
||||
if (!isInvokeOnLambda(insn.owner, insn.name)) continue
|
||||
val frame = sourceFrames[insn.index()] ?: continue
|
||||
val receiver = findReceiverOfInvoke(frame, insn).takeIf { it?.isSuspendLambda(insn) == true } as? FieldInsnNode ?: continue
|
||||
val aload = receiver.findPreviousOrNull { it.opcode != Opcodes.GETFIELD } ?: error("GETFIELD cannot be the first instruction")
|
||||
assert(aload.opcode == Opcodes.ALOAD) { "Before GETFIELD there shall be ALOAD" }
|
||||
noinlineInvokes.add(insn to aload)
|
||||
}
|
||||
|
||||
surroundInvokesWithSuspendMarkers(methodNode, noinlineInvokes)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.isSuspendLambda(invoke: MethodInsnNode): Boolean {
|
||||
if (opcode != Opcodes.GETFIELD) return false
|
||||
this as FieldInsnNode
|
||||
if (desc != "L${invoke.owner};") return false
|
||||
var current: FieldInsnNode? = this
|
||||
// Unroll the battery of
|
||||
// GETFIELD <outer1>.this$0 L<outer2>;
|
||||
// GETFIELD <outer2>.this$0 L<outer3>;
|
||||
// ...
|
||||
// GETFIELD <outerN>.$action Lkotlin/jvm/functions/FunctionM;
|
||||
while (current != null) {
|
||||
if (current.owner == thisName) break
|
||||
if (current.previous?.opcode != Opcodes.GETFIELD || current.previous.cast<FieldInsnNode>().name != CAPTURED_THIS_FIELD) return false
|
||||
current = current.previous as FieldInsnNode
|
||||
}
|
||||
return isCapturedSuspendLambda(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionalArgument.isSuspendLambda(): Boolean =
|
||||
(this is NonInlineableArgumentForInlineableParameterCalledInSuspend && isSuspend) ||
|
||||
(this is PsiExpressionLambda && invokeMethodDescriptor.isSuspend)
|
||||
|
||||
fun surroundInvokesWithSuspendMarkers(
|
||||
methodNode: MethodNode,
|
||||
noinlineInvokes: List<Pair<AbstractInsnNode, AbstractInsnNode>>
|
||||
) {
|
||||
for ((invoke, aload) in noinlineInvokes) {
|
||||
// Generate inline markers for stack transformation. It is required for local variables spilling.
|
||||
methodNode.instructions.insertBefore(aload, withInstructionAdapter {
|
||||
addInlineMarker(this, isStartNotEnd = true)
|
||||
})
|
||||
methodNode.instructions.insertBefore(invoke, withInstructionAdapter {
|
||||
addSuspendMarker(this, isStartNotEnd = true)
|
||||
})
|
||||
methodNode.instructions.insert(invoke, withInstructionAdapter {
|
||||
addSuspendMarker(this, isStartNotEnd = false)
|
||||
addInlineMarker(this, isStartNotEnd = false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: What to do if suddenly there are not exactly one receiver?
|
||||
fun findReceiverOfInvoke(frame: Frame<SourceValue>, insn: MethodInsnNode): AbstractInsnNode? =
|
||||
frame.getStack(frame.stackSize - insn.owner.removePrefix(NUMBERED_FUNCTION_PREFIX).toInt() - 1)?.insns?.singleOrNull()
|
||||
|
||||
fun AbstractInsnNode.isNoinlineCallMarker(): Boolean =
|
||||
opcode == Opcodes.INVOKESTATIC && cast<MethodInsnNode>().let { it.owner == NOINLINE_CALL_MARKER && it.name == NOINLINE_CALL_MARKER }
|
||||
|
||||
@@ -25,7 +25,7 @@ class NewJavaField(val name: String, val type: Type, val skip: Boolean)
|
||||
fun getNewFieldsToGenerate(params: List<CapturedParamInfo>): List<NewJavaField> {
|
||||
return params.filter {
|
||||
//not inlined
|
||||
it.lambda == null
|
||||
it.functionalArgument !is LambdaInfo
|
||||
}.map {
|
||||
NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor)
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.kotlin.getRepresentativeUpperBound
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.jvm.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
|
||||
@@ -44,7 +44,7 @@ private fun getSignatureElementForMangling(type: KotlinType): String = buildStri
|
||||
}
|
||||
|
||||
is TypeParameterDescriptor -> {
|
||||
append(getSignatureElementForMangling(getRepresentativeUpperBound(descriptor)))
|
||||
append(getSignatureElementForMangling(descriptor.representativeUpperBound))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
@Argument(
|
||||
value = "-jvm-target",
|
||||
valueDescription = "<version>",
|
||||
description = "Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6"
|
||||
description = "Target version of the generated JVM bytecode (1.6, 1.8, 9, 10, 11 or 12), default is 1.6"
|
||||
)
|
||||
var jvmTarget: String? by NullableStringFreezableVar(JvmTarget.DEFAULT.description)
|
||||
|
||||
|
||||
@@ -215,10 +215,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
val libPath = PathUtil.kotlinPathsForCompiler.libPath.takeIf { it.exists() && it.isDirectory } ?: File(".")
|
||||
with(PathUtil) {
|
||||
val jars = arrayOf(
|
||||
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMMON_JAR,
|
||||
KOTLIN_SCRIPTING_JVM_JAR
|
||||
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_IMPL_JAR,
|
||||
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR
|
||||
).mapNotNull { File(libPath, it).takeIf { it.exists() }?.canonicalPath }
|
||||
if (jars.size == 3) {
|
||||
if (jars.size == 4) {
|
||||
pluginClasspaths = jars + pluginClasspaths
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
val sourceScope = if (separateModules) sourceModuleSearchScope else GlobalSearchScope.allScope(project)
|
||||
val moduleClassResolver = SourceOrBinaryModuleClassResolver(sourceScope)
|
||||
|
||||
val jvmTarget = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.JVM_1_6
|
||||
val jvmTarget = configuration.get(JVMConfigurationKeys.JVM_TARGET, JvmTarget.DEFAULT)
|
||||
val languageVersionSettings = configuration.languageVersionSettings
|
||||
|
||||
val optionalBuiltInsModule =
|
||||
|
||||
@@ -56,7 +56,8 @@ open class GenericReplChecker(
|
||||
if (get(JVMConfigurationKeys.JVM_TARGET) == null) {
|
||||
put(JVMConfigurationKeys.JVM_TARGET,
|
||||
System.getProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY)?.let { JvmTarget.fromString(it) }
|
||||
?: if (getJavaVersion() >= 0x10008) JvmTarget.JVM_1_8 else JvmTarget.JVM_1_6)
|
||||
?: System.getProperty("java.specification.version")?.let { JvmTarget.fromString(it) }
|
||||
?: JvmTarget.DEFAULT)
|
||||
}
|
||||
}
|
||||
KotlinCoreEnvironment.createForProduction(disposable, compilerConfiguration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
@@ -97,21 +98,3 @@ open class GenericReplChecker(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initially taken from libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt
|
||||
// fixed according to JEP 223 - http://openjdk.java.net/jeps/223
|
||||
// TODO: consider to place it to some common place
|
||||
private fun getJavaVersion(): Int {
|
||||
val default = 0x10006
|
||||
val version = System.getProperty("java.specification.version") ?: return default
|
||||
val components = version.split('.')
|
||||
return try {
|
||||
when (components.size) {
|
||||
0 -> default
|
||||
1 -> components[0].toInt() * 0x10000
|
||||
else -> components[0].toInt() * 0x10000 + components[1].toInt()
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ sourceSets {
|
||||
"test" {}
|
||||
}
|
||||
|
||||
publish()
|
||||
|
||||
val jar: Jar by tasks
|
||||
|
||||
runtimeJar(rewriteDepsToShadedCompiler(jar))
|
||||
sourcesJar()
|
||||
javadocJar()
|
||||
|
||||
publish()
|
||||
|
||||
@@ -38,7 +38,10 @@ object DynamicComponentDescriptor : ValueDescriptor {
|
||||
override fun toString(): String = "Dynamic"
|
||||
}
|
||||
|
||||
class StorageComponentContainer(private val id: String, parent: StorageComponentContainer? = null) : ComponentContainer, ComponentProvider, Closeable {
|
||||
class StorageComponentContainer(
|
||||
private val id: String,
|
||||
parent: StorageComponentContainer? = null
|
||||
) : ComponentContainer, ComponentProvider, Closeable {
|
||||
val unknownContext: ComponentResolveContext by lazy {
|
||||
val parentContext = parent?.let { ComponentResolveContext(it, DynamicComponentDescriptor) }
|
||||
ComponentResolveContext(this, DynamicComponentDescriptor, parentContext)
|
||||
@@ -102,7 +105,10 @@ class StorageComponentContainer(private val id: String, parent: StorageComponent
|
||||
override fun <T> create(request: Class<T>): T {
|
||||
val constructorBinding = request.bindToConstructor(unknownContext)
|
||||
val args = constructorBinding.argumentDescriptors.map { it.getValue() }.toTypedArray()
|
||||
return runWithUnwrappingInvocationException { constructorBinding.constructor.newInstance(*args) as T }
|
||||
return runWithUnwrappingInvocationException {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
constructorBinding.constructor.newInstance(*args) as T
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = "Container $id"
|
||||
|
||||
@@ -42,7 +42,7 @@ class ComponentContainerTest {
|
||||
|
||||
val descriptor = container.resolve<TestComponentInterface>()
|
||||
assertNotNull(descriptor)
|
||||
val instance = descriptor!!.getValue() as TestComponentInterface
|
||||
val instance = descriptor.getValue() as TestComponentInterface
|
||||
assertNotNull(instance)
|
||||
assertFails {
|
||||
instance.foo()
|
||||
@@ -58,14 +58,14 @@ class ComponentContainerTest {
|
||||
|
||||
val descriptor = container.resolve<TestClientComponent>()
|
||||
assertNotNull(descriptor)
|
||||
val instance = descriptor!!.getValue() as TestClientComponent
|
||||
val instance = descriptor.getValue() as TestClientComponent
|
||||
assertNotNull(instance)
|
||||
assertNotNull(instance.dep)
|
||||
assertFails {
|
||||
instance.dep.foo()
|
||||
}
|
||||
assertTrue(instance.dep is ManualTestComponent)
|
||||
assertEquals("name", (instance.dep as ManualTestComponent).name)
|
||||
assertEquals("name", instance.dep.name)
|
||||
container.close()
|
||||
assertTrue(instance.disposed)
|
||||
assertFalse(instance.dep.disposed) // should not dispose manually passed instances
|
||||
@@ -80,7 +80,7 @@ class ComponentContainerTest {
|
||||
|
||||
val descriptor = container.resolve<TestClientComponent>()
|
||||
assertNotNull(descriptor)
|
||||
val instance = descriptor!!.getValue() as TestClientComponent
|
||||
val instance = descriptor.getValue() as TestClientComponent
|
||||
assertNotNull(instance)
|
||||
assertNotNull(instance.dep)
|
||||
assertFails {
|
||||
@@ -114,8 +114,8 @@ class ComponentContainerTest {
|
||||
assertNotNull(descriptor1)
|
||||
val descriptor2 = it.resolve<TestClientComponentInterface>()
|
||||
assertNotNull(descriptor2)
|
||||
assertTrue(descriptor1 == descriptor2)
|
||||
assertTrue(descriptor1!!.getValue() == descriptor2!!.getValue())
|
||||
assertEquals(descriptor1, descriptor2)
|
||||
assertEquals(descriptor1.getValue(), descriptor2.getValue())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +129,9 @@ class ComponentContainerTest {
|
||||
assertNotNull(descriptor1)
|
||||
val descriptor2 = it.resolve<TestAdhocComponent2>()
|
||||
assertNotNull(descriptor2)
|
||||
val component1 = descriptor1!!.getValue() as TestAdhocComponent1
|
||||
val component2 = descriptor2!!.getValue() as TestAdhocComponent2
|
||||
assertTrue(component1.service === component2.service)
|
||||
val component1 = descriptor1.getValue() as TestAdhocComponent1
|
||||
val component2 = descriptor2.getValue() as TestAdhocComponent2
|
||||
assertSame(component1.service, component2.service)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,10 +142,10 @@ class ComponentContainerTest {
|
||||
useImpl<TestClientComponent>()
|
||||
useImpl<TestClientComponent2>()
|
||||
useImpl<TestIterableComponent>()
|
||||
}.use {
|
||||
val descriptor = it.resolve<TestIterableComponent>()
|
||||
}.use { container ->
|
||||
val descriptor = container.resolve<TestIterableComponent>()
|
||||
assertNotNull(descriptor)
|
||||
val iterableComponent = descriptor!!.getValue() as TestIterableComponent
|
||||
val iterableComponent = descriptor.getValue() as TestIterableComponent
|
||||
assertEquals(2, iterableComponent.components.count())
|
||||
assertTrue(iterableComponent.components.any { it is TestClientComponent })
|
||||
assertTrue(iterableComponent.components.any { it is TestClientComponent2 })
|
||||
@@ -160,10 +160,10 @@ class ComponentContainerTest {
|
||||
useImpl<TestClientComponent2>()
|
||||
useImpl<TestStringComponent>()
|
||||
useImpl<JavaTestComponents>()
|
||||
}.use {
|
||||
val descriptor = it.resolve<JavaTestComponents>()
|
||||
}.use { container ->
|
||||
val descriptor = container.resolve<JavaTestComponents>()
|
||||
assertNotNull(descriptor)
|
||||
val iterableComponent = descriptor!!.getValue() as JavaTestComponents
|
||||
val iterableComponent = descriptor.getValue() as JavaTestComponents
|
||||
assertEquals(2, iterableComponent.components.count())
|
||||
assertTrue(iterableComponent.components.any { it is TestClientComponent })
|
||||
assertTrue(iterableComponent.components.any { it is TestClientComponent2 })
|
||||
@@ -181,7 +181,7 @@ class ComponentContainerTest {
|
||||
}.use {
|
||||
val descriptor = it.resolve<TestGenericClient>()
|
||||
assertNotNull(descriptor)
|
||||
val genericClient = descriptor!!.getValue() as TestGenericClient
|
||||
val genericClient = descriptor.getValue() as TestGenericClient
|
||||
assertTrue(genericClient.component1 is TestStringComponent)
|
||||
assertTrue(genericClient.component2 is TestIntComponent)
|
||||
}
|
||||
@@ -219,9 +219,11 @@ class ComponentContainerTest {
|
||||
class WithSetters {
|
||||
var isSetterCalled = false
|
||||
|
||||
@Suppress("unused")
|
||||
var tc: TestComponent? = null
|
||||
@Inject set(v) {
|
||||
isSetterCalled = true
|
||||
field = v
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +267,7 @@ class ComponentContainerTest {
|
||||
|
||||
val b = a.b
|
||||
assertTrue(b is B)
|
||||
val c = b!!.c
|
||||
val c = b.c
|
||||
assertTrue(c is C)
|
||||
}
|
||||
|
||||
@@ -284,10 +286,13 @@ class ComponentContainerTest {
|
||||
val b = bc.get<B>()
|
||||
|
||||
val a = ac.get<A>()
|
||||
@Suppress("USELESS_IS_CHECK")
|
||||
assertTrue(b is B)
|
||||
@Suppress("USELESS_IS_CHECK")
|
||||
assertTrue(b.a is A)
|
||||
@Suppress("USELESS_IS_CHECK")
|
||||
assertTrue(a is A)
|
||||
assertTrue(b.a === a)
|
||||
assertSame(b.a, a)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -306,10 +311,11 @@ class ComponentContainerTest {
|
||||
useImpl<B>()
|
||||
}
|
||||
val a = ac.get<A>()
|
||||
@Suppress("USELESS_IS_CHECK")
|
||||
assertTrue(a is A)
|
||||
assertTrue(a === bc2.get<B>().a)
|
||||
assertTrue(a === bc1.get<B>().a)
|
||||
assertTrue(a === bc1.get<A>())
|
||||
assertSame(a, bc2.get<B>().a)
|
||||
assertSame(a, bc1.get<B>().a)
|
||||
assertSame(a, bc1.get())
|
||||
}
|
||||
|
||||
@DefaultImplementation(impl = Impl::class)
|
||||
@@ -317,7 +323,7 @@ class ComponentContainerTest {
|
||||
|
||||
class Impl : I()
|
||||
|
||||
class Impl2: I()
|
||||
class Impl2 : I()
|
||||
|
||||
class Use(val i: I)
|
||||
|
||||
@@ -346,7 +352,7 @@ class ComponentContainerTest {
|
||||
@DefaultImplementation(impl = A::class)
|
||||
interface S
|
||||
|
||||
object A: S
|
||||
object A : S
|
||||
|
||||
class UseS(val s: S)
|
||||
|
||||
@@ -356,6 +362,6 @@ class ComponentContainerTest {
|
||||
useImpl<UseS>()
|
||||
}.get<UseS>()
|
||||
|
||||
assertTrue(useS.s === A)
|
||||
assertSame(useS.s, A)
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,8 @@ sourceSets {
|
||||
"test" {}
|
||||
}
|
||||
|
||||
publish()
|
||||
|
||||
noDefaultJar()
|
||||
|
||||
runtimeJar(task<ShadowJar>("shadowJar")) {
|
||||
@@ -55,5 +57,3 @@ javadocJar()
|
||||
dist()
|
||||
|
||||
ideaPlugin()
|
||||
|
||||
publish()
|
||||
|
||||
@@ -41,7 +41,10 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.daemon.report.*
|
||||
import org.jetbrains.kotlin.daemon.report.CompileServicesFacadeMessageCollector
|
||||
import org.jetbrains.kotlin.daemon.report.DaemonMessageReporter
|
||||
import org.jetbrains.kotlin.daemon.report.DaemonMessageReporterPrintStreamAdapter
|
||||
import org.jetbrains.kotlin.daemon.report.getICReporter
|
||||
import org.jetbrains.kotlin.incremental.*
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.jetbrains.kotlin.config
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -21,10 +22,13 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
enum class JvmTarget(override val description: String) : TargetPlatformVersion {
|
||||
JVM_1_6("1.6"),
|
||||
JVM_1_8("1.8"),
|
||||
JVM_9("9"),
|
||||
JVM_10("10"),
|
||||
JVM_11("11"),
|
||||
JVM_12("12"),
|
||||
;
|
||||
|
||||
val bytecodeVersion: Int by lazy {
|
||||
@Suppress("DEPRECATION")
|
||||
when (this) {
|
||||
JVM_1_6 -> Opcodes.V1_6
|
||||
JVM_1_8 ->
|
||||
@@ -33,6 +37,10 @@ enum class JvmTarget(override val description: String) : TargetPlatformVersion {
|
||||
java.lang.Boolean.valueOf(System.getProperty("kotlin.test.substitute.bytecode.1.8.to.1.9")) -> Opcodes.V9
|
||||
else -> Opcodes.V1_8
|
||||
}
|
||||
JVM_9 -> Opcodes.V9
|
||||
JVM_10 -> Opcodes.V9 + 1
|
||||
JVM_11 -> Opcodes.V9 + 2
|
||||
JVM_12 -> Opcodes.V9 + 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,16 +52,13 @@ enum class JvmTarget(override val description: String) : TargetPlatformVersion {
|
||||
fun fromString(string: String) = values().find { it.description == string }
|
||||
|
||||
fun getDescription(bytecodeVersion: Int): String {
|
||||
@Suppress("DEPRECATION")
|
||||
val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?:
|
||||
when (bytecodeVersion) {
|
||||
Opcodes.V1_7 -> "1.7"
|
||||
Opcodes.V9 -> "1.9"
|
||||
else -> null
|
||||
}
|
||||
val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?: when (bytecodeVersion) {
|
||||
Opcodes.V1_7 -> "1.7"
|
||||
else -> null
|
||||
}
|
||||
|
||||
return if (platformDescription != null) "JVM target $platformDescription"
|
||||
else "JVM bytecode version $bytecodeVersion"
|
||||
else "JVM bytecode version $bytecodeVersion"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ object JvmAnalyzerFacade : ResolverForModuleFactory() {
|
||||
resolverForModule.componentProvider.get<JavaDescriptorResolver>()
|
||||
}
|
||||
|
||||
val jvmTarget = targetPlatformVersion as? JvmTarget ?: JvmTarget.JVM_1_6
|
||||
val jvmTarget = targetPlatformVersion as? JvmTarget ?: JvmTarget.DEFAULT
|
||||
val trace = CodeAnalyzerInitializer.getInstance(project).createTrace()
|
||||
|
||||
val lookupTracker = LookupTracker.DO_NOTHING
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.*
|
||||
class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker {
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val supportDefaults = jvmTarget == JvmTarget.JVM_1_8
|
||||
val supportDefaults = jvmTarget >= JvmTarget.JVM_1_8
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||
if (descriptor is JavaPropertyDescriptor) return
|
||||
|
||||
@@ -28,7 +28,10 @@ import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
object RepeatableAnnotationChecker: AdditionalAnnotationChecker {
|
||||
@@ -81,12 +84,8 @@ object FileClassAnnotationsChecker: AdditionalAnnotationChecker {
|
||||
if (classDescriptor.getAnnotationRetention() != KotlinRetention.SOURCE) {
|
||||
trace.report(ErrorsJvm.ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES.on(entry, classFqName))
|
||||
}
|
||||
if (classFqName == JvmFileClassUtil.JVM_PACKAGE_NAME) {
|
||||
trace.report(ErrorsJvm.JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_MULTIFILE_CLASSES.on(entry))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for ((entry, classDescriptor) in fileAnnotationsToCheck) {
|
||||
if (classDescriptor.fqNameSafe != JvmFileClassUtil.JVM_PACKAGE_NAME) continue
|
||||
|
||||
@@ -97,13 +96,11 @@ object FileClassAnnotationsChecker: AdditionalAnnotationChecker {
|
||||
val value = (stringTemplateEntries.singleOrNull() as? KtLiteralStringTemplateEntry)?.text
|
||||
if (value == null) {
|
||||
trace.report(ErrorsJvm.JVM_PACKAGE_NAME_CANNOT_BE_EMPTY.on(entry))
|
||||
}
|
||||
else if (!isValidJavaFqName(value)) {
|
||||
} else if (!isValidJavaFqName(value)) {
|
||||
trace.report(ErrorsJvm.JVM_PACKAGE_NAME_MUST_BE_VALID_NAME.on(entry))
|
||||
}
|
||||
else if (entry.containingKtFile.declarations.any {
|
||||
it !is KtFunction && it !is KtProperty && it !is KtTypeAlias
|
||||
}) {
|
||||
} else if (entry.containingKtFile.declarations.any {
|
||||
it !is KtFunction && it !is KtProperty && it !is KtTypeAlias
|
||||
}) {
|
||||
trace.report(ErrorsJvm.JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_FILES_WITH_CLASSES.on(entry))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(NON_SOURCE_REPEATED_ANNOTATION, "Repeatable annotations with non-SOURCE retention are not yet supported");
|
||||
MAP.put(ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES, "Annotation ''@{0}'' is not applicable to the multi-file classes", TO_STRING);
|
||||
|
||||
MAP.put(JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_MULTIFILE_CLASSES, "''@JvmPackageName'' annotation is not supported in multi-file classes");
|
||||
MAP.put(JVM_PACKAGE_NAME_CANNOT_BE_EMPTY, "''@JvmPackageName'' annotation value cannot be empty");
|
||||
MAP.put(JVM_PACKAGE_NAME_MUST_BE_VALID_NAME, "''@JvmPackageName'' annotation value must be a valid dot-qualified name of a package");
|
||||
MAP.put(JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_FILES_WITH_CLASSES, "''@JvmPackageName'' annotation is not supported for files with class declarations");
|
||||
|
||||
@@ -68,7 +68,6 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, FqName> ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtAnnotationEntry> JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_MULTIFILE_CLASSES = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> JVM_PACKAGE_NAME_CANNOT_BE_EMPTY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> JVM_PACKAGE_NAME_MUST_BE_VALID_NAME = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_FILES_WITH_CLASSES = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
@@ -736,7 +737,9 @@ class ControlFlowInformationProvider private constructor(
|
||||
return
|
||||
}
|
||||
!languageVersionSettings.supportsFeature(LanguageFeature.WarningOnMainUnusedParameter) -> {
|
||||
trace.record(UNUSED_MAIN_PARAMETER, element)
|
||||
if (owner.containingClassOrObject == null) {
|
||||
trace.record(UNUSED_MAIN_PARAMETER, element)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +231,8 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotatedExpression> ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> ANNOTATION_USED_AS_ANNOTATION_ARGUMENT = DiagnosticFactory0.create(ERROR);
|
||||
@@ -798,6 +800,8 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory2<KtElement, KotlinType, KotlinType> INCOMPATIBLE_ENUM_COMPARISON =
|
||||
DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<KtElement, KotlinType, KotlinType> INCOMPATIBLE_ENUM_COMPARISON_ERROR =
|
||||
DiagnosticFactory2.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<KtExpression, KotlinType> HAS_NEXT_MISSING = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, KotlinType> HAS_NEXT_FUNCTION_AMBIGUITY = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
@@ -741,6 +741,7 @@ public class DefaultErrorMessages {
|
||||
}, RENDER_TYPE, RENDER_TYPE);
|
||||
|
||||
MAP.put(INCOMPATIBLE_ENUM_COMPARISON, "Comparison of incompatible enums ''{0}'' and ''{1}'' is always unsuccessful", RENDER_TYPE, RENDER_TYPE);
|
||||
MAP.put(INCOMPATIBLE_ENUM_COMPARISON_ERROR, "Comparison of incompatible enums ''{0}'' and ''{1}'' is always unsuccessful", RENDER_TYPE, RENDER_TYPE);
|
||||
|
||||
MAP.put(SENSELESS_COMPARISON, "Condition ''{0}'' is always ''{1}''", ELEMENT_TEXT, TO_STRING);
|
||||
MAP.put(SENSELESS_NULL_IN_WHEN, "Expression under 'when' is never equal to null");
|
||||
@@ -866,6 +867,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_CONST, "An annotation argument must be a compile-time constant");
|
||||
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST, "An enum annotation argument must be a enum constant");
|
||||
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL, "An annotation argument must be a class literal (T::class)");
|
||||
MAP.put(ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER, "Type parameter in a class literal is not allowed in an annotation argument");
|
||||
MAP.put(ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR, "Type parameter in a class literal is deprecated in an annotation argument");
|
||||
MAP.put(ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT, "Default value of annotation parameter must be a compile-time constant");
|
||||
|
||||
MAP.put(ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE,
|
||||
|
||||
@@ -127,7 +127,13 @@ class ConstantExpressionEvaluator(
|
||||
val descriptor = expressionType.constructor.declarationDescriptor
|
||||
val diagnosticFactory = when {
|
||||
DescriptorUtils.isEnumClass(descriptor) -> Errors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
|
||||
descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor) -> Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||
descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor) -> {
|
||||
if (isTypeParameterOrArrayOfTypeParameter(expressionType.arguments.singleOrNull()?.type)) {
|
||||
Errors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR
|
||||
} else {
|
||||
Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||
}
|
||||
}
|
||||
else -> Errors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||
}
|
||||
|
||||
@@ -177,6 +183,8 @@ class ConstantExpressionEvaluator(
|
||||
} else {
|
||||
trace.report(Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||
}
|
||||
} else if (doubleColonLhs is DoubleColonLHS.Type && isTypeParameterOrArrayOfTypeParameter(doubleColonLhs.type)) {
|
||||
trace.report(Errors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER.on(argumentExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -324,6 +332,13 @@ class ConstantExpressionEvaluator(
|
||||
fun getPossiblyErrorConstant(expression: KtExpression, bindingContext: BindingContext): CompileTimeConstant<*>? {
|
||||
return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression)
|
||||
}
|
||||
|
||||
internal fun isTypeParameterOrArrayOfTypeParameter(type: KotlinType?): Boolean =
|
||||
when {
|
||||
type == null -> false
|
||||
KotlinBuiltIns.isArray(type) -> isTypeParameterOrArrayOfTypeParameter(type.arguments.singleOrNull()?.type)
|
||||
else -> type.constructor.declarationDescriptor is TypeParameterDescriptor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,6 +351,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
private val trace: BindingTrace
|
||||
) : KtVisitor<CompileTimeConstant<*>?, KotlinType>() {
|
||||
private val languageVersionSettings = constantExpressionEvaluator.languageVersionSettings
|
||||
private val builtIns = constantExpressionEvaluator.module.builtIns
|
||||
|
||||
fun evaluate(expression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||
@@ -613,7 +629,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
trace.report(Errors.DIVISION_BY_ZERO.on(parentExpression))
|
||||
|
||||
if ((isIntegerType(argumentForReceiver.value) && isIntegerType(argumentForParameter.value)) ||
|
||||
!constantExpressionEvaluator.languageVersionSettings.supportsFeature(LanguageFeature.DivisionByZeroInConstantExpressions)) {
|
||||
!languageVersionSettings.supportsFeature(LanguageFeature.DivisionByZeroInConstantExpressions)
|
||||
) {
|
||||
return ErrorValue.create("Division by zero").wrap()
|
||||
}
|
||||
}
|
||||
@@ -883,11 +900,19 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
}
|
||||
|
||||
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||
val type = trace.getType(expression)!!
|
||||
if (type.isError) return null
|
||||
val descriptor = type.constructor.declarationDescriptor
|
||||
val kClassType = trace.getType(expression)!!
|
||||
if (kClassType.isError) return null
|
||||
val descriptor = kClassType.constructor.declarationDescriptor
|
||||
if (descriptor !is ClassDescriptor || !KotlinBuiltIns.isKClass(descriptor)) return null
|
||||
return KClassValue.create(type.arguments.first().type)?.wrap()
|
||||
|
||||
val type = kClassType.arguments.singleOrNull()?.type ?: return null
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitTypeParametersInClassLiteralsInAnnotationArguments) &&
|
||||
ConstantExpressionEvaluator.isTypeParameterOrArrayOfTypeParameter(type)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
return KClassValue.create(type)?.wrap()
|
||||
}
|
||||
|
||||
private fun resolveArguments(valueArguments: List<ValueArgument>, expectedType: KotlinType): List<CompileTimeConstant<*>?> {
|
||||
@@ -983,12 +1008,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
parameters: CompileTimeConstant.Parameters,
|
||||
expectedType: KotlinType
|
||||
): CompileTimeConstant<*>? {
|
||||
if (parameters.isUnsignedNumberLiteral &&
|
||||
!checkAccessibilityOfUnsignedTypes(
|
||||
constantExpressionEvaluator.module,
|
||||
constantExpressionEvaluator.languageVersionSettings
|
||||
)
|
||||
) {
|
||||
if (parameters.isUnsignedNumberLiteral && !checkAccessibilityOfUnsignedTypes()) {
|
||||
return UnsignedErrorValueTypeConstant(value, parameters)
|
||||
}
|
||||
|
||||
@@ -1019,8 +1039,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
}.wrap(parameters)
|
||||
}
|
||||
|
||||
private fun checkAccessibilityOfUnsignedTypes(module: ModuleDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||
val uInt = module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uInt) ?: return false
|
||||
private fun checkAccessibilityOfUnsignedTypes(): Boolean {
|
||||
val uInt = constantExpressionEvaluator.module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uInt) ?: return false
|
||||
val accessibility = uInt.checkSinceKotlinVersionAccessibility(languageVersionSettings)
|
||||
// Case `NotAccessibleButWasExperimental` will be checked later in `checkExperimentalityOfConstantLiteral`
|
||||
return accessibility is SinceKotlinAccessibility.Accessible
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.lazy.data;
|
||||
|
||||
import kotlin.DeprecationLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.psi.KtClass;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
@@ -23,8 +24,18 @@ import org.jetbrains.kotlin.psi.KtObjectDeclaration;
|
||||
|
||||
public class KtClassInfoUtil {
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #createClassOrObjectInfo(KtClassOrObject)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@kotlin.Deprecated(message = "Use createClassOrObjectInfo(KtClassOrObject) instead", level = DeprecationLevel.ERROR)
|
||||
@NotNull
|
||||
public static KtClassOrObjectInfo<? extends KtClassOrObject> createClassLikeInfo(@NotNull KtClassOrObject classOrObject) {
|
||||
public static KtClassLikeInfo createClassLikeInfo(@NotNull KtClassOrObject classOrObject) {
|
||||
return createClassOrObjectInfo(classOrObject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static KtClassOrObjectInfo<? extends KtClassOrObject> createClassOrObjectInfo(@NotNull KtClassOrObject classOrObject) {
|
||||
if (classOrObject instanceof KtClass) {
|
||||
return new KtClassInfo((KtClass) classOrObject);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ abstract class AbstractPsiBasedDeclarationProvider(storageManager: StorageManage
|
||||
is KtTypeAlias ->
|
||||
typeAliases.put(declaration.nameAsName.safeNameForLazyResolve(), declaration)
|
||||
is KtClassOrObject ->
|
||||
classesAndObjects.put(declaration.nameAsName.safeNameForLazyResolve(), KtClassInfoUtil.createClassLikeInfo(declaration))
|
||||
classesAndObjects.put(declaration.nameAsName.safeNameForLazyResolve(), KtClassInfoUtil.createClassOrObjectInfo(declaration))
|
||||
is KtScript ->
|
||||
scripts.put(KtScriptInfo(declaration).script.nameAsName, KtScriptInfo(declaration))
|
||||
is KtDestructuringDeclaration -> {
|
||||
|
||||
@@ -18,9 +18,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase;
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -454,7 +452,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
@Nullable
|
||||
private static KtClassLikeInfo getCompanionObjectInfo(@Nullable KtObjectDeclaration companionObject) {
|
||||
if (companionObject != null) {
|
||||
return KtClassInfoUtil.createClassLikeInfo(companionObject);
|
||||
return KtClassInfoUtil.createClassOrObjectInfo(companionObject);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.CallHandle;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -41,11 +40,6 @@ public class TypeIntersector {
|
||||
return intersectTypes(new LinkedHashSet<>(Arrays.asList(typeA, typeB))) == null;
|
||||
}
|
||||
|
||||
public static boolean isIncompatibleEnums(@NotNull KotlinType typeA, @NotNull KotlinType typeB) {
|
||||
if (!TypeUtilsKt.isEnum(typeA) || !TypeUtilsKt.isEnum(typeB)) return false;
|
||||
return !typeA.getConstructor().equals(typeB.getConstructor());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KotlinType intersectTypes(@NotNull Collection<KotlinType> types) {
|
||||
assert !types.isEmpty() : "Attempting to intersect empty collection of types, this case should be dealt with on the call site.";
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
|
||||
fun checkEnumsForCompatibility(context: ExpressionTypingContext, reportOn: KtElement, typeA: KotlinType, typeB: KotlinType) {
|
||||
if (isIncompatibleEnums(typeA, typeB)) {
|
||||
val diagnostic = if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitComparisonOfIncompatibleEnums)) {
|
||||
Errors.INCOMPATIBLE_ENUM_COMPARISON_ERROR
|
||||
} else {
|
||||
Errors.INCOMPATIBLE_ENUM_COMPARISON
|
||||
}
|
||||
|
||||
context.trace.report(diagnostic.on(reportOn, typeA, typeB))
|
||||
}
|
||||
}
|
||||
|
||||
private fun isIncompatibleEnums(typeA: KotlinType, typeB: KotlinType): Boolean {
|
||||
if (!typeA.isEnum() && !typeB.isEnum()) return false
|
||||
if (TypeUtils.isNullableType(typeA) && TypeUtils.isNullableType(typeB)) return false
|
||||
|
||||
// TODO: remove this line once KT-30266 will be fixed
|
||||
// For now, this check is needed as isSubClass contains bug wrt Nothing
|
||||
if (typeA.isNothingOrNullableNothing() || typeB.isNothingOrNullableNothing()) return false
|
||||
|
||||
val representativeTypeA = typeA.representativeTypeForTypeParameter()
|
||||
val representativeTypeB = typeB.representativeTypeForTypeParameter()
|
||||
|
||||
val classA = representativeTypeA.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
val classB = representativeTypeB.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
|
||||
return !DescriptorUtils.isSubclass(classA, classB) && !DescriptorUtils.isSubclass(classB, classA)
|
||||
}
|
||||
|
||||
private fun KotlinType.representativeTypeForTypeParameter(): KotlinType {
|
||||
val descriptor = constructor.declarationDescriptor
|
||||
return if (descriptor is TypeParameterDescriptor) descriptor.representativeUpperBound else this
|
||||
}
|
||||
@@ -1430,10 +1430,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (rightType != null) {
|
||||
if (TypeIntersector.isIntersectionEmpty(leftType, rightType)) {
|
||||
context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
|
||||
} else {
|
||||
EnumCompatibilityCheckerKt.checkEnumsForCompatibility(context, expression, leftType, rightType);
|
||||
}
|
||||
else if (TypeIntersector.isIncompatibleEnums(leftType, rightType)) {
|
||||
context.trace.report(INCOMPATIBLE_ENUM_COMPARISON.on(expression, leftType, rightType));
|
||||
}
|
||||
|
||||
|
||||
SenselessComparisonChecker.checkSenselessComparisonWithNull(
|
||||
expression, left, right, context,
|
||||
|
||||
@@ -169,7 +169,7 @@ class LocalClassDescriptorHolder(
|
||||
},
|
||||
containingDeclaration,
|
||||
classOrObject.nameAsSafeName,
|
||||
KtClassInfoUtil.createClassLikeInfo(classOrObject),
|
||||
KtClassInfoUtil.createClassOrObjectInfo(classOrObject),
|
||||
classOrObject.hasModifier(KtTokens.EXTERNAL_KEYWORD)
|
||||
)
|
||||
writableScope?.addClassifierDescriptor(classDescriptor!!)
|
||||
|
||||
@@ -684,9 +684,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
||||
return
|
||||
}
|
||||
|
||||
if (TypeIntersector.isIncompatibleEnums(type, subjectType)) {
|
||||
context.trace.report(INCOMPATIBLE_ENUM_COMPARISON.on(reportErrorOn, subjectType, type))
|
||||
}
|
||||
checkEnumsForCompatibility(context, reportErrorOn, subjectType, type)
|
||||
|
||||
// check if the pattern is essentially a 'null' expression
|
||||
if (KotlinBuiltIns.isNullableNothing(type) && !TypeUtils.isNullableType(subjectType)) {
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.io.File
|
||||
import java.io.ObjectOutputStream
|
||||
|
||||
fun makeIncrementally(
|
||||
cachesDir: File,
|
||||
@@ -126,6 +127,8 @@ class IncrementalJvmCompilerRunner(
|
||||
override fun destinationDir(args: K2JVMCompilerArguments): File =
|
||||
args.destinationAsFile
|
||||
|
||||
private var dirtyClasspathChanges: Collection<FqName> = emptySet<FqName>()
|
||||
|
||||
private val psiFileFactory: PsiFileFactory by lazy {
|
||||
val rootDisposable = Disposer.newDisposable()
|
||||
val configuration = CompilerConfiguration()
|
||||
@@ -163,6 +166,7 @@ class IncrementalJvmCompilerRunner(
|
||||
}
|
||||
is ChangesEither.Known -> {
|
||||
dirtyFiles.addByDirtySymbols(classpathChanges.lookupSymbols)
|
||||
dirtyClasspathChanges = classpathChanges.fqNames
|
||||
dirtyFiles.addByDirtyClasses(classpathChanges.fqNames)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
package org.jetbrains.kotlin.backend.common.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
@@ -41,13 +41,20 @@ abstract class WrappedDeclarationDescriptor<T : IrDeclaration>(annotations: Anno
|
||||
|
||||
private val annotationsFromOwner by lazy {
|
||||
val ownerAnnotations = (owner as? IrAnnotationContainer)?.annotations ?: return@lazy Annotations.EMPTY
|
||||
Annotations.create(ownerAnnotations.map { call ->
|
||||
AnnotationDescriptorImpl(
|
||||
call.symbol.owner.parentAsClass.defaultType.toKotlinType(),
|
||||
call.symbol.owner.valueParameters.associate { it.name to call.getValueArgument(it.index)!!.toConstantValue() },
|
||||
/*TODO*/ SourceElement.NO_SOURCE
|
||||
)
|
||||
})
|
||||
Annotations.create(ownerAnnotations.map { it.toAnnotationDescriptor() })
|
||||
}
|
||||
|
||||
private fun IrCall.toAnnotationDescriptor(): AnnotationDescriptor {
|
||||
assert(symbol.owner is IrConstructor && symbol.owner.parentAsClass.isAnnotationClass) {
|
||||
"Expected call to constructor of annotation class but was: ${this.dump()}"
|
||||
}
|
||||
return AnnotationDescriptorImpl(
|
||||
symbol.owner.parentAsClass.defaultType.toKotlinType(),
|
||||
symbol.owner.valueParameters.map { it.name to getValueArgument(it.index) }
|
||||
.filter { it.second != null }
|
||||
.associate { it.first to it.second!!.toConstantValue() },
|
||||
/*TODO*/ SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrElement.toConstantValue(): ConstantValue<*> {
|
||||
@@ -77,7 +84,9 @@ abstract class WrappedDeclarationDescriptor<T : IrDeclaration>(annotations: Anno
|
||||
|
||||
this is IrClassReference -> KClassValue(classType.classifierOrFail.descriptor.classId!!, /*TODO*/0)
|
||||
|
||||
else -> error("$this is not expected")
|
||||
this is IrCall -> AnnotationValue(this.toAnnotationDescriptor())
|
||||
|
||||
else -> error("$this is not expected: ${this.dump()}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +592,7 @@ open class WrappedClassDescriptor(
|
||||
private val _typeConstructor: TypeConstructor by lazy {
|
||||
LazyTypeConstructor(
|
||||
this,
|
||||
{ emptyList() },
|
||||
{ owner.typeParameters.map { it.descriptor } },
|
||||
{ owner.superTypes.map { it.toKotlinType() } },
|
||||
LockBasedStorageManager.NO_LOCKS
|
||||
)
|
||||
|
||||
@@ -234,7 +234,7 @@ open class DefaultParameterInjector(
|
||||
type = context.irBuiltIns.unitType,
|
||||
symbol = symbolForCall as IrConstructorSymbol,
|
||||
descriptor = symbolForCall.descriptor,
|
||||
typeArgumentsCount = symbolForCall.owner.typeParameters.size
|
||||
typeArgumentsCount = expression.typeArgumentsCount
|
||||
)
|
||||
.apply {
|
||||
copyTypeArgumentsFrom(expression)
|
||||
|
||||
@@ -99,7 +99,7 @@ class IrInlineCodegen(
|
||||
parameter.type.isExtensionFunctionType
|
||||
).also { lambda ->
|
||||
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
|
||||
closureInfo.lambda = lambda
|
||||
closureInfo.functionalArgument = lambda
|
||||
expressionMap[closureInfo.index] = lambda
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class IrSourceCompilerForInline(
|
||||
get() = OwnerKind.getMemberOwnerKind(callElement.descriptor.containingDeclaration)
|
||||
|
||||
override val inlineCallSiteInfo: InlineCallSiteInfo
|
||||
get() = InlineCallSiteInfo("TODO", null, null)
|
||||
get() = InlineCallSiteInfo("TODO", null, null, false)
|
||||
|
||||
override val lazySourceMapper: DefaultSourceMapper
|
||||
get() = codegen.classCodegen.getOrCreateSourceMapper()
|
||||
|
||||
@@ -271,3 +271,42 @@ fun IrBuilderWithScope.irSetField(receiver: IrExpression, irField: IrField, valu
|
||||
value = value,
|
||||
type = context.irBuiltIns.unitType
|
||||
)
|
||||
|
||||
inline fun IrBuilderWithScope.irBlock(
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset,
|
||||
origin: IrStatementOrigin? = null,
|
||||
resultType: IrType? = null,
|
||||
body: IrBlockBuilder.() -> Unit
|
||||
): IrExpression =
|
||||
IrBlockBuilder(
|
||||
context, scope,
|
||||
startOffset,
|
||||
endOffset,
|
||||
origin, resultType
|
||||
).block(body)
|
||||
|
||||
inline fun IrBuilderWithScope.irComposite(
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset,
|
||||
origin: IrStatementOrigin? = null,
|
||||
resultType: IrType? = null,
|
||||
body: IrBlockBuilder.() -> Unit
|
||||
): IrExpression =
|
||||
IrBlockBuilder(
|
||||
context, scope,
|
||||
startOffset,
|
||||
endOffset,
|
||||
origin, resultType, true
|
||||
).block(body)
|
||||
|
||||
inline fun IrBuilderWithScope.irBlockBody(
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset,
|
||||
body: IrBlockBodyBuilder.() -> Unit
|
||||
): IrBlockBody =
|
||||
IrBlockBodyBuilder(
|
||||
context, scope,
|
||||
startOffset,
|
||||
endOffset
|
||||
).blockBody(body)
|
||||
|
||||
@@ -143,8 +143,7 @@ fun <T : IrBuilder> T.at(startOffset: Int, endOffset: Int) = apply {
|
||||
}
|
||||
|
||||
inline fun IrGeneratorWithScope.irBlock(
|
||||
startOffset: Int = UNDEFINED_OFFSET,
|
||||
endOffset: Int = UNDEFINED_OFFSET,
|
||||
startOffset: Int, endOffset: Int,
|
||||
origin: IrStatementOrigin? = null,
|
||||
resultType: IrType? = null,
|
||||
body: IrBlockBuilder.() -> Unit
|
||||
@@ -157,8 +156,7 @@ inline fun IrGeneratorWithScope.irBlock(
|
||||
).block(body)
|
||||
|
||||
inline fun IrGeneratorWithScope.irComposite(
|
||||
startOffset: Int = UNDEFINED_OFFSET,
|
||||
endOffset: Int = UNDEFINED_OFFSET,
|
||||
startOffset: Int, endOffset: Int,
|
||||
origin: IrStatementOrigin? = null,
|
||||
resultType: IrType? = null,
|
||||
body: IrBlockBuilder.() -> Unit
|
||||
@@ -171,7 +169,7 @@ inline fun IrGeneratorWithScope.irComposite(
|
||||
).block(body)
|
||||
|
||||
inline fun IrGeneratorWithScope.irBlockBody(
|
||||
startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET,
|
||||
startOffset: Int, endOffset: Int,
|
||||
body: IrBlockBodyBuilder.() -> Unit
|
||||
): IrBlockBody =
|
||||
IrBlockBodyBuilder(
|
||||
|
||||
@@ -34,20 +34,20 @@ public interface KtNodeTypes {
|
||||
IElementType OBJECT_DECLARATION = KtStubElementTypes.OBJECT_DECLARATION;
|
||||
IElementType TYPEALIAS = KtStubElementTypes.TYPEALIAS;
|
||||
|
||||
IElementType ENUM_ENTRY = KtStubElementTypes.ENUM_ENTRY;
|
||||
IElementType CLASS_INITIALIZER = KtStubElementTypes.CLASS_INITIALIZER;
|
||||
IElementType SCRIPT_INITIALIZER = new KtNodeType("SCRIPT_INITIALIZER", KtScriptInitializer.class);
|
||||
IElementType ENUM_ENTRY = KtStubElementTypes.ENUM_ENTRY;
|
||||
IElementType CLASS_INITIALIZER = KtStubElementTypes.CLASS_INITIALIZER;
|
||||
IElementType SCRIPT_INITIALIZER = new KtNodeType("SCRIPT_INITIALIZER", KtScriptInitializer.class);
|
||||
IElementType SECONDARY_CONSTRUCTOR = KtStubElementTypes.SECONDARY_CONSTRUCTOR;
|
||||
IElementType PRIMARY_CONSTRUCTOR = KtStubElementTypes.PRIMARY_CONSTRUCTOR;
|
||||
|
||||
IElementType TYPE_PARAMETER_LIST = KtStubElementTypes.TYPE_PARAMETER_LIST;
|
||||
IElementType TYPE_PARAMETER = KtStubElementTypes.TYPE_PARAMETER;
|
||||
IElementType SUPER_TYPE_LIST = KtStubElementTypes.SUPER_TYPE_LIST;
|
||||
IElementType DELEGATED_SUPER_TYPE_ENTRY = KtStubElementTypes.DELEGATED_SUPER_TYPE_ENTRY;
|
||||
IElementType SUPER_TYPE_CALL_ENTRY = KtStubElementTypes.SUPER_TYPE_CALL_ENTRY;
|
||||
IElementType SUPER_TYPE_ENTRY = KtStubElementTypes.SUPER_TYPE_ENTRY;
|
||||
KtNodeType PROPERTY_DELEGATE = new KtNodeType("PROPERTY_DELEGATE", KtPropertyDelegate.class);
|
||||
IElementType CONSTRUCTOR_CALLEE = KtStubElementTypes.CONSTRUCTOR_CALLEE;
|
||||
IElementType TYPE_PARAMETER_LIST = KtStubElementTypes.TYPE_PARAMETER_LIST;
|
||||
IElementType TYPE_PARAMETER = KtStubElementTypes.TYPE_PARAMETER;
|
||||
IElementType SUPER_TYPE_LIST = KtStubElementTypes.SUPER_TYPE_LIST;
|
||||
IElementType DELEGATED_SUPER_TYPE_ENTRY = KtStubElementTypes.DELEGATED_SUPER_TYPE_ENTRY;
|
||||
IElementType SUPER_TYPE_CALL_ENTRY = KtStubElementTypes.SUPER_TYPE_CALL_ENTRY;
|
||||
IElementType SUPER_TYPE_ENTRY = KtStubElementTypes.SUPER_TYPE_ENTRY;
|
||||
IElementType PROPERTY_DELEGATE = new KtNodeType("PROPERTY_DELEGATE", KtPropertyDelegate.class);
|
||||
IElementType CONSTRUCTOR_CALLEE = KtStubElementTypes.CONSTRUCTOR_CALLEE;
|
||||
IElementType VALUE_PARAMETER_LIST = KtStubElementTypes.VALUE_PARAMETER_LIST;
|
||||
IElementType VALUE_PARAMETER = KtStubElementTypes.VALUE_PARAMETER;
|
||||
|
||||
@@ -72,20 +72,17 @@ public interface KtNodeTypes {
|
||||
IElementType DYNAMIC_TYPE = KtStubElementTypes.DYNAMIC_TYPE;
|
||||
IElementType FUNCTION_TYPE = KtStubElementTypes.FUNCTION_TYPE;
|
||||
IElementType FUNCTION_TYPE_RECEIVER = KtStubElementTypes.FUNCTION_TYPE_RECEIVER;
|
||||
KtNodeType SELF_TYPE = new KtNodeType("SELF_TYPE", KtSelfType.class);
|
||||
IElementType NULLABLE_TYPE = KtStubElementTypes.NULLABLE_TYPE;
|
||||
IElementType TYPE_PROJECTION = KtStubElementTypes.TYPE_PROJECTION;
|
||||
|
||||
// TODO: review
|
||||
IElementType PROPERTY_ACCESSOR = KtStubElementTypes.PROPERTY_ACCESSOR;
|
||||
IElementType INITIALIZER_LIST = KtStubElementTypes.INITIALIZER_LIST;
|
||||
IElementType TYPE_CONSTRAINT_LIST = KtStubElementTypes.TYPE_CONSTRAINT_LIST;
|
||||
IElementType TYPE_CONSTRAINT = KtStubElementTypes.TYPE_CONSTRAINT;
|
||||
|
||||
IElementType CONSTRUCTOR_DELEGATION_CALL = new KtNodeType.KtLeftBoundNodeType("CONSTRUCTOR_DELEGATION_CALL", KtConstructorDelegationCall.class);
|
||||
KtNodeType CONSTRUCTOR_DELEGATION_REFERENCE = new KtNodeType.KtLeftBoundNodeType("CONSTRUCTOR_DELEGATION_REFERENCE", KtConstructorDelegationReferenceExpression.class);
|
||||
IElementType CONSTRUCTOR_DELEGATION_REFERENCE = new KtNodeType.KtLeftBoundNodeType("CONSTRUCTOR_DELEGATION_REFERENCE", KtConstructorDelegationReferenceExpression.class);
|
||||
|
||||
// TODO: Not sure if we need separate NT for each kind of constants
|
||||
IElementType NULL = KtStubElementTypes.NULL;
|
||||
IElementType BOOLEAN_CONSTANT = KtStubElementTypes.BOOLEAN_CONSTANT;
|
||||
IElementType FLOAT_CONSTANT = KtStubElementTypes.FLOAT_CONSTANT;
|
||||
@@ -98,63 +95,63 @@ public interface KtNodeTypes {
|
||||
IElementType LITERAL_STRING_TEMPLATE_ENTRY = KtStubElementTypes.LITERAL_STRING_TEMPLATE_ENTRY;
|
||||
IElementType ESCAPE_STRING_TEMPLATE_ENTRY = KtStubElementTypes.ESCAPE_STRING_TEMPLATE_ENTRY;
|
||||
|
||||
KtNodeType PARENTHESIZED = new KtNodeType("PARENTHESIZED", KtParenthesizedExpression.class);
|
||||
KtNodeType RETURN = new KtNodeType("RETURN", KtReturnExpression.class);
|
||||
KtNodeType THROW = new KtNodeType("THROW", KtThrowExpression.class);
|
||||
KtNodeType CONTINUE = new KtNodeType("CONTINUE", KtContinueExpression.class);
|
||||
KtNodeType BREAK = new KtNodeType("BREAK", KtBreakExpression.class);
|
||||
KtNodeType IF = new KtNodeType("IF", KtIfExpression.class);
|
||||
KtNodeType CONDITION = new KtNodeType("CONDITION", KtContainerNode.class);
|
||||
KtNodeType THEN = new KtNodeType("THEN", KtContainerNodeForControlStructureBody.class);
|
||||
KtNodeType ELSE = new KtNodeType("ELSE", KtContainerNodeForControlStructureBody.class);
|
||||
KtNodeType TRY = new KtNodeType("TRY", KtTryExpression.class);
|
||||
KtNodeType CATCH = new KtNodeType("CATCH", KtCatchClause.class);
|
||||
KtNodeType FINALLY = new KtNodeType("FINALLY", KtFinallySection.class);
|
||||
KtNodeType FOR = new KtNodeType("FOR", KtForExpression.class);
|
||||
KtNodeType WHILE = new KtNodeType("WHILE", KtWhileExpression.class);
|
||||
KtNodeType DO_WHILE = new KtNodeType("DO_WHILE", KtDoWhileExpression.class);
|
||||
KtNodeType LOOP_RANGE = new KtNodeType("LOOP_RANGE", KtContainerNode.class);
|
||||
KtNodeType BODY = new KtNodeType("BODY", KtContainerNodeForControlStructureBody.class);
|
||||
KtNodeType BLOCK = new KtNodeType("BLOCK", KtBlockExpression.class);
|
||||
IElementType PARENTHESIZED = new KtNodeType("PARENTHESIZED", KtParenthesizedExpression.class);
|
||||
IElementType RETURN = new KtNodeType("RETURN", KtReturnExpression.class);
|
||||
IElementType THROW = new KtNodeType("THROW", KtThrowExpression.class);
|
||||
IElementType CONTINUE = new KtNodeType("CONTINUE", KtContinueExpression.class);
|
||||
IElementType BREAK = new KtNodeType("BREAK", KtBreakExpression.class);
|
||||
IElementType IF = new KtNodeType("IF", KtIfExpression.class);
|
||||
IElementType CONDITION = new KtNodeType("CONDITION", KtContainerNode.class);
|
||||
IElementType THEN = new KtNodeType("THEN", KtContainerNodeForControlStructureBody.class);
|
||||
IElementType ELSE = new KtNodeType("ELSE", KtContainerNodeForControlStructureBody.class);
|
||||
IElementType TRY = new KtNodeType("TRY", KtTryExpression.class);
|
||||
IElementType CATCH = new KtNodeType("CATCH", KtCatchClause.class);
|
||||
IElementType FINALLY = new KtNodeType("FINALLY", KtFinallySection.class);
|
||||
IElementType FOR = new KtNodeType("FOR", KtForExpression.class);
|
||||
IElementType WHILE = new KtNodeType("WHILE", KtWhileExpression.class);
|
||||
IElementType DO_WHILE = new KtNodeType("DO_WHILE", KtDoWhileExpression.class);
|
||||
IElementType LOOP_RANGE = new KtNodeType("LOOP_RANGE", KtContainerNode.class);
|
||||
IElementType BODY = new KtNodeType("BODY", KtContainerNodeForControlStructureBody.class);
|
||||
IElementType BLOCK = new KtNodeType("BLOCK", KtBlockExpression.class);
|
||||
|
||||
IElementType LAMBDA_EXPRESSION = new LambdaExpressionElementType();
|
||||
|
||||
KtNodeType FUNCTION_LITERAL = new KtNodeType("FUNCTION_LITERAL", KtFunctionLiteral.class);
|
||||
KtNodeType ANNOTATED_EXPRESSION = new KtNodeType("ANNOTATED_EXPRESSION", KtAnnotatedExpression.class);
|
||||
IElementType FUNCTION_LITERAL = new KtNodeType("FUNCTION_LITERAL", KtFunctionLiteral.class);
|
||||
IElementType ANNOTATED_EXPRESSION = new KtNodeType("ANNOTATED_EXPRESSION", KtAnnotatedExpression.class);
|
||||
|
||||
IElementType REFERENCE_EXPRESSION = KtStubElementTypes.REFERENCE_EXPRESSION;
|
||||
IElementType ENUM_ENTRY_SUPERCLASS_REFERENCE_EXPRESSION = KtStubElementTypes.ENUM_ENTRY_SUPERCLASS_REFERENCE_EXPRESSION;
|
||||
KtNodeType OPERATION_REFERENCE = new KtNodeType("OPERATION_REFERENCE", KtOperationReferenceExpression.class);
|
||||
KtNodeType LABEL = new KtNodeType("LABEL", KtLabelReferenceExpression.class);
|
||||
IElementType OPERATION_REFERENCE = new KtNodeType("OPERATION_REFERENCE", KtOperationReferenceExpression.class);
|
||||
IElementType LABEL = new KtNodeType("LABEL", KtLabelReferenceExpression.class);
|
||||
|
||||
KtNodeType LABEL_QUALIFIER = new KtNodeType("LABEL_QUALIFIER", KtContainerNode.class);
|
||||
IElementType LABEL_QUALIFIER = new KtNodeType("LABEL_QUALIFIER", KtContainerNode.class);
|
||||
|
||||
KtNodeType THIS_EXPRESSION = new KtNodeType("THIS_EXPRESSION", KtThisExpression.class);
|
||||
KtNodeType SUPER_EXPRESSION = new KtNodeType("SUPER_EXPRESSION", KtSuperExpression.class);
|
||||
KtNodeType BINARY_EXPRESSION = new KtNodeType("BINARY_EXPRESSION", KtBinaryExpression.class);
|
||||
KtNodeType BINARY_WITH_TYPE = new KtNodeType("BINARY_WITH_TYPE", KtBinaryExpressionWithTypeRHS.class);
|
||||
KtNodeType IS_EXPRESSION = new KtNodeType("IS_EXPRESSION", KtIsExpression.class); // TODO:
|
||||
KtNodeType PREFIX_EXPRESSION = new KtNodeType("PREFIX_EXPRESSION", KtPrefixExpression.class);
|
||||
KtNodeType POSTFIX_EXPRESSION = new KtNodeType("POSTFIX_EXPRESSION", KtPostfixExpression.class);
|
||||
KtNodeType LABELED_EXPRESSION = new KtNodeType("LABELED_EXPRESSION", KtLabeledExpression.class);
|
||||
KtNodeType CALL_EXPRESSION = new KtNodeType("CALL_EXPRESSION", KtCallExpression.class);
|
||||
KtNodeType ARRAY_ACCESS_EXPRESSION = new KtNodeType("ARRAY_ACCESS_EXPRESSION", KtArrayAccessExpression.class);
|
||||
KtNodeType INDICES = new KtNodeType("INDICES", KtContainerNode.class);
|
||||
IElementType DOT_QUALIFIED_EXPRESSION = KtStubElementTypes.DOT_QUALIFIED_EXPRESSION;
|
||||
KtNodeType CALLABLE_REFERENCE_EXPRESSION = new KtNodeType("CALLABLE_REFERENCE_EXPRESSION", KtCallableReferenceExpression.class);
|
||||
KtNodeType CLASS_LITERAL_EXPRESSION = new KtNodeType("CLASS_LITERAL_EXPRESSION", KtClassLiteralExpression.class);
|
||||
KtNodeType SAFE_ACCESS_EXPRESSION = new KtNodeType("SAFE_ACCESS_EXPRESSION", KtSafeQualifiedExpression.class);
|
||||
IElementType THIS_EXPRESSION = new KtNodeType("THIS_EXPRESSION", KtThisExpression.class);
|
||||
IElementType SUPER_EXPRESSION = new KtNodeType("SUPER_EXPRESSION", KtSuperExpression.class);
|
||||
IElementType BINARY_EXPRESSION = new KtNodeType("BINARY_EXPRESSION", KtBinaryExpression.class);
|
||||
IElementType BINARY_WITH_TYPE = new KtNodeType("BINARY_WITH_TYPE", KtBinaryExpressionWithTypeRHS.class);
|
||||
IElementType IS_EXPRESSION = new KtNodeType("IS_EXPRESSION", KtIsExpression.class);
|
||||
IElementType PREFIX_EXPRESSION = new KtNodeType("PREFIX_EXPRESSION", KtPrefixExpression.class);
|
||||
IElementType POSTFIX_EXPRESSION = new KtNodeType("POSTFIX_EXPRESSION", KtPostfixExpression.class);
|
||||
IElementType LABELED_EXPRESSION = new KtNodeType("LABELED_EXPRESSION", KtLabeledExpression.class);
|
||||
IElementType CALL_EXPRESSION = new KtNodeType("CALL_EXPRESSION", KtCallExpression.class);
|
||||
IElementType ARRAY_ACCESS_EXPRESSION = new KtNodeType("ARRAY_ACCESS_EXPRESSION", KtArrayAccessExpression.class);
|
||||
IElementType INDICES = new KtNodeType("INDICES", KtContainerNode.class);
|
||||
IElementType DOT_QUALIFIED_EXPRESSION = KtStubElementTypes.DOT_QUALIFIED_EXPRESSION;
|
||||
IElementType CALLABLE_REFERENCE_EXPRESSION = new KtNodeType("CALLABLE_REFERENCE_EXPRESSION", KtCallableReferenceExpression.class);
|
||||
IElementType CLASS_LITERAL_EXPRESSION = new KtNodeType("CLASS_LITERAL_EXPRESSION", KtClassLiteralExpression.class);
|
||||
IElementType SAFE_ACCESS_EXPRESSION = new KtNodeType("SAFE_ACCESS_EXPRESSION", KtSafeQualifiedExpression.class);
|
||||
|
||||
KtNodeType OBJECT_LITERAL = new KtNodeType("OBJECT_LITERAL", KtObjectLiteralExpression.class);
|
||||
IElementType OBJECT_LITERAL = new KtNodeType("OBJECT_LITERAL", KtObjectLiteralExpression.class);
|
||||
|
||||
KtNodeType WHEN = new KtNodeType("WHEN", KtWhenExpression.class);
|
||||
KtNodeType WHEN_ENTRY = new KtNodeType("WHEN_ENTRY", KtWhenEntry.class);
|
||||
IElementType WHEN = new KtNodeType("WHEN", KtWhenExpression.class);
|
||||
IElementType WHEN_ENTRY = new KtNodeType("WHEN_ENTRY", KtWhenEntry.class);
|
||||
|
||||
KtNodeType WHEN_CONDITION_IN_RANGE = new KtNodeType("WHEN_CONDITION_IN_RANGE", KtWhenConditionInRange.class);
|
||||
KtNodeType WHEN_CONDITION_IS_PATTERN = new KtNodeType("WHEN_CONDITION_IS_PATTERN", KtWhenConditionIsPattern.class);
|
||||
KtNodeType WHEN_CONDITION_EXPRESSION = new KtNodeType("WHEN_CONDITION_WITH_EXPRESSION", KtWhenConditionWithExpression.class);
|
||||
IElementType WHEN_CONDITION_IN_RANGE = new KtNodeType("WHEN_CONDITION_IN_RANGE", KtWhenConditionInRange.class);
|
||||
IElementType WHEN_CONDITION_IS_PATTERN = new KtNodeType("WHEN_CONDITION_IS_PATTERN", KtWhenConditionIsPattern.class);
|
||||
IElementType WHEN_CONDITION_EXPRESSION = new KtNodeType("WHEN_CONDITION_WITH_EXPRESSION", KtWhenConditionWithExpression.class);
|
||||
|
||||
KtNodeType COLLECTION_LITERAL_EXPRESSION = new KtNodeType("COLLECTION_LITERAL_EXPRESSION", KtCollectionLiteralExpression.class);
|
||||
IElementType COLLECTION_LITERAL_EXPRESSION = new KtNodeType("COLLECTION_LITERAL_EXPRESSION", KtCollectionLiteralExpression.class);
|
||||
|
||||
IElementType PACKAGE_DIRECTIVE = KtStubElementTypes.PACKAGE_DIRECTIVE;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.kdoc.parser
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
|
||||
enum class KDocKnownTag private constructor(val isReferenceRequired: Boolean, val isSectionStart: Boolean) {
|
||||
enum class KDocKnownTag(val isReferenceRequired: Boolean, val isSectionStart: Boolean) {
|
||||
AUTHOR(false, false),
|
||||
THROWS(true, false),
|
||||
EXCEPTION(true, false),
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.KtNodeType;
|
||||
import org.jetbrains.kotlin.KtNodeTypes;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
@@ -155,7 +154,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
|
||||
AS(AS_KEYWORD, AS_SAFE) {
|
||||
@Override
|
||||
public KtNodeType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
public IElementType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
parser.myKotlinParsing.parseTypeRef();
|
||||
return BINARY_WITH_TYPE;
|
||||
}
|
||||
@@ -173,7 +172,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
ELVIS(KtTokens.ELVIS),
|
||||
IN_OR_IS(IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS) {
|
||||
@Override
|
||||
public KtNodeType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
public IElementType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
if (operation == IS_KEYWORD || operation == NOT_IS) {
|
||||
parser.myKotlinParsing.parseTypeRef();
|
||||
return IS_EXPRESSION;
|
||||
@@ -216,7 +215,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* @param parser the parser object
|
||||
* @return node type of the result
|
||||
*/
|
||||
public KtNodeType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
public IElementType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
parseHigherPrecedence(parser);
|
||||
return BINARY_EXPRESSION;
|
||||
}
|
||||
@@ -316,7 +315,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
|
||||
parseOperationReference();
|
||||
|
||||
KtNodeType resultType = precedence.parseRightHandSide(operation, this);
|
||||
IElementType resultType = precedence.parseRightHandSide(operation, this);
|
||||
expression.done(resultType);
|
||||
expression = expression.precede();
|
||||
}
|
||||
@@ -1008,7 +1007,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
parseAsCollectionLiteralExpression(COLLECTION_LITERAL_EXPRESSION, true, "Expecting an element");
|
||||
}
|
||||
|
||||
private void parseAsCollectionLiteralExpression(KtNodeType nodeType, boolean canBeEmpty, String missingElementErrorMessage) {
|
||||
private void parseAsCollectionLiteralExpression(IElementType nodeType, boolean canBeEmpty, String missingElementErrorMessage) {
|
||||
assert _at(LBRACKET);
|
||||
|
||||
PsiBuilder.Marker innerExpressions = mark();
|
||||
@@ -1627,7 +1626,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* : "continue" getEntryPoint?
|
||||
* : "break" getEntryPoint?
|
||||
*/
|
||||
private void parseJump(KtNodeType type) {
|
||||
private void parseJump(IElementType type) {
|
||||
assert _at(BREAK_KEYWORD) || _at(CONTINUE_KEYWORD);
|
||||
|
||||
PsiBuilder.Marker marker = mark();
|
||||
|
||||
@@ -7,13 +7,13 @@ package org.jetbrains.kotlin.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtNodeType
|
||||
import com.intellij.psi.tree.IElementType
|
||||
|
||||
abstract class KtExpressionImpl(node: ASTNode) : KtElementImpl(node), KtExpression {
|
||||
|
||||
override fun <R, D> accept(visitor: KtVisitor<R, D>, data: D) = visitor.visitExpression(this, data)
|
||||
|
||||
protected fun findExpressionUnder(type: KtNodeType): KtExpression? {
|
||||
protected fun findExpressionUnder(type: IElementType): KtExpression? {
|
||||
val containerNode = findChildByType<KtContainerNode>(type) ?: return null
|
||||
return containerNode.findChildByClass<KtExpression>(KtExpression::class.java)
|
||||
}
|
||||
|
||||
@@ -431,6 +431,9 @@ fun PsiElement.before(element: PsiElement) = textRange.endOffset <= element.text
|
||||
|
||||
inline fun <reified T : PsiElement> PsiElement.getLastParentOfTypeInRow() = parents.takeWhile { it is T }.lastOrNull() as? T
|
||||
|
||||
inline fun <reified T : PsiElement> PsiElement.getLastParentOfTypeInRowWithSelf() = parentsWithSelf
|
||||
.takeWhile { it is T }.lastOrNull() as? T
|
||||
|
||||
fun KtModifierListOwner.hasExpectModifier() = hasModifier(KtTokens.HEADER_KEYWORD) || hasModifier(KtTokens.EXPECT_KEYWORD)
|
||||
fun KtModifierList.hasExpectModifier() = hasModifier(KtTokens.HEADER_KEYWORD) || hasModifier(KtTokens.EXPECT_KEYWORD)
|
||||
|
||||
|
||||
2
compiler/testData/cli/jvm/help.out
vendored
2
compiler/testData/cli/jvm/help.out
vendored
@@ -5,7 +5,7 @@ where possible options include:
|
||||
-include-runtime Include Kotlin runtime in to resulting .jar
|
||||
-java-parameters Generate metadata for Java 1.8 reflection on method parameters
|
||||
-jdk-home <path> Path to JDK home directory to include into classpath, if differs from default JAVA_HOME
|
||||
-jvm-target <version> Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6
|
||||
-jvm-target <version> Target version of the generated JVM bytecode (1.6, 1.8, 9, 10, 11 or 12), default is 1.6
|
||||
-module-name <name> Name of the generated .kotlin_module file
|
||||
-no-jdk Don't include Java runtime into classpath
|
||||
-no-reflect Don't include kotlin-reflect.jar into classpath
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
error: unknown JVM target version: 1.5
|
||||
Supported versions: 1.6, 1.8
|
||||
Supported versions: 1.6, 1.8, 9, 10, 11, 12
|
||||
COMPILATION_ERROR
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
@@ -17,26 +18,22 @@ fun test(name: String, annotations: Array<out Annotation>) {
|
||||
assertEquals(1, annotations.filterIsInstance<Ann>().single().x, "$name[0]")
|
||||
}
|
||||
|
||||
fun testAbsence(name: String, annotations: Array<out Annotation>) {
|
||||
assertEquals(0, annotations.filterIsInstance<Ann>().size, "$name")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val foo = A::class.java.getDeclaredMethods().first { it.getName() == "foo" }
|
||||
test("foo", foo.getDeclaredAnnotations())
|
||||
|
||||
val fooDefault = A::class.java.getDeclaredMethods().first { it.getName() == "foo\$default" }
|
||||
testAbsence("foo\$default", fooDefault.getDeclaredAnnotations())
|
||||
test("foo", foo.getDeclaredAnnotations())
|
||||
|
||||
val (secondary, secondaryDefault) = A::class.java.getDeclaredConstructors().partition { it.getParameterTypes().size == 3 }
|
||||
|
||||
test("secondary", secondary[0].getDeclaredAnnotations())
|
||||
testAbsence("secondary\$default", secondaryDefault[0].getDeclaredAnnotations())
|
||||
test("secondary\$default", secondaryDefault[0].getDeclaredAnnotations())
|
||||
|
||||
val (primary, primaryDefault) = B::class.java.getConstructors().partition { it.getParameterTypes().size == 3 }
|
||||
|
||||
test("primary", primary[0].getDeclaredAnnotations())
|
||||
testAbsence("primary\$default", primaryDefault[0].getDeclaredAnnotations())
|
||||
test("primary\$default", primaryDefault[0].getDeclaredAnnotations())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
192
compiler/testData/codegen/box/coroutines/javaInterop/objectWithSeveralSuspends.kt
vendored
Normal file
192
compiler/testData/codegen/box/coroutines/javaInterop/objectWithSeveralSuspends.kt
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
// CHECK_STATE_MACHINE
|
||||
|
||||
// FILE: inlineMe.kt
|
||||
|
||||
package test
|
||||
|
||||
import helpers.*
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
suspend fun run1()
|
||||
suspend fun run2()
|
||||
}
|
||||
|
||||
inline fun inlineMe(crossinline c: suspend () -> Unit) = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c(); c()
|
||||
}
|
||||
override suspend fun run1() {
|
||||
c(); c()
|
||||
}
|
||||
override suspend fun run2() {
|
||||
inlineMeInner()
|
||||
}
|
||||
inline suspend fun inlineMeInner() {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}
|
||||
// TODO: call it from run1
|
||||
inline suspend fun inlineMeCapturing() {
|
||||
c(); c()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
|
||||
|
||||
inline fun inlineMe3(crossinline c: suspend () -> Unit) = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
var sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr.run()
|
||||
sr.run1()
|
||||
sr.run2()
|
||||
}
|
||||
|
||||
override suspend fun run1() {
|
||||
}
|
||||
override suspend fun run2() {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import test.InlineMeKt;
|
||||
import helpers.CoroutineUtilKt;
|
||||
import helpers.EmptyContinuation;
|
||||
import kotlin.Unit;
|
||||
|
||||
public class A {
|
||||
public static Object call() {
|
||||
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call2() {
|
||||
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call3() {
|
||||
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import test.*
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(CheckStateMachineContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
(A.call() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call() as SuspendRunnable).run1()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call() as SuspendRunnable).run2()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as SuspendRunnable).run1()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as SuspendRunnable).run2()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call3() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(10)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
builder {
|
||||
inlineMe {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run1()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
builder {
|
||||
inlineMe {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run2()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe2 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe2 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run1()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
builder {
|
||||
inlineMe2 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run2()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe3 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(18)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
104
compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt
vendored
Normal file
104
compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
// CHECK_STATE_MACHINE
|
||||
|
||||
// FILE: inlineMe.kt
|
||||
|
||||
package test
|
||||
|
||||
inline fun inlineMe(crossinline c: suspend () -> Unit) = suspend { c(); c() }
|
||||
|
||||
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
|
||||
|
||||
inline fun inlineMe3(crossinline c: suspend () -> Unit) = suspend {
|
||||
var sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr()
|
||||
sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr()
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import test.InlineMeKt;
|
||||
import helpers.CoroutineUtilKt;
|
||||
import helpers.EmptyContinuation;
|
||||
import kotlin.Unit;
|
||||
|
||||
public class A {
|
||||
public static Object call() {
|
||||
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call2() {
|
||||
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call3() {
|
||||
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import test.*
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(CheckStateMachineContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
(A.call() as (suspend () -> Unit))()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as (suspend () -> Unit))()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call3() as (suspend () -> Unit))()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe2 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe3 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}()
|
||||
}
|
||||
StateMachineChecker.check(16)
|
||||
return "OK"
|
||||
}
|
||||
114
compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt
vendored
Normal file
114
compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
// CHECK_STATE_MACHINE
|
||||
|
||||
// FILE: inlineMe.kt
|
||||
|
||||
package test
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
inline fun inlineMe(crossinline c: suspend () -> Unit) = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c(); c()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
|
||||
|
||||
inline fun inlineMe3(crossinline c: suspend () -> Unit) = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
var sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr.run()
|
||||
sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import test.InlineMeKt;
|
||||
import helpers.CoroutineUtilKt;
|
||||
import helpers.EmptyContinuation;
|
||||
import kotlin.Unit;
|
||||
|
||||
public class A {
|
||||
public static Object call() {
|
||||
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call2() {
|
||||
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call3() {
|
||||
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import test.*
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(CheckStateMachineContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
(A.call() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call3() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe2 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe3 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(16)
|
||||
return "OK"
|
||||
}
|
||||
283
compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt
vendored
Normal file
283
compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_STATE_MACHINE
|
||||
|
||||
// FILE: inlineMe.kt
|
||||
|
||||
package test
|
||||
|
||||
import helpers.*
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run1()
|
||||
suspend fun run2()
|
||||
}
|
||||
|
||||
inline fun inlineMe(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable {
|
||||
override suspend fun run1() {
|
||||
c1(); c1()
|
||||
}
|
||||
override suspend fun run2() {
|
||||
c2(); c2()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun inlineMe2(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = inlineMe({ c1(); c1() }) { c2(); c2() }
|
||||
|
||||
inline fun inlineMe3(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable {
|
||||
override suspend fun run1() {
|
||||
val sr = inlineMe({ c1(); c1() }) { c2(); c2() }
|
||||
sr.run1()
|
||||
sr.run2()
|
||||
}
|
||||
override suspend fun run2() {
|
||||
val sr = inlineMe2({ c1(); c1() }) { c2(); c2() }
|
||||
sr.run1()
|
||||
sr.run2()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun inlineMe4(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable {
|
||||
override suspend fun run1() {
|
||||
val sr = suspend {
|
||||
c1();
|
||||
c2()
|
||||
}
|
||||
sr()
|
||||
sr()
|
||||
}
|
||||
override suspend fun run2() {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run1() {
|
||||
c1(); c1()
|
||||
}
|
||||
override suspend fun run2() {
|
||||
c2(); c2()
|
||||
}
|
||||
}
|
||||
sr.run1()
|
||||
sr.run2()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun inlineMe5(crossinline c1: suspend () -> Unit) = inlineMe({ c1(); c1() }) {
|
||||
StateMachineChecker.suspendHere()
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import test.InlineMeKt;
|
||||
import helpers.CoroutineUtilKt;
|
||||
import helpers.EmptyContinuation;
|
||||
import kotlin.Unit;
|
||||
|
||||
public class A {
|
||||
public static Object call() {
|
||||
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call2() {
|
||||
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call3() {
|
||||
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call4() {
|
||||
return InlineMeKt.inlineMe4((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call5() {
|
||||
return InlineMeKt.inlineMe5((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import test.*
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(CheckStateMachineContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
(A.call() as SuspendRunnable).run1()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call() as SuspendRunnable).run2()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as SuspendRunnable).run1()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as SuspendRunnable).run2()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call3() as SuspendRunnable).run1()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call3() as SuspendRunnable).run2()
|
||||
}
|
||||
StateMachineChecker.check(16)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call4() as SuspendRunnable).run1()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call4() as SuspendRunnable).run2()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call5() as SuspendRunnable).run1()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call5() as SuspendRunnable).run2()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run1()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
builder {
|
||||
inlineMe({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run2()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe2 ({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run1()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
builder {
|
||||
inlineMe2 ({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run2()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe3 ({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run1()
|
||||
}
|
||||
StateMachineChecker.check(16)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe3 ({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run2()
|
||||
}
|
||||
StateMachineChecker.check(32)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe4 ({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run1()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe4 ({
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}) {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run2()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe5 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run1()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe5 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run2()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -16,8 +16,8 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
@@ -40,6 +40,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -50,11 +51,18 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1
|
||||
@@ -72,11 +80,12 @@ public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
@@ -93,8 +102,8 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$1 {
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
@@ -129,11 +138,27 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1 {
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1
|
||||
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1
|
||||
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1$1
|
||||
public method <init>(p0: CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1 {
|
||||
synthetic final field $acc$inlined: kotlin.jvm.internal.Ref$ObjectRef
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1
|
||||
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
@@ -174,6 +199,7 @@ public final class CrossinlineKt$consumeEach$2 {
|
||||
inner class CrossinlineKt$consumeEach$2$send$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -195,8 +221,8 @@ public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
@@ -219,6 +245,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -229,11 +256,18 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1
|
||||
@@ -251,6 +285,7 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -284,7 +319,11 @@ public final class CrossinlineKt$range$$inlined$source$1 {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$source$1$consume$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$source$1
|
||||
@@ -300,6 +339,7 @@ public final class CrossinlineKt$source$1 {
|
||||
inner class CrossinlineKt$source$1
|
||||
inner class CrossinlineKt$source$1$consume$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
@@ -54,11 +54,29 @@ public final class CrossinlineKt$box$1$doResume$$inlined$filter$1 {
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$doResume$$inlined$fold$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$doResume$$inlined$fold$1
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$fold$1
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$fold$1$1
|
||||
public method <init>(p0: CrossinlineKt$box$1$doResume$$inlined$fold$1, p1: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||
synthetic final method getLabel(): int
|
||||
synthetic final method setLabel(p0: int): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$doResume$$inlined$fold$1 {
|
||||
synthetic final field $acc$inlined: kotlin.jvm.internal.Ref$ObjectRef
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$fold$1
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$fold$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
@@ -108,6 +126,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -118,11 +137,17 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1
|
||||
@@ -142,6 +167,7 @@ public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -180,6 +206,7 @@ public final class CrossinlineKt$consumeEach$2 {
|
||||
inner class CrossinlineKt$consumeEach$2$send$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -227,6 +254,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -237,11 +265,17 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1
|
||||
@@ -261,6 +295,7 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -296,6 +331,9 @@ public final class CrossinlineKt$range$$inlined$source$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$source$1$consume$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$source$1
|
||||
@@ -313,6 +351,7 @@ public final class CrossinlineKt$source$1 {
|
||||
inner class CrossinlineKt$source$1
|
||||
inner class CrossinlineKt$source$1$consume$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt$box$1$invokeSuspend$$inlined$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field label: int
|
||||
inner class EpamKt$box$1$invokeSuspend$$inlined$zip$1
|
||||
public method <init>(p0: MyDeferred, p1: MyDeferred, p2: kotlin.coroutines.Continuation): void
|
||||
@@ -48,16 +50,20 @@ final class EpamKt$box$second$1 {
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
synthetic final field $zipper: kotlin.jvm.functions.Function2
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field label: int
|
||||
inner class EpamKt$zip$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2, p1: MyDeferred, p2: MyDeferred, p3: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ public final class EpamKt$box$1$doResume$$inlined$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
inner class EpamKt$box$1$doResume$$inlined$zip$1
|
||||
public method <init>(p0: MyDeferred, p1: MyDeferred, p2: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
@@ -46,9 +47,12 @@ public final class EpamKt$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
synthetic final field $zipper: kotlin.jvm.functions.Function2
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
inner class EpamKt$zip$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2, p1: MyDeferred, p2: MyDeferred, p3: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
public final @org.jetbrains.annotations.Nullable method doResume$$forInline(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user