mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-28 08:31:30 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3674663d30 | ||
|
|
e74282753a | ||
|
|
bbb92ead5b | ||
|
|
08e9ff602f | ||
|
|
73596f7464 | ||
|
|
0dcf34bb55 | ||
|
|
0bcdfce84b | ||
|
|
e8be0962c2 | ||
|
|
8afd6421bb | ||
|
|
a946126dca | ||
|
|
47895c0cc2 | ||
|
|
bb6677620a | ||
|
|
06104521f2 | ||
|
|
63fc7110a7 | ||
|
|
f5bab93fd1 | ||
|
|
8f2c05668e | ||
|
|
737763cc67 | ||
|
|
2bd44799f8 | ||
|
|
e13fb0e7bc | ||
|
|
16df7a9d92 | ||
|
|
d5d803963f | ||
|
|
20a15dc175 | ||
|
|
26bd8600cf | ||
|
|
abb116ef9a | ||
|
|
a336888858 | ||
|
|
19501aac59 | ||
|
|
f9ac5ae737 | ||
|
|
9cb5defc43 | ||
|
|
4782077357 |
4
.idea/ant.xml
generated
4
.idea/ant.xml
generated
@@ -3,7 +3,7 @@
|
||||
<component name="AntConfiguration">
|
||||
<buildFile url="file://$PROJECT_DIR$/compiler/frontend/buildLexer.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/build.xml">
|
||||
<antCommandLine value="-J-XX:MaxPermSize=100m -J-ea" />
|
||||
<antCommandLine value="-J-XX:MaxPermSize=100m" />
|
||||
<maximumHeapSize value="1024" />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/update_dependencies.xml" />
|
||||
@@ -11,12 +11,12 @@
|
||||
<maximumHeapSize value="512" />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/idea-runner/runner.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/replicate_versions.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/libraries/build-docs.xml">
|
||||
<maximumHeapSize value="1024" />
|
||||
<properties>
|
||||
<property name="dokka.path" value="../../dokka" />
|
||||
</properties>
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/TeamCityRelay.xml" />
|
||||
</component>
|
||||
</project>
|
||||
26
.idea/artifacts/KotlinAndroidExtensions.xml
generated
Normal file
26
.idea/artifacts/KotlinAndroidExtensions.xml
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact name="KotlinAndroidExtensions">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/KotlinAndroidExtensions</output-path>
|
||||
<properties id="ant-postprocessing">
|
||||
<options enabled="true">
|
||||
<file>file://$PROJECT_DIR$/idea-runner/runner.xml</file>
|
||||
<target>copy-runtime-for-idea-plugin</target>
|
||||
</options>
|
||||
</properties>
|
||||
<root id="root">
|
||||
<element id="directory" name="lib">
|
||||
<element id="archive" name="kotlin-android-extensions.jar">
|
||||
<element id="module-output" name="android-idea-plugin" />
|
||||
</element>
|
||||
<element id="directory" name="jps">
|
||||
<element id="archive" name="kotlin-android-extensions-jps.jar">
|
||||
<element id="module-output" name="android-jps-plugin" />
|
||||
</element>
|
||||
</element>
|
||||
<element id="archive" name="android-compiler-plugin.jar">
|
||||
<element id="module-output" name="android-compiler-plugin" />
|
||||
</element>
|
||||
</element>
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
5
.idea/artifacts/KotlinJpsPlugin.xml
generated
5
.idea/artifacts/KotlinJpsPlugin.xml
generated
@@ -19,11 +19,10 @@
|
||||
<element id="module-output" name="util" />
|
||||
<element id="module-output" name="util.runtime" />
|
||||
<element id="file-copy" path="$PROJECT_DIR$/resources/kotlinManifest.properties" />
|
||||
<element id="module-output" name="daemon-client" />
|
||||
<element id="module-output" name="daemon-common" />
|
||||
<element id="module-output" name="kotlinr" />
|
||||
<element id="module-output" name="rmi-interface" />
|
||||
<element id="module-output" name="deserialization" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/native-platform-uberjar.jar" path-in-jar="/" />
|
||||
<element id="module-output" name="android-jps-plugin" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
10
.idea/artifacts/KotlinPlugin.xml
generated
10
.idea/artifacts/KotlinPlugin.xml
generated
@@ -42,22 +42,16 @@
|
||||
<element id="module-output" name="serialization" />
|
||||
<element id="module-output" name="idea-completion" />
|
||||
<element id="module-output" name="idea-core" />
|
||||
<element id="module-output" name="idea-js" />
|
||||
<element id="module-output" name="container" />
|
||||
<element id="module-output" name="daemon-common" />
|
||||
<element id="module-output" name="rmi-interface" />
|
||||
<element id="module-output" name="idea-repl" />
|
||||
<element id="module-output" name="idea-live-templates" />
|
||||
</element>
|
||||
<element id="library" level="project" name="javax.inject" />
|
||||
<element id="directory" name="jps">
|
||||
<element id="artifact" artifact-name="KotlinJpsPlugin" />
|
||||
</element>
|
||||
<element id="library" level="project" name="markdown" />
|
||||
<element id="archive" name="kotlin-android-extensions-plugin.jar">
|
||||
<element id="module-output" name="android-idea-plugin" />
|
||||
</element>
|
||||
<element id="archive" name="kotlin-android-extensions-compiler-plugin.jar">
|
||||
<element id="module-output" name="android-compiler-plugin" />
|
||||
</element>
|
||||
</element>
|
||||
<element id="directory" name="kotlinc">
|
||||
<element id="dir-copy" path="$PROJECT_DIR$/dist/kotlinc" />
|
||||
|
||||
1
.idea/dictionaries/Nikolay_Krasko.xml
generated
1
.idea/dictionaries/Nikolay_Krasko.xml
generated
@@ -2,7 +2,6 @@
|
||||
<dictionary name="Nikolay.Krasko">
|
||||
<words>
|
||||
<w>accessors</w>
|
||||
<w>fqname</w>
|
||||
<w>goto</w>
|
||||
<w>gradle</w>
|
||||
<w>intrinsics</w>
|
||||
|
||||
BIN
.idea/icon.png
generated
BIN
.idea/icon.png
generated
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
13
.idea/libraries/kotlin_test.xml
generated
13
.idea/libraries/kotlin_test.xml
generated
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="kotlin-test">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/bootstrap-compiler/Kotlin/kotlinc/lib/kotlin-test.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/shared/src/main/kotlin" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/shared/src/main/kotlin.jvm" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/junit/src/main/kotlin" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
11
.idea/modules.xml
generated
11
.idea/modules.xml
generated
@@ -21,9 +21,6 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/tests/compiler-tests.iml" filepath="$PROJECT_DIR$/compiler/tests/compiler-tests.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" filepath="$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/container/container.iml" filepath="$PROJECT_DIR$/compiler/container/container.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/daemon/daemon.iml" filepath="$PROJECT_DIR$/compiler/daemon/daemon.iml" group="compiler/daemon" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/daemon/daemon-client/daemon-client.iml" filepath="$PROJECT_DIR$/compiler/daemon/daemon-client/daemon-client.iml" group="compiler/daemon" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/daemon/daemon-common/daemon-common.iml" filepath="$PROJECT_DIR$/compiler/daemon/daemon-common/daemon-common.iml" group="compiler/daemon" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/descriptor.loader.java/descriptor.loader.java.iml" filepath="$PROJECT_DIR$/core/descriptor.loader.java/descriptor.loader.java.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/descriptors/descriptors.iml" filepath="$PROJECT_DIR$/core/descriptors/descriptors.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/descriptors.runtime/descriptors.runtime.iml" filepath="$PROJECT_DIR$/core/descriptors.runtime/descriptors.runtime.iml" group="core" />
|
||||
@@ -39,8 +36,8 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" filepath="$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-core/idea-core.iml" filepath="$PROJECT_DIR$/idea/idea-core/idea-core.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" filepath="$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" filepath="$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-js/idea-js.iml" filepath="$PROJECT_DIR$/idea/idea-js/idea-js.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea-runner/idea-runner.iml" filepath="$PROJECT_DIR$/idea-runner/idea-runner.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" filepath="$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" filepath="$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" group="compiler/cli" />
|
||||
@@ -56,13 +53,15 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/js/js.translator/js.translator.iml" filepath="$PROJECT_DIR$/js/js.translator/js.translator.iml" group="compiler/js" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" filepath="$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" group="ide/jps" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/kotlin-android-plugin/kotlin-android-plugin.iml" filepath="$PROJECT_DIR$/idea/kotlin-android-plugin/kotlin-android-plugin.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/rmi/kotlinr/kotlinr.iml" filepath="$PROJECT_DIR$/compiler/rmi/kotlinr/kotlinr.iml" group="rmi" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/light-classes/light-classes.iml" filepath="$PROJECT_DIR$/compiler/light-classes/light-classes.iml" group="compiler/java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" filepath="$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/preloader.iml" filepath="$PROJECT_DIR$/compiler/preloader/preloader.iml" group="compiler/cli" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/reflection.jvm/reflection.jvm.iml" filepath="$PROJECT_DIR$/core/reflection.jvm/reflection.jvm.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/rmi/rmi-interface/rmi-interface.iml" filepath="$PROJECT_DIR$/compiler/rmi/rmi-interface/rmi-interface.iml" group="rmi" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/rmi/rmi-server/rmi-server.iml" filepath="$PROJECT_DIR$/compiler/rmi/rmi-server/rmi-server.iml" group="rmi" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" filepath="$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/serialization/serialization.iml" filepath="$PROJECT_DIR$/compiler/serialization/serialization.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/temp-jdk8/temp-jdk8.iml" filepath="$PROJECT_DIR$/temp-jdk8/temp-jdk8.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/util/util.iml" filepath="$PROJECT_DIR$/compiler/util/util.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/util.runtime/util.runtime.iml" filepath="$PROJECT_DIR$/core/util.runtime/util.runtime.iml" group="core" />
|
||||
</modules>
|
||||
|
||||
4
.idea/runConfigurations/Android_Studio.xml
generated
4
.idea/runConfigurations/Android_Studio.xml
generated
@@ -24,7 +24,9 @@
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinPlugin" />
|
||||
</option>
|
||||
<option name="BuildArtifacts" enabled="true" />
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinAndroidExtensions" />
|
||||
</option>
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
4
.idea/runConfigurations/IDEA.xml
generated
4
.idea/runConfigurations/IDEA.xml
generated
@@ -43,7 +43,9 @@
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinPlugin" />
|
||||
</option>
|
||||
<option name="BuildArtifacts" enabled="true" />
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinAndroidExtensions" />
|
||||
</option>
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea-runner/runner.xml" target="force-enable-kotlin-plugin" />
|
||||
</method>
|
||||
</configuration>
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinPlugin" />
|
||||
</option>
|
||||
<option name="BuildArtifacts" enabled="true" />
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinAndroidExtensions" />
|
||||
</option>
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea-runner/runner.xml" target="force-enable-kotlin-plugin" />
|
||||
</method>
|
||||
</configuration>
|
||||
|
||||
7
.idea/runConfigurations/IDEA__win_.xml
generated
7
.idea/runConfigurations/IDEA__win_.xml
generated
@@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="IDEA (win)" type="Application" factoryName="Application">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
@@ -5,7 +6,7 @@
|
||||
<option name="VM_PARAMETERS" value="-Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=450m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=${JAVA_HOME}\lib\tools.jar,../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/ideaSDK/bin" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="1.7" />
|
||||
<option name="ENABLE_SWING_INSPECTOR" value="false" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
@@ -16,7 +17,9 @@
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinPlugin" />
|
||||
</option>
|
||||
<option name="BuildArtifacts" enabled="true" />
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinAndroidExtensions" />
|
||||
</option>
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea-runner/runner.xml" target="force-enable-kotlin-plugin" />
|
||||
</method>
|
||||
</configuration>
|
||||
|
||||
4
.idea/runConfigurations/Update_Dist_Run.xml
generated
4
.idea/runConfigurations/Update_Dist_Run.xml
generated
@@ -22,7 +22,9 @@
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinPlugin" />
|
||||
</option>
|
||||
<option name="BuildArtifacts" enabled="true" />
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="KotlinAndroidExtensions" />
|
||||
</option>
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea_runner/runner.xml" target="force_enable_kotlin_plugin" />
|
||||
</method>
|
||||
</configuration>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<a href="http://kotlinslackin.herokuapp.com"><img src="https://kotlinslackin.herokuapp.com/badge.svg" height="20"></a>
|
||||
[](https://teamcity.jetbrains.com/viewType.html?buildTypeId=bt345&branch_Kotlin=%3Cdefault%3E&tab=buildTypeStatusDiv)
|
||||
[](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.jetbrains.kotlin%22)
|
||||
[](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<project name="Kotlin CI Steps" default="none">
|
||||
<import file="build.xml" optional="false"/>
|
||||
<import file="replicate_versions.xml" optional="false"/>
|
||||
|
||||
<property name="build.number" value="snapshot"/>
|
||||
<property name="jdk16.home" value="${java.home}"/>
|
||||
@@ -12,6 +13,10 @@
|
||||
<property name="plugin.xml.bk" value="${version_substitute_dir}/plugin.xml.bk"/>
|
||||
<property name="plugin.xml.versioned" value="${plugin.xml}.versioned"/>
|
||||
|
||||
<property name="android-extensions.plugin.xml" value="plugins/android-idea-plugin/src/META-INF/plugin.xml"/>
|
||||
<property name="android-extensions.plugin.xml.bk" value="${version_substitute_dir}/kotlin-android-extensions.plugin.xml.bk"/>
|
||||
<property name="android-extensions.plugin.xml.versioned" value="${android-extensions.plugin.xml}.versioned"/>
|
||||
|
||||
<property name="compiler.version.java" value="compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/KotlinVersion.java"/>
|
||||
<property name="compiler.version.java.bk" value="${version_substitute_dir}/KotlinVersion.java.bk"/>
|
||||
<property name="compiler.version.java.versioned" value="${compiler.version.java}.versioned"/>
|
||||
@@ -20,9 +25,6 @@
|
||||
<property name="bare.plugin.zip" value="${artifact.output.path}/kotlin-bare-plugin-${build.number}.zip"/>
|
||||
<property name="android-extensions.zip" value="${artifact.output.path}/kotlin-android-extensions-plugin-${build.number}.zip"/>
|
||||
|
||||
<property name="kotlin.bare.plugin.xml" value="jps-plugin/bare-plugin/src/META-INF/plugin.xml"/>
|
||||
<property name="kotlin.bare.plugin.xml.bk" value="${version_substitute_dir}/kotlin.bare.plugin.xml.bk"/>
|
||||
|
||||
<macrodef name="echoprop">
|
||||
<attribute name="prop"/>
|
||||
<sequential>
|
||||
@@ -85,23 +87,25 @@
|
||||
target.file.versioned="${plugin.xml.versioned}"
|
||||
test.string="<version>@snapshot@</version>"/>
|
||||
|
||||
<substituteVersionInFile
|
||||
target.file="${android-extensions.plugin.xml}"
|
||||
target.file.bk="${android-extensions.plugin.xml.bk}"
|
||||
target.file.versioned="${android-extensions.plugin.xml.versioned}"
|
||||
test.string="<version>@snapshot@</version>"/>
|
||||
|
||||
<substituteVersionInFile
|
||||
target.file="${compiler.version.java}"
|
||||
target.file.bk="${compiler.version.java.bk}"
|
||||
target.file.versioned="${compiler.version.java.versioned}"
|
||||
test.string="public static final String VERSION = "@snapshot@";"/>
|
||||
|
||||
<substituteVersionInFile
|
||||
target.file="${kotlin.bare.plugin.xml}"
|
||||
target.file.bk="${kotlin.bare.plugin.xml.bk}"
|
||||
test.string="<version>@snapshot@</version>"/>
|
||||
|
||||
</target>
|
||||
<replicateIdeaVersion target.file="${android-extensions.plugin.xml}"/>
|
||||
</target>
|
||||
|
||||
<target name="revertTemplateFiles">
|
||||
<copy file="${plugin.xml.bk}" tofile="${plugin.xml}" overwrite="true"/>
|
||||
<copy file="${android-extensions.plugin.xml.bk}" tofile="${android-extensions.plugin.xml}" overwrite="true"/>
|
||||
<copy file="${compiler.version.java.bk}" tofile="${compiler.version.java}" overwrite="true"/>
|
||||
<copy file="${kotlin.bare.plugin.xml.bk}" tofile="${kotlin.bare.plugin.xml}" overwrite="true"/>
|
||||
|
||||
<delete dir="${version_substitute_dir}" quiet="true"/>
|
||||
</target>
|
||||
@@ -129,8 +133,9 @@
|
||||
<zipPlugin filename="${bare.plugin.zip}" dir="BareKotlin"/>
|
||||
|
||||
<zip destfile="${android-extensions.zip}">
|
||||
<zipfileset prefix="META-INF" dir="${basedir}/plugins/android-idea-plugin/old_plugin" includes="plugin.xml" />
|
||||
<zipfileset prefix="KotlinAndroidExtensions" dir="${artifact.output.path}/KotlinAndroidExtensions"/>
|
||||
</zip>
|
||||
<delete dir="${artifact.output.path}/KotlinAndroidExtensions" quiet="true"/>
|
||||
</target>
|
||||
|
||||
<macrodef name="print-statistic">
|
||||
@@ -158,11 +163,11 @@
|
||||
<print-file-size-statistic path="${kotlin-home}/lib" file-name="kotlin-reflect.jar"/>
|
||||
|
||||
<print-file-size-statistic path="${kotlin-home}/lib" file-name="kotlin-jslib.jar"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="kotlin.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="builtins.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="builtins.meta.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="stdlib.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="stdlib.meta.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="kotlin.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="builtins.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="builtins.meta.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="stdlib.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="stdlib.meta.js"/>
|
||||
</target>
|
||||
|
||||
<target name="post_build" depends="zipArtifacts, revertTemplateFiles, printStatistics, remove_internal_artifacts, dont_remove_internal_artifacts"/>
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
<project name="Change plugins version" default="change-version">
|
||||
<property name="relay.origin.version" value="1.0.0-beta-2423"/>
|
||||
<property name="relay.substitute.version" value="1.0.0-beta-2423-IJ-141-3"/>
|
||||
<property name="relay.plugins.dir" value="artifacts"/>
|
||||
<property name="relay.unpack.directory" value="relay-dir"/>
|
||||
|
||||
<macrodef name="substituteRegexpInFile">
|
||||
<attribute name="src.file"/>
|
||||
<attribute name="output.dir"/>
|
||||
<attribute name="origin.version"/>
|
||||
<attribute name="substituted.version"/>
|
||||
<sequential>
|
||||
<copy todir="@{output.dir}">
|
||||
<fileset file="@{src.file}"/>
|
||||
<filterchain>
|
||||
<replaceregex pattern="@{origin.version}" replace="@{substituted.version}" />
|
||||
</filterchain>
|
||||
</copy>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<macrodef name="substitudeVersionInPlugin">
|
||||
<attribute name="plugin.path"/>
|
||||
<attribute name="plugin.jar.name"/>
|
||||
<attribute name="origin.version"/>
|
||||
<attribute name="substituted.version"/>
|
||||
<attribute name="plugin.subdir"/>
|
||||
|
||||
<attribute name="output-dir" default="@{substituted.version}"/>
|
||||
<attribute name="output.plugin.file.name" default="@{plugin.jar.name}-@{substituted.version}.zip"/>
|
||||
|
||||
<attribute name="temp.origin.dir" default="${relay.unpack.directory}/@{plugin.jar.name}/plugin-origin"/>
|
||||
<attribute name="temp.substitute.dir" default="${relay.unpack.directory}/@{plugin.jar.name}/substitute"/>
|
||||
|
||||
<sequential>
|
||||
<delete dir="${relay.unpack.directory}/@{plugin.jar.name}"/>
|
||||
<mkdir dir="${relay.unpack.directory}/@{plugin.jar.name}"/>
|
||||
|
||||
<unzip src="@{plugin.path}" dest="@{temp.origin.dir}">
|
||||
<patternset>
|
||||
<include name="**/lib/@{plugin.jar.name}.jar" />
|
||||
</patternset>
|
||||
<flattenmapper/>
|
||||
</unzip>
|
||||
|
||||
<unzip src="@{temp.origin.dir}/@{plugin.jar.name}.jar" dest="@{temp.origin.dir}">
|
||||
<patternset>
|
||||
<include name="**/META-INF/plugin.xml" />
|
||||
</patternset>
|
||||
<flattenmapper/>
|
||||
</unzip>
|
||||
|
||||
<substituteRegexpInFile
|
||||
src.file="@{temp.origin.dir}/plugin.xml" output.dir="@{temp.substitute.dir}"
|
||||
origin.version="@{origin.version}" substituted.version="@{substituted.version}"/>
|
||||
|
||||
<!-- Copy updated file back into jar -->
|
||||
<copy file="@{temp.origin.dir}/@{plugin.jar.name}.jar" todir="@{temp.substitute.dir}"/>
|
||||
<jar destfile="@{temp.substitute.dir}/@{plugin.jar.name}.jar" update="true">
|
||||
<zipfileset file="@{temp.substitute.dir}/plugin.xml" prefix="META-INF"/>
|
||||
</jar>
|
||||
|
||||
<!-- Pack updated plugin.jar back to zip file -->
|
||||
<copy file="@{plugin.path}" tofile="@{substituted.version}/@{output.plugin.file.name}"/>
|
||||
<zip destfile="@{substituted.version}/@{output.plugin.file.name}" update="true">
|
||||
<zipfileset file="@{temp.substitute.dir}/@{plugin.jar.name}.jar" prefix="@{plugin.subdir}/lib"/>
|
||||
</zip>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<target name="change-version" description="Repack plugin with other version">
|
||||
<delete dir="${relay.unpack.directory}"/>
|
||||
<delete dir="${relay.substitute.version}"/>
|
||||
|
||||
<mkdir dir="${relay.unpack.directory}"/>
|
||||
<mkdir dir="${relay.substitute.version}"/>
|
||||
|
||||
<substitudeVersionInPlugin
|
||||
plugin.jar.name="kotlin-plugin"
|
||||
plugin.path="${relay.plugins.dir}/kotlin-plugin-${relay.origin.version}.zip"
|
||||
origin.version="${relay.origin.version}"
|
||||
plugin.subdir="Kotlin"
|
||||
substituted.version="${relay.substitute.version}"/>
|
||||
|
||||
<substitudeVersionInPlugin
|
||||
plugin.jar.name="kotlin-bare-plugin"
|
||||
plugin.path="${relay.plugins.dir}/kotlin-bare-plugin-${relay.origin.version}.zip"
|
||||
origin.version="${relay.origin.version}"
|
||||
plugin.subdir="BareKotlin"
|
||||
substituted.version="${relay.substitute.version}"/>
|
||||
|
||||
<substitudeVersionInPlugin
|
||||
plugin.jar.name="kotlin-android-extensions"
|
||||
plugin.path="${relay.plugins.dir}/kotlin-android-extensions-plugin-${relay.origin.version}.zip"
|
||||
origin.version="${relay.origin.version}"
|
||||
plugin.subdir="KotlinAndroidExtensions"
|
||||
substituted.version="${relay.substitute.version}"/>
|
||||
</target>
|
||||
</project>
|
||||
87
build.xml
87
build.xml
@@ -12,10 +12,8 @@
|
||||
<property name="bootstrap.compiler.home" value="${bootstrap.home}/Kotlin/kotlinc"/>
|
||||
<property name="bootstrap.runtime" value="${bootstrap.compiler.home}/lib/kotlin-runtime.jar"/>
|
||||
<property name="bootstrap.reflect" value="${bootstrap.compiler.home}/lib/kotlin-reflect.jar"/>
|
||||
<property name="bootstrap.kotlin.test" value="${bootstrap.compiler.home}/lib/kotlin-test.jar" />
|
||||
|
||||
<property name="output" value="${basedir}/dist"/>
|
||||
<property name="js.stdlib.output.dir" value="${output}/js"/>
|
||||
<property name="intermediate-sources" value="out/src" />
|
||||
<property name="kotlin-home" value="${output}/kotlinc"/>
|
||||
<property name="build.number" value="snapshot"/>
|
||||
@@ -57,7 +55,6 @@
|
||||
|
||||
<path id="classpath">
|
||||
<file file="${bootstrap.runtime}"/>
|
||||
<file file="${bootstrap.kotlin.test}" />
|
||||
<file file="${bootstrap.reflect}"/>
|
||||
<fileset dir="${idea.sdk}" includes="core/*.jar"/>
|
||||
<pathelement location="${protobuf.jar}"/>
|
||||
@@ -94,8 +91,8 @@
|
||||
<include name="compiler/frontend.java/src"/>
|
||||
<include name="compiler/light-classes/src"/>
|
||||
<include name="compiler/plugin-api/src"/>
|
||||
<include name="compiler/daemon/src"/>
|
||||
<include name="compiler/daemon/daemon-common/src"/>
|
||||
<include name="compiler/rmi/rmi-server/src"/>
|
||||
<include name="compiler/rmi/rmi-interface/src"/>
|
||||
<include name="compiler/serialization/src"/>
|
||||
<include name="compiler/util/src"/>
|
||||
<include name="js/js.dart-ast/src"/>
|
||||
@@ -121,7 +118,8 @@
|
||||
<include name="cli/**"/>
|
||||
<include name="cli-common/**"/>
|
||||
<include name="conditional-preprocessor/**"/>
|
||||
<include name="daemon/**"/>
|
||||
<include name="rmi-server/**"/>
|
||||
<include name="rmi-interface/**"/>
|
||||
<include name="util/**"/>
|
||||
<include name="util.runtime/**"/>
|
||||
<include name="light-classes/**"/>
|
||||
@@ -180,33 +178,19 @@
|
||||
<sequential if:true="${bootstrap.or.local.build}">
|
||||
<copy file="${bootstrap.runtime}" tofile="${kotlin-home}/lib/kotlin-runtime-internal-bootstrap.jar"/>
|
||||
<copy file="${bootstrap.reflect}" tofile="${kotlin-home}/lib/kotlin-reflect-internal-bootstrap.jar"/>
|
||||
<copy file="${bootstrap.kotlin.test}" tofile="${kotlin-home}/lib/kotlin-test-internal-bootstrap.jar" failonerror="false"/>
|
||||
<jar destfile="${kotlin-home}/lib/kotlin-reflect-internal-bootstrap.jar" update="true">
|
||||
<manifest>
|
||||
<attribute name="Class-Path" value="kotlin-runtime-internal-bootstrap.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
<jar destfile="${kotlin-home}/lib/kotlin-test-internal-bootstrap.jar" update="true">
|
||||
<manifest>
|
||||
<attribute name="Class-Path" value="kotlin-runtime-internal-bootstrap.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</sequential>
|
||||
|
||||
<sequential unless:true="${bootstrap.or.local.build}">
|
||||
<copy file="${bootstrap.runtime}" todir="${kotlin-home}/lib"/>
|
||||
<copy file="${bootstrap.reflect}" todir="${kotlin-home}/lib"/>
|
||||
<copy file="${bootstrap.kotlin.test}" todir="${kotlin-home}/lib"/>
|
||||
</sequential>
|
||||
</target>
|
||||
|
||||
<target name="copy-dist-to-bootstrap">
|
||||
<delete dir="${basedir}/dependencies/bootstrap-compiler/Kotlin/kotlinc" />
|
||||
<copy todir="${basedir}/dependencies/bootstrap-compiler/Kotlin/kotlinc">
|
||||
<fileset dir="${basedir}/dist/kotlinc" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="compiler-sources">
|
||||
<jar jarfile="${output}/kotlin-compiler-sources.jar">
|
||||
<!-- TODO How to convert it from pathset or dirset ? -->
|
||||
@@ -220,8 +204,8 @@
|
||||
<fileset dir="compiler/cli/src"/>
|
||||
<fileset dir="compiler/cli/cli-common/src"/>
|
||||
<fileset dir="compiler/conditional-preprocessor/src"/>
|
||||
<fileset dir="compiler/daemon/src"/>
|
||||
<fileset dir="compiler/daemon/daemon-common/src"/>
|
||||
<fileset dir="compiler/rmi/rmi-server/src"/>
|
||||
<fileset dir="compiler/rmi/rmi-interface/src"/>
|
||||
<fileset dir="compiler/container/src"/>
|
||||
<fileset dir="compiler/frontend/src"/>
|
||||
<fileset dir="compiler/frontend.java/src"/>
|
||||
@@ -310,7 +294,6 @@
|
||||
<arg value="@{output}"/>
|
||||
<arg value="-no-stdlib"/>
|
||||
<arg value="-meta-info"/>
|
||||
<arg value="-kjsm"/>
|
||||
<arg line="-main noCall"/>
|
||||
</java>
|
||||
</sequential>
|
||||
@@ -325,13 +308,13 @@
|
||||
|
||||
<kotlin-pp src="libraries/stdlib/src" output="${intermediate-sources}/stdlib/js" profile="JS" />
|
||||
|
||||
<new-kotlin2js output="${js.stdlib.output.dir}/${compiled.builtins.js}">
|
||||
<new-kotlin2js output="${output}/${compiled.builtins.js}">
|
||||
<src>
|
||||
<fileset refid="kotlin.builtin.files"/>
|
||||
</src>
|
||||
</new-kotlin2js>
|
||||
|
||||
<new-kotlin2js output="${js.stdlib.output.dir}/${compiled.stdlib.js}">
|
||||
<new-kotlin2js output="${output}/${compiled.stdlib.js}">
|
||||
<src>
|
||||
<resources refid="js.lib.files"/>
|
||||
</src>
|
||||
@@ -351,7 +334,7 @@
|
||||
prettyprint="true"
|
||||
languagein="ECMASCRIPT5_STRICT"
|
||||
warning="${warningLevel}"
|
||||
output="${js.stdlib.output.dir}/kotlin.js">
|
||||
output="${output}/kotlin.js">
|
||||
|
||||
<sources dir="${stdlib.js.dir}">
|
||||
<file name="kotlin_lib_ecma5.js"/>
|
||||
@@ -360,11 +343,11 @@
|
||||
<file name="long.js"/>
|
||||
</sources>
|
||||
|
||||
<sources dir="${js.stdlib.output.dir}">
|
||||
<sources dir="${output}">
|
||||
<file name="${compiled.builtins.js}"/>
|
||||
</sources>
|
||||
|
||||
<sources dir="${js.stdlib.output.dir}">
|
||||
<sources dir="${output}">
|
||||
<file name="${compiled.stdlib.js}"/>
|
||||
</sources>
|
||||
|
||||
@@ -379,11 +362,8 @@
|
||||
|
||||
<jar jarfile="${kotlin-home}/lib/kotlin-jslib.jar" duplicate="fail">
|
||||
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
|
||||
<zipfileset dir="${js.stdlib.output.dir}" prefix="">
|
||||
<include name="kotlin.js"/>
|
||||
<include name="${compiled.stdlib.meta.js}"/>
|
||||
<include name="stdlib/**"/>
|
||||
</zipfileset>
|
||||
<zipfileset file="${output}/kotlin.js" prefix=""/>
|
||||
<zipfileset file="${output}/${compiled.stdlib.meta.js}" prefix=""/>
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
|
||||
@@ -600,12 +580,12 @@
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="daemon-client">
|
||||
<cleandir dir="${output}/classes/daemon-client"/>
|
||||
<target name="kotlinr">
|
||||
<cleandir dir="${output}/classes/kotlinr"/>
|
||||
|
||||
<kotlinc output="${output}/classes/daemon-client" modulename="client">
|
||||
<kotlinc output="${output}/classes/kotlinr" modulename="kotlin-rmi">
|
||||
<src>
|
||||
<pathelement path="compiler/daemon/daemon-client/src"/>
|
||||
<pathelement path="compiler/rmi/kotlinr/src"/>
|
||||
</src>
|
||||
<classpath>
|
||||
<pathelement path="${bootstrap.runtime}"/>
|
||||
@@ -615,8 +595,8 @@
|
||||
</classpath>
|
||||
</kotlinc>
|
||||
|
||||
<jar destfile="${kotlin-home}/lib/kotlin-daemon-client.jar">
|
||||
<fileset dir="${output}/classes/daemon-client"/>
|
||||
<jar destfile="${kotlin-home}/lib/kotlinr.jar">
|
||||
<fileset dir="${output}/classes/kotlinr"/>
|
||||
<zipfileset src="${dependencies.dir}/native-platform-uberjar.jar" includes="**" />
|
||||
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
|
||||
</jar>
|
||||
@@ -798,7 +778,7 @@
|
||||
</target>
|
||||
|
||||
<target name="stdlib">
|
||||
<new-kotlinc output="${output}/classes/stdlib" moduleName="kotlin-stdlib" additionalOptions="-Xmultifile-facades-open">
|
||||
<new-kotlinc output="${output}/classes/stdlib" moduleName="kotlin-stdlib">
|
||||
<src>
|
||||
<include name="libraries/stdlib/src"/>
|
||||
</src>
|
||||
@@ -808,20 +788,6 @@
|
||||
</new-kotlinc>
|
||||
</target>
|
||||
|
||||
<target name="kotlin.test">
|
||||
<new-kotlinc output="${output}/classes/kotlin.test" moduleName="kotlin-test">
|
||||
<src>
|
||||
<include name="libraries/kotlin.test/shared/src/main/kotlin" />
|
||||
<include name="libraries/kotlin.test/shared/src/main/kotlin.jvm" />
|
||||
<include name="libraries/kotlin.test/junit/src/main/kotlin" />
|
||||
</src>
|
||||
<class-path>
|
||||
<pathelement path="${output}/classes/builtins"/>
|
||||
<pathelement path="libraries/lib/junit-4.11.jar"/>
|
||||
</class-path>
|
||||
</new-kotlinc>
|
||||
</target>
|
||||
|
||||
<target name="core">
|
||||
<new-kotlinc output="${output}/classes/core" moduleName="kotlin-core">
|
||||
<src>
|
||||
@@ -966,23 +932,15 @@
|
||||
</pack-runtime-jar>
|
||||
</target>
|
||||
|
||||
<target name="pack-kotlin-test">
|
||||
<pack-runtime-jar jar-name="kotlin-test.jar" implementation-title="${manifest.impl.title.kotlin.test}">
|
||||
<jar-content>
|
||||
<fileset dir="${output}/classes/kotlin.test" includes="**/*" excludes="kotlin/internal/OnlyInputTypes*,kotlin/internal"/>
|
||||
</jar-content>
|
||||
</pack-runtime-jar>
|
||||
</target>
|
||||
|
||||
<target name="runtime"
|
||||
depends="builtins,stdlib,core,reflection,pack-runtime,pack-runtime-sources"/>
|
||||
|
||||
<target name="dist"
|
||||
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin.test,pack-kotlin-test,kotlin-js-stdlib,android-compiler-plugin,daemon-client"
|
||||
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin-js-stdlib,android-compiler-plugin,kotlinr"
|
||||
description="Builds redistributables from sources"/>
|
||||
|
||||
<target name="dist-quick"
|
||||
depends="clean,init,prepare-dist,preloader,serialize-builtins,compiler-quick,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin.test,pack-kotlin-test,kotlin-js-stdlib,android-compiler-plugin"
|
||||
depends="clean,init,prepare-dist,preloader,serialize-builtins,compiler-quick,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin-js-stdlib,android-compiler-plugin"
|
||||
description="Builds everything, but classes are reused from project out dir, doesn't run proguard and javadoc"/>
|
||||
|
||||
<target name="dist-quick-compiler-only"
|
||||
@@ -1077,5 +1035,4 @@
|
||||
<target name="build-bootstrap-artifacts" depends="dist,zip-compiler"/>
|
||||
|
||||
<target name="build-artifacts" depends="dist,zip-compiler,kotlin-for-upsource,zip-test-data"/>
|
||||
<!-- Dummy change to see build in TeamCity dependencies -->
|
||||
</project>
|
||||
|
||||
@@ -93,14 +93,14 @@ public class CodegenUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<FunctionDescriptor, FunctionDescriptor> getNonPrivateTraitMethods(ClassDescriptor descriptor) {
|
||||
public static Map<FunctionDescriptor, FunctionDescriptor> getTraitMethods(ClassDescriptor descriptor) {
|
||||
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>();
|
||||
for (DeclarationDescriptor declaration : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||
if (!(declaration instanceof CallableMemberDescriptor)) continue;
|
||||
|
||||
CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
|
||||
CallableMemberDescriptor traitMember = ImplKt.findTraitImplementation(inheritedMember);
|
||||
if (traitMember == null || Visibilities.isPrivate(traitMember.getVisibility())) continue;
|
||||
if (traitMember == null) continue;
|
||||
|
||||
assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember;
|
||||
|
||||
@@ -140,7 +140,7 @@ public class CodegenUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getSuperClassBySuperTypeListEntry(@NotNull KtSuperTypeListEntry specifier, @NotNull BindingContext bindingContext) {
|
||||
public static ClassDescriptor getSuperClassByDelegationSpecifier(@NotNull KtDelegationSpecifier specifier, @NotNull BindingContext bindingContext) {
|
||||
KotlinType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
assert superType != null : "superType should not be null: " + specifier.getText();
|
||||
|
||||
@@ -188,12 +188,6 @@ public class CodegenUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (statement instanceof KtConstructorDelegationReferenceExpression && statement.getTextLength() == 0) {
|
||||
// PsiElement for constructor delegation reference is always generated, so we shouldn't mark it's line number if it's empty
|
||||
return null;
|
||||
}
|
||||
|
||||
Document document = file.getViewProvider().getDocument();
|
||||
return document != null ? document.getLineNumber(markEndOffset ? statement.getTextRange().getEndOffset() : statement.getTextOffset()) + 1 : null;
|
||||
}
|
||||
|
||||
@@ -31,41 +31,37 @@ public object CodegenUtilKt {
|
||||
|
||||
// class Foo : Bar by baz
|
||||
// descriptor = Foo
|
||||
// toInterface = Bar
|
||||
// toTrait = Bar
|
||||
// delegateExpressionType = typeof(baz)
|
||||
// return Map<member of Foo, corresponding member of typeOf(baz)>
|
||||
@JvmStatic
|
||||
public fun getDelegates(
|
||||
descriptor: ClassDescriptor,
|
||||
toInterface: ClassDescriptor,
|
||||
toTrait: ClassDescriptor,
|
||||
delegateExpressionType: KotlinType? = null
|
||||
): Map<CallableMemberDescriptor, CallableDescriptor> {
|
||||
if (delegateExpressionType?.isDynamic() ?: false) return mapOf();
|
||||
|
||||
return descriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
|
||||
return descriptor.getDefaultType().getMemberScope().getContributedDescriptors().asSequence()
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
|
||||
.filter { it.getKind() == CallableMemberDescriptor.Kind.DELEGATION }
|
||||
.asIterable()
|
||||
.sortedWith(MemberComparator.INSTANCE)
|
||||
.keysToMapExceptNulls {
|
||||
delegatingMember ->
|
||||
|
||||
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
||||
.mapNotNull {
|
||||
.filter { it.getContainingDeclaration() == toTrait }
|
||||
.map {
|
||||
overriddenDescriptor ->
|
||||
if (overriddenDescriptor.containingDeclaration == toInterface) {
|
||||
val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope
|
||||
val name = overriddenDescriptor.name
|
||||
val scope = (delegateExpressionType ?: toTrait.getDefaultType()).getMemberScope()
|
||||
val name = overriddenDescriptor.getName()
|
||||
|
||||
// this is the actual member of delegateExpressionType that we are delegating to
|
||||
(scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND))
|
||||
.firstOrNull {
|
||||
(listOf(it) + DescriptorUtils.getAllOverriddenDescriptors(it))
|
||||
.map { it.original }
|
||||
.contains(overriddenDescriptor.original)
|
||||
}
|
||||
}
|
||||
else null
|
||||
// this is the actual member of delegateExpressionType that we are delegating to
|
||||
(scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND))
|
||||
.first {
|
||||
(listOf(it) + DescriptorUtils.getAllOverriddenDescriptors(it)).map { it.getOriginal() }.contains(overriddenDescriptor.getOriginal())
|
||||
}
|
||||
}
|
||||
assert(actualDelegates.size() <= 1) { "Many delegates found for $delegatingMember: $actualDelegates" }
|
||||
|
||||
|
||||
@@ -43,16 +43,5 @@ public class SimpleOutputFile(
|
||||
override fun asByteArray(): ByteArray = content.toByteArray()
|
||||
override fun asText(): String = content
|
||||
|
||||
override fun toString() = "$relativePath (compiled from $sourceFiles)"
|
||||
}
|
||||
|
||||
public class SimpleOutputBinaryFile(
|
||||
override val sourceFiles: List<File>,
|
||||
override val relativePath: String,
|
||||
private val content: ByteArray
|
||||
) : OutputFile {
|
||||
override fun asByteArray(): ByteArray = content
|
||||
override fun asText(): String = String(content)
|
||||
|
||||
override fun toString() = "$relativePath (compiled from $sourceFiles)"
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
public class AccessorForConstructorDescriptor(
|
||||
private val calleeDescriptor: ConstructorDescriptor,
|
||||
@@ -39,16 +38,6 @@ public class AccessorForConstructorDescriptor(
|
||||
|
||||
override fun getSuperCallTarget(): ClassDescriptor? = superCallTarget
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor) = super.substitute(substitutor) as ConstructorDescriptor
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?, kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean
|
||||
): AccessorForConstructorDescriptor {
|
||||
throw UnsupportedOperationException("Trying to copy synthetic accessor $this")
|
||||
}
|
||||
|
||||
override fun getOriginal(): AccessorForConstructorDescriptor = this
|
||||
|
||||
init {
|
||||
initialize(
|
||||
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
|
||||
|
||||
@@ -426,7 +426,7 @@ public abstract class AnnotationCodegen {
|
||||
for (ConstantValue<?> value : values) {
|
||||
if (value instanceof EnumValue) {
|
||||
ClassDescriptor enumEntry = ((EnumValue) value).getValue();
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassObjectType(enumEntry);
|
||||
if (classObjectType != null) {
|
||||
if ("java/lang/annotation/ElementType".equals(typeMapper.mapType(classObjectType).getInternalName())) {
|
||||
result.add(ElementType.valueOf(enumEntry.getName().asString()));
|
||||
@@ -454,7 +454,7 @@ public abstract class AnnotationCodegen {
|
||||
ConstantValue<?> compileTimeConstant = valueArguments.iterator().next();
|
||||
if (compileTimeConstant instanceof EnumValue) {
|
||||
ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue();
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassObjectType(enumEntry);
|
||||
if (classObjectType != null) {
|
||||
if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
|
||||
return RetentionPolicy.valueOf(enumEntry.getName().asString());
|
||||
|
||||
@@ -38,17 +38,20 @@ import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.resolve.DeprecationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.types.FlexibleTypesKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
@@ -226,9 +229,9 @@ public class AsmUtil {
|
||||
int flags = getVisibilityAccessFlag(functionDescriptor);
|
||||
flags |= getVarargsFlag(functionDescriptor);
|
||||
flags |= getDeprecatedAccessFlag(functionDescriptor);
|
||||
if (DeprecationUtilKt.isHiddenInResolution(functionDescriptor)
|
||||
if (DeprecationUtilKt.isAnnotatedAsHidden(functionDescriptor)
|
||||
|| functionDescriptor instanceof PropertyAccessorDescriptor
|
||||
&& DeprecationUtilKt.isHiddenInResolution(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) {
|
||||
&& DeprecationUtilKt.isAnnotatedAsHidden(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) {
|
||||
flags |= ACC_SYNTHETIC;
|
||||
}
|
||||
return flags;
|
||||
@@ -325,6 +328,9 @@ public class AsmUtil {
|
||||
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
Visibility memberVisibility = memberDescriptor.getVisibility();
|
||||
if (isJvmInterface(containingDeclaration)) {
|
||||
return memberVisibility == Visibilities.PRIVATE ? NO_FLAG_PACKAGE_PRIVATE : ACC_PUBLIC;
|
||||
}
|
||||
|
||||
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
return ACC_PUBLIC;
|
||||
@@ -376,6 +382,11 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (memberDescriptor instanceof PropertyDescriptor &&
|
||||
((PropertyDescriptor) memberDescriptor).isConst() || hasJvmFieldAnnotation(memberDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -438,6 +449,14 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<FieldInfo> transformCapturedParams(List<Pair<String, Type>> allFields, Type owner) {
|
||||
List<FieldInfo> result = new ArrayList<FieldInfo>();
|
||||
for (Pair<String, Type> field : allFields) {
|
||||
result.add(FieldInfo.createForHiddenField(owner, field.second, field.first));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) {
|
||||
assert !info.isStatic();
|
||||
Type fieldType = info.getFieldType();
|
||||
@@ -632,6 +651,43 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean genNotNullAssertionForField(
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull PropertyDescriptor descriptor
|
||||
) {
|
||||
return genNotNullAssertion(v, state, descriptor, "checkFieldIsNotNull");
|
||||
}
|
||||
|
||||
private static boolean genNotNullAssertion(
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull CallableDescriptor descriptor,
|
||||
@NotNull String assertMethodToCall
|
||||
) {
|
||||
// Assertions are generated elsewhere for platform types
|
||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return false;
|
||||
|
||||
if (!state.isCallAssertionsEnabled()) return false;
|
||||
|
||||
if (!isDeclaredInJava(descriptor)) return false;
|
||||
|
||||
KotlinType type = descriptor.getReturnType();
|
||||
if (type == null || isNullableType(FlexibleTypesKt.lowerIfFlexible(type))) return false;
|
||||
|
||||
Type asmType = state.getTypeMapper().mapReturnType(descriptor);
|
||||
if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) {
|
||||
v.dup();
|
||||
v.visitLdcInsn(descriptor.getContainingDeclaration().getName().asString());
|
||||
v.visitLdcInsn(descriptor.getName().asString());
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, assertMethodToCall,
|
||||
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StackValue genNotNullAssertions(
|
||||
@NotNull GenerationState state,
|
||||
@@ -656,6 +712,19 @@ public class AsmUtil {
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isDeclaredInJava(@NotNull CallableDescriptor callableDescriptor) {
|
||||
CallableDescriptor descriptor = callableDescriptor;
|
||||
while (true) {
|
||||
if (descriptor instanceof JavaCallableMemberDescriptor) {
|
||||
return true;
|
||||
}
|
||||
CallableDescriptor original = descriptor.getOriginal();
|
||||
if (descriptor == original) break;
|
||||
descriptor = original;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
||||
v.aconst(null);
|
||||
|
||||
@@ -90,7 +90,7 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> actualArgsWithDeclIndex) {
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex) {
|
||||
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex, valueParameterTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ public interface Callable {
|
||||
}
|
||||
}
|
||||
|
||||
public fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||
public fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||
@@ -30,7 +31,7 @@ import org.jetbrains.org.objectweb.asm.util.Printer
|
||||
public class CallableMethod(
|
||||
override val owner: Type,
|
||||
private val defaultImplOwner: Type?,
|
||||
private val defaultMethodDesc: String,
|
||||
private val defaultImplParam: Type?,
|
||||
private val signature: JvmMethodSignature,
|
||||
private val invokeOpcode: Int,
|
||||
override val dispatchReceiverType: Type?,
|
||||
@@ -55,21 +56,24 @@ public class CallableMethod(
|
||||
}
|
||||
|
||||
public fun genInvokeDefaultInstruction(v: InstructionAdapter) {
|
||||
if (defaultImplOwner == null) {
|
||||
if (defaultImplOwner == null || defaultImplParam == null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
val method = getAsmMethod()
|
||||
val desc = JetTypeMapper.getDefaultDescriptor(
|
||||
method,
|
||||
if (invokeOpcode == INVOKESTATIC) null else defaultImplParam.getDescriptor(),
|
||||
extensionReceiverType != null
|
||||
)
|
||||
|
||||
if ("<init>".equals(method.getName())) {
|
||||
v.aconst(null)
|
||||
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.getInternalName(), "<init>", defaultMethodDesc, false)
|
||||
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.getInternalName(), "<init>", desc, false)
|
||||
}
|
||||
else {
|
||||
v.visitMethodInsn(INVOKESTATIC, defaultImplOwner.getInternalName(),
|
||||
method.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, false)
|
||||
|
||||
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
|
||||
method.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, desc, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -52,19 +51,11 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
|
||||
@Override
|
||||
protected void generateBody() {
|
||||
List<KtObjectDeclaration> companions = new ArrayList<KtObjectDeclaration>();
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS) {
|
||||
//generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
|
||||
for (KtDeclaration declaration : myClass.getDeclarations()) {
|
||||
if (shouldProcessFirst(declaration)) {
|
||||
//Generate companions after class body generation (need to record all synthetic accessors)
|
||||
if (declaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) declaration).isCompanion()) {
|
||||
companions.add((KtObjectDeclaration) declaration);
|
||||
CodegenUtilKt.populateCompanionBackingFieldNamesToOuterContextIfNeeded((KtObjectDeclaration) declaration, context, state);
|
||||
}
|
||||
else {
|
||||
generateDeclaration(declaration);
|
||||
}
|
||||
generateDeclaration(declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,14 +66,6 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
}
|
||||
}
|
||||
|
||||
generatePrimaryConstructorProperties();
|
||||
generateConstructors();
|
||||
generateDefaultImplsIfNeeded();
|
||||
|
||||
for (KtObjectDeclaration companion : companions) {
|
||||
generateDeclaration(companion);
|
||||
}
|
||||
|
||||
if (!DescriptorUtils.isInterface(descriptor)) {
|
||||
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||
if (memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
@@ -105,14 +88,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void generateConstructors() {
|
||||
|
||||
}
|
||||
|
||||
protected void generateDefaultImplsIfNeeded() {
|
||||
|
||||
generatePrimaryConstructorProperties();
|
||||
}
|
||||
|
||||
private static boolean shouldProcessFirst(KtDeclaration declaration) {
|
||||
|
||||
@@ -275,7 +275,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
if (bridge.equals(delegate)) return;
|
||||
|
||||
MethodVisitor mv =
|
||||
v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC,
|
||||
v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE,
|
||||
bridge.getName(), bridge.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||
@@ -283,7 +283,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
mv.visitCode();
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
MemberCodegen.markLineNumberForDescriptor(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
|
||||
MemberCodegen.markLineNumberForSyntheticFunction(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
|
||||
|
||||
iv.load(0, asmType);
|
||||
|
||||
@@ -368,6 +368,13 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage",
|
||||
Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false);
|
||||
}
|
||||
else if (container instanceof ScriptDescriptor) {
|
||||
// TODO: correct container for scripts (KScript?)
|
||||
StackValue value = generateClassLiteralReference(
|
||||
state.getTypeMapper(), ((ScriptDescriptor) container).getClassDescriptor().getDefaultType()
|
||||
);
|
||||
value.put(K_CLASS_TYPE, iv);
|
||||
}
|
||||
else {
|
||||
iv.aconst(null);
|
||||
}
|
||||
|
||||
@@ -108,13 +108,15 @@ class CollectionStubMethodGenerator(
|
||||
val genericSignatureInfo = overriddenMethod.getSpecialSignatureInfo()
|
||||
|
||||
val specialGenericSignature =
|
||||
genericSignatureInfo?.replaceValueParametersIn(overriddenMethodSignature.genericsSignature)
|
||||
?: overriddenMethodSignature.genericsSignature
|
||||
if (genericSignatureInfo != null)
|
||||
genericSignatureInfo.signature
|
||||
else
|
||||
overriddenMethodSignature.genericsSignature
|
||||
|
||||
val (asmMethod, valueParameters) =
|
||||
// if current method has special generic signature,
|
||||
// like `Collection.remove(E): Boolean` in Kotlin, use original signature to obtain `remove(Object)`
|
||||
if (genericSignatureInfo?.isObjectReplacedWithTypeParameter ?: false)
|
||||
// if remove(E) in Kotlin -> remove(Object) in Java
|
||||
// so choose original signature
|
||||
if (genericSignatureInfo == SpecialSignatureInfo.GENERIC_PARAMETER)
|
||||
Pair(originalSignature.asmMethod, originalSignature.valueParameters)
|
||||
else
|
||||
Pair(overriddenMethodSignature.asmMethod, overriddenMethodSignature.valueParameters)
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ScriptCodeDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
@@ -57,6 +58,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
@@ -308,29 +310,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
public void gen(KtElement expr, Type type) {
|
||||
StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr);
|
||||
// for repl store the result of the last line into special field
|
||||
if (value.type != Type.VOID_TYPE && state.getReplSpecific().getShouldGenerateScriptResultValue()) {
|
||||
ScriptContext context = getScriptContext();
|
||||
if (expr == context.getLastStatement()) {
|
||||
StackValue.Field resultValue = StackValue.field(context.getResultFieldInfo(), StackValue.LOCAL_0);
|
||||
resultValue.store(value, v);
|
||||
state.getReplSpecific().setHasResult(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
value.put(type, v);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ScriptContext getScriptContext() {
|
||||
CodegenContext context = getContext();
|
||||
while (!(context instanceof ScriptContext)) {
|
||||
context = context.getParentContext();
|
||||
}
|
||||
return (ScriptContext) context;
|
||||
}
|
||||
|
||||
public StackValue genLazy(KtElement expr, Type type) {
|
||||
StackValue value = gen(expr);
|
||||
return StackValue.coercion(value, type);
|
||||
@@ -668,7 +650,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
});
|
||||
}
|
||||
else {
|
||||
KtDestructuringDeclaration multiParameter = forExpression.getDestructuringParameter();
|
||||
KtMultiDeclaration multiParameter = forExpression.getMultiParameter();
|
||||
assert multiParameter != null;
|
||||
|
||||
// E tmp<e> = tmp<iterator>.next()
|
||||
@@ -686,15 +668,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
assignToLoopParameter();
|
||||
|
||||
if (forExpression.getLoopParameter() == null) {
|
||||
KtDestructuringDeclaration multiParameter = forExpression.getDestructuringParameter();
|
||||
KtMultiDeclaration multiParameter = forExpression.getMultiParameter();
|
||||
assert multiParameter != null;
|
||||
|
||||
generateMultiVariables(multiParameter.getEntries());
|
||||
}
|
||||
}
|
||||
|
||||
private void generateMultiVariables(List<KtDestructuringDeclarationEntry> entries) {
|
||||
for (KtDestructuringDeclarationEntry variableDeclaration : entries) {
|
||||
private void generateMultiVariables(List<KtMultiDeclarationEntry> entries) {
|
||||
for (KtMultiDeclarationEntry variableDeclaration : entries) {
|
||||
final VariableDescriptor componentDescriptor = bindingContext.get(VARIABLE, variableDeclaration);
|
||||
|
||||
@SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType());
|
||||
@@ -761,7 +743,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
// This method consumes range/progression from stack
|
||||
// The result is stored to local variable
|
||||
protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) {
|
||||
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + elementType.getDescriptor(), false);
|
||||
Type boxedType = boxType(elementType);
|
||||
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor(), false);
|
||||
StackValue.coerce(boxedType, elementType, v);
|
||||
v.store(varToStore, elementType);
|
||||
}
|
||||
}
|
||||
@@ -917,6 +901,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator {
|
||||
protected int endVar;
|
||||
|
||||
// For integer progressions instead of comparing loopParameterVar with endVar at the beginning of an iteration we check whether
|
||||
// loopParameterVar == finalVar at the end of the iteration (and also if there should be any iterations at all, before the loop)
|
||||
protected final boolean isIntegerProgression;
|
||||
|
||||
private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) {
|
||||
super(forExpression);
|
||||
|
||||
@@ -926,6 +914,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
case Type.SHORT:
|
||||
case Type.CHAR:
|
||||
case Type.LONG:
|
||||
isIntegerProgression = true;
|
||||
break;
|
||||
|
||||
case Type.DOUBLE:
|
||||
case Type.FLOAT:
|
||||
isIntegerProgression = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -940,12 +934,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
endVar = createLoopTempVariable(asmElementType);
|
||||
}
|
||||
|
||||
// Index of the local variable holding the actual last value of the loop parameter.
|
||||
// For ranges it equals end, for progressions it's a function of start, end and increment
|
||||
protected abstract int getFinalVar();
|
||||
|
||||
protected void checkPostCondition(@NotNull Label loopExit) {
|
||||
assert endVar != -1 :
|
||||
"endVar must be allocated, endVar = " + endVar;
|
||||
int finalVar = getFinalVar();
|
||||
assert isIntegerProgression && finalVar != -1 :
|
||||
"Post-condition should be checked only in case of integer progressions, finalVar = " + finalVar;
|
||||
|
||||
v.load(loopParameterVar, asmElementType);
|
||||
v.load(endVar, asmElementType);
|
||||
v.load(finalVar, asmElementType);
|
||||
if (asmElementType.getSort() == Type.LONG) {
|
||||
v.lcmp();
|
||||
v.ifeq(loopExit);
|
||||
@@ -954,10 +953,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
v.ificmpeq(loopExit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPreCondition(@NotNull Label loopExit) {
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
|
||||
@@ -974,8 +969,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
protected abstract void storeRangeStartAndEnd();
|
||||
|
||||
@Override
|
||||
protected int getFinalVar() {
|
||||
return endVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPreCondition(@NotNull Label loopExit) {
|
||||
if (isIntegerProgression) return;
|
||||
|
||||
v.load(loopParameterVar, asmElementType);
|
||||
v.load(endVar, asmElementType);
|
||||
|
||||
v.cmpg(asmElementType);
|
||||
v.ifgt(loopExit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkEmptyLoop(@NotNull Label loopExit) {
|
||||
if (!isIntegerProgression) return;
|
||||
|
||||
v.load(loopParameterVar, asmElementType);
|
||||
v.load(endVar, asmElementType);
|
||||
@@ -994,7 +1006,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@Override
|
||||
protected void increment(@NotNull Label loopExit) {
|
||||
checkPostCondition(loopExit);
|
||||
if (isIntegerProgression) {
|
||||
checkPostCondition(loopExit);
|
||||
}
|
||||
|
||||
if (asmElementType == Type.INT_TYPE) {
|
||||
v.iinc(loopParameterVar, 1);
|
||||
@@ -1041,9 +1055,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
gen(forExpression.getLoopRange(), asmLoopRangeType);
|
||||
v.dup();
|
||||
|
||||
// ranges inherit first and last from corresponding progressions
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1051,10 +1064,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private int incrementVar;
|
||||
private Type incrementType;
|
||||
|
||||
private int finalVar;
|
||||
|
||||
private ForInProgressionExpressionLoopGenerator(@NotNull KtForExpression forExpression) {
|
||||
super(forExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFinalVar() {
|
||||
return finalVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeLoop() {
|
||||
super.beforeLoop();
|
||||
@@ -1074,13 +1094,66 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
v.dup();
|
||||
v.dup();
|
||||
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar);
|
||||
|
||||
storeFinalVar();
|
||||
}
|
||||
|
||||
private void storeFinalVar() {
|
||||
if (!isIntegerProgression) {
|
||||
finalVar = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
v.load(loopParameterVar, asmElementType);
|
||||
v.load(endVar, asmElementType);
|
||||
v.load(incrementVar, incrementType);
|
||||
|
||||
Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE;
|
||||
v.invokestatic("kotlin/internal/ProgressionUtilKt", "getProgressionFinalElement",
|
||||
Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType), false);
|
||||
|
||||
finalVar = createLoopTempVariable(asmElementType);
|
||||
v.store(finalVar, asmElementType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPreCondition(@NotNull Label loopExit) {
|
||||
if (isIntegerProgression) return;
|
||||
|
||||
v.load(loopParameterVar, asmElementType);
|
||||
v.load(endVar, asmElementType);
|
||||
v.load(incrementVar, incrementType);
|
||||
|
||||
Label negativeIncrement = new Label();
|
||||
Label afterIf = new Label();
|
||||
|
||||
if (incrementType.getSort() == Type.DOUBLE) {
|
||||
v.dconst(0.0);
|
||||
}
|
||||
else {
|
||||
v.fconst(0.0f);
|
||||
}
|
||||
v.cmpl(incrementType);
|
||||
v.ifle(negativeIncrement); // if increment < 0, jump
|
||||
|
||||
// increment > 0
|
||||
v.cmpg(asmElementType); // if loop parameter is NaN, exit from loop, as well
|
||||
v.ifgt(loopExit);
|
||||
v.goTo(afterIf);
|
||||
|
||||
// increment < 0
|
||||
v.mark(negativeIncrement);
|
||||
v.cmpl(asmElementType); // if loop parameter is NaN, exit from loop, as well
|
||||
v.iflt(loopExit);
|
||||
v.mark(afterIf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkEmptyLoop(@NotNull Label loopExit) {
|
||||
if (!isIntegerProgression) return;
|
||||
|
||||
v.load(loopParameterVar, asmElementType);
|
||||
v.load(endVar, asmElementType);
|
||||
@@ -1125,7 +1198,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@Override
|
||||
protected void increment(@NotNull Label loopExit) {
|
||||
checkPostCondition(loopExit);
|
||||
if (isIntegerProgression) {
|
||||
checkPostCondition(loopExit);
|
||||
}
|
||||
|
||||
v.load(loopParameterVar, asmElementType);
|
||||
v.load(incrementVar, asmElementType);
|
||||
@@ -1154,7 +1229,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private StackValue generateBreakOrContinueExpression(
|
||||
@NotNull KtExpressionWithLabel expression,
|
||||
boolean isBreak,
|
||||
final @NotNull Label afterBreakContinueLabel
|
||||
@NotNull Label afterBreakContinueLabel
|
||||
) {
|
||||
assert expression instanceof KtContinueExpression || expression instanceof KtBreakExpression;
|
||||
|
||||
@@ -1173,16 +1248,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (labelElement == null ||
|
||||
loopBlockStackElement.targetLabel != null &&
|
||||
labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) {
|
||||
final Label label = isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel;
|
||||
return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
PseudoInsnsKt.fixStackAndJump(v, label);
|
||||
v.mark(afterBreakContinueLabel);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
}
|
||||
);
|
||||
Label label = isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel;
|
||||
PseudoInsnsKt.fixStackAndJump(v, label);
|
||||
v.mark(afterBreakContinueLabel);
|
||||
return StackValue.none();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1331,7 +1400,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitLambdaExpression(@NotNull KtLambdaExpression expression, StackValue receiver) {
|
||||
public StackValue visitFunctionLiteralExpression(@NotNull KtFunctionLiteralExpression expression, StackValue receiver) {
|
||||
if (Boolean.TRUE.equals(bindingContext.get(BLOCK, expression))) {
|
||||
return gen(expression.getFunctionLiteral().getBodyExpression());
|
||||
}
|
||||
@@ -1568,9 +1637,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
|
||||
private void putDescriptorIntoFrameMap(@NotNull KtElement statement) {
|
||||
if (statement instanceof KtDestructuringDeclaration) {
|
||||
KtDestructuringDeclaration multiDeclaration = (KtDestructuringDeclaration) statement;
|
||||
for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
if (statement instanceof KtMultiDeclaration) {
|
||||
KtMultiDeclaration multiDeclaration = (KtMultiDeclaration) statement;
|
||||
for (KtMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
putLocalVariableIntoFrameMap(entry);
|
||||
}
|
||||
}
|
||||
@@ -1608,9 +1677,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull Label blockEnd,
|
||||
@NotNull List<Function<StackValue, Void>> leaveTasks
|
||||
) {
|
||||
if (statement instanceof KtDestructuringDeclaration) {
|
||||
KtDestructuringDeclaration multiDeclaration = (KtDestructuringDeclaration) statement;
|
||||
for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
if (statement instanceof KtMultiDeclaration) {
|
||||
KtMultiDeclaration multiDeclaration = (KtMultiDeclaration) statement;
|
||||
for (KtMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
addLeaveTaskToRemoveLocalVariableFromFrameMap(entry, blockEnd, leaveTasks);
|
||||
}
|
||||
}
|
||||
@@ -1790,37 +1859,33 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitReturnExpression(@NotNull final KtReturnExpression expression, StackValue receiver) {
|
||||
return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
KtExpression returnedExpression = expression.getReturnedExpression();
|
||||
CallableMemberDescriptor descriptor = getContext().getContextDescriptor();
|
||||
NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression);
|
||||
boolean isNonLocalReturn = nonLocalReturn != null;
|
||||
if (isNonLocalReturn && !state.isInlineEnabled()) {
|
||||
state.getDiagnostics().report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression));
|
||||
genThrow(v, "java/lang/UnsupportedOperationException",
|
||||
"Non-local returns are not allowed with inlining disabled");
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
public StackValue visitReturnExpression(@NotNull KtReturnExpression expression, StackValue receiver) {
|
||||
KtExpression returnedExpression = expression.getReturnedExpression();
|
||||
CallableMemberDescriptor descriptor = getContext().getContextDescriptor();
|
||||
NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression);
|
||||
boolean isNonLocalReturn = nonLocalReturn != null;
|
||||
if (isNonLocalReturn && !state.isInlineEnabled()) {
|
||||
state.getDiagnostics().report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression));
|
||||
genThrow(v, "java/lang/UnsupportedOperationException",
|
||||
"Non-local returns are not allowed with inlining disabled");
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : ExpressionCodegen.this.returnType;
|
||||
if (returnedExpression != null) {
|
||||
gen(returnedExpression, returnType);
|
||||
}
|
||||
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : this.returnType;
|
||||
if (returnedExpression != null) {
|
||||
gen(returnedExpression, returnType);
|
||||
}
|
||||
|
||||
Label afterReturnLabel = new Label();
|
||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel);
|
||||
Label afterReturnLabel = new Label();
|
||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel);
|
||||
|
||||
if (isNonLocalReturn) {
|
||||
InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName);
|
||||
}
|
||||
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
|
||||
v.mark(afterReturnLabel);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
if (isNonLocalReturn) {
|
||||
InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName);
|
||||
}
|
||||
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
|
||||
v.mark(afterReturnLabel);
|
||||
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
public void generateFinallyBlocksIfNeeded(Type returnType, @NotNull Label afterReturnLabel) {
|
||||
@@ -1878,10 +1943,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (!endsWithReturn(expr)) {
|
||||
markLineNumber(expr, true);
|
||||
|
||||
if (isLambdaVoidBody(expr, returnType)) {
|
||||
markLineNumber((KtFunctionLiteral) expr.getParent(), true);
|
||||
}
|
||||
|
||||
if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) {
|
||||
StackValue.none().put(returnType, v);
|
||||
}
|
||||
@@ -1899,17 +1960,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return bodyExpression instanceof KtReturnExpression;
|
||||
}
|
||||
|
||||
private static boolean isLambdaVoidBody(KtElement bodyExpression, Type returnType) {
|
||||
if (bodyExpression instanceof KtBlockExpression) {
|
||||
PsiElement parent = bodyExpression.getParent();
|
||||
if (parent instanceof KtFunctionLiteral) {
|
||||
return Type.VOID_TYPE.equals(returnType);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, @NotNull StackValue receiver) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
|
||||
@@ -1993,6 +2043,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (localOrCaptured != null) {
|
||||
return localOrCaptured;
|
||||
}
|
||||
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
if (descriptor instanceof ValueParameterDescriptor && container instanceof ScriptCodeDescriptor) {
|
||||
ScriptCodeDescriptor scriptCodeDescriptor = (ScriptCodeDescriptor) container;
|
||||
ScriptDescriptor scriptDescriptor = (ScriptDescriptor) scriptCodeDescriptor.getContainingDeclaration();
|
||||
Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
|
||||
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
|
||||
ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
StackValue script = StackValue.thisOrOuter(this, scriptClass, false, false);
|
||||
Type fieldType = typeMapper.mapType(valueParameterDescriptor);
|
||||
return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false, script,
|
||||
valueParameterDescriptor);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
||||
}
|
||||
|
||||
@@ -2071,10 +2136,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
PropertyGetterDescriptor getter = descriptor.getGetter();
|
||||
if (getter != null) {
|
||||
Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter);
|
||||
if (call != null) {
|
||||
assert call.getExplicitReceiver() != null : "No explicit receiver for call:" + call;
|
||||
return ((ReceiverValue) call.getExplicitReceiver()).getType();
|
||||
}
|
||||
return call != null ? call.getExplicitReceiver().getType() : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -2122,7 +2184,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (isBackingFieldInClassCompanion && forceField) {
|
||||
fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION;
|
||||
}
|
||||
else if (syntheticBackingField && context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration) {
|
||||
else if (syntheticBackingField && context.getParentContext().getContextDescriptor() != containingDeclaration) {
|
||||
fieldAccessorKind = FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||
}
|
||||
boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) ||
|
||||
@@ -2163,7 +2225,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
if (!couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) {
|
||||
propertyDescriptor = context.getAccessorForSuperCallIfNeeded(propertyDescriptor, superCallTarget);
|
||||
if (isSuper && !isJvmInterface(containingDeclaration)) {
|
||||
CodegenContext c = context.findParentContextWithDescriptor(superCallTarget);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
|
||||
if (c != context.getParentContext()) {
|
||||
propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor, superCallTarget);
|
||||
}
|
||||
}
|
||||
|
||||
propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superCallTarget);
|
||||
|
||||
@@ -2247,8 +2315,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
final SamType samType = bindingContext.get(SAM_VALUE, probablyParenthesizedExpression);
|
||||
if (samType == null || expression == null) return null;
|
||||
|
||||
if (expression instanceof KtLambdaExpression) {
|
||||
return genClosure(((KtLambdaExpression) expression).getFunctionLiteral(), samType);
|
||||
if (expression instanceof KtFunctionLiteralExpression) {
|
||||
return genClosure(((KtFunctionLiteralExpression) expression).getFunctionLiteral(), samType);
|
||||
}
|
||||
|
||||
if (expression instanceof KtNamedFunction) {
|
||||
@@ -2321,19 +2389,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
|
||||
FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall);
|
||||
ClassDescriptor superCallTarget = getSuperCallTarget(call);
|
||||
boolean superCall = superCallTarget != null;
|
||||
|
||||
fd = context.getAccessorForSuperCallIfNeeded(fd, superCallTarget);
|
||||
|
||||
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
|
||||
if (!codegenExtensions.isEmpty()) {
|
||||
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
|
||||
for (ExpressionCodegenExtension extension : codegenExtensions) {
|
||||
StackValue stackValue = extension.applyFunction(receiver, resolvedCall, context);
|
||||
if (stackValue != null) return stackValue;
|
||||
if (superCall && !isJvmInterface(fd.getContainingDeclaration())) {
|
||||
CodegenContext c = context.findParentContextWithDescriptor(superCallTarget);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + fd;
|
||||
if (c != context.getParentContext()) {
|
||||
fd = (FunctionDescriptor) c.getAccessor(fd, superCallTarget);
|
||||
}
|
||||
}
|
||||
|
||||
Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall);
|
||||
Callable callable = resolveToCallable(fd, superCall, resolvedCall);
|
||||
|
||||
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||
}
|
||||
@@ -2390,10 +2456,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull CallGenerator callGenerator,
|
||||
@NotNull ArgumentGenerator argumentGenerator
|
||||
) {
|
||||
callableMethod.beforeParameterGeneration(v, null);
|
||||
|
||||
if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
|
||||
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
|
||||
|
||||
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
|
||||
if (!codegenExtensions.isEmpty()) {
|
||||
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
|
||||
for (ExpressionCodegenExtension extension : codegenExtensions) {
|
||||
if (extension.applyFunction(receiver, resolvedCall, context)) return;
|
||||
}
|
||||
}
|
||||
|
||||
receiver.put(receiver.type, v);
|
||||
callableMethod.afterReceiverGeneration(v);
|
||||
}
|
||||
|
||||
callGenerator.putHiddenParams();
|
||||
@@ -2472,8 +2548,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
else {
|
||||
mappings.addParameterMappingToNewParameter(
|
||||
key.getName().getIdentifier(), type,
|
||||
parameterDescriptor.getName().getIdentifier());
|
||||
key.getName().getIdentifier(),
|
||||
parameterDescriptor.getName().getIdentifier()
|
||||
);
|
||||
}
|
||||
}
|
||||
return getOrCreateCallGenerator(
|
||||
@@ -2482,9 +2559,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateReceiverValue(@Nullable ReceiverValue receiverValue, boolean isSuper) {
|
||||
if (receiverValue instanceof ImplicitClassReceiver) {
|
||||
ClassDescriptor receiverDescriptor = ((ImplicitClassReceiver) receiverValue).getDeclarationDescriptor();
|
||||
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue, boolean isSuper) {
|
||||
if (receiverValue instanceof ClassReceiver) {
|
||||
ClassDescriptor receiverDescriptor = ((ClassReceiver) receiverValue).getDeclarationDescriptor();
|
||||
if (DescriptorUtils.isCompanionObject(receiverDescriptor)) {
|
||||
CallableMemberDescriptor contextDescriptor = context.getContextDescriptor();
|
||||
if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) {
|
||||
@@ -2494,15 +2571,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.singleton(receiverDescriptor, typeMapper);
|
||||
}
|
||||
}
|
||||
else if (receiverDescriptor instanceof ScriptDescriptor) {
|
||||
return generateScriptReceiver
|
||||
((ScriptDescriptor) receiverDescriptor);
|
||||
}
|
||||
else {
|
||||
return StackValue.thisOrOuter(this, receiverDescriptor, isSuper,
|
||||
receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor));
|
||||
receiverValue instanceof CastClassReceiver || isEnumEntry(receiverDescriptor));
|
||||
}
|
||||
}
|
||||
else if (receiverValue instanceof ScriptReceiver) {
|
||||
return generateScript((ScriptReceiver) receiverValue);
|
||||
}
|
||||
else if (receiverValue instanceof ExtensionReceiver) {
|
||||
return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor());
|
||||
}
|
||||
@@ -2519,8 +2595,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return context.generateReceiver(descriptor, state, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue generateScriptReceiver(@NotNull ScriptDescriptor receiver) {
|
||||
private StackValue generateScript(@NotNull ScriptReceiver receiver) {
|
||||
CodegenContext cur = context;
|
||||
StackValue result = StackValue.LOCAL_0;
|
||||
boolean inStartConstructorContext = cur instanceof ConstructorContext;
|
||||
@@ -2532,14 +2607,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (cur instanceof ScriptContext) {
|
||||
ScriptContext scriptContext = (ScriptContext) cur;
|
||||
|
||||
if (scriptContext.getScriptDescriptor() == receiver) {
|
||||
ScriptDescriptor receiverDeclarationDescriptor = receiver.getDeclarationDescriptor();
|
||||
if (scriptContext.getScriptDescriptor() == receiverDeclarationDescriptor) {
|
||||
//TODO lazy
|
||||
return result;
|
||||
}
|
||||
Type currentScriptType = typeMapper.mapType(scriptContext.getScriptDescriptor());
|
||||
Type classType = typeMapper.mapType(receiver);
|
||||
String fieldName = scriptContext.getScriptFieldName(receiver);
|
||||
return StackValue.field(classType, currentScriptType, fieldName, false, result, receiver);
|
||||
else {
|
||||
Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor());
|
||||
Type classType = asmTypeForScriptDescriptor(bindingContext, receiverDeclarationDescriptor);
|
||||
String fieldName = scriptContext.getScriptFieldName(receiverDeclarationDescriptor);
|
||||
return StackValue.field(classType, currentScriptType, fieldName, false, result, receiverDeclarationDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
result = cur.getOuterExpression(result, false);
|
||||
@@ -2555,6 +2633,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) {
|
||||
return generateThisOrOuter(calleeContainingClass, isSuper, false);
|
||||
@@ -2746,7 +2825,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull KtElement element,
|
||||
@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull VariableDescriptor target,
|
||||
@Nullable ReceiverValue dispatchReceiver
|
||||
@NotNull ReceiverValue dispatchReceiver
|
||||
) {
|
||||
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||
|
||||
@@ -3264,7 +3343,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration multiDeclaration, StackValue receiver) {
|
||||
public StackValue visitMultiDeclaration(@NotNull KtMultiDeclaration multiDeclaration, StackValue receiver) {
|
||||
KtExpression initializer = multiDeclaration.getInitializer();
|
||||
if (initializer == null) return StackValue.none();
|
||||
|
||||
@@ -3281,7 +3360,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
v.store(tempVarIndex, initializerAsmType);
|
||||
StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType);
|
||||
|
||||
for (KtDestructuringDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) {
|
||||
for (KtMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) {
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration);
|
||||
assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText();
|
||||
Call call = makeFakeCall(initializerAsReceiver);
|
||||
@@ -3317,14 +3396,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
Type varType = asmType(variableDescriptor.getType());
|
||||
|
||||
StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType);
|
||||
StackValue storeTo;
|
||||
if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) {
|
||||
KtScript scriptPsi = KtPsiUtil.getScript(variableDeclaration);
|
||||
assert scriptPsi != null;
|
||||
Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi);
|
||||
storeTo = StackValue.field(varType, scriptClassType, variableDeclaration.getName(), false, StackValue.LOCAL_0, variableDescriptor);
|
||||
}
|
||||
else if (sharedVarType == null) {
|
||||
storeTo = StackValue.local(index, varType);
|
||||
}
|
||||
else {
|
||||
storeTo = StackValue.shared(index, varType);
|
||||
}
|
||||
|
||||
storeTo.putReceiver(v, false);
|
||||
initializer.put(initializer.type, v);
|
||||
|
||||
markLineNumber(variableDeclaration, false);
|
||||
|
||||
storeTo.storeSelector(initializer.type, v);
|
||||
storeTo.store(initializer, v);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -3361,7 +3447,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (dispatchReceiver != null) {
|
||||
Type receiverType = typeMapper.mapType(dispatchReceiver.getType());
|
||||
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
|
||||
boolean callSuper = containingDeclaration.isInner() && receiver instanceof ImplicitClassReceiver;
|
||||
boolean callSuper = containingDeclaration.isInner() && receiver instanceof ClassReceiver;
|
||||
generateReceiverValue(receiver, callSuper).put(receiverType, v);
|
||||
}
|
||||
|
||||
@@ -3485,15 +3571,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitThrowExpression(@NotNull final KtThrowExpression expression, StackValue receiver) {
|
||||
return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE);
|
||||
v.athrow();
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
public StackValue visitThrowExpression(@NotNull KtThrowExpression expression, StackValue receiver) {
|
||||
gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE);
|
||||
v.athrow();
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3677,8 +3758,13 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
|
||||
if (opToken != KtTokens.AS_SAFE) {
|
||||
if (!TypeUtils.isNullableType(rightType) && !TypeUtils.isReifiedTypeParameter(rightType)) {
|
||||
CodegenUtilKt.generateNullCheckForNonSafeAs(v, rightType);
|
||||
if (!TypeUtils.isNullableType(rightType)) {
|
||||
v.dup();
|
||||
Label nonnull = new Label();
|
||||
v.ifnonnull(nonnull);
|
||||
genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " +
|
||||
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(rightType));
|
||||
v.mark(nonnull);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -3734,7 +3820,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
return negated ? StackValue.not(value) : value;
|
||||
}
|
||||
|
||||
private StackValue generateInstanceOf(final StackValue expressionToGen, final KotlinType kotlinType, final boolean leaveExpressionOnStack) {
|
||||
private StackValue generateInstanceOf(final StackValue expressionToGen, final KotlinType jetType, final boolean leaveExpressionOnStack) {
|
||||
return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
@@ -3742,13 +3828,22 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dup();
|
||||
}
|
||||
CodegenUtilKt.generateIsCheck(v, kotlinType.isMarkedNullable() && !TypeUtils.isReifiedTypeParameter(kotlinType), new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
generateInstanceOfInstruction(kotlinType);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
if (jetType.isMarkedNullable()) {
|
||||
Label nope = new Label();
|
||||
Label end = new Label();
|
||||
|
||||
v.dup();
|
||||
v.ifnull(nope);
|
||||
generateInstanceOfInstruction(jetType);
|
||||
v.goTo(end);
|
||||
v.mark(nope);
|
||||
v.pop();
|
||||
v.iconst(1);
|
||||
v.mark(end);
|
||||
}
|
||||
else {
|
||||
generateInstanceOfInstruction(jetType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@@ -3777,8 +3872,8 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
parentCodegen.getReifiedTypeParametersUsages().
|
||||
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||
}
|
||||
boolean putNullableFlag = ReifiedTypeInliner.isNullableMarkerInstruction(markerMethodName) && type.isMarkedNullable();
|
||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString() + (putNullableFlag ? "?" : ""));
|
||||
|
||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -59,7 +58,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
@@ -221,6 +219,8 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
endVisit(mv, null, origin.getElement());
|
||||
|
||||
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
|
||||
}
|
||||
|
||||
private void generateMethodAnnotations(
|
||||
@@ -354,10 +354,6 @@ public class FunctionCodegen {
|
||||
mv.visitLabel(methodBegin);
|
||||
|
||||
JetTypeMapper typeMapper = parentCodegen.typeMapper;
|
||||
if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, getSignatureMapper(typeMapper))) {
|
||||
generateTypeCheckBarrierIfNeeded(
|
||||
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), /* delegateParameterType = */null);
|
||||
}
|
||||
|
||||
Label methodEnd;
|
||||
|
||||
@@ -371,11 +367,11 @@ public class FunctionCodegen {
|
||||
else {
|
||||
FrameMap frameMap = createFrameMap(parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(),
|
||||
functionDescriptor));
|
||||
if (context.isInlineMethodContext()) {
|
||||
if (context.isInlineFunction()) {
|
||||
functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
}
|
||||
|
||||
if (context instanceof InlineLambdaContext) {
|
||||
if (context.isInliningLambda()) {
|
||||
lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
}
|
||||
|
||||
@@ -396,7 +392,7 @@ public class FunctionCodegen {
|
||||
Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
|
||||
generateLocalVariableTable(mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind());
|
||||
|
||||
if (context.isInlineMethodContext() && functionFakeIndex != -1) {
|
||||
if (context.isInlineFunction() && functionFakeIndex != -1) {
|
||||
mv.visitLocalVariable(
|
||||
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + functionDescriptor.getName().asString(),
|
||||
Type.INT_TYPE.getDescriptor(), null,
|
||||
@@ -404,7 +400,7 @@ public class FunctionCodegen {
|
||||
functionFakeIndex);
|
||||
}
|
||||
|
||||
if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
|
||||
if (context.isInliningLambda() && thisType != null && lambdaFakeIndex != -1) {
|
||||
String name = thisType.getClassName();
|
||||
int indexOfLambdaOrdinal = name.lastIndexOf("$");
|
||||
if (indexOfLambdaOrdinal > 0) {
|
||||
@@ -553,13 +549,18 @@ public class FunctionCodegen {
|
||||
// If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges
|
||||
if (CallResolverUtilKt.isOrOverridesSynthesized(descriptor)) return;
|
||||
|
||||
boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) != null;
|
||||
boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(descriptor) != null;
|
||||
|
||||
Set<Bridge<Method>> bridgesToGenerate;
|
||||
if (!isSpecial) {
|
||||
bridgesToGenerate = ImplKt.generateBridgesForFunctionDescriptor(
|
||||
descriptor,
|
||||
getSignatureMapper(typeMapper)
|
||||
new Function1<FunctionDescriptor, Method>() {
|
||||
@Override
|
||||
public Method invoke(FunctionDescriptor descriptor) {
|
||||
return typeMapper.mapSignature(descriptor).getAsmMethod();
|
||||
}
|
||||
}
|
||||
);
|
||||
if (!bridgesToGenerate.isEmpty()) {
|
||||
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
|
||||
@@ -574,7 +575,12 @@ public class FunctionCodegen {
|
||||
else {
|
||||
Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
||||
descriptor,
|
||||
getSignatureMapper(typeMapper)
|
||||
new Function1<FunctionDescriptor, Method>() {
|
||||
@Override
|
||||
public Method invoke(FunctionDescriptor descriptor) {
|
||||
return typeMapper.mapSignature(descriptor).getAsmMethod();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!specials.isEmpty()) {
|
||||
@@ -587,7 +593,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
|
||||
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
|
||||
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(descriptor);
|
||||
assert overridden != null;
|
||||
|
||||
Method method = typeMapper.mapSignature(descriptor).getAsmMethod();
|
||||
@@ -597,16 +603,6 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Function1<FunctionDescriptor, Method> getSignatureMapper(final @NotNull JetTypeMapper typeMapper) {
|
||||
return new Function1<FunctionDescriptor, Method>() {
|
||||
@Override
|
||||
public Method invoke(FunctionDescriptor descriptor) {
|
||||
return typeMapper.mapSignature(descriptor).getAsmMethod();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) {
|
||||
String name = descriptor.getName().asString();
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
|
||||
@@ -853,11 +849,9 @@ public class FunctionCodegen {
|
||||
Type[] originalArgTypes = delegateTo.getArgumentTypes();
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
|
||||
MemberCodegen.markLineNumberForSyntheticFunction(owner.getThisDescriptor(), iv);
|
||||
|
||||
if (delegateTo.getArgumentTypes().length == 1 && isSpecialBridge) {
|
||||
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes()[0]);
|
||||
}
|
||||
generateInstanceOfBarrierIfNeeded(iv, descriptor, bridge, delegateTo);
|
||||
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
@@ -882,45 +876,58 @@ public class FunctionCodegen {
|
||||
endVisit(mv, "bridge method", origin);
|
||||
}
|
||||
|
||||
private static void generateTypeCheckBarrierIfNeeded(
|
||||
private static void generateInstanceOfBarrierIfNeeded(
|
||||
@NotNull InstructionAdapter iv,
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
@NotNull Type returnType,
|
||||
@Nullable final Type delegateParameterType
|
||||
@NotNull Method bridge,
|
||||
@NotNull Method delegateTo
|
||||
) {
|
||||
BuiltinMethodsWithSpecialGenericSignature.DefaultValue defaultValue =
|
||||
BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
|
||||
if (defaultValue == null) return;
|
||||
if (BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) == null) return;
|
||||
|
||||
assert descriptor.getValueParameters().size() == 1 : "Should be descriptor with one value parameter, but found: " + descriptor;
|
||||
|
||||
boolean isCheckForAny = delegateParameterType == null || OBJECT_TYPE.equals(delegateParameterType);
|
||||
|
||||
final KotlinType kotlinType = descriptor.getValueParameters().get(0).getType();
|
||||
|
||||
if (isCheckForAny && TypeUtils.isNullableType(kotlinType)) return;
|
||||
if (bridge.getArgumentTypes()[0].getSort() != Type.OBJECT) return;
|
||||
|
||||
iv.load(1, OBJECT_TYPE);
|
||||
|
||||
Label afterBarrier = new Label();
|
||||
KotlinType jetType = descriptor.getValueParameters().get(0).getType();
|
||||
|
||||
if (isCheckForAny) {
|
||||
assert !TypeUtils.isNullableType(kotlinType) : "Only bridges for not-nullable types are necessary";
|
||||
iv.ifnonnull(afterBarrier);
|
||||
// TODO: reuse logic from ExpressionCodegen
|
||||
if (jetType.isMarkedNullable()) {
|
||||
Label nope = new Label();
|
||||
Label end = new Label();
|
||||
|
||||
iv.dup();
|
||||
iv.ifnull(nope);
|
||||
TypeIntrinsics.instanceOf(
|
||||
iv,
|
||||
jetType,
|
||||
boxType(delegateTo.getArgumentTypes()[0])
|
||||
);
|
||||
iv.goTo(end);
|
||||
iv.mark(nope);
|
||||
iv.pop();
|
||||
iv.iconst(1);
|
||||
iv.mark(end);
|
||||
}
|
||||
else {
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType.isMarkedNullable(), new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
TypeIntrinsics.instanceOf(adapter, kotlinType, boxType(delegateParameterType));
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
iv.ifne(afterBarrier);
|
||||
TypeIntrinsics.instanceOf(
|
||||
iv,
|
||||
jetType,
|
||||
boxType(delegateTo.getArgumentTypes()[0])
|
||||
);
|
||||
}
|
||||
|
||||
StackValue.constant(defaultValue.getValue(), returnType).put(returnType, iv);
|
||||
iv.areturn(returnType);
|
||||
Label afterBarrier = new Label();
|
||||
|
||||
iv.ifne(afterBarrier);
|
||||
|
||||
String shortName = getFqName(descriptor).shortName().asString();
|
||||
StackValue returnValue =
|
||||
("indexOf".equals(shortName) || "lastIndexOf".equals(shortName)) ? StackValue.constant(-1, Type.INT_TYPE) : StackValue.none();
|
||||
|
||||
returnValue.put(bridge.getReturnType(), iv);
|
||||
iv.areturn(bridge.getReturnType());
|
||||
|
||||
iv.visitLabel(afterBarrier);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DelegatingResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
@@ -36,6 +35,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
|
||||
public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> {
|
||||
private final ResolvedCall<?> resolvedCall;
|
||||
private final FunctionDescriptor referencedFunction;
|
||||
@@ -80,13 +81,13 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public ReceiverValue getExtensionReceiver() {
|
||||
return extensionReceiver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public ReceiverValue getDispatchReceiver() {
|
||||
return dispatchReceiver;
|
||||
@@ -117,7 +118,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
}
|
||||
}
|
||||
else {
|
||||
Call call = CallMaker.makeCall(fakeExpression, null, null, fakeExpression, fakeArguments);
|
||||
Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
|
||||
result = codegen.invokeFunction(call, fakeResolvedCall, StackValue.none());
|
||||
}
|
||||
|
||||
@@ -155,18 +156,18 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
private ReceiverValue computeAndSaveReceiver(
|
||||
@NotNull JvmMethodSignature signature,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@Nullable ReceiverParameterDescriptor receiver
|
||||
) {
|
||||
if (receiver == null) return null;
|
||||
if (receiver == null) return NO_RECEIVER;
|
||||
|
||||
KtExpression receiverExpression = KtPsiFactoryKt
|
||||
.KtPsiFactory(state.getProject()).createExpression("callableReferenceFakeReceiver");
|
||||
codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature));
|
||||
return ExpressionReceiver.Companion.create(receiverExpression, receiver.getType(), BindingContext.EMPTY);
|
||||
return new ExpressionReceiver(receiverExpression, receiver.getType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -63,7 +63,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -98,8 +98,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
private List<PropertyAndDefaultValue> companionObjectPropertiesToCopy;
|
||||
|
||||
private final DelegationFieldsInfo delegationFieldsInfo;
|
||||
|
||||
private final List<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>> additionalTasks =
|
||||
new ArrayList<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>>();
|
||||
|
||||
@@ -114,7 +112,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
super(aClass, context, v, state, parentCodegen);
|
||||
this.classAsmType = typeMapper.mapClass(descriptor);
|
||||
this.isLocal = isLocal;
|
||||
delegationFieldsInfo = getDelegationFieldsInfo(myClass.getSuperTypeListEntries());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,7 +227,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDefaultImplsIfNeeded() {
|
||||
protected void generateBody() {
|
||||
super.generateBody();
|
||||
if (isInterface(descriptor) && !isLocal) {
|
||||
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
|
||||
ClassBuilder defaultImplsBuilder =
|
||||
@@ -239,7 +237,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
CodegenContext parentContext = context.getParentContext();
|
||||
assert parentContext != null : "Parent context of interface declaration should not be null";
|
||||
|
||||
ClassContext defaultImplsContext = parentContext.intoDefaultImplsClass(descriptor, (ClassContext) context, state);
|
||||
ClassContext defaultImplsContext = parentContext.intoClass(descriptor, OwnerKind.DEFAULT_IMPLS, state);
|
||||
new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
|
||||
}
|
||||
}
|
||||
@@ -304,7 +302,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private JvmClassSignature signature() {
|
||||
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
|
||||
|
||||
typeMapper.writeFormalTypeParameters(descriptor.getDeclaredTypeParameters(), sw);
|
||||
typeMapper.writeFormalTypeParameters(descriptor.getTypeConstructor().getParameters(), sw);
|
||||
|
||||
sw.writeSuperclass();
|
||||
if (superClassType == null) {
|
||||
@@ -373,31 +371,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateCompanionObjectBackingFieldCopies();
|
||||
|
||||
generateTraitMethods();
|
||||
|
||||
generateDelegates(delegationFieldsInfo);
|
||||
|
||||
if (!isInterface(descriptor) || kind == OwnerKind.DEFAULT_IMPLS) {
|
||||
generateSyntheticAccessors();
|
||||
}
|
||||
|
||||
generateEnumMethods();
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
new CollectionStubMethodGenerator(state, descriptor, functionCodegen, v).generate();
|
||||
|
||||
generateToArray();
|
||||
|
||||
genClosureFields(context.closure, v, typeMapper);
|
||||
|
||||
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
|
||||
extension.generateClassSyntheticParts(v, state, myClass, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateConstructors() {
|
||||
DelegationFieldsInfo delegationFieldsInfo = getDelegationFieldsInfo(myClass.getDelegationSpecifiers());
|
||||
try {
|
||||
lookupConstructorExpressionsInClosureIfPresent();
|
||||
generatePrimaryConstructor(delegationFieldsInfo);
|
||||
@@ -414,6 +388,26 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
catch (RuntimeException e) {
|
||||
throw new RuntimeException("Error generating constructors of class " + myClass.getName() + " with kind " + kind, e);
|
||||
}
|
||||
|
||||
generateTraitMethods();
|
||||
|
||||
generateDelegates(delegationFieldsInfo);
|
||||
|
||||
generateSyntheticAccessors();
|
||||
|
||||
generateEnumMethods();
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
new CollectionStubMethodGenerator(state, descriptor, functionCodegen, v).generate();
|
||||
|
||||
generateToArray();
|
||||
|
||||
genClosureFields(context.closure, v, typeMapper);
|
||||
|
||||
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
|
||||
extension.generateClassSyntheticParts(v, state, myClass, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isGenericToArrayPresent() {
|
||||
@@ -857,7 +851,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||
// Invoke the object constructor but ignore the result because INSTANCE$ will be initialized in the first line of <init>
|
||||
InstructionAdapter v = createOrGetClInitCodegen().v;
|
||||
markLineNumberForElement(element, v);
|
||||
markLineNumberForSyntheticFunction(element, v);
|
||||
v.anew(classAsmType);
|
||||
v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
|
||||
|
||||
@@ -892,7 +886,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
int modifiers = ACC_STATIC | ACC_FINAL | ACC_PUBLIC | (property.isConst() ? 0 : ACC_DEPRECATED);
|
||||
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.Synthetic(DescriptorToSourceUtils.descriptorToDeclaration(property), property),
|
||||
modifiers, context.getFieldName(property, false),
|
||||
type.getDescriptor(), typeMapper.mapFieldSignature(property.getType(), property),
|
||||
type.getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
|
||||
info.defaultValue);
|
||||
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type);
|
||||
@@ -948,14 +942,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||
|
||||
final KtPrimaryConstructor primaryConstructor = myClass.getPrimaryConstructor();
|
||||
KtPrimaryConstructor primaryConstructor = myClass.getPrimaryConstructor();
|
||||
JvmDeclarationOrigin origin = JvmDeclarationOriginKt
|
||||
.OtherOrigin(primaryConstructor != null ? primaryConstructor : myClass, constructorDescriptor);
|
||||
functionCodegen.generateMethod(origin, constructorDescriptor, constructorContext,
|
||||
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
generatePrimaryConstructorImpl(callableDescriptor, codegen, delegationFieldsInfo, primaryConstructor);
|
||||
generatePrimaryConstructorImpl(callableDescriptor, codegen, delegationFieldsInfo);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -964,6 +958,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
DefaultParameterValueLoader.DEFAULT, null);
|
||||
|
||||
new DefaultParameterValueSubstitutor(state).generatePrimaryConstructorOverloadsIfNeeded(constructorDescriptor, v, kind, myClass);
|
||||
|
||||
if (isCompanionObject(descriptor)) {
|
||||
context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateSecondaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
|
||||
@@ -995,13 +993,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private void generatePrimaryConstructorImpl(
|
||||
@NotNull ConstructorDescriptor constructorDescriptor,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull DelegationFieldsInfo fieldsInfo,
|
||||
@Nullable KtPrimaryConstructor primaryConstructor
|
||||
@NotNull DelegationFieldsInfo fieldsInfo
|
||||
) {
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
markLineNumberForConstructor(constructorDescriptor, primaryConstructor, codegen);
|
||||
|
||||
generateClosureInitialization(iv);
|
||||
|
||||
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor,
|
||||
@@ -1014,9 +1009,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatedSuperTypeEntry) specifier, fieldsInfo);
|
||||
for (KtDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatorByExpressionSpecifier) specifier, fieldsInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,11 +1053,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
) {
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
KtSecondaryConstructor constructor =
|
||||
(KtSecondaryConstructor) DescriptorToSourceUtils.descriptorToDeclaration(constructorDescriptor);
|
||||
|
||||
markLineNumberForConstructor(constructorDescriptor, constructor, codegen);
|
||||
|
||||
ResolvedCall<ConstructorDescriptor> constructorDelegationCall =
|
||||
getDelegationConstructorCall(bindingContext, constructorDescriptor);
|
||||
ConstructorDescriptor delegateConstructor = constructorDelegationCall == null ? null :
|
||||
@@ -1075,6 +1065,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
generateInitializers(codegen);
|
||||
}
|
||||
|
||||
KtSecondaryConstructor constructor =
|
||||
(KtSecondaryConstructor) DescriptorToSourceUtils.descriptorToDeclaration(constructorDescriptor);
|
||||
assert constructor != null;
|
||||
if (constructor.hasBody()) {
|
||||
codegen.gen(constructor.getBodyExpression(), Type.VOID_TYPE);
|
||||
@@ -1083,29 +1075,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.visitInsn(RETURN);
|
||||
}
|
||||
|
||||
private static void markLineNumberForConstructor(
|
||||
@NotNull ConstructorDescriptor descriptor,
|
||||
@Nullable KtConstructor constructor,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
if (constructor == null) {
|
||||
markLineNumberForDescriptor(descriptor.getContainingDeclaration(), codegen.v);
|
||||
}
|
||||
else if (constructor.hasBody() && !(constructor instanceof KtSecondaryConstructor && !((KtSecondaryConstructor) constructor).hasImplicitDelegationCall())) {
|
||||
KtBlockExpression bodyExpression = constructor.getBodyExpression();
|
||||
List<KtExpression> statements = bodyExpression != null ? bodyExpression.getStatements() : Collections.<KtExpression>emptyList();
|
||||
if (!statements.isEmpty()) {
|
||||
codegen.markStartLineNumber(statements.iterator().next());
|
||||
}
|
||||
else {
|
||||
codegen.markStartLineNumber(bodyExpression != null ? bodyExpression : constructor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
codegen.markStartLineNumber(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInitializers(@NotNull final ExpressionCodegen codegen) {
|
||||
generateInitializers(new Function0<ExpressionCodegen>() {
|
||||
@Override
|
||||
@@ -1155,41 +1124,41 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return StackValue.field(type, classAsmType, name, false, StackValue.none());
|
||||
}
|
||||
}
|
||||
private final Map<KtDelegatedSuperTypeEntry, Field> fields = new HashMap<KtDelegatedSuperTypeEntry, Field>();
|
||||
private final Map<KtDelegatorByExpressionSpecifier, Field> fields = new HashMap<KtDelegatorByExpressionSpecifier, Field>();
|
||||
|
||||
@NotNull
|
||||
public Field getInfo(KtDelegatedSuperTypeEntry specifier) {
|
||||
public Field getInfo(KtDelegatorByExpressionSpecifier specifier) {
|
||||
return fields.get(specifier);
|
||||
}
|
||||
|
||||
private void addField(KtDelegatedSuperTypeEntry specifier, PropertyDescriptor propertyDescriptor) {
|
||||
private void addField(KtDelegatorByExpressionSpecifier specifier, PropertyDescriptor propertyDescriptor) {
|
||||
fields.put(specifier,
|
||||
new Field(typeMapper.mapType(propertyDescriptor), propertyDescriptor.getName().asString(), false));
|
||||
}
|
||||
|
||||
private void addField(KtDelegatedSuperTypeEntry specifier, Type type, String name) {
|
||||
private void addField(KtDelegatorByExpressionSpecifier specifier, Type type, String name) {
|
||||
fields.put(specifier, new Field(type, name, true));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List<KtSuperTypeListEntry> delegationSpecifiers) {
|
||||
private DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List<KtDelegationSpecifier> delegationSpecifiers) {
|
||||
DelegationFieldsInfo result = new DelegationFieldsInfo();
|
||||
int n = 0;
|
||||
for (KtSuperTypeListEntry specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
KtExpression expression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
for (KtDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
KtExpression expression = ((KtDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||
PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext);
|
||||
|
||||
|
||||
if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) {
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, propertyDescriptor);
|
||||
result.addField((KtDelegatorByExpressionSpecifier) specifier, propertyDescriptor);
|
||||
}
|
||||
else {
|
||||
KotlinType expressionType = expression != null ? bindingContext.getType(expression) : null;
|
||||
Type asmType =
|
||||
expressionType != null ? typeMapper.mapType(expressionType) : typeMapper.mapType(getSuperClass(specifier));
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, "$delegate_" + n);
|
||||
result.addField((KtDelegatorByExpressionSpecifier) specifier, asmType, "$delegate_" + n);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
@@ -1198,14 +1167,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ClassDescriptor getSuperClass(@NotNull KtSuperTypeListEntry specifier) {
|
||||
return CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
|
||||
private ClassDescriptor getSuperClass(@NotNull KtDelegationSpecifier specifier) {
|
||||
return CodegenUtil.getSuperClassByDelegationSpecifier(specifier, bindingContext);
|
||||
}
|
||||
|
||||
private void genCallToDelegatorByExpressionSpecifier(
|
||||
InstructionAdapter iv,
|
||||
ExpressionCodegen codegen,
|
||||
KtDelegatedSuperTypeEntry specifier,
|
||||
KtDelegatorByExpressionSpecifier specifier,
|
||||
DelegationFieldsInfo fieldsInfo
|
||||
) {
|
||||
KtExpression expression = specifier.getDelegateExpression();
|
||||
@@ -1237,7 +1206,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
ResolvedCall<? extends CallableDescriptor> call = CallUtilKt.getResolvedCall(expr, bindingContext);
|
||||
if (call != null) {
|
||||
lookupReceiver(call.getDispatchReceiver());
|
||||
lookupReceiver((ReceiverValue) call.getExtensionReceiver());
|
||||
lookupReceiver(call.getExtensionReceiver());
|
||||
}
|
||||
}
|
||||
else if (descriptor instanceof VariableDescriptor) {
|
||||
@@ -1250,8 +1219,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void lookupReceiver(@Nullable ReceiverValue value) {
|
||||
if (value instanceof ImplicitReceiver) {
|
||||
private void lookupReceiver(@NotNull ReceiverValue value) {
|
||||
if (value instanceof ThisReceiver) {
|
||||
if (value instanceof ExtensionReceiver) {
|
||||
ReceiverParameterDescriptor parameter =
|
||||
((ExtensionReceiver) value).getDeclarationDescriptor().getExtensionReceiverParameter();
|
||||
@@ -1259,7 +1228,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
lookupInContext(parameter);
|
||||
}
|
||||
else {
|
||||
lookupInContext(((ImplicitReceiver) value).getDeclarationDescriptor());
|
||||
lookupInContext(((ThisReceiver) value).getDeclarationDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1295,8 +1264,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
initializer.accept(visitor);
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof KtAnonymousInitializer) {
|
||||
KtAnonymousInitializer initializer = (KtAnonymousInitializer) declaration;
|
||||
else if (declaration instanceof KtClassInitializer) {
|
||||
KtClassInitializer initializer = (KtClassInitializer) declaration;
|
||||
initializer.accept(visitor);
|
||||
}
|
||||
else if (declaration instanceof KtSecondaryConstructor) {
|
||||
@@ -1305,9 +1274,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
for (KtDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
KtExpression delegateExpression = ((KtDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||
assert delegateExpression != null;
|
||||
delegateExpression.accept(visitor);
|
||||
}
|
||||
@@ -1333,7 +1302,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private void generateTraitMethods() {
|
||||
if (isInterface(descriptor)) return;
|
||||
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getTraitMethods(descriptor).entrySet()) {
|
||||
FunctionDescriptor traitFun = entry.getKey();
|
||||
//skip java 8 default methods
|
||||
if (!(traitFun instanceof JavaCallableMemberDescriptor)) {
|
||||
@@ -1561,7 +1530,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> args) {
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> args) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1573,8 +1542,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
for (KtEnumEntry enumEntry : enumEntries) {
|
||||
ClassDescriptor descriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
|
||||
int isDeprecated = KotlinBuiltIns.isDeprecated(descriptor) ? ACC_DEPRECATED : 0;
|
||||
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL | isDeprecated,
|
||||
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL,
|
||||
descriptor.getName().asString(), classAsmType.getDescriptor(), null, null);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor, null);
|
||||
}
|
||||
@@ -1622,7 +1590,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.aconst(enumEntry.getName());
|
||||
iv.iconst(ordinal);
|
||||
|
||||
List<KtSuperTypeListEntry> delegationSpecifiers = enumEntry.getSuperTypeListEntries();
|
||||
List<KtDelegationSpecifier> delegationSpecifiers = enumEntry.getDelegationSpecifiers();
|
||||
if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumEntry)) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(delegationSpecifiers.get(0), bindingContext);
|
||||
|
||||
@@ -1640,11 +1608,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateDelegates(DelegationFieldsInfo delegationFieldsInfo) {
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatedSuperTypeEntry) specifier);
|
||||
for (KtDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatorByExpressionSpecifier) specifier);
|
||||
generateDelegateField(field);
|
||||
KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
KtExpression delegateExpression = ((KtDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||
KotlinType delegateExpressionType = delegateExpression != null ? bindingContext.getType(delegateExpression) : null;
|
||||
generateDelegates(getSuperClass(specifier), delegateExpressionType, field);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class InterfaceImplBodyCodegen(
|
||||
|
||||
override fun generateDeclaration() {
|
||||
v.defineClass(
|
||||
myClass, V1_6, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
|
||||
myClass, V1_6, ACC_PUBLIC or ACC_FINAL,
|
||||
typeMapper.mapDefaultImpls(descriptor).internalName,
|
||||
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
|
||||
)
|
||||
@@ -63,7 +63,7 @@ public class InterfaceImplBodyCodegen(
|
||||
if (DescriptorUtils.isLocal(descriptor)) return null
|
||||
val classDescriptorImpl = ClassDescriptorImpl(
|
||||
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
||||
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE)
|
||||
Modality.FINAL, Collections.emptyList(), SourceElement.NO_SOURCE)
|
||||
|
||||
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
|
||||
return classDescriptorImpl
|
||||
@@ -103,8 +103,6 @@ public class InterfaceImplBodyCodegen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generateSyntheticAccessors()
|
||||
}
|
||||
|
||||
private fun generateDelegationToSuperTraitImpl(descriptor: FunctionDescriptor, implementation: FunctionDescriptor) {
|
||||
|
||||
@@ -134,13 +134,12 @@ public class JvmCodegenUtil {
|
||||
@NotNull PropertyDescriptor property,
|
||||
boolean forGetter,
|
||||
boolean isDelegated,
|
||||
@NotNull MethodContext contextBeforeInline
|
||||
@NotNull MethodContext context
|
||||
) {
|
||||
if (JetTypeMapper.isAccessor(property)) return false;
|
||||
|
||||
CodegenContext context = contextBeforeInline.getFirstCrossInlineOrNonInlineContext();
|
||||
// Inline functions can't use direct access because a field may not be visible at the call site
|
||||
if (context.isInlineMethodContext()) {
|
||||
if (context.isInlineFunction()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -165,7 +164,7 @@ public class JvmCodegenUtil {
|
||||
return Visibilities.isPrivate(property.getVisibility()) || accessor.getModality() == FINAL;
|
||||
}
|
||||
|
||||
private static boolean isDebuggerContext(@NotNull CodegenContext context) {
|
||||
private static boolean isDebuggerContext(@NotNull MethodContext context) {
|
||||
KtFile file = DescriptorToSourceUtils.getContainingFile(context.getContextDescriptor());
|
||||
return file != null && CodeFragmentUtilKt.getSuppressDiagnosticsInDebugMode(file);
|
||||
}
|
||||
|
||||
@@ -24,20 +24,40 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtScript;
|
||||
import org.jetbrains.kotlin.resolve.ScriptNameUtil;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.registerClassNameForScript;
|
||||
|
||||
public class KotlinCodegenFacade {
|
||||
|
||||
public static void prepareForCompilation(@NotNull GenerationState state) {
|
||||
for (KtFile file : state.getFiles()) {
|
||||
if (file.isScript()) {
|
||||
KtScript script = file.getScript();
|
||||
assert script != null;
|
||||
|
||||
FqName name = ScriptNameUtil.classNameForScript(script);
|
||||
Type type = AsmUtil.asmTypeByFqNameWithoutInnerClasses(name);
|
||||
registerClassNameForScript(state.getBindingTrace(), script, type, state.getFileClassesProvider());
|
||||
}
|
||||
}
|
||||
|
||||
state.beforeCompile();
|
||||
}
|
||||
|
||||
public static void compileCorrectFiles(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull CompilationErrorHandler errorHandler
|
||||
) {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
|
||||
state.beforeCompile();
|
||||
prepareForCompilation(state);
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
@@ -64,7 +65,8 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlag
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isStaticDeclaration;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
|
||||
@@ -142,18 +144,18 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void markLineNumberForDescriptor(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) {
|
||||
public static void markLineNumberForSyntheticFunction(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) {
|
||||
if (declarationDescriptor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiElement classElement = DescriptorToSourceUtils.getSourceFromDescriptor(declarationDescriptor);
|
||||
if (classElement != null) {
|
||||
markLineNumberForElement(classElement, v);
|
||||
markLineNumberForSyntheticFunction(classElement, v);
|
||||
}
|
||||
}
|
||||
|
||||
public static void markLineNumberForElement(@NotNull PsiElement element, @NotNull InstructionAdapter v) {
|
||||
public static void markLineNumberForSyntheticFunction(@NotNull PsiElement element, @NotNull InstructionAdapter v) {
|
||||
Integer lineNumber = CodegenUtil.getLineNumberForElement(element, false);
|
||||
if (lineNumber != null) {
|
||||
Label label = new Label();
|
||||
@@ -271,16 +273,20 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
String outerClassInternalName = null;
|
||||
if (containing instanceof ClassDescriptor) {
|
||||
outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
|
||||
}
|
||||
} /* disabled cause of KT-7775
|
||||
else if (containing instanceof ScriptDescriptor) {
|
||||
outerClassInternalName = asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containing).getInternalName();
|
||||
}*/
|
||||
|
||||
String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
|
||||
|
||||
String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
|
||||
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
|
||||
}
|
||||
|
||||
protected void writeOuterClassAndEnclosingMethod() {
|
||||
CodegenContext context = this.context.getParentContext();
|
||||
|
||||
while (context instanceof InlineLambdaContext) {
|
||||
while (context instanceof MethodContext && ((MethodContext) context).isInliningLambda()) {
|
||||
// If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
|
||||
//noinspection ConstantConditions
|
||||
context = context.getParentContext().getParentContext();
|
||||
@@ -314,7 +320,10 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile());
|
||||
}
|
||||
}
|
||||
|
||||
/*disabled cause of KT-7775
|
||||
else if (outermost instanceof ScriptContext) {
|
||||
return asmTypeForScriptDescriptor(bindingContext, ((ScriptContext) outermost).getScriptDescriptor());
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -364,8 +373,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
initializeProperty(codegen.invoke(), (KtProperty) declaration);
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof KtAnonymousInitializer) {
|
||||
KtExpression body = ((KtAnonymousInitializer) declaration).getBody();
|
||||
else if (declaration instanceof KtClassInitializer) {
|
||||
KtExpression body = ((KtClassInitializer) declaration).getBody();
|
||||
if (body != null) {
|
||||
codegen.invoke().gen(body, Type.VOID_TYPE);
|
||||
}
|
||||
@@ -483,13 +492,13 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
if (delegatedProperties.isEmpty()) return;
|
||||
|
||||
v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
|
||||
"[" + K_PROPERTY_TYPE, null, null);
|
||||
"[" + PROPERTY_METADATA_TYPE, null, null);
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
|
||||
|
||||
InstructionAdapter iv = createOrGetClInitCodegen().v;
|
||||
iv.iconst(delegatedProperties.size());
|
||||
iv.newarray(K_PROPERTY_TYPE);
|
||||
iv.newarray(PROPERTY_METADATA_TYPE);
|
||||
|
||||
for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
|
||||
PropertyDescriptor property =
|
||||
@@ -524,16 +533,16 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
//noinspection ConstantConditions
|
||||
value = createOrGetClInitCodegen().generatePropertyReference(
|
||||
delegatedProperties.get(i).getDelegate(), property, property,
|
||||
dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : null
|
||||
dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : ReceiverValue.NO_RECEIVER
|
||||
);
|
||||
}
|
||||
|
||||
value.put(K_PROPERTY_TYPE, iv);
|
||||
value.put(PROPERTY_METADATA_TYPE, iv);
|
||||
|
||||
iv.astore(K_PROPERTY_TYPE);
|
||||
iv.astore(PROPERTY_METADATA_TYPE);
|
||||
}
|
||||
|
||||
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE);
|
||||
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
@@ -600,10 +609,9 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, accessor) {
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
markLineNumberForElement(element, codegen.v);
|
||||
|
||||
generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), codegen.v);
|
||||
markLineNumberForSyntheticFunction(element, codegen.v);
|
||||
|
||||
generateMethodCallTo(original, accessor, codegen.v);
|
||||
codegen.v.areturn(signature.getReturnType());
|
||||
}
|
||||
}
|
||||
@@ -631,7 +639,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
markLineNumberForElement(element, iv);
|
||||
markLineNumberForSyntheticFunction(element, iv);
|
||||
|
||||
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
|
||||
for (int i = 0, reg = 0; i < argTypes.length; i++) {
|
||||
@@ -642,7 +650,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
}
|
||||
|
||||
if (callableDescriptor instanceof PropertyGetterDescriptor) {
|
||||
property.put(signature.getReturnType(), iv);
|
||||
property.put(property.type, iv);
|
||||
}
|
||||
else {
|
||||
property.store(StackValue.onStack(property.type), iv, true);
|
||||
@@ -672,7 +680,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
private StackValue generateMethodCallTo(
|
||||
private void generateMethodCallTo(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@Nullable FunctionDescriptor accessorDescriptor,
|
||||
@NotNull InstructionAdapter iv
|
||||
@@ -683,7 +691,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
|
||||
);
|
||||
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isInterface(functionDescriptor.getContainingDeclaration());
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor);
|
||||
int reg = hasDispatchReceiver ? 1 : 0;
|
||||
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||
if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
|
||||
@@ -708,7 +716,5 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
}
|
||||
|
||||
callableMethod.genInvokeInstruction(iv);
|
||||
|
||||
return StackValue.onStack(callableMethod.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClassPart
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
@@ -51,7 +50,6 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
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 java.util.*
|
||||
|
||||
public class MultifileClassCodegen(
|
||||
@@ -88,18 +86,12 @@ public class MultifileClassCodegen(
|
||||
|
||||
val singleSourceFile = if (previouslyCompiledCallables.isNotEmpty()) null else filesWithCallables.singleOrNull()
|
||||
|
||||
classBuilder.defineClass(singleSourceFile, Opcodes.V1_6,
|
||||
if (state.generateOpenMultifileClasses) OPEN_FACADE_CLASS_ATTRIBUTES else FACADE_CLASS_ATTRIBUTES,
|
||||
classBuilder.defineClass(singleSourceFile, Opcodes.V1_6, FACADE_CLASS_ATTRIBUTES,
|
||||
facadeClassType.internalName,
|
||||
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY)
|
||||
if (singleSourceFile != null) {
|
||||
classBuilder.visitSource(singleSourceFile.name, null)
|
||||
}
|
||||
|
||||
if (state.generateOpenMultifileClasses) {
|
||||
generateMultifileFacadeClassConstructor(classBuilder, originFile)
|
||||
}
|
||||
|
||||
classBuilder
|
||||
}
|
||||
|
||||
@@ -156,16 +148,6 @@ public class MultifileClassCodegen(
|
||||
MemberCodegen.genClassOrObject(packagePartContext, classOrObject, state, null)
|
||||
}
|
||||
|
||||
|
||||
private fun generateMultifileFacadeClassConstructor(classBuilder: ClassBuilder, originFile: KtFile?) {
|
||||
val mv = classBuilder.newMethod(JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_PUBLIC, "<init>", "()V", null, null)
|
||||
val v = InstructionAdapter(mv)
|
||||
v.load(0, facadeClassType)
|
||||
v.invokespecial("java/lang/Object", "<init>", "()V", false)
|
||||
v.visitInsn(Opcodes.RETURN)
|
||||
FunctionCodegen.endVisit(v, "multifile class constructor", originFile)
|
||||
}
|
||||
|
||||
private fun generatePart(
|
||||
file: KtFile,
|
||||
generateCallableMemberTasks: MutableMap<CallableMemberDescriptor, () -> Unit>,
|
||||
@@ -297,8 +279,7 @@ public class MultifileClassCodegen(
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER
|
||||
private val OPEN_FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_SUPER
|
||||
private val FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL
|
||||
|
||||
private fun getOnlyPackageFragment(packageFqName: FqName, files: Collection<KtFile>, bindingContext: BindingContext): PackageFragmentDescriptor? {
|
||||
val fragments = SmartList<PackageFragmentDescriptor>()
|
||||
|
||||
@@ -46,7 +46,7 @@ public class MultifileClassPartCodegen(
|
||||
|
||||
override fun generateDeclaration() {
|
||||
v.defineClass(element, Opcodes.V1_6,
|
||||
Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_SUPER,
|
||||
Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC,
|
||||
filePartType.internalName,
|
||||
null,
|
||||
"java/lang/Object",
|
||||
|
||||
@@ -143,18 +143,12 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
|
||||
this.typeParameters = new ArrayList<TypeParameterDescriptor>(typeParameters);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public void createTypeConstructor() {
|
||||
assert typeConstructor == null : typeConstructor;
|
||||
this.typeConstructor = TypeConstructorImpl.createForClass(
|
||||
this,
|
||||
Annotations.Companion.getEMPTY(),
|
||||
ModalityKt.isFinalClass(this),
|
||||
!getModality().isOverridable(),
|
||||
getName().asString(),
|
||||
typeParameters,
|
||||
supertypes
|
||||
|
||||
@@ -63,7 +63,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
@Override
|
||||
protected void generateDeclaration() {
|
||||
v.defineClass(element, V1_6,
|
||||
ACC_PUBLIC | ACC_FINAL | ACC_SUPER,
|
||||
ACC_PUBLIC | ACC_FINAL,
|
||||
packagePartType.getInternalName(),
|
||||
null,
|
||||
"java/lang/Object",
|
||||
|
||||
@@ -58,7 +58,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.K_PROPERTY_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.PROPERTY_METADATA_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@@ -118,7 +118,16 @@ public class PropertyCodegen {
|
||||
if (CodegenContextUtil.isImplClassOwner(context)) {
|
||||
assert declaration != null : "Declaration is null for different context: " + context;
|
||||
|
||||
genBackingFieldAndAnnotations(declaration, descriptor, false);
|
||||
boolean hasBackingField = hasBackingField(declaration, descriptor);
|
||||
|
||||
AnnotationSplitter annotationSplitter = AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS,
|
||||
descriptor.getAnnotations(), AnnotationSplitter.getTargetSet(false, descriptor.isVar(), hasBackingField));
|
||||
|
||||
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
|
||||
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
|
||||
|
||||
generateBackingField(declaration, descriptor, fieldAnnotations);
|
||||
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
|
||||
}
|
||||
|
||||
if (isAccessorNeeded(declaration, descriptor, getter)) {
|
||||
@@ -127,21 +136,8 @@ public class PropertyCodegen {
|
||||
if (isAccessorNeeded(declaration, descriptor, setter)) {
|
||||
generateSetter(declaration, descriptor, setter);
|
||||
}
|
||||
}
|
||||
|
||||
private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) {
|
||||
boolean hasBackingField = hasBackingField(declaration, descriptor);
|
||||
|
||||
AnnotationSplitter annotationSplitter =
|
||||
AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS,
|
||||
descriptor.getAnnotations(),
|
||||
AnnotationSplitter.getTargetSet(isParameter, descriptor.isVar(), hasBackingField));
|
||||
|
||||
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
|
||||
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
|
||||
|
||||
generateBackingField(declaration, descriptor, fieldAnnotations);
|
||||
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
|
||||
context.recordSyntheticAccessorIfNeeded(descriptor, bindingContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,20 +174,21 @@ public class PropertyCodegen {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean areAccessorsNeededForPrimaryConstructorProperty(
|
||||
@NotNull PropertyDescriptor descriptor
|
||||
) {
|
||||
if (hasJvmFieldAnnotation(descriptor)) return false;
|
||||
public void generatePrimaryConstructorProperty(KtParameter p, PropertyDescriptor descriptor) {
|
||||
AnnotationSplitter annotationSplitter = AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS,
|
||||
descriptor.getAnnotations(), AnnotationSplitter.getTargetSet(true, descriptor.isVar(), hasBackingField(p, descriptor)));
|
||||
|
||||
return !Visibilities.isPrivate(descriptor.getVisibility());
|
||||
}
|
||||
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
|
||||
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
|
||||
|
||||
public void generatePrimaryConstructorProperty(@NotNull KtParameter p, @NotNull PropertyDescriptor descriptor) {
|
||||
genBackingFieldAndAnnotations(p, descriptor, true);
|
||||
generateBackingField(p, descriptor, fieldAnnotations);
|
||||
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
|
||||
|
||||
if (areAccessorsNeededForPrimaryConstructorProperty(descriptor)) {
|
||||
if (!Visibilities.isPrivate(descriptor.getVisibility())) {
|
||||
generateGetter(p, descriptor, null);
|
||||
generateSetter(p, descriptor, null);
|
||||
if (descriptor.isVar()) {
|
||||
generateSetter(p, descriptor, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,7 +355,7 @@ public class PropertyCodegen {
|
||||
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name));
|
||||
|
||||
FieldVisitor fv = builder.newField(JvmDeclarationOriginKt.OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||
typeMapper.mapFieldSignature(jetType, propertyDescriptor), defaultValue);
|
||||
typeMapper.mapFieldSignature(jetType), defaultValue);
|
||||
|
||||
Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(fieldAnnotated, type, AnnotationUseSiteTarget.FIELD);
|
||||
@@ -524,15 +521,13 @@ public class PropertyCodegen {
|
||||
|
||||
codegen.tempVariables.put(
|
||||
resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(),
|
||||
new StackValue(K_PROPERTY_TYPE) {
|
||||
new StackValue(PROPERTY_METADATA_TYPE) {
|
||||
@Override
|
||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
Field array = StackValue.field(
|
||||
Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none()
|
||||
);
|
||||
StackValue.arrayElement(
|
||||
K_PROPERTY_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)
|
||||
).put(type, v);
|
||||
Field array = StackValue
|
||||
.field(Type.getType("[" + PROPERTY_METADATA_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true,
|
||||
StackValue.none());
|
||||
StackValue.arrayElement(PROPERTY_METADATA_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)).put(type, v);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ScriptReceiver
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -47,11 +48,19 @@ public class PropertyReferenceCodegen(
|
||||
classBuilder: ClassBuilder,
|
||||
private val classDescriptor: ClassDescriptor,
|
||||
private val target: VariableDescriptor,
|
||||
dispatchReceiver: ReceiverValue?
|
||||
dispatchReceiver: ReceiverValue
|
||||
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
||||
private val asmType = typeMapper.mapClass(classDescriptor)
|
||||
|
||||
private val dispatchReceiverType = dispatchReceiver?.type
|
||||
private val dispatchReceiverType =
|
||||
when {
|
||||
dispatchReceiver is ScriptReceiver -> {
|
||||
// TODO: fix receiver for scripts, see ScriptReceiver#getType
|
||||
dispatchReceiver.declarationDescriptor.classDescriptor.defaultType
|
||||
}
|
||||
dispatchReceiver.exists() -> dispatchReceiver.type
|
||||
else -> null
|
||||
}
|
||||
|
||||
private val extensionReceiverType = target.extensionReceiverParameter?.type
|
||||
|
||||
@@ -127,7 +136,7 @@ public class PropertyReferenceCodegen(
|
||||
StackValue.singleton(containingObject, typeMapper).put(typeMapper.mapClass(containingObject), this)
|
||||
}
|
||||
|
||||
for ((index, type) in listOfNotNull(dispatchReceiverType, extensionReceiverType).withIndex()) {
|
||||
for ((index, type) in listOf(dispatchReceiverType, extensionReceiverType).filterNotNull().withIndex()) {
|
||||
StackValue.local(index + 1, OBJECT_TYPE).put(typeMapper.mapType(type), this)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,21 +38,10 @@ public class RangeCodegenUtil {
|
||||
private static final ImmutableMap<FqName, PrimitiveType> RANGE_TO_ELEMENT_TYPE;
|
||||
private static final ImmutableMap<FqName, PrimitiveType> PROGRESSION_TO_ELEMENT_TYPE;
|
||||
|
||||
private static PrimitiveType[] supportedRangeTypes() {
|
||||
return new PrimitiveType[] {
|
||||
PrimitiveType.CHAR,
|
||||
PrimitiveType.INT,
|
||||
PrimitiveType.LONG,
|
||||
// deprecated:
|
||||
PrimitiveType.BYTE,
|
||||
PrimitiveType.SHORT,
|
||||
};
|
||||
}
|
||||
|
||||
static {
|
||||
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
|
||||
ImmutableMap.Builder<FqName, PrimitiveType> progressionBuilder = ImmutableMap.builder();
|
||||
for (PrimitiveType primitiveType : supportedRangeTypes()) {
|
||||
for (PrimitiveType primitiveType : PrimitiveType.values()) {
|
||||
FqName rangeClassFqName = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Range"));
|
||||
FqName progressionClassFqName = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Progression"));
|
||||
rangeBuilder.put(rangeClassFqName, primitiveType);
|
||||
|
||||
@@ -70,7 +70,6 @@ public class SamWrapperCodegen {
|
||||
samType.getJavaClassDescriptor().getContainingDeclaration(),
|
||||
fqName.shortName(),
|
||||
Modality.FINAL,
|
||||
ClassKind.CLASS,
|
||||
Collections.singleton(samType.getType()),
|
||||
SourceElement.NO_SOURCE
|
||||
);
|
||||
@@ -86,7 +85,7 @@ public class SamWrapperCodegen {
|
||||
ClassBuilder cv = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(erasedInterfaceFunction), asmType, file);
|
||||
cv.defineClass(file,
|
||||
V1_6,
|
||||
ACC_FINAL | ACC_SUPER,
|
||||
ACC_FINAL,
|
||||
asmType.getInternalName(),
|
||||
null,
|
||||
OBJECT_TYPE.getInternalName(),
|
||||
|
||||
@@ -23,11 +23,12 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.context.ScriptContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
@@ -37,6 +38,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForScriptDescriptor;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -52,16 +55,18 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, declaration);
|
||||
assert scriptDescriptor != null;
|
||||
|
||||
Type classType = state.getTypeMapper().mapType(scriptDescriptor);
|
||||
ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
|
||||
assert classDescriptorForScript != null;
|
||||
|
||||
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, scriptDescriptor),
|
||||
Type classType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
|
||||
|
||||
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, classDescriptorForScript),
|
||||
classType, declaration.getContainingFile());
|
||||
List<ScriptDescriptor> earlierScripts = state.getReplSpecific().getEarlierScriptsForReplInterpreter();
|
||||
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
|
||||
ScriptContext scriptContext = parentContext.intoScript(
|
||||
scriptDescriptor,
|
||||
earlierScripts == null ? Collections.<ScriptDescriptor>emptyList() : earlierScripts,
|
||||
scriptDescriptor,
|
||||
state.getTypeMapper()
|
||||
classDescriptorForScript
|
||||
);
|
||||
return new ScriptCodegen(declaration, state, scriptContext, builder);
|
||||
}
|
||||
@@ -88,7 +93,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
|
||||
v.defineClass(scriptDeclaration,
|
||||
V1_6,
|
||||
ACC_PUBLIC | ACC_SUPER,
|
||||
ACC_PUBLIC,
|
||||
classType.getInternalName(),
|
||||
null,
|
||||
"java/lang/Object",
|
||||
@@ -99,8 +104,8 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
protected void generateBody() {
|
||||
genMembers();
|
||||
genFieldsForParameters(scriptDescriptor, v);
|
||||
genConstructor(scriptDescriptor, v,
|
||||
context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor()));
|
||||
genConstructor(scriptDescriptor, context.getContextDescriptor(), v,
|
||||
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,25 +115,22 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
|
||||
private void genConstructor(
|
||||
@NotNull ScriptDescriptor scriptDescriptor,
|
||||
@NotNull ClassDescriptor classDescriptorForScript,
|
||||
@NotNull ClassBuilder classBuilder,
|
||||
@NotNull MethodContext methodContext
|
||||
) {
|
||||
//noinspection ConstantConditions
|
||||
Type blockType = typeMapper.mapType(scriptDescriptor.getScriptCodeDescriptor().getReturnType());
|
||||
|
||||
PropertyDescriptor scriptResultProperty = scriptDescriptor.getScriptResultProperty();
|
||||
classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(scriptResultProperty),
|
||||
ACC_PUBLIC | ACC_FINAL, scriptResultProperty.getName().asString(),
|
||||
blockType.getDescriptor(), null, null);
|
||||
|
||||
JvmMethodSignature jvmSignature = typeMapper.mapScriptSignature(scriptDescriptor, context.getEarlierScripts());
|
||||
|
||||
if (state.getReplSpecific().getShouldGenerateScriptResultValue()) {
|
||||
FieldInfo resultFieldInfo = context.getResultFieldInfo();
|
||||
classBuilder.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN,
|
||||
ACC_PUBLIC | ACC_FINAL,
|
||||
resultFieldInfo.getFieldName(),
|
||||
resultFieldInfo.getFieldType().getDescriptor(),
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
MethodVisitor mv = classBuilder.newMethod(
|
||||
JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getUnsubstitutedPrimaryConstructor()),
|
||||
JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getClassDescriptor().getUnsubstitutedPrimaryConstructor()),
|
||||
ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(),
|
||||
null, null);
|
||||
|
||||
@@ -137,7 +139,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
Type classType = typeMapper.mapType(scriptDescriptor);
|
||||
Type classType = typeMapper.mapType(classDescriptorForScript);
|
||||
|
||||
iv.load(0, classType);
|
||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
|
||||
@@ -154,23 +156,22 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
|
||||
int add = 0;
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters();
|
||||
for (int i = 0; i < valueParameters.size(); i++) {
|
||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||
for (int i = 0; i < scriptDescriptor.getScriptCodeDescriptor().getValueParameters().size(); i++) {
|
||||
ValueParameterDescriptor parameter = scriptDescriptor.getScriptCodeDescriptor().getValueParameters().get(i);
|
||||
frameMap.enter(parameter, argTypes[i + add]);
|
||||
}
|
||||
|
||||
int offset = 1;
|
||||
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassType = typeMapper.mapClass(earlierScript);
|
||||
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript);
|
||||
iv.load(0, classType);
|
||||
iv.load(offset, earlierClassType);
|
||||
offset += earlierClassType.getSize();
|
||||
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
for (ValueParameterDescriptor parameter : scriptDescriptor.getScriptCodeDescriptor().getValueParameters()) {
|
||||
Type parameterType = typeMapper.mapType(parameter.getType());
|
||||
iv.load(0, classType);
|
||||
iv.load(offset, parameterType);
|
||||
@@ -187,6 +188,16 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
}
|
||||
});
|
||||
|
||||
StackValue stackValue = codegen.gen(scriptDeclaration.getBlockExpression());
|
||||
if (stackValue.type != Type.VOID_TYPE) {
|
||||
StackValue.Field resultValue = StackValue
|
||||
.field(blockType, classType, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, false, StackValue.LOCAL_0);
|
||||
resultValue.store(stackValue, iv);
|
||||
}
|
||||
else {
|
||||
stackValue.put(blockType, iv);
|
||||
}
|
||||
|
||||
iv.areturn(Type.VOID_TYPE);
|
||||
}
|
||||
|
||||
@@ -196,12 +207,12 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
|
||||
private void genFieldsForParameters(@NotNull ScriptDescriptor script, @NotNull ClassBuilder classBuilder) {
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassName = typeMapper.mapType(earlierScript);
|
||||
int access = ACC_PUBLIC | ACC_FINAL;
|
||||
Type earlierClassName = asmTypeForScriptDescriptor(bindingContext, earlierScript);
|
||||
int access = ACC_PRIVATE | ACC_FINAL;
|
||||
classBuilder.newField(NO_ORIGIN, access, context.getScriptFieldName(earlierScript), earlierClassName.getDescriptor(), null, null);
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
|
||||
for (ValueParameterDescriptor parameter : script.getScriptCodeDescriptor().getValueParameters()) {
|
||||
Type parameterType = typeMapper.mapType(parameter);
|
||||
int access = ACC_PUBLIC | ACC_FINAL;
|
||||
classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(parameter), access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null);
|
||||
|
||||
@@ -235,8 +235,8 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Field field(@NotNull FieldInfo info, @NotNull StackValue receiver) {
|
||||
return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), info.isStatic(), receiver);
|
||||
private static Field field(@NotNull FieldInfo info) {
|
||||
return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), true, none());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -501,20 +501,20 @@ public abstract class StackValue {
|
||||
callDispatchReceiver = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverForBackend();
|
||||
}
|
||||
|
||||
ReceiverValue callExtensionReceiver = (ReceiverValue) resolvedCall.getExtensionReceiver();
|
||||
if (callDispatchReceiver != null || callExtensionReceiver != null
|
||||
ReceiverValue callExtensionReceiver = resolvedCall.getExtensionReceiver();
|
||||
if (callDispatchReceiver.exists() || callExtensionReceiver.exists()
|
||||
|| isLocalFunCall(callableMethod) || isCallToMemberObjectImportedByName(resolvedCall)) {
|
||||
ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter();
|
||||
ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter();
|
||||
|
||||
if (descriptor.getOriginal() instanceof SamAdapterExtensionFunctionDescriptor) {
|
||||
callDispatchReceiver = callExtensionReceiver;
|
||||
callExtensionReceiver = null;
|
||||
callExtensionReceiver = ReceiverValue.NO_RECEIVER;
|
||||
dispatchReceiverParameter = extensionReceiverParameter;
|
||||
extensionReceiverParameter = null;
|
||||
}
|
||||
|
||||
boolean hasExtensionReceiver = callExtensionReceiver != null;
|
||||
boolean hasExtensionReceiver = callExtensionReceiver.exists();
|
||||
StackValue dispatchReceiver = platformStaticCallIfPresent(
|
||||
genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, callDispatchReceiver, false),
|
||||
descriptor
|
||||
@@ -532,11 +532,11 @@ public abstract class StackValue {
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull ResolvedCall resolvedCall,
|
||||
@Nullable Callable callableMethod,
|
||||
@Nullable ReceiverValue receiverValue,
|
||||
ReceiverValue receiverValue,
|
||||
boolean isExtension
|
||||
) {
|
||||
if (receiver == none()) {
|
||||
if (receiverValue != null) {
|
||||
if (receiverValue.exists()) {
|
||||
return codegen.generateReceiverValue(receiverValue, false);
|
||||
}
|
||||
else if (isLocalFunCall(callableMethod) && !isExtension) {
|
||||
@@ -548,7 +548,7 @@ public abstract class StackValue {
|
||||
return singleton(((ImportedFromObjectCallableDescriptor) resolvedCall.getResultingDescriptor()).getContainingObject(), codegen.typeMapper);
|
||||
}
|
||||
}
|
||||
else if (receiverValue != null) {
|
||||
else if (receiverValue.exists()) {
|
||||
return receiver;
|
||||
}
|
||||
return none();
|
||||
@@ -593,15 +593,15 @@ public abstract class StackValue {
|
||||
|
||||
@NotNull
|
||||
public static Field singleton(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) {
|
||||
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper), none());
|
||||
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper));
|
||||
}
|
||||
|
||||
public static Field singletonViaInstance(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) {
|
||||
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, false), none());
|
||||
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, false));
|
||||
}
|
||||
|
||||
public static Field oldSingleton(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) {
|
||||
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper, true), none());
|
||||
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper, true));
|
||||
}
|
||||
|
||||
public static StackValue operation(Type type, Function1<InstructionAdapter, Unit> lambda) {
|
||||
@@ -832,9 +832,9 @@ public abstract class StackValue {
|
||||
v.store(firstParamIndex, type);
|
||||
}
|
||||
|
||||
ReceiverValue receiverParameter = (ReceiverValue) resolvedGetCall.getExtensionReceiver();
|
||||
ReceiverValue receiverParameter = resolvedGetCall.getExtensionReceiver();
|
||||
int receiverIndex = -1;
|
||||
if (receiverParameter != null) {
|
||||
if (receiverParameter.exists()) {
|
||||
Type type = codegen.typeMapper.mapType(receiverParameter.getType());
|
||||
receiverIndex = frame.enterTemp(type);
|
||||
v.store(receiverIndex, type);
|
||||
@@ -842,7 +842,7 @@ public abstract class StackValue {
|
||||
|
||||
ReceiverValue dispatchReceiver = resolvedGetCall.getDispatchReceiver();
|
||||
int thisIndex = -1;
|
||||
if (dispatchReceiver != null) {
|
||||
if (dispatchReceiver.exists()) {
|
||||
thisIndex = frame.enterTemp(OBJECT_TYPE);
|
||||
v.store(thisIndex, OBJECT_TYPE);
|
||||
}
|
||||
@@ -863,14 +863,14 @@ public abstract class StackValue {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
if (resolvedSetCall.getDispatchReceiver() != null) {
|
||||
if (resolvedSetCall.getExtensionReceiver() != null) {
|
||||
if (resolvedSetCall.getDispatchReceiver().exists()) {
|
||||
if (resolvedSetCall.getExtensionReceiver().exists()) {
|
||||
codegen.generateReceiverValue(resolvedSetCall.getDispatchReceiver(), false).put(OBJECT_TYPE, v);
|
||||
}
|
||||
v.load(realReceiverIndex, realReceiverType);
|
||||
}
|
||||
else {
|
||||
if (resolvedSetCall.getExtensionReceiver() != null) {
|
||||
if (resolvedSetCall.getExtensionReceiver().exists()) {
|
||||
v.load(realReceiverIndex, realReceiverType);
|
||||
}
|
||||
else {
|
||||
@@ -970,8 +970,8 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.getDispatchReceiver() != null) {
|
||||
if (call.getExtensionReceiver() != null) {
|
||||
if (call.getDispatchReceiver().exists()) {
|
||||
if (call.getExtensionReceiver().exists()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1084,7 +1084,9 @@ public abstract class StackValue {
|
||||
|
||||
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
|
||||
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||
genNotNullAssertionForLateInitIfNeeded(v);
|
||||
if (!genNotNullAssertionForField(v, state, descriptor)) {
|
||||
genNotNullAssertionForLateInitIfNeeded(v);
|
||||
}
|
||||
coerceTo(type, v);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -98,7 +98,6 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
correctContainerForLambda(callableDescriptor, element),
|
||||
Name.special("<closure-" + simpleName + ">"),
|
||||
Modality.FINAL,
|
||||
ClassKind.CLASS,
|
||||
supertypes,
|
||||
KotlinSourceElementKt.toSourceElement(element)
|
||||
);
|
||||
@@ -129,7 +128,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
if (element instanceof KtObjectDeclaration &&
|
||||
element.getParent() instanceof KtObjectLiteralExpression &&
|
||||
child instanceof KtSuperTypeList) {
|
||||
child instanceof KtDelegationSpecifierList) {
|
||||
// If we're passing an anonymous object's super call, it means "container" is ConstructorDescriptor of that object.
|
||||
// To reach outer context, we should call getContainingDeclaration() twice
|
||||
// TODO: this is probably not entirely correct, mostly because DECLARATION_TO_DESCRIPTOR can return null
|
||||
@@ -159,26 +158,30 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitScript(@NotNull KtScript script) {
|
||||
classStack.push(bindingContext.get(SCRIPT, script));
|
||||
nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(script.getFqName()));
|
||||
script.acceptChildren(this);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitKtFile(@NotNull KtFile file) {
|
||||
nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(file.getPackageFqName()));
|
||||
if (file.isScript()) {
|
||||
// TODO: replace with visitScript override
|
||||
//noinspection ConstantConditions
|
||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, bindingContext.get(SCRIPT, file.getScript()));
|
||||
classStack.push(classDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
nameStack.push(asmTypeForScriptPsi(bindingContext, file.getScript()).getInternalName());
|
||||
}
|
||||
else {
|
||||
nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(file.getPackageFqName()));
|
||||
}
|
||||
file.acceptChildren(this);
|
||||
nameStack.pop();
|
||||
if (file.isScript()) {
|
||||
classStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnumEntry(@NotNull KtEnumEntry enumEntry) {
|
||||
if (enumEntry.getDeclarations().isEmpty()) {
|
||||
for (KtSuperTypeListEntry specifier : enumEntry.getSuperTypeListEntries()) {
|
||||
for (KtDelegationSpecifier specifier : enumEntry.getDelegationSpecifiers()) {
|
||||
specifier.accept(this);
|
||||
}
|
||||
return;
|
||||
@@ -248,7 +251,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
String name = inventAnonymousClassName();
|
||||
recordClosure(classDescriptor, name);
|
||||
|
||||
KtSuperTypeList delegationSpecifierList = object.getSuperTypeList();
|
||||
KtDelegationSpecifierList delegationSpecifierList = object.getDelegationSpecifierList();
|
||||
if (delegationSpecifierList != null) {
|
||||
delegationSpecifierList.accept(this);
|
||||
}
|
||||
@@ -264,8 +267,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambdaExpression(@NotNull KtLambdaExpression lambdaExpression) {
|
||||
KtFunctionLiteral functionLiteral = lambdaExpression.getFunctionLiteral();
|
||||
public void visitFunctionLiteralExpression(@NotNull KtFunctionLiteralExpression expression) {
|
||||
KtFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||
FunctionDescriptor functionDescriptor =
|
||||
(FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, functionLiteral);
|
||||
// working around a problem with shallow analysis
|
||||
@@ -278,7 +281,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(name);
|
||||
super.visitLambdaExpression(lambdaExpression);
|
||||
super.visitFunctionLiteralExpression(expression);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
@@ -383,7 +386,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
String peek = peekFromStack(nameStack);
|
||||
String name = safeIdentifier(descriptor.getName()).asString();
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
if (containingDeclaration instanceof ClassDescriptor || containingDeclaration instanceof ScriptDescriptor) {
|
||||
return peek + '$' + name;
|
||||
}
|
||||
else if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||
@@ -432,8 +435,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSuperTypeCallEntry(@NotNull KtSuperTypeCallEntry call) {
|
||||
super.visitSuperTypeCallEntry(call);
|
||||
public void visitDelegationToSuperCallSpecifier(@NotNull KtDelegatorToSuperCall call) {
|
||||
super.visitDelegationToSuperCallSpecifier(call);
|
||||
checkSamCall(call);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,13 +24,17 @@ import org.jetbrains.kotlin.codegen.SamType;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
|
||||
import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice;
|
||||
import org.jetbrains.kotlin.util.slicedMap.Slices;
|
||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
||||
@@ -39,12 +43,15 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
|
||||
public class CodegenBinding {
|
||||
public static final WritableSlice<ClassDescriptor, MutableClosure> CLOSURE = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<CallableDescriptor, ClassDescriptor> CLASS_FOR_CALLABLE = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ScriptDescriptor, ClassDescriptor> CLASS_FOR_SCRIPT = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ClassDescriptor, Type> ASM_TYPE = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ClassDescriptor, Boolean> ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice();
|
||||
@@ -82,6 +89,22 @@ public class CodegenBinding {
|
||||
return Boolean.TRUE.equals(bindingContext.get(ENUM_ENTRY_CLASS_NEED_SUBCLASS, classDescriptor));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type asmTypeForScriptDescriptor(BindingContext bindingContext, @NotNull ScriptDescriptor scriptDescriptor) {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
return getAsmType(bindingContext, classDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type asmTypeForScriptPsi(BindingContext bindingContext, @NotNull KtScript script) {
|
||||
ScriptDescriptor scriptDescriptor = bindingContext.get(SCRIPT, script);
|
||||
if (scriptDescriptor == null) {
|
||||
throw new IllegalStateException("Script descriptor not found by PSI " + script);
|
||||
}
|
||||
return asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor anonymousClassForCallable(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@@ -140,7 +163,7 @@ public class CodegenBinding {
|
||||
@NotNull Type asmType,
|
||||
@NotNull JvmFileClassesProvider fileClassesManager
|
||||
) {
|
||||
KtElement element = (KtElement) DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor);
|
||||
KtElement element = (KtElement) descriptorToDeclaration(classDescriptor);
|
||||
assert element != null : "No source element for " + classDescriptor;
|
||||
|
||||
MutableClosure closure = new MutableClosure(classDescriptor, enclosing);
|
||||
@@ -173,6 +196,29 @@ public class CodegenBinding {
|
||||
innerClasses.add(inner);
|
||||
}
|
||||
|
||||
public static void registerClassNameForScript(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull KtScript script,
|
||||
@NotNull Type asmType,
|
||||
@NotNull JvmFileClassesProvider fileClassesManager
|
||||
) {
|
||||
ScriptDescriptor descriptor = trace.getBindingContext().get(SCRIPT, script);
|
||||
if (descriptor == null) {
|
||||
throw new IllegalStateException("Script descriptor is not found for PSI: " + PsiUtilsKt.getElementTextWithContext(script));
|
||||
}
|
||||
|
||||
String simpleName = asmType.getInternalName().substring(asmType.getInternalName().lastIndexOf('/') + 1);
|
||||
ClassDescriptorImpl classDescriptor =
|
||||
new ClassDescriptorImpl(descriptor, Name.special("<script-" + simpleName + ">"), Modality.FINAL,
|
||||
Collections.singleton(DescriptorUtilsKt.getBuiltIns(descriptor).getAnyType()),
|
||||
KotlinSourceElementKt.toSourceElement(script));
|
||||
classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.<ConstructorDescriptor>emptySet(), null);
|
||||
|
||||
recordClosure(trace, classDescriptor, null, asmType, fileClassesManager);
|
||||
|
||||
trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<KtFile> allFilesInPackages(BindingContext bindingContext, Collection<KtFile> files) {
|
||||
// todo: we use Set and add given files but ignoring other scripts because something non-clear kept in binding
|
||||
|
||||
@@ -20,19 +20,20 @@ import org.jetbrains.kotlin.backend.common.bridges.DescriptorBasedFunctionHandle
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findAllReachableDeclarations
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findConcreteSuperDeclaration
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescriptor
|
||||
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinWithDifferentJvmDescriptor
|
||||
import org.jetbrains.kotlin.load.java.hasRealKotlinSuperClassWithOverrideOf
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
import java.util.*
|
||||
|
||||
@@ -51,7 +52,7 @@ object BuiltinSpecialBridgesUtil {
|
||||
|
||||
val functionHandle = DescriptorBasedFunctionHandle(function)
|
||||
val fake = !functionHandle.isDeclaration
|
||||
val overriddenBuiltin = function.getOverriddenBuiltinReflectingJvmDescriptor()!!
|
||||
val overriddenBuiltin = function.getOverriddenBuiltinWithDifferentJvmDescriptor()!!
|
||||
|
||||
val reachableDeclarations = findAllReachableDeclarations(function)
|
||||
|
||||
@@ -62,6 +63,7 @@ object BuiltinSpecialBridgesUtil {
|
||||
|
||||
val needGenerateSpecialBridge = needGenerateSpecialBridge(
|
||||
function, reachableDeclarations, overriddenBuiltin, signatureByDescriptor, overriddenBuiltinSignature)
|
||||
&& methodItself != overriddenBuiltinSignature
|
||||
|
||||
val specialBridge = if (needGenerateSpecialBridge)
|
||||
BridgeForBuiltinSpecial(overriddenBuiltinSignature, methodItself, isSpecial = true)
|
||||
@@ -92,16 +94,6 @@ object BuiltinSpecialBridgesUtil {
|
||||
|
||||
return bridges
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun <Signature> FunctionDescriptor.shouldHaveTypeSafeBarrier(
|
||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||
): Boolean {
|
||||
if (BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(this) == null) return false
|
||||
|
||||
val builtin = getOverriddenBuiltinReflectingJvmDescriptor()!!
|
||||
return signatureByDescriptor(this) == signatureByDescriptor(builtin)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,24 +115,13 @@ private fun <Signature> needGenerateSpecialBridge(
|
||||
signatureByDescriptor: (FunctionDescriptor) -> Signature,
|
||||
overriddenBuiltinSignature: Signature
|
||||
): Boolean {
|
||||
if (signatureByDescriptor(functionDescriptor) == overriddenBuiltinSignature) return false
|
||||
if (specialCallableDescriptor.modality == Modality.FINAL) return false
|
||||
|
||||
// Is there Kotlin superclass that already has generated special bridge
|
||||
if (functionDescriptor.firstOverridden { overridden ->
|
||||
val originalOverridden = overridden.original
|
||||
if (overridden === functionDescriptor
|
||||
|| originalOverridden !is FunctionDescriptor
|
||||
|| originalOverridden.containingDeclaration is JavaClassDescriptor
|
||||
|| DescriptorUtils.isInterface(originalOverridden.containingDeclaration)) return@firstOverridden false
|
||||
|
||||
val overriddenSpecial = originalOverridden.getOverriddenBuiltinReflectingJvmDescriptor()?.original ?: return@firstOverridden false
|
||||
|
||||
signatureByDescriptor(originalOverridden) != signatureByDescriptor(overriddenSpecial)
|
||||
} != null) return false
|
||||
|
||||
return reachableDeclarations.none { it.modality == Modality.FINAL
|
||||
&& signatureByDescriptor(it) == overriddenBuiltinSignature }
|
||||
val classDescriptor = functionDescriptor.containingDeclaration as ClassDescriptor
|
||||
return !classDescriptor.hasRealKotlinSuperClassWithOverrideOf(specialCallableDescriptor)
|
||||
&& specialCallableDescriptor.modality != Modality.FINAL
|
||||
&& reachableDeclarations.none {
|
||||
it.modality == Modality.FINAL
|
||||
&& signatureByDescriptor(it) == overriddenBuiltinSignature
|
||||
}
|
||||
}
|
||||
|
||||
public fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
|
||||
@@ -153,7 +134,12 @@ public fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
|
||||
if (KtPsiUtil.deparenthesize(argumentExpression) !== element) return false
|
||||
|
||||
val candidateDescriptor = parentCall.getResolvedCall(bindingContext)?.candidateDescriptor as CallableMemberDescriptor?
|
||||
?: return false
|
||||
?: return false
|
||||
|
||||
return candidateDescriptor.getSpecialSignatureInfo()?.isObjectReplacedWithTypeParameter ?: false
|
||||
|
||||
if (candidateDescriptor.getSpecialSignatureInfo() == BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo.GENERIC_PARAMETER) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
|
||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
fun generateIsCheck(
|
||||
v: InstructionAdapter,
|
||||
isNullable: Boolean,
|
||||
generateInstanceOfInstruction: (InstructionAdapter) -> Unit
|
||||
) {
|
||||
if (isNullable) {
|
||||
val nope = Label()
|
||||
val end = Label()
|
||||
|
||||
with(v) {
|
||||
dup()
|
||||
|
||||
ifnull(nope)
|
||||
|
||||
generateInstanceOfInstruction(this)
|
||||
goTo(end)
|
||||
|
||||
mark(nope)
|
||||
pop()
|
||||
iconst(1)
|
||||
|
||||
mark(end)
|
||||
}
|
||||
}
|
||||
else {
|
||||
generateInstanceOfInstruction(v)
|
||||
}
|
||||
}
|
||||
|
||||
fun generateNullCheckForNonSafeAs(
|
||||
v: InstructionAdapter,
|
||||
type: KotlinType
|
||||
) {
|
||||
with(v) {
|
||||
dup()
|
||||
val nonnull = Label()
|
||||
ifnonnull(nonnull)
|
||||
AsmUtil.genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type))
|
||||
mark(nonnull)
|
||||
}
|
||||
}
|
||||
|
||||
public fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String?
|
||||
= valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") }
|
||||
|
||||
fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(companion: KtObjectDeclaration, outerContext: FieldOwnerContext<*>, state: GenerationState) {
|
||||
val descriptor = state.bindingContext.get(BindingContext.CLASS, companion)
|
||||
|
||||
if (descriptor == null || ErrorUtils.isError(descriptor)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!AsmUtil.isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
|
||||
return
|
||||
}
|
||||
val properties = companion.declarations.filterIsInstance<KtProperty>()
|
||||
|
||||
properties.forEach {
|
||||
val variableDescriptor = state.bindingContext.get(BindingContext.VARIABLE, it)
|
||||
if (variableDescriptor is PropertyDescriptor) {
|
||||
outerContext.getFieldName(variableDescriptor, it.hasDelegate())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen.context;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ReadOnly;
|
||||
import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -28,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue;
|
||||
@@ -37,7 +37,7 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.NEED_SYNTHETIC_ACCESSOR;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
|
||||
|
||||
@@ -267,10 +267,6 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return new MultifileClassFacadeContext(descriptor, this, multifileClassType, filePartType);
|
||||
}
|
||||
|
||||
public ClassContext intoDefaultImplsClass(ClassDescriptor descriptor, ClassContext interfaceContext, GenerationState state) {
|
||||
return new DefaultImplsClassContext(state.getTypeMapper(), descriptor, OwnerKind.DEFAULT_IMPLS, this, null, interfaceContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
||||
if (descriptor.isCompanionObject()) {
|
||||
@@ -283,7 +279,11 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
ClassContext classContext = new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
|
||||
|
||||
if (descriptor.getCompanionObjectDescriptor() != null) {
|
||||
//We can't call descriptor.getCompanionObjectDescriptor() on light class generation
|
||||
// because it triggers companion light class generation via putting it to BindingContext.CLASS
|
||||
// (so MemberCodegen doesn't skip it in genClassOrObject).
|
||||
if (state.getTypeMapper().getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES &&
|
||||
descriptor.getCompanionObjectDescriptor() != null) {
|
||||
//We need to create companion object context ahead of time
|
||||
// because otherwise we can't generate synthetic accessor for private members in companion object
|
||||
classContext.intoClass(descriptor.getCompanionObjectDescriptor(), OwnerKind.IMPLEMENTATION, state);
|
||||
@@ -298,12 +298,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
|
||||
@NotNull
|
||||
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this, null);
|
||||
return new MethodContext(descriptor, getContextKind(), this, null, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline) {
|
||||
return new InlineLambdaContext(descriptor, getContextKind(), this, null, isCrossInline);
|
||||
public MethodContext intoInlinedLambda(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this, null, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -315,10 +315,9 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
public ScriptContext intoScript(
|
||||
@NotNull ScriptDescriptor script,
|
||||
@NotNull List<ScriptDescriptor> earlierScripts,
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull JetTypeMapper typeMapper
|
||||
@NotNull ClassDescriptor classDescriptor
|
||||
) {
|
||||
return new ScriptContext(typeMapper, script, earlierScripts, classDescriptor, this);
|
||||
return new ScriptContext(script, earlierScripts, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -365,24 +364,11 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
public <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
return getAccessor(descriptor, FieldAccessorKind.NORMAL, null, superCallTarget);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
public <D extends CallableMemberDescriptor> D getAccessorForSuperCallIfNeeded(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
if (superCallTarget != null && !isJvmInterface(descriptor.getContainingDeclaration())) {
|
||||
CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext();
|
||||
CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + descriptor;
|
||||
if (c != afterInline.getParentContext()) {
|
||||
return (D) c.getAccessor(descriptor, superCallTarget);
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <D extends CallableMemberDescriptor> D getAccessor(
|
||||
@NotNull D possiblySubstitutedDescriptor,
|
||||
@@ -515,35 +501,38 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ReadOnly
|
||||
public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() {
|
||||
return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
public <D extends CallableMemberDescriptor> D accessibleDescriptor(
|
||||
@NotNull D descriptor,
|
||||
@Nullable ClassDescriptor superCallTarget
|
||||
) {
|
||||
CodegenContext properContext = getFirstCrossInlineOrNonInlineContext();
|
||||
DeclarationDescriptor enclosing = descriptor.getContainingDeclaration();
|
||||
boolean isInliningContext = properContext.isInlineMethodContext();
|
||||
if (!isInliningContext && (
|
||||
!properContext.hasThisDescriptor() ||
|
||||
enclosing == properContext.getThisDescriptor() ||
|
||||
enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor())) {
|
||||
if (!isInlineMethodContext() && (
|
||||
!hasThisDescriptor() ||
|
||||
enclosing == getThisDescriptor() ||
|
||||
enclosing == getClassOrPackageParentContext().getContextDescriptor())) {
|
||||
return descriptor;
|
||||
}
|
||||
return (D) properContext.accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext);
|
||||
|
||||
return accessibleDescriptorIfNeeded(descriptor, superCallTarget);
|
||||
}
|
||||
|
||||
public void recordSyntheticAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BindingContext bindingContext) {
|
||||
if (hasThisDescriptor() && Boolean.TRUE.equals(bindingContext.get(NEED_SYNTHETIC_ACCESSOR, descriptor))) {
|
||||
// Not a super call because neither constructors nor private members can be targets of super calls
|
||||
accessibleDescriptorIfNeeded(descriptor, /* superCallTarget = */ null);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded(
|
||||
@NotNull D descriptor,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
boolean withinInliningContext
|
||||
@Nullable ClassDescriptor superCallTarget
|
||||
) {
|
||||
CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor);
|
||||
|
||||
@@ -564,14 +553,10 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
superCallTarget = (ClassDescriptor) enclosed;
|
||||
}
|
||||
|
||||
if (descriptorContext == null && withinInliningContext && superCallTarget != null) {
|
||||
//generate super calls within inline function through synthetic accessors
|
||||
descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this);
|
||||
}
|
||||
|
||||
if (descriptorContext == null) {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
int propertyAccessFlag = getVisibilityAccessFlag(descriptor);
|
||||
@@ -579,14 +564,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||
int getterAccessFlag = getter == null ? propertyAccessFlag
|
||||
: propertyAccessFlag | getVisibilityAccessFlag(getter);
|
||||
boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext,
|
||||
withinInliningContext, superCallTarget != null);
|
||||
boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext);
|
||||
|
||||
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
||||
int setterAccessFlag = setter == null ? propertyAccessFlag
|
||||
: propertyAccessFlag | getVisibilityAccessFlag(setter);
|
||||
boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext,
|
||||
withinInliningContext, superCallTarget != null);
|
||||
boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext);
|
||||
|
||||
if (!getterAccessorRequired && !setterAccessorRequired) {
|
||||
return descriptor;
|
||||
@@ -595,7 +578,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
else {
|
||||
int flag = getVisibilityAccessFlag(unwrappedDescriptor);
|
||||
if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext, withinInliningContext, superCallTarget != null)) {
|
||||
if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext)) {
|
||||
return descriptor;
|
||||
}
|
||||
return (D) descriptorContext.getAccessor(descriptor, superCallTarget);
|
||||
@@ -605,14 +588,10 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
private static boolean isAccessorRequired(
|
||||
int accessFlag,
|
||||
@NotNull CallableMemberDescriptor unwrappedDescriptor,
|
||||
@NotNull CodegenContext descriptorContext,
|
||||
boolean withinInline,
|
||||
boolean isSuperCall
|
||||
@NotNull CodegenContext descriptorContext
|
||||
) {
|
||||
return isSuperCall && withinInline ||
|
||||
(accessFlag & ACC_PRIVATE) != 0 ||
|
||||
((accessFlag & ACC_PROTECTED) != 0 &&
|
||||
(withinInline || !isInSamePackage(unwrappedDescriptor, descriptorContext.getContextDescriptor())));
|
||||
return (accessFlag & ACC_PRIVATE) != 0 ||
|
||||
((accessFlag & ACC_PROTECTED) != 0 && !isInSamePackage(unwrappedDescriptor, descriptorContext.getContextDescriptor()));
|
||||
}
|
||||
|
||||
private static boolean isInSamePackage(DeclarationDescriptor descriptor1, DeclarationDescriptor descriptor2) {
|
||||
@@ -640,7 +619,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CodegenContext findChildContext(@NotNull DeclarationDescriptor child) {
|
||||
public CodegenContext findChildContext(@NotNull DeclarationDescriptor child) {
|
||||
return childContexts == null ? null : childContexts.get(child);
|
||||
}
|
||||
|
||||
@@ -648,12 +627,18 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return value instanceof StackValue.Field && ((StackValue.Field) value).isStaticPut;
|
||||
}
|
||||
|
||||
public boolean isInlineMethodContext() {
|
||||
private boolean isInsideInliningContext() {
|
||||
CodegenContext current = this;
|
||||
while (current != null) {
|
||||
if (current instanceof MethodContext && ((MethodContext) current).isInlineFunction()) {
|
||||
return true;
|
||||
}
|
||||
current = current.getParentContext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CodegenContext getFirstCrossInlineOrNonInlineContext() {
|
||||
return this;
|
||||
private boolean isInlineMethodContext() {
|
||||
return this instanceof MethodContext && ((MethodContext) this).isInlineFunction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class ConstructorContext extends MethodContext {
|
||||
@NotNull CodegenContext parent,
|
||||
@Nullable MutableClosure closure
|
||||
) {
|
||||
super(contextDescriptor, kind, parent, closure);
|
||||
super(contextDescriptor, kind, parent, closure, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AccessorForCallableDescriptor
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
|
||||
class DefaultImplsClassContext(
|
||||
typeMapper: JetTypeMapper,
|
||||
contextDescriptor: ClassDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
parentContext: CodegenContext<*>?,
|
||||
localLookup: ((DeclarationDescriptor) -> Boolean)?,
|
||||
val interfaceContext: ClassContext
|
||||
) : ClassContext(typeMapper, contextDescriptor, contextKind, parentContext, localLookup) {
|
||||
|
||||
override fun getCompanionObjectContext(): CodegenContext<*>? {
|
||||
return interfaceContext.companionObjectContext
|
||||
}
|
||||
|
||||
override fun getAccessors(): Collection<AccessorForCallableDescriptor<*>> {
|
||||
val accessors = super.getAccessors()
|
||||
val alreadyExistKeys = accessors.map ({ Pair(it.calleeDescriptor, it.superCallTarget) })
|
||||
val filtered = interfaceContext.accessors.toMap ({ Pair(it.calleeDescriptor, it.superCallTarget) }, {it}) - alreadyExistKeys
|
||||
return accessors + filtered.values
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
|
||||
class InlineLambdaContext(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
parentContext: CodegenContext<*>,
|
||||
closure: MutableClosure?,
|
||||
val isCrossInline: Boolean
|
||||
) : MethodContext(functionDescriptor, contextKind, parentContext, closure) {
|
||||
|
||||
override fun getFirstCrossInlineOrNonInlineContext(): CodegenContext<*> {
|
||||
if (isCrossInline) return this
|
||||
|
||||
val parent = parentContext as? ClosureContext ?:
|
||||
throw AssertionError("Parent of inlining lambda body should be ClosureContext, but: $parentContext")
|
||||
|
||||
val grandParent = parent.parentContext ?:
|
||||
throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
|
||||
return grandParent.firstCrossInlineOrNonInlineContext
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
private final boolean isInliningLambda;
|
||||
private Label methodStartLabel;
|
||||
private Label methodEndLabel;
|
||||
|
||||
@@ -43,10 +44,12 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull OwnerKind contextKind,
|
||||
@NotNull CodegenContext parentContext,
|
||||
@Nullable MutableClosure closure
|
||||
@Nullable MutableClosure closure,
|
||||
boolean isInliningLambda
|
||||
) {
|
||||
super(JvmCodegenUtil.getDirectMember(functionDescriptor), contextKind, parentContext, closure,
|
||||
parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
|
||||
this.isInliningLambda = isInliningLambda;
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
}
|
||||
|
||||
@@ -114,10 +117,14 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
return "Method: " + getContextDescriptor();
|
||||
}
|
||||
|
||||
public boolean isInlineMethodContext() {
|
||||
public boolean isInlineFunction() {
|
||||
return InlineUtil.isInline(getContextDescriptor());
|
||||
}
|
||||
|
||||
public boolean isInliningLambda() {
|
||||
return isInliningLambda;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FunctionDescriptor getFunctionDescriptor() {
|
||||
return functionDescriptor;
|
||||
|
||||
@@ -16,48 +16,30 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context;
|
||||
|
||||
import kotlin.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.FieldInfo;
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtAnonymousInitializer;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtScript;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ScriptContext extends ClassContext {
|
||||
public class ScriptContext extends FieldOwnerContext<ClassDescriptor> {
|
||||
private final ScriptDescriptor scriptDescriptor;
|
||||
private final List<ScriptDescriptor> earlierScripts;
|
||||
private final KtExpression lastStatement;
|
||||
|
||||
public ScriptContext(
|
||||
@NotNull JetTypeMapper typeMapper,
|
||||
@NotNull ScriptDescriptor scriptDescriptor,
|
||||
@NotNull List<ScriptDescriptor> earlierScripts,
|
||||
@NotNull ClassDescriptor contextDescriptor,
|
||||
@Nullable CodegenContext parentContext
|
||||
@NotNull OwnerKind contextKind,
|
||||
@Nullable CodegenContext parentContext,
|
||||
@Nullable MutableClosure closure
|
||||
) {
|
||||
super(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null);
|
||||
super(contextDescriptor, contextKind, parentContext, closure, contextDescriptor, null);
|
||||
this.scriptDescriptor = scriptDescriptor;
|
||||
this.earlierScripts = earlierScripts;
|
||||
KtScript script = (KtScript) DescriptorToSourceUtils.getSourceFromDescriptor(scriptDescriptor);
|
||||
assert script != null : "Declaration should be present for script: " + scriptDescriptor;
|
||||
KtDeclaration lastDeclaration = CollectionsKt.lastOrNull(script.getDeclarations());
|
||||
if (lastDeclaration instanceof KtAnonymousInitializer) {
|
||||
this.lastStatement = ((KtAnonymousInitializer) lastDeclaration).getBody();
|
||||
}
|
||||
else {
|
||||
this.lastStatement = null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -65,15 +47,6 @@ public class ScriptContext extends ClassContext {
|
||||
return scriptDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FieldInfo getResultFieldInfo() {
|
||||
assert getState().getReplSpecific().getShouldGenerateScriptResultValue() : "Should not be called unless 'scriptResultFieldName' is set";
|
||||
GenerationState state = getState();
|
||||
String scriptResultFieldName = state.getReplSpecific().getScriptResultFieldName();
|
||||
assert scriptResultFieldName != null;
|
||||
return FieldInfo.createForHiddenField(state.getTypeMapper().mapClass(scriptDescriptor), AsmTypes.OBJECT_TYPE, scriptResultFieldName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ScriptDescriptor> getEarlierScripts() {
|
||||
return earlierScripts;
|
||||
@@ -88,11 +61,6 @@ public class ScriptContext extends ClassContext {
|
||||
return "script$" + (index + 1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public KtExpression getLastStatement() {
|
||||
return lastStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Script: " + getContextDescriptor().getName().asString();
|
||||
|
||||
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
|
||||
public interface ExpressionCodegenExtension {
|
||||
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>(
|
||||
"org.jetbrains.kotlin.expressionCodegenExtension", ExpressionCodegenExtension::class.java)
|
||||
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>("org.jetbrains.kotlin.expressionCodegenExtension", javaClass<ExpressionCodegenExtension>())
|
||||
|
||||
public class Context(
|
||||
public val typeMapper: JetTypeMapper,
|
||||
@@ -42,10 +42,10 @@ public interface ExpressionCodegenExtension {
|
||||
public fun applyProperty(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
||||
|
||||
/**
|
||||
* Used for generating custom byte code for the function call. This function has lazy semantics.
|
||||
* Returns new stack value.
|
||||
* Used for generating custom byte code for the function call. This function has non-lazy semantics.
|
||||
* Returns true if the stack was modified.
|
||||
*/
|
||||
public fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
||||
public fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): Boolean = false
|
||||
|
||||
public fun generateClassSyntheticParts(
|
||||
classBuilder: ClassBuilder,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,11 +28,13 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.tree.*;
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
|
||||
public class AnonymousObjectTransformer {
|
||||
@@ -62,6 +65,8 @@ public class AnonymousObjectTransformer {
|
||||
|
||||
private final Map<String, List<String>> fieldNames = new HashMap<String, List<String>>();
|
||||
|
||||
private final TypeRemapper typeRemapper;
|
||||
|
||||
public AnonymousObjectTransformer(
|
||||
@NotNull String objectInternalName,
|
||||
@NotNull InliningContext inliningContext,
|
||||
@@ -76,12 +81,12 @@ public class AnonymousObjectTransformer {
|
||||
this.newLambdaType = newLambdaType;
|
||||
|
||||
reader = InlineCodegenUtil.buildClassReaderByInternalName(state, objectInternalName);
|
||||
typeRemapper = new TypeRemapper(inliningContext.typeMapping);
|
||||
transformationResult = InlineResult.create();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public InlineResult doTransform(@NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull FieldRemapper parentRemapper) {
|
||||
final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>();
|
||||
ClassBuilder classBuilder = createClassBuilder();
|
||||
final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();
|
||||
|
||||
@@ -96,11 +101,6 @@ public class AnonymousObjectTransformer {
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) {
|
||||
innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(@NotNull String owner, String name, String desc) {
|
||||
InliningContext parent = inliningContext.getParent();
|
||||
@@ -179,7 +179,7 @@ public class AnonymousObjectTransformer {
|
||||
ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder();
|
||||
List<CapturedParamInfo> additionalFakeParams =
|
||||
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder,
|
||||
anonymousObjectGen, parentRemapper);
|
||||
anonymousObjectGen);
|
||||
List<MethodVisitor> deferringMethods = new ArrayList();
|
||||
|
||||
for (MethodNode next : methodsToTransform) {
|
||||
@@ -192,7 +192,7 @@ public class AnonymousObjectTransformer {
|
||||
String oldFunReturnType = returnType.getInternalName();
|
||||
String newFunReturnType = funResult.getChangedTypes().get(oldFunReturnType);
|
||||
if (newFunReturnType != null) {
|
||||
inliningContext.typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType);
|
||||
typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType);
|
||||
}
|
||||
}
|
||||
deferringMethods.add(deferringVisitor);
|
||||
@@ -206,10 +206,6 @@ public class AnonymousObjectTransformer {
|
||||
|
||||
SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);
|
||||
|
||||
for (InnerClassNode node : innerClassNodes) {
|
||||
classBuilder.getVisitor().visitInnerClass(node.name, node.outerName, node.innerName, node.access);
|
||||
}
|
||||
|
||||
classBuilder.done();
|
||||
|
||||
anonymousObjectGen.setNewLambdaType(newLambdaType);
|
||||
@@ -240,7 +236,7 @@ public class AnonymousObjectTransformer {
|
||||
@NotNull ParametersBuilder capturedBuilder,
|
||||
boolean isConstructor
|
||||
) {
|
||||
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode);
|
||||
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
|
||||
Parameters parameters = isConstructor ? capturedBuilder.buildParameters() : getMethodParametersWithCaptured(capturedBuilder, sourceNode);
|
||||
|
||||
RegeneratedLambdaFieldRemapper remapper =
|
||||
@@ -288,23 +284,26 @@ public class AnonymousObjectTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
List<Pair<String, Type>> capturedFieldsToGenerate = new ArrayList<Pair<String, Type>>();
|
||||
for (CapturedParamInfo capturedParamInfo : allCapturedBuilder.listCaptured()) {
|
||||
if (capturedParamInfo.getLambda() == null) { //not inlined
|
||||
capturedFieldsToGenerate.add(new Pair<String, Type>(capturedParamInfo.getNewFieldName(), capturedParamInfo.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()]));
|
||||
|
||||
MethodVisitor constructorVisitor = classBuilder.newMethod(NO_ORIGIN,
|
||||
AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
||||
"<init>", constructorDescriptor,
|
||||
null, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
|
||||
//initialize captured fields
|
||||
List<NewJavaField> newFieldsWithSkipped = TransformationUtilsKt.getNewFieldsToGenerate(allCapturedBuilder.listCaptured());
|
||||
List<FieldInfo> fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo(newLambdaType, newFieldsWithSkipped);
|
||||
|
||||
List<FieldInfo> fields = AsmUtil.transformCapturedParams(capturedFieldsToGenerate, newLambdaType);
|
||||
int paramIndex = 0;
|
||||
InstructionAdapter capturedFieldInitializer = new InstructionAdapter(constructorVisitor);
|
||||
for (int i = 0; i < fieldInfoWithSkipped.size(); i++) {
|
||||
FieldInfo fieldInfo = fieldInfoWithSkipped.get(i);
|
||||
if (!newFieldsWithSkipped.get(i).getSkip()) {
|
||||
AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer);
|
||||
}
|
||||
for (FieldInfo fieldInfo : fields) {
|
||||
AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
@@ -328,7 +327,8 @@ public class AnonymousObjectTransformer {
|
||||
|
||||
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
|
||||
constructorVisitor.visitEnd();
|
||||
AsmUtil.genClosureFields(TransformationUtilsKt.toNameTypePair(TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder);
|
||||
|
||||
AsmUtil.genClosureFields(capturedFieldsToGenerate, classBuilder);
|
||||
//TODO for inline method make public class
|
||||
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
|
||||
}
|
||||
@@ -348,7 +348,7 @@ public class AnonymousObjectTransformer {
|
||||
@NotNull
|
||||
private ClassBuilder createClassBuilder() {
|
||||
ClassBuilder classBuilder = state.getFactory().newVisitor(NO_ORIGIN, newLambdaType, inliningContext.getRoot().callElement.getContainingFile());
|
||||
return new RemappingClassBuilder(classBuilder, inliningContext.typeRemapper);
|
||||
return new RemappingClassBuilder(classBuilder, typeRemapper);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -378,8 +378,7 @@ public class AnonymousObjectTransformer {
|
||||
@NotNull MethodNode constructor,
|
||||
@NotNull ParametersBuilder capturedParamBuilder,
|
||||
@NotNull ParametersBuilder constructorParamBuilder,
|
||||
@NotNull final AnonymousObjectGeneration anonymousObjectGen,
|
||||
@NotNull FieldRemapper parentFieldRemapper
|
||||
@NotNull final AnonymousObjectGeneration anonymousObjectGen
|
||||
) {
|
||||
|
||||
CapturedParamOwner owner = new CapturedParamOwner() {
|
||||
@@ -389,7 +388,7 @@ public class AnonymousObjectTransformer {
|
||||
}
|
||||
};
|
||||
|
||||
Set<LambdaInfo> capturedLambdas = new LinkedHashSet<LambdaInfo>(); //captured var of inlined parameter
|
||||
List<LambdaInfo> capturedLambdas = new ArrayList<LambdaInfo>(); //captured var of inlined parameter
|
||||
List<CapturedParamInfo> constructorAdditionalFakeParams = new ArrayList<CapturedParamInfo>();
|
||||
Map<Integer, LambdaInfo> indexToLambda = anonymousObjectGen.getLambdasToInline();
|
||||
Set<Integer> capturedParams = new HashSet<Integer>();
|
||||
@@ -399,8 +398,7 @@ public class AnonymousObjectTransformer {
|
||||
while (cur != null) {
|
||||
if (cur instanceof FieldInsnNode) {
|
||||
FieldInsnNode fieldNode = (FieldInsnNode) cur;
|
||||
String fieldName = fieldNode.name;
|
||||
if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldName)) {
|
||||
if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldNode.name)) {
|
||||
|
||||
boolean isPrevVarNode = fieldNode.getPrevious() instanceof VarInsnNode;
|
||||
boolean isPrevPrevVarNode = isPrevVarNode && fieldNode.getPrevious().getPrevious() instanceof VarInsnNode;
|
||||
@@ -411,8 +409,7 @@ public class AnonymousObjectTransformer {
|
||||
VarInsnNode previous = (VarInsnNode) fieldNode.getPrevious();
|
||||
int varIndex = previous.var;
|
||||
LambdaInfo lambdaInfo = indexToLambda.get(varIndex);
|
||||
String newFieldName = isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values()) ? getNewFieldName(fieldName, true) : fieldName;
|
||||
CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldName, newFieldName, Type.getType(fieldNode.desc), lambdaInfo != null, null);
|
||||
CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldNode.name, Type.getType(fieldNode.desc), lambdaInfo != null, null);
|
||||
if (lambdaInfo != null) {
|
||||
info.setLambda(lambdaInfo);
|
||||
capturedLambdas.add(lambdaInfo);
|
||||
@@ -457,57 +454,23 @@ public class AnonymousObjectTransformer {
|
||||
//TODO: some of such parameters could be skipped - we should perform additional analysis
|
||||
Map<String, LambdaInfo> capturedLambdasToInline = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
|
||||
List<CapturedParamDesc> allRecapturedParameters = new ArrayList<CapturedParamDesc>();
|
||||
boolean addCapturedNotAddOuter = parentFieldRemapper.isRoot() || (parentFieldRemapper instanceof InlinedLambdaRemapper && parentFieldRemapper.getParent().isRoot());
|
||||
Map<String, CapturedParamInfo> alreadyAdded = new HashMap<String, CapturedParamInfo>();
|
||||
for (LambdaInfo info : capturedLambdas) {
|
||||
if (addCapturedNotAddOuter) {
|
||||
for (CapturedParamDesc desc : info.getCapturedVars()) {
|
||||
String key = desc.getFieldName() + "$$$" + desc.getType().getClassName();
|
||||
CapturedParamInfo alreadyAddedParam = alreadyAdded.get(key);
|
||||
for (CapturedParamDesc desc : info.getCapturedVars()) {
|
||||
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName()));
|
||||
StackValue composed = StackValue.field(desc.getType(),
|
||||
oldObjectType, /*TODO owner type*/
|
||||
recapturedParamInfo.getNewFieldName(),
|
||||
false,
|
||||
StackValue.LOCAL_0);
|
||||
recapturedParamInfo.setRemapValue(composed);
|
||||
allRecapturedParameters.add(desc);
|
||||
|
||||
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(
|
||||
desc,
|
||||
alreadyAddedParam != null ? alreadyAddedParam.getNewFieldName() : getNewFieldName(desc.getFieldName(), false));
|
||||
StackValue composed = StackValue.field(desc.getType(),
|
||||
oldObjectType, /*TODO owner type*/
|
||||
recapturedParamInfo.getNewFieldName(),
|
||||
false,
|
||||
StackValue.LOCAL_0);
|
||||
recapturedParamInfo.setRemapValue(composed);
|
||||
allRecapturedParameters.add(desc);
|
||||
|
||||
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
|
||||
if (alreadyAddedParam != null) {
|
||||
recapturedParamInfo.setSkipInConstructor(true);
|
||||
}
|
||||
|
||||
if (isThis0(desc.getFieldName())) {
|
||||
alreadyAdded.put(key, recapturedParamInfo);
|
||||
}
|
||||
}
|
||||
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
|
||||
}
|
||||
capturedLambdasToInline.put(info.getLambdaClassType().getInternalName(), info);
|
||||
}
|
||||
|
||||
if (parentFieldRemapper instanceof InlinedLambdaRemapper && !capturedLambdas.isEmpty() && !addCapturedNotAddOuter) {
|
||||
//lambda with non InlinedLambdaRemapper already have outer
|
||||
FieldRemapper parent = parentFieldRemapper.getParent();
|
||||
assert parent instanceof RegeneratedLambdaFieldRemapper;
|
||||
final Type ownerType = Type.getObjectType(parent.getLambdaInternalName());
|
||||
|
||||
CapturedParamDesc desc = new CapturedParamDesc(new CapturedParamOwner() {
|
||||
@Override
|
||||
public Type getType() {
|
||||
return ownerType;
|
||||
}
|
||||
}, InlineCodegenUtil.THIS, ownerType);
|
||||
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.THIS$0/*outer lambda/object*/);
|
||||
StackValue composed = StackValue.LOCAL_0;
|
||||
recapturedParamInfo.setRemapValue(composed);
|
||||
allRecapturedParameters.add(desc);
|
||||
|
||||
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
|
||||
}
|
||||
|
||||
anonymousObjectGen.setAllRecapturedParameters(allRecapturedParameters);
|
||||
anonymousObjectGen.setCapturedLambdasToInline(capturedLambdasToInline);
|
||||
@@ -515,30 +478,13 @@ public class AnonymousObjectTransformer {
|
||||
return constructorAdditionalFakeParams;
|
||||
}
|
||||
|
||||
private static boolean shouldRenameThis0(@NotNull FieldRemapper parentFieldRemapper, Collection<LambdaInfo> values) {
|
||||
if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
|
||||
for (LambdaInfo value : values) {
|
||||
for (CapturedParamDesc desc : value.getCapturedVars()) {
|
||||
if (isThis0(desc.getFieldName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getNewFieldName(@NotNull String oldName, boolean originalField) {
|
||||
public String getNewFieldName(@NotNull String oldName) {
|
||||
if (InlineCodegenUtil.THIS$0.equals(oldName)) {
|
||||
if (!originalField) {
|
||||
return oldName;
|
||||
} else {
|
||||
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
|
||||
return addUniqueField(oldName + InlineCodegenUtil.INLINE_FUN_THIS_0_SUFFIX);
|
||||
}
|
||||
//"this$0" couldn't clash and we should keep this name invariant for further transformations
|
||||
return oldName;
|
||||
}
|
||||
return addUniqueField(oldName + InlineCodegenUtil.INLINE_TRANSFORMATION_SUFFIX);
|
||||
return addUniqueField(oldName + "$inlined");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -553,8 +499,4 @@ public class AnonymousObjectTransformer {
|
||||
existNames.add(newName);
|
||||
return newName;
|
||||
}
|
||||
|
||||
private static boolean isFirstDeclSiteLambdaFieldRemapper(FieldRemapper parentRemapper) {
|
||||
return !(parentRemapper instanceof RegeneratedLambdaFieldRemapper) && !(parentRemapper instanceof InlinedLambdaRemapper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,6 @@ public class CapturedParamInfo extends ParameterInfo {
|
||||
|
||||
private final String newFieldName;
|
||||
|
||||
private boolean skipInConstructor;
|
||||
|
||||
public CapturedParamInfo(@NotNull CapturedParamDesc desc, boolean skipped, int index, int remapIndex) {
|
||||
this(desc, desc.getFieldName(), skipped, index, remapIndex);
|
||||
}
|
||||
@@ -70,7 +68,6 @@ public class CapturedParamInfo extends ParameterInfo {
|
||||
public CapturedParamInfo clone(int newIndex, StackValue newRamapIndex) {
|
||||
CapturedParamInfo capturedParamInfo = new CapturedParamInfo(desc, newFieldName, isSkipped, newIndex, newRamapIndex);
|
||||
capturedParamInfo.setLambda(lambda);
|
||||
capturedParamInfo.setSkipInConstructor(skipInConstructor);
|
||||
return capturedParamInfo;
|
||||
}
|
||||
|
||||
@@ -78,12 +75,4 @@ public class CapturedParamInfo extends ParameterInfo {
|
||||
public String getContainingLambdaName() {
|
||||
return desc.getContainingLambdaName();
|
||||
}
|
||||
|
||||
public boolean isSkipInConstructor() {
|
||||
return skipInConstructor;
|
||||
}
|
||||
|
||||
public void setSkipInConstructor(boolean skipInConstructor) {
|
||||
this.skipInConstructor = skipInConstructor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
|
||||
@@ -121,10 +120,6 @@ public class FieldRemapper {
|
||||
return lambdaInternalName;
|
||||
}
|
||||
|
||||
public String getNewLambdaInternalName() {
|
||||
return lambdaInternalName;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.modules.TargetId;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
@@ -63,6 +62,7 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||
@@ -246,7 +246,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) {
|
||||
MethodNode node = nodeAndSmap.getNode();
|
||||
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node);
|
||||
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions);
|
||||
generateClosuresBodies();
|
||||
|
||||
//through generation captured parameters will be added to invocationParamBuilder
|
||||
@@ -310,7 +310,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
MethodContext parentContext = codegen.getContext();
|
||||
|
||||
MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor, info.isCrossInline);
|
||||
MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor);
|
||||
|
||||
JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(descriptor);
|
||||
Method asmMethod = jvmMethodSignature.getAsmMethod();
|
||||
@@ -539,34 +539,26 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
/*lambda or callable reference*/
|
||||
public boolean isInliningParameter(KtExpression expression, ValueParameterDescriptor valueParameterDescriptor) {
|
||||
public static boolean isInliningParameter(KtExpression expression, ValueParameterDescriptor valueParameterDescriptor) {
|
||||
//TODO deparenthisise typed
|
||||
KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression);
|
||||
|
||||
if (deparenthesized instanceof KtCallableReferenceExpression) {
|
||||
// TODO: support inline of property references passed to inlinable function parameters
|
||||
SimpleFunctionDescriptor functionReference = state.getBindingContext().get(BindingContext.FUNCTION, deparenthesized);
|
||||
if (functionReference == null) return false;
|
||||
}
|
||||
|
||||
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) &&
|
||||
isInlinableParameterExpression(deparenthesized);
|
||||
}
|
||||
|
||||
protected static boolean isInlinableParameterExpression(KtExpression deparenthesized) {
|
||||
return deparenthesized instanceof KtLambdaExpression ||
|
||||
return deparenthesized instanceof KtFunctionLiteralExpression ||
|
||||
deparenthesized instanceof KtNamedFunction ||
|
||||
deparenthesized instanceof KtCallableReferenceExpression;
|
||||
}
|
||||
|
||||
public void rememberClosure(KtExpression expression, Type type, ValueParameterDescriptor parameter) {
|
||||
public void rememberClosure(KtExpression expression, Type type, int parameterIndex) {
|
||||
KtExpression lambda = KtPsiUtil.deparenthesize(expression);
|
||||
assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
|
||||
|
||||
LambdaInfo info = new LambdaInfo(lambda, typeMapper);
|
||||
|
||||
LambdaInfo info = new LambdaInfo(lambda, typeMapper, parameter.isCrossinline());
|
||||
|
||||
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex());
|
||||
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameterIndex);
|
||||
closureInfo.setLambda(info);
|
||||
expressionMap.put(closureInfo.getIndex(), info);
|
||||
}
|
||||
@@ -606,16 +598,18 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state, sourceFile);
|
||||
|
||||
if (descriptor instanceof ScriptDescriptor) {
|
||||
List<ScriptDescriptor> earlierScripts = state.getReplSpecific().getEarlierScriptsForReplInterpreter();
|
||||
return parent.intoScript((ScriptDescriptor) descriptor,
|
||||
earlierScripts == null ? Collections.emptyList() : earlierScripts,
|
||||
(ClassDescriptor) descriptor, state.getTypeMapper());
|
||||
}
|
||||
else if (descriptor instanceof ClassDescriptor) {
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
OwnerKind kind = DescriptorUtils.isInterface(descriptor) ? OwnerKind.DEFAULT_IMPLS : OwnerKind.IMPLEMENTATION;
|
||||
return parent.intoClass((ClassDescriptor) descriptor, kind, state);
|
||||
}
|
||||
else if (descriptor instanceof ScriptDescriptor) {
|
||||
ClassDescriptor classDescriptorForScript = state.getBindingContext().get(CLASS_FOR_SCRIPT, (ScriptDescriptor) descriptor);
|
||||
assert classDescriptorForScript != null : "Can't find class for script: " + descriptor;
|
||||
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
|
||||
return parent.intoScript((ScriptDescriptor) descriptor,
|
||||
earlierScripts == null ? Collections.emptyList() : earlierScripts,
|
||||
classDescriptorForScript);
|
||||
}
|
||||
else if (descriptor instanceof FunctionDescriptor) {
|
||||
return parent.intoFunction((FunctionDescriptor) descriptor);
|
||||
}
|
||||
@@ -639,7 +633,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
int parameterIndex
|
||||
) {
|
||||
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
|
||||
rememberClosure(argumentExpression, parameterType, valueParameterDescriptor);
|
||||
rememberClosure(argumentExpression, parameterType, valueParameterDescriptor.getIndex());
|
||||
}
|
||||
else {
|
||||
StackValue value = codegen.gen(argumentExpression);
|
||||
@@ -787,7 +781,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
@Override
|
||||
public void reorderArgumentsIfNeeded(
|
||||
@NotNull List<ArgumentAndDeclIndex> actualArgsWithDeclIndex, @NotNull List<? extends Type> valueParameterTypes
|
||||
@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex, @NotNull List<? extends Type> valueParameterTypes
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@@ -29,9 +29,7 @@ import org.jetbrains.kotlin.codegen.MemberCodegen;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -64,7 +62,6 @@ public class InlineCodegenUtil {
|
||||
|
||||
public static final String CAPTURED_FIELD_PREFIX = "$";
|
||||
public static final String THIS$0 = "this$0";
|
||||
public static final String THIS = "this";
|
||||
public static final String RECEIVER$0 = "receiver$0";
|
||||
public static final String NON_LOCAL_RETURN = "$$$$$NON_LOCAL_RETURN$$$$$";
|
||||
public static final String FIRST_FUN_LABEL = "$$$$$ROOT$$$$$";
|
||||
@@ -74,9 +71,6 @@ public class InlineCodegenUtil {
|
||||
public static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall";
|
||||
public static final String INLINE_MARKER_FINALLY_START = "finallyStart";
|
||||
public static final String INLINE_MARKER_FINALLY_END = "finallyEnd";
|
||||
public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined";
|
||||
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
|
||||
public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
|
||||
|
||||
@Nullable
|
||||
public static SMAPAndMethodNode getMethodNode(
|
||||
@@ -123,7 +117,7 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
}, ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));
|
||||
|
||||
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.asString(), lines[0], lines[1]);
|
||||
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.toString(), lines[0], lines[1]);
|
||||
return new SMAPAndMethodNode(node[0], smap);
|
||||
}
|
||||
|
||||
@@ -132,7 +126,7 @@ public class InlineCodegenUtil {
|
||||
CodegenContext<?> parentContext = context.getParentContext();
|
||||
while (parentContext != null) {
|
||||
if (parentContext instanceof MethodContext) {
|
||||
if (((MethodContext) parentContext).isInlineMethodContext()) {
|
||||
if (((MethodContext) parentContext).isInlineFunction()) {
|
||||
//just init default one to one mapping
|
||||
codegen.getOrCreateSourceMapper();
|
||||
break;
|
||||
@@ -312,7 +306,8 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull InsnList instructions, @NotNull AbstractInsnNode beforeNode) {
|
||||
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) {
|
||||
InsnList instructions = to.instructions;
|
||||
ListIterator<AbstractInsnNode> iterator = from.instructions.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
AbstractInsnNode next = iterator.next();
|
||||
@@ -320,10 +315,6 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) {
|
||||
insertNodeBefore(from, to.instructions, beforeNode);
|
||||
}
|
||||
|
||||
|
||||
public static MethodNode createEmptyMethodNode() {
|
||||
return new MethodNode(API, 0, "fake", "()V", null, null);
|
||||
@@ -399,7 +390,7 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
|
||||
public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) {
|
||||
return context.isInlineMethodContext() || context instanceof InlineLambdaContext;
|
||||
return context.isInlineFunction() || context.isInliningLambda();
|
||||
}
|
||||
|
||||
public static int getConstant(AbstractInsnNode ins) {
|
||||
@@ -494,26 +485,4 @@ public class InlineCodegenUtil {
|
||||
public static boolean isFakeLocalVariableForInline(@NotNull String name) {
|
||||
return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT);
|
||||
}
|
||||
|
||||
public static boolean isThis0(String name) {
|
||||
return THIS$0.equals(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AbstractInsnNode getPrevMeaningful(@NotNull AbstractInsnNode node) {
|
||||
AbstractInsnNode result = node.getPrevious();
|
||||
while (result != null && !UtilKt.isMeaningful(result)) {
|
||||
result = result.getPrevious();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void removeInterval(@NotNull MethodNode node, @NotNull AbstractInsnNode startInc, @NotNull AbstractInsnNode endInc) {
|
||||
while (startInc != endInc) {
|
||||
AbstractInsnNode next = startInc.getNext();
|
||||
node.instructions.remove(startInc);
|
||||
startInc = next;
|
||||
}
|
||||
node.instructions.remove(startInc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.inline;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -51,15 +50,4 @@ public class InlinedLambdaRemapper extends FieldRemapper {
|
||||
public boolean isInsideInliningLambda() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StackValue getFieldForInline(@NotNull FieldInsnNode node, @Nullable StackValue prefix) {
|
||||
if (parent.isRoot()) {
|
||||
return super.getFieldForInline(node, prefix);
|
||||
} else {
|
||||
return parent.getFieldForInline(node, prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class InliningContext {
|
||||
|
||||
public final NameGenerator nameGenerator;
|
||||
|
||||
public final TypeRemapper typeRemapper;
|
||||
public final Map<String, String> typeMapping;
|
||||
|
||||
public final ReifiedTypeInliner reifedTypeInliner;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class InliningContext {
|
||||
@NotNull Map<Integer, LambdaInfo> map,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull NameGenerator nameGenerator,
|
||||
@NotNull TypeRemapper typeRemapper,
|
||||
@NotNull Map<String, String> typeMapping,
|
||||
@NotNull ReifiedTypeInliner reifedTypeInliner,
|
||||
boolean isInliningLambda,
|
||||
boolean classRegeneration
|
||||
@@ -57,7 +57,7 @@ public class InliningContext {
|
||||
expressionMap = map;
|
||||
this.state = state;
|
||||
this.nameGenerator = nameGenerator;
|
||||
this.typeRemapper = typeRemapper;
|
||||
this.typeMapping = typeMapping;
|
||||
this.reifedTypeInliner = reifedTypeInliner;
|
||||
this.isInliningLambda = isInliningLambda;
|
||||
this.classRegeneration = classRegeneration;
|
||||
@@ -78,12 +78,13 @@ public class InliningContext {
|
||||
}
|
||||
|
||||
public InliningContext subInlineWithClassRegeneration(@NotNull NameGenerator generator,
|
||||
@NotNull Map<String, String> newTypeMappings,
|
||||
@NotNull Map<String, String> additionalTypeMappings,
|
||||
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
|
||||
) {
|
||||
Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
|
||||
newTypeMappings.putAll(additionalTypeMappings);
|
||||
return new RegeneratedClassContext(this, expressionMap, state, generator,
|
||||
new TypeRemapper(typeRemapper, newTypeMappings),
|
||||
reifedTypeInliner, isInliningLambda, anonymousObjectGeneration);
|
||||
newTypeMappings, reifedTypeInliner, isInliningLambda, anonymousObjectGeneration);
|
||||
}
|
||||
|
||||
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings, boolean isInliningLambda) {
|
||||
@@ -96,8 +97,10 @@ public class InliningContext {
|
||||
boolean isInliningLambda,
|
||||
boolean isRegeneration
|
||||
) {
|
||||
Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
|
||||
newTypeMappings.putAll(additionalTypeMappings);
|
||||
return new InliningContext(this, expressionMap, state, generator,
|
||||
new TypeRemapper(typeRemapper, additionalTypeMappings), reifedTypeInliner, isInliningLambda, isRegeneration);
|
||||
newTypeMappings, reifedTypeInliner, isInliningLambda, isRegeneration);
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteralExpression;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
@@ -50,8 +50,6 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner {
|
||||
|
||||
private final CalculatedClosure closure;
|
||||
|
||||
public final boolean isCrossInline;
|
||||
|
||||
private SMAPAndMethodNode node;
|
||||
|
||||
private List<CapturedParamDesc> capturedVars;
|
||||
@@ -62,10 +60,9 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner {
|
||||
|
||||
private final Type closureClassType;
|
||||
|
||||
LambdaInfo(@NotNull KtExpression expr, @NotNull JetTypeMapper typeMapper, boolean isCrossInline) {
|
||||
this.isCrossInline = isCrossInline;
|
||||
this.expression = expr instanceof KtLambdaExpression ?
|
||||
((KtLambdaExpression) expr).getFunctionLiteral() : expr;
|
||||
LambdaInfo(@NotNull KtExpression expr, @NotNull JetTypeMapper typeMapper) {
|
||||
this.expression = expr instanceof KtFunctionLiteralExpression ?
|
||||
((KtFunctionLiteralExpression) expr).getFunctionLiteral() : expr;
|
||||
|
||||
this.typeMapper = typeMapper;
|
||||
BindingContext bindingContext = typeMapper.getBindingContext();
|
||||
|
||||
@@ -97,6 +97,10 @@ public class LocalVarRemapper {
|
||||
//add entries only for shifted vars
|
||||
if (SHIFT == info.status) {
|
||||
int newIndex = ((StackValue.Local) info.value).index;
|
||||
if (newIndex != 0 && "this".equals(name)) {
|
||||
/*skip additional this for now*/
|
||||
return;
|
||||
}
|
||||
mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen.inline;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen;
|
||||
import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
@@ -78,7 +77,7 @@ public class MethodInliner {
|
||||
public MethodInliner(
|
||||
@NotNull MethodNode node,
|
||||
@NotNull Parameters parameters,
|
||||
@NotNull InliningContext inliningContext,
|
||||
@NotNull InliningContext parent,
|
||||
@NotNull FieldRemapper nodeRemapper,
|
||||
boolean isSameModule,
|
||||
@NotNull String errorPrefix,
|
||||
@@ -86,12 +85,12 @@ public class MethodInliner {
|
||||
) {
|
||||
this.node = node;
|
||||
this.parameters = parameters;
|
||||
this.inliningContext = inliningContext;
|
||||
this.inliningContext = parent;
|
||||
this.nodeRemapper = nodeRemapper;
|
||||
this.isSameModule = isSameModule;
|
||||
this.errorPrefix = errorPrefix;
|
||||
this.sourceMapper = sourceMapper;
|
||||
this.typeMapper = inliningContext.state.getTypeMapper();
|
||||
this.typeMapper = parent.state.getTypeMapper();
|
||||
this.result = InlineResult.create();
|
||||
}
|
||||
|
||||
@@ -153,9 +152,8 @@ public class MethodInliner {
|
||||
|
||||
final Iterator<AnonymousObjectGeneration> iterator = anonymousObjectGenerations.iterator();
|
||||
|
||||
final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping);
|
||||
RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(resultNode.access, resultNode.desc, resultNode,
|
||||
remapper);
|
||||
new TypeRemapper(currentTypeMapping));
|
||||
|
||||
final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node);
|
||||
InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) {
|
||||
@@ -168,7 +166,7 @@ public class MethodInliner {
|
||||
//TODO: need poping of type but what to do with local funs???
|
||||
String oldClassName = anonymousObjectGen.getOwnerInternalName();
|
||||
String newClassName = inliningContext.nameGenerator.genLambdaClassName();
|
||||
remapper.addMapping(oldClassName, newClassName);
|
||||
currentTypeMapping.put(oldClassName, newClassName);
|
||||
AnonymousObjectTransformer transformer =
|
||||
new AnonymousObjectTransformer(oldClassName,
|
||||
inliningContext
|
||||
@@ -262,14 +260,7 @@ public class MethodInliner {
|
||||
visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(),
|
||||
"$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor());
|
||||
}
|
||||
String newInternalName = anonymousObjectGen.getNewLambdaType().getInternalName();
|
||||
super.visitMethodInsn(opcode, newInternalName, name, anonymousObjectGen.getNewConstructorDescriptor(), itf);
|
||||
|
||||
//TODO: add new inner class also for other contexts
|
||||
if (inliningContext.getParent() instanceof RegeneratedClassContext) {
|
||||
inliningContext.getParent().typeRemapper.addAdditionalMappings(anonymousObjectGen.getOwnerInternalName(), newInternalName);
|
||||
}
|
||||
|
||||
super.visitMethodInsn(opcode, anonymousObjectGen.getNewLambdaType().getInternalName(), name, anonymousObjectGen.getNewConstructorDescriptor(), itf);
|
||||
anonymousObjectGen = null;
|
||||
} else {
|
||||
super.visitMethodInsn(opcode, changeOwnerForExternalPackage(owner, opcode), name, desc, itf);
|
||||
@@ -361,9 +352,7 @@ public class MethodInliner {
|
||||
@NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index
|
||||
) {
|
||||
if (isInliningLambda || InlineCodegenUtil.GENERATE_SMAP) {
|
||||
String varSuffix = inliningContext.isRoot() && !InlineCodegenUtil.isFakeLocalVariableForInline(name) ? INLINE_FUN_VAR_SUFFIX : "";
|
||||
String varName = !varSuffix.isEmpty() && name.equals("this") ? name + "_" : name;
|
||||
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index));
|
||||
super.visitLocalVariable(name, desc, signature, start, end, getNewIndex(index));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -451,16 +440,11 @@ public class MethodInliner {
|
||||
|
||||
if (sourceValue.insns.size() == 1) {
|
||||
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
|
||||
AbstractInsnNode processingInstruction = insnNode;
|
||||
|
||||
if (insnNode.getOpcode() == Opcodes.SWAP) {
|
||||
processingInstruction = InlineCodegenUtil.getPrevMeaningful(insnNode);
|
||||
}
|
||||
lambdaInfo = getLambdaIfExists(processingInstruction);
|
||||
lambdaInfo = getLambdaIfExists(insnNode);
|
||||
if (lambdaInfo != null) {
|
||||
//remove inlinable access
|
||||
assert processingInstruction != null;
|
||||
InlineCodegenUtil.removeInterval(node, processingInstruction, insnNode);
|
||||
node.instructions.remove(insnNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,15 +543,10 @@ public class MethodInliner {
|
||||
}
|
||||
|
||||
private boolean isAlreadyRegenerated(@NotNull String owner) {
|
||||
return inliningContext.typeRemapper.hasNoAdditionalMapping(owner);
|
||||
return inliningContext.typeMapping.containsKey(owner);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
|
||||
if (insnNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) {
|
||||
if (insnNode.getOpcode() == Opcodes.ALOAD) {
|
||||
int varIndex = ((VarInsnNode) insnNode).var;
|
||||
return getLambdaIfExists(varIndex);
|
||||
|
||||
@@ -77,11 +77,10 @@ internal class ParametersBuilder private constructor(){
|
||||
fun addCapturedParam(
|
||||
containingLambda: CapturedParamOwner,
|
||||
fieldName: String,
|
||||
newFieldName: String,
|
||||
type: Type,
|
||||
skipped: Boolean,
|
||||
original: ParameterInfo?): CapturedParamInfo {
|
||||
val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), newFieldName, skipped, nextCapturedIndex(),
|
||||
val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCapturedIndex(),
|
||||
if (original != null) original.getIndex() else -1)
|
||||
if (original != null) {
|
||||
info.setLambda(original.getLambda())
|
||||
|
||||
@@ -30,12 +30,12 @@ public class RegeneratedClassContext extends InliningContext {
|
||||
@NotNull Map<Integer, LambdaInfo> map,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull NameGenerator nameGenerator,
|
||||
@NotNull TypeRemapper typeRemapper,
|
||||
@NotNull Map<String, String> typeMapping,
|
||||
@NotNull ReifiedTypeInliner reifiedTypeInliner,
|
||||
boolean isInliningLambda,
|
||||
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
|
||||
) {
|
||||
super(parent, map, state, nameGenerator, typeRemapper, reifiedTypeInliner, isInliningLambda, true);
|
||||
super(parent, map, state, nameGenerator, typeMapping, reifiedTypeInliner, isInliningLambda, true);
|
||||
this.anonymousObjectGeneration = anonymousObjectGeneration;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,11 +51,11 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
|
||||
@Override
|
||||
public boolean canProcess(@NotNull String fieldOwner, String fieldName, boolean isFolding) {
|
||||
return super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner, isFolding);
|
||||
return super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner);
|
||||
}
|
||||
|
||||
private boolean isRecapturedLambdaType(String owner, boolean isFolding) {
|
||||
return recapturedLambdas.containsKey(owner) && (isFolding || false == parent instanceof InlinedLambdaRemapper);
|
||||
private boolean isRecapturedLambdaType(String owner) {
|
||||
return recapturedLambdas.containsKey(owner);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -79,20 +79,10 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
return super.findField(fieldInsnNode, parameters.getCaptured());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNewLambdaInternalName() {
|
||||
return newOwnerType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StackValue getFieldForInline(@NotNull FieldInsnNode node, @Nullable StackValue prefix) {
|
||||
assert node.name.startsWith("$$$") : "Captured field template should start with $$$ prefix";
|
||||
if (node.name.equals("$$$" + InlineCodegenUtil.THIS)) {
|
||||
assert oldOwnerType.equals(node.owner) : "Can't unfold '$$$THIS' parameter";
|
||||
return StackValue.LOCAL_0;
|
||||
}
|
||||
|
||||
FieldInsnNode fin = new FieldInsnNode(node.getOpcode(), node.owner, node.name.substring(3), node.desc);
|
||||
CapturedParamInfo field = findFieldInMyCaptured(fin);
|
||||
|
||||
@@ -105,9 +95,8 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
}
|
||||
}
|
||||
|
||||
StackValue result = StackValue.field(field.isSkipped ?
|
||||
Type.getObjectType(parent.parent.getNewLambdaInternalName()) : field.getType(),
|
||||
Type.getObjectType(getNewLambdaInternalName()), /*TODO owner type*/
|
||||
StackValue result = StackValue.field(field.getType(),
|
||||
Type.getObjectType(newOwnerType), /*TODO owner type*/
|
||||
field.getNewFieldName(), false,
|
||||
prefix == null ? StackValue.LOCAL_0 : prefix);
|
||||
|
||||
|
||||
@@ -18,22 +18,16 @@ package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.generateIsCheck
|
||||
import org.jetbrains.kotlin.codegen.generateNullCheckForNonSafeAs
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
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.signature.SignatureReader
|
||||
import org.jetbrains.org.objectweb.asm.signature.SignatureWriter
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
|
||||
private class ParameterNameAndNullability(val name: String, val nullable: Boolean)
|
||||
|
||||
public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParameterMappings?) {
|
||||
|
||||
companion object {
|
||||
@@ -70,23 +64,15 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE), false
|
||||
);
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun isNullableMarkerInstruction(marker: String) = INSTANCEOF_MARKER_METHOD_NAME == marker ||
|
||||
CHECKCAST_MARKER_METHOD_NAME == marker
|
||||
}
|
||||
|
||||
private var maxStackSize = 0
|
||||
|
||||
/**
|
||||
* @return set of type parameters' identifiers contained in markers that should be reified further
|
||||
* e.g. when we're generating inline function containing reified T
|
||||
* and another function containing reifiable parts is inlined into that function
|
||||
*/
|
||||
public fun reifyInstructions(node: MethodNode): ReifiedTypeParametersUsages {
|
||||
public fun reifyInstructions(instructions: InsnList): ReifiedTypeParametersUsages {
|
||||
if (parametersMapping == null) return ReifiedTypeParametersUsages()
|
||||
val instructions = node.instructions
|
||||
maxStackSize = 0
|
||||
var result = ReifiedTypeParametersUsages()
|
||||
for (insn in instructions.toArray()) {
|
||||
if (isParametrisedReifiedMarker(insn)) {
|
||||
@@ -97,7 +83,6 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
}
|
||||
}
|
||||
|
||||
node.maxStack = node.maxStack + maxStackSize
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -142,25 +127,20 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
* or null if it shouldn't
|
||||
*/
|
||||
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): String? {
|
||||
val parameter = getParameter(insn) ?: return null
|
||||
val mapping = parametersMapping?.get(parameter.name) ?: return null
|
||||
val kotlinType =
|
||||
if (isNullableMarkerInstruction(insn.name) && parameter.nullable)
|
||||
TypeUtils.makeNullable(mapping.type)
|
||||
else
|
||||
mapping.type
|
||||
|
||||
val mapping = getTypeParameterMapping(insn) ?: return null
|
||||
|
||||
val asmType = mapping.asmType
|
||||
if (asmType != null) {
|
||||
val jetType = mapping.type ?: return null
|
||||
|
||||
// process* methods return false if marker should be reified further
|
||||
// or it's invalid (may be emitted explicitly in code)
|
||||
// they return true if instruction is reified and marker can be deleted
|
||||
if (when (insn.name) {
|
||||
NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType)
|
||||
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, kotlinType, asmType, safe = false)
|
||||
SAFE_CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, kotlinType, asmType, safe = true)
|
||||
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, instructions, kotlinType, asmType)
|
||||
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, jetType, asmType, safe = false)
|
||||
SAFE_CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, jetType, asmType, safe = true)
|
||||
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, instructions, jetType, asmType)
|
||||
JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType)
|
||||
else -> false
|
||||
}) {
|
||||
@@ -170,8 +150,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
|
||||
return null
|
||||
} else {
|
||||
val nullableSuffix = if (isNullableMarkerInstruction(insn.name) && kotlinType.isMarkedNullable) "?" else ""
|
||||
instructions.set(insn.previous!!, LdcInsnNode(mapping.newName + nullableSuffix))
|
||||
instructions.set(insn.getPrevious()!!, LdcInsnNode(mapping.newName))
|
||||
return mapping.newName
|
||||
}
|
||||
}
|
||||
@@ -179,66 +158,20 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
private fun processNewArray(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY)
|
||||
|
||||
private fun processCheckcast(insn: MethodInsnNode,
|
||||
instructions: InsnList,
|
||||
jetType: KotlinType,
|
||||
asmType: Type,
|
||||
safe: Boolean) =
|
||||
private fun processCheckcast(insn: MethodInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type, safe: Boolean) =
|
||||
rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { instanceofInsn: AbstractInsnNode ->
|
||||
if (instanceofInsn !is TypeInsnNode) return false
|
||||
|
||||
addNullCheckForAsIfNeeded(insn.previous!!, instructions, jetType, safe)
|
||||
TypeIntrinsics.checkcast(instanceofInsn, instructions, jetType, asmType, safe)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun addNullCheckForAsIfNeeded(insn: AbstractInsnNode, instructions: InsnList, jetType: KotlinType, safe: Boolean) {
|
||||
if (!safe && !TypeUtils.isNullableType(jetType)) {
|
||||
val methodNode = MethodNode(InlineCodegenUtil.API)
|
||||
generateNullCheckForNonSafeAs(InstructionAdapter(methodNode), jetType)
|
||||
|
||||
InlineCodegenUtil.insertNodeBefore(methodNode, instructions, insn)
|
||||
maxStackSize = Math.max(maxStackSize, 4)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processInstanceof(insn: MethodInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type) =
|
||||
rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { instanceofInsn: AbstractInsnNode ->
|
||||
if (instanceofInsn !is TypeInsnNode) return false
|
||||
|
||||
addNullCheckForIsIfNeeded(insn, instructions, jetType)
|
||||
TypeIntrinsics.instanceOf(instanceofInsn, instructions, jetType, asmType)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun addNullCheckForIsIfNeeded(insn: AbstractInsnNode, instructions: InsnList, type: KotlinType) {
|
||||
if (TypeUtils.isNullableType(type)) {
|
||||
val instanceOf = insn.next
|
||||
insertNullCheckAround(instructions, insn.previous!!, instanceOf)
|
||||
maxStackSize = Math.max(maxStackSize, 2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun insertNullCheckAround(instructions: InsnList, start: AbstractInsnNode, end: AbstractInsnNode) {
|
||||
val methodNode = MethodNode(InlineCodegenUtil.API)
|
||||
var splitIndex: Int = -1
|
||||
generateIsCheck(InstructionAdapter(methodNode), true) {
|
||||
splitIndex = methodNode.instructions.size()
|
||||
}
|
||||
assert(splitIndex >= 0) {
|
||||
"Split index should be non-negative, but $splitIndex"
|
||||
}
|
||||
|
||||
val nullCheckInsns = methodNode.instructions.toArray()
|
||||
nullCheckInsns.take(splitIndex).forEach {
|
||||
instructions.insertBefore(start, it)
|
||||
}
|
||||
|
||||
nullCheckInsns.drop(splitIndex).reversed().forEach {
|
||||
instructions.insert(end, it)
|
||||
}
|
||||
}
|
||||
|
||||
inline private fun rewriteNextTypeInsn(
|
||||
marker: MethodInsnNode,
|
||||
expectedNextOpcode: Int,
|
||||
@@ -262,16 +195,17 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getParameter(insn: MethodInsnNode): ParameterNameAndNullability? {
|
||||
private fun getParameterName(insn: MethodInsnNode): String? {
|
||||
val prev = insn.getPrevious()!!
|
||||
|
||||
val parameterNameWithFlag = when (prev.getOpcode()) {
|
||||
return when (prev.getOpcode()) {
|
||||
Opcodes.LDC -> (prev as LdcInsnNode).cst as String
|
||||
else -> return null
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
val parameterName = if (parameterNameWithFlag.endsWith("?")) parameterNameWithFlag.dropLast(1) else parameterNameWithFlag
|
||||
return ParameterNameAndNullability(parameterName, parameterName !== parameterNameWithFlag)
|
||||
private fun getTypeParameterMapping(insn: MethodInsnNode): ReifiedTypeParameterMapping? {
|
||||
return parametersMapping?.get(getParameterName(insn) ?: return null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,17 +216,17 @@ public class ReifiedTypeParameterMappings() {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type, asmType, newName = null, signature = signature)
|
||||
}
|
||||
|
||||
public fun addParameterMappingToNewParameter(name: String, type: KotlinType, newName: String) {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type = type, asmType = null, newName = newName, signature = null)
|
||||
public fun addParameterMappingToNewParameter(name: String, newName: String) {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type = null, asmType = null, newName = newName, signature = null)
|
||||
}
|
||||
|
||||
operator fun get(name: String): ReifiedTypeParameterMapping? {
|
||||
fun get(name: String): ReifiedTypeParameterMapping? {
|
||||
return mappingsByName[name]
|
||||
}
|
||||
}
|
||||
|
||||
public class ReifiedTypeParameterMapping(
|
||||
val name: String, val type: KotlinType, val asmType: Type?, val newName: String?, val signature: String?
|
||||
val name: String, val type: KotlinType?, val asmType: Type?, val newName: String?, val signature: String?
|
||||
)
|
||||
|
||||
public class ReifiedTypeParametersUsages {
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class RootInliningContext extends InliningContext {
|
||||
@@ -37,7 +38,7 @@ public class RootInliningContext extends InliningContext {
|
||||
@NotNull String classNameToInline,
|
||||
@NotNull ReifiedTypeInliner inliner
|
||||
) {
|
||||
super(null, map, state, nameGenerator, TypeRemapper.createEmpty(), inliner, false, false);
|
||||
super(null, map, state, nameGenerator, Collections.<String, String>emptyMap(), inliner, false, false);
|
||||
this.callElement = callElement;
|
||||
this.startContext = startContext;
|
||||
this.classNameToInline = classNameToInline;
|
||||
|
||||
@@ -23,43 +23,14 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TypeRemapper extends Remapper {
|
||||
//typeMapping field could be changed outside through method processing
|
||||
private final Map<String, String> typeMapping;
|
||||
|
||||
private Map<String, String> additionalMappings;
|
||||
|
||||
//typeMapping field could be changed outside through method processing
|
||||
private TypeRemapper(@NotNull Map<String, String> typeMapping) {
|
||||
//typeMapping could be changed outside through method processing
|
||||
public TypeRemapper(@NotNull Map<String, String> typeMapping) {
|
||||
this.typeMapping = typeMapping;
|
||||
}
|
||||
|
||||
public TypeRemapper(@NotNull TypeRemapper remapper, @NotNull Map<String, String> newTypeMappings) {
|
||||
this(createNewAndMerge(remapper, newTypeMappings));
|
||||
}
|
||||
|
||||
public static TypeRemapper createEmpty() {
|
||||
return new TypeRemapper(new HashMap<String, String>());
|
||||
}
|
||||
|
||||
public static TypeRemapper createFrom(Map<String, String> mappings) {
|
||||
return new TypeRemapper(mappings);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<String, String> createNewAndMerge(@NotNull TypeRemapper remapper, @NotNull Map<String, String> additionalTypeMappings) {
|
||||
Map<String, String> map = new HashMap<String, String>(remapper.typeMapping);
|
||||
map.putAll(additionalTypeMappings);
|
||||
return map;
|
||||
}
|
||||
|
||||
public void addMapping(String type, String newType) {
|
||||
typeMapping.put(type, newType);
|
||||
}
|
||||
|
||||
public boolean hasNoAdditionalMapping(String type) {
|
||||
return typeMapping.containsKey(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String map(String type) {
|
||||
String newType = typeMapping.get(type);
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.intellij.openapi.util.Pair
|
||||
import org.jetbrains.kotlin.codegen.FieldInfo
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
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
|
||||
}.map {
|
||||
NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor)
|
||||
}
|
||||
}
|
||||
|
||||
fun transformToFieldInfo(lambdaType: Type, newFields: List<NewJavaField>): List<FieldInfo> {
|
||||
return newFields.map { field ->
|
||||
FieldInfo.createForHiddenField(lambdaType, field.type, field.name)
|
||||
}
|
||||
}
|
||||
|
||||
fun filterSkipped(fields: List<NewJavaField>): List<NewJavaField> {
|
||||
return fields.filter { !it.skip }
|
||||
}
|
||||
|
||||
fun toNameTypePair(fields: List<NewJavaField>): List<Pair<String, Type>> = fields.map { Pair(it.name, it.type) }
|
||||
@@ -17,17 +17,18 @@
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.genInvokeAppendMethod
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.genStringBuilderConstructor
|
||||
import org.jetbrains.kotlin.codegen.Callable
|
||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -40,11 +41,11 @@ public class Concat : IntrinsicMethod() {
|
||||
arguments: List<KtExpression>,
|
||||
receiver: StackValue
|
||||
): Type {
|
||||
if (element is KtBinaryExpression && element.operationReference.getReferencedNameElementType() == KtTokens.PLUS) {
|
||||
if (element is KtBinaryExpression && element.getOperationReference().getReferencedNameElementType() == KtTokens.PLUS) {
|
||||
// LHS + RHS
|
||||
genStringBuilderConstructor(v)
|
||||
codegen.invokeAppend(element.left)
|
||||
codegen.invokeAppend(element.right)
|
||||
codegen.invokeAppend(element.getLeft())
|
||||
codegen.invokeAppend(element.getRight())
|
||||
}
|
||||
else {
|
||||
// LHS?.plus(RHS)
|
||||
@@ -59,6 +60,7 @@ public class Concat : IntrinsicMethod() {
|
||||
return JAVA_STRING_TYPE
|
||||
}
|
||||
|
||||
|
||||
override fun toCallable(method: CallableMethod): Callable =
|
||||
object : IntrinsicCallable(method) {
|
||||
override fun invokeMethodWithArguments(
|
||||
@@ -66,37 +68,16 @@ public class Concat : IntrinsicMethod() {
|
||||
receiver: StackValue,
|
||||
codegen: ExpressionCodegen
|
||||
): StackValue {
|
||||
if (resolvedCall.call.callElement.parent is KtCallableReferenceExpression) {
|
||||
// NB we come here only in case of inlined callable reference to String::plus.
|
||||
// This will map arguments properly, invoking callbacks defined in Callable.
|
||||
return super.invokeMethodWithArguments(resolvedCall, receiver, codegen)
|
||||
}
|
||||
return StackValue.operation(returnType) {
|
||||
val arguments = resolvedCall.call.valueArguments.map { it.getArgumentExpression()!! }
|
||||
val arguments = resolvedCall.getCall().getValueArguments().map { it.getArgumentExpression()!! }
|
||||
val actualType = generateImpl(
|
||||
codegen, it, returnType,
|
||||
resolvedCall.call.callElement,
|
||||
resolvedCall.getCall().getCallElement(),
|
||||
arguments,
|
||||
StackValue.receiver(resolvedCall, receiver, codegen, this)
|
||||
)
|
||||
StackValue.coerce(actualType, returnType, it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
|
||||
v.dupX1()
|
||||
v.swap()
|
||||
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
|
||||
}
|
||||
|
||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||
// String::plus has type String.(Any?) -> String, thus we have no argument type information
|
||||
// in case of callable reference passed to a generic function, e.g.:
|
||||
// charArrayOf('O', 'K').fold("", String::plus)
|
||||
// TODO Make String::plus generic, and invoke proper StringBuilder#append.
|
||||
AsmUtil.genInvokeAppendMethod(v, AsmTypes.OBJECT_TYPE)
|
||||
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,17 +37,17 @@ public abstract class IntrinsicMethod {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Callable toCallable(@NotNull CallableMethod method, boolean isSuper, @NotNull ResolvedCall resolvedCall) {
|
||||
public Callable toCallable(@NotNull CallableMethod method, boolean isSuper, @NotNull ResolvedCall resolvedCall) {
|
||||
return toCallable(method, isSuper);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Callable toCallable(@NotNull CallableMethod method, boolean isSuperCall) {
|
||||
public Callable toCallable(@NotNull CallableMethod method, boolean isSuperCall) {
|
||||
return toCallable(method);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Callable toCallable(@NotNull CallableMethod method) {
|
||||
public Callable toCallable(@NotNull CallableMethod method) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.codegen.intrinsics;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import kotlin.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
@@ -27,7 +26,6 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -65,12 +63,11 @@ public class IntrinsicMethods {
|
||||
namedMethods.put("kotlin.javaClass.function", new JavaClassFunction());
|
||||
namedMethods.put("kotlin.javaClass.property", new JavaClassProperty());
|
||||
namedMethods.put("kotlin.KClass.java.property", new KClassJavaProperty());
|
||||
namedMethods.put("kotlin.arrays.array", new JavaClassArray());
|
||||
namedMethods.put("kotlin.jvm.internal.unsafe.monitorEnter", MonitorInstruction.MONITOR_ENTER);
|
||||
namedMethods.put("kotlin.jvm.internal.unsafe.monitorExit", MonitorInstruction.MONITOR_EXIT);
|
||||
namedMethods.put("kotlin.jvm.isArrayOf", new IsArrayOf());
|
||||
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOf", 1, new JavaClassArray());
|
||||
|
||||
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
|
||||
for (Name method : primitiveCastMethods) {
|
||||
String methodName = method.asString();
|
||||
@@ -97,10 +94,6 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicFunction(typeName, "equals", 1, EQUALS);
|
||||
declareIntrinsicFunction(typeName, "hashCode", 0, HASH_CODE);
|
||||
declareIntrinsicFunction(typeName, "toString", 0, TO_STRING);
|
||||
|
||||
intrinsicsMap.registerIntrinsic(
|
||||
BUILT_INS_PACKAGE_FQ_NAME, null, StringsKt.decapitalize(type.getArrayTypeName().asString()) + "Of", 1, new JavaClassArray()
|
||||
);
|
||||
}
|
||||
|
||||
declareBinaryOp("plus", IADD);
|
||||
|
||||
@@ -58,7 +58,7 @@ public class JavaClassProperty : IntrinsicPropertyGetter() {
|
||||
}
|
||||
|
||||
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
||||
val classType = codegen.getState().typeMapper.mapType(resolvedCall.getCall().getDispatchReceiver()!!.getType())
|
||||
val classType = codegen.getState().typeMapper.mapType(resolvedCall.getCall().getDispatchReceiver().getType())
|
||||
return object : IntrinsicCallable(getType(javaClass<Class<Any>>()), listOf(), classType, null) {
|
||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||
if (isPrimitive(classType)) {
|
||||
|
||||
@@ -25,15 +25,13 @@ import org.jetbrains.kotlin.psi.KtClassLiteralExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
public class KClassJavaProperty : IntrinsicPropertyGetter() {
|
||||
override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
|
||||
val extensionReceiver = resolvedCall!!.extensionReceiver as ReceiverValue
|
||||
val type = extensionReceiver.type.arguments.single().type
|
||||
val type = resolvedCall!!.extensionReceiver.type.arguments.single().type
|
||||
val asmType = codegen.state.typeMapper.mapType(type)
|
||||
|
||||
return when {
|
||||
|
||||
@@ -44,19 +44,10 @@ public class RangeTo : IntrinsicMethod() {
|
||||
nullOr(method.dispatchReceiverType, argType),
|
||||
nullOr(method.extensionReceiverType, argType)
|
||||
) {
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||
override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
|
||||
v.anew(returnType)
|
||||
when (argType.size) {
|
||||
1 -> {
|
||||
v.dupX1()
|
||||
v.swap()
|
||||
}
|
||||
2 -> {
|
||||
v.dup()
|
||||
v.dup2X2()
|
||||
v.pop2()
|
||||
}
|
||||
}
|
||||
v.dup()
|
||||
value?.moveToTopOfStack(value.type, v, 2)
|
||||
}
|
||||
|
||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||
|
||||
@@ -29,11 +29,11 @@ public class RedundantGotoMethodTransformer : MethodTransformer() {
|
||||
* Removes redundant GOTO's, i.e. to subsequent labels
|
||||
*/
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
val insns = methodNode.instructions.toArray().apply { reverse() }
|
||||
val insns = methodNode.instructions.toArray()
|
||||
val insnsToRemove = arrayListOf<AbstractInsnNode>()
|
||||
|
||||
val currentLabels = hashSetOf<LabelNode>()
|
||||
for (insn in insns) {
|
||||
for (insn in insns.reversed()) {
|
||||
if (insn.isMeaningful) {
|
||||
if (insn.getOpcode() == Opcodes.GOTO && (insn as JumpInsnNode).label in currentLabels) {
|
||||
insnsToRemove.add(insn)
|
||||
|
||||
@@ -125,7 +125,7 @@ public open class MethodAnalyzer<V : Value>(
|
||||
frames[instructions.indexOf(insn)]
|
||||
|
||||
private fun checkAssertions() {
|
||||
if (instructions.toArray().any { it.getOpcode() == Opcodes.JSR || it.getOpcode() == Opcodes.RET })
|
||||
if (instructions.toArray() any { it.getOpcode() == Opcodes.JSR || it.getOpcode() == Opcodes.RET })
|
||||
throw AssertionError("Subroutines are deprecated since Java 6")
|
||||
}
|
||||
|
||||
|
||||
@@ -91,28 +91,27 @@ public class OptimizationBasicInterpreter extends BasicInterpreter {
|
||||
public BasicValue merge(
|
||||
@NotNull BasicValue v, @NotNull BasicValue w
|
||||
) {
|
||||
if (v == BasicValue.UNINITIALIZED_VALUE || w == BasicValue.UNINITIALIZED_VALUE) {
|
||||
if (!v.equals(w)) {
|
||||
if (v == BasicValue.UNINITIALIZED_VALUE || w == BasicValue.UNINITIALIZED_VALUE) {
|
||||
return BasicValue.UNINITIALIZED_VALUE;
|
||||
}
|
||||
|
||||
// if merge of two references then `lub` is java/lang/Object
|
||||
// arrays also are BasicValues with reference type's
|
||||
if (v.getType().getSort() == Type.OBJECT && w.getType().getSort() == Type.OBJECT) {
|
||||
return BasicValue.REFERENCE_VALUE;
|
||||
}
|
||||
|
||||
assert v.getType().getSort() != Type.ARRAY && w.getType().getSort() != Type.ARRAY : "There should not be arrays";
|
||||
|
||||
// if merge of something can be stored in int var (int, char, boolean, byte, character)
|
||||
if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE &&
|
||||
w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) {
|
||||
return BasicValue.INT_VALUE;
|
||||
}
|
||||
|
||||
return BasicValue.UNINITIALIZED_VALUE;
|
||||
}
|
||||
// Objects must be equal, others can just have the same sort
|
||||
if (v.getType().getSort() == w.getType().getSort() && (v.getType().getSort() != Type.OBJECT || v.equals(w))) {
|
||||
return v;
|
||||
}
|
||||
|
||||
// if merge of two references then `lub` is java/lang/Object
|
||||
// arrays also are BasicValues with reference type's
|
||||
if (v.getType().getSort() == Type.OBJECT && w.getType().getSort() == Type.OBJECT) {
|
||||
return BasicValue.REFERENCE_VALUE;
|
||||
}
|
||||
|
||||
assert v.getType().getSort() != Type.ARRAY && w.getType().getSort() != Type.ARRAY : "There should not be arrays";
|
||||
|
||||
// if merge of something can be stored in int var (int, char, boolean, byte, character)
|
||||
if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE &&
|
||||
w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) {
|
||||
return BasicValue.INT_VALUE;
|
||||
}
|
||||
|
||||
return BasicValue.UNINITIALIZED_VALUE;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,19 +17,19 @@
|
||||
package org.jetbrains.kotlin.codegen.serialization;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import kotlin.jvm.functions.Function3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice;
|
||||
import org.jetbrains.kotlin.util.slicedMap.MutableSlicedMap;
|
||||
import org.jetbrains.kotlin.util.slicedMap.SlicedMapImpl;
|
||||
import org.jetbrains.kotlin.util.slicedMap.Slices;
|
||||
import org.jetbrains.kotlin.util.slicedMap.*;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public final class JvmSerializationBindings {
|
||||
public static final SerializationMappingSlice<FunctionDescriptor, Method> METHOD_FOR_FUNCTION =
|
||||
SerializationMappingSlice.create();
|
||||
@@ -70,7 +70,32 @@ public final class JvmSerializationBindings {
|
||||
BasicWritableSlice.initSliceDebugNames(JvmSerializationBindings.class);
|
||||
}
|
||||
|
||||
private final MutableSlicedMap map = SlicedMapImpl.create();
|
||||
private final MutableSlicedMap map;
|
||||
|
||||
private JvmSerializationBindings(@NotNull MutableSlicedMap map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public JvmSerializationBindings() {
|
||||
this(SlicedMapImpl.create());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JvmSerializationBindings union(@NotNull Collection<JvmSerializationBindings> bindings) {
|
||||
final MutableSlicedMap result = SlicedMapImpl.create();
|
||||
|
||||
for (JvmSerializationBindings binding : bindings) {
|
||||
binding.map.forEach(new Function3<WritableSlice, Object, Object, Void>() {
|
||||
@Override
|
||||
public Void invoke(WritableSlice slice, Object key, Object value) {
|
||||
result.put(slice, key, value);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new JvmSerializationBindings(result);
|
||||
}
|
||||
|
||||
public <K, V> void put(@NotNull SerializationMappingSlice<K, V> slice, @NotNull K key, @NotNull V value) {
|
||||
map.put(slice, key, value);
|
||||
|
||||
@@ -118,15 +118,6 @@ public class BothSignatureWriter {
|
||||
writeAsmType0(asmType);
|
||||
}
|
||||
|
||||
public void writeOuterClassBegin(Type resultingAsmType, String outerInternalName) {
|
||||
signatureVisitor().visitClassType(outerInternalName);
|
||||
writeAsmType0(resultingAsmType);
|
||||
}
|
||||
|
||||
public void writeInnerClass(String name) {
|
||||
signatureVisitor().visitInnerClassType(name);
|
||||
}
|
||||
|
||||
public void writeClassEnd() {
|
||||
signatureVisitor().visitEnd();
|
||||
}
|
||||
@@ -263,13 +254,13 @@ public class BothSignatureWriter {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JvmMethodSignature makeJvmMethodSignature(@NotNull String name, boolean skipGenericSignature) {
|
||||
public JvmMethodSignature makeJvmMethodSignature(@NotNull String name) {
|
||||
List<Type> types = new ArrayList<Type>(kotlinParameterTypes.size());
|
||||
for (JvmMethodParameterSignature parameter : kotlinParameterTypes) {
|
||||
types.add(parameter.getAsmType());
|
||||
}
|
||||
Method asmMethod = new Method(name, jvmReturnType, types.toArray(new Type[types.size()]));
|
||||
return new JvmMethodSignature(asmMethod, !skipGenericSignature ? makeJavaGenericSignature() : null, kotlinParameterTypes);
|
||||
return new JvmMethodSignature(asmMethod, makeJavaGenericSignature(), kotlinParameterTypes);
|
||||
}
|
||||
|
||||
public int getCurrentSignatureSize() {
|
||||
|
||||
@@ -40,10 +40,10 @@ class BuilderFactoryForDuplicateClassNameDiagnostics(
|
||||
}
|
||||
|
||||
private fun reportError(internalName: String, vararg another: JvmDeclarationOrigin) {
|
||||
val fromString = another.mapNotNull { it.descriptor }.
|
||||
val fromString = another.map { it.descriptor }.filterNotNull().
|
||||
joinToString { DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(it) }
|
||||
|
||||
another.mapNotNull { it.element }.forEach {
|
||||
another.map { it.element }.filterNotNull().forEach {
|
||||
diagnostics.report(ErrorsJvm.DUPLICATE_CLASS_NAMES.on(it, internalName, fromString))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,17 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider
|
||||
import org.jetbrains.kotlin.fileClasses.isInsideJvmMultifileClassFile
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.getParentJavaStaticClassScope
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
@@ -52,18 +56,10 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
|
||||
// Avoid errors when some classes are not loaded for some reason
|
||||
private val typeMapper = JetTypeMapper(bindingContext, ClassBuilderMode.LIGHT_CLASSES, fileClassesProvider, incrementalCache, moduleName)
|
||||
private val reportDiagnosticsTasks = ArrayList<() -> Unit>()
|
||||
|
||||
fun reportDiagnostics() {
|
||||
reportDiagnosticsTasks.forEach { it() }
|
||||
reportDiagnosticsTasks.clear()
|
||||
}
|
||||
private val mainFunctionDetector = MainFunctionDetector(bindingContext)
|
||||
|
||||
override fun handleClashingSignatures(data: ConflictingJvmDeclarationsData) {
|
||||
reportDiagnosticsTasks.add { reportConflictingJvmSignatures(data) }
|
||||
}
|
||||
|
||||
private fun reportConflictingJvmSignatures(data: ConflictingJvmDeclarationsData) {
|
||||
val noOwnImplementations = data.signatureOrigins.all { it.originKind in EXTERNAL_SOURCES_KINDS }
|
||||
|
||||
val elements = LinkedHashSet<PsiElement>()
|
||||
@@ -91,14 +87,6 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
classOrigin: JvmDeclarationOrigin,
|
||||
classInternalName: String?,
|
||||
signatures: MultiMap<RawSignature, JvmDeclarationOrigin>
|
||||
) {
|
||||
reportDiagnosticsTasks.add { reportClashingSignaturesInHierarchy(classOrigin, classInternalName, signatures) }
|
||||
}
|
||||
|
||||
private fun reportClashingSignaturesInHierarchy(
|
||||
classOrigin: JvmDeclarationOrigin,
|
||||
classInternalName: String?,
|
||||
signatures: MultiMap<RawSignature, JvmDeclarationOrigin>
|
||||
) {
|
||||
val descriptor = classOrigin.descriptor
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
@@ -114,7 +102,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
|
||||
signatures@
|
||||
for ((rawSignature, origins) in groupedBySignature.entrySet()) {
|
||||
if (origins.size <= 1) continue
|
||||
if (origins.size() <= 1) continue
|
||||
|
||||
var memberElement: PsiElement? = null
|
||||
var ownNonFakeCount = 0
|
||||
@@ -174,7 +162,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
descriptor.getParentJavaStaticClassScope()?.run {
|
||||
getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||
.filter {
|
||||
it is FunctionDescriptor && Visibilities.isVisibleWithIrrelevantReceiver(it, descriptor)
|
||||
it is FunctionDescriptor && Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, it, descriptor)
|
||||
}
|
||||
.forEach(::processMember)
|
||||
}
|
||||
@@ -182,7 +170,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
return groupedBySignature
|
||||
}
|
||||
|
||||
private fun isOrOverridesSamAdapter(descriptor: CallableMemberDescriptor): Boolean {
|
||||
public fun isOrOverridesSamAdapter(descriptor: CallableMemberDescriptor): Boolean {
|
||||
if (descriptor is SamAdapterDescriptor<*>) return true
|
||||
|
||||
return descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.`when`.MappingsClassesForWhenByEnum
|
||||
@@ -30,7 +28,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.OptimizationClassBuilderFactory
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
@@ -41,7 +38,6 @@ import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import java.io.File
|
||||
|
||||
public class GenerationState @JvmOverloads constructor(
|
||||
@@ -56,6 +52,7 @@ public class GenerationState @JvmOverloads constructor(
|
||||
disableInline: Boolean = false,
|
||||
disableOptimization: Boolean = false,
|
||||
public val useTypeTableInSerializer: Boolean = false,
|
||||
public val diagnostics: DiagnosticSink = DiagnosticSink.DO_NOTHING,
|
||||
public val packagesWithObsoleteParts: Collection<FqName> = emptySet(),
|
||||
public val obsoleteMultifileClasses: Collection<FqName> = emptySet(),
|
||||
// for PackageCodegen in incremental compilation mode
|
||||
@@ -66,20 +63,19 @@ public class GenerationState @JvmOverloads constructor(
|
||||
// TODO: get rid of it with the proper module infrastructure
|
||||
public val outDirectory: File? = null,
|
||||
public val incrementalCompilationComponents: IncrementalCompilationComponents? = null,
|
||||
public val generateOpenMultifileClasses: Boolean = false,
|
||||
public val progress: Progress = Progress.DEAF
|
||||
) {
|
||||
public abstract class GenerateClassFilter {
|
||||
public abstract fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldAnnotateClass(classOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldGenerateClass(classOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldGeneratePackagePart(jetFile: KtFile): Boolean
|
||||
public abstract fun shouldGenerateScript(script: KtScript): Boolean
|
||||
|
||||
companion object {
|
||||
public val GENERATE_ALL: GenerateClassFilter = object : GenerateClassFilter() {
|
||||
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
||||
override fun shouldAnnotateClass(classOrObject: KtClassOrObject): Boolean = true
|
||||
|
||||
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
||||
override fun shouldGenerateClass(classOrObject: KtClassOrObject): Boolean = true
|
||||
|
||||
override fun shouldGenerateScript(script: KtScript): Boolean = true
|
||||
|
||||
@@ -95,16 +91,6 @@ public class GenerationState @JvmOverloads constructor(
|
||||
incrementalCompilationComponents.getIncrementalCache(targetId)
|
||||
else null
|
||||
|
||||
private val extraJvmDiagnosticsTrace: BindingTrace = DelegatingBindingTrace(bindingContext, false, "For extra diagnostics in ${this.javaClass}")
|
||||
private val interceptedBuilderFactory: ClassBuilderFactory
|
||||
private var used = false
|
||||
|
||||
public val diagnostics: DiagnosticSink get() = extraJvmDiagnosticsTrace
|
||||
public val collectedExtraJvmDiagnostics: Diagnostics = LazyJvmDiagnostics {
|
||||
duplicateSignatureFactory.reportDiagnostics()
|
||||
extraJvmDiagnosticsTrace.bindingContext.diagnostics
|
||||
}
|
||||
|
||||
public val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
|
||||
public val classBuilderMode: ClassBuilderMode = builderFactory.getClassBuilderMode()
|
||||
public val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState")
|
||||
@@ -114,20 +100,12 @@ public class GenerationState @JvmOverloads constructor(
|
||||
public val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
|
||||
public val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
|
||||
public val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
|
||||
public var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null
|
||||
public val reflectionTypes: ReflectionTypes = ReflectionTypes(module)
|
||||
public val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes()
|
||||
public val factory: ClassFileFactory
|
||||
private val duplicateSignatureFactory: BuilderFactoryForDuplicateSignatureDiagnostics
|
||||
|
||||
public val replSpecific = ForRepl()
|
||||
|
||||
//TODO: should be refactored out
|
||||
public class ForRepl {
|
||||
public var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null
|
||||
public var scriptResultFieldName: String? = null
|
||||
public val shouldGenerateScriptResultValue: Boolean get() = scriptResultFieldName != null
|
||||
public var hasResult: Boolean = false
|
||||
}
|
||||
private val interceptedBuilderFactory: ClassBuilderFactory
|
||||
private var used = false
|
||||
|
||||
public val isCallAssertionsEnabled: Boolean = !disableCallAssertions
|
||||
@JvmName("isCallAssertionsEnabled") get
|
||||
@@ -143,13 +121,12 @@ public class GenerationState @JvmOverloads constructor(
|
||||
|
||||
init {
|
||||
val optimizationClassBuilderFactory = OptimizationClassBuilderFactory(builderFactory, disableOptimization)
|
||||
duplicateSignatureFactory = BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
var interceptedBuilderFactory: ClassBuilderFactory = BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
optimizationClassBuilderFactory, this.bindingContext, diagnostics, fileClassesProvider,
|
||||
getIncrementalCacheForThisTarget(),
|
||||
this.moduleName)
|
||||
|
||||
var interceptedBuilderFactory: ClassBuilderFactory
|
||||
= BuilderFactoryForDuplicateClassNameDiagnostics(duplicateSignatureFactory, diagnostics)
|
||||
interceptedBuilderFactory = BuilderFactoryForDuplicateClassNameDiagnostics(interceptedBuilderFactory, diagnostics);
|
||||
|
||||
val interceptExtensions = ClassBuilderInterceptorExtension.getInstances(project)
|
||||
|
||||
@@ -177,20 +154,3 @@ public class GenerationState @JvmOverloads constructor(
|
||||
interceptedBuilderFactory.close()
|
||||
}
|
||||
}
|
||||
|
||||
private class LazyJvmDiagnostics(compute: () -> Diagnostics): Diagnostics {
|
||||
private val delegate by lazy(LazyThreadSafetyMode.SYNCHRONIZED, compute)
|
||||
|
||||
override val modificationTracker: ModificationTracker
|
||||
get() = delegate.modificationTracker
|
||||
|
||||
override fun all(): Collection<Diagnostic> = delegate.all()
|
||||
|
||||
override fun forElement(psiElement: PsiElement) = delegate.forElement(psiElement)
|
||||
|
||||
override fun isEmpty() = delegate.isEmpty()
|
||||
|
||||
override fun noSuppression() = delegate.noSuppression()
|
||||
|
||||
override fun iterator() = delegate.iterator()
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.state;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.Pair;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment;
|
||||
@@ -49,7 +49,7 @@ import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteral;
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteralExpression;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
||||
@@ -111,6 +111,40 @@ public class JetTypeMapper {
|
||||
return bindingContext;
|
||||
}
|
||||
|
||||
private enum JetTypeMapperMode {
|
||||
/**
|
||||
* foo.Bar is mapped to Lfoo/Bar;
|
||||
*/
|
||||
IMPL,
|
||||
/**
|
||||
* kotlin.Int is mapped to I
|
||||
*/
|
||||
VALUE,
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
*/
|
||||
TYPE_PARAMETER,
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
* No projections allowed in immediate arguments
|
||||
*/
|
||||
SUPER_TYPE,
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* Other types mapped as VALUE
|
||||
*/
|
||||
VALUE_FOR_ANNOTATION,
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* Other types mapped as TYPE_PARAMETER
|
||||
*/
|
||||
TYPE_PARAMETER_FOR_ANNOTATION;
|
||||
|
||||
boolean isForAnnotation() {
|
||||
return this == VALUE_FOR_ANNOTATION || this == TYPE_PARAMETER_FOR_ANNOTATION;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapOwner(@NotNull DeclarationDescriptor descriptor) {
|
||||
return mapOwner(descriptor, true);
|
||||
@@ -134,6 +168,9 @@ public class JetTypeMapper {
|
||||
else if (container instanceof ClassDescriptor) {
|
||||
return mapClass((ClassDescriptor) container);
|
||||
}
|
||||
else if (container instanceof ScriptDescriptor) {
|
||||
return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
|
||||
}
|
||||
@@ -320,53 +357,42 @@ public class JetTypeMapper {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
else if (descriptor instanceof FunctionDescriptor && forceBoxedReturnType((FunctionDescriptor) descriptor)) {
|
||||
// GENERIC_TYPE is a hack to automatically box the return type
|
||||
// TYPE_PARAMETER is a hack to automatically box the return type
|
||||
//noinspection ConstantConditions
|
||||
return mapType(descriptor.getReturnType(), sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
}
|
||||
else if (DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
|
||||
//noinspection ConstantConditions
|
||||
return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
|
||||
}
|
||||
else {
|
||||
return mapType(returnType, sw, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE);
|
||||
}
|
||||
|
||||
return mapReturnType(descriptor, sw, returnType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw, @NotNull KotlinType returnType) {
|
||||
boolean isAnnotationMethod = DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration());
|
||||
TypeMappingMode typeMappingModeFromAnnotation =
|
||||
TypeMappingUtil.extractTypeMappingModeFromAnnotation(descriptor, returnType, isAnnotationMethod);
|
||||
if (typeMappingModeFromAnnotation != null) {
|
||||
return mapType(returnType, sw, typeMappingModeFromAnnotation);
|
||||
}
|
||||
|
||||
TypeMappingMode mappingMode = TypeMappingMode.getOptimalModeForReturnType(
|
||||
returnType,
|
||||
/* isAnnotationMethod = */ isAnnotationMethod);
|
||||
|
||||
return mapType(returnType, sw, mappingMode);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapType(@NotNull KotlinType jetType, @NotNull TypeMappingMode mode) {
|
||||
private Type mapType(@NotNull KotlinType jetType, @NotNull JetTypeMapperMode mode) {
|
||||
return mapType(jetType, null, mode);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapSupertype(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor) {
|
||||
return mapType(jetType, signatureVisitor, TypeMappingMode.SUPER_TYPE);
|
||||
return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapTypeParameter(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor) {
|
||||
return mapType(jetType, signatureVisitor, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
return mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapClass(@NotNull ClassifierDescriptor classifier) {
|
||||
return mapType(classifier.getDefaultType(), null, TypeMappingMode.DEFAULT);
|
||||
return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapType(@NotNull KotlinType jetType) {
|
||||
return mapType(jetType, null, TypeMappingMode.DEFAULT);
|
||||
return mapType(jetType, null, JetTypeMapperMode.VALUE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -379,9 +405,9 @@ public class JetTypeMapper {
|
||||
public JvmMethodSignature mapAnnotationParameterSignature(@NotNull PropertyDescriptor descriptor) {
|
||||
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
|
||||
sw.writeReturnType();
|
||||
mapType(descriptor.getType(), sw, TypeMappingMode.VALUE_FOR_ANNOTATION);
|
||||
mapType(descriptor.getType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
|
||||
sw.writeReturnTypeEnd();
|
||||
return sw.makeJvmMethodSignature(descriptor.getName().asString(), false);
|
||||
return sw.makeJvmMethodSignature(descriptor.getName().asString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -389,18 +415,37 @@ public class JetTypeMapper {
|
||||
return mapType(descriptor.getDefaultType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapType(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
|
||||
return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapType(
|
||||
@NotNull KotlinType jetType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull TypeMappingMode mode
|
||||
@NotNull JetTypeMapperMode kind,
|
||||
@NotNull Variance howThisTypeIsUsed
|
||||
) {
|
||||
Type builtinType = mapBuiltinType(jetType);
|
||||
Type known = mapBuiltinType(jetType);
|
||||
|
||||
if (builtinType != null) {
|
||||
Type asmType = mode.getNeedPrimitiveBoxing() ? boxType(builtinType) : builtinType;
|
||||
writeGenericType(jetType, asmType, signatureVisitor, mode);
|
||||
return asmType;
|
||||
boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
|
||||
if (known != null) {
|
||||
if (kind == JetTypeMapperMode.VALUE || kind == JetTypeMapperMode.VALUE_FOR_ANNOTATION) {
|
||||
return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
|
||||
}
|
||||
else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE ||
|
||||
kind == JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION) {
|
||||
return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, projectionsAllowed);
|
||||
}
|
||||
else if (kind == JetTypeMapperMode.IMPL) {
|
||||
// TODO: enable and fix tests
|
||||
//throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
|
||||
return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("unknown kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
TypeConstructor constructor = jetType.getConstructor();
|
||||
@@ -441,10 +486,13 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
else {
|
||||
arrayElementType = boxType(mapType(memberType, mode));
|
||||
arrayElementType = boxType(mapType(memberType, kind));
|
||||
if (signatureVisitor != null) {
|
||||
signatureVisitor.writeArrayType();
|
||||
mapType(memberType, signatureVisitor, mode.toGenericArgumentMode(memberProjection.getProjectionKind()));
|
||||
JetTypeMapperMode newMode = kind.isForAnnotation() ?
|
||||
JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION :
|
||||
JetTypeMapperMode.TYPE_PARAMETER;
|
||||
mapType(memberType, signatureVisitor, newMode, memberProjection.getProjectionKind());
|
||||
signatureVisitor.writeArrayEnd();
|
||||
}
|
||||
}
|
||||
@@ -453,15 +501,15 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
Type asmType = mode.isForAnnotationParameter() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
|
||||
Type asmType = kind.isForAnnotation() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
|
||||
AsmTypes.JAVA_CLASS_TYPE :
|
||||
computeAsmType((ClassDescriptor) descriptor.getOriginal());
|
||||
writeGenericType(jetType, asmType, signatureVisitor, mode);
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
|
||||
return asmType;
|
||||
}
|
||||
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
Type type = mapType(getRepresentativeUpperBound((TypeParameterDescriptor) descriptor), mode);
|
||||
Type type = mapType(getRepresentativeUpperBound((TypeParameterDescriptor) descriptor), kind);
|
||||
if (signatureVisitor != null) {
|
||||
signatureVisitor.writeTypeVariable(descriptor.getName(), type);
|
||||
}
|
||||
@@ -531,6 +579,10 @@ public class JetTypeMapper {
|
||||
return fqName.isRoot() ? name : fqName.asString().replace('.', '/') + '/' + name;
|
||||
}
|
||||
|
||||
if (container instanceof ScriptDescriptor) {
|
||||
return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container).getInternalName() + "$" + name;
|
||||
}
|
||||
|
||||
assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
|
||||
|
||||
String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container);
|
||||
@@ -574,144 +626,71 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
private void writeGenericType(
|
||||
@NotNull KotlinType type,
|
||||
@NotNull Type asmType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull TypeMappingMode mode
|
||||
BothSignatureWriter signatureVisitor,
|
||||
Type asmType,
|
||||
KotlinType jetType,
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
|
||||
// Nothing mapping rules:
|
||||
// Map<Nothing, Foo> -> Map
|
||||
// Map<Foo, List<Nothing>> -> Map<Foo, List>
|
||||
// In<Nothing, Foo> == In<*, Foo> -> In<?, Foo>
|
||||
// In<Nothing, Nothing> -> In
|
||||
// Inv<in Nothing, Foo> -> Inv
|
||||
if (hasNothingInNonContravariantPosition(type) || type.getArguments().isEmpty()) {
|
||||
if (hasNothingInArguments(jetType)) {
|
||||
signatureVisitor.writeAsmType(asmType);
|
||||
return;
|
||||
}
|
||||
|
||||
PossiblyInnerType possiblyInnerType = TypeParameterUtilsKt.buildPossiblyInnerType(type);
|
||||
assert possiblyInnerType != null : "possiblyInnerType with arguments should not be null";
|
||||
signatureVisitor.writeClassBegin(asmType);
|
||||
|
||||
List<PossiblyInnerType> innerTypesAsList = possiblyInnerType.segments();
|
||||
PossiblyInnerType outermostInnerType = innerTypesAsList.get(0);
|
||||
ClassDescriptor outermostClass = outermostInnerType.getClassDescriptor();
|
||||
List<TypeProjection> arguments = jetType.getArguments();
|
||||
for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
|
||||
TypeProjection argument = arguments.get(parameter.getIndex());
|
||||
|
||||
if (innerTypesAsList.size() == 1) {
|
||||
signatureVisitor.writeClassBegin(asmType);
|
||||
if (projectionsAllowed && argument.isStarProjection()) {
|
||||
signatureVisitor.writeUnboundedWildcard();
|
||||
}
|
||||
else {
|
||||
Variance projectionKind = projectionsAllowed
|
||||
? getEffectiveVariance(
|
||||
parameter.getVariance(),
|
||||
argument.getProjectionKind(),
|
||||
howThisTypeIsUsed
|
||||
)
|
||||
: Variance.INVARIANT;
|
||||
signatureVisitor.writeTypeArgument(projectionKind);
|
||||
|
||||
mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
signatureVisitor.writeTypeArgumentEnd();
|
||||
}
|
||||
}
|
||||
else {
|
||||
signatureVisitor.writeOuterClassBegin(
|
||||
asmType,
|
||||
mapType(outermostClass.getDefaultType()).getInternalName());
|
||||
}
|
||||
|
||||
writeGenericArguments(
|
||||
signatureVisitor,
|
||||
outermostInnerType.getArguments(), outermostClass.getDeclaredTypeParameters(), mode);
|
||||
|
||||
for (PossiblyInnerType innerPart : innerTypesAsList.subList(1, innerTypesAsList.size())) {
|
||||
ClassDescriptor classDescriptor = innerPart.getClassDescriptor();
|
||||
signatureVisitor.writeInnerClass(getJvmShortName(classDescriptor));
|
||||
writeGenericArguments(
|
||||
signatureVisitor, innerPart.getArguments(),
|
||||
classDescriptor.getDeclaredTypeParameters(), mode);
|
||||
}
|
||||
|
||||
signatureVisitor.writeClassEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getJvmShortName(@NotNull ClassDescriptor klass) {
|
||||
ClassId classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(DescriptorUtils.getFqName(klass));
|
||||
if (classId != null) {
|
||||
return classId.getShortClassName().asString();
|
||||
}
|
||||
|
||||
return SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
|
||||
}
|
||||
|
||||
private void writeGenericArguments(
|
||||
@NotNull BothSignatureWriter signatureVisitor,
|
||||
@NotNull List<? extends TypeProjection> arguments,
|
||||
@NotNull List<? extends TypeParameterDescriptor> parameters,
|
||||
@NotNull TypeMappingMode mode
|
||||
) {
|
||||
for (Pair<? extends TypeParameterDescriptor, ? extends TypeProjection> item : CollectionsKt.zip(parameters, arguments)) {
|
||||
TypeParameterDescriptor parameter = item.getFirst();
|
||||
TypeProjection argument = item.getSecond();
|
||||
|
||||
if (
|
||||
argument.isStarProjection() ||
|
||||
// In<Nothing, Foo> == In<*, Foo> -> In<?, Foo>
|
||||
KotlinBuiltIns.isNothing(argument.getType()) && parameter.getVariance() == Variance.IN_VARIANCE
|
||||
) {
|
||||
signatureVisitor.writeUnboundedWildcard();
|
||||
private static boolean hasNothingInArguments(KotlinType jetType) {
|
||||
boolean hasNothingInArguments = CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(TypeProjection projection) {
|
||||
return KotlinBuiltIns.isNothingOrNullableNothing(projection.getType());
|
||||
}
|
||||
else {
|
||||
TypeMappingMode argumentMode = TypeMappingUtil.updateArgumentModeFromAnnotations(mode, argument.getType());
|
||||
Variance projectionKind = getVarianceForWildcard(parameter, argument, argumentMode);
|
||||
});
|
||||
|
||||
signatureVisitor.writeTypeArgument(projectionKind);
|
||||
if (hasNothingInArguments) return true;
|
||||
|
||||
mapType(argument.getType(), signatureVisitor,
|
||||
argumentMode.toGenericArgumentMode(
|
||||
TypeMappingUtil.getEffectiveVariance(parameter.getVariance(), argument.getProjectionKind())));
|
||||
|
||||
signatureVisitor.writeTypeArgumentEnd();
|
||||
return CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(TypeProjection projection) {
|
||||
return !projection.isStarProjection() && hasNothingInArguments(projection.getType());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean hasNothingInNonContravariantPosition(KotlinType kotlinType) {
|
||||
List<TypeParameterDescriptor> parameters = kotlinType.getConstructor().getParameters();
|
||||
List<TypeProjection> arguments = kotlinType.getArguments();
|
||||
private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
|
||||
// Return type must not contain wildcards
|
||||
if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
|
||||
|
||||
for (int i = 0; i < arguments.size(); i++) {
|
||||
TypeProjection projection = arguments.get(i);
|
||||
|
||||
if (projection.isStarProjection()) continue;
|
||||
|
||||
KotlinType type = projection.getType();
|
||||
|
||||
if (KotlinBuiltIns.isNullableNothing(type) ||
|
||||
KotlinBuiltIns.isNothing(type) && parameters.get(i).getVariance() != Variance.IN_VARIANCE) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Variance getVarianceForWildcard(
|
||||
@NotNull TypeParameterDescriptor parameter,
|
||||
@NotNull TypeProjection projection,
|
||||
@NotNull TypeMappingMode mode
|
||||
) {
|
||||
Variance projectionKind = projection.getProjectionKind();
|
||||
|
||||
if (mode.getSkipDeclarationSiteWildcards() && projectionKind == Variance.INVARIANT) {
|
||||
return Variance.INVARIANT;
|
||||
}
|
||||
|
||||
Variance parameterVariance = parameter.getVariance();
|
||||
if (parameterVariance == Variance.INVARIANT) {
|
||||
return projectionKind;
|
||||
}
|
||||
|
||||
if (projectionKind == Variance.INVARIANT) {
|
||||
if (mode.getSkipDeclarationSiteWildcardsIfPossible() && !projection.isStarProjection()) {
|
||||
if (parameterVariance == Variance.OUT_VARIANCE && TypeMappingUtil.isMostPreciseCovariantArgument(projection.getType())){
|
||||
return Variance.INVARIANT;
|
||||
}
|
||||
|
||||
if (parameterVariance == Variance.IN_VARIANCE
|
||||
&& TypeMappingUtil.isMostPreciseContravariantArgument(projection.getType(), parameter)) {
|
||||
return Variance.INVARIANT;
|
||||
}
|
||||
}
|
||||
return parameterVariance;
|
||||
}
|
||||
if (parameterVariance == projectionKind) {
|
||||
@@ -723,13 +702,39 @@ public class JetTypeMapper {
|
||||
return Variance.OUT_VARIANCE;
|
||||
}
|
||||
|
||||
private Type mapKnownAsmType(
|
||||
KotlinType jetType,
|
||||
Type asmType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull Variance howThisTypeIsUsed
|
||||
) {
|
||||
return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, true);
|
||||
}
|
||||
|
||||
private Type mapKnownAsmType(
|
||||
KotlinType jetType,
|
||||
Type asmType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull Variance howThisTypeIsUsed,
|
||||
boolean allowProjections
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
if (jetType.getArguments().isEmpty()) {
|
||||
signatureVisitor.writeAsmType(asmType);
|
||||
}
|
||||
else {
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
|
||||
}
|
||||
}
|
||||
return asmType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CallableMethod mapToCallableMethod(@NotNull FunctionDescriptor descriptor, boolean superCall) {
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
JvmMethodSignature method = mapSignature(descriptor);
|
||||
Type owner = mapClass(((ConstructorDescriptor) descriptor).getContainingDeclaration());
|
||||
String defaultImplDesc = mapDefaultMethod(descriptor, OwnerKind.IMPLEMENTATION).getDescriptor();
|
||||
return new CallableMethod(owner, owner, defaultImplDesc, method, INVOKESPECIAL, null, null, null);
|
||||
return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
|
||||
}
|
||||
|
||||
DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
|
||||
@@ -739,7 +744,7 @@ public class JetTypeMapper {
|
||||
JvmMethodSignature signature;
|
||||
Type owner;
|
||||
Type ownerForDefaultImpl;
|
||||
FunctionDescriptor baseMethodDescriptor;
|
||||
Type ownerForDefaultParam;
|
||||
int invokeOpcode;
|
||||
Type thisClass;
|
||||
|
||||
@@ -754,11 +759,11 @@ public class JetTypeMapper {
|
||||
|
||||
boolean isInterface = currentIsInterface && originalIsInterface;
|
||||
|
||||
baseMethodDescriptor = findBaseDeclaration(functionDescriptor).getOriginal();
|
||||
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
|
||||
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
|
||||
ClassDescriptor ownerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
|
||||
ownerForDefaultParam = mapClass(ownerForDefault);
|
||||
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : ownerForDefaultParam;
|
||||
|
||||
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE || isAccessor(descriptor))) {
|
||||
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE)) {
|
||||
thisClass = mapClass(currentOwner);
|
||||
if (declarationOwner instanceof JavaClassDescriptor) {
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
@@ -788,7 +793,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
FunctionDescriptor overriddenSpecialBuiltinFunction =
|
||||
SpecialBuiltinMembers.<FunctionDescriptor>getOverriddenBuiltinReflectingJvmDescriptor(functionDescriptor.getOriginal());
|
||||
SpecialBuiltinMembers.<FunctionDescriptor>getOverriddenBuiltinWithDifferentJvmDescriptor(functionDescriptor.getOriginal());
|
||||
FunctionDescriptor functionToCall = overriddenSpecialBuiltinFunction != null && !superCall
|
||||
? overriddenSpecialBuiltinFunction.getOriginal()
|
||||
: functionDescriptor.getOriginal();
|
||||
@@ -805,8 +810,8 @@ public class JetTypeMapper {
|
||||
else {
|
||||
signature = mapSignature(functionDescriptor.getOriginal());
|
||||
owner = mapOwner(functionDescriptor);
|
||||
ownerForDefaultParam = owner;
|
||||
ownerForDefaultImpl = owner;
|
||||
baseMethodDescriptor = functionDescriptor;
|
||||
if (functionParent instanceof PackageFragmentDescriptor) {
|
||||
invokeOpcode = INVOKESTATIC;
|
||||
thisClass = null;
|
||||
@@ -831,11 +836,8 @@ public class JetTypeMapper {
|
||||
else {
|
||||
receiverParameterType = null;
|
||||
}
|
||||
|
||||
String defaultImplDesc = mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)).getDescriptor();
|
||||
|
||||
return new CallableMethod(
|
||||
owner, ownerForDefaultImpl, defaultImplDesc, signature, invokeOpcode,
|
||||
owner, ownerForDefaultImpl, ownerForDefaultParam, signature, invokeOpcode,
|
||||
thisClass, receiverParameterType, calleeType);
|
||||
}
|
||||
|
||||
@@ -898,7 +900,7 @@ public class JetTypeMapper {
|
||||
PsiElement element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor);
|
||||
if (element instanceof KtFunctionLiteral) {
|
||||
PsiElement expression = element.getParent();
|
||||
if (expression instanceof KtLambdaExpression) {
|
||||
if (expression instanceof KtFunctionLiteralExpression) {
|
||||
SamType samType = bindingContext.get(SAM_VALUE, (KtExpression) expression);
|
||||
if (samType != null) {
|
||||
return samType.getAbstractMethod().getName().asString();
|
||||
@@ -916,18 +918,6 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static OwnerKind getKindForDefaultImplCall(@NotNull FunctionDescriptor baseMethodDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = baseMethodDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||
return OwnerKind.PACKAGE;
|
||||
}
|
||||
else if (isInterface(containingDeclaration)) {
|
||||
return OwnerKind.DEFAULT_IMPLS;
|
||||
}
|
||||
return OwnerKind.IMPLEMENTATION;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String mapDefaultFieldName(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegated) {
|
||||
String name;
|
||||
@@ -967,7 +957,7 @@ public class JetTypeMapper {
|
||||
public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
|
||||
if (f.getInitialSignatureDescriptor() != null && f != f.getInitialSignatureDescriptor()) {
|
||||
// Overrides of special builtin in Kotlin classes always have special signature
|
||||
if (SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(f) == null ||
|
||||
if (SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(f) == null ||
|
||||
f.getContainingDeclaration().getOriginal() instanceof JavaClassDescriptor) {
|
||||
return mapSignature(f.getInitialSignatureDescriptor(), kind);
|
||||
}
|
||||
@@ -993,7 +983,7 @@ public class JetTypeMapper {
|
||||
writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
|
||||
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
writeParameter(sw, parameter.getType(), f);
|
||||
writeParameter(sw, parameter.getType());
|
||||
}
|
||||
|
||||
if (f instanceof AccessorForConstructorDescriptor) {
|
||||
@@ -1010,12 +1000,12 @@ public class JetTypeMapper {
|
||||
|
||||
ReceiverParameterDescriptor receiverParameter = f.getExtensionReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType(), f);
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType());
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
if (writeCustomParameter(f, parameter, sw)) continue;
|
||||
writeParameter(sw, parameter.getType(), f);
|
||||
writeParameter(sw, parameter.getType());
|
||||
}
|
||||
|
||||
sw.writeReturnType();
|
||||
@@ -1023,15 +1013,15 @@ public class JetTypeMapper {
|
||||
sw.writeReturnTypeEnd();
|
||||
}
|
||||
|
||||
JvmMethodSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f), f instanceof AccessorForCallableDescriptor);
|
||||
JvmMethodSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f));
|
||||
|
||||
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS) {
|
||||
SpecialSignatureInfo specialSignatureInfo = BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo(f);
|
||||
|
||||
if (specialSignatureInfo != null) {
|
||||
String newGenericSignature = CodegenUtilKt.replaceValueParametersIn(
|
||||
specialSignatureInfo, signature.getGenericsSignature());
|
||||
return new JvmMethodSignature(signature.getAsmMethod(), newGenericSignature, signature.getValueParameters());
|
||||
return new JvmMethodSignature(
|
||||
signature.getAsmMethod(), specialSignatureInfo.getSignature(), signature.getValueParameters());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1049,7 +1039,7 @@ public class JetTypeMapper {
|
||||
if (SpecialBuiltinMembers.isFromJavaOrBuiltins(f)) return false;
|
||||
|
||||
if (overridden.getName().asString().equals("remove") && mapType(parameter.getType()).getSort() == Type.INT) {
|
||||
writeParameter(sw, TypeUtils.makeNullable(parameter.getType()), f);
|
||||
writeParameter(sw, TypeUtils.makeNullable(parameter.getType()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1057,7 +1047,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
|
||||
public static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
|
||||
String descriptor = method.getDescriptor();
|
||||
int argumentsCount = Type.getArgumentTypes(descriptor).length;
|
||||
if (isExtension) {
|
||||
@@ -1122,16 +1112,9 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String mapFieldSignature(@NotNull KotlinType backingFieldType, @NotNull PropertyDescriptor propertyDescriptor) {
|
||||
public String mapFieldSignature(@NotNull KotlinType backingFieldType) {
|
||||
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
|
||||
|
||||
if (!propertyDescriptor.isVar()) {
|
||||
mapReturnType(propertyDescriptor, sw, backingFieldType);
|
||||
}
|
||||
else {
|
||||
writeParameterType(sw, backingFieldType, propertyDescriptor);
|
||||
}
|
||||
|
||||
mapType(backingFieldType, sw, JetTypeMapperMode.VALUE);
|
||||
return sw.makeJavaGenericSignature();
|
||||
}
|
||||
|
||||
@@ -1149,7 +1132,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
else return;
|
||||
|
||||
writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType(), descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1183,7 +1166,7 @@ public class JetTypeMapper {
|
||||
for (KotlinType jetType : typeParameterDescriptor.getUpperBounds()) {
|
||||
if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
|
||||
if (!isJvmInterface(jetType)) {
|
||||
mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
break classBound;
|
||||
}
|
||||
}
|
||||
@@ -1201,13 +1184,13 @@ public class JetTypeMapper {
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
if (isJvmInterface(jetType)) {
|
||||
sw.writeInterfaceBound();
|
||||
mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
sw.writeInterfaceBoundEnd();
|
||||
}
|
||||
}
|
||||
else if (classifier instanceof TypeParameterDescriptor) {
|
||||
sw.writeInterfaceBound();
|
||||
mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
sw.writeInterfaceBoundEnd();
|
||||
}
|
||||
else {
|
||||
@@ -1216,50 +1199,16 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeParameter(
|
||||
@NotNull BothSignatureWriter sw,
|
||||
@NotNull KotlinType type,
|
||||
@Nullable CallableDescriptor callableDescriptor
|
||||
) {
|
||||
writeParameter(sw, JvmMethodParameterKind.VALUE, type, callableDescriptor);
|
||||
private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull KotlinType type) {
|
||||
writeParameter(sw, JvmMethodParameterKind.VALUE, type);
|
||||
}
|
||||
|
||||
private void writeParameter(
|
||||
@NotNull BothSignatureWriter sw,
|
||||
@NotNull JvmMethodParameterKind kind,
|
||||
@NotNull KotlinType type,
|
||||
@Nullable CallableDescriptor callableDescriptor
|
||||
) {
|
||||
private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull KotlinType type) {
|
||||
sw.writeParameterType(kind);
|
||||
|
||||
writeParameterType(sw, type, callableDescriptor);
|
||||
|
||||
mapType(type, sw, JetTypeMapperMode.VALUE);
|
||||
sw.writeParameterTypeEnd();
|
||||
}
|
||||
|
||||
private void writeParameterType(
|
||||
@NotNull BothSignatureWriter sw,
|
||||
@NotNull KotlinType type,
|
||||
@Nullable CallableDescriptor callableDescriptor
|
||||
) {
|
||||
TypeMappingMode typeMappingMode;
|
||||
|
||||
TypeMappingMode typeMappingModeFromAnnotation =
|
||||
TypeMappingUtil.extractTypeMappingModeFromAnnotation(callableDescriptor, type, /* isForAnnotationParameter = */ false);
|
||||
|
||||
if (typeMappingModeFromAnnotation != null) {
|
||||
typeMappingMode = typeMappingModeFromAnnotation;
|
||||
}
|
||||
else if (TypeMappingUtil.isMethodWithDeclarationSiteWildcards(callableDescriptor) && !type.getArguments().isEmpty()) {
|
||||
typeMappingMode = TypeMappingMode.GENERIC_ARGUMENT; // Render all wildcards
|
||||
}
|
||||
else {
|
||||
typeMappingMode = TypeMappingMode.getOptimalModeForValueParameter(type);
|
||||
}
|
||||
|
||||
mapType(type, sw, typeMappingMode);
|
||||
}
|
||||
|
||||
private static void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull Type type) {
|
||||
sw.writeParameterType(kind);
|
||||
sw.writeAsmType(type);
|
||||
@@ -1271,20 +1220,18 @@ public class JetTypeMapper {
|
||||
|
||||
ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
|
||||
if (captureThis != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType());
|
||||
}
|
||||
|
||||
KotlinType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
|
||||
if (captureReceiverType != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType, descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType);
|
||||
}
|
||||
|
||||
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
|
||||
writeParameter(
|
||||
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor);
|
||||
writeParameter(
|
||||
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType(), descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType());
|
||||
writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType());
|
||||
}
|
||||
|
||||
if (closure == null) return;
|
||||
@@ -1380,16 +1327,18 @@ public class JetTypeMapper {
|
||||
sw.writeParametersStart();
|
||||
|
||||
for (ScriptDescriptor importedScript : importedScripts) {
|
||||
writeParameter(sw, importedScript.getDefaultType(), /* callableDescriptor = */ null);
|
||||
ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
|
||||
assert descriptor != null : "Script not found: " + importedScript;
|
||||
writeParameter(sw, descriptor.getDefaultType());
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
|
||||
writeParameter(sw, valueParameter.getType(), /* callableDescriptor = */ null);
|
||||
for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) {
|
||||
writeParameter(sw, valueParameter.getType());
|
||||
}
|
||||
|
||||
writeVoidReturn(sw);
|
||||
|
||||
return sw.makeJvmMethodSignature("<init>", false);
|
||||
return sw.makeJvmMethodSignature("<init>");
|
||||
}
|
||||
|
||||
public Type getSharedVarType(DeclarationDescriptor descriptor) {
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
internal class TypeMappingMode private constructor(
|
||||
val needPrimitiveBoxing: Boolean = true,
|
||||
val isForAnnotationParameter: Boolean = false,
|
||||
// Here DeclarationSiteWildcards means wildcard generated because of declaration-site variance
|
||||
val skipDeclarationSiteWildcards: Boolean = false,
|
||||
val skipDeclarationSiteWildcardsIfPossible: Boolean = false,
|
||||
private val genericArgumentMode: TypeMappingMode? = null,
|
||||
private val genericContravariantArgumentMode: TypeMappingMode? = genericArgumentMode,
|
||||
private val genericInvariantArgumentMode: TypeMappingMode? = genericArgumentMode
|
||||
) {
|
||||
companion object {
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
*/
|
||||
@JvmField
|
||||
val GENERIC_ARGUMENT = TypeMappingMode()
|
||||
|
||||
/**
|
||||
* kotlin.Int is mapped to I
|
||||
*/
|
||||
@JvmField
|
||||
val DEFAULT = TypeMappingMode(genericArgumentMode = GENERIC_ARGUMENT, needPrimitiveBoxing = false)
|
||||
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
* No projections allowed in immediate arguments
|
||||
*/
|
||||
@JvmField
|
||||
val SUPER_TYPE = TypeMappingMode(skipDeclarationSiteWildcards = true, genericArgumentMode = GENERIC_ARGUMENT)
|
||||
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* Other types mapped as DEFAULT
|
||||
*/
|
||||
@JvmField
|
||||
val VALUE_FOR_ANNOTATION = TypeMappingMode(
|
||||
isForAnnotationParameter = true,
|
||||
needPrimitiveBoxing = false,
|
||||
genericArgumentMode = TypeMappingMode(isForAnnotationParameter = true, genericArgumentMode = GENERIC_ARGUMENT))
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun getOptimalModeForValueParameter(
|
||||
type: KotlinType
|
||||
) = getOptimalModeForSignaturePart(type, isForAnnotationParameter = false, canBeUsedInSupertypePosition = true)
|
||||
|
||||
@JvmStatic
|
||||
fun getOptimalModeForReturnType(
|
||||
type: KotlinType,
|
||||
isAnnotationMethod: Boolean
|
||||
) = getOptimalModeForSignaturePart(type, isForAnnotationParameter = isAnnotationMethod, canBeUsedInSupertypePosition = false)
|
||||
|
||||
private fun getOptimalModeForSignaturePart(
|
||||
type: KotlinType,
|
||||
isForAnnotationParameter: Boolean,
|
||||
canBeUsedInSupertypePosition: Boolean
|
||||
): TypeMappingMode {
|
||||
if (type.arguments.isEmpty()) return DEFAULT
|
||||
|
||||
val contravariantArgumentMode =
|
||||
if (!canBeUsedInSupertypePosition)
|
||||
TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = false,
|
||||
skipDeclarationSiteWildcardsIfPossible = true)
|
||||
else
|
||||
null
|
||||
|
||||
val invariantArgumentMode =
|
||||
if (canBeUsedInSupertypePosition)
|
||||
getOptimalModeForSignaturePart(type, isForAnnotationParameter, canBeUsedInSupertypePosition = false)
|
||||
else
|
||||
null
|
||||
|
||||
return TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = !canBeUsedInSupertypePosition,
|
||||
skipDeclarationSiteWildcardsIfPossible = true,
|
||||
genericContravariantArgumentMode = contravariantArgumentMode,
|
||||
genericInvariantArgumentMode = invariantArgumentMode)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createWithConstantDeclarationSiteWildcardsMode(
|
||||
skipDeclarationSiteWildcards: Boolean,
|
||||
isForAnnotationParameter: Boolean,
|
||||
fallbackMode: TypeMappingMode? = null
|
||||
) = TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = skipDeclarationSiteWildcards,
|
||||
genericArgumentMode = fallbackMode)
|
||||
}
|
||||
|
||||
fun toGenericArgumentMode(effectiveVariance: Variance): TypeMappingMode =
|
||||
when (effectiveVariance) {
|
||||
Variance.IN_VARIANCE -> genericContravariantArgumentMode ?: this
|
||||
Variance.INVARIANT -> genericInvariantArgumentMode ?: this
|
||||
else -> genericArgumentMode ?: this
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:JvmName("TypeMappingUtil")
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
fun KotlinType.isMostPreciseContravariantArgument(parameter: TypeParameterDescriptor): Boolean =
|
||||
// TODO: probably class upper bound should be used
|
||||
KotlinBuiltIns.isAnyOrNullableAny(this)
|
||||
|
||||
fun KotlinType.isMostPreciseCovariantArgument(): Boolean = !canHaveSubtypesIgnoringNullability()
|
||||
|
||||
private fun KotlinType.canHaveSubtypesIgnoringNullability(): Boolean {
|
||||
val constructor = constructor
|
||||
val descriptor = constructor.declarationDescriptor
|
||||
|
||||
when (descriptor) {
|
||||
is TypeParameterDescriptor -> return true
|
||||
is ClassDescriptor -> if (!descriptor.isFinalClass) return true
|
||||
}
|
||||
|
||||
for ((parameter, argument) in constructor.parameters.zip(arguments)) {
|
||||
if (argument.isStarProjection) return true
|
||||
val projectionKind = argument.projectionKind
|
||||
val type = argument.type
|
||||
|
||||
val effectiveVariance = getEffectiveVariance(parameter.variance, projectionKind)
|
||||
if (effectiveVariance == Variance.OUT_VARIANCE && !type.isMostPreciseCovariantArgument()) return true
|
||||
if (effectiveVariance == Variance.IN_VARIANCE && !type.isMostPreciseContravariantArgument(parameter)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public fun getEffectiveVariance(parameterVariance: Variance, projectionKind: Variance): Variance {
|
||||
if (parameterVariance === Variance.INVARIANT) {
|
||||
return projectionKind
|
||||
}
|
||||
if (projectionKind === Variance.INVARIANT) {
|
||||
return parameterVariance
|
||||
}
|
||||
if (parameterVariance === projectionKind) {
|
||||
return parameterVariance
|
||||
}
|
||||
|
||||
// In<out X> = In<*>
|
||||
// Out<in X> = Out<*>
|
||||
return Variance.OUT_VARIANCE
|
||||
}
|
||||
|
||||
val CallableDescriptor?.isMethodWithDeclarationSiteWildcards: Boolean
|
||||
get() {
|
||||
if (this !is CallableMemberDescriptor) return false
|
||||
return firstOverridden {
|
||||
METHODS_WITH_DECLARATION_SITE_WILDCARDS.containsRaw(it.propertyIfAccessor.fqNameOrNull())
|
||||
} != null
|
||||
}
|
||||
|
||||
private val METHODS_WITH_DECLARATION_SITE_WILDCARDS = setOf(
|
||||
FqName("kotlin.MutableCollection.addAll"),
|
||||
FqName("kotlin.MutableList.addAll"),
|
||||
FqName("kotlin.MutableMap.putAll")
|
||||
)
|
||||
|
||||
internal fun TypeMappingMode.updateArgumentModeFromAnnotations(type: KotlinType): TypeMappingMode {
|
||||
type.suppressWildcardsMode()?.let {
|
||||
return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
|
||||
skipDeclarationSiteWildcards = it, isForAnnotationParameter = isForAnnotationParameter)
|
||||
}
|
||||
|
||||
if (type.annotations.hasAnnotation(JVM_WILDCARD_ANNOTATION_FQ_NAME)) {
|
||||
return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
|
||||
skipDeclarationSiteWildcards = false, isForAnnotationParameter = isForAnnotationParameter, fallbackMode = this)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
internal fun extractTypeMappingModeFromAnnotation(
|
||||
callableDescriptor: CallableDescriptor?,
|
||||
outerType: KotlinType,
|
||||
isForAnnotationParameter: Boolean
|
||||
): TypeMappingMode? =
|
||||
(outerType.suppressWildcardsMode() ?: callableDescriptor?.suppressWildcardsMode())?.let {
|
||||
if (outerType.arguments.isNotEmpty())
|
||||
TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
|
||||
skipDeclarationSiteWildcards = it, isForAnnotationParameter = isForAnnotationParameter)
|
||||
else
|
||||
TypeMappingMode.DEFAULT
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.suppressWildcardsMode(): Boolean? =
|
||||
parentsWithSelf.mapNotNull {
|
||||
it.annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME)
|
||||
}.firstOrNull().suppressWildcardsMode()
|
||||
|
||||
private fun KotlinType.suppressWildcardsMode(): Boolean? =
|
||||
annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME).suppressWildcardsMode()
|
||||
|
||||
private fun AnnotationDescriptor?.suppressWildcardsMode(): Boolean? {
|
||||
return (this ?: return null).allValueArguments.values.firstOrNull()?.value as? Boolean ?: true
|
||||
}
|
||||
|
||||
private val JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmSuppressWildcards")
|
||||
private val JVM_WILDCARD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmWildcard")
|
||||
@@ -47,7 +47,7 @@ public class MappingClassesForWhenByEnumCodegen {
|
||||
cb.defineClass(
|
||||
srcFile,
|
||||
V1_6,
|
||||
ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_SYNTHETIC,
|
||||
ACC_FINAL | ACC_SYNTHETIC | ACC_PUBLIC,
|
||||
mappingsClass.getInternalName(),
|
||||
null,
|
||||
OBJECT_TYPE.getInternalName(),
|
||||
|
||||
@@ -132,18 +132,24 @@ public class BuiltInsSerializer(private val dependOnOldBuiltIns: Boolean) {
|
||||
val fragments = packageView.fragments
|
||||
val packageProto = DescriptorSerializer.createTopLevel(extension).packageProto(fragments).build()
|
||||
packageProto.writeTo(packageStream)
|
||||
write(destDir, BuiltInsSerializedResourcePaths.getPackageFilePath(fqName), packageStream)
|
||||
write(destDir, BuiltInsSerializedResourcePaths.getPackageFilePath(fqName), packageStream,
|
||||
BuiltInsSerializedResourcePaths.fallbackPaths.getPackageFilePath(fqName))
|
||||
|
||||
val nameStream = ByteArrayOutputStream()
|
||||
extension.stringTable.serializeTo(nameStream)
|
||||
write(destDir, BuiltInsSerializedResourcePaths.getStringTableFilePath(fqName), nameStream)
|
||||
write(destDir, BuiltInsSerializedResourcePaths.getStringTableFilePath(fqName), nameStream,
|
||||
BuiltInsSerializedResourcePaths.fallbackPaths.getStringTableFilePath(fqName))
|
||||
}
|
||||
|
||||
private fun write(destDir: File, fileName: String, stream: ByteArrayOutputStream) {
|
||||
private fun write(destDir: File, fileName: String, stream: ByteArrayOutputStream, legacyFileName: String? = null) {
|
||||
totalSize += stream.size()
|
||||
totalFiles++
|
||||
File(destDir, fileName).parentFile.mkdirs()
|
||||
File(destDir, fileName).writeBytes(stream.toByteArray())
|
||||
|
||||
legacyFileName?.let { fileName ->
|
||||
File(destDir, fileName).writeBytes(stream.toByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
private fun serializeClass(
|
||||
|
||||
@@ -16,20 +16,27 @@
|
||||
|
||||
package org.jetbrains.kotlin.serialization.builtins
|
||||
|
||||
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
public class BuiltInsSerializerExtension : SerializerExtension() {
|
||||
private val stringTable = StringTableImpl()
|
||||
private val annotationSerializer = AnnotationSerializer(stringTable)
|
||||
|
||||
override fun getStringTable(): StringTable = stringTable
|
||||
|
||||
public class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
|
||||
override fun shouldUseTypeTable(): Boolean = true
|
||||
|
||||
override fun serializePackage(packageFragments: Collection<PackageFragmentDescriptor>, proto: ProtoBuf.Package.Builder) {
|
||||
if (packageFragments.isEmpty()) return
|
||||
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) {
|
||||
for (annotation in descriptor.annotations) {
|
||||
proto.addExtension(BuiltInsProtoBuf.classAnnotation, annotationSerializer.serializeAnnotation(annotation))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializePackage(packageFragments: Collection<PackageFragmentDescriptor>, proto: ProtoBuf.Package.Builder) {
|
||||
val classes = packageFragments.flatMap {
|
||||
it.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS).filterIsInstance<ClassDescriptor>()
|
||||
}
|
||||
@@ -37,7 +44,40 @@ public class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltIn
|
||||
for (descriptor in DescriptorSerializer.sort(classes)) {
|
||||
proto.addExtension(BuiltInsProtoBuf.className, stringTable.getSimpleNameIndex(descriptor.name))
|
||||
}
|
||||
}
|
||||
|
||||
proto.setExtension(BuiltInsProtoBuf.packageFqName, stringTable.getPackageFqNameIndex(packageFragments.first().fqName))
|
||||
override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder) {
|
||||
for (annotation in descriptor.annotations) {
|
||||
proto.addExtension(BuiltInsProtoBuf.constructorAnnotation, annotationSerializer.serializeAnnotation(annotation))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) {
|
||||
for (annotation in descriptor.annotations) {
|
||||
proto.addExtension(BuiltInsProtoBuf.functionAnnotation, annotationSerializer.serializeAnnotation(annotation))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) {
|
||||
for (annotation in descriptor.annotations) {
|
||||
proto.addExtension(BuiltInsProtoBuf.propertyAnnotation, annotationSerializer.serializeAnnotation(annotation))
|
||||
}
|
||||
val compileTimeConstant = descriptor.compileTimeInitializer ?: return
|
||||
if (compileTimeConstant !is NullValue) {
|
||||
val valueProto = annotationSerializer.valueProto(compileTimeConstant)
|
||||
proto.setExtension(BuiltInsProtoBuf.compileTimeValue, valueProto.build())
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeValueParameter(descriptor: ValueParameterDescriptor, proto: ProtoBuf.ValueParameter.Builder) {
|
||||
for (annotation in descriptor.annotations) {
|
||||
proto.addExtension(BuiltInsProtoBuf.parameterAnnotation, annotationSerializer.serializeAnnotation(annotation))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeType(type: KotlinType, proto: ProtoBuf.Type.Builder) {
|
||||
for (annotation in type.annotations) {
|
||||
proto.addExtension(BuiltInsProtoBuf.typeAnnotation, annotationSerializer.serializeAnnotation(annotation))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,10 @@ found top-level declarations to <destination dir> (files such as
|
||||
|
||||
val destDir = File(args[0])
|
||||
|
||||
val srcDirs = args.drop(1).map { File(it) }
|
||||
val srcDirs = args drop(1) map { File(it) }
|
||||
assert(srcDirs.isNotEmpty()) { "At least one source directory should be specified" }
|
||||
|
||||
val missing = srcDirs.filterNot { it.exists() }
|
||||
val missing = srcDirs filterNot { it.exists() }
|
||||
assert(missing.isEmpty()) { "These source directories are missing: $missing" }
|
||||
|
||||
BuiltInsSerializer(dependOnOldBuiltIns = false).serialize(destDir, srcDirs, listOf()) { totalSize, totalFiles ->
|
||||
|
||||
@@ -17,11 +17,3 @@
|
||||
package org.jetbrains.kotlin.cli.common
|
||||
|
||||
public val KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY = "kotlin.environment.keepalive"
|
||||
|
||||
|
||||
fun String?.toBooleanLenient(): Boolean? = when (this?.toLowerCase()) {
|
||||
null -> false
|
||||
in listOf("", "yes", "true", "on", "y") -> true
|
||||
in listOf("no", "false", "off", "n") -> false
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -41,9 +41,6 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
|
||||
@Argument(value = "meta-info", description = "Generate metadata")
|
||||
public boolean metaInfo;
|
||||
|
||||
@Argument(value = "kjsm", description = "Generate kjsm-files (for creating libraries)")
|
||||
public boolean kjsm;
|
||||
|
||||
@Argument(value = "target", description = "Generate JS files for specific ECMA version (only ECMA 5 is supported)")
|
||||
@ValueDescription("<version>")
|
||||
public String target;
|
||||
|
||||
@@ -64,9 +64,6 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
|
||||
@Argument(value = "Xreport-perf", description = "Report detailed performance statistics")
|
||||
public boolean reportPerf;
|
||||
|
||||
@Argument(value = "Xmultifile-facades-open", description = "Compile multifile facade classes as open")
|
||||
public boolean multifileFacadesOpen;
|
||||
|
||||
// Paths to output directories for friend modules.
|
||||
public String[] friendPaths;
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class GroupingMessageCollector implements MessageCollector {
|
||||
|
||||
private final MessageCollector delegate;
|
||||
@@ -50,14 +48,13 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
public void flush() {
|
||||
boolean hasError = false;
|
||||
|
||||
Collection<String> keys = sortedKeys();
|
||||
for (String path : keys) {
|
||||
for (String path : groupedMessages.keySet()) {
|
||||
for (Message message : groupedMessages.get(path)) {
|
||||
hasError |= CompilerMessageSeverity.ERRORS.contains(message.severity);
|
||||
}
|
||||
}
|
||||
|
||||
for (String path : keys) {
|
||||
for (String path : groupedMessages.keySet()) {
|
||||
for (Message message : groupedMessages.get(path)) {
|
||||
if (!hasError || CompilerMessageSeverity.ERRORS.contains(message.severity)) {
|
||||
delegate.report(message.severity, message.message, message.location);
|
||||
@@ -68,22 +65,6 @@ public class GroupingMessageCollector implements MessageCollector {
|
||||
groupedMessages.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<String> sortedKeys() {
|
||||
List<String> sortedKeys = new ArrayList<String>(groupedMessages.keySet());
|
||||
// ensure that messages with no location i.e. perf, incomplete hierarchy are always reported first
|
||||
Collections.sort(sortedKeys, new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
if (o1 == o2) return 0;
|
||||
if (o1 == null) return -1;
|
||||
if (o2 == null) return 1;
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
});
|
||||
return sortedKeys;
|
||||
}
|
||||
|
||||
private static class Message {
|
||||
private final CompilerMessageSeverity severity;
|
||||
private final String message;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user