FIR checker: resolve property with protected getter and public setter

Assuming Java class `Super` has a protected `getName` method and a
public `setName` method.

Then, in a subclass of `Super`, FE1.0 allows calls to `setName` via the
property syntax if the property is protected and invisible due to
dispatch receiver is not `this` or `super`.
This commit is contained in:
Tianyu Geng
2021-09-07 15:14:58 -07:00
committed by TeamCityServer
parent f27f91b03a
commit f35680f0a4
10 changed files with 151 additions and 16 deletions
@@ -5,14 +5,18 @@
package org.jetbrains.kotlin.fir.java
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
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.utils.visibility
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
@NoMutableState
object FirJavaVisibilityChecker : FirVisibilityChecker() {
@@ -22,18 +26,25 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
useSiteFile: FirFile,
containingDeclarations: List<FirDeclaration>,
dispatchReceiver: ReceiverValue?,
session: FirSession
session: FirSession,
isCallToPropertySetter: Boolean,
): Boolean {
return when (declarationVisibility) {
JavaVisibilities.ProtectedAndPackage, JavaVisibilities.ProtectedStaticVisibility -> {
if (symbol.packageFqName() == useSiteFile.packageFqName) {
true
} else {
val ownerLookupTag = symbol.getOwnerLookupTag()
ownerLookupTag != null && canSeeProtectedMemberOf(
containingDeclarations, dispatchReceiver, ownerLookupTag, session,
isVariableOrNamedFunction = symbol is FirVariableSymbol || symbol is FirNamedFunctionSymbol
)
val ownerLookupTag = symbol.getOwnerLookupTag() ?: return false
if (canSeeProtectedMemberOf(
containingDeclarations, dispatchReceiver, ownerLookupTag, session,
isVariableOrNamedFunction = symbol is FirVariableSymbol || symbol is FirNamedFunctionSymbol
)
) return true
// FE1.0 allows calling public setters with property assignment syntax if the getter is protected.
if (!isCallToPropertySetter || symbol !is FirSyntheticPropertySymbol) return false
val setterVisibility = symbol.setterSymbol?.visibility
setterVisibility != null && setterVisibility == Visibilities.Public
}
}