FIR resolve: introduce draft version of the visibility checker

This commit is contained in:
Simon Ogorodnik
2019-04-25 14:30:44 +03:00
committed by Mikhail Glukhikh
parent adf845b2fd
commit 9169071d60
4 changed files with 72 additions and 6 deletions
+1
View File
@@ -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,
@@ -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()