Support reading from class files of the type use annotations on type parameters and type arguments
^KT-11454 Fixed
This commit is contained in:
+89
-39
@@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-4
@@ -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()
|
||||
|
||||
+45
-7
@@ -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)
|
||||
|
||||
|
||||
+38
-19
@@ -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)
|
||||
|
||||
|
||||
+62
-64
@@ -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
-19
@@ -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()
|
||||
|
||||
|
||||
+12
-23
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user