[FIR IDE] LC Fix annotations and modifiers for class members

This commit is contained in:
Igor Yakovlev
2020-12-10 03:09:11 +03:00
parent 3019f439fb
commit 2e7866ca86
12 changed files with 105 additions and 68 deletions
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.name.FqName
@@ -117,8 +118,18 @@ class FirLightClassForFacade(
}
for (propertySymbol in propertySymbols) {
val forceStaticAndPropertyVisibility = propertySymbol is KtKotlinPropertySymbol && propertySymbol.isConst
|| propertySymbol.hasJvmFieldAnnotation()
val isLateInitWithPublicAccessors = if (propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit) {
val getterIsPublic = propertySymbol.getter?.toPsiVisibilityForMember(isTopLevel = true)
?.let { it == PsiModifier.PUBLIC } ?: true
val setterIsPublic = propertySymbol.setter?.toPsiVisibilityForMember(isTopLevel = true)
?.let { it == PsiModifier.PUBLIC } ?: true
getterIsPublic && setterIsPublic
} else false
val forceStaticAndPropertyVisibility = isLateInitWithPublicAccessors ||
(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isConst) ||
propertySymbol.hasJvmFieldAnnotation()
createField(
propertySymbol,
nameGenerator,
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.load.java.JvmAbi
internal open class FirLightClassForSymbol(
internal class FirLightClassForSymbol(
private val classOrObjectSymbol: KtClassOrObjectSymbol,
manager: PsiManager
) : FirLightClassForClassOrObjectSymbol(classOrObjectSymbol, manager) {
@@ -54,7 +54,7 @@ internal open class FirLightClassForSymbol(
private val _modifierList: PsiModifierList? by lazyPub {
val modifiers = mutableSetOf(classOrObjectSymbol.computeVisibility(isTopLevel))
val modifiers = mutableSetOf(classOrObjectSymbol.toPsiVisibilityForClass(isTopLevel))
classOrObjectSymbol.computeSimpleModality()?.run {
modifiers.add(this)
}
@@ -185,8 +185,9 @@ internal open class FirLightClassForSymbol(
for (propertySymbol in propertySymbols) {
val isJvmField = propertySymbol.hasJvmFieldAnnotation()
val isJvmStatic = propertySymbol.hasJvmStaticAnnotation()
val forceStatic = isObject && (propertySymbol is KtKotlinPropertySymbol && propertySymbol.isConst || isJvmStatic || isJvmField)
val takePropertyVisibility = !isCompanionObject && (isJvmField || (isObject && isJvmStatic))
val takePropertyVisibility = !isCompanionObject && (isJvmField || forceStatic)
createField(
declaration = propertySymbol,
@@ -29,7 +29,7 @@ internal abstract class FirLightInterfaceOrAnnotationClassSymbol(
val isTopLevel: Boolean = classOrObjectSymbol.symbolKind == KtSymbolKind.TOP_LEVEL
val modifiers = mutableSetOf(classOrObjectSymbol.computeVisibility(isTopLevel), PsiModifier.ABSTRACT)
val modifiers = mutableSetOf(classOrObjectSymbol.toPsiVisibilityForClass(isTopLevel), PsiModifier.ABSTRACT)
val annotations = classOrObjectSymbol.computeAnnotations(
parent = this@FirLightInterfaceOrAnnotationClassSymbol,
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.idea.asJava.*
import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithDeclarations
@@ -155,8 +154,14 @@ internal fun FirLightClassBase.createMethods(
}
is KtPropertySymbol -> {
if (declaration is KtKotlinPropertySymbol && declaration.isConst) continue
if (declaration.visibility == KtSymbolVisibility.PRIVATE &&
declaration.getter?.hasBody == false &&
declaration.setter?.hasBody == false
) continue
if (declaration.hasJvmFieldAnnotation()) continue
if (declaration.visibility == KtSymbolVisibility.PRIVATE) continue
fun KtPropertyAccessorSymbol.needToCreateAccessor(siteTarget: AnnotationUseSiteTarget): Boolean {
if (isInline) return false
@@ -217,8 +222,8 @@ internal fun FirLightClassBase.createField(
property.modality == KtCommonSymbolModality.ABSTRACT -> false
property.isHiddenOrSynthetic() -> false
property.isLateInit -> true
//IS PARAMETER -> true
property.getter == null && property.setter == null -> true
//TODO Fix it when KtFirConstructorValueParameterSymbol be ready
property.psi.let { it == null || it is KtParameter } -> true
property.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.FIELD) -> false
else -> property.hasBackingField
}
@@ -25,7 +25,7 @@ internal class FirLightFieldForObjectSymbol(
override fun getName(): String = name
private val _modifierList: PsiModifierList by lazyPub {
val modifiers = setOf(objectSymbol.computeVisibility(isTopLevel = false), PsiModifier.STATIC, PsiModifier.FINAL)
val modifiers = setOf(objectSymbol.toPsiVisibilityForMember(isTopLevel = false), PsiModifier.STATIC, PsiModifier.FINAL)
val notNullAnnotation = FirLightSimpleAnnotation("org.jetbrains.annotations.NotNull", this)
FirLightClassModifierList(this, modifiers, listOf(notNullAnnotation))
}
@@ -69,7 +69,7 @@ internal class FirLightFieldForPropertySymbol(
}
val visibility =
if (takePropertyVisibility) propertySymbol.computeVisibility(isTopLevel = false) else PsiModifier.PRIVATE
if (takePropertyVisibility) propertySymbol.toPsiVisibilityForMember(isTopLevel = false) else PsiModifier.PRIVATE
modifiers.add(visibility)
if (!suppressFinal) {
@@ -82,7 +82,7 @@ internal class FirLightFieldForPropertySymbol(
modifiers.add(PsiModifier.VOLATILE)
}
val nullability = if (visibility != PsiModifier.PRIVATE)
val nullability = if (visibility != PsiModifier.PRIVATE && !(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit))
propertySymbol.type.getTypeNullability(propertySymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
else NullabilityType.Unknown
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
import org.jetbrains.kotlin.idea.frontend.api.types.*
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.load.kotlin.TypeMappingModeInternals
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import java.text.StringCharacterIterator
@@ -120,6 +121,7 @@ private fun ConeKotlinType.asPsiType(
val correctedType = AnonymousTypesSubstitutor(session, state).substituteOrSelf(this)
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
//TODO Check thread safety
session.jvmTypeMapper.mapType(correctedType, mode, signatureWriter)
@@ -225,23 +227,20 @@ internal fun KtSymbolWithModality<KtCommonSymbolModality>.computeModalityForMeth
}
}
internal fun FirMemberDeclaration.computeVisibility(isTopLevel: Boolean): String {
return when (this.visibility) {
// Top-level private class has PACKAGE_LOCAL visibility in Java
// Nested private class has PRIVATE visibility
Visibilities.Private -> if (isTopLevel) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE
Visibilities.Protected -> PsiModifier.PROTECTED
else -> PsiModifier.PUBLIC
}
}
internal fun KtSymbolWithVisibility.computeVisibility(isTopLevel: Boolean): String =
visibility.toPsiVisibility(isTopLevel)
internal fun KtSymbolWithVisibility.toPsiVisibilityForMember(isTopLevel: Boolean): String =
visibility.toPsiVisibility(isTopLevel, forClass = false)
internal fun KtSymbolVisibility.toPsiVisibility(isTopLevel: Boolean): String = when (this) {
internal fun KtSymbolWithVisibility.toPsiVisibilityForClass(isTopLevel: Boolean): String =
visibility.toPsiVisibility(isTopLevel, forClass = true)
internal fun KtSymbolVisibility.toPsiVisibilityForMember(isTopLevel: Boolean): String =
toPsiVisibility(isTopLevel, forClass = false)
private fun KtSymbolVisibility.toPsiVisibility(isTopLevel: Boolean, forClass: Boolean): String = when (this) {
// Top-level private class has PACKAGE_LOCAL visibility in Java
// Nested private class has PRIVATE visibility
KtSymbolVisibility.PRIVATE -> if (isTopLevel) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE
KtSymbolVisibility.PRIVATE -> if (forClass && isTopLevel) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE
KtSymbolVisibility.PROTECTED -> PsiModifier.PROTECTED
else -> PsiModifier.PUBLIC
}
@@ -14,21 +14,19 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertyAccessorSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertyGetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.util.ifTrue
import org.jetbrains.kotlin.load.java.JvmAbi.getterName
import org.jetbrains.kotlin.load.java.JvmAbi.setterName
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtParameter
internal class FirLightAccessorMethodForSymbol(
private val propertyAccessorSymbol: KtPropertyAccessorSymbol,
containingPropertySymbol: KtPropertySymbol,
private val containingPropertySymbol: KtPropertySymbol,
lightMemberOrigin: LightMemberOrigin?,
containingClass: FirLightClassBase,
isTopLevel: Boolean,
private val isTopLevel: Boolean,
) : FirLightMethod(
lightMemberOrigin,
containingClass,
@@ -40,10 +38,12 @@ internal class FirLightAccessorMethodForSymbol(
if (isGetter) getterName(this) else setterName(this)
private val _name: String by lazyPub {
val defaultName = containingPropertySymbol.name.identifier.let {
if (containingClass.isAnnotationType) it else it.abiName()
propertyAccessorSymbol.getJvmNameFromAnnotation() ?: run {
val defaultName = containingPropertySymbol.name.identifier.let {
if (containingClass.isAnnotationType) it else it.abiName()
}
containingPropertySymbol.computeJvmMethodName(defaultName, containingClass, accessorSite)
}
containingPropertySymbol.computeJvmMethodName(defaultName, containingClass, accessorSite)
}
override fun getName(): String = _name
@@ -62,20 +62,34 @@ internal class FirLightAccessorMethodForSymbol(
if (propertyAccessorSymbol is KtPropertyGetterSymbol) AnnotationUseSiteTarget.PROPERTY_GETTER
else AnnotationUseSiteTarget.PROPERTY_SETTER
private val _annotations: List<PsiAnnotation> by lazyPub {
//TODO Fix it when KtFirConstructorValueParameterSymbol be ready
private val isParameter: Boolean get() = containingPropertySymbol.psi.let { it == null || it is KtParameter }
val nullabilityType = if (isGetter) containingPropertySymbol.type
private fun computeAnnotations(isPrivate: Boolean): List<PsiAnnotation> {
val nullabilityApplicable = isGetter &&
!isPrivate &&
!(isParameter && (containingClass.isAnnotationType || containingClass.isEnum))
val nullabilityType = if (nullabilityApplicable) containingPropertySymbol.type
.getTypeNullability(containingPropertySymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
else NullabilityType.Unknown
containingPropertySymbol.computeAnnotations(
val annotationsFromProperty = containingPropertySymbol.computeAnnotations(
parent = this,
nullability = nullabilityType,
annotationUseSiteTarget = accessorSite,
)
val annotationsFromAccessor = propertyAccessorSymbol.computeAnnotations(
parent = this,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
return annotationsFromProperty + annotationsFromAccessor
}
private val _modifiers: Set<String> by lazyPub {
private fun computeModifiers(): Set<String> {
val isOverrideMethod = propertyAccessorSymbol.isOverride || containingPropertySymbol.isOverride
val isInterfaceMethod = containingClass.isInterface
@@ -90,8 +104,8 @@ internal class FirLightAccessorMethodForSymbol(
val visibility = isOverrideMethod.ifTrue {
(containingClass as? FirLightClassForSymbol)
?.tryGetEffectiveVisibility(containingPropertySymbol)
?.toPsiVisibility(isTopLevel)
} ?: propertyAccessorSymbol.computeVisibility(isTopLevel)
?.toPsiVisibilityForMember(isTopLevel)
} ?: propertyAccessorSymbol.toPsiVisibilityForMember(isTopLevel)
modifiers.add(visibility)
if (containingPropertySymbol.hasJvmStaticAnnotation(accessorSite)) {
@@ -102,11 +116,13 @@ internal class FirLightAccessorMethodForSymbol(
modifiers.add(PsiModifier.ABSTRACT)
}
modifiers
return modifiers
}
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, _modifiers, _annotations)
val modifiers = computeModifiers()
val annotations = computeAnnotations(modifiers.contains(PsiModifier.PRIVATE))
FirLightClassModifierList(this, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList = _modifierList
@@ -42,7 +42,7 @@ internal class FirLightConstructorForSymbol(
override fun isDeprecated(): Boolean = _isDeprecated
private val _modifiers: Set<String> by lazyPub {
setOf(constructorSymbol.computeVisibility(isTopLevel = false))
setOf(constructorSymbol.toPsiVisibilityForMember(isTopLevel = false))
}
private val _modifierList: PsiModifierList by lazyPub {
@@ -21,9 +21,9 @@ internal class FirLightSimpleMethodForSymbol(
lightMemberOrigin: LightMemberOrigin?,
containingClass: FirLightClassBase,
methodIndex: Int,
isTopLevel: Boolean,
private val isTopLevel: Boolean,
argumentsSkipMask: BitSet? = null,
suppressStatic: Boolean = false
private val suppressStatic: Boolean = false
) : FirLightMethodForSymbol(
functionSymbol = functionSymbol,
lightMemberOrigin = lightMemberOrigin,
@@ -55,35 +55,24 @@ internal class FirLightSimpleMethodForSymbol(
override fun getTypeParameters(): Array<PsiTypeParameter> =
_typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
private val _annotations: List<PsiAnnotation> by lazyPub {
val needUnknownNullability =
isVoidReturnType || (_visibility == PsiModifier.PRIVATE)
val nullability = if (needUnknownNullability)
private fun computeAnnotations(isPrivate: Boolean): List<PsiAnnotation> {
val nullability = if (isVoidReturnType || isPrivate)
NullabilityType.Unknown
else functionSymbol.type.getTypeNullability(
context = functionSymbol,
phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE
)
functionSymbol.computeAnnotations(
return functionSymbol.computeAnnotations(
parent = this,
nullability = nullability,
annotationUseSiteTarget = null,
)
}
private val _visibility: String by lazyPub {
functionSymbol.isOverride.ifTrue {
(containingClass as? FirLightClassForSymbol)
?.tryGetEffectiveVisibility(functionSymbol)
?.toPsiVisibility(isTopLevel)
} ?: functionSymbol.computeVisibility(isTopLevel = isTopLevel)
}
private fun computeModifiers(): Set<String> {
private val _modifiers: Set<String> by lazyPub {
if (functionSymbol.hasInlineOnlyAnnotation()) return@lazyPub setOf(PsiModifier.FINAL, PsiModifier.PRIVATE)
if (functionSymbol.hasInlineOnlyAnnotation()) return setOf(PsiModifier.FINAL, PsiModifier.PRIVATE)
val finalModifier = kotlinOrigin?.hasModifier(KtTokens.FINAL_KEYWORD) == true
@@ -95,7 +84,13 @@ internal class FirLightSimpleMethodForSymbol(
result = modifiers
)
modifiers.add(_visibility)
val visibility: String = functionSymbol.isOverride.ifTrue {
(containingClass as? FirLightClassForSymbol)
?.tryGetEffectiveVisibility(functionSymbol)
?.toPsiVisibilityForMember(isTopLevel)
} ?: functionSymbol.toPsiVisibilityForMember(isTopLevel = isTopLevel)
modifiers.add(visibility)
if (!suppressStatic && functionSymbol.hasJvmStaticAnnotation()) {
modifiers.add(PsiModifier.STATIC)
@@ -107,7 +102,7 @@ internal class FirLightSimpleMethodForSymbol(
modifiers.add(PsiModifier.SYNCHRONIZED)
}
modifiers
return modifiers
}
private val _isDeprecated: Boolean by lazyPub {
@@ -117,7 +112,9 @@ internal class FirLightSimpleMethodForSymbol(
override fun isDeprecated(): Boolean = _isDeprecated
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, _modifiers, _annotations)
val modifiers = computeModifiers()
val annotations = computeAnnotations(modifiers.contains(PsiModifier.PRIVATE))
FirLightClassModifierList(this, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList = _modifierList
@@ -59,7 +59,7 @@ internal class FirLightParameterForReceiver private constructor(
override fun getName(): String = _name
override fun isVarArgs() = false
override fun hasModifierProperty(name: String): Boolean = false //TODO()
override fun hasModifierProperty(name: String): Boolean = false
override val kotlinOrigin: KtParameter? = null
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.util.ifTrue
@@ -34,11 +35,18 @@ internal class FirLightParameterForSymbol(
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
}
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } &&
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
val nullabilityType = if (nullabilityApplicable)
parameterSymbol.type.getTypeNullability(parameterSymbol, FirResolvePhase.TYPES)
else NullabilityType.Unknown
parameterSymbol.computeAnnotations(
parent = this,
nullability = parameterSymbol.type.getTypeNullability(parameterSymbol, FirResolvePhase.TYPES),
nullability = nullabilityType,
annotationUseSiteTarget = annotationSite,
includeAnnotationsWithoutSite = false
includeAnnotationsWithoutSite = true
)
}