mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-25 08:31:32 +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 |
2
.idea/ant.xml
generated
2
.idea/ant.xml
generated
@@ -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" />
|
||||
|
||||
8
.idea/modules.xml
generated
8
.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,7 +36,7 @@
|
||||
<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-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" />
|
||||
@@ -56,10 +53,13 @@
|
||||
<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$/compiler/util/util.iml" filepath="$PROJECT_DIR$/compiler/util/util.iml" />
|
||||
|
||||
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>
|
||||
|
||||
5
.idea/runConfigurations/IDEA__win_.xml
generated
5
.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" />
|
||||
@@ -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">
|
||||
|
||||
@@ -1,92 +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}"/>
|
||||
</target>
|
||||
</project>
|
||||
43
build.xml
43
build.xml
@@ -91,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"/>
|
||||
@@ -118,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/**"/>
|
||||
@@ -203,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"/>
|
||||
@@ -293,7 +294,6 @@
|
||||
<arg value="@{output}"/>
|
||||
<arg value="-no-stdlib"/>
|
||||
<arg value="-meta-info"/>
|
||||
<arg value="-kjsm"/>
|
||||
<arg line="-main noCall"/>
|
||||
</java>
|
||||
</sequential>
|
||||
@@ -308,13 +308,13 @@
|
||||
|
||||
<kotlin-pp src="libraries/stdlib/src" output="${intermediate-sources}/stdlib/js" profile="JS" />
|
||||
|
||||
<new-kotlin2js output="${output}/js/${compiled.builtins.js}">
|
||||
<new-kotlin2js output="${output}/${compiled.builtins.js}">
|
||||
<src>
|
||||
<fileset refid="kotlin.builtin.files"/>
|
||||
</src>
|
||||
</new-kotlin2js>
|
||||
|
||||
<new-kotlin2js output="${output}/js/${compiled.stdlib.js}">
|
||||
<new-kotlin2js output="${output}/${compiled.stdlib.js}">
|
||||
<src>
|
||||
<resources refid="js.lib.files"/>
|
||||
</src>
|
||||
@@ -334,7 +334,7 @@
|
||||
prettyprint="true"
|
||||
languagein="ECMASCRIPT5_STRICT"
|
||||
warning="${warningLevel}"
|
||||
output="${output}/js/kotlin.js">
|
||||
output="${output}/kotlin.js">
|
||||
|
||||
<sources dir="${stdlib.js.dir}">
|
||||
<file name="kotlin_lib_ecma5.js"/>
|
||||
@@ -343,11 +343,11 @@
|
||||
<file name="long.js"/>
|
||||
</sources>
|
||||
|
||||
<sources dir="${output}/js">
|
||||
<sources dir="${output}">
|
||||
<file name="${compiled.builtins.js}"/>
|
||||
</sources>
|
||||
|
||||
<sources dir="${output}/js">
|
||||
<sources dir="${output}">
|
||||
<file name="${compiled.stdlib.js}"/>
|
||||
</sources>
|
||||
|
||||
@@ -362,11 +362,8 @@
|
||||
|
||||
<jar jarfile="${kotlin-home}/lib/kotlin-jslib.jar" duplicate="fail">
|
||||
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
|
||||
<zipfileset dir="${output}/js" 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}"/>
|
||||
@@ -583,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}"/>
|
||||
@@ -598,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>
|
||||
@@ -939,7 +936,7 @@
|
||||
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-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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,8 +38,6 @@ public class AccessorForConstructorDescriptor(
|
||||
|
||||
override fun getSuperCallTarget(): ClassDescriptor? = superCallTarget
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor) = super.substitute(substitutor) as ConstructorDescriptor
|
||||
|
||||
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;
|
||||
@@ -446,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();
|
||||
@@ -640,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,
|
||||
@@ -664,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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -309,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);
|
||||
@@ -762,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);
|
||||
}
|
||||
}
|
||||
@@ -918,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);
|
||||
|
||||
@@ -927,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:
|
||||
@@ -941,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);
|
||||
@@ -955,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 {
|
||||
@@ -975,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);
|
||||
@@ -995,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);
|
||||
@@ -1042,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1052,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();
|
||||
@@ -1075,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);
|
||||
@@ -1126,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);
|
||||
@@ -1155,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;
|
||||
|
||||
@@ -1174,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 {
|
||||
@@ -1791,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) {
|
||||
@@ -1879,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);
|
||||
}
|
||||
@@ -1900,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);
|
||||
@@ -1994,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);
|
||||
}
|
||||
|
||||
@@ -2072,7 +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);
|
||||
return call != null ? ((ReceiverValue) call.getExplicitReceiver()).getType() : null;
|
||||
return call != null ? call.getExplicitReceiver().getType() : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -2335,15 +2399,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
|
||||
if (!codegenExtensions.isEmpty()) {
|
||||
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
|
||||
for (ExpressionCodegenExtension extension : codegenExtensions) {
|
||||
StackValue stackValue = extension.applyFunction(receiver, resolvedCall, context);
|
||||
if (stackValue != null) return stackValue;
|
||||
}
|
||||
}
|
||||
|
||||
Callable callable = resolveToCallable(fd, superCall, resolvedCall);
|
||||
|
||||
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||
@@ -2401,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();
|
||||
@@ -2495,8 +2560,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@NotNull
|
||||
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue, boolean isSuper) {
|
||||
if (receiverValue instanceof ImplicitClassReceiver) {
|
||||
ClassDescriptor receiverDescriptor = ((ImplicitClassReceiver) receiverValue).getDeclarationDescriptor();
|
||||
if (receiverValue instanceof ClassReceiver) {
|
||||
ClassDescriptor receiverDescriptor = ((ClassReceiver) receiverValue).getDeclarationDescriptor();
|
||||
if (DescriptorUtils.isCompanionObject(receiverDescriptor)) {
|
||||
CallableMemberDescriptor contextDescriptor = context.getContextDescriptor();
|
||||
if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) {
|
||||
@@ -2506,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());
|
||||
}
|
||||
@@ -2531,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;
|
||||
@@ -2544,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);
|
||||
@@ -2567,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);
|
||||
@@ -3329,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
|
||||
@@ -3373,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);
|
||||
}
|
||||
|
||||
@@ -3497,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
|
||||
@@ -3751,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) {
|
||||
@@ -3759,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, 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;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
@@ -356,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;
|
||||
|
||||
@@ -561,7 +555,12 @@ public class FunctionCodegen {
|
||||
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;
|
||||
@@ -576,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()) {
|
||||
@@ -599,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();
|
||||
@@ -855,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++) {
|
||||
@@ -884,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, 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;
|
||||
@@ -168,7 +167,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
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;
|
||||
@@ -302,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) {
|
||||
@@ -851,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);
|
||||
|
||||
@@ -942,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);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -993,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,
|
||||
@@ -1056,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 :
|
||||
@@ -1073,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);
|
||||
@@ -1081,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
|
||||
@@ -1235,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) {
|
||||
@@ -1249,7 +1220,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void lookupReceiver(@NotNull ReceiverValue value) {
|
||||
if (value instanceof ImplicitReceiver) {
|
||||
if (value instanceof ThisReceiver) {
|
||||
if (value instanceof ExtensionReceiver) {
|
||||
ReceiverParameterDescriptor parameter =
|
||||
((ExtensionReceiver) value).getDeclarationDescriptor().getExtensionReceiverParameter();
|
||||
@@ -1257,7 +1228,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
lookupInContext(parameter);
|
||||
}
|
||||
else {
|
||||
lookupInContext(((ImplicitReceiver) value).getDeclarationDescriptor());
|
||||
lookupInContext(((ThisReceiver) value).getDeclarationDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1293,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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -144,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();
|
||||
@@ -273,8 +273,13 @@ 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));
|
||||
}
|
||||
@@ -315,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;
|
||||
}
|
||||
|
||||
@@ -365,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);
|
||||
}
|
||||
@@ -484,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 =
|
||||
@@ -529,12 +537,12 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
);
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -601,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());
|
||||
}
|
||||
}
|
||||
@@ -632,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++) {
|
||||
@@ -643,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);
|
||||
@@ -673,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
|
||||
@@ -709,7 +716,5 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
}
|
||||
|
||||
callableMethod.genInvokeInstruction(iv);
|
||||
|
||||
return StackValue.onStack(callableMethod.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,12 +143,6 @@ 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(
|
||||
|
||||
@@ -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)) {
|
||||
@@ -131,21 +140,6 @@ public class PropertyCodegen {
|
||||
context.recordSyntheticAccessorIfNeeded(descriptor, bindingContext);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if it's necessary to generate an accessor to the property, i.e. if this property can be referenced via getter/setter
|
||||
* for any reason
|
||||
@@ -180,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,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
|
||||
@@ -51,7 +52,15 @@ public class PropertyReferenceCodegen(
|
||||
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
||||
private val asmType = typeMapper.mapClass(classDescriptor)
|
||||
|
||||
private val dispatchReceiverType = if (dispatchReceiver.exists()) dispatchReceiver.type else null
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,7 +501,7 @@ public abstract class StackValue {
|
||||
callDispatchReceiver = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverForBackend();
|
||||
}
|
||||
|
||||
ReceiverValue callExtensionReceiver = (ReceiverValue) resolvedCall.getExtensionReceiver();
|
||||
ReceiverValue callExtensionReceiver = resolvedCall.getExtensionReceiver();
|
||||
if (callDispatchReceiver.exists() || callExtensionReceiver.exists()
|
||||
|| isLocalFunCall(callableMethod) || isCallToMemberObjectImportedByName(resolvedCall)) {
|
||||
ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter();
|
||||
@@ -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,7 +832,7 @@ public abstract class StackValue {
|
||||
v.store(firstParamIndex, type);
|
||||
}
|
||||
|
||||
ReceiverValue receiverParameter = (ReceiverValue) resolvedGetCall.getExtensionReceiver();
|
||||
ReceiverValue receiverParameter = resolvedGetCall.getExtensionReceiver();
|
||||
int receiverIndex = -1;
|
||||
if (receiverParameter.exists()) {
|
||||
Type type = codegen.typeMapper.mapType(receiverParameter.getType());
|
||||
@@ -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 {
|
||||
|
||||
@@ -158,20 +158,24 @@ 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
|
||||
@@ -382,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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,10 +19,15 @@ package org.jetbrains.kotlin.codegen
|
||||
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.*
|
||||
import org.jetbrains.kotlin.load.java.*
|
||||
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.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
|
||||
@@ -58,6 +63,7 @@ object BuiltinSpecialBridgesUtil {
|
||||
|
||||
val needGenerateSpecialBridge = needGenerateSpecialBridge(
|
||||
function, reachableDeclarations, overriddenBuiltin, signatureByDescriptor, overriddenBuiltinSignature)
|
||||
&& methodItself != overriddenBuiltinSignature
|
||||
|
||||
val specialBridge = if (needGenerateSpecialBridge)
|
||||
BridgeForBuiltinSpecial(overriddenBuiltinSignature, methodItself, isSpecial = true)
|
||||
@@ -88,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 = getOverriddenBuiltinWithDifferentJvmDescriptor()!!
|
||||
return signatureByDescriptor(this) == signatureByDescriptor(builtin)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,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.getOverriddenBuiltinWithDifferentJvmDescriptor()?.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(
|
||||
|
||||
@@ -1,51 +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.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
fun generateIsCheck(
|
||||
v: InstructionAdapter,
|
||||
type: KotlinType,
|
||||
generateInstanceOfInstruction: (InstructionAdapter) -> Unit
|
||||
) {
|
||||
if (type.isMarkedNullable) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -512,21 +511,20 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@Nullable ClassDescriptor superCallTarget
|
||||
) {
|
||||
DeclarationDescriptor enclosing = descriptor.getContainingDeclaration();
|
||||
boolean isInliningContext = isInlineMethodContext();
|
||||
if (!isInliningContext && (
|
||||
if (!isInlineMethodContext() && (
|
||||
!hasThisDescriptor() ||
|
||||
enclosing == getThisDescriptor() ||
|
||||
enclosing == getClassOrPackageParentContext().getContextDescriptor())) {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
return 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, false);
|
||||
accessibleDescriptorIfNeeded(descriptor, /* superCallTarget = */ null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,8 +532,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@NotNull
|
||||
private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded(
|
||||
@NotNull D descriptor,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
boolean withinInliningContext
|
||||
@Nullable ClassDescriptor superCallTarget
|
||||
) {
|
||||
CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor);
|
||||
|
||||
@@ -556,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);
|
||||
@@ -571,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;
|
||||
@@ -587,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);
|
||||
@@ -597,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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -35,7 +35,6 @@ 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 {
|
||||
@@ -180,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) {
|
||||
@@ -285,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++;
|
||||
}
|
||||
|
||||
@@ -325,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);
|
||||
}
|
||||
@@ -375,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() {
|
||||
@@ -386,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>();
|
||||
@@ -396,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;
|
||||
@@ -408,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);
|
||||
@@ -454,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);
|
||||
@@ -512,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
|
||||
@@ -550,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;
|
||||
}
|
||||
|
||||
@@ -62,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;
|
||||
@@ -597,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);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ 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.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.*;
|
||||
@@ -63,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$$$$$";
|
||||
@@ -73,8 +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";
|
||||
|
||||
@Nullable
|
||||
public static SMAPAndMethodNode getMethodNode(
|
||||
@@ -121,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);
|
||||
}
|
||||
|
||||
@@ -489,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -441,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,12 +546,7 @@ public class MethodInliner {
|
||||
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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ public class ReifiedTypeParameterMappings() {
|
||||
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]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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,9 +26,12 @@ 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.*
|
||||
@@ -54,6 +57,8 @@ 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 mainFunctionDetector = MainFunctionDetector(bindingContext)
|
||||
|
||||
override fun handleClashingSignatures(data: ConflictingJvmDeclarationsData) {
|
||||
val noOwnImplementations = data.signatureOrigins.all { it.originKind in EXTERNAL_SOURCES_KINDS }
|
||||
|
||||
@@ -97,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
|
||||
|
||||
@@ -38,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(
|
||||
@@ -53,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
|
||||
@@ -91,13 +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 get() = 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")
|
||||
@@ -107,19 +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
|
||||
|
||||
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
|
||||
|
||||
@@ -19,7 +19,6 @@ 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;
|
||||
@@ -169,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);
|
||||
}
|
||||
@@ -405,7 +407,7 @@ public class JetTypeMapper {
|
||||
sw.writeReturnType();
|
||||
mapType(descriptor.getType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
|
||||
sw.writeReturnTypeEnd();
|
||||
return sw.makeJvmMethodSignature(descriptor.getName().asString(), false);
|
||||
return sw.makeJvmMethodSignature(descriptor.getName().asString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -577,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);
|
||||
@@ -622,91 +628,43 @@ public class JetTypeMapper {
|
||||
private void writeGenericType(
|
||||
BothSignatureWriter signatureVisitor,
|
||||
Type asmType,
|
||||
KotlinType type,
|
||||
KotlinType jetType,
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
if (hasNothingInArguments(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(),
|
||||
howThisTypeIsUsed, projectionsAllowed);
|
||||
|
||||
for (PossiblyInnerType innerPart : innerTypesAsList.subList(1, innerTypesAsList.size())) {
|
||||
ClassDescriptor classDescriptor = innerPart.getClassDescriptor();
|
||||
signatureVisitor.writeInnerClass(getJvmShortName(classDescriptor));
|
||||
writeGenericArguments(
|
||||
signatureVisitor, innerPart.getArguments(),
|
||||
classDescriptor.getDeclaredTypeParameters(),
|
||||
howThisTypeIsUsed, projectionsAllowed
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
BothSignatureWriter signatureVisitor,
|
||||
List<? extends TypeProjection> arguments,
|
||||
List<? extends TypeParameterDescriptor> parameters,
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
for (Pair<? extends TypeParameterDescriptor, ? extends TypeProjection> item : CollectionsKt.zip(parameters, arguments)) {
|
||||
TypeParameterDescriptor parameter = item.getFirst();
|
||||
TypeProjection argument = item.getSecond();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasNothingInArguments(KotlinType jetType) {
|
||||
boolean hasNothingInArguments = CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
@@ -776,8 +734,7 @@ public class JetTypeMapper {
|
||||
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();
|
||||
@@ -787,7 +744,7 @@ public class JetTypeMapper {
|
||||
JvmMethodSignature signature;
|
||||
Type owner;
|
||||
Type ownerForDefaultImpl;
|
||||
FunctionDescriptor baseMethodDescriptor;
|
||||
Type ownerForDefaultParam;
|
||||
int invokeOpcode;
|
||||
Type thisClass;
|
||||
|
||||
@@ -802,9 +759,9 @@ 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)) {
|
||||
thisClass = mapClass(currentOwner);
|
||||
@@ -853,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;
|
||||
@@ -879,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);
|
||||
}
|
||||
|
||||
@@ -964,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;
|
||||
@@ -1071,7 +1013,8 @@ 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);
|
||||
@@ -1104,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) {
|
||||
@@ -1384,16 +1327,18 @@ public class JetTypeMapper {
|
||||
sw.writeParametersStart();
|
||||
|
||||
for (ScriptDescriptor importedScript : importedScripts) {
|
||||
writeParameter(sw, importedScript.getDefaultType());
|
||||
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()) {
|
||||
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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -28,7 +28,6 @@ public class ModuleBuilder(
|
||||
private val sourceFiles = ArrayList<String>()
|
||||
private val classpathRoots = ArrayList<String>()
|
||||
private val javaSourceRoots = ArrayList<JavaRootPath>()
|
||||
private val friendDirs = ArrayList<String>()
|
||||
|
||||
public fun addSourceFiles(pattern: String) {
|
||||
sourceFiles.add(pattern)
|
||||
@@ -42,12 +41,7 @@ public class ModuleBuilder(
|
||||
javaSourceRoots.add(rootPath)
|
||||
}
|
||||
|
||||
public fun addFriendDir(friendDir: String) {
|
||||
friendDirs.add(friendDir)
|
||||
}
|
||||
|
||||
override fun getOutputDirectory(): String = outputDir
|
||||
override fun getFriendPaths(): List<String> = friendDirs
|
||||
override fun getJavaSourceRoots(): List<JavaRootPath> = javaSourceRoots
|
||||
override fun getSourceFiles(): List<String> = sourceFiles
|
||||
override fun getClasspathRoots(): List<String> = classpathRoots
|
||||
|
||||
@@ -47,7 +47,6 @@ public class ModuleXmlParser {
|
||||
public static final String TYPE_PRODUCTION = "java-production";
|
||||
public static final String TYPE_TEST = "java-test";
|
||||
public static final String OUTPUT_DIR = "outputDir";
|
||||
public static final String FRIEND_DIR = "friendDir";
|
||||
public static final String SOURCES = "sources";
|
||||
public static final String JAVA_SOURCE_ROOTS = "javaSourceRoots";
|
||||
public static final String JAVA_SOURCE_PACKAGE_PREFIX = "packagePrefix";
|
||||
@@ -163,10 +162,6 @@ public class ModuleXmlParser {
|
||||
String path = getAttribute(attributes, PATH, qName);
|
||||
moduleBuilder.addSourceFiles(path);
|
||||
}
|
||||
else if (FRIEND_DIR.equalsIgnoreCase(qName)) {
|
||||
String path = getAttribute(attributes, PATH, qName);
|
||||
moduleBuilder.addFriendDir(path);
|
||||
}
|
||||
else if (CLASSPATH.equalsIgnoreCase(qName)) {
|
||||
String path = getAttribute(attributes, PATH, qName);
|
||||
moduleBuilder.addClasspathEntry(path);
|
||||
|
||||
@@ -18,12 +18,13 @@ package org.jetbrains.kotlin.cli.common
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
|
||||
import org.jetbrains.kotlin.load.kotlin.getSourceElement
|
||||
import org.jetbrains.kotlin.load.kotlin.isContainedByCompiledPartOfOurModule
|
||||
import org.jetbrains.kotlin.load.kotlin.isFromIncrementalPackageFragment
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.util.ModuleVisibilityHelper
|
||||
@@ -43,43 +44,37 @@ class ModuleVisibilityHelperImpl : ModuleVisibilityHelper {
|
||||
}
|
||||
|
||||
val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(project)
|
||||
|
||||
fun findModule(kotlinFile: KtFile): Module? = moduleVisibilityManager.chunk.firstOrNull { it.getSourceFiles().containsRaw(kotlinFile.virtualFile.path) }
|
||||
|
||||
val whatSource = getSourceElement(what)
|
||||
if (whatSource is KotlinSourceElement) {
|
||||
if (moduleVisibilityManager.chunk.size > 1 && fromSource is KotlinSourceElement) {
|
||||
val fromSourceKotlinFile = fromSource.psi.getContainingKtFile()
|
||||
val whatSourceKotlinFile = whatSource.psi.getContainingKtFile()
|
||||
return findModule(whatSourceKotlinFile) === findModule(fromSourceKotlinFile)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
moduleVisibilityManager.friendPaths.forEach {
|
||||
if (isContainedByCompiledPartOfOurModule(what, File(it))) return true
|
||||
}
|
||||
|
||||
val modules = moduleVisibilityManager.chunk
|
||||
|
||||
val whatSource = getSourceElement(what)
|
||||
if (whatSource is KotlinSourceElement) {
|
||||
if (modules.size > 1 && fromSource is KotlinSourceElement) {
|
||||
return findModule(what, modules) === findModule(from, modules)
|
||||
}
|
||||
val outputDirectories = modules.map { File(it.getOutputDirectory()) }
|
||||
if (outputDirectories.isEmpty()) return isContainedByCompiledPartOfOurModule(what, null)
|
||||
|
||||
return true
|
||||
outputDirectories.forEach {
|
||||
if (isContainedByCompiledPartOfOurModule(what, it)) return true
|
||||
}
|
||||
|
||||
if (modules.isEmpty()) return false
|
||||
// Hack in order to allow access to internal elements in production code from tests
|
||||
if (modules.singleOrNull()?.getModuleType() == ModuleXmlParser.TYPE_TEST) return true
|
||||
|
||||
// Hack for incremental compilation (now there is no way to determine the module of descriptor in case of incremental package fragment)
|
||||
// TODO Implement full check for access to internal for incremental compilation
|
||||
if (what.isFromIncrementalPackageFragment) return true
|
||||
|
||||
if (modules.size == 1 && isContainedByCompiledPartOfOurModule(what, File(modules.single().getOutputDirectory()))) return true
|
||||
|
||||
return findModule(from, modules) === findModule(what, modules)
|
||||
}
|
||||
|
||||
private fun findModule(descriptor: DeclarationDescriptor, modules: Collection<Module>): Module? {
|
||||
val sourceElement = getSourceElement(descriptor)
|
||||
if (sourceElement is KotlinSourceElement) {
|
||||
return modules.singleOrNull() ?: modules.firstOrNull { sourceElement.psi.getContainingKtFile().virtualFile.path in it.getSourceFiles() }
|
||||
}
|
||||
else {
|
||||
return modules.firstOrNull { module ->
|
||||
isContainedByCompiledPartOfOurModule(descriptor, File(module.getOutputDirectory())) ||
|
||||
module.getFriendPaths().any { isContainedByCompiledPartOfOurModule(descriptor, File(it))}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +264,6 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
.sourceMap(arguments.sourceMap)
|
||||
.inlineEnabled(inlineEnabled)
|
||||
.metaInfo(arguments.metaInfo)
|
||||
.kjsm(arguments.kjsm)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,13 @@ import org.jetbrains.kotlin.codegen.CompilationException
|
||||
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.PluginCliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.cliPluginUsageString
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.config.addKotlinSourceRoot
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||
import org.jetbrains.kotlin.resolve.AnalyzerScriptParameter
|
||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
|
||||
@@ -123,10 +126,10 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
return ExitCode.OK
|
||||
}
|
||||
|
||||
if (arguments.script) {
|
||||
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition)
|
||||
shouldReportPerf = false
|
||||
}
|
||||
configuration.put<List<AnalyzerScriptParameter>>(JVMConfigurationKeys.SCRIPT_PARAMETERS, if (arguments.script)
|
||||
CommandLineScriptUtils.scriptParameters()
|
||||
else
|
||||
emptyList<AnalyzerScriptParameter>())
|
||||
|
||||
putAdvancedOptions(configuration, arguments)
|
||||
|
||||
@@ -233,7 +236,6 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
// allows to track GC time for each run when repeated compilation is used
|
||||
private val elapsedGCTime = hashMapOf<String, Long>()
|
||||
private var elapsedJITTime = 0L
|
||||
private var shouldReportPerf = true
|
||||
|
||||
public fun resetInitStartTime() {
|
||||
if (initStartNanos == 0L) {
|
||||
@@ -247,8 +249,6 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
|
||||
public fun reportPerf(configuration: CompilerConfiguration, message: String) {
|
||||
if (!shouldReportPerf) return
|
||||
|
||||
val collector = configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!!
|
||||
collector.report(CompilerMessageSeverity.INFO, "PERF: " + message, CompilerMessageLocation.NO_LOCATION)
|
||||
}
|
||||
|
||||
@@ -92,13 +92,13 @@ public class CliLightClassGenerationSupport(project: Project) : LightClassGenera
|
||||
}
|
||||
|
||||
override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject> {
|
||||
return ResolveSessionUtils.getClassDescriptorsByFqName(module, fqName).mapNotNull {
|
||||
return ResolveSessionUtils.getClassDescriptorsByFqName(module, fqName).map {
|
||||
val element = DescriptorToSourceUtils.getSourceFromDescriptor(it)
|
||||
if (element is KtClassOrObject && PsiSearchScopeUtil.isInScope(searchScope, element)) {
|
||||
element
|
||||
}
|
||||
else null
|
||||
}
|
||||
}.filterNotNull()
|
||||
}
|
||||
|
||||
override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> {
|
||||
@@ -216,7 +216,7 @@ public class CliLightClassGenerationSupport(project: Project) : LightClassGenera
|
||||
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
return PackagePartClassUtils.getFilesWithCallables(findFilesForPackage(packageFqName, scope)).groupBy {
|
||||
JvmFileClassUtil.getFileClassInfoNoResolve(it).facadeClassFqName
|
||||
}.mapNotNull { KtLightClassForFacade.createForFacade(psiManager, it.key, scope, it.value) }
|
||||
}.map { KtLightClassForFacade.createForFacade(psiManager, it.key, scope, it.value) }.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.cli.jvm.compiler;
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.AnalyzerScriptParameter;
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.types.Variance.INVARIANT;
|
||||
|
||||
public class CommandLineScriptUtils {
|
||||
private static final Name ARGS_NAME = Name.identifier("args");
|
||||
|
||||
private CommandLineScriptUtils() {
|
||||
}
|
||||
|
||||
public static List<AnalyzerScriptParameter> scriptParameters() {
|
||||
KotlinBuiltIns builtIns = JvmPlatform.INSTANCE$.getBuiltIns();
|
||||
KotlinType arrayOfStrings = builtIns.getArrayType(INVARIANT, builtIns.getStringType());
|
||||
AnalyzerScriptParameter argsParameter = new AnalyzerScriptParameter(ARGS_NAME, arrayOfStrings);
|
||||
return Collections.singletonList(argsParameter);
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class JvmDependenciesIndex(_roots: List<JavaRoot>) {
|
||||
private class Cache {
|
||||
private val innerPackageCaches = HashMap<String, Cache>()
|
||||
|
||||
operator fun get(name: String) = innerPackageCaches.getOrPut(name) { Cache() }
|
||||
fun get(name: String) = innerPackageCaches.getOrPut(name) { Cache() }
|
||||
|
||||
// indices of roots that are known to contain this package
|
||||
// if this list contains [1, 3, 5] then roots with indices 1, 3 and 5 are known to contain this package, 2 and 4 are known not to (no information about roots 6 or higher)
|
||||
|
||||
@@ -28,9 +28,9 @@ public class JvmPackagePartProvider(val env: KotlinCoreEnvironment) : PackagePar
|
||||
val roots by lazy {
|
||||
env.configuration.getList(CommonConfigurationKeys.CONTENT_ROOTS).
|
||||
filterIsInstance<JvmClasspathRoot>().
|
||||
mapNotNull {
|
||||
map {
|
||||
env.contentRootToVirtualFile(it);
|
||||
}.filter { it.findChild("META-INF") != null }
|
||||
}.filter { it?.findChild("META-INF") != null }.filterNotNull()
|
||||
}
|
||||
|
||||
override fun findPackageParts(packageFqName: String): List<String> {
|
||||
@@ -43,10 +43,10 @@ public class JvmPackagePartProvider(val env: KotlinCoreEnvironment) : PackagePar
|
||||
else parent.findChild(part) ?: return@filter false
|
||||
}
|
||||
true
|
||||
}.mapNotNull {
|
||||
}.map {
|
||||
it.findChild("META-INF")
|
||||
}.flatMap {
|
||||
it.children.filter<VirtualFile> { it.name.endsWith(ModuleMapping.MAPPING_FILE_EXT) }
|
||||
}.filterNotNull().flatMap {
|
||||
it.children.filter { it.name.endsWith(ModuleMapping.MAPPING_FILE_EXT) }.toList<VirtualFile>()
|
||||
}.map {
|
||||
try {
|
||||
ModuleMapping.create(it.contentsToByteArray())
|
||||
@@ -55,6 +55,6 @@ public class JvmPackagePartProvider(val env: KotlinCoreEnvironment) : PackagePar
|
||||
}
|
||||
}
|
||||
|
||||
return mappings.mapNotNull { it.findPackageParts(packageFqName) }.flatMap { it.parts }.distinct()
|
||||
return mappings.map { it.findPackageParts(packageFqName) }.filterNotNull().flatMap { it.parts }.distinct()
|
||||
}
|
||||
}
|
||||
@@ -57,12 +57,13 @@ public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager)
|
||||
// which supposedly shouldn't have errors so the dependencies exist in general
|
||||
// Most classes are top level classes so we will try to find them fast
|
||||
// but we must sometimes fallback to support finding inner/nested classes
|
||||
return qName.toSafeTopLevelClassId()?.let { classId -> findClass(classId, scope) } ?: super.findClass(qName, scope)
|
||||
return qName.toSafeTopLevelClassId()?.let { classId -> findClass(classId, scope) }
|
||||
?: super<CoreJavaFileManager>.findClass(qName, scope)
|
||||
}
|
||||
|
||||
override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> {
|
||||
return perfCounter.time {
|
||||
val classIdAsTopLevelClass = qName.toSafeTopLevelClassId() ?: return@time super.findClasses(qName, scope)
|
||||
val classIdAsTopLevelClass = qName.toSafeTopLevelClassId() ?: return@time super<CoreJavaFileManager>.findClasses(qName, scope)
|
||||
|
||||
val result = ArrayList<PsiClass>()
|
||||
val classNameWithInnerClasses = classIdAsTopLevelClass.getRelativeClassName().asString()
|
||||
@@ -75,7 +76,7 @@ public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager)
|
||||
true
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
super.findClasses(qName, scope)
|
||||
super<CoreJavaFileManager>.findClasses(qName, scope)
|
||||
}
|
||||
else {
|
||||
result.toTypedArray()
|
||||
@@ -121,7 +122,7 @@ public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KotlinCliJavaFileManagerImpl::class.java)
|
||||
private val LOG = Logger.getInstance(javaClass<KotlinCliJavaFileManagerImpl>())
|
||||
|
||||
private fun findClassInPsiFile(classNameWithInnerClassesDotSeparated: String, file: PsiClassOwner): PsiClass? {
|
||||
for (topLevelClass in file.getClasses()) {
|
||||
|
||||
@@ -28,8 +28,7 @@ import com.intellij.mock.MockApplication
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.extensions.ExtensionsArea
|
||||
import com.intellij.openapi.extensions.*
|
||||
import com.intellij.openapi.fileTypes.FileTypeExtensionPoint
|
||||
import com.intellij.openapi.fileTypes.PlainTextFileType
|
||||
import com.intellij.openapi.project.Project
|
||||
@@ -79,14 +78,13 @@ import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.isValidJavaFqName
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.parsing.KotlinScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
@@ -133,7 +131,7 @@ public class KotlinCoreEnvironment private constructor(
|
||||
}
|
||||
})
|
||||
|
||||
KotlinScriptDefinitionProvider.getInstance(project).setScriptDefinitions(configuration.getList(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY))
|
||||
KotlinScriptDefinitionProvider.getInstance(project).addScriptDefinitions(configuration.getList(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY))
|
||||
|
||||
project.registerService(javaClass<JvmVirtualFileFinderFactory>(), JvmCliVirtualFileFinderFactory(index))
|
||||
|
||||
@@ -141,7 +139,6 @@ public class KotlinCoreEnvironment private constructor(
|
||||
ExpressionCodegenExtension.registerExtensionPoint(project)
|
||||
ClassBuilderInterceptorExtension.registerExtensionPoint(project)
|
||||
AnalysisCompletedHandlerExtension.registerExtensionPoint(project)
|
||||
PackageFragmentProviderExtension.registerExtensionPoint(project)
|
||||
StorageComponentContainerContributor.registerExtensionPoint(project)
|
||||
|
||||
for (registrar in configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) {
|
||||
@@ -288,9 +285,6 @@ public class KotlinCoreEnvironment private constructor(
|
||||
return KotlinCoreEnvironment(parentDisposable, createApplicationEnvironment(parentDisposable, configuration, extensionConfigs), configuration)
|
||||
}
|
||||
|
||||
// used in the daemon for jar cache cleanup
|
||||
public val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment
|
||||
|
||||
private fun getOrCreateApplicationEnvironmentForProduction(configuration: CompilerConfiguration, configFilePaths: List<String>): JavaCoreApplicationEnvironment {
|
||||
synchronized (APPLICATION_LOCK) {
|
||||
if (ourApplicationEnvironment != null)
|
||||
@@ -315,7 +309,7 @@ public class KotlinCoreEnvironment private constructor(
|
||||
if (ourApplicationEnvironment == null) return
|
||||
val environment = ourApplicationEnvironment
|
||||
ourApplicationEnvironment = null
|
||||
Disposer.dispose(environment.getParentDisposable())
|
||||
Disposer.dispose(environment!!.getParentDisposable())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,20 +54,20 @@ import org.jetbrains.kotlin.modules.Module;
|
||||
import org.jetbrains.kotlin.modules.TargetId;
|
||||
import org.jetbrains.kotlin.modules.TargetIdKt;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.parsing.KotlinScriptDefinition;
|
||||
import org.jetbrains.kotlin.parsing.KotlinScriptDefinitionProvider;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtScript;
|
||||
import org.jetbrains.kotlin.resolve.AnalyzerScriptParameter;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.BindingTraceContext;
|
||||
import org.jetbrains.kotlin.resolve.ScriptNameUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM;
|
||||
import org.jetbrains.kotlin.util.PerformanceCounter;
|
||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
@@ -257,39 +257,15 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
) {
|
||||
Class<?> scriptClass = compileScript(configuration, paths, environment);
|
||||
if (scriptClass == null) return;
|
||||
Constructor<?> scriptConstructor = getScriptConstructor(scriptClass);
|
||||
|
||||
try {
|
||||
scriptConstructor.newInstance(new Object[] {ArrayUtil.toStringArray(scriptArgs)});
|
||||
scriptClass.getConstructor(String[].class).newInstance(new Object[] {ArrayUtil.toStringArray(scriptArgs)});
|
||||
}
|
||||
catch (Throwable e) {
|
||||
reportExceptionFromScript(e);
|
||||
catch (RuntimeException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportExceptionFromScript(@NotNull Throwable exception) {
|
||||
// expecting InvocationTargetException from constructor invocation with cause that describes the actual cause
|
||||
PrintStream stream = System.err;
|
||||
Throwable cause = exception.getCause();
|
||||
if (!(exception instanceof InvocationTargetException) || cause == null) {
|
||||
exception.printStackTrace(stream);
|
||||
return;
|
||||
}
|
||||
stream.println(cause);
|
||||
StackTraceElement[] fullTrace = cause.getStackTrace();
|
||||
int relevantEntries = fullTrace.length - exception.getStackTrace().length;
|
||||
for (int i = 0; i < relevantEntries; i++) {
|
||||
stream.println("\tat " + fullTrace[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Constructor<?> getScriptConstructor(Class<?> scriptClass) {
|
||||
try {
|
||||
return scriptClass.getConstructor(String[].class);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw ExceptionUtilsKt.rethrow(e);
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Failed to evaluate script: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +275,12 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
@NotNull KotlinPaths paths,
|
||||
@NotNull KotlinCoreEnvironment environment
|
||||
) {
|
||||
List<AnalyzerScriptParameter> scriptParameters = environment.getConfiguration().getList(JVMConfigurationKeys.SCRIPT_PARAMETERS);
|
||||
if (!scriptParameters.isEmpty()) {
|
||||
KotlinScriptDefinitionProvider.getInstance(environment.getProject()).addScriptDefinition(
|
||||
new KotlinScriptDefinition(".kts", scriptParameters)
|
||||
);
|
||||
}
|
||||
GenerationState state = analyzeAndGenerate(environment);
|
||||
if (state == null) {
|
||||
return null;
|
||||
@@ -315,9 +297,7 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
new URLClassLoader(classPaths.toArray(new URL[classPaths.size()]), null)
|
||||
);
|
||||
|
||||
KtScript script = environment.getSourceFiles().get(0).getScript();
|
||||
assert script != null : "Script must be parsed";
|
||||
FqName nameForScript = script.getFqName();
|
||||
FqName nameForScript = ScriptNameUtil.classNameForScript(environment.getSourceFiles().get(0).getScript());
|
||||
return classLoader.loadClass(nameForScript.asString());
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -421,6 +401,7 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
obsoleteMultifileClasses.add(JvmClassName.byInternalName(obsoleteFacadeInternalName).getFqNameForClassNameWithoutDollars());
|
||||
}
|
||||
}
|
||||
BindingTraceContext diagnosticHolder = new BindingTraceContext();
|
||||
GenerationState generationState = new GenerationState(
|
||||
environment.getProject(),
|
||||
ClassBuilderFactories.BINARIES,
|
||||
@@ -433,6 +414,7 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
configuration.get(JVMConfigurationKeys.DISABLE_INLINE, false),
|
||||
configuration.get(JVMConfigurationKeys.DISABLE_OPTIMIZATION, false),
|
||||
/* useTypeTableInSerializer = */ false,
|
||||
diagnosticHolder,
|
||||
packagesWithObsoleteParts,
|
||||
obsoleteMultifileClasses,
|
||||
targetId,
|
||||
@@ -455,7 +437,7 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
|
||||
AnalyzerWithCompilerReport.reportDiagnostics(
|
||||
new FilteredJvmDiagnostics(
|
||||
generationState.getCollectedExtraJvmDiagnostics(),
|
||||
diagnosticHolder.getBindingContext().getDiagnostics(),
|
||||
result.getBindingContext().getDiagnostics()
|
||||
),
|
||||
environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.config;
|
||||
|
||||
import org.jetbrains.kotlin.modules.Module;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.CompilerJarLocator;
|
||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey;
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents;
|
||||
import org.jetbrains.kotlin.modules.Module;
|
||||
import org.jetbrains.kotlin.resolve.AnalyzerScriptParameter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -27,6 +28,9 @@ public class JVMConfigurationKeys {
|
||||
private JVMConfigurationKeys() {
|
||||
}
|
||||
|
||||
public static final CompilerConfigurationKey<List<AnalyzerScriptParameter>> SCRIPT_PARAMETERS =
|
||||
CompilerConfigurationKey.create("script");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> DISABLE_CALL_ASSERTIONS =
|
||||
CompilerConfigurationKey.create("disable not-null call assertions");
|
||||
public static final CompilerConfigurationKey<Boolean> DISABLE_PARAM_ASSERTIONS =
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.jvm.repl;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class EarlierLine {
|
||||
@NotNull
|
||||
@@ -28,17 +29,21 @@ public class EarlierLine {
|
||||
private final Class<?> scriptClass;
|
||||
@NotNull
|
||||
private final Object scriptInstance;
|
||||
@NotNull
|
||||
private final Type classType;
|
||||
|
||||
public EarlierLine(
|
||||
@NotNull String code,
|
||||
@NotNull ScriptDescriptor scriptDescriptor,
|
||||
@NotNull Class<?> scriptClass,
|
||||
@NotNull Object scriptInstance
|
||||
@NotNull Object scriptInstance,
|
||||
@NotNull Type classType
|
||||
) {
|
||||
this.code = code;
|
||||
this.scriptDescriptor = scriptDescriptor;
|
||||
this.scriptClass = scriptClass;
|
||||
this.scriptInstance = scriptInstance;
|
||||
this.classType = classType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -60,4 +65,9 @@ public class EarlierLine {
|
||||
public Object getScriptInstance() {
|
||||
return scriptInstance;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type getClassType() {
|
||||
return classType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,9 @@ import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
@@ -29,6 +30,7 @@ import com.intellij.testFramework.LightVirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport;
|
||||
import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport;
|
||||
@@ -48,7 +50,6 @@ import org.jetbrains.kotlin.codegen.ClassBuilderFactories;
|
||||
import org.jetbrains.kotlin.codegen.CompilationErrorHandler;
|
||||
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.context.MutableModuleContext;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
@@ -56,7 +57,6 @@ import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtScript;
|
||||
@@ -67,10 +67,10 @@ import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM;
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
|
||||
import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo;
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.*;
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
import org.jetbrains.kotlin.script.*;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
@@ -84,9 +84,11 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ReplInterpreter {
|
||||
private static final String SCRIPT_RESULT_FIELD_NAME = "$$result";
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.registerClassNameForScript;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
|
||||
public class ReplInterpreter {
|
||||
private int lineNumber = 0;
|
||||
|
||||
@Nullable
|
||||
@@ -106,24 +108,6 @@ public class ReplInterpreter {
|
||||
|
||||
private final boolean ideMode;
|
||||
private final ReplSystemInWrapper replReader;
|
||||
private final static KotlinScriptDefinition REPL_LINE_AS_SCRIPT_DEFINITION = new KotlinScriptDefinition() {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ScriptParameter> getScriptParameters(@NotNull ScriptDescriptor scriptDescriptor) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScript(@NotNull PsiFile file) {
|
||||
return StandardScriptDefinition.INSTANCE.isScript(file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Name getScriptName(@NotNull KtScript script) {
|
||||
return StandardScriptDefinition.INSTANCE.getScriptName(script);
|
||||
}
|
||||
};
|
||||
|
||||
public ReplInterpreter(
|
||||
@NotNull Disposable disposable,
|
||||
@@ -131,12 +115,9 @@ public class ReplInterpreter {
|
||||
boolean ideMode,
|
||||
@Nullable ReplSystemInWrapper replReader
|
||||
) {
|
||||
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, REPL_LINE_AS_SCRIPT_DEFINITION);
|
||||
|
||||
KotlinCoreEnvironment environment =
|
||||
KotlinCoreEnvironment.createForProduction(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
Project project = environment.getProject();
|
||||
|
||||
this.psiFileFactory = (PsiFileFactoryImpl) PsiFileFactory.getInstance(project);
|
||||
this.trace = new CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace();
|
||||
MutableModuleContext moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(project, ModuleNameKt
|
||||
@@ -281,6 +262,7 @@ public class ReplInterpreter {
|
||||
++lineNumber;
|
||||
|
||||
FqName scriptFqName = new FqName("Line" + lineNumber);
|
||||
Type scriptClassType = asmTypeByFqNameWithoutInnerClasses(scriptFqName);
|
||||
|
||||
StringBuilder fullText = new StringBuilder();
|
||||
for (String prevLine : previousIncompleteLines) {
|
||||
@@ -324,16 +306,16 @@ public class ReplInterpreter {
|
||||
return LineResult.compileError(errorHolder.getRenderedDiagnostics());
|
||||
}
|
||||
|
||||
List<ScriptDescriptor> earlierScripts = Lists.newArrayList();
|
||||
List<Pair<ScriptDescriptor, Type>> earlierScripts = Lists.newArrayList();
|
||||
|
||||
for (EarlierLine earlierLine : earlierLines) {
|
||||
earlierScripts.add(earlierLine.getScriptDescriptor());
|
||||
earlierScripts.add(Pair.create(earlierLine.getScriptDescriptor(), earlierLine.getClassType()));
|
||||
}
|
||||
|
||||
GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.BINARIES,
|
||||
module, trace.getBindingContext(), Collections.singletonList(psiFile));
|
||||
|
||||
compileScript(psiFile.getScript(), earlierScripts, state, CompilationErrorHandler.THROW_EXCEPTION);
|
||||
compileScript(psiFile.getScript(), scriptClassType, earlierScripts, state, CompilationErrorHandler.THROW_EXCEPTION);
|
||||
|
||||
for (OutputFile outputFile : state.getFactory().asList()) {
|
||||
if(outputFile.getRelativePath().endsWith(".class")) {
|
||||
@@ -365,13 +347,14 @@ public class ReplInterpreter {
|
||||
setReplScriptExecuting(false);
|
||||
}
|
||||
|
||||
Field rvField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME);
|
||||
Field rvField = scriptClass.getDeclaredField("rv");
|
||||
rvField.setAccessible(true);
|
||||
Object rv = rvField.get(scriptInstance);
|
||||
|
||||
earlierLines.add(new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance));
|
||||
earlierLines.add(new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance, scriptClassType));
|
||||
|
||||
return LineResult.successful(rv, !state.getReplSpecific().getHasResult());
|
||||
KotlinType returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType();
|
||||
return LineResult.successful(rv, returnType != null && KotlinBuiltIns.isUnit(returnType));
|
||||
}
|
||||
catch (Throwable e) {
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
@@ -432,8 +415,12 @@ public class ReplInterpreter {
|
||||
return null;
|
||||
}
|
||||
|
||||
LazyScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript());
|
||||
lastLineScope = scriptDescriptor.getScopeForInitializerResolution();
|
||||
ScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript());
|
||||
lastLineScope = trace.get(BindingContext.SCRIPT_SCOPE, scriptDescriptor);
|
||||
if (lastLineScope == null) {
|
||||
throw new IllegalStateException("last line scope is not initialized");
|
||||
}
|
||||
|
||||
return scriptDescriptor;
|
||||
}
|
||||
|
||||
@@ -441,14 +428,33 @@ public class ReplInterpreter {
|
||||
classLoader.dumpClasses(out);
|
||||
}
|
||||
|
||||
private static void registerEarlierScripts(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull List<Pair<ScriptDescriptor, Type>> earlierScripts
|
||||
) {
|
||||
List<ScriptDescriptor> earlierScriptDescriptors = new ArrayList<ScriptDescriptor>(earlierScripts.size());
|
||||
for (Pair<ScriptDescriptor, Type> pair : earlierScripts) {
|
||||
ScriptDescriptor earlierDescriptor = pair.first;
|
||||
Type earlierClassType = pair.second;
|
||||
|
||||
PsiElement jetScript = descriptorToDeclaration(earlierDescriptor);
|
||||
if (jetScript != null) {
|
||||
registerClassNameForScript(state.getBindingTrace(), (KtScript) jetScript, earlierClassType, state.getFileClassesProvider());
|
||||
earlierScriptDescriptors.add(earlierDescriptor);
|
||||
}
|
||||
}
|
||||
state.setEarlierScriptsForReplInterpreter(earlierScriptDescriptors);
|
||||
}
|
||||
|
||||
public static void compileScript(
|
||||
@NotNull KtScript script,
|
||||
@NotNull List<ScriptDescriptor> earlierScripts,
|
||||
@NotNull Type classType,
|
||||
@NotNull List<Pair<ScriptDescriptor, Type>> earlierScripts,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull CompilationErrorHandler errorHandler
|
||||
) {
|
||||
state.getReplSpecific().setScriptResultFieldName(SCRIPT_RESULT_FIELD_NAME);
|
||||
state.getReplSpecific().setEarlierScriptsForReplInterpreter(new ArrayList<ScriptDescriptor>(earlierScripts));
|
||||
registerEarlierScripts(state, earlierScripts);
|
||||
registerClassNameForScript(state.getBindingTrace(), script, classType, state.getFileClassesProvider());
|
||||
|
||||
state.beforeCompile();
|
||||
KotlinCodegenFacade.generatePackage(
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
|
||||
import java.io.File
|
||||
|
||||
public class ConsoleReplCommandReader : ReplCommandReader {
|
||||
private val consoleReader = ConsoleReader("kotlin", System.`in`, System.`out`, null).apply {
|
||||
private val consoleReader = ConsoleReader("kotlin", System.`in`, System.`out`, null) apply {
|
||||
isHistoryEnabled = true
|
||||
expandEvents = false
|
||||
history = FileHistory(File(File(System.getProperty("user.home")), ".kotlin_history"))
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
||||
|
||||
data class PositionalAndNamedArguments(val positional: List<ValueArgument>, val named: List<ValueArgument>)
|
||||
{
|
||||
operator fun get(position: Int, name: String): ValueArgument? =
|
||||
fun get(position: Int, name: String): ValueArgument? =
|
||||
positional.getOrNull(position) ?: named.find { it.getArgumentName()!!.asName.asString() == name }
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.container
|
||||
import java.util.ArrayList
|
||||
import java.util.HashSet
|
||||
|
||||
public fun <T> topologicalSort(items: Iterable<T>, dependencies: (T) -> Iterable<T>): List<T> {
|
||||
public fun topologicalSort<T>(items: Iterable<T>, dependencies: (T) -> Iterable<T>): List<T> {
|
||||
val itemsInProgress = HashSet<T>()
|
||||
val completedItems = HashSet<T>()
|
||||
val result = ArrayList<T>()
|
||||
@@ -45,7 +45,7 @@ public fun <T> topologicalSort(items: Iterable<T>, dependencies: (T) -> Iterable
|
||||
for (item in items)
|
||||
DfsVisit(item)
|
||||
|
||||
return result.apply { reverse() }
|
||||
return result.reversed()
|
||||
}
|
||||
|
||||
public class CycleInTopoSortException : Exception()
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.container
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun createContainer(id: String, init: StorageComponentContainer.() -> Unit): StorageComponentContainer {
|
||||
val c = StorageComponentContainer(id)
|
||||
c.init()
|
||||
@@ -26,11 +24,11 @@ public fun createContainer(id: String, init: StorageComponentContainer.() -> Uni
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any> StorageComponentContainer.useImpl() {
|
||||
registerSingleton(T::class.java)
|
||||
registerSingleton(javaClass<T>())
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any> ComponentProvider.get(): T {
|
||||
return getService(T::class.java)
|
||||
return getService(javaClass<T>())
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -42,6 +40,6 @@ public fun StorageComponentContainer.useInstance(instance: Any) {
|
||||
registerInstance(instance)
|
||||
}
|
||||
|
||||
inline operator fun <reified T : Any> ComponentProvider.getValue(thisRef: Any?, desc: KProperty<*>): T {
|
||||
return getService(T::class.java)
|
||||
public inline fun <reified T : Any> ComponentProvider.get(thisRef: Any?, desc: PropertyMetadata): T {
|
||||
return getService(javaClass<T>())
|
||||
}
|
||||
|
||||
@@ -1,82 +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.daemon.common
|
||||
|
||||
import java.io.File
|
||||
import java.rmi.ConnectException
|
||||
import java.rmi.registry.LocateRegistry
|
||||
|
||||
|
||||
internal val MAX_PORT_NUMBER = 0xffff
|
||||
|
||||
|
||||
enum class DaemonReportCategory {
|
||||
DEBUG, INFO, EXCEPTION;
|
||||
}
|
||||
|
||||
|
||||
fun makeRunFilenameString(timestamp: String, digest: String, port: String, escapeSequence: String = ""): String =
|
||||
"${COMPILE_DAEMON_DEFAULT_FILES_PREFIX}$escapeSequence.$timestamp$escapeSequence.$digest$escapeSequence.$port$escapeSequence.run"
|
||||
|
||||
|
||||
fun makePortFromRunFilenameExtractor(digest: String): (String) -> Int? {
|
||||
val regex = makeRunFilenameString(timestamp = "[0-9TZ:\\.\\+-]+", digest = digest, port = "(\\d+)", escapeSequence = "\\").toRegex()
|
||||
return { regex.find(it)
|
||||
?.groups?.get(1)
|
||||
?.value?.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun walkDaemons(registryDir: File,
|
||||
compilerId: CompilerId,
|
||||
filter: (File, Int) -> Boolean = { f, p -> true },
|
||||
report: (DaemonReportCategory, String) -> Unit = { cat, msg -> }
|
||||
): Sequence<CompileService> {
|
||||
val classPathDigest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest().toHexString()
|
||||
val portExtractor = makePortFromRunFilenameExtractor(classPathDigest)
|
||||
return registryDir.walk()
|
||||
.map { Pair(it, portExtractor(it.name)) }
|
||||
.filter { it.second != null && filter(it.first, it.second!!) }
|
||||
.mapNotNull {
|
||||
assert(it.second!! > 0 && it.second!! < MAX_PORT_NUMBER)
|
||||
report(DaemonReportCategory.DEBUG, "found daemon on port ${it.second}, trying to connect")
|
||||
val daemon = tryConnectToDaemon(it.second!!, report)
|
||||
// cleaning orphaned file; note: daemon should shut itself down if it detects that the run file is deleted
|
||||
if (daemon == null && !it.first.delete()) {
|
||||
report(DaemonReportCategory.INFO, "WARNING: unable to delete seemingly orphaned file '${it.first.absolutePath}', cleanup recommended")
|
||||
}
|
||||
daemon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private inline fun tryConnectToDaemon(port: Int, report: (DaemonReportCategory, String) -> Unit): CompileService? {
|
||||
try {
|
||||
val daemon = LocateRegistry.getRegistry(LoopbackNetworkInterface.loopbackInetAddressName, port)
|
||||
?.lookup(COMPILER_SERVICE_RMI_NAME)
|
||||
if (daemon != null)
|
||||
return daemon as? CompileService ?:
|
||||
throw ClassCastException("Unable to cast compiler service, actual class received: ${daemon.javaClass}")
|
||||
report(DaemonReportCategory.EXCEPTION, "daemon not found")
|
||||
}
|
||||
catch (e: ConnectException) {
|
||||
report(DaemonReportCategory.EXCEPTION, "cannot connect to registry: " + (e.cause?.message ?: e.message ?: "unknown exception"))
|
||||
// ignoring it - processing below
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -1,125 +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.daemon.common
|
||||
|
||||
import java.io.Serializable
|
||||
import java.rmi.Remote
|
||||
import java.rmi.RemoteException
|
||||
|
||||
interface CompileService : Remote {
|
||||
|
||||
enum class OutputFormat : Serializable {
|
||||
PLAIN,
|
||||
XML
|
||||
}
|
||||
|
||||
enum class TargetPlatform : Serializable {
|
||||
JVM,
|
||||
JS
|
||||
}
|
||||
|
||||
companion object {
|
||||
val NO_SESSION: Int = 0
|
||||
}
|
||||
|
||||
sealed class CallResult<out R> : Serializable {
|
||||
|
||||
class Good<R>(val result: R) : CallResult<R>() {
|
||||
override fun get(): R = result
|
||||
override fun equals(other: Any?): Boolean = other is Good<*> && this.result == other.result
|
||||
override fun hashCode(): Int = this.javaClass.hashCode() + (result?.hashCode() ?: 1)
|
||||
}
|
||||
class Ok : CallResult<Nothing>() {
|
||||
override fun get(): Nothing = throw IllegalStateException("Gey is inapplicable to Ok call result")
|
||||
override fun equals(other: Any?): Boolean = other is Ok
|
||||
override fun hashCode(): Int = this.javaClass.hashCode() + 1 // avoiding clash with the hash of class itself
|
||||
}
|
||||
class Dying : CallResult<Nothing>() {
|
||||
override fun get(): Nothing = throw IllegalStateException("Service is dying")
|
||||
override fun equals(other: Any?): Boolean = other is Dying
|
||||
override fun hashCode(): Int = this.javaClass.hashCode() + 1 // see comment to Ok.hashCode
|
||||
}
|
||||
class Error(val message: String) : CallResult<Nothing>() {
|
||||
override fun get(): Nothing = throw Exception(message)
|
||||
override fun equals(other: Any?): Boolean = other is Error && this.message == other.message
|
||||
override fun hashCode(): Int = this.javaClass.hashCode() + message.hashCode()
|
||||
}
|
||||
|
||||
val isGood: Boolean get() = this is Good<*>
|
||||
|
||||
abstract fun get(): R
|
||||
}
|
||||
|
||||
// TODO: remove!
|
||||
@Throws(RemoteException::class)
|
||||
fun checkCompilerId(expectedCompilerId: CompilerId): Boolean
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun getUsedMemory(): CallResult<Long>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun getDaemonOptions(): CallResult<DaemonOptions>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun getDaemonJVMOptions(): CallResult<DaemonJVMOptions>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun registerClient(aliveFlagPath: String?): CallResult<Nothing>
|
||||
|
||||
// TODO: consider adding another client alive checking mechanism, e.g. socket/port
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun getClients(): CallResult<List<String>>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun leaseCompileSession(aliveFlagPath: String?): CallResult<Int>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun releaseCompileSession(sessionId: Int): CallResult<Nothing>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun shutdown(): CallResult<Nothing>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun scheduleShutdown(graceful: Boolean): CallResult<Boolean>
|
||||
|
||||
// TODO: consider adding async version of shutdown and release
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun remoteCompile(
|
||||
sessionId: Int,
|
||||
targetPlatform: TargetPlatform,
|
||||
args: Array<out String>,
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
outputFormat: OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): CallResult<Int>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun remoteIncrementalCompile(
|
||||
sessionId: Int,
|
||||
targetPlatform: TargetPlatform,
|
||||
args: Array<out String>,
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
compilerOutputFormat: OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): CallResult<Int>
|
||||
}
|
||||
@@ -1,561 +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.daemon
|
||||
|
||||
import com.intellij.openapi.vfs.impl.ZipHandler
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.rmi.NoSuchObjectException
|
||||
import java.rmi.registry.Registry
|
||||
import java.rmi.server.UnicastRemoteObject
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import java.util.logging.Level
|
||||
import java.util.logging.Logger
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.schedule
|
||||
import kotlin.concurrent.write
|
||||
|
||||
fun nowSeconds() = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime())
|
||||
|
||||
interface CompilerSelector {
|
||||
operator fun get(targetPlatform: CompileService.TargetPlatform): CLICompiler<*>
|
||||
}
|
||||
|
||||
interface EventManger {
|
||||
fun onCompilationFinished(f : () -> Unit)
|
||||
}
|
||||
|
||||
private class EventMangerImpl : EventManger {
|
||||
private val onCompilationFinished = arrayListOf<() -> Unit>()
|
||||
|
||||
override fun onCompilationFinished(f: () -> Unit) {
|
||||
onCompilationFinished.add(f)
|
||||
}
|
||||
|
||||
fun fireCompilationFinished() {
|
||||
onCompilationFinished.forEach { it() }
|
||||
}
|
||||
}
|
||||
|
||||
class CompileServiceImpl(
|
||||
val registry: Registry,
|
||||
val compiler: CompilerSelector,
|
||||
val compilerId: CompilerId,
|
||||
val daemonOptions: DaemonOptions,
|
||||
val daemonJVMOptions: DaemonJVMOptions,
|
||||
val port: Int,
|
||||
val timer: Timer,
|
||||
val onShutdown: () -> Unit
|
||||
) : CompileService {
|
||||
|
||||
// wrapped in a class to encapsulate alive check logic
|
||||
private class ClientOrSessionProxy(val aliveFlagPath: String?) {
|
||||
val registered = nowSeconds()
|
||||
val secondsSinceRegistered: Long get() = nowSeconds() - registered
|
||||
val isAlive: Boolean get() = aliveFlagPath?.let { File(it).exists() } ?: true // assuming that if no file was given, the client is alive
|
||||
}
|
||||
|
||||
private val sessionsIdCounter = AtomicInteger(0)
|
||||
private val compilationsCounter = AtomicInteger(0)
|
||||
private val internalRng = Random()
|
||||
|
||||
private val classpathWatcher = LazyClasspathWatcher(compilerId.compilerClasspath)
|
||||
|
||||
enum class Aliveness {
|
||||
// !!! ordering of values is used in state comparison
|
||||
Dying, LastSession, Alive
|
||||
}
|
||||
|
||||
// TODO: encapsulate operations on state here
|
||||
private val state = object {
|
||||
|
||||
val clientProxies: MutableSet<ClientOrSessionProxy> = hashSetOf()
|
||||
val sessions: MutableMap<Int, ClientOrSessionProxy> = hashMapOf()
|
||||
|
||||
val delayedShutdownQueued = AtomicBoolean(false)
|
||||
|
||||
var alive = AtomicInteger(Aliveness.Alive.ordinal)
|
||||
}
|
||||
|
||||
@Volatile private var _lastUsedSeconds = nowSeconds()
|
||||
val lastUsedSeconds: Long get() = if (rwlock.isWriteLocked || rwlock.readLockCount - rwlock.readHoldCount > 0) nowSeconds() else _lastUsedSeconds
|
||||
|
||||
private val log by lazy { Logger.getLogger("compiler") }
|
||||
|
||||
private val rwlock = ReentrantReadWriteLock()
|
||||
|
||||
private var runFile: File
|
||||
|
||||
init {
|
||||
val runFileDir = File(daemonOptions.runFilesPathOrDefault)
|
||||
runFileDir.mkdirs()
|
||||
runFile = File(runFileDir,
|
||||
makeRunFilenameString(timestamp = "%tFT%<tH-%<tM-%<tS.%<tLZ".format(Calendar.getInstance(TimeZone.getTimeZone("Z"))),
|
||||
digest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest().toHexString(),
|
||||
port = port.toString()))
|
||||
try {
|
||||
if (!runFile.createNewFile()) throw Exception("createNewFile returned false")
|
||||
} catch (e: Exception) {
|
||||
throw IllegalStateException("Unable to create run file '${runFile.absolutePath}'", e)
|
||||
}
|
||||
runFile.deleteOnExit()
|
||||
}
|
||||
|
||||
// RMI-exposed API
|
||||
|
||||
override fun getDaemonOptions(): CompileService.CallResult<DaemonOptions> = ifAlive { daemonOptions }
|
||||
|
||||
override fun getDaemonJVMOptions(): CompileService.CallResult<DaemonJVMOptions> = ifAlive { daemonJVMOptions }
|
||||
|
||||
override fun registerClient(aliveFlagPath: String?): CompileService.CallResult<Nothing> = ifAlive_Nothing {
|
||||
synchronized(state.clientProxies) {
|
||||
state.clientProxies.add(ClientOrSessionProxy(aliveFlagPath))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getClients(): CompileService.CallResult<List<String>> = ifAlive {
|
||||
synchronized(state.clientProxies) {
|
||||
state.clientProxies.mapNotNull { it.aliveFlagPath }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consider tying a session to a client and use this info to cleanup
|
||||
override fun leaseCompileSession(aliveFlagPath: String?): CompileService.CallResult<Int> = ifAlive(minAliveness = Aliveness.Alive) {
|
||||
// fighting hypothetical integer wrapping
|
||||
var newId = sessionsIdCounter.incrementAndGet()
|
||||
val session = ClientOrSessionProxy(aliveFlagPath)
|
||||
for (attempt in 1..100) {
|
||||
if (newId != CompileService.NO_SESSION) {
|
||||
synchronized(state.sessions) {
|
||||
if (!state.sessions.containsKey(newId)) {
|
||||
state.sessions.put(newId, session)
|
||||
log.info("leased a new session $newId, client alive file: $aliveFlagPath")
|
||||
return@ifAlive newId
|
||||
}
|
||||
}
|
||||
}
|
||||
// assuming wrap, jumping to random number to reduce probability of further clashes
|
||||
newId = sessionsIdCounter.addAndGet(internalRng.nextInt())
|
||||
}
|
||||
throw IllegalStateException("Invalid state or algorithm error")
|
||||
}
|
||||
|
||||
override fun releaseCompileSession(sessionId: Int) = ifAlive_Nothing(minAliveness = Aliveness.LastSession) {
|
||||
synchronized(state.sessions) {
|
||||
state.sessions.remove(sessionId)
|
||||
log.info("cleaning after session $sessionId")
|
||||
clearJarCache()
|
||||
if (state.sessions.isEmpty()) {
|
||||
// TODO: and some goes here
|
||||
}
|
||||
}
|
||||
timer.schedule(0) {
|
||||
periodicAndAfterSessionCheck()
|
||||
}
|
||||
}
|
||||
|
||||
override fun checkCompilerId(expectedCompilerId: CompilerId): Boolean =
|
||||
(compilerId.compilerVersion.isEmpty() || compilerId.compilerVersion == expectedCompilerId.compilerVersion) &&
|
||||
(compilerId.compilerClasspath.all { expectedCompilerId.compilerClasspath.contains(it) }) &&
|
||||
!classpathWatcher.isChanged
|
||||
|
||||
override fun getUsedMemory(): CompileService.CallResult<Long> = ifAlive { usedMemory(withGC = true) }
|
||||
|
||||
override fun shutdown(): CompileService.CallResult<Nothing> = ifAliveExclusive_Nothing(minAliveness = Aliveness.LastSession, ignoreCompilerChanged = true) {
|
||||
shutdownImpl()
|
||||
}
|
||||
|
||||
override fun scheduleShutdown(graceful: Boolean): CompileService.CallResult<Boolean> = ifAlive(minAliveness = Aliveness.Alive) {
|
||||
if (!graceful || state.alive.compareAndSet(Aliveness.Alive.ordinal, Aliveness.LastSession.ordinal)) {
|
||||
timer.schedule(0) {
|
||||
ifAliveExclusive(minAliveness = Aliveness.LastSession, ignoreCompilerChanged = true) {
|
||||
if (!graceful || state.sessions.isEmpty()) {
|
||||
shutdownImpl()
|
||||
}
|
||||
else {
|
||||
log.info("Some sessions are active, waiting for them to finish")
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
else false
|
||||
}
|
||||
|
||||
override fun remoteCompile(sessionId: Int,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
args: Array<out String>,
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
outputFormat: CompileService.OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): CompileService.CallResult<Int> =
|
||||
doCompile(sessionId, args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, eventManager, profiler ->
|
||||
when (outputFormat) {
|
||||
CompileService.OutputFormat.PLAIN -> compiler[targetPlatform].exec(printStream, *args)
|
||||
CompileService.OutputFormat.XML -> compiler[targetPlatform].execAndOutputXml(printStream, createCompileServices(servicesFacade, eventManager, profiler), *args)
|
||||
}
|
||||
}
|
||||
|
||||
override fun remoteIncrementalCompile(sessionId: Int,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
args: Array<out String>,
|
||||
servicesFacade: CompilerCallbackServicesFacade,
|
||||
compilerOutputStream: RemoteOutputStream,
|
||||
compilerOutputFormat: CompileService.OutputFormat,
|
||||
serviceOutputStream: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?
|
||||
): CompileService.CallResult<Int> =
|
||||
doCompile(sessionId, args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, eventManager, profiler ->
|
||||
when (compilerOutputFormat) {
|
||||
CompileService.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation")
|
||||
CompileService.OutputFormat.XML -> compiler[targetPlatform].execAndOutputXml(printStream, createCompileServices(servicesFacade, eventManager, profiler), *args)
|
||||
}
|
||||
}
|
||||
|
||||
// internal implementation stuff
|
||||
|
||||
// TODO: consider matching compilerId coming from outside with actual one
|
||||
// private val selfCompilerId by lazy {
|
||||
// CompilerId(
|
||||
// compilerClasspath = System.getProperty("java.class.path")
|
||||
// ?.split(File.pathSeparator)
|
||||
// ?.map { File(it) }
|
||||
// ?.filter { it.exists() }
|
||||
// ?.map { it.absolutePath }
|
||||
// ?: listOf(),
|
||||
// compilerVersion = loadKotlinVersionFromResource()
|
||||
// )
|
||||
// }
|
||||
|
||||
init {
|
||||
// assuming logically synchronized
|
||||
try {
|
||||
// cleanup for the case of incorrect restart and many other situations
|
||||
UnicastRemoteObject.unexportObject(this, false)
|
||||
}
|
||||
catch (e: NoSuchObjectException) {
|
||||
// ignoring if object already exported
|
||||
}
|
||||
|
||||
val stub = UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory) as CompileService
|
||||
registry.rebind (COMPILER_SERVICE_RMI_NAME, stub);
|
||||
|
||||
timer.schedule(0) {
|
||||
initiateElections()
|
||||
}
|
||||
timer.schedule(delay = DAEMON_PERIODIC_CHECK_INTERVAL_MS, period = DAEMON_PERIODIC_CHECK_INTERVAL_MS) {
|
||||
try {
|
||||
periodicAndAfterSessionCheck()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
System.err.println("Exception in timer thread: " + e.message)
|
||||
e.printStackTrace(System.err)
|
||||
log.log(Level.SEVERE, "Exception in timer thread", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun periodicAndAfterSessionCheck() {
|
||||
|
||||
ifAlive_Nothing(minAliveness = Aliveness.LastSession) {
|
||||
|
||||
// 1. check if unused for a timeout - shutdown
|
||||
if (shutdownCondition({ daemonOptions.autoshutdownUnusedSeconds != COMPILE_DAEMON_TIMEOUT_INFINITE_S && compilationsCounter.get() == 0 && nowSeconds() - lastUsedSeconds > daemonOptions.autoshutdownUnusedSeconds },
|
||||
"Unused timeout exceeded ${daemonOptions.autoshutdownUnusedSeconds}s, shutting down")) {
|
||||
shutdown()
|
||||
}
|
||||
else {
|
||||
synchronized(state.sessions) {
|
||||
// 2. check if any session hanged - clean
|
||||
// making copy of the list before calling release
|
||||
state.sessions.filterValues { !it.isAlive }.keys.toArrayList()
|
||||
}.forEach { releaseCompileSession(it) }
|
||||
|
||||
// 3. check if in graceful shutdown state and all sessions are closed
|
||||
if (shutdownCondition({ state.alive.get() == Aliveness.LastSession.ordinal && state.sessions.none()}, "All sessions finished, shutting down")) {
|
||||
shutdown()
|
||||
}
|
||||
|
||||
// 4. clean dead clients, then check if any left - conditional shutdown (with small delay)
|
||||
synchronized(state.clientProxies) { state.clientProxies.removeAll(state.clientProxies.filter { !it.isAlive }) }
|
||||
if (state.clientProxies.isEmpty() && compilationsCounter.get() > 0 && !state.delayedShutdownQueued.get()) {
|
||||
log.info("No more clients left, delayed shutdown in ${daemonOptions.shutdownDelayMilliseconds}ms")
|
||||
shutdownWithDelay()
|
||||
}
|
||||
// 5. check idle timeout - shutdown
|
||||
if (shutdownCondition({ daemonOptions.autoshutdownIdleSeconds != COMPILE_DAEMON_TIMEOUT_INFINITE_S && nowSeconds() - lastUsedSeconds > daemonOptions.autoshutdownIdleSeconds },
|
||||
"Idle timeout exceeded ${daemonOptions.autoshutdownIdleSeconds}s, shutting down") ||
|
||||
// 6. discovery file removed - shutdown
|
||||
shutdownCondition({ !runFile.exists() }, "Run file removed, shutting down") ||
|
||||
// 7. compiler changed (seldom check) - shutdown
|
||||
// TODO: could be too expensive anyway, consider removing this check
|
||||
shutdownCondition({ classpathWatcher.isChanged }, "Compiler changed")) {
|
||||
shutdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun initiateElections() {
|
||||
|
||||
ifAlive_Nothing {
|
||||
|
||||
val aliveWithOpts = walkDaemons(File(daemonOptions.runFilesPathOrDefault), compilerId, filter = { f, p -> p != port }, report = { lvl, msg -> log.info(msg) })
|
||||
.map { Pair(it, it.getDaemonJVMOptions()) }
|
||||
.filter { it.second.isGood }
|
||||
.sortedWith(compareBy(DaemonJVMOptionsMemoryComparator().reversed(), { it.second.get() }))
|
||||
if (aliveWithOpts.any()) {
|
||||
val fattestOpts = aliveWithOpts.first().second.get()
|
||||
// second part of the condition means that we prefer other daemon if is "equal" to the current one
|
||||
if (fattestOpts memorywiseFitsInto daemonJVMOptions && !(daemonJVMOptions memorywiseFitsInto fattestOpts)) {
|
||||
// all others are smaller that me, take overs' clients and shut them down
|
||||
aliveWithOpts.forEach {
|
||||
it.first.getClients().check { it.isGood }?.let {
|
||||
it.get().forEach { registerClient(it) }
|
||||
}
|
||||
it.first.scheduleShutdown(true)
|
||||
}
|
||||
}
|
||||
else if (daemonJVMOptions memorywiseFitsInto fattestOpts) {
|
||||
// there is at least one bigger, handover my clients to it and shutdown
|
||||
scheduleShutdown(true)
|
||||
aliveWithOpts.first().first.let { fattest ->
|
||||
getClients().check { it.isGood }?.let {
|
||||
it.get().forEach { fattest.registerClient(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
// else - do nothing, all daemons are staying
|
||||
// TODO: implement some behaviour here, e.g.:
|
||||
// - shutdown/takeover smaller daemon
|
||||
// - run (or better persuade client to run) a bigger daemon (in fact may be even simple shutdown will do, because of client's daemon choosing logic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shutdownImpl() {
|
||||
log.info("Shutdown started")
|
||||
state.alive.set(Aliveness.Dying.ordinal)
|
||||
UnicastRemoteObject.unexportObject(this, true)
|
||||
log.info("Shutdown complete")
|
||||
onShutdown()
|
||||
}
|
||||
|
||||
private fun shutdownWithDelay() {
|
||||
state.delayedShutdownQueued.set(true)
|
||||
val currentCompilationsCount = compilationsCounter.get()
|
||||
timer.schedule(daemonOptions.shutdownDelayMilliseconds) {
|
||||
state.delayedShutdownQueued.set(false)
|
||||
if (currentCompilationsCount == compilationsCounter.get()) {
|
||||
log.fine("Execute delayed shutdown")
|
||||
shutdown()
|
||||
}
|
||||
else {
|
||||
log.info("Cancel delayed shutdown due to new client")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun shutdownCondition(check: () -> Boolean, message: String): Boolean {
|
||||
val res = check()
|
||||
if (res) {
|
||||
log.info(message)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
private fun doCompile(sessionId: Int,
|
||||
args: Array<out String>,
|
||||
compilerMessagesStreamProxy: RemoteOutputStream,
|
||||
serviceOutputStreamProxy: RemoteOutputStream,
|
||||
operationsTracer: RemoteOperationsTracer?,
|
||||
body: (PrintStream, EventManger, Profiler) -> ExitCode): CompileService.CallResult<Int> =
|
||||
ifAlive {
|
||||
|
||||
operationsTracer?.before("compile")
|
||||
compilationsCounter.incrementAndGet()
|
||||
val rpcProfiler = if (daemonOptions.reportPerf) WallAndThreadTotalProfiler() else DummyProfiler()
|
||||
val eventManger = EventMangerImpl()
|
||||
val compilerMessagesStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(compilerMessagesStreamProxy, rpcProfiler), 4096))
|
||||
val serviceOutputStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(serviceOutputStreamProxy, rpcProfiler), 4096))
|
||||
try {
|
||||
checkedCompile(args, serviceOutputStream, rpcProfiler) {
|
||||
val res = body(compilerMessagesStream, eventManger, rpcProfiler).code
|
||||
_lastUsedSeconds = nowSeconds()
|
||||
res
|
||||
}
|
||||
}
|
||||
finally {
|
||||
serviceOutputStream.flush()
|
||||
compilerMessagesStream.flush()
|
||||
eventManger.fireCompilationFinished()
|
||||
operationsTracer?.after("compile")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCompileServices(facade: CompilerCallbackServicesFacade, eventManger: EventManger, rpcProfiler: Profiler): Services {
|
||||
val builder = Services.Builder()
|
||||
if (facade.hasIncrementalCaches() || facade.hasLookupTracker()) {
|
||||
builder.register(IncrementalCompilationComponents::class.java, RemoteIncrementalCompilationComponentsClient(facade, eventManger, rpcProfiler))
|
||||
}
|
||||
if (facade.hasCompilationCanceledStatus()) {
|
||||
builder.register(CompilationCanceledStatus::class.java, RemoteCompilationCanceledStatusClient(facade, rpcProfiler))
|
||||
}
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
|
||||
private fun<R> checkedCompile(args: Array<out String>, serviceOut: PrintStream, rpcProfiler: Profiler, body: () -> R): R {
|
||||
try {
|
||||
if (args.none())
|
||||
throw IllegalArgumentException("Error: empty arguments list.")
|
||||
log.info("Starting compilation with args: " + args.joinToString(" "))
|
||||
|
||||
val profiler = if (daemonOptions.reportPerf) WallAndThreadAndMemoryTotalProfiler(withGC = false) else DummyProfiler()
|
||||
|
||||
val res = profiler.withMeasure(null, body)
|
||||
|
||||
val endMem = if (daemonOptions.reportPerf) usedMemory(withGC = false) else 0L
|
||||
|
||||
log.info("Done with result " + res.toString())
|
||||
|
||||
if (daemonOptions.reportPerf) {
|
||||
fun Long.ms() = TimeUnit.NANOSECONDS.toMillis(this)
|
||||
fun Long.kb() = this / 1024
|
||||
val pc = profiler.getTotalCounters()
|
||||
val rpc = rpcProfiler.getTotalCounters()
|
||||
|
||||
"PERF: Compile on daemon: ${pc.time.ms()} ms; thread: user ${pc.threadUserTime.ms()} ms, sys ${(pc.threadTime - pc.threadUserTime).ms()} ms; rpc: ${rpc.count} calls, ${rpc.time.ms()} ms, thread ${rpc.threadTime.ms()} ms; memory: ${endMem.kb()} kb (${"%+d".format(pc.memory.kb())} kb)".let {
|
||||
serviceOut.println(it)
|
||||
log.info(it)
|
||||
}
|
||||
|
||||
// this will only be reported if if appropriate (e.g. ByClass) profiler is used
|
||||
for ((obj, counters) in rpcProfiler.getCounters()) {
|
||||
"PERF: rpc by $obj: ${counters.count} calls, ${counters.time.ms()} ms, thread ${counters.threadTime.ms()} ms".let {
|
||||
serviceOut.println(it)
|
||||
log.info(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
// TODO: consider possibilities to handle OutOfMemory
|
||||
catch (e: Exception) {
|
||||
log.info("Error: $e")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearJarCache() {
|
||||
ZipHandler.clearFileAccessorCache()
|
||||
val classloader = javaClass.classLoader
|
||||
// TODO: replace the following code with direct call to CoreJarFileSystem.<clearCache> as soon as it will be available (hopefully in 15.02)
|
||||
try {
|
||||
KotlinCoreEnvironment.applicationEnvironment?.jarFileSystem.let { jarfs ->
|
||||
val jarfsClass = classloader.loadClass("com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem")
|
||||
val privateHandlersField = jarfsClass.getDeclaredField("myHandlers")
|
||||
privateHandlersField.isAccessible = true
|
||||
privateHandlersField.get(jarfs)?.let {
|
||||
val clearMethod = privateHandlersField.type.getMethod("clear")
|
||||
if (clearMethod != null) {
|
||||
clearMethod.invoke(it)
|
||||
log.info("successfully cleared com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem.myHandlers")
|
||||
}
|
||||
else {
|
||||
log.info("unable to access com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem.myHandlers.clear")
|
||||
}
|
||||
} ?: log.info("unable to access CoreJarFileSystem.myHandlers (${privateHandlersField.get(jarfs)})")
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
log.log(Level.SEVERE, "error clearing CoreJarFileSystem", e)
|
||||
}
|
||||
}
|
||||
|
||||
// copied (with edit) from gradle plugin
|
||||
private fun callVoidStaticMethod(classFqName: String, methodName: String) {
|
||||
// compiler classloader == current classloader for now
|
||||
// TODO: consider abstracting classloader, for easier changing it for a compiler
|
||||
val cls = this.javaClass.classLoader.loadClass(classFqName)
|
||||
|
||||
val method = cls.getMethod(methodName)
|
||||
|
||||
method.invoke(null)
|
||||
}
|
||||
|
||||
private fun<R> ifAlive(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> R): CompileService.CallResult<R> = rwlock.read {
|
||||
ifAliveChecksImpl(minAliveness, ignoreCompilerChanged) { CompileService.CallResult.Good(body()) }
|
||||
}
|
||||
|
||||
// TODO: find how to implement it without using unique name for this variant; making name deliberately ugly meanwhile
|
||||
private fun ifAlive_Nothing(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> Unit): CompileService.CallResult<Nothing> = rwlock.read {
|
||||
ifAliveChecksImpl(minAliveness, ignoreCompilerChanged) {
|
||||
body()
|
||||
CompileService.CallResult.Ok()
|
||||
}
|
||||
}
|
||||
|
||||
private fun<R> ifAliveExclusive(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> R): CompileService.CallResult<R> = rwlock.write {
|
||||
ifAliveChecksImpl(minAliveness, ignoreCompilerChanged) { CompileService.CallResult.Good(body()) }
|
||||
}
|
||||
|
||||
// see comment to ifAliveNothing
|
||||
private fun<R> ifAliveExclusive_Nothing(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> Unit): CompileService.CallResult<R> = rwlock.write {
|
||||
ifAliveChecksImpl(minAliveness, ignoreCompilerChanged) {
|
||||
body()
|
||||
CompileService.CallResult.Ok()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline private fun<R> ifAliveChecksImpl(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> CompileService.CallResult<R>): CompileService.CallResult<R> =
|
||||
when {
|
||||
state.alive.get() < minAliveness.ordinal -> CompileService.CallResult.Dying()
|
||||
!ignoreCompilerChanged && classpathWatcher.isChanged -> {
|
||||
log.info("Compiler changed, scheduling shutdown")
|
||||
timer.schedule(0) { shutdown() }
|
||||
CompileService.CallResult.Dying()
|
||||
}
|
||||
else -> {
|
||||
try {
|
||||
body()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
log.log(Level.SEVERE, "Exception", e)
|
||||
CompileService.CallResult.Error(e.message ?: "unknown")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +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.daemon
|
||||
|
||||
import org.jetbrains.kotlin.incremental.components.LookupInfo
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.components.Position
|
||||
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||
import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade
|
||||
import org.jetbrains.kotlin.daemon.common.DummyProfiler
|
||||
import org.jetbrains.kotlin.daemon.common.Profiler
|
||||
|
||||
|
||||
class RemoteLookupTrackerClient(val facade: CompilerCallbackServicesFacade, val eventManger: EventManger, val profiler: Profiler = DummyProfiler()) : LookupTracker {
|
||||
private val isDoNothing = profiler.withMeasure(this) { facade.lookupTracker_isDoNothing() }
|
||||
|
||||
private val lookups = hashSetOf<LookupInfo>()
|
||||
|
||||
override val requiresPosition: Boolean = profiler.withMeasure(this) { facade.lookupTracker_requiresPosition() }
|
||||
|
||||
override fun record(filePath: String, position: Position, scopeFqName: String, scopeKind: ScopeKind, name: String) {
|
||||
if (isDoNothing) return
|
||||
|
||||
lookups.add(LookupInfo(filePath, position, scopeFqName, scopeKind, name))
|
||||
}
|
||||
|
||||
init {
|
||||
eventManger.onCompilationFinished { flush() }
|
||||
}
|
||||
|
||||
private fun flush() {
|
||||
if (isDoNothing || lookups.isEmpty()) return
|
||||
|
||||
profiler.withMeasure(this) {
|
||||
facade.lookupTracker_record(lookups)
|
||||
}
|
||||
|
||||
lookups.clear()
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,16 @@ import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.getImplClassNameForDeserialized
|
||||
import org.jetbrains.kotlin.load.java.descriptors.getImplClassNameForProto
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
|
||||
|
||||
public object JvmFileClassUtil {
|
||||
public val JVM_NAME: FqName = FqName("kotlin.jvm.JvmName")
|
||||
|
||||
@@ -22,21 +22,30 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
interface JvmFileClassesProvider {
|
||||
fun getFileClassInfo(file: KtFile): JvmFileClassInfo
|
||||
public interface JvmFileClassesProvider {
|
||||
public fun getFileClassInfo(file: KtFile): JvmFileClassInfo
|
||||
}
|
||||
|
||||
val FqName.internalNameWithoutInnerClasses: String
|
||||
get() = JvmClassName.byFqNameWithoutInnerClasses(this).internalName
|
||||
public fun FqName.getInternalName(): String =
|
||||
JvmClassName.byFqNameWithoutInnerClasses(this).internalName
|
||||
|
||||
fun JvmFileClassesProvider.getFileClassFqName(file: KtFile): FqName =
|
||||
public fun FqName.getClassType(): Type =
|
||||
Type.getObjectType(getInternalName())
|
||||
|
||||
public fun JvmFileClassesProvider.getFileClassFqName(file: KtFile): FqName =
|
||||
getFileClassInfo(file).fileClassFqName
|
||||
|
||||
fun JvmFileClassesProvider.getFileClassInternalName(file: KtFile): String =
|
||||
getFileClassFqName(file).internalNameWithoutInnerClasses
|
||||
public fun JvmFileClassesProvider.getFileClassInternalName(file: KtFile): String =
|
||||
getFileClassFqName(file).getInternalName()
|
||||
|
||||
fun JvmFileClassesProvider.getFileClassType(file: KtFile): Type =
|
||||
Type.getObjectType(getFileClassFqName(file).internalNameWithoutInnerClasses)
|
||||
public fun JvmFileClassesProvider.getFileClassType(file: KtFile): Type =
|
||||
getFileClassFqName(file).getClassType()
|
||||
|
||||
fun JvmFileClassesProvider.getFacadeClassInternalName(file: KtFile): String =
|
||||
getFileClassInfo(file).facadeClassFqName.internalNameWithoutInnerClasses
|
||||
public fun JvmFileClassesProvider.getFacadeClassFqName(file: KtFile): FqName =
|
||||
getFileClassInfo(file).facadeClassFqName
|
||||
|
||||
public fun JvmFileClassesProvider.getFacadeClassInternalName(file: KtFile): String =
|
||||
getFacadeClassFqName(file).getInternalName()
|
||||
|
||||
public fun JvmFileClassesProvider.getFacadeClassType(file: KtFile): Type =
|
||||
getFacadeClassFqName(file).getClassType()
|
||||
@@ -56,7 +56,7 @@ public fun StorageComponentContainer.configureJavaTopDownAnalysis(moduleContentS
|
||||
useInstance(JvmVirtualFileFinderFactory.SERVICE.getInstance(project).create(moduleContentScope))
|
||||
|
||||
useImpl<JavaClassFinderImpl>()
|
||||
useImpl<SignaturePropagatorImpl>()
|
||||
useImpl<TraceBasedExternalSignatureResolver>()
|
||||
useImpl<LazyResolveBasedCache>()
|
||||
useImpl<TraceBasedErrorReporter>()
|
||||
useImpl<PsiBasedExternalAnnotationResolver>()
|
||||
|
||||
@@ -49,10 +49,10 @@ public fun inlineFunctionsJvmNames(bytes: ByteArray): Set<String> {
|
||||
private fun inlineFunctionsJvmNames(functions: List<ProtoBuf.Function>, nameResolver: NameResolver, protoTypeTable: ProtoBuf.TypeTable): Set<String> {
|
||||
val typeTable = TypeTable(protoTypeTable)
|
||||
val inlineFunctions = functions.filter { Flags.IS_INLINE.get(it.flags) }
|
||||
val jvmNames = inlineFunctions.mapNotNull {
|
||||
val jvmNames = inlineFunctions.map {
|
||||
JvmProtoBufUtil.getJvmMethodSignature(it, nameResolver, typeTable)
|
||||
}
|
||||
return jvmNames.toSet()
|
||||
return jvmNames.filterNotNull().toSet()
|
||||
}
|
||||
|
||||
private fun readKotlinHeader(bytes: ByteArray): KotlinClassHeader {
|
||||
|
||||
@@ -1,62 +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.load.java.components;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JavaBindingContext;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.SignaturesPropagationData;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SignaturePropagatorImpl implements SignaturePropagator {
|
||||
private final BindingTrace trace;
|
||||
|
||||
public SignaturePropagatorImpl(@NotNull BindingTrace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PropagatedSignature resolvePropagatedSignature(
|
||||
@NotNull JavaMethod method,
|
||||
@NotNull ClassDescriptor owner,
|
||||
@NotNull KotlinType returnType,
|
||||
@Nullable KotlinType receiverType,
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters
|
||||
) {
|
||||
SignaturesPropagationData data =
|
||||
new SignaturesPropagationData(owner, returnType, receiverType, valueParameters, typeParameters, method);
|
||||
return new PropagatedSignature(
|
||||
returnType, data.getModifiedReceiverType(), data.getModifiedValueParameters(),
|
||||
typeParameters, data.getSignatureErrors(), data.getModifiedHasStableParameterNames()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportSignatureErrors(@NotNull CallableMemberDescriptor descriptor, @NotNull List<String> signatureErrors) {
|
||||
trace.record(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, descriptor.getOriginal(), signatureErrors);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.load.java.components;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JavaBindingContext;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaConstructor;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaField;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMember;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.AlternativeFieldSignatureData;
|
||||
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.AlternativeMethodSignatureData;
|
||||
import org.jetbrains.kotlin.resolve.jvm.kotlinSignature.SignaturesPropagationData;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TraceBasedExternalSignatureResolver implements ExternalSignatureResolver {
|
||||
@NotNull private final BindingTrace trace;
|
||||
@NotNull private final Project project;
|
||||
|
||||
public TraceBasedExternalSignatureResolver(
|
||||
@NotNull Project project,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
this.project = project;
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PropagatedMethodSignature resolvePropagatedSignature(
|
||||
@NotNull JavaMethod method,
|
||||
@NotNull ClassDescriptor owner,
|
||||
@NotNull KotlinType returnType,
|
||||
@Nullable KotlinType receiverType,
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters
|
||||
) {
|
||||
SignaturesPropagationData data =
|
||||
new SignaturesPropagationData(owner, returnType, receiverType, valueParameters, typeParameters, method);
|
||||
return new PropagatedMethodSignature(data.getModifiedReturnType(), data.getModifiedReceiverType(),
|
||||
data.getModifiedValueParameters(), data.getModifiedTypeParameters(), data.getSignatureErrors(),
|
||||
data.getModifiedHasStableParameterNames(), data.getSuperFunctions());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public AlternativeMethodSignature resolveAlternativeMethodSignature(
|
||||
@NotNull JavaMember methodOrConstructor,
|
||||
boolean hasSuperMethods,
|
||||
@Nullable KotlinType returnType,
|
||||
@Nullable KotlinType receiverType,
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
boolean hasStableParameterNames
|
||||
) {
|
||||
assert methodOrConstructor instanceof JavaMethod || methodOrConstructor instanceof JavaConstructor :
|
||||
"Not a method or a constructor: " + methodOrConstructor.getName();
|
||||
|
||||
AlternativeMethodSignatureData data = new AlternativeMethodSignatureData(
|
||||
methodOrConstructor, receiverType, project, valueParameters, returnType, typeParameters, hasSuperMethods
|
||||
);
|
||||
|
||||
if (data.isAnnotated() && !data.hasErrors()) {
|
||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) {
|
||||
return new AlternativeMethodSignature(returnType, receiverType, valueParameters,
|
||||
typeParameters, Collections.<String>emptyList(), hasStableParameterNames);
|
||||
}
|
||||
return new AlternativeMethodSignature(data.getReturnType(), receiverType, data.getValueParameters(), data.getTypeParameters(),
|
||||
Collections.<String>emptyList(), true);
|
||||
}
|
||||
|
||||
List<String> error = data.hasErrors() ? Collections.singletonList(data.getError()) : Collections.<String>emptyList();
|
||||
return new AlternativeMethodSignature(returnType, receiverType, valueParameters, typeParameters, error, hasStableParameterNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public AlternativeFieldSignature resolveAlternativeFieldSignature(
|
||||
@NotNull JavaField field,
|
||||
@NotNull KotlinType returnType,
|
||||
boolean isVar
|
||||
) {
|
||||
AlternativeFieldSignatureData data = new AlternativeFieldSignatureData(field, returnType, project, isVar);
|
||||
|
||||
if (data.isAnnotated() && !data.hasErrors()) {
|
||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) {
|
||||
return new AlternativeFieldSignature(returnType, null);
|
||||
}
|
||||
return new AlternativeFieldSignature(data.getReturnType(), null);
|
||||
}
|
||||
|
||||
String error = data.hasErrors() ? data.getError() : null;
|
||||
return new AlternativeFieldSignature(returnType, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportSignatureErrors(@NotNull CallableMemberDescriptor descriptor, @NotNull List<String> signatureErrors) {
|
||||
trace.record(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, descriptor.getOriginal(), signatureErrors);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
|
||||
@@ -103,7 +104,7 @@ public class SingleAbstractMethodUtils {
|
||||
KotlinType type = fixProjections(substitute);
|
||||
if (type == null) return null;
|
||||
|
||||
if (FlexibleTypesKt.isNullabilityFlexible(samType)) {
|
||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES() && FlexibleTypesKt.isNullabilityFlexible(samType)) {
|
||||
return LazyJavaTypeResolver.FlexibleJavaClassifierTypeCapabilities.create(type, TypeUtils.makeNullable(type));
|
||||
}
|
||||
|
||||
@@ -226,7 +227,7 @@ public class SingleAbstractMethodUtils {
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull KotlinType returnType
|
||||
) {
|
||||
result.initialize(valueParameters, original.getVisibility());
|
||||
result.initialize(typeParameters, valueParameters, original.getVisibility());
|
||||
result.setReturnType(returnType);
|
||||
}
|
||||
});
|
||||
@@ -288,10 +289,6 @@ public class SingleAbstractMethodUtils {
|
||||
@NotNull List<TypeParameterDescriptor> originalParameters,
|
||||
@Nullable DeclarationDescriptor newOwner
|
||||
) {
|
||||
if (newOwner instanceof SamAdapterConstructorDescriptor) {
|
||||
return new TypeParameters(originalParameters, TypeSubstitutor.EMPTY);
|
||||
}
|
||||
|
||||
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> traitToFunTypeParameters =
|
||||
JavaResolverUtils.recreateTypeParametersAndReturnMapping(originalParameters, newOwner);
|
||||
TypeSubstitutor typeParametersSubstitutor = JavaResolverUtils.createSubstitutorForTypeParameters(traitToFunTypeParameters);
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
package org.jetbrains.kotlin.load.java.structure.impl;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.load.java.structure.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.types;
|
||||
|
||||
public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implements JavaClassifierType {
|
||||
private static class ResolutionResult {
|
||||
private final JavaClassifier classifier;
|
||||
@@ -109,33 +110,6 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JavaType> getTypeArguments() {
|
||||
JavaClassifier classifier = getClassifier();
|
||||
|
||||
// parameters including ones from outer class
|
||||
Iterable<PsiTypeParameter> parameters = classifier instanceof JavaClassImpl
|
||||
? getReversedTypeParameters((JavaClassImpl) classifier)
|
||||
: Collections.<PsiTypeParameter>emptyList();
|
||||
|
||||
JavaTypeSubstitutor substitutor = getSubstitutor();
|
||||
|
||||
List<JavaType> result = new ArrayList<JavaType>();
|
||||
for (PsiTypeParameter typeParameter : parameters) {
|
||||
result.add(substitutor.substitute(new JavaTypeParameterImpl(typeParameter)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Collection<PsiTypeParameter> getReversedTypeParameters(@NotNull JavaClassImpl classifier) {
|
||||
Iterable<PsiTypeParameter> parameters = PsiUtil.typeParametersIterable(classifier.getPsi());
|
||||
List<PsiTypeParameter> result = new ArrayList<PsiTypeParameter>();
|
||||
|
||||
for (PsiTypeParameter parameter : parameters) {
|
||||
result.add(parameter);
|
||||
}
|
||||
|
||||
Collections.reverse(result);
|
||||
|
||||
return result;
|
||||
return types(getPsi().getParameters());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,9 +119,10 @@ public class IncrementalPackageFragmentProvider(
|
||||
} ?: emptyList<String>()
|
||||
|
||||
val scopes = actualPackagePartFiles
|
||||
.mapNotNull {
|
||||
.map {
|
||||
incrementalCache.getPackagePartData(it)
|
||||
}
|
||||
.filterNotNull()
|
||||
.map {
|
||||
IncrementalPackageScope(JvmProtoBufUtil.readPackageDataFrom(it.data, it.strings))
|
||||
}
|
||||
@@ -148,7 +149,7 @@ public class IncrementalPackageFragmentProvider(
|
||||
val partsNames: Collection<String>
|
||||
) : PackageFragmentDescriptorImpl(moduleDescriptor, multifileClassFqName.parent()) {
|
||||
val memberScope = storageManager.createLazyValue {
|
||||
val partsData = partsNames.mapNotNull { incrementalCache.getPackagePartData(it) }
|
||||
val partsData = partsNames.map { incrementalCache.getPackagePartData(it) }.filterNotNull()
|
||||
if (partsData.isEmpty())
|
||||
MemberScope.Empty
|
||||
else {
|
||||
@@ -181,7 +182,8 @@ public class IncrementalPackageFragmentProvider(
|
||||
|
||||
if (LOG.isDebugEnabled) {
|
||||
val allPackageParts = allMemberProtos
|
||||
.mapNotNull(::getPackagePart)
|
||||
.map(::getPackagePart)
|
||||
.filterNotNull()
|
||||
.toSet()
|
||||
val skippedPackageParts = allPackageParts.filter { shouldSkipPackagePart(it) }
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ internal class IncrementalPackagePartProvider private constructor(
|
||||
val packagePartsFromParent = parent.findPackageParts(packageFqName)
|
||||
if (packageFqName in fqNamesToIgnore) return packagePartsFromParent
|
||||
|
||||
val packagePartsFromCompiled = moduleMappings().mapNotNull { it.findPackageParts(packageFqName) }.flatMap { it.parts }
|
||||
val packagePartsFromCompiled = moduleMappings().map { it.findPackageParts(packageFqName) }.filterNotNull().flatMap { it.parts }
|
||||
return (packagePartsFromCompiled + packagePartsFromParent).distinct()
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user