Support reading from class files of the type use annotations on type parameters and type arguments

^KT-11454 Fixed
This commit is contained in:
Victor Petukhov
2020-12-01 18:21:44 +03:00
parent 0833719a79
commit a89329e077
54 changed files with 2077 additions and 262 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.load.java.structure.impl.classFiles
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotation.Companion.computeTargetType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -56,10 +57,7 @@ internal class AnnotationsAndParameterCollectorMethodVisitor(
}
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(
member.annotations as MutableCollection<JavaAnnotation>,
desc, context, signatureParser
)
BinaryJavaAnnotation.addAnnotation(member, desc, context, signatureParser)
@Suppress("NOTHING_TO_OVERRIDE")
override fun visitAnnotableParameterCount(parameterCount: Int, visible: Boolean) {
@@ -76,33 +74,38 @@ internal class AnnotationsAndParameterCollectorMethodVisitor(
val index = absoluteParameterIndex - parametersToSkipNumber
if (index < 0) return null
val annotations =
member.valueParameters[index].annotations as MutableCollection<JavaAnnotation>?
?: return null
return BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
return BinaryJavaAnnotation.addAnnotation(member.valueParameters[index], desc, context, signatureParser)
}
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String, visible: Boolean): AnnotationVisitor? {
// TODO: support annotations on type arguments
if (typePath != null) return null
val typeReference = TypeReference(typeRef)
return when (typeReference.sort) {
TypeReference.METHOD_RETURN -> member.safeAs<BinaryJavaMethod>()?.returnType?.let {
BinaryJavaAnnotation.addTypeAnnotation(it, desc, context, signatureParser)
}
if (typePath != null) {
val baseType = when (typeReference.sort) {
TypeReference.METHOD_RETURN -> member.safeAs<BinaryJavaMethod>()?.returnType
TypeReference.METHOD_FORMAL_PARAMETER -> member.valueParameters[typeReference.formalParameterIndex].type
TypeReference.METHOD_TYPE_PARAMETER_BOUND ->
BinaryJavaAnnotation.computeTypeParameterBound(member.typeParameters, typeReference)
else -> null
} ?: return null
TypeReference.METHOD_FORMAL_PARAMETER ->
BinaryJavaAnnotation.addTypeAnnotation(
member.valueParameters[typeReference.formalParameterIndex].type,
desc, context, signatureParser
)
else -> null
return BinaryJavaAnnotation.addAnnotation(
computeTargetType(baseType, translatePath(typePath)) as JavaPlainType, desc, context, signatureParser
)
}
val targetType = when (typeReference.sort) {
TypeReference.METHOD_RETURN -> (member as? BinaryJavaMethod)?.returnType as JavaPlainType
TypeReference.METHOD_TYPE_PARAMETER -> member.typeParameters[typeReference.typeParameterIndex] as BinaryJavaTypeParameter
TypeReference.METHOD_FORMAL_PARAMETER -> member.valueParameters[typeReference.formalParameterIndex].type as JavaPlainType
TypeReference.METHOD_TYPE_PARAMETER_BOUND -> BinaryJavaAnnotation.computeTypeParameterBound(member.typeParameters, typeReference) as JavaPlainType
else -> null
} ?: return null
return BinaryJavaAnnotation.addAnnotation(targetType, desc, context, signatureParser)
}
enum class PathElementType { ARRAY_ELEMENT, WILDCARD_BOUND, ENCLOSING_CLASS, TYPE_ARGUMENT }
}
class BinaryJavaAnnotation private constructor(
@@ -125,29 +128,76 @@ class BinaryJavaAnnotation private constructor(
}
fun addAnnotation(
annotations: MutableCollection<JavaAnnotation>,
desc: String,
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
annotationOwner: MutableJavaAnnotationOwner,
desc: String,
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
): AnnotationVisitor {
val (javaAnnotation, annotationVisitor) = createAnnotationAndVisitor(desc, context, signatureParser)
annotations.add(javaAnnotation)
annotationOwner.annotations.add(javaAnnotation)
return annotationVisitor
}
fun addTypeAnnotation(
type: JavaType,
desc: String,
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
): AnnotationVisitor? {
type as? PlainJavaClassifierType ?: return null
internal fun translatePath(path: TypePath): List<Pair<AnnotationsAndParameterCollectorMethodVisitor.PathElementType, Int?>> {
val length = path.length
val list = mutableListOf<Pair<AnnotationsAndParameterCollectorMethodVisitor.PathElementType, Int?>>()
for (i in 0 until length) {
when (path.getStep(i)) {
TypePath.INNER_TYPE -> {
continue
}
TypePath.ARRAY_ELEMENT -> {
list.add(AnnotationsAndParameterCollectorMethodVisitor.PathElementType.ARRAY_ELEMENT to null)
}
TypePath.WILDCARD_BOUND -> {
list.add(AnnotationsAndParameterCollectorMethodVisitor.PathElementType.WILDCARD_BOUND to null)
}
TypePath.TYPE_ARGUMENT -> {
list.add(AnnotationsAndParameterCollectorMethodVisitor.PathElementType.TYPE_ARGUMENT to path.getStepArgument(i))
}
}
}
return list
}
val (javaAnnotation, annotationVisitor) = createAnnotationAndVisitor(desc, context, signatureParser)
type.addAnnotation(javaAnnotation)
internal fun computeTargetType(
baseType: JavaType,
typePath: List<Pair<AnnotationsAndParameterCollectorMethodVisitor.PathElementType, Int?>>
): JavaType {
var targetType = baseType
return annotationVisitor
for (element in typePath) {
when (element.first) {
AnnotationsAndParameterCollectorMethodVisitor.PathElementType.TYPE_ARGUMENT -> {
if (targetType is JavaClassifierType) {
targetType = targetType.typeArguments[element.second!!]!!
}
}
AnnotationsAndParameterCollectorMethodVisitor.PathElementType.WILDCARD_BOUND -> {
if (targetType is JavaWildcardType) {
targetType = targetType.bound!!
}
}
AnnotationsAndParameterCollectorMethodVisitor.PathElementType.ARRAY_ELEMENT -> {
if (targetType is JavaArrayType) {
targetType = targetType.componentType
}
}
}
}
return targetType
}
internal fun computeTypeParameterBound(
typeParameters: List<JavaTypeParameter>,
typeReference: TypeReference
): JavaClassifierType {
val typeParameter = typeParameters[typeReference.typeParameterIndex] as BinaryJavaTypeParameter
val boundIndex =
if (typeParameter.hasImplicitObjectClassBound) typeReference.typeParameterBoundIndex - 1 else typeReference.typeParameterBoundIndex
return typeParameters[typeReference.typeParameterIndex].upperBounds.toList()[boundIndex]
}
}
@@ -66,13 +66,20 @@ class BinaryClassSignatureParser {
// postpone list allocation till a second bound is seen; ignore sole Object bound
val bounds: MutableList<JavaClassifierType> = SmartList()
var hasImplicitObjectBound = false
while (signature.current() == ':') {
signature.next()
val bound = parseClassifierRefSignature(signature, context) ?: continue
bounds.add(bound)
// '::' means that the implicit object bound is between ':'
if (signature.current() == ':') {
hasImplicitObjectBound = true
continue
}
bounds.add(parseClassifierRefSignature(signature, context) ?: continue)
}
return BinaryJavaTypeParameter(Name.identifier(parameterName), bounds)
return BinaryJavaTypeParameter(Name.identifier(parameterName), bounds, hasImplicitObjectBound)
}
fun parseClassifierRefSignature(signature: CharacterIterator, context: ClassifierResolutionContext): JavaClassifierType? {
@@ -83,7 +90,7 @@ class BinaryClassSignatureParser {
}
}
private fun parseTypeVariableRefSignature(signature: CharacterIterator, context: ClassifierResolutionContext): JavaClassifierType? {
private fun parseTypeVariableRefSignature(signature: CharacterIterator, context: ClassifierResolutionContext): JavaClassifierType {
val id = StringBuilder()
signature.next()
@@ -22,6 +22,7 @@ import gnu.trove.THashMap
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotation.Companion.computeTypeParameterBound
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartList
@@ -38,12 +39,12 @@ class BinaryJavaClass(
override var access: Int = 0,
override val outerClass: JavaClass?,
classContent: ByteArray? = null
) : ClassVisitor(ASM_API_VERSION_FOR_CLASS_READING), VirtualFileBoundJavaClass, BinaryJavaModifierListOwner, MapBasedJavaAnnotationOwner {
private lateinit var myInternalName: String
) : ClassVisitor(ASM_API_VERSION_FOR_CLASS_READING), VirtualFileBoundJavaClass, BinaryJavaModifierListOwner, MutableJavaAnnotationOwner {
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
override lateinit var typeParameters: List<JavaTypeParameter>
override lateinit var supertypes: Collection<JavaClassifierType>
override lateinit var supertypes: List<JavaClassifierType>
override val methods = arrayListOf<JavaMethod>()
override val fields = arrayListOf<JavaField>()
override val constructors = arrayListOf<JavaConstructor>()
@@ -51,6 +52,12 @@ class BinaryJavaClass(
override fun hasDefaultConstructor() = false // never: all constructors explicit in bytecode
private lateinit var myInternalName: String
// In accordance with JVMS, super class always comes before the interface list
private val superclass: JavaClassifierType? get() = supertypes.firstOrNull()
private val interfaces: List<JavaClassifierType> get() = supertypes.drop(1)
override val annotationsByFqName by buildLazyValueForMap()
// Short name of a nested class of this class -> access flags as seen in the InnerClasses attribute value.
@@ -75,6 +82,37 @@ class BinaryJavaClass(
override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = false
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, descriptor: String?, visible: Boolean): AnnotationVisitor? {
val typeReference = TypeReference(typeRef)
if (descriptor == null)
return null
if (typePath != null) {
val translatedPath = BinaryJavaAnnotation.translatePath(typePath)
when (typeReference.sort) {
TypeReference.CLASS_TYPE_PARAMETER_BOUND -> {
val baseType = computeTypeParameterBound(typeParameters, typeReference)
val targetType = BinaryJavaAnnotation.computeTargetType(baseType, translatedPath)
return BinaryJavaAnnotation.addAnnotation(targetType as JavaPlainType, descriptor, context, signatureParser)
}
}
}
return when (typeReference.sort) {
TypeReference.CLASS_TYPE_PARAMETER ->
BinaryJavaAnnotation.addAnnotation(
typeParameters[typeReference.typeParameterIndex] as BinaryJavaTypeParameter, descriptor, context, signatureParser
)
TypeReference.CLASS_TYPE_PARAMETER_BOUND ->
BinaryJavaAnnotation.addAnnotation(
computeTypeParameterBound(typeParameters, typeReference) as JavaPlainType, descriptor, context, signatureParser
)
else -> null
}
}
override fun visitEnd() {
methods.trimToSize()
fields.trimToSize()
@@ -181,11 +219,11 @@ class BinaryJavaClass(
object : FieldVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(this@run.annotations, desc, context, signatureParser)
BinaryJavaAnnotation.addAnnotation(this@run, desc, context, signatureParser)
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String, visible: Boolean) =
if (typePath == null)
BinaryJavaAnnotation.addTypeAnnotation(type, desc, context, signatureParser)
BinaryJavaAnnotation.addAnnotation(type as JavaPlainType, desc, context, signatureParser)
else
null
}
@@ -222,7 +260,7 @@ class BinaryJavaClass(
}
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
BinaryJavaAnnotation.addAnnotation(this, desc, context, signatureParser)
override fun findInnerClass(name: Name): JavaClass? = findInnerClass(name, classFileContent = null)
@@ -22,6 +22,7 @@ import gnu.trove.THashMap
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotation.Companion.computeTypeParameterBound
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartList
@@ -38,12 +39,12 @@ class BinaryJavaClass(
override var access: Int = 0,
override val outerClass: JavaClass?,
classContent: ByteArray? = null
) : ClassVisitor(ASM_API_VERSION_FOR_CLASS_READING), VirtualFileBoundJavaClass, BinaryJavaModifierListOwner, MapBasedJavaAnnotationOwner {
private lateinit var myInternalName: String
) : ClassVisitor(ASM_API_VERSION_FOR_CLASS_READING), VirtualFileBoundJavaClass, BinaryJavaModifierListOwner, MutableJavaAnnotationOwner {
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
override lateinit var typeParameters: List<JavaTypeParameter>
override lateinit var supertypes: Collection<JavaClassifierType>
override lateinit var supertypes: List<JavaClassifierType>
override val methods = arrayListOf<JavaMethod>()
override val fields = arrayListOf<JavaField>()
override val constructors = arrayListOf<JavaConstructor>()
@@ -51,6 +52,12 @@ class BinaryJavaClass(
override fun hasDefaultConstructor() = false // never: all constructors explicit in bytecode
private lateinit var myInternalName: String
// In accordance with JVMS, super class always comes before the interface list
private val superclass: JavaClassifierType? get() = supertypes.firstOrNull()
private val implementedInterfaces: List<JavaClassifierType> get() = supertypes.drop(1)
override val annotationsByFqName by buildLazyValueForMap()
// Short name of a nested class of this class -> access flags as seen in the InnerClasses attribute value.
@@ -69,11 +76,34 @@ class BinaryJavaClass(
override val isRecord get() = false
override val lightClassOriginKind: LightClassOriginKind? get() = null
override val isSealed: Boolean get() = permittedTypes.isNotEmpty()
override val permittedTypes = arrayListOf<JavaClassifierType>()
override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = false
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, descriptor: String?, visible: Boolean): AnnotationVisitor? {
if (descriptor == null)
return null
fun getTargetType(baseType: JavaType) =
if (typePath != null) BinaryJavaAnnotation.computeTargetType(baseType, typePath) else baseType
val typeReference = TypeReference(typeRef)
val annotationOwner = when (typeReference.sort) {
TypeReference.CLASS_EXTENDS ->
getTargetType(if (typeReference.superTypeIndex == -1) superclass!! else implementedInterfaces[typeReference.superTypeIndex])
TypeReference.CLASS_TYPE_PARAMETER -> typeParameters[typeReference.typeParameterIndex]
TypeReference.CLASS_TYPE_PARAMETER_BOUND -> getTargetType(computeTypeParameterBound(typeParameters, typeReference))
else -> return null
}
if (annotationOwner !is MutableJavaAnnotationOwner) return null
return BinaryJavaAnnotation.addAnnotation(annotationOwner, descriptor, context, signatureParser, isFreshlySupportedAnnotation = true)
}
override fun visitEnd() {
methods.trimToSize()
fields.trimToSize()
@@ -172,23 +202,12 @@ class BinaryJavaClass(
if (access.isSet(Opcodes.ACC_SYNTHETIC)) return null
val type = signatureParser.parseTypeString(StringCharacterIterator(signature ?: desc), context)
val processedValue = processValue(value, type)
val filed = BinaryJavaField(Name.identifier(name), access, this, access.isSet(Opcodes.ACC_ENUM), type, processedValue)
return BinaryJavaField(Name.identifier(name), access, this, access.isSet(Opcodes.ACC_ENUM), type, processedValue).run {
fields.add(this)
fields.add(filed)
object : FieldVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(this@run.annotations, desc, context, signatureParser)
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String, visible: Boolean) =
if (typePath == null)
BinaryJavaAnnotation.addTypeAnnotation(type, desc, context, signatureParser)
else
null
}
}
return AnnotationsCollectorFieldVisitor(filed, context, signatureParser)
}
/**
@@ -211,7 +230,7 @@ class BinaryJavaClass(
}
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
BinaryJavaAnnotation.addAnnotation(this, desc, context, signatureParser)
override fun findInnerClass(name: Name): JavaClass? = findInnerClass(name, classFileContent = null)
@@ -29,31 +29,30 @@ import java.text.CharacterIterator
import java.text.StringCharacterIterator
abstract class BinaryJavaMethodBase(
override val access: Int,
override val containingClass: JavaClass,
val valueParameters: List<BinaryJavaValueParameter>,
val typeParameters: List<JavaTypeParameter>,
override val name: Name
) : JavaMember, MapBasedJavaAnnotationOwner, BinaryJavaModifierListOwner {
override val access: Int,
override val containingClass: JavaClass,
val valueParameters: List<BinaryJavaValueParameter>,
val typeParameters: List<JavaTypeParameter>,
override val name: Name
) : JavaMember, BinaryJavaModifierListOwner, MutableJavaAnnotationOwner {
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
override val annotationsByFqName by buildLazyValueForMap()
override val annotations: Collection<JavaAnnotation> = SmartList()
companion object {
private class MethodInfo(
val returnType: JavaType,
val typeParameters: List<JavaTypeParameter>,
val valueParameterTypes: List<JavaType>
val returnType: JavaType,
val typeParameters: List<JavaTypeParameter>,
val valueParameterTypes: List<JavaType>
)
fun create(
name: String,
access: Int,
desc: String,
signature: String?,
containingClass: JavaClass,
parentContext: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
name: String,
access: Int,
desc: String,
signature: String?,
containingClass: JavaClass,
parentContext: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
): Pair<JavaMember, MethodVisitor> {
val isConstructor = "<init>" == name
val isVarargs = access.isSet(Opcodes.ACC_VARARGS)
@@ -61,23 +60,23 @@ abstract class BinaryJavaMethodBase(
val isInnerClassConstructor = isConstructor && containingClass.outerClass != null && !containingClass.isStatic
val isEnumConstructor = containingClass.isEnum && isConstructor
val info: MethodInfo =
if (signature != null) {
val contextForMethod = parentContext.copyForMember()
parseMethodSignature(signature, signatureParser, contextForMethod).also {
contextForMethod.addTypeParameters(it.typeParameters)
}
} else
parseMethodDescription(desc, parentContext, signatureParser).let {
when {
isEnumConstructor ->
// skip ordinal/name parameters for enum constructors
MethodInfo(it.returnType, it.typeParameters, it.valueParameterTypes.drop(2))
isInnerClassConstructor ->
// omit synthetic inner class constructor parameter
MethodInfo(it.returnType, it.typeParameters, it.valueParameterTypes.drop(1))
else -> it
}
if (signature != null) {
val contextForMethod = parentContext.copyForMember()
parseMethodSignature(signature, signatureParser, contextForMethod).also {
contextForMethod.addTypeParameters(it.typeParameters)
}
} else
parseMethodDescription(desc, parentContext, signatureParser).let {
when {
isEnumConstructor ->
// skip ordinal/name parameters for enum constructors
MethodInfo(it.returnType, it.typeParameters, it.valueParameterTypes.drop(2))
isInnerClassConstructor ->
// omit synthetic inner class constructor parameter
MethodInfo(it.returnType, it.typeParameters, it.valueParameterTypes.drop(1))
else -> it
}
}
val parameterTypes = info.valueParameterTypes
val paramCount = parameterTypes.size
@@ -87,15 +86,15 @@ abstract class BinaryJavaMethodBase(
}
val member: BinaryJavaMethodBase =
if (isConstructor)
BinaryJavaConstructor(access, containingClass, parameterList, info.typeParameters)
else
BinaryJavaMethod(
access, containingClass,
parameterList,
info.typeParameters,
Name.identifier(name), info.returnType
)
if (isConstructor)
BinaryJavaConstructor(access, containingClass, parameterList, info.typeParameters)
else
BinaryJavaMethod(
access, containingClass,
parameterList,
info.typeParameters,
Name.identifier(name), info.returnType
)
val paramIgnoreCount = when {
isEnumConstructor -> 2
@@ -114,9 +113,9 @@ abstract class BinaryJavaMethodBase(
}
private fun parseMethodDescription(
desc: String,
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
desc: String,
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
): MethodInfo {
val returnType = signatureParser.mapAsmType(Type.getReturnType(desc), context)
val parameterTypes = Type.getArgumentTypes(desc).map { signatureParser.mapAsmType(it, context) }
@@ -125,9 +124,9 @@ abstract class BinaryJavaMethodBase(
}
private fun parseMethodSignature(
signature: String,
signatureParser: BinaryClassSignatureParser,
context: ClassifierResolutionContext
signature: String,
signatureParser: BinaryClassSignatureParser,
context: ClassifierResolutionContext
): MethodInfo {
val iterator = StringCharacterIterator(signature)
val typeParameters = signatureParser.parseTypeParametersDeclaration(iterator, context)
@@ -137,8 +136,7 @@ abstract class BinaryJavaMethodBase(
var paramTypes: List<JavaType>
if (iterator.current() == ')') {
paramTypes = emptyList()
}
else {
} else {
paramTypes = mutableListOf()
while (iterator.current() != ')' && iterator.current() != CharacterIterator.DONE) {
paramTypes.add(signatureParser.parseTypeString(iterator, context))
@@ -157,14 +155,14 @@ abstract class BinaryJavaMethodBase(
}
class BinaryJavaMethod(
flags: Int,
containingClass: JavaClass,
valueParameters: List<BinaryJavaValueParameter>,
typeParameters: List<JavaTypeParameter>,
name: Name,
override val returnType: JavaType
flags: Int,
containingClass: JavaClass,
valueParameters: List<BinaryJavaValueParameter>,
typeParameters: List<JavaTypeParameter>,
name: Name,
override val returnType: JavaType
) : BinaryJavaMethodBase(
flags, containingClass, valueParameters, typeParameters, name
flags, containingClass, valueParameters, typeParameters, name
), JavaMethod {
override var annotationParameterDefaultValue: JavaAnnotationArgument? = null
internal set(value) {
@@ -178,11 +176,11 @@ class BinaryJavaMethod(
}
class BinaryJavaConstructor(
flags: Int,
containingClass: JavaClass,
valueParameters: List<BinaryJavaValueParameter>,
typeParameters: List<JavaTypeParameter>
flags: Int,
containingClass: JavaClass,
valueParameters: List<BinaryJavaValueParameter>,
typeParameters: List<JavaTypeParameter>
) : BinaryJavaMethodBase(
flags, containingClass, valueParameters, typeParameters,
SpecialNames.NO_NAME_PROVIDED
flags, containingClass, valueParameters, typeParameters,
SpecialNames.NO_NAME_PROVIDED
), JavaConstructor
@@ -17,20 +17,19 @@
package org.jetbrains.kotlin.load.java.structure.impl.classFiles
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassVisitor
class BinaryJavaField(
override val name: Name,
override val access: Int,
override val containingClass: JavaClass,
override val isEnumEntry: Boolean,
override val type: JavaType,
override val initializerValue: Any?
) : JavaField, MapBasedJavaAnnotationOwner, BinaryJavaModifierListOwner {
override val name: Name,
override val access: Int,
override val containingClass: JavaClass,
override val isEnumEntry: Boolean,
override val type: JavaType,
override val initializerValue: Any?
) : JavaField, BinaryJavaModifierListOwner, MutableJavaAnnotationOwner {
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
override val annotationsByFqName by buildLazyValueForMap()
@@ -39,20 +38,19 @@ class BinaryJavaField(
}
class BinaryJavaTypeParameter(
override val name: Name,
override val upperBounds: Collection<JavaClassifierType>
) : JavaTypeParameter {
// TODO: support annotations on type parameters
override val annotations get() = emptyList<JavaAnnotation>()
override fun findAnnotation(fqName: FqName) = null
override val isDeprecatedInJavaDoc get() = false
override val name: Name,
override val upperBounds: Collection<JavaClassifierType>,
// If all bounds are interfaces then a type parameter has implicit Object class bound
val hasImplicitObjectClassBound: Boolean
) : JavaTypeParameter, ListBasedJavaAnnotationOwner, MutableJavaAnnotationOwner {
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
override val isDeprecatedInJavaDoc = false
}
class BinaryJavaValueParameter(
override val type: JavaType,
override val isVararg: Boolean
) : JavaValueParameter, MapBasedJavaAnnotationOwner {
override val type: JavaType,
override val isVararg: Boolean
) : JavaValueParameter, MapBasedJavaAnnotationOwner, MutableJavaAnnotationOwner {
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
override val annotationsByFqName by buildLazyValueForMap()
@@ -18,21 +18,25 @@ package org.jetbrains.kotlin.load.java.structure.impl.classFiles
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal abstract class JavaPlainType : ListBasedJavaAnnotationOwner, MutableJavaAnnotationOwner {
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
override val isDeprecatedInJavaDoc = false
}
// They are only used for java class files, but potentially may be used in other cases
// It would be better to call them like JavaSomeTypeImpl, but these names are already occupied by the PSI based types
internal class PlainJavaArrayType(override val componentType: JavaType) : JavaArrayType
internal class PlainJavaWildcardType(override val bound: JavaType?, override val isExtends: Boolean) : JavaWildcardType
internal class PlainJavaPrimitiveType(override val type: PrimitiveType?) : JavaPrimitiveType
internal class PlainJavaArrayType(override val componentType: JavaType) : JavaPlainType(), JavaArrayType
internal class PlainJavaWildcardType(override val bound: JavaType?, override val isExtends: Boolean) : JavaPlainType(), JavaWildcardType
internal class PlainJavaPrimitiveType(override val type: PrimitiveType?) : JavaPlainType(), JavaPrimitiveType
internal class PlainJavaClassifierType(
// calculation of classifier and canonicalText
classifierComputation: () -> ClassifierResolutionContext.Result,
override val typeArguments: List<JavaType>
) : JavaClassifierType {
// calculation of classifier and canonicalText
classifierComputation: () -> ClassifierResolutionContext.Result,
override val typeArguments: List<JavaType>
) : JavaPlainType(), JavaClassifierType {
private val classifierResolverResult by lazy(LazyThreadSafetyMode.NONE, classifierComputation)
override val classifier get() = classifierResolverResult.classifier
@@ -40,21 +44,6 @@ internal class PlainJavaClassifierType(
get() = typeArguments.isEmpty() &&
classifierResolverResult.classifier?.safeAs<JavaClass>()?.typeParameters?.isNotEmpty() == true
private var _annotations = emptyList<JavaAnnotation>()
override val annotations get() = _annotations
override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName }
internal fun addAnnotation(annotation: JavaAnnotation) {
if (_annotations.isEmpty()) {
_annotations = SmartList()
}
(_annotations as MutableList).add(annotation)
}
override val isDeprecatedInJavaDoc get() = false
override val classifierQualifiedName: String
get() = classifierResolverResult.qualifiedName