From 2a8f78339335b3a24be4c792bbb3464f6c314d03 Mon Sep 17 00:00:00 2001 From: Igor Yakovlev Date: Tue, 17 Nov 2020 15:00:02 +0300 Subject: [PATCH] [FIR IDE] HL API Better support of nullability and modality --- .../org/jetbrains/kotlin/fir/Primitives.kt | 2 +- .../lightClasses/DeprecatedEnumEntry.kt | 4 ++- .../compilationErrors/EnumNameOverride.kt | 2 ++ .../ImplementingCharSequenceAndNumber.kt | 4 ++- .../ideRegression/OverridingInternal.kt | 3 +- .../nullabilityAnnotations/Primitives.kt | 4 ++- .../asJava/ultraLightClasses/inheritance.kt | 2 ++ .../asJava/ultraLightFacades/jvmField.kt | 2 ++ .../api/symbols/KtPropertyAccessorSymbol.kt | 1 + .../api/symbols/KtVariableLikeSymbol.kt | 2 ++ .../asJava/annotations/annotationsUtils.kt | 8 +++-- .../asJava/classes/FirLightClassForFacade.kt | 12 +++++-- .../idea/asJava/classes/firLightClassUtils.kt | 32 ++++++++++++------- .../fields/FirLightFieldForPropertySymbol.kt | 8 +++-- .../FirLightAccessorMethodForSymbol.kt | 6 ++-- .../idea/asJava/methods/FirLightMethod.kt | 11 +++++-- .../methods/FirLightSimpleMethodForSymbol.kt | 27 +++++++--------- .../parameters/FirLightParameterForSymbol.kt | 14 +++++--- .../fir/symbols/KtFirPropertyGetterSymbol.kt | 1 + .../fir/symbols/KtFirPropertySetterSymbol.kt | 2 ++ .../api/fir/symbols/KtFirPropertySymbol.kt | 2 ++ .../resolve/AbstractIdeLightClassTest.kt | 22 ++++++------- 22 files changed, 115 insertions(+), 56 deletions(-) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Primitives.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Primitives.kt index 0f32bf94638..50223d28e3e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Primitives.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Primitives.kt @@ -34,7 +34,7 @@ fun ConeClassLikeType.isByte(): Boolean = lookupTag.classId == StandardClassIds. fun ConeClassLikeType.isBoolean(): Boolean = lookupTag.classId == StandardClassIds.Boolean fun ConeClassLikeType.isChar(): Boolean = lookupTag.classId == StandardClassIds.Char -fun ConeClassLikeType.isPrimitiveType(): Boolean = isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() +fun ConeClassLikeType.isPrimitiveType(): Boolean = isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() || isChar() fun ConeClassLikeType.isPrimitiveNumberType(): Boolean = lookupTag.classId in PRIMITIVE_NUMBER_CLASS_IDS fun ConeClassLikeType.isPrimitiveUnsignedNumberType(): Boolean = lookupTag.classId in PRIMITIVE_UNSIGNED_NUMBER_CLASS_IDS fun ConeClassLikeType.isPrimitiveNumberOrUnsignedNumberType(): Boolean = isPrimitiveNumberType() || isPrimitiveUnsignedNumberType() diff --git a/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt index 0accee6b2f8..66da0e415b5 100644 --- a/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt +++ b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt @@ -9,4 +9,6 @@ enum class E { Entry2, @Deprecated("b") Entry3 -} \ No newline at end of file +} + +// FIR_COMPARISON \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt b/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt index 150fc7a0abe..ed136384d39 100644 --- a/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt +++ b/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt @@ -9,3 +9,5 @@ interface Bar : Foo { } enum class EnumNameOverride : Bar + +// FIR_COMPARISON \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt b/compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt index d19fc5fda77..4598b3afbf0 100644 --- a/compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt +++ b/compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt @@ -44,4 +44,6 @@ class Container { TODO("not implemented") } } -} \ No newline at end of file +} + +// FIR_COMPARISON \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.kt b/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.kt index cea2a77e24a..cbd66f203b5 100644 --- a/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.kt +++ b/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.kt @@ -13,4 +13,5 @@ class C : A(), I { override fun if() = 5 } -// LAZINESS:NoLaziness \ No newline at end of file +// LAZINESS:NoLaziness +// FIR_COMPARISON \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt index b00fda10d7f..b9be700e09e 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt @@ -20,4 +20,6 @@ interface Primitives { val long: Long val float: Float val double: Double -} \ No newline at end of file +} + +// FIR_COMPARISON \ No newline at end of file diff --git a/compiler/testData/asJava/ultraLightClasses/inheritance.kt b/compiler/testData/asJava/ultraLightClasses/inheritance.kt index dba936c8021..3b71ba7d286 100644 --- a/compiler/testData/asJava/ultraLightClasses/inheritance.kt +++ b/compiler/testData/asJava/ultraLightClasses/inheritance.kt @@ -29,3 +29,5 @@ private class Private { override val overridesNothing: Boolean get() = false } + +// FIR_COMPARISON \ No newline at end of file diff --git a/compiler/testData/asJava/ultraLightFacades/jvmField.kt b/compiler/testData/asJava/ultraLightFacades/jvmField.kt index b9fdefe6a29..451977c84d7 100644 --- a/compiler/testData/asJava/ultraLightFacades/jvmField.kt +++ b/compiler/testData/asJava/ultraLightFacades/jvmField.kt @@ -2,3 +2,5 @@ val a: Collection<*> = emptyList() @JvmField var b: Int = 1 + +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPropertyAccessorSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPropertyAccessorSymbol.kt index e902aaf6b0b..f3c0dbfcf73 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPropertyAccessorSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPropertyAccessorSymbol.kt @@ -14,6 +14,7 @@ sealed class KtPropertyAccessorSymbol : KtCallableSymbol(), abstract val isDefault: Boolean abstract val isInline: Boolean abstract val isOverride: Boolean + abstract val hasBody: Boolean abstract val symbolKind: KtSymbolKind diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt index 929bd7fd476..894ec2ed04d 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt @@ -53,6 +53,8 @@ abstract class KtPropertySymbol : KtVariableSymbol(), abstract val hasBackingField: Boolean + abstract val isLateInit: Boolean + abstract val isConst: Boolean abstract val isOverride: Boolean diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt index 74733d103d8..e2146d4acbe 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/annotations/annotationsUtils.kt @@ -87,7 +87,8 @@ internal fun KtAnnotatedSymbol.hasAnnotation(classIdString: String, annotationUs internal fun KtAnnotatedSymbol.computeAnnotations( parent: PsiElement, nullability: NullabilityType, - annotationUseSiteTarget: AnnotationUseSiteTarget? + annotationUseSiteTarget: AnnotationUseSiteTarget?, + includeAnnotationsWithoutSite: Boolean = true ): List { if (nullability == NullabilityType.Unknown && annotations.isEmpty()) return emptyList() @@ -108,7 +109,10 @@ internal fun KtAnnotatedSymbol.computeAnnotations( for (annotation in annotations) { val siteTarget = annotation.useSiteTarget - if (siteTarget == null || siteTarget == annotationUseSiteTarget) { + + if ((includeAnnotationsWithoutSite && siteTarget == null) || + siteTarget == annotationUseSiteTarget + ) { result.add(FirLightAnnotationForAnnotationCall(annotation, parent)) } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt index 7aad6cd5fdd..b5e01365a3d 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/FirLightClassForFacade.kt @@ -13,9 +13,15 @@ import com.intellij.psi.impl.light.LightModifierList import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.asJava.classes.* import org.jetbrains.kotlin.asJava.elements.* -import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade +import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass +import org.jetbrains.kotlin.asJava.elements.KtLightField +import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.isConst import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.asJava.classes.createFields import org.jetbrains.kotlin.idea.asJava.classes.createMethods @@ -23,7 +29,9 @@ import org.jetbrains.kotlin.idea.frontend.api.analyze import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.psiUtil.isPrivate class FirLightClassForFacade( diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/firLightClassUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/firLightClassUtils.kt index a3b4b5cc41d..d691a59b138 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/firLightClassUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/classes/firLightClassUtils.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.idea.frontend.api.analyze 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.KtSymbolWithVisibility import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -147,11 +148,17 @@ internal fun FirLightClassBase.createMethods( is KtPropertySymbol -> { if (declaration.hasJvmFieldAnnotation()) continue + if (declaration.visibility == KtSymbolVisibility.PRIVATE) continue + + fun KtPropertyAccessorSymbol.needToCreateAccessor(siteTarget: AnnotationUseSiteTarget): Boolean { + if (isInline) return false + if (!hasBody && visibility == KtSymbolVisibility.PRIVATE) return false + return !declaration.hasJvmSyntheticAnnotation(siteTarget) + && !declaration.isHiddenByDeprecation(siteTarget) + } val getter = declaration.getter?.takeIf { - !declaration.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.PROPERTY_GETTER) && - !it.isInline && - !declaration.isHiddenByDeprecation(AnnotationUseSiteTarget.PROPERTY_GETTER) + it.needToCreateAccessor(AnnotationUseSiteTarget.PROPERTY_GETTER) } if (getter != null) { @@ -167,10 +174,7 @@ internal fun FirLightClassBase.createMethods( } val setter = declaration.setter?.takeIf { - !isAnnotationType && - !declaration.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.PROPERTY_SETTER) && - !it.isInline && - !declaration.isHiddenByDeprecation(AnnotationUseSiteTarget.PROPERTY_GETTER) + !isAnnotationType && it.needToCreateAccessor(AnnotationUseSiteTarget.PROPERTY_SETTER) } if (setter != null) { @@ -194,13 +198,19 @@ internal fun FirLightClassBase.createFields( isTopLevel: Boolean, result: MutableList ) { + fun hasBackingField(property: KtPropertySymbol): Boolean { + if (property.modality == KtCommonSymbolModality.ABSTRACT) return false + if (property.isLateInit) return true + //IS PARAMETER -> true + if (property.getter == null && property.setter == null) return true + if (property.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.FIELD)) return false + return property.hasBackingField + } + //TODO isHiddenByDeprecation for (declaration in declarations) { if (declaration !is KtPropertySymbol) continue - - if (!declaration.hasBackingField) continue - if (declaration.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.FIELD)) continue - if (declaration.modality == KtCommonSymbolModality.ABSTRACT) continue + if (!hasBackingField(declaration)) continue result.add( FirLightFieldForPropertySymbol( diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt index 9ad155160d2..2c1ce5a15f3 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt @@ -42,7 +42,7 @@ internal class FirLightFieldForPropertySymbol( private val _modifierList: PsiModifierList by lazyPub { val isJvmField = propertySymbol.hasJvmFieldAnnotation() - val suppressFinal = !isJvmField && !propertySymbol.isVal + val suppressFinal = !propertySymbol.isVal val modifiersFromSymbol = propertySymbol.computeModalityForMethod( isTopLevel = isTopLevel, @@ -64,9 +64,13 @@ internal class FirLightFieldForPropertySymbol( `if` = !suppressFinal ) + val nullability = if (visibility != PsiModifier.PRIVATE) + propertySymbol.type.getTypeNullability(propertySymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) + else NullabilityType.Unknown + val annotations = propertySymbol.computeAnnotations( parent = this, - nullability = propertySymbol.type.getTypeNullability(propertySymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE), + nullability = nullability, annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD, ) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt index d4519a771ea..93802abc726 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt @@ -45,7 +45,7 @@ internal class FirLightAccessorMethodForSymbol( val defaultName = containingPropertySymbol.name.identifier.let { if (containingClass.isAnnotationType) it else it.abiName(propertyAccessorSymbol) } - containingPropertySymbol.computeJvmMethodName(defaultName, accessorSite) + containingPropertySymbol.computeJvmMethodName(defaultName, containingClass, accessorSite) } override fun getName(): String = _name @@ -61,9 +61,11 @@ internal class FirLightAccessorMethodForSymbol( else AnnotationUseSiteTarget.PROPERTY_SETTER private val _annotations: List by lazyPub { + val nullabilityType = containingPropertySymbol.type + .getTypeNullability(containingPropertySymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) containingPropertySymbol.computeAnnotations( parent = this, - nullability = NullabilityType.Unknown, + nullability = nullabilityType, annotationUseSiteTarget = accessorSite, ) } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightMethod.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightMethod.kt index d1a4b089bd6..2dc1e68bb3e 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightMethod.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightMethod.kt @@ -17,9 +17,11 @@ import org.jetbrains.kotlin.asJava.classes.cannotModify import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility +import org.jetbrains.kotlin.idea.util.ifTrue import org.jetbrains.kotlin.idea.util.module internal abstract class FirLightMethod( @@ -83,11 +85,16 @@ internal abstract class FirLightMethod( protected fun T.computeJvmMethodName( defaultName: String, + containingClass: FirLightClassBase, annotationUseSiteTarget: AnnotationUseSiteTarget? = null - ): String where T : KtAnnotatedSymbol, T : KtSymbolWithVisibility { + ): String where T : KtAnnotatedSymbol, T : KtSymbolWithVisibility, T : KtCallableSymbol { getJvmNameFromAnnotation(annotationUseSiteTarget)?.let { return it } - if (visibility != KtSymbolVisibility.INTERNAL) return defaultName + val effectiveVisibilityIfNotInternal = (visibility != KtSymbolVisibility.INTERNAL).ifTrue { + (containingClass as? FirLightClassForSymbol)?.tryGetEffectiveVisibility(this) + } ?: this.visibility + + if (effectiveVisibilityIfNotInternal != KtSymbolVisibility.INTERNAL) return defaultName val moduleName = module?.name ?: return defaultName diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt index 95a73dcafeb..ae99fbe640d 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt @@ -34,14 +34,16 @@ internal class FirLightSimpleMethodForSymbol( ) { private val _name: String by lazyPub { - functionSymbol.computeJvmMethodName(functionSymbol.name.asString()) + functionSymbol.computeJvmMethodName(functionSymbol.name.asString(), containingClass) } override fun getName(): String = _name private val _annotations: List by lazyPub { - val nullability = if (functionSymbol.type.isUnit) NullabilityType.Unknown else functionSymbol.type.getTypeNullability( + val needUnknownNullability = functionSymbol.type.isUnit || (_visibility == PsiModifier.PRIVATE) + + val nullability = if (needUnknownNullability) NullabilityType.Unknown else functionSymbol.type.getTypeNullability( functionSymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE ) @@ -53,29 +55,24 @@ internal class FirLightSimpleMethodForSymbol( ) } - open class X { - open val x: Int = 2 - open fun u() = 2 + private val _visibility: String by lazyPub { + functionSymbol.isOverride.ifTrue { + (containingClass as? FirLightClassForSymbol) + ?.tryGetEffectiveVisibility(functionSymbol) + ?.toPsiVisibility(isTopLevel) + } ?: functionSymbol.computeVisibility(isTopLevel = isTopLevel) } private val _modifiers: Set by lazyPub { if (functionSymbol.hasInlineOnlyAnnotation()) return@lazyPub setOf(PsiModifier.FINAL, PsiModifier.PRIVATE) - val isOverrideMethod = functionSymbol.isOverride - - val visibility = isOverrideMethod.ifTrue { - (containingClass as? FirLightClassForSymbol) - ?.tryGetEffectiveVisibility(functionSymbol) - ?.toPsiVisibility(isTopLevel) - } ?: functionSymbol.computeVisibility(isTopLevel = isTopLevel) - val finalModifier = kotlinOrigin?.hasModifier(KtTokens.FINAL_KEYWORD) == true val modifiers = functionSymbol.computeModalityForMethod( isTopLevel = isTopLevel, - suppressFinal = !finalModifier && isOverrideMethod - ) + visibility + suppressFinal = !finalModifier && functionSymbol.isOverride + ) + _visibility modifiers.add( what = PsiModifier.STATIC, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterForSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterForSymbol.kt index b5924e94336..3962788a89b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterForSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterForSymbol.kt @@ -7,8 +7,11 @@ package org.jetbrains.kotlin.idea.asJava import com.intellij.psi.* import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.fir.declarations.FirResolvePhase 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 import org.jetbrains.kotlin.psi.KtParameter internal class FirLightParameterForSymbol( @@ -26,10 +29,15 @@ internal class FirLightParameterForSymbol( override val kotlinOrigin: KtParameter? = parameterSymbol.psi as? KtParameter private val _annotations: List by lazyPub { + val annotationSite = (containingMethod.isConstructor && parameterSymbol.symbolKind == KtSymbolKind.MEMBER).ifTrue { + AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER + } + parameterSymbol.computeAnnotations( parent = this, nullability = parameterSymbol.type.getTypeNullability(parameterSymbol, FirResolvePhase.TYPES), - annotationUseSiteTarget = null, + annotationUseSiteTarget = annotationSite, + includeAnnotationsWithoutSite = false ) } @@ -50,9 +58,7 @@ internal class FirLightParameterForSymbol( override fun equals(other: Any?): Boolean = this === other || - (other is FirLightParameterForSymbol && - kotlinOrigin == other.kotlinOrigin && - parameterSymbol == other.parameterSymbol) + (other is FirLightParameterForSymbol && parameterSymbol == other.parameterSymbol) override fun hashCode(): Int = kotlinOrigin.hashCode() } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertyGetterSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertyGetterSymbol.kt index f414881c400..6e462353a26 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertyGetterSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertyGetterSymbol.kt @@ -39,6 +39,7 @@ internal class KtFirPropertyGetterSymbol( override val isDefault: Boolean get() = firRef.withFir { it is FirDefaultPropertyAccessor } override val isInline: Boolean get() = firRef.withFir { it.isInline } override val isOverride: Boolean get() = firRef.withFir { it.isOverride } + override val hasBody: Boolean get() = firRef.withFir { it.body != null } override val symbolKind: KtSymbolKind get() = firRef.withFir { fir -> diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySetterSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySetterSymbol.kt index b7bcc2894ad..067ccff9f76 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySetterSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySetterSymbol.kt @@ -39,6 +39,8 @@ internal class KtFirPropertySetterSymbol( override val isDefault: Boolean get() = firRef.withFir { it is FirDefaultPropertyAccessor } override val isInline: Boolean get() = firRef.withFir { it.isInline } override val isOverride: Boolean get() = firRef.withFir { it.isOverride } + override val hasBody: Boolean get() = firRef.withFir { it.body != null } + override val modality: KtCommonSymbolModality get() = firRef.withFir(FirResolvePhase.STATUS) { it.modality.getSymbolModality() } override val visibility: KtSymbolVisibility get() = firRef.withFir(FirResolvePhase.STATUS) { it.visibility.getSymbolVisibility() } override val parameter: KtSetterParameterSymbol by firRef.withFirAndCache { fir -> diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt index 44f2392bfd6..5e10089371b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt @@ -80,6 +80,8 @@ internal class KtFirPropertySymbol( override val hasBackingField: Boolean get() = firRef.withFir { it.hasBackingField } + override val isLateInit: Boolean get() = firRef.withFir { it.isLateInit } + override val isConst: Boolean get() = firRef.withFir { it.isConst } override val isOverride: Boolean get() = firRef.withFir { it.isOverride } diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractIdeLightClassTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractIdeLightClassTest.kt index 5eb3a847aaf..82e7d84cffe 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractIdeLightClassTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractIdeLightClassTest.kt @@ -151,12 +151,10 @@ fun findClass(fqName: String, ktFile: KtFile?, project: Project): PsiClass? { return it.toLightClass() } - return JavaPsiFacade.getInstance(project).findClass(fqName, GlobalSearchScope.allScope(project)) ?: PsiTreeUtil.findChildrenOfType( - ktFile, - KtClassOrObject::class.java - ) - .find { fqName.endsWith(it.nameAsName!!.asString()) } - ?.let { KtLightClassForSourceDeclaration.create(it) } + return JavaPsiFacade.getInstance(project).findClass(fqName, GlobalSearchScope.allScope(project)) + ?: PsiTreeUtil.findChildrenOfType(ktFile, KtClassOrObject::class.java) + .find { fqName.endsWith(it.nameAsName!!.asString()) } + ?.toLightClass() } object LightClassLazinessChecker { @@ -276,11 +274,13 @@ object LightClassLazinessChecker { // see KtLightNullabilityAnnotation assertTrue( lightAnnotations.isNotEmpty(), - "Missing $fqName annotation in '${modifierListOwner}' have only ${annotations?.joinToString( - ", ", - "[", - "]" - ) { it.toString() }}" + "Missing $fqName annotation in '${modifierListOwner}' have only ${ + annotations?.joinToString( + ", ", + "[", + "]" + ) { it.toString() } + }" ) } clsAnnotations.zip(lightAnnotations).forEach { (clsAnnotation, lightAnnotation) ->