Compare commits

..

29 Commits
beta3 ... beta2

Author SHA1 Message Date
Dmitry Jemerov
3674663d30 use Kotlin call hierarchy provider only for Kotlin elements, to ensure that it does not interfere with standard Java features of IntelliJ IDEA
(cherry picked from commit 7004917)
2015-11-26 11:34:34 +01:00
Natalia Ukhorskaya
e74282753a Fix compatibility with AS 2.0
#KT-10153 Fixed
2015-11-24 19:06:47 +03:00
Dmitry Jemerov
bbb92ead5b ensure that the short name of the Kotlin unused import inspection does not clash with Java (KT-10046)
(cherry picked from commit 30084df)
2015-11-20 14:07:12 +01:00
Michael Nedzelsky
08e9ff602f fix KT-10068 JsLibraryStdDetectionUtil does not use caching through JarUserDataManager
#KT-10068 Fixed
(cherry picked from commit ea4470a)
2015-11-19 18:54:44 +01:00
Nikolay Krasko
73596f7464 Enable bootstrapping for the branch 2015-11-19 16:14:54 +03:00
Alexander Udalov
0dcf34bb55 Fix deadlock on static initializers of KProperty implementations
#KT-10041 Fixed
2015-11-19 02:58:00 +03:00
Mikhail Glukhikh
0bcdfce84b Diagnostics corrected for smart cast impossible (cherry picked from commit 03287d5) 2015-11-18 20:13:28 +03:00
Yan Zhulanow
e8be0962c2 Android extensions: get descriptors using reflection (temporary change)
(cherry picked from commit f228c04)
2015-11-17 20:29:53 +03:00
Yan Zhulanow
8afd6421bb Revert "do not package kotlin-runtime and kotlin-reflect into Kotlin Android extensions zip"
This reverts commit 83bf5daf7f.
(cherry picked from commit a1dcede)
2015-11-17 20:29:45 +03:00
Dmitry Jemerov
a946126dca do not package kotlin-runtime and kotlin-reflect into Kotlin Android extensions zip
(cherry picked from commit 83bf5da)
2015-11-17 13:15:24 +01:00
Ilya Gorbunov
47895c0cc2 Correct deprecation replacement for Progression constructors.
Update testdata for LoadBuiltinsTest
2015-11-13 21:57:27 +03:00
Ilya Chernikov
bb6677620a Additional fix to the previous one: Disabling parallel builds without daemon again and undoing apprpriate fix to broken tests problem, since it effectively cancelled fix for parallel building itself and was causing exceptions on heavy builds 2015-11-12 19:14:00 +01:00
Ilya Chernikov
06104521f2 Disabling parallel builds without daemon again and undoing apprpriate fix to broken tests problem, since it effectively cancelled fix for parallel building itself and was causing exceptions on heavy builds 2015-11-12 17:13:26 +01:00
Valentin Kipyatkov
63fc7110a7 KT-9981 Code cleanup replace usages of !in incorrectly
#KT-9981 Fixed
2015-11-12 15:11:07 +03:00
Michael Bogdanov
f5bab93fd1 Additional diagnostic for KT-9980: KotlinFrontEndException: Exception while analyzing expression 2015-11-12 15:11:29 +03:00
Ilya Gorbunov
8f2c05668e Make MutableMap.set return Unit
#KT-7853 Fixed
2015-11-11 19:15:52 +03:00
Ilya Gorbunov
737763cc67 Restore correct sorting order (after cleanup in 17fc1d95) 2015-11-11 19:15:51 +03:00
Ilya Gorbunov
2bd44799f8 Simplify message expression from lambda argument when converting assert to if. 2015-11-11 19:15:50 +03:00
Ilya Gorbunov
e13fb0e7bc Deprecated with ERROR preconditions with eager message. 2015-11-11 19:15:49 +03:00
Ilya Gorbunov
16df7a9d92 Replace getStackTrace usages in j2k and testData. 2015-11-11 19:15:48 +03:00
Ilya Gorbunov
d5d803963f Replace Regex.match and matchAll usages 2015-11-11 19:15:47 +03:00
Ilya Gorbunov
20a15dc175 Refactor intention test files enumerating, do not use deprecated filter method, which would get another behavior after dropping deprecated one. 2015-11-11 19:15:46 +03:00
Ilya Gorbunov
26bd8600cf Drop deprecations and tighten up left ones. 2015-11-11 19:15:45 +03:00
Nikolay Krasko
abb116ef9a Fix locator syntax 2015-11-11 19:06:57 +03:00
Ilya Gorbunov
a336888858 Make emptyMap upperbound to be Any? rather than Any.
#KT-9963
2015-11-11 17:17:42 +03:00
Ilya Gorbunov
19501aac59 Do not override default AbstractList iterator() implementation for primitiveArray.asList wrappers.
#KT-9927 Fixed
2015-11-11 17:17:41 +03:00
Nikolay Krasko
f9ac5ae737 Enable auto-increment in beta2 branch 2015-11-11 17:13:27 +03:00
Dmitry Jemerov
9cb5defc43 don't analyze class repeatedly if we already found an annotated member there
#KT-8557 Fixed
(cherry picked from commit 6f2fb3f)
2015-11-11 15:10:12 +01:00
Valentin Kipyatkov
4782077357 KT-9928 Replacement not offered for a usage of symbol deprecated with DeprecationLevel.ERROR
#KT-9928 Fixed
(cherry picked from commit de11d57)
2015-11-11 17:08:58 +03:00
3879 changed files with 26134 additions and 40609 deletions

