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
203_202
193
as40_193
as41
as42_202
201
as41_201
as42
+1
View File
@@ -10,6 +10,7 @@
<w>commonizers</w>
<w>commonizes</w>
<w>commonizing</w>
<w>interop</w>
<w>jetbrains</w>
<w>konan</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
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/)
* [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"
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)
@@ -467,7 +467,7 @@ allprojects {
}
tasks.withType<Test> {
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KT-37089") { true }
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KTI-112") { !isTestDistributionEnabled() }
}
normalization {
@@ -854,6 +854,8 @@ tasks {
register("kaptIdeTest") {
dependsOn(":kotlin-annotation-processing:test")
dependsOn(":kotlin-annotation-processing-base:test")
dependsOn(":kotlin-annotation-processing-cli:test")
}
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("org.gradle:test-retry-gradle-plugin:1.1.9")
implementation("com.gradle.enterprise:test-distribution-gradle-plugin:1.2.1")
}
samWithReceiver {
+2 -1
View File
@@ -54,11 +54,12 @@ var Project.javaHome: String?
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
mainClass.set(fqName)
workingDir = rootDir
systemProperty("line.separator", "\n")
configure()
}
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
}
val fullFileText =
FileUtil.loadFile(file, true).replace("COROUTINES_PACKAGE", "kotlin.coroutines")
val fullFileText = FileUtil.loadFile(file, true)
if (fullFileText.contains("// WITH_COROUTINES")) {
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> =
CodegenTestCase.createTestFilesFromFile(file, expectedText, "kotlin.coroutines", false, TargetBackend.JVM)
CodegenTestCase.createTestFilesFromFile(file, expectedText, false, TargetBackend.JVM)
companion object {
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.org.objectweb.asm.*;
import java.util.ArrayList;
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) {};
public static final RecordComponentVisitor EMPTY_RECORD_VISITOR = new RecordComponentVisitor(Opcodes.API_VERSION) {};
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
private String thisName;
@@ -91,6 +91,16 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
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
@NotNull
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 returnKotlinType: KotlinType?,
val isInterfaceMethod: Boolean,
private val isDefaultMethodInInterface: Boolean
private val isDefaultMethodInInterface: Boolean,
private val boxInlineClassBeforeInvoke: Boolean
) : Callable {
private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod)
@@ -49,6 +50,9 @@ class CallableMethod(
get() = getAsmMethod().argumentTypes
override fun genInvokeInstruction(v: InstructionAdapter) {
if (boxInlineClassBeforeInvoke) {
StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v)
}
v.visitMethodInsn(
invokeOpcode,
owner.internalName,
@@ -19,14 +19,10 @@ 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.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.*;
public interface ClassBuilder {
@NotNull
@@ -49,6 +45,12 @@ public interface ClassBuilder {
@Nullable String[] exceptions
);
@NotNull RecordComponentVisitor newRecordComponent(
@NotNull String name,
@NotNull String desc,
@Nullable String signature
);
@NotNull
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 (classOrObject.isLocal) return false
if (classDescriptor.isInline) return false
if (classDescriptor.isInlineClass()) return false
if (shouldHideConstructorDueToInlineClassTypeValueParameters(constructorDescriptor)) 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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
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.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.*;
public abstract class DelegatingClassBuilder implements ClassBuilder {
@NotNull
@@ -58,6 +54,14 @@ public abstract class DelegatingClassBuilder implements ClassBuilder {
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
@Override
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) {
if (!(functionDescriptor instanceof ConstructorDescriptor)) return false;
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) {
@@ -559,7 +559,7 @@ public class DescriptorAsmUtil {
if (receiverKotlinType.isMarkedNullable()) return null;
DeclarationDescriptor receiverTypeDescriptor = receiverKotlinType.getConstructor().getDeclarationDescriptor();
assert receiverTypeDescriptor instanceof ClassDescriptor && ((ClassDescriptor) receiverTypeDescriptor).isInline() :
assert receiverTypeDescriptor != null && InlineClassesUtilsKt.isInlineClass(receiverTypeDescriptor) :
"Inline class type expected: " + receiverKotlinType;
ClassDescriptor receiverClassDescriptor = (ClassDescriptor) receiverTypeDescriptor;
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.KtClassOrObject
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.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
@@ -55,6 +56,13 @@ class ErasedInlineClassBodyCodegen(
generateUnboxMethod()
generateFunctionsFromAny()
generateSpecializedEqualsStub()
generateJvmInlineAnnotation()
}
private fun generateJvmInlineAnnotation() {
if (descriptor.isInline) {
v.newAnnotation(JVM_INLINE_ANNOTATION_FQ_NAME.topLevelClassAsmType().descriptor, true).visitEnd()
}
}
private fun generateFunctionsFromAny() {
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.lexer.KtTokens;
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.MethodSignatureMappingKt;
import org.jetbrains.kotlin.name.Name;
@@ -375,22 +376,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
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
.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(functionDescriptor, typeMapper);
StackValue stackValueToWrap = stackValue;
KotlinType originalKotlinType;
if (unboxedInlineClass != null) {
originalKotlinType = unboxedInlineClass;
} else {
originalKotlinType = stackValueToWrap.kotlinType;
}
Type originalType;
if (unboxedInlineClass != null) {
originalType = typeMapper.mapType(unboxedInlineClass);
} else {
originalType = stackValueToWrap.type;
}
KotlinType originalKotlinType = unboxedInlineClass != null ? unboxedInlineClass : stackValueToWrap.kotlinType;
Type originalType = unboxedInlineClass != null ? typeMapper.mapType(unboxedInlineClass) : stackValueToWrap.type;
stackValue = new StackValue(originalType, originalKotlinType) {
@Override
@@ -1195,7 +1191,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ClassDescriptor captureThis = closure.getCapturedOuterClassDescriptor();
if (captureThis != null) {
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;
callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++);
}
@@ -2409,9 +2405,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
fieldName = KotlinTypeMapper.mapDefaultFieldName(propertyDescriptor, isDelegatedProperty);
}
KotlinType propertyType = propertyDescriptor.getOriginal().getType();
if (propertyDescriptor instanceof JavaPropertyDescriptor && InlineClassesUtilsKt.isInlineClassType(propertyType)) {
propertyType = TypeUtils.makeNullable(propertyType);
}
return StackValue.property(
propertyDescriptor, backingFieldOwner,
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyType),
isStaticBackingField, fieldName, callableGetter, callableSetter, receiver, this, resolvedCall, skipLateinitAssertion,
isDelegatedProperty && forceField ? delegateType : null
);
@@ -4380,6 +4381,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Type exprType = expressionType(expr);
KotlinType exprKotlinType = kotlinType(expr);
if (exprKotlinType != null && InlineClassesUtilsKt.isInlineClassType(exprKotlinType) &&
FlexibleTypesKt.isNullabilityFlexible(exprKotlinType)) {
exprKotlinType = TypeUtils.makeNullable(exprKotlinType);
}
StackValue value;
if (compileTimeConstant != null) {
value = StackValue.constant(compileTimeConstant.getValue(), exprType, exprKotlinType);
@@ -4835,7 +4840,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter();
ClassDescriptor containingDeclaration = constructor.getContainingDeclaration();
if (!containingDeclaration.isInline()) {
if (!InlineClassesUtilsKt.isInlineClass(containingDeclaration)) {
v.anew(objectType);
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
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);
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
// 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;
for (int i = 0; i < argTypes.length; ++i) {
@@ -1609,7 +1614,7 @@ public class FunctionCodegen {
if (toClass.getKind() == ClassKind.INTERFACE) {
iv.invokeinterface(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
}
else if (toClass.isInline()) {
else if (InlineClassesUtilsKt.isInlineClass(toClass)) {
iv.invokestatic(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor(), false);
}
else {
@@ -84,7 +84,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
String toStringMethodDesc = getToStringDesc();
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);
return;
}
@@ -161,7 +161,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
String hashCodeMethodDesc = getHashCodeDesc();
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);
return;
}
@@ -233,7 +233,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
String equalsMethodDesc = getEqualsDesc();
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);
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.VariableAsFunctionResolvedCall;
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.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
@@ -221,6 +222,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
access |= ACC_ENUM;
}
if (JvmAnnotationUtilKt.isJvmRecord(descriptor)) {
access |= ACC_RECORD;
}
v.defineClass(
myClass.getPsiOrParent(),
state.getClassFileVersion(),
@@ -260,7 +265,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateErasedInlineClassIfNeeded() {
if (!(myClass instanceof KtClass)) return;
if (!descriptor.isInline()) return;
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
ClassContext erasedInlineClassContext = context.intoWrapperForErasedInlineClass(descriptor, state);
new ErasedInlineClassBodyCodegen((KtClass) myClass, erasedInlineClassContext, v, state, this).generate();
@@ -269,7 +274,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateUnboxMethodForInlineClass() {
if (!(myClass instanceof KtClass)) return;
if (!descriptor.isInline()) return;
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
Type ownerType = typeMapper.mapClass(descriptor);
ValueParameterDescriptor inlinedValue = InlineClassesUtilsKt.underlyingRepresentation(this.descriptor);
@@ -450,7 +455,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
try {
lookupConstructorExpressionsInClosureIfPresent();
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
for (ClassConstructorDescriptor secondaryConstructor : DescriptorUtilsKt.getSecondaryConstructors(descriptor)) {
constructorCodegen.generateSecondaryConstructor(secondaryConstructor, superClassAsmType);
@@ -552,7 +557,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateFunctionsFromAnyForInlineClasses() {
if (!descriptor.isInline()) return;
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
if (!(myClass instanceof KtClassOrObject)) return;
new FunctionsFromAnyGeneratorImpl(
(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.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;
@@ -435,9 +436,10 @@ public class PropertyCodegen {
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(),
isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor), defaultValue
signature, defaultValue
);
if (annotatedField != null) {
@@ -450,6 +452,10 @@ public class PropertyCodegen {
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);
}
}
}
@@ -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.
// 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);
}
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.org.objectweb.asm.Type;
@@ -48,7 +49,7 @@ public class ConstructorContext extends MethodContext {
ClassDescriptor capturedOuterClassDescriptor = closure != null ? closure.getCapturedOuterClassDescriptor() : null;
StackValue stackValue;
if (capturedOuterClassDescriptor != null) {
if (capturedOuterClassDescriptor.isInline()) {
if (InlineClassesUtilsKt.isInlineClass(capturedOuterClassDescriptor)) {
SimpleType outerClassKotlinType = capturedOuterClassDescriptor.getDefaultType();
Type outerClassType = kotlinTypeMapper.mapType(capturedOuterClassDescriptor);
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.descriptorUtil.builtIns
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.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
@@ -294,7 +295,7 @@ class CoroutineCodegenForLambda private constructor(
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, funDescriptor,
object : FunctionGenerationStrategy.CodegenBased(state) {
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()
with(InstructionAdapter(mv)) {
generateInvokeMethod(jvmMethodSignature)
generateInvokeMethod(jvmMethodSignature, untypedDescriptor)
}
FunctionCodegen.endVisit(mv, "invoke", element)
}
private fun InstructionAdapter.generateInvokeMethod(signature: JvmMethodSignature) {
private fun InstructionAdapter.generateInvokeMethod(signature: JvmMethodSignature, descriptor: FunctionDescriptor) {
// this
load(0, AsmTypes.OBJECT_TYPE)
val parameterTypes = signature.valueParameters.map { it.asmType }
@@ -348,16 +349,23 @@ class CoroutineCodegenForLambda private constructor(
load(arraySlot, AsmTypes.OBJECT_TYPE)
} else {
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) ->
load(varIndex + 1, type)
StackValue.coerce(type, createArgumentTypes[index++], this)
StackValue.coerce(type, fromKotlinTypes[index], createArgumentTypes[index], toKotlinTypes[index], this)
index++
}
}
// this.create(..)
invokevirtual(
v.thisName,
createCoroutineDescriptor.name.identifier,
typeMapper.mapFunctionName(createCoroutineDescriptor, null),
Type.getMethodDescriptor(
languageVersionSettings.continuationAsmType(),
*createArgumentTypes.toTypedArray()
@@ -439,12 +447,24 @@ class CoroutineCodegenForLambda private constructor(
)
} else {
if (generateErasedCreate) {
load(index, AsmTypes.OBJECT_TYPE)
StackValue.coerce(
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
this
)
if (parameter.type.isInlineClassType()) {
load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
load(index, AsmTypes.OBJECT_TYPE)
StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, parameter.type, 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 {
load(index, fieldInfoForCoroutineLambdaParameter.fieldType)
}
@@ -831,3 +851,6 @@ private object FailingFunctionGenerationStrategy : FunctionGenerationStrategy()
fun reportSuspensionPointInsideMonitor(element: KtElement, state: GenerationState, stackTraceElement: String) {
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
}
method.localVariables.clear()
// Skip `this` for suspend lamdba
// Skip `this` for suspend lambda
val start = if (isForNamedFunction) 0 else 1
val oldLvtNodeToLatestNewLvtNode = mutableMapOf<LocalVariableNode, LocalVariableNode>()
for (variableIndex in start until method.maxLocals) {
if (oldLvt.none { it.index == variableIndex }) continue
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
// startLabel can be null in case of parameters
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
var recordToExtend: LocalVariableNode? = null
for (record in method.localVariables) {
if (record.name == lvtRecord.name &&
record.desc == lvtRecord.desc &&
record.signature == lvtRecord.signature &&
record.index == lvtRecord.index
) {
if (InsnSequence(record.end, startLabel).none { isBeforeSuspendMarker(it) }) {
recordToExtend = record
break
}
}
}
if (recordToExtend != null) {
// Attempt to extend existing local variable node corresponding to the record in
// the original local variable table.
var recordToExtend: LocalVariableNode? = oldLvtNodeToLatestNewLvtNode[lvtRecord]
if (recordToExtend != null && InsnSequence(recordToExtend.end, startLabel).none { isBeforeSuspendMarker(it) }) {
recordToExtend.end = endLabel
} else {
method.localVariables.add(
LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
)
val node = 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.psiUtil.getElementTextWithContext
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.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
@@ -92,7 +93,9 @@ class SuspendFunctionGenerationStrategy(
sourceFile = declaration.containingKtFile.name,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
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,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() &&
@@ -136,9 +136,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
) {
var nodeAndSmap: SMAPAndMethodNode? = null
try {
nodeAndSmap = createInlineMethodNode(
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
)
nodeAndSmap = createInlineMethodNode(mapDefaultSignature, typeArguments, typeSystem)
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
} catch (e: CompilationException) {
throw e
@@ -274,6 +272,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
abstract fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean
fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
@@ -512,38 +512,33 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
companion object {
internal fun createInlineMethodNode(
functionDescriptor: FunctionDescriptor,
methodOwner: Type,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
typeArguments: List<TypeParameterMarker>?,
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)
internal fun createInlineMethodNode(
callDefault: Boolean,
typeArguments: List<TypeParameterMarker>?,
typeSystem: TypeSystemCommonBackendContext
): SMAPAndMethodNode {
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
if (intrinsic != null) {
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
}
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 {
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
assert(directMember is DescriptorWithContainerSource) {
@@ -577,7 +572,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod)
else
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)
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.linkWithLabel
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
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.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class InlineCodegenForDefaultBody(
@@ -41,8 +39,10 @@ class InlineCodegenForDefaultBody(
}
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
val nodeAndSmap = InlineCodegen.createInlineMethodNode(
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline
val nodeAndSmap = PsiInlineCodegen(
codegen, state, function, methodOwner, jvmSignature, TypeParameterMappings(), sourceCompilerForInline
).createInlineMethodNode(
callDefault, null, codegen.typeSystem
)
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.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
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.JvmMethodSignature
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.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -208,4 +210,7 @@ class PsiInlineCodegen(
::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.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)
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
@@ -44,6 +41,10 @@ fun CallableDescriptor.isGenericParameter(): Boolean {
fun classFileContainsMethod(descriptor: FunctionDescriptor, state: GenerationState, method: Method): Boolean? {
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 {
descriptor.containingDeclaration is DeserializedClassDescriptor -> {
(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)
?.contentsToByteArray() ?: return null
var found = false
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Pair
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Type
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? {
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)
}
@@ -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.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.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 runtimeStringConcat =
if (target.bytecodeVersion >= JvmTarget.JVM_9.bytecodeVersion)
if (target.majorVersion >= JvmTarget.JVM_9.majorVersion)
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE
else JvmStringConcat.INLINE
@@ -272,7 +272,10 @@ class GenerationState private constructor(
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)
@@ -5,4 +5,4 @@
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
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.descriptors.JavaCallableMemberDescriptor
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.getJvmMethodNameIfSpecial
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.isBoxedLocalCapturedInClosure
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.calls.model.DefaultValueArgument
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.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER
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.annotations.isCompiledToJvmDefault
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
@@ -379,7 +382,8 @@ class KotlinTypeMapper @JvmOverloads constructor(
val originalDescriptor = descriptor.original
return CallableMethod(
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?
var isInterfaceMember = false
var isDefaultMethodInInterface = false
var boxInlineClassBeforeInvoke = false
if (functionParent is ClassDescriptor) {
val declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor)
@@ -445,18 +450,22 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
}
} else {
val toInlinedErasedClass = functionParent.isInline &&
val toInlinedErasedClass = functionParent.isInlineClass() &&
(!isAccessor(functionDescriptor) || isInlineClassConstructorAccessor(functionDescriptor))
if (toInlinedErasedClass) {
functionDescriptor = descriptor
}
val isStaticInvocation =
isStaticDeclaration(functionDescriptor) && functionDescriptor !is ImportedFromObjectCallableDescriptor<*> ||
isStaticAccessor(functionDescriptor) ||
functionDescriptor.isJvmStaticInObjectOrClassOrInterface() ||
toInlinedErasedClass
val isFakeOverrideOfJvmDefault = toInlinedErasedClass &&
functionDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
functionDescriptor.overridesJvmDefault()
val isStaticInvocation = !isFakeOverrideOfJvmDefault &&
(isStaticDeclaration(functionDescriptor) && functionDescriptor !is ImportedFromObjectCallableDescriptor<*> ||
isStaticAccessor(functionDescriptor) ||
functionDescriptor.isJvmStaticInObjectOrClassOrInterface() ||
toInlinedErasedClass)
when {
isStaticInvocation -> {
invokeOpcode = INVOKESTATIC
@@ -466,8 +475,13 @@ class KotlinTypeMapper @JvmOverloads constructor(
invokeOpcode = INVOKEINTERFACE
isInterfaceMember = true
}
isFakeOverrideOfJvmDefault -> {
invokeOpcode = INVOKEVIRTUAL
boxInlineClassBeforeInvoke = true
}
else -> {
val isPrivateFunInvocation = DescriptorVisibilities.isPrivate(functionDescriptor.visibility) && !functionDescriptor.isSuspend
val isPrivateFunInvocation =
DescriptorVisibilities.isPrivate(functionDescriptor.visibility) && !functionDescriptor.isSuspend
invokeOpcode = if (superCall || isPrivateFunInvocation) INVOKESPECIAL else INVOKEVIRTUAL
isInterfaceMember = false
}
@@ -479,7 +493,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
else
functionDescriptor.original
signature = if (toInlinedErasedClass)
signature = if (toInlinedErasedClass && !isFakeOverrideOfJvmDefault)
mapSignatureForInlineErasedClassSkipGeneric(functionToCall)
else
mapSignature(
@@ -547,10 +561,18 @@ class KotlinTypeMapper @JvmOverloads constructor(
signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType,
calleeType, returnKotlinType,
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 {
if (descriptor !is JavaCallableMemberDescriptor) {
val platformName = getJvmName(descriptor)
@@ -563,10 +585,16 @@ class KotlinTypeMapper @JvmOverloads constructor(
return when {
descriptor is PropertyAccessorDescriptor -> {
val property = descriptor.correspondingProperty
if (isAnnotationClass(property.containingDeclaration)) {
val containingDeclaration = property.containingDeclaration
if (isAnnotationClass(containingDeclaration) &&
(!property.hasJvmStaticAnnotation() && !descriptor.hasJvmStaticAnnotation())
) {
return property.name.asString()
}
if ((containingDeclaration as? ClassDescriptor)?.hasJavaLangRecordSupertype() == true) return property.name.asString()
val isAccessor = property is AccessorForPropertyDescriptor
val propertyName = if (isAccessor)
(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 =
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)
@@ -965,7 +996,8 @@ class KotlinTypeMapper @JvmOverloads constructor(
if ((isFunctionExpression(descriptor) || isFunctionLiteral(descriptor)) && returnType.isInlineClassType()) return true
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) =
@@ -1031,7 +1063,11 @@ class KotlinTypeMapper @JvmOverloads constructor(
fun writeParameterType(sw: JvmSignatureWriter, type: KotlinType, callableDescriptor: CallableDescriptor?) {
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
}
@@ -7,12 +7,12 @@ package org.jetbrains.kotlin.codegen.state
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
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.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.types.KotlinType
@@ -85,6 +85,7 @@ fun getManglingSuffixBasedOnKotlinSignature(
): String? {
if (descriptor !is FunctionDescriptor) return null
if (descriptor is ConstructorDescriptor) return null
if (descriptor is JavaMethodDescriptor) return null
if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null
// Don't mangle functions with '@JvmName' annotation.
@@ -111,7 +112,7 @@ fun getManglingSuffixBasedOnKotlinSignature(
private fun getInfoForMangling(type: KotlinType): InfoForMangling? {
val descriptor = type.constructor.declarationDescriptor ?: return null
return when (descriptor) {
is ClassDescriptor -> InfoForMangling(descriptor.fqNameUnsafe, descriptor.isInline, type.isMarkedNullable)
is ClassDescriptor -> InfoForMangling(descriptor.fqNameUnsafe, descriptor.isInlineClass(), type.isMarkedNullable)
is TypeParameterDescriptor -> {
getInfoForMangling(descriptor.representativeUpperBound)
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
@@ -93,4 +94,4 @@ fun KotlinType.removeExternalProjections(): KotlinType {
fun isInlineClassConstructorAccessor(descriptor: FunctionDescriptor): Boolean =
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.ideaExt.idea
import java.io.File
plugins {
@@ -69,10 +70,20 @@ dependencies {
antLauncherJar(toolsJar())
}
val generationRoot = projectDir.resolve("tests-gen")
sourceSets {
"main" {}
"test" {
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()
+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" ^
org.jetbrains.kotlin.runner.Main %KOTLIN_OPTS%
) else (
setlocal EnableDelayedExpansion
SET _ADDITIONAL_CLASSPATH=
if not "%_KOTLIN_TOOL%"=="" (
@@ -56,7 +57,7 @@ if "%_KOTLIN_RUNNER%"=="1" (
)
"%_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%
)
@@ -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")
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")
var irOnly: Boolean by FreezableVar(false)
@@ -418,6 +418,13 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
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> {
val result = super.configureAnalysisFlags(collector)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
@@ -438,6 +445,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
result[JvmAnalysisFlags.sanitizeParentheses] = sanitizeParentheses
result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError
result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames
result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview
result[AnalysisFlags.reportErrorsOnIrDependencies] = !useIR && !useFir && !allowJvmIrDependencies
result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses
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.KotlinCoreEnvironment
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.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
@@ -261,7 +264,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
generateDceJs = arguments.irDce,
dceDriven = arguments.irDceDriven,
multiModule = arguments.irPerModule,
relativeRequirePath = true
relativeRequirePath = true,
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
)
} catch (e: JsIrCompilationError) {
return COMPILATION_ERROR
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
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.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
@@ -128,7 +127,7 @@ class AnalyzerWithCompilerReport(
psiElement: E, factory: DiagnosticFactory0<E>, val message: String
) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) {
override fun isValid(): Boolean = true
override val isValid: Boolean = true
}
companion object {
@@ -154,16 +153,16 @@ class AnalyzerWithCompilerReport(
return diagnostic.severity == Severity.ERROR
}
fun reportDiagnostics(unsortedDiagnostics: Diagnostics, reporter: DiagnosticMessageReporter): Boolean {
fun reportDiagnostics(unsortedDiagnostics: GenericDiagnostics<*>, reporter: DiagnosticMessageReporter): Boolean {
var hasErrors = false
val diagnostics = sortedDiagnostics(unsortedDiagnostics.all())
val diagnostics = sortedDiagnostics(unsortedDiagnostics.all().filterIsInstance<Diagnostic>())
for (diagnostic in diagnostics) {
hasErrors = hasErrors or reportDiagnostic(diagnostic, reporter)
}
return hasErrors
}
fun reportDiagnostics(diagnostics: Diagnostics, messageCollector: MessageCollector): Boolean {
fun reportDiagnostics(diagnostics: GenericDiagnostics<*>, messageCollector: MessageCollector): Boolean {
val hasErrors = reportDiagnostics(diagnostics, DefaultDiagnosticReporter(messageCollector))
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;
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.PsiFile;
import org.jetbrains.annotations.NotNull;
@@ -53,10 +51,6 @@ public class MessageUtil {
@NotNull
public static String virtualFileToPath(@NotNull VirtualFile virtualFile) {
// Convert path to platform-dependent format when virtualFile is local file.
if (virtualFile instanceof CoreLocalVirtualFile || virtualFile instanceof CoreJarVirtualFile) {
return toSystemDependentName(virtualFile.getPath());
}
return virtualFile.getPath();
return toSystemDependentName(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
}
@Suppress("UNCHECKED_CAST")
override fun <K, V> get(slice: ReadOnlySlice<K, V>, key: K): V? {
val value = super.get(slice, key)
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)) {
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(ContainerProvider.EP_NAME, ContainerProvider.class);
registerApplicationExtensionPoint(ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class);
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
@@ -52,4 +51,4 @@ public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnviron
protected VirtualFileSystem createJrtFileSystem() {
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.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
@@ -249,6 +252,8 @@ class KotlinCoreEnvironment private constructor(
project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, fun(roots: List<File>) {
updateClasspath(roots.map { JavaSourceRoot(it, null) })
})
LanguageLevelProjectExtension.getInstance(project).languageLevel = LanguageLevel.JDK_15_PREVIEW
}
private fun collectAdditionalSources(project: MockProject) {
@@ -509,6 +514,11 @@ class KotlinCoreEnvironment private constructor(
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)
@@ -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.vfs.*
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiJavaModule
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.SimpleOutputFileCollection
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.jvmPhases
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.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.fir.FirPsiSourceElement
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.FirMetadataSerializer
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.psi.KtFile
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.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
@@ -342,9 +340,7 @@ object KotlinToJVMBytecodeCompiler {
firAnalyzerFacade.runResolution()
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
AnalyzerWithCompilerReport.reportDiagnostics(
SimpleDiagnostics(
firDiagnostics.map { it.toRegularDiagnostic() }
),
SimpleGenericDiagnostics(firDiagnostics),
environment.messageCollector
)
performanceManager?.notifyAnalysisFinished()
@@ -356,7 +352,8 @@ object KotlinToJVMBytecodeCompiler {
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val (moduleFragment, symbolTable, sourceManager, components) = firAnalyzerFacade.convertToIr()
val extensions = JvmGeneratorExtensions()
val (moduleFragment, symbolTable, sourceManager, components) = firAnalyzerFacade.convertToIr(extensions)
performanceManager?.notifyIRTranslationFinished()
@@ -392,9 +389,9 @@ object KotlinToJVMBytecodeCompiler {
performanceManager?.notifyIRGenerationStarted()
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager
generationState, moduleFragment, symbolTable, sourceManager, extensions
) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent)
FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent)
}
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
@@ -427,30 +424,6 @@ object KotlinToJVMBytecodeCompiler {
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> =
if (buildFile == null) sourceFilePaths
else sourceFilePaths.map { path ->
@@ -490,6 +463,10 @@ object KotlinToJVMBytecodeCompiler {
environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) })
}
if (result.additionalClassPathRoots.isNotEmpty()) {
environment.updateClasspath(result.additionalClassPathRoots.map { JvmClasspathRoot(it, false) })
}
if (result.additionalKotlinRoots.isNotEmpty()) {
environment.addKotlinSourceRoots(result.additionalKotlinRoots)
}
@@ -499,8 +476,8 @@ object KotlinToJVMBytecodeCompiler {
// Clear all diagnostic messages
configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear()
// Repeat analysis with additional Java roots (kapt generated sources)
return analyze(environment)
// Repeat analysis with additional source roots generated by compiler plugins.
return repeatAnalysisIfNeeded(analyze(environment), environment)
}
return result
@@ -12,4 +12,6 @@ fun setupIdeaStandaloneExecution() {
System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000")
System.getProperties().setProperty("ide.hide.excluded.files", "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("ide.hide.excluded.files", "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
if (jvmTarget.bytecodeVersion < JvmTarget.JVM_1_8.bytecodeVersion) {
if (jvmTarget.majorVersion < JvmTarget.JVM_1_8.majorVersion) {
val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
if (jvmDefaultMode.forAllMethodsWithBody) {
messageCollector.report(
@@ -53,7 +53,7 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
val runtimeStringConcat = JvmStringConcat.fromString(arguments.stringConcat!!)
if (runtimeStringConcat != null) {
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(
WARNING,
"`-Xstring-concat=${arguments.stringConcat}` does nothing with JVM target `${jvmTarget.description}`."
@@ -61,8 +61,8 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
} else {
messageCollector.report(
ERROR, "Unknown `string-concat` mode: ${arguments.jvmTarget}\n" +
"Supported versions: ${JvmStringConcat.values().joinToString { it.name.toLowerCase() }}"
ERROR, "Unknown -Xstring-concat mode: ${arguments.jvmTarget}\n" +
"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_OLD_SPILLED_VAR_TYPE_ANALYSIS, arguments.useOldSpilledVarTypeAnalysis)
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) }
}
@@ -242,4 +248,4 @@ fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments)
?.toTypedArray()
?.filterNot { it.isEmpty() }
?.let { put(JVMConfigurationKeys.KLIB_PATHS, it) }
}
}
@@ -140,4 +140,7 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> USE_OLD_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
val disableUltraLightClasses by AnalysisFlag.Delegates.Boolean
@JvmStatic
val enableJvmPreview by AnalysisFlag.Delegates.Boolean
private object Delegates {
object JavaTypeEnhancementStateWarnByDefault {
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.org.objectweb.asm.Opcodes
enum class JvmTarget(override val description: String) : TargetPlatformVersion {
JVM_1_6("1.6"),
JVM_1_8("1.8"),
JVM_9("9"),
JVM_10("10"),
JVM_11("11"),
JVM_12("12"),
JVM_13("13"),
JVM_14("14"),
JVM_15("15"),
enum class JvmTarget(
override val description: String,
val majorVersion: Int,
) : TargetPlatformVersion {
JVM_1_6("1.6", Opcodes.V1_6),
JVM_1_8("1.8", Opcodes.V1_8),
JVM_9("9", Opcodes.V9),
JVM_10("10", Opcodes.V10),
JVM_11("11", Opcodes.V11),
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 {
@JvmField
val DEFAULT = JVM_1_6
@@ -52,14 +41,14 @@ enum class JvmTarget(override val description: String) : TargetPlatformVersion {
@JvmStatic
fun fromString(string: String) = values().find { it.description == string }
fun getDescription(bytecodeVersion: Int): String {
val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?: when (bytecodeVersion) {
fun getDescription(majorVersion: Int): String {
val platformDescription = values().find { it.majorVersion == majorVersion }?.description ?: when (majorVersion) {
Opcodes.V1_7 -> "1.7"
else -> null
}
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.
* 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") }
}
val generationRoot = projectDir.resolve("tests-gen")
sourceSets {
"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) {
@@ -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|
}
@@ -10,7 +10,7 @@
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|
}
@@ -6,19 +6,19 @@
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|
}
@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|
}
@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|
}
@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|
}
@@ -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|
}
@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|
}
@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|
}
@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|
}
@@ -54,11 +54,11 @@
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|
}
@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|
}
@@ -12,15 +12,15 @@
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|
}
@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|
}
@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|
}
@@ -10,11 +10,11 @@
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|
}
@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|
}
@@ -10,11 +10,11 @@ public open class A : R|kotlin/Any| {
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|
}
@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|
}
@@ -1,9 +1,9 @@
FILE: RedundantSingleExpressionStringTemplateChecker.kt
public final val x: R|kotlin/String| = String(Hello)
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 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 final fun toString(x: R|kotlin/String|): R|kotlin/String| {
^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 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> {
^ R|<local>/it|.R|kotlin/Any.toString|()
^ <strcat>(R|<local>/it|.R|kotlin/Any.toString|())
}
)
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 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|
}
@@ -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 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|
}
@@ -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 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|
@@ -8,5 +8,5 @@ FILE: stringTemplates.kt
public final fun foo(s: R|kotlin/String|): 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
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 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 val x: Int
open val y = 1
open val y = <!PROPERTY_INITIALIZER_IN_INTERFACE!>1<!>
open val z get() = 1
open var xx: Int
open var yy = 1
open var yy = <!PROPERTY_INITIALIZER_IN_INTERFACE!>1<!>
open var zz: Int
set(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