FIR resolve: introduce draft version of the visibility checker
This commit is contained in:
committed by
Mikhail Glukhikh
parent
adf845b2fd
commit
9169071d60
@@ -5,6 +5,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
compile(project(":core:descriptors"))
|
||||
compile(project(":core:descriptors.jvm"))
|
||||
compile(project(":core:deserialization"))
|
||||
compile(project(":compiler:fir:cones"))
|
||||
compile(project(":compiler:fir:tree"))
|
||||
|
||||
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
@@ -40,6 +38,9 @@ class CallInfo(
|
||||
val arguments: List<FirExpression>,
|
||||
|
||||
val typeArguments: List<FirTypeProjection>,
|
||||
val session: FirSession,
|
||||
val containingFile: FirFile,
|
||||
val container: FirDeclaration,
|
||||
val typeProvider: (FirExpression) -> FirTypeRef?
|
||||
) {
|
||||
val argumentCount get() = arguments.size
|
||||
|
||||
@@ -5,12 +5,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firSafeNullable
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import java.lang.IllegalStateException
|
||||
@@ -140,14 +150,57 @@ internal object DiscriminateSynthetics : CheckerStage() {
|
||||
|
||||
}
|
||||
|
||||
internal object CheckVisibility : CheckerStage() {
|
||||
|
||||
private fun ConeSymbol.packageFqName(): FqName {
|
||||
return when (this) {
|
||||
is ConeClassLikeSymbol -> classId.packageFqName
|
||||
is ConeCallableSymbol -> callableId.packageName
|
||||
else -> error("No package fq name for ${this}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
||||
val symbol = candidate.symbol
|
||||
val declaration = symbol.firSafeNullable<FirMemberDeclaration>()
|
||||
if (declaration != null && !declaration.visibility.isPublicAPI) {
|
||||
val visible = when (declaration.visibility) {
|
||||
JavaVisibilities.PACKAGE_VISIBILITY ->
|
||||
symbol.packageFqName() == callInfo.containingFile.packageFqName
|
||||
Visibilities.PRIVATE, Visibilities.PRIVATE_TO_THIS -> {
|
||||
if (declaration.session == callInfo.session) {
|
||||
val provider = callInfo.session.service<FirProvider>()
|
||||
val candidateFile = when (symbol) {
|
||||
is ConeCallableSymbol -> provider.getFirCallableContainerFile(symbol)
|
||||
is ConeClassLikeSymbol -> provider.getFirClassifierContainerFile(symbol.classId)
|
||||
else -> null
|
||||
}
|
||||
candidateFile == callInfo.containingFile
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
Visibilities.INTERNAL ->
|
||||
declaration.session == callInfo.session
|
||||
else -> true
|
||||
}
|
||||
|
||||
if (!visible) {
|
||||
sink.reportApplicability(CandidateApplicability.HIDDEN)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun functionCallResolutionSequence() = listOf(
|
||||
MapArguments, CheckExplicitReceiverConsistency, CreateFreshTypeVariableSubstitutorStage,
|
||||
CheckVisibility, MapArguments, CheckExplicitReceiverConsistency, CreateFreshTypeVariableSubstitutorStage,
|
||||
CheckReceivers.Dispatch, CheckReceivers.Extension, CheckArguments
|
||||
)
|
||||
|
||||
|
||||
internal fun qualifiedAccessResolutionSequence() = listOf(
|
||||
CheckVisibility,
|
||||
DiscriminateSynthetics,
|
||||
CheckExplicitReceiverConsistency,
|
||||
CreateFreshTypeVariableSubstitutorStage,
|
||||
|
||||
+13
-2
@@ -48,9 +48,12 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
}
|
||||
|
||||
private var packageFqName = FqName.ROOT
|
||||
private lateinit var file: FirFile
|
||||
private var container: FirDeclaration? = null
|
||||
|
||||
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
|
||||
packageFqName = file.packageFqName
|
||||
this.file = file
|
||||
return withScopeCleanup(scopes) {
|
||||
scopes.addImportingScopes(file, session)
|
||||
scopes += FirTopLevelDeclaredMemberScope(file, session)
|
||||
@@ -210,7 +213,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
|
||||
val receiver = qualifiedAccess.explicitReceiver?.transformSingle(this, noExpectedType)
|
||||
|
||||
val info = CallInfo(CallKind.VariableAccess, receiver, emptyList(), emptyList()) { it.resultType }
|
||||
val info = CallInfo(CallKind.VariableAccess, receiver, emptyList(), emptyList(), session, file, container!!) { it.resultType }
|
||||
val resolver = CallResolver(jump, inferenceComponents)
|
||||
resolver.callInfo = info
|
||||
resolver.scopes = (scopes + localScopes).asReversed()
|
||||
@@ -320,7 +323,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
val arguments = functionCall.arguments
|
||||
val typeArguments = functionCall.typeArguments
|
||||
|
||||
val info = CallInfo(CallKind.Function, explicitReceiver, arguments, typeArguments) { it.resultType }
|
||||
val info = CallInfo(CallKind.Function, explicitReceiver, arguments, typeArguments, session, file, container!!) { it.resultType }
|
||||
val resolver = CallResolver(jump, inferenceComponents)
|
||||
resolver.callInfo = info
|
||||
resolver.scopes = (scopes + localScopes).asReversed()
|
||||
@@ -606,6 +609,14 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
}
|
||||
|
||||
|
||||
override fun transformDeclaration(declaration: FirDeclaration, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||
val prevContainer = container
|
||||
container = declaration
|
||||
val result = super.transformDeclaration(declaration, data)
|
||||
container = prevContainer
|
||||
return result
|
||||
}
|
||||
|
||||
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||
if (namedFunction.returnTypeRef !is FirImplicitTypeRef && implicitTypeOnly) return namedFunction.compose()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user