2
.idea/ant.xml generated
View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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
View File

@@ -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" />

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,4 +1,3 @@
<a href="http://kotlinslackin.herokuapp.com"><img src="https://kotlinslackin.herokuapp.com/badge.svg" height="20"></a>
[![TeamCity (simple build status)](https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/bt345.svg)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=bt345&branch_Kotlin=%3Cdefault%3E&tab=buildTypeStatusDiv)
[![Maven Central](https://img.shields.io/maven-central/v/org.jetbrains.kotlin/kotlin-maven-plugin.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.jetbrains.kotlin%22)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)

View File

@@ -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="&lt;version&gt;@snapshot@&lt;/version&gt;"/>
<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="&lt;version&gt;@snapshot@&lt;/version&gt;"/>
<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 = &quot;@snapshot@&quot;;"/>
<substituteVersionInFile
target.file="${kotlin.bare.plugin.xml}"
target.file.bk="${kotlin.bare.plugin.xml.bk}"
test.string="&lt;version&gt;@snapshot@&lt;/version&gt;"/>
</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">

View File

@@ -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>

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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)"
}

View File

@@ -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),

View File

@@ -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());

View File

@@ -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);

View File

@@ -45,7 +45,8 @@ public interface Callable {
}
}
public fun afterReceiverGeneration(v: InstructionAdapter) {
public fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
}
}

View File

@@ -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)
}
}

View File

@@ -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);
}

View File

@@ -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;
}
});

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -24,20 +24,40 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.psi.KtScript;
import org.jetbrains.kotlin.resolve.ScriptNameUtil;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.registerClassNameForScript;
public class KotlinCodegenFacade {
public static void prepareForCompilation(@NotNull GenerationState state) {
for (KtFile file : state.getFiles()) {
if (file.isScript()) {
KtScript script = file.getScript();
assert script != null;
FqName name = ScriptNameUtil.classNameForScript(script);
Type type = AsmUtil.asmTypeByFqNameWithoutInnerClasses(name);
registerClassNameForScript(state.getBindingTrace(), script, type, state.getFileClassesProvider());
}
}
state.beforeCompile();
}
public static void compileCorrectFiles(
@NotNull GenerationState state,
@NotNull CompilationErrorHandler errorHandler
) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
state.beforeCompile();
prepareForCompilation(state);
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();

View File

@@ -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());
}
}

View File

@@ -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(

View File

@@ -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);
}
}
);

View File

@@ -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)
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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

View File

@@ -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(

View File

@@ -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)
}
}

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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,

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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())

View File

@@ -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);

View File

@@ -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]
}
}

View File

@@ -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) }

View File

@@ -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)
}
}
}
}

View File

@@ -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");
}

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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")
}

View File

@@ -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);

View File

@@ -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() {

View File

@@ -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))
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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(

View File

@@ -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 ->

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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
}
}

View File

@@ -264,7 +264,6 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
.sourceMap(arguments.sourceMap)
.inlineEnabled(inlineEnabled)
.metaInfo(arguments.metaInfo)
.kjsm(arguments.kjsm)
.build();
}

View File

@@ -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)
}

View File

@@ -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> {

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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()
}
}

View File

@@ -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()) {

View File

@@ -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())
}
}

View File

@@ -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)

View File

@@ -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 =

View File

@@ -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;
}
}

View File

@@ -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(

View File

@@ -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"))

View File

@@ -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 }
}

View File

@@ -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()

View File

@@ -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>())
}

View File

@@ -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
}

View File

@@ -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>
}

View File

@@ -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")
}
}
}
}

View File

@@ -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()
}
}

View File

@@ -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")

View File

@@ -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()

View File

@@ -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>()

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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) }

View File

@@ -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