Load some of the TYPE_USE annotations in fast class reading mode

Only top-level types on fields, methods' return types and
value parameters are supported to catch-up how class-files are loaded
in IntelliJ (see IDEA-153093)

NB: this commit also affects
ForeignJava8AnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated
that were failing before

 #KT-20016 Fixed
This commit is contained in:
Denis Zharkov
2017-09-11 13:15:24 +03:00
parent 08f3dbce67
commit d6ee774243
10 changed files with 162 additions and 6 deletions
@@ -22,9 +22,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.*
import java.lang.reflect.Array
internal class AnnotationsCollectorMethodVisitor(
@@ -55,6 +53,27 @@ internal class AnnotationsCollectorMethodVisitor(
return BinaryJavaAnnotation.addAnnotation(annotations, 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)
}
TypeReference.METHOD_FORMAL_PARAMETER ->
BinaryJavaAnnotation.addTypeAnnotation(
member.valueParameters[typeReference.formalParameterIndex].type,
desc, context, signatureParser
)
else -> null
}
}
}
class BinaryJavaAnnotation private constructor(
@@ -87,6 +106,20 @@ class BinaryJavaAnnotation private constructor(
return annotationVisitor
}
fun addTypeAnnotation(
type: JavaType,
desc: String,
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser
): AnnotationVisitor? {
type as? PlainJavaClassifierType ?: return null
val (javaAnnotation, annotationVisitor) = createAnnotationAndVisitor(desc, context, signatureParser)
type.addAnnotation(javaAnnotation)
return annotationVisitor
}
}
private val classifierResolutionResult by lazy(LazyThreadSafetyMode.NONE) {
@@ -162,6 +162,12 @@ 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)
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String, visible: Boolean) =
if (typePath == null)
BinaryJavaAnnotation.addTypeAnnotation(type, desc, context, signatureParser)
else
null
}
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.load.java.structure.impl.classFiles
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.FqName
@@ -39,9 +40,18 @@ internal class PlainJavaClassifierType(
get() = typeArguments.isEmpty() &&
classifierResolverResult.classifier?.safeAs<JavaClass>()?.typeParameters?.isNotEmpty() == true
// TODO: support type annotations
override val annotations get() = emptyList<JavaAnnotation>()
override fun findAnnotation(fqName: FqName) = null
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 = ContainerUtil.newSmartList()
}
(_annotations as MutableList).add(annotation)
}
override val isDeprecatedInJavaDoc get() = false