mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-11 15:52:06 +00:00
Compare commits
68 Commits
native-too
...
master_181
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c0c1c81bc | ||
|
|
73f08e5d63 | ||
|
|
e49aebeac2 | ||
|
|
312609d91c | ||
|
|
e0cb01eeb9 | ||
|
|
d707573493 | ||
|
|
2796a72652 | ||
|
|
02cf31e812 | ||
|
|
a9f98fbbe5 | ||
|
|
324f231f2b | ||
|
|
39cc7aa7cf | ||
|
|
eeabc28385 | ||
|
|
2926690e6c | ||
|
|
3fa4ddb5b5 | ||
|
|
83071b8823 | ||
|
|
70231ae12a | ||
|
|
8ce37d248a | ||
|
|
7903186b84 | ||
|
|
90bbce0eb9 | ||
|
|
23adb5bd15 | ||
|
|
2ed9c9c009 | ||
|
|
d51e304525 | ||
|
|
fd0bb96605 | ||
|
|
8d79b4d14c | ||
|
|
d681c19d7a | ||
|
|
56dd6c9801 | ||
|
|
5d17b3e4d6 | ||
|
|
a47eebf2b9 | ||
|
|
ed764834b6 | ||
|
|
11dd7a4284 | ||
|
|
de5006c465 | ||
|
|
b4c784a0de | ||
|
|
b80d2c9a90 | ||
|
|
70858b6774 | ||
|
|
e87748cf4d | ||
|
|
d47f5c337d | ||
|
|
a872281647 | ||
|
|
62113cc539 | ||
|
|
173af4f9eb | ||
|
|
ac9198914a | ||
|
|
d8a72ad137 | ||
|
|
014c23f71a | ||
|
|
389ed8787c | ||
|
|
11de3b4ba8 | ||
|
|
e054c7f800 | ||
|
|
3fa2985c9c | ||
|
|
ac96bc7e80 | ||
|
|
b8ddda6986 | ||
|
|
3f45689b1f | ||
|
|
dd428286c7 | ||
|
|
31e21f3d45 | ||
|
|
837362d911 | ||
|
|
0bbed83235 | ||
|
|
dc1ff036c8 | ||
|
|
72a841e77f | ||
|
|
0c7b876412 | ||
|
|
ba50a3ddf9 | ||
|
|
4ab1ddde71 | ||
|
|
1ee1e79d31 | ||
|
|
76cdd7b87a | ||
|
|
56dc3a1dcb | ||
|
|
8b6961f22c | ||
|
|
db5b83d72a | ||
|
|
1171fea35f | ||
|
|
00034d56b2 | ||
|
|
ca86dde953 | ||
|
|
0698280b7d | ||
|
|
26968d7d19 |
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,14 +0,0 @@
|
||||
Many thanks for your contribution, we genuinely appreciate it.
|
||||
Make sure that you can say "YES" to each point in this short checklist:
|
||||
|
||||
- You do not have merge commits in PR
|
||||
- You made a few changes
|
||||
- You provided the link to related issue from YouTrack
|
||||
- You can describe changes made in PR
|
||||
- You made changes related to only one issue
|
||||
- You are ready to defend your changes on code review
|
||||
- You didn't touch what you don't understand
|
||||
- You ran the build locally, and verified new functionality
|
||||
- You ran related tests locally, and it passed
|
||||
|
||||
Thank you for your contribution!
|
||||
9
.idea/ant.xml
generated
9
.idea/ant.xml
generated
@@ -1,8 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AntConfiguration">
|
||||
<buildFile url="file://$PROJECT_DIR$/update_dependencies.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/TeamCityBuild.xml">
|
||||
<maximumHeapSize value="512" />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/idea-runner/runner.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>
|
||||
19
.idea/codeStyles/Project.xml
generated
19
.idea/codeStyles/Project.xml
generated
@@ -56,7 +56,14 @@
|
||||
</option>
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="false" />
|
||||
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="false" />
|
||||
<option name="CONTINUATION_INDENT_IN_IF_CONDITIONS" value="false" />
|
||||
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="1" />
|
||||
<option name="IF_RPAREN_ON_NEW_LINE" value="true" />
|
||||
</JetCodeStyleSettings>
|
||||
<MarkdownNavigatorCodeStyleSettings>
|
||||
<option name="RIGHT_MARGIN" value="72" />
|
||||
@@ -270,8 +277,16 @@
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="5" />
|
||||
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
|
||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
1
.idea/dictionaries/bashor.xml
generated
1
.idea/dictionaries/bashor.xml
generated
@@ -4,7 +4,6 @@
|
||||
<w>ctor</w>
|
||||
<w>inlining</w>
|
||||
<w>interner</w>
|
||||
<w>intrinsicify</w>
|
||||
<w>kclass</w>
|
||||
<w>lookups</w>
|
||||
<w>minification</w>
|
||||
|
||||
31
.idea/inspectionProfiles/idea_default.xml
generated
31
.idea/inspectionProfiles/idea_default.xml
generated
@@ -98,27 +98,6 @@
|
||||
<option name="insideTryAllowed" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="IfStatementWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="IncompatibleAPI" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="problems">
|
||||
<list>
|
||||
<Problem reference="org.jetbrains.plugins.gradle.util.GradleConstants#KOTLIN_DSL_SCRIPT_EXTENSION" reason="Absent in 172. Please inline." />
|
||||
<Problem reference="com.intellij.psi.impl.compiled.ClsClassImpl#getQualifiedName" reason="Nullable in 173, platform in 172. Use qualifiedNameEx instead." />
|
||||
<Problem reference="com.intellij.internal.statistic.utils.StatisticsUtilKt#getEnumUsage" reason="Absent in 172. Use org.jetbrains.kotlin.idea.util.compat.statistic.StatisticKt.getEnumUsage instead." />
|
||||
<Problem reference="com.intellij.internal.statistic.utils.StatisticsUtilKt#getBooleanUsage" reason="Absent in 172 Use org.jetbrains.kotlin.idea.util.compat.statistic.StatisticKt.getBooleanUsage instead." />
|
||||
<Problem reference="com.intellij.internal.statistic.AbstractProjectsUsagesCollector" reason="Absent in 172. Use org.jetbrains.kotlin.idea.util.compat.statistic.AbstractProjectsUsagesCollector instead." />
|
||||
<Problem reference="com.intellij.openapi.progress.ProgressManager#getProgressIndicator" reason="Not null starting from 181. Use getProgressIndicatorNullable instead." />
|
||||
<Problem reference="com.intellij.testFramework.PlatformTestCase#createModuleAt" reason="Not static anymore in 181 after 7dacf096c47d2125e17031c71a037b63ab00ec53" />
|
||||
<Problem reference="com.intellij.testFramework.PlatformTestCase#doCreateRealModuleIn" reason="Not static anymore in 181 after 7dacf096c47d2125e17031c71a037b63ab00ec53" />
|
||||
<Problem reference="com.intellij.openapi.progress.ProgressManager#getProgressIndicator" reason="Nullable in 181. Temporary use progressIndicatorNullable instead." />
|
||||
<Problem reference="com.intellij.testFramework.fixtures.CodeInsightTestFixture#getProjectDisposable" reason="Method was introduced in 173 and absent in 172. Use getProjectDisposableEx instead. (95eaf81e0ea497f8c69263c11fd3202d28a7a1b2)" />
|
||||
<Problem reference="org.jetbrains.org.objectweb.asm.Opcodes#V9" reason="Absent in 172 branch. Use V1_9 while 172 is supported." />
|
||||
<Problem reference="com.intellij.psi.codeStyle.CommonCodeStyleSettings#getSoftMargins" reason="Absent in 172." />
|
||||
<Problem reference="com.intellij.util.xmlb.XmlSerializer#serializeInto(java.lang.Object, org.jdom.Element)" reason="Absent in 172." />
|
||||
<Problem reference="org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler#addSpace" reason="Method was replaced with outher methods in 182. Use addSpaceEx instead." />
|
||||
<Problem reference="com.intellij.psi.util.PsiUtil#canBeOverridden" reason="Absent in 172. Use org.jetbrains.kotlin.idea.core.util.compat.psi.canBeOverridden() instead." />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="InnerClassMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="InstanceofCatchParameter" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="InstanceofIncompatibleInterface" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
@@ -296,16 +275,6 @@
|
||||
<inspection_tool class="PackageDirectoryMismatch" enabled="true" level="WARNING" enabled_by_default="false">
|
||||
<scope name="all except testData" level="WARNING" enabled="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ProblematicAPIUsage" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="problems">
|
||||
<list>
|
||||
<Problem reference="com.intellij.testFramework.PlatformTestCase#createModuleAt" reason="Not static anymore in 181 after 7dacf096c47d2125e17031c71a037b63ab00ec53" />
|
||||
<Problem reference="com.intellij.testFramework.PlatformTestCase#doCreateRealModuleIn" reason="Not static anymore in 181 after 7dacf096c47d2125e17031c71a037b63ab00ec53" />
|
||||
<Problem reference="com.intellij.openapi.progress.ProgressManager#getProgressIndicator" reason="Nullable in 181. Temporary use progressIndicatorNullable instead." />
|
||||
<Problem reference="com.intellij.testFramework.fixtures.CodeInsightTestFixture#getProjectDisposable" reason="Method was introduced in 173 and absent in 172. Use getProjectDisposableEx instead. (95eaf81e0ea497f8c69263c11fd3202d28a7a1b2)" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ProtectedMemberInFinalClass" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PublicFieldAccessedInSynchronizedContext" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
|
||||
32
.idea/misc.xml
generated
32
.idea/misc.xml
generated
@@ -44,38 +44,6 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.validation.constraints.NotNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectResources">
|
||||
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
|
||||
</component>
|
||||
|
||||
2
.idea/runConfigurations/IDEA.xml
generated
2
.idea/runConfigurations/IDEA.xml
generated
@@ -15,6 +15,6 @@
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<method v="2" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -10,6 +10,9 @@
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value=":kotlin-runtime:clean" />
|
||||
<option value=":kotlin-stdlib:clean" />
|
||||
<option value=":kotlin-reflect:clean" />
|
||||
<option value=":tools:binary-compatibility-validator:cleanTest" />
|
||||
<option value=":tools:binary-compatibility-validator:test" />
|
||||
</list>
|
||||
|
||||
481
ChangeLog.md
481
ChangeLog.md
@@ -1,486 +1,5 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 1.2.50
|
||||
|
||||
### Compiler
|
||||
|
||||
- [`KT-23360`](https://youtrack.jetbrains.com/issue/KT-23360) Do not serialize annotations with retention SOURCE to metadata
|
||||
- [`KT-24278`](https://youtrack.jetbrains.com/issue/KT-24278) Hard-code to kotlin compiler annotation for android library migration
|
||||
- [`KT-24472`](https://youtrack.jetbrains.com/issue/KT-24472) Support argfiles in kotlinc with -Xargfile
|
||||
- [`KT-24593`](https://youtrack.jetbrains.com/issue/KT-24593) Support -XXLanguage:{+|-}LanguageFeature compiler arguments to enable/disable specific features
|
||||
- [`KT-24637`](https://youtrack.jetbrains.com/issue/KT-24637) Introduce "progressive" mode of compiler
|
||||
|
||||
#### Backend. JS
|
||||
|
||||
- [`KT-23094`](https://youtrack.jetbrains.com/issue/KT-23094) JS compiler: Delegation fails to pass the continuation parameter to child suspend function
|
||||
- [`KT-23582`](https://youtrack.jetbrains.com/issue/KT-23582) JS: Fails to inline, produces bad code
|
||||
- [`KT-24335`](https://youtrack.jetbrains.com/issue/KT-24335) JS: Invalid implement of external interface
|
||||
|
||||
#### Backend. JVM
|
||||
|
||||
- [`KT-12330`](https://youtrack.jetbrains.com/issue/KT-12330) Slightly improve generated bytecode for data class equals/hashCode methods
|
||||
- [`KT-18576`](https://youtrack.jetbrains.com/issue/KT-18576) Debugger fails to show decomposed suspend lambda parameters
|
||||
- [`KT-22063`](https://youtrack.jetbrains.com/issue/KT-22063) Add intrinsics for javaObjectType and javaPrimitiveType
|
||||
- [`KT-23402`](https://youtrack.jetbrains.com/issue/KT-23402) Internal error: Couldn't inline method call because the compiler couldn't obtain compiled body for inline function with reified type parameter
|
||||
- [`KT-23704`](https://youtrack.jetbrains.com/issue/KT-23704) Unstable `checkExpressionValueIsNotNull()` generation in bytecode
|
||||
- [`KT-23707`](https://youtrack.jetbrains.com/issue/KT-23707) Unstable bridge generation order
|
||||
- [`KT-23857`](https://youtrack.jetbrains.com/issue/KT-23857) Annotation with target TYPE is not applicable to TYPE_USE in Java sources
|
||||
- [`KT-23910`](https://youtrack.jetbrains.com/issue/KT-23910) @JvmOverloads doesn't work with default arguments in common code
|
||||
- [`KT-24427`](https://youtrack.jetbrains.com/issue/KT-24427) Protected function having toArray-like signature from collection becomes public in bytecode
|
||||
- [`KT-24661`](https://youtrack.jetbrains.com/issue/KT-24661) Support binary compatibility mode for @JvmDefault
|
||||
|
||||
#### Frontend
|
||||
|
||||
- [`KT-21129`](https://youtrack.jetbrains.com/issue/KT-21129) Unused parameter in property setter is not reported
|
||||
- [`KT-21157`](https://youtrack.jetbrains.com/issue/KT-21157) Kotlin script: engine can take forever to eval certain code after several times
|
||||
- [`KT-22740`](https://youtrack.jetbrains.com/issue/KT-22740) REPL slows down during extensions compiling
|
||||
- [`KT-23124`](https://youtrack.jetbrains.com/issue/KT-23124) Kotlin multiplatform project causes IntelliJ build errors
|
||||
- [`KT-23209`](https://youtrack.jetbrains.com/issue/KT-23209) Compiler throwing frontend exception
|
||||
- [`KT-23589`](https://youtrack.jetbrains.com/issue/KT-23589) Report a warning on local annotation classes
|
||||
- [`KT-23760`](https://youtrack.jetbrains.com/issue/KT-23760) Unable to implement common interface with fun member function with typealiased parameter
|
||||
|
||||
### Android
|
||||
|
||||
- [`KT-23244`](https://youtrack.jetbrains.com/issue/KT-23244) Option to Disable View Binding generation in Kotlin Android Extensions Plugin
|
||||
|
||||
### IDE
|
||||
|
||||
- [`KT-8407`](https://youtrack.jetbrains.com/issue/KT-8407) TestNG: running tests from context creates new run configuration every time
|
||||
- [`KT-9218`](https://youtrack.jetbrains.com/issue/KT-9218) Searching for compilable files takes too long
|
||||
- [`KT-15019`](https://youtrack.jetbrains.com/issue/KT-15019) Editor: `args` reference in .kts file is red
|
||||
- [`KT-18769`](https://youtrack.jetbrains.com/issue/KT-18769) Expand Selection on opening curly brace should select the entire block right away
|
||||
- [`KT-19055`](https://youtrack.jetbrains.com/issue/KT-19055) Idea hangs on copy-paste big Kotlin files
|
||||
- [`KT-20605`](https://youtrack.jetbrains.com/issue/KT-20605) Unresolved reference on instance from common module function
|
||||
- [`KT-20824`](https://youtrack.jetbrains.com/issue/KT-20824) Type mismatch for common function taking a non-mapped Kotlin's expected class from stdlib-common, with actual typealias on JVM
|
||||
- [`KT-20897`](https://youtrack.jetbrains.com/issue/KT-20897) Can't navigate to declaration after PsiInvalidElementAccessException exception
|
||||
- [`KT-22527`](https://youtrack.jetbrains.com/issue/KT-22527) Kotlin UAST does not evaluate values inside delegation expressions
|
||||
- [`KT-22868`](https://youtrack.jetbrains.com/issue/KT-22868) Implementing an `expected class` declaration using `actual typealias` produces "good code that is red"
|
||||
- [`KT-22922`](https://youtrack.jetbrains.com/issue/KT-22922) Override Members should add experimental annotation when required
|
||||
- [`KT-23384`](https://youtrack.jetbrains.com/issue/KT-23384) Hotspot in org.jetbrains.kotlin.idea.caches.resolve.IDELightClassGenerationSupport.getKotlinInternalClasses(FqName, GlobalSearchScope) IDELightClassGenerationSupport.kt ?
|
||||
- [`KT-23408`](https://youtrack.jetbrains.com/issue/KT-23408) Don't render @NonNull and @Nullable annotations in parameter info for Java methods
|
||||
- [`KT-23557`](https://youtrack.jetbrains.com/issue/KT-23557) Expression Bodies should have implicit `return` in Uast
|
||||
- [`KT-23745`](https://youtrack.jetbrains.com/issue/KT-23745) Unable to implement common interface
|
||||
- [`KT-23746`](https://youtrack.jetbrains.com/issue/KT-23746) Logger$EmptyThrowable "[kts] cannot find a valid script definition annotation on the class class ScriptTemplateWithArgs" with LivePlugin enabled
|
||||
- [`KT-23975`](https://youtrack.jetbrains.com/issue/KT-23975) Move Kotlin internal actions under Idea Internal actions menu
|
||||
- [`KT-24268`](https://youtrack.jetbrains.com/issue/KT-24268) Other main menu item
|
||||
- [`KT-24438`](https://youtrack.jetbrains.com/issue/KT-24438) ISE “The provided plugin org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar is not compatible with this version of compiler” after rebuilding simple Gradle-based project via JPS.
|
||||
|
||||
#### IDE. Configuration
|
||||
|
||||
- [`KT-10935`](https://youtrack.jetbrains.com/issue/KT-10935) Add menu entry to create new kotlin .kts scripts
|
||||
- [`KT-20511`](https://youtrack.jetbrains.com/issue/KT-20511) Library added from maven (using IDEA UI) is not detected as Kotlin/JS library (since type="repository")
|
||||
- [`KT-20665`](https://youtrack.jetbrains.com/issue/KT-20665) Kotlin Gradle script created by New Project/Module wizard fails with Gradle 4.1+
|
||||
- [`KT-21844`](https://youtrack.jetbrains.com/issue/KT-21844) Create Kotlin class dialog: make class abstract automatically
|
||||
- [`KT-22305`](https://youtrack.jetbrains.com/issue/KT-22305) Language and API versions of Kotlin compiler are “Latest” by default in some ways of creating new project
|
||||
- [`KT-23261`](https://youtrack.jetbrains.com/issue/KT-23261) New MPP design: please show popup with error message if module name is not set
|
||||
- [`KT-23638`](https://youtrack.jetbrains.com/issue/KT-23638) Kotlin plugin breaks project opening for PhpStorm/WebStorm
|
||||
- [`KT-23658`](https://youtrack.jetbrains.com/issue/KT-23658) Unclear options “Gradle” and “Gradle (Javascript)” on configuring Kotlin in Gradle- and Maven-based projects
|
||||
- [`KT-23845`](https://youtrack.jetbrains.com/issue/KT-23845) IntelliJ Maven Plugin does not pass javaParameters option to Kotlin facet
|
||||
- [`KT-23980`](https://youtrack.jetbrains.com/issue/KT-23980) Move "Update Channel" from "Configure Kotlin Plugin Updates" to settings
|
||||
- [`KT-24504`](https://youtrack.jetbrains.com/issue/KT-24504) Existent JPS-based Kotlin/JS module is converted to new format, while New Project wizard and facet manipulations still create old format
|
||||
|
||||
#### IDE. Debugger
|
||||
|
||||
- [`KT-23886`](https://youtrack.jetbrains.com/issue/KT-23886) Both java and kotlin breakpoints in kotlin files
|
||||
- [`KT-24136`](https://youtrack.jetbrains.com/issue/KT-24136) Debugger: update drop-down menu for the line with lambdas
|
||||
|
||||
#### IDE. Editing
|
||||
|
||||
- [`KT-2582`](https://youtrack.jetbrains.com/issue/KT-2582) When user inputs triple quote, add matching triple quote automatically
|
||||
- [`KT-5206`](https://youtrack.jetbrains.com/issue/KT-5206) Long lists of arguments are not foldable
|
||||
- [`KT-23457`](https://youtrack.jetbrains.com/issue/KT-23457) Auto-import and Import quick fix do not suggest classes from common module [Common test can't find class with word `Abstract` in name.]
|
||||
- [`KT-23235`](https://youtrack.jetbrains.com/issue/KT-23235) Super slow editing with auto imports enabled
|
||||
|
||||
#### IDE. Gradle
|
||||
|
||||
- [`KT-23234`](https://youtrack.jetbrains.com/issue/KT-23234) Test names for tests containing inner classes are sporadically reported to teamcity runs.
|
||||
- [`KT-23383`](https://youtrack.jetbrains.com/issue/KT-23383) Optional plugin dependency for kotlin gradle plugin 'java' subsystem dependent features
|
||||
- [`KT-22588`](https://youtrack.jetbrains.com/issue/KT-22588) Resolver for 'project source roots and libraries for platform JVM' does not know how to resolve on Gradle Kotlin DSL project without Java and Kotlin
|
||||
- [`KT-23616`](https://youtrack.jetbrains.com/issue/KT-23616) Synchronize script dependencies not at Gradle Sync
|
||||
- [`KT-24444`](https://youtrack.jetbrains.com/issue/KT-24444) Do not store proxy objects from Gradle importer in the project model
|
||||
- [`KT-24586`](https://youtrack.jetbrains.com/issue/KT-24586) MVNFE “Cannot resolve external dependency org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.41 because no repositories are defined.” on creating Gradle project with Kotlin only (probably due to lack of repositories block)
|
||||
- [`KT-24671`](https://youtrack.jetbrains.com/issue/KT-24671) dependencies missed in buildscript block after creating new Gradle-based project in 173 IDEA
|
||||
|
||||
#### IDE. Inspections and Intentions
|
||||
|
||||
##### New Features
|
||||
|
||||
- [`KT-7822`](https://youtrack.jetbrains.com/issue/KT-7822) Convert foreach to for loop should place caret on the variable declaration
|
||||
- [`KT-9943`](https://youtrack.jetbrains.com/issue/KT-9943) Quick fix/Intention to indent a raw string
|
||||
- [`KT-15063`](https://youtrack.jetbrains.com/issue/KT-15063) Inspection for coroutine: unused Deferred result
|
||||
- [`KT-16085`](https://youtrack.jetbrains.com/issue/KT-16085) Inspection "main should return Unit"
|
||||
- [`KT-20305`](https://youtrack.jetbrains.com/issue/KT-20305) Inspection: Refactor sealed sub-class to object
|
||||
- [`KT-21413`](https://youtrack.jetbrains.com/issue/KT-21413) Missing inspection: parentheses can be deleted when the only constructor parameter is a function not existing
|
||||
- [`KT-23137`](https://youtrack.jetbrains.com/issue/KT-23137) Intention for converting to block comment and vise versa
|
||||
- [`KT-23266`](https://youtrack.jetbrains.com/issue/KT-23266) Add intention(s) to put arguments / parameters on one line
|
||||
- [`KT-23419`](https://youtrack.jetbrains.com/issue/KT-23419) Intention to replace vararg with array and vice versa
|
||||
- [`KT-23617`](https://youtrack.jetbrains.com/issue/KT-23617) Add inspection: redundant internal in local anonymous object / class
|
||||
- [`KT-23775`](https://youtrack.jetbrains.com/issue/KT-23775) IntelliJ plugin: improve "accessor call that can be replaced with property"
|
||||
- [`KT-24235`](https://youtrack.jetbrains.com/issue/KT-24235) Inspection to replace async.await with withContext
|
||||
- [`KT-24263`](https://youtrack.jetbrains.com/issue/KT-24263) Add `Make variable immutable` quickfix for const
|
||||
- [`KT-24433`](https://youtrack.jetbrains.com/issue/KT-24433) Inspection for coroutines: unused async result
|
||||
|
||||
##### Performance Improvements
|
||||
|
||||
- [`KT-23566`](https://youtrack.jetbrains.com/issue/KT-23566) "Can be private" works on ResolutionResultsCache.kt (from Kotlin project) enormously slow
|
||||
|
||||
##### Fixes
|
||||
|
||||
- [`KT-6364`](https://youtrack.jetbrains.com/issue/KT-6364) Incorrect quick-fixes are suggested for nullable extension function call
|
||||
- [`KT-11156`](https://youtrack.jetbrains.com/issue/KT-11156) Incorrect highlighting for nested class in "Redundant SAM-constructor" inspection
|
||||
- [`KT-11427`](https://youtrack.jetbrains.com/issue/KT-11427) "Replace if with when" does not take break / continue into account
|
||||
- [`KT-11740`](https://youtrack.jetbrains.com/issue/KT-11740) Invert if condition intention should not remove line breaks
|
||||
- [`KT-12042`](https://youtrack.jetbrains.com/issue/KT-12042) "Merge with next when" is not applicable when the statements delimited by semicolon or comment
|
||||
- [`KT-12168`](https://youtrack.jetbrains.com/issue/KT-12168) "Remove explicit type specification" intention produce incompilable code in case of function type
|
||||
- [`KT-14391`](https://youtrack.jetbrains.com/issue/KT-14391) RemoveUnnecessaryParenthesesIntention lost comment on closing parenthesis
|
||||
- [`KT-14556`](https://youtrack.jetbrains.com/issue/KT-14556) Quickfix to suggest use of spread operator does not work with mapOf
|
||||
- [`KT-15195`](https://youtrack.jetbrains.com/issue/KT-15195) Redundant parentheses shouldn't be reported if lambda is not on the same line
|
||||
- [`KT-16770`](https://youtrack.jetbrains.com/issue/KT-16770) Change type of function quickfix does not propose most idiomatic solutions
|
||||
- [`KT-19629`](https://youtrack.jetbrains.com/issue/KT-19629) "Convert to primary constructor" quick fix should not move `init{...}` section down
|
||||
- [`KT-20123`](https://youtrack.jetbrains.com/issue/KT-20123) Kotlin Gradle script: “Refactoring cannot be performed. Cannot modify build.gradle.kts” for some refactorings and intentions
|
||||
- [`KT-20332`](https://youtrack.jetbrains.com/issue/KT-20332) Unused property declaration suppression by annotation doesn't work if annotation is targeted to getter
|
||||
- [`KT-21878`](https://youtrack.jetbrains.com/issue/KT-21878) "arrayOf() call can be replaced by array litteral [...]" quick fix inserts extra parentheses
|
||||
- [`KT-22092`](https://youtrack.jetbrains.com/issue/KT-22092) Intention "Specify return type explicitly": Propose types from overriden declarations
|
||||
- [`KT-22615`](https://youtrack.jetbrains.com/issue/KT-22615) "Replace with" intention does not work for equal names
|
||||
- [`KT-22632`](https://youtrack.jetbrains.com/issue/KT-22632) Gutter icon "go to actual declaration" is absent for enum values on actual side
|
||||
- [`KT-22741`](https://youtrack.jetbrains.com/issue/KT-22741) Wrong suggestion for `Replace 'if' expression with elvis expression`
|
||||
- [`KT-22831`](https://youtrack.jetbrains.com/issue/KT-22831) Inspection for converting to elvis operator does not work for local vars
|
||||
- [`KT-22860`](https://youtrack.jetbrains.com/issue/KT-22860) "Add annotation target" quick fix does not take into account existent annotations in Java source
|
||||
- [`KT-22918`](https://youtrack.jetbrains.com/issue/KT-22918) Create interface quickfix is missing 'current class' container
|
||||
- [`KT-23133`](https://youtrack.jetbrains.com/issue/KT-23133) "Remove redundant calls of the conversion method" wrongly shown for Boolan to Int conversion
|
||||
- [`KT-23167`](https://youtrack.jetbrains.com/issue/KT-23167) Report "use expression body" also on left brace
|
||||
- [`KT-23194`](https://youtrack.jetbrains.com/issue/KT-23194) Inspection "map.put() should be converted to assignment" leads to red code in case of labled return
|
||||
- [`KT-23303`](https://youtrack.jetbrains.com/issue/KT-23303) "Might be const" inspection does not check explicit type specification
|
||||
- [`KT-23320`](https://youtrack.jetbrains.com/issue/KT-23320) Quick fix to add constructor invocation doesn't work for sealed classes
|
||||
- [`KT-23321`](https://youtrack.jetbrains.com/issue/KT-23321) Intention to move type to separate file shouldn't be available for sealed classes
|
||||
- [`KT-23346`](https://youtrack.jetbrains.com/issue/KT-23346) Lift Assignment quick fix incorrectly processes block assignments
|
||||
- [`KT-23377`](https://youtrack.jetbrains.com/issue/KT-23377) Simplify boolean expression produces incorrect results when mixing nullable and non-nullable variables
|
||||
- [`KT-23465`](https://youtrack.jetbrains.com/issue/KT-23465) False positive `suspicious callable reference` on lambda invoke with parameters
|
||||
- [`KT-23511`](https://youtrack.jetbrains.com/issue/KT-23511) "Remove parameter" quick fix makes generic function call incompilable when type could be inferred from removed parameter only
|
||||
- [`KT-23513`](https://youtrack.jetbrains.com/issue/KT-23513) "Remove parameter" quick fix makes caret jump to the top of the editor
|
||||
- [`KT-23559`](https://youtrack.jetbrains.com/issue/KT-23559) Wrong hint text for "assignment can be replaced with operator assignment"
|
||||
- [`KT-23608`](https://youtrack.jetbrains.com/issue/KT-23608) AE “Failed to create expression from text” after applying quick fix “Convert too long character literal to string”
|
||||
- [`KT-23620`](https://youtrack.jetbrains.com/issue/KT-23620) False positive `Redundant Companion reference` on calling object from companion
|
||||
- [`KT-23634`](https://youtrack.jetbrains.com/issue/KT-23634) 'Add use-site target' intention drops annotation arguments
|
||||
- [`KT-23753`](https://youtrack.jetbrains.com/issue/KT-23753) "Remove variable" quick fix should not remove comment
|
||||
- [`KT-23756`](https://youtrack.jetbrains.com/issue/KT-23756) Bogus "Might be const" warning in object expression
|
||||
- [`KT-23778`](https://youtrack.jetbrains.com/issue/KT-23778) "Convert function to property" intention shows broken warning
|
||||
- [`KT-23796`](https://youtrack.jetbrains.com/issue/KT-23796) "Create extension function/property" quick fix suggests one for nullable type while creates for not-null
|
||||
- [`KT-23801`](https://youtrack.jetbrains.com/issue/KT-23801) "Convert to constructor" (IntelliJ) quick fix uses wrong use-site target for annotating properties
|
||||
- [`KT-23977`](https://youtrack.jetbrains.com/issue/KT-23977) wrong hint Unit redundant
|
||||
- [`KT-24066`](https://youtrack.jetbrains.com/issue/KT-24066) 'Remove redundant Unit' false positive when Unit is returned as Any
|
||||
- [`KT-24165`](https://youtrack.jetbrains.com/issue/KT-24165) @Deprecated ReplaceWith Constant gets replaced with nothing
|
||||
- [`KT-24207`](https://youtrack.jetbrains.com/issue/KT-24207) Add parameter intent/red bulb should use auto casted type.
|
||||
- [`KT-24215`](https://youtrack.jetbrains.com/issue/KT-24215) ReplaceWith produces broken code for lambda following default parameter
|
||||
|
||||
#### IDE. Multiplatform
|
||||
|
||||
- [`KT-20406`](https://youtrack.jetbrains.com/issue/KT-20406) Overload resolution ambiguity in IDE on expect class / actual typealias from kotlin-stdlib-common / kotlin-stdlib
|
||||
- [`KT-24316`](https://youtrack.jetbrains.com/issue/KT-24316) Missing dependencies in Kotlin MPP when using gradle composite builds
|
||||
|
||||
#### IDE. Navigation
|
||||
|
||||
- [`KT-7622`](https://youtrack.jetbrains.com/issue/KT-7622) Searching usages of a field/constructor parameter in a private class seems to scan through the whole project
|
||||
- [`KT-23182`](https://youtrack.jetbrains.com/issue/KT-23182) Find Usages checks whether there are unused variables in functions which contain search result candidates
|
||||
- [`KT-23223`](https://youtrack.jetbrains.com/issue/KT-23223) Navigate to actual declaration from actual usage
|
||||
|
||||
#### IDE. Refactorings
|
||||
|
||||
- [`KT-12078`](https://youtrack.jetbrains.com/issue/KT-12078) Introduce Variable adds explicit type when invoked on anonymous object
|
||||
- [`KT-15517`](https://youtrack.jetbrains.com/issue/KT-15517) Change signature refactoring shows confusing warning dialog
|
||||
- [`KT-22387`](https://youtrack.jetbrains.com/issue/KT-22387) Change signature reports "Type cannot be resolved" for class from different package
|
||||
- [`KT-22669`](https://youtrack.jetbrains.com/issue/KT-22669) Refactor / Copy Kotlin source to plain text causes CCE: "PsiPlainTextFileImpl cannot be cast to KtFile" at CopyKotlinDeclarationsHandler$doCopy$2$1$1.invoke()
|
||||
- [`KT-22888`](https://youtrack.jetbrains.com/issue/KT-22888) Rename completion cuts off all characters except letters from existent name
|
||||
- [`KT-23298`](https://youtrack.jetbrains.com/issue/KT-23298) AE: "2 declarations in null..." on rename of a field to `object` or `class`
|
||||
- [`KT-23563`](https://youtrack.jetbrains.com/issue/KT-23563) null by org.jetbrains.kotlin.idea.refactoring.rename.KotlinMemberInplaceRenameHandler$RenamerImpl exception on trying in-place Rename of non-scratch functions
|
||||
- [`KT-23613`](https://youtrack.jetbrains.com/issue/KT-23613) Kotlin safe delete processor handles java code when it should not
|
||||
- [`KT-23644`](https://youtrack.jetbrains.com/issue/KT-23644) Named parameters in generated Kotlin Annotations
|
||||
- [`KT-23714`](https://youtrack.jetbrains.com/issue/KT-23714) Add Parameter quickfix not working when the called method is in java.
|
||||
- [`KT-23838`](https://youtrack.jetbrains.com/issue/KT-23838) Do not search for usages in other files when renaming local variable
|
||||
- [`KT-24069`](https://youtrack.jetbrains.com/issue/KT-24069) 'Create from usage' doesn't use type info with smart casts
|
||||
|
||||
#### IDE. Scratch
|
||||
|
||||
- [`KT-6928`](https://youtrack.jetbrains.com/issue/KT-6928) Support Kotlin scratch files
|
||||
- [`KT-23441`](https://youtrack.jetbrains.com/issue/KT-23441) Scratch options reset on IDE restart
|
||||
- [`KT-23480`](https://youtrack.jetbrains.com/issue/KT-23480) java.util.NoSuchElementException: "Collection contains no element matching the predicate" on run of a scratch file with unresolved function parameter
|
||||
- [`KT-23587`](https://youtrack.jetbrains.com/issue/KT-23587) Scratch: references from scratch file aren't taken into account
|
||||
- [`KT-24016`](https://youtrack.jetbrains.com/issue/KT-24016) Make long scratch output lines readable
|
||||
- [`KT-24315`](https://youtrack.jetbrains.com/issue/KT-24315) Checkbox labels aren't aligned in scratch panel
|
||||
- [`KT-24636`](https://youtrack.jetbrains.com/issue/KT-24636) Run Scratch when there are compilation errors in module
|
||||
|
||||
#### Tools. J2K
|
||||
|
||||
- [`KT-22989`](https://youtrack.jetbrains.com/issue/KT-22989) Exception "Assertion failed: Refactorings should be invoked inside transaction" on creating UI Component/Notification
|
||||
|
||||
### Libraries
|
||||
|
||||
- [`KT-10456`](https://youtrack.jetbrains.com/issue/KT-10456) Common Int.toString(radix: Int) method
|
||||
- [`KT-22298`](https://youtrack.jetbrains.com/issue/KT-22298) Improve docs for Array.copyOf(newSize: Int)
|
||||
- [`KT-22400`](https://youtrack.jetbrains.com/issue/KT-22400) coroutineContext shall be in kotlin.coroutines.experimental package
|
||||
- [`KT-23356`](https://youtrack.jetbrains.com/issue/KT-23356) Cross-platform function to convert CharArray slice to String
|
||||
- [`KT-23920`](https://youtrack.jetbrains.com/issue/KT-23920) CharSequence.trimEnd calls substring instead of subSequence
|
||||
- [`KT-24353`](https://youtrack.jetbrains.com/issue/KT-24353) Add support for junit 5 in kotlin.test
|
||||
- [`KT-24371`](https://youtrack.jetbrains.com/issue/KT-24371) Invalid @returns tag does not display in Android Studio popup properly
|
||||
|
||||
### Gradle plugin
|
||||
|
||||
- [`KT-20214`](https://youtrack.jetbrains.com/issue/KT-20214) NoClassDefFound from Gradle (should report missing tools.jar)
|
||||
- [`KT-20608`](https://youtrack.jetbrains.com/issue/KT-20608) Cannot reference operator overloads across submodules (.kotlin_module not loaded when a module name has a slash)
|
||||
- [`KT-22431`](https://youtrack.jetbrains.com/issue/KT-22431) Inter-project incremental compilation does not work with Android plugin 2.3+
|
||||
- [`KT-22510`](https://youtrack.jetbrains.com/issue/KT-22510) Common sources aren't added when compiling custom source set with Gradle multiplatform plugin
|
||||
- [`KT-22623`](https://youtrack.jetbrains.com/issue/KT-22623) Kotlin JVM tasks in independent projects are not executed in parallel with Gradle 4.2+ and Kotlin 1.2.20+
|
||||
- [`KT-23092`](https://youtrack.jetbrains.com/issue/KT-23092) Gradle plugin for MPP common modules should not remove the 'compileJava' task from `project.tasks`
|
||||
- [`KT-23574`](https://youtrack.jetbrains.com/issue/KT-23574) 'archivesBaseName' does not affect module name in common modules
|
||||
- [`KT-23719`](https://youtrack.jetbrains.com/issue/KT-23719) Incorrect Gradle Warning for expectedBy in kotlin-platform-android module
|
||||
- [`KT-23878`](https://youtrack.jetbrains.com/issue/KT-23878) Kapt: Annotation processors are run when formatting is changed
|
||||
- [`KT-24420`](https://youtrack.jetbrains.com/issue/KT-24420) Kapt plugin: Kapt task has overlapping outputs (and inputs) with Gradle's JavaCompile task
|
||||
- [`KT-24440`](https://youtrack.jetbrains.com/issue/KT-24440) Gradle daemon OOM due to function descriptors stuck forever
|
||||
|
||||
### Tools. kapt
|
||||
|
||||
- [`KT-23286`](https://youtrack.jetbrains.com/issue/KT-23286) kapt + nonascii = weird pathes
|
||||
- [`KT-23427`](https://youtrack.jetbrains.com/issue/KT-23427) kapt: for element with multiple annotations, annotation values erroneously use default when first annotation uses default
|
||||
- [`KT-23721`](https://youtrack.jetbrains.com/issue/KT-23721) Warning informing user that 'tools.jar' is absent in the plugin classpath is not show when there is also an error
|
||||
- [`KT-23898`](https://youtrack.jetbrains.com/issue/KT-23898) Kapt: Do now show a warning for APs from 'annotationProcessor' configuration also declared in 'kapt' configuration
|
||||
- [`KT-23964`](https://youtrack.jetbrains.com/issue/KT-23964) Kotlin Gradle plugin does not define inputs and outputs of annotation processors
|
||||
|
||||
## 1.2.41
|
||||
|
||||
### Compiler – Fixes
|
||||
- [`KT-23901`](https://youtrack.jetbrains.com/issue/KT-23901) Incremental compilation fails on Java 9
|
||||
- [`KT-23931`](https://youtrack.jetbrains.com/issue/KT-23931) Exception on optimizing eternal loops
|
||||
- [`KT-23900`](https://youtrack.jetbrains.com/issue/KT-23900) Exception on some cases with nested arrays
|
||||
- [`KT-23809`](https://youtrack.jetbrains.com/issue/KT-23809) Exception on processing complex hierarchies with `suspend` functions when `-Xdump-declarations-to` is active
|
||||
|
||||
### Other
|
||||
- [`KT-23973`](https://youtrack.jetbrains.com/issue/KT-23973) New compiler behavior lead to ambiguous mappings in Spring Boot temporarily reverted
|
||||
|
||||
## 1.2.40
|
||||
|
||||
### Compiler
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-22703`](https://youtrack.jetbrains.com/issue/KT-22703) Allow expect/actual annotation constructors to have default values
|
||||
- [`KT-19159`](https://youtrack.jetbrains.com/issue/KT-19159) Support `crossinline` lambda parameters of `suspend` function type
|
||||
- [`KT-21913`](https://youtrack.jetbrains.com/issue/KT-21913) Support default arguments for expected declarations
|
||||
- [`KT-19120`](https://youtrack.jetbrains.com/issue/KT-19120) Provide extra compiler arguments in `ScriptTemplateDefinition`
|
||||
- [`KT-19415`](https://youtrack.jetbrains.com/issue/KT-19415) Introduce `@JvmDefault` annotation
|
||||
- [`KT-21515`](https://youtrack.jetbrains.com/issue/KT-21515) Restrict visibility of classifiers inside `companion object`s
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-10057`](https://youtrack.jetbrains.com/issue/KT-10057) Use `lcmp` instruction instead of `kotlin/jvm/internal/Intrinsics.compare`
|
||||
- [`KT-14258`](https://youtrack.jetbrains.com/issue/KT-14258) Suboptimal codegen for private fieldaccess to private field in companion object
|
||||
- [`KT-18731`](https://youtrack.jetbrains.com/issue/KT-18731) `==` between enums should use reference equality, not `Intrinsics.areEqual()`.
|
||||
- [`KT-22714`](https://youtrack.jetbrains.com/issue/KT-22714) Unnecessary checkcast to array of object from an array of specific type
|
||||
- [`KT-5177`](https://youtrack.jetbrains.com/issue/KT-5177) Optimize code generation for `for` loop with `withIndex()`
|
||||
- [`KT-19477`](https://youtrack.jetbrains.com/issue/KT-19477) Allow to implement several common modules with a single platform module
|
||||
- [`KT-21347`](https://youtrack.jetbrains.com/issue/KT-21347) Add compiler warning about using kotlin-stdlib-jre7 or kotlin-stdlib-jre8 artifacts
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-16424`](https://youtrack.jetbrains.com/issue/KT-16424) Broken bytecode for nullable generic methods
|
||||
- [`KT-17171`](https://youtrack.jetbrains.com/issue/KT-17171) `ClassCastException` in case of SAM conversion with `out` variance
|
||||
- [`KT-19399`](https://youtrack.jetbrains.com/issue/KT-19399) Incorrect bytecode generated for inline functions in some complex cases
|
||||
- [`KT-21696`](https://youtrack.jetbrains.com/issue/KT-21696) Incorrect warning for use-site target on extension function
|
||||
- [`KT-22031`](https://youtrack.jetbrains.com/issue/KT-22031) Non-`abstract` expect classes should not have `abstract` members
|
||||
- [`KT-22260`](https://youtrack.jetbrains.com/issue/KT-22260) Never flag `inline suspend fun` with `NOTHING_TO_INLINE`
|
||||
- [`KT-22352`](https://youtrack.jetbrains.com/issue/KT-22352) Expect/actual checker can't handle properties and functions with the same name
|
||||
- [`KT-22652`](https://youtrack.jetbrains.com/issue/KT-22652) Interface with default overrides is not perceived as a SAM
|
||||
- [`KT-22904`](https://youtrack.jetbrains.com/issue/KT-22904) Incorrect bytecode generated for withIndex iteration on `Array<Int>`
|
||||
- [`KT-22906`](https://youtrack.jetbrains.com/issue/KT-22906) Invalid class name generated for lambda created from method reference in anonymous object
|
||||
- [`KT-23044`](https://youtrack.jetbrains.com/issue/KT-23044) Overriden public property with internal setter cannot be found in runtime
|
||||
- [`KT-23104`](https://youtrack.jetbrains.com/issue/KT-23104) Incorrect code generated for LHS of an intrinsified `in` operator in case of generic type substituted with `Character`
|
||||
- [`KT-23309`](https://youtrack.jetbrains.com/issue/KT-23309) Minor spelling errors in JVM internal error messages
|
||||
- [`KT-22001`](https://youtrack.jetbrains.com/issue/KT-22001) JS: compiler crashes on += with "complex" receiver
|
||||
- [`KT-23239`](https://youtrack.jetbrains.com/issue/KT-23239) JS: Default arguments for non-final member function support is missing for MPP
|
||||
- [`KT-17091`](https://youtrack.jetbrains.com/issue/KT-17091) Converting to SAM Java type appends non-deterministic hash to class name
|
||||
- [`KT-21521`](https://youtrack.jetbrains.com/issue/KT-21521) Compilation exception when trying to compile a `suspend` function with `tailrec` keyword
|
||||
- [`KT-21605`](https://youtrack.jetbrains.com/issue/KT-21605) Cross-inlined coroutine with captured outer receiver creates unverifiable code
|
||||
- [`KT-21864`](https://youtrack.jetbrains.com/issue/KT-21864) Expect-actual matcher doesn't consider generic upper bounds
|
||||
- [`KT-21906`](https://youtrack.jetbrains.com/issue/KT-21906) `ACTUAL_MISSING` is reported for actual constructor of non-actual class
|
||||
- [`KT-21939`](https://youtrack.jetbrains.com/issue/KT-21939) Improve `ACTUAL_MISSING` diagnostics message
|
||||
- [`KT-22513`](https://youtrack.jetbrains.com/issue/KT-22513) Flaky "JarURLConnection.getUseCaches" NPE during compilation when using compiler plugins
|
||||
|
||||
### Libraries
|
||||
|
||||
- [`KT-11208`](https://youtrack.jetbrains.com/issue/KT-11208) `readLine()` shouldn't use buffered reader
|
||||
|
||||
### IDE
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-10368`](https://youtrack.jetbrains.com/issue/KT-10368) Run Action for Kotlin Scratch Files
|
||||
- [`KT-16892`](https://youtrack.jetbrains.com/issue/KT-16892) Shortcut to navigate between header and impl
|
||||
- [`KT-23005`](https://youtrack.jetbrains.com/issue/KT-23005) Support `prefix`/`suffix` attributes for language injection in Kotlin with annotations and comments
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-19484`](https://youtrack.jetbrains.com/issue/KT-19484) KotlinBinaryClassCache retains a lot of memory
|
||||
- [`KT-23183`](https://youtrack.jetbrains.com/issue/KT-23183) `ConfigureKotlinNotification.getNotificationString()` scans modules with Kotlin files twice
|
||||
- [`KT-23380`](https://youtrack.jetbrains.com/issue/KT-23380) Improve IDE performance when working with Spring projects
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-15482`](https://youtrack.jetbrains.com/issue/KT-15482) `KotlinNullPointerException` in IDE from expected class with nested class
|
||||
- [`KT-15739`](https://youtrack.jetbrains.com/issue/KT-15739) Internal visibility across common and platform-dependent modules
|
||||
- [`KT-19025`](https://youtrack.jetbrains.com/issue/KT-19025) Not imported `build.gradle.kts` is all red
|
||||
- [`KT-19165`](https://youtrack.jetbrains.com/issue/KT-19165) IntelliJ should suggest to reload Gradle projects when `build.gradle.kts` changes
|
||||
- [`KT-20282`](https://youtrack.jetbrains.com/issue/KT-20282) 'Move statement up' works incorrectly for statement after `finally` block if `try` block contains closure
|
||||
- [`KT-20521`](https://youtrack.jetbrains.com/issue/KT-20521) Kotlin Gradle script: valid `build.gradle.kts` is red and becomes normal only after reopening the project
|
||||
- [`KT-20592`](https://youtrack.jetbrains.com/issue/KT-20592) `KotlinNullPointerException`: nested class inside expect / actual interface
|
||||
- [`KT-21013`](https://youtrack.jetbrains.com/issue/KT-21013) "Move statement up/down" fails for multiline declarations
|
||||
- [`KT-21420`](https://youtrack.jetbrains.com/issue/KT-21420) `.gradle.kts` editor should do no semantic highlighting until the first successful dependency resolver response
|
||||
- [`KT-21683`](https://youtrack.jetbrains.com/issue/KT-21683) Language injection: JPAQL. Injection should be present for "query" parameter of `@NamedNativeQueries`
|
||||
- [`KT-21745`](https://youtrack.jetbrains.com/issue/KT-21745) Warning and quickfix about kotlin-stdlib-jre7/8 -> kotlin-stdlib-jdk7/8 in Maven
|
||||
- [`KT-21746`](https://youtrack.jetbrains.com/issue/KT-21746) Warning and quickfix about kotlin-stdlib-jre7/8 -> kotlin-stdlib-jdk7/8 in Gradle
|
||||
- [`KT-21753`](https://youtrack.jetbrains.com/issue/KT-21753) Language injection: SpEL. Not injected for key in `@Caching`
|
||||
- [`KT-21771`](https://youtrack.jetbrains.com/issue/KT-21771) All annotations in `Annotations.kt` from kotlin-test-js module wrongly have ACTUAL_MISSING
|
||||
- [`KT-21831`](https://youtrack.jetbrains.com/issue/KT-21831) Opening class from `kotlin-stdlib-jdk8.jar` fails with EE: "Stub list in ... length differs from PSI"
|
||||
- [`KT-22229`](https://youtrack.jetbrains.com/issue/KT-22229) Kotlin local delegated property Import auto-removed with "Java: Optimize imports on the fly"
|
||||
- [`KT-22724`](https://youtrack.jetbrains.com/issue/KT-22724) ISE: "psiFile must not be null" at `KotlinNodeJsRunConfigurationProducer.setupConfigurationFromContext()`
|
||||
- [`KT-22817`](https://youtrack.jetbrains.com/issue/KT-22817) Hitting 'Propagate Parameters' in Change Signature throws `UnsupportedOperationException`
|
||||
- [`KT-22851`](https://youtrack.jetbrains.com/issue/KT-22851) Apply button is always active on Kotlin compiler settings tab
|
||||
- [`KT-22858`](https://youtrack.jetbrains.com/issue/KT-22858) Multiplatform: String constructor parameter is reported in Java file of jvm module on creation of a new instance of a class from common module
|
||||
- [`KT-22865`](https://youtrack.jetbrains.com/issue/KT-22865) Support multiple expectedBy dependencies when importing project from Gradle or Maven
|
||||
- [`KT-22873`](https://youtrack.jetbrains.com/issue/KT-22873) Common module-based light classes do not see JDK
|
||||
- [`KT-22874`](https://youtrack.jetbrains.com/issue/KT-22874) Exception on surround with "if else" when resulting if should be wrapped with `()`
|
||||
- [`KT-22925`](https://youtrack.jetbrains.com/issue/KT-22925) Unable to view Type Hierarchy from constructor call in expression
|
||||
- [`KT-22926`](https://youtrack.jetbrains.com/issue/KT-22926) Confusing behavior of Type Hierarchy depending on the caret position at superclass constructor
|
||||
- [`KT-23097`](https://youtrack.jetbrains.com/issue/KT-23097) Enhance multiplatform project wizard
|
||||
- [`KT-23271`](https://youtrack.jetbrains.com/issue/KT-23271) Warn about using kotlin-stdlib-jre* libs in `dependencyManagement` section in Maven with `eap` and `dev` Kotlin versions
|
||||
- [`KT-20672`](https://youtrack.jetbrains.com/issue/KT-20672) IDE can't resolve references to elements from files with `@JvmPackageName`
|
||||
- [`KT-23546`](https://youtrack.jetbrains.com/issue/KT-23546) Variable name auto-completion popup gets in the way
|
||||
- [`KT-23546`](https://youtrack.jetbrains.com/issue/KT-23546) Do not show duplicated names in variables completion list
|
||||
- [`KT-19120`](https://youtrack.jetbrains.com/issue/KT-19120) Use script compiler options on script dependencies in the IDE as well
|
||||
|
||||
### IDE. Gradle. Script
|
||||
|
||||
- [`KT-23228`](https://youtrack.jetbrains.com/issue/KT-23228) Do not highlight `.gradle.kts` files in non-Gradle projects
|
||||
|
||||
### IDE. Inspections and Intentions
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-16382`](https://youtrack.jetbrains.com/issue/KT-16382) Intention to convert `expr.unsafeCast<Type>()` to `expr as Type` and vice versa
|
||||
- [`KT-20439`](https://youtrack.jetbrains.com/issue/KT-20439) Intentions to add/remove labeled return to last expression in a lambda
|
||||
- [`KT-22011`](https://youtrack.jetbrains.com/issue/KT-22011) Inspection to report the usage of Java Collections methods on immutable Kotlin Collections
|
||||
- [`KT-22933`](https://youtrack.jetbrains.com/issue/KT-22933) Intention/inspection to convert Pair constructor to `to` function
|
||||
- [`KT-19871`](https://youtrack.jetbrains.com/issue/KT-19871) Intentions for specifying use-site targets for an annotation
|
||||
- [`KT-22971`](https://youtrack.jetbrains.com/issue/KT-22971) Inspection to highlight and remove unnecessary explicit companion object references
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-12226`](https://youtrack.jetbrains.com/issue/KT-12226) "Convert concatenation to template" does not process `$` sign as a Char
|
||||
- [`KT-15858`](https://youtrack.jetbrains.com/issue/KT-15858) "Replace with a `foreach` function call" intention breaks code
|
||||
- [`KT-16332`](https://youtrack.jetbrains.com/issue/KT-16332) Add braces to 'if' statement intention does not put end-of-line comment properly into braces
|
||||
- [`KT-17058`](https://youtrack.jetbrains.com/issue/KT-17058) "Create implementations from headers": each implementation gets own file
|
||||
- [`KT-17306`](https://youtrack.jetbrains.com/issue/KT-17306) Don't report package name mismatch if there's no Java code in the module
|
||||
- [`KT-19730`](https://youtrack.jetbrains.com/issue/KT-19730) Quickfix for delegated properties boilerplate generation doesn't work on locals
|
||||
- [`KT-21005`](https://youtrack.jetbrains.com/issue/KT-21005) "Missing KDoc inspection" is broken
|
||||
- [`KT-21082`](https://youtrack.jetbrains.com/issue/KT-21082) "Create actual declaration" of top-level subclass of expected `sealed class` in the same file as actual declaration of sealed class present
|
||||
- [`KT-22110`](https://youtrack.jetbrains.com/issue/KT-22110) "Can be joined with assignment" inspection underlining extends into comment
|
||||
- [`KT-22329`](https://youtrack.jetbrains.com/issue/KT-22329) "Create class" quickfix is not suggested in `when` branch
|
||||
- [`KT-22428`](https://youtrack.jetbrains.com/issue/KT-22428) Create member function from usage shouldn't present type parameters as options
|
||||
- [`KT-22492`](https://youtrack.jetbrains.com/issue/KT-22492) "Specify explicit lambda signature" intention is available only on lambda braces
|
||||
- [`KT-22719`](https://youtrack.jetbrains.com/issue/KT-22719) Incorrect warning 'Redundant semicolon' when having method call before lambda expression
|
||||
- [`KT-22861`](https://youtrack.jetbrains.com/issue/KT-22861) "Add annotation target" quickfix is not available on annotation with use site target
|
||||
- [`KT-22862`](https://youtrack.jetbrains.com/issue/KT-22862) "Add annotation target" quickfix does not process existent annotations with use site target
|
||||
- [`KT-22917`](https://youtrack.jetbrains.com/issue/KT-22917) Update order of containers for `create class` quickfix
|
||||
- [`KT-22949`](https://youtrack.jetbrains.com/issue/KT-22949) NPE on conversion of `run`/`apply` with explicit lambda signature to `let`/`also`
|
||||
- [`KT-22950`](https://youtrack.jetbrains.com/issue/KT-22950) Convert stdlib extension function to scoping function works incorrectly in case of explicit lambda signature
|
||||
- [`KT-22954`](https://youtrack.jetbrains.com/issue/KT-22954) "Sort modifiers" quickfix works incorrectly when method is annotated
|
||||
- [`KT-22970`](https://youtrack.jetbrains.com/issue/KT-22970) Add explicit this intention/inspection missing for lambda invocation
|
||||
- [`KT-23109`](https://youtrack.jetbrains.com/issue/KT-23109) "Remove redundant 'if' statement" inspection breaks code with labeled return
|
||||
- [`KT-23215`](https://youtrack.jetbrains.com/issue/KT-23215) "Add function to supertype" quickfix works incorrectly
|
||||
- [`KT-14270`](https://youtrack.jetbrains.com/issue/KT-14270) Intentions "Add/Remove braces" should be applied to the statement where caret is if there several nested statements one into another
|
||||
- [`KT-21743`](https://youtrack.jetbrains.com/issue/KT-21743) Method reference not correctly moved into parentheses
|
||||
- [`KT-23045`](https://youtrack.jetbrains.com/issue/KT-23045) AE “Failed to create expression from text” on concatenating string with broken quote mark char literal
|
||||
- [`KT-23046`](https://youtrack.jetbrains.com/issue/KT-23046) CCE ”KtBinaryExpression cannot be cast to KtStringTemplateExpression” on concatenating broken quote mark char literal with string
|
||||
- [`KT-23227`](https://youtrack.jetbrains.com/issue/KT-23227) "Add annotation target" quickfix is not suggested for `field:` use-site target
|
||||
|
||||
### IDE. Refactorings
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-13255`](https://youtrack.jetbrains.com/issue/KT-13255) Refactor / Rename: renaming local variable or class to existing name gives no warning
|
||||
- [`KT-13284`](https://youtrack.jetbrains.com/issue/KT-13284) Refactor / Rename: superfluous imports and FQNs in Java using `@JvmOverloads` functions
|
||||
- [`KT-13907`](https://youtrack.jetbrains.com/issue/KT-13907) Rename refactoring warns about name conflict if there is function with different signature but the same name
|
||||
- [`KT-13986`](https://youtrack.jetbrains.com/issue/KT-13986) Full qualified names of classes in comments should be changed after class Move, if comment contains backquotes
|
||||
- [`KT-14671`](https://youtrack.jetbrains.com/issue/KT-14671) `typealias`: refactor/rename should propose to rename occurrences in comments
|
||||
- [`KT-15039`](https://youtrack.jetbrains.com/issue/KT-15039) Extra usage is found for a parameter in data class in destructuring construction
|
||||
- [`KT-15228`](https://youtrack.jetbrains.com/issue/KT-15228) Extract function from inline function should create public function
|
||||
- [`KT-15302`](https://youtrack.jetbrains.com/issue/KT-15302) Reference to typealias in SAM conversion is not found
|
||||
- [`KT-16510`](https://youtrack.jetbrains.com/issue/KT-16510) Can't rename quoted identifier `is`
|
||||
- [`KT-17827`](https://youtrack.jetbrains.com/issue/KT-17827) Refactor / Move corrupts bound references when containing class of member element is changed
|
||||
- [`KT-19561`](https://youtrack.jetbrains.com/issue/KT-19561) Name conflict warning when renaming method to a name matching an extension method with the same name exists
|
||||
- [`KT-20178`](https://youtrack.jetbrains.com/issue/KT-20178) Refactor → Rename can't make companion object name empty
|
||||
- [`KT-22282`](https://youtrack.jetbrains.com/issue/KT-22282) Moving a Kotlin file to another package does not change imports in itself
|
||||
- [`KT-22482`](https://youtrack.jetbrains.com/issue/KT-22482) Rename refactoring insert qualifier for non related property call
|
||||
- [`KT-22661`](https://youtrack.jetbrains.com/issue/KT-22661) Refactor/Move: top level field reference is not imported automatically after move to the source root
|
||||
- [`KT-22678`](https://youtrack.jetbrains.com/issue/KT-22678) Refactor / Copy: "Class uses constructor which will be inaccessible after move" when derived class has a protected constructor
|
||||
- [`KT-22692`](https://youtrack.jetbrains.com/issue/KT-22692) Refactor/Move: unnecessary curly braces added on moving to a separate file a top level function with a top level field usage
|
||||
- [`KT-22745`](https://youtrack.jetbrains.com/issue/KT-22745) Refactor/Move inserts FQ function name at the call site if there is a field same named as the function
|
||||
- [`KT-22747`](https://youtrack.jetbrains.com/issue/KT-22747) Moving top-level function to a different (existing) file doesn't update references from Java
|
||||
- [`KT-22751`](https://youtrack.jetbrains.com/issue/KT-22751) Refactor/Rename: type alias name clash is not reported
|
||||
- [`KT-22769`](https://youtrack.jetbrains.com/issue/KT-22769) Refactor/Move: there is no warning on moving sealed class or its inheritors to another file
|
||||
- [`KT-22771`](https://youtrack.jetbrains.com/issue/KT-22771) Refactor/Move: there is no warning on moving nested class to another class with stricter visibility
|
||||
- [`KT-22812`](https://youtrack.jetbrains.com/issue/KT-22812) Refactor/Rename extension functions incorrectly conflicts with other extension functions
|
||||
- [`KT-23065`](https://youtrack.jetbrains.com/issue/KT-23065) Refactor/Move: Specify the warning message on moving sealed class inheritors without moving the sealed class itself
|
||||
|
||||
### IDE. Script
|
||||
|
||||
- [`KT-22647`](https://youtrack.jetbrains.com/issue/KT-22647) Run script Action in IDE should use Kotlin compiler from the IDE plugin
|
||||
- [`KT-18930`](https://youtrack.jetbrains.com/issue/KT-18930) IDEA is unstable With Gradle Kotlin DSL
|
||||
- [`KT-21042`](https://youtrack.jetbrains.com/issue/KT-21042) Gradle Script Kotlin project is full-red
|
||||
- [`KT-11618`](https://youtrack.jetbrains.com/issue/KT-11618) Running .kts file from IntelliJ IDEA doesn't allow to import classes in other files which are also part of the project
|
||||
|
||||
|
||||
### IDE. Debugger
|
||||
|
||||
- [`KT-22205`](https://youtrack.jetbrains.com/issue/KT-22205) Breakpoints won't work for Kotlin testing with JUnit
|
||||
|
||||
### JavaScript
|
||||
|
||||
- [`KT-22019`](https://youtrack.jetbrains.com/issue/KT-22019) Fix wrong list sorting order
|
||||
|
||||
### Tools. CLI
|
||||
|
||||
- [`KT-22777`](https://youtrack.jetbrains.com/issue/KT-22777) Unstable language version setting has no effect when attached runtime has lower version
|
||||
|
||||
### Tools. Gradle
|
||||
|
||||
- [`KT-22824`](https://youtrack.jetbrains.com/issue/KT-22824) `expectedBy` dependency should be expressed as `compile` dependency in POM
|
||||
- [`KT-15371`](https://youtrack.jetbrains.com/issue/KT-15371) Multiplatform: setting free compiler args can break build
|
||||
- [`KT-22864`](https://youtrack.jetbrains.com/issue/KT-22864) Allow multiple expectedBy configuration dependencies in Gradle
|
||||
- [`KT-22895`](https://youtrack.jetbrains.com/issue/KT-22895) 'kotlin-runtime' library is missing in the compiler classpath sometimes
|
||||
- [`KT-23085`](https://youtrack.jetbrains.com/issue/KT-23085) Use proper names for the Gradle task inputs/outputs added at runtime
|
||||
- [`KT-23694`](https://youtrack.jetbrains.com/issue/KT-23694) Fix parallel build in Kotlin IC – invalid KotlinCoreEnvironment disposal
|
||||
|
||||
### Tools. Android
|
||||
- Android Extensions: Support fragments from kotlinx package;
|
||||
|
||||
### Tools. Incremental Compile
|
||||
|
||||
- [`KT-20516`](https://youtrack.jetbrains.com/issue/KT-20516) "Unresolved reference" when project declares same class as its dependency
|
||||
- [`KT-22542`](https://youtrack.jetbrains.com/issue/KT-22542) "Source file or directory not found" for incremental compilation with Kobalt
|
||||
- [`KT-23165`](https://youtrack.jetbrains.com/issue/KT-23165) Incremental compilation is sometimes broken after moving one class
|
||||
|
||||
### Tools. JPS
|
||||
|
||||
- [`KT-16091`](https://youtrack.jetbrains.com/issue/KT-16091) Incremental compilation ignores changes in Java static field
|
||||
- [`KT-22995`](https://youtrack.jetbrains.com/issue/KT-22995) EA-91869 - NA: `LookupStorage.<init>`
|
||||
|
||||
### Tools. kapt
|
||||
|
||||
- [`KT-21735`](https://youtrack.jetbrains.com/issue/KT-21735) Kapt cache was not cleared sometimes
|
||||
|
||||
### Tools. REPL
|
||||
|
||||
- [`KT-21611`](https://youtrack.jetbrains.com/issue/KT-21611) REPL: Empty lines should be ignored
|
||||
|
||||
## 1.2.30
|
||||
|
||||
### Android
|
||||
|
||||
22
ReadMe.md
22
ReadMe.md
@@ -23,7 +23,7 @@ Welcome to [Kotlin](https://kotlinlang.org/)! Some handy links:
|
||||
|
||||
* [Kotlin IntelliJ IDEA Plugin](https://kotlinlang.org/docs/tutorials/getting-started.html)
|
||||
* [Kotlin Eclipse Plugin](https://kotlinlang.org/docs/tutorials/getting-started-eclipse.html)
|
||||
* [Kotlin Sublime Text Package](https://github.com/vkostyukov/kotlin-sublime-package)
|
||||
* [Kotlin TextMate Bundle](https://github.com/vkostyukov/kotlin-sublime-package)
|
||||
|
||||
## Build environment requirements
|
||||
|
||||
@@ -81,24 +81,6 @@ command line parameters on the first run:
|
||||
**OPTIONAL:** Some artifacts, mainly Maven plugin ones, are built separately with Maven.
|
||||
Refer to [libraries/ReadMe.md](libraries/ReadMe.md) for details.
|
||||
|
||||
|
||||
### Building for different versions of IntelliJ IDEA and Android Studio
|
||||
|
||||
Kotlin plugin is indented to work with several recent versions of IntelliJ IDEA and Android Studio. Each platform is allowed to have a different set of features and might provide a slightly different API. Instead of using several parallel Git branches, project stores everything in a single branch, but files may have counterparts with version extensions (\*.as32, \*.172, \*.181). The primary file is expected to be replaced with its counterpart when targeting non-default platform.
|
||||
|
||||
More detailed description of this scheme can be found at https://github.com/JetBrains/bunches/blob/master/ReadMe.md.
|
||||
|
||||
Usually, there's no need to care about multiple platforms as all features are enabled everywhere by default. Additional counterparts should be created if there's an expected difference in behavior or an incompatible API usage is required **and** there's no reasonable workaround to save source compatibility. Kotlin plugin contains a pre-commit check that shows a warning if a file has been updated without its counterparts.
|
||||
|
||||
Development for some particular platform is possible after 'switching' that can be done with [Bunch Tool](https://github.com/JetBrains/bunches/releases) from the command line.
|
||||
|
||||
```sh
|
||||
cd kotlin-project-dir
|
||||
|
||||
# switching to IntelliJ Idea 2018.2
|
||||
bunch switch . 182
|
||||
```
|
||||
|
||||
## <a name="working-in-idea"></a> Working with the project in IntelliJ IDEA
|
||||
|
||||
Working with the Kotlin project requires IntelliJ IDEA 2017.3. You can download IntelliJ IDEA 2017.3 [here](https://www.jetbrains.com/idea/download).
|
||||
@@ -108,7 +90,7 @@ To import the project in Intellij choose project directory in Open project dialo
|
||||
|
||||
In the import dialog, select `use default gradle wrapper`.
|
||||
|
||||
To be able to run tests from IntelliJ easily, check `Delegate IDE build/run actions to Gradle` and choose `Gradle Test Runner` in the Gradle runner settings.
|
||||
To be able to run tests from IntelliJ easily, check `Delegate IDE build/run actions to Gradle` in the Gradle runner settings.
|
||||
|
||||
At this time, you can use the latest released 1.2.x version of the Kotlin plugin for working with the code. To make sure you have the latest version installed, use Tools | Kotlin | Configure Kotlin Plugin Updates and press "Check for updates now".
|
||||
|
||||
|
||||
121
TeamCityBuild.xml
Normal file
121
TeamCityBuild.xml
Normal file
@@ -0,0 +1,121 @@
|
||||
<project name="Kotlin CI Steps" default="none">
|
||||
<import file="common.xml" optional="false"/>
|
||||
<property name="kotlin-home" value="${output}/kotlinc"/>
|
||||
|
||||
<property name="build.number" value="snapshot"/>
|
||||
<property name="fail.on.plugin.verifier.error" value="true"/>
|
||||
|
||||
<property name="version_substitute_dir" value="${basedir}/versions_temp/"/>
|
||||
|
||||
<property name="artifact.output.path" value="${basedir}/dist/artifacts/ideaPlugin"/>
|
||||
<property name="plugin.xml" value="idea/src/META-INF/plugin.xml"/>
|
||||
<property name="plugin.xml.bk" value="${version_substitute_dir}/plugin.xml.bk"/>
|
||||
<property name="plugin.xml.versioned" value="${plugin.xml}.versioned"/>
|
||||
<property name="plugin.xml.version.number" value="${build.number}"/>
|
||||
|
||||
<property name="compiler.version.java" value="core/util.runtime/src/org/jetbrains/kotlin/config/KotlinCompilerVersion.java"/>
|
||||
<property name="compiler.version.java.bk" value="${version_substitute_dir}/KotlinCompilerVersion.java.bk"/>
|
||||
<property name="compiler.version.java.versioned" value="${compiler.version.java}.versioned"/>
|
||||
<property name="compiler.version.number" value="${build.number}"/>
|
||||
<property name="compiler.ant.fork.jvmargs" value="-Xmx1024m"/>
|
||||
|
||||
<property name="plugin.zip" value="${artifact.output.path}/kotlin-plugin-${build.number}.zip"/>
|
||||
<property name="pluginArtifactDir" value="Kotlin" />
|
||||
|
||||
<macrodef name="echoprop">
|
||||
<attribute name="prop"/>
|
||||
<sequential>
|
||||
<echo>@{prop}=${@{prop}}</echo>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<echoprop prop="os.name"/>
|
||||
<echoprop prop="os.version"/>
|
||||
<echoprop prop="os.arch"/>
|
||||
<echoprop prop="java.home"/>
|
||||
<echoprop prop="java.vendor"/>
|
||||
<echoprop prop="java.version"/>
|
||||
<echoprop prop="user.name"/>
|
||||
<echoprop prop="user.home"/>
|
||||
<echoprop prop="user.dir"/>
|
||||
|
||||
<macrodef name="run-gradle">
|
||||
<attribute name="tasks" />
|
||||
<attribute name="args" default="" />
|
||||
<sequential>
|
||||
<java classname="org.gradle.wrapper.GradleWrapperMain"
|
||||
fork="true"
|
||||
dir="${basedir}"
|
||||
failonerror="true"
|
||||
timeout="4000000"
|
||||
maxmemory="400m"
|
||||
taskname="gradle">
|
||||
<classpath>
|
||||
<pathelement location="${basedir}/gradle/wrapper/gradle-wrapper.jar"/>
|
||||
</classpath>
|
||||
<arg line="--no-daemon" />
|
||||
<arg line="@{tasks}" />
|
||||
<arg line="@{args}" />
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<target name="cleanupArtifacts">
|
||||
<run-gradle tasks="cleanupArtifacts" />
|
||||
</target>
|
||||
|
||||
<target name="zip-compiler">
|
||||
<run-gradle tasks="zipCompiler" args="-PdeployVersion=${build.number}" />
|
||||
</target>
|
||||
|
||||
<target name="zip-test-data">
|
||||
<run-gradle tasks="zipTestData" />
|
||||
</target>
|
||||
|
||||
<target name="writeCompilerVersionToTemplateFile">
|
||||
<!-- empty, version is written in gradle build -->
|
||||
</target>
|
||||
|
||||
<target name="writePluginVersionToTemplateFile">
|
||||
<run-gradle tasks="writePluginVersion" args="-PpluginVersion=${plugin.xml.version.number}" />
|
||||
</target>
|
||||
|
||||
<target name="zipArtifacts">
|
||||
<run-gradle tasks="zipPlugin" args="-PpluginArtifactDir=${pluginArtifactDir} -PpluginZipPath=${plugin.zip}"/>
|
||||
</target>
|
||||
|
||||
<macrodef name="print-statistic">
|
||||
<attribute name="key"/>
|
||||
<attribute name="value"/>
|
||||
|
||||
<sequential>
|
||||
<echo message="##teamcity[buildStatisticValue key='@{key}' value='@{value}']"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<macrodef name="print-file-size-statistic">
|
||||
<attribute name="path"/>
|
||||
<attribute name="file-name"/>
|
||||
|
||||
<sequential>
|
||||
<local name="file.size"/>
|
||||
<length file="@{path}/@{file-name}" property="file.size"/>
|
||||
<print-statistic key="@{file-name} size" value="${file.size}"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<target name="printStatistics">
|
||||
<print-file-size-statistic path="${kotlin-home}/lib" file-name="kotlin-stdlib.jar"/>
|
||||
<print-file-size-statistic path="${kotlin-home}/lib" file-name="kotlin-reflect.jar"/>
|
||||
|
||||
<print-file-size-statistic path="${kotlin-home}/lib" file-name="kotlin-stdlib-js.jar"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="kotlin.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="kotlin-test.js"/>
|
||||
<print-file-size-statistic path="${basedir}/libraries/stdlib/js/build/classes/main" file-name="kotlin.meta.js"/>
|
||||
</target>
|
||||
|
||||
<target name="none">
|
||||
<fail message="Either specify pre_build or post_build"/>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
92
TeamCityRelay.xml
Normal file
92
TeamCityRelay.xml
Normal file
@@ -0,0 +1,92 @@
|
||||
<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-android-extensions"
|
||||
plugin.path="${relay.plugins.dir}/kotlin-android-extensions-plugin-${relay.origin.version}.zip"
|
||||
origin.version="${relay.origin.version}"
|
||||
plugin.subdir="KotlinAndroidExtensions"
|
||||
substituted.version="${relay.substitute.version}"/>
|
||||
</target>
|
||||
</project>
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.config.isPreRelease
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
interface BuildMetaInfo {
|
||||
val isEAP: Boolean
|
||||
val compilerBuildVersion: String
|
||||
val languageVersionString: String
|
||||
val apiVersionString: String
|
||||
val coroutinesEnable: Boolean
|
||||
val coroutinesWarn: Boolean
|
||||
val coroutinesError: Boolean
|
||||
val multiplatformEnable: Boolean
|
||||
val metadataVersionMajor: Int
|
||||
val metadataVersionMinor: Int
|
||||
val metadataVersionPatch: Int
|
||||
val ownVersion: Int
|
||||
val coroutinesVersion: Int
|
||||
val multiplatformVersion: Int
|
||||
}
|
||||
|
||||
abstract class BuildMetaInfoFactory<T : BuildMetaInfo>(private val metaInfoClass: KClass<T>) {
|
||||
protected abstract fun create(
|
||||
isEAP: Boolean,
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
multiplatformVersion: Int
|
||||
): T
|
||||
|
||||
fun create(args: CommonCompilerArguments): T {
|
||||
val languageVersion = args.languageVersion?.let((LanguageVersion)::fromVersionString) ?: LanguageVersion.LATEST_STABLE
|
||||
|
||||
return create(
|
||||
isEAP = languageVersion.isPreRelease(),
|
||||
compilerBuildVersion = KotlinCompilerVersion.VERSION,
|
||||
languageVersionString = languageVersion.versionString,
|
||||
apiVersionString = args.apiVersion ?: languageVersion.versionString,
|
||||
coroutinesEnable = args.coroutinesState == CommonCompilerArguments.ENABLE,
|
||||
coroutinesWarn = args.coroutinesState == CommonCompilerArguments.WARN,
|
||||
coroutinesError = args.coroutinesState == CommonCompilerArguments.ERROR,
|
||||
multiplatformEnable = args.multiPlatform,
|
||||
ownVersion = OWN_VERSION,
|
||||
coroutinesVersion = COROUTINES_VERSION,
|
||||
multiplatformVersion = MULTIPLATFORM_VERSION
|
||||
)
|
||||
}
|
||||
|
||||
fun serializeToString(info: T): String =
|
||||
serializeToPlainText(info, metaInfoClass)
|
||||
|
||||
fun deserializeFromString(str: String): T? =
|
||||
deserializeFromPlainText(str, metaInfoClass)
|
||||
|
||||
companion object {
|
||||
const val OWN_VERSION: Int = 0
|
||||
const val COROUTINES_VERSION: Int = 0
|
||||
const val MULTIPLATFORM_VERSION: Int = 0
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.utils.JsMetadataVersion
|
||||
|
||||
/**
|
||||
* If you want to add a new field, check its type is supported by [serializeToPlainText], [deserializeFromPlainText]
|
||||
*/
|
||||
data class CommonBuildMetaInfo(
|
||||
override val isEAP: Boolean,
|
||||
override val compilerBuildVersion: String,
|
||||
override val languageVersionString: String,
|
||||
override val apiVersionString: String,
|
||||
override val coroutinesEnable: Boolean,
|
||||
override val coroutinesWarn: Boolean,
|
||||
override val coroutinesError: Boolean,
|
||||
override val multiplatformEnable: Boolean,
|
||||
override val metadataVersionMajor: Int,
|
||||
override val metadataVersionMinor: Int,
|
||||
override val metadataVersionPatch: Int,
|
||||
override val ownVersion: Int,
|
||||
override val coroutinesVersion: Int,
|
||||
override val multiplatformVersion: Int
|
||||
) : BuildMetaInfo {
|
||||
companion object : BuildMetaInfoFactory<CommonBuildMetaInfo>(CommonBuildMetaInfo::class) {
|
||||
override fun create(
|
||||
isEAP: Boolean,
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
multiplatformVersion: Int
|
||||
) = CommonBuildMetaInfo(
|
||||
isEAP = isEAP,
|
||||
compilerBuildVersion = compilerBuildVersion,
|
||||
languageVersionString = languageVersionString,
|
||||
apiVersionString = apiVersionString,
|
||||
coroutinesEnable = coroutinesEnable,
|
||||
coroutinesWarn = coroutinesWarn,
|
||||
coroutinesError = coroutinesError,
|
||||
multiplatformEnable = multiplatformEnable,
|
||||
metadataVersionMajor = JvmMetadataVersion.INSTANCE.major,
|
||||
metadataVersionMinor = JvmMetadataVersion.INSTANCE.minor,
|
||||
metadataVersionPatch = JvmMetadataVersion.INSTANCE.patch,
|
||||
ownVersion = ownVersion,
|
||||
coroutinesVersion = coroutinesVersion,
|
||||
multiplatformVersion = multiplatformVersion
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import org.jetbrains.kotlin.utils.JsMetadataVersion
|
||||
|
||||
/**
|
||||
* If you want to add a new field, check its type is supported by [serializeToPlainText], [deserializeFromPlainText]
|
||||
*/
|
||||
data class JsBuildMetaInfo(
|
||||
override val isEAP: Boolean,
|
||||
override val compilerBuildVersion: String,
|
||||
override val languageVersionString: String,
|
||||
override val apiVersionString: String,
|
||||
override val coroutinesEnable: Boolean,
|
||||
override val coroutinesWarn: Boolean,
|
||||
override val coroutinesError: Boolean,
|
||||
override val multiplatformEnable: Boolean,
|
||||
override val metadataVersionMajor: Int,
|
||||
override val metadataVersionMinor: Int,
|
||||
override val metadataVersionPatch: Int,
|
||||
override val ownVersion: Int,
|
||||
override val coroutinesVersion: Int,
|
||||
override val multiplatformVersion: Int
|
||||
) : BuildMetaInfo {
|
||||
companion object : BuildMetaInfoFactory<JsBuildMetaInfo>(JsBuildMetaInfo::class) {
|
||||
override fun create(
|
||||
isEAP: Boolean,
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
multiplatformVersion: Int
|
||||
) = JsBuildMetaInfo(
|
||||
isEAP = isEAP,
|
||||
compilerBuildVersion = compilerBuildVersion,
|
||||
languageVersionString = languageVersionString,
|
||||
apiVersionString = apiVersionString,
|
||||
coroutinesEnable = coroutinesEnable,
|
||||
coroutinesWarn = coroutinesWarn,
|
||||
coroutinesError = coroutinesError,
|
||||
multiplatformEnable = multiplatformEnable,
|
||||
metadataVersionMajor = JsMetadataVersion.INSTANCE.major,
|
||||
metadataVersionMinor = JsMetadataVersion.INSTANCE.minor,
|
||||
metadataVersionPatch = JsMetadataVersion.INSTANCE.patch,
|
||||
ownVersion = ownVersion,
|
||||
coroutinesVersion = coroutinesVersion,
|
||||
multiplatformVersion = multiplatformVersion
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -16,62 +16,66 @@
|
||||
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmBytecodeBinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.config.isPreRelease
|
||||
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
||||
|
||||
/**
|
||||
* If you want to add a new field, check its type is supported by [serializeToPlainText], [deserializeFromPlainText]
|
||||
*/
|
||||
data class JvmBuildMetaInfo(
|
||||
override val isEAP: Boolean,
|
||||
override val compilerBuildVersion: String,
|
||||
override val languageVersionString: String,
|
||||
override val apiVersionString: String,
|
||||
override val coroutinesEnable: Boolean,
|
||||
override val coroutinesWarn: Boolean,
|
||||
override val coroutinesError: Boolean,
|
||||
override val multiplatformEnable: Boolean,
|
||||
override val metadataVersionMajor: Int,
|
||||
override val metadataVersionMinor: Int,
|
||||
override val metadataVersionPatch: Int,
|
||||
val bytecodeVersionMajor: Int,
|
||||
val bytecodeVersionMinor: Int,
|
||||
val bytecodeVersionPatch: Int,
|
||||
override val ownVersion: Int,
|
||||
override val coroutinesVersion: Int,
|
||||
override val multiplatformVersion: Int
|
||||
) : BuildMetaInfo {
|
||||
companion object : BuildMetaInfoFactory<JvmBuildMetaInfo>(JvmBuildMetaInfo::class) {
|
||||
override fun create(
|
||||
isEAP: Boolean,
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
multiplatformVersion: Int
|
||||
) = JvmBuildMetaInfo(
|
||||
isEAP = isEAP,
|
||||
compilerBuildVersion = compilerBuildVersion,
|
||||
languageVersionString = languageVersionString,
|
||||
apiVersionString = apiVersionString,
|
||||
coroutinesEnable = coroutinesEnable,
|
||||
coroutinesWarn = coroutinesWarn,
|
||||
coroutinesError = coroutinesError,
|
||||
multiplatformEnable = multiplatformEnable,
|
||||
val isEAP: Boolean,
|
||||
val compilerBuildVersion: String,
|
||||
val languageVersionString: String,
|
||||
val apiVersionString: String,
|
||||
val coroutinesEnable: Boolean,
|
||||
val coroutinesWarn: Boolean,
|
||||
val coroutinesError: Boolean,
|
||||
val multiplatformEnable: Boolean,
|
||||
val metadataVersionMajor: Int,
|
||||
val metadataVersionMinor: Int,
|
||||
val metadataVersionPatch: Int,
|
||||
val bytecodeVersionMajor: Int,
|
||||
val bytecodeVersionMinor: Int,
|
||||
val bytecodeVersionPatch: Int,
|
||||
val ownVersion: Int = JvmBuildMetaInfo.OWN_VERSION,
|
||||
val coroutinesVersion: Int = JvmBuildMetaInfo.COROUTINES_VERSION,
|
||||
val multiplatformVersion: Int = JvmBuildMetaInfo.MULTIPLATFORM_VERSION
|
||||
) {
|
||||
companion object {
|
||||
const val OWN_VERSION: Int = 0
|
||||
const val COROUTINES_VERSION: Int = 0
|
||||
const val MULTIPLATFORM_VERSION: Int = 0
|
||||
|
||||
fun serializeToString(info: JvmBuildMetaInfo): String =
|
||||
serializeToPlainText(info)
|
||||
|
||||
fun deserializeFromString(str: String): JvmBuildMetaInfo? =
|
||||
deserializeFromPlainText(str)
|
||||
}
|
||||
}
|
||||
|
||||
fun JvmBuildMetaInfo(args: CommonCompilerArguments): JvmBuildMetaInfo {
|
||||
val languageVersion = args.languageVersion?.let((LanguageVersion)::fromVersionString) ?: LanguageVersion.LATEST_STABLE
|
||||
|
||||
return JvmBuildMetaInfo(
|
||||
isEAP = languageVersion.isPreRelease(),
|
||||
compilerBuildVersion = KotlinCompilerVersion.VERSION,
|
||||
languageVersionString = languageVersion.versionString,
|
||||
apiVersionString = args.apiVersion ?: languageVersion.versionString,
|
||||
coroutinesEnable = args.coroutinesState == CommonCompilerArguments.ENABLE,
|
||||
coroutinesWarn = args.coroutinesState == CommonCompilerArguments.WARN,
|
||||
coroutinesError = args.coroutinesState == CommonCompilerArguments.ERROR,
|
||||
multiplatformEnable = args.multiPlatform,
|
||||
metadataVersionMajor = JvmMetadataVersion.INSTANCE.major,
|
||||
metadataVersionMinor = JvmMetadataVersion.INSTANCE.minor,
|
||||
metadataVersionPatch = JvmMetadataVersion.INSTANCE.patch,
|
||||
bytecodeVersionMajor = JvmBytecodeBinaryVersion.INSTANCE.major,
|
||||
bytecodeVersionMinor = JvmBytecodeBinaryVersion.INSTANCE.minor,
|
||||
bytecodeVersionPatch = JvmBytecodeBinaryVersion.INSTANCE.patch,
|
||||
ownVersion = ownVersion,
|
||||
coroutinesVersion = coroutinesVersion,
|
||||
multiplatformVersion = multiplatformVersion
|
||||
)
|
||||
}
|
||||
bytecodeVersionPatch = JvmBytecodeBinaryVersion.INSTANCE.patch
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import java.io.File
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ public class ArgumentUtils {
|
||||
Class<? extends CommonToolArguments> argumentsClass = arguments.getClass();
|
||||
convertArgumentsToStringList(arguments, argumentsClass.newInstance(), JvmClassMappingKt.getKotlinClass(argumentsClass), result);
|
||||
result.addAll(arguments.getFreeArgs());
|
||||
result.addAll(arguments.getInternalArguments());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.deserialization.supertypes
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Incremental cache common for JVM and JS, ClassName type aware
|
||||
*/
|
||||
interface IncrementalCacheCommon {
|
||||
val thisWithDependentCaches: Iterable<AbstractIncrementalCache<*>>
|
||||
fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName>
|
||||
fun getSubtypesOf(className: FqName): Sequence<FqName>
|
||||
fun getSourceFileIfClass(fqName: FqName): File?
|
||||
fun markDirty(removedAndCompiledSources: Collection<File>)
|
||||
fun clearCacheForRemovedClasses(changesCollector: ChangesCollector)
|
||||
fun clearComplementaryFilesMapping(dirtyFiles: Collection<File>): Collection<File>
|
||||
fun registerComplementaryFiles(expectActualTracker: ExpectActualTrackerImpl)
|
||||
fun dump(): String
|
||||
}
|
||||
|
||||
/**
|
||||
* Incremental cache common for JVM and JS for specifit ClassName type
|
||||
*/
|
||||
abstract class AbstractIncrementalCache<ClassName>(workingDir: File) : BasicMapsOwner(workingDir), IncrementalCacheCommon {
|
||||
companion object {
|
||||
private val SUBTYPES = "subtypes"
|
||||
private val SUPERTYPES = "supertypes"
|
||||
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
||||
private val COMPLEMENTARY_FILES = "complementary-files"
|
||||
@JvmStatic protected val SOURCE_TO_CLASSES = "source-to-classes"
|
||||
@JvmStatic protected val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
||||
}
|
||||
|
||||
private val dependents = arrayListOf<AbstractIncrementalCache<ClassName>>()
|
||||
fun addDependentCache(cache: AbstractIncrementalCache<ClassName>) {
|
||||
dependents.add(cache)
|
||||
}
|
||||
override val thisWithDependentCaches: Iterable<AbstractIncrementalCache<ClassName>> by lazy {
|
||||
val result = arrayListOf(this)
|
||||
result.addAll(dependents)
|
||||
result
|
||||
}
|
||||
|
||||
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
||||
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
||||
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
|
||||
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
|
||||
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
|
||||
|
||||
/**
|
||||
* A file X is a complementary to a file Y if they contain corresponding expect/actual declarations.
|
||||
* Complementary files should be compiled together during IC so the compiler does not complain
|
||||
* about missing parts.
|
||||
* TODO: provide a better solution (maintain an index of expect/actual declarations akin to IncrementalPackagePartProvider)
|
||||
*/
|
||||
private val complementaryFilesMap = registerMap(FilesMap(COMPLEMENTARY_FILES.storageFile))
|
||||
|
||||
override fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName> =
|
||||
files.flatMapTo(HashSet()) { sourceToClassesMap.getFqNames(it) }
|
||||
|
||||
override fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||
subtypesMap[className].asSequence()
|
||||
|
||||
override fun getSourceFileIfClass(fqName: FqName): File? =
|
||||
classFqNameToSourceMap[fqName]
|
||||
|
||||
override fun markDirty(removedAndCompiledSources: Collection<File>) {
|
||||
for (sourceFile in removedAndCompiledSources) {
|
||||
val classes = sourceToClassesMap[sourceFile]
|
||||
classes.forEach {
|
||||
dirtyOutputClassesMap.markDirty(it)
|
||||
}
|
||||
|
||||
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun addToClassStorage(proto: ProtoBuf.Class, nameResolver: NameResolver, srcFile: File) {
|
||||
val supertypes = proto.supertypes(TypeTable(proto.typeTable))
|
||||
val parents = supertypes.map { nameResolver.getClassId(it.className).asSingleFqName() }
|
||||
.filter { it.asString() != "kotlin.Any" }
|
||||
.toSet()
|
||||
val child = nameResolver.getClassId(proto.fqName).asSingleFqName()
|
||||
|
||||
parents.forEach { subtypesMap.add(it, child) }
|
||||
|
||||
val removedSupertypes = supertypesMap[child].filter { it !in parents }
|
||||
removedSupertypes.forEach { subtypesMap.removeValues(it, setOf(child)) }
|
||||
|
||||
supertypesMap[child] = parents
|
||||
classFqNameToSourceMap[child] = srcFile
|
||||
}
|
||||
|
||||
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>, changesCollector: ChangesCollector) {
|
||||
if (removedClasses.isEmpty()) return
|
||||
|
||||
val removedFqNames = removedClasses.toSet()
|
||||
|
||||
for (removedClass in removedFqNames) {
|
||||
for (affectedClass in withSubtypes(removedClass, thisWithDependentCaches)) {
|
||||
changesCollector.collectSignature(affectedClass, areSubclassesAffected = false)
|
||||
}
|
||||
}
|
||||
|
||||
for (cache in thisWithDependentCaches) {
|
||||
val parentsFqNames = hashSetOf<FqName>()
|
||||
val childrenFqNames = hashSetOf<FqName>()
|
||||
|
||||
for (removedFqName in removedFqNames) {
|
||||
parentsFqNames.addAll(cache.supertypesMap[removedFqName])
|
||||
childrenFqNames.addAll(cache.subtypesMap[removedFqName])
|
||||
|
||||
cache.supertypesMap.remove(removedFqName)
|
||||
cache.subtypesMap.remove(removedFqName)
|
||||
}
|
||||
|
||||
for (child in childrenFqNames) {
|
||||
cache.supertypesMap.removeValues(child, removedFqNames)
|
||||
}
|
||||
|
||||
for (parent in parentsFqNames) {
|
||||
cache.subtypesMap.removeValues(parent, removedFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
removedFqNames.forEach { classFqNameToSourceMap.remove(it) }
|
||||
}
|
||||
|
||||
protected class ClassFqNameToSourceMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
|
||||
operator fun set(fqName: FqName, sourceFile: File) {
|
||||
storage[fqName.asString()] = sourceFile.canonicalPath
|
||||
}
|
||||
|
||||
operator fun get(fqName: FqName): File? =
|
||||
storage[fqName.asString()]?.let(::File)
|
||||
|
||||
fun remove(fqName: FqName) {
|
||||
storage.remove(fqName.asString())
|
||||
}
|
||||
|
||||
override fun dumpValue(value: String) = value
|
||||
}
|
||||
|
||||
override fun clearComplementaryFilesMapping(dirtyFiles: Collection<File>): Collection<File> {
|
||||
val complementaryFiles = HashSet<File>()
|
||||
val filesQueue = ArrayDeque(dirtyFiles)
|
||||
while (filesQueue.isNotEmpty()) {
|
||||
val file = filesQueue.pollFirst()
|
||||
complementaryFilesMap.remove(file).filterTo(filesQueue) { complementaryFiles.add(it) }
|
||||
}
|
||||
complementaryFiles.removeAll(dirtyFiles)
|
||||
return complementaryFiles
|
||||
}
|
||||
|
||||
override fun registerComplementaryFiles(expectActualTracker: ExpectActualTrackerImpl) {
|
||||
val actualToExpect = hashMapOf<File, MutableSet<File>>()
|
||||
for ((expect, actuals) in expectActualTracker.expectToActualMap) {
|
||||
for (actual in actuals) {
|
||||
actualToExpect.getOrPut(actual) { hashSetOf() }.add(expect)
|
||||
}
|
||||
complementaryFilesMap[expect] = actuals
|
||||
}
|
||||
|
||||
for ((actual, expects) in actualToExpect) {
|
||||
complementaryFilesMap[actual] = expects
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,13 @@ package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmBytecodeBinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
private val NORMAL_VERSION = 9
|
||||
private val DATA_CONTAINER_VERSION = 3
|
||||
private val NORMAL_VERSION = 8
|
||||
private val DATA_CONTAINER_VERSION = 2
|
||||
|
||||
private val NORMAL_VERSION_FILE_NAME = "format-version.txt"
|
||||
private val DATA_CONTAINER_VERSION_FILE_NAME = "data-container-format-version.txt"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import java.io.File
|
||||
|
||||
class ExpectActualTrackerImpl : ExpectActualTracker {
|
||||
private val expectToActual = hashMapOf<File, MutableSet<File>>()
|
||||
|
||||
val expectToActualMap: Map<File, Set<File>>
|
||||
get() = expectToActual
|
||||
|
||||
override fun report(expectedFile: File, actualFile: File) {
|
||||
expectToActual.getOrPut(expectedFile) { hashSetOf() }.add(actualFile)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.deserialization.supertypes
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Incremental cache common for JVM and JS
|
||||
*/
|
||||
abstract class IncrementalCacheCommon<ClassName>(workingDir: File) : BasicMapsOwner(workingDir) {
|
||||
companion object {
|
||||
private val SUBTYPES = "subtypes"
|
||||
private val SUPERTYPES = "supertypes"
|
||||
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
||||
@JvmStatic protected val SOURCE_TO_CLASSES = "source-to-classes"
|
||||
@JvmStatic protected val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
||||
}
|
||||
|
||||
private val dependents = arrayListOf<IncrementalCacheCommon<ClassName>>()
|
||||
fun addDependentCache(cache: IncrementalCacheCommon<ClassName>) {
|
||||
dependents.add(cache)
|
||||
}
|
||||
val thisWithDependentCaches: Iterable<IncrementalCacheCommon<ClassName>> by lazy {
|
||||
val result = arrayListOf(this)
|
||||
result.addAll(dependents)
|
||||
result
|
||||
}
|
||||
|
||||
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
||||
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
||||
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
|
||||
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
|
||||
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
|
||||
|
||||
fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName> =
|
||||
files.flatMapTo(HashSet()) { sourceToClassesMap.getFqNames(it) }
|
||||
|
||||
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||
subtypesMap[className].asSequence()
|
||||
|
||||
fun getSourceFileIfClass(fqName: FqName): File? =
|
||||
classFqNameToSourceMap[fqName]
|
||||
|
||||
open fun markDirty(removedAndCompiledSources: Collection<File>) {
|
||||
for (sourceFile in removedAndCompiledSources) {
|
||||
val classes = sourceToClassesMap[sourceFile]
|
||||
classes.forEach {
|
||||
dirtyOutputClassesMap.markDirty(it)
|
||||
}
|
||||
|
||||
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun addToClassStorage(proto: ProtoBuf.Class, nameResolver: NameResolver, srcFile: File) {
|
||||
val supertypes = proto.supertypes(TypeTable(proto.typeTable))
|
||||
val parents = supertypes.map { nameResolver.getClassId(it.className).asSingleFqName() }
|
||||
.filter { it.asString() != "kotlin.Any" }
|
||||
.toSet()
|
||||
val child = nameResolver.getClassId(proto.fqName).asSingleFqName()
|
||||
|
||||
parents.forEach { subtypesMap.add(it, child) }
|
||||
|
||||
val removedSupertypes = supertypesMap[child].filter { it !in parents }
|
||||
removedSupertypes.forEach { subtypesMap.removeValues(it, setOf(child)) }
|
||||
|
||||
supertypesMap[child] = parents
|
||||
classFqNameToSourceMap[child] = srcFile
|
||||
}
|
||||
|
||||
abstract fun clearCacheForRemovedClasses(changesCollector: ChangesCollector)
|
||||
|
||||
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>, changesCollector: ChangesCollector) {
|
||||
if (removedClasses.isEmpty()) return
|
||||
|
||||
val removedFqNames = removedClasses.toSet()
|
||||
|
||||
for (removedClass in removedFqNames) {
|
||||
for (affectedClass in withSubtypes(removedClass, thisWithDependentCaches)) {
|
||||
changesCollector.collectSignature(affectedClass, areSubclassesAffected = false)
|
||||
}
|
||||
}
|
||||
|
||||
for (cache in thisWithDependentCaches) {
|
||||
val parentsFqNames = hashSetOf<FqName>()
|
||||
val childrenFqNames = hashSetOf<FqName>()
|
||||
|
||||
for (removedFqName in removedFqNames) {
|
||||
parentsFqNames.addAll(cache.supertypesMap[removedFqName])
|
||||
childrenFqNames.addAll(cache.subtypesMap[removedFqName])
|
||||
|
||||
cache.supertypesMap.remove(removedFqName)
|
||||
cache.subtypesMap.remove(removedFqName)
|
||||
}
|
||||
|
||||
for (child in childrenFqNames) {
|
||||
cache.supertypesMap.removeValues(child, removedFqNames)
|
||||
}
|
||||
|
||||
for (parent in parentsFqNames) {
|
||||
cache.subtypesMap.removeValues(parent, removedFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
removedFqNames.forEach { classFqNameToSourceMap.remove(it) }
|
||||
}
|
||||
|
||||
protected class ClassFqNameToSourceMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
|
||||
operator fun set(fqName: FqName, sourceFile: File) {
|
||||
storage[fqName.asString()] = sourceFile.canonicalPath
|
||||
}
|
||||
|
||||
operator fun get(fqName: FqName): File? =
|
||||
storage[fqName.asString()]?.let(::File)
|
||||
|
||||
fun remove(fqName: FqName) {
|
||||
storage.remove(fqName.asString())
|
||||
}
|
||||
|
||||
override fun dumpValue(value: String) = value
|
||||
}
|
||||
}
|
||||
@@ -36,13 +36,11 @@ import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
|
||||
open class IncrementalJsCache(cachesDir: File) : AbstractIncrementalCache<FqName>(cachesDir) {
|
||||
open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon<FqName>(cachesDir) {
|
||||
companion object {
|
||||
private val TRANSLATION_RESULT_MAP = "translation-result"
|
||||
private val INLINE_FUNCTIONS = "inline-functions"
|
||||
private val HEADER_FILE_NAME = "header.meta"
|
||||
|
||||
fun hasHeaderFile(cachesDir: File) = File(cachesDir, HEADER_FILE_NAME).exists()
|
||||
}
|
||||
|
||||
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile))
|
||||
|
||||
@@ -25,12 +25,12 @@ import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
@@ -44,7 +44,7 @@ val KOTLIN_CACHE_DIRECTORY_NAME = "kotlin"
|
||||
open class IncrementalJvmCache(
|
||||
private val targetDataRoot: File,
|
||||
targetOutputDir: File?
|
||||
) : AbstractIncrementalCache<JvmClassName>(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
|
||||
) : IncrementalCacheCommon<JvmClassName>(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
|
||||
companion object {
|
||||
private val PROTO_MAP = "proto"
|
||||
private val CONSTANTS_MAP = "constants"
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.metadata.java.JavaClassProtoBuf
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
@@ -95,15 +94,8 @@ fun JavaClassDescriptor.convertToProto(): SerializedJavaClassWithSource {
|
||||
val file = javaSourceFile.sure { "convertToProto should only be called for source based classes" }
|
||||
|
||||
val extension = JavaClassesSerializerExtension()
|
||||
val classProto = try {
|
||||
DescriptorSerializer.create(this, extension).classProto(this).build()
|
||||
} catch (e: Exception) {
|
||||
throw IllegalStateException(
|
||||
"Error during writing proto for descriptor: ${DescriptorRenderer.DEBUG_TEXT.render(this)}\n" +
|
||||
"Source file: $file",
|
||||
e
|
||||
)
|
||||
}
|
||||
val serializer = DescriptorSerializer.createTopLevel(extension)
|
||||
val classProto = serializer.classProto(this).build()
|
||||
|
||||
val (stringTable, qualifiedNameTable) = extension.stringTable.buildProto()
|
||||
|
||||
|
||||
@@ -81,10 +81,10 @@ fun makeCompileServices(
|
||||
}
|
||||
|
||||
fun updateIncrementalCache(
|
||||
generatedFiles: Iterable<GeneratedFile>,
|
||||
cache: IncrementalJvmCache,
|
||||
changesCollector: ChangesCollector,
|
||||
javaChangesTracker: JavaClassesTrackerImpl?
|
||||
generatedFiles: Iterable<GeneratedFile>,
|
||||
cache: IncrementalJvmCache,
|
||||
changesCollector: ChangesCollector,
|
||||
javaChangesTracker: JavaClassesTrackerImpl?
|
||||
) {
|
||||
for (generatedFile in generatedFiles) {
|
||||
when {
|
||||
@@ -119,8 +119,8 @@ data class DirtyData(
|
||||
)
|
||||
|
||||
fun ChangesCollector.getDirtyData(
|
||||
caches: Iterable<IncrementalCacheCommon>,
|
||||
reporter: ICReporter
|
||||
caches: Iterable<IncrementalCacheCommon<*>>,
|
||||
reporter: ICReporter
|
||||
): DirtyData {
|
||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
val dirtyClassesFqNames = HashSet<FqName>()
|
||||
@@ -173,10 +173,10 @@ fun mapLookupSymbolsToFiles(
|
||||
}
|
||||
|
||||
fun mapClassesFqNamesToFiles(
|
||||
caches: Iterable<IncrementalCacheCommon>,
|
||||
classesFqNames: Iterable<FqName>,
|
||||
reporter: ICReporter,
|
||||
excludes: Set<File> = emptySet()
|
||||
caches: Iterable<IncrementalCacheCommon<*>>,
|
||||
classesFqNames: Iterable<FqName>,
|
||||
reporter: ICReporter,
|
||||
excludes: Set<File> = emptySet()
|
||||
): Set<File> {
|
||||
val dirtyFiles = HashSet<File>()
|
||||
|
||||
@@ -195,7 +195,7 @@ fun mapClassesFqNamesToFiles(
|
||||
|
||||
fun withSubtypes(
|
||||
typeFqName: FqName,
|
||||
caches: Iterable<IncrementalCacheCommon>
|
||||
caches: Iterable<IncrementalCacheCommon<*>>
|
||||
): Set<FqName> {
|
||||
val types = LinkedList(listOf(typeFqName))
|
||||
val subtypes = hashSetOf<FqName>()
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.js
|
||||
|
||||
import org.jetbrains.kotlin.incremental.IncrementalJsCache
|
||||
import java.io.File
|
||||
|
||||
class IncrementalDataProviderFromCache(private val cache: IncrementalJsCache) : IncrementalDataProvider {
|
||||
override val headerMetadata: ByteArray
|
||||
get() = cache.header
|
||||
|
||||
override val compiledPackageParts: Map<File, TranslationResultValue>
|
||||
get() = cache.nonDirtyPackageParts()
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.io.File
|
||||
|
||||
internal class FileToIdMap(file: File) : BasicMap<File, Int>(file, FileKeyDescriptor, IntExternalizer) {
|
||||
@@ -33,12 +34,5 @@ internal class FileToIdMap(file: File) : BasicMap<File, Int>(file, FileKeyDescri
|
||||
storage.remove(file)
|
||||
}
|
||||
|
||||
fun toMap(): Map<File, Int> {
|
||||
val result = HashMap<File, Int>()
|
||||
for (key in storage.keys) {
|
||||
val value = storage[key] ?: continue
|
||||
result[key] = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
fun toMap(): Map<File, Int> = storage.keys.keysToMap { storage[it]!! }
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||
import java.io.File
|
||||
|
||||
class FilesMap(storageFile: File)
|
||||
: BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
|
||||
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
|
||||
storage[sourceFile.absolutePath] = outputFiles.map { it.absolutePath }
|
||||
}
|
||||
|
||||
operator fun get(sourceFile: File): Collection<File> =
|
||||
storage[sourceFile.absolutePath].orEmpty().map(::File)
|
||||
|
||||
override fun dumpValue(value: Collection<String>) =
|
||||
value.dumpCollection()
|
||||
|
||||
fun remove(file: File): Collection<File> =
|
||||
get(file).also { storage.remove(file.absolutePath) }
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Test
|
||||
|
||||
class BuildMetaInfoTest : TestCase() {
|
||||
@Test
|
||||
fun testJvmSerialization() {
|
||||
val args = K2JVMCompilerArguments()
|
||||
val info = JvmBuildMetaInfo.create(args)
|
||||
val actual = JvmBuildMetaInfo.serializeToString(info)
|
||||
val expectedKeys = listOf(
|
||||
"apiVersionString",
|
||||
"bytecodeVersionMajor",
|
||||
"bytecodeVersionMinor",
|
||||
"bytecodeVersionPatch",
|
||||
"compilerBuildVersion",
|
||||
"coroutinesEnable",
|
||||
"coroutinesError",
|
||||
"coroutinesVersion",
|
||||
"coroutinesWarn",
|
||||
"isEAP",
|
||||
"languageVersionString",
|
||||
"metadataVersionMajor",
|
||||
"metadataVersionMinor",
|
||||
"metadataVersionPatch",
|
||||
"multiplatformEnable",
|
||||
"multiplatformVersion",
|
||||
"ownVersion"
|
||||
)
|
||||
assertEquals(expectedKeys, actual.split("\r\n", "\n").map { line -> line.split("=").first() })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJvmSerializationDeserialization() {
|
||||
val args = K2JVMCompilerArguments()
|
||||
val info = JvmBuildMetaInfo.create(args)
|
||||
val serialized = JvmBuildMetaInfo.serializeToString(info)
|
||||
val deserialized = JvmBuildMetaInfo.deserializeFromString(serialized)
|
||||
assertEquals(info, deserialized)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJsSerializationDeserialization() {
|
||||
val args = K2JVMCompilerArguments()
|
||||
val info = JvmBuildMetaInfo.create(args)
|
||||
val serialized = JvmBuildMetaInfo.serializeToString(info)
|
||||
val deserialized = JvmBuildMetaInfo.deserializeFromString(serialized)
|
||||
assertEquals(info, deserialized)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJvmEquals() {
|
||||
val args1 = K2JVMCompilerArguments()
|
||||
args1.coroutinesState = CommonCompilerArguments.ENABLE
|
||||
val info1 = JvmBuildMetaInfo.create(args1)
|
||||
|
||||
val args2 = K2JVMCompilerArguments()
|
||||
args2.coroutinesState = CommonCompilerArguments.WARN
|
||||
val info2 = JvmBuildMetaInfo.create(args2)
|
||||
|
||||
assertNotEquals(info1, info2)
|
||||
assertEquals(info1, info2.copy(coroutinesEnable = true, coroutinesWarn = false))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Test
|
||||
|
||||
class JvmBuildMetaInfoTest : TestCase() {
|
||||
@Test
|
||||
fun testSerialization() {
|
||||
val args = K2JVMCompilerArguments()
|
||||
val info = JvmBuildMetaInfo(args)
|
||||
val actual = JvmBuildMetaInfo.serializeToString(info)
|
||||
val expectedKeys = listOf(
|
||||
"apiVersionString",
|
||||
"bytecodeVersionMajor",
|
||||
"bytecodeVersionMinor",
|
||||
"bytecodeVersionPatch",
|
||||
"compilerBuildVersion",
|
||||
"coroutinesEnable",
|
||||
"coroutinesError",
|
||||
"coroutinesVersion",
|
||||
"coroutinesWarn",
|
||||
"isEAP",
|
||||
"languageVersionString",
|
||||
"metadataVersionMajor",
|
||||
"metadataVersionMinor",
|
||||
"metadataVersionPatch",
|
||||
"multiplatformEnable",
|
||||
"multiplatformVersion",
|
||||
"ownVersion"
|
||||
)
|
||||
assertEquals(expectedKeys, actual.split("\r\n", "\n").map { line -> line.split("=").first() })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSerializationDeserialization() {
|
||||
val args = K2JVMCompilerArguments()
|
||||
val info = JvmBuildMetaInfo(args)
|
||||
val serialized = JvmBuildMetaInfo.serializeToString(info)
|
||||
val deserialized = JvmBuildMetaInfo.deserializeFromString(serialized)
|
||||
assertEquals(info, deserialized)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEquals() {
|
||||
val args1 = K2JVMCompilerArguments()
|
||||
args1.coroutinesState = CommonCompilerArguments.ENABLE
|
||||
val info1 = JvmBuildMetaInfo(args1)
|
||||
|
||||
val args2 = K2JVMCompilerArguments()
|
||||
args2.coroutinesState = CommonCompilerArguments.WARN
|
||||
val info2 = JvmBuildMetaInfo(args2)
|
||||
|
||||
assertNotEquals(info1, info2)
|
||||
assertEquals(info1, info2.copy(coroutinesEnable = true, coroutinesWarn = false))
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,7 @@
|
||||
package org.jetbrains.kotlin.incremental.testingUtils
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream
|
||||
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
|
||||
import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapError
|
||||
import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapParser
|
||||
import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapSuccess
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.metadata.DebugProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.js.DebugJsProtoBuf
|
||||
@@ -29,7 +25,6 @@ import org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding
|
||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistry
|
||||
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
@@ -37,10 +32,14 @@ import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceClassVisitor
|
||||
import org.junit.Assert
|
||||
import org.junit.Assert.assertNotNull
|
||||
import java.io.*
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.util.*
|
||||
import java.util.zip.CRC32
|
||||
import java.util.zip.GZIPInputStream
|
||||
import kotlin.comparisons.compareBy
|
||||
|
||||
// Set this to true if you want to dump all bytecode (test will fail in this case)
|
||||
private val DUMP_ALL = System.getProperty("comparison.dump.all") == "true"
|
||||
@@ -187,39 +186,6 @@ private fun metaJsToString(metaJsFile: File): String {
|
||||
return out.toString()
|
||||
}
|
||||
|
||||
private fun kjsmToString(kjsmFile: File): String {
|
||||
val out = StringWriter()
|
||||
|
||||
val stream = DataInputStream(kjsmFile.inputStream())
|
||||
// Read and skip the metadata version
|
||||
repeat(stream.readInt()) { stream.readInt() }
|
||||
|
||||
val (header, content) =
|
||||
DebugJsProtoBuf.Header.parseDelimitedFrom(stream, JsSerializerProtocol.extensionRegistry) to
|
||||
DebugJsProtoBuf.Library.parseFrom(stream, JsSerializerProtocol.extensionRegistry)
|
||||
|
||||
out.write("\n------ header -----\n$header")
|
||||
out.write("\n------ library -----\n$content")
|
||||
|
||||
return out.toString()
|
||||
}
|
||||
|
||||
private fun sourceMapFileToString(sourceMapFile: File, generatedJsFile: File): String {
|
||||
val sourceMapParseResult = SourceMapParser.parse(StringReader(sourceMapFile.readText()))
|
||||
return when (sourceMapParseResult) {
|
||||
is SourceMapSuccess -> {
|
||||
val bytesOut = ByteArrayOutputStream()
|
||||
PrintStream(bytesOut).use { printStream ->
|
||||
sourceMapParseResult.value.debugVerbose(printStream, generatedJsFile)
|
||||
}
|
||||
bytesOut.toString()
|
||||
}
|
||||
is SourceMapError -> {
|
||||
sourceMapParseResult.message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getExtensionRegistry(): ExtensionRegistry {
|
||||
val registry = ExtensionRegistry.newInstance()!!
|
||||
DebugJvmProtoBuf.registerAllExtensions(registry)
|
||||
@@ -234,13 +200,6 @@ private fun fileToStringRepresentation(file: File): String {
|
||||
file.name.endsWith(KotlinJavascriptMetadataUtils.META_JS_SUFFIX) -> {
|
||||
metaJsToString(file)
|
||||
}
|
||||
file.name.endsWith(KotlinJavascriptSerializationUtil.CLASS_METADATA_FILE_EXTENSION) -> {
|
||||
kjsmToString(file)
|
||||
}
|
||||
file.name.endsWith(".js.map") -> {
|
||||
val generatedJsPath = file.canonicalPath.removeSuffix(".map")
|
||||
sourceMapFileToString(file, File(generatedJsPath))
|
||||
}
|
||||
else -> {
|
||||
file.readText()
|
||||
}
|
||||
|
||||
@@ -39,14 +39,14 @@ fun copyTestSources(testDataDir: File, sourceDestinationDir: File, filePrefix: S
|
||||
if (!file.isFile) continue
|
||||
|
||||
val renamedFile =
|
||||
if (filePrefix.isEmpty()) {
|
||||
file
|
||||
}
|
||||
else {
|
||||
File(sourceDestinationDir, file.name.removePrefix(filePrefix)).apply {
|
||||
file.renameTo(this)
|
||||
if (filePrefix.isEmpty()) {
|
||||
file
|
||||
}
|
||||
else {
|
||||
File(sourceDestinationDir, file.name.removePrefix(filePrefix)).apply {
|
||||
file.renameTo(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mapping[renamedFile] = File(testDataDir, file.name)
|
||||
}
|
||||
@@ -55,10 +55,10 @@ fun copyTestSources(testDataDir: File, sourceDestinationDir: File, filePrefix: S
|
||||
}
|
||||
|
||||
fun getModificationsToPerform(
|
||||
testDataDir: File,
|
||||
moduleNames: Collection<String>?,
|
||||
allowNoFilesWithSuffixInTestData: Boolean,
|
||||
touchPolicy: TouchPolicy
|
||||
testDataDir: File,
|
||||
moduleNames: Collection<String>?,
|
||||
allowNoFilesWithSuffixInTestData: Boolean,
|
||||
touchPolicy: TouchPolicy
|
||||
): List<List<Modification>> {
|
||||
|
||||
fun getModificationsForIteration(newSuffix: String, touchSuffix: String, deleteSuffix: String): List<Modification> {
|
||||
@@ -80,9 +80,9 @@ fun getModificationsToPerform(
|
||||
}
|
||||
|
||||
val rules = mapOf<String, (String, File) -> Modification>(
|
||||
newSuffix to { path, file -> ModifyContent(path, file) },
|
||||
touchSuffix to { path, _ -> TouchFile(path, touchPolicy) },
|
||||
deleteSuffix to { path, _ -> DeleteFile(path) }
|
||||
newSuffix to { path, file -> ModifyContent(path, file) },
|
||||
touchSuffix to { path, _ -> TouchFile(path, touchPolicy) },
|
||||
deleteSuffix to { path, _ -> DeleteFile(path) }
|
||||
)
|
||||
|
||||
val modifications = ArrayList<Modification>()
|
||||
@@ -122,8 +122,8 @@ fun getModificationsToPerform(
|
||||
}
|
||||
else {
|
||||
return (1..10)
|
||||
.map { getModificationsForIteration(".new.$it", ".touch.$it", ".delete.$it") }
|
||||
.filter { it.isNotEmpty() }
|
||||
.map { getModificationsForIteration(".new.$it", ".touch.$it", ".delete.$it") }
|
||||
.filter { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import proguard.gradle.ProGuardTask
|
||||
buildscript {
|
||||
extra["defaultSnapshotVersion"] = "1.2-SNAPSHOT"
|
||||
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.60-dev-980", onlySuccessBootstrap = false))
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.50-dev-310", onlySuccessBootstrap = false))
|
||||
|
||||
val mirrorRepo: String? = findProperty("maven.repository.mirror")?.toString()
|
||||
|
||||
@@ -22,8 +22,7 @@ buildscript {
|
||||
"https://jcenter.bintray.com/",
|
||||
"https://plugins.gradle.org/m2",
|
||||
"http://dl.bintray.com/kotlin/kotlinx",
|
||||
"https://jetbrains.bintray.com/kotlin-native-dependencies",
|
||||
"https://repo.gradle.org/gradle/ext-releases-local", // for native-platform
|
||||
"https://repo.gradle.org/gradle/libs-releases-local", // for native-platform
|
||||
"https://jetbrains.bintray.com/intellij-third-party-dependencies", // for jflex
|
||||
"https://dl.bintray.com/jetbrains/markdown" // for org.jetbrains:markdown
|
||||
)
|
||||
@@ -36,14 +35,7 @@ buildscript {
|
||||
}
|
||||
}
|
||||
|
||||
// a workaround for kotlin compiler classpath in kotlin project: sometimes gradle substitutes
|
||||
// kotlin-stdlib external dependency with local project :kotlin-stdlib in kotlinCompilerClasspath configuration.
|
||||
// see also configureCompilerClasspath@
|
||||
val bootstrapCompilerClasspath by configurations.creating
|
||||
|
||||
dependencies {
|
||||
bootstrapCompilerClasspath(kotlinDep("compiler-embeddable", bootstrapKotlinVersion))
|
||||
|
||||
classpath("com.gradle.publish:plugin-publish-plugin:0.9.7")
|
||||
classpath(kotlinDep("gradle-plugin", bootstrapKotlinVersion))
|
||||
classpath("net.sf.proguard:proguard-gradle:5.3.3")
|
||||
@@ -56,15 +48,6 @@ plugins {
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
pill {
|
||||
excludedDirs(
|
||||
"out",
|
||||
"buildSrc/build",
|
||||
"buildSrc/prepare-deps/android-dx/build",
|
||||
"buildSrc/prepare-deps/intellij-sdk/build"
|
||||
)
|
||||
}
|
||||
|
||||
buildScan {
|
||||
setTermsOfServiceUrl("https://gradle.com/terms-of-service")
|
||||
setTermsOfServiceAgree("yes")
|
||||
@@ -128,6 +111,15 @@ extra["ideaUltimatePluginDir"] = project.file(ideaUltimatePluginDir)
|
||||
extra["cidrPluginDir"] = project.file(cidrPluginDir)
|
||||
extra["isSonatypeRelease"] = false
|
||||
|
||||
Properties().apply {
|
||||
load(File(rootDir, "resources", "kotlinManifest.properties").reader())
|
||||
forEach {
|
||||
val key = it.key
|
||||
if (key != null && key is String)
|
||||
extra[key] = it.value
|
||||
}
|
||||
}
|
||||
|
||||
extra["JDK_16"] = jdkPath("1.6")
|
||||
extra["JDK_17"] = jdkPath("1.7")
|
||||
extra["JDK_18"] = jdkPath("1.8")
|
||||
@@ -136,7 +128,6 @@ extra["JDK_10"] = jdkPathIfFound("10")
|
||||
|
||||
rootProject.apply {
|
||||
from(rootProject.file("versions.gradle.kts"))
|
||||
from(rootProject.file("report.gradle.kts"))
|
||||
}
|
||||
|
||||
extra["versions.protobuf-java"] = "2.6.1"
|
||||
@@ -171,12 +162,12 @@ extra["intellijSeparateSdks"] = intellijSeparateSdks
|
||||
extra["IntellijCoreDependencies"] =
|
||||
listOf("annotations",
|
||||
"asm-all",
|
||||
"guava",
|
||||
"guava-21.0",
|
||||
"jdom",
|
||||
"jna",
|
||||
"log4j",
|
||||
"picocontainer",
|
||||
"snappy-in-java",
|
||||
"snappy-in-java-0.5.1",
|
||||
"streamex",
|
||||
"trove4j")
|
||||
|
||||
@@ -195,6 +186,7 @@ extra["nativePlatformVariants"] =
|
||||
extra["compilerModules"] = arrayOf(
|
||||
":compiler:util",
|
||||
":compiler:container",
|
||||
":compiler:conditional-preprocessor",
|
||||
":compiler:resolution",
|
||||
":compiler:serialization",
|
||||
":compiler:psi",
|
||||
@@ -240,7 +232,6 @@ val coreLibProjects = listOf(
|
||||
":kotlin-test:kotlin-test-common",
|
||||
":kotlin-test:kotlin-test-jvm",
|
||||
":kotlin-test:kotlin-test-junit",
|
||||
":kotlin-test:kotlin-test-junit5",
|
||||
":kotlin-test:kotlin-test-testng",
|
||||
":kotlin-test:kotlin-test-js",
|
||||
":kotlin-reflect"
|
||||
@@ -271,6 +262,11 @@ apply {
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.allprojectsRecursive(body: Project.() -> Unit) {
|
||||
this.body()
|
||||
this.subprojects { allprojectsRecursive(body) }
|
||||
}
|
||||
|
||||
fun Task.listConfigurationContents(configName: String) {
|
||||
doFirst {
|
||||
project.configurations.findByName(configName)?.let {
|
||||
@@ -294,7 +290,7 @@ allprojects {
|
||||
// therefore it is disabled by default
|
||||
// buildDir = File(commonBuildDir, project.name)
|
||||
|
||||
val repos = rootProject.extra["repos"] as List<String>
|
||||
val repos: List<String> by rootProject.extra
|
||||
repositories {
|
||||
intellijSdkRepo(project)
|
||||
androidDxJarRepo(project)
|
||||
@@ -355,19 +351,12 @@ allprojects {
|
||||
fun FileCollection.printClassPath(role: String) =
|
||||
println("${project.path} $role classpath:\n ${joinToString("\n ") { it.toProjectRootRelativePathOrSelf() } }")
|
||||
|
||||
try { javaPluginConvention() } catch (_: UnknownDomainObjectException) { null }?.let { javaConvention ->
|
||||
try { the<JavaPluginConvention>() } catch (_: UnknownDomainObjectException) { null }?.let { javaConvention ->
|
||||
task("printCompileClasspath") { doFirst { javaConvention.sourceSets["main"].compileClasspath.printClassPath("compile") } }
|
||||
task("printRuntimeClasspath") { doFirst { javaConvention.sourceSets["main"].runtimeClasspath.printClassPath("runtime") } }
|
||||
task("printTestCompileClasspath") { doFirst { javaConvention.sourceSets["test"].compileClasspath.printClassPath("test compile") } }
|
||||
task("printTestRuntimeClasspath") { doFirst { javaConvention.sourceSets["test"].runtimeClasspath.printClassPath("test runtime") } }
|
||||
}
|
||||
|
||||
run configureCompilerClasspath@ {
|
||||
val bootstrapCompilerClasspath by rootProject.buildscript.configurations
|
||||
configurations.findByName("kotlinCompilerClasspath")?.let {
|
||||
dependencies.add(it.name, files(bootstrapCompilerClasspath))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,6 +389,7 @@ tasks {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: copied from TeamCityBuild.xml (with ultimate-related modification), consider removing after migrating from it
|
||||
"cleanupArtifacts" {
|
||||
doLast {
|
||||
delete(ideaPluginDir)
|
||||
@@ -412,7 +402,6 @@ tasks {
|
||||
(coreLibProjects + listOf(
|
||||
":kotlin-stdlib:samples",
|
||||
":kotlin-test:kotlin-test-js:kotlin-test-js-it",
|
||||
":kotlinx-metadata-jvm",
|
||||
":tools:binary-compatibility-validator"
|
||||
)).forEach {
|
||||
dependsOn(it + ":check")
|
||||
@@ -455,10 +444,6 @@ tasks {
|
||||
dependsOn(":compiler:incremental-compilation-impl:test")
|
||||
}
|
||||
|
||||
"toolsTest" {
|
||||
dependsOn(":tools:kotlinp:test")
|
||||
}
|
||||
|
||||
"examplesTest" {
|
||||
dependsOn("dist")
|
||||
(project(":examples").subprojects + project(":kotlin-gradle-subplugin-example")).forEach { p ->
|
||||
@@ -468,7 +453,6 @@ tasks {
|
||||
|
||||
"distTest" {
|
||||
dependsOn("compilerTest")
|
||||
dependsOn("toolsTest")
|
||||
dependsOn("gradlePluginTest")
|
||||
dependsOn("examplesTest")
|
||||
}
|
||||
@@ -596,26 +580,13 @@ val zipPlugin by task<Zip> {
|
||||
val cidrPlugin by task<Copy> {
|
||||
dependsOn(ideaPlugin)
|
||||
into(cidrPluginDir)
|
||||
from(ideaPluginDir) {
|
||||
exclude("lib/kotlin-plugin.jar")
|
||||
|
||||
exclude("lib/android-lint.jar")
|
||||
exclude("lib/android-ide.jar")
|
||||
exclude("lib/android-output-parser-ide.jar")
|
||||
exclude("lib/android-extensions-ide.jar")
|
||||
exclude("lib/android-extensions-compiler.jar")
|
||||
exclude("lib/kapt3-idea.jar")
|
||||
exclude("lib/jps-ide.jar")
|
||||
exclude("lib/jps/**")
|
||||
exclude("kotlinc/**")
|
||||
exclude("lib/maven-ide.jar")
|
||||
}
|
||||
from(ideaPluginDir) { exclude("lib/kotlin-plugin.jar") }
|
||||
from(cidrKotlinPlugin) { into("lib") }
|
||||
}
|
||||
|
||||
val zipCidrPlugin by task<Zip> {
|
||||
val destPath = project.findProperty("pluginZipPath") as String?
|
||||
?: "$distDir/artifacts/kotlin-plugin-$kotlinVersion-CIDR.zip"
|
||||
?: "$distDir/artifacts/kotlin-plugin-$kotlinVersion-CIDR"
|
||||
val destFile = File(destPath)
|
||||
|
||||
destinationDir = destFile.parentFile
|
||||
@@ -681,7 +652,7 @@ tasks.create("findShadowJarsInClasspath").doLast {
|
||||
for (task in project.tasks) {
|
||||
when (task) {
|
||||
is ShadowJar -> {
|
||||
shadowJars.add(fileFrom(task.archivePath))
|
||||
shadowJars.add(File(task.archivePath))
|
||||
}
|
||||
is ProGuardTask -> {
|
||||
shadowJars.addAll(task.outputs.files.toList())
|
||||
|
||||
@@ -33,9 +33,9 @@ plugins {
|
||||
|
||||
gradlePlugin {
|
||||
(plugins) {
|
||||
"pill-configurable" {
|
||||
id = "pill-configurable"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.PillConfigurablePlugin"
|
||||
"jps-compatible-base" {
|
||||
id = "jps-compatible-base"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatibleBasePlugin"
|
||||
}
|
||||
"jps-compatible" {
|
||||
id = "jps-compatible"
|
||||
@@ -68,7 +68,7 @@ repositories {
|
||||
extra["buildSrcKotlinRepo"]?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
maven(url = "https://repo.gradle.org/gradle/ext-releases-local") // for native-platform
|
||||
maven(url = "https://repo.gradle.org/gradle/libs-releases-local") // for native-platform
|
||||
jcenter()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
|
||||
buildscript {
|
||||
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
|
||||
val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?)
|
||||
extra["versions.shadow"] = "2.0.2"
|
||||
extra["versions.native-platform"] = "0.14"
|
||||
|
||||
repositories {
|
||||
buildSrcKotlinRepo?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$buildSrcKotlinVersion")
|
||||
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:$buildSrcKotlinVersion")
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("buildSrcKotlinVersion: " + extra["buildSrcKotlinVersion"])
|
||||
logger.info("buildSrc kotlin compiler version: " + org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
|
||||
logger.info("buildSrc stdlib version: " + KotlinVersion.CURRENT)
|
||||
|
||||
apply {
|
||||
plugin("kotlin")
|
||||
plugin("kotlin-sam-with-receiver")
|
||||
}
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
`java-gradle-plugin`
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
(plugins) {
|
||||
"pill-configurable" {
|
||||
id = "pill-configurable"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.PillConfigurablePlugin"
|
||||
}
|
||||
"jps-compatible" {
|
||||
id = "jps-compatible"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatiblePlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
|
||||
val v = it.toString()
|
||||
if (v.isBlank()) true
|
||||
else v.toBoolean()
|
||||
}
|
||||
|
||||
rootProject.apply {
|
||||
from(rootProject.file("../versions.gradle.kts"))
|
||||
}
|
||||
|
||||
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
|
||||
val intellijUltimateEnabled by extra(project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild)
|
||||
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
|
||||
|
||||
extra["intellijRepo"] = "https://www.jetbrains.com/intellij-repository"
|
||||
extra["intellijReleaseType"] = "snapshots" // or "snapshots"
|
||||
extra["versions.androidDxSources"] = "5.0.0_r2"
|
||||
|
||||
extra["customDepsOrg"] = "kotlin.build.custom.deps"
|
||||
|
||||
repositories {
|
||||
extra["buildSrcKotlinRepo"]?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
maven(url = "https://repo.gradle.org/gradle/ext-releases-local") // for native-platform
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
|
||||
compile("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
|
||||
compile("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}")
|
||||
compile("com.jakewharton.dex:dex-method-list:3.0.0")
|
||||
// TODO: adding the dep to the plugin breaks the build unexpectedly, resolve and uncomment
|
||||
// compile("org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.extra["bootstrap_kotlin_version"]}")
|
||||
// Shadow plugin is used in many projects of the main build. Once it's no longer used in buildSrc, please move this dependency to the root project
|
||||
compile("com.github.jengelman.gradle.plugins:shadow:${property("versions.shadow")}")
|
||||
compile("org.ow2.asm:asm-all:6.0_BETA")
|
||||
}
|
||||
|
||||
samWithReceiver {
|
||||
annotation("org.gradle.api.HasImplicitReceiver")
|
||||
}
|
||||
|
||||
fun Project.`samWithReceiver`(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit =
|
||||
extensions.configure("samWithReceiver", configure)
|
||||
|
||||
tasks["build"].dependsOn(":prepare-deps:android-dx:build", ":prepare-deps:intellij-sdk:build")
|
||||
@@ -1,9 +0,0 @@
|
||||
org.gradle.daemon=true
|
||||
org.gradle.parallel=false
|
||||
org.gradle.configureondemand=false
|
||||
org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m
|
||||
|
||||
#buildSrc.kotlin.repo=https://jcenter.bintray.com
|
||||
#buildSrc.kotlin.version=1.1.50
|
||||
|
||||
intellijUltimateEnabled=false
|
||||
@@ -1,9 +0,0 @@
|
||||
org.gradle.daemon=true
|
||||
org.gradle.parallel=false
|
||||
org.gradle.configureondemand=false
|
||||
org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m
|
||||
|
||||
#buildSrc.kotlin.repo=https://jcenter.bintray.com
|
||||
#buildSrc.kotlin.version=1.1.50
|
||||
|
||||
intellijUltimateEnabled=false
|
||||
@@ -26,9 +26,6 @@ repositories {
|
||||
ivy {
|
||||
artifactPattern("https://dl-ssl.google.com/android/repository/[artifact]_[revision](-[classifier]).[ext]")
|
||||
artifactPattern("https://android.googlesource.com/platform/dalvik/+archive/android-$dxSourcesVersion/[artifact].[ext]")
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,8 @@ val intellijSeparateSdks: Boolean by rootProject.extra
|
||||
val installIntellijCommunity = !intellijUltimateEnabled || intellijSeparateSdks
|
||||
val installIntellijUltimate = intellijUltimateEnabled
|
||||
|
||||
val intellijVersionDelimiterIndex = intellijVersion.indexOfAny(charArrayOf('.', '-'))
|
||||
if (intellijVersionDelimiterIndex == -1) {
|
||||
error("Invalid IDEA version $intellijVersion")
|
||||
}
|
||||
|
||||
val platformBaseVersion = intellijVersion.substring(0, intellijVersionDelimiterIndex)
|
||||
val platformBaseVersion = intellijVersion.substringBefore('.', "").takeIf { it.isNotEmpty() }
|
||||
?: error("Invalid IDEA version $intellijVersion")
|
||||
|
||||
logger.info("intellijUltimateEnabled: $intellijUltimateEnabled")
|
||||
|
||||
@@ -61,18 +57,12 @@ repositories {
|
||||
if (androidStudioRelease != null) {
|
||||
ivy {
|
||||
artifactPattern("https://dl.google.com/dl/android/studio/ide-zips/$androidStudioRelease/[artifact]-[revision]-$studioOs.zip")
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
maven { setUrl("$intellijRepo/$intellijReleaseType") }
|
||||
maven { setUrl("https://plugins.jetbrains.com/maven") }
|
||||
ivy {
|
||||
artifactPattern("https://raw.github.com/JetBrains/intellij-community/[revision]/lib/src/[artifact].zip")
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,12 +93,7 @@ dependencies {
|
||||
}
|
||||
}
|
||||
sources("com.jetbrains.intellij.idea:ideaIC:$intellijVersion:sources@jar")
|
||||
if (platformBaseVersion == "182") {
|
||||
// There is no asm sources for 182 yet
|
||||
`asm-shaded-sources`("asmsources:asm-src:181@zip")
|
||||
} else {
|
||||
`asm-shaded-sources`("asmsources:asm-src:$platformBaseVersion@zip")
|
||||
}
|
||||
`asm-shaded-sources`("asmsources:asm-src:$platformBaseVersion@zip")
|
||||
`jps-standalone`("com.jetbrains.intellij.idea:jps-standalone:$intellijVersion")
|
||||
`jps-build-test`("com.jetbrains.intellij.idea:jps-build-test:$intellijVersion")
|
||||
`intellij-core`("com.jetbrains.intellij.idea:intellij-core:$intellijVersion")
|
||||
|
||||
@@ -4,7 +4,6 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import java.io.File
|
||||
|
||||
fun RepositoryHandler.androidDxJarRepo(project: Project): IvyArtifactRepository = ivy {
|
||||
val baseDir = File("${project.rootDir}/buildSrc/prepare-deps/android-dx/build/repo")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// usages in build scripts are not tracked properly
|
||||
@file:Suppress("unused")
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Project
|
||||
@@ -7,11 +6,11 @@ import org.gradle.api.Task
|
||||
import org.gradle.api.file.CopySourceSpec
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import org.gradle.kotlin.dsl.creating
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.gradle.kotlin.dsl.get
|
||||
import org.gradle.kotlin.dsl.the
|
||||
import java.io.File
|
||||
import java.util.concurrent.Callable
|
||||
@@ -22,7 +21,7 @@ fun Project.callGroovy(name: String, vararg args: Any?): Any? {
|
||||
return (property(name) as Closure<*>).call(*args)
|
||||
}
|
||||
|
||||
inline fun <T : Any> Project.withJavaPlugin(crossinline body: () -> T?): T? {
|
||||
inline fun<T: Any> Project.withJavaPlugin(crossinline body: () -> T?): T? {
|
||||
var res: T? = null
|
||||
pluginManager.withPlugin("java") {
|
||||
res = body()
|
||||
@@ -30,30 +29,31 @@ inline fun <T : Any> Project.withJavaPlugin(crossinline body: () -> T?): T? {
|
||||
return res
|
||||
}
|
||||
|
||||
fun Project.getCompiledClasses(): SourceSetOutput? = withJavaPlugin { mainSourceSet.output }
|
||||
fun Project.getCompiledClasses(): SourceSetOutput? = withJavaPlugin {
|
||||
the<JavaPluginConvention>().sourceSets.getByName("main").output
|
||||
}
|
||||
|
||||
fun Project.getSources(): SourceDirectorySet? = withJavaPlugin { mainSourceSet.allSource }
|
||||
fun Project.getSources(): SourceDirectorySet? = withJavaPlugin {
|
||||
the<JavaPluginConvention>().sourceSets.getByName("main").allSource
|
||||
}
|
||||
|
||||
fun Project.getResourceFiles(): SourceDirectorySet? = withJavaPlugin { mainSourceSet.resources }
|
||||
fun Project.getResourceFiles(): SourceDirectorySet? = withJavaPlugin {
|
||||
the<JavaPluginConvention>().sourceSets.getByName("main").resources
|
||||
}
|
||||
|
||||
fun fileFrom(root: File, vararg children: String): File = children.fold(root) { f, c -> File(f, c) }
|
||||
|
||||
fun fileFrom(root: String, vararg children: String): File = children.fold(File(root)) { f, c -> File(f, c) }
|
||||
fun File(root: File, vararg children: String): File = children.fold(root, { f, c -> File(f, c) })
|
||||
fun File(root: String, vararg children: String): File = children.fold(File(root), { f, c -> File(f, c) })
|
||||
|
||||
var Project.jvmTarget: String?
|
||||
get() = extra.takeIf { it.has("jvmTarget") }?.get("jvmTarget") as? String
|
||||
set(v) {
|
||||
extra["jvmTarget"] = v
|
||||
}
|
||||
set(v) { extra["jvmTarget"] = v }
|
||||
|
||||
var Project.javaHome: String?
|
||||
get() = extra.takeIf { it.has("javaHome") }?.get("javaHome") as? String
|
||||
set(v) {
|
||||
extra["javaHome"] = v
|
||||
}
|
||||
set(v) { extra["javaHome"] = v }
|
||||
|
||||
fun Project.generator(fqName: String, sourceSet: SourceSet? = null) = smartJavaExec {
|
||||
classpath = (sourceSet ?: testSourceSet).runtimeClasspath
|
||||
fun Project.generator(fqName: String) = task<JavaExec> {
|
||||
classpath = the<JavaPluginConvention>().sourceSets["test"].runtimeClasspath
|
||||
main = fqName
|
||||
workingDir = rootDir
|
||||
}
|
||||
@@ -65,5 +65,3 @@ fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)
|
||||
}
|
||||
|
||||
inline fun CopySourceSpec.from(crossinline filesProvider: () -> Any?): CopySourceSpec = from(Callable { filesProvider() })
|
||||
|
||||
fun Project.javaPluginConvention(): JavaPluginConvention = the()
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.task
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
fun Project.smartJavaExec(configure: JavaExec.() -> Unit) = task<JavaExec> javaExec@{
|
||||
configure()
|
||||
|
||||
val jarTask = project.task("${name}WriteClassPath", Jar::class) {
|
||||
val classpath = classpath
|
||||
val main = main
|
||||
dependsOn(classpath)
|
||||
inputs.property("main", main)
|
||||
doFirst {
|
||||
val classPathString = classpath.joinToString(" ") { project.file(it).toURI().toString() }
|
||||
manifest {
|
||||
attributes(
|
||||
mapOf(
|
||||
"Class-Path" to classPathString,
|
||||
"Main-Class" to main
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
archiveName = "$main.${this@javaExec.name}.classpath.container.$extension"
|
||||
destinationDir = temporaryDir
|
||||
}
|
||||
|
||||
|
||||
|
||||
dependsOn(jarTask)
|
||||
|
||||
doFirst {
|
||||
main = "-jar"
|
||||
|
||||
classpath = project.files()
|
||||
val copyArgs = args.orEmpty().toList()
|
||||
args(jarTask.outputs.files.singleFile)
|
||||
args(copyArgs)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ fun Project.classesDirsArtifact(): FileCollection {
|
||||
|
||||
val classesDirsCfg = configurations.getOrCreate("classes-dirs")
|
||||
|
||||
val classesDirs = mainSourceSet.output.classesDirs
|
||||
val classesDirs = the<JavaPluginConvention>().sourceSets["main"].output.classesDirs
|
||||
|
||||
val classesTask = tasks["classes"]
|
||||
|
||||
@@ -44,7 +44,7 @@ fun Project.testsJar(body: Jar.() -> Unit = {}): Jar {
|
||||
return task<Jar>(MAGIC_DO_NOT_CHANGE_TEST_JAR_TASK_NAME) {
|
||||
dependsOn("testClasses")
|
||||
pluginManager.withPlugin("java") {
|
||||
from(testSourceSet.output)
|
||||
from(project.the<JavaPluginConvention>().sourceSets.getByName("test").output)
|
||||
}
|
||||
classifier = "tests"
|
||||
body()
|
||||
@@ -88,7 +88,7 @@ fun Project.sourcesJar(sourceSet: String? = "main", body: Jar.() -> Unit = {}):
|
||||
try {
|
||||
if (sourceSet != null) {
|
||||
project.pluginManager.withPlugin("java-base") {
|
||||
from(project.javaPluginConvention().sourceSets[sourceSet].allSource)
|
||||
from(project.the<JavaPluginConvention>().sourceSets[sourceSet].allSource)
|
||||
}
|
||||
}
|
||||
} catch (e: UnknownDomainObjectException) {
|
||||
|
||||
@@ -50,7 +50,7 @@ fun Project.preloadedDeps(vararg artifactBaseNames: String, baseDir: File = File
|
||||
}
|
||||
|
||||
fun Project.ideaUltimatePreloadedDeps(vararg artifactBaseNames: String, subdir: String? = null): ConfigurableFileCollection {
|
||||
val ultimateDepsDir = fileFrom(rootDir, "ultimate", "dependencies")
|
||||
val ultimateDepsDir = File(rootDir, "ultimate", "dependencies")
|
||||
return if (ultimateDepsDir.isDirectory) preloadedDeps(*artifactBaseNames, baseDir = ultimateDepsDir, subdir = subdir)
|
||||
else files()
|
||||
}
|
||||
@@ -112,14 +112,6 @@ fun AbstractCopyTask.fromEmbeddedComponents() {
|
||||
if (this is ShadowJar) {
|
||||
from(embeddedComponents)
|
||||
} else {
|
||||
dependsOn(embeddedComponents)
|
||||
from {
|
||||
embeddedComponents.map { file ->
|
||||
if (file.isDirectory)
|
||||
project.files(file)
|
||||
else
|
||||
project.zipTree(file)
|
||||
}
|
||||
}
|
||||
embeddedComponents.forEach { from(if (it.isDirectory) it else project.zipTree(it)) }
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import org.gradle.api.file.DuplicatesStrategy
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.task
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import java.io.File
|
||||
|
||||
val kotlinEmbeddableRootPackage = "org.jetbrains.kotlin"
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ fun Project.configureInstrumentation() {
|
||||
// classes from the "friendly directory" to the compile classpath.
|
||||
val testCompile = tasks.findByName("compileTestKotlin") as AbstractCompile?
|
||||
testCompile?.doFirst {
|
||||
val mainSourceSet = the<JavaPluginConvention>().sourceSets.getByName("main")
|
||||
testCompile.classpath = (testCompile.classpath
|
||||
- mainSourceSet.output.classesDirs
|
||||
+ files((mainSourceSet as ExtensionAware).extra.get("classesDirsCopy")))
|
||||
@@ -58,7 +59,7 @@ fun Project.configureInstrumentation() {
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
sourceSets.all { sourceSetParam ->
|
||||
the<JavaPluginConvention>().sourceSets.all { sourceSetParam ->
|
||||
// This copy will ignore filters, but they are unlikely to be used.
|
||||
val classesDirs = (sourceSetParam.output.classesDirs as ConfigurableFileCollection).from as Collection<Any>
|
||||
|
||||
@@ -149,7 +150,7 @@ open class IntelliJInstrumentCodeTask : ConventionTask() {
|
||||
|
||||
// Instrumentation needs to have access to sources of forms for inclusion
|
||||
val depSourceDirectorySets = project.configurations["compile"].dependencies.withType(ProjectDependency::class.java)
|
||||
.map { p -> p.dependencyProject.mainSourceSet.allSource.sourceDirectories }
|
||||
.map { p -> p.dependencyProject.the<JavaPluginConvention>().sourceSets.getByName("main").allSource.sourceDirectories }
|
||||
val instrumentationClasspath =
|
||||
depSourceDirectorySets.fold(sourceSet!!.compileClasspath) { acc, v -> acc + v }.asPath.also {
|
||||
logger.info("Using following dependency source dirs: $it")
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.plugins.ExtensionAware
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import java.io.File
|
||||
|
||||
fun Project.configureInstrumentation() {
|
||||
plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.all {
|
||||
// When we change the output classes directory, Gradle will automatically configure
|
||||
// the test compile tasks to use the instrumented classes. Normally this is fine,
|
||||
// however, it causes problems for Kotlin projects:
|
||||
|
||||
// The "internal" modifier can be used to restrict access to the same module.
|
||||
// To make it possible to use internal methods from the main source set in test classes,
|
||||
// the Kotlin Gradle plugin adds the original output directory of the Java task
|
||||
// as "friendly directory" which makes it possible to access internal members
|
||||
// of the main module. Also this directory should be available on classpath during compilation
|
||||
|
||||
// This fails when we change the classes dir. The easiest fix is to prepend the
|
||||
// classes from the "friendly directory" to the compile classpath.
|
||||
val testCompile = tasks.findByName("compileTestKotlin") as AbstractCompile?
|
||||
testCompile?.doFirst {
|
||||
testCompile.classpath = (testCompile.classpath
|
||||
- mainSourceSet.output.classesDirs
|
||||
+ files((mainSourceSet as ExtensionAware).extra.get("classesDirsCopy")))
|
||||
}
|
||||
}
|
||||
|
||||
val instrumentationClasspathCfg = configurations.create("instrumentationClasspath")
|
||||
|
||||
dependencies {
|
||||
instrumentationClasspathCfg(intellijDep()) { includeJars("javac2", "jdom", "asm-all") }
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
sourceSets.all { sourceSetParam ->
|
||||
// This copy will ignore filters, but they are unlikely to be used.
|
||||
val classesDirs = (sourceSetParam.output.classesDirs as ConfigurableFileCollection).from as Collection<Any>
|
||||
|
||||
val classesDirsCopy = project.files(classesDirs.toTypedArray()).filter { it.exists() }
|
||||
(sourceSetParam as ExtensionAware).extra.set("classesDirsCopy", classesDirsCopy)
|
||||
|
||||
logger.info("Saving old sources dir for project ${project.name}")
|
||||
val instrumentedClassesDir = File(project.buildDir, "classes/${sourceSetParam.name}-instrumented")
|
||||
(sourceSetParam.output.classesDirs as ConfigurableFileCollection).setFrom(instrumentedClassesDir)
|
||||
val instrumentTask = project.tasks.create(sourceSetParam.getTaskName("instrument", "classes"), IntelliJInstrumentCodeTask::class.java)
|
||||
instrumentTask.apply {
|
||||
dependsOn(sourceSetParam.classesTaskName).onlyIf { !classesDirsCopy.isEmpty }
|
||||
sourceSet = sourceSetParam
|
||||
instrumentationClasspath = instrumentationClasspathCfg
|
||||
originalClassesDirs = classesDirsCopy
|
||||
output = instrumentedClassesDir
|
||||
}
|
||||
|
||||
instrumentTask.outputs.dir(instrumentedClassesDir)
|
||||
// Ensure that our task is invoked when the source set is built
|
||||
sourceSetParam.compiledBy(instrumentTask)
|
||||
@Suppress("UNUSED_EXPRESSION")
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CacheableTask
|
||||
open class IntelliJInstrumentCodeTask : ConventionTask() {
|
||||
companion object {
|
||||
private const val FILTER_ANNOTATION_REGEXP_CLASS = "com.intellij.ant.ClassFilterAnnotationRegexp"
|
||||
private const val LOADER_REF = "java2.loader"
|
||||
}
|
||||
|
||||
var sourceSet: SourceSet? = null
|
||||
|
||||
var instrumentationClasspath: Configuration? = null
|
||||
|
||||
@Input
|
||||
var originalClassesDirs: FileCollection? = null
|
||||
|
||||
@get:InputFiles
|
||||
val sourceDirs: FileCollection
|
||||
get() = project.files(sourceSet!!.allSource.srcDirs.filter { !sourceSet!!.resources.contains(it) && it.exists() })
|
||||
|
||||
@get:OutputDirectory
|
||||
var output: File? = null
|
||||
|
||||
@TaskAction
|
||||
fun instrumentClasses() {
|
||||
logger.info("input files are: ${originalClassesDirs?.joinToString("; ", transform = { "'${it.name}'${if (it.exists()) "" else " (does not exists)" }"})}")
|
||||
output?.deleteRecursively()
|
||||
copyOriginalClasses()
|
||||
|
||||
val classpath = instrumentationClasspath!!
|
||||
|
||||
ant.withGroovyBuilder {
|
||||
"taskdef"("name" to "instrumentIdeaExtensions",
|
||||
"classpath" to classpath.asPath,
|
||||
"loaderref" to LOADER_REF,
|
||||
"classname" to "com.intellij.ant.InstrumentIdeaExtensions")
|
||||
}
|
||||
|
||||
logger.info("Compiling forms and instrumenting code with nullability preconditions")
|
||||
val instrumentNotNull = prepareNotNullInstrumenting(classpath.asPath)
|
||||
instrumentCode(sourceDirs, instrumentNotNull)
|
||||
}
|
||||
|
||||
private fun copyOriginalClasses() {
|
||||
project.copy {
|
||||
from(originalClassesDirs)
|
||||
into(output)
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareNotNullInstrumenting(classpath: String): Boolean {
|
||||
ant.withGroovyBuilder {
|
||||
"typedef"("name" to "skip",
|
||||
"classpath" to classpath,
|
||||
"loaderref" to LOADER_REF,
|
||||
"classname" to FILTER_ANNOTATION_REGEXP_CLASS)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun instrumentCode(srcDirs: FileCollection, instrumentNotNull: Boolean) {
|
||||
val headlessOldValue = System.setProperty("java.awt.headless", "true")
|
||||
|
||||
// Instrumentation needs to have access to sources of forms for inclusion
|
||||
val depSourceDirectorySets = project.configurations["compile"].dependencies.withType(ProjectDependency::class.java)
|
||||
.map { p -> p.dependencyProject.mainSourceSet.allSource.sourceDirectories }
|
||||
val instrumentationClasspath =
|
||||
depSourceDirectorySets.fold(sourceSet!!.compileClasspath) { acc, v -> acc + v }.asPath.also {
|
||||
logger.info("Using following dependency source dirs: $it")
|
||||
}
|
||||
|
||||
logger.info("Running instrumentIdeaExtensions with srcdir=${srcDirs.asPath}}, destdir=$output and classpath=$instrumentationClasspath")
|
||||
|
||||
ant.withGroovyBuilder {
|
||||
"instrumentIdeaExtensions"("srcdir" to srcDirs.asPath,
|
||||
"destdir" to output,
|
||||
"classpath" to instrumentationClasspath,
|
||||
"includeantruntime" to false,
|
||||
"instrumentNotNull" to instrumentNotNull) {
|
||||
if (instrumentNotNull) {
|
||||
ant.withGroovyBuilder {
|
||||
"skip"("pattern" to "kotlin/Metadata")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (headlessOldValue != null) {
|
||||
System.setProperty("java.awt.headless", headlessOldValue)
|
||||
} else {
|
||||
System.clearProperty("java.awt.headless")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,17 +43,12 @@ fun RepositoryHandler.intellijSdkRepo(project: Project): IvyArtifactRepository =
|
||||
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module].ivy.xml")
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[revision]/intellij.plugin.[module].ivy.xml")
|
||||
ivyPattern("${baseDir.canonicalPath}/[organisation]/[revision]/plugins-[module].ivy.xml")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/intellij/plugins/[module]/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/plugins-[module]/[module]/lib/[artifact](-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]/[artifact].jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/[module]/[artifact](-[revision])(-[classifier]).jar")
|
||||
artifactPattern("${baseDir.canonicalPath}/[organisation]/[revision]/sources/[artifact]-[revision]-[classifier].[ext]")
|
||||
|
||||
metadataSources {
|
||||
ivyDescriptor()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.intellijDep(module: String = "intellij") = "kotlin.build.custom.deps:$module:${rootProject.extra["versions.intellijSdk"]}"
|
||||
@@ -123,7 +118,7 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
|
||||
return task<JavaExec>(name) {
|
||||
val ideaSandboxConfigDir = File(ideaSandboxDir, "config")
|
||||
|
||||
classpath = mainSourceSet.runtimeClasspath
|
||||
classpath = the<JavaPluginConvention>().sourceSets["main"].runtimeClasspath
|
||||
|
||||
main = "com.intellij.idea.Main"
|
||||
|
||||
@@ -142,6 +137,7 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
|
||||
"-Dapple.awt.graphics.UseQuartz=true",
|
||||
"-Dsun.io.useCanonCaches=false",
|
||||
"-Dplugin.path=${ideaPluginDir.absolutePath}",
|
||||
"-Dkotlin.internal.mode.enabled=true",
|
||||
"-Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar"
|
||||
)
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ fun MutableCollection<JdkId>.discoverJdksOnUnix(project: Project) {
|
||||
val installedJdks = File(loc).listFiles { dir ->
|
||||
dir.isDirectory &&
|
||||
unixConventionalJdkDirRex.containsMatchIn(dir.name) &&
|
||||
fileFrom(dir, "bin", "java").isFile
|
||||
File(dir, "bin", "java").isFile
|
||||
} ?: continue
|
||||
for (dir in installedJdks) {
|
||||
val versionMatch = javaVersionRegex.find(dir.name)
|
||||
@@ -172,7 +172,7 @@ fun MutableCollection<JdkId>.discoverJdksOnWindows(project: Project) {
|
||||
else {
|
||||
javaHome.takeIf { it.isNotEmpty() }
|
||||
?.let { File(it) }
|
||||
?.takeIf { it.isDirectory && fileFrom(it, "bin", "java.exe").isFile }
|
||||
?.takeIf { it.isDirectory && File(it, "bin", "java.exe").isFile }
|
||||
?.let {
|
||||
addIfBetter(project, versionMatch.value, jdkKey, it)
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ class DependencyMapper(
|
||||
|
||||
class MappedDependency(val main: PDependency, val deferred: List<PDependency> = emptyList())
|
||||
|
||||
class ParserContext(val dependencyMappers: List<DependencyMapper>, val variant: PillExtension.Variant)
|
||||
class ParserContext(val dependencyMappers: List<DependencyMapper>)
|
||||
@@ -1,39 +0,0 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package org.jetbrains.kotlin.pill
|
||||
|
||||
import java.io.File
|
||||
import org.gradle.api.Project
|
||||
|
||||
open class PillExtension {
|
||||
enum class Variant {
|
||||
// Default variant (./gradlew pill)
|
||||
BASE() { override val includes = setOf(BASE) },
|
||||
|
||||
// Full variant (./gradlew pill -Dpill.variant=full)
|
||||
FULL() { override val includes = setOf(BASE, FULL) },
|
||||
|
||||
// Do not import the project to JPS model, but set some options for it
|
||||
NONE() { override val includes = emptySet<Variant>() },
|
||||
|
||||
// 'BASE' if the "jps-compatible" plugin is applied, 'NONE' otherwise
|
||||
DEFAULT() { override val includes = emptySet<Variant>() };
|
||||
|
||||
abstract val includes: Set<Variant>
|
||||
}
|
||||
|
||||
open var variant: Variant = Variant.DEFAULT
|
||||
|
||||
open var importAsLibrary: Boolean = false
|
||||
|
||||
open var excludedDirs: List<File> = emptyList()
|
||||
|
||||
fun Project.excludedDirs(vararg dirs: String) {
|
||||
excludedDirs = excludedDirs + dirs.map { File(projectDir, it) }
|
||||
}
|
||||
|
||||
open var libraryPath: File? = null
|
||||
set(v) {
|
||||
importAsLibrary = true
|
||||
field = v
|
||||
}
|
||||
}
|
||||
@@ -153,10 +153,7 @@ fun generateKotlinPluginArtifactFile(rootProject: Project): PFile {
|
||||
.findByName(EmbeddedComponents.CONFIGURATION_NAME)?.resolvedConfiguration
|
||||
|
||||
if (embeddedComponents != null) {
|
||||
val configuration = CollectedConfiguration(embeddedComponents, Scope.COMPILE)
|
||||
for (dependencyInfo in listOf(configuration).collectDependencies()) {
|
||||
val dependency = (dependencyInfo as? DependencyInfo.ResolvedDependencyInfo)?.dependency ?: continue
|
||||
|
||||
for ((_, _, dependency) in listOf(embeddedComponents to Scope.COMPILE).collectDependencies()) {
|
||||
if (dependency.configuration == "runtimeElements") {
|
||||
archiveForJar.add(ModuleOutput(dependency.moduleName + ".src"))
|
||||
} else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") {
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.jetbrains.kotlin.pill
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.*
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
@@ -12,7 +11,6 @@ import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.internal.HasConvention
|
||||
import org.jetbrains.kotlin.pill.POrderRoot.*
|
||||
import org.jetbrains.kotlin.pill.PSourceRoot.*
|
||||
import org.jetbrains.kotlin.pill.PillExtension.*
|
||||
import java.io.File
|
||||
import java.util.LinkedList
|
||||
|
||||
@@ -43,34 +41,13 @@ data class PContentRoot(
|
||||
|
||||
data class PSourceRoot(
|
||||
val path: File,
|
||||
val kind: Kind,
|
||||
val kotlinOptions: PSourceRootKotlinOptions?
|
||||
val kind: Kind
|
||||
) {
|
||||
enum class Kind { PRODUCTION, TEST, RESOURCES, TEST_RESOURCES }
|
||||
}
|
||||
enum class Kind {
|
||||
PRODUCTION, TEST, RESOURCES, TEST_RESOURCES;
|
||||
|
||||
data class PSourceRootKotlinOptions(
|
||||
val noStdlib: Boolean?,
|
||||
val noReflect: Boolean?,
|
||||
val moduleName: String?,
|
||||
val apiVersion: String?,
|
||||
val languageVersion: String?,
|
||||
val jvmTarget: String?,
|
||||
val addCompilerBuiltIns: Boolean?,
|
||||
val loadBuiltInsFromDependencies: Boolean?,
|
||||
val extraArguments: List<String>
|
||||
) {
|
||||
fun intersect(other: PSourceRootKotlinOptions) = PSourceRootKotlinOptions(
|
||||
if (noStdlib == other.noStdlib) noStdlib else null,
|
||||
if (noReflect == other.noReflect) noReflect else null,
|
||||
if (moduleName == other.moduleName) moduleName else null,
|
||||
if (apiVersion == other.apiVersion) apiVersion else null,
|
||||
if (languageVersion == other.languageVersion) languageVersion else null,
|
||||
if (jvmTarget == other.jvmTarget) jvmTarget else null,
|
||||
if (addCompilerBuiltIns == other.addCompilerBuiltIns) addCompilerBuiltIns else null,
|
||||
if (loadBuiltInsFromDependencies == other.loadBuiltInsFromDependencies) loadBuiltInsFromDependencies else null,
|
||||
extraArguments.intersect(other.extraArguments).toList()
|
||||
)
|
||||
val isResources get() = this == RESOURCES || this == TEST_RESOURCES
|
||||
}
|
||||
}
|
||||
|
||||
data class POrderRoot(
|
||||
@@ -106,16 +83,9 @@ fun parse(project: Project, libraries: List<PLibrary>, context: ParserContext):
|
||||
error("$project is not a root project")
|
||||
}
|
||||
|
||||
fun Project.matchesSelectedVariant(): Boolean {
|
||||
val extension = this.extensions.findByType(PillExtension::class.java) ?: return true
|
||||
val projectVariant = extension.variant.takeUnless { it == Variant.DEFAULT } ?: Variant.BASE
|
||||
return projectVariant in context.variant.includes
|
||||
}
|
||||
|
||||
val (includedProjects, excludedProjects) = project.allprojects
|
||||
.partition { it.plugins.hasPlugin(JpsCompatiblePlugin::class.java) && it.matchesSelectedVariant() }
|
||||
|
||||
val modules = includedProjects.flatMap { parseModules(it, excludedProjects) }
|
||||
val modules = project.allprojects
|
||||
.filter { it.plugins.hasPlugin(JpsCompatiblePlugin::class.java) }
|
||||
.flatMap { parseModules(it) }
|
||||
|
||||
return PProject("Kotlin", project.projectDir, modules, libraries)
|
||||
}
|
||||
@@ -138,7 +108,12 @@ private val TEST_CONFIGURATION_MAPPING = mapOf(
|
||||
listOf("jpsTest") to Scope.TEST
|
||||
)
|
||||
|
||||
private fun ParserContext.parseModules(project: Project, excludedProjects: List<Project>): List<PModule> {
|
||||
private val SOURCE_SET_MAPPING = mapOf(
|
||||
"main" to Kind.PRODUCTION,
|
||||
"test" to Kind.TEST
|
||||
)
|
||||
|
||||
private fun ParserContext.parseModules(project: Project): List<PModule> {
|
||||
val (productionContentRoots, testContentRoots) = parseContentRoots(project).partition { !it.forTests }
|
||||
|
||||
val modules = mutableListOf<PModule>()
|
||||
@@ -146,10 +121,7 @@ private fun ParserContext.parseModules(project: Project, excludedProjects: List<
|
||||
fun getJavaExcludedDirs() = project.plugins.findPlugin(IdeaPlugin::class.java)
|
||||
?.model?.module?.excludeDirs?.toList() ?: emptyList()
|
||||
|
||||
fun getPillExcludedDirs() = project.extensions.getByType(PillExtension::class.java).excludedDirs
|
||||
|
||||
val allExcludedDirs = getPillExcludedDirs() + getJavaExcludedDirs() + project.buildDir +
|
||||
(if (project == project.rootProject) excludedProjects.map { it.buildDir } else emptyList())
|
||||
val allExcludedDirs = getJavaExcludedDirs() + project.buildDir
|
||||
|
||||
var productionSourcesModule: PModule? = null
|
||||
|
||||
@@ -190,8 +162,8 @@ private fun ParserContext.parseModules(project: Project, excludedProjects: List<
|
||||
}
|
||||
}
|
||||
|
||||
val mainModuleFileRelativePath = when (project) {
|
||||
project.rootProject -> File(project.rootProject.projectDir, project.name + ".iml")
|
||||
val mainModuleFileRelativePath = when {
|
||||
project == project.rootProject -> File(project.rootProject.projectDir, project.name + ".iml")
|
||||
else -> getModuleFile()
|
||||
}
|
||||
|
||||
@@ -227,101 +199,55 @@ private fun parseSourceRoots(project: Project): List<PSourceRoot> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val kotlinTasksBySourceSet = project.tasks
|
||||
.filter { it.name.startsWith("compile") && it.name.endsWith("Kotlin") }
|
||||
.associateBy { it.invokeInternal("getSourceSetName") }
|
||||
|
||||
val sourceRoots = mutableListOf<PSourceRoot>()
|
||||
|
||||
for (sourceSet in project.sourceSets) {
|
||||
val kotlinCompileTask = kotlinTasksBySourceSet[sourceSet.name]
|
||||
val kind = if (sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME) Kind.TEST else Kind.PRODUCTION
|
||||
project.configure<JavaPluginConvention> {
|
||||
for ((sourceSetName, kind) in SOURCE_SET_MAPPING) {
|
||||
val sourceSet = sourceSets.findByName(sourceSetName) ?: continue
|
||||
|
||||
fun Any.getKotlin(): SourceDirectorySet {
|
||||
val kotlinMethod = javaClass.getMethod("getKotlin")
|
||||
val oldIsAccessible = kotlinMethod.isAccessible
|
||||
try {
|
||||
kotlinMethod.isAccessible = true
|
||||
return kotlinMethod(this) as SourceDirectorySet
|
||||
} finally {
|
||||
kotlinMethod.isAccessible = oldIsAccessible
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinSourceDirectories = (sourceSet as HasConvention).convention
|
||||
.plugins["kotlin"]?.getKotlin()?.srcDirs
|
||||
?: emptySet()
|
||||
|
||||
val directories = (sourceSet.java.sourceDirectories.files + kotlinSourceDirectories).toList()
|
||||
.filter { it.exists() }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: continue
|
||||
|
||||
val kotlinOptions = kotlinCompileTask?.let { getKotlinOptions(it) }
|
||||
|
||||
for (resourceRoot in sourceSet.resources.sourceDirectories.files) {
|
||||
if (!resourceRoot.exists() || resourceRoot in directories) {
|
||||
continue
|
||||
fun Any.getKotlin(): SourceDirectorySet {
|
||||
val kotlinMethod = javaClass.getMethod("getKotlin")
|
||||
val oldIsAccessible = kotlinMethod.isAccessible
|
||||
try {
|
||||
kotlinMethod.isAccessible = true
|
||||
return kotlinMethod(this) as SourceDirectorySet
|
||||
} finally {
|
||||
kotlinMethod.isAccessible = oldIsAccessible
|
||||
}
|
||||
}
|
||||
|
||||
val resourceRootKind = when (kind) {
|
||||
Kind.PRODUCTION -> Kind.RESOURCES
|
||||
Kind.TEST -> Kind.TEST_RESOURCES
|
||||
else -> error("Invalid source root kind $kind")
|
||||
val kotlinSourceDirectories = (sourceSet as HasConvention).convention
|
||||
.plugins["kotlin"]?.getKotlin()?.srcDirs
|
||||
?: emptySet()
|
||||
|
||||
val directories = (sourceSet.java.sourceDirectories.files + kotlinSourceDirectories).toList()
|
||||
.filter { it.exists() }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: continue
|
||||
|
||||
for (resourceRoot in sourceSet.resources.sourceDirectories.files) {
|
||||
if (!resourceRoot.exists() || resourceRoot in directories) {
|
||||
continue
|
||||
}
|
||||
|
||||
val resourceRootKind = when (kind) {
|
||||
Kind.PRODUCTION -> Kind.RESOURCES
|
||||
Kind.TEST -> Kind.TEST_RESOURCES
|
||||
else -> error("Invalid source root kind $kind")
|
||||
}
|
||||
|
||||
sourceRoots += PSourceRoot(resourceRoot, resourceRootKind)
|
||||
}
|
||||
|
||||
sourceRoots += PSourceRoot(resourceRoot, resourceRootKind, kotlinOptions)
|
||||
}
|
||||
|
||||
for (directory in directories) {
|
||||
sourceRoots += PSourceRoot(directory, kind, kotlinOptions)
|
||||
for (directory in directories) {
|
||||
sourceRoots += PSourceRoot(directory, kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sourceRoots
|
||||
}
|
||||
|
||||
private fun getKotlinOptions(kotlinCompileTask: Any): PSourceRootKotlinOptions? {
|
||||
val compileArguments = kotlinCompileTask.invokeInternal("getSerializedCompilerArguments") as List<String>
|
||||
fun parseBoolean(name: String) = compileArguments.contains("-$name")
|
||||
fun parseString(name: String) = compileArguments.dropWhile { it != "-$name" }.drop(1).firstOrNull()
|
||||
|
||||
val addCompilerBuiltins = "Xadd-compiler-builtins"
|
||||
val loadBuiltinsFromDependencies = "Xload-builtins-from-dependencies"
|
||||
|
||||
fun isOptionForScriptingCompilerPlugin(option: String)
|
||||
= option.startsWith("-Xplugin=") && option.contains("kotlin-scripting-gradle")
|
||||
|
||||
val extraArguments = compileArguments.filter {
|
||||
it.startsWith("-X") && !isOptionForScriptingCompilerPlugin(it)
|
||||
&& it != "-$addCompilerBuiltins" && it != "-$loadBuiltinsFromDependencies"
|
||||
}
|
||||
|
||||
return PSourceRootKotlinOptions(
|
||||
parseBoolean("no-stdlib"),
|
||||
parseBoolean("no-reflect"),
|
||||
parseString("module-name"),
|
||||
parseString("api-version"),
|
||||
parseString("language-version"),
|
||||
parseString("jvm-target"),
|
||||
parseBoolean(addCompilerBuiltins),
|
||||
parseBoolean(loadBuiltinsFromDependencies),
|
||||
extraArguments
|
||||
)
|
||||
}
|
||||
|
||||
private fun Any.invokeInternal(name: String, instance: Any = this): Any? {
|
||||
val method = javaClass.methods.single { it.name.startsWith(name) && it.parameterTypes.isEmpty() }
|
||||
|
||||
val oldIsAccessible = method.isAccessible
|
||||
try {
|
||||
method.isAccessible = true
|
||||
return method.invoke(instance)
|
||||
} finally {
|
||||
method.isAccessible = oldIsAccessible
|
||||
}
|
||||
}
|
||||
|
||||
private fun ParserContext.parseDependencies(project: Project, forTests: Boolean): List<POrderRoot> {
|
||||
val configurationMapping = if (forTests) TEST_CONFIGURATION_MAPPING else CONFIGURATION_MAPPING
|
||||
|
||||
@@ -329,34 +255,20 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
val mainRoots = mutableListOf<POrderRoot>()
|
||||
val deferredRoots = mutableListOf<POrderRoot>()
|
||||
|
||||
fun collectConfigurations(): List<CollectedConfiguration> {
|
||||
val configurations = mutableListOf<CollectedConfiguration>()
|
||||
fun collectConfigurations(): List<Pair<ResolvedConfiguration, Scope>> {
|
||||
val configurations = mutableListOf<Pair<ResolvedConfiguration, Scope>>()
|
||||
|
||||
for ((configurationNames, scope) in configurationMapping) {
|
||||
for (configurationName in configurationNames) {
|
||||
val configuration = findByName(configurationName)?.also { it.resolve() } ?: continue
|
||||
|
||||
val extraDependencies = resolveExtraDependencies(configuration)
|
||||
configurations += CollectedConfiguration(configuration.resolvedConfiguration, scope, extraDependencies)
|
||||
configurations += Pair(configuration.resolvedConfiguration, scope)
|
||||
}
|
||||
}
|
||||
|
||||
return configurations
|
||||
}
|
||||
|
||||
nextDependency@ for (dependencyInfo in collectConfigurations().collectDependencies()) {
|
||||
val scope = dependencyInfo.scope
|
||||
|
||||
if (dependencyInfo is DependencyInfo.CustomDependencyInfo) {
|
||||
val files = dependencyInfo.files
|
||||
val library = PLibrary(files.firstOrNull()?.nameWithoutExtension ?: "unnamed", classes = files)
|
||||
|
||||
mainRoots += POrderRoot(PDependency.ModuleLibrary(library), scope)
|
||||
continue
|
||||
}
|
||||
|
||||
val dependency = (dependencyInfo as DependencyInfo.ResolvedDependencyInfo).dependency
|
||||
|
||||
nextDependency@ for ((configuration, scope, dependency) in collectConfigurations().collectDependencies()) {
|
||||
for (mapper in dependencyMappers) {
|
||||
if (dependency.moduleGroup == mapper.group
|
||||
&& dependency.moduleName == mapper.module
|
||||
@@ -365,7 +277,12 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
val mappedDependency = mapper.mapping(dependency)
|
||||
|
||||
if (mappedDependency != null) {
|
||||
mainRoots += POrderRoot(mappedDependency.main, scope)
|
||||
val orderRoot = POrderRoot(mappedDependency.main, scope)
|
||||
if (mappedDependency.main is PDependency.Module) {
|
||||
mainRoots += orderRoot
|
||||
} else {
|
||||
mainRoots += orderRoot
|
||||
}
|
||||
|
||||
for (deferredDep in mappedDependency.deferred) {
|
||||
deferredRoots += POrderRoot(deferredDep, scope)
|
||||
@@ -376,10 +293,10 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
}
|
||||
}
|
||||
|
||||
mainRoots += if (dependency.configuration == "runtimeElements" && scope != Scope.TEST) {
|
||||
POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope)
|
||||
if (dependency.configuration == "runtimeElements" && scope != Scope.TEST) {
|
||||
mainRoots += POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope)
|
||||
} else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") {
|
||||
POrderRoot(
|
||||
mainRoots += POrderRoot(
|
||||
PDependency.Module(dependency.moduleName + ".test"),
|
||||
scope,
|
||||
isProductionOnTestDependency = true
|
||||
@@ -387,7 +304,7 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
} else {
|
||||
val classes = dependency.moduleArtifacts.map { it.file }
|
||||
val library = PLibrary(dependency.moduleName, classes)
|
||||
POrderRoot(PDependency.ModuleLibrary(library), scope)
|
||||
mainRoots += POrderRoot(PDependency.ModuleLibrary(library), scope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,23 +312,9 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveExtraDependencies(configuration: Configuration): List<File> {
|
||||
return configuration.dependencies
|
||||
.filterIsInstance<SelfResolvingDependency>()
|
||||
.map { it.resolve() }
|
||||
.filter { isGradleApiDependency(it) }
|
||||
.flatMap { it }
|
||||
}
|
||||
|
||||
private fun isGradleApiDependency(files: Iterable<File>): Boolean {
|
||||
return listOf("gradle-api", "groovy-all").all { dep ->
|
||||
files.any { it.extension == "jar" && it.name.startsWith("$dep-") }
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
|
||||
val dependenciesByScope = roots.groupBy { it.scope }.mapValues { it.value.mapTo(mutableSetOf()) { it.dependency } }
|
||||
fun dependenciesFor(scope: Scope) = dependenciesByScope[scope] ?: emptySet<PDependency>()
|
||||
fun depenciesFor(scope: Scope) = dependenciesByScope[scope] ?: emptySet<PDependency>()
|
||||
|
||||
val result = mutableSetOf<POrderRoot>()
|
||||
for (root in roots.distinct()) {
|
||||
@@ -422,16 +325,16 @@ private fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
|
||||
continue
|
||||
}
|
||||
|
||||
if ((scope == Scope.PROVIDED || scope == Scope.RUNTIME) && dependency in dependenciesFor(Scope.COMPILE)) {
|
||||
if ((scope == Scope.PROVIDED || scope == Scope.RUNTIME) && dependency in depenciesFor(Scope.COMPILE)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (scope == Scope.PROVIDED && dependency in dependenciesFor(Scope.RUNTIME)) {
|
||||
if (scope == Scope.PROVIDED && dependency in depenciesFor(Scope.RUNTIME)) {
|
||||
result += POrderRoot(dependency, Scope.COMPILE)
|
||||
continue
|
||||
}
|
||||
|
||||
if (scope == Scope.RUNTIME && dependency in dependenciesFor(Scope.PROVIDED)) {
|
||||
if (scope == Scope.RUNTIME && dependency in depenciesFor(Scope.PROVIDED)) {
|
||||
result += POrderRoot(dependency, Scope.COMPILE)
|
||||
continue
|
||||
}
|
||||
@@ -442,29 +345,17 @@ private fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
|
||||
return result.toList()
|
||||
}
|
||||
|
||||
data class CollectedConfiguration(
|
||||
val configuration: ResolvedConfiguration,
|
||||
val scope: Scope,
|
||||
val extraDependencies: List<File> = emptyList())
|
||||
data class DependencyInfo(val configuration: ResolvedConfiguration, val scope: Scope, val dependency: ResolvedDependency)
|
||||
|
||||
sealed class DependencyInfo(val scope: Scope) {
|
||||
class ResolvedDependencyInfo(scope: Scope, val dependency: ResolvedDependency) : DependencyInfo(scope)
|
||||
class CustomDependencyInfo(scope: Scope, val files: List<File>) : DependencyInfo(scope)
|
||||
}
|
||||
|
||||
fun List<CollectedConfiguration>.collectDependencies(): List<DependencyInfo> {
|
||||
fun List<Pair<ResolvedConfiguration, Scope>>.collectDependencies(): List<DependencyInfo> {
|
||||
val dependencies = mutableListOf<DependencyInfo>()
|
||||
|
||||
val unprocessed = LinkedList<DependencyInfo>()
|
||||
val existing = mutableSetOf<Pair<Scope, ResolvedDependency>>()
|
||||
|
||||
for ((configuration, scope, extraDependencies) in this) {
|
||||
for ((configuration, scope) in this) {
|
||||
for (dependency in configuration.firstLevelModuleDependencies) {
|
||||
unprocessed += DependencyInfo.ResolvedDependencyInfo(scope, dependency)
|
||||
}
|
||||
|
||||
if (!extraDependencies.isEmpty()) {
|
||||
unprocessed += DependencyInfo.CustomDependencyInfo(scope, extraDependencies)
|
||||
unprocessed += DependencyInfo(configuration, scope, dependency)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,26 +363,17 @@ fun List<CollectedConfiguration>.collectDependencies(): List<DependencyInfo> {
|
||||
val info = unprocessed.removeAt(0)
|
||||
dependencies += info
|
||||
|
||||
info as? DependencyInfo.ResolvedDependencyInfo ?: continue
|
||||
|
||||
val data = Pair(info.scope, info.dependency)
|
||||
existing += data
|
||||
|
||||
for (child in info.dependency.children) {
|
||||
if (Pair(info.scope, child) in existing) {
|
||||
if (child.moduleGroup != "org.jetbrains.kotlin" && Pair(info.scope, child) in existing) {
|
||||
continue
|
||||
}
|
||||
|
||||
unprocessed += DependencyInfo.ResolvedDependencyInfo(info.scope, child)
|
||||
unprocessed += DependencyInfo(info.configuration, info.scope, child)
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies
|
||||
}
|
||||
|
||||
private val Project.sourceSets: SourceSetContainer
|
||||
get() {
|
||||
lateinit var result: SourceSetContainer
|
||||
project.configure<JavaPluginConvention> { result = sourceSets }
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ interface PathContext {
|
||||
}
|
||||
}
|
||||
|
||||
class ProjectContext private constructor(private val projectDir: File) : PathContext {
|
||||
class ProjectContext private constructor(val projectDir: File) : PathContext {
|
||||
constructor(project: PProject) : this(project.rootDirectory)
|
||||
constructor(project: Project) : this(project.projectDir)
|
||||
|
||||
@@ -32,7 +32,10 @@ class ModuleContext(val project: PProject, val module: PModule) : PathContext {
|
||||
return file.absolutePath
|
||||
}
|
||||
|
||||
return "\$MODULE_DIR\$/" + file.toRelativeString(module.moduleFile.parentFile)
|
||||
return "\$MODULE_DIR\$/" +
|
||||
project.rootDirectory.toRelativeString(module.moduleFile.parentFile).withSlash() +
|
||||
module.rootDirectory.toRelativeString(project.rootDirectory).withSlash() +
|
||||
file.toRelativeString(module.rootDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package org.jetbrains.kotlin.pill
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
@@ -11,15 +10,16 @@ import shadow.org.jdom2.output.Format
|
||||
import shadow.org.jdom2.output.XMLOutputter
|
||||
import java.io.File
|
||||
|
||||
class PillConfigurablePlugin : Plugin<Project> {
|
||||
class JpsCompatibleBasePlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
project.configurations.create(EmbeddedComponents.CONFIGURATION_NAME)
|
||||
project.extensions.create("pill", PillExtension::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
class JpsCompatiblePlugin : Plugin<Project> {
|
||||
companion object {
|
||||
private const val JPS_LIBRARY_PATH = "jpsLibraryPath"
|
||||
|
||||
private fun mapper(module: String, vararg configurations: String): DependencyMapper {
|
||||
return DependencyMapper("org.jetbrains.kotlin", module, *configurations) { MappedDependency(PDependency.Library(module)) }
|
||||
}
|
||||
@@ -47,24 +47,21 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
fun getProjectLibraries(rootProject: Project): List<PLibrary> {
|
||||
val distLibDir = File(rootProject.extra["distLibDir"].toString())
|
||||
fun distJar(name: String) = File(rootProject.projectDir, "dist/kotlinc/lib/$name.jar")
|
||||
fun projectFile(path: String) = File(rootProject.projectDir, path)
|
||||
|
||||
val libraries = rootProject.allprojects
|
||||
.mapNotNull { library ->
|
||||
val libraryExtension = library.extensions.findByType(PillExtension::class.java)
|
||||
?.takeIf { it.importAsLibrary }
|
||||
?: return@mapNotNull null
|
||||
|
||||
val libraryPath = libraryExtension.libraryPath ?: distLibDir
|
||||
.filter { it.extra.has(JPS_LIBRARY_PATH) }
|
||||
.map { library ->
|
||||
val libraryPath = library.extra.get(JPS_LIBRARY_PATH).toString()
|
||||
val archivesBaseName = library.convention.findPlugin(BasePluginConvention::class.java)?.archivesBaseName ?: library.name
|
||||
|
||||
fun List<File>.filterExisting() = filter { it.exists() }
|
||||
|
||||
PLibrary(
|
||||
library.name,
|
||||
classes = listOf(File(libraryPath, "$archivesBaseName.jar")).filterExisting(),
|
||||
sources = listOf(File(libraryPath, "$archivesBaseName-sources.jar")).filterExisting()
|
||||
classes = listOf(File(libraryPath, archivesBaseName + ".jar")).filterExisting(),
|
||||
sources = listOf(File(libraryPath, archivesBaseName + "-sources.jar")).filterExisting()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -73,18 +70,15 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
override fun apply(project: Project) {
|
||||
project.plugins.apply(PillConfigurablePlugin::class.java)
|
||||
project.plugins.apply(JpsCompatibleBasePlugin::class.java)
|
||||
// 'jpsTest' does not require the 'tests-jar' artifact
|
||||
project.configurations.create("jpsTest")
|
||||
|
||||
if (project == project.rootProject) {
|
||||
project.tasks.create("pill") {
|
||||
doLast { pill(project) }
|
||||
|
||||
if (System.getProperty("pill.android.tests", "false") == "true") {
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
TaskUtils.useAndroidJar(this)
|
||||
}
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
TaskUtils.useAndroidJar(this)
|
||||
}
|
||||
|
||||
project.tasks.create("unpill") {
|
||||
@@ -109,22 +103,8 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
private fun pill(rootProject: Project) {
|
||||
initEnvironment(rootProject)
|
||||
|
||||
val variantOptionValue = System.getProperty("pill.variant", "base").toUpperCase()
|
||||
val variant = PillExtension.Variant.values().firstOrNull { it.name == variantOptionValue }
|
||||
?: run {
|
||||
rootProject.logger.error("Invalid variant name: $variantOptionValue")
|
||||
return
|
||||
}
|
||||
|
||||
rootProject.logger.lifecycle("Pill: Setting up project for the '${variant.name.toLowerCase()}' variant...")
|
||||
|
||||
if (variant == PillExtension.Variant.NONE || variant == PillExtension.Variant.DEFAULT) {
|
||||
rootProject.logger.error("'none' and 'default' should not be passed as a Pill variant property value")
|
||||
return
|
||||
}
|
||||
|
||||
val projectLibraries = getProjectLibraries(rootProject)
|
||||
val parserContext = ParserContext(getDependencyMappers(projectLibraries), variant)
|
||||
val parserContext = ParserContext(getDependencyMappers(projectLibraries))
|
||||
|
||||
val jpsProject = parse(rootProject, projectLibraries, parserContext)
|
||||
.mapLibraries(this::attachPlatformSources, this::attachAsmSources)
|
||||
@@ -222,9 +202,8 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() }
|
||||
|
||||
fun addOrReplaceOptionValue(name: String, value: Any?) {
|
||||
val optionsWithoutNewValue = options.filter { !it.startsWith("-D$name=") }
|
||||
options = if (value == null) optionsWithoutNewValue else (optionsWithoutNewValue + listOf("-D$name=$value"))
|
||||
fun addOrReplaceOptionValue(name: String, value: Any) {
|
||||
options = options.filter { !it.startsWith("-D$name=") } + listOf("-D$name=$value")
|
||||
}
|
||||
|
||||
val robolectricClasspath = project.rootProject
|
||||
@@ -232,21 +211,16 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
.configurations.getByName("robolectricClasspath")
|
||||
.files.joinToString(File.pathSeparator)
|
||||
|
||||
val androidJarPath = project.configurations.getByName("androidJar").singleFile
|
||||
val androidSdkPath = project.configurations.getByName("androidSdk").singleFile
|
||||
|
||||
addOrReplaceOptionValue("idea.home.path", platformDirProjectRelative)
|
||||
addOrReplaceOptionValue("ideaSdk.androidPlugin.path", platformDirProjectRelative + "/plugins/android/lib")
|
||||
addOrReplaceOptionValue("robolectric.classpath", robolectricClasspath)
|
||||
addOrReplaceOptionValue("use.pill", "true")
|
||||
|
||||
val isAndroidStudioBunch = project.findProperty("versions.androidStudioRelease") != null
|
||||
addOrReplaceOptionValue("idea.platform.prefix", if (isAndroidStudioBunch) "AndroidStudio" else null)
|
||||
|
||||
val androidJarPath = project.configurations.findByName("androidJar")?.singleFile
|
||||
val androidSdkPath = project.configurations.findByName("androidSdk")?.singleFile
|
||||
|
||||
if (androidJarPath != null && androidSdkPath != null) {
|
||||
addOrReplaceOptionValue("android.sdk", "\$PROJECT_DIR\$/" + androidSdkPath.toRelativeString(projectDir))
|
||||
addOrReplaceOptionValue("android.jar", "\$PROJECT_DIR\$/" + androidJarPath.toRelativeString(projectDir))
|
||||
}
|
||||
addOrReplaceOptionValue("android.sdk", "\$PROJECT_DIR\$/" + androidSdkPath.toRelativeString(projectDir))
|
||||
addOrReplaceOptionValue("android.jar", "\$PROJECT_DIR\$/" + androidJarPath.toRelativeString(projectDir))
|
||||
|
||||
vmParams.setAttribute("value", options.joinToString(" "))
|
||||
}
|
||||
|
||||
@@ -54,58 +54,11 @@ private fun renderModule(project: PProject, module: PModule) = PFile(
|
||||
xml("component", "name" to "TestModuleProperties", "production-module" to moduleForProductionSources.name)
|
||||
}
|
||||
|
||||
val kotlinCompileOptionsList = module.contentRoots.flatMap { it.sourceRoots }.mapNotNull { it.kotlinOptions }
|
||||
var kotlinCompileOptions = kotlinCompileOptionsList.firstOrNull()
|
||||
for (otherOptions in kotlinCompileOptionsList.drop(1)) {
|
||||
kotlinCompileOptions = kotlinCompileOptions?.intersect(otherOptions)
|
||||
}
|
||||
|
||||
val pathContext = ModuleContext(project, module)
|
||||
|
||||
val platformVersion = (kotlinCompileOptions?.jvmTarget ?: "1.8")
|
||||
val classesDirectory = File(project.rootDirectory, "out/production/${module.name}")
|
||||
|
||||
if (kotlinCompileOptions != null) {
|
||||
xml("component", "name" to "FacetManager") {
|
||||
xml("facet", "type" to "kotlin-language", "name" to "Kotlin") {
|
||||
xml("configuration", "version" to 3, "platform" to "JVM $platformVersion", "useProjectSettings" to "false") {
|
||||
xml("compilerSettings") {
|
||||
xml(
|
||||
"option",
|
||||
"name" to "additionalArguments",
|
||||
"value" to kotlinCompileOptions.extraArguments.joinToString(" ")
|
||||
)
|
||||
}
|
||||
xml("compilerArguments") {
|
||||
xml("option", "name" to "destination", "value" to pathContext(classesDirectory))
|
||||
|
||||
fun Any?.option(name: String) {
|
||||
if (this != null) xml("option", "name" to name, "value" to this.toString())
|
||||
}
|
||||
|
||||
kotlinCompileOptions.noStdlib.option("noStdlib")
|
||||
kotlinCompileOptions.noReflect.option("noReflect")
|
||||
kotlinCompileOptions.moduleName.option("moduleName")
|
||||
kotlinCompileOptions.languageVersion.option("languageVersion")
|
||||
kotlinCompileOptions.apiVersion.option("apiVersion")
|
||||
kotlinCompileOptions.addCompilerBuiltIns.option("addCompilerBuiltIns")
|
||||
kotlinCompileOptions.loadBuiltInsFromDependencies.option("loadBuiltInsFromDependencies")
|
||||
|
||||
xml("option", "name" to "pluginOptions") { xml("array") }
|
||||
xml("option", "name" to "pluginClasspaths") { xml("array") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml("component",
|
||||
"name" to "NewModuleRootManager",
|
||||
"LANGUAGE_LEVEL" to "JDK_${platformVersion.replace('.', '_')}",
|
||||
"inherit-compiler-output" to "true"
|
||||
) {
|
||||
xml("component", "name" to "NewModuleRootManager", "inherit-compiler-output" to "true") {
|
||||
xml("exclude-output")
|
||||
|
||||
val pathContext = ModuleContext(project, module)
|
||||
|
||||
for (contentRoot in module.contentRoots) {
|
||||
xml("content", pathContext.url(contentRoot.path)) {
|
||||
for (sourceRoot in contentRoot.sourceRoots) {
|
||||
@@ -145,6 +98,7 @@ private fun renderModule(project: PProject, module: PModule) = PFile(
|
||||
"name" to dependency.name,
|
||||
"level" to "project"
|
||||
)
|
||||
else -> error("Unsupported dependency type: $dependency")
|
||||
}
|
||||
|
||||
if (dependency is PDependency.Module && orderRoot.isProductionOnTestDependency) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import shadow.org.jdom2.Element
|
||||
import shadow.org.jdom2.output.Format
|
||||
import shadow.org.jdom2.output.XMLOutputter
|
||||
|
||||
class xml(val name: String, private vararg val args: Pair<String, Any>, block: xml.() -> Unit = {}) {
|
||||
class xml(val name: String, vararg val args: Pair<String, Any>, block: xml.() -> Unit = {}) {
|
||||
private companion object {
|
||||
fun makeXml(name: String, vararg args: Pair<String, Any>, block: xml.() -> Unit = {}): xml {
|
||||
return xml(name, *args, block = block)
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import com.jakewharton.dex.*
|
||||
@@ -19,10 +30,6 @@ open class DexMethodCount : DefaultTask() {
|
||||
val byClass: Map<String, Int>
|
||||
)
|
||||
|
||||
init {
|
||||
outputs.upToDateWhen { !shouldPrintTeamCityStatistics } // always execute when teamCityStatistics output is required
|
||||
}
|
||||
|
||||
@InputFile
|
||||
lateinit var jarFile: File
|
||||
|
||||
@@ -35,9 +42,6 @@ open class DexMethodCount : DefaultTask() {
|
||||
@Optional
|
||||
var teamCityStatistics: Boolean? = null
|
||||
|
||||
private val shouldPrintTeamCityStatistics = teamCityStatistics ?: project.hasProperty("teamcity")
|
||||
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
var artifactName: String? = null
|
||||
@@ -50,12 +54,8 @@ open class DexMethodCount : DefaultTask() {
|
||||
dependsOn(jar)
|
||||
}
|
||||
|
||||
@Internal // plain output properties are not supported, mark as internal to suppress warning from validateTaskProperties
|
||||
lateinit var counts: Counts
|
||||
|
||||
@get:OutputFile
|
||||
val detailOutputFile: File get() = project.buildDir.resolve("$artifactOrArchiveName-method-count.txt")
|
||||
|
||||
@TaskAction
|
||||
fun invoke() {
|
||||
val methods = dexMethods(jarFile)
|
||||
@@ -96,7 +96,7 @@ open class DexMethodCount : DefaultTask() {
|
||||
}
|
||||
|
||||
private fun printTCStats(counts: Counts) {
|
||||
if (shouldPrintTeamCityStatistics) {
|
||||
if (teamCityStatistics ?: project.hasProperty("teamcity")) {
|
||||
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='${counts.total}']")
|
||||
counts.totalOwnPackages?.let { value ->
|
||||
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OwnPackages' value='$value']")
|
||||
@@ -108,7 +108,8 @@ open class DexMethodCount : DefaultTask() {
|
||||
}
|
||||
|
||||
private fun outputDetails(counts: Counts) {
|
||||
detailOutputFile.printWriter().use { writer ->
|
||||
val detailFile = project.buildDir.resolve("$artifactOrArchiveName-method-count.txt")
|
||||
detailFile.printWriter().use { writer ->
|
||||
writer.println("${counts.total.padRight()}\tTotal methods")
|
||||
ownPackages?.let { packages ->
|
||||
writer.println("${counts.totalOwnPackages?.padRight()}\tTotal methods from packages ${packages.joinToString { "$it.*" }}")
|
||||
|
||||
@@ -85,16 +85,6 @@ open class PublishedKotlinModule : Plugin<Project> {
|
||||
dependencies.removeIf {
|
||||
InvokerHelper.getMetaClass(it).getProperty(it, "scope") == "test"
|
||||
}
|
||||
|
||||
dependencies
|
||||
.find {
|
||||
InvokerHelper.getMetaClass(it).getProperty(it, "groupId") == "org.jetbrains.kotlin"
|
||||
&& InvokerHelper.getMetaClass(it).getProperty(it, "artifactId") == "kotlin-stdlib"
|
||||
}
|
||||
?.also {
|
||||
InvokerHelper.getMetaClass(it).setProperty(it, "exclusions", emptyList<Any>())
|
||||
logger.warn("WARNING! Removed exclusions from kotlin-stdlib dependency of ${this.artifactId} artifact's maven metadata, check kotlin-stdlib dependency of ${project.path} project")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,14 @@ inline fun Project.sourceSets(crossinline body: SourceSetsBuilder.() -> Unit) =
|
||||
|
||||
class SourceSetsBuilder(val project: Project) {
|
||||
|
||||
inline operator fun String.invoke(crossinline body: SourceSet.() -> Unit): SourceSet {
|
||||
inline operator fun String.invoke(crossinline body: SourceSet.() -> Unit) {
|
||||
val sourceSetName = this
|
||||
return project.sourceSets.maybeCreate(sourceSetName).apply {
|
||||
none()
|
||||
body()
|
||||
project.configure<JavaPluginConvention>
|
||||
{
|
||||
sourceSets.matching { it.name == sourceSetName }.forEach {
|
||||
none()
|
||||
it.body()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,14 +55,8 @@ fun SourceSet.projectDefault() {
|
||||
|
||||
fun Project.getSourceSetsFrom(projectPath: String): SourceSetContainer {
|
||||
evaluationDependsOn(projectPath)
|
||||
return project(projectPath).sourceSets
|
||||
return project(projectPath).the<JavaPluginConvention>().sourceSets
|
||||
}
|
||||
|
||||
val Project.sourceSets: SourceSetContainer
|
||||
get() = javaPluginConvention().sourceSets
|
||||
|
||||
val Project.mainSourceSet: SourceSet
|
||||
get() = sourceSets.getByName("main")
|
||||
|
||||
val Project.testSourceSet: SourceSet
|
||||
get() = sourceSets.getByName("test")
|
||||
|
||||
@@ -14,58 +14,44 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
// usages in build scripts are not tracked properly
|
||||
@file:Suppress("unused")
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.gradle.kotlin.dsl.project
|
||||
import org.gradle.kotlin.dsl.task
|
||||
import org.gradle.kotlin.dsl.the
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import java.lang.Character.isLowerCase
|
||||
import java.lang.Character.isUpperCase
|
||||
|
||||
fun Project.projectTest(taskName: String = "test", body: Test.() -> Unit = {}): Test = getOrCreateTask(taskName) {
|
||||
doFirst {
|
||||
val commandLineIncludePatterns = (filter as? DefaultTestFilter)?.commandLineIncludePatterns ?: emptySet()
|
||||
val patterns = filter.includePatterns + commandLineIncludePatterns
|
||||
val patterns = filter.includePatterns + ((filter as? DefaultTestFilter)?.commandLineIncludePatterns ?: emptySet())
|
||||
if (patterns.isEmpty() || patterns.any { '*' in it }) return@doFirst
|
||||
patterns.forEach { pattern ->
|
||||
var isClassPattern = false
|
||||
val maybeMethodName = pattern.substringAfterLast('.')
|
||||
val maybeClassFqName = if (maybeMethodName.isFirstChar(::isLowerCase)) {
|
||||
val maybeClassFqName = if (maybeMethodName.isFirstChar(::isLowerCase))
|
||||
pattern.substringBeforeLast('.')
|
||||
} else {
|
||||
isClassPattern = true
|
||||
else
|
||||
pattern
|
||||
}
|
||||
|
||||
if (!maybeClassFqName.substringAfterLast('.').isFirstChar(::isUpperCase)) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val classFileNameWithoutExtension = maybeClassFqName.replace('.', '/')
|
||||
val classFileName = "$classFileNameWithoutExtension.class"
|
||||
|
||||
if (isClassPattern) {
|
||||
val innerClassPattern = "$pattern$*"
|
||||
if (pattern in commandLineIncludePatterns) {
|
||||
commandLineIncludePatterns.add(innerClassPattern)
|
||||
(filter as? DefaultTestFilter)?.setCommandLineIncludePatterns(commandLineIncludePatterns)
|
||||
} else {
|
||||
filter.includePatterns.add(innerClassPattern)
|
||||
}
|
||||
}
|
||||
val classFileName = classFileNameWithoutExtension + ".class"
|
||||
|
||||
include {
|
||||
val path = it.path
|
||||
if (it.isDirectory) {
|
||||
classFileNameWithoutExtension.startsWith(path)
|
||||
} else {
|
||||
path == classFileName || (path.endsWith(".class") && path.startsWith("$classFileNameWithoutExtension$"))
|
||||
path == classFileName || (path.endsWith(".class") && path.startsWith(classFileNameWithoutExtension + "$"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,22 +67,14 @@ fun Project.projectTest(taskName: String = "test", body: Test.() -> Unit = {}):
|
||||
|
||||
dependsOn(":test-instrumenter:jar")
|
||||
|
||||
jvmArgs(
|
||||
"-ea",
|
||||
"-XX:+HeapDumpOnOutOfMemoryError",
|
||||
"-Xmx1600m",
|
||||
"-XX:+UseCodeCacheFlushing",
|
||||
"-XX:ReservedCodeCacheSize=128m",
|
||||
"-Djna.nosys=true"
|
||||
)
|
||||
|
||||
jvmArgs("-ea", "-XX:+HeapDumpOnOutOfMemoryError", "-Xmx1600m", "-XX:+UseCodeCacheFlushing", "-XX:ReservedCodeCacheSize=128m", "-Djna.nosys=true")
|
||||
maxHeapSize = "1600m"
|
||||
systemProperty("idea.is.unit.test", "true")
|
||||
systemProperty("idea.home.path", intellijRootDir().canonicalPath)
|
||||
environment("NO_FS_ROOTS_ACCESS_CHECK", "true")
|
||||
environment("PROJECT_CLASSES_DIRS", testSourceSet.output.classesDirs.asPath)
|
||||
environment("PROJECT_CLASSES_DIRS", the<JavaPluginConvention>().sourceSets.getByName("test").output.classesDirs.asPath)
|
||||
environment("PROJECT_BUILD_DIR", buildDir)
|
||||
systemProperty("jps.kotlin.home", rootProject.extra["distKotlinHomeDir"]!!)
|
||||
systemProperty("jps.kotlin.home", rootProject.extra["distKotlinHomeDir"])
|
||||
systemProperty("kotlin.ni", if (rootProject.hasProperty("newInferenceTests")) "true" else "false")
|
||||
body()
|
||||
}
|
||||
@@ -104,7 +82,7 @@ fun Project.projectTest(taskName: String = "test", body: Test.() -> Unit = {}):
|
||||
private inline fun String.isFirstChar(f: (Char) -> Boolean) = isNotEmpty() && f(first())
|
||||
|
||||
inline fun <reified T : Task> Project.getOrCreateTask(taskName: String, body: T.() -> Unit): T =
|
||||
(tasks.findByName(taskName)?.let { it as T } ?: task<T>(taskName)).apply { body() }
|
||||
(tasks.findByName(taskName)?.let { it as T } ?: task<T>(taskName)).apply { body() }
|
||||
|
||||
object TaskUtils {
|
||||
fun useAndroidSdk(task: Task) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<module name="idea-runner" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$PROJECT_DIR$/local/ideaSandbox -Didea.config.path=$PROJECT_DIR$/local/ideaSandbox/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$IDEA_HOME_PATH$/system -Didea.config.path=$IDEA_HOME_PATH$/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$IDEA_HOME_PATH$" />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<module name="idea-runner" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$PROJECT_DIR$/local/ideaSandbox -Didea.config.path=$PROJECT_DIR$/local/ideaSandbox/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.ProcessCanceledException=disabled" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$IDEA_HOME_PATH$/system -Didea.config.path=$IDEA_HOME_PATH$/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.ProcessCanceledException=disabled" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$IDEA_HOME_PATH$" />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="" />
|
||||
|
||||
29
common.xml
Normal file
29
common.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<project name="Commons">
|
||||
<condition property="isWindows">
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
|
||||
<condition property="isMac">
|
||||
<os family="mac"/>
|
||||
</condition>
|
||||
|
||||
<condition property="isLinux">
|
||||
<and>
|
||||
<os family="unix"/>
|
||||
<not>
|
||||
<os family="mac"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
|
||||
<property name="dependencies" value="${basedir}/dependencies"/>
|
||||
|
||||
<property name="output" value="${basedir}/dist"/>
|
||||
<property name="js.stdlib.output.dir" value="${output}/js"/>
|
||||
|
||||
|
||||
<target name="make-dependency-dirs">
|
||||
<mkdir dir="${dependencies}"/>
|
||||
<mkdir dir="${dependencies}/download"/>
|
||||
</target>
|
||||
</project>
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
|
||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAllTo
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.codegen.CodegenTestCase
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestFiles
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.android.tests;
|
||||
|
||||
import java.util.HashSet;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class SpecialFiles {
|
||||
private static final Set<String> excludedFiles = new HashSet<>();
|
||||
private static final Set<String> excludedFiles = Sets.newHashSet();
|
||||
|
||||
static {
|
||||
fillExcludedFiles();
|
||||
|
||||
@@ -78,26 +78,20 @@ abstract class DataClassMethodGenerator(protected val declaration: KtClassOrObje
|
||||
}
|
||||
|
||||
private fun generateDataClassToStringIfNeeded(properties: List<PropertyDescriptor>) {
|
||||
val function = getMemberToGenerate(
|
||||
classDescriptor, "toString",
|
||||
KotlinBuiltIns::isString, List<ValueParameterDescriptor>::isEmpty
|
||||
) ?: return
|
||||
val function = getMemberToGenerate(classDescriptor, "toString",
|
||||
KotlinBuiltIns::isString, List<ValueParameterDescriptor>::isEmpty) ?: return
|
||||
generateToStringMethod(function, properties)
|
||||
}
|
||||
|
||||
private fun generateDataClassHashCodeIfNeeded(properties: List<PropertyDescriptor>) {
|
||||
val function = getMemberToGenerate(
|
||||
classDescriptor, "hashCode",
|
||||
KotlinBuiltIns::isInt, List<ValueParameterDescriptor>::isEmpty
|
||||
) ?: return
|
||||
val function = getMemberToGenerate(classDescriptor, "hashCode",
|
||||
KotlinBuiltIns::isInt, List<ValueParameterDescriptor>::isEmpty) ?: return
|
||||
generateHashCodeMethod(function, properties)
|
||||
}
|
||||
|
||||
private fun generateDataClassEqualsIfNeeded(properties: List<PropertyDescriptor>) {
|
||||
val function = getMemberToGenerate(
|
||||
classDescriptor, "equals",
|
||||
KotlinBuiltIns::isBoolean
|
||||
) { parameters ->
|
||||
val function = getMemberToGenerate(classDescriptor, "equals",
|
||||
KotlinBuiltIns::isBoolean) { parameters ->
|
||||
parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type)
|
||||
} ?: return
|
||||
generateEqualsMethod(function, properties)
|
||||
@@ -105,8 +99,8 @@ abstract class DataClassMethodGenerator(protected val declaration: KtClassOrObje
|
||||
|
||||
private val dataProperties: List<PropertyDescriptor>
|
||||
get() = primaryConstructorParameters
|
||||
.filter { it.hasValOrVar() }
|
||||
.map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! }
|
||||
.filter { it.hasValOrVar() }
|
||||
.map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! }
|
||||
|
||||
private val primaryConstructorParameters: List<KtParameter>
|
||||
get() = (declaration as? KtClass)?.primaryConstructorParameters.orEmpty()
|
||||
|
||||
@@ -56,7 +56,7 @@ fun <Function : FunctionHandle, Signature> generateBridges(
|
||||
|
||||
val implementation = findConcreteSuperDeclaration(function)
|
||||
|
||||
val bridgesToGenerate = findAllReachableDeclarations(function).mapTo(LinkedHashSet<Signature>(), signature)
|
||||
val bridgesToGenerate = findAllReachableDeclarations(function).mapTo(HashSet<Signature>(), signature)
|
||||
|
||||
if (fake) {
|
||||
// If it's a concrete fake override, some of the bridges may be inherited from the super-classes. Specifically, bridges for all
|
||||
@@ -85,7 +85,7 @@ fun <Function : FunctionHandle> findAllReachableDeclarations(function: Function)
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
DFS.dfs(listOf(function), { it.getOverridden() as Iterable<Function> }, collector)
|
||||
return LinkedHashSet(collector.result())
|
||||
return HashSet(collector.result())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_1_2_20_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
|
||||
val SUSPEND_COROUTINE_OR_RETURN_NAME = Name.identifier("suspendCoroutineOrReturn")
|
||||
val INTERCEPTED_NAME = Name.identifier("intercepted")
|
||||
@@ -20,33 +34,33 @@ val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED")
|
||||
|
||||
val SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME = Name.identifier("suspendCoroutineUninterceptedOrReturn")
|
||||
|
||||
fun FunctionDescriptor.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||
fun FunctionDescriptor.isBuiltInIntercepted(): Boolean {
|
||||
if (name != INTERCEPTED_NAME) return false
|
||||
val original =
|
||||
module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
|
||||
module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope
|
||||
.getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull() as CallableDescriptor
|
||||
return DescriptorEquivalenceForOverrides.areEquivalent(original, this)
|
||||
}
|
||||
|
||||
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturn(): Boolean {
|
||||
if (name != SUSPEND_COROUTINE_OR_RETURN_NAME) return false
|
||||
|
||||
val originalDeclaration = getBuiltInSuspendCoroutineOrReturn(languageVersionSettings) ?: return false
|
||||
val originalDeclaration = getBuiltInSuspendCoroutineOrReturn() ?: return false
|
||||
|
||||
return DescriptorEquivalenceForOverrides.areEquivalent(
|
||||
originalDeclaration, this
|
||||
)
|
||||
}
|
||||
|
||||
fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn(languageVersionSettings: LanguageVersionSettings) =
|
||||
module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
|
||||
fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn() =
|
||||
module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope
|
||||
.getContributedFunctions(SUSPEND_COROUTINE_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull()
|
||||
|
||||
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean {
|
||||
if (name != SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME) return false
|
||||
val original = module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
|
||||
val original = module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope
|
||||
.getContributedFunctions(SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull() as CallableDescriptor
|
||||
return DescriptorEquivalenceForOverrides.areEquivalent(original, this)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
|
||||
public interface AccessorForCallableDescriptor<T extends CallableMemberDescriptor> {
|
||||
@NotNull
|
||||
T getCalleeDescriptor();
|
||||
|
||||
@Nullable
|
||||
ClassDescriptor getSuperCallTarget();
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
|
||||
interface AccessorForCallableDescriptor<T : CallableMemberDescriptor> {
|
||||
val calleeDescriptor: T
|
||||
|
||||
val superCallTarget: ClassDescriptor?
|
||||
|
||||
val accessorKind: AccessorKind
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class AccessorForCompanionObjectInstanceFieldDescriptor(
|
||||
val companionObjectDescriptor: ClassDescriptor,
|
||||
name: Name
|
||||
) :
|
||||
SimpleFunctionDescriptorImpl(
|
||||
companionObjectDescriptor.containingDeclaration,
|
||||
null, Annotations.EMPTY,
|
||||
name,
|
||||
CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE
|
||||
) {
|
||||
|
||||
init {
|
||||
initialize(
|
||||
null, null, emptyList(), emptyList(),
|
||||
companionObjectDescriptor.defaultType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
)
|
||||
}
|
||||
|
||||
override fun createSubstitutedCopy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
original: FunctionDescriptor?,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
newName: Name?,
|
||||
annotations: Annotations,
|
||||
source: SourceElement
|
||||
): FunctionDescriptorImpl {
|
||||
throw UnsupportedOperationException("Accessor for companion object $companionObjectDescriptor should not be substituted")
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
class AccessorForConstructorDescriptor(
|
||||
override val calleeDescriptor: ClassConstructorDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
override val superCallTarget: ClassDescriptor?,
|
||||
override val accessorKind: AccessorKind
|
||||
private val calleeDescriptor: ClassConstructorDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
private val superCallTarget: ClassDescriptor?
|
||||
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("<init>")),
|
||||
ClassConstructorDescriptor,
|
||||
AccessorForCallableDescriptor<ConstructorDescriptor> {
|
||||
ClassConstructorDescriptor,
|
||||
AccessorForCallableDescriptor<ConstructorDescriptor> {
|
||||
override fun getCalleeDescriptor(): ConstructorDescriptor = calleeDescriptor
|
||||
|
||||
override fun getContainingDeclaration(): ClassDescriptor = calleeDescriptor.containingDeclaration
|
||||
|
||||
@@ -39,15 +39,16 @@ class AccessorForConstructorDescriptor(
|
||||
|
||||
override fun getReturnType(): KotlinType = super.getReturnType()!!
|
||||
|
||||
override fun getSuperCallTarget(): ClassDescriptor? = superCallTarget
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor) = super.substitute(substitutor) as ClassConstructorDescriptor
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
): AccessorForConstructorDescriptor {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
@@ -56,13 +57,13 @@ class AccessorForConstructorDescriptor(
|
||||
|
||||
init {
|
||||
initialize(
|
||||
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
|
||||
calleeDescriptor.dispatchReceiverParameter,
|
||||
copyTypeParameters(calleeDescriptor),
|
||||
copyValueParameters(calleeDescriptor),
|
||||
calleeDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
|
||||
calleeDescriptor.dispatchReceiverParameter,
|
||||
copyTypeParameters(calleeDescriptor),
|
||||
copyValueParameters(calleeDescriptor),
|
||||
calleeDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDescriptor implements AccessorForCallableDescriptor<FunctionDescriptor> {
|
||||
private final FunctionDescriptor calleeDescriptor;
|
||||
private final ClassDescriptor superCallTarget;
|
||||
private final String nameSuffix;
|
||||
|
||||
public AccessorForFunctionDescriptor(
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix
|
||||
) {
|
||||
super(containingDeclaration,
|
||||
Name.identifier("access$" + nameSuffix));
|
||||
this.calleeDescriptor = descriptor;
|
||||
this.superCallTarget = superCallTarget;
|
||||
this.nameSuffix = nameSuffix;
|
||||
|
||||
initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()),
|
||||
descriptor instanceof ConstructorDescriptor || CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)
|
||||
? null
|
||||
: descriptor.getDispatchReceiverParameter(),
|
||||
copyTypeParameters(descriptor),
|
||||
copyValueParameters(descriptor),
|
||||
descriptor.getReturnType(),
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL);
|
||||
|
||||
setSuspend(descriptor.isSuspend());
|
||||
if (descriptor.getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) {
|
||||
userDataMap = new LinkedHashMap<>();
|
||||
userDataMap.put(
|
||||
CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION,
|
||||
descriptor.getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected FunctionDescriptorImpl createSubstitutedCopy(
|
||||
@NotNull DeclarationDescriptor newOwner,
|
||||
@Nullable FunctionDescriptor original,
|
||||
@NotNull Kind kind,
|
||||
@Nullable Name newName,
|
||||
@NotNull Annotations annotations,
|
||||
@NotNull SourceElement source
|
||||
) {
|
||||
return new AccessorForFunctionDescriptor(calleeDescriptor, newOwner, superCallTarget, nameSuffix);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionDescriptor getCalleeDescriptor() {
|
||||
return calleeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return superCallTarget;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
import java.util.LinkedHashMap
|
||||
|
||||
class AccessorForFunctionDescriptor(
|
||||
override val calleeDescriptor: FunctionDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
override val superCallTarget: ClassDescriptor?,
|
||||
private val nameSuffix: String,
|
||||
override val accessorKind: AccessorKind
|
||||
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.identifier("access$$nameSuffix")),
|
||||
AccessorForCallableDescriptor<FunctionDescriptor> {
|
||||
|
||||
init {
|
||||
initialize(
|
||||
DescriptorUtils.getReceiverParameterType(calleeDescriptor.extensionReceiverParameter),
|
||||
if (calleeDescriptor is ConstructorDescriptor || calleeDescriptor.isJvmStaticInObjectOrClassOrInterface())
|
||||
null
|
||||
else
|
||||
calleeDescriptor.dispatchReceiverParameter,
|
||||
copyTypeParameters(calleeDescriptor),
|
||||
copyValueParameters(calleeDescriptor),
|
||||
calleeDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
)
|
||||
|
||||
isSuspend = calleeDescriptor.isSuspend
|
||||
if (calleeDescriptor.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) {
|
||||
userDataMap = LinkedHashMap<FunctionDescriptor.UserDataKey<*>, Any>()
|
||||
userDataMap[INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION] =
|
||||
calleeDescriptor.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createSubstitutedCopy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
original: FunctionDescriptor?,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
newName: Name?,
|
||||
annotations: Annotations,
|
||||
source: SourceElement
|
||||
): FunctionDescriptorImpl {
|
||||
return AccessorForFunctionDescriptor(calleeDescriptor, newOwner, superCallTarget, nameSuffix, accessorKind)
|
||||
}
|
||||
}
|
||||
@@ -22,20 +22,19 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class AccessorForPropertyBackingField(
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
delegateType: KotlinType?,
|
||||
extensionReceiverParameter: ReceiverParameterDescriptor?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
nameSuffix: String,
|
||||
fieldAccessorKind: AccessorKind
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
delegateType: KotlinType?,
|
||||
extensionReceiverParameter: ReceiverParameterDescriptor?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
nameSuffix: String,
|
||||
val fieldAccessorKind: FieldAccessorKind
|
||||
) : AccessorForPropertyDescriptor(
|
||||
property,
|
||||
delegateType ?: property.type,
|
||||
extensionReceiverParameter?.type,
|
||||
dispatchReceiverParameter,
|
||||
containingDeclaration,
|
||||
null,
|
||||
nameSuffix,
|
||||
fieldAccessorKind
|
||||
property,
|
||||
delegateType ?: property.type,
|
||||
extensionReceiverParameter?.type,
|
||||
dispatchReceiverParameter,
|
||||
containingDeclaration,
|
||||
null,
|
||||
nameSuffix
|
||||
)
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
|
||||
private final PropertyDescriptor calleeDescriptor;
|
||||
private final ClassDescriptor superCallTarget;
|
||||
private final String nameSuffix;
|
||||
private final boolean withSyntheticGetterAccessor;
|
||||
private final boolean withSyntheticSetterAccessor;
|
||||
|
||||
public AccessorForPropertyDescriptor(
|
||||
@NotNull PropertyDescriptor property,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix,
|
||||
boolean getterAccessorRequired,
|
||||
boolean setterAccessorRequired
|
||||
) {
|
||||
this(property, property.getType(), DescriptorUtils.getReceiverParameterType(property.getExtensionReceiverParameter()),
|
||||
/* dispatchReceiverParameter = */
|
||||
CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(property) ? null : property.getDispatchReceiverParameter(),
|
||||
containingDeclaration, superCallTarget, nameSuffix,
|
||||
getterAccessorRequired, setterAccessorRequired);
|
||||
}
|
||||
|
||||
protected AccessorForPropertyDescriptor(
|
||||
@NotNull PropertyDescriptor original,
|
||||
@NotNull KotlinType propertyType,
|
||||
@Nullable KotlinType receiverType,
|
||||
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix
|
||||
) {
|
||||
this(original, propertyType, receiverType, dispatchReceiverParameter, containingDeclaration, superCallTarget, nameSuffix, true, true);
|
||||
}
|
||||
|
||||
private AccessorForPropertyDescriptor(
|
||||
@NotNull PropertyDescriptor original,
|
||||
@NotNull KotlinType propertyType,
|
||||
@Nullable KotlinType receiverType,
|
||||
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix,
|
||||
boolean getterAccessorRequired,
|
||||
boolean setterAccessorRequired
|
||||
) {
|
||||
super(containingDeclaration, null, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
|
||||
original.isVar(), Name.identifier("access$" + nameSuffix), Kind.DECLARATION, SourceElement.NO_SOURCE,
|
||||
false, false, false, false, false, false);
|
||||
|
||||
this.calleeDescriptor = original;
|
||||
this.superCallTarget = superCallTarget;
|
||||
this.nameSuffix = nameSuffix;
|
||||
setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
|
||||
|
||||
this.withSyntheticGetterAccessor = getterAccessorRequired;
|
||||
this.withSyntheticSetterAccessor = setterAccessorRequired;
|
||||
|
||||
PropertyGetterDescriptorImpl getterDescriptor =
|
||||
getterAccessorRequired ? new Getter(this) : (PropertyGetterDescriptorImpl) original.getGetter();
|
||||
PropertySetterDescriptor setterDescriptor =
|
||||
setterAccessorRequired ? new Setter(this) : original.getSetter();
|
||||
initialize(getterDescriptor, setterDescriptor);
|
||||
}
|
||||
|
||||
public static class Getter extends PropertyGetterDescriptorImpl implements AccessorForCallableDescriptor<PropertyGetterDescriptor> {
|
||||
public Getter(AccessorForPropertyDescriptor property) {
|
||||
super(property, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
|
||||
/* isDefault = */ false, /* isExternal = */ false, /* isInline = */false, Kind.DECLARATION, null, SourceElement.NO_SOURCE);
|
||||
initialize(property.getType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PropertyGetterDescriptor getCalleeDescriptor() {
|
||||
//noinspection ConstantConditions
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallTarget();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Setter extends PropertySetterDescriptorImpl implements AccessorForCallableDescriptor<PropertySetterDescriptor>{
|
||||
public Setter(AccessorForPropertyDescriptor property) {
|
||||
super(property, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
|
||||
/* isDefault = */ false, /* isExternal = */ false, /* isInline = */ false, Kind.DECLARATION, null, SourceElement.NO_SOURCE);
|
||||
initializeDefault();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PropertySetterDescriptor getCalleeDescriptor() {
|
||||
//noinspection ConstantConditions
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getSetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PropertyDescriptor getCalleeDescriptor() {
|
||||
return calleeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return superCallTarget;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getAccessorSuffix() {
|
||||
return nameSuffix;
|
||||
}
|
||||
|
||||
public boolean isWithSyntheticGetterAccessor() {
|
||||
return withSyntheticGetterAccessor;
|
||||
}
|
||||
|
||||
public boolean isWithSyntheticSetterAccessor() {
|
||||
return withSyntheticSetterAccessor;
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
open class AccessorForPropertyDescriptor private constructor(
|
||||
override val calleeDescriptor: PropertyDescriptor,
|
||||
propertyType: KotlinType,
|
||||
receiverType: KotlinType?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
override val superCallTarget: ClassDescriptor?,
|
||||
val accessorSuffix: String,
|
||||
val isWithSyntheticGetterAccessor: Boolean,
|
||||
val isWithSyntheticSetterAccessor: Boolean,
|
||||
final override val accessorKind: AccessorKind
|
||||
) : PropertyDescriptorImpl(
|
||||
containingDeclaration,
|
||||
null,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL,
|
||||
calleeDescriptor.isVar,
|
||||
Name.identifier("access$$accessorSuffix"),
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
), AccessorForCallableDescriptor<PropertyDescriptor> {
|
||||
|
||||
constructor(
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
superCallTarget: ClassDescriptor?,
|
||||
nameSuffix: String,
|
||||
getterAccessorRequired: Boolean,
|
||||
setterAccessorRequired: Boolean,
|
||||
accessorKind: AccessorKind
|
||||
) : this(
|
||||
property, property.type, DescriptorUtils.getReceiverParameterType(property.extensionReceiverParameter),
|
||||
/* dispatchReceiverParameter = */
|
||||
if (property.isJvmStaticInObjectOrClassOrInterface()) null else property.dispatchReceiverParameter,
|
||||
containingDeclaration, superCallTarget, nameSuffix,
|
||||
getterAccessorRequired, setterAccessorRequired,
|
||||
accessorKind
|
||||
)
|
||||
|
||||
protected constructor(
|
||||
original: PropertyDescriptor,
|
||||
propertyType: KotlinType,
|
||||
receiverType: KotlinType?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
superCallTarget: ClassDescriptor?,
|
||||
nameSuffix: String,
|
||||
accessorKind: AccessorKind
|
||||
) : this(
|
||||
original,
|
||||
propertyType,
|
||||
receiverType,
|
||||
dispatchReceiverParameter,
|
||||
containingDeclaration,
|
||||
superCallTarget,
|
||||
nameSuffix,
|
||||
true,
|
||||
true,
|
||||
accessorKind
|
||||
)
|
||||
|
||||
init {
|
||||
setType(propertyType, emptyList<TypeParameterDescriptorImpl>(), dispatchReceiverParameter, receiverType)
|
||||
|
||||
val getterDescriptor =
|
||||
if (isWithSyntheticGetterAccessor) Getter(this, accessorKind) else calleeDescriptor.getter as PropertyGetterDescriptorImpl?
|
||||
val setterDescriptor = if (isWithSyntheticSetterAccessor) Setter(this, accessorKind) else calleeDescriptor.setter
|
||||
initialize(getterDescriptor, setterDescriptor)
|
||||
}
|
||||
|
||||
class Getter(property: AccessorForPropertyDescriptor, override val accessorKind: AccessorKind) : PropertyGetterDescriptorImpl(
|
||||
property,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
), AccessorForCallableDescriptor<PropertyGetterDescriptor> {
|
||||
|
||||
override val calleeDescriptor: PropertyGetterDescriptor
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).calleeDescriptor.getter!!
|
||||
|
||||
override val superCallTarget: ClassDescriptor?
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).superCallTarget
|
||||
|
||||
init {
|
||||
initialize(property.type)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Setter(property: AccessorForPropertyDescriptor, override val accessorKind: AccessorKind) : PropertySetterDescriptorImpl(
|
||||
property,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
), AccessorForCallableDescriptor<PropertySetterDescriptor> {
|
||||
|
||||
override val calleeDescriptor: PropertySetterDescriptor
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).calleeDescriptor.setter!!
|
||||
|
||||
override val superCallTarget: ClassDescriptor?
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).superCallTarget
|
||||
|
||||
init {
|
||||
initializeDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,10 +300,6 @@ public abstract class AnnotationCodegen {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (classDescriptor.isExpect()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
innerClassConsumer.addInnerClassInfoFromAnnotation(classDescriptor);
|
||||
|
||||
String asmTypeDescriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
|
||||
@@ -405,26 +401,6 @@ public abstract class AnnotationCodegen {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitUByteValue(UByteValue value, Void data) {
|
||||
return visitSimpleValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitUShortValue(UShortValue value, Void data) {
|
||||
return visitSimpleValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitUIntValue(UIntValue value, Void data) {
|
||||
return visitSimpleValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitULongValue(ULongValue value, Void data) {
|
||||
return visitSimpleValue(value);
|
||||
}
|
||||
|
||||
private Void visitSimpleValue(ConstantValue<?> value) {
|
||||
annotationVisitor.visit(name, value.getValue());
|
||||
return null;
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.Unit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -26,7 +25,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil;
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding;
|
||||
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -36,6 +35,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
|
||||
@@ -244,8 +244,7 @@ public class AsmUtil {
|
||||
int flags = getVisibilityAccessFlag(functionDescriptor);
|
||||
flags |= getVarargsFlag(functionDescriptor);
|
||||
flags |= getDeprecatedAccessFlag(functionDescriptor);
|
||||
if (state.getDeprecationProvider().isDeprecatedHidden(functionDescriptor) ||
|
||||
(functionDescriptor.isSuspend()) && functionDescriptor.getVisibility().equals(Visibilities.PRIVATE)) {
|
||||
if (state.getDeprecationProvider().isDeprecatedHidden(functionDescriptor)) {
|
||||
flags |= ACC_SYNTHETIC;
|
||||
}
|
||||
return flags;
|
||||
@@ -257,18 +256,13 @@ public class AsmUtil {
|
||||
return specialCase;
|
||||
}
|
||||
Visibility visibility = descriptor.getVisibility();
|
||||
Integer defaultMapping = getVisibilityAccessFlag(visibility);
|
||||
Integer defaultMapping = visibilityToAccessFlag.get(visibility);
|
||||
if (defaultMapping == null) {
|
||||
throw new IllegalStateException(visibility + " is not a valid visibility in backend for " + DescriptorRenderer.DEBUG_TEXT.render(descriptor));
|
||||
}
|
||||
return defaultMapping;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Integer getVisibilityAccessFlag(Visibility visibility) {
|
||||
return visibilityToAccessFlag.get(visibility);
|
||||
}
|
||||
|
||||
/*
|
||||
Use this method to get visibility flag for class to define it in byte code (v.defineClass method).
|
||||
For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor)
|
||||
@@ -400,10 +394,6 @@ public class AsmUtil {
|
||||
return NO_FLAG_PACKAGE_PRIVATE;
|
||||
}
|
||||
|
||||
if (memberDescriptor instanceof AccessorForCompanionObjectInstanceFieldDescriptor) {
|
||||
return NO_FLAG_PACKAGE_PRIVATE;
|
||||
}
|
||||
|
||||
// the following code is only for PRIVATE visibility of member
|
||||
if (memberDescriptor instanceof ConstructorDescriptor) {
|
||||
if (isEnumEntry(containingDeclaration)) {
|
||||
@@ -517,7 +507,7 @@ public class AsmUtil {
|
||||
});
|
||||
}
|
||||
|
||||
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type, JvmTarget jvmTarget) {
|
||||
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type, JvmTarget jvmTarget, boolean isInterface) {
|
||||
if (type.getSort() == Type.ARRAY) {
|
||||
Type elementType = correctElementType(type);
|
||||
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
|
||||
@@ -528,7 +518,7 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
else if (type.getSort() == Type.OBJECT) {
|
||||
iv.invokevirtual("java/lang/Object", "hashCode", "()I", false);
|
||||
iv.invokevirtual((isInterface ? AsmTypes.OBJECT_TYPE : type).getInternalName(), "hashCode", "()I", false);
|
||||
}
|
||||
else if (type.getSort() == Type.BOOLEAN) {
|
||||
Label end = new Label();
|
||||
@@ -900,11 +890,11 @@ public class AsmUtil {
|
||||
public static void writeAnnotationData(
|
||||
@NotNull AnnotationVisitor av, @NotNull MessageLite message, @NotNull JvmStringTable stringTable
|
||||
) {
|
||||
writeAnnotationData(av, JvmProtoBufUtil.writeData(message, stringTable), ArrayUtil.toStringArray(stringTable.getStrings()));
|
||||
writeAnnotationData(av, BitEncoding.encodeBytes(DescriptorSerializer.serialize(message, stringTable)), stringTable.getStrings());
|
||||
}
|
||||
|
||||
public static void writeAnnotationData(
|
||||
@NotNull AnnotationVisitor av, @NotNull String[] data, @NotNull String[] strings
|
||||
@NotNull AnnotationVisitor av, @NotNull String[] data, @NotNull List<String> strings
|
||||
) {
|
||||
AnnotationVisitor dataVisitor = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME);
|
||||
for (String string : data) {
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.coroutines.createCustomCopy
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.JVMAssertionsMode
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
val assertionsDisabledFieldName = "\$assertionsDisabled"
|
||||
private const val ALWAYS_ENABLED_ASSERT_FUNCTION_NAME = "alwaysEnabledAssert"
|
||||
private const val LAMBDA_INTERNAL_NAME = "kotlin/jvm/functions/Function0"
|
||||
private const val ASSERTION_ERROR_INTERNAL_NAME = "java/lang/AssertionError"
|
||||
private const val THROWABLE_INTERNAL_NAME = "java/lang/Throwable"
|
||||
|
||||
fun isAssertCall(resolvedCall: ResolvedCall<*>) = resolvedCall.resultingDescriptor.isTopLevelInPackage("assert", "kotlin")
|
||||
|
||||
private fun FunctionDescriptor.isBuiltinAlwaysEnabledAssertWithLambda() =
|
||||
this.isTopLevelInPackage(ALWAYS_ENABLED_ASSERT_FUNCTION_NAME, "kotlin") && this.valueParameters.size == 2
|
||||
|
||||
private fun FunctionDescriptor.isBuiltinAlwaysEnabledAssertWithoutLambda() =
|
||||
this.isTopLevelInPackage(ALWAYS_ENABLED_ASSERT_FUNCTION_NAME, "kotlin") && this.valueParameters.size == 1
|
||||
|
||||
fun FunctionDescriptor.isBuiltinAlwaysEnabledAssert() =
|
||||
this.isBuiltinAlwaysEnabledAssertWithLambda() || this.isBuiltinAlwaysEnabledAssertWithoutLambda()
|
||||
|
||||
fun createMethodNodeForAlwaysEnabledAssert(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
typeMapper: KotlinTypeMapper
|
||||
): MethodNode {
|
||||
assert(functionDescriptor.isBuiltinAlwaysEnabledAssert()) {
|
||||
"functionDescriptor must be kotlin.alwaysEnabledAssert, but got $functionDescriptor"
|
||||
}
|
||||
|
||||
val node =
|
||||
org.jetbrains.org.objectweb.asm.tree.MethodNode(
|
||||
Opcodes.ASM5,
|
||||
Opcodes.ACC_STATIC,
|
||||
"fake",
|
||||
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
|
||||
)
|
||||
|
||||
val v = InstructionAdapter(node)
|
||||
val returnLabel = Label()
|
||||
|
||||
// if (!condition)
|
||||
v.load(0, Type.BOOLEAN_TYPE)
|
||||
v.ifne(returnLabel)
|
||||
if (functionDescriptor.isBuiltinAlwaysEnabledAssertWithLambda()) {
|
||||
// val err = AssertionError(lambda())
|
||||
v.load(1, Type.getObjectType(LAMBDA_INTERNAL_NAME))
|
||||
v.invokeinterface(LAMBDA_INTERNAL_NAME, "invoke", "()Ljava/lang/Object;")
|
||||
v.store(2, AsmTypes.OBJECT_TYPE)
|
||||
v.anew(Type.getObjectType(ASSERTION_ERROR_INTERNAL_NAME))
|
||||
v.dup()
|
||||
v.load(2, AsmTypes.OBJECT_TYPE)
|
||||
v.invokespecial(ASSERTION_ERROR_INTERNAL_NAME, "<init>", "(Ljava/lang/Object;)V", false)
|
||||
} else {
|
||||
// val err = AssertionError("Assertion failed")
|
||||
v.anew(Type.getObjectType(ASSERTION_ERROR_INTERNAL_NAME))
|
||||
v.dup()
|
||||
v.visitLdcInsn("Assertion failed")
|
||||
v.invokespecial(ASSERTION_ERROR_INTERNAL_NAME, "<init>", "(Ljava/lang/Object;)V", false)
|
||||
}
|
||||
// throw err
|
||||
v.checkcast(Type.getObjectType(THROWABLE_INTERNAL_NAME))
|
||||
v.athrow()
|
||||
// else return
|
||||
v.mark(returnLabel)
|
||||
v.areturn(Type.VOID_TYPE)
|
||||
node.visitMaxs(3, 3)
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
fun generateAssert(
|
||||
assertionsMode: JVMAssertionsMode,
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
codegen: ExpressionCodegen,
|
||||
parentCodegen: MemberCodegen<*>
|
||||
) {
|
||||
assert(isAssertCall(resolvedCall)) { "generateAssert expects call of kotlin.assert function" }
|
||||
when (assertionsMode) {
|
||||
JVMAssertionsMode.ALWAYS_ENABLE -> inlineAlwaysInlineAssert(resolvedCall, codegen)
|
||||
JVMAssertionsMode.ALWAYS_DISABLE -> {
|
||||
// Nothing to do: assertions disabled
|
||||
}
|
||||
JVMAssertionsMode.JVM -> generateJvmAssert(resolvedCall, codegen, parentCodegen)
|
||||
else -> error("legacy assertions mode shall be handled in ExpressionCodegen")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateJvmAssert(resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen, parentCodegen: MemberCodegen<*>) {
|
||||
parentCodegen.generateAssertField()
|
||||
|
||||
val label = Label()
|
||||
with(codegen.v) {
|
||||
getstatic(parentCodegen.v.thisName, "\$assertionsDisabled", "Z")
|
||||
ifne(label)
|
||||
inlineAlwaysInlineAssert(resolvedCall, codegen)
|
||||
mark(label)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun inlineAlwaysInlineAssert(resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen) {
|
||||
val replaced = (resolvedCall as ResolvedCall<FunctionDescriptor>).replaceAssertWithAssertInner()
|
||||
codegen.invokeMethodWithArguments(
|
||||
codegen.typeMapper.mapToCallableMethod(replaced.resultingDescriptor, false),
|
||||
replaced,
|
||||
StackValue.none()
|
||||
)
|
||||
}
|
||||
|
||||
fun generateAssertionsDisabledFieldInitialization(parentCodegen: MemberCodegen<*>) {
|
||||
parentCodegen.v.newField(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC, assertionsDisabledFieldName,
|
||||
"Z", null, null
|
||||
)
|
||||
val clInitCodegen = parentCodegen.createOrGetClInitCodegen()
|
||||
MemberCodegen.markLineNumberForElement(parentCodegen.element.psiOrParent, clInitCodegen.v)
|
||||
val thenLabel = Label()
|
||||
val elseLabel = Label()
|
||||
with(clInitCodegen.v) {
|
||||
aconst(Type.getObjectType(parentCodegen.v.thisName))
|
||||
invokevirtual("java/lang/Class", "desiredAssertionStatus", "()Z", false)
|
||||
ifne(thenLabel)
|
||||
iconst(1)
|
||||
goTo(elseLabel)
|
||||
|
||||
mark(thenLabel)
|
||||
iconst(0)
|
||||
|
||||
mark(elseLabel)
|
||||
putstatic(parentCodegen.v.thisName, assertionsDisabledFieldName, "Z")
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D : FunctionDescriptor> ResolvedCall<D>.replaceAssertWithAssertInner(): ResolvedCall<D> {
|
||||
val newCandidateDescriptor = resultingDescriptor.createCustomCopy {
|
||||
setName(Name.identifier(ALWAYS_ENABLED_ASSERT_FUNCTION_NAME))
|
||||
}
|
||||
val newResolvedCall = ResolvedCallImpl(
|
||||
call,
|
||||
newCandidateDescriptor,
|
||||
dispatchReceiver, extensionReceiver, explicitReceiverKind,
|
||||
null, DelegatingBindingTrace(BindingTraceContext().bindingContext, "Temporary trace for assertInner"),
|
||||
TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
|
||||
)
|
||||
valueArguments.forEach {
|
||||
newResolvedCall.recordValueArgument(newCandidateDescriptor.valueParameters[it.key.index], it.value)
|
||||
}
|
||||
return newResolvedCall
|
||||
}
|
||||
@@ -20,11 +20,12 @@ import org.jetbrains.kotlin.codegen.inline.NameGenerator
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
interface BaseExpressionCodegen {
|
||||
|
||||
val frameMap: FrameMapBase<*>
|
||||
val frameMap: FrameMap
|
||||
|
||||
val visitor: InstructionAdapter
|
||||
|
||||
@@ -37,10 +38,10 @@ interface BaseExpressionCodegen {
|
||||
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
|
||||
|
||||
fun pushClosureOnStack(
|
||||
classDescriptor: ClassDescriptor,
|
||||
putThis: Boolean,
|
||||
callGenerator: CallGenerator,
|
||||
functionReferenceReceiver: StackValue?
|
||||
classDescriptor: ClassDescriptor,
|
||||
putThis: Boolean,
|
||||
callGenerator: CallGenerator,
|
||||
functionReferenceReceiver: StackValue?
|
||||
)
|
||||
|
||||
fun markLineNumberAfterInlineIfNeeded()
|
||||
|
||||
@@ -91,6 +91,12 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
genClassOrObject(companion);
|
||||
}
|
||||
|
||||
// Generate synthetic (non-declared) companion if needed
|
||||
ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
|
||||
if (companionObjectDescriptor instanceof SyntheticClassOrObjectDescriptor) {
|
||||
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
|
||||
}
|
||||
|
||||
// Generate synthetic nested classes
|
||||
Collection<DeclarationDescriptor> classifiers = descriptor
|
||||
.getUnsubstitutedMemberScope()
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ClassBuilderFactories {
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilderMode getClassBuilderMode() {
|
||||
return ClassBuilderMode.FULL;
|
||||
return ClassBuilderMode.full(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -56,15 +56,21 @@ public class ClassBuilderFactories {
|
||||
}
|
||||
};
|
||||
|
||||
public static ClassBuilderFactory TEST = new TestClassBuilderFactory();
|
||||
public static ClassBuilderFactory TEST = new TestClassBuilderFactory(false);
|
||||
|
||||
public static ClassBuilderFactory TEST_WITH_SOURCE_RETENTION_ANNOTATIONS = new TestClassBuilderFactory(true);
|
||||
|
||||
public static class TestClassBuilderFactory implements ClassBuilderFactory {
|
||||
public TestClassBuilderFactory() {}
|
||||
private final boolean generateSourceRetentionAnnotations;
|
||||
|
||||
public TestClassBuilderFactory(boolean generateSourceRetentionAnnotations) {
|
||||
this.generateSourceRetentionAnnotations = generateSourceRetentionAnnotations;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilderMode getClassBuilderMode() {
|
||||
return ClassBuilderMode.FULL;
|
||||
return ClassBuilderMode.full(generateSourceRetentionAnnotations);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -95,33 +101,37 @@ public class ClassBuilderFactories {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilderMode getClassBuilderMode() {
|
||||
return ClassBuilderMode.FULL;
|
||||
}
|
||||
public static ClassBuilderFactory binaries(boolean generateSourceRetentionAnnotations) {
|
||||
return new ClassBuilderFactory() {
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilderMode getClassBuilderMode() {
|
||||
return ClassBuilderMode.full(generateSourceRetentionAnnotations);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) {
|
||||
return new AbstractClassBuilder.Concrete(new BinaryClassWriter());
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) {
|
||||
return new AbstractClassBuilder.Concrete(new BinaryClassWriter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asText(ClassBuilder builder) {
|
||||
throw new UnsupportedOperationException("BINARIES generator asked for text");
|
||||
}
|
||||
@Override
|
||||
public String asText(ClassBuilder builder) {
|
||||
throw new UnsupportedOperationException("BINARIES generator asked for text");
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] asBytes(ClassBuilder builder) {
|
||||
ClassWriter visitor = (ClassWriter) builder.getVisitor();
|
||||
return visitor.toByteArray();
|
||||
}
|
||||
@Override
|
||||
public byte[] asBytes(ClassBuilder builder) {
|
||||
ClassWriter visitor = (ClassWriter) builder.getVisitor();
|
||||
return visitor.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
};
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ClassBuilderFactories() {
|
||||
}
|
||||
|
||||
@@ -35,11 +35,15 @@ public class ClassBuilderMode {
|
||||
this.generateSourceRetentionAnnotations = generateSourceRetentionAnnotations;
|
||||
this.generateMultiFileFacadePartClasses = generateMultiFileFacadePartClasses;
|
||||
}
|
||||
|
||||
public static ClassBuilderMode full(boolean generateSourceRetentionAnnotations) {
|
||||
return generateSourceRetentionAnnotations ? KAPT : FULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full function bodies
|
||||
*/
|
||||
public final static ClassBuilderMode FULL = new ClassBuilderMode(
|
||||
private final static ClassBuilderMode FULL = new ClassBuilderMode(
|
||||
/* bodies = */ true,
|
||||
/* metadata = */ true,
|
||||
/* sourceRetention = */ false,
|
||||
@@ -53,6 +57,15 @@ public class ClassBuilderMode {
|
||||
/* metadata = */ false,
|
||||
/* sourceRetention = */ true,
|
||||
/* generateMultiFileFacadePartClasses = */ false);
|
||||
|
||||
/**
|
||||
* Function signatures + metadata (to support incremental compilation with kapt)
|
||||
*/
|
||||
public final static ClassBuilderMode KAPT = new ClassBuilderMode(
|
||||
/* bodies = */ false,
|
||||
/* metadata = */ true,
|
||||
/* sourceRetention = */ true,
|
||||
/* generateMultiFileFacadePartClasses = */ false);
|
||||
|
||||
/**
|
||||
* Function signatures + metadata (to support incremental compilation with kapt)
|
||||
|
||||
@@ -32,14 +32,11 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMappingUtilKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageParts;
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf;
|
||||
import org.jetbrains.kotlin.metadata.jvm.JvmModuleProtoBuf;
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion;
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping;
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMappingKt;
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
@@ -126,7 +123,7 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
generators.put(outputFilePath, new OutAndSourceFileList(CollectionsKt.toList(packagePartSourceFiles)) {
|
||||
@Override
|
||||
public byte[] asBytes(ClassBuilderFactory factory) {
|
||||
return ModuleMappingKt.serializeToByteArray(moduleProto, JvmMetadataVersion.INSTANCE.toArray());
|
||||
return ClassFileUtilsKt.serializeToByteArray(moduleProto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -195,9 +192,8 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
answer.append(file.asText());
|
||||
break;
|
||||
case "kotlin_module": {
|
||||
ModuleMapping mapping = ModuleMappingUtilKt.loadModuleMapping(
|
||||
ModuleMapping.Companion, file.asByteArray(), relativePath.getPath(),
|
||||
CompilerDeserializationConfiguration.Default.INSTANCE
|
||||
ModuleMapping mapping = ModuleMapping.Companion.create(
|
||||
file.asByteArray(), relativePath.getPath(), CompilerDeserializationConfiguration.Default.INSTANCE
|
||||
);
|
||||
for (Map.Entry<String, PackageParts> entry : mapping.getPackageFqName2Parts().entrySet()) {
|
||||
FqName packageFqName = new FqName(entry.getKey());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -422,7 +422,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
|
||||
String superClassConstructorDescriptor;
|
||||
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
|
||||
superClassAsmType.equals(CoroutineCodegenUtilKt.coroutineImplAsmType(state.getLanguageVersionSettings()))) {
|
||||
superClassAsmType.equals(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE)) {
|
||||
int arity = calculateArity();
|
||||
iv.iconst(arity);
|
||||
if (shouldHaveBoundReferenceReceiver) {
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.CollectionStub
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeCheckerImpl
|
||||
@@ -310,16 +309,8 @@ class CollectionStubMethodGenerator(
|
||||
}
|
||||
|
||||
private fun createSyntheticSubclass(): Pair<MutableClassDescriptor, List<TypeParameterDescriptor>> {
|
||||
val child = MutableClassDescriptor(
|
||||
descriptor.containingDeclaration,
|
||||
ClassKind.CLASS,
|
||||
/* isInner = */ false,
|
||||
/* isExternal */ false,
|
||||
Name.special("<synthetic inheritor of ${descriptor.name}>"),
|
||||
descriptor.source,
|
||||
LockBasedStorageManager.NO_LOCKS
|
||||
)
|
||||
|
||||
val child = MutableClassDescriptor(descriptor.containingDeclaration, ClassKind.CLASS, /* isInner = */ false,
|
||||
/* isExternal */ false, Name.special("<synthetic inheritor of ${descriptor.name}>"), descriptor.source)
|
||||
child.modality = Modality.FINAL
|
||||
child.visibility = Visibilities.PUBLIC
|
||||
val typeParameters = descriptor.typeConstructor.parameters
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.kotlin.util.ExceptionUtilKt;
|
||||
|
||||
public interface CompilationErrorHandler {
|
||||
CompilationErrorHandler THROW_EXCEPTION = (exception, fileUrl) -> {
|
||||
throw new IllegalStateException(
|
||||
ExceptionUtilKt.getExceptionMessage("Backend", "Exception during code generation", exception, fileUrl),
|
||||
exception
|
||||
);
|
||||
if (exception instanceof RuntimeException) {
|
||||
throw (RuntimeException) exception;
|
||||
}
|
||||
throw new IllegalStateException(exception);
|
||||
};
|
||||
|
||||
void reportException(Throwable exception, String fileUrl);
|
||||
|
||||
@@ -39,8 +39,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
private companion object {
|
||||
// rename -> JvmOverloads
|
||||
private val ANNOTATION_TYPE_DESCRIPTOR_FOR_JVM_OVERLOADS_GENERATED_METHODS: String =
|
||||
Type.getObjectType("synthetic/kotlin/jvm/GeneratedByJvmOverloads").descriptor
|
||||
private val ANNOTATION_TYPE_DESCRIPTOR_FOR_JVMOVERLOADS_GENERATED_METHODS: String =
|
||||
Type.getObjectType("synthetic/kotlin/jvm/GeneratedByJvmOverloads").descriptor
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,26 +48,29 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
* generates a no-argument constructor that passes default values for all arguments.
|
||||
*/
|
||||
fun generatePrimaryConstructorOverloadsIfNeeded(
|
||||
constructorDescriptor: ConstructorDescriptor,
|
||||
classBuilder: ClassBuilder,
|
||||
memberCodegen: MemberCodegen<*>,
|
||||
contextKind: OwnerKind,
|
||||
classOrObject: KtPureClassOrObject
|
||||
constructorDescriptor: ConstructorDescriptor,
|
||||
classBuilder: ClassBuilder,
|
||||
memberCodegen: MemberCodegen<*>,
|
||||
contextKind: OwnerKind,
|
||||
classOrObject: KtPureClassOrObject
|
||||
) {
|
||||
val element = classOrObject.primaryConstructor ?: classOrObject
|
||||
val methodElement = classOrObject.primaryConstructor ?: classOrObject
|
||||
|
||||
if (!generateOverloadsIfNeeded(element, constructorDescriptor, constructorDescriptor, contextKind, classBuilder, memberCodegen) &&
|
||||
isEmptyConstructorNeeded(constructorDescriptor, classOrObject)
|
||||
) {
|
||||
generateOverloadWithSubstitutedParameters(
|
||||
constructorDescriptor, constructorDescriptor, classBuilder, memberCodegen, element, contextKind,
|
||||
constructorDescriptor.countDefaultParameters()
|
||||
)
|
||||
if (generateOverloadsIfNeeded(methodElement, constructorDescriptor, constructorDescriptor, contextKind, classBuilder, memberCodegen)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!isEmptyConstructorNeeded(constructorDescriptor, classOrObject)) {
|
||||
return
|
||||
}
|
||||
|
||||
generateOverloadWithSubstitutedParameters(
|
||||
constructorDescriptor, constructorDescriptor, classBuilder, memberCodegen, methodElement, contextKind,
|
||||
constructorDescriptor.countDefaultParameters())
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function is annotated with [kotlin.jvm.JvmOverloads], generates Java methods that
|
||||
* If the function is annotated with [kotlin.jvm.jvmOverloads], generates Java methods that
|
||||
* have the default parameter values substituted. If a method has N parameters and M of which
|
||||
* have default values, M overloads are generated: the first one takes N-1 parameters (all but
|
||||
* the last one that takes a default value), the second takes N-2 parameters, and so on.
|
||||
@@ -80,18 +83,20 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
* @return true if the overloads annotation was found on the element, false otherwise
|
||||
*/
|
||||
fun generateOverloadsIfNeeded(
|
||||
methodElement: KtPureElement?,
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
delegateFunctionDescriptor: FunctionDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
classBuilder: ClassBuilder,
|
||||
memberCodegen: MemberCodegen<*>
|
||||
methodElement: KtPureElement?,
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
delegateFunctionDescriptor: FunctionDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
classBuilder: ClassBuilder,
|
||||
memberCodegen: MemberCodegen<*>
|
||||
): Boolean {
|
||||
if (functionDescriptor.findJvmOverloadsAnnotation() == null) return false
|
||||
functionDescriptor.findJvmOverloadsAnnotation() ?: return false
|
||||
|
||||
for (i in 1..functionDescriptor.countDefaultParameters()) {
|
||||
val count = functionDescriptor.countDefaultParameters()
|
||||
|
||||
for (i in 1..count) {
|
||||
generateOverloadWithSubstitutedParameters(
|
||||
functionDescriptor, delegateFunctionDescriptor, classBuilder, memberCodegen, methodElement, contextKind, i
|
||||
functionDescriptor, delegateFunctionDescriptor, classBuilder, memberCodegen, methodElement, contextKind, i
|
||||
)
|
||||
}
|
||||
|
||||
@@ -113,44 +118,40 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
* @param methodElement the PSI element for the method implementation (used in diagnostic messages only)
|
||||
*/
|
||||
private fun generateOverloadWithSubstitutedParameters(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
delegateFunctionDescriptor: FunctionDescriptor,
|
||||
classBuilder: ClassBuilder,
|
||||
memberCodegen: MemberCodegen<*>,
|
||||
methodElement: KtPureElement?,
|
||||
contextKind: OwnerKind,
|
||||
substituteCount: Int
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
delegateFunctionDescriptor: FunctionDescriptor,
|
||||
classBuilder: ClassBuilder,
|
||||
memberCodegen: MemberCodegen<*>,
|
||||
methodElement: KtPureElement?,
|
||||
contextKind: OwnerKind,
|
||||
substituteCount: Int
|
||||
) {
|
||||
val typeMapper = state.typeMapper
|
||||
val isStatic = AsmUtil.isStaticMethod(contextKind, functionDescriptor)
|
||||
val baseMethodFlags = AsmUtil.getCommonCallableFlags(functionDescriptor, state) and Opcodes.ACC_VARARGS.inv()
|
||||
val remainingParameters = getRemainingParameters(functionDescriptor.original, substituteCount)
|
||||
val flags =
|
||||
baseMethodFlags or
|
||||
(if (isStatic) Opcodes.ACC_STATIC else 0) or
|
||||
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0) or
|
||||
(if (remainingParameters.lastOrNull()?.varargElementType != null) Opcodes.ACC_VARARGS else 0)
|
||||
baseMethodFlags or
|
||||
(if (isStatic) Opcodes.ACC_STATIC else 0) or
|
||||
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0) or
|
||||
(if (remainingParameters.lastOrNull()?.varargElementType != null) Opcodes.ACC_VARARGS else 0)
|
||||
val signature = typeMapper.mapSignatureWithCustomParameters(functionDescriptor, contextKind, remainingParameters, false)
|
||||
val mv = classBuilder.newMethod(
|
||||
OtherOriginFromPure(methodElement, functionDescriptor), flags,
|
||||
signature.asmMethod.name,
|
||||
signature.asmMethod.descriptor,
|
||||
signature.genericsSignature,
|
||||
FunctionCodegen.getThrownExceptions(functionDescriptor, typeMapper)
|
||||
)
|
||||
val mv = classBuilder.newMethod(OtherOriginFromPure(methodElement, functionDescriptor), flags,
|
||||
signature.asmMethod.name,
|
||||
signature.asmMethod.descriptor,
|
||||
signature.genericsSignature,
|
||||
FunctionCodegen.getThrownExceptions(functionDescriptor, typeMapper))
|
||||
|
||||
AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper).genAnnotations(functionDescriptor, signature.returnType)
|
||||
|
||||
if (state.classBuilderMode == ClassBuilderMode.KAPT3) {
|
||||
mv.visitAnnotation(ANNOTATION_TYPE_DESCRIPTOR_FOR_JVM_OVERLOADS_GENERATED_METHODS, false)
|
||||
mv.visitAnnotation(ANNOTATION_TYPE_DESCRIPTOR_FOR_JVMOVERLOADS_GENERATED_METHODS, /* visible = */ false)
|
||||
}
|
||||
|
||||
FunctionCodegen.generateParameterAnnotations(functionDescriptor, mv, signature, remainingParameters, memberCodegen, state)
|
||||
|
||||
if (!state.classBuilderMode.generateBodies) {
|
||||
FunctionCodegen.generateLocalVariablesForParameters(
|
||||
mv, signature, null, Label(), Label(), remainingParameters, isStatic, typeMapper
|
||||
)
|
||||
FunctionCodegen.generateLocalVariablesForParameters(mv, signature, null, Label(), Label(), remainingParameters, isStatic, typeMapper)
|
||||
mv.visitEnd()
|
||||
return
|
||||
}
|
||||
@@ -175,7 +176,8 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
v.load(outerIndex, typeMapper.mapType(captureThis))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
val delegateOwner = delegateFunctionDescriptor.containingDeclaration
|
||||
if (delegateOwner is ClassDescriptor && delegateOwner.isCompanionObject) {
|
||||
val singletonValue = StackValue.singleton(delegateOwner, typeMapper)
|
||||
@@ -189,8 +191,8 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
val receiverIndex = frameMap.enter(receiver, receiverType)
|
||||
StackValue.local(receiverIndex, receiverType).put(receiverType, v)
|
||||
}
|
||||
for (parameter in remainingParameters) {
|
||||
frameMap.enter(parameter, typeMapper.mapType(parameter))
|
||||
remainingParameters.forEach {
|
||||
frameMap.enter(it, typeMapper.mapType(it))
|
||||
}
|
||||
|
||||
var mask = 0
|
||||
@@ -200,7 +202,8 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
if (parameterDescriptor in remainingParameters) {
|
||||
val index = frameMap.getIndex(parameterDescriptor)
|
||||
StackValue.local(index, paramType).put(paramType, v)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
AsmUtil.pushDefaultValueOnStack(paramType, v)
|
||||
val i = parameterDescriptor.index
|
||||
if (i != 0 && i % Integer.SIZE == 0) {
|
||||
@@ -223,7 +226,8 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
val defaultMethod = typeMapper.mapDefaultMethod(delegateFunctionDescriptor, contextKind)
|
||||
if (functionDescriptor is ConstructorDescriptor) {
|
||||
v.invokespecial(methodOwner.internalName, defaultMethod.name, defaultMethod.descriptor, false)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
v.invokestatic(methodOwner.internalName, defaultMethod.name, defaultMethod.descriptor, false)
|
||||
}
|
||||
v.areturn(signature.returnType)
|
||||
@@ -231,16 +235,16 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
val methodEnd = Label()
|
||||
mv.visitLabel(methodEnd)
|
||||
|
||||
FunctionCodegen.generateLocalVariablesForParameters(
|
||||
mv, signature, null, methodBegin, methodEnd, remainingParameters, isStatic, typeMapper
|
||||
)
|
||||
FunctionCodegen.generateLocalVariablesForParameters(mv, signature, null, methodBegin, methodEnd,
|
||||
remainingParameters, isStatic, typeMapper)
|
||||
|
||||
FunctionCodegen.endVisit(mv, null, methodElement)
|
||||
}
|
||||
|
||||
private fun getRemainingParameters(functionDescriptor: FunctionDescriptor, substituteCount: Int): List<ValueParameterDescriptor> {
|
||||
private fun getRemainingParameters(functionDescriptor: FunctionDescriptor,
|
||||
substituteCount: Int): List<ValueParameterDescriptor> {
|
||||
var remainingCount = functionDescriptor.countDefaultParameters() - substituteCount
|
||||
return functionDescriptor.valueParameters.filter { !it.hasDefaultValue() || --remainingCount >= 0 }
|
||||
return functionDescriptor.valueParameters.filter { !it.declaresDefaultValue() || --remainingCount >= 0 }
|
||||
}
|
||||
|
||||
private fun isEmptyConstructorNeeded(constructorDescriptor: ConstructorDescriptor, classOrObject: KtPureClassOrObject): Boolean {
|
||||
@@ -251,14 +255,16 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
|
||||
if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false
|
||||
|
||||
if (Visibilities.isPrivate(constructorDescriptor.visibility)) return false
|
||||
if (Visibilities.isPrivate(constructorDescriptor.visibility))
|
||||
return false
|
||||
|
||||
if (constructorDescriptor.valueParameters.isEmpty()) return false
|
||||
if (classOrObject is KtClass && hasSecondaryConstructorsWithNoParameters(classOrObject)) return false
|
||||
|
||||
return constructorDescriptor.valueParameters.all { it.hasDefaultValue() }
|
||||
return constructorDescriptor.valueParameters.all { it.declaresDefaultValue() }
|
||||
}
|
||||
|
||||
private fun hasSecondaryConstructorsWithNoParameters(klass: KtClass) =
|
||||
klass.secondaryConstructors.any { it.valueParameters.isEmpty() }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -23,9 +23,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenForLambda;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.ResolvedCallWithRealDescriptor;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*;
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
||||
import org.jetbrains.kotlin.codegen.inline.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.*;
|
||||
@@ -40,9 +38,9 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
|
||||
import org.jetbrains.kotlin.config.ApiVersion;
|
||||
import org.jetbrains.kotlin.config.JVMAssertionsMode;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||
@@ -61,7 +59,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.checkers.PrimitiveNumericComparisonInfo;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
@@ -130,7 +127,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
* When we create a temporary variable to hold some value not to compute it many times
|
||||
* we put it into this map to emit access to that variable instead of evaluating the whole expression
|
||||
*/
|
||||
public final Map<KtElement, StackValue> tempVariables = new HashMap<>();
|
||||
public final Map<KtElement, StackValue> tempVariables = Maps.newHashMap();
|
||||
|
||||
private int myLastLineNumber = -1;
|
||||
private boolean shouldMarkLineNumbers = true;
|
||||
@@ -359,16 +356,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return (ScriptContext) context;
|
||||
}
|
||||
|
||||
private StackValue genLazy(KtElement expr, Type type) {
|
||||
public StackValue genLazy(KtElement expr, Type type) {
|
||||
StackValue value = gen(expr);
|
||||
return StackValue.coercion(value, type, null);
|
||||
}
|
||||
|
||||
private StackValue genLazy(KtElement expr, Type type, KotlinType kotlinType) {
|
||||
StackValue value = gen(expr);
|
||||
return StackValue.coercion(value, type, kotlinType);
|
||||
}
|
||||
|
||||
private StackValue genStatement(KtElement statement) {
|
||||
return genQualified(StackValue.none(), statement, statementVisitor);
|
||||
}
|
||||
@@ -494,12 +486,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
Label end = new Label();
|
||||
|
||||
gen(thenExpression, asmType, kotlinType);
|
||||
gen(thenExpression, asmType);
|
||||
|
||||
v.goTo(end);
|
||||
v.mark(elseLabel);
|
||||
|
||||
gen(elseExpression, asmType, kotlinType);
|
||||
gen(elseExpression, asmType);
|
||||
|
||||
markLineNumber(expression, isStatement);
|
||||
v.mark(end);
|
||||
@@ -883,10 +875,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
constantValue.append(String.valueOf(compileTimeConstant.getValue()));
|
||||
}
|
||||
else {
|
||||
String accumulatedConstantValue = constantValue.toString();
|
||||
if (accumulatedConstantValue.length() > 0) {
|
||||
result.add(new StringTemplateEntry.Constant(accumulatedConstantValue));
|
||||
}
|
||||
result.add(new StringTemplateEntry.Constant(constantValue.toString()));
|
||||
constantValue.setLength(0);
|
||||
|
||||
result.add(new StringTemplateEntry.Expression(entryExpression));
|
||||
@@ -1739,9 +1728,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
resolvedCall, false);
|
||||
}
|
||||
|
||||
if (descriptor instanceof FakeCallableDescriptorForTypeAliasObject) {
|
||||
descriptor = ((FakeCallableDescriptorForTypeAliasObject) descriptor).getTypeAliasDescriptor();
|
||||
}
|
||||
if (descriptor instanceof TypeAliasDescriptor) {
|
||||
ClassDescriptor classDescriptor = ((TypeAliasDescriptor) descriptor).getClassDescriptor();
|
||||
if (classDescriptor == null) {
|
||||
@@ -1756,9 +1742,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (shouldGenerateSingletonAsThisOrOuterFromContext(classDescriptor)) {
|
||||
return generateThisOrOuterFromContext(classDescriptor, false, false);
|
||||
}
|
||||
if (isCompanionObject(classDescriptor) && !couldUseDirectAccessToCompanionObject(classDescriptor, context)) {
|
||||
return generateAccessorCallForCompanionObject(classDescriptor);
|
||||
}
|
||||
if (isObject(classDescriptor)) {
|
||||
return StackValue.singleton(classDescriptor, typeMapper);
|
||||
}
|
||||
@@ -1951,7 +1934,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private CodegenContext getBackingFieldContext(
|
||||
@NotNull AccessorKind accessorKind,
|
||||
@NotNull FieldAccessorKind accessorKind,
|
||||
@NotNull DeclarationDescriptor containingDeclaration
|
||||
) {
|
||||
switch (accessorKind) {
|
||||
@@ -2001,22 +1984,22 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
|
||||
boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
AccessorKind fieldAccessorKind;
|
||||
FieldAccessorKind fieldAccessorKind;
|
||||
if (skipLateinitAssertion) {
|
||||
fieldAccessorKind = AccessorKind.LATEINIT_INTRINSIC;
|
||||
fieldAccessorKind = FieldAccessorKind.LATEINIT_INTRINSIC;
|
||||
}
|
||||
else if (isBackingFieldInClassCompanion &&
|
||||
(forceField ||
|
||||
(Visibilities.isPrivate(propertyDescriptor.getVisibility()) &&
|
||||
isDefaultAccessor(propertyDescriptor.getGetter()) && isDefaultAccessor(propertyDescriptor.getSetter())))) {
|
||||
fieldAccessorKind = AccessorKind.IN_CLASS_COMPANION;
|
||||
fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION;
|
||||
}
|
||||
else if ((syntheticBackingField &&
|
||||
context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration)) {
|
||||
fieldAccessorKind = AccessorKind.FIELD_FROM_LOCAL;
|
||||
fieldAccessorKind = FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||
}
|
||||
else {
|
||||
fieldAccessorKind = AccessorKind.NORMAL;
|
||||
fieldAccessorKind = FieldAccessorKind.NORMAL;
|
||||
}
|
||||
boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) ||
|
||||
AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor);
|
||||
@@ -2031,7 +2014,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
CodegenContext backingFieldContext = getBackingFieldContext(fieldAccessorKind, containingDeclaration);
|
||||
boolean isPrivateProperty =
|
||||
fieldAccessorKind != AccessorKind.NORMAL &&
|
||||
fieldAccessorKind != FieldAccessorKind.NORMAL &&
|
||||
(AsmUtil.getVisibilityForBackingField(propertyDescriptor, isDelegatedProperty) & ACC_PRIVATE) != 0;
|
||||
DeclarationDescriptor ownerDescriptor;
|
||||
boolean skipPropertyAccessors;
|
||||
@@ -2042,7 +2025,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
boolean directAccessToSetter = couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context,
|
||||
state.getShouldInlineConstVals());
|
||||
|
||||
if (fieldAccessorKind == AccessorKind.LATEINIT_INTRINSIC) {
|
||||
if (fieldAccessorKind == FieldAccessorKind.LATEINIT_INTRINSIC) {
|
||||
skipPropertyAccessors = !isPrivateProperty || context.getClassOrPackageParentContext() == backingFieldContext;
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
@@ -2051,7 +2034,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
ownerDescriptor = propertyDescriptor;
|
||||
}
|
||||
else if (fieldAccessorKind == AccessorKind.IN_CLASS_COMPANION || fieldAccessorKind == AccessorKind.FIELD_FROM_LOCAL) {
|
||||
else if (fieldAccessorKind == FieldAccessorKind.IN_CLASS_COMPANION || fieldAccessorKind == FieldAccessorKind.FIELD_FROM_LOCAL) {
|
||||
// Do not use accessor 'access<property name>$cp' when the property can be accessed directly by its backing field.
|
||||
skipPropertyAccessors = skipAccessorsForPrivateFieldInOuterClass ||
|
||||
(directAccessToGetter && (!propertyDescriptor.isVar() || directAccessToSetter));
|
||||
@@ -2254,7 +2237,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull
|
||||
public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
|
||||
ResolvedCallWithRealDescriptor callWithRealDescriptor =
|
||||
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(resolvedCall, state);
|
||||
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(
|
||||
resolvedCall, state.getProject(), state.getBindingContext()
|
||||
);
|
||||
if (callWithRealDescriptor != null) {
|
||||
prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression());
|
||||
return invokeFunction(callWithRealDescriptor.getResolvedCall(), receiver);
|
||||
@@ -2367,13 +2352,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull CallGenerator callGenerator,
|
||||
@NotNull ArgumentGenerator argumentGenerator
|
||||
) {
|
||||
if (AssertCodegenUtilKt.isAssertCall(resolvedCall) && !state.getAssertionsMode().equals(JVMAssertionsMode.LEGACY)) {
|
||||
AssertCodegenUtilKt.generateAssert(state.getAssertionsMode(), resolvedCall, this, parentCodegen);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isSuspendNoInlineCall =
|
||||
CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall, this, state.getLanguageVersionSettings());
|
||||
boolean isSuspendNoInlineCall = CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall, this);
|
||||
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
|
||||
if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) {
|
||||
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, isSuspendNoInlineCall, isConstructor);
|
||||
@@ -2524,7 +2503,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor original =
|
||||
CoroutineCodegenUtilKt.getOriginalSuspendFunctionView(
|
||||
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())),
|
||||
bindingContext, state
|
||||
bindingContext
|
||||
);
|
||||
if (isDefaultCompilation) {
|
||||
return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement));
|
||||
@@ -2615,11 +2594,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
else if (isPossiblyUninitializedSingleton(receiverDescriptor) && isInsideSingleton(receiverDescriptor)) {
|
||||
return generateThisOrOuterFromContext(receiverDescriptor, false, false);
|
||||
}
|
||||
else if (couldUseDirectAccessToCompanionObject(receiverDescriptor, context)) {
|
||||
return StackValue.singleton(receiverDescriptor, typeMapper);
|
||||
}
|
||||
else {
|
||||
return generateAccessorCallForCompanionObject(receiverDescriptor);
|
||||
return StackValue.singleton(receiverDescriptor, typeMapper);
|
||||
}
|
||||
}
|
||||
else if (receiverDescriptor instanceof ScriptDescriptor) {
|
||||
@@ -2648,41 +2624,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue generateAccessorCallForCompanionObject(@NotNull ClassDescriptor companionObjectDescriptor) {
|
||||
DeclarationDescriptor hostClassDescriptor = companionObjectDescriptor.getContainingDeclaration();
|
||||
assert hostClassDescriptor instanceof ClassDescriptor :
|
||||
"Containing declaration of the companion object " + companionObjectDescriptor +
|
||||
": expected a class, actual: " + hostClassDescriptor;
|
||||
|
||||
CodegenContext hostClassContext = context;
|
||||
while (hostClassContext.getContextDescriptor() != hostClassDescriptor) {
|
||||
hostClassContext = hostClassContext.getParentContext();
|
||||
assert hostClassContext != null :
|
||||
"Host class context for " + hostClassDescriptor + " not found in context hierarchy for " + context;
|
||||
}
|
||||
|
||||
hostClassContext.markCompanionObjectDescriptorWithAccessorRequired(companionObjectDescriptor);
|
||||
|
||||
Type hostClassType = typeMapper.mapClass((ClassifierDescriptor) hostClassDescriptor);
|
||||
Type companionObjectType = typeMapper.mapClass(companionObjectDescriptor);
|
||||
|
||||
// TODO given that we actually have corresponding AccessorForCompanionObjectInstanceFieldDescriptor,
|
||||
// it might be a better idea to use general method call generation
|
||||
return StackValue.operation(
|
||||
companionObjectType,
|
||||
companionObjectDescriptor.getDefaultType(),
|
||||
v -> {
|
||||
v.invokestatic(
|
||||
hostClassType.getInternalName(),
|
||||
getCompanionObjectAccessorName(companionObjectDescriptor),
|
||||
Type.getMethodDescriptor(companionObjectType),
|
||||
/* itf */ false
|
||||
);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue generateExtensionReceiver(@NotNull CallableDescriptor descriptor) {
|
||||
ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter();
|
||||
@@ -3065,7 +3006,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.coercion(generateSafeQualifiedExpression((KtSafeQualifiedExpression) expression, ifnull), type, kotlinType);
|
||||
}
|
||||
else {
|
||||
return genLazy(expression, type, kotlinType);
|
||||
return genLazy(expression, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3187,10 +3128,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@Nullable KtExpression left,
|
||||
@Nullable KtExpression right,
|
||||
@NotNull IElementType opToken,
|
||||
@Nullable StackValue pregeneratedSubject,
|
||||
@Nullable StackValue pregeneratedLeft,
|
||||
@Nullable PrimitiveNumericComparisonInfo primitiveNumericComparisonInfo
|
||||
) {
|
||||
Type leftType = pregeneratedSubject != null ? pregeneratedSubject.type : expressionType(left);
|
||||
Type leftType = expressionType(left);
|
||||
Type rightType = expressionType(right);
|
||||
|
||||
if (KtPsiUtil.isNullConstant(left)) {
|
||||
@@ -3198,7 +3139,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
if (KtPsiUtil.isNullConstant(right)) {
|
||||
return genCmpWithNull(left, opToken, pregeneratedSubject);
|
||||
return genCmpWithNull(left, opToken, pregeneratedLeft);
|
||||
}
|
||||
|
||||
if (isIntZero(left, leftType) && isIntPrimitive(rightType)) {
|
||||
@@ -3206,23 +3147,23 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
if (isIntZero(right, rightType) && isIntPrimitive(leftType)) {
|
||||
return genCmpWithZero(left, opToken, pregeneratedSubject);
|
||||
return genCmpWithZero(left, opToken, pregeneratedLeft);
|
||||
}
|
||||
|
||||
if (pregeneratedSubject == null && left instanceof KtSafeQualifiedExpression &&
|
||||
if (pregeneratedLeft == null && left instanceof KtSafeQualifiedExpression &&
|
||||
isSelectorPureNonNullType((KtSafeQualifiedExpression) left) && isPrimitive(rightType)) {
|
||||
return genCmpSafeCallToPrimitive((KtSafeQualifiedExpression) left, right, rightType, opToken);
|
||||
}
|
||||
|
||||
if (isPrimitive(leftType) && right instanceof KtSafeQualifiedExpression &&
|
||||
isSelectorPureNonNullType(((KtSafeQualifiedExpression) right))) {
|
||||
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken, pregeneratedSubject);
|
||||
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken, pregeneratedLeft);
|
||||
}
|
||||
|
||||
if (BoxedToPrimitiveEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return BoxedToPrimitiveEquality.create(
|
||||
opToken,
|
||||
genLazyUnlessProvided(pregeneratedSubject, left, leftType), leftType,
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
|
||||
genLazy(right, rightType), rightType,
|
||||
myFrameMap
|
||||
);
|
||||
@@ -3231,7 +3172,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (PrimitiveToBoxedEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return PrimitiveToBoxedEquality.create(
|
||||
opToken,
|
||||
genLazyUnlessProvided(pregeneratedSubject, left, leftType), leftType,
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
|
||||
genLazy(right, rightType), rightType
|
||||
);
|
||||
}
|
||||
@@ -3239,7 +3180,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (PrimitiveToObjectEquality.isApplicable(opToken, leftType, rightType)) {
|
||||
return PrimitiveToObjectEquality.create(
|
||||
opToken,
|
||||
genLazyUnlessProvided(pregeneratedSubject, left, leftType), leftType,
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
|
||||
genLazy(right, rightType), rightType
|
||||
);
|
||||
}
|
||||
@@ -3256,34 +3197,28 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.cmp(
|
||||
opToken,
|
||||
operandType,
|
||||
genLazyUnlessProvided(pregeneratedSubject, left, leftType),
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
|
||||
genLazy(right, rightType)
|
||||
);
|
||||
}
|
||||
|
||||
if ((opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
||||
(isEnumExpression(left) || isEnumExpression(right))) {
|
||||
(isEnumClass(bindingContext.getType(left).getConstructor().getDeclarationDescriptor()) ||
|
||||
isEnumClass(bindingContext.getType(right).getConstructor().getDeclarationDescriptor()))) {
|
||||
// Reference equality can be used for enums.
|
||||
return StackValue.cmp(
|
||||
opToken == KtTokens.EQEQ ? KtTokens.EQEQEQ : KtTokens.EXCLEQEQEQ,
|
||||
OBJECT_TYPE,
|
||||
genLazyUnlessProvided(pregeneratedSubject, left, leftType),
|
||||
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
|
||||
genLazy(right, rightType)
|
||||
);
|
||||
}
|
||||
|
||||
return genEqualsForExpressionsPreferIeee754Arithmetic(
|
||||
left, right, opToken, leftType, rightType, pregeneratedSubject, primitiveNumericComparisonInfo
|
||||
left, right, opToken, leftType, rightType, pregeneratedLeft, primitiveNumericComparisonInfo
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isEnumExpression(@Nullable KtExpression expression) {
|
||||
KotlinType expressionType = bindingContext.getType(expression);
|
||||
if (expressionType == null) return false;
|
||||
return isEnumClass(expressionType.getConstructor().getDeclarationDescriptor());
|
||||
}
|
||||
|
||||
|
||||
private boolean isSelectorPureNonNullType(@NotNull KtSafeQualifiedExpression safeExpression) {
|
||||
KtExpression expression = safeExpression.getSelectorExpression();
|
||||
if (expression == null) return false;
|
||||
@@ -3648,7 +3583,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext);
|
||||
|
||||
ResolvedCallWithRealDescriptor callWithRealDescriptor =
|
||||
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(resolvedCall, state);
|
||||
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(
|
||||
resolvedCall, state.getProject(), state.getBindingContext()
|
||||
);
|
||||
if (callWithRealDescriptor != null) {
|
||||
prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression());
|
||||
resolvedCall = callWithRealDescriptor.getResolvedCall();
|
||||
@@ -4542,12 +4479,12 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
|
||||
public StackValue generateWhenExpression(KtWhenExpression expression, boolean isStatement) {
|
||||
KtExpression expr = expression.getSubjectExpression();
|
||||
Type subjectType = expressionType(expr);
|
||||
|
||||
Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression);
|
||||
|
||||
return StackValue.operation(resultType, v -> {
|
||||
KtProperty subjectVariable = expression.getSubjectVariable();
|
||||
KtExpression subjectExpression = expression.getSubjectExpression();
|
||||
|
||||
SwitchCodegen switchCodegen = switchCodegenProvider.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, CodegenUtil.isExhaustive(bindingContext, expression, isStatement)
|
||||
);
|
||||
@@ -4556,31 +4493,12 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
return null;
|
||||
}
|
||||
|
||||
int subjectLocal;
|
||||
Type subjectType;
|
||||
VariableDescriptor subjectVariableDescriptor = null;
|
||||
if (subjectVariable != null) {
|
||||
subjectVariableDescriptor = bindingContext.get(BindingContext.VARIABLE, subjectVariable);
|
||||
assert subjectVariableDescriptor != null : "Unresolved subject variable: " + subjectVariable.getName();
|
||||
subjectType = asmType(subjectVariableDescriptor.getType());
|
||||
subjectLocal = myFrameMap.enter(subjectVariableDescriptor, subjectType);
|
||||
visitProperty(subjectVariable, null);
|
||||
tempVariables.put(subjectExpression, StackValue.local(subjectLocal, subjectType));
|
||||
}
|
||||
else if (subjectExpression != null) {
|
||||
subjectType = expressionType(subjectExpression);
|
||||
subjectLocal = myFrameMap.enterTemp(subjectType);
|
||||
gen(subjectExpression, subjectType);
|
||||
tempVariables.put(subjectExpression, StackValue.local(subjectLocal, subjectType));
|
||||
int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
|
||||
if (subjectLocal != -1) {
|
||||
gen(expr, subjectType);
|
||||
tempVariables.put(expr, StackValue.local(subjectLocal, subjectType));
|
||||
v.store(subjectLocal, subjectType);
|
||||
}
|
||||
else {
|
||||
subjectLocal = -1;
|
||||
subjectType = Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
Label begin = new Label();
|
||||
v.mark(begin);
|
||||
|
||||
Label end = new Label();
|
||||
boolean hasElse = KtPsiUtil.checkWhenExpressionHasSingleElse(expression);
|
||||
@@ -4596,7 +4514,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
if (!whenEntry.isElse()) {
|
||||
KtWhenCondition[] conditions = whenEntry.getConditions();
|
||||
for (int i = 0; i < conditions.length; i++) {
|
||||
StackValue conditionValue = generateWhenCondition(subjectExpression, subjectType, subjectLocal, conditions[i]);
|
||||
StackValue conditionValue = generateWhenCondition(expr, subjectType, subjectLocal, conditions[i]);
|
||||
BranchedValue.Companion.condJump(conditionValue, nextCondition, true, v);
|
||||
if (i < conditions.length - 1) {
|
||||
v.goTo(thisEntry);
|
||||
@@ -4621,17 +4539,8 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
markLineNumber(expression, isStatement);
|
||||
v.mark(end);
|
||||
|
||||
if (subjectVariableDescriptor != null) {
|
||||
myFrameMap.leave(subjectVariableDescriptor);
|
||||
v.visitLocalVariable(
|
||||
subjectVariableDescriptor.getName().asString(), subjectType.getDescriptor(), null,
|
||||
begin, end, subjectLocal
|
||||
);
|
||||
}
|
||||
else {
|
||||
myFrameMap.leaveTemp(subjectType);
|
||||
}
|
||||
tempVariables.remove(subjectExpression);
|
||||
myFrameMap.leaveTemp(subjectType);
|
||||
tempVariables.remove(expr);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
132
compiler/backend/src/org/jetbrains/kotlin/codegen/FrameMap.java
Normal file
132
compiler/backend/src/org/jetbrains/kotlin/codegen/FrameMap.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import gnu.trove.TObjectIntIterator;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class FrameMap {
|
||||
private final TObjectIntHashMap<DeclarationDescriptor> myVarIndex = new TObjectIntHashMap<>();
|
||||
private final TObjectIntHashMap<DeclarationDescriptor> myVarSizes = new TObjectIntHashMap<>();
|
||||
private int myMaxIndex = 0;
|
||||
|
||||
public int enter(DeclarationDescriptor descriptor, Type type) {
|
||||
int index = myMaxIndex;
|
||||
myVarIndex.put(descriptor, index);
|
||||
myMaxIndex += type.getSize();
|
||||
myVarSizes.put(descriptor, type.getSize());
|
||||
return index;
|
||||
}
|
||||
|
||||
public int leave(DeclarationDescriptor descriptor) {
|
||||
int size = myVarSizes.get(descriptor);
|
||||
myMaxIndex -= size;
|
||||
myVarSizes.remove(descriptor);
|
||||
int oldIndex = myVarIndex.remove(descriptor);
|
||||
if (oldIndex != myMaxIndex) {
|
||||
throw new IllegalStateException("Descriptor can be left only if it is last: " + descriptor);
|
||||
}
|
||||
return oldIndex;
|
||||
}
|
||||
|
||||
public int enterTemp(Type type) {
|
||||
int result = myMaxIndex;
|
||||
myMaxIndex += type.getSize();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void leaveTemp(Type type) {
|
||||
myMaxIndex -= type.getSize();
|
||||
}
|
||||
|
||||
public int getIndex(DeclarationDescriptor descriptor) {
|
||||
return myVarIndex.contains(descriptor) ? myVarIndex.get(descriptor) : -1;
|
||||
}
|
||||
|
||||
public Mark mark() {
|
||||
return new Mark(myMaxIndex);
|
||||
}
|
||||
|
||||
public int getCurrentSize() {
|
||||
return myMaxIndex;
|
||||
}
|
||||
|
||||
public class Mark {
|
||||
private final int myIndex;
|
||||
|
||||
public Mark(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public void dropTo() {
|
||||
List<DeclarationDescriptor> descriptorsToDrop = new ArrayList<>();
|
||||
TObjectIntIterator<DeclarationDescriptor> iterator = myVarIndex.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
iterator.advance();
|
||||
if (iterator.value() >= myIndex) {
|
||||
descriptorsToDrop.add(iterator.key());
|
||||
}
|
||||
}
|
||||
for (DeclarationDescriptor declarationDescriptor : descriptorsToDrop) {
|
||||
myVarIndex.remove(declarationDescriptor);
|
||||
myVarSizes.remove(declarationDescriptor);
|
||||
}
|
||||
myMaxIndex = myIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (myVarIndex.size() != myVarSizes.size()) {
|
||||
return "inconsistent";
|
||||
}
|
||||
|
||||
List<Trinity<DeclarationDescriptor, Integer, Integer>> descriptors = Lists.newArrayList();
|
||||
|
||||
for (Object descriptor0 : myVarIndex.keys()) {
|
||||
DeclarationDescriptor descriptor = (DeclarationDescriptor) descriptor0;
|
||||
int varIndex = myVarIndex.get(descriptor);
|
||||
int varSize = myVarSizes.get(descriptor);
|
||||
descriptors.add(Trinity.create(descriptor, varIndex, varSize));
|
||||
}
|
||||
|
||||
descriptors.sort(Comparator.comparingInt(left -> left.second));
|
||||
|
||||
sb.append("size=").append(myMaxIndex);
|
||||
|
||||
boolean first = true;
|
||||
for (Trinity<DeclarationDescriptor, Integer, Integer> t : descriptors) {
|
||||
if (!first) {
|
||||
sb.append(", ");
|
||||
}
|
||||
first = false;
|
||||
sb.append(t.first).append(",i=").append(t.second).append(",s=").append(t.third);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,122 +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 com.google.common.collect.Lists
|
||||
import com.intellij.openapi.util.Trinity
|
||||
import gnu.trove.TObjectIntHashMap
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class FrameMap : FrameMapBase<DeclarationDescriptor>()
|
||||
|
||||
open class FrameMapBase<T : Any> {
|
||||
private val myVarIndex = TObjectIntHashMap<T>()
|
||||
private val myVarSizes = TObjectIntHashMap<T>()
|
||||
var currentSize = 0
|
||||
private set
|
||||
|
||||
fun enter(descriptor: T, type: Type): Int {
|
||||
val index = currentSize
|
||||
myVarIndex.put(descriptor, index)
|
||||
currentSize += type.size
|
||||
myVarSizes.put(descriptor, type.size)
|
||||
return index
|
||||
}
|
||||
|
||||
fun leave(descriptor: T): Int {
|
||||
val size = myVarSizes.get(descriptor)
|
||||
currentSize -= size
|
||||
myVarSizes.remove(descriptor)
|
||||
val oldIndex = myVarIndex.remove(descriptor)
|
||||
if (oldIndex != currentSize) {
|
||||
throw IllegalStateException("Descriptor can be left only if it is last: $descriptor")
|
||||
}
|
||||
return oldIndex
|
||||
}
|
||||
|
||||
fun enterTemp(type: Type): Int {
|
||||
val result = currentSize
|
||||
currentSize += type.size
|
||||
return result
|
||||
}
|
||||
|
||||
fun leaveTemp(type: Type) {
|
||||
currentSize -= type.size
|
||||
}
|
||||
|
||||
fun getIndex(descriptor: T): Int {
|
||||
return if (myVarIndex.contains(descriptor)) myVarIndex.get(descriptor) else -1
|
||||
}
|
||||
|
||||
fun mark(): Mark {
|
||||
return Mark(currentSize)
|
||||
}
|
||||
|
||||
inner class Mark(private val myIndex: Int) {
|
||||
|
||||
fun dropTo() {
|
||||
val descriptorsToDrop = ArrayList<T>()
|
||||
val iterator = myVarIndex.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
iterator.advance()
|
||||
if (iterator.value() >= myIndex) {
|
||||
descriptorsToDrop.add(iterator.key())
|
||||
}
|
||||
}
|
||||
for (declarationDescriptor in descriptorsToDrop) {
|
||||
myVarIndex.remove(declarationDescriptor)
|
||||
myVarSizes.remove(declarationDescriptor)
|
||||
}
|
||||
currentSize = myIndex
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
if (myVarIndex.size() != myVarSizes.size()) {
|
||||
return "inconsistent"
|
||||
}
|
||||
|
||||
val descriptors = Lists.newArrayList<Trinity<T, Int, Int>>()
|
||||
|
||||
for (descriptor0 in myVarIndex.keys()) {
|
||||
val descriptor = descriptor0 as T
|
||||
val varIndex = myVarIndex.get(descriptor)
|
||||
val varSize = myVarSizes.get(descriptor)
|
||||
descriptors.add(Trinity.create(descriptor, varIndex, varSize))
|
||||
}
|
||||
|
||||
descriptors.sortBy { left -> left.second }
|
||||
|
||||
sb.append("size=").append(currentSize)
|
||||
|
||||
var first = true
|
||||
for (t in descriptors) {
|
||||
if (!first) {
|
||||
sb.append(", ")
|
||||
}
|
||||
first = false
|
||||
sb.append(t.first).append(",i=").append(t.second).append(",s=").append(t.third)
|
||||
}
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -20,18 +20,13 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.SuspendInlineFunctionGenerationStrategy;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
import org.jetbrains.kotlin.config.JvmDefaultMode;
|
||||
import org.jetbrains.kotlin.config.JvmTarget;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
|
||||
@@ -39,7 +34,6 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
@@ -129,28 +123,16 @@ public class FunctionCodegen {
|
||||
|
||||
if (owner.getContextKind() != OwnerKind.DEFAULT_IMPLS || function.hasBody()) {
|
||||
FunctionGenerationStrategy strategy;
|
||||
if (functionDescriptor.isSuspend()) {
|
||||
if (AnnotationUtilKt.isEffectivelyInlineOnly(functionDescriptor)) {
|
||||
strategy = new FunctionGenerationStrategy.FunctionDefault(state, function);
|
||||
} else if (!functionDescriptor.isInline()) {
|
||||
strategy = new SuspendFunctionGenerationStrategy(
|
||||
state,
|
||||
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
|
||||
function,
|
||||
v.getThisName(),
|
||||
state.getConstructorCallNormalizationMode()
|
||||
);
|
||||
} else {
|
||||
strategy = new SuspendInlineFunctionGenerationStrategy(
|
||||
state,
|
||||
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
|
||||
function,
|
||||
v.getThisName(),
|
||||
state.getConstructorCallNormalizationMode(),
|
||||
this
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (functionDescriptor.isSuspend() && !functionDescriptor.isInline()) {
|
||||
strategy = new SuspendFunctionGenerationStrategy(
|
||||
state,
|
||||
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
|
||||
function,
|
||||
v.getThisName(),
|
||||
state.getConstructorCallNormalizationMode()
|
||||
);
|
||||
}
|
||||
else {
|
||||
strategy = new FunctionGenerationStrategy.FunctionDefault(state, function);
|
||||
}
|
||||
|
||||
@@ -179,8 +161,7 @@ public class FunctionCodegen {
|
||||
@NotNull FunctionGenerationStrategy strategy
|
||||
) {
|
||||
if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(descriptor)) {
|
||||
generateMethod(origin, CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, state.getLanguageVersionSettings()
|
||||
.supportsFeature(LanguageFeature.ReleaseCoroutines), bindingContext), strategy);
|
||||
generateMethod(origin, CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, bindingContext), strategy);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,10 +176,7 @@ public class FunctionCodegen {
|
||||
) {
|
||||
OwnerKind contextKind = methodContext.getContextKind();
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||
if (isInterface(containingDeclaration) &&
|
||||
!processInterfaceMethod(functionDescriptor, contextKind, false, false, state.getJvmDefaultMode())) {
|
||||
return;
|
||||
}
|
||||
if (isInterface(containingDeclaration) && !processInterfaceMethod(functionDescriptor, contextKind, false)) return;
|
||||
|
||||
boolean hasSpecialBridge = hasSpecialBridgeMethod(functionDescriptor);
|
||||
JvmMethodGenericSignature jvmSignature = strategy.mapMethodSignature(functionDescriptor, typeMapper, contextKind, hasSpecialBridge);
|
||||
@@ -217,12 +195,12 @@ public class FunctionCodegen {
|
||||
|
||||
MethodVisitor mv =
|
||||
strategy.wrapMethodVisitor(
|
||||
newMethod(origin,
|
||||
flags,
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
jvmSignature.getGenericsSignature(),
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
v.newMethod(origin,
|
||||
flags,
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
jvmSignature.getGenericsSignature(),
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
),
|
||||
flags, asmMethod.getName(),
|
||||
asmMethod.getDescriptor()
|
||||
@@ -269,18 +247,6 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
return v.newMethod(origin, access, name, desc, signature, exceptions);
|
||||
}
|
||||
|
||||
private static boolean shouldDelegateMethodBodyToInlineClass(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@@ -415,7 +381,6 @@ public class FunctionCodegen {
|
||||
new Label(),
|
||||
contextKind,
|
||||
typeMapper,
|
||||
Collections.emptyList(),
|
||||
0);
|
||||
|
||||
mv.visitEnd();
|
||||
@@ -423,7 +388,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
if (!functionDescriptor.isExternal()) {
|
||||
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen, state.getJvmDefaultMode());
|
||||
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
|
||||
}
|
||||
else if (staticInCompanionObject) {
|
||||
// native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
|
||||
@@ -433,7 +398,7 @@ public class FunctionCodegen {
|
||||
Method accessorMethod =
|
||||
typeMapper.mapAsmMethod(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
|
||||
Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
|
||||
generateDelegateToStaticMethodBody(false, mv, accessorMethod, owningType.getInternalName(), false);
|
||||
generateDelegateToStaticMethodBody(false, mv, accessorMethod, owningType.getInternalName());
|
||||
}
|
||||
|
||||
endVisit(mv, null, origin.getElement());
|
||||
@@ -605,8 +570,7 @@ public class FunctionCodegen {
|
||||
@NotNull MethodContext context,
|
||||
@NotNull JvmMethodSignature signature,
|
||||
@NotNull FunctionGenerationStrategy strategy,
|
||||
@NotNull MemberCodegen<?> parentCodegen,
|
||||
@NotNull JvmDefaultMode jvmDefaultMode
|
||||
@NotNull MemberCodegen<?> parentCodegen
|
||||
) {
|
||||
mv.visitCode();
|
||||
|
||||
@@ -616,7 +580,7 @@ public class FunctionCodegen {
|
||||
KotlinTypeMapper typeMapper = parentCodegen.typeMapper;
|
||||
if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, typeMapper::mapAsmMethod)) {
|
||||
generateTypeCheckBarrierIfNeeded(
|
||||
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), null, typeMapper);
|
||||
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), /* delegateParameterTypes = */null);
|
||||
}
|
||||
|
||||
Label methodEnd;
|
||||
@@ -628,20 +592,6 @@ public class FunctionCodegen {
|
||||
generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else if (isCompatibilityStubInDefaultImpls(functionDescriptor, context, jvmDefaultMode)) {
|
||||
FunctionDescriptor compatibility = ((DefaultImplsClassContext) context.getParentContext()).getInterfaceContext()
|
||||
.getAccessorForJvmDefaultCompatibility(functionDescriptor);
|
||||
int flags = AsmUtil.getMethodAsmFlags(functionDescriptor, OwnerKind.DEFAULT_IMPLS, context.getState());
|
||||
assert (flags & Opcodes.ACC_ABSTRACT) == 0 : "Interface method with body should be non-abstract" + functionDescriptor;
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(compatibility, false);
|
||||
|
||||
generateDelegateToStaticMethodBody(
|
||||
true, mv,
|
||||
method.getAsmMethod(),
|
||||
method.getOwner().getInternalName(),
|
||||
true);
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else {
|
||||
FrameMap frameMap = createFrameMap(
|
||||
parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(),
|
||||
@@ -675,32 +625,11 @@ public class FunctionCodegen {
|
||||
Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
|
||||
|
||||
if (functionDescriptor instanceof AnonymousFunctionDescriptor && functionDescriptor.isSuspend()) {
|
||||
functionDescriptor = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
|
||||
functionDescriptor,
|
||||
parentCodegen.state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines),
|
||||
typeMapper.getBindingContext()
|
||||
);
|
||||
functionDescriptor = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(functionDescriptor, typeMapper.getBindingContext());
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> destructuredParametersForSuspendLambda = new ArrayList<>();
|
||||
if (context.getParentContext() instanceof ClosureContext) {
|
||||
if (context instanceof InlineLambdaContext) {
|
||||
CallableMemberDescriptor lambdaDescriptor = context.getContextDescriptor();
|
||||
if (lambdaDescriptor instanceof FunctionDescriptor &&
|
||||
((FunctionDescriptor) lambdaDescriptor).isSuspend()) {
|
||||
destructuredParametersForSuspendLambda.addAll(lambdaDescriptor.getValueParameters());
|
||||
}
|
||||
} else {
|
||||
FunctionDescriptor lambdaDescriptor = ((ClosureContext) context.getParentContext()).getOriginalSuspendLambdaDescriptor();
|
||||
if (lambdaDescriptor != null && functionDescriptor.getName().equals(Name.identifier("doResume"))) {
|
||||
destructuredParametersForSuspendLambda.addAll(lambdaDescriptor.getValueParameters());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generateLocalVariableTable(
|
||||
mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind(), typeMapper,
|
||||
destructuredParametersForSuspendLambda, (functionFakeIndex >= 0 ? 1 : 0) + (lambdaFakeIndex >= 0 ? 1 : 0)
|
||||
(functionFakeIndex >= 0 ? 1 : 0) + (lambdaFakeIndex >= 0 ? 1 : 0)
|
||||
);
|
||||
|
||||
//TODO: it's best to move all below logic to 'generateLocalVariableTable' method
|
||||
@@ -736,16 +665,6 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCompatibilityStubInDefaultImpls(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodContext context,
|
||||
@NotNull JvmDefaultMode jvmDefaultMode
|
||||
) {
|
||||
return OwnerKind.DEFAULT_IMPLS == context.getContextKind() &&
|
||||
hasJvmDefaultAnnotation(functionDescriptor) &&
|
||||
jvmDefaultMode.isCompatibility();
|
||||
}
|
||||
|
||||
private static void generateLocalVariableTable(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmMethodSignature,
|
||||
@@ -755,7 +674,6 @@ public class FunctionCodegen {
|
||||
@NotNull Label methodEnd,
|
||||
@NotNull OwnerKind ownerKind,
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull List<ValueParameterDescriptor> destructuredParametersForSuspendLambda,
|
||||
int shiftForDestructuringVariables
|
||||
) {
|
||||
if (functionDescriptor.isSuspend()) {
|
||||
@@ -774,8 +692,7 @@ public class FunctionCodegen {
|
||||
)
|
||||
),
|
||||
unwrapped,
|
||||
thisType, methodBegin, methodEnd, ownerKind, typeMapper, destructuredParametersForSuspendLambda,
|
||||
shiftForDestructuringVariables
|
||||
thisType, methodBegin, methodEnd, ownerKind, typeMapper, shiftForDestructuringVariables
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -784,7 +701,6 @@ public class FunctionCodegen {
|
||||
generateLocalVariablesForParameters(mv,
|
||||
jvmMethodSignature,
|
||||
thisType, methodBegin, methodEnd, functionDescriptor.getValueParameters(),
|
||||
destructuredParametersForSuspendLambda,
|
||||
AsmUtil.isStaticMethod(ownerKind, functionDescriptor), typeMapper, shiftForDestructuringVariables
|
||||
);
|
||||
}
|
||||
@@ -800,8 +716,8 @@ public class FunctionCodegen {
|
||||
KotlinTypeMapper typeMapper
|
||||
) {
|
||||
generateLocalVariablesForParameters(
|
||||
mv, jvmMethodSignature, thisType, methodBegin, methodEnd, valueParameters, Collections.emptyList(), isStatic, typeMapper,
|
||||
0);
|
||||
mv, jvmMethodSignature, thisType, methodBegin, methodEnd, valueParameters, isStatic, typeMapper, 0
|
||||
);
|
||||
}
|
||||
|
||||
private static void generateLocalVariablesForParameters(
|
||||
@@ -811,7 +727,6 @@ public class FunctionCodegen {
|
||||
@NotNull Label methodBegin,
|
||||
@NotNull Label methodEnd,
|
||||
Collection<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull List<ValueParameterDescriptor> destructuredParametersForSuspendLambda,
|
||||
boolean isStatic,
|
||||
KotlinTypeMapper typeMapper,
|
||||
int shiftForDestructuringVariables
|
||||
@@ -858,19 +773,6 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
shift += shiftForDestructuringVariables;
|
||||
shift = generateDestructuredParameterEntries(mv, methodBegin, methodEnd, valueParameters, typeMapper, shift);
|
||||
shift = generateDestructuredParametersForSuspendLambda(mv, methodBegin, methodEnd, typeMapper, shift, destructuredParametersForSuspendLambda);
|
||||
generateDestructuredParameterEntries(mv, methodBegin, methodEnd, destructuredParametersForSuspendLambda, typeMapper, shift);
|
||||
}
|
||||
|
||||
private static int generateDestructuredParameterEntries(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Label methodBegin,
|
||||
@NotNull Label methodEnd,
|
||||
Collection<ValueParameterDescriptor> valueParameters,
|
||||
KotlinTypeMapper typeMapper,
|
||||
int shift
|
||||
) {
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
List<VariableDescriptor> destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter);
|
||||
if (destructuringVariables == null) continue;
|
||||
@@ -881,26 +783,6 @@ public class FunctionCodegen {
|
||||
shift += type.getSize();
|
||||
}
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
private static int generateDestructuredParametersForSuspendLambda(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Label methodBegin,
|
||||
@NotNull Label methodEnd,
|
||||
KotlinTypeMapper typeMapper,
|
||||
int shift,
|
||||
List<ValueParameterDescriptor> destructuredParametersForSuspendLambda
|
||||
) {
|
||||
for (ValueParameterDescriptor parameter : destructuredParametersForSuspendLambda) {
|
||||
List<VariableDescriptor> destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter);
|
||||
if (destructuringVariables == null) continue;
|
||||
|
||||
Type type = typeMapper.mapType(parameter.getType());
|
||||
mv.visitLocalVariable("$" + joinParameterNames(destructuringVariables), type.getDescriptor(), null, methodBegin, methodEnd, shift);
|
||||
shift += type.getSize();
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
private static String computeParameterName(int i, ValueParameterDescriptor parameter) {
|
||||
@@ -925,7 +807,7 @@ public class FunctionCodegen {
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull MultifileClassFacadeContext context
|
||||
) {
|
||||
generateDelegateToStaticMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName(), false);
|
||||
generateDelegateToStaticMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName());
|
||||
}
|
||||
|
||||
private static void generateDelegateToMethodBody(
|
||||
@@ -993,10 +875,9 @@ public class FunctionCodegen {
|
||||
boolean isStatic,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull String classToDelegateTo,
|
||||
boolean isInterfaceMethodCall
|
||||
@NotNull String classToDelegateTo
|
||||
) {
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, isInterfaceMethodCall);
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, false);
|
||||
}
|
||||
|
||||
private static boolean needIndexForVar(JvmMethodParameterKind kind) {
|
||||
@@ -1176,7 +1057,7 @@ public class FunctionCodegen {
|
||||
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
||||
|
||||
if (isInterface(contextClass) &&
|
||||
!processInterfaceMethod(functionDescriptor, kind, true, false, state.getJvmDefaultMode())) {
|
||||
!processInterfaceMethod(functionDescriptor, kind, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1191,7 +1072,7 @@ public class FunctionCodegen {
|
||||
AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
|
||||
int flags = visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
|
||||
if (!(functionDescriptor instanceof ConstructorDescriptor)) {
|
||||
flags |= ACC_STATIC | ACC_BRIDGE;
|
||||
flags |= ACC_STATIC;
|
||||
}
|
||||
|
||||
Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind);
|
||||
@@ -1221,17 +1102,6 @@ public class FunctionCodegen {
|
||||
generateFacadeDelegateMethodBody(mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
|
||||
endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
else if (isCompatibilityStubInDefaultImpls(functionDescriptor, owner, state.getJvmDefaultMode())) {
|
||||
mv.visitCode();
|
||||
Method interfaceDefaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
generateDelegateToStaticMethodBody(
|
||||
true, mv,
|
||||
interfaceDefaultMethod,
|
||||
typeMapper.mapOwner(functionDescriptor).getInternalName(),
|
||||
true
|
||||
);
|
||||
endVisit(mv, "default method delegation to interface one", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
else {
|
||||
mv.visitCode();
|
||||
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
|
||||
@@ -1423,23 +1293,16 @@ public class FunctionCodegen {
|
||||
Type[] argTypes = bridge.getArgumentTypes();
|
||||
Type[] originalArgTypes = delegateTo.getArgumentTypes();
|
||||
|
||||
List<ParameterDescriptor> allKotlinParameters = new ArrayList<>(argTypes.length);
|
||||
if (descriptor.getExtensionReceiverParameter() != null) allKotlinParameters.add(descriptor.getExtensionReceiverParameter());
|
||||
allKotlinParameters.addAll(descriptor.getValueParameters());
|
||||
|
||||
boolean safeToUseKotlinTypes = allKotlinParameters.size() == argTypes.length;
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
|
||||
|
||||
if (delegateTo.getArgumentTypes().length > 0 && isSpecialBridge) {
|
||||
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes(), typeMapper);
|
||||
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes());
|
||||
}
|
||||
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
KotlinType kotlinType = safeToUseKotlinTypes ? allKotlinParameters.get(i).getType() : null;
|
||||
StackValue.local(reg, argTypes[i], kotlinType).put(originalArgTypes[i], kotlinType, iv);
|
||||
StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argTypes[i].getSize();
|
||||
}
|
||||
@@ -1459,8 +1322,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
KotlinType returnType = descriptor.getReturnType();
|
||||
StackValue.coerce(delegateTo.getReturnType(), returnType, bridge.getReturnType(), returnType, iv);
|
||||
StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
|
||||
iv.areturn(bridge.getReturnType());
|
||||
|
||||
endVisit(mv, "bridge method", origin);
|
||||
@@ -1470,8 +1332,7 @@ public class FunctionCodegen {
|
||||
@NotNull InstructionAdapter iv,
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
@NotNull Type returnType,
|
||||
@Nullable Type[] delegateParameterTypes,
|
||||
@NotNull KotlinTypeMapper typeMapper
|
||||
@Nullable Type[] delegateParameterTypes
|
||||
) {
|
||||
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription typeSafeBarrierDescription =
|
||||
BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
|
||||
@@ -1499,13 +1360,7 @@ public class FunctionCodegen {
|
||||
iv.ifnull(defaultBranch);
|
||||
}
|
||||
else {
|
||||
Type targetBoxedType;
|
||||
if (InlineClassesUtilsKt.isInlineClassType(kotlinType)) {
|
||||
targetBoxedType = typeMapper.mapTypeAsDeclaration(kotlinType);
|
||||
} else {
|
||||
targetBoxedType = boxType(delegateParameterTypes[i]);
|
||||
}
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType, targetBoxedType);
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType, boxType(delegateParameterTypes[i]));
|
||||
iv.ifeq(defaultBranch);
|
||||
}
|
||||
}
|
||||
@@ -1621,21 +1476,18 @@ public class FunctionCodegen {
|
||||
public static boolean processInterfaceMethod(
|
||||
@NotNull CallableMemberDescriptor memberDescriptor,
|
||||
@NotNull OwnerKind kind,
|
||||
boolean isDefault,
|
||||
boolean isSynthetic,
|
||||
JvmDefaultMode mode
|
||||
boolean isDefaultOrSynthetic
|
||||
) {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
|
||||
containingDeclaration;
|
||||
|
||||
if (hasJvmDefaultAnnotation(memberDescriptor)) {
|
||||
return (kind != OwnerKind.DEFAULT_IMPLS && !isSynthetic) ||
|
||||
(kind == OwnerKind.DEFAULT_IMPLS && (isSynthetic || mode.isCompatibility()));
|
||||
return kind != OwnerKind.DEFAULT_IMPLS;
|
||||
} else {
|
||||
switch (kind) {
|
||||
case DEFAULT_IMPLS: return true;
|
||||
case IMPLEMENTATION: return !Visibilities.isPrivate(memberDescriptor.getVisibility()) && !isDefault && !isSynthetic;
|
||||
case IMPLEMENTATION: return !Visibilities.isPrivate(memberDescriptor.getVisibility()) && !isDefaultOrSynthetic;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
|
||||
@@ -573,9 +574,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.ifne(ne);
|
||||
}
|
||||
else {
|
||||
StackValue value =
|
||||
genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType));
|
||||
value.put(Type.BOOLEAN_TYPE, iv);
|
||||
if (isPrimitive(asmType)) {
|
||||
StackValue value = StackValue.cmp(KtTokens.EQEQ, asmType, StackValue.onStack(asmType), StackValue.onStack(asmType));
|
||||
value.put(Type.BOOLEAN_TYPE, iv);
|
||||
} else {
|
||||
Type owner =
|
||||
DescriptorUtils.isInterface(propertyDescriptor.getType().getConstructor().getDeclarationDescriptor())
|
||||
? AsmTypes.OBJECT_TYPE
|
||||
: asmType;
|
||||
iv.invokevirtual(owner.getInternalName(), "equals",
|
||||
Type.getMethodDescriptor(Type.BOOLEAN_TYPE, AsmTypes.OBJECT_TYPE), false);
|
||||
}
|
||||
iv.ifeq(ne);
|
||||
}
|
||||
}
|
||||
@@ -616,7 +625,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.ifnull(ifNull);
|
||||
}
|
||||
|
||||
genHashCode(mv, iv, asmType, state.getTarget());
|
||||
genHashCode(mv, iv, asmType, state.getTarget(),
|
||||
DescriptorUtils.isInterface(propertyDescriptor.getType().getConstructor().getDeclarationDescriptor()));
|
||||
|
||||
if (ifNull != null) {
|
||||
Label end = new Label();
|
||||
@@ -1405,7 +1415,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateTraitMethods() {
|
||||
if (isJvmInterface(descriptor)) return;
|
||||
if (isInterface(descriptor)) return;
|
||||
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||
FunctionDescriptor interfaceFun = entry.getKey();
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import java.util.*
|
||||
|
||||
interface InnerClassConsumer {
|
||||
@@ -37,14 +36,14 @@ interface InnerClassConsumer {
|
||||
if (defaultImpls) {
|
||||
if (DescriptorUtils.isLocal(descriptor)) return null
|
||||
val classDescriptorImpl = ClassDescriptorImpl(
|
||||
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
||||
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false, LockBasedStorageManager.NO_LOCKS
|
||||
)
|
||||
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
||||
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false)
|
||||
|
||||
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
|
||||
return classDescriptorImpl
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return if (DescriptorUtils.isTopLevelDeclaration(descriptor)) null else descriptor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,17 +72,21 @@ class InterfaceImplBodyCodegen(
|
||||
// If implementation is a default interface method (JVM 8 only)
|
||||
if (implementation.isDefinitelyNotDefaultImplsMethod()) continue
|
||||
|
||||
// We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body
|
||||
val copy = memberDescriptor.copy(memberDescriptor.containingDeclaration, Modality.OPEN, memberDescriptor.visibility,
|
||||
CallableMemberDescriptor.Kind.DECLARATION, true)
|
||||
|
||||
if (memberDescriptor is FunctionDescriptor) {
|
||||
generateDelegationToSuperDefaultImpls(memberDescriptor, implementation as FunctionDescriptor)
|
||||
generateDelegationToSuperDefaultImpls(copy as FunctionDescriptor, implementation as FunctionDescriptor)
|
||||
}
|
||||
else if (memberDescriptor is PropertyDescriptor) {
|
||||
implementation as PropertyDescriptor
|
||||
val getter = memberDescriptor.getter
|
||||
val getter = (copy as PropertyDescriptor).getter
|
||||
val implGetter = implementation.getter
|
||||
if (getter != null && implGetter != null) {
|
||||
generateDelegationToSuperDefaultImpls(getter, implGetter)
|
||||
}
|
||||
val setter = memberDescriptor.setter
|
||||
val setter = copy.setter
|
||||
val implSetter = implementation.setter
|
||||
if (setter != null && implSetter != null) {
|
||||
generateDelegationToSuperDefaultImpls(setter, implSetter)
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
interface JvmBackendClassResolver {
|
||||
fun resolveToClassDescriptors(type: Type): List<ClassDescriptor>
|
||||
|
||||
object Dummy : JvmBackendClassResolver {
|
||||
override fun resolveToClassDescriptors(type: Type): List<ClassDescriptor> = emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JvmBackendClassResolverForModuleWithDependencies(
|
||||
private val moduleDescriptor: ModuleDescriptor
|
||||
) : JvmBackendClassResolver {
|
||||
|
||||
override fun resolveToClassDescriptors(type: Type): List<ClassDescriptor> {
|
||||
if (type.sort != Type.OBJECT) return emptyList()
|
||||
|
||||
val className = type.className
|
||||
val lastDotIndex = className.lastIndexOf('.')
|
||||
val packageFQN = if (lastDotIndex >= 0) FqName(className.substring(0, lastDotIndex)) else FqName.ROOT
|
||||
val classRelativeNameWithDollars = if (lastDotIndex >= 0) className.substring(lastDotIndex + 1) else className
|
||||
val classFQN = FqName(classRelativeNameWithDollars.replace('$', '.'))
|
||||
val platformClass = moduleDescriptor.findClassAcrossModuleDependencies(ClassId(packageFQN, classFQN, false)) ?: return emptyList()
|
||||
|
||||
return JavaToKotlinClassMap.mapPlatformClass(platformClass) + platformClass
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user