Fix loading default Java annotation values in actual typealias from binary classes

#KT-22704 Fixed
This commit is contained in:
Alexander Udalov
2018-12-24 17:48:01 +01:00
parent 3fee84b966
commit 8ab9226805
15 changed files with 243 additions and 84 deletions
@@ -16,14 +16,13 @@
package org.jetbrains.kotlin.load.java.structure.impl;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiAnnotationMethod;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.load.java.structure.JavaMethod;
import org.jetbrains.kotlin.load.java.structure.JavaType;
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter;
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.load.java.structure.*;
import org.jetbrains.kotlin.name.Name;
import java.util.List;
@@ -57,9 +56,17 @@ public class JavaMethodImpl extends JavaMemberImpl<PsiMethod> implements JavaMet
}
@Override
public boolean getHasAnnotationParameterDefaultValue() {
@Nullable
public JavaAnnotationArgument getAnnotationParameterDefaultValue() {
PsiMethod psiMethod = getPsi();
return psiMethod instanceof PsiAnnotationMethod && ((PsiAnnotationMethod) psiMethod).getDefaultValue() != null;
if (psiMethod instanceof PsiAnnotationMethod) {
PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod) psiMethod).getDefaultValue();
if (defaultValue != null) {
return JavaAnnotationArgumentImpl.Factory.create(defaultValue, null);
}
}
return null;
}
@Override
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
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.*
import java.lang.reflect.Array
@@ -37,11 +36,10 @@ internal class AnnotationsAndParameterCollectorMethodVisitor(
private var visibleAnnotableParameterCount = parametersCountInMethodDesc
private var invisibleAnnotableParameterCount = parametersCountInMethodDesc
override fun visitAnnotationDefault(): AnnotationVisitor? {
member.safeAs<BinaryJavaMethod>()?.hasAnnotationParameterDefaultValue = true
// We don't store default value in Java model
return null
}
override fun visitAnnotationDefault(): AnnotationVisitor? =
BinaryJavaAnnotationVisitor(context, signatureParser) {
member.safeAs<BinaryJavaMethod>()?.annotationParameterDefaultValue = it
}
override fun visitParameter(name: String?, access: Int) {
if (name != null) {
@@ -165,19 +163,26 @@ class BinaryJavaAnnotation private constructor(
}
class BinaryJavaAnnotationVisitor(
private val context: ClassifierResolutionContext,
private val signatureParser: BinaryClassSignatureParser,
private val arguments: MutableCollection<JavaAnnotationArgument>
private val context: ClassifierResolutionContext,
private val signatureParser: BinaryClassSignatureParser,
private val sink: (JavaAnnotationArgument) -> Unit
) : AnnotationVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
constructor(
context: ClassifierResolutionContext,
signatureParser: BinaryClassSignatureParser,
arguments: MutableCollection<JavaAnnotationArgument>
) : this(context, signatureParser, { arguments.add(it) })
private fun addArgument(argument: JavaAnnotationArgument?) {
arguments.addIfNotNull(argument)
if (argument != null) {
sink(argument)
}
}
override fun visitAnnotation(name: String?, desc: String): AnnotationVisitor {
val (annotation, visitor) =
BinaryJavaAnnotation.createAnnotationAndVisitor(desc, context, signatureParser)
val (annotation, visitor) = BinaryJavaAnnotation.createAnnotationAndVisitor(desc, context, signatureParser)
arguments.add(PlainJavaAnnotationAsAnnotationArgument(name, annotation))
sink(PlainJavaAnnotationAsAnnotationArgument(name, annotation))
return visitor
}
@@ -169,7 +169,15 @@ class BinaryJavaMethod(
) : BinaryJavaMethodBase(
flags, containingClass, valueParameters, typeParameters, name
), JavaMethod {
override var hasAnnotationParameterDefaultValue: Boolean = false
override var annotationParameterDefaultValue: JavaAnnotationArgument? = null
internal set(value) {
if (field != null) {
throw AssertionError(
"Annotation method cannot have two default values: $this (old=$field, new=$value)"
)
}
field = value
}
}
class BinaryJavaConstructor(
@@ -5,13 +5,12 @@
package org.jetbrains.kotlin.resolve.jvm.multiplatform
import com.intellij.psi.PsiAnnotationMethod
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluatorImpl
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.JavaAnnotationArgumentImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
@@ -23,11 +22,10 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.builtIns
class JavaActualAnnotationArgumentExtractor : ExpectedActualDeclarationChecker.ActualAnnotationArgumentExtractor {
override fun extractActualValue(argument: PsiElement, expectedType: KotlinType): ConstantValue<*>? =
(argument as? PsiAnnotationMethod)
?.defaultValue
?.let { JavaAnnotationArgumentImpl.create(it, null) }
?.convert(expectedType)
override fun extractDefaultValue(parameter: ValueParameterDescriptor, expectedType: KotlinType): ConstantValue<*>? {
val element = (parameter.source as? JavaSourceElement)?.javaElement
return (element as? JavaMethod)?.annotationParameterDefaultValue?.convert(expectedType)
}
// This code is similar to LazyJavaAnnotationDescriptor.resolveAnnotationArgument, but cannot be reused until
// KClassValue/AnnotationValue are untied from descriptors/types, because here we do not have an instance of LazyJavaResolverContext.