UL properties supports JvmSynthetic annotation for get: and set: modifiers

(+small refactoring)
Fixed #KT-34973
This commit is contained in:
Igor Yakovlev
2020-03-16 14:50:17 +03:00
parent 0e26194a27
commit af1e3fb10d
4 changed files with 69 additions and 44 deletions
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.asJava.elements.convertToLightAnnotationMemberValue
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
@@ -32,12 +31,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
import org.jetbrains.kotlin.resolve.inline.isInlineOnly import org.jetbrains.kotlin.resolve.inline.isInlineOnly
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_OVERLOADS_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.*
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.util.isOrdinaryClass
internal class UltraLightMembersCreator( internal class UltraLightMembersCreator(
private val containingClass: KtLightClass, private val containingClass: KtLightClass,
@@ -72,8 +67,8 @@ internal class UltraLightMembersCreator(
val fieldName = generateUniqueFieldName((variable.name ?: "") + (if (hasDelegate) "\$delegate" else ""), usedPropertyNames) val fieldName = generateUniqueFieldName((variable.name ?: "") + (if (hasDelegate) "\$delegate" else ""), usedPropertyNames)
val visibility = when { val visibility = when {
variable.hasModifier(KtTokens.PRIVATE_KEYWORD) -> PsiModifier.PRIVATE variable.hasModifier(PRIVATE_KEYWORD) -> PsiModifier.PRIVATE
variable.hasModifier(KtTokens.LATEINIT_KEYWORD) || variable.isConstOrJvmField() -> { variable.hasModifier(LATEINIT_KEYWORD) || variable.isConstOrJvmField() -> {
val declaration = property?.setter ?: variable val declaration = property?.setter ?: variable
declaration.simpleVisibility() declaration.simpleVisibility()
} }
@@ -87,7 +82,7 @@ internal class UltraLightMembersCreator(
else -> error("Unexpected type of variable: ${variable::class.java}") else -> error("Unexpected type of variable: ${variable::class.java}")
} }
if (!isMutable || variable.hasModifier(KtTokens.CONST_KEYWORD) || hasDelegate) { if (!isMutable || variable.hasModifier(CONST_KEYWORD) || hasDelegate) {
modifiers.add(PsiModifier.FINAL) modifiers.add(PsiModifier.FINAL)
} }
@@ -99,8 +94,8 @@ internal class UltraLightMembersCreator(
} }
private fun hasBackingField(property: KtProperty): Boolean { private fun hasBackingField(property: KtProperty): Boolean {
if (property.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return false if (property.hasModifier(ABSTRACT_KEYWORD)) return false
if (property.hasModifier(KtTokens.LATEINIT_KEYWORD) || property.accessors.isEmpty()) return true if (property.hasModifier(LATEINIT_KEYWORD) || property.accessors.isEmpty()) return true
val context = LightClassGenerationSupport.getInstance(containingClass.project).analyze(property) val context = LightClassGenerationSupport.getInstance(containingClass.project).analyze(property)
val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property) val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property)
@@ -282,13 +277,13 @@ internal class UltraLightMembersCreator(
if (forcePrivate || declaration.isPrivate() || accessedProperty?.isPrivate() == true) { if (forcePrivate || declaration.isPrivate() || accessedProperty?.isPrivate() == true) {
return name == PsiModifier.PRIVATE return name == PsiModifier.PRIVATE
} }
if (declaration.hasModifier(KtTokens.PROTECTED_KEYWORD) || accessedProperty if (declaration.hasModifier(PROTECTED_KEYWORD) || accessedProperty
?.hasModifier(KtTokens.PROTECTED_KEYWORD) == true ?.hasModifier(PROTECTED_KEYWORD) == true
) { ) {
return name == PsiModifier.PROTECTED return name == PsiModifier.PROTECTED
} }
if (outerDeclaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { if (outerDeclaration.hasModifier(OVERRIDE_KEYWORD)) {
when ((outerDeclaration.resolve() as? CallableDescriptor)?.visibility) { when ((outerDeclaration.resolve() as? CallableDescriptor)?.visibility) {
Visibilities.PUBLIC -> return name == PsiModifier.PUBLIC Visibilities.PUBLIC -> return name == PsiModifier.PUBLIC
Visibilities.PRIVATE -> return name == PsiModifier.PRIVATE Visibilities.PRIVATE -> return name == PsiModifier.PRIVATE
@@ -301,7 +296,7 @@ internal class UltraLightMembersCreator(
return when (name) { return when (name) {
PsiModifier.FINAL -> !containingClass.isInterface && outerDeclaration !is KtConstructor<*> && isFinal(outerDeclaration) PsiModifier.FINAL -> !containingClass.isInterface && outerDeclaration !is KtConstructor<*> && isFinal(outerDeclaration)
PsiModifier.ABSTRACT -> containingClass.isInterface || outerDeclaration.hasModifier(KtTokens.ABSTRACT_KEYWORD) PsiModifier.ABSTRACT -> containingClass.isInterface || outerDeclaration.hasModifier(ABSTRACT_KEYWORD)
PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outerDeclaration.isJvmStatic(support) || declaration PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outerDeclaration.isJvmStatic(support) || declaration
.isJvmStatic(support)) .isJvmStatic(support))
PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME) PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME)
@@ -312,10 +307,10 @@ internal class UltraLightMembersCreator(
} }
private fun KtDeclaration.isPrivate() = private fun KtDeclaration.isPrivate() =
hasModifier(KtTokens.PRIVATE_KEYWORD) || this is KtConstructor<*> && containingClassIsSealed || isInlineOnly() hasModifier(PRIVATE_KEYWORD) || this is KtConstructor<*> && containingClassIsSealed || isInlineOnly()
private fun KtDeclaration.isInlineOnly(): Boolean { private fun KtDeclaration.isInlineOnly(): Boolean {
if (this !is KtCallableDeclaration || !hasModifier(KtTokens.INLINE_KEYWORD)) return false if (this !is KtCallableDeclaration || !hasModifier(INLINE_KEYWORD)) return false
if (annotationEntries.isEmpty()) return false if (annotationEntries.isEmpty()) return false
val descriptor = resolve() as? CallableMemberDescriptor ?: return false val descriptor = resolve() as? CallableMemberDescriptor ?: return false
@@ -378,9 +373,9 @@ internal class UltraLightMembersCreator(
} }
private tailrec fun isInternalNonPublishedApi(declaration: KtDeclaration): Boolean { private tailrec fun isInternalNonPublishedApi(declaration: KtDeclaration): Boolean {
if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || if (declaration.hasModifier(PRIVATE_KEYWORD) ||
declaration.hasModifier(KtTokens.PROTECTED_KEYWORD) || declaration.hasModifier(PROTECTED_KEYWORD) ||
declaration.hasModifier(KtTokens.PUBLIC_KEYWORD) declaration.hasModifier(PUBLIC_KEYWORD)
) { ) {
return false return false
} }
@@ -394,12 +389,12 @@ internal class UltraLightMembersCreator(
private fun KtAnnotated.hasAnnotation(name: FqName) = support.findAnnotation(this, name) != null private fun KtAnnotated.hasAnnotation(name: FqName) = support.findAnnotation(this, name) != null
private fun isInternal(f: KtDeclaration): Boolean { private fun isInternal(f: KtDeclaration): Boolean {
if (f.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { if (f.hasModifier(OVERRIDE_KEYWORD)) {
val desc = f.resolve() val desc = f.resolve()
return desc is CallableDescriptor && return desc is CallableDescriptor &&
desc.visibility.effectiveVisibility(desc, false) == EffectiveVisibility.Internal desc.visibility.effectiveVisibility(desc, false) == EffectiveVisibility.Internal
} }
return f.hasModifier(KtTokens.INTERNAL_KEYWORD) return f.hasModifier(INTERNAL_KEYWORD)
} }
fun propertyAccessors( fun propertyAccessors(
@@ -419,29 +414,36 @@ internal class UltraLightMembersCreator(
val ktGetter = (declaration as? KtProperty)?.getter val ktGetter = (declaration as? KtProperty)?.getter
val ktSetter = (declaration as? KtProperty)?.setter val ktSetter = (declaration as? KtProperty)?.setter
val isPrivate = !forceStatic && declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) val isPrivate = !forceStatic && declaration.hasModifier(PRIVATE_KEYWORD)
if (isPrivate && declaration !is KtProperty) return emptyList() if (isPrivate && declaration !is KtProperty) return emptyList()
fun needsAccessor(accessor: KtPropertyAccessor?): Boolean { fun needsAccessor(accessor: KtPropertyAccessor?, type: MethodType): Boolean {
if (!onlyJvmStatic || declaration.isJvmStatic(support) || accessor != null && accessor.isJvmStatic(support)) {
if (declaration is KtProperty && declaration.hasDelegate()) { if (onlyJvmStatic && !declaration.isJvmStatic(support) && !(accessor != null && accessor.isJvmStatic(support)))
return true return false
}
if (accessor?.hasModifier(KtTokens.PRIVATE_KEYWORD) == true || accessor if (declaration is KtProperty && declaration.hasDelegate())
?.hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME) == true return true
) {
return false if (accessor?.hasModifier(PRIVATE_KEYWORD) == true || accessor?.hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME) == true)
} return false
if (!isPrivate || accessor?.hasBody() == true) {
return true if (isPrivate && accessor?.hasBody() != true) return false
}
if (!declaration.hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME)) return true
val annotated = (declaration.resolve() as? PropertyDescriptor) ?: return false
val propertyAnnotated = when (type) {
MethodType.GETTER -> annotated.getter
MethodType.SETTER -> annotated.setter
else -> throw NotImplementedError()
} }
return false return propertyAnnotated?.hasJvmSyntheticAnnotation() != true
} }
val result = arrayListOf<KtLightMethod>() val result = arrayListOf<KtLightMethod>()
if (needsAccessor(ktGetter)) { if (needsAccessor(ktGetter, MethodType.GETTER)) {
val auxiliaryOrigin = ktGetter ?: declaration val auxiliaryOrigin = ktGetter ?: declaration
val lightMemberOrigin = LightMemberOriginForDeclaration( val lightMemberOrigin = LightMemberOriginForDeclaration(
originalElement = declaration, originalElement = declaration,
@@ -473,7 +475,7 @@ internal class UltraLightMembersCreator(
result.add(getterMethodResult) result.add(getterMethodResult)
} }
if (!createAsAnnotationMethod && mutable && needsAccessor(ktSetter)) { if (!createAsAnnotationMethod && mutable && needsAccessor(ktSetter, MethodType.SETTER)) {
val auxiliaryOrigin = ktSetter ?: declaration val auxiliaryOrigin = ktSetter ?: declaration
val lightMemberOrigin = LightMemberOriginForDeclaration( val lightMemberOrigin = LightMemberOriginForDeclaration(
originalElement = declaration, originalElement = declaration,
@@ -521,15 +523,15 @@ internal class UltraLightMembersCreator(
typeParameters.any { it.hasModifier(REIFIED_KEYWORD) } typeParameters.any { it.hasModifier(REIFIED_KEYWORD) }
private fun KtCallableDeclaration.isConstOrJvmField() = private fun KtCallableDeclaration.isConstOrJvmField() =
hasModifier(KtTokens.CONST_KEYWORD) || isJvmField() hasModifier(CONST_KEYWORD) || isJvmField()
private fun KtCallableDeclaration.isJvmField() = hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME) private fun KtCallableDeclaration.isJvmField() = hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME)
private fun isFinal(declaration: KtDeclaration): Boolean { private fun isFinal(declaration: KtDeclaration): Boolean {
if (declaration.hasModifier(KtTokens.FINAL_KEYWORD)) return true if (declaration.hasModifier(FINAL_KEYWORD)) return true
return declaration !is KtPropertyAccessor && return declaration !is KtPropertyAccessor &&
!declaration.hasModifier(KtTokens.OPEN_KEYWORD) && !declaration.hasModifier(OPEN_KEYWORD) &&
!declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD) && !declaration.hasModifier(OVERRIDE_KEYWORD) &&
!declaration.hasModifier(KtTokens.ABSTRACT_KEYWORD) !declaration.hasModifier(ABSTRACT_KEYWORD)
} }
} }
@@ -0,0 +1,9 @@
public final class X /* X*/ {
@null()
public X();
public final int getW();
public final void setV(int);
}
@@ -0,0 +1,9 @@
class X {
@get:JvmSynthetic
var v = 1
@set:JvmSynthetic
var w = 1
}
@@ -138,6 +138,11 @@ public class UltraLightClassLoadingTestGenerated extends AbstractUltraLightClass
runTest("compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt"); runTest("compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt");
} }
@TestMetadata("jvmSyntheticForAccessors.kt")
public void testJvmSyntheticForAccessors() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/jvmSyntheticForAccessors.kt");
}
@TestMetadata("jvmWildcardAnnotations.kt") @TestMetadata("jvmWildcardAnnotations.kt")
public void testJvmWildcardAnnotations() throws Exception { public void testJvmWildcardAnnotations() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/jvmWildcardAnnotations.kt"); runTest("compiler/testData/asJava/ultraLightClasses/jvmWildcardAnnotations.kt");