diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 495d5816e07..b88a3be6021 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -86,6 +87,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by warning(PositioningStrategy.VAL_OR_VAR_NODE) { parameter("valOrVar") } + val INVISIBLE_SETTER by error(PositioningStrategy.ASSIGNMENT_LHS) { + parameter("property") + parameter("visibility") + parameter("callableId") + } } val UNRESOLVED by object : DiagnosticGroup("Unresolved") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 2c12d6ebdf5..67d9fdf010a 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -116,6 +117,7 @@ object FirErrors { val VAL_OR_VAR_ON_FUN_PARAMETER by warning1(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAL_OR_VAR_ON_CATCH_PARAMETER by warning1(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by warning1(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) + val INVISIBLE_SETTER by error3(SourceElementPositioningStrategies.ASSIGNMENT_LHS) // Unresolved val INVISIBLE_REFERENCE by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt index 7d20046589a..93be9c55f02 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt @@ -59,7 +59,7 @@ object CommonExpressionCheckers : ExpressionCheckers() { override val variableAssignmentCheckers: Set get() = setOf( - FirValReassignmentChecker, + FirReassignmentAndInvisibleSetterChecker, FirAssignmentTypeMismatchChecker ) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt new file mode 100644 index 00000000000..17960d94007 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt @@ -0,0 +1,125 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest +import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor +import org.jetbrains.kotlin.fir.declarations.utils.isCompanion +import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast +import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment +import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol +import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.references.FirBackingFieldReference +import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol +import org.jetbrains.kotlin.fir.types.toSymbol +import org.jetbrains.kotlin.fir.visibilityChecker + +object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker() { + override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { + checkInvisibleSetter(expression, context, reporter) + checkValReassignmentViaBackingField(expression, context, reporter) + checkValReassignmentOnValueParameter(expression, context, reporter) + } + + private fun checkInvisibleSetter( + expression: FirVariableAssignment, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + fun shouldInvisibleSetterBeReported(symbol: FirPropertySymbol): Boolean { + val setterSymbol = symbol.setterSymbol + + @OptIn(SymbolInternals::class) + val setterFir = setterSymbol?.fir + if (setterFir != null) { + val isVisible = context.session.visibilityChecker.isVisible( + setterFir, + context.session, + context.findClosest()!!, + context.containingDeclarations, + ExpressionReceiverValue(expression.dispatchReceiver), + ) + if (!isVisible) { + // Report SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC in another checker + val dispatchReceiverTypeSymbol = symbol.dispatchReceiverType?.toSymbol(context.session) + return setterFir.visibility != Visibilities.Protected || + dispatchReceiverTypeSymbol !is FirRegularClassSymbol || + !dispatchReceiverTypeSymbol.isCompanion + } + } + + return false + } + + val callableSymbol = expression.calleeReference.toResolvedCallableSymbol() + if (callableSymbol is FirPropertySymbol && shouldInvisibleSetterBeReported(callableSymbol)) { + val explicitReceiver = expression.explicitReceiver + // Try to get type from smartcast + if (explicitReceiver is FirExpressionWithSmartcast) { + val symbol = explicitReceiver.originalType.toRegularClassSymbol(context.session) + if (symbol != null) { + for (declarationSymbol in symbol.declarationSymbols) { + if (declarationSymbol is FirPropertySymbol && declarationSymbol.name == callableSymbol.name) { + if (!shouldInvisibleSetterBeReported(declarationSymbol)) { + return + } + } + } + } + } + reporter.reportOn( + expression.source, + FirErrors.INVISIBLE_SETTER, + callableSymbol, + callableSymbol.setterSymbol!!.visibility, + callableSymbol.callableId, + context + ) + } + } + + private fun checkValReassignmentViaBackingField( + expression: FirVariableAssignment, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val backingFieldReference = expression.lValue as? FirBackingFieldReference ?: return + val propertySymbol = backingFieldReference.resolvedSymbol + if (propertySymbol.isVar) return + val closestGetter = context.findClosest { it.isGetter }?.symbol ?: return + if (propertySymbol.getterSymbol != closestGetter) return + + backingFieldReference.source?.let { + if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfValReassignmentViaBackingField)) { + reporter.reportOn(it, FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR, propertySymbol, context) + } else { + reporter.reportOn(it, FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD, propertySymbol, context) + } + } + } + + private fun checkValReassignmentOnValueParameter( + expression: FirVariableAssignment, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val valueParameter = (expression.lValue as? FirResolvedNamedReference)?.resolvedSymbol as? FirValueParameterSymbol ?: return + reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, valueParameter, context) + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirValReassignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirValReassignmentChecker.kt deleted file mode 100644 index 717b119e1c1..00000000000 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirValReassignmentChecker.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.fir.analysis.checkers.expression - -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest -import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors -import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn -import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor -import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment -import org.jetbrains.kotlin.fir.languageVersionSettings -import org.jetbrains.kotlin.fir.references.FirBackingFieldReference -import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference -import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol - -object FirValReassignmentChecker : FirVariableAssignmentChecker() { - override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { - checkValReassignmentViaBackingField(expression, context, reporter) - checkValReassignmentOnValueParameter(expression, context, reporter) - } - - private fun checkValReassignmentViaBackingField( - expression: FirVariableAssignment, - context: CheckerContext, - reporter: DiagnosticReporter - ) { - val backingFieldReference = expression.lValue as? FirBackingFieldReference ?: return - val propertySymbol = backingFieldReference.resolvedSymbol - if (propertySymbol.isVar) return - val closestGetter = context.findClosest { it.isGetter }?.symbol ?: return - if (propertySymbol.getterSymbol != closestGetter) return - - backingFieldReference.source?.let { - if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfValReassignmentViaBackingField)) { - reporter.reportOn(it, FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR, propertySymbol, context) - } else { - reporter.reportOn(it, FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD, propertySymbol, context) - } - } - } - - private fun checkValReassignmentOnValueParameter( - expression: FirVariableAssignment, - context: CheckerContext, - reporter: DiagnosticReporter - ) { - val valueParameter = (expression.lValue as? FirResolvedNamedReference)?.resolvedSymbol as? FirValueParameterSymbol ?: return - reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, valueParameter, context) - } -} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 7e1b317e86d..36a0565ad1b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FQ_N import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.COLLECTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.MODULE_DATA import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FUNCTION_PARAMETERS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME_OF_CONTAINING_DECLARATION_OR_FILE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NOT_RENDERED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NULLABLE_STRING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT @@ -227,6 +228,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SU import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_IF_AS_EXPRESSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_REFERENCE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_SETTER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IS_ENUM_ENTRY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE @@ -480,6 +482,7 @@ class FirDefaultErrorMessages { // Unresolved map.put(INVISIBLE_REFERENCE, "Symbol {0} is invisible", SYMBOL) + map.put(INVISIBLE_SETTER, "Cannot access ''{0}'': it is {1} in {2}", VARIABLE_NAME, VISIBILITY, NAME_OF_CONTAINING_DECLARATION_OR_FILE) map.put(UNRESOLVED_REFERENCE, "Unresolved reference: {0}", NULLABLE_STRING) map.put(UNRESOLVED_LABEL, "Unresolved label") map.put(DESERIALIZATION_ERROR, "Deserialization error") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt index 6a95fc363bd..31a62f01c2e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt @@ -13,16 +13,14 @@ import org.jetbrains.kotlin.diagnostics.rendering.Renderer import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirRenderer -import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.render -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject -import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.render +import org.jetbrains.kotlin.name.CallableId object FirDiagnosticRenderers { val NULLABLE_STRING = Renderer { it ?: "null" } @@ -136,6 +134,15 @@ object FirDiagnosticRenderers { "Module ${it.name}" } + val NAME_OF_CONTAINING_DECLARATION_OR_FILE = Renderer { symbol: CallableId -> + val classId = symbol.classId + if (classId == null) { + "file" + } else { + "'${classId}'" + } + } + @Suppress("FunctionName") fun COLLECTION(renderer: ContextIndependentParameterRenderer): ContextIndependentParameterRenderer> { return Renderer { list -> diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt index 33a25349c59..60ff57db246 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.java.JavaVisibilities import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -29,7 +30,13 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() { true } else { val ownerId = symbol.getOwnerId() - ownerId != null && canSeeProtectedMemberOf(containingDeclarations, dispatchReceiver, ownerId, session) + ownerId != null && canSeeProtectedMemberOf( + containingDeclarations, + dispatchReceiver, + ownerId, + symbol.fir is FirSyntheticPropertyAccessor, + session + ) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index 612c49b9247..a3fdfa21150 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -5,22 +5,23 @@ package org.jetbrains.kotlin.fir +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor import org.jetbrains.kotlin.fir.declarations.utils.* +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression +import org.jetbrains.kotlin.fir.references.impl.FirExplicitSuperReference +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue -import org.jetbrains.kotlin.fir.resolve.firProvider -import org.jetbrains.kotlin.fir.resolve.fullyExpandedType -import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes -import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.toSymbol import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -116,7 +117,13 @@ abstract class FirVisibilityChecker : FirSessionComponent { Visibilities.Protected -> { val ownerId = symbol.getOwnerId() - ownerId != null && canSeeProtectedMemberOf(containingDeclarations, dispatchReceiver, ownerId, session) + ownerId != null && canSeeProtectedMemberOf( + containingDeclarations, + dispatchReceiver, + ownerId, + symbol.fir is FirSyntheticPropertyAccessor, + session + ) } else -> platformVisibilityCheck( @@ -171,22 +178,43 @@ abstract class FirVisibilityChecker : FirSessionComponent { } private fun canSeeProtectedMemberOf( - containingUseSiteClass: FirClass, + containingUseSiteClassSymbol: FirClassSymbol<*>, dispatchReceiver: ReceiverValue?, - ownerId: ClassId, session: FirSession + ownerId: ClassId, + isSyntheticProperty: Boolean, + session: FirSession ): Boolean { dispatchReceiver?.ownerIfCompanion(session)?.let { companionOwnerClassId -> - if (containingUseSiteClass.isSubClass(companionOwnerClassId, session)) return true + if (containingUseSiteClassSymbol.isSubClass(companionOwnerClassId, session)) return true } - // TODO: Add check for receiver, see org.jetbrains.kotlin.descriptors.Visibility#doesReceiverFitForProtectedVisibility - return containingUseSiteClass.isSubClass(ownerId, session) + if (containingUseSiteClassSymbol.isSubClass(ownerId, session)) { + val receiverExpression = dispatchReceiver?.receiverExpression + if (receiverExpression == null || + receiverExpression is FirThisReceiverExpression || + (receiverExpression is FirQualifiedAccessExpression && receiverExpression.calleeReference is FirExplicitSuperReference) || + dispatchReceiver.type.toSymbol(session).isSubClass(containingUseSiteClassSymbol.classId, session) + ) { + return true + } + + if (isSyntheticProperty) { + return if (session.languageVersionSettings.supportsFeature(LanguageFeature.ImproveReportingDiagnosticsOnProtectedMembersOfBaseClass)) + containingUseSiteClassSymbol.classId.packageFqName == ownerId.packageFqName + else + true + } + } + + return false } - private fun FirClass.isSubClass(ownerId: ClassId, session: FirSession): Boolean { + private fun FirBasedSymbol<*>?.isSubClass(ownerId: ClassId, session: FirSession): Boolean { + val classSymbol = this as? FirClassSymbol<*> ?: return false + val classId = classSymbol.classId if (classId.isSame(ownerId)) return true - return lookupSuperTypes(this, lookupInterfaces = true, deep = true, session).any { superType -> + return lookupSuperTypes(classSymbol, lookupInterfaces = true, deep = true, session).any { superType -> (superType as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag?.classId?.isSame(ownerId) == true } } @@ -207,14 +235,16 @@ abstract class FirVisibilityChecker : FirSessionComponent { protected fun canSeeProtectedMemberOf( containingDeclarationOfUseSite: List, dispatchReceiver: ReceiverValue?, - ownerId: ClassId, session: FirSession + ownerId: ClassId, + isSyntheticProperty: Boolean, + session: FirSession ): Boolean { if (canSeePrivateMemberOf(containingDeclarationOfUseSite, ownerId, session)) return true for (containingDeclaration in containingDeclarationOfUseSite) { if (containingDeclaration !is FirClass) continue val boundSymbol = containingDeclaration.symbol - if (canSeeProtectedMemberOf(boundSymbol.fir, dispatchReceiver, ownerId, session)) return true + if (canSeeProtectedMemberOf(boundSymbol.fir.symbol, dispatchReceiver, ownerId, isSyntheticProperty, session)) return true } return false diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt index 8c5625a063c..4b62790dfb0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt @@ -49,9 +49,20 @@ fun lookupSuperTypes( useSiteSession: FirSession, supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default, substituteTypes: Boolean = false +): List { + return lookupSuperTypes(klass.symbol, lookupInterfaces, deep, useSiteSession, supertypeSupplier, substituteTypes) +} + +fun lookupSuperTypes( + classSymbol: FirClassSymbol<*>, + lookupInterfaces: Boolean, + deep: Boolean, + useSiteSession: FirSession, + supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default, + substituteTypes: Boolean = false ): List { return SmartList().also { - klass.symbol.collectSuperTypes(it, SmartSet.create(), deep, lookupInterfaces, substituteTypes, useSiteSession, supertypeSupplier) + classSymbol.collectSuperTypes(it, SmartSet.create(), deep, lookupInterfaces, substituteTypes, useSiteSession, supertypeSupplier) } } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/builder/FirExplicitSuperReferenceBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/builder/FirExplicitSuperReferenceBuilder.kt index 003a89dc56f..9f472318a7a 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/builder/FirExplicitSuperReferenceBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/builder/FirExplicitSuperReferenceBuilder.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.references.builder import kotlin.contracts.* +import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.references.FirSuperReference @@ -24,6 +25,7 @@ class FirExplicitSuperReferenceBuilder { var labelName: String? = null lateinit var superTypeRef: FirTypeRef + @OptIn(FirImplementationDetail::class) fun build(): FirSuperReference { return FirExplicitSuperReference( source, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/impl/FirExplicitSuperReference.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/impl/FirExplicitSuperReference.kt index e82515492fa..6a319e6f105 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/impl/FirExplicitSuperReference.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/references/impl/FirExplicitSuperReference.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.references.impl +import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.types.FirTypeRef @@ -15,7 +16,7 @@ import org.jetbrains.kotlin.fir.visitors.* * DO NOT MODIFY IT MANUALLY */ -internal class FirExplicitSuperReference( +class FirExplicitSuperReference @FirImplementationDetail constructor( override val source: FirSourceElement?, override val labelName: String?, override var superTypeRef: FirTypeRef, diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index 5bd7bd68428..1dbc7f5b9cb 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -399,7 +399,9 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() } } - impl(superReference, "FirExplicitSuperReference") + impl(superReference, "FirExplicitSuperReference") { + publicImplementation() + } noImpl(controlFlowGraphReference) diff --git a/compiler/testData/diagnostics/tests/OverridenSetterVisibility.fir.kt b/compiler/testData/diagnostics/tests/OverridenSetterVisibility.fir.kt index 53033533d59..9d9d797028f 100644 --- a/compiler/testData/diagnostics/tests/OverridenSetterVisibility.fir.kt +++ b/compiler/testData/diagnostics/tests/OverridenSetterVisibility.fir.kt @@ -22,7 +22,7 @@ class Test: ATest(), ITest { fun main() { val test = Test() - test.prop = 12 + test.prop = 12 val itest: ITest = test itest.prop = 12 // No error here diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2330.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2330.fir.kt index 2964014cd39..23e18692ae9 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2330.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2330.fir.kt @@ -23,23 +23,23 @@ class P { fun foo() { val p = P() - p.x = 34 //should be an error here + p.x = 34 //should be an error here p.y = 23 fun inner() { - p.x = 44 + p.x = 44 } } class R { val p = P(); init { - p.x = 42 + p.x = 42 } val testInGetterInOtherClass : Int get() { - p.x = 33 + p.x = 33 return 3 } } @@ -50,4 +50,4 @@ fun test() { p.x = 43 } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2960.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2960.fir.kt deleted file mode 100644 index 24429bf8014..00000000000 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2960.fir.kt +++ /dev/null @@ -1,36 +0,0 @@ -//KT-2960 Perform control flow checks for package property initializers - -package b - -class P { - var x : Int = 0 - private set -} - -val p = P() -var f = { -> p.x = 32 } - -val o = object { - fun run() { - p.x = 4 - - val z : Int - doSmth(z) - } -} - -val g = { -> - val x: Int - doSmth(x) -} - -class A { - val a : Int = 1 - get() { - val x : Int - doSmth(x) - return field - } -} - -fun doSmth(i: Int) = i \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2960.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2960.kt index f09f34d3411..ff06fda7566 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2960.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2960.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL //KT-2960 Perform control flow checks for package property initializers package b diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.fir.kt deleted file mode 100644 index 87364ae72a8..00000000000 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -open class X(s : String) { - public var n: String = s - private set - -} - -class Z : X("subclass") { - fun print(): String { - n = n - return n; - } -} - - -fun box() : String { - return Z().print() //error -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.kt index b4335ce390e..c5afe3b301b 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/privateSetter.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class X(s : String) { public var n: String = s private set diff --git a/compiler/testData/diagnostics/tests/privateInFile/visibility.fir.kt b/compiler/testData/diagnostics/tests/privateInFile/visibility.fir.kt index b179904c0cf..905eb64e3ab 100644 --- a/compiler/testData/diagnostics/tests/privateInFile/visibility.fir.kt +++ b/compiler/testData/diagnostics/tests/privateInFile/visibility.fir.kt @@ -40,7 +40,7 @@ fun test() { val po = PO val v = xx - xx = 40 + xx = 40 } class B : A() {} diff --git a/compiler/testData/diagnostics/tests/scopes/invisibleSetter.fir.kt b/compiler/testData/diagnostics/tests/scopes/invisibleSetter.fir.kt deleted file mode 100644 index d37a025755f..00000000000 --- a/compiler/testData/diagnostics/tests/scopes/invisibleSetter.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -class A { - public var x: Int = 0 - private set -} - -fun main() { - val a = A() - a.x = 1 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/invisibleSetter.kt b/compiler/testData/diagnostics/tests/scopes/invisibleSetter.kt index 09e2f95e1ea..95ff8ee22fd 100644 --- a/compiler/testData/diagnostics/tests/scopes/invisibleSetter.kt +++ b/compiler/testData/diagnostics/tests/scopes/invisibleSetter.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL class A { public var x: Int = 0 private set diff --git a/compiler/testData/diagnostics/tests/scopes/kt9430.fir.kt b/compiler/testData/diagnostics/tests/scopes/kt9430.fir.kt index dc6cae66ada..1db50eab125 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt9430.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/kt9430.fir.kt @@ -6,8 +6,8 @@ class B: A() class C: A() { fun bar() { - A().foo() - B().foo() + A().foo() + B().foo() } } diff --git a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/complexCompanion.fir.kt b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/complexCompanion.fir.kt index d21b87baa85..989b88c592c 100644 --- a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/complexCompanion.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/complexCompanion.fir.kt @@ -13,6 +13,6 @@ class B { class C: A() { init { - B.foo() // Error: receiver is not suitable + B.foo() // Error: receiver is not suitable } } diff --git a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.fir.kt b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.fir.kt index aab40362af0..286d569e69e 100644 --- a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.fir.kt @@ -21,9 +21,8 @@ class B : A() { b.foo b.bar = b.bar + "" - a.foo - // TODO: should be INVISIBLE_SETTER - a.bar = a.bar + "" + a.foo + a.bar = a.bar + "" if (a is B) { a.foo @@ -32,14 +31,13 @@ class B : A() { if (d.x is B) { d.x.abc // Ok - d.x.foo - // TODO: should be INVISIBLE_SETTER - d.x.bar = d.x.bar + "" + d.x.foo + d.x.bar = d.x.bar + "" } } } fun baz(a: A) { a.foo - a.bar = a.bar + "" + a.bar = a.bar + "" } diff --git a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.kt b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.kt index a26cafecede..656a477f5ba 100644 --- a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.kt +++ b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticPropertyExtensions.kt @@ -22,7 +22,6 @@ class B : A() { b.bar = b.bar + "" a.foo - // TODO: should be INVISIBLE_SETTER a.bar = a.bar + "" if (a is B) { @@ -33,7 +32,6 @@ class B : A() { if (d.x is B) { d.x.abc // Ok d.x.foo - // TODO: should be INVISIBLE_SETTER d.x.bar = d.x.bar + "" } } diff --git a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.fir.kt b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.fir.kt index 442e01b09da..7ef9df01c66 100644 --- a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.fir.kt @@ -11,7 +11,7 @@ class Data(var x: A) class B : A() { fun baz(a: A, b: B, d: Data) { - a.foo { } + a.foo { } b.foo { } @@ -20,7 +20,7 @@ class B : A() { } if (d.x is B) { - d.x.foo {} + d.x.foo {} } } } diff --git a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/unstableSmartCast.fir.kt b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/unstableSmartCast.fir.kt index de47b4d7ce6..696d0b72931 100644 --- a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/unstableSmartCast.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/unstableSmartCast.fir.kt @@ -11,8 +11,8 @@ fun BaseOuter.foo(): String = "" class Derived : BaseOuter() { fun test(foo: Foo) { if (foo.base is Derived) { - foo.base.foo() checkType { _() } // Resolved to extension - foo.base.bar() + foo.base.foo() checkType { _() } // Resolved to extension + foo.base.bar() } } } diff --git a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.fir.kt b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.fir.kt index e6f83a964cc..d3859c5764c 100644 --- a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/withSmartcast.fir.kt @@ -11,11 +11,11 @@ class Derived : Base() { override fun bar() { } protected fun baz(x: Base) { - x.foo() - x.bar() + x.foo() + x.bar() - x.x = x.x + 1 - x.y = x.y + 1 + x.x = x.x + 1 + x.y = x.y + 1 if (x is Derived) { x.foo() diff --git a/compiler/testData/diagnostics/tests/scopes/visibility.fir.kt b/compiler/testData/diagnostics/tests/scopes/visibility.fir.kt index 6db9b2fd4eb..ebd01913dc3 100644 --- a/compiler/testData/diagnostics/tests/scopes/visibility.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/visibility.fir.kt @@ -72,7 +72,7 @@ class E : C() { class F : C() { fun test8(c: C) { - doSmth(c.i) + doSmth(c.i) } } diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.fir.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.fir.kt index 12b86439d5d..dfda95bed2c 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.fir.kt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.fir.kt @@ -8,7 +8,7 @@ fun foo(javaClass: JavaClass) { javaClass.somethingProtected javaClass.somethingPrivate javaClass.somethingPackage - javaClass.somethingPublic = 1 + javaClass.somethingPublic = 1 } // FILE: JavaClass.java diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.fir.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.fir.kt index c6fff226bdc..f0444beb6e7 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.fir.kt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.fir.kt @@ -12,7 +12,7 @@ fun foo(javaClass: JavaClass) { class X : JavaClass() { fun foo(other: JavaClass) { doSomething { bar() } - other.doSomething { bar() } + other.doSomething { bar() } } } diff --git a/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClass.fir.kt b/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClass.fir.kt index bd3fbbf6a49..f4b5a37cda9 100644 --- a/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClass.fir.kt +++ b/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClass.fir.kt @@ -18,12 +18,12 @@ class Data(var x: Foo) class B : Foo() { fun baz(a: Foo, t: Foo, d: Data) { - a.bar = t.bar - a.foo = t.foo + a.bar = t.bar + a.foo = t.foo if (d.x is B) { - d.x.bar = d.x.bar + "" - d.x.foo = d.x.foo + "" + d.x.bar = d.x.bar + "" + d.x.foo = d.x.foo + "" } } } diff --git a/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClassWithDisabledFeature.fir.kt b/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClassWithDisabledFeature.fir.kt index 9ee3b7b757d..90ec72a9356 100644 --- a/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClassWithDisabledFeature.fir.kt +++ b/compiler/testData/diagnostics/tests/visibility/invisibleSetterOfJavaClassWithDisabledFeature.fir.kt @@ -19,11 +19,11 @@ class Data(var x: Foo) class B : Foo() { fun baz(a: Foo, t: Foo, d: Data) { a.bar = t.bar - a.foo = t.foo + a.foo = t.foo if (d.x is B) { d.x.bar = d.x.bar + "" - d.x.foo = d.x.foo + "" + d.x.foo = d.x.foo + "" } } } diff --git a/compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.fir.kt b/compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.fir.kt index 7c542493194..8d6b426f6db 100644 --- a/compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.fir.kt +++ b/compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.fir.kt @@ -13,11 +13,11 @@ class Data(var x: Foo) class B : Foo() { fun baz(a: Foo, t: Foo, d: Data) { a.bar = t.bar - a.foo = t.foo + a.foo = t.foo if (d.x is B) { d.x.bar = d.x.bar + "" - d.x.foo = d.x.foo + "" + d.x.foo = d.x.foo + "" } } } diff --git a/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt b/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt index 8ec61cff58c..cf16a00d871 100644 --- a/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt +++ b/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtExpression @@ -300,6 +301,7 @@ private object FirToKtConversionCreator { FqName::class, FirModuleData::class, ExpectActualCompatibility.Incompatible::class, + CallableId::class ) private val KType.kClass: KClass<*> diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 55b8fbe2fa7..8ad07304fbb 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -241,6 +241,15 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.INVISIBLE_SETTER) { firDiagnostic -> + InvisibleSetterImpl( + firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a.fir), + firDiagnostic.b, + firDiagnostic.c, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirErrors.INVISIBLE_REFERENCE) { firDiagnostic -> InvisibleReferenceImpl( firSymbolBuilder.buildSymbol(firDiagnostic.a.fir), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 3c9e7f6fb50..b5712eb0dec 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -197,6 +198,13 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val valOrVar: KtKeywordToken } + abstract class InvisibleSetter : KtFirDiagnostic() { + override val diagnosticClass get() = InvisibleSetter::class + abstract val property: KtVariableSymbol + abstract val visibility: Visibility + abstract val callableId: CallableId + } + abstract class InvisibleReference : KtFirDiagnostic() { override val diagnosticClass get() = InvisibleReference::class abstract val reference: KtSymbol diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 5faef308a83..21f707be0f5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -282,6 +283,16 @@ internal class ValOrVarOnSecondaryConstructorParameterImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class InvisibleSetterImpl( + override val property: KtVariableSymbol, + override val visibility: Visibility, + override val callableId: CallableId, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InvisibleSetter(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class InvisibleReferenceImpl( override val reference: KtSymbol, firDiagnostic: FirPsiDiagnostic,