[FIR] Set actual modifier on implicitly actual primary constructors
... of annotations and inline classes. #KT-60139 Fixed
This commit is contained in:
committed by
Space Team
parent
fb04356829
commit
b0f1746012
+2
-4
@@ -10,10 +10,7 @@ import org.jetbrains.kotlin.diagnostics.reportOn
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.expectForActual
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.getSingleExpectForActualOrNull
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
@@ -32,6 +29,7 @@ object FirActualCallableDeclarationChecker : FirCallableDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkActualFunctionWithDefaultArguments(function: FirFunction, reporter: DiagnosticReporter, context: CheckerContext) {
|
private fun checkActualFunctionWithDefaultArguments(function: FirFunction, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
|
if (function.symbol.isAnnotationConstructor(context.session)) return
|
||||||
for (valueParameter in function.valueParameters) {
|
for (valueParameter in function.valueParameters) {
|
||||||
if (valueParameter.defaultValue != null) {
|
if (valueParameter.defaultValue != null) {
|
||||||
reporter.reportOn(valueParameter.source, FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS, context)
|
reporter.reportOn(valueParameter.source, FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS, context)
|
||||||
|
|||||||
+10
-9
@@ -122,7 +122,6 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
) {
|
) {
|
||||||
val symbol = declaration.symbol
|
val symbol = declaration.symbol
|
||||||
val compatibilityToMembersMap = symbol.expectForActual ?: return
|
val compatibilityToMembersMap = symbol.expectForActual ?: return
|
||||||
val session = context.session
|
|
||||||
|
|
||||||
checkAmbiguousExpects(symbol, compatibilityToMembersMap, symbol, context, reporter)
|
checkAmbiguousExpects(symbol, compatibilityToMembersMap, symbol, context, reporter)
|
||||||
|
|
||||||
@@ -131,7 +130,7 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
if (compatibilityToMembersMap.allStrongIncompatibilities()) return
|
if (compatibilityToMembersMap.allStrongIncompatibilities()) return
|
||||||
|
|
||||||
if (Compatible in compatibilityToMembersMap) {
|
if (Compatible in compatibilityToMembersMap) {
|
||||||
if (checkActual && requireActualModifier(symbol, session)) {
|
if (checkActual) {
|
||||||
reporter.reportOn(source, FirErrors.ACTUAL_MISSING, context)
|
reporter.reportOn(source, FirErrors.ACTUAL_MISSING, context)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -168,13 +167,15 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Compatible !in compatibilityToMembersMap -> {
|
Compatible !in compatibilityToMembersMap -> {
|
||||||
reporter.reportOn(
|
if (requireActualModifier(declaration.symbol, context.session)) {
|
||||||
source,
|
reporter.reportOn(
|
||||||
FirErrors.ACTUAL_WITHOUT_EXPECT,
|
source,
|
||||||
symbol,
|
FirErrors.ACTUAL_WITHOUT_EXPECT,
|
||||||
compatibilityToMembersMap,
|
symbol,
|
||||||
context
|
compatibilityToMembersMap,
|
||||||
)
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
|
|||||||
+5
-3
@@ -550,7 +550,8 @@ class LightTreeRawFirDeclarationBuilder(
|
|||||||
selfType.source,
|
selfType.source,
|
||||||
classWrapper,
|
classWrapper,
|
||||||
delegatedConstructorSource,
|
delegatedConstructorSource,
|
||||||
containingClassIsExpectClass = status.isExpect
|
containingClassIsExpectClass = status.isExpect,
|
||||||
|
isImplicitlyActual = status.isActual && (status.isInline || classKind == ClassKind.ANNOTATION_CLASS)
|
||||||
)
|
)
|
||||||
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
|
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
|
||||||
firPrimaryConstructor?.let { declarations += it }
|
firPrimaryConstructor?.let { declarations += it }
|
||||||
@@ -884,7 +885,8 @@ class LightTreeRawFirDeclarationBuilder(
|
|||||||
classWrapper: ClassWrapper,
|
classWrapper: ClassWrapper,
|
||||||
delegatedConstructorSource: KtLightSourceElement?,
|
delegatedConstructorSource: KtLightSourceElement?,
|
||||||
isEnumEntry: Boolean = false,
|
isEnumEntry: Boolean = false,
|
||||||
containingClassIsExpectClass: Boolean
|
containingClassIsExpectClass: Boolean,
|
||||||
|
isImplicitlyActual: Boolean = false,
|
||||||
): PrimaryConstructor? {
|
): PrimaryConstructor? {
|
||||||
fun ClassKind.isEnumRelated(): Boolean = this == ClassKind.ENUM_CLASS || this == ClassKind.ENUM_ENTRY
|
fun ClassKind.isEnumRelated(): Boolean = this == ClassKind.ENUM_CLASS || this == ClassKind.ENUM_ENTRY
|
||||||
val shouldGenerateImplicitConstructor =
|
val shouldGenerateImplicitConstructor =
|
||||||
@@ -955,7 +957,7 @@ class LightTreeRawFirDeclarationBuilder(
|
|||||||
}
|
}
|
||||||
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility, Modality.FINAL).apply {
|
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility, Modality.FINAL).apply {
|
||||||
isExpect = modifiers.hasExpect() || context.containerIsExpect
|
isExpect = modifiers.hasExpect() || context.containerIsExpect
|
||||||
isActual = modifiers.hasActual()
|
isActual = modifiers.hasActual() || isImplicitlyActual
|
||||||
isInner = classWrapper.isInner()
|
isInner = classWrapper.isInner()
|
||||||
isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.Private
|
isFromSealedClass = classWrapper.isSealed() && explicitVisibility !== Visibilities.Private
|
||||||
isFromEnumClass = classWrapper.isEnum()
|
isFromEnumClass = classWrapper.isEnum()
|
||||||
|
|||||||
+3
-1
@@ -983,6 +983,7 @@ open class PsiRawFirBuilder(
|
|||||||
containingClassIsExpectClass,
|
containingClassIsExpectClass,
|
||||||
copyConstructedTypeRefWithImplicitSource = true,
|
copyConstructedTypeRefWithImplicitSource = true,
|
||||||
isErrorConstructor = !hasPrimaryConstructor,
|
isErrorConstructor = !hasPrimaryConstructor,
|
||||||
|
isImplicitlyActual = container.status.isActual && (container.status.isInline || classKind == ClassKind.ANNOTATION_CLASS)
|
||||||
)
|
)
|
||||||
container.declarations += firPrimaryConstructor
|
container.declarations += firPrimaryConstructor
|
||||||
}
|
}
|
||||||
@@ -1003,6 +1004,7 @@ open class PsiRawFirBuilder(
|
|||||||
containingClassIsExpectClass: Boolean,
|
containingClassIsExpectClass: Boolean,
|
||||||
copyConstructedTypeRefWithImplicitSource: Boolean,
|
copyConstructedTypeRefWithImplicitSource: Boolean,
|
||||||
isErrorConstructor: Boolean = false,
|
isErrorConstructor: Boolean = false,
|
||||||
|
isImplicitlyActual: Boolean = false,
|
||||||
): FirConstructor {
|
): FirConstructor {
|
||||||
val constructorSource = this?.toFirSourceElement()
|
val constructorSource = this?.toFirSourceElement()
|
||||||
?: owner.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitConstructor)
|
?: owner.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitConstructor)
|
||||||
@@ -1050,7 +1052,7 @@ open class PsiRawFirBuilder(
|
|||||||
val explicitVisibility = this?.visibility?.takeUnless { it == Visibilities.Unknown }
|
val explicitVisibility = this?.visibility?.takeUnless { it == Visibilities.Unknown }
|
||||||
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility(), Modality.FINAL).apply {
|
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility(), Modality.FINAL).apply {
|
||||||
isExpect = this@toFirConstructor?.hasExpectModifier() == true || this@PsiRawFirBuilder.context.containerIsExpect
|
isExpect = this@toFirConstructor?.hasExpectModifier() == true || this@PsiRawFirBuilder.context.containerIsExpect
|
||||||
isActual = this@toFirConstructor?.hasActualModifier() == true
|
isActual = this@toFirConstructor?.hasActualModifier() == true || isImplicitlyActual
|
||||||
isInner = owner.parent.parent !is KtScript && owner.hasModifier(INNER_KEYWORD) // a warning about inner script class is reported on the class itself
|
isInner = owner.parent.parent !is KtScript && owner.hasModifier(INNER_KEYWORD) // a warning about inner script class is reported on the class itself
|
||||||
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.Private
|
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.Private
|
||||||
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
|
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
|
||||||
|
|||||||
+1
-8
@@ -83,7 +83,7 @@ open class FirExpectActualMatcherTransformer(
|
|||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
fun transformMemberDeclaration(memberDeclaration: FirMemberDeclaration) {
|
fun transformMemberDeclaration(memberDeclaration: FirMemberDeclaration) {
|
||||||
if (!memberDeclaration.isActual && !memberDeclaration.isImplicitlyActual()) return
|
if (!memberDeclaration.isActual) return
|
||||||
val actualSymbol = memberDeclaration.symbol
|
val actualSymbol = memberDeclaration.symbol
|
||||||
|
|
||||||
// Regardless of whether any `expect` symbols are found for `memberDeclaration`, it must be assigned an `expectForActual` map.
|
// Regardless of whether any `expect` symbols are found for `memberDeclaration`, it must be assigned an `expectForActual` map.
|
||||||
@@ -97,11 +97,4 @@ open class FirExpectActualMatcherTransformer(
|
|||||||
) ?: mapOf()
|
) ?: mapOf()
|
||||||
memberDeclaration.expectForActual = expectForActualData
|
memberDeclaration.expectForActual = expectForActualData
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO KT-60139 Remove special handling when implicitly actual elements have the actual flag set.
|
|
||||||
private fun FirMemberDeclaration.isImplicitlyActual(): Boolean {
|
|
||||||
if (this !is FirPrimaryConstructor) return false
|
|
||||||
val klass = getContainingClass(session) ?: return false
|
|
||||||
return klass.isActual && (klass.isInline || klass.classKind == ClassKind.ANNOTATION_CLASS)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user