UL properties supports JvmSynthetic annotation for get: and set: modifiers
(+small refactoring) Fixed #KT-34973
This commit is contained in:
+46
-44
@@ -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
|
||||||
|
}
|
||||||
+5
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user