diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index ac52890d758..91aeac0076e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -1103,6 +1103,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt"); } + @Test + @TestMetadata("ConstructorCallAllowed.kt") + public void testConstructorCallAllowed() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt"); + } + @Test @TestMetadata("DanglingMixed.kt") public void testDanglingMixed() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 84a41d5e0ce..08899a2c828 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -1103,6 +1103,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt"); } + @Test + @TestMetadata("ConstructorCallAllowed.kt") + public void testConstructorCallAllowed() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt"); + } + @Test @TestMetadata("DanglingMixed.kt") public void testDanglingMixed() throws Exception { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt index 130e18b93cc..f06f206c95b 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 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. */ diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index e5016b6851c..c7d57435468 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -380,6 +380,76 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT } } + @Nested + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + public class Instances { + @Test + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("annotationEnclosingName.kt") + public void testAnnotationEnclosingName() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationEnclosingName.kt"); + } + + @Test + @TestMetadata("annotationEqHc.kt") + public void testAnnotationEqHc() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt"); + } + + @Test + @TestMetadata("annotationInstances.kt") + public void testAnnotationInstances() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt"); + } + + @Test + @TestMetadata("annotationInstancesEmptyDefault.kt") + public void testAnnotationInstancesEmptyDefault() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefault.kt"); + } + + @Test + @TestMetadata("annotationToString.kt") + public void testAnnotationToString() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt"); + } + + @Test + @TestMetadata("annotationType.kt") + public void testAnnotationType() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt"); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt"); + } + + @Test + @TestMetadata("multifileEqHc.kt") + public void testMultifileEqHc() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt"); + } + + @Test + @TestMetadata("multimoduleInlining.kt") + public void testMultimoduleInlining() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/multimoduleInlining.kt"); + } + + @Test + @TestMetadata("multiplatformInstantiation.kt") + public void testMultiplatformInstantiation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java index 40c1c1f2bc8..53c77a61944 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java @@ -25,6 +25,28 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("annotationInstanceInlining.kt") + public void testAnnotationInstanceInlining() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt"); + } + + @Test + @TestMetadata("instanceInAnonymousClass.kt") + public void testInstanceInAnonymousClass() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt index 17a8d8fba63..3f5906103ea 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt @@ -1,17 +1,6 @@ /* - * 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. + * Copyright 2010-2021 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.resolve.calls @@ -238,7 +227,8 @@ class CallExpressionResolver( if (functionDescriptor is ConstructorDescriptor) { val constructedClass = functionDescriptor.constructedClass if (DescriptorUtils.isAnnotationClass(constructedClass) && !canInstantiateAnnotationClass(callExpression, context.trace)) { - context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression)) + val supported = context.languageVersionSettings.supportsFeature(LanguageFeature.InstantiationOfAnnotationClasses) && constructedClass.declaredTypeParameters.isEmpty() + if (!supported) context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression)) } if (DescriptorUtils.isEnumClass(constructedClass)) { context.trace.report(ENUM_CLASS_CONSTRUCTOR_CALL.on(callExpression)) @@ -515,7 +505,7 @@ class CallExpressionResolver( companion object { - private fun canInstantiateAnnotationClass(expression: KtCallExpression, trace: BindingTrace): Boolean { + fun canInstantiateAnnotationClass(expression: KtCallExpression, trace: BindingTrace): Boolean { //noinspection unchecked var parent: PsiElement? = PsiTreeUtil.getParentOfType(expression, KtValueArgument::class.java, KtParameter::class.java) if (parent is KtValueArgument) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InstantiationOfAnnotationClassesCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InstantiationOfAnnotationClassesCallChecker.kt new file mode 100644 index 00000000000..76dd4a840cc --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InstantiationOfAnnotationClassesCallChecker.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2021 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.resolve.calls.checkers + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall + +/** + * Additional checker that prohibits usage of LanguageFeature.InstantiationOfAnnotationClasses on backends + * that do not support this feature yet + */ +object InstantiationOfAnnotationClassesCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + if (!context.languageVersionSettings.supportsFeature(LanguageFeature.InstantiationOfAnnotationClasses)) return + val calledDescriptor = resolvedCall.resultingDescriptor as? ConstructorDescriptor ?: return + val constructedClass = calledDescriptor.constructedClass + val expression = resolvedCall.call.callElement as? KtCallExpression ?: return + if (DescriptorUtils.isAnnotationClass(constructedClass) && !CallExpressionResolver.canInstantiateAnnotationClass( + expression, + context.trace + ) + ) { + val supported = constructedClass.declaredTypeParameters.isEmpty() + if (supported) { + context.trace.report(Errors.ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(expression)) + } else { + // already reported in CallExpressionResolver.getCallExpressionTypeInfoWithoutFinalTypeCheck + } + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt new file mode 100644 index 00000000000..249d05441bd --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt @@ -0,0 +1,208 @@ +/* + * Copyright 2010-2021 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.backend.common.lower + +import org.jetbrains.kotlin.backend.common.BackendContext +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.deepCopyWithVariables +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.declarations.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.isKClass +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +val ANNOTATION_IMPLEMENTATION = object : IrDeclarationOriginImpl("ANNOTATION_IMPLEMENTATION", isSynthetic = true) {} + +class AnnotationImplementationLowering( + val transformer: (IrFile) -> AnnotationImplementationTransformer +) : FileLoweringPass { + override fun lower(irFile: IrFile) { + val tf = transformer(irFile) + irFile.transformChildrenVoid(tf) + tf.implementations.values.forEach { + val parentClass = it.parent as IrDeclarationContainer + parentClass.declarations += it + } + } +} + +open class AnnotationImplementationTransformer(val context: BackendContext, val irFile: IrFile) : IrElementTransformerVoidWithContext() { + internal val implementations: MutableMap = mutableMapOf() + + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + val constructedClass = expression.type.classOrNull?.owner ?: return expression + if (!constructedClass.isAnnotationClass) return expression + if (constructedClass.typeParameters.isNotEmpty()) return expression // Not supported yet + + val implClass = implementations.getOrPut(constructedClass) { createAnnotationImplementation(constructedClass) } + val ctor = implClass.constructors.single() + val newCall = IrConstructorCallImpl.fromSymbolOwner( + expression.startOffset, + expression.endOffset, + implClass.defaultType, + ctor.symbol, + ) + newCall.copyTypeAndValueArgumentsFrom(expression) + newCall.transformChildrenVoid() // for annotations in annotations + return newCall + } + + private fun createAnnotationImplementation(annotationClass: IrClass): IrClass { + val localDeclarationParent = currentClass?.scope?.getLocalDeclarationParent() as? IrClass + val parentFqName = annotationClass.fqNameWhenAvailable!!.asString().replace('.', '_') + val wrapperName = Name.identifier("annotationImpl\$$parentFqName$0") + val subclass = context.irFactory.buildClass { + name = wrapperName + origin = ANNOTATION_IMPLEMENTATION + // It can be seen from inline functions and multiple classes within one file + // JavaDescriptorVisibilities.PACKAGE_VISIBILITY also can be used here, like in SAM, but that's not a big difference + // since declaration is synthetic anyway + visibility = DescriptorVisibilities.INTERNAL + }.apply { + parent = localDeclarationParent ?: irFile + createImplicitParameterDeclarationWithWrappedDescriptor() + superTypes = listOf(annotationClass.defaultType) + } + + val ctor = subclass.addConstructor { + visibility = DescriptorVisibilities.PUBLIC + } + val (originalProps, implementationProps) = implementAnnotationProperties(subclass, annotationClass, ctor) + implementEqualsAndHashCode(annotationClass, subclass, originalProps, implementationProps) + implementPlatformSpecificParts(annotationClass, subclass) + return subclass + } + + fun implementAnnotationProperties(implClass: IrClass, annotationClass: IrClass, generatedConstructor: IrConstructor): Pair, List> { + val ctorBody = context.irFactory.createBlockBody( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf( + IrDelegatingConstructorCallImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, context.irBuiltIns.anyClass.constructors.single(), + typeArgumentsCount = 0, valueArgumentsCount = 0 + ) + ) + ) + + generatedConstructor.body = ctorBody + + val properties = annotationClass.getAnnotationProperties() + + return properties to properties.map { property -> + + val propType = property.getter!!.returnType + val propName = property.name + val field = context.irFactory.buildField { + name = propName + type = propType + origin = ANNOTATION_IMPLEMENTATION + isFinal = true + visibility = DescriptorVisibilities.PRIVATE + }.also { it.parent = implClass } + + val parameter = generatedConstructor.addValueParameter(propName.asString(), propType) + // VALUE_FROM_PARAMETER + val originalParameter = ((property.backingField?.initializer?.expression as? IrGetValue)?.symbol?.owner as? IrValueParameter) + if (originalParameter?.defaultValue != null) { + parameter.defaultValue = originalParameter.defaultValue!!.deepCopyWithVariables().also { it.transformChildrenVoid() } + } + + ctorBody.statements += IrSetFieldImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol, + IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, implClass.thisReceiver!!.symbol), + IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.symbol), + context.irBuiltIns.unitType, + ) + + val prop = implClass.addProperty { + name = propName + isVar = false + origin = ANNOTATION_IMPLEMENTATION + }.apply { + backingField = field + parent = implClass + } + + prop.addGetter { + name = propName // Annotation value getter should be named 'x', not 'getX' + returnType = propType.kClassToJClassIfNeeded() // On JVM, annotation store j.l.Class even if declared with KClass + origin = ANNOTATION_IMPLEMENTATION + visibility = DescriptorVisibilities.PUBLIC + modality = Modality.FINAL + }.apply { + dispatchReceiverParameter = implClass.thisReceiver!!.copyTo(this) + body = context.createIrBuilder(symbol).irBlockBody { + var value: IrExpression = irGetField(irGet(dispatchReceiverParameter!!), field) + if (propType.isKClass()) value = this.kClassExprToJClassIfNeeded(value) + +irReturn(value) + } + } + + prop + } + + } + + fun IrClass.getAnnotationProperties(): List { + // For some weird reason, annotations defined in other IrFiles, do not have IrProperties in declarations. + // (although annotations imported from Java do have) + val props = declarations.filterIsInstance() + if (props.isNotEmpty()) return props + return declarations.filterIsInstance().filter { it.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR } + .mapNotNull { it.correspondingPropertySymbol?.owner } + } + + open fun IrType.kClassToJClassIfNeeded(): IrType = this + + open fun IrBuilderWithScope.kClassExprToJClassIfNeeded(irExpression: IrExpression): IrExpression = irExpression + + open fun generatedEquals(irBuilder: IrBlockBodyBuilder, type: IrType, arg1: IrExpression, arg2: IrExpression): IrExpression = + irBuilder.irEquals(arg1, arg2) + + @Suppress("UNUSED_VARIABLE") + fun implementEqualsAndHashCode(annotationClass: IrClass, implClass: IrClass, originalProps: List, childProps: List) { + val creator = MethodsFromAnyGeneratorForLowerings(context, implClass, ANNOTATION_IMPLEMENTATION) + val generator = + creator.LoweringDataClassMemberGenerator( + nameForToString = "@" + annotationClass.fqNameWhenAvailable!!.asString(), + typeForEquals = annotationClass.defaultType + ) { type, a, b -> + generatedEquals(this, type, a, b) + } + + // Manual implementation of equals is required for two reasons: + // 1. `other` should be casted to interface instead of implementation + // 2. Properties should be retrieved using getters without accessing backing fields + // (DataClassMembersGenerator typically tries to access fields) + val eqFun = creator.createEqualsMethodDeclaration() + generator.generateEqualsUsingGetters(eqFun, annotationClass.defaultType, originalProps) + + val hcFun = creator.createHashCodeMethodDeclaration() + generator.generateHashCodeMethod(hcFun, childProps) + + val toStringFun = creator.createToStringMethodDeclaration() + generator.generateToStringMethod(toStringFun, childProps) + } + + open fun implementPlatformSpecificParts(annotationClass: IrClass, implClass: IrClass) {} +} + diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/MethodsFromAnyGeneratorForLowerings.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/MethodsFromAnyGeneratorForLowerings.kt new file mode 100644 index 00000000000..4edf806144a --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/MethodsFromAnyGeneratorForLowerings.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2021 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.backend.common.lower + +import org.jetbrains.kotlin.backend.common.BackendContext +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.declarations.addFunction +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.types.isArray +import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator +import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.ir.util.isPrimitiveArray + +class MethodsFromAnyGeneratorForLowerings(val context: BackendContext, val irClass: IrClass, val origin: IrDeclarationOrigin) { + fun createToStringMethodDeclaration(): IrSimpleFunction = irClass.addFunction("toString", context.irBuiltIns.stringType).apply { + overriddenSymbols = irClass.collectOverridenSymbols { it.isToString() } + } + + fun createHashCodeMethodDeclaration(): IrSimpleFunction = irClass.addFunction("hashCode", context.irBuiltIns.intType).apply { + overriddenSymbols = irClass.collectOverridenSymbols { it.isHashCode() } + } + + fun createEqualsMethodDeclaration(): IrSimpleFunction = irClass.addFunction("equals", context.irBuiltIns.booleanType).apply { + overriddenSymbols = irClass.collectOverridenSymbols { it.isEquals(context) } + addValueParameter("other", context.irBuiltIns.anyNType) + } + + inner class LoweringDataClassMemberGenerator( + val nameForToString: String, + val typeForEquals: IrType, + val selectEquals: IrBlockBodyBuilder.(IrType, IrExpression, IrExpression) -> IrExpression, + ) : + DataClassMembersGenerator( + IrGeneratorContextBase(context.irBuiltIns), + context.ir.symbols.externalSymbolTable, + irClass, + origin + ) { + + override fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction { + error("Descriptor API shouldn't be used in lowerings") + } + + override fun generateSyntheticFunctionParameterDeclarations(irFunction: IrFunction) { + // no-op — irFunction from lowering should already have necessary parameters + } + + override fun getProperty(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrProperty? { + error("Descriptor API shouldn't be used in lowerings") + } + + override fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType { + error("Descriptor API shouldn't be used in lowerings") + } + + override fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo { + val symbol = if (type.isArray() || type.isPrimitiveArray()) { + context.irBuiltIns.dataClassArrayMemberHashCodeSymbol + } else { + context.irBuiltIns.anyClass.functions.single { it.owner.name.asString() == "hashCode" } + } + return object : HashCodeFunctionInfo { + override val symbol: IrSimpleFunctionSymbol = symbol + + override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>) {} + } + } + + override fun IrClass.classNameForToString(): String = nameForToString + + fun generateEqualsUsingGetters(equalsFun: IrSimpleFunction, typeForEquals: IrType, properties: List) = equalsFun.apply { + body = this@MethodsFromAnyGeneratorForLowerings.context.createIrBuilder(symbol).irBlockBody { + val irType = typeForEquals + fun irOther() = irGet(valueParameters[0]) + fun irThis() = irGet(dispatchReceiverParameter!!) + fun IrProperty.get(receiver: IrExpression) = irCall(getter!!).apply { + dispatchReceiver = receiver + } + + +irIfThenReturnFalse(irNotIs(irOther(), irType)) + val otherWithCast = irTemporary(irAs(irOther(), irType), "other_with_cast") + for (property in properties) { + val arg1 = property.get(irThis()) + val arg2 = property.get(irGet(irType, otherWithCast.symbol)) + +irIfThenReturnFalse(irNot(selectEquals(property.getter?.returnType ?: property.backingField!!.type, arg1, arg2))) + } + +irReturnTrue() + } + } + } + + companion object { + fun IrFunction.isToString(): Boolean = + name.asString() == "toString" && extensionReceiverParameter == null && valueParameters.isEmpty() + + fun IrFunction.isHashCode() = + name.asString() == "hashCode" && extensionReceiverParameter == null && valueParameters.isEmpty() + + fun IrFunction.isEquals(context: BackendContext) = + name.asString() == "equals" && + extensionReceiverParameter == null && + valueParameters.singleOrNull()?.type == context.irBuiltIns.anyNType + + + fun IrClass.collectOverridenSymbols(predicate: (IrFunction) -> Boolean): List = + superTypes.mapNotNull { it.getClass()?.functions?.singleOrNull(predicate)?.symbol } + + } +} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt index f549d9bb8f1..9fc26ba2b40 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 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. */ @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor +import org.jetbrains.kotlin.backend.common.lower.MethodsFromAnyGeneratorForLowerings.Companion.isHashCode import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibility @@ -273,8 +274,9 @@ class SamEqualsHashCodeMethodsGenerator( fun generate() { generateGetFunctionDelegate() - generateEquals() - generateHashCode() + val anyGenerator = MethodsFromAnyGeneratorForLowerings(context, klass, IrDeclarationOrigin.SYNTHETIC_GENERATED_SAM_IMPLEMENTATION) + generateEquals(anyGenerator) + generateHashCode(anyGenerator) } private fun generateGetFunctionDelegate() { @@ -286,17 +288,9 @@ class SamEqualsHashCodeMethodsGenerator( } } - private fun generateEquals() { - klass.addFunction("equals", builtIns.booleanType).apply { - overriddenSymbols = klass.superTypes.mapNotNull { - it.getClass()?.functions?.singleOrNull { - it.name.asString() == "equals" && - it.extensionReceiverParameter == null && - it.valueParameters.singleOrNull()?.type == builtIns.anyNType - }?.symbol - } - - val other = addValueParameter("other", builtIns.anyNType) + private fun generateEquals(anyGenerator: MethodsFromAnyGeneratorForLowerings) { + anyGenerator.createEqualsMethodDeclaration().apply { + val other = valueParameters[0] body = context.createIrBuilder(symbol).run { irExprBody( irIfThenElse( @@ -322,16 +316,9 @@ class SamEqualsHashCodeMethodsGenerator( } } - private fun generateHashCode() { - klass.addFunction("hashCode", builtIns.intType).apply { - - fun isHashCode(function: IrSimpleFunction) = - function.name.asString() == "hashCode" && function.extensionReceiverParameter == null && function.valueParameters.isEmpty() - - overriddenSymbols = klass.superTypes.mapNotNull { - it.getClass()?.functions?.singleOrNull(::isHashCode)?.symbol - } - val hashCode = context.irBuiltIns.functionClass.owner.functions.single(::isHashCode).symbol + private fun generateHashCode(anyGenerator: MethodsFromAnyGeneratorForLowerings) { + anyGenerator.createHashCodeMethodDeclaration().apply { + val hashCode = context.irBuiltIns.functionClass.owner.functions.single{ it.isHashCode() }.symbol body = context.createIrBuilder(symbol).run { irExprBody( irCall(hashCode).also { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 871edb0f7aa..0c971f36f12 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 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. */ @@ -324,6 +324,7 @@ private val jvmFilePhases = listOf( inventNamesForLocalClassesPhase, kCallableNamePropertyPhase, annotationPhase, + annotationImplementationPhase, polymorphicSignaturePhase, varargPhase, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt index 0d8217ef2a8..ad4d12e2f1b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 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. */ @@ -802,19 +802,30 @@ class JvmSymbols( } } + private fun IrClass.addArraysEqualsFunction(arrayType: IrSimpleType) { + addFunction("equals", irBuiltIns.booleanType, isStatic = true).apply { + addValueParameter("a", arrayType) + addValueParameter("b", arrayType) + + } + } + val arraysClass: IrClassSymbol = createClass(FqName("java.util.Arrays")) { irClass -> - irClass.addArraysCopyOfFunction(booleanArrayType) - irClass.addArraysCopyOfFunction(byteArrayType) - irClass.addArraysCopyOfFunction(charArrayType) - irClass.addArraysCopyOfFunction(shortArrayType) - irClass.addArraysCopyOfFunction(intArrayType) - irClass.addArraysCopyOfFunction(longArrayType) - irClass.addArraysCopyOfFunction(floatArrayType) - irClass.addArraysCopyOfFunction(doubleArrayType) - - // public static T[] copyOf(T[] original, int newLength) - irClass.addArraysCopyOfFunction(arrayOfAnyNType) + for (type in listOf( + booleanArrayType, + byteArrayType, + charArrayType, + shortArrayType, + intArrayType, + longArrayType, + floatArrayType, + doubleArrayType, + arrayOfAnyNType + )) { + irClass.addArraysCopyOfFunction(type) + irClass.addArraysEqualsFunction(type) + } } fun getArraysCopyOfFunction(arrayType: IrSimpleType): IrSimpleFunctionSymbol { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmAnnotationImplementationTransformer.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmAnnotationImplementationTransformer.kt new file mode 100644 index 00000000000..c163521b593 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmAnnotationImplementationTransformer.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2021 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.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.lower.ANNOTATION_IMPLEMENTATION +import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationLowering +import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder +import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companion.javaClassReference +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.declarations.addFunction +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.findDeclaration +import org.jetbrains.kotlin.ir.util.isPrimitiveArray +import org.jetbrains.kotlin.ir.util.render + +internal val annotationImplementationPhase = makeIrFilePhase( + { ctxt -> AnnotationImplementationLowering { JvmAnnotationImplementationTransformer(ctxt, it) } }, + name = "AnnotationImplementation", + description = "Create synthetic annotations implementations and use them in annotations constructor calls" +) + +class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext, file: IrFile) : + AnnotationImplementationTransformer(jvmContext, file) { + override fun IrType.kClassToJClassIfNeeded(): IrType = when { + this.isKClass() -> jvmContext.ir.symbols.javaLangClass.starProjectedType + this.isKClassArray() -> jvmContext.irBuiltIns.arrayClass.typeWith( + jvmContext.ir.symbols.javaLangClass.starProjectedType + ) + else -> this + } + + private fun IrType.isKClassArray() = + this is IrSimpleType && isArray() && arguments.single().typeOrNull?.isKClass() == true + + override fun IrBuilderWithScope.kClassExprToJClassIfNeeded(irExpression: IrExpression): IrExpression { + with(this) { + return irGet( + jvmContext.ir.symbols.javaLangClass.starProjectedType, + null, + jvmContext.ir.symbols.kClassJava.owner.getter!!.symbol + ).apply { + extensionReceiver = irExpression + } + } + } + + override fun generatedEquals(irBuilder: IrBlockBodyBuilder, type: IrType, arg1: IrExpression, arg2: IrExpression): IrExpression { + return if (type.isArray() || type.isPrimitiveArray()) { + val targetType = if (type.isPrimitiveArray()) type else jvmContext.ir.symbols.arrayOfAnyNType + val requiredSymbol = jvmContext.ir.symbols.arraysClass.owner.findDeclaration { + it.name.asString() == "equals" && it.valueParameters.size == 2 && it.valueParameters.first().type == targetType + } + requireNotNull(requiredSymbol) { "Can't find Arrays.equals method for type ${targetType.render()}" } + irBuilder.irCall( + requiredSymbol.symbol + ).apply { + putValueArgument(0, arg1) + putValueArgument(1, arg2) + } + } else super.generatedEquals(irBuilder, type, arg1, arg2) + } + + override fun implementPlatformSpecificParts(annotationClass: IrClass, implClass: IrClass) { + implClass.addFunction( + name = "annotationType", + returnType = jvmContext.ir.symbols.javaLangClass.starProjectedType, + origin = ANNOTATION_IMPLEMENTATION, + isStatic = false + ).apply { + body = jvmContext.createJvmIrBuilder(symbol).run { + irBlockBody { + +irReturn(javaClassReference(annotationClass.defaultType)) + } + } + } + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt index 98bddaae0ed..b90e5e16abb 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 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. */ @@ -16,9 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.mapTypeParameters import org.jetbrains.kotlin.ir.expressions.mapValueParameters -import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull @@ -34,7 +32,7 @@ import org.jetbrains.kotlin.name.Name @OptIn(ObsoleteDescriptorBasedAPI::class) abstract class DataClassMembersGenerator( val context: IrGeneratorContext, - val symbolTable: SymbolTable, + val symbolTable: ReferenceSymbolTable, val irClass: IrClass, val origin: IrDeclarationOrigin ) { @@ -43,7 +41,7 @@ abstract class DataClassMembersGenerator( inline fun T.buildWithScope(builder: (T) -> Unit): T = also { irDeclaration -> - symbolTable.withScope(irDeclaration) { + symbolTable.withReferenceScope(irDeclaration) { builder(irDeclaration) } } @@ -206,7 +204,7 @@ abstract class DataClassMembersGenerator( fun generateToStringMethodBody(properties: List) { val irConcat = irConcat() - irConcat.addArgument(irString(irClass.name.asString() + "(")) + irConcat.addArgument(irString(irClass.classNameForToString() + "(")) var first = true for (property in properties) { if (!first) irConcat.addArgument(irString(", ")) @@ -362,4 +360,6 @@ abstract class DataClassMembersGenerator( generateToStringMethodBody(properties) } } + + open fun IrClass.classNameForToString(): String = irClass.name.asString() } diff --git a/compiler/testData/codegen/box/annotations/instances/annotationEnclosingName.kt b/compiler/testData/codegen/box/annotations/instances/annotationEnclosingName.kt new file mode 100644 index 00000000000..4cce7f5dfd4 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/annotationEnclosingName.kt @@ -0,0 +1,53 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +// FILE: a.kt + +package test + +annotation class A1 + +annotation class A2 + +fun interface I { + fun run(): A1 +} + +// FILE: test.kt + +package test + +class E { + fun insideClass(): A1 = A1() + fun insideLammbda(): A1 = run { A1() } + fun insideSAM(): I = I { A1() } +} + +class G { + // test that we can reuse instance in different classes from same file + fun insideClassAgain(): A1 = A1() +} + +fun outsideClass(): A2 = A2() + +fun test(instance: Any, parent: String, fqa: String) { + val clz = instance.javaClass + assert(clz.getName().startsWith(parent)) + assert(clz.getName().contains(fqa)) + assert(clz.getEnclosingMethod() == null) + assert(clz.getEnclosingClass().getName() == parent) + // SAM treated as anonymous because of Origin or something else, see ClassCodegen#IrClass.isAnonymousInnerClass + // assert(clz.getDeclaringClass() == null) +} + +fun box(): String { + test(E().insideClass(), "test.E", "test_A1") + test(E().insideLammbda(), "test.E", "test_A1") + test(E().insideSAM().run(), "test.E", "test_A1") + test(G().insideClassAgain(), "test.E", "test_A1") + test(outsideClass(), "test.TestKt", "test_A2") + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt b/compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt new file mode 100644 index 00000000000..61cc143de22 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt @@ -0,0 +1,30 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +import kotlin.reflect.KClass + +annotation class Bar(val i:Int, val s: String, val f: Float) + +annotation class Foo( + val int: Int, + val s: String, + val arr: Array, + val arr2: IntArray, + val kClass: KClass<*>, + val bar: Bar +) + +data class BarLike(val i:Int, val s: String, val f: Float) + +fun box(): String { + val foo1 = Foo(42, "foo", arrayOf("a", "b"), intArrayOf(1,2), Bar::class, Bar(10, "bar", Float.NaN)) + val foo2 = Foo(42, "foo", arrayOf("a", "b"), intArrayOf(1,2), Bar::class, Bar(10, "bar", Float.NaN)) + if (foo1 != foo2) return "Failed equals" + val barlike = BarLike(10, "bar", Float.NaN) + if (barlike.hashCode() != foo1.bar.hashCode()) return "Failed HC1" + if (barlike.hashCode() != foo2.bar.hashCode()) return "Failed HC2" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/annotationInstances.kt b/compiler/testData/codegen/box/annotations/instances/annotationInstances.kt new file mode 100644 index 00000000000..f6ccc5d8b19 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/annotationInstances.kt @@ -0,0 +1,70 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +// note: taken from ../parameters.kt and ../parametersWithPrimitiveValues.kt +import kotlin.reflect.KClass +import kotlin.test.assertEquals + +enum class E { E0 } +annotation class Empty + +annotation class A( + val b: Byte, + val s: Short, + val i: Int, + val f: Float, + val d: Double, + val l: Long, + val c: Char, + val bool: Boolean +) + +@Retention(AnnotationRetention.RUNTIME) +annotation class Anno( + val s: String, + val i: Int, + val f: Double, + val u: UInt, + val e: E, + val a: A, + val k: KClass<*>, + val arr: Array, + val intArr: IntArray, + val arrOfE: Array, + val arrOfA: Array, + val arrOfK: Array> +) + + +fun box(): String { + val anno = Anno( + "OK", 42, 2.718281828, 43u, E.E0, + A(1, 1, 1, 1.0.toFloat(), 1.0, 1, 'c', true), + A::class, emptyArray(), intArrayOf(1, 2), arrayOf(E.E0), arrayOf(Empty()), arrayOf(E::class, Empty::class) + ) + assertEquals(anno.s, "OK") + assertEquals(anno.i, 42) + assert(anno.f > 2.0 && anno.f < 3.0) + assertEquals(anno.u, 43u) + assertEquals(anno.e, E.E0) + assert(anno.a is A) + assert(anno.k == A::class) + assert(anno.arr.isEmpty()) + assert(anno.intArr.contentEquals(intArrayOf(1, 2))) + assert(anno.arrOfE.contentEquals(arrayOf(E.E0))) + assert(anno.arrOfA.size == 1) +// assert(anno.arrOfK.size == 2) TODO(KT-47703): Array to Array conversion + val ann = anno.a + assertEquals(ann.b, 1.toByte()) + assertEquals(ann.s, 1.toShort()) + assertEquals(ann.i, 1) + assertEquals(ann.f, 1.toFloat()) + assertEquals(ann.d, 1.0) + assertEquals(ann.l, 1.toLong()) + assertEquals(ann.c, 'c') + assert(ann.bool) + return "OK" +} diff --git a/compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefault.kt b/compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefault.kt new file mode 100644 index 00000000000..b3ee37fddb8 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefault.kt @@ -0,0 +1,38 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +package test + +import kotlin.reflect.KClass + +enum class E { A, B } + +annotation class A() + +annotation class B(val a: A = A()) + +annotation class C( + val i: Int = 42, + val b: B = B(), + val kClass: KClass<*> = B::class, + val e: E = E.B, + val aS: Array = arrayOf("a", "b"), + val aI: IntArray = intArrayOf(1, 2) +) + +annotation class Partial( + val i: Int = 42, + val s: String = "foo", + val e: E = E.A +) + +fun box(): String { + val c = C() + assert(c.toString() == "@test.C(i=42, b=@test.B(a=@test.A()), kClass=interface test.B (Kotlin reflection is not available), e=B, aS=[a, b], aI=[1, 2])") + val p = Partial(e = E.B, s = "bar") + assert(p.toString() == "@test.Partial(i=42, s=bar, e=B)") + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/annotationToString.kt b/compiler/testData/codegen/box/annotations/instances/annotationToString.kt new file mode 100644 index 00000000000..cc2194fb01a --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/annotationToString.kt @@ -0,0 +1,50 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +package test + +import kotlin.reflect.KClass + +enum class E { E0 } +annotation class Empty + +annotation class A( + val b: Byte, + val s: Short, + val i: Int, + val f: Float, + val d: Double, + val l: Long, + val c: Char, + val bool: Boolean +) + +@Retention(AnnotationRetention.RUNTIME) +annotation class Anno( + val s: String, + val i: Int, + val f: Double, + val u: UInt, + val e: E, + val a: A, + val k: KClass<*>, + val arr: Array, + val intArr: IntArray, + val arrOfE: Array, + val arrOfA: Array, +) + +fun box(): String { + val anno = Anno( + "OK", 42, 2.718281828, 43u, E.E0, + A(1, 1, 1, 1.0.toFloat(), 1.0, 1, 'c', true), + A::class, emptyArray(), intArrayOf(1, 2), arrayOf(E.E0), arrayOf(Empty()) + ) + val s = anno.toString() + val target = "@test.Anno(s=OK, i=42, f=2.718281828, u=43, e=E0, a=@test.A(b=1, s=1, i=1, f=1.0, d=1.0, l=1, c=c, bool=true), " + + "k=interface test.A (Kotlin reflection is not available), arr=[], intArr=[1, 2], arrOfE=[E0], arrOfA=[@test.Empty()])" + return if (s == target) "OK" else "FAILED, got string $s" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/annotationType.kt b/compiler/testData/codegen/box/annotations/instances/annotationType.kt new file mode 100644 index 00000000000..3e06b96bb22 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/annotationType.kt @@ -0,0 +1,18 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +annotation class Foo( + val int: Int, +) + +fun box(): String { + val foo = Foo(42) + val jClass = (foo as java.lang.annotation.Annotation).annotationType() + val kClass = foo.annotationClass + if (kClass != Foo::class) return "FAIL $kClass" + if (jClass != Foo::class.java) return "FAIL $jClass" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt b/compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt new file mode 100644 index 00000000000..dcc61aa3262 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt @@ -0,0 +1,44 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +// FILE: A.java + +public @interface A {} + +// FILE: B.java + +public @interface B { + String value(); +} + +// FILE: C.java + +public @interface C { + int[] v1(); + String v2(); +} + +// FILE: D.java + +public @interface D { + String value() default "hello"; +} + +// FILE: b.kt + +fun box(): String { + val a = A() + val b = B("OK") + assert(b.value == "OK") + val c = C(v2 = "v2", v1 = intArrayOf(1)) + assert(c.v2 == "v2") + // TODO(KT-47702): Looks like we have to force users either to pass default java parameters explicitly + // or hack LazyJavaClassDescriptor/JavaPropertyDescriptor to load annotation param default value, + // because it is not stored currently anywhere. + // val d = D() + val d = D("OK").value + return d +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt b/compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt new file mode 100644 index 00000000000..49a28df2e74 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt @@ -0,0 +1,26 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + + +// FILE: a.kt +package a + +annotation class A(val i: Int) + +fun createInOtherFile(): A = A(10) + +// FILE: b.kt + +import a.* + +fun here(): A = A(10) + +fun box(): String { + if (here() != createInOtherFile()) return "Fail equals" + if (here().hashCode() != createInOtherFile().hashCode()) return "Fail hashCode" + if (here().toString() != createInOtherFile().toString()) return "Fail toString" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/multimoduleInlining.kt b/compiler/testData/codegen/box/annotations/instances/multimoduleInlining.kt new file mode 100644 index 00000000000..4500a8b9f01 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/multimoduleInlining.kt @@ -0,0 +1,42 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR +// IGNORE_DEXING + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +// MODULE: lib +// FILE: lib.kt + +package a + +annotation class A(val i: Int) + +inline fun foo(i: Int): A = A(i) + +inline fun bar(f: () -> Int): A = A(f()) + +// MODULE: app(lib) +// FILE: app.kt + +package test + +import a.* + +class C { + fun one(): A = foo(1) + fun two(): A = bar { 2 } +} + +fun box(): String { + val one = C().one() + val two = C().two() + assert(one.i == 1) + assert(two.i == 2) + // Just like SAM wrappers, annotation implementation classes should be copied from inline functions + // into current module to avoid compatibility problems when inline fun implementation in origin module + // has changed (e.g. do not instantiate annotation anymore) + assert(one.javaClass.getEnclosingClass().getName() == "test.C") + assert(two.javaClass.getEnclosingClass().getName() == "test.C") + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt b/compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt new file mode 100644 index 00000000000..7e05594f8fa --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt @@ -0,0 +1,30 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses +MultiPlatformProjects + +// MODULE: lib +// FILE: common.kt + +expect annotation class A(val value: String) + +fun createCommon(): A = A("OK") + +// FILE: platform.kt + +actual annotation class A(actual val value: String) + +fun createPlatform(): A = A("OK") + +// MODULE: main(lib) +// FILE: main.kt + +fun createApp(): A = A("OK") + +fun box(): String { + if (createApp().value != "OK") return "FAIL app" + if (createCommon().value != "OK") return "FAIL common" + if (createPlatform().value != "OK") return "FAIL platform" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt b/compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt new file mode 100644 index 00000000000..7f5fbd66cb0 --- /dev/null +++ b/compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt @@ -0,0 +1,41 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_MULTI_MODULE: JVM_MULTI_MODULE_OLD_AGAINST_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses +// IGNORE_DEXING +// TODO: D8 fails with AssertionError and does not print reason, need further investigation + +// FILE: 1.kt + +package a + +annotation class A(val i: Int) + +inline fun foo(i: Int): A = A(i) + +inline fun bar(f: () -> Int): A = A(f()) + +// FILE: 2.kt + +import a.* + +class C { + fun one(): A { + return foo(1) + } +} + +fun two(): A { + return bar { 2 } +} + +fun box(): String { + val one = C().one() + assert(one.i == 1) + val two = two() + assert(two.i == 2) + // During cross-module inlining, anonymous classes are copied + // println(one.javaClass.getName().startsWith("a._1Kt")) + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt b/compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt new file mode 100644 index 00000000000..b0e3f21eabc --- /dev/null +++ b/compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt @@ -0,0 +1,35 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_MULTI_MODULE: JVM_MULTI_MODULE_OLD_AGAINST_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses +// IGNORE_DEXING +// TODO: D8 fails with AssertionError and does not print reason, need further investigation + +// FILE: 1.kt + +package a + +annotation class A(val i: String) + +interface I { + fun g(): A +} + +inline fun foo(i: String): I = object : I { + override fun g(): A { + return A(i) + } +} + +// FILE: 2.kt + +import a.* + +class C() { + fun one(): A = foo("OK").g() +} + +fun box(): String { + return C().one().i +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.kt b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.kt new file mode 100644 index 00000000000..19f726b4e52 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM +// !LANGUAGE: +InstantiationOfAnnotationClasses + +annotation class Foo(val int: Int) + +annotation class Bar + +fun box() { + val foo = Foo(42) +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.txt b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.txt new file mode 100644 index 00000000000..7c9ff361c04 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.txt @@ -0,0 +1,32 @@ +@kotlin.Metadata +public synthetic final class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0 { + // source: 'annotationCtorCallGenerateSynthetic.kt' + private synthetic final field int: int + public method (p0: int): void + public synthetic final method annotationType(): java.lang.Class + public final method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public final method hashCode(): int + public synthetic final method int(): int + public final @org.jetbrains.annotations.NotNull method toString(): java.lang.String + public synthetic inner class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0 +} + +@kotlin.Metadata +public final class AnnotationCtorCallGenerateSyntheticKt { + // source: 'annotationCtorCallGenerateSynthetic.kt' + public final static method box(): void + public synthetic inner class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0 +} + +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class Bar { + // source: 'annotationCtorCallGenerateSynthetic.kt' +} + +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class Foo { + // source: 'annotationCtorCallGenerateSynthetic.kt' + public abstract method int(): int +} diff --git a/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.kt b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.kt new file mode 100644 index 00000000000..d0e548c2f26 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.kt @@ -0,0 +1,10 @@ +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +annotation class Foo(val bar: Bar) + +annotation class Bar + +@Foo(Bar()) +fun box() { +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.txt b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.txt new file mode 100644 index 00000000000..ecc3311752a --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.txt @@ -0,0 +1,18 @@ +@kotlin.Metadata +public final class AnnotationCtorCallNoSyntheticKt { + // source: 'annotationCtorCallNoSynthetic.kt' + public final static @Foo method box(): void +} + +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class Bar { + // source: 'annotationCtorCallNoSynthetic.kt' +} + +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class Foo { + // source: 'annotationCtorCallNoSynthetic.kt' + public abstract method bar(): Bar +} diff --git a/compiler/testData/diagnostics/nativeTests/annotationConstructorCallNative.kt b/compiler/testData/diagnostics/nativeTests/annotationConstructorCallNative.kt new file mode 100644 index 00000000000..19d1916b228 --- /dev/null +++ b/compiler/testData/diagnostics/nativeTests/annotationConstructorCallNative.kt @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// WITH_RUNTIME +// SKIP_TXT +// !LANGUAGE: +InstantiationOfAnnotationClasses + +// FILE: test.kt + +import kotlin.reflect.KClass + +annotation class A +annotation class B(val int: Int) +annotation class C(val int: Int = 42) + +annotation class G(val int: KClass) + +fun box() { + val a = A() + val b = B(4) + val c = C() + val foo = G(Int::class) +} diff --git a/compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.fir.kt b/compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.fir.kt new file mode 100644 index 00000000000..619c82e32d3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.fir.kt @@ -0,0 +1,18 @@ +// WITH_RUNTIME +// SKIP_TXT +// !LANGUAGE: +InstantiationOfAnnotationClasses + +import kotlin.reflect.KClass + +annotation class A +annotation class B(val int: Int) +annotation class C(val int: Int = 42) + +annotation class G(val int: KClass) + +fun box() { + val a = A() + val b = B(4) + val c = C() + val foo = G(Int::class) +} diff --git a/compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt b/compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt new file mode 100644 index 00000000000..d7ce8303e49 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt @@ -0,0 +1,18 @@ +// WITH_RUNTIME +// SKIP_TXT +// !LANGUAGE: +InstantiationOfAnnotationClasses + +import kotlin.reflect.KClass + +annotation class A +annotation class B(val int: Int) +annotation class C(val int: Int = 42) + +annotation class G(val int: KClass) + +fun box() { + val a = A() + val b = B(4) + val c = C() + val foo = G(Int::class) +} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/annotationConstructorCallJs.kt b/compiler/testData/diagnostics/testsWithJsStdLib/annotationConstructorCallJs.kt new file mode 100644 index 00000000000..6269f2b4431 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/annotationConstructorCallJs.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// WITH_RUNTIME +// SKIP_TXT +// !LANGUAGE: +InstantiationOfAnnotationClasses + +import kotlin.reflect.KClass + +annotation class A +annotation class B(val int: Int) +annotation class C(val int: Int = 42) + +annotation class G(val int: KClass) + +fun box() { + val a = A() + val b = B(4) + val c = C() + val foo = G(Int::class) +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index b2eb6a2037c..42545d7dc44 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -1103,6 +1103,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt"); } + @Test + @TestMetadata("ConstructorCallAllowed.kt") + public void testConstructorCallAllowed() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt"); + } + @Test @TestMetadata("DanglingInScript.kts") public void testDanglingInScript() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsNativeTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsNativeTestGenerated.java index af343085cf4..053b55897fd 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsNativeTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsNativeTestGenerated.java @@ -24,6 +24,12 @@ public class DiagnosticsNativeTestGenerated extends AbstractDiagnosticsNativeTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/nativeTests"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @Test + @TestMetadata("annotationConstructorCallNative.kt") + public void testAnnotationConstructorCallNative() throws Exception { + runTest("compiler/testData/diagnostics/nativeTests/annotationConstructorCallNative.kt"); + } + @Test @TestMetadata("sharedImmutable.kt") public void testSharedImmutable() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJsStdLibGenerated.java index 823ea6751de..24f3f6d5ac7 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJsStdLibGenerated.java @@ -24,6 +24,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @Test + @TestMetadata("annotationConstructorCallJs.kt") + public void testAnnotationConstructorCallJs() throws Exception { + runTest("compiler/testData/diagnostics/testsWithJsStdLib/annotationConstructorCallJs.kt"); + } + @Test @TestMetadata("funConstructorCallJS.kt") public void testFunConstructorCallJS() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 1479994f547..97185b63323 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -380,6 +380,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @Nested + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + public class Instances { + @Test + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } + @Nested @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java index c885eb97785..d80275040a6 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -25,6 +25,16 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java index 018dc25d1b6..c18d059f8cf 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java @@ -316,6 +316,18 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("annotationCtorCallGenerateSynthetic.kt") + public void testAnnotationCtorCallGenerateSynthetic() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.kt"); + } + + @Test + @TestMetadata("annotationCtorCallNoSynthetic.kt") + public void testAnnotationCtorCallNoSynthetic() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.kt"); + } + @Test @TestMetadata("annotationsOnDelegatedMembers.kt") public void testAnnotationsOnDelegatedMembers() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 1cb8e768483..6ee0eb227b0 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -25,6 +25,16 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 040d1df8697..12bf56ebf39 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -380,6 +380,76 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @Nested + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + public class Instances { + @Test + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("annotationEnclosingName.kt") + public void testAnnotationEnclosingName() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationEnclosingName.kt"); + } + + @Test + @TestMetadata("annotationEqHc.kt") + public void testAnnotationEqHc() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt"); + } + + @Test + @TestMetadata("annotationInstances.kt") + public void testAnnotationInstances() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt"); + } + + @Test + @TestMetadata("annotationInstancesEmptyDefault.kt") + public void testAnnotationInstancesEmptyDefault() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefault.kt"); + } + + @Test + @TestMetadata("annotationToString.kt") + public void testAnnotationToString() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt"); + } + + @Test + @TestMetadata("annotationType.kt") + public void testAnnotationType() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt"); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt"); + } + + @Test + @TestMetadata("multifileEqHc.kt") + public void testMultifileEqHc() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt"); + } + + @Test + @TestMetadata("multimoduleInlining.kt") + public void testMultimoduleInlining() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/multimoduleInlining.kt"); + } + + @Test + @TestMetadata("multiplatformInstantiation.kt") + public void testMultiplatformInstantiation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java index e8b0dd5a561..0e3050640bf 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java @@ -25,6 +25,28 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("annotationInstanceInlining.kt") + public void testAnnotationInstanceInlining() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt"); + } + + @Test + @TestMetadata("instanceInAnonymousClass.kt") + public void testInstanceInAnonymousClass() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java index 9e3ba33ab51..345ec1b4319 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java @@ -316,6 +316,18 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("annotationCtorCallGenerateSynthetic.kt") + public void testAnnotationCtorCallGenerateSynthetic() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.kt"); + } + + @Test + @TestMetadata("annotationCtorCallNoSynthetic.kt") + public void testAnnotationCtorCallNoSynthetic() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.kt"); + } + @Test @TestMetadata("annotationsOnDelegatedMembers.kt") public void testAnnotationsOnDelegatedMembers() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 3946c829658..8f1e0437dd8 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -25,6 +25,28 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("annotationInstanceInlining.kt") + public void testAnnotationInstanceInlining() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt"); + } + + @Test + @TestMetadata("instanceInAnonymousClass.kt") + public void testInstanceInAnonymousClass() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java index 08f9efec461..8b6262cb83a 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -25,6 +25,28 @@ public class IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated extends Ab KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("annotationInstanceInlining.kt") + public void testAnnotationInstanceInlining() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt"); + } + + @Test + @TestMetadata("instanceInAnonymousClass.kt") + public void testInstanceInAnonymousClass() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java index 6baf01777fb..ece8648a4ed 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java @@ -25,6 +25,28 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_IR_AGAINST_OLD, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_IR_AGAINST_OLD, true); + } + + @Test + @TestMetadata("annotationInstanceInlining.kt") + public void testAnnotationInstanceInlining() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt"); + } + + @Test + @TestMetadata("instanceInAnonymousClass.kt") + public void testInstanceInAnonymousClass() throws Exception { + runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java index 448045711b8..30cf54b721b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java @@ -25,6 +25,16 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_OLD_AGAINST_IR, true); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + public class Annotations { + @Test + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_OLD_AGAINST_IR, true); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 3c56cf51476..d3feaf17c09 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -335,6 +335,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Instances extends AbstractLightAnalysisModeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 6055452ecac..f7dc7a3ba5a 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 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. */ @@ -216,6 +216,7 @@ enum class LanguageFeature( TypeInferenceOnCallsWithSelfTypes(KOTLIN_1_6), OptInRelease(KOTLIN_1_6), WarnAboutNonExhaustiveWhenOnAlgebraicTypes(KOTLIN_1_6, kind = BUG_FIX), + InstantiationOfAnnotationClasses(KOTLIN_1_6), // 1.7 diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index acb31dd6845..22d4bd92d08 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -1103,6 +1103,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt"); } + @Test + @TestMetadata("ConstructorCallAllowed.kt") + public void testConstructorCallAllowed() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt"); + } + @Test @TestMetadata("DanglingMixed.kt") public void testDanglingMixed() throws Exception { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index 5cbd2b9d11e..39e15b50aab 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.js.analyze.JsNativeDiagnosticSuppressor import org.jetbrains.kotlin.js.naming.NameSuggestion import org.jetbrains.kotlin.js.resolve.diagnostics.* import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase +import org.jetbrains.kotlin.resolve.calls.checkers.InstantiationOfAnnotationClassesCallChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport import org.jetbrains.kotlin.types.DynamicTypesAllowed @@ -29,9 +30,10 @@ object JsPlatformConfigurator : PlatformConfiguratorBase( JsExportDeclarationChecker ), additionalCallCheckers = listOf( - JsModuleCallChecker, - JsDynamicCallChecker, - JsDefinedExternallyCallChecker, + JsModuleCallChecker, + JsDynamicCallChecker, + JsDefinedExternallyCallChecker, + InstantiationOfAnnotationClassesCallChecker ), identifierChecker = JsIdentifierChecker ) { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 8430191ba3e..2a799ca76b0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -80,6 +80,19 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes } } + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Instances extends AbstractIrJsCodegenBoxES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java index bd21243bdc3..ae6c9a4d8a9 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java @@ -30,6 +30,19 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Annotations extends AbstractIrJsCodegenInlineES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 20fc0409a05..c2fa5e2f6bd 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -80,6 +80,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Instances extends AbstractIrJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java index df8871f0c57..5718cf9b421 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java @@ -30,6 +30,19 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Annotations extends AbstractIrJsCodegenInlineTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 140b6deb7ae..d52fbaf2ed0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -80,6 +80,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Instances extends AbstractJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java index 346b356a3cf..2124f822b3b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java @@ -30,6 +30,19 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } + @TestMetadata("compiler/testData/codegen/boxInline/annotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Annotations extends AbstractJsCodegenInlineTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInAnnotations() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 83733bc47c5..f907b608cfd 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -75,6 +75,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest } } + @TestMetadata("compiler/testData/codegen/box/annotations/instances") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Instances extends AbstractIrCodegenBoxWasmTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath); + } + + public void testAllFilesPresentInInstances() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt index 04eb768078f..9bc8aab4834 100644 --- a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt +++ b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase +import org.jetbrains.kotlin.resolve.calls.checkers.InstantiationOfAnnotationClassesCallChecker import org.jetbrains.kotlin.resolve.calls.checkers.TypeOfChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.inline.ReasonableInlineRule @@ -25,6 +26,7 @@ import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeTopLevelSingletonChe object NativePlatformConfigurator : PlatformConfiguratorBase( additionalCallCheckers = listOf( SuperCallWithDefaultArgumentsChecker(), + InstantiationOfAnnotationClassesCallChecker ), additionalDeclarationCheckers = listOf( NativeThrowsChecker, NativeSharedImmutableChecker,