Add UL-annotations support

This commit is contained in:
Igor Yakovlev
2019-06-24 18:25:36 +03:00
parent 4fed624942
commit afe784e79e
5 changed files with 83 additions and 27 deletions
@@ -14,7 +14,6 @@ import com.intellij.psi.impl.light.LightMethodBuilder
import org.jetbrains.kotlin.asJava.builder.LightClassData
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
import org.jetbrains.kotlin.asJava.elements.KtUltraLightModifierList
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
@@ -246,7 +245,13 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
for (parameter in propertyParameters()) {
result.addAll(
membersBuilder.propertyAccessors(parameter, parameter.isMutable, forceStatic = false, onlyJvmStatic = false)
membersBuilder.propertyAccessors(
parameter,
parameter.isMutable,
forceStatic = false,
onlyJvmStatic = false,
createAsAnnotationMethod = isAnnotationType
)
)
}
@@ -257,8 +262,16 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
this.classOrObject.companionObjects.firstOrNull()?.let { companion ->
for (declaration in companion.declarations.filterNot { isHiddenByDeprecation(it) }) {
when (declaration) {
is KtNamedFunction -> if (isJvmStatic(declaration)) result.addAll(membersBuilder.createMethods(declaration, true))
is KtProperty -> result.addAll(membersBuilder.propertyAccessors(declaration, declaration.isVar, false, true))
is KtNamedFunction ->
if (isJvmStatic(declaration)) result.addAll(membersBuilder.createMethods(declaration,forceStatic = true))
is KtProperty -> result.addAll(
membersBuilder.propertyAccessors(
declaration,
declaration.isVar,
forceStatic = false,
onlyJvmStatic = true
)
)
}
}
}
@@ -5,8 +5,7 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiType
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.impl.light.LightModifierList
import com.intellij.psi.impl.light.LightParameterListBuilder
@@ -14,6 +13,7 @@ import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.convertToLightAnnotationMemberValue
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
@@ -132,6 +132,19 @@ internal class UltraLightMembersCreator(
return result
}
internal class KtUltraLightAnnotationMethod(
psiMethod: KtLightMethod,
expression: KtExpression
) : KtLightMethod by psiMethod,
PsiAnnotationMethod {
private val value by lazyPub {
convertToLightAnnotationMemberValue(psiMethod, expression)
}
override fun getDefaultValue(): PsiAnnotationMemberValue? = value
}
private fun asJavaMethod(
ktFunction: KtFunction,
forceStatic: Boolean,
@@ -146,7 +159,7 @@ internal class UltraLightMembersCreator(
val method = lightMethod(name.orEmpty(), ktFunction, forceStatic, forcePrivate)
val wrapper = KtUltraLightMethodForSourceDeclaration(method, ktFunction, support, containingClass)
addReceiverParameter(ktFunction, wrapper)
addReceiverParameter(ktFunction, wrapper, method)
var remainingNumberOfDefaultParametersToAdd =
if (numberOfDefaultParametersToAdd >= 0)
@@ -180,9 +193,14 @@ internal class UltraLightMembersCreator(
return wrapper
}
private fun addReceiverParameter(callable: KtCallableDeclaration, method: KtUltraLightMethod) {
private fun addReceiverParameter(callable: KtCallableDeclaration, wrapper: KtUltraLightMethod, associatedBuilder: LightMethodBuilder) {
if (callable.receiverTypeReference == null) return
method.delegate.addParameter(KtUltraLightReceiverParameter(callable, support, method))
require(wrapper.delegate == associatedBuilder) {
"Invalid use. Wrapper does not wrap an associated method builder."
}
associatedBuilder.addParameter(KtUltraLightReceiverParameter(callable, support, wrapper))
}
private fun methodReturnType(ktDeclaration: KtDeclaration, wrapper: KtUltraLightMethod, isSuspendFunction: Boolean): PsiType {
@@ -250,7 +268,9 @@ internal class UltraLightMembersCreator(
return when (name) {
PsiModifier.FINAL -> !containingClass.isInterface && outer !is KtConstructor<*> && isFinal(outer)
PsiModifier.ABSTRACT -> containingClass.isInterface || outer.hasModifier(KtTokens.ABSTRACT_KEYWORD)
PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outer.isJvmStatic(support) || declaration.isJvmStatic(support))
PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outer.isJvmStatic(support) || declaration.isJvmStatic(
support
))
PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME)
PsiModifier.SYNCHRONIZED -> declaration is KtFunction && declaration.hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME)
else -> false
@@ -336,7 +356,8 @@ internal class UltraLightMembersCreator(
declaration: KtCallableDeclaration,
mutable: Boolean,
forceStatic: Boolean,
onlyJvmStatic: Boolean
onlyJvmStatic: Boolean,
createAsAnnotationMethod: Boolean = false
): List<KtLightMethod> {
val propertyName = declaration.name ?: return emptyList()
@@ -373,16 +394,24 @@ internal class UltraLightMembersCreator(
auxiliaryOriginalElement = auxiliaryOrigin
)
val getterName = computeMethodName(auxiliaryOrigin, JvmAbi.getterName(propertyName), MethodType.GETTER)
val getterPrototype = lightMethod(getterName, auxiliaryOrigin, onlyJvmStatic || forceStatic)
val defaultGetterName = if (createAsAnnotationMethod) propertyName else JvmAbi.getterName(propertyName)
val getterName = computeMethodName(auxiliaryOrigin, defaultGetterName, MethodType.GETTER)
val getterPrototype = lightMethod(getterName, auxiliaryOrigin, forceStatic = onlyJvmStatic || forceStatic)
val getterWrapper = KtUltraLightMethodForSourceDeclaration(getterPrototype, lightMemberOrigin, support, containingClass)
val getterType: PsiType by lazyPub { methodReturnType(declaration, getterWrapper, isSuspendFunction = false) }
getterPrototype.setMethodReturnType { getterType }
addReceiverParameter(declaration, getterWrapper)
result.add(getterWrapper)
addReceiverParameter(declaration, getterWrapper, getterPrototype)
val defaultExpression = if (createAsAnnotationMethod && declaration is KtParameter) declaration.defaultValue else null
val getterMethodResult = defaultExpression?.let {
KtUltraLightAnnotationMethod(getterWrapper, it)
} ?: getterWrapper
result.add(getterMethodResult)
}
if (mutable && needsAccessor(ktSetter)) {
if (!createAsAnnotationMethod && mutable && needsAccessor(ktSetter)) {
val auxiliaryOrigin = ktSetter ?: declaration
val lightMemberOrigin = LightMemberOriginForDeclaration(
originalElement = declaration,
@@ -390,11 +419,13 @@ internal class UltraLightMembersCreator(
auxiliaryOriginalElement = auxiliaryOrigin
)
val setterName = computeMethodName(auxiliaryOrigin, JvmAbi.setterName(propertyName), MethodType.SETTER)
val setterPrototype = lightMethod(setterName, auxiliaryOrigin, onlyJvmStatic || forceStatic)
val setterPrototype = lightMethod(setterName, auxiliaryOrigin, forceStatic = onlyJvmStatic || forceStatic)
.setMethodReturnType(PsiType.VOID)
val setterWrapper = KtUltraLightMethodForSourceDeclaration(setterPrototype, lightMemberOrigin, support, containingClass)
addReceiverParameter(declaration, setterWrapper)
addReceiverParameter(declaration, setterWrapper, setterPrototype)
val setterParameter = ktSetter?.parameter
setterPrototype.addParameter(
if (setterParameter != null)
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.types.KotlinType
internal abstract class KtUltraLightMethod(
internal val delegate: LightMethodBuilder,
internal val delegate: PsiMethod,
lightMemberOrigin: LightMemberOrigin?,
protected val support: KtUltraLightSupport,
containingClass: KtLightClass
@@ -101,7 +101,7 @@ internal abstract class KtUltraLightMethod(
}
internal class KtUltraLightMethodForSourceDeclaration(
delegate: LightMethodBuilder,
delegate: PsiMethod,
lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport,
containingClass: KtLightClass
@@ -112,7 +112,7 @@ internal class KtUltraLightMethodForSourceDeclaration(
containingClass
) {
constructor(
delegate: LightMethodBuilder,
delegate: PsiMethod,
declaration: KtDeclaration,
support: KtUltraLightSupport,
containingClass: KtLightClass
@@ -67,16 +67,24 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
override fun toString() = "Light modifier list of $owner"
protected open fun nonSourceAnnotations(sourceAnnotationNames: Set<String>): List<KtLightAbstractAnnotation> {
val annotations = parent.clsDelegate.modifierList?.annotations
if (annotations.isNullOrEmpty()) return emptyList()
return annotations
.filter { it.qualifiedName !in sourceAnnotationNames }
.map { KtLightNonSourceAnnotation(this, it) }
}
private fun computeAnnotations(): List<KtLightAbstractAnnotation> {
val annotationsForEntries =
owner.givenAnnotations ?: lightAnnotationsForEntries(this)
val modifierListOwner = parent
if (modifierListOwner is KtLightClassForSourceDeclaration && modifierListOwner.isAnnotationType) {
val sourceAnnotationNames = annotationsForEntries.mapTo(mutableSetOf()) { it.qualifiedName }
val specialAnnotationsOnAnnotationClass = modifierListOwner.clsDelegate.modifierList?.annotations.orEmpty().filter {
it.qualifiedName !in sourceAnnotationNames
}.map { KtLightNonSourceAnnotation(this, it) }
return annotationsForEntries + specialAnnotationsOnAnnotationClass
val sourceAnnotationNames = annotationsForEntries.mapNotNullTo(mutableSetOf()) { it.qualifiedName }
return annotationsForEntries + nonSourceAnnotations(sourceAnnotationNames)
}
if ((modifierListOwner is KtLightMember<*> && modifierListOwner !is KtLightFieldImpl.KtLightEnumConstant)
|| modifierListOwner is LightParameter
@@ -114,6 +122,10 @@ abstract class KtUltraLightModifierList<out T : KtLightElement<KtModifierListOwn
override fun checkSetModifierProperty(name: String, value: Boolean): Unit = throwInvalidOperation()
override fun addAnnotation(qualifiedName: String): PsiAnnotation = throwInvalidOperation()
override fun nonSourceAnnotations(sourceAnnotationNames: Set<String>): List<KtLightAbstractAnnotation> {
return emptyList()
}
}
open class KtLightSimpleModifierList(
@@ -148,7 +148,7 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
}
private fun findTooComplexDeclaration(declaration: KtDeclaration): PsiElement? {
if (declaration.hasExpectModifier() || declaration.hasModifier(KtTokens.ANNOTATION_KEYWORD)) {
if (declaration.hasExpectModifier()) {
return declaration
}