diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java index 86ac9fd755b..9090acb75f2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java @@ -100,6 +100,20 @@ public class ClassFileFactory implements OutputFileCollection { return answer; } + @NotNull + public ClassBuilder newVisitor( + @NotNull JvmDeclarationOrigin origin, + @NotNull Type asmType, + @NotNull List sourceFiles + ) { + ClassBuilder answer = builderFactory.newClassBuilder(origin); + generators.put( + asmType.getInternalName() + ".class", + new ClassBuilderAndSourceFileList(answer, sourceFiles) + ); + return answer; + } + public void done() { if (!isDone) { isDone = true; diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index 97d1f1426bc..5d5f4e5c934 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -38,10 +38,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection -import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor -import org.jetbrains.kotlin.ir.util.defaultType -import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.ir.util.patchDeclarationParents +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -114,6 +111,15 @@ val IrSimpleFunction.isOverridableOrOverrides: Boolean get() = isOverridable || val IrClass.isFinalClass: Boolean get() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS +// For an annotation, get the annotation class. +fun IrCall.getAnnotationClass(): IrClass { + val callable = symbol.owner + assert(callable is IrConstructor) { "Constructor call expected, got ${ir2string(this)}" } + val annotationClass = callable.parentAsClass + assert(annotationClass.isAnnotationClass) { "Annotation class expected, got ${ir2string(annotationClass)}" } + return annotationClass +} + val IrTypeParametersContainer.classIfConstructor get() = if (this is IrConstructor) parentAsClass else this fun IrValueParameter.copyTo( diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index 1e71f82c1a1..f76e36a5491 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -549,6 +549,8 @@ class LocalDeclarationsLowering( newDeclaration.valueParameters += createTransformedValueParameters(capturedValues, oldDeclaration, newDeclaration) newDeclaration.recordTransformedValueParameters(localFunctionContext) + newDeclaration.annotations.addAll(oldDeclaration.annotations) + transformedDeclarations[oldDeclaration] = newDeclaration } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt index c2972eaaa8a..97e2cbafdc3 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt @@ -84,9 +84,7 @@ class PropertiesLowering( body = IrBlockBodyImpl(-1, -1) - // TODO: uncomment this and derive annotations from owner in wrapped descriptors - // annotations.addAll(declaration.annotations) - + annotations.addAll(declaration.annotations) metadata = declaration.metadata } } 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 5e15569f34f..81c5b90faa8 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 @@ -105,6 +105,7 @@ val jvmPhases = namedIrFilePhase( foldConstantLoweringPhase then flattenStringConcatenationPhase then jvmBuiltinOptimizationLoweringPhase then + additionalClassAnnotationPhase then makePatchParentsPhase(3) ) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt new file mode 100644 index 00000000000..1b0cd27ef86 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt @@ -0,0 +1,317 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.jvm.codegen + +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable +import org.jetbrains.kotlin.backend.common.ir.ir2string +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.synthetic.isVisibleOutside +import org.jetbrains.org.objectweb.asm.* +import java.lang.annotation.RetentionPolicy + +class AnnotationCodegen( + private val innerClassConsumer: InnerClassConsumer, + state: GenerationState, + private val visitAnnotation: (descriptor: String, visible: Boolean) -> AnnotationVisitor +) { + + private val typeMapper = state.typeMapper + + /** + * @param returnType can be null if not applicable (e.g. [annotated] is a class) + */ + fun genAnnotations(annotated: IrAnnotationContainer?, returnType: Type?) { + if (annotated == null) return + + val annotationDescriptorsAlreadyPresent = mutableSetOf() + + val annotations = annotated.annotations + + for (annotation in annotations) { + val applicableTargets = annotation.applicableTargetSet() + if (annotated is IrSimpleFunction && + annotated.origin === IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA && + KotlinTarget.FUNCTION !in applicableTargets && + KotlinTarget.PROPERTY_GETTER !in applicableTargets && + KotlinTarget.PROPERTY_SETTER !in applicableTargets + ) { + assert(KotlinTarget.EXPRESSION in applicableTargets) { + "Inconsistent target list for lambda annotation: $applicableTargets on $annotated" + } + continue + } + if (annotated is IrClass && + KotlinTarget.CLASS !in applicableTargets && + KotlinTarget.ANNOTATION_CLASS !in applicableTargets + ) { + if (annotated.visibility == Visibilities.LOCAL) { + assert(KotlinTarget.EXPRESSION in applicableTargets) { + "Inconsistent target list for object literal annotation: $applicableTargets on $annotated" + } + continue + } + } + + genAnnotation(annotation)?.let { descriptor -> + annotationDescriptorsAlreadyPresent.add(descriptor) + } + } + + generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent) + } + + private fun generateAdditionalAnnotations( + annotated: IrAnnotationContainer, + returnType: Type?, + annotationDescriptorsAlreadyPresent: MutableSet + ) { + if (annotated is IrDeclaration) { + if (returnType != null && !AsmUtil.isPrimitive(returnType)) { + generateNullabilityAnnotationForCallable(annotated, annotationDescriptorsAlreadyPresent) + } + } + } + + private fun generateNullabilityAnnotationForCallable( + declaration: IrDeclaration, // There is no superclass that encompasses IrFunction, IrField and nothing else. + annotationDescriptorsAlreadyPresent: MutableSet + ) { + // No need to annotate privates, synthetic accessors and their parameters + if (isInvisibleFromTheOutside(declaration)) return + if (declaration is IrValueParameter && isInvisibleFromTheOutside(declaration.parent as? IrDeclaration)) return + + // No need to annotate annotation methods since they're always non-null + if (declaration is IrSimpleFunction && declaration.correspondingProperty != null && + declaration.parentAsClass.isAnnotationClass + ) { + return + } + + val type = when (declaration) { + is IrFunction -> declaration.returnType + is IrField -> declaration.type + is IrValueDeclaration -> declaration.type + else -> return + } + + if (isBareTypeParameterWithNullableUpperBound(type)) { + // This is to account for the case of, say + // class Function { fun invoke(): R } + // it would be a shame to put @Nullable on the return type of the function, and force all callers to check for null, + // so we put no annotations + return + } + + val annotationClass = if (type.isNullable()) Nullable::class.java else NotNull::class.java + + generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass) + } + + private fun generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent: MutableSet, annotationClass: Class<*>) { + val descriptor = Type.getType(annotationClass).descriptor + if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) { + visitAnnotation(descriptor, false).visitEnd() + } + } + + fun generateAnnotationDefaultValue(value: IrExpression) { + val visitor = visitAnnotation("", false) // Parameters are unimportant + genCompileTimeValue(null, value, visitor) + visitor.visitEnd() + } + + private fun genAnnotation(annotation: IrCall): String? { + val annotationClass = annotation.annotationClass + val rp = getRetentionPolicy(annotationClass) + if (rp == RetentionPolicy.SOURCE && !typeMapper.classBuilderMode.generateSourceRetentionAnnotations) { + return null + } + + innerClassConsumer.addInnerClassInfoFromAnnotation(annotationClass) + + val asmTypeDescriptor = typeMapper.mapType(annotation.type.toKotlinType()).descriptor + val annotationVisitor = visitAnnotation(asmTypeDescriptor, rp == RetentionPolicy.RUNTIME) + + genAnnotationArguments(annotation, annotationVisitor) + annotationVisitor.visitEnd() + + return asmTypeDescriptor + } + + private fun genAnnotationArguments(annotation: IrCall, annotationVisitor: AnnotationVisitor) { + val annotationClass = annotation.annotationClass + for (param in annotation.symbol.owner.valueParameters) { + val value = annotation.getValueArgument(param.index) + if (value == null) { + if (param.defaultValue != null) continue // Default value will be supplied by JVM at runtime. + else error("No value for annotation parameter $param") + } + genCompileTimeValue(getAnnotationArgumentJvmName(annotationClass, param.name), value, annotationVisitor) + } + } + + private fun getAnnotationArgumentJvmName(annotationClass: IrClass?, parameterName: Name): String { + if (annotationClass == null) return parameterName.asString() + + val field = + annotationClass.declarations.filterIsInstance().singleOrNull { it.name == parameterName } + ?: return parameterName.asString() + + return typeMapper.mapAnnotationParameterName(field.descriptor) + } + + private fun genCompileTimeValue( + name: String?, + value: IrExpression, + annotationVisitor: AnnotationVisitor + ) { + fun visitUnsupportedValue(value: IrExpression) { + val mode = typeMapper.classBuilderMode + if (mode.generateBodies) { + throw IllegalStateException("Don't know how to compile annotation value ${ir2string(value)}") + } + } + + when (value) { + is IrConst<*> -> annotationVisitor.visit(name, value.value) + is IrCall -> { + val callee = value.symbol.owner + when { + callee is IrConstructor && callee.parentAsClass.isAnnotationClass -> { + val internalAnnName = typeMapper.mapType(callee.returnType.toKotlinType()).descriptor + val visitor = annotationVisitor.visitAnnotation(name, internalAnnName) + genAnnotationArguments(value, visitor) + visitor.visitEnd() + } + else -> error("Not supported as annotation! ${ir2string(value)}") + } + } + is IrGetEnumValue -> { + val enumClassInternalName = typeMapper.mapClass(value.symbol.owner.parentAsClass.descriptor).descriptor + val enumEntryName = value.symbol.owner.name + annotationVisitor.visitEnum(name, enumClassInternalName, enumEntryName.asString()) + } + is IrVararg -> { // array constructor + val visitor = annotationVisitor.visitArray(name) + for (element in value.elements) { + genCompileTimeValue(null, element as IrExpression, visitor) + } + visitor.visitEnd() + } + is IrClassReference -> { + annotationVisitor.visit(name, typeMapper.mapType(value.classType.toKotlinType())) + } + is IrErrorExpression -> visitUnsupportedValue(value) + else -> error("Unsupported compiletime value ${ir2string(value)}") + } + } + + companion object { + private fun isInvisibleFromTheOutside(declaration: IrDeclaration?): Boolean { + if (declaration is IrSimpleFunction && declaration.origin === JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) { + return true + } + if (declaration is IrDeclarationWithVisibility) { + return !declaration.visibility.isVisibleOutside() + } + return false + } + + private val annotationRetentionMap = mapOf( + KotlinRetention.SOURCE to RetentionPolicy.SOURCE, + KotlinRetention.BINARY to RetentionPolicy.CLASS, + KotlinRetention.RUNTIME to RetentionPolicy.RUNTIME + ) + + private fun getRetentionPolicy(irClass: IrClass): RetentionPolicy { + val retention = irClass.getAnnotationRetention() + if (retention != null) { + return annotationRetentionMap[retention]!! + } + irClass.getAnnotation(FqName(java.lang.annotation.Retention::class.java.name))?.let { retentionAnnotation -> + val value = retentionAnnotation.getValueArgument(0) + if (value is IrEnumEntry) { + val enumClassFqName = value.parentAsClass.fqNameWhenAvailable + if (RetentionPolicy::class.java.name == enumClassFqName?.asString()) { + return RetentionPolicy.valueOf(value.name.asString()) + } + } + } + + return RetentionPolicy.RUNTIME + } + + /* Temporary? */ + fun IrCall.applicableTargetSet() = + annotationClass.applicableTargetSet() ?: KotlinTarget.DEFAULT_TARGET_SET + + val IrCall.annotationClass get() = symbol.owner.parentAsClass + } +} + +interface InnerClassConsumer { + fun addInnerClassInfoFromAnnotation(irClass: IrClass) +} + +private fun isBareTypeParameterWithNullableUpperBound(type: IrType): Boolean { + return type.classifierOrNull?.owner is IrTypeParameter && !type.isMarkedNullable() && type.isNullable() +} + +private val RETENTION_PARAMETER_NAME = Name.identifier("value") + +private fun IrClass.getAnnotationRetention(): KotlinRetention? { + val retentionArgument = + getAnnotation(KotlinBuiltIns.FQ_NAMES.retention)?.getValueArgument(RETENTION_PARAMETER_NAME) + as? IrGetEnumValue?: return null + val retentionArgumentValue = retentionArgument.symbol.owner + return KotlinRetention.valueOf(retentionArgumentValue.name.asString()) +} + +// To be generalized to IrMemberAccessExpression as soon as properties get symbols. +private fun IrCall.getValueArgument(name: Name): IrExpression? { + val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null + return getValueArgument(index) +} + +// Copied and modified from AnnotationChecker.kt + +private val TARGET_ALLOWED_TARGETS = Name.identifier("allowedTargets") + +private fun IrClass.applicableTargetSet(): Set? { + val targetEntry = getAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null + return loadAnnotationTargets(targetEntry) +} + +private fun loadAnnotationTargets(targetEntry: IrCall): Set? { + val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS) + as? IrVararg ?: return null + return valueArgument.elements.filterIsInstance().mapNotNull { + KotlinTarget.valueOrNull(it.symbol.owner.name.asString()) + }.toSet() +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 828f00d937e..ec502dabe69 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -103,7 +103,7 @@ open class ClassCodegen protected constructor( signature.superclassName, signature.interfaces.toTypedArray() ) - AnnotationCodegen.forClass(visitor.visitor, this, context.state).genAnnotations(descriptor, null) + AnnotationCodegen(this, context.state, visitor.visitor::visitAnnotation).genAnnotations(irClass, null) /* TODO: Temporary workaround: ClassBuilder needs a pathless name. */ val shortName = File(fileEntry.name).name visitor.visitSource(shortName, null) @@ -222,9 +222,7 @@ open class ClassCodegen protected constructor( fieldSignature, null/*TODO support default values*/ ) - if (field.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) { - AnnotationCodegen.forField(fv, this, state).genAnnotations(field.descriptor, null) - } + AnnotationCodegen(this, state, fv::visitAnnotation).genAnnotations(field, fieldType) val descriptor = field.metadata?.descriptor if (descriptor != null) { @@ -295,8 +293,8 @@ open class ClassCodegen protected constructor( // It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations // See FileBasedKotlinClass.convertAnnotationVisitor - override fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor) { - var current: DeclarationDescriptor? = classDescriptor + override fun addInnerClassInfoFromAnnotation(irClass: IrClass) { + var current: DeclarationDescriptor? = irClass.descriptor while (current != null && !isTopLevelDeclaration(current)) { if (current is ClassDescriptor) { innerClasses.add(current) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index baa75810270..a3ad7bab9eb 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -575,7 +575,7 @@ class ExpressionCodegen( val hasSpread = arguments.firstIsInstanceOrNull() != null if (hasSpread) { - val arrayOfReferences = KotlinBuiltIns.isArray(outType.toKotlinType()!!) + val arrayOfReferences = KotlinBuiltIns.isArray(outType.toKotlinType()) if (size == 1) { // Arrays.copyOf(receiverValue, newLength) val argument = (arguments[0] as IrSpreadElement).expression @@ -633,7 +633,7 @@ class ExpressionCodegen( } else { mv.iconst(size) newArrayInstruction(expression.type.toKotlinType()) - val elementKotlinType = classCodegen.context.builtIns.getArrayElementType(outType.toKotlinType()!!) + val elementKotlinType = classCodegen.context.builtIns.getArrayElementType(outType.toKotlinType()) for ((i, element) in expression.elements.withIndex()) { mv.dup() StackValue.constant(i).put(mv) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index 2f43b3c9309..f2c0f6fcd3a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -10,18 +10,19 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.isAnnotationClass -import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature -import org.jetbrains.kotlin.resolve.source.getPsi +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter @@ -46,8 +47,8 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class val methodVisitor = createMethod(flags, signature) if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) { - AnnotationCodegen.forMethod(methodVisitor, classCodegen, state).genAnnotations(descriptor, signature.asmMethod.returnType) - FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, classCodegen, state) + AnnotationCodegen(classCodegen, state, methodVisitor::visitAnnotation).genAnnotations(irFunction, signature.asmMethod.returnType) + FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, DummyOldInnerClassConsumer(), state) } if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0 || irFunction.isExternal) { @@ -105,21 +106,25 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class } private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) { - if (classCodegen.irClass.isAnnotationClass) { - val source = JvmCodegenUtil.getDirectMember(descriptor).source - (source.getPsi() as? KtParameter)?.defaultValue?.apply { - val defaultValue = this - val constant = org.jetbrains.kotlin.codegen.ExpressionCodegen.getCompileTimeConstant( - defaultValue, state.bindingContext, true, state.shouldInlineConstVals - ) - assert(!state.classBuilderMode.generateBodies || constant != null) { "Default value for annotation parameter should be compile time value: " + defaultValue.text } - if (constant != null) { - val annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(methodVisitor, classCodegen, state) - annotationCodegen.generateAnnotationDefaultValue(constant, descriptor.returnType!!) - } - } + getAnnotationDefaultValueExpression()?.let { defaultValueExpression -> + val annotationCodegen = AnnotationCodegen(classCodegen, state) { _, _ -> methodVisitor.visitAnnotationDefault() } + annotationCodegen.generateAnnotationDefaultValue(defaultValueExpression) } } + + private fun getAnnotationDefaultValueExpression(): IrExpression? { + if (!classCodegen.irClass.isAnnotationClass) return null + // TODO: any simpler way to get to the value expression? + // Are there other valid IR structures that represent the default value? + return irFunction.safeAs() + ?.correspondingProperty + ?.backingField + ?.initializer.safeAs() + ?.expression?.safeAs() + ?.symbol?.owner?.safeAs() + ?.defaultValue?.safeAs() + ?.expression + } } private fun createFrameMapWithReceivers( @@ -153,3 +158,13 @@ private fun createFrameMapWithReceivers( return frameMap } + +/**/// TODO: temporary, to allow calling the old FunctionCodegen.generateParameterAnnotations +private class DummyOldInnerClassConsumer() + : org.jetbrains.kotlin.codegen.InnerClassConsumer { + + override fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor) { + + } + +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AdditionalClassAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AdditionalClassAnnotationLowering.kt new file mode 100644 index 00000000000..0b220691b44 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AdditionalClassAnnotationLowering.kt @@ -0,0 +1,247 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.descriptors.WrappedEnumEntryDescriptor +import org.jetbrains.kotlin.backend.common.ir.addChild +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget +import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor +import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrEnumEntryImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrEnumEntrySymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal val additionalClassAnnotationPhase = makeIrFilePhase( + ::AdditionalClassAnnotationLowering, + name = "AdditionalClassAnnotation", + description = "Add Documented, Retention and Target annotations to annotation classes" +) + +private class AdditionalClassAnnotationLowering(private val context: JvmBackendContext) : ClassLoweringPass { + + val typeMapper = context.state.typeMapper + + // TODO: import IR structures from the library? + + private val annotationPackage: IrPackageFragment = IrExternalPackageFragmentImpl( + IrExternalPackageFragmentSymbolImpl( + EmptyPackageFragmentDescriptor( + context.ir.irModule.descriptor, + FqName("java.lang.annotation") + ) + ) + ) + + private fun buildAnnotationClass( + className: String, + classKind: ClassKind = ClassKind.ANNOTATION_CLASS + ): IrClass = buildClass { + name = Name.identifier(className) + kind = classKind + }.apply { + val irClass = this + parent = annotationPackage + annotationPackage.addChild(this) + thisReceiver = buildValueParameter { + name = Name.identifier("\$this") + type = IrSimpleTypeImpl(irClass.symbol, false, emptyList(), emptyList()) + } + } + + private fun buildAnnotationConstructor(annotationClass: IrClass): IrConstructor = buildConstructor { + isPrimary = true + }.apply { + parent = annotationClass + annotationClass.addChild(this) + returnType = annotationClass.defaultType + } + + private fun buildEnumEntry(enumClass: IrClass, entryName: String): IrEnumEntry = IrEnumEntryImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB, + IrEnumEntrySymbolImpl(WrappedEnumEntryDescriptor()), + Name.identifier(entryName) + ).apply { + (descriptor as WrappedEnumEntryDescriptor).bind(this) + parent = enumClass + enumClass.addChild(this) + } + + private val documentedConstructor = buildAnnotationConstructor(buildAnnotationClass("Documented")) + + private val retentionPolicyEnum = buildAnnotationClass("RetentionPolicy", classKind = ClassKind.ENUM_CLASS) + private val rpSource = buildEnumEntry(retentionPolicyEnum, "SOURCE") + private val rpClass = buildEnumEntry(retentionPolicyEnum, "CLASS") + private val rpRuntime = buildEnumEntry(retentionPolicyEnum, "RUNTIME") + + private val retentionConstructor = buildAnnotationConstructor(buildAnnotationClass("Retention")).apply { + addValueParameter(Name.identifier("value"), retentionPolicyEnum.defaultType, IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) + } + + private val elementTypeEnum = buildAnnotationClass("ElementType", classKind = ClassKind.ENUM_CLASS) + private val etAnnotationType = buildEnumEntry(elementTypeEnum, "ANNOTATION_TYPE") + private val etConstructor = buildEnumEntry(elementTypeEnum, "CONSTRUCTOR") + private val etField = buildEnumEntry(elementTypeEnum, "FIELD") + private val etLocalVariable = buildEnumEntry(elementTypeEnum, "LOCAL_VARIABLE") + private val etMethod = buildEnumEntry(elementTypeEnum, "METHOD") + private val etPackage = buildEnumEntry(elementTypeEnum, "PACKAGE") + private val etParameter = buildEnumEntry(elementTypeEnum, "PARAMETER") + private val etType = buildEnumEntry(elementTypeEnum, "TYPE") + private val etTypeParameter = buildEnumEntry(elementTypeEnum, "TYPE_PARAMETER") + private val etTypeUse = buildEnumEntry(elementTypeEnum, "TYPE_USE") + + private val targetConstructor = buildAnnotationConstructor(buildAnnotationClass("Target")).apply { + addValueParameter(Name.identifier("value"), elementTypeEnum.defaultType, IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) + } + + + override fun lower(irClass: IrClass) { + if (!irClass.isAnnotationClass) return + + generateDocumentedAnnotation(irClass) + generateRetentionAnnotation(irClass) + generateTargetAnnotation(irClass) + } + + private fun generateDocumentedAnnotation(irClass: IrClass) { + if (irClass.hasAnnotation(KotlinBuiltIns.FQ_NAMES.mustBeDocumented) && + !irClass.hasAnnotation(FqName("java.lang.annotation.Documented")) + ) { + return + } + + irClass.annotations.add( + IrCallImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, documentedConstructor.returnType, documentedConstructor.symbol + ) + ) + } + + private val annotationRetentionMap = mapOf( + KotlinRetention.SOURCE to rpSource, + KotlinRetention.BINARY to rpClass, + KotlinRetention.RUNTIME to rpRuntime + ) + + private fun generateRetentionAnnotation(irClass: IrClass) { + if (irClass.hasAnnotation(FqName("java.lang.annotation.Retention"))) return + val kotlinRetentionPolicy = irClass.getAnnotation(FqName("kotlin.annotation.Retention")) + val javaRetentionPolicy = annotationRetentionMap[kotlinRetentionPolicy] ?: rpRuntime + + irClass.annotations.add( + IrCallImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionConstructor.returnType, retentionConstructor.symbol + ).apply { + putValueArgument( + 0, + IrGetEnumValueImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionPolicyEnum.defaultType, javaRetentionPolicy.symbol + ) + ) + } + ) + } + + private val annotationTargetMaps: Map> = + mapOf( + JvmTarget.JVM_1_6 to mutableMapOf( + KotlinTarget.CLASS to etType, + KotlinTarget.ANNOTATION_CLASS to etAnnotationType, + KotlinTarget.CONSTRUCTOR to etConstructor, + KotlinTarget.LOCAL_VARIABLE to etLocalVariable, + KotlinTarget.FUNCTION to etMethod, + KotlinTarget.PROPERTY_GETTER to etMethod, + KotlinTarget.PROPERTY_SETTER to etMethod, + KotlinTarget.FIELD to etField, + KotlinTarget.VALUE_PARAMETER to etParameter + ), + // additional values for jvm8 + JvmTarget.JVM_1_8 to mutableMapOf( + KotlinTarget.TYPE_PARAMETER to etTypeParameter, + KotlinTarget.TYPE to etTypeUse + ) + ) + + init { + annotationTargetMaps[JvmTarget.JVM_1_8]!!.putAll(annotationTargetMaps[JvmTarget.JVM_1_6]!!.toList()) + } + + + private fun generateTargetAnnotation(irClass: IrClass) { + if (irClass.hasAnnotation(FqName("java.lang.annotation.Target"))) return + val annotationTargetMap = annotationTargetMaps[typeMapper.jvmTarget] + ?: throw AssertionError("No annotation target map for JVM target ${typeMapper.jvmTarget}") + + val targets = irClass.applicableTargetSet() ?: return + val javaTargets = targets.mapNotNull { annotationTargetMap[it] } + + val vararg = IrVarargImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + type = context.irBuiltIns.arrayClass.typeWith(elementTypeEnum.defaultType), + varargElementType = elementTypeEnum.defaultType + ) + for (target in javaTargets) { + vararg.elements.add( + IrGetEnumValueImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, elementTypeEnum.defaultType, target.symbol + ) + ) + } + + irClass.annotations.add( + IrCallImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol + ).apply { + putValueArgument(0, vararg) + } + ) + // TODO + } +} + +// To be generalized to IrMemberAccessExpression as soon as properties get symbols. +private fun IrCall.getValueArgument(name: Name): IrExpression? { + val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null + return getValueArgument(index) +} + +// Copied and modified from AnnotationChecker.kt + +private val TARGET_ALLOWED_TARGETS = Name.identifier("allowedTargets") + +private fun IrClass.applicableTargetSet(): Set? { + val targetEntry = getAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null + return loadAnnotationTargets(targetEntry) +} + +private fun loadAnnotationTargets(targetEntry: IrCall): Set? { + val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS) + as? IrVararg ?: return null + return valueArgument.elements.filterIsInstance().mapNotNull { + KotlinTarget.valueOrNull(it.symbol.owner.name.asString()) + }.toSet() +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt index 0fc9a7dcca2..7505f00a6a1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt @@ -346,6 +346,8 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL val function = this parent = functionReferenceClass overriddenSymbols.add(superFunction.symbol) + annotations.addAll(callee.annotations) + dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function) val unboundArgsSet = unboundCalleeParameters.toSet() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt index 9ad60ee07c2..1f784a6f25c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt @@ -220,6 +220,7 @@ private class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringP enumEntry, (enumEntry.correspondingClass ?: enumEntry.parentAsClass).defaultType ).also { it.initializer = IrExpressionBodyImpl(enumEntry.initializerExpression!!) + it.annotations.addAll(enumEntry.annotations) enumEntryFields.add(it) enumEntriesByField[it] = enumEntry } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt index c5fd931b0d5..268e71e288b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt @@ -134,6 +134,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl parent = inheritedFun.parent overriddenSymbols.addAll(inheritedFun.overriddenSymbols) copyParameterDeclarationsFrom(inheritedFun) + annotations.addAll(inheritedFun.annotations) } } else context.declarationFactory.getDefaultImplsFunction(inheritedFun) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt index a92679dc713..874255b028f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt @@ -167,10 +167,12 @@ private class SingletonObjectJvmStaticLowering( irClass.declarations.filter(::isJvmStaticFunction).forEach { val jvmStaticFunction = it as IrSimpleFunction - val oldDispatchReceiverParameter = jvmStaticFunction.dispatchReceiverParameter!! - jvmStaticFunction.dispatchReceiverParameter = null - modifyBody(jvmStaticFunction, irClass, oldDispatchReceiverParameter) - functionsMadeStatic.add(jvmStaticFunction.symbol) + // dispatch receiver parameter is already null for synthetic property annotation methods + jvmStaticFunction.dispatchReceiverParameter?.let { oldDispatchReceiverParameter -> + jvmStaticFunction.dispatchReceiverParameter = null + modifyBody(jvmStaticFunction, irClass, oldDispatchReceiverParameter) + functionsMadeStatic.add(jvmStaticFunction.symbol) + } } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt index 5bd2817c955..d90c5cd457f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt @@ -18,10 +18,12 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides import org.jetbrains.kotlin.psi.* @@ -31,7 +33,10 @@ import org.jetbrains.kotlin.psi2ir.isConstructorDelegatingToSuper import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator +import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor +import org.jetbrains.kotlin.utils.addToStdlib.safeAs class FunctionGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) { @@ -114,10 +119,10 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio generateValueParameterDeclarations(irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference) val ktBodyExpression = ktAccessor?.bodyExpression irAccessor.body = - if (ktBodyExpression != null) - createBodyGenerator(irAccessor.symbol).generateFunctionBody(ktBodyExpression) - else - generateDefaultAccessorBody(descriptor, irAccessor) + if (ktBodyExpression != null) + createBodyGenerator(irAccessor.symbol).generateFunctionBody(ktBodyExpression) + else + generateDefaultAccessorBody(descriptor, irAccessor) } fun generateDefaultAccessorForPrimaryConstructorParameter( @@ -299,8 +304,13 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio ): IrValueParameter = declareParameter(valueParameterDescriptor, ktParameter, irOwnerElement).also { irValueParameter -> if (withDefaultValues) { - irValueParameter.defaultValue = ktParameter?.defaultValue?.let { - bodyGenerator.generateExpressionBody(it) + irValueParameter.defaultValue = ktParameter?.defaultValue?.let { defaultValue -> + val inAnnotation = + valueParameterDescriptor.containingDeclaration.safeAs()?.isAnnotationConstructor() ?: false + if (inAnnotation) { + generateDefaultAnnotationParameterValue(defaultValue, valueParameterDescriptor) + } else + bodyGenerator.generateExpressionBody(defaultValue) } } } @@ -320,4 +330,19 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio descriptor, descriptor.type.toIrType(), (descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType() ) + + private fun generateDefaultAnnotationParameterValue( + valueExpression: KtExpression, + valueParameterDescriptor: ValueParameterDescriptor + ): IrExpressionBody { + val constantDefaultValue = + ConstantExpressionEvaluator.getConstant(valueExpression, context.bindingContext)?.toConstantValue(valueParameterDescriptor.type) + ?: error("Constant value expected for default parameter value in annotation, got $valueExpression") + return IrExpressionBodyImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + context.constantValueGenerator.generateConstantValueAsExpression( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, constantDefaultValue, valueParameterDescriptor.varargElementType + ) + ) + } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt index 8e908694bef..0bde993b49a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt @@ -66,8 +66,6 @@ class IrLazyClass( symbol.bind(this) } - override val annotations: MutableList = arrayListOf() - override val descriptor: ClassDescriptor get() = symbol.descriptor override var thisReceiver: IrValueParameter? by lazyVar { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt index 3d5ac6f6a4a..5b1f47975e4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt @@ -50,7 +50,11 @@ abstract class IrLazyDeclarationBase( createLazyParent()!! } - override val annotations: MutableList = arrayListOf() + override val annotations: MutableList by lazy { + descriptor.annotations.map { + typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(it) + }.toMutableList() + } override var metadata: Nothing? get() = null diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt index 67623fab628..c278b6d6a71 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt @@ -14,10 +14,12 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.source.PsiSourceElement +import org.jetbrains.kotlin.resolve.source.PsiSourceFile import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -116,8 +118,8 @@ class ConstantValueGenerator( val primaryConstructorSymbol = symbolTable.referenceConstructor(primaryConstructorDescriptor) val psi = annotationDescriptor.source.safeAs()?.psi - val startOffset = psi?.startOffset ?: UNDEFINED_OFFSET - val endOffset = psi?.startOffset ?: UNDEFINED_OFFSET + val startOffset = psi?.takeUnless { it.containingFile.fileType.isBinary }?.startOffset ?: UNDEFINED_OFFSET + val endOffset = psi?.takeUnless { it.containingFile.fileType.isBinary }?.endOffset ?: UNDEFINED_OFFSET val irCall = IrCallImpl( startOffset, endOffset, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index adca044e7cf..1d0d791f366 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -19,6 +19,8 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -278,6 +280,12 @@ val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY val IrClass.isInterface get() = kind == ClassKind.INTERFACE val IrClass.isClass get() = kind == ClassKind.CLASS val IrClass.isObject get() = kind == ClassKind.OBJECT +val IrDeclarationWithName.fqNameWhenAvailable: FqName? + get() = when (val parent = parent) { + is IrDeclarationWithName -> parent.fqNameWhenAvailable?.child(name) + is IrPackageFragment -> parent.fqName.child(name) + else -> null + } val IrDeclaration.parentAsClass get() = parent as IrClass diff --git a/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt b/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt index 1e99b4fadda..0742890df6a 100644 --- a/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt +++ b/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/annotations/parameters.kt b/compiler/testData/codegen/box/annotations/parameters.kt new file mode 100644 index 00000000000..7baf4b0657a --- /dev/null +++ b/compiler/testData/codegen/box/annotations/parameters.kt @@ -0,0 +1,46 @@ +// IGNORE_BACKEND: JS_IR +// TODO: muted automatically, investigate should it be ran for JS or not +// IGNORE_BACKEND: JS, NATIVE + +// WITH_REFLECT + +import kotlin.test.assertEquals +import kotlin.reflect.KClass + +enum class E { E0 } +annotation class A + +@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 +) + +@Anno("OK", 42, 2.718281828, 43u, E.E0, A(), A::class, emptyArray(), intArrayOf(1, 2), arrayOf(E.E0), arrayOf(A())) +class TTT + +fun box(): String { + val anno = TTT::class.annotations.single() as Anno + 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) +// TODO: problems with KClass/Class conversion in JVM_IR, unrelated to annotation codegen +// assert(anno.k == A::class.java) + assert(anno.arr.isEmpty()) + assert(anno.intArr.contentEquals(intArrayOf(1, 2))) + assert(anno.arrOfE.contentEquals(arrayOf(E.E0))) + assert(anno.arrOfA.size == 1) + return "OK" +} diff --git a/compiler/testData/codegen/box/jvmName/annotationProperties.kt b/compiler/testData/codegen/box/jvmName/annotationProperties.kt index 8d6f4876b18..76bdc070218 100644 --- a/compiler/testData/codegen/box/jvmName/annotationProperties.kt +++ b/compiler/testData/codegen/box/jvmName/annotationProperties.kt @@ -1,4 +1,5 @@ // TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM_IR // WITH_REFLECT package test diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/annotations.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/annotations.kt index 543f91a6550..bce27c89f87 100644 --- a/compiler/testData/codegen/box/multiplatform/defaultArguments/annotations.kt +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/annotations.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +MultiPlatformProjects -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: common.kt diff --git a/compiler/testData/codegen/box/synchronized/sync.kt b/compiler/testData/codegen/box/synchronized/sync.kt index fc4b9c2f190..e48f6181edb 100644 --- a/compiler/testData/codegen/box/synchronized/sync.kt +++ b/compiler/testData/codegen/box/synchronized/sync.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/compileKotlinAgainstKotlin/jvmNames.kt b/compiler/testData/compileKotlinAgainstKotlin/jvmNames.kt index a0f955970d4..0d588dc21a1 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/jvmNames.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/jvmNames.kt @@ -1,4 +1,5 @@ // TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM_IR // FILE: A.kt package lib diff --git a/compiler/testData/ir/irText/stubs/constFromBuiltins__kotlin.Int.txt b/compiler/testData/ir/irText/stubs/constFromBuiltins__kotlin.Int.txt index 31b83934e23..d7c7edf6e61 100644 --- a/compiler/testData/ir/irText/stubs/constFromBuiltins__kotlin.Int.txt +++ b/compiler/testData/ir/irText/stubs/constFromBuiltins__kotlin.Int.txt @@ -78,22 +78,64 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType:kotlin.Int - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="Use rem(other) instead" + 2: CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="rem(other)" + 2: VARARG type=> varargElementType= + 3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type= + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType: - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="Use rem(other) instead" + 2: CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="rem(other)" + 2: VARARG type=> varargElementType= + 3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type= + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType: - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="Use rem(other) instead" + 2: CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="rem(other)" + 2: VARARG type=> varargElementType= + 3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type= + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:kotlin.Int) returnType:kotlin.Int - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="Use rem(other) instead" + 2: CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="rem(other)" + 2: VARARG type=> varargElementType= + 3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type= + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:kotlin.Int FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType: - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="Use rem(other) instead" + 2: CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="rem(other)" + 2: VARARG type=> varargElementType= + 3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type= + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType:kotlin.Int - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="Use rem(other) instead" + 2: CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="rem(other)" + 2: VARARG type=> varargElementType= + 3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type= + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:or visibility:public modality:FINAL <> ($this:kotlin.Int, other:kotlin.Int) returnType:kotlin.Int $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int @@ -129,22 +171,40 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType:kotlin.Int - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.1" + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType: - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.1" + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType: - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.1" + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:kotlin.Int) returnType:kotlin.Int - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.1" + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:kotlin.Int FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType: - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.1" + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:) returnType:kotlin.Int - $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.1" + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type: FUN IR_EXTERNAL_DECLARATION_STUB name:shl visibility:public modality:FINAL <> ($this:kotlin.Int, bitCount:kotlin.Int) returnType:kotlin.Int $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int @@ -231,14 +291,20 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:MIN_VALUE visibility:public modality:FINAL [const,val] $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int.Companion PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS visibility:public modality:FINAL [const,val] - FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS type:kotlin.Int visibility:public [final] + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.3" + FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS type:kotlin.Int visibility:public [final] EXPRESSION_BODY CONST Int type=kotlin.Int value=32 FUN IR_EXTERNAL_DECLARATION_STUB name: visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS visibility:public modality:FINAL [const,val] $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:kotlin.Int.Companion PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES visibility:public modality:FINAL [const,val] - FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES type:kotlin.Int visibility:public [final] + annotations: + CALL 'UNBOUND IrConstructorSymbolImpl' type= origin=null + 1: CONST String type= value="1.3" + FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES type:kotlin.Int visibility:public [final] EXPRESSION_BODY CONST Int type=kotlin.Int value=4 FUN IR_EXTERNAL_DECLARATION_STUB name: visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index ac1e9ee2fef..ec24c7eea9a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -141,6 +141,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/annotations/parameterWithPrimitiveType.kt"); } + @TestMetadata("parameters.kt") + public void testParameters() throws Exception { + runTest("compiler/testData/codegen/box/annotations/parameters.kt"); + } + @TestMetadata("propertyWithPropertyInInitializerAsParameter.kt") public void testPropertyWithPropertyInInitializerAsParameter() throws Exception { runTest("compiler/testData/codegen/box/annotations/propertyWithPropertyInInitializerAsParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index d81c3475d7b..d5518a9af85 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -146,6 +146,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/annotations/parameterWithPrimitiveType.kt"); } + @TestMetadata("parameters.kt") + public void testParameters() throws Exception { + runTest("compiler/testData/codegen/box/annotations/parameters.kt"); + } + @TestMetadata("propertyWithPropertyInInitializerAsParameter.kt") public void testPropertyWithPropertyInInitializerAsParameter() throws Exception { runTest("compiler/testData/codegen/box/annotations/propertyWithPropertyInInitializerAsParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 4509ec6a461..3c2f648128b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -141,6 +141,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/annotations/parameterWithPrimitiveType.kt"); } + @TestMetadata("parameters.kt") + public void testParameters() throws Exception { + runTest("compiler/testData/codegen/box/annotations/parameters.kt"); + } + @TestMetadata("propertyWithPropertyInInitializerAsParameter.kt") public void testPropertyWithPropertyInInitializerAsParameter() throws Exception { runTest("compiler/testData/codegen/box/annotations/propertyWithPropertyInInitializerAsParameter.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 191a730fdd7..71530dcc78b 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -46,6 +46,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt"); } + @TestMetadata("parameters.kt") + public void testParameters() throws Exception { + runTest("compiler/testData/codegen/box/annotations/parameters.kt"); + } + @TestMetadata("resolveWithLowPriorityAnnotation.kt") public void testResolveWithLowPriorityAnnotation() throws Exception { runTest("compiler/testData/codegen/box/annotations/resolveWithLowPriorityAnnotation.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index c508367ac89..b05f66d057b 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -46,6 +46,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt"); } + @TestMetadata("parameters.kt") + public void testParameters() throws Exception { + runTest("compiler/testData/codegen/box/annotations/parameters.kt"); + } + @TestMetadata("resolveWithLowPriorityAnnotation.kt") public void testResolveWithLowPriorityAnnotation() throws Exception { runTest("compiler/testData/codegen/box/annotations/resolveWithLowPriorityAnnotation.kt");