Merge commits from both masters and update to 1.5.0-dev-1023

Kotlin/Native base commit: 858a1d77dd0f92d5f926a1ab3d5ab61230758714

Merge branches 'to-native-merge' and 'tmp_branch4merge' into native-merge
This commit is contained in:
Nikolay Krasko
2020-12-29 00:15:37 +03:00
1142 changed files with 18279 additions and 12466 deletions
+1 -2
View File
@@ -10,12 +10,11 @@
</option>
<option name="taskNames">
<list>
<option value=":compiler:generateTests" />
<option value=":compiler:tests-for-compiler-generator:generateTests" />
<option value=":compiler:tests-java8:generateTests" />
<option value=":compiler:tests-against-klib:generateTests" />
<option value=":js:js.tests:generateTests" />
<option value=":core:descriptors.runtime:generateTests" />
<option value=":compiler:tests-common-new:generateTests" />
</list>
</option>
<option name="vmOptions" value="" />
+3 -1
View File
@@ -293,6 +293,7 @@ extra["compilerModules"] = arrayOf(
":compiler:fir:checkers",
":compiler:fir:entrypoint",
":compiler:fir:analysis-tests",
":compiler:fir:analysis-tests:legacy-fir-tests",
":wasm:wasm.ir"
)
@@ -667,6 +668,7 @@ tasks {
dependsOn(":compiler:fir:raw-fir:psi2fir:test")
dependsOn(":compiler:fir:raw-fir:light-tree2fir:test")
dependsOn(":compiler:fir:analysis-tests:test")
dependsOn(":compiler:fir:analysis-tests:legacy-fir-tests:test")
dependsOn(":compiler:fir:fir2ir:test")
}
@@ -676,6 +678,7 @@ tasks {
":compiler:fir:raw-fir:psi2fir:test",
":compiler:fir:raw-fir:light-tree2fir:test",
":compiler:fir:analysis-tests:test",
":compiler:fir:analysis-tests:legacy-fir-tests:test",
":compiler:fir:fir2ir:test",
":plugins:fir:fir-plugin-prototype:test"
)
@@ -711,7 +714,6 @@ tasks {
}
register("miscCompilerTest") {
dependsOn("wasmCompilerTest")
dependsOn("nativeCompilerTest")
dependsOn("firCompilerTest")
+10 -1
View File
@@ -20,6 +20,10 @@ internal const val PLUGIN_MARKER_SUFFIX = ".gradle.plugin"
@OptIn(ExperimentalStdlibApi::class)
fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
fun Project.isSonatypePublish(): Boolean =
hasProperty("isSonatypePublish") && property("isSonatypePublish") as Boolean
val pluginDevelopment = extensions.getByType<PluginBundleExtension>()
val publishingExtension = extensions.getByType<PublishingExtension>()
val mainPublication = publishingExtension.publications[KotlinBuildPublishingPlugin.PUBLICATION_NAME] as MavenPublication
@@ -32,7 +36,12 @@ fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
tasks.named<PublishToMavenRepository>(
"publish${markerPublication.name.capitalize(Locale.ROOT)}PublicationTo${KotlinBuildPublishingPlugin.REPOSITORY_NAME}Repository"
).configureRepository()
).apply {
configureRepository()
configure {
onlyIf { !isSonatypePublish() }
}
}
}
}
@@ -0,0 +1,13 @@
/*
* 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.codegen
import org.jetbrains.org.objectweb.asm.Opcodes
// This object should help compiling against different ASM versions in different bunch versions
object VersionIndependentOpcodes {
const val ACC_RECORD = Opcodes.ACC_RECORD
}
@@ -0,0 +1,13 @@
/*
* 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.codegen
import org.jetbrains.org.objectweb.asm.Opcodes
// This object should help compiling against different ASM versions from different bunch versions
object VersionIndependentOpcodes {
const val ACC_RECORD = 0
}
@@ -0,0 +1,10 @@
/*
* 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.codegen
fun ClassBuilder.addRecordComponent(name: String, desc: String, signature: String?) {
newRecordComponent(name, desc, signature)
}
@@ -0,0 +1,10 @@
/*
* 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.codegen
fun ClassBuilder.addRecordComponent(name: String, desc: String, signature: String?) {
// newRecordComponent(name, desc, signature)
}
@@ -223,7 +223,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
if (JvmAnnotationUtilKt.isJvmRecord(descriptor)) {
access |= ACC_RECORD;
access |= VersionIndependentOpcodes.ACC_RECORD;
}
v.defineClass(
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl;
@@ -83,7 +84,9 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
private final MemberCodegen<?> parentCodegen;
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
private final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<>();
private final Collection<SyntheticInnerClassInfo> syntheticInnerClasses = new LinkedHashSet<>();
private ExpressionCodegen clInit;
private NameGenerator inlineNameGenerator;
@@ -316,6 +319,10 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
genClassOrObject(context, descriptor.getSyntheticDeclaration(), state, this, descriptor);
}
public void addSyntheticAnonymousInnerClass(SyntheticInnerClassInfo syntheticInnerClassInfo) {
syntheticInnerClasses.add(syntheticInnerClassInfo);
}
private void writeInnerClasses() {
// JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
// for each enclosing class and for each immediate member
@@ -331,6 +338,9 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
for (ClassDescriptor innerClass : innerClasses) {
writeInnerClass(innerClass);
}
for (SyntheticInnerClassInfo syntheticInnerClass : syntheticInnerClasses) {
v.visitInnerClass(syntheticInnerClass.getInternalName(), null, null, syntheticInnerClass.getFlags());
}
}
protected void addParentsToInnerClassesIfNeeded(@NotNull Collection<ClassDescriptor> innerClasses) {
@@ -376,18 +386,12 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
protected void writeOuterClassAndEnclosingMethod() {
CodegenContext context = this.context.getParentContext();
while (context instanceof InlineLambdaContext) {
// If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
//noinspection ConstantConditions
context = context.getParentContext().getParentContext();
}
CodegenContext<?> context = getNonInlineOuterContext(this.context.getParentContext());
assert context != null : "Outermost context can't be null: " + this.context;
Type enclosingAsmType = computeOuterClass(context);
Type enclosingAsmType = computeOuterClass(typeMapper, state.getJvmDefaultMode(), element, context);
if (enclosingAsmType != null) {
Method method = computeEnclosingMethod(context);
Method method = computeEnclosingMethod(typeMapper, context);
v.visitOuterClass(
enclosingAsmType.getInternalName(),
@@ -397,15 +401,31 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
}
public static CodegenContext<?> getNonInlineOuterContext(CodegenContext<?> parentContext) {
CodegenContext<?> context = parentContext;
while (context instanceof InlineLambdaContext) {
// If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
//noinspection ConstantConditions
context = context.getParentContext().getParentContext();
}
return context;
}
@Nullable
private Type computeOuterClass(@NotNull CodegenContext<?> context) {
public static Type computeOuterClass(
@NotNull KotlinTypeMapper typeMapper,
@NotNull JvmDefaultMode jvmDefaultMode,
@NotNull KtPureElement element,
@NotNull CodegenContext<?> context
) {
CodegenContext<? extends ClassOrPackageFragmentDescriptor> outermost = context.getClassOrPackageParentContext();
if (outermost instanceof ClassContext) {
ClassDescriptor classDescriptor = ((ClassContext) outermost).getContextDescriptor();
if (context instanceof MethodContext) {
FunctionDescriptor functionDescriptor = ((MethodContext) context).getFunctionDescriptor();
if (isInterface(functionDescriptor.getContainingDeclaration()) && !JvmAnnotationUtilKt
.isCompiledToJvmDefault(functionDescriptor, state.getJvmDefaultMode())) {
if (isInterface(functionDescriptor.getContainingDeclaration()) &&
!JvmAnnotationUtilKt.isCompiledToJvmDefault(functionDescriptor, jvmDefaultMode)
) {
return typeMapper.mapDefaultImpls(classDescriptor);
}
}
@@ -425,7 +445,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
@Nullable
private Method computeEnclosingMethod(@NotNull CodegenContext context) {
public static Method computeEnclosingMethod(@NotNull KotlinTypeMapper typeMapper, @NotNull CodegenContext context) {
if (context instanceof MethodContext) {
FunctionDescriptor functionDescriptor = ((MethodContext) context).getFunctionDescriptor();
if ("<clinit>".equals(functionDescriptor.getName().asString())) {
@@ -454,7 +454,7 @@ public class PropertyCodegen {
}
if (propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor && JvmAnnotationUtilKt.isJvmRecord((ClassDescriptor) propertyDescriptor.getContainingDeclaration())) {
builder.newRecordComponent(name, type.getDescriptor(), signature);
ClassBuilderRecordKt.addRecordComponent(builder, name, type.getDescriptor(), signature);
}
}
}
@@ -1,680 +0,0 @@
/*
* 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);
}
}
}
@@ -20,6 +20,8 @@ import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.context.ClassContext;
import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
@@ -62,6 +64,7 @@ public class SamWrapperCodegen {
private final SamType samType;
private final MemberCodegen<?> parentCodegen;
private final int visibility;
private final int classFlags;
public static final String SAM_WRAPPER_SUFFIX = "$0";
public SamWrapperCodegen(
@@ -76,6 +79,7 @@ public class SamWrapperCodegen {
this.samType = samType;
this.parentCodegen = parentCodegen;
visibility = isInsideInline ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE;
classFlags = visibility | ACC_FINAL | ACC_SUPER;
}
@NotNull
@@ -121,7 +125,7 @@ public class SamWrapperCodegen {
cv.defineClass(
file,
state.getClassFileVersion(),
ACC_FINAL | ACC_SUPER | visibility,
classFlags,
asmType.getInternalName(),
null,
OBJECT_TYPE.getInternalName(),
@@ -131,6 +135,8 @@ public class SamWrapperCodegen {
WriteAnnotationUtilKt.writeSyntheticClassMetadata(cv, state);
generateInnerClassInformation(file, asmType, cv);
// e.g. ASM type for Function2
Type functionAsmType = typeMapper.mapType(functionType);
@@ -160,6 +166,24 @@ public class SamWrapperCodegen {
return asmType;
}
private void generateInnerClassInformation(@NotNull KtFile file, Type asmType, ClassBuilder cv) {
parentCodegen.addSyntheticAnonymousInnerClass(new SyntheticInnerClassInfo(asmType.getInternalName(), classFlags));
FieldOwnerContext<?> parentContext = parentCodegen.context;
CodegenContext<?> outerContext = MemberCodegen.getNonInlineOuterContext(parentContext);
assert outerContext != null :
"Outer context for SAM wrapper " + asmType.getInternalName() + " is null, parentContext:" + parentContext;
Type outerClassType = MemberCodegen.computeOuterClass(state.getTypeMapper(), state.getJvmDefaultMode(), file, outerContext);
assert outerClassType != null :
"Outer class for SAM wrapper " + asmType.getInternalName() + " is null, parentContext:" + parentContext;
Method enclosingMethod = MemberCodegen.computeEnclosingMethod(state.getTypeMapper(), outerContext);
cv.visitOuterClass(
outerClassType.getInternalName(),
enclosingMethod == null ? null : enclosingMethod.getName(),
enclosingMethod == null ? null : enclosingMethod.getDescriptor()
);
cv.visitInnerClass(asmType.getInternalName(), null, null, classFlags);
}
private void generateConstructor(Type ownerType, Type functionType, ClassBuilder cv) {
MethodVisitor mv = cv.newMethod(JvmDeclarationOriginKt.OtherOrigin(samType.getClassDescriptor()),
visibility, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), null, null);
@@ -0,0 +1,8 @@
/*
* 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.codegen
data class SyntheticInnerClassInfo(val internalName: String, val flags: Int)
@@ -1113,7 +1113,7 @@ inline fun withInstructionAdapter(block: InstructionAdapter.() -> Unit): InsnLis
return tmpMethodNode.instructions
}
internal fun Type.normalize() =
fun Type.normalize() =
when (sort) {
Type.ARRAY, Type.OBJECT -> AsmTypes.OBJECT_TYPE
else -> this
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.Position
import org.jetbrains.kotlin.incremental.components.ScopeKind
@@ -522,10 +523,15 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
}
val asmMethod = if (callDefault)
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
else
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
var asmMethod = mapMethod(callDefault)
if (asmMethod.name.contains("-") &&
!state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME) &&
classFileContainsMethod(functionDescriptor, state, asmMethod) == false
) {
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = true
asmMethod = mapMethod(callDefault)
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = false
}
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !descriptorIsDeserialized(directMember)) {
@@ -537,6 +543,10 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
}
private fun mapMethod(callDefault: Boolean): Method =
if (callDefault) state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
else mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
companion object {
internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode {
@@ -298,7 +298,7 @@ class GenerationState private constructor(
?: if (languageVersionSettings.languageVersion >= LanguageVersion.LATEST_STABLE) JvmMetadataVersion.INSTANCE
else JvmMetadataVersion(1, 1, 18)
val isIrWithStableAbi = configuration.getBoolean(JVMConfigurationKeys.IS_IR_WITH_STABLE_ABI)
val abiStability = configuration.get(JVMConfigurationKeys.ABI_STABILITY)
val globalSerializationBindings = JvmSerializationBindings()
var mapInlineClass: (ClassDescriptor) -> Type = { descriptor -> typeMapper.mapType(descriptor.defaultType) }
+1 -4
View File
@@ -46,7 +46,7 @@ dependencies {
testCompile(projectTests(":compiler:fir:raw-fir:psi2fir"))
testCompile(projectTests(":compiler:fir:raw-fir:light-tree2fir"))
testCompile(projectTests(":compiler:fir:fir2ir"))
testCompile(projectTests(":compiler:fir:analysis-tests"))
testCompile(projectTests(":compiler:fir:analysis-tests:legacy-fir-tests"))
testCompile(projectTests(":compiler:visualizer"))
testCompile(projectTests(":generators:test-generator"))
testCompile(project(":compiler:ir.ir2cfg"))
@@ -99,8 +99,5 @@ projectTest(parallel = true) {
}
val generateTestData by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestDataKt")
val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestsKt") {
dependsOn(generateTestData)
}
testsJar()
@@ -95,18 +95,20 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
var irCheckLocalNames: Boolean by FreezableVar(false)
@Argument(
value = "-Xallow-jvm-ir-dependencies",
description = "When not using the IR backend, do not report errors on those classes in dependencies, " +
"which were compiled by the IR backend"
value = "-Xallow-unstable-dependencies",
description = "Do not report errors on classes in dependencies, which were compiled by an unstable version of the Kotlin compiler"
)
var allowJvmIrDependencies: Boolean by FreezableVar(false)
var allowUnstableDependencies: Boolean by FreezableVar(false)
@Argument(
value = "-Xir-binary-with-stable-abi",
description = "When using the IR backend, produce binaries which can be read by non-IR backend.\n" +
"The author is responsible for verifying that the resulting binaries do indeed have the correct ABI"
value = "-Xabi-stability",
valueDescription = "{stable|unstable}",
description = "When using unstable compiler features such as FIR, use 'stable' to mark generated class files as stable\n" +
"to prevent diagnostics from stable compilers at the call site.\n" +
"When using the JVM IR backend, conversely, use 'unstable' to mark generated class files as unstable\n" +
"to force diagnostics to be reported."
)
var isIrWithStableAbi: Boolean by FreezableVar(false)
var abiStability: String? by FreezableVar(null)
@Argument(
value = "-Xir-do-not-clear-binding-context",
@@ -446,7 +448,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError
result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames
result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview
result[AnalysisFlags.reportErrorsOnIrDependencies] = !useIR && !useFir && !allowJvmIrDependencies
result[AnalysisFlags.allowUnstableDependencies] = allowUnstableDependencies || useFir
result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses
return result
}
@@ -182,11 +182,19 @@ class AnalyzerWithCompilerReport(
)
}
if (diagnostics.any { it.factory == Errors.IR_COMPILED_CLASS }) {
if (diagnostics.any { it.factory == Errors.IR_WITH_UNSTABLE_ABI_COMPILED_CLASS }) {
messageCollector.report(
ERROR,
"Classes compiled by a new Kotlin compiler backend were found in dependencies. " +
"Remove them from the classpath or use '-Xallow-jvm-ir-dependencies' to suppress errors"
"Classes compiled by an unstable version of the Kotlin compiler were found in dependencies. " +
"Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors"
)
}
if (diagnostics.any { it.factory == Errors.FIR_COMPILED_CLASS }) {
messageCollector.report(
ERROR,
"Classes compiled by the new Kotlin compiler frontend were found in dependencies. " +
"Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors"
)
}
@@ -0,0 +1,14 @@
/*
* 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.openapi.project.Project
import com.intellij.openapi.roots.LanguageLevelProjectExtension
import com.intellij.pom.java.LanguageLevel
fun Project.setupHighestLanguageLevel() {
LanguageLevelProjectExtension.getInstance(this).languageLevel = LanguageLevel.JDK_15_PREVIEW
}
@@ -0,0 +1,14 @@
/*
* 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.openapi.project.Project
import com.intellij.openapi.roots.LanguageLevelProjectExtension
import com.intellij.pom.java.LanguageLevel
fun Project.setupHighestLanguageLevel() {
// LanguageLevelProjectExtension.getInstance(this).languageLevel = LanguageLevel.JDK_15_PREVIEW
}
@@ -253,7 +253,7 @@ class KotlinCoreEnvironment private constructor(
updateClasspath(roots.map { JavaSourceRoot(it, null) })
})
LanguageLevelProjectExtension.getInstance(project).languageLevel = LanguageLevel.JDK_15_PREVIEW
project.setupHighestLanguageLevel()
}
private fun collectAdditionalSources(project: MockProject) {
@@ -1,703 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.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)
}
}
}
}
}
@@ -52,10 +52,10 @@ import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
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.diagnostics.Severity
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.session.FirJvmModuleInfo
@@ -389,10 +389,8 @@ object KotlinToJVMBytecodeCompiler {
performanceManager?.notifyIRGenerationStarted()
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager, extensions
) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent)
}
generationState, moduleFragment, symbolTable, sourceManager, extensions, FirJvmBackendExtension(session, components)
)
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
@@ -572,8 +570,6 @@ object KotlinToJVMBytecodeCompiler {
sourceFiles: List<KtFile>,
module: Module?
): GenerationState {
val isIR = (configuration.getBoolean(JVMConfigurationKeys.IR) ||
configuration.getBoolean(CommonConfigurationKeys.USE_FIR))
val generationState = GenerationState.Builder(
environment.project,
ClassBuilderFactories.BINARIES,
@@ -583,13 +579,12 @@ object KotlinToJVMBytecodeCompiler {
configuration
)
.codegenFactory(
if (isIR) JvmIrCodegenFactory(
if (configuration.getBoolean(JVMConfigurationKeys.IR)) JvmIrCodegenFactory(
configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases)
) else DefaultCodegenFactory
)
.withModule(module)
.onIndependentPartCompilationEnd(createOutputFilesFlushingCallbackIfPossible(configuration))
.isIrBackend(isIR)
.build()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.getLibraryFromHome
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
@@ -19,9 +20,6 @@ import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArguments) {
val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
put(JVMConfigurationKeys.INCLUDE_RUNTIME, arguments.includeRuntime)
putIfNotNull(JVMConfigurationKeys.FRIEND_PATHS, arguments.friendPaths?.asList())
@@ -71,9 +69,6 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): Boolean {
val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
if (arguments.noJdk) {
put(JVMConfigurationKeys.NO_JDK, true)
@@ -84,7 +79,7 @@ fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): B
}
if (arguments.jdkHome != null) {
val jdkHome = File(arguments.jdkHome)
val jdkHome = File(arguments.jdkHome!!)
if (!jdkHome.exists()) {
messageCollector.report(ERROR, "JDK home directory does not exist: $jdkHome")
return false
@@ -114,7 +109,6 @@ fun CompilerConfiguration.configureExplicitContentRoots(arguments: K2JVMCompiler
}
fun CompilerConfiguration.configureStandardLibs(paths: KotlinPaths?, arguments: K2JVMCompilerArguments) {
val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val isModularJava = isModularJava()
fun addRoot(moduleName: String, libraryName: String, getLibrary: (KotlinPaths) -> File, noLibraryArgument: String) {
@@ -171,8 +165,23 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters)
put(JVMConfigurationKeys.IR, arguments.useIR && !arguments.noUseIR)
put(JVMConfigurationKeys.IS_IR_WITH_STABLE_ABI, arguments.isIrWithStableAbi)
val useIR = (arguments.useIR && !arguments.noUseIR) || arguments.useFir
put(JVMConfigurationKeys.IR, useIR)
val abiStability = JvmAbiStability.fromStringOrNull(arguments.abiStability)
if (arguments.abiStability != null) {
if (abiStability == null) {
messageCollector.report(
ERROR,
"Unknown ABI stability mode: ${arguments.abiStability}, supported modes: ${JvmAbiStability.values().map { it.description }}"
)
} else if (!useIR && abiStability == JvmAbiStability.UNSTABLE) {
messageCollector.report(ERROR, "-Xabi-stability=unstable is not supported in the old JVM backend")
} else {
put(JVMConfigurationKeys.ABI_STABILITY, abiStability)
}
}
put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, arguments.doNotClearBindingContext)
put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions)
put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions)
@@ -189,43 +198,34 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.NO_UNIFIED_NULL_CHECKS, arguments.noUnifiedNullChecks)
if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
messageCollector.report(
ERROR,
"Unknown constructor call normalization mode: ${arguments.constructorCallNormalizationMode}, " +
"supported modes: ${JVMConstructorCallNormalizationMode.values().map { it.description }}"
)
}
val constructorCallNormalizationMode =
JVMConstructorCallNormalizationMode.fromStringOrNull(arguments.constructorCallNormalizationMode)
val constructorCallNormalizationMode = JVMConstructorCallNormalizationMode.fromStringOrNull(arguments.constructorCallNormalizationMode)
if (constructorCallNormalizationMode != null) {
put(
JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE,
constructorCallNormalizationMode
)
put(JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE, constructorCallNormalizationMode)
}
val assertionsMode =
JVMAssertionsMode.fromStringOrNull(arguments.assertionsMode)
if (assertionsMode == null) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
messageCollector.report(
ERROR,
"Unknown assertions mode: ${arguments.assertionsMode}, " +
"supported modes: ${JVMAssertionsMode.values().map { it.description }}"
"Unknown assertions mode: ${arguments.assertionsMode}, supported modes: ${JVMAssertionsMode.values().map { it.description }}"
)
}
put(
JVMConfigurationKeys.ASSERTIONS_MODE,
assertionsMode ?: JVMAssertionsMode.DEFAULT
)
put(JVMConfigurationKeys.ASSERTIONS_MODE, assertionsMode ?: JVMAssertionsMode.DEFAULT)
put(JVMConfigurationKeys.USE_TYPE_TABLE, arguments.useTypeTable)
put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck)
put(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING, arguments.useOldClassFilesReading)
if (arguments.useOldClassFilesReading) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
.report(INFO, "Using the old java class files reading implementation")
messageCollector.report(INFO, "Using the old java class files reading implementation")
}
put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
@@ -235,8 +235,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.ENABLE_JVM_PREVIEW, arguments.enableJvmPreview)
if (arguments.enableJvmPreview) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
.report(INFO, "Using preview Java language features")
messageCollector.report(INFO, "Using preview Java language features")
}
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
@@ -249,3 +248,6 @@ fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments)
?.filterNot { it.isEmpty() }
?.let { put(JVMConfigurationKeys.KLIB_PATHS, it) }
}
private val CompilerConfiguration.messageCollector: MessageCollector
get() = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
@@ -117,8 +117,8 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<List<String>> KLIB_PATHS =
CompilerConfigurationKey.create("Paths to .klib libraries");
public static final CompilerConfigurationKey<Boolean> IS_IR_WITH_STABLE_ABI =
CompilerConfigurationKey.create("Is IR with stable ABI");
public static final CompilerConfigurationKey<JvmAbiStability> ABI_STABILITY =
CompilerConfigurationKey.create("ABI stability of class files produced by JVM IR and/or FIR");
public static final CompilerConfigurationKey<Boolean> DO_NOT_CLEAR_BINDING_CONTEXT =
CompilerConfigurationKey.create("When using the IR backend, do not clear BindingContext between psi2ir and lowerings");
@@ -0,0 +1,17 @@
/*
* 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.config
enum class JvmAbiStability(val description: String) {
STABLE("stable"),
UNSTABLE("unstable"),
;
companion object {
fun fromStringOrNull(string: String?): JvmAbiStability? =
values().find { it.description == string }
}
}
@@ -46,7 +46,7 @@ object AnalysisFlags {
val ideMode by AnalysisFlag.Delegates.Boolean
@JvmStatic
val reportErrorsOnIrDependencies by AnalysisFlag.Delegates.Boolean
val allowUnstableDependencies by AnalysisFlag.Delegates.Boolean
@JvmStatic
val libraryToSourceAnalysis by AnalysisFlag.Delegates.Boolean
+51 -11
View File
@@ -14,21 +14,59 @@ dependencies {
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
testApi(intellijDep())
testApi(commonDep("junit:junit"))
testCompileOnly(project(":kotlin-test:kotlin-test-jvm"))
testCompileOnly(project(":kotlin-test:kotlin-test-junit"))
testApi(projectTests(":compiler:tests-common"))
testApi(projectTests(":compiler:test-infrastructure"))
testApi(projectTests(":compiler:test-infrastructure-utils"))
testApi(projectTests(":compiler:tests-compiler-utils"))
testApi(projectTests(":compiler:tests-common-new"))
testApi(project(":compiler:cli"))
testApi(project(":compiler:fir:checkers"))
testApi(project(":compiler:fir:entrypoint"))
testApi(project(":compiler:frontend"))
testCompileOnly(project(":kotlin-reflect-api"))
testRuntime(project(":kotlin-reflect"))
testRuntime(project(":core:descriptors.runtime"))
testApi(platform("org.junit:junit-bom:5.7.0"))
testApi("org.junit.jupiter:junit-jupiter")
testApi("org.junit.platform:junit-platform-commons:1.7.0")
testCompileOnly(intellijCoreDep()) { includeJars("intellij-core") }
testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") }
testCompileOnly(project(":kotlin-reflect-api"))
testRuntimeOnly(project(":kotlin-reflect"))
testRuntimeOnly(project(":core:descriptors.runtime"))
testImplementation(intellijCoreDep()) { includeJars("intellij-core") }
testImplementation(intellijDep()) {
// This dependency is needed only for FileComparisonFailure
includeJars("idea_rt", rootProject = rootProject)
isTransitive = false
}
// This is needed only for using FileComparisonFailure, which relies on JUnit 3 classes
testRuntimeOnly(commonDep("junit:junit"))
testRuntimeOnly(intellijDep()) {
includeJars(
"jps-model",
"extensions",
"util",
"platform-api",
"platform-impl",
"idea",
"guava",
"trove4j",
"asm-all",
"log4j",
"jdom",
"streamex",
"bootstrap",
"jna",
rootProject = rootProject
)
}
Platform[202] {
testRuntimeOnly(intellijDep()) { includeJars("intellij-deps-fastutil-8.3.1-1") }
}
Platform[203].orHigher {
testRuntimeOnly(intellijDep()) { includeJars("intellij-deps-fastutil-8.3.1-3") }
}
testRuntimeOnly(toolsJar())
}
val generationRoot = projectDir.resolve("tests-gen")
@@ -48,11 +86,13 @@ if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
}
}
projectTest(parallel = true) {
projectTest(parallel = true, jUnit5Enabled = true) {
dependsOn(":dist")
workingDir = rootDir
jvmArgs!!.removeIf { it.contains("-Xmx") }
maxHeapSize = "3g"
useJUnitPlatform()
}
testsJar()
@@ -0,0 +1,58 @@
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.
*/
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
testApi(intellijDep())
testApi(commonDep("junit:junit"))
testCompileOnly(project(":kotlin-test:kotlin-test-jvm"))
testCompileOnly(project(":kotlin-test:kotlin-test-junit"))
testApi(projectTests(":compiler:tests-common"))
testApi(project(":compiler:fir:checkers"))
testApi(project(":compiler:fir:entrypoint"))
testApi(project(":compiler:frontend"))
testCompileOnly(project(":kotlin-reflect-api"))
testRuntimeOnly(project(":kotlin-reflect"))
testRuntimeOnly(project(":core:descriptors.runtime"))
testCompileOnly(intellijCoreDep()) { includeJars("intellij-core") }
testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") }
}
val generationRoot = projectDir.resolve("tests-gen")
sourceSets {
"main" { none() }
"test" {
projectDefault()
this.java.srcDir(generationRoot.name)
}
}
if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
apply(plugin = "idea")
idea {
this.module.generatedSourceDirs.add(generationRoot)
}
}
projectTest(parallel = true) {
dependsOn(":dist")
workingDir = rootDir
jvmArgs!!.removeIf { it.contains("-Xmx") }
maxHeapSize = "3g"
}
testsJar()
@@ -1685,6 +1685,419 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ExtendedCheckers extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInExtendedCheckers() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/extendedCheckers"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("ArrayEqualityCanBeReplacedWithEquals.kt")
public void testArrayEqualityCanBeReplacedWithEquals() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/ArrayEqualityCanBeReplacedWithEquals.kt");
}
@TestMetadata("CanBeValChecker.kt")
public void testCanBeValChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/CanBeValChecker.kt");
}
@TestMetadata("RedundantExplicitTypeChecker.kt")
public void testRedundantExplicitTypeChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantExplicitTypeChecker.kt");
}
@TestMetadata("RedundantModalityModifierChecker.kt")
public void testRedundantModalityModifierChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantModalityModifierChecker.kt");
}
@TestMetadata("RedundantReturnUnitTypeChecker.kt")
public void testRedundantReturnUnitTypeChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantReturnUnitTypeChecker.kt");
}
@TestMetadata("RedundantSetterParameterTypeChecker.kt")
public void testRedundantSetterParameterTypeChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantSetterParameterTypeChecker.kt");
}
@TestMetadata("RedundantSingleExpressionStringTemplateChecker.kt")
public void testRedundantSingleExpressionStringTemplateChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantSingleExpressionStringTemplateChecker.kt");
}
@TestMetadata("RedundantVisibilityModifierChecker.kt")
public void testRedundantVisibilityModifierChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierChecker.kt");
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class CanBeReplacedWithOperatorAssignment extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCanBeReplacedWithOperatorAssignment() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("BasicTest.kt")
public void testBasicTest() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/BasicTest.kt");
}
@TestMetadata("ComplexExpression.kt")
public void testComplexExpression() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/ComplexExpression.kt");
}
@TestMetadata("flexibleTypeBug.kt")
public void testFlexibleTypeBug() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/flexibleTypeBug.kt");
}
@TestMetadata("illegalMultipleOperators.kt")
public void testIllegalMultipleOperators() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/illegalMultipleOperators.kt");
}
@TestMetadata("illegalMultipleOperatorsMiddle.kt")
public void testIllegalMultipleOperatorsMiddle() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/illegalMultipleOperatorsMiddle.kt");
}
@TestMetadata("invalidSubtraction.kt")
public void testInvalidSubtraction() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/invalidSubtraction.kt");
}
@TestMetadata("list.kt")
public void testList() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/list.kt");
}
@TestMetadata("logicOperators.kt")
public void testLogicOperators() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/logicOperators.kt");
}
@TestMetadata("multipleOperators.kt")
public void testMultipleOperators() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/multipleOperators.kt");
}
@TestMetadata("multipleOperatorsRightSideRepeat.kt")
public void testMultipleOperatorsRightSideRepeat() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/multipleOperatorsRightSideRepeat.kt");
}
@TestMetadata("mutableList.kt")
public void testMutableList() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/mutableList.kt");
}
@TestMetadata("nonCommutativeRepeat.kt")
public void testNonCommutativeRepeat() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/nonCommutativeRepeat.kt");
}
@TestMetadata("nonRepeatingAssignment.kt")
public void testNonRepeatingAssignment() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/nonRepeatingAssignment.kt");
}
@TestMetadata("OperatorAssignment.kt")
public void testOperatorAssignment() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/OperatorAssignment.kt");
}
@TestMetadata("plusAssignConflict.kt")
public void testPlusAssignConflict() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/plusAssignConflict.kt");
}
@TestMetadata("rightSideRepeat.kt")
public void testRightSideRepeat() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/rightSideRepeat.kt");
}
@TestMetadata("simpleAssign.kt")
public void testSimpleAssign() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/simpleAssign.kt");
}
@TestMetadata("validAddition.kt")
public void testValidAddition() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/validAddition.kt");
}
@TestMetadata("validSubtraction.kt")
public void testValidSubtraction() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment/validSubtraction.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/emptyRangeChecker")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EmptyRangeChecker extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEmptyRangeChecker() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/emptyRangeChecker"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("NoWarning.kt")
public void testNoWarning() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/emptyRangeChecker/NoWarning.kt");
}
@TestMetadata("Warning.kt")
public void testWarning() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/emptyRangeChecker/Warning.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class RedundantCallOfConversionMethod extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInRedundantCallOfConversionMethod() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("booleanToInt.kt")
public void testBooleanToInt() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/booleanToInt.kt");
}
@TestMetadata("byte.kt")
public void testByte() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/byte.kt");
}
@TestMetadata("char.kt")
public void testChar() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/char.kt");
}
@TestMetadata("double.kt")
public void testDouble() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/double.kt");
}
@TestMetadata("float.kt")
public void testFloat() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/float.kt");
}
@TestMetadata("int.kt")
public void testInt() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/int.kt");
}
@TestMetadata("long.kt")
public void testLong() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/long.kt");
}
@TestMetadata("nullable.kt")
public void testNullable() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/nullable.kt");
}
@TestMetadata("nullable2.kt")
public void testNullable2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/nullable2.kt");
}
@TestMetadata("safeString.kt")
public void testSafeString() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/safeString.kt");
}
@TestMetadata("safeString2.kt")
public void testSafeString2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/safeString2.kt");
}
@TestMetadata("short.kt")
public void testShort() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/short.kt");
}
@TestMetadata("string.kt")
public void testString() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/string.kt");
}
@TestMetadata("StringTemplate.kt")
public void testStringTemplate() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/StringTemplate.kt");
}
@TestMetadata("toOtherType.kt")
public void testToOtherType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/toOtherType.kt");
}
@TestMetadata("uByte.kt")
public void testUByte() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/uByte.kt");
}
@TestMetadata("uInt.kt")
public void testUInt() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/uInt.kt");
}
@TestMetadata("uLong.kt")
public void testULong() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/uLong.kt");
}
@TestMetadata("uShort.kt")
public void testUShort() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/uShort.kt");
}
@TestMetadata("variable.kt")
public void testVariable() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantCallOfConversionMethod/variable.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Unused extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUnused() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("classProperty.kt")
public void testClassProperty() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused/classProperty.kt");
}
@TestMetadata("invoke.kt")
public void testInvoke() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused/invoke.kt");
}
@TestMetadata("lambda.kt")
public void testLambda() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused/lambda.kt");
}
@TestMetadata("localVariable.kt")
public void testLocalVariable() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused/localVariable.kt");
}
@TestMetadata("manyLocalVariables.kt")
public void testManyLocalVariables() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused/manyLocalVariables.kt");
}
@TestMetadata("usedInAnnotationArguments.kt")
public void testUsedInAnnotationArguments() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused/usedInAnnotationArguments.kt");
}
@TestMetadata("valueIsNeverRead.kt")
public void testValueIsNeverRead() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/unused/valueIsNeverRead.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UselessCallOnNotNullChecker extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUselessCallOnNotNullChecker() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("Basic.kt")
public void testBasic() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/Basic.kt");
}
@TestMetadata("NotNullType.kt")
public void testNotNullType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/NotNullType.kt");
}
@TestMetadata("NotNullTypeChain.kt")
public void testNotNullTypeChain() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/NotNullTypeChain.kt");
}
@TestMetadata("NullOrBlankSafe.kt")
public void testNullOrBlankSafe() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/NullOrBlankSafe.kt");
}
@TestMetadata("NullOrEmpty.kt")
public void testNullOrEmpty() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/NullOrEmpty.kt");
}
@TestMetadata("NullOrEmptyFake.kt")
public void testNullOrEmptyFake() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/NullOrEmptyFake.kt");
}
@TestMetadata("NullOrEmptySafe.kt")
public void testNullOrEmptySafe() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/NullOrEmptySafe.kt");
}
@TestMetadata("OrEmptyFake.kt")
public void testOrEmptyFake() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/OrEmptyFake.kt");
}
@TestMetadata("SafeCall.kt")
public void testSafeCall() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/SafeCall.kt");
}
@TestMetadata("Sequence.kt")
public void testSequence() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/Sequence.kt");
}
@TestMetadata("String.kt")
public void testString() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/UselessCallOnNotNullChecker/String.kt");
}
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/fromBuilder")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -61,7 +61,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
}
private fun createJarWithForeignAnnotations(): File =
MockLibraryUtil.compileJavaFilesLibraryToJar(FOREIGN_ANNOTATIONS_SOURCES_PATH, "foreign-annotations")
MockLibraryUtilExt.compileJavaFilesLibraryToJar(FOREIGN_ANNOTATIONS_SOURCES_PATH, "foreign-annotations")
private fun createEnvironment(content: String): KotlinCoreEnvironment {
val classpath = mutableListOf(getAnnotationsJar(), ForTestCompileRuntime.runtimeJarForTests())
@@ -1,17 +0,0 @@
// WITH_RUNTIME
fun foo(p: Int) {
val a = arrayOf(1, 2, 3)
val b = arrayOf(3, 2, 1)
if (a <!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS!>==<!> b) { }
}
fun testsFromIdea() {
val a = arrayOf("a")
val b = a
val c: Any? = null
a <!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS!>==<!> b
a == c
a <!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS!>!=<!> b
}
@@ -1,5 +0,0 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
fun foo(s: String?) {
val <!UNUSED_VARIABLE!>t<!>: String = s.toString()
}
@@ -1,6 +0,0 @@
// WITH_RUNTIME
data class Foo(val name: String)
fun test(foo: Foo?) {
val <!UNUSED_VARIABLE!>s<!>: String? = foo?.name?.<!REDUNDANT_CALL_OF_CONVERSION_METHOD!>toString()<!>
}
@@ -1,4 +0,0 @@
// WITH_RUNTIME
fun test(i: UByte) {
val <!UNUSED_VARIABLE!>foo<!> = i.<!REDUNDANT_CALL_OF_CONVERSION_METHOD!>toUByte()<!>
}
@@ -1,4 +0,0 @@
// WITH_RUNTIME
fun test(i: UInt) {
val <!UNUSED_VARIABLE!>foo<!> = i.<!REDUNDANT_CALL_OF_CONVERSION_METHOD!>toUInt()<!>
}
@@ -1,4 +0,0 @@
// WITH_RUNTIME
fun test(i: ULong) {
val <!UNUSED_VARIABLE!>foo<!> = i.<!REDUNDANT_CALL_OF_CONVERSION_METHOD!>toULong()<!>
}
@@ -1,4 +0,0 @@
// WITH_RUNTIME
fun test(i: UShort) {
val <!UNUSED_VARIABLE!>foo<!> = i.<!REDUNDANT_CALL_OF_CONVERSION_METHOD!>toUShort()<!>
}
@@ -1,76 +0,0 @@
import kotlin.reflect.KClass
@Target(AnnotationTarget.TYPE)
annotation class A
fun annotated() {
val <!UNUSED_VARIABLE!>x<!>: @A Int /* NOT redundant */ = 1
}
object SomeObj
fun fer() {
val <!UNUSED_VARIABLE!>x<!>: Any /* NOT redundant */ = SomeObj
}
fun f2(y: String?): String {
val <!UNUSED_VARIABLE!>f<!>: KClass<*> = (y ?: return "")::class
return ""
}
object Obj {}
interface IA
interface IB : IA
fun IA.extFun(x: IB) {}
fun testWithExpectedType() {
val <!UNUSED_VARIABLE!>extFun_AB_A<!>: IA.(IB) -> Unit = IA::extFun
}
interface Point {
val x: Int
val y: Int
}
class PointImpl(override val x: Int, override val y: Int) : Point
fun foo() {
val <!UNUSED_VARIABLE!>s<!>: <!REDUNDANT_EXPLICIT_TYPE!>String<!> = "Hello ${10+1}"
val <!UNUSED_VARIABLE!>str<!>: String? = ""
val <!UNUSED_VARIABLE!>o<!>: <!REDUNDANT_EXPLICIT_TYPE!>Obj<!> = Obj
val <!UNUSED_VARIABLE!>p<!>: Point = PointImpl(1, 2)
val <!UNUSED_VARIABLE!>a<!>: <!REDUNDANT_EXPLICIT_TYPE!>Boolean<!> = true
val <!UNUSED_VARIABLE!>i<!>: Int = 2 * 2
val <!UNUSED_VARIABLE!>l<!>: <!REDUNDANT_EXPLICIT_TYPE!>Long<!> = 1234567890123L
val <!UNUSED_VARIABLE!>s<!>: String? = null
val <!UNUSED_VARIABLE!>sh<!>: Short = 42
val <!UNUSED_VARIABLE!>integer<!>: <!REDUNDANT_EXPLICIT_TYPE!>Int<!> = 42
val <!UNUSED_VARIABLE!>piFloat<!>: <!REDUNDANT_EXPLICIT_TYPE!>Float<!> = 3.14f
val <!UNUSED_VARIABLE!>piDouble<!>: <!REDUNDANT_EXPLICIT_TYPE!>Double<!> = 3.14
val <!UNUSED_VARIABLE!>charZ<!>: <!REDUNDANT_EXPLICIT_TYPE!>Char<!> = 'z'
<!CAN_BE_VAL!>var<!> <!UNUSED_VARIABLE!>alpha<!>: <!REDUNDANT_EXPLICIT_TYPE!>Int<!> = 0
}
fun test(boolean: Boolean) {
val <!UNUSED_VARIABLE!>expectedLong<!>: Long = if (boolean) {
42
} else {
return
}
}
class My {
val x: Int = 1
}
val ZERO: Int = 0
fun main() {
val <!UNUSED_VARIABLE!>id<!>: Id = 11
}
typealias Id = Int
@@ -1,85 +0,0 @@
object O {
fun foo() {}
}
// Interface
interface Interface {
// Questionable cuz compiler reports warning here in FE 1.0
<!REDUNDANT_MODALITY_MODIFIER!>open<!> val gav: Int
get() = 42
// Redundant
<!REDUNDANT_MODALITY_MODIFIER!>abstract<!> fun foo()
// error
private final fun bar() {}
<!REDUNDANT_MODALITY_MODIFIER!>open<!> fun goo() {}
<!REDUNDANT_MODALITY_MODIFIER!>abstract<!> fun tar()
// error
abstract fun too() {}
}
interface B {
<!REDUNDANT_MODALITY_MODIFIER!>abstract<!> var bar: Unit
<!REDUNDANT_MODALITY_MODIFIER!>abstract<!> fun foo()
}
interface Foo
expect abstract class AbstractClass : Foo {
abstract override fun foo()
abstract fun bar()
abstract val baz: Int
}
// Abstract
abstract class Base {
// Redundant final
<!REDUNDANT_MODALITY_MODIFIER!>final<!> fun foo() {}
// Abstract
abstract fun bar()
// Open
open val gav = 42
}
class FinalDerived : Base() {
// Redundant final
override <!REDUNDANT_MODALITY_MODIFIER!>final<!> fun bar() {}
// Non-final member in final class
override open val gav = 13
}
// Open
open class OpenDerived : Base() {
// Final
override final fun bar() {}
// Redundant open
override <!REDUNDANT_MODALITY_MODIFIER!>open<!> val gav = 13
}
// Redundant final
<!REDUNDANT_MODALITY_MODIFIER!>final<!> class Final
// Derived interface
interface Derived : Interface {
// Redundant
override <!REDUNDANT_MODALITY_MODIFIER!>open<!> fun foo() {}
// error
final class Nested
}
// Derived abstract class
abstract class AbstractDerived1(override final val gav: Int) : Interface {
// Redundant
override <!REDUNDANT_MODALITY_MODIFIER!>open<!> fun foo() {}
}
// Derived abstract class
abstract class AbstractDerived2 : Interface {
// Final
override final fun foo() {}
// Redundant
override <!REDUNDANT_MODALITY_MODIFIER!>open<!> val gav = 13
}
// Redundant abstract interface
abstract interface AbstractInterface
// Redundant final object
<!REDUNDANT_MODALITY_MODIFIER!>final<!> object FinalObject
// Open interface
open interface OpenInterface
@@ -1,86 +0,0 @@
fun f() {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> <!CAN_BE_VAL!>var<!> <!UNUSED_VARIABLE!>baz<!> = 0
class LocalClass {
<!REDUNDANT_VISIBILITY_MODIFIER!>internal<!> var foo = 0
}
LocalClass().foo = 1
}
internal inline fun internal() {
f()
}
<!REDECLARATION!>class C {
internal val z = object {
fun foo() = 13
}
}<!>
class Foo2<
T1,
T2: T1,
> {
fun <T1,
T2, > foo2() {}
internal inner class B<T,T2,>
}
<!REDECLARATION!><!REDUNDANT_VISIBILITY_MODIFIER!>public<!> class C {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> val foo: Int = 0
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> fun bar() {}
}<!>
open class D {
protected open fun willRemainProtected() {
}
protected open fun willBecomePublic() {
}
}
class E : D() {
<!REDUNDANT_VISIBILITY_MODIFIER!>protected<!> override fun willRemainProtected() {
}
public override fun willBecomePublic() {
}
}
enum class F <!REDUNDANT_VISIBILITY_MODIFIER!>private<!> constructor(val x: Int) {
FIRST(42)
}
sealed class G constructor(val y: Int) {
<!REDUNDANT_VISIBILITY_MODIFIER!>private<!> constructor(): this(42)
object H : G()
}
interface I {
fun bar()
}
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> var baz = 0
open class J {
protected val baz = 0
<!REDUNDANT_VISIBILITY_MODIFIER!>protected<!> get() = field * 2
var baf = 0
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> get() = 1
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> set(value) {
field = value
}
var buf = 0
private get() = 42
protected set(value) {
field = value
}
var bar = 0
get() = 3.1415926535
set(value) {}
}
@@ -1,5 +0,0 @@
// WITH_RUNTIME
fun test(s: Sequence<Int>) {
val <!UNUSED_VARIABLE!>foo<!> = s.<!USELESS_CALL_ON_NOT_NULL!>orEmpty()<!>
}
@@ -1,7 +0,0 @@
fun goo() {
var a = 2
val b = 4
a <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> a + 1 + b
a <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> (a + 1)
<!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = a * b + 1
}
@@ -1,5 +0,0 @@
fun foo() {
var x = 0
<!CAN_BE_VAL!>var<!> y = 0
<!ASSIGNED_VALUE_IS_NEVER_READ!>x<!> <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x + y + 5
}
@@ -1,5 +0,0 @@
fun foo() {
var x = 0
<!CAN_BE_VAL!>var<!> y = 0
<!ASSIGNED_VALUE_IS_NEVER_READ!>x<!> <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> y + x + 5
}
@@ -1,8 +0,0 @@
fun foo() {
var x = 0
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x - 1 - 1
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x / 1
x = 1 / x
<!ASSIGNED_VALUE_IS_NEVER_READ!>x<!> <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> -1 + x
}
@@ -1,4 +0,0 @@
fun foo() {
var x = 0
<!ASSIGNED_VALUE_IS_NEVER_READ!>x<!> <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> 1 + x
}
@@ -1,5 +0,0 @@
fun foo() {
var y = 0
val x = 0
<!ASSIGNED_VALUE_IS_NEVER_READ!>y<!> <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> y + x
}
@@ -1,4 +0,0 @@
fun foo() {
var x = 0
<!ASSIGNED_VALUE_IS_NEVER_READ!>x<!> <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x + 1
}
@@ -1,4 +0,0 @@
fun foo() {
var x = 0
<!ASSIGNED_VALUE_IS_NEVER_READ!>x<!> <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x - 1
}
@@ -0,0 +1,17 @@
// WITH_RUNTIME
fun foo(p: Int) {
val a = arrayOf(1, 2, 3)
val b = arrayOf(3, 2, 1)
if (<!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS{LT}!>a <!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS{PSI}!>==<!> b<!>) { }
}
fun testsFromIdea() {
val a = arrayOf("a")
val b = a
val c: Any? = null
<!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS{LT}!>a <!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS{PSI}!>==<!> b<!>
a == c
<!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS{LT}!>a <!ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS{PSI}!>!=<!> b<!>
}
@@ -4,8 +4,8 @@ import kotlin.reflect.KProperty
import kotlin.properties.Delegates
fun testDelegator() {
var <!UNUSED_VARIABLE!>x<!>: Boolean by LocalFreezableVar(true)
var <!UNUSED_VARIABLE!>y<!> by LocalFreezableVar("")
<!UNUSED_VARIABLE{LT}!>var <!UNUSED_VARIABLE{PSI}!>x<!>: Boolean by LocalFreezableVar(true)<!>
<!UNUSED_VARIABLE{LT}!>var <!UNUSED_VARIABLE{PSI}!>y<!> by LocalFreezableVar("")<!>
}
class LocalFreezableVar<T>(private var value: T) {
@@ -23,7 +23,7 @@ operator fun C.plusAssign(a: Any) {}
fun testOperatorAssignment() {
val c = C()
c += ""
<!CAN_BE_VAL!>var<!> c1 = C()
<!CAN_BE_VAL{LT}!><!CAN_BE_VAL{PSI}!>var<!> c1 = C()<!>
<!ASSIGN_OPERATOR_AMBIGUITY!>c1 += ""<!>
var a = 1
@@ -33,7 +33,7 @@ fun testOperatorAssignment() {
fun destructuringDeclaration() {
<!CAN_BE_VAL!>var<!> (v1, <!UNUSED_VARIABLE!>v2<!>) = getPair()
<!CAN_BE_VAL{LT}!><!CAN_BE_VAL{PSI}!>var<!> (v1, <!UNUSED_VARIABLE!>v2<!>) = getPair()<!>
print(v1)
var (v3, <!VARIABLE_NEVER_READ!>v4<!>) = getPair()
@@ -49,11 +49,11 @@ fun destructuringDeclaration() {
val (<!UNUSED_VARIABLE!>a<!>, <!UNUSED_VARIABLE!>b<!>, <!UNUSED_VARIABLE!>c<!>) = Triple(1, 1, 1)
<!CAN_BE_VAL!>var<!> (<!UNUSED_VARIABLE!>x<!>, <!UNUSED_VARIABLE!>y<!>, <!UNUSED_VARIABLE!>z<!>) = Triple(1, 1, 1)
<!CAN_BE_VAL{LT}!><!CAN_BE_VAL{PSI}!>var<!> (<!UNUSED_VARIABLE!>x<!>, <!UNUSED_VARIABLE!>y<!>, <!UNUSED_VARIABLE!>z<!>) = Triple(1, 1, 1)<!>
}
fun stackOverflowBug() {
<!CAN_BE_VAL!>var<!> <!VARIABLE_NEVER_READ!>a<!>: Int
<!CAN_BE_VAL{LT}, VARIABLE_NEVER_READ{LT}!><!CAN_BE_VAL{PSI}!>var<!> <!VARIABLE_NEVER_READ{PSI}!>a<!>: Int<!>
<!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 1
for (i in 1..10)
print(i)
@@ -71,8 +71,8 @@ fun smth(flag: Boolean) {
}
fun withAnnotation(p: List<Any>) {
@Suppress("UNCHECKED_CAST")
<!CAN_BE_VAL!>var<!> v = p as List<String>
<!CAN_BE_VAL{LT}!>@Suppress("UNCHECKED_CAST")
<!CAN_BE_VAL{PSI}!>var<!> v = p as List<String><!>
print(v)
}
@@ -86,9 +86,9 @@ fun getPair(): Pair<Int, String> = Pair(1, "1")
fun listReceiver(p: List<String>) {}
fun withInitializer() {
var <!VARIABLE_NEVER_READ!>v1<!> = 1
<!VARIABLE_NEVER_READ{LT}!>var <!VARIABLE_NEVER_READ{PSI}!>v1<!> = 1<!>
var v2 = 2
<!CAN_BE_VAL!>var<!> v3 = 3
<!CAN_BE_VAL{LT}!><!CAN_BE_VAL{PSI}!>var<!> v3 = 3<!>
<!ASSIGNED_VALUE_IS_NEVER_READ!>v1<!> = 1
<!ASSIGNED_VALUE_IS_NEVER_READ!>v2<!>++ // todo mark this UNUSED_CHANGED_VALUES
print(v3)
@@ -102,10 +102,10 @@ fun test() {
}
fun foo() {
<!CAN_BE_VAL!>var<!> <!VARIABLE_NEVER_READ!>a<!>: Int
<!CAN_BE_VAL{LT}, VARIABLE_NEVER_READ{LT}!><!CAN_BE_VAL{PSI}!>var<!> <!VARIABLE_NEVER_READ{PSI}!>a<!>: Int<!>
val bool = true
if (bool) <!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 4 else <!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 42
val <!UNUSED_VARIABLE!>b<!>: String
<!UNUSED_VARIABLE{LT}!>val <!UNUSED_VARIABLE{PSI}!>b<!>: String<!>
<!ASSIGNED_VALUE_IS_NEVER_READ!>bool<!> = false
}
@@ -116,7 +116,7 @@ fun cycles() {
a--
}
var <!VARIABLE_NEVER_READ!>b<!>: Int
<!VARIABLE_NEVER_READ{LT}!>var <!VARIABLE_NEVER_READ{PSI}!>b<!>: Int<!>
while (a < 10) {
a++
<!ASSIGNED_VALUE_IS_NEVER_READ!>b<!> = a
@@ -124,14 +124,14 @@ fun cycles() {
}
fun assignedTwice(p: Int) {
var <!VARIABLE_NEVER_READ!>v<!>: Int
<!VARIABLE_NEVER_READ{LT}!>var <!VARIABLE_NEVER_READ{PSI}!>v<!>: Int<!>
<!ASSIGNED_VALUE_IS_NEVER_READ!>v<!> = 0
if (p > 0) <!ASSIGNED_VALUE_IS_NEVER_READ!>v<!> = 1
}
fun main(args: Array<String?>) {
<!CAN_BE_VAL!>var<!> a: String?
val <!UNUSED_VARIABLE!>unused<!> = 0
<!CAN_BE_VAL{LT}!><!CAN_BE_VAL{PSI}!>var<!> a: String?<!>
<!UNUSED_VARIABLE{LT}!>val <!UNUSED_VARIABLE{PSI}!>unused<!> = 0<!>
if (args.size == 1) {
<!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = args[0]
@@ -144,7 +144,7 @@ fun main(args: Array<String?>) {
fun run(f: () -> Unit) = f()
fun lambda() {
var <!VARIABLE_NEVER_READ!>a<!>: Int
<!VARIABLE_NEVER_READ{LT}!>var <!VARIABLE_NEVER_READ{PSI}!>a<!>: Int<!>
<!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 10
run {
@@ -153,7 +153,7 @@ fun lambda() {
}
fun lambdaInitialization() {
<!CAN_BE_VAL!>var<!> <!VARIABLE_NEVER_READ!>a<!>: Int
<!CAN_BE_VAL{LT}, VARIABLE_NEVER_READ{LT}!><!CAN_BE_VAL{PSI}!>var<!> <!VARIABLE_NEVER_READ{PSI}!>a<!>: Int<!>
run {
<!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 20
@@ -161,7 +161,7 @@ fun lambdaInitialization() {
}
fun notAssignedWhenNotUsed(p: Int) {
<!CAN_BE_VAL!>var<!> v: Int
<!CAN_BE_VAL{LT}!><!CAN_BE_VAL{PSI}!>var<!> v: Int<!>
if (p > 0) {
v = 1
print(v)
@@ -180,6 +180,6 @@ class C {
}
fun withDelegate() {
var <!VARIABLE_NEVER_READ!>s<!>: String by Delegates.notNull()
<!VARIABLE_NEVER_READ{LT}!>var <!VARIABLE_NEVER_READ{PSI}!>s<!>: String by Delegates.notNull()<!>
<!ASSIGNED_VALUE_IS_NEVER_READ!>s<!> = ""
}
@@ -0,0 +1,5 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
fun foo(s: String?) {
<!UNUSED_VARIABLE{LT}!>val <!UNUSED_VARIABLE{PSI}!>t<!>: String = s.toString()<!>
}
@@ -3,5 +3,5 @@
data class Foo(val name: String)
fun nullable2(foo: Foo?) {
val <!UNUSED_VARIABLE!>s<!>: String = foo?.name.toString()
}
<!UNUSED_VARIABLE{LT}!>val <!UNUSED_VARIABLE{PSI}!>s<!>: String = foo?.name.toString()<!>
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
data class Foo(val name: String)
fun test(foo: Foo?) {
<!UNUSED_VARIABLE{LT}!>val <!UNUSED_VARIABLE{PSI}!>s<!>: String? = foo?.name?.<!REDUNDANT_CALL_OF_CONVERSION_METHOD!>toString()<!><!>
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun test(i: UByte) {
<!UNUSED_VARIABLE{LT}!>val <!UNUSED_VARIABLE{PSI}!>foo<!> = i.<!REDUNDANT_CALL_OF_CONVERSION_METHOD!>toUByte()<!><!>
}

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