Rewrite AnnotationCodegen for IR, removing descriptors
This commit is contained in:
@@ -100,6 +100,20 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
return answer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassBuilder newVisitor(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
@NotNull Type asmType,
|
||||
@NotNull List<File> sourceFiles
|
||||
) {
|
||||
ClassBuilder answer = builderFactory.newClassBuilder(origin);
|
||||
generators.put(
|
||||
asmType.getInternalName() + ".class",
|
||||
new ClassBuilderAndSourceFileList(answer, sourceFiles)
|
||||
);
|
||||
return answer;
|
||||
}
|
||||
|
||||
public void done() {
|
||||
if (!isDone) {
|
||||
isDone = true;
|
||||
|
||||
@@ -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(
|
||||
|
||||
+2
@@ -549,6 +549,8 @@ class LocalDeclarationsLowering(
|
||||
newDeclaration.valueParameters += createTransformedValueParameters(capturedValues, oldDeclaration, newDeclaration)
|
||||
newDeclaration.recordTransformedValueParameters(localFunctionContext)
|
||||
|
||||
newDeclaration.annotations.addAll(oldDeclaration.annotations)
|
||||
|
||||
transformedDeclarations[oldDeclaration] = newDeclaration
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ val jvmPhases = namedIrFilePhase(
|
||||
foldConstantLoweringPhase then
|
||||
flattenStringConcatenationPhase then
|
||||
jvmBuiltinOptimizationLoweringPhase then
|
||||
additionalClassAnnotationPhase then
|
||||
|
||||
makePatchParentsPhase(3)
|
||||
)
|
||||
|
||||
+317
@@ -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<String>()
|
||||
|
||||
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<String>
|
||||
) {
|
||||
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<String>
|
||||
) {
|
||||
// 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<R> { 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<String>, 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<IrField>().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<KotlinTarget>? {
|
||||
val targetEntry = getAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null
|
||||
return loadAnnotationTargets(targetEntry)
|
||||
}
|
||||
|
||||
private fun loadAnnotationTargets(targetEntry: IrCall): Set<KotlinTarget>? {
|
||||
val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS)
|
||||
as? IrVararg ?: return null
|
||||
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
|
||||
KotlinTarget.valueOrNull(it.symbol.owner.name.asString())
|
||||
}.toSet()
|
||||
}
|
||||
+4
-6
@@ -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)
|
||||
|
||||
+2
-2
@@ -575,7 +575,7 @@ class ExpressionCodegen(
|
||||
val hasSpread = arguments.firstIsInstanceOrNull<IrSpreadElement>() != 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)
|
||||
|
||||
+32
-17
@@ -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<IrSimpleFunction>()
|
||||
?.correspondingProperty
|
||||
?.backingField
|
||||
?.initializer.safeAs<IrExpressionBody>()
|
||||
?.expression?.safeAs<IrGetValue>()
|
||||
?.symbol?.owner?.safeAs<IrValueParameter>()
|
||||
?.defaultValue?.safeAs<IrExpressionBody>()
|
||||
?.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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+247
@@ -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<JvmTarget, MutableMap<KotlinTarget, IrEnumEntry>> =
|
||||
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<KotlinTarget>? {
|
||||
val targetEntry = getAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null
|
||||
return loadAnnotationTargets(targetEntry)
|
||||
}
|
||||
|
||||
private fun loadAnnotationTargets(targetEntry: IrCall): Set<KotlinTarget>? {
|
||||
val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS)
|
||||
as? IrVararg ?: return null
|
||||
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
|
||||
KotlinTarget.valueOrNull(it.symbol.owner.name.asString())
|
||||
}.toSet()
|
||||
}
|
||||
+2
@@ -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()
|
||||
|
||||
+1
@@ -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
|
||||
}
|
||||
|
||||
+1
@@ -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)
|
||||
|
||||
|
||||
+6
-4
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+31
-6
@@ -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<ConstructorDescriptor>()?.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
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -66,8 +66,6 @@ class IrLazyClass(
|
||||
symbol.bind(this)
|
||||
}
|
||||
|
||||
override val annotations: MutableList<IrCall> = arrayListOf()
|
||||
|
||||
override val descriptor: ClassDescriptor get() = symbol.descriptor
|
||||
|
||||
override var thisReceiver: IrValueParameter? by lazyVar {
|
||||
|
||||
+5
-1
@@ -50,7 +50,11 @@ abstract class IrLazyDeclarationBase(
|
||||
createLazyParent()!!
|
||||
}
|
||||
|
||||
override val annotations: MutableList<IrCall> = arrayListOf()
|
||||
override val annotations: MutableList<IrCall> by lazy {
|
||||
descriptor.annotations.map {
|
||||
typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(it)
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
override var metadata: Nothing?
|
||||
get() = null
|
||||
|
||||
@@ -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<PsiSourceElement>()?.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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -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<String>,
|
||||
val intArr: IntArray,
|
||||
val arrOfE: Array<E>,
|
||||
val arrOfA: Array<A>
|
||||
)
|
||||
|
||||
@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"
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_REFLECT
|
||||
package test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: common.kt
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: A.kt
|
||||
|
||||
package lib
|
||||
|
||||
@@ -78,22 +78,64 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
|
||||
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
|
||||
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
|
||||
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
|
||||
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
|
||||
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
|
||||
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
|
||||
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
|
||||
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
|
||||
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
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:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
|
||||
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
|
||||
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
|
||||
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> 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:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
|
||||
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
|
||||
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
|
||||
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
|
||||
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
|
||||
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
|
||||
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
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:<this> 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:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
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:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> 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:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
annotations:
|
||||
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
|
||||
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
|
||||
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
|
||||
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:<this> 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:<this> 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=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> 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:<get-SIZE_BITS> 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:<this> 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=<unbound IrClassSymbolImpl> origin=null
|
||||
1: CONST String type=<unbound IrClassSymbolImpl> 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:<get-SIZE_BYTES> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user