Merge commits from both masters and update to 1.5.0-dev-500 compiler

Kotlin/Native base commit: ed1035eb82d63dde60823852276901aaeacb644b
This commit is contained in:
Stanislav Erokhin
2020-12-14 15:37:29 +01:00
3931 changed files with 108567 additions and 40072 deletions
+3 -6
View File
@@ -1,7 +1,4 @@
201
202 202
203_202 201
193 as41_201
as40_193 as42
as41
as42_202
+1
View File
@@ -10,6 +10,7 @@
<w>commonizers</w> <w>commonizers</w>
<w>commonizes</w> <w>commonizes</w>
<w>commonizing</w> <w>commonizing</w>
<w>interop</w>
<w>jetbrains</w> <w>jetbrains</w>
<w>konan</w> <w>konan</w>
<w>kotlinx</w> <w>kotlinx</w>
+1304
View File
File diff suppressed because it is too large Load Diff
+2697
View File
File diff suppressed because it is too large Load Diff
+2042
View File
File diff suppressed because it is too large Load Diff
+3879
View File
File diff suppressed because it is too large Load Diff
+143 -10045
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -5,7 +5,10 @@
# Kotlin Programming Language # Kotlin Programming Language
Welcome to [Kotlin](https://kotlinlang.org/)! Some handy links: Welcome to [Kotlin](https://kotlinlang.org/)!
It is an open-source, statically typed programming language supported and developed by [JetBrains](https://www.jetbrains.com/) and open-source contributors.
Some handy links:
* [Kotlin Site](https://kotlinlang.org/) * [Kotlin Site](https://kotlinlang.org/)
* [Getting Started Guide](https://kotlinlang.org/docs/tutorials/getting-started.html) * [Getting Started Guide](https://kotlinlang.org/docs/tutorials/getting-started.html)
+4 -2
View File
@@ -188,7 +188,7 @@ extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion
extra["versions.ktor-network"] = "1.0.1" extra["versions.ktor-network"] = "1.0.1"
if (!project.hasProperty("versions.kotlin-native")) { if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.4.30-dev-17200" extra["versions.kotlin-native"] = "1.4.30-dev-17395"
} }
val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled) val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled)
@@ -467,7 +467,7 @@ allprojects {
} }
tasks.withType<Test> { tasks.withType<Test> {
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KT-37089") { true } outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KTI-112") { !isTestDistributionEnabled() }
} }
normalization { normalization {
@@ -854,6 +854,8 @@ tasks {
register("kaptIdeTest") { register("kaptIdeTest") {
dependsOn(":kotlin-annotation-processing:test") dependsOn(":kotlin-annotation-processing:test")
dependsOn(":kotlin-annotation-processing-base:test")
dependsOn(":kotlin-annotation-processing-cli:test")
} }
register("gradleIdeTest") { register("gradleIdeTest") {
+1
View File
@@ -114,6 +114,7 @@ dependencies {
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5") implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")
implementation("org.gradle:test-retry-gradle-plugin:1.1.9") implementation("org.gradle:test-retry-gradle-plugin:1.1.9")
implementation("com.gradle.enterprise:test-distribution-gradle-plugin:1.2.1")
} }
samWithReceiver { samWithReceiver {
+2 -1
View File
@@ -54,11 +54,12 @@ var Project.javaHome: String?
extra["javaHome"] = v extra["javaHome"] = v
} }
fun Project.generator(fqName: String, sourceSet: SourceSet? = null) = smartJavaExec { fun Project.generator(fqName: String, sourceSet: SourceSet? = null, configure: JavaExec.() -> Unit = {}) = smartJavaExec {
classpath = (sourceSet ?: testSourceSet).runtimeClasspath classpath = (sourceSet ?: testSourceSet).runtimeClasspath
mainClass.set(fqName) mainClass.set(fqName)
workingDir = rootDir workingDir = rootDir
systemProperty("line.separator", "\n") systemProperty("line.separator", "\n")
configure()
} }
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let { fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
import com.gradle.enterprise.gradleplugin.testdistribution.TestDistributionExtension
import org.gradle.api.tasks.testing.Test
import org.gradle.internal.os.OperatingSystem
fun Test.configureTestDistribution(configure: TestDistributionExtension.() -> Unit = {}) {
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
val testDistributionEnabled = project.findProperty("kotlin.build.test.distribution.enabled")?.toString()?.toBoolean()
?: isTeamcityBuild
useJUnitPlatform()
extensions.configure(TestDistributionExtension::class.java) {
enabled.set(testDistributionEnabled)
maxRemoteExecutors.set(20)
if (isTeamcityBuild) {
requirements.set(setOf("os=${OperatingSystem.current().familyName}"))
} else {
maxLocalExecutors.set(0)
}
configure()
}
}
fun Test.isTestDistributionEnabled(): Boolean =
extensions.findByType(TestDistributionExtension::class.java)?.enabled?.orNull ?: false
@@ -269,8 +269,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
continue continue
} }
val fullFileText = val fullFileText = FileUtil.loadFile(file, true)
FileUtil.loadFile(file, true).replace("COROUTINES_PACKAGE", "kotlin.coroutines")
if (fullFileText.contains("// WITH_COROUTINES")) { if (fullFileText.contains("// WITH_COROUTINES")) {
if (fullFileText.contains("kotlin.coroutines.experimental")) continue if (fullFileText.contains("kotlin.coroutines.experimental")) continue
@@ -317,7 +316,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
} }
private fun createTestFiles(file: File, expectedText: String): List<KotlinBaseTest.TestFile> = private fun createTestFiles(file: File, expectedText: String): List<KotlinBaseTest.TestFile> =
CodegenTestCase.createTestFilesFromFile(file, expectedText, "kotlin.coroutines", false, TargetBackend.JVM) CodegenTestCase.createTestFilesFromFile(file, expectedText, false, TargetBackend.JVM)
companion object { companion object {
const val GRADLE_VERSION = "5.6.4" // update GRADLE_SHA_256 on change const val GRADLE_VERSION = "5.6.4" // update GRADLE_SHA_256 on change
@@ -26,13 +26,13 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.*;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
public abstract class AbstractClassBuilder implements ClassBuilder { public abstract class AbstractClassBuilder implements ClassBuilder {
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {}; protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {};
public static final RecordComponentVisitor EMPTY_RECORD_VISITOR = new RecordComponentVisitor(Opcodes.API_VERSION) {};
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {}; protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
private String thisName; private String thisName;
@@ -91,6 +91,16 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
return visitor; return visitor;
} }
@NotNull
@Override
public RecordComponentVisitor newRecordComponent(@NotNull String name, @NotNull String desc, @Nullable String signature) {
RecordComponentVisitor visitor = getVisitor().visitRecordComponent(name, desc, signature);
if (visitor == null) {
return EMPTY_RECORD_VISITOR;
}
return visitor;
}
@Override @Override
@NotNull @NotNull
public JvmSerializationBindings getSerializationBindings() { public JvmSerializationBindings getSerializationBindings() {
@@ -0,0 +1,158 @@
/*
* 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.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SMAPBuilder;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
import java.util.List;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
public abstract class AbstractClassBuilder implements ClassBuilder {
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {};
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
private String thisName;
private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
private String sourceName;
private String debugInfo;
public static class Concrete extends AbstractClassBuilder {
private final ClassVisitor v;
public Concrete(@NotNull ClassVisitor v) {
this.v = v;
}
@Override
@NotNull
public ClassVisitor getVisitor() {
return v;
}
}
@Override
@NotNull
public FieldVisitor newField(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable Object value
) {
FieldVisitor visitor = getVisitor().visitField(access, name, desc, signature, value);
if (visitor == null) {
return EMPTY_FIELD_VISITOR;
}
return visitor;
}
@Override
@NotNull
public MethodVisitor newMethod(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable String[] exceptions
) {
MethodVisitor visitor = getVisitor().visitMethod(access, name, desc, signature, exceptions);
if (visitor == null) {
return EMPTY_METHOD_VISITOR;
}
return visitor;
}
@Override
@NotNull
public JvmSerializationBindings getSerializationBindings() {
return serializationBindings;
}
@Override
@NotNull
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
return getVisitor().visitAnnotation(desc, visible);
}
@Override
public void done() {
getVisitor().visitSource(sourceName, debugInfo);
getVisitor().visitEnd();
}
@Override
public void defineClass(
@Nullable PsiElement origin,
int version,
int access,
@NotNull String name,
@Nullable String signature,
@NotNull String superName,
@NotNull String[] interfaces
) {
thisName = name;
getVisitor().visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visitSource(@NotNull String name, @Nullable String debug) {
assert sourceName == null || sourceName.equals(name) : "inconsistent file name: " + sourceName + " vs " + name;
sourceName = name;
debugInfo = debug;
}
@Override
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
if (!GENERATE_SMAP) return;
List<FileMapping> fileMappings = smap.getResultMappings();
if (fileMappings.isEmpty()) return;
visitSource(fileMappings.get(0).getName(), SMAPBuilder.INSTANCE.build(fileMappings, backwardsCompatibleSyntax));
}
@Override
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
getVisitor().visitOuterClass(owner, name, desc);
}
@Override
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
getVisitor().visitInnerClass(name, outerName, innerName, access);
}
@Override
@NotNull
public String getThisName() {
assert thisName != null : "This name isn't set";
return thisName;
}
}
@@ -29,7 +29,8 @@ class CallableMethod(
override val generateCalleeType: Type?, override val generateCalleeType: Type?,
override val returnKotlinType: KotlinType?, override val returnKotlinType: KotlinType?,
val isInterfaceMethod: Boolean, val isInterfaceMethod: Boolean,
private val isDefaultMethodInInterface: Boolean private val isDefaultMethodInInterface: Boolean,
private val boxInlineClassBeforeInvoke: Boolean
) : Callable { ) : Callable {
private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod) private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod)
@@ -49,6 +50,9 @@ class CallableMethod(
get() = getAsmMethod().argumentTypes get() = getAsmMethod().argumentTypes
override fun genInvokeInstruction(v: InstructionAdapter) { override fun genInvokeInstruction(v: InstructionAdapter) {
if (boxInlineClassBeforeInvoke) {
StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v)
}
v.visitMethodInsn( v.visitMethodInsn(
invokeOpcode, invokeOpcode,
owner.internalName, owner.internalName,
@@ -19,14 +19,10 @@ package org.jetbrains.kotlin.codegen;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SourceMapper; import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings; import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor; import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
public interface ClassBuilder { public interface ClassBuilder {
@NotNull @NotNull
@@ -49,6 +45,12 @@ public interface ClassBuilder {
@Nullable String[] exceptions @Nullable String[] exceptions
); );
@NotNull RecordComponentVisitor newRecordComponent(
@NotNull String name,
@NotNull String desc,
@Nullable String signature
);
@NotNull @NotNull
JvmSerializationBindings getSerializationBindings(); JvmSerializationBindings getSerializationBindings();
@@ -0,0 +1,79 @@
/*
* 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.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
public interface ClassBuilder {
@NotNull
FieldVisitor newField(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable Object value
);
@NotNull
MethodVisitor newMethod(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable String[] exceptions
);
@NotNull
JvmSerializationBindings getSerializationBindings();
@NotNull
AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible);
void done();
@NotNull
ClassVisitor getVisitor();
void defineClass(
@Nullable PsiElement origin,
int version,
int access,
@NotNull String name,
@Nullable String signature,
@NotNull String superName,
@NotNull String[] interfaces
);
void visitSource(@NotNull String name, @Nullable String debug);
void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax);
void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc);
void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access);
@NotNull
String getThisName();
}
@@ -267,7 +267,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
if (classDescriptor.kind != ClassKind.CLASS) return false if (classDescriptor.kind != ClassKind.CLASS) return false
if (classOrObject.isLocal) return false if (classOrObject.isLocal) return false
if (classDescriptor.isInline) return false if (classDescriptor.isInlineClass()) return false
if (shouldHideConstructorDueToInlineClassTypeValueParameters(constructorDescriptor)) return false if (shouldHideConstructorDueToInlineClassTypeValueParameters(constructorDescriptor)) return false
if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false
@@ -19,14 +19,10 @@ package org.jetbrains.kotlin.codegen;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SourceMapper; import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings; import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor; import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
public abstract class DelegatingClassBuilder implements ClassBuilder { public abstract class DelegatingClassBuilder implements ClassBuilder {
@NotNull @NotNull
@@ -58,6 +54,14 @@ public abstract class DelegatingClassBuilder implements ClassBuilder {
return getDelegate().newMethod(origin, access, name, desc, signature, exceptions); return getDelegate().newMethod(origin, access, name, desc, signature, exceptions);
} }
@NotNull
@Override
public RecordComponentVisitor newRecordComponent(
@NotNull String name, @NotNull String desc, @Nullable String signature
) {
return getDelegate().newRecordComponent(name, desc, signature);
}
@NotNull @NotNull
@Override @Override
public JvmSerializationBindings getSerializationBindings() { public JvmSerializationBindings getSerializationBindings() {
@@ -0,0 +1,118 @@
/*
* 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.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
public abstract class DelegatingClassBuilder implements ClassBuilder {
@NotNull
protected abstract ClassBuilder getDelegate();
@NotNull
@Override
public FieldVisitor newField(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable Object value
) {
return getDelegate().newField(origin, access, name, desc, signature, value);
}
@NotNull
@Override
public MethodVisitor newMethod(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable String[] exceptions
) {
return getDelegate().newMethod(origin, access, name, desc, signature, exceptions);
}
@NotNull
@Override
public JvmSerializationBindings getSerializationBindings() {
return getDelegate().getSerializationBindings();
}
@NotNull
@Override
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
return getDelegate().newAnnotation(desc, visible);
}
@Override
public void done() {
getDelegate().done();
}
@NotNull
@Override
public ClassVisitor getVisitor() {
return getDelegate().getVisitor();
}
@Override
public void defineClass(
@Nullable PsiElement origin,
int version,
int access,
@NotNull String name,
@Nullable String signature,
@NotNull String superName,
@NotNull String[] interfaces
) {
getDelegate().defineClass(origin, version, access, name, signature, superName, interfaces);
}
@Override
public void visitSource(@NotNull String name, @Nullable String debug) {
getDelegate().visitSource(name, debug);
}
@Override
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
getDelegate().visitSMAP(smap, backwardsCompatibleSyntax);
}
@Override
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
getDelegate().visitOuterClass(owner, name, desc);
}
@Override
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
getDelegate().visitInnerClass(name, outerName, innerName, access);
}
@NotNull
@Override
public String getThisName() {
return getDelegate().getThisName();
}
}
@@ -216,7 +216,7 @@ public class DescriptorAsmUtil {
private static boolean isInlineClassWrapperConstructor(@NotNull FunctionDescriptor functionDescriptor, @Nullable OwnerKind kind) { private static boolean isInlineClassWrapperConstructor(@NotNull FunctionDescriptor functionDescriptor, @Nullable OwnerKind kind) {
if (!(functionDescriptor instanceof ConstructorDescriptor)) return false; if (!(functionDescriptor instanceof ConstructorDescriptor)) return false;
ClassDescriptor classDescriptor = ((ConstructorDescriptor) functionDescriptor).getConstructedClass(); ClassDescriptor classDescriptor = ((ConstructorDescriptor) functionDescriptor).getConstructedClass();
return classDescriptor.isInline() && kind == OwnerKind.IMPLEMENTATION; return InlineClassesUtilsKt.isInlineClass(classDescriptor) && kind == OwnerKind.IMPLEMENTATION;
} }
public static int getCommonCallableFlags(FunctionDescriptor functionDescriptor, @NotNull GenerationState state) { public static int getCommonCallableFlags(FunctionDescriptor functionDescriptor, @NotNull GenerationState state) {
@@ -559,7 +559,7 @@ public class DescriptorAsmUtil {
if (receiverKotlinType.isMarkedNullable()) return null; if (receiverKotlinType.isMarkedNullable()) return null;
DeclarationDescriptor receiverTypeDescriptor = receiverKotlinType.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor receiverTypeDescriptor = receiverKotlinType.getConstructor().getDeclarationDescriptor();
assert receiverTypeDescriptor instanceof ClassDescriptor && ((ClassDescriptor) receiverTypeDescriptor).isInline() : assert receiverTypeDescriptor != null && InlineClassesUtilsKt.isInlineClass(receiverTypeDescriptor) :
"Inline class type expected: " + receiverKotlinType; "Inline class type expected: " + receiverKotlinType;
ClassDescriptor receiverClassDescriptor = (ClassDescriptor) receiverTypeDescriptor; ClassDescriptor receiverClassDescriptor = (ClassDescriptor) receiverTypeDescriptor;
FunctionDescriptor toStringDescriptor = receiverClassDescriptor.getUnsubstitutedMemberScope() FunctionDescriptor toStringDescriptor = receiverClassDescriptor.getUnsubstitutedMemberScope()
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
@@ -55,6 +56,13 @@ class ErasedInlineClassBodyCodegen(
generateUnboxMethod() generateUnboxMethod()
generateFunctionsFromAny() generateFunctionsFromAny()
generateSpecializedEqualsStub() generateSpecializedEqualsStub()
generateJvmInlineAnnotation()
}
private fun generateJvmInlineAnnotation() {
if (descriptor.isInline) {
v.newAnnotation(JVM_INLINE_ANNOTATION_FQ_NAME.topLevelClassAsmType().descriptor, true).visitEnd()
}
} }
private fun generateFunctionsFromAny() { private fun generateFunctionsFromAny() {
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil; import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil;
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
import org.jetbrains.kotlin.load.kotlin.DescriptorBasedTypeSignatureMappingKt; import org.jetbrains.kotlin.load.kotlin.DescriptorBasedTypeSignatureMappingKt;
import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt; import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
@@ -375,22 +376,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
if (!functionDescriptor.isSuspend()) return stackValue; if (!functionDescriptor.isSuspend()) return stackValue;
// When we call suspend operator fun invoke using parens, we cannot box receiver as return type inline class
if (resolvedCall instanceof VariableAsFunctionResolvedCall &&
functionDescriptor.isOperator() && functionDescriptor.getName().getIdentifier().equals("invoke")
) return stackValue;
KotlinType unboxedInlineClass = CoroutineCodegenUtilKt KotlinType unboxedInlineClass = CoroutineCodegenUtilKt
.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(functionDescriptor, typeMapper); .originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(functionDescriptor, typeMapper);
StackValue stackValueToWrap = stackValue; StackValue stackValueToWrap = stackValue;
KotlinType originalKotlinType; KotlinType originalKotlinType = unboxedInlineClass != null ? unboxedInlineClass : stackValueToWrap.kotlinType;
if (unboxedInlineClass != null) { Type originalType = unboxedInlineClass != null ? typeMapper.mapType(unboxedInlineClass) : stackValueToWrap.type;
originalKotlinType = unboxedInlineClass;
} else {
originalKotlinType = stackValueToWrap.kotlinType;
}
Type originalType;
if (unboxedInlineClass != null) {
originalType = typeMapper.mapType(unboxedInlineClass);
} else {
originalType = stackValueToWrap.type;
}
stackValue = new StackValue(originalType, originalKotlinType) { stackValue = new StackValue(originalType, originalKotlinType) {
@Override @Override
@@ -1195,7 +1191,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ClassDescriptor captureThis = closure.getCapturedOuterClassDescriptor(); ClassDescriptor captureThis = closure.getCapturedOuterClassDescriptor();
if (captureThis != null) { if (captureThis != null) {
StackValue thisOrOuter = generateThisOrOuter(captureThis, false); StackValue thisOrOuter = generateThisOrOuter(captureThis, false);
assert !isPrimitive(thisOrOuter.type) || captureThis.isInline() : assert !isPrimitive(thisOrOuter.type) || InlineClassesUtilsKt.isInlineClass(captureThis) :
"This or outer for " + captureThis + " should be non-primitive: " + thisOrOuter.type; "This or outer for " + captureThis + " should be non-primitive: " + thisOrOuter.type;
callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++); callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++);
} }
@@ -2409,9 +2405,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
fieldName = KotlinTypeMapper.mapDefaultFieldName(propertyDescriptor, isDelegatedProperty); fieldName = KotlinTypeMapper.mapDefaultFieldName(propertyDescriptor, isDelegatedProperty);
} }
KotlinType propertyType = propertyDescriptor.getOriginal().getType();
if (propertyDescriptor instanceof JavaPropertyDescriptor && InlineClassesUtilsKt.isInlineClassType(propertyType)) {
propertyType = TypeUtils.makeNullable(propertyType);
}
return StackValue.property( return StackValue.property(
propertyDescriptor, backingFieldOwner, propertyDescriptor, backingFieldOwner,
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyType),
isStaticBackingField, fieldName, callableGetter, callableSetter, receiver, this, resolvedCall, skipLateinitAssertion, isStaticBackingField, fieldName, callableGetter, callableSetter, receiver, this, resolvedCall, skipLateinitAssertion,
isDelegatedProperty && forceField ? delegateType : null isDelegatedProperty && forceField ? delegateType : null
); );
@@ -4380,6 +4381,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Type exprType = expressionType(expr); Type exprType = expressionType(expr);
KotlinType exprKotlinType = kotlinType(expr); KotlinType exprKotlinType = kotlinType(expr);
if (exprKotlinType != null && InlineClassesUtilsKt.isInlineClassType(exprKotlinType) &&
FlexibleTypesKt.isNullabilityFlexible(exprKotlinType)) {
exprKotlinType = TypeUtils.makeNullable(exprKotlinType);
}
StackValue value; StackValue value;
if (compileTimeConstant != null) { if (compileTimeConstant != null) {
value = StackValue.constant(compileTimeConstant.getValue(), exprType, exprKotlinType); value = StackValue.constant(compileTimeConstant.getValue(), exprType, exprKotlinType);
@@ -4835,7 +4840,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter(); ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter();
ClassDescriptor containingDeclaration = constructor.getContainingDeclaration(); ClassDescriptor containingDeclaration = constructor.getContainingDeclaration();
if (!containingDeclaration.isInline()) { if (!InlineClassesUtilsKt.isInlineClass(containingDeclaration)) {
v.anew(objectType); v.anew(objectType);
v.dup(); v.dup();
} }
@@ -1221,7 +1221,12 @@ public class FunctionCodegen {
// 'null' because the "could not find expected declaration" error has been already reported in isDefaultNeeded earlier // 'null' because the "could not find expected declaration" error has been already reported in isDefaultNeeded earlier
List<ValueParameterDescriptor> valueParameters = List<ValueParameterDescriptor> valueParameters =
CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null); functionDescriptor.isSuspend()
? CollectionsKt.plus(
CodegenUtil.getFunctionParametersForDefaultValueGeneration(
CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(functionDescriptor), null),
CollectionsKt.last(functionDescriptor.getValueParameters()))
: CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null);
boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor); boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic); FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic);
@@ -1589,7 +1594,7 @@ public class FunctionCodegen {
// When delegating to inline class, we invoke static implementation method // When delegating to inline class, we invoke static implementation method
// that takes inline class underlying value as 1st argument. // that takes inline class underlying value as 1st argument.
int toArgsShift = toClass.isInline() ? 1 : 0; int toArgsShift = InlineClassesUtilsKt.isInlineClass(toClass) ? 1 : 0;
int reg = 1; int reg = 1;
for (int i = 0; i < argTypes.length; ++i) { for (int i = 0; i < argTypes.length; ++i) {
@@ -1609,7 +1614,7 @@ public class FunctionCodegen {
if (toClass.getKind() == ClassKind.INTERFACE) { if (toClass.getKind() == ClassKind.INTERFACE) {
iv.invokeinterface(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor()); iv.invokeinterface(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
} }
else if (toClass.isInline()) { else if (InlineClassesUtilsKt.isInlineClass(toClass)) {
iv.invokestatic(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor(), false); iv.invokestatic(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor(), false);
} }
else { else {
@@ -84,7 +84,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
String toStringMethodDesc = getToStringDesc(); String toStringMethodDesc = getToStringDesc();
MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), toStringMethodName, toStringMethodDesc, null, null); MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), toStringMethodName, toStringMethodDesc, null, null);
if (!isInErasedInlineClass && classDescriptor.isInline()) { if (!isInErasedInlineClass && InlineClassesUtilsKt.isInlineClass(classDescriptor)) {
FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper); FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper);
return; return;
} }
@@ -161,7 +161,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
String hashCodeMethodDesc = getHashCodeDesc(); String hashCodeMethodDesc = getHashCodeDesc();
MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), hashCodeMethodName, hashCodeMethodDesc, null, null); MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), hashCodeMethodName, hashCodeMethodDesc, null, null);
if (!isInErasedInlineClass && classDescriptor.isInline()) { if (!isInErasedInlineClass && InlineClassesUtilsKt.isInlineClass(classDescriptor)) {
FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper); FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper);
return; return;
} }
@@ -233,7 +233,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
String equalsMethodDesc = getEqualsDesc(); String equalsMethodDesc = getEqualsDesc();
MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), equalsMethodName, equalsMethodDesc, null, null); MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), equalsMethodName, equalsMethodDesc, null, null);
if (!isInErasedInlineClass && classDescriptor.isInline()) { if (!isInErasedInlineClass && InlineClassesUtilsKt.isInlineClass(classDescriptor)) {
FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper); FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper);
return; return;
} }
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
@@ -221,6 +222,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
access |= ACC_ENUM; access |= ACC_ENUM;
} }
if (JvmAnnotationUtilKt.isJvmRecord(descriptor)) {
access |= ACC_RECORD;
}
v.defineClass( v.defineClass(
myClass.getPsiOrParent(), myClass.getPsiOrParent(),
state.getClassFileVersion(), state.getClassFileVersion(),
@@ -260,7 +265,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override @Override
protected void generateErasedInlineClassIfNeeded() { protected void generateErasedInlineClassIfNeeded() {
if (!(myClass instanceof KtClass)) return; if (!(myClass instanceof KtClass)) return;
if (!descriptor.isInline()) return; if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
ClassContext erasedInlineClassContext = context.intoWrapperForErasedInlineClass(descriptor, state); ClassContext erasedInlineClassContext = context.intoWrapperForErasedInlineClass(descriptor, state);
new ErasedInlineClassBodyCodegen((KtClass) myClass, erasedInlineClassContext, v, state, this).generate(); new ErasedInlineClassBodyCodegen((KtClass) myClass, erasedInlineClassContext, v, state, this).generate();
@@ -269,7 +274,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override @Override
protected void generateUnboxMethodForInlineClass() { protected void generateUnboxMethodForInlineClass() {
if (!(myClass instanceof KtClass)) return; if (!(myClass instanceof KtClass)) return;
if (!descriptor.isInline()) return; if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
Type ownerType = typeMapper.mapClass(descriptor); Type ownerType = typeMapper.mapClass(descriptor);
ValueParameterDescriptor inlinedValue = InlineClassesUtilsKt.underlyingRepresentation(this.descriptor); ValueParameterDescriptor inlinedValue = InlineClassesUtilsKt.underlyingRepresentation(this.descriptor);
@@ -450,7 +455,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
try { try {
lookupConstructorExpressionsInClosureIfPresent(); lookupConstructorExpressionsInClosureIfPresent();
constructorCodegen.generatePrimaryConstructor(delegationFieldsInfo, superClassAsmType); constructorCodegen.generatePrimaryConstructor(delegationFieldsInfo, superClassAsmType);
if (!descriptor.isInline() && !(descriptor instanceof SyntheticClassOrObjectDescriptor)) { if (!InlineClassesUtilsKt.isInlineClass(descriptor) && !(descriptor instanceof SyntheticClassOrObjectDescriptor)) {
// Synthetic classes does not have declarations for secondary constructors // Synthetic classes does not have declarations for secondary constructors
for (ClassConstructorDescriptor secondaryConstructor : DescriptorUtilsKt.getSecondaryConstructors(descriptor)) { for (ClassConstructorDescriptor secondaryConstructor : DescriptorUtilsKt.getSecondaryConstructors(descriptor)) {
constructorCodegen.generateSecondaryConstructor(secondaryConstructor, superClassAsmType); constructorCodegen.generateSecondaryConstructor(secondaryConstructor, superClassAsmType);
@@ -552,7 +557,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateFunctionsFromAnyForInlineClasses() { private void generateFunctionsFromAnyForInlineClasses() {
if (!descriptor.isInline()) return; if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
if (!(myClass instanceof KtClassOrObject)) return; if (!(myClass instanceof KtClassOrObject)) return;
new FunctionsFromAnyGeneratorImpl( new FunctionsFromAnyGeneratorImpl(
(KtClassOrObject) myClass, bindingContext, descriptor, classAsmType, context, v, state (KtClassOrObject) myClass, bindingContext, descriptor, classAsmType, context, v, state
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt; import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
@@ -435,9 +436,10 @@ public class PropertyCodegen {
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, new Pair<>(type, name)); v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, new Pair<>(type, name));
if (isBackingFieldOwner) { if (isBackingFieldOwner) {
String signature = isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor);
FieldVisitor fv = builder.newField( FieldVisitor fv = builder.newField(
JvmDeclarationOriginKt.OtherOrigin(propertyDescriptor), modifiers, name, type.getDescriptor(), JvmDeclarationOriginKt.OtherOrigin(propertyDescriptor), modifiers, name, type.getDescriptor(),
isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor), defaultValue signature, defaultValue
); );
if (annotatedField != null) { if (annotatedField != null) {
@@ -450,6 +452,10 @@ public class PropertyCodegen {
AnnotationCodegen.forField(fv, memberCodegen, state, skipNullabilityAnnotations) AnnotationCodegen.forField(fv, memberCodegen, state, skipNullabilityAnnotations)
.genAnnotations(annotatedField, type, propertyDescriptor.getType(), null, additionalVisibleAnnotations); .genAnnotations(annotatedField, type, propertyDescriptor.getType(), null, additionalVisibleAnnotations);
} }
if (propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor && JvmAnnotationUtilKt.isJvmRecord((ClassDescriptor) propertyDescriptor.getContainingDeclaration())) {
builder.newRecordComponent(name, type.getDescriptor(), signature);
}
} }
} }
@@ -0,0 +1,680 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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 com.intellij.psi.PsiElement;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
import org.jetbrains.kotlin.codegen.context.MultifileClassFacadeContext;
import org.jetbrains.kotlin.codegen.context.MultifileClassPartContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorFactory;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getDeprecatedAccessFlag;
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getVisibilityForBackingField;
import static org.jetbrains.kotlin.codegen.FunctionCodegen.processInterfaceMethod;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*;
import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND;
import static org.jetbrains.kotlin.fileClasses.JvmFileClassUtilKt.isTopLevelInJvmMultifileClass;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.K_PROPERTY_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmFieldAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmSyntheticAnnotation;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PropertyCodegen {
private final GenerationState state;
private final ClassBuilder v;
private final FunctionCodegen functionCodegen;
private final KotlinTypeMapper typeMapper;
private final BindingContext bindingContext;
private final FieldOwnerContext context;
private final MemberCodegen<?> memberCodegen;
private final OwnerKind kind;
public PropertyCodegen(
@NotNull FieldOwnerContext context,
@NotNull ClassBuilder v,
@NotNull FunctionCodegen functionCodegen,
@NotNull MemberCodegen<?> memberCodegen
) {
this.state = functionCodegen.state;
this.v = v;
this.functionCodegen = functionCodegen;
this.typeMapper = state.getTypeMapper();
this.bindingContext = state.getBindingContext();
this.context = context;
this.memberCodegen = memberCodegen;
this.kind = context.getContextKind();
}
public void gen(@NotNull KtProperty property) {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
if (!(variableDescriptor instanceof PropertyDescriptor)) {
throw ExceptionLogger.logDescriptorNotFound(
"Property " + property.getName() + " should have a property descriptor: " + variableDescriptor, property
);
}
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
gen(property, propertyDescriptor, property.getGetter(), property.getSetter());
}
public void genDestructuringDeclaration(@NotNull KtDestructuringDeclarationEntry entry) {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, entry);
if (!(variableDescriptor instanceof PropertyDescriptor)) {
throw ExceptionLogger.logDescriptorNotFound(
"Destructuring declaration entry" + entry.getName() + " should have a property descriptor: " + variableDescriptor, entry
);
}
if (!UnderscoreUtilKt.isSingleUnderscore(entry)) {
genDestructuringDeclaration((PropertyDescriptor) variableDescriptor);
}
}
public void generateInPackageFacade(@NotNull DeserializedPropertyDescriptor deserializedProperty) {
assert context instanceof MultifileClassFacadeContext : "should be called only for generating facade: " + context;
genBackingFieldAndAnnotations(deserializedProperty);
if (!isConstOrHasJvmFieldAnnotation(deserializedProperty)) {
generateGetter(deserializedProperty, null);
generateSetter(deserializedProperty, null);
}
}
private void gen(
@NotNull KtProperty declaration,
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor getter,
@Nullable KtPropertyAccessor setter
) {
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION ||
kind == OwnerKind.DEFAULT_IMPLS || kind == OwnerKind.ERASED_INLINE_CLASS
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
genBackingFieldAndAnnotations(descriptor);
boolean isDefaultGetterAndSetter = isDefaultAccessor(getter) && isDefaultAccessor(setter);
if (isAccessorNeeded(descriptor, getter, isDefaultGetterAndSetter)) {
generateGetter(descriptor, getter);
}
if (isAccessorNeeded(descriptor, setter, isDefaultGetterAndSetter)) {
generateSetter(descriptor, setter);
}
}
private static boolean isDefaultAccessor(@Nullable KtPropertyAccessor accessor) {
return accessor == null || !accessor.hasBody();
}
private void genDestructuringDeclaration(@NotNull PropertyDescriptor descriptor) {
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DEFAULT_IMPLS
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
genBackingFieldAndAnnotations(descriptor);
generateGetter(descriptor, null);
generateSetter(descriptor, null);
}
private void genBackingFieldAndAnnotations(@NotNull PropertyDescriptor descriptor) {
// Fields and '$annotations' methods for non-private const properties are generated in the multi-file facade
boolean isBackingFieldOwner = descriptor.isConst() && !DescriptorVisibilities.isPrivate(descriptor.getVisibility())
? !(context instanceof MultifileClassPartContext)
: CodegenContextUtil.isImplementationOwner(context, descriptor);
generateBackingField(descriptor, isBackingFieldOwner);
generateSyntheticMethodIfNeeded(descriptor, isBackingFieldOwner);
}
private boolean isAccessorNeeded(
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor accessor,
boolean isDefaultGetterAndSetter
) {
return isAccessorNeeded(descriptor, accessor, isDefaultGetterAndSetter, kind);
}
public static boolean isReferenceablePropertyWithGetter(@NotNull PropertyDescriptor descriptor) {
PsiElement psiElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
KtDeclaration ktDeclaration = psiElement instanceof KtDeclaration ? (KtDeclaration) psiElement : null;
if (ktDeclaration instanceof KtProperty) {
KtProperty ktProperty = (KtProperty) ktDeclaration;
boolean isDefaultGetterAndSetter =
isDefaultAccessor(ktProperty.getGetter()) && isDefaultAccessor(ktProperty.getSetter());
return isAccessorNeeded(descriptor, ktProperty.getGetter(), isDefaultGetterAndSetter, OwnerKind.IMPLEMENTATION);
} else if (ktDeclaration instanceof KtParameter) {
return isAccessorNeeded(descriptor, null, true, OwnerKind.IMPLEMENTATION);
} else {
return isAccessorNeeded(descriptor, null, false, OwnerKind.IMPLEMENTATION);
}
}
/**
* Determines if it's necessary to generate an accessor to the property, i.e. if this property can be referenced via getter/setter
* for any reason
*
* @see JvmCodegenUtil#couldUseDirectAccessToProperty
*/
private static boolean isAccessorNeeded(
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor accessor,
boolean isDefaultGetterAndSetter,
OwnerKind kind
) {
if (isConstOrHasJvmFieldAnnotation(descriptor)) return false;
boolean isDefaultAccessor = isDefaultAccessor(accessor);
// Don't generate accessors for interface properties with default accessors in DefaultImpls
if (kind == OwnerKind.DEFAULT_IMPLS && isDefaultAccessor) return false;
// Delegated or extension properties can only be referenced via accessors
if (descriptor.isDelegated() || descriptor.getExtensionReceiverParameter() != null) return true;
// Companion object properties should have accessors for non-private properties because these properties can be referenced
// via getter/setter. But these accessors getter/setter are not required for private properties that have a default getter
// and setter, in this case, the property can always be accessed through the accessor 'access<property name>$cp' and avoid some
// useless indirection by using others accessors.
if (isCompanionObject(descriptor.getContainingDeclaration())) {
if (DescriptorVisibilities.isPrivate(descriptor.getVisibility()) && isDefaultGetterAndSetter) {
return false;
}
return true;
}
// Non-const properties from multifile classes have accessors regardless of visibility
if (isTopLevelInJvmMultifileClass(descriptor)) return true;
// Private class properties have accessors only in cases when those accessors are non-trivial
if (DescriptorVisibilities.isPrivate(descriptor.getVisibility())) {
return !isDefaultAccessor;
}
// Non-private properties with private setter should not be generated for trivial properties
// as the class will use direct field access instead
//noinspection ConstantConditions
if (accessor != null && accessor.isSetter() && DescriptorVisibilities.isPrivate(descriptor.getSetter().getVisibility())) {
return !isDefaultAccessor;
}
// Non-public API (private and internal) primary vals of inline classes don't have getter
if (InlineClassesUtilsKt.isUnderlyingPropertyOfInlineClass(descriptor) && !descriptor.getVisibility().isPublicAPI()) {
return false;
}
return true;
}
private static boolean areAccessorsNeededForPrimaryConstructorProperty(
@NotNull PropertyDescriptor descriptor,
@NotNull OwnerKind kind
) {
if (hasJvmFieldAnnotation(descriptor)) return false;
if (kind == OwnerKind.ERASED_INLINE_CLASS) return false;
DescriptorVisibility visibility = descriptor.getVisibility();
if (InlineClassesUtilsKt.isInlineClass(descriptor.getContainingDeclaration())) {
return visibility.isPublicAPI();
}
else {
return !DescriptorVisibilities.isPrivate(visibility);
}
}
public void generatePrimaryConstructorProperty(@NotNull PropertyDescriptor descriptor) {
genBackingFieldAndAnnotations(descriptor);
if (areAccessorsNeededForPrimaryConstructorProperty(descriptor, context.getContextKind())) {
generateGetter(descriptor, null);
generateSetter(descriptor, null);
}
}
public void generateConstructorPropertyAsMethodForAnnotationClass(
@NotNull KtParameter parameter,
@NotNull PropertyDescriptor descriptor,
@Nullable FunctionDescriptor expectedAnnotationConstructor
) {
JvmMethodGenericSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor);
Method asmMethod = signature.getAsmMethod();
MethodVisitor mv = v.newMethod(
JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor),
ACC_PUBLIC | ACC_ABSTRACT,
asmMethod.getName(),
asmMethod.getDescriptor(),
signature.getGenericsSignature(),
null
);
PropertyGetterDescriptor getter = descriptor.getGetter();
assert getter != null : "Annotation property should have a getter: " + descriptor;
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, getter, asmMethod);
AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations(getter, asmMethod.getReturnType(), null);
KtExpression defaultValue = loadAnnotationArgumentDefaultValue(parameter, descriptor, expectedAnnotationConstructor);
if (defaultValue != null) {
ConstantValue<?> constant = ExpressionCodegen.getCompileTimeConstant(
defaultValue, bindingContext, true, state.getShouldInlineConstVals());
assert !state.getClassBuilderMode().generateBodies || constant != null
: "Default value for annotation parameter should be compile time value: " + defaultValue.getText();
if (constant != null) {
AnnotationCodegen annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(mv, memberCodegen, state);
annotationCodegen.generateAnnotationDefaultValue(constant, descriptor.getType());
}
}
mv.visitEnd();
}
private KtExpression loadAnnotationArgumentDefaultValue(
@NotNull KtParameter ktParameter,
@NotNull PropertyDescriptor descriptor,
@Nullable FunctionDescriptor expectedAnnotationConstructor
) {
KtExpression value = ktParameter.getDefaultValue();
if (value != null) return value;
if (expectedAnnotationConstructor != null) {
ValueParameterDescriptor expectedParameter = CollectionsKt.single(
expectedAnnotationConstructor.getValueParameters(), parameter -> parameter.getName().equals(descriptor.getName())
);
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(expectedParameter);
if (!(element instanceof KtParameter)) {
state.getDiagnostics().report(EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(ktParameter));
return null;
}
return ((KtParameter) element).getDefaultValue();
}
return null;
}
private void generateBackingField(@NotNull PropertyDescriptor descriptor, boolean isBackingFieldOwner) {
if (isJvmInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.DEFAULT_IMPLS ||
kind == OwnerKind.ERASED_INLINE_CLASS) {
return;
}
Object defaultValue;
if (descriptor.isDelegated()) {
defaultValue = null;
}
else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
if (shouldWriteFieldInitializer(descriptor)) {
ConstantValue<?> initializer = descriptor.getCompileTimeInitializer();
defaultValue = initializer == null ? null : initializer.getValue();
}
else {
defaultValue = null;
}
}
else {
return;
}
generateBackingField(descriptor, descriptor.isDelegated(), defaultValue, isBackingFieldOwner);
}
// Annotations on properties are stored in bytecode on an empty synthetic method. This way they're still
// accessible via reflection, and 'deprecated' and 'synthetic' flags prevent this method from being called accidentally
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, boolean isBackingFieldOwner) {
Annotations annotations = descriptor.getAnnotations();
if (annotations.isEmpty()) return;
Method signature = typeMapper.mapSyntheticMethodForPropertyAnnotations(descriptor);
if (kind != OwnerKind.DEFAULT_IMPLS && CodegenContextUtil.isImplementationOwner(context, descriptor)) {
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, signature);
}
if (isBackingFieldOwner) {
if (!isInterface(context.getContextDescriptor()) ||
processInterfaceMethod(descriptor, kind, false, true, state.getJvmDefaultMode())) {
memberCodegen.generateSyntheticAnnotationsMethod(descriptor, signature, annotations);
}
}
}
private void generateBackingField(
@NotNull PropertyDescriptor propertyDescriptor,
boolean isDelegate,
@Nullable Object defaultValue,
boolean isBackingFieldOwner
) {
FieldDescriptor annotatedField = isDelegate ? propertyDescriptor.getDelegateField() : propertyDescriptor.getBackingField();
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) {
modifiers |= flagAnnotation.getJvmFlag(annotatedField);
}
if (kind == OwnerKind.PACKAGE) {
modifiers |= ACC_STATIC;
}
if (!propertyDescriptor.isLateInit() && (!propertyDescriptor.isVar() || isDelegate)) {
modifiers |= ACC_FINAL;
}
if (hasJvmSyntheticAnnotation(propertyDescriptor)) {
modifiers |= ACC_SYNTHETIC;
}
KotlinType kotlinType = isDelegate ? getDelegateTypeForProperty(propertyDescriptor, bindingContext) : propertyDescriptor.getType();
Type type = typeMapper.mapType(kotlinType);
ClassBuilder builder = v;
FieldOwnerContext backingFieldContext = context;
List<String> additionalVisibleAnnotations = Collections.emptyList();
if (DescriptorAsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor) ) {
modifiers |= ACC_STATIC;
if (DescriptorsJvmAbiUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor)) {
ImplementationBodyCodegen codegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
builder = codegen.v;
backingFieldContext = codegen.context;
if (DescriptorVisibilities.isPrivate(((ClassDescriptor) propertyDescriptor.getContainingDeclaration()).getVisibility())) {
modifiers |= ACC_DEPRECATED;
additionalVisibleAnnotations = Collections.singletonList(CodegenUtilKt.JAVA_LANG_DEPRECATED);
}
}
}
modifiers |= getVisibilityForBackingField(propertyDescriptor, isDelegate);
if (DescriptorAsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) {
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
parentBodyCodegen.addCompanionObjectPropertyToCopy(propertyDescriptor, defaultValue);
}
String name = backingFieldContext.getFieldName(propertyDescriptor, isDelegate);
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, new Pair<>(type, name));
if (isBackingFieldOwner) {
String signature = isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor);
FieldVisitor fv = builder.newField(
JvmDeclarationOriginKt.OtherOrigin(propertyDescriptor), modifiers, name, type.getDescriptor(),
signature, defaultValue
);
if (annotatedField != null) {
// Don't emit nullability annotations for backing field if:
// - backing field is synthetic;
// - property is lateinit (since corresponding field is actually nullable).
boolean skipNullabilityAnnotations =
(modifiers & ACC_SYNTHETIC) != 0 ||
propertyDescriptor.isLateInit();
AnnotationCodegen.forField(fv, memberCodegen, state, skipNullabilityAnnotations)
.genAnnotations(annotatedField, type, propertyDescriptor.getType(), null, additionalVisibleAnnotations);
}
if (propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor && JvmAnnotationUtilKt.isJvmRecord((ClassDescriptor) propertyDescriptor.getContainingDeclaration())) {
// builder.newRecordComponent(name, type.getDescriptor(), signature);
}
}
}
@NotNull
public static KotlinType getDelegateTypeForProperty(
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull BindingContext bindingContext
) {
ResolvedCall<FunctionDescriptor> provideDelegateResolvedCall =
bindingContext.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, propertyDescriptor);
KtProperty property = (KtProperty) DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
KtExpression delegateExpression = property != null ? property.getDelegateExpression() : null;
KotlinType delegateType;
if (provideDelegateResolvedCall != null) {
delegateType = provideDelegateResolvedCall.getResultingDescriptor().getReturnType();
}
else if (delegateExpression != null) {
delegateType = bindingContext.getType(delegateExpression);
}
else {
delegateType = null;
}
if (delegateType == null) {
// Delegation convention is unresolved
delegateType = ErrorUtils.createErrorType("Delegate type");
}
return delegateType;
}
private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) {
if (!descriptor.isConst() &&
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.NoConstantValueAttributeForNonConstVals)) {
return false;
}
//final field of primitive or String type
if (!descriptor.isVar()) {
Type type = typeMapper.mapType(descriptor);
return AsmUtil.isPrimitive(type) || "java.lang.String".equals(type.getClassName());
}
return false;
}
private void generateGetter(@NotNull PropertyDescriptor descriptor, @Nullable KtPropertyAccessor getter) {
generateAccessor(
getter,
descriptor.getGetter() != null ? descriptor.getGetter() : DescriptorFactory.createDefaultGetter(
descriptor, Annotations.Companion.getEMPTY()
)
);
}
private void generateSetter(@NotNull PropertyDescriptor descriptor, @Nullable KtPropertyAccessor setter) {
if (!descriptor.isVar()) return;
generateAccessor(
setter,
descriptor.getSetter() != null ? descriptor.getSetter() : DescriptorFactory.createDefaultSetter(
descriptor, Annotations.Companion.getEMPTY(), Annotations.Companion.getEMPTY()
)
);
}
private void generateAccessor(@Nullable KtPropertyAccessor accessor, @NotNull PropertyAccessorDescriptor descriptor) {
if (context instanceof MultifileClassFacadeContext &&
(DescriptorVisibilities.isPrivate(descriptor.getVisibility()) ||
DescriptorAsmUtil.getVisibilityAccessFlag(descriptor) == Opcodes.ACC_PRIVATE)) {
return;
}
FunctionGenerationStrategy strategy;
if (accessor == null || !accessor.hasBody()) {
if (descriptor.getCorrespondingProperty().isDelegated()) {
strategy = new DelegatedPropertyAccessorStrategy(state, descriptor);
}
else {
strategy = new DefaultPropertyAccessorStrategy(state, descriptor);
}
}
else {
strategy = new FunctionGenerationStrategy.FunctionDefault(state, accessor);
}
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), descriptor, strategy);
}
private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
private final PropertyAccessorDescriptor propertyAccessorDescriptor;
public DefaultPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
super(state);
propertyAccessorDescriptor = descriptor;
}
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
InstructionAdapter v = codegen.v;
PropertyDescriptor propertyDescriptor = propertyAccessorDescriptor.getCorrespondingProperty();
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
PsiElement jetProperty = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
if (jetProperty instanceof KtProperty || jetProperty instanceof KtParameter) {
codegen.markLineNumber((KtElement) jetProperty, false);
}
if (propertyAccessorDescriptor instanceof PropertyGetterDescriptor) {
Type type = signature.getReturnType();
property.put(type, v);
v.areturn(type);
}
else if (propertyAccessorDescriptor instanceof PropertySetterDescriptor) {
List<ValueParameterDescriptor> valueParameters = propertyAccessorDescriptor.getValueParameters();
assert valueParameters.size() == 1 : "Property setter should have only one value parameter but has " + propertyAccessorDescriptor;
int parameterIndex = codegen.lookupLocalIndex(valueParameters.get(0));
assert parameterIndex >= 0 : "Local index for setter parameter should be positive or zero: " + propertyAccessorDescriptor;
Type type = codegen.typeMapper.mapType(propertyDescriptor);
property.store(StackValue.local(parameterIndex, type), codegen.v);
v.visitInsn(RETURN);
}
else {
throw new IllegalStateException("Unknown property accessor: " + propertyAccessorDescriptor);
}
}
}
public static StackValue invokeDelegatedPropertyConventionMethod(
@NotNull ExpressionCodegen codegen,
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
@NotNull StackValue receiver,
@NotNull PropertyDescriptor propertyDescriptor
) {
codegen.tempVariables.put(
resolvedCall.getCall().getValueArguments().get(1).asElement(),
getDelegatedPropertyMetadata(propertyDescriptor, codegen.getBindingContext())
);
return codegen.invokeFunction(resolvedCall, receiver);
}
public static boolean isDelegatedPropertyWithOptimizedMetadata(
@NotNull VariableDescriptorWithAccessors descriptor,
@NotNull BindingContext bindingContext
) {
return Boolean.TRUE == bindingContext.get(DELEGATED_PROPERTY_WITH_OPTIMIZED_METADATA, descriptor);
}
public static @NotNull StackValue getOptimizedDelegatedPropertyMetadataValue() {
return StackValue.constant(null, K_PROPERTY_TYPE);
}
@NotNull
public static StackValue getDelegatedPropertyMetadata(
@NotNull VariableDescriptorWithAccessors descriptor,
@NotNull BindingContext bindingContext
) {
if (isDelegatedPropertyWithOptimizedMetadata(descriptor, bindingContext)) {
return getOptimizedDelegatedPropertyMetadataValue();
}
Type owner = bindingContext.get(DELEGATED_PROPERTY_METADATA_OWNER, descriptor);
assert owner != null : "Delegated property owner not found: " + descriptor;
List<VariableDescriptorWithAccessors> allDelegatedProperties = bindingContext.get(DELEGATED_PROPERTIES_WITH_METADATA, owner);
int index = allDelegatedProperties == null ? -1 : allDelegatedProperties.indexOf(descriptor);
if (index < 0) {
throw new AssertionError("Delegated property not found in " + owner + ": " + descriptor);
}
StackValue.Field array = StackValue.field(
Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none()
);
return StackValue.arrayElement(K_PROPERTY_TYPE, null, array, StackValue.constant(index));
}
private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
private final PropertyAccessorDescriptor propertyAccessorDescriptor;
public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
super(state);
this.propertyAccessorDescriptor = descriptor;
}
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
InstructionAdapter v = codegen.v;
BindingContext bindingContext = state.getBindingContext();
ResolvedCall<FunctionDescriptor> resolvedCall =
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, propertyAccessorDescriptor);
assert resolvedCall != null : "Resolve call should be recorded for delegate call " + signature.toString();
PropertyDescriptor propertyDescriptor = propertyAccessorDescriptor.getCorrespondingProperty();
StackValue.Property property = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
StackValue.Property delegate = property.getDelegateOrNull();
assert delegate != null : "No delegate for delegated property: " + propertyDescriptor;
StackValue lastValue = invokeDelegatedPropertyConventionMethod(codegen, resolvedCall, delegate, propertyDescriptor);
Type asmType = signature.getReturnType();
KotlinType kotlinReturnType = propertyAccessorDescriptor.getOriginal().getReturnType();
lastValue.put(asmType, kotlinReturnType, v);
v.areturn(asmType);
}
}
public void genDelegate(@NotNull PropertyDescriptor delegate, @NotNull PropertyDescriptor delegateTo, @NotNull StackValue field) {
ClassDescriptor toClass = (ClassDescriptor) delegateTo.getContainingDeclaration();
PropertyGetterDescriptor getter = delegate.getGetter();
if (getter != null) {
//noinspection ConstantConditions
functionCodegen.genDelegate(getter, delegateTo.getGetter().getOriginal(), toClass, field);
}
PropertySetterDescriptor setter = delegate.getSetter();
if (setter != null) {
//noinspection ConstantConditions
functionCodegen.genDelegate(setter, delegateTo.getSetter().getOriginal(), toClass, field);
}
}
}
@@ -775,7 +775,8 @@ public abstract class StackValue {
) { ) {
// Coerce 'this' for the case when it is smart cast. // Coerce 'this' for the case when it is smart cast.
// Do not coerce for other cases due to the 'protected' access issues (JVMS 7, 4.9.2 Structural Constraints). // Do not coerce for other cases due to the 'protected' access issues (JVMS 7, 4.9.2 Structural Constraints).
boolean coerceType = descriptor.getKind() == ClassKind.INTERFACE || descriptor.isInline() || (castReceiver && !isSuper); boolean coerceType = descriptor.getKind() == ClassKind.INTERFACE || InlineClassesUtilsKt.isInlineClass(descriptor) ||
(castReceiver && !isSuper);
return new ThisOuter(codegen, descriptor, isSuper, coerceType); return new ThisOuter(codegen, descriptor, isSuper, coerceType);
} }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor; import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.types.SimpleType; import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type;
@@ -48,7 +49,7 @@ public class ConstructorContext extends MethodContext {
ClassDescriptor capturedOuterClassDescriptor = closure != null ? closure.getCapturedOuterClassDescriptor() : null; ClassDescriptor capturedOuterClassDescriptor = closure != null ? closure.getCapturedOuterClassDescriptor() : null;
StackValue stackValue; StackValue stackValue;
if (capturedOuterClassDescriptor != null) { if (capturedOuterClassDescriptor != null) {
if (capturedOuterClassDescriptor.isInline()) { if (InlineClassesUtilsKt.isInlineClass(capturedOuterClassDescriptor)) {
SimpleType outerClassKotlinType = capturedOuterClassDescriptor.getDefaultType(); SimpleType outerClassKotlinType = capturedOuterClassDescriptor.getDefaultType();
Type outerClassType = kotlinTypeMapper.mapType(capturedOuterClassDescriptor); Type outerClassType = kotlinTypeMapper.mapType(capturedOuterClassDescriptor);
stackValue = StackValue.local(1, outerClassType, outerClassKotlinType); stackValue = StackValue.local(1, outerClassType, outerClassKotlinType);
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
@@ -294,7 +295,7 @@ class CoroutineCodegenForLambda private constructor(
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, funDescriptor, functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, funDescriptor,
object : FunctionGenerationStrategy.CodegenBased(state) { object : FunctionGenerationStrategy.CodegenBased(state) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) { override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
codegen.v.generateInvokeMethod(signature) codegen.v.generateInvokeMethod(signature, funDescriptor)
} }
}) })
} }
@@ -316,13 +317,13 @@ class CoroutineCodegenForLambda private constructor(
) )
mv.visitCode() mv.visitCode()
with(InstructionAdapter(mv)) { with(InstructionAdapter(mv)) {
generateInvokeMethod(jvmMethodSignature) generateInvokeMethod(jvmMethodSignature, untypedDescriptor)
} }
FunctionCodegen.endVisit(mv, "invoke", element) FunctionCodegen.endVisit(mv, "invoke", element)
} }
private fun InstructionAdapter.generateInvokeMethod(signature: JvmMethodSignature) { private fun InstructionAdapter.generateInvokeMethod(signature: JvmMethodSignature, descriptor: FunctionDescriptor) {
// this // this
load(0, AsmTypes.OBJECT_TYPE) load(0, AsmTypes.OBJECT_TYPE)
val parameterTypes = signature.valueParameters.map { it.asmType } val parameterTypes = signature.valueParameters.map { it.asmType }
@@ -348,16 +349,23 @@ class CoroutineCodegenForLambda private constructor(
load(arraySlot, AsmTypes.OBJECT_TYPE) load(arraySlot, AsmTypes.OBJECT_TYPE)
} else { } else {
var index = 0 var index = 0
val fromKotlinTypes =
if (!generateErasedCreate && doNotGenerateInvokeBridge) funDescriptor.allValueParameterTypes()
else funDescriptor.allValueParameterTypes().map { funDescriptor.module.builtIns.nullableAnyType }
val toKotlinTypes =
if (!generateErasedCreate && doNotGenerateInvokeBridge) createCoroutineDescriptor.allValueParameterTypes()
else descriptor.allValueParameterTypes()
parameterTypes.withVariableIndices().forEach { (varIndex, type) -> parameterTypes.withVariableIndices().forEach { (varIndex, type) ->
load(varIndex + 1, type) load(varIndex + 1, type)
StackValue.coerce(type, createArgumentTypes[index++], this) StackValue.coerce(type, fromKotlinTypes[index], createArgumentTypes[index], toKotlinTypes[index], this)
index++
} }
} }
// this.create(..) // this.create(..)
invokevirtual( invokevirtual(
v.thisName, v.thisName,
createCoroutineDescriptor.name.identifier, typeMapper.mapFunctionName(createCoroutineDescriptor, null),
Type.getMethodDescriptor( Type.getMethodDescriptor(
languageVersionSettings.continuationAsmType(), languageVersionSettings.continuationAsmType(),
*createArgumentTypes.toTypedArray() *createArgumentTypes.toTypedArray()
@@ -439,12 +447,24 @@ class CoroutineCodegenForLambda private constructor(
) )
} else { } else {
if (generateErasedCreate) { if (generateErasedCreate) {
load(index, AsmTypes.OBJECT_TYPE) if (parameter.type.isInlineClassType()) {
StackValue.coerce( load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType, load(index, AsmTypes.OBJECT_TYPE)
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType, StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, parameter.type, this)
this putfield(
) fieldInfoForCoroutineLambdaParameter.ownerInternalName,
fieldInfoForCoroutineLambdaParameter.fieldName,
fieldInfoForCoroutineLambdaParameter.fieldType.descriptor
)
continue
} else {
load(index, AsmTypes.OBJECT_TYPE)
StackValue.coerce(
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
this
)
}
} else { } else {
load(index, fieldInfoForCoroutineLambdaParameter.fieldType) load(index, fieldInfoForCoroutineLambdaParameter.fieldType)
} }
@@ -831,3 +851,6 @@ private object FailingFunctionGenerationStrategy : FunctionGenerationStrategy()
fun reportSuspensionPointInsideMonitor(element: KtElement, state: GenerationState, stackTraceElement: String) { fun reportSuspensionPointInsideMonitor(element: KtElement, state: GenerationState, stackTraceElement: String) {
state.diagnostics.report(ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR.on(element, stackTraceElement)) state.diagnostics.report(ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR.on(element, stackTraceElement))
} }
private fun FunctionDescriptor.allValueParameterTypes(): List<KotlinType> =
(listOfNotNull(extensionReceiverParameter?.type)) + valueParameters.map { it.type }
@@ -1222,8 +1222,9 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
oldLvt += record oldLvt += record
} }
method.localVariables.clear() method.localVariables.clear()
// Skip `this` for suspend lamdba // Skip `this` for suspend lambda
val start = if (isForNamedFunction) 0 else 1 val start = if (isForNamedFunction) 0 else 1
val oldLvtNodeToLatestNewLvtNode = mutableMapOf<LocalVariableNode, LocalVariableNode>()
for (variableIndex in start until method.maxLocals) { for (variableIndex in start until method.maxLocals) {
if (oldLvt.none { it.index == variableIndex }) continue if (oldLvt.none { it.index == variableIndex }) continue
var startLabel: LabelNode? = null var startLabel: LabelNode? = null
@@ -1239,25 +1240,15 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue
// startLabel can be null in case of parameters // startLabel can be null in case of parameters
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start @Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
var recordToExtend: LocalVariableNode? = null // Attempt to extend existing local variable node corresponding to the record in
for (record in method.localVariables) { // the original local variable table.
if (record.name == lvtRecord.name && var recordToExtend: LocalVariableNode? = oldLvtNodeToLatestNewLvtNode[lvtRecord]
record.desc == lvtRecord.desc && if (recordToExtend != null && InsnSequence(recordToExtend.end, startLabel).none { isBeforeSuspendMarker(it) }) {
record.signature == lvtRecord.signature &&
record.index == lvtRecord.index
) {
if (InsnSequence(record.end, startLabel).none { isBeforeSuspendMarker(it) }) {
recordToExtend = record
break
}
}
}
if (recordToExtend != null) {
recordToExtend.end = endLabel recordToExtend.end = endLabel
} else { } else {
method.localVariables.add( val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index) method.localVariables.add(node)
) oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
} }
} }
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.resolve.inline.isEffectivelyInlineOnly import org.jetbrains.kotlin.resolve.inline.isEffectivelyInlineOnly
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
@@ -92,7 +93,9 @@ class SuspendFunctionGenerationStrategy(
sourceFile = declaration.containingKtFile.name, sourceFile = declaration.containingKtFile.name,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null, needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
internalNameForDispatchReceiver = containingClassInternalNameOrNull(), internalNameForDispatchReceiver = (originalSuspendDescriptor.containingDeclaration as? ClassDescriptor)?.let {
if (it.isInlineClass()) state.typeMapper.mapType(it).internalName else null
} ?: containingClassInternalNameOrNull(),
languageVersionSettings = languageVersionSettings, languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true && disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() && originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() &&
@@ -136,9 +136,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
) { ) {
var nodeAndSmap: SMAPAndMethodNode? = null var nodeAndSmap: SMAPAndMethodNode? = null
try { try {
nodeAndSmap = createInlineMethodNode( nodeAndSmap = createInlineMethodNode(mapDefaultSignature, typeArguments, typeSystem)
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
)
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards) endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
} catch (e: CompilationException) { } catch (e: CompilationException) {
throw e throw e
@@ -274,6 +272,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
abstract fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean
fun generateAndInsertFinallyBlocks( fun generateAndInsertFinallyBlocks(
intoNode: MethodNode, intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>, insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
@@ -512,38 +512,33 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
} }
companion object { internal fun createInlineMethodNode(
callDefault: Boolean,
internal fun createInlineMethodNode( typeArguments: List<TypeParameterMarker>?,
functionDescriptor: FunctionDescriptor, typeSystem: TypeSystemCommonBackendContext
methodOwner: Type, ): SMAPAndMethodNode {
jvmSignature: JvmMethodSignature, val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
callDefault: Boolean, if (intrinsic != null) {
typeArguments: List<TypeParameterMarker>?, return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
typeSystem: TypeSystemCommonBackendContext,
state: GenerationState,
sourceCompilerForInline: SourceCompilerForInline
): SMAPAndMethodNode {
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
if (intrinsic != null) {
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
}
val asmMethod = if (callDefault)
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompilerForInline.contextKind)
else
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DescriptorWithContainerSource) {
val node = sourceCompilerForInline.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
return node
}
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
} }
val asmMethod = if (callDefault)
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
else
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !descriptorIsDeserialized(directMember)) {
val node = sourceCompiler.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
return node
}
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
}
companion object {
internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode { internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode {
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor) val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
assert(directMember is DescriptorWithContainerSource) { assert(directMember is DescriptorWithContainerSource) {
@@ -577,7 +572,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod) doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod)
else else
null null
result ?: throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor") result ?:
throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor")
} }
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP) return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.codegen.inline package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.linkWithLabel
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
@@ -16,7 +15,6 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
class InlineCodegenForDefaultBody( class InlineCodegenForDefaultBody(
@@ -41,8 +39,10 @@ class InlineCodegenForDefaultBody(
} }
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) { override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
val nodeAndSmap = InlineCodegen.createInlineMethodNode( val nodeAndSmap = PsiInlineCodegen(
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline codegen, state, function, methodOwner, jvmSignature, TypeParameterMappings(), sourceCompilerForInline
).createInlineMethodNode(
callDefault, null, codegen.typeSystem
) )
val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP) val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP)
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpres
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
@@ -208,4 +210,7 @@ class PsiInlineCodegen(
::PsiDefaultLambda ::PsiDefaultLambda
) )
} }
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
memberDescriptor is DescriptorWithContainerSource
} }
@@ -130,7 +130,9 @@ fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
node.instructions.insert(position, newInsn) node.instructions.insert(position, newInsn)
} }
node.localVariables.removeIf { it.start in toDelete && it.end in toDelete } node.localVariables.removeIf {
(it.start in toDelete && it.end in toDelete) || defaultLambdas.contains(it.index)
}
node.remove(toDelete) node.remove(toDelete)
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.codegen package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
@@ -44,6 +41,10 @@ fun CallableDescriptor.isGenericParameter(): Boolean {
fun classFileContainsMethod(descriptor: FunctionDescriptor, state: GenerationState, method: Method): Boolean? { fun classFileContainsMethod(descriptor: FunctionDescriptor, state: GenerationState, method: Method): Boolean? {
if (descriptor !is DeserializedSimpleFunctionDescriptor) return null if (descriptor !is DeserializedSimpleFunctionDescriptor) return null
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
return descriptor.overriddenDescriptors.any { classFileContainsMethod(it, state, method) == true }
}
val classId: ClassId = when { val classId: ClassId = when {
descriptor.containingDeclaration is DeserializedClassDescriptor -> { descriptor.containingDeclaration is DeserializedClassDescriptor -> {
(descriptor.containingDeclaration as DeserializedClassDescriptor).classId ?: return null (descriptor.containingDeclaration as DeserializedClassDescriptor).classId ?: return null
@@ -56,6 +57,10 @@ fun classFileContainsMethod(descriptor: FunctionDescriptor, state: GenerationSta
} }
} }
return classFileContainsMethod(classId, state, method)
}
fun classFileContainsMethod(classId: ClassId, state: GenerationState, method: Method): Boolean? {
val bytes = VirtualFileFinder.getInstance(state.project, state.module).findVirtualFileWithHeader(classId) val bytes = VirtualFileFinder.getInstance(state.project, state.module).findVirtualFileWithHeader(classId)
?.contentsToByteArray() ?: return null ?.contentsToByteArray() ?: return null
var found = false var found = false
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Pair
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
@@ -119,7 +120,7 @@ fun getUnboxedType(boxedType: Type, state: GenerationState): Type {
fun unboxedTypeOfInlineClass(boxedType: Type, state: GenerationState): Type? { fun unboxedTypeOfInlineClass(boxedType: Type, state: GenerationState): Type? {
val descriptor = val descriptor =
state.jvmBackendClassResolver.resolveToClassDescriptors(boxedType).singleOrNull()?.takeIf { it.isInline } ?: return null state.jvmBackendClassResolver.resolveToClassDescriptors(boxedType).singleOrNull()?.takeIf { it.isInlineClass() } ?: return null
return state.mapInlineClass(descriptor) return state.mapInlineClass(descriptor)
} }
@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?> typealias TypeAnnotatedFrames = Array<Frame<BasicValue>>
@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>> typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?>
@@ -201,7 +201,7 @@ class GenerationState private constructor(
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
val runtimeStringConcat = val runtimeStringConcat =
if (target.bytecodeVersion >= JvmTarget.JVM_9.bytecodeVersion) if (target.majorVersion >= JvmTarget.JVM_9.majorVersion)
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE
else JvmStringConcat.INLINE else JvmStringConcat.INLINE
@@ -272,7 +272,10 @@ class GenerationState private constructor(
val rootContext: CodegenContext<*> = RootContext(this) val rootContext: CodegenContext<*> = RootContext(this)
val classFileVersion: Int = target.bytecodeVersion val classFileVersion: Int = run {
val minorVersion = if (configuration.getBoolean(JVMConfigurationKeys.ENABLE_JVM_PREVIEW)) 0xffff else 0
(minorVersion shl 16) + target.majorVersion
}
val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA) val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA)
@@ -5,4 +5,4 @@
package org.jetbrains.kotlin.codegen.state package org.jetbrains.kotlin.codegen.state
typealias JvmMethodExceptionTypes = Array<out String>? typealias JvmMethodExceptionTypes = Array<out String?>?
@@ -5,4 +5,4 @@
package org.jetbrains.kotlin.codegen.state package org.jetbrains.kotlin.codegen.state
typealias JvmMethodExceptionTypes = Array<out String?>? typealias JvmMethodExceptionTypes = Array<out String>?
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.load.java.descriptors.getImplClassNameForDeserialized import org.jetbrains.kotlin.load.java.descriptors.getImplClassNameForDeserialized
import org.jetbrains.kotlin.load.java.getJvmMethodNameIfSpecial import org.jetbrains.kotlin.load.java.getJvmMethodNameIfSpecial
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescriptor import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescriptor
@@ -50,6 +51,7 @@ import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall import org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall
import org.jetbrains.kotlin.resolve.BindingContextUtils.isBoxedLocalCapturedInClosure import org.jetbrains.kotlin.resolve.BindingContextUtils.isBoxedLocalCapturedInClosure
import org.jetbrains.kotlin.resolve.DescriptorUtils.* import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -60,6 +62,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER import org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.resolve.jvm.JAVA_LANG_RECORD_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.annotations.isCompiledToJvmDefault import org.jetbrains.kotlin.resolve.jvm.annotations.isCompiledToJvmDefault
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
@@ -379,7 +382,8 @@ class KotlinTypeMapper @JvmOverloads constructor(
val originalDescriptor = descriptor.original val originalDescriptor = descriptor.original
return CallableMethod( return CallableMethod(
owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION) }, method, INVOKESPECIAL, owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION) }, method, INVOKESPECIAL,
null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false,
boxInlineClassBeforeInvoke = false
) )
} }
@@ -402,6 +406,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
val dispatchReceiverKotlinType: KotlinType? val dispatchReceiverKotlinType: KotlinType?
var isInterfaceMember = false var isInterfaceMember = false
var isDefaultMethodInInterface = false var isDefaultMethodInInterface = false
var boxInlineClassBeforeInvoke = false
if (functionParent is ClassDescriptor) { if (functionParent is ClassDescriptor) {
val declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor) val declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor)
@@ -445,18 +450,22 @@ class KotlinTypeMapper @JvmOverloads constructor(
} }
} }
} else { } else {
val toInlinedErasedClass = functionParent.isInline && val toInlinedErasedClass = functionParent.isInlineClass() &&
(!isAccessor(functionDescriptor) || isInlineClassConstructorAccessor(functionDescriptor)) (!isAccessor(functionDescriptor) || isInlineClassConstructorAccessor(functionDescriptor))
if (toInlinedErasedClass) { if (toInlinedErasedClass) {
functionDescriptor = descriptor functionDescriptor = descriptor
} }
val isStaticInvocation = val isFakeOverrideOfJvmDefault = toInlinedErasedClass &&
isStaticDeclaration(functionDescriptor) && functionDescriptor !is ImportedFromObjectCallableDescriptor<*> || functionDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
isStaticAccessor(functionDescriptor) || functionDescriptor.overridesJvmDefault()
functionDescriptor.isJvmStaticInObjectOrClassOrInterface() ||
toInlinedErasedClass val isStaticInvocation = !isFakeOverrideOfJvmDefault &&
(isStaticDeclaration(functionDescriptor) && functionDescriptor !is ImportedFromObjectCallableDescriptor<*> ||
isStaticAccessor(functionDescriptor) ||
functionDescriptor.isJvmStaticInObjectOrClassOrInterface() ||
toInlinedErasedClass)
when { when {
isStaticInvocation -> { isStaticInvocation -> {
invokeOpcode = INVOKESTATIC invokeOpcode = INVOKESTATIC
@@ -466,8 +475,13 @@ class KotlinTypeMapper @JvmOverloads constructor(
invokeOpcode = INVOKEINTERFACE invokeOpcode = INVOKEINTERFACE
isInterfaceMember = true isInterfaceMember = true
} }
isFakeOverrideOfJvmDefault -> {
invokeOpcode = INVOKEVIRTUAL
boxInlineClassBeforeInvoke = true
}
else -> { else -> {
val isPrivateFunInvocation = DescriptorVisibilities.isPrivate(functionDescriptor.visibility) && !functionDescriptor.isSuspend val isPrivateFunInvocation =
DescriptorVisibilities.isPrivate(functionDescriptor.visibility) && !functionDescriptor.isSuspend
invokeOpcode = if (superCall || isPrivateFunInvocation) INVOKESPECIAL else INVOKEVIRTUAL invokeOpcode = if (superCall || isPrivateFunInvocation) INVOKESPECIAL else INVOKEVIRTUAL
isInterfaceMember = false isInterfaceMember = false
} }
@@ -479,7 +493,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
else else
functionDescriptor.original functionDescriptor.original
signature = if (toInlinedErasedClass) signature = if (toInlinedErasedClass && !isFakeOverrideOfJvmDefault)
mapSignatureForInlineErasedClassSkipGeneric(functionToCall) mapSignatureForInlineErasedClassSkipGeneric(functionToCall)
else else
mapSignature( mapSignature(
@@ -547,10 +561,18 @@ class KotlinTypeMapper @JvmOverloads constructor(
signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType, signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType,
calleeType, returnKotlinType, calleeType, returnKotlinType,
if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE, if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE,
isDefaultMethodInInterface isDefaultMethodInInterface, boxInlineClassBeforeInvoke
) )
} }
private fun CallableMemberDescriptor.overridesJvmDefault(): Boolean {
if (kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
return overriddenDescriptors.any { it.overridesJvmDefault() }
}
if (isCompiledToJvmDefault(jvmDefaultMode)) return true
return (containingDeclaration as? JavaClassDescriptor)?.kind == ClassKind.INTERFACE && modality != Modality.ABSTRACT
}
fun mapFunctionName(descriptor: FunctionDescriptor, kind: OwnerKind?): String { fun mapFunctionName(descriptor: FunctionDescriptor, kind: OwnerKind?): String {
if (descriptor !is JavaCallableMemberDescriptor) { if (descriptor !is JavaCallableMemberDescriptor) {
val platformName = getJvmName(descriptor) val platformName = getJvmName(descriptor)
@@ -563,10 +585,16 @@ class KotlinTypeMapper @JvmOverloads constructor(
return when { return when {
descriptor is PropertyAccessorDescriptor -> { descriptor is PropertyAccessorDescriptor -> {
val property = descriptor.correspondingProperty val property = descriptor.correspondingProperty
if (isAnnotationClass(property.containingDeclaration)) { val containingDeclaration = property.containingDeclaration
if (isAnnotationClass(containingDeclaration) &&
(!property.hasJvmStaticAnnotation() && !descriptor.hasJvmStaticAnnotation())
) {
return property.name.asString() return property.name.asString()
} }
if ((containingDeclaration as? ClassDescriptor)?.hasJavaLangRecordSupertype() == true) return property.name.asString()
val isAccessor = property is AccessorForPropertyDescriptor val isAccessor = property is AccessorForPropertyDescriptor
val propertyName = if (isAccessor) val propertyName = if (isAccessor)
(property as AccessorForPropertyDescriptor).accessorSuffix (property as AccessorForPropertyDescriptor).accessorSuffix
@@ -601,6 +629,9 @@ class KotlinTypeMapper @JvmOverloads constructor(
} }
} }
private fun ClassDescriptor.hasJavaLangRecordSupertype() =
typeConstructor.supertypes.any { KotlinBuiltIns.isConstructedFromGivenClass(it, JAVA_LANG_RECORD_FQ_NAME) }
private val shouldMangleByReturnType = private val shouldMangleByReturnType =
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses) languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)
@@ -965,7 +996,8 @@ class KotlinTypeMapper @JvmOverloads constructor(
if ((isFunctionExpression(descriptor) || isFunctionLiteral(descriptor)) && returnType.isInlineClassType()) return true if ((isFunctionExpression(descriptor) || isFunctionLiteral(descriptor)) && returnType.isInlineClassType()) return true
return isJvmPrimitive(returnType) && return isJvmPrimitive(returnType) &&
getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitive(it.returnType!!) } getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitive(it.returnType!!) } ||
returnType.isInlineClassType() && descriptor is JavaMethodDescriptor
} }
private fun isJvmPrimitive(kotlinType: KotlinType) = private fun isJvmPrimitive(kotlinType: KotlinType) =
@@ -1031,7 +1063,11 @@ class KotlinTypeMapper @JvmOverloads constructor(
fun writeParameterType(sw: JvmSignatureWriter, type: KotlinType, callableDescriptor: CallableDescriptor?) { fun writeParameterType(sw: JvmSignatureWriter, type: KotlinType, callableDescriptor: CallableDescriptor?) {
if (sw.skipGenericSignature()) { if (sw.skipGenericSignature()) {
mapType(type, sw, TypeMappingMode.DEFAULT) if (type.isInlineClassType() && callableDescriptor is JavaMethodDescriptor) {
mapType(type, sw, TypeMappingMode.GENERIC_ARGUMENT)
} else {
mapType(type, sw, TypeMappingMode.DEFAULT)
}
return return
} }
@@ -7,12 +7,12 @@ package org.jetbrains.kotlin.codegen.state
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -85,6 +85,7 @@ fun getManglingSuffixBasedOnKotlinSignature(
): String? { ): String? {
if (descriptor !is FunctionDescriptor) return null if (descriptor !is FunctionDescriptor) return null
if (descriptor is ConstructorDescriptor) return null if (descriptor is ConstructorDescriptor) return null
if (descriptor is JavaMethodDescriptor) return null
if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null
// Don't mangle functions with '@JvmName' annotation. // Don't mangle functions with '@JvmName' annotation.
@@ -111,7 +112,7 @@ fun getManglingSuffixBasedOnKotlinSignature(
private fun getInfoForMangling(type: KotlinType): InfoForMangling? { private fun getInfoForMangling(type: KotlinType): InfoForMangling? {
val descriptor = type.constructor.declarationDescriptor ?: return null val descriptor = type.constructor.declarationDescriptor ?: return null
return when (descriptor) { return when (descriptor) {
is ClassDescriptor -> InfoForMangling(descriptor.fqNameUnsafe, descriptor.isInline, type.isMarkedNullable) is ClassDescriptor -> InfoForMangling(descriptor.fqNameUnsafe, descriptor.isInlineClass(), type.isMarkedNullable)
is TypeParameterDescriptor -> { is TypeParameterDescriptor -> {
getInfoForMangling(descriptor.representativeUpperBound) getInfoForMangling(descriptor.representativeUpperBound)
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
@@ -93,4 +94,4 @@ fun KotlinType.removeExternalProjections(): KotlinType {
fun isInlineClassConstructorAccessor(descriptor: FunctionDescriptor): Boolean = fun isInlineClassConstructorAccessor(descriptor: FunctionDescriptor): Boolean =
descriptor is AccessorForConstructorDescriptor && descriptor is AccessorForConstructorDescriptor &&
descriptor.calleeDescriptor.constructedClass.isInline descriptor.calleeDescriptor.constructedClass.isInlineClass()
+15 -1
View File
@@ -1,4 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.ideaExt.idea
import java.io.File import java.io.File
plugins { plugins {
@@ -69,10 +70,20 @@ dependencies {
antLauncherJar(toolsJar()) antLauncherJar(toolsJar())
} }
val generationRoot = projectDir.resolve("tests-gen")
sourceSets { sourceSets {
"main" {} "main" {}
"test" { "test" {
projectDefault() projectDefault()
this.java.srcDir(generationRoot.name)
}
}
if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
apply(plugin = "idea")
idea {
this.module.generatedSourceDirs.add(generationRoot)
} }
} }
@@ -87,6 +98,9 @@ projectTest(parallel = true) {
} }
} }
val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestsKt") val generateTestData by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestDataKt")
val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestsKt") {
dependsOn(generateTestData)
}
testsJar() testsJar()
+2 -1
View File
@@ -49,6 +49,7 @@ if "%_KOTLIN_RUNNER%"=="1" (
"%_JAVACMD%" %JAVA_OPTS% "-Dkotlin.home=%_KOTLIN_HOME%" -cp "%_KOTLIN_HOME%\lib\kotlin-runner.jar" ^ "%_JAVACMD%" %JAVA_OPTS% "-Dkotlin.home=%_KOTLIN_HOME%" -cp "%_KOTLIN_HOME%\lib\kotlin-runner.jar" ^
org.jetbrains.kotlin.runner.Main %KOTLIN_OPTS% org.jetbrains.kotlin.runner.Main %KOTLIN_OPTS%
) else ( ) else (
setlocal EnableDelayedExpansion
SET _ADDITIONAL_CLASSPATH= SET _ADDITIONAL_CLASSPATH=
if not "%_KOTLIN_TOOL%"=="" ( if not "%_KOTLIN_TOOL%"=="" (
@@ -56,7 +57,7 @@ if "%_KOTLIN_RUNNER%"=="1" (
) )
"%_JAVACMD%" %JAVA_OPTS% -noverify -cp "%_KOTLIN_HOME%\lib\kotlin-preloader.jar" ^ "%_JAVACMD%" %JAVA_OPTS% -noverify -cp "%_KOTLIN_HOME%\lib\kotlin-preloader.jar" ^
org.jetbrains.kotlin.preloading.Preloader -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar%_ADDITIONAL_CLASSPATH%" ^ org.jetbrains.kotlin.preloading.Preloader -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar!_ADDITIONAL_CLASSPATH!" ^
%_KOTLIN_COMPILER% %KOTLIN_OPTS% %_KOTLIN_COMPILER% %KOTLIN_OPTS%
) )
@@ -0,0 +1,12 @@
<idea-plugin>
<id>org.jetbrains.kotlin</id>
<version>1.2</version>
<!-- Don't add more extension points here! Logic in KotlinCoreEnvironment assumes that there is only one EP. -->
<!-- And this file should be removed once 202 is no longer supported -->
<extensionPoints>
<extensionPoint qualifiedName="com.intellij.psi.classFileDecompiler"
interface="com.intellij.psi.compiled.ClassFileDecompilers$Decompiler"
dynamic="true"/>
</extensionPoints>
</idea-plugin>
@@ -125,6 +125,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-Xir-dce-print-reachability-info", description = "Print declarations' reachability info to stdout during performing DCE") @Argument(value = "-Xir-dce-print-reachability-info", description = "Print declarations' reachability info to stdout during performing DCE")
var irDcePrintReachabilityInfo: Boolean by FreezableVar(false) var irDcePrintReachabilityInfo: Boolean by FreezableVar(false)
@Argument(value = "-Xir-property-lazy-initialization", description = "Perform lazy initialization for properties")
var irPropertyLazyInitialization: Boolean by FreezableVar(false)
@Argument(value = "-Xir-only", description = "Disables pre-IR backend") @Argument(value = "-Xir-only", description = "Disables pre-IR backend")
var irOnly: Boolean by FreezableVar(false) var irOnly: Boolean by FreezableVar(false)
@@ -418,6 +418,13 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
) )
var useOldInlineClassesManglingScheme: Boolean by FreezableVar(false) var useOldInlineClassesManglingScheme: Boolean by FreezableVar(false)
@Argument(
value = "-Xjvm-enable-preview",
description = "Allow using features from Java language that are in preview phase.\n" +
"Works as `--enable-preview` in Java. All class files are marked as preview-generated thus it won't be possible to use them in release environment"
)
var enableJvmPreview: Boolean by FreezableVar(false)
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> { override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
val result = super.configureAnalysisFlags(collector) val result = super.configureAnalysisFlags(collector)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
@@ -438,6 +445,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
result[JvmAnalysisFlags.sanitizeParentheses] = sanitizeParentheses result[JvmAnalysisFlags.sanitizeParentheses] = sanitizeParentheses
result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError
result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames
result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview
result[AnalysisFlags.reportErrorsOnIrDependencies] = !useIR && !useFir && !allowJvmIrDependencies result[AnalysisFlags.reportErrorsOnIrDependencies] = !useIR && !useFir && !allowJvmIrDependencies
result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses
return result return result
@@ -27,7 +27,10 @@ import org.jetbrains.kotlin.cli.common.messages.MessageUtil
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
@@ -261,7 +264,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
generateDceJs = arguments.irDce, generateDceJs = arguments.irDce,
dceDriven = arguments.irDceDriven, dceDriven = arguments.irDceDriven,
multiModule = arguments.irPerModule, multiModule = arguments.irPerModule,
relativeRequirePath = true relativeRequirePath = true,
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
) )
} catch (e: JsIrCompilationError) { } catch (e: JsIrCompilationError) {
return COMPILATION_ERROR return COMPILATION_ERROR
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
@@ -128,7 +127,7 @@ class AnalyzerWithCompilerReport(
psiElement: E, factory: DiagnosticFactory0<E>, val message: String psiElement: E, factory: DiagnosticFactory0<E>, val message: String
) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) { ) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) {
override fun isValid(): Boolean = true override val isValid: Boolean = true
} }
companion object { companion object {
@@ -154,16 +153,16 @@ class AnalyzerWithCompilerReport(
return diagnostic.severity == Severity.ERROR return diagnostic.severity == Severity.ERROR
} }
fun reportDiagnostics(unsortedDiagnostics: Diagnostics, reporter: DiagnosticMessageReporter): Boolean { fun reportDiagnostics(unsortedDiagnostics: GenericDiagnostics<*>, reporter: DiagnosticMessageReporter): Boolean {
var hasErrors = false var hasErrors = false
val diagnostics = sortedDiagnostics(unsortedDiagnostics.all()) val diagnostics = sortedDiagnostics(unsortedDiagnostics.all().filterIsInstance<Diagnostic>())
for (diagnostic in diagnostics) { for (diagnostic in diagnostics) {
hasErrors = hasErrors or reportDiagnostic(diagnostic, reporter) hasErrors = hasErrors or reportDiagnostic(diagnostic, reporter)
} }
return hasErrors return hasErrors
} }
fun reportDiagnostics(diagnostics: Diagnostics, messageCollector: MessageCollector): Boolean { fun reportDiagnostics(diagnostics: GenericDiagnostics<*>, messageCollector: MessageCollector): Boolean {
val hasErrors = reportDiagnostics(diagnostics, DefaultDiagnosticReporter(messageCollector)) val hasErrors = reportDiagnostics(diagnostics, DefaultDiagnosticReporter(messageCollector))
if (diagnostics.any { it.factory == Errors.INCOMPATIBLE_CLASS }) { if (diagnostics.any { it.factory == Errors.INCOMPATIBLE_CLASS }) {
@@ -1,36 +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.cli.common.messages
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
/**
* This class behaviour is the same as [MessageCollector.report] in [AnalyzerWithCompilerReport.reportDiagnostic].
*/
class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
val messageCollector: MessageCollector
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
render,
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
)
}
@@ -17,8 +17,6 @@
package org.jetbrains.kotlin.cli.common.messages; package org.jetbrains.kotlin.cli.common.messages;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.jar.CoreJarVirtualFile;
import com.intellij.openapi.vfs.local.CoreLocalVirtualFile;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -53,10 +51,6 @@ public class MessageUtil {
@NotNull @NotNull
public static String virtualFileToPath(@NotNull VirtualFile virtualFile) { public static String virtualFileToPath(@NotNull VirtualFile virtualFile) {
// Convert path to platform-dependent format when virtualFile is local file. return toSystemDependentName(virtualFile.getPath());
if (virtualFile instanceof CoreLocalVirtualFile || virtualFile instanceof CoreJarVirtualFile) {
return toSystemDependentName(virtualFile.getPath());
}
return virtualFile.getPath();
} }
} }
@@ -1,54 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.common.messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils;
import static com.intellij.openapi.util.io.FileUtil.toSystemDependentName;
public class MessageUtil {
private MessageUtil() {}
@Nullable
public static CompilerMessageLocation psiElementToMessageLocation(@Nullable PsiElement element) {
if (element == null) return null;
PsiFile file = element.getContainingFile();
return psiFileToMessageLocation(file, "<no path>", DiagnosticUtils.getLineAndColumnInPsiFile(file, element.getTextRange()));
}
@Nullable
public static CompilerMessageLocation psiFileToMessageLocation(
@NotNull PsiFile file,
@Nullable String defaultValue,
@NotNull PsiDiagnosticUtils.LineAndColumn lineAndColumn
) {
VirtualFile virtualFile = file.getVirtualFile();
String path = virtualFile != null ? virtualFileToPath(virtualFile) : defaultValue;
return CompilerMessageLocation.create(path, lineAndColumn.getLine(), lineAndColumn.getColumn(), lineAndColumn.getLineContent());
}
@NotNull
public static String virtualFileToPath(@NotNull VirtualFile virtualFile) {
return toSystemDependentName(virtualFile.getPath());
}
}
@@ -77,15 +77,23 @@ open class CliBindingTrace @TestOnly constructor() : BindingTraceContext() {
this.kotlinCodeAnalyzer = kotlinCodeAnalyzer this.kotlinCodeAnalyzer = kotlinCodeAnalyzer
} }
@Suppress("UNCHECKED_CAST")
override fun <K, V> get(slice: ReadOnlySlice<K, V>, key: K): V? { override fun <K, V> get(slice: ReadOnlySlice<K, V>, key: K): V? {
val value = super.get(slice, key) val value = super.get(slice, key)
if (value == null) { if (value == null) {
if (BindingContext.FUNCTION === slice || BindingContext.VARIABLE === slice) { if (key is KtDeclaration) {
if (key is KtDeclaration) { // NB: intentional code duplication, see https://youtrack.jetbrains.com/issue/KT-43296
if (BindingContext.FUNCTION === slice) {
if (!KtPsiUtil.isLocal(key)) { if (!KtPsiUtil.isLocal(key)) {
kotlinCodeAnalyzer!!.resolveToDescriptor(key) kotlinCodeAnalyzer!!.resolveToDescriptor(key)
return super.get(slice, key) return super.get(slice, key) as V?
}
}
if (BindingContext.VARIABLE === slice) {
if (!KtPsiUtil.isLocal(key)) {
kotlinCodeAnalyzer!!.resolveToDescriptor(key)
return super.get(slice, key) as V?
} }
} }
} }
@@ -40,7 +40,6 @@ public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnviron
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class); registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class); registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
registerApplicationExtensionPoint(ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class);
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class); registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
@@ -52,4 +51,4 @@ public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnviron
protected VirtualFileSystem createJrtFileSystem() { protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem(); return new CoreJrtFileSystem();
} }
} }
@@ -1,55 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.cli.jvm.compiler;
import com.intellij.DynamicBundle;
import com.intellij.codeInsight.ContainerProvider;
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.lang.MetaLanguage;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.FileContextProvider;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.meta.MetaDataContributor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment {
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
KotlinCoreApplicationEnvironment environment = new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
registerExtensionPoints();
return environment;
}
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
super(parentDisposable, unitTestMode);
}
private static void registerExtensionPoints() {
registerApplicationExtensionPoint(DynamicBundle.LanguageBundleEP.EP_NAME, DynamicBundle.LanguageBundleEP.class);
registerApplicationExtensionPoint(FileContextProvider.EP_NAME, FileContextProvider.class);
registerApplicationExtensionPoint(MetaDataContributor.EP_NAME, MetaDataContributor.class);
registerApplicationExtensionPoint(PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
registerApplicationExtensionPoint(ClassFileDecompilers.getInstance().EP_NAME, ClassFileDecompilers.Decompiler.class);
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(Extensions.getRootArea());
}
@Nullable
@Override
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.cli.jvm.compiler;
import com.intellij.DynamicBundle;
import com.intellij.codeInsight.ContainerProvider;
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.lang.MetaLanguage;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.FileContextProvider;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.meta.MetaDataContributor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment {
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
KotlinCoreApplicationEnvironment environment = new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
registerExtensionPoints();
return environment;
}
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
super(parentDisposable, unitTestMode);
}
private static void registerExtensionPoints() {
registerApplicationExtensionPoint(DynamicBundle.LanguageBundleEP.EP_NAME, DynamicBundle.LanguageBundleEP.class);
registerApplicationExtensionPoint(FileContextProvider.EP_NAME, FileContextProvider.class);
registerApplicationExtensionPoint(MetaDataContributor.EP_NAME, MetaDataContributor.class);
registerApplicationExtensionPoint(PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(Extensions.getRootArea());
}
@Nullable
@Override
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
}
@@ -33,13 +33,16 @@ import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.ExtensionsArea import com.intellij.openapi.extensions.ExtensionsArea
import com.intellij.openapi.fileTypes.PlainTextFileType import com.intellij.openapi.fileTypes.PlainTextFileType
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.LanguageLevelProjectExtension
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.* import com.intellij.openapi.vfs.*
import com.intellij.openapi.vfs.impl.ZipHandler import com.intellij.openapi.vfs.impl.ZipHandler
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.compiled.ClassFileDecompilers
import com.intellij.psi.impl.JavaClassSupersImpl import com.intellij.psi.impl.JavaClassSupersImpl
import com.intellij.psi.impl.PsiElementFinderImpl import com.intellij.psi.impl.PsiElementFinderImpl
import com.intellij.psi.impl.PsiTreeChangePreprocessor import com.intellij.psi.impl.PsiTreeChangePreprocessor
@@ -249,6 +252,8 @@ class KotlinCoreEnvironment private constructor(
project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, fun(roots: List<File>) { project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, fun(roots: List<File>) {
updateClasspath(roots.map { JavaSourceRoot(it, null) }) updateClasspath(roots.map { JavaSourceRoot(it, null) })
}) })
LanguageLevelProjectExtension.getInstance(project).languageLevel = LanguageLevel.JDK_15_PREVIEW
} }
private fun collectAdditionalSources(project: MockProject) { private fun collectAdditionalSources(project: MockProject) {
@@ -509,6 +514,11 @@ class KotlinCoreEnvironment private constructor(
val applicationEnvironment = KotlinCoreApplicationEnvironment.create(parentDisposable, unitTestMode) val applicationEnvironment = KotlinCoreApplicationEnvironment.create(parentDisposable, unitTestMode)
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/compiler.xml") registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/compiler.xml")
// FIX ME WHEN BUNCH 202 REMOVED: this code is required to support compiler bundled to both 202 and 203.
// Please, remove "com.intellij.psi.classFileDecompiler" EP registration once 202 is no longer supported by the compiler
if (!Extensions.getRootArea().hasExtensionPoint("com.intellij.psi.classFileDecompiler")) {
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/core.xml")
}
registerApplicationServicesForCLI(applicationEnvironment) registerApplicationServicesForCLI(applicationEnvironment)
registerApplicationServices(applicationEnvironment) registerApplicationServices(applicationEnvironment)
@@ -692,4 +702,4 @@ class KotlinCoreEnvironment private constructor(
} }
} }
} }
} }
@@ -0,0 +1,703 @@
/*
* 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.cli.jvm.compiler
import com.intellij.codeInsight.ExternalAnnotationsManager
import com.intellij.codeInsight.InferredAnnotationsManager
import com.intellij.core.CoreApplicationEnvironment
import com.intellij.core.CoreJavaFileManager
import com.intellij.core.JavaCoreProjectEnvironment
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.lang.java.JavaParserDefinition
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.TransactionGuard
import com.intellij.openapi.application.TransactionGuardImpl
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.ExtensionsArea
import com.intellij.openapi.fileTypes.PlainTextFileType
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.LanguageLevelProjectExtension
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.*
import com.intellij.openapi.vfs.impl.ZipHandler
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiManager
import com.intellij.psi.compiled.ClassFileDecompilers
import com.intellij.psi.impl.JavaClassSupersImpl
import com.intellij.psi.impl.PsiElementFinderImpl
import com.intellij.psi.impl.PsiTreeChangePreprocessor
import com.intellij.psi.impl.file.impl.JavaFileManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.JavaClassSupers
import com.intellij.util.io.URLUtil
import com.intellij.util.lang.UrlClassLoader
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.FacadeCache
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
import org.jetbrains.kotlin.cli.common.config.ContentRoot
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.extensions.ShellExtension
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.index.*
import org.jetbrains.kotlin.cli.jvm.javac.JavacWrapperRegistrar
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.extensions.*
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptor
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver
import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.nio.file.FileSystems
import java.util.zip.ZipFile
class KotlinCoreEnvironment private constructor(
val projectEnvironment: JavaCoreProjectEnvironment,
private val initialConfiguration: CompilerConfiguration,
configFiles: EnvironmentConfigFiles
) {
class ProjectEnvironment(
disposable: Disposable,
applicationEnvironment: KotlinCoreApplicationEnvironment
) :
KotlinCoreProjectEnvironment(disposable, applicationEnvironment) {
private var extensionRegistered = false
override fun preregisterServices() {
registerProjectExtensionPoints(project.extensionArea)
}
fun registerExtensionsFromPlugins(configuration: CompilerConfiguration) {
if (!extensionRegistered) {
registerPluginExtensionPoints(project)
registerExtensionsFromPlugins(project, configuration)
extensionRegistered = true
}
}
override fun registerJavaPsiFacade() {
with(project) {
registerService(
CoreJavaFileManager::class.java,
ServiceManager.getService(this, JavaFileManager::class.java) as CoreJavaFileManager
)
registerKotlinLightClassSupport(project)
registerService(ExternalAnnotationsManager::class.java, MockExternalAnnotationsManager())
registerService(InferredAnnotationsManager::class.java, MockInferredAnnotationsManager())
}
super.registerJavaPsiFacade()
}
}
private val sourceFiles = mutableListOf<KtFile>()
private val rootsIndex: JvmDependenciesDynamicCompoundIndex
private val packagePartProviders = mutableListOf<JvmPackagePartProvider>()
private val classpathRootsResolver: ClasspathRootsResolver
private val initialRoots = ArrayList<JavaRoot>()
val configuration: CompilerConfiguration = initialConfiguration.apply { setupJdkClasspathRoots(configFiles) }.copy()
init {
PersistentFSConstants::class.java.getDeclaredField("ourMaxIntellisenseFileSize")
.apply { isAccessible = true }
.setInt(null, FileUtilRt.LARGE_FOR_CONTENT_LOADING)
val project = projectEnvironment.project
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
(projectEnvironment as? ProjectEnvironment)?.registerExtensionsFromPlugins(configuration)
// otherwise consider that project environment is properly configured before passing to the environment
// TODO: consider some asserts to check important extension points
project.registerService(DeclarationProviderFactoryService::class.java, CliDeclarationProviderFactoryService(sourceFiles))
val isJvm = configFiles == EnvironmentConfigFiles.JVM_CONFIG_FILES
project.registerService(ModuleVisibilityManager::class.java, CliModuleVisibilityManagerImpl(isJvm))
registerProjectServicesForCLI(projectEnvironment)
registerProjectServices(projectEnvironment.project)
for (extension in CompilerConfigurationExtension.getInstances(project)) {
extension.updateConfiguration(configuration)
}
sourceFiles += createKtFiles(project)
collectAdditionalSources(project)
sourceFiles.sortBy { it.virtualFile.path }
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
})
val outputDirectory =
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)?.absolutePath
classpathRootsResolver = ClasspathRootsResolver(
PsiManager.getInstance(project),
messageCollector,
configuration.getList(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES),
this::contentRootToVirtualFile,
javaModuleFinder,
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
outputDirectory?.let(this::findLocalFile)
)
val (initialRoots, javaModules) =
classpathRootsResolver.convertClasspathRoots(configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS))
this.initialRoots.addAll(initialRoots)
if (!configuration.getBoolean(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK) && messageCollector != null) {
JvmRuntimeVersionsConsistencyChecker.checkCompilerClasspathConsistency(
messageCollector,
configuration,
initialRoots.mapNotNull { (file, type) -> if (type == JavaRoot.RootType.BINARY) file else null }
)
}
val (roots, singleJavaFileRoots) =
initialRoots.partition { (file) -> file.isDirectory || file.extension != JavaFileType.DEFAULT_EXTENSION }
// REPL and kapt2 update classpath dynamically
rootsIndex = JvmDependenciesDynamicCompoundIndex().apply {
addIndex(JvmDependenciesIndexImpl(roots))
updateClasspathFromRootsIndex(this)
}
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
rootsIndex,
packagePartProviders,
SingleJavaFileRootsIndex(singleJavaFileRoots),
configuration.getBoolean(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING)
)
project.registerService(
JavaModuleResolver::class.java,
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)
project.registerService(MetadataFinderFactory::class.java, finderFactory)
project.registerService(VirtualFileFinderFactory::class.java, finderFactory)
project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, fun(roots: List<File>) {
updateClasspath(roots.map { JavaSourceRoot(it, null) })
})
}
private fun collectAdditionalSources(project: MockProject) {
var unprocessedSources: Collection<KtFile> = sourceFiles
val processedSources = HashSet<KtFile>()
val processedSourcesByExtension = HashMap<CollectAdditionalSourcesExtension, Collection<KtFile>>()
// repeat feeding extensions with sources while new sources a being added
var sourceCollectionIterations = 0
while (unprocessedSources.isNotEmpty()) {
if (sourceCollectionIterations++ > 10) { // TODO: consider using some appropriate global constant
throw IllegalStateException("Unable to collect additional sources in reasonable number of iterations")
}
processedSources.addAll(unprocessedSources)
val allNewSources = ArrayList<KtFile>()
for (extension in CollectAdditionalSourcesExtension.getInstances(project)) {
// do not feed the extension with the sources it returned on the previous iteration
val sourcesToProcess = unprocessedSources - (processedSourcesByExtension[extension] ?: emptyList())
val newSources = extension.collectAdditionalSourcesAndUpdateConfiguration(sourcesToProcess, configuration, project)
if (newSources.isNotEmpty()) {
allNewSources.addAll(newSources)
processedSourcesByExtension[extension] = newSources
}
}
unprocessedSources = allNewSources.filterNot { processedSources.contains(it) }.distinct()
sourceFiles += unprocessedSources
}
}
fun addKotlinSourceRoots(rootDirs: List<File>) {
val roots = rootDirs.map { KotlinSourceRoot(it.absolutePath, isCommon = false) }
sourceFiles += createSourceFilesFromSourceRoots(configuration, project, roots)
}
fun createPackagePartProvider(scope: GlobalSearchScope): JvmPackagePartProvider {
return JvmPackagePartProvider(configuration.languageVersionSettings, scope).apply {
addRoots(initialRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY))
packagePartProviders += this
(ModuleAnnotationsResolver.getInstance(project) as CliModuleAnnotationsResolver).addPackagePartProvider(this)
}
}
private val VirtualFile.javaFiles: List<VirtualFile>
get() = mutableListOf<VirtualFile>().apply {
VfsUtilCore.processFilesRecursively(this@javaFiles) { file ->
if (file.fileType == JavaFileType.INSTANCE) {
add(file)
}
true
}
}
private val allJavaFiles: List<File>
get() = configuration.javaSourceRoots
.mapNotNull(this::findLocalFile)
.flatMap { it.javaFiles }
.map { File(it.canonicalPath) }
fun registerJavac(
javaFiles: List<File> = allJavaFiles,
kotlinFiles: List<KtFile> = sourceFiles,
arguments: Array<String>? = null,
bootClasspath: List<File>? = null,
sourcePath: List<File>? = null
): Boolean {
return JavacWrapperRegistrar.registerJavac(
projectEnvironment.project, configuration, javaFiles, kotlinFiles, arguments, bootClasspath, sourcePath,
LightClassGenerationSupport.getInstance(project), packagePartProviders
)
}
private val applicationEnvironment: CoreApplicationEnvironment
get() = projectEnvironment.environment
val project: Project
get() = projectEnvironment.project
internal fun countLinesOfCode(sourceFiles: List<KtFile>): Int =
sourceFiles.sumBy { sourceFile ->
val text = sourceFile.text
StringUtil.getLineBreakCount(text) + (if (StringUtil.endsWithLineBreak(text)) 0 else 1)
}
private fun updateClasspathFromRootsIndex(index: JvmDependenciesIndex) {
index.indexedRoots.forEach {
projectEnvironment.addSourcesToClasspath(it.file)
}
}
fun updateClasspath(contentRoots: List<ContentRoot>): List<File>? {
// TODO: add new Java modules to CliJavaModuleResolver
val newRoots = classpathRootsResolver.convertClasspathRoots(contentRoots).roots
if (packagePartProviders.isEmpty()) {
initialRoots.addAll(newRoots)
} else {
for (packagePartProvider in packagePartProviders) {
packagePartProvider.addRoots(newRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY))
}
}
return rootsIndex.addNewIndexForRoots(newRoots)?.let { newIndex ->
updateClasspathFromRootsIndex(newIndex)
newIndex.indexedRoots.mapNotNull { (file) ->
VfsUtilCore.virtualToIoFile(VfsUtilCore.getVirtualFileForJar(file) ?: file)
}.toList()
}.orEmpty()
}
private fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? =
when (root) {
is JvmClasspathRoot ->
if (root.file.isFile) findJarRoot(root.file) else findExistingRoot(root, "Classpath entry")
is JvmModulePathRoot ->
if (root.file.isFile) findJarRoot(root.file) else findExistingRoot(root, "Java module root")
is JavaSourceRoot ->
findExistingRoot(root, "Java source root")
else ->
throw IllegalStateException("Unexpected root: $root")
}
internal fun findLocalFile(path: String): VirtualFile? =
applicationEnvironment.localFileSystem.findFileByPath(path)
private fun findExistingRoot(root: JvmContentRoot, rootDescription: String): VirtualFile? {
return findLocalFile(root.file.absolutePath).also {
if (it == null) {
report(STRONG_WARNING, "$rootDescription points to a non-existent location: ${root.file}")
}
}
}
private fun findJarRoot(file: File): VirtualFile? =
applicationEnvironment.jarFileSystem.findFileByPath("$file${URLUtil.JAR_SEPARATOR}")
private fun getSourceRootsCheckingForDuplicates(): List<KotlinSourceRoot> {
val uniqueSourceRoots = hashSetOf<String>()
val result = mutableListOf<KotlinSourceRoot>()
for (root in configuration.kotlinSourceRoots) {
if (!uniqueSourceRoots.add(root.path)) {
report(STRONG_WARNING, "Duplicate source root: ${root.path}")
}
result.add(root)
}
return result
}
fun getSourceFiles(): List<KtFile> = sourceFiles
private fun createKtFiles(project: Project): List<KtFile> =
createSourceFilesFromSourceRoots(configuration, project, getSourceRootsCheckingForDuplicates())
internal fun report(severity: CompilerMessageSeverity, message: String) = configuration.report(severity, message)
companion object {
private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
private val APPLICATION_LOCK = Object()
private var ourApplicationEnvironment: KotlinCoreApplicationEnvironment? = null
private var ourProjectCount = 0
@JvmStatic
fun createForProduction(
parentDisposable: Disposable, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles
): KotlinCoreEnvironment {
setupIdeaStandaloneExecution()
val appEnv = getOrCreateApplicationEnvironmentForProduction(parentDisposable, configuration)
val projectEnv = ProjectEnvironment(parentDisposable, appEnv)
val environment = KotlinCoreEnvironment(projectEnv, configuration, configFiles)
synchronized(APPLICATION_LOCK) {
ourProjectCount++
}
return environment
}
@JvmStatic
fun createForProduction(
projectEnvironment: JavaCoreProjectEnvironment, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles
): KotlinCoreEnvironment {
val environment = KotlinCoreEnvironment(projectEnvironment, configuration, configFiles)
if (projectEnvironment.environment == applicationEnvironment) {
// accounting for core environment disposing
synchronized(APPLICATION_LOCK) {
ourProjectCount++
}
}
return environment
}
@TestOnly
@JvmStatic
fun createForTests(
parentDisposable: Disposable, initialConfiguration: CompilerConfiguration, extensionConfigs: EnvironmentConfigFiles
): KotlinCoreEnvironment {
val configuration = initialConfiguration.copy()
// Tests are supposed to create a single project and dispose it right after use
val appEnv = createApplicationEnvironment(parentDisposable, configuration, unitTestMode = true)
val projectEnv = ProjectEnvironment(parentDisposable, appEnv)
return KotlinCoreEnvironment(projectEnv, configuration, extensionConfigs)
}
// used in the daemon for jar cache cleanup
val applicationEnvironment: KotlinCoreApplicationEnvironment? get() = ourApplicationEnvironment
fun getOrCreateApplicationEnvironmentForProduction(
parentDisposable: Disposable, configuration: CompilerConfiguration
): KotlinCoreApplicationEnvironment {
synchronized(APPLICATION_LOCK) {
if (ourApplicationEnvironment == null) {
val disposable = Disposer.newDisposable()
ourApplicationEnvironment = createApplicationEnvironment(disposable, configuration, unitTestMode = false)
ourProjectCount = 0
Disposer.register(disposable, Disposable {
synchronized(APPLICATION_LOCK) {
ourApplicationEnvironment = null
}
})
}
// Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally
// breaks a lot of tests, therefore it is disabled for production and enabled for tests
if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY).toBooleanLenient() != true) {
// JPS may run many instances of the compiler in parallel (there's an option for compiling independent modules in parallel in IntelliJ)
// All projects share the same ApplicationEnvironment, and when the last project is disposed, the ApplicationEnvironment is disposed as well
@Suppress("ObjectLiteralToLambda") // Disposer tree depends on identity of disposables.
Disposer.register(parentDisposable, object : Disposable {
override fun dispose() {
synchronized(APPLICATION_LOCK) {
if (--ourProjectCount <= 0) {
disposeApplicationEnvironment()
}
}
}
})
}
return ourApplicationEnvironment!!
}
}
/**
* This method is also used in Gradle after configuration phase finished.
*/
fun disposeApplicationEnvironment() {
synchronized(APPLICATION_LOCK) {
val environment = ourApplicationEnvironment ?: return
ourApplicationEnvironment = null
Disposer.dispose(environment.parentDisposable)
ZipHandler.clearFileAccessorCache()
}
}
private fun createApplicationEnvironment(
parentDisposable: Disposable, configuration: CompilerConfiguration, unitTestMode: Boolean
): KotlinCoreApplicationEnvironment {
val applicationEnvironment = KotlinCoreApplicationEnvironment.create(parentDisposable, unitTestMode)
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/compiler.xml")
// FIX ME WHEN BUNCH 202 REMOVED: this code is required to support compiler bundled to both 202 and 203.
// Please, remove "com.intellij.psi.classFileDecompiler" EP registration once 202 is no longer supported by the compiler
if (!Extensions.getRootArea().hasExtensionPoint("com.intellij.psi.classFileDecompiler")) {
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/core.xml")
}
registerApplicationServicesForCLI(applicationEnvironment)
registerApplicationServices(applicationEnvironment)
return applicationEnvironment
}
private fun registerApplicationExtensionPointsAndExtensionsFrom(configuration: CompilerConfiguration, configFilePath: String) {
fun File.hasConfigFile(configFile: String): Boolean =
if (isDirectory) File(this, "META-INF" + File.separator + configFile).exists()
else try {
ZipFile(this).use {
it.getEntry("META-INF/$configFile") != null
}
} catch (e: Throwable) {
false
}
val pluginRoot: File =
configuration.get(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT)?.let(::File)
?: PathUtil.getResourcePathForClass(this::class.java).takeIf { it.hasConfigFile(configFilePath) }
// hack for load extensions when compiler run directly from project directory (e.g. in tests)
?: File("compiler/cli/cli-common/resources").takeIf { it.hasConfigFile(configFilePath) }
?: throw IllegalStateException(
"Unable to find extension point configuration $configFilePath " +
"(cp:\n ${(Thread.currentThread().contextClassLoader as? UrlClassLoader)?.urls?.joinToString("\n ") { it.file }})"
)
CoreApplicationEnvironment.registerExtensionPointAndExtensions(
FileSystems.getDefault().getPath(pluginRoot.path),
configFilePath,
Extensions.getRootArea()
)
}
@JvmStatic
@Suppress("MemberVisibilityCanPrivate") // made public for CLI Android Lint
fun registerPluginExtensionPoints(project: MockProject) {
ExpressionCodegenExtension.registerExtensionPoint(project)
SyntheticResolveExtension.registerExtensionPoint(project)
ClassBuilderInterceptorExtension.registerExtensionPoint(project)
AnalysisHandlerExtension.registerExtensionPoint(project)
PackageFragmentProviderExtension.registerExtensionPoint(project)
StorageComponentContainerContributor.registerExtensionPoint(project)
DeclarationAttributeAltererExtension.registerExtensionPoint(project)
PreprocessedVirtualFileFactoryExtension.registerExtensionPoint(project)
JsSyntheticTranslateExtension.registerExtensionPoint(project)
CompilerConfigurationExtension.registerExtensionPoint(project)
CollectAdditionalSourcesExtension.registerExtensionPoint(project)
ExtraImportsProviderExtension.registerExtensionPoint(project)
IrGenerationExtension.registerExtensionPoint(project)
ScriptEvaluationExtension.registerExtensionPoint(project)
ShellExtension.registerExtensionPoint(project)
TypeResolutionInterceptor.registerExtensionPoint(project)
CandidateInterceptor.registerExtensionPoint(project)
DescriptorSerializerPlugin.registerExtensionPoint(project)
}
internal fun registerExtensionsFromPlugins(project: MockProject, configuration: CompilerConfiguration) {
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
for (registrar in configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) {
try {
registrar.registerProjectComponents(project, configuration)
} catch (e: AbstractMethodError) {
val message = "The provided plugin ${registrar.javaClass.name} is not compatible with this version of compiler"
// Since the scripting plugin is often discovered in the compiler environment, it is often taken from the incompatible
// location, and in many cases this is not a fatal error, therefore strong warning is generated instead of exception
if (registrar.javaClass.simpleName == "ScriptingCompilerConfigurationComponentRegistrar") {
messageCollector?.report(STRONG_WARNING, "Default scripting plugin is disabled: $message")
} else {
throw IllegalStateException(message, e)
}
}
}
}
private fun registerApplicationServicesForCLI(applicationEnvironment: KotlinCoreApplicationEnvironment) {
// ability to get text from annotations xml files
applicationEnvironment.registerFileType(PlainTextFileType.INSTANCE, "xml")
applicationEnvironment.registerParserDefinition(JavaParserDefinition())
}
// made public for Upsource
@Suppress("MemberVisibilityCanBePrivate")
@JvmStatic
fun registerApplicationServices(applicationEnvironment: KotlinCoreApplicationEnvironment) {
with(applicationEnvironment) {
registerFileType(KotlinFileType.INSTANCE, "kt")
registerFileType(KotlinFileType.INSTANCE, KotlinParserDefinition.STD_SCRIPT_SUFFIX)
registerParserDefinition(KotlinParserDefinition())
application.registerService(KotlinBinaryClassCache::class.java, KotlinBinaryClassCache())
application.registerService(JavaClassSupers::class.java, JavaClassSupersImpl::class.java)
application.registerService(TransactionGuard::class.java, TransactionGuardImpl::class.java)
}
}
@JvmStatic
fun registerProjectExtensionPoints(area: ExtensionsArea) {
CoreApplicationEnvironment.registerExtensionPoint(
area, PsiTreeChangePreprocessor.EP.name, PsiTreeChangePreprocessor::class.java
)
CoreApplicationEnvironment.registerExtensionPoint(area, PsiElementFinder.EP.name, PsiElementFinder::class.java)
IdeaExtensionPoints.registerVersionSpecificProjectExtensionPoints(area)
}
// made public for Upsource
@JvmStatic
@Deprecated("Use registerProjectServices(project) instead.", ReplaceWith("registerProjectServices(projectEnvironment.project)"))
fun registerProjectServices(
projectEnvironment: JavaCoreProjectEnvironment,
@Suppress("UNUSED_PARAMETER") messageCollector: MessageCollector?
) {
registerProjectServices(projectEnvironment.project)
}
// made public for Android Lint
@JvmStatic
fun registerProjectServices(project: MockProject) {
with(project) {
registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this))
registerService(FacadeCache::class.java, FacadeCache(this))
registerService(ModuleAnnotationsResolver::class.java, CliModuleAnnotationsResolver())
}
}
private fun registerProjectServicesForCLI(@Suppress("UNUSED_PARAMETER") projectEnvironment: JavaCoreProjectEnvironment) {
/**
* Note that Kapt may restart code analysis process, and CLI services should be aware of that.
* Use PsiManager.getModificationTracker() to ensure that all the data you cached is still valid.
*/
}
// made public for Android Lint
@JvmStatic
fun registerKotlinLightClassSupport(project: MockProject) {
with(project) {
val traceHolder = CliTraceHolder()
val cliLightClassGenerationSupport = CliLightClassGenerationSupport(traceHolder, project)
val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder)
registerService(LightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(CliLightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(KotlinAsJavaSupport::class.java, kotlinAsJavaSupport)
registerService(CodeAnalyzerInitializer::class.java, traceHolder)
// We don't pass Disposable because in some tests, we manually unregister these extensions, and that leads to LOG.error
// exception from `ExtensionPointImpl.doRegisterExtension`, because the registered extension can no longer be found
// when the project is being disposed.
// For example, see the `unregisterExtension` call in `GenerationUtils.compileFilesUsingFrontendIR`.
// TODO: refactor this to avoid registering unneeded extensions in the first place, and avoid using deprecated API.
@Suppress("DEPRECATION")
PsiElementFinder.EP.getPoint(project).registerExtension(JavaElementFinder(this, kotlinAsJavaSupport))
@Suppress("DEPRECATION")
PsiElementFinder.EP.getPoint(project).registerExtension(PsiElementFinderImpl(this))
}
}
private fun CompilerConfiguration.setupJdkClasspathRoots(configFiles: EnvironmentConfigFiles) {
if (getBoolean(JVMConfigurationKeys.NO_JDK)) return
val jvmTarget = configFiles == EnvironmentConfigFiles.JVM_CONFIG_FILES
if (!jvmTarget) return
val jdkHome = get(JVMConfigurationKeys.JDK_HOME)
val (javaRoot, classesRoots) = if (jdkHome == null) {
val javaHome = File(System.getProperty("java.home"))
put(JVMConfigurationKeys.JDK_HOME, javaHome)
javaHome to PathUtil.getJdkClassesRootsFromCurrentJre()
} else {
jdkHome to PathUtil.getJdkClassesRoots(jdkHome)
}
if (!CoreJrtFileSystem.isModularJdk(javaRoot)) {
if (classesRoots.isEmpty()) {
report(ERROR, "No class roots are found in the JDK path: $javaRoot")
} else {
addJvmSdkRoots(classesRoots)
}
}
}
}
}
@@ -686,4 +686,4 @@ class KotlinCoreEnvironment private constructor(
} }
} }
} }
} }
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.* import com.intellij.openapi.vfs.*
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiJavaModule import com.intellij.psi.PsiJavaModule
import com.intellij.psi.search.DelegatingGlobalSearchScope import com.intellij.psi.search.DelegatingGlobalSearchScope
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.jvmPhases import org.jetbrains.kotlin.backend.jvm.jvmPhases
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
@@ -53,9 +53,7 @@ import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.* import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.fir.FirPsiSourceElement
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
@@ -71,7 +69,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.diagnostics.SimpleDiagnostics import org.jetbrains.kotlin.resolve.diagnostics.SimpleGenericDiagnostics
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
@@ -342,9 +340,7 @@ object KotlinToJVMBytecodeCompiler {
firAnalyzerFacade.runResolution() firAnalyzerFacade.runResolution()
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten() val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
AnalyzerWithCompilerReport.reportDiagnostics( AnalyzerWithCompilerReport.reportDiagnostics(
SimpleDiagnostics( SimpleGenericDiagnostics(firDiagnostics),
firDiagnostics.map { it.toRegularDiagnostic() }
),
environment.messageCollector environment.messageCollector
) )
performanceManager?.notifyAnalysisFinished() performanceManager?.notifyAnalysisFinished()
@@ -356,7 +352,8 @@ object KotlinToJVMBytecodeCompiler {
performanceManager?.notifyGenerationStarted() performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted() performanceManager?.notifyIRTranslationStarted()
val (moduleFragment, symbolTable, sourceManager, components) = firAnalyzerFacade.convertToIr() val extensions = JvmGeneratorExtensions()
val (moduleFragment, symbolTable, sourceManager, components) = firAnalyzerFacade.convertToIr(extensions)
performanceManager?.notifyIRTranslationFinished() performanceManager?.notifyIRTranslationFinished()
@@ -392,9 +389,9 @@ object KotlinToJVMBytecodeCompiler {
performanceManager?.notifyIRGenerationStarted() performanceManager?.notifyIRGenerationStarted()
generationState.beforeCompile() generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode( codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager generationState, moduleFragment, symbolTable, sourceManager, extensions
) { context, irClass, _, serializationBindings, parent -> ) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent) FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent)
} }
CodegenFactory.doCheckCancelled(generationState) CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done() generationState.factory.done()
@@ -427,30 +424,6 @@ object KotlinToJVMBytecodeCompiler {
return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName) return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName)
} }
private fun FirDiagnostic<*>.toRegularDiagnostic(): Diagnostic {
val psiSource = element as FirPsiSourceElement<*>
@Suppress("UNCHECKED_CAST")
when (this) {
is FirSimpleDiagnostic ->
return SimpleDiagnostic(
psiSource.psi, factory.psiDiagnosticFactory as DiagnosticFactory0<PsiElement>, severity
)
is FirDiagnosticWithParameters1<*, *> ->
return DiagnosticWithParameters1(
psiSource.psi, this.a, factory.psiDiagnosticFactory as DiagnosticFactory1<PsiElement, Any>, severity
)
is FirDiagnosticWithParameters2<*, *, *> ->
return DiagnosticWithParameters2(
psiSource.psi, this.a, this.b, factory.psiDiagnosticFactory as DiagnosticFactory2<PsiElement, Any, Any>, severity
)
is FirDiagnosticWithParameters3<*, *, *, *> ->
return DiagnosticWithParameters3(
psiSource.psi, this.a, this.b, this.c,
factory.psiDiagnosticFactory as DiagnosticFactory3<PsiElement, Any, Any, Any>, severity
)
}
}
private fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> = private fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> =
if (buildFile == null) sourceFilePaths if (buildFile == null) sourceFilePaths
else sourceFilePaths.map { path -> else sourceFilePaths.map { path ->
@@ -490,6 +463,10 @@ object KotlinToJVMBytecodeCompiler {
environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) }) environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) })
} }
if (result.additionalClassPathRoots.isNotEmpty()) {
environment.updateClasspath(result.additionalClassPathRoots.map { JvmClasspathRoot(it, false) })
}
if (result.additionalKotlinRoots.isNotEmpty()) { if (result.additionalKotlinRoots.isNotEmpty()) {
environment.addKotlinSourceRoots(result.additionalKotlinRoots) environment.addKotlinSourceRoots(result.additionalKotlinRoots)
} }
@@ -499,8 +476,8 @@ object KotlinToJVMBytecodeCompiler {
// Clear all diagnostic messages // Clear all diagnostic messages
configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear() configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear()
// Repeat analysis with additional Java roots (kapt generated sources) // Repeat analysis with additional source roots generated by compiler plugins.
return analyze(environment) return repeatAnalysisIfNeeded(analyze(environment), environment)
} }
return result return result
@@ -12,4 +12,6 @@ fun setupIdeaStandaloneExecution() {
System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000") System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000")
System.getProperties().setProperty("ide.hide.excluded.files", "false") System.getProperties().setProperty("ide.hide.excluded.files", "false")
System.getProperties().setProperty("ast.loading.filter", "false") System.getProperties().setProperty("ast.loading.filter", "false")
System.getProperties().setProperty("idea.ignore.disabled.plugins", "true")
System.getProperties().setProperty("idea.home.path", System.getProperty("java.io.tmpdir"))
} }
@@ -12,6 +12,4 @@ fun setupIdeaStandaloneExecution() {
System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000") System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000")
System.getProperties().setProperty("ide.hide.excluded.files", "false") System.getProperties().setProperty("ide.hide.excluded.files", "false")
System.getProperties().setProperty("ast.loading.filter", "false") System.getProperties().setProperty("ast.loading.filter", "false")
System.getProperties().setProperty("idea.ignore.disabled.plugins", "true")
System.getProperties().setProperty("idea.home.path", System.getProperty("java.io.tmpdir"))
} }
@@ -39,7 +39,7 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
} }
val jvmTarget = get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT val jvmTarget = get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
if (jvmTarget.bytecodeVersion < JvmTarget.JVM_1_8.bytecodeVersion) { if (jvmTarget.majorVersion < JvmTarget.JVM_1_8.majorVersion) {
val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode) val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
if (jvmDefaultMode.forAllMethodsWithBody) { if (jvmDefaultMode.forAllMethodsWithBody) {
messageCollector.report( messageCollector.report(
@@ -53,7 +53,7 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
val runtimeStringConcat = JvmStringConcat.fromString(arguments.stringConcat!!) val runtimeStringConcat = JvmStringConcat.fromString(arguments.stringConcat!!)
if (runtimeStringConcat != null) { if (runtimeStringConcat != null) {
put(JVMConfigurationKeys.STRING_CONCAT, runtimeStringConcat) put(JVMConfigurationKeys.STRING_CONCAT, runtimeStringConcat)
if (jvmTarget.bytecodeVersion < JvmTarget.JVM_9.bytecodeVersion && runtimeStringConcat != JvmStringConcat.INLINE) { if (jvmTarget.majorVersion < JvmTarget.JVM_9.majorVersion && runtimeStringConcat != JvmStringConcat.INLINE) {
messageCollector.report( messageCollector.report(
WARNING, WARNING,
"`-Xstring-concat=${arguments.stringConcat}` does nothing with JVM target `${jvmTarget.description}`." "`-Xstring-concat=${arguments.stringConcat}` does nothing with JVM target `${jvmTarget.description}`."
@@ -61,8 +61,8 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
} }
} else { } else {
messageCollector.report( messageCollector.report(
ERROR, "Unknown `string-concat` mode: ${arguments.jvmTarget}\n" + ERROR, "Unknown -Xstring-concat mode: ${arguments.jvmTarget}\n" +
"Supported versions: ${JvmStringConcat.values().joinToString { it.name.toLowerCase() }}" "Supported versions: ${JvmStringConcat.values().joinToString { it.description }}"
) )
} }
} }
@@ -232,6 +232,12 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule) put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
put(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS, arguments.useOldSpilledVarTypeAnalysis) put(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS, arguments.useOldSpilledVarTypeAnalysis)
put(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME, arguments.useOldInlineClassesManglingScheme) put(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME, arguments.useOldInlineClassesManglingScheme)
put(JVMConfigurationKeys.ENABLE_JVM_PREVIEW, arguments.enableJvmPreview)
if (arguments.enableJvmPreview) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
.report(INFO, "Using preview Java language features")
}
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) } arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
} }
@@ -242,4 +248,4 @@ fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments)
?.toTypedArray() ?.toTypedArray()
?.filterNot { it.isEmpty() } ?.filterNot { it.isEmpty() }
?.let { put(JVMConfigurationKeys.KLIB_PATHS, it) } ?.let { put(JVMConfigurationKeys.KLIB_PATHS, it) }
} }
@@ -140,4 +140,7 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> USE_OLD_INLINE_CLASSES_MANGLING_SCHEME = public static final CompilerConfigurationKey<Boolean> USE_OLD_INLINE_CLASSES_MANGLING_SCHEME =
CompilerConfigurationKey.create("Use old, 1.4 version of inline classes mangling scheme"); CompilerConfigurationKey.create("Use old, 1.4 version of inline classes mangling scheme");
public static final CompilerConfigurationKey<Boolean> ENABLE_JVM_PREVIEW =
CompilerConfigurationKey.create("Enable Java language preview features");
} }
@@ -33,6 +33,9 @@ object JvmAnalysisFlags {
@JvmStatic @JvmStatic
val disableUltraLightClasses by AnalysisFlag.Delegates.Boolean val disableUltraLightClasses by AnalysisFlag.Delegates.Boolean
@JvmStatic
val enableJvmPreview by AnalysisFlag.Delegates.Boolean
private object Delegates { private object Delegates {
object JavaTypeEnhancementStateWarnByDefault { object JavaTypeEnhancementStateWarnByDefault {
operator fun provideDelegate(instance: Any?, property: KProperty<*>): AnalysisFlag.Delegate<JavaTypeEnhancementState> = operator fun provideDelegate(instance: Any?, property: KProperty<*>): AnalysisFlag.Delegate<JavaTypeEnhancementState> =
@@ -19,32 +19,21 @@ package org.jetbrains.kotlin.config
import org.jetbrains.kotlin.platform.TargetPlatformVersion import org.jetbrains.kotlin.platform.TargetPlatformVersion
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
enum class JvmTarget(override val description: String) : TargetPlatformVersion { enum class JvmTarget(
JVM_1_6("1.6"), override val description: String,
JVM_1_8("1.8"), val majorVersion: Int,
JVM_9("9"), ) : TargetPlatformVersion {
JVM_10("10"), JVM_1_6("1.6", Opcodes.V1_6),
JVM_11("11"), JVM_1_8("1.8", Opcodes.V1_8),
JVM_12("12"), JVM_9("9", Opcodes.V9),
JVM_13("13"), JVM_10("10", Opcodes.V10),
JVM_14("14"), JVM_11("11", Opcodes.V11),
JVM_15("15"), JVM_12("12", Opcodes.V12),
JVM_13("13", Opcodes.V12 + 1),
JVM_14("14", Opcodes.V12 + 2),
JVM_15("15", Opcodes.V12 + 3),
; ;
val bytecodeVersion: Int by lazy {
when (this) {
JVM_1_6 -> Opcodes.V1_6
JVM_1_8 -> Opcodes.V1_8
JVM_9 -> Opcodes.V9
JVM_10 -> Opcodes.V10
JVM_11 -> Opcodes.V11
JVM_12 -> Opcodes.V12
JVM_13 -> Opcodes.V12 + 1
JVM_14 -> Opcodes.V12 + 2
JVM_15 -> Opcodes.V12 + 3
}
}
companion object { companion object {
@JvmField @JvmField
val DEFAULT = JVM_1_6 val DEFAULT = JVM_1_6
@@ -52,14 +41,14 @@ enum class JvmTarget(override val description: String) : TargetPlatformVersion {
@JvmStatic @JvmStatic
fun fromString(string: String) = values().find { it.description == string } fun fromString(string: String) = values().find { it.description == string }
fun getDescription(bytecodeVersion: Int): String { fun getDescription(majorVersion: Int): String {
val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?: when (bytecodeVersion) { val platformDescription = values().find { it.majorVersion == majorVersion }?.description ?: when (majorVersion) {
Opcodes.V1_7 -> "1.7" Opcodes.V1_7 -> "1.7"
else -> null else -> null
} }
return if (platformDescription != null) "JVM target $platformDescription" return if (platformDescription != null) "JVM target $platformDescription"
else "JVM bytecode version $bytecodeVersion" else "JVM bytecode version $majorVersion"
} }
} }
} }
+15 -1
View File
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.ideaExt.idea
/* /*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
@@ -29,9 +31,21 @@ dependencies {
testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") } testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") }
} }
val generationRoot = projectDir.resolve("tests-gen")
sourceSets { sourceSets {
"main" { none() } "main" { none() }
"test" { projectDefault() } "test" {
projectDefault()
this.java.srcDir(generationRoot.name)
}
}
if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
apply(plugin = "idea")
idea {
this.module.generatedSourceDirs.add(generationRoot)
}
} }
projectTest(parallel = true) { projectTest(parallel = true) {
@@ -1,4 +1,4 @@
@R|java/lang/annotation/Documented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.NEVER|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) public abstract annotation class MyNullable : R|kotlin/Annotation| { @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.NEVER|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public abstract annotation class MyNullable : R|kotlin/Annotation| {
public constructor(): R|MyNullable| public constructor(): R|MyNullable|
} }
@@ -10,7 +10,7 @@
public constructor(): R|A| public constructor(): R|A|
} }
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| { @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| {
public constructor(): R|FieldsAreNullable| public constructor(): R|FieldsAreNullable|
} }
@@ -6,19 +6,19 @@
public constructor(): R|A| public constructor(): R|A|
} }
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|kotlin/Annotation| { @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|kotlin/Annotation| {
public constructor(): R|spr/ForceFlexibility| public constructor(): R|spr/ForceFlexibility|
} }
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi| public constructor(): R|spr/NonNullApi|
} }
@R|java/lang/annotation/Target|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| {
public constructor(): R|spr/Nullable| public constructor(): R|spr/Nullable|
} }
@R|java/lang/annotation/Documented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) public abstract annotation class UnknownNullability : R|kotlin/Annotation| { @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public abstract annotation class UnknownNullability : R|kotlin/Annotation| {
public constructor(): R|spr/UnknownNullability| public constructor(): R|spr/UnknownNullability|
} }
@@ -20,15 +20,15 @@ public abstract interface B : R|kotlin/Any| {
public abstract fun foobar(@R|javax/annotation/Nonnull|() x: R|@EnhancedNullability kotlin/String|): R|kotlin/Unit| public abstract fun foobar(@R|javax/annotation/Nonnull|() x: R|@EnhancedNullability kotlin/String|): R|kotlin/Unit|
} }
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|kotlin/Annotation| { @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|kotlin/Annotation| {
public constructor(): R|spr/ForceFlexibility| public constructor(): R|spr/ForceFlexibility|
} }
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi| public constructor(): R|spr/NonNullApi|
} }
@R|java/lang/annotation/Documented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) public abstract annotation class UnknownNullability : R|kotlin/Annotation| { @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) public abstract annotation class UnknownNullability : R|kotlin/Annotation| {
public constructor(): R|spr/UnknownNullability| public constructor(): R|spr/UnknownNullability|
} }
@@ -54,11 +54,11 @@
public constructor(): R|C| public constructor(): R|C|
} }
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|NonNullApi| public constructor(): R|NonNullApi|
} }
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|kotlin/Annotation| {
public constructor(): R|NullableApi| public constructor(): R|NullableApi|
} }
@@ -12,15 +12,15 @@
public constructor(): R|A| public constructor(): R|A|
} }
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| { @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| {
public constructor(): R|FieldsAreNullable| public constructor(): R|FieldsAreNullable|
} }
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| { @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|NonNullApi| public constructor(): R|NonNullApi|
} }
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|kotlin/Annotation| { @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|kotlin/Annotation| {
public constructor(): R|NullableApi| public constructor(): R|NullableApi|
} }
@@ -10,11 +10,11 @@
public constructor(): R|A| public constructor(): R|A|
} }
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.CLASS|(), R|kotlin/annotation/AnnotationTarget.FILE|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi| public constructor(): R|spr/NonNullApi|
} }
@R|java/lang/annotation/Target|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| {
public constructor(): R|spr/Nullable| public constructor(): R|spr/Nullable|
} }
@@ -10,11 +10,11 @@ public open class A : R|kotlin/Any| {
public constructor(): R|test/A| public constructor(): R|test/A|
} }
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.PACKAGE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>()) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
public constructor(): R|spr/NonNullApi| public constructor(): R|spr/NonNullApi|
} }
@R|java/lang/annotation/Target|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(<implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|(), R|kotlin/annotation/AnnotationTarget.FUNCTION|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|(), R|kotlin/annotation/AnnotationTarget.PROPERTY_SETTER|())) @R|kotlin/annotation/Retention|(R|kotlin/annotation/AnnotationRetention.RUNTIME|()) @R|kotlin/annotation/MustBeDocumented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|kotlin/Annotation| {
public constructor(): R|spr/Nullable| public constructor(): R|spr/Nullable|
} }
@@ -1,9 +1,9 @@
FILE: RedundantSingleExpressionStringTemplateChecker.kt FILE: RedundantSingleExpressionStringTemplateChecker.kt
public final val x: R|kotlin/String| = String(Hello) public final val x: R|kotlin/String| = String(Hello)
public get(): R|kotlin/String| public get(): R|kotlin/String|
public final val y: R|kotlin/String| = R|/x|.R|kotlin/Any.toString|() public final val y: R|kotlin/String| = <strcat>(R|/x|.R|kotlin/Any.toString|())
public get(): R|kotlin/String| public get(): R|kotlin/String|
public final val z: R|kotlin/String| = R|/y|.R|kotlin/Any.hashCode|().R|kotlin/Any.toString|() public final val z: R|kotlin/String| = <strcat>(R|/y|.R|kotlin/Any.hashCode|().R|kotlin/Any.toString|())
public get(): R|kotlin/String| public get(): R|kotlin/String|
public final fun toString(x: R|kotlin/String|): R|kotlin/String| { public final fun toString(x: R|kotlin/String|): R|kotlin/String| {
^toString <strcat>(String(IC), R|<local>/x|.R|kotlin/Any.toString|()) ^toString <strcat>(String(IC), R|<local>/x|.R|kotlin/Any.toString|())
@@ -2,7 +2,7 @@ FILE: NotNullTypeChain.kt
public final val list1: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1)) public final val list1: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1))
public get(): R|kotlin/collections/List<kotlin/Int>| public get(): R|kotlin/collections/List<kotlin/Int>|
public final val list: R|kotlin/collections/List<kotlin/String>| = R|/list1|.R|kotlin/collections/orEmpty|<R|kotlin/Int|>().R|kotlin/collections/map|<R|kotlin/Int|, R|kotlin/String|>(<L> = map@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/String| <kind=UNKNOWN> { public final val list: R|kotlin/collections/List<kotlin/String>| = R|/list1|.R|kotlin/collections/orEmpty|<R|kotlin/Int|>().R|kotlin/collections/map|<R|kotlin/Int|, R|kotlin/String|>(<L> = map@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/String| <kind=UNKNOWN> {
^ R|<local>/it|.R|kotlin/Any.toString|() ^ <strcat>(R|<local>/it|.R|kotlin/Any.toString|())
} }
) )
public get(): R|kotlin/collections/List<kotlin/String>| public get(): R|kotlin/collections/List<kotlin/String>|
@@ -0,0 +1,7 @@
annotation class Ann(val value: Int)
fun foo(): Int {
val x = 3
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>x<!>) val y = 5
return y
}
@@ -0,0 +1,15 @@
FILE: usedInAnnotationArguments.kt
public final annotation class Ann : R|kotlin/Annotation| {
public constructor(value: R|kotlin/Int|): R|Ann| {
super<R|kotlin/Any|>()
}
public final val value: R|kotlin/Int| = R|<local>/value|
public get(): R|kotlin/Int|
}
public final fun foo(): R|kotlin/Int| {
lval x: R|kotlin/Int| = Int(3)
@R|Ann|(R|<local>/x|) lval y: R|kotlin/Int| = Int(5)
^foo R|<local>/y|
}
@@ -28,7 +28,7 @@ public final class Test : R|kotlin/Any| {
} }
public final inline class Z : R|kotlin/Any| { @R|kotlin/jvm/JvmInline|() public final inline class Z : R|kotlin/Any| {
public open operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| public open operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean|
public open fun hashCode(): R|kotlin/Int| public open fun hashCode(): R|kotlin/Int|
@@ -41,3 +41,4 @@ public final inline class Z : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|test/Z| public constructor(x: R|kotlin/Int|): R|test/Z|
} }
@@ -1,4 +1,4 @@
public final inline class Z : R|kotlin/Any| { @R|kotlin/jvm/JvmInline|() public final inline class Z : R|kotlin/Any| {
public open operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| public open operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean|
public open fun hashCode(): R|kotlin/Int| public open fun hashCode(): R|kotlin/Int|
@@ -11,3 +11,4 @@ public final inline class Z : R|kotlin/Any| {
@R|kotlin/PublishedApi|() internal constructor(value: R|kotlin/Int|): R|test/Z| @R|kotlin/PublishedApi|() internal constructor(value: R|kotlin/Int|): R|test/Z|
} }
@@ -40,6 +40,6 @@ public final const val s: R|kotlin/Short| = Short(20000)
public final const val s1: R|kotlin/Short| = Short(1) public final const val s1: R|kotlin/Short| = Short(1)
public get(): R|kotlin/Short| public get(): R|kotlin/Short|
public final const val str: R|kotlin/String| public final const val str: R|kotlin/String| = String(:))
public get(): R|kotlin/String| public get(): R|kotlin/String|
@@ -8,5 +8,5 @@ FILE: stringTemplates.kt
public final fun foo(s: R|kotlin/String|): R|kotlin/Unit| { public final fun foo(s: R|kotlin/String|): R|kotlin/Unit| {
} }
public final fun test(a: R|A|): R|kotlin/Unit| { public final fun test(a: R|A|): R|kotlin/Unit| {
R|/foo|(R|<local>/a|.R|kotlin/Any.toString|()) R|/foo|(<strcat>(R|<local>/a|.R|kotlin/Any.toString|()))
} }
@@ -5,4 +5,4 @@ interface B : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>A
interface C interface C
class D class D
interface E : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>A<!>(), C, D() interface E : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>A<!>(), C, <!SUPERTYPE_INITIALIZED_IN_INTERFACE!>D<!>()
@@ -8,6 +8,6 @@ interface D : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>C
interface E : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>Any<!>() interface E : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>Any<!>()
interface F : A, <!SUPERTYPE_INITIALIZED_IN_INTERFACE!>B<!>(), <!INTERFACE_WITH_SUPERCLASS!>C<!>, D(), Any() { interface F : A, <!SUPERTYPE_INITIALIZED_IN_INTERFACE!>B<!>(), <!INTERFACE_WITH_SUPERCLASS!>C<!>, <!SUPERTYPE_INITIALIZED_IN_INTERFACE!>D<!>(), <!SUPERTYPE_INITIALIZED_IN_INTERFACE!>Any<!>() {
} }
@@ -3,11 +3,11 @@ interface Some {
open fun bar() {} open fun bar() {}
open val x: Int open val x: Int
open val y = 1 open val y = <!PROPERTY_INITIALIZER_IN_INTERFACE!>1<!>
open val z get() = 1 open val z get() = 1
open var xx: Int open var xx: Int
open var yy = 1 open var yy = <!PROPERTY_INITIALIZER_IN_INTERFACE!>1<!>
open var zz: Int open var zz: Int
set(value) { set(value) {
field = value field = value
@@ -0,0 +1,44 @@
interface CommonBackendContext
interface PhaserState<Data> {
var depth: Int
}
interface PhaseConfig {
val needProfiling: Boolean
}
inline fun <R, D> PhaserState<D>.downlevel(nlevels: Int, block: () -> R): R {
depth += nlevels
val result = block()
depth -= nlevels
return result
}
interface CompilerPhase<in Context : CommonBackendContext, Input, Output> {
fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output
}
class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
private val lower: CompilerPhase<Context, Data, Data>
) : CompilerPhase<Context, Data, Data> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, input: Data): Data {
// Expected: output: Data, Actual: output: Data?
val output = if (phaseConfig.needProfiling) {
runAndProfile(phaseConfig, phaserState, context, input)
} else {
phaserState.downlevel(1) {
lower.invoke(phaseConfig, phaserState, context, input)
}
}
runAfter(phaseConfig, phaserState, context, output)
}
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, output: Data) {
}
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, source: Data): Data {
}
}
@@ -0,0 +1,55 @@
FILE: compilerPhase.kt
public abstract interface CommonBackendContext : R|kotlin/Any| {
}
public abstract interface PhaserState<Data> : R|kotlin/Any| {
public abstract var depth: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
}
public abstract interface PhaseConfig : R|kotlin/Any| {
public abstract val needProfiling: R|kotlin/Boolean|
public get(): R|kotlin/Boolean|
}
public final inline fun <R, D> R|PhaserState<D>|.downlevel(nlevels: R|kotlin/Int|, block: R|() -> R|): R|R| {
this@R|/downlevel|.R|/PhaserState.depth| = this@R|/downlevel|.R|/PhaserState.depth|.R|kotlin/Int.plus|(R|<local>/nlevels|)
lval result: R|R| = R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|R|>|()
this@R|/downlevel|.R|/PhaserState.depth| = this@R|/downlevel|.R|/PhaserState.depth|.R|kotlin/Int.minus|(R|<local>/nlevels|)
^downlevel R|<local>/result|
}
public abstract interface CompilerPhase<in Context : R|CommonBackendContext|, Input, Output> : R|kotlin/Any| {
public abstract fun invoke(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Input>|, context: R|Context|, input: R|Input|): R|Output|
}
public final class NamedCompilerPhase<in Context : R|CommonBackendContext|, Data> : R|CompilerPhase<Context, Data, Data>| {
public constructor<in Context : R|CommonBackendContext|, Data>(lower: R|CompilerPhase<Context, Data, Data>|): R|NamedCompilerPhase<Context, Data>| {
super<R|kotlin/Any|>()
}
private final val lower: R|CompilerPhase<Context, Data, Data>| = R|<local>/lower|
private get(): R|CompilerPhase<Context, Data, Data>|
public final override fun invoke(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, input: R|Data|): R|Data| {
lval output: R|Data| = when () {
R|<local>/phaseConfig|.R|/PhaseConfig.needProfiling| -> {
this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.runAndProfile|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/input|)
}
else -> {
R|<local>/phaserState|.R|/downlevel|<R|Data|, R|Data|>(Int(1), <L> = downlevel@fun <anonymous>(): R|Data| <kind=UNKNOWN> {
^ this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.lower|.R|SubstitutionOverride</CompilerPhase.invoke: R|Data|>|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/input|)
}
)
}
}
this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.runAfter|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/output|)
}
private final fun runAfter(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, output: R|Data|): R|kotlin/Unit| {
}
private final fun runAndProfile(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, source: R|Data|): R|Data| {
}
}
@@ -0,0 +1,14 @@
interface A
interface B
fun foo(x: A) {}
fun foo(x: B) {}
open class C : A, B
fun main(a: A) {
foo(a)
val anonymousA: A = object : C() {}
foo(anonymousA)
}
@@ -0,0 +1,26 @@
FILE: questionableSmartCast.kt
public abstract interface A : R|kotlin/Any| {
}
public abstract interface B : R|kotlin/Any| {
}
public final fun foo(x: R|A|): R|kotlin/Unit| {
}
public final fun foo(x: R|B|): R|kotlin/Unit| {
}
public open class C : R|A|, R|B| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
}
public final fun main(a: R|A|): R|kotlin/Unit| {
R|/foo|(R|<local>/a|)
lval anonymousA: R|A| = object : R|C| {
private constructor(): R|<anonymous>| {
super<R|C|>()
}
}
R|/foo|(R|<local>/anonymousA|)
}
@@ -0,0 +1,20 @@
// FILE: AliasFor.java
public @interface AliasFor {
@AliasFor(value = "attribute")
String value() default "";
@AliasFor(value = "value")
String attribute() default "";
}
// FILE: Service.java
public @interface Service {
@AliasFor(value = "component")
String value() default "";
}
// FILE: Annotated.kt
@Service(value = "Your")
class My
@@ -0,0 +1,7 @@
FILE: Annotated.kt
@R|Service|(value = String(Your)) public final class My : R|kotlin/Any| {
public constructor(): R|My| {
super<R|kotlin/Any|>()
}
}

Some files were not shown because too many files have changed in this diff Show More