[FIR] KT-45972, KT-49072: Add visibility checks to the type resolution
This commit is contained in:
committed by
TeamCityServer
parent
2dc2a90755
commit
0eb2d117ef
+6
@@ -12477,6 +12477,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("InaccessiblePrivateInFile.kt")
|
||||
public void testInaccessiblePrivateInFile() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateInFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invisibleFakeReferenceInImport.kt")
|
||||
public void testInvisibleFakeReferenceInImport() throws Exception {
|
||||
|
||||
+6
@@ -12477,6 +12477,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("InaccessiblePrivateInFile.kt")
|
||||
public void testInaccessiblePrivateInFile() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateInFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invisibleFakeReferenceInImport.kt")
|
||||
public void testInvisibleFakeReferenceInImport() throws Exception {
|
||||
|
||||
+6
@@ -12477,6 +12477,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("InaccessiblePrivateInFile.kt")
|
||||
public void testInaccessiblePrivateInFile() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateInFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invisibleFakeReferenceInImport.kt")
|
||||
public void testInvisibleFakeReferenceInImport() throws Exception {
|
||||
|
||||
@@ -7,12 +7,19 @@ package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
abstract class FirTypeResolver : FirSessionComponent {
|
||||
abstract fun resolveType(typeRef: FirTypeRef, scopeClassDeclaration: ScopeClassDeclaration, areBareTypesAllowed: Boolean, isOperandOfIsOperator: Boolean): ConeKotlinType
|
||||
abstract fun resolveType(
|
||||
typeRef: FirTypeRef,
|
||||
scopeClassDeclaration: ScopeClassDeclaration,
|
||||
areBareTypesAllowed: Boolean,
|
||||
isOperandOfIsOperator: Boolean,
|
||||
useSiteFile: FirFile?
|
||||
): ConeKotlinType
|
||||
}
|
||||
|
||||
val FirSession.typeResolver: FirTypeResolver by FirSession.sessionComponentAccessor()
|
||||
|
||||
+71
-27
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
@@ -23,7 +22,6 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeWrongNumberOfTypeArgumen
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
@@ -54,9 +52,52 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveSymbol(
|
||||
symbol: FirBasedSymbol<*>,
|
||||
qualifier: List<FirQualifierPart>,
|
||||
qualifierResolver: FirQualifierResolver,
|
||||
): FirBasedSymbol<*>? {
|
||||
return when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> {
|
||||
if (qualifier.size == 1) {
|
||||
symbol
|
||||
} else {
|
||||
resolveLocalClassChain(symbol, qualifier)
|
||||
?: qualifierResolver.resolveSymbolWithPrefix(qualifier, symbol.classId)
|
||||
?: qualifierResolver.resolveEnumEntrySymbol(qualifier, symbol.classId)
|
||||
}
|
||||
}
|
||||
is FirTypeParameterSymbol -> {
|
||||
assert(qualifier.size == 1)
|
||||
symbol
|
||||
}
|
||||
else -> error("!")
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirBasedSymbol<*>?.isVisible(
|
||||
useSiteFile: FirFile?,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
): Boolean {
|
||||
val declaration = this?.fir
|
||||
return if (useSiteFile != null && declaration is FirMemberDeclaration) {
|
||||
session.visibilityChecker.isVisible(
|
||||
declaration,
|
||||
session,
|
||||
useSiteFile,
|
||||
containingDeclarations,
|
||||
null,
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveToSymbol(
|
||||
typeRef: FirTypeRef,
|
||||
scopes: List<FirScope>,
|
||||
scopeClassDeclaration: ScopeClassDeclaration,
|
||||
useSiteFile: FirFile?,
|
||||
): Pair<FirBasedSymbol<*>?, ConeSubstitutor?> {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> {
|
||||
@@ -66,37 +107,39 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
|
||||
is FirUserTypeRef -> {
|
||||
val qualifierResolver = session.qualifierResolver
|
||||
var resolvedSymbol: FirBasedSymbol<*>? = null
|
||||
var acceptedSymbol: FirBasedSymbol<*>? = null
|
||||
var firstNonApplicable: FirBasedSymbol<*>? = null
|
||||
var substitutor: ConeSubstitutor? = null
|
||||
val qualifier = typeRef.qualifier
|
||||
val scopes = scopeClassDeclaration.scopes
|
||||
val containingDeclarations = scopeClassDeclaration.containingDeclarations
|
||||
|
||||
for (scope in scopes) {
|
||||
if (resolvedSymbol != null) {
|
||||
if (acceptedSymbol != null) {
|
||||
break
|
||||
}
|
||||
scope.processClassifiersByNameWithSubstitution(qualifier.first().name) { symbol, substitutorFromScope ->
|
||||
if (resolvedSymbol != null) return@processClassifiersByNameWithSubstitution
|
||||
resolvedSymbol = when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> {
|
||||
if (qualifier.size == 1) {
|
||||
symbol
|
||||
} else {
|
||||
resolveLocalClassChain(symbol, qualifier)
|
||||
?: qualifierResolver.resolveSymbolWithPrefix(qualifier, symbol.classId)
|
||||
?: qualifierResolver.resolveEnumEntrySymbol(qualifier, symbol.classId)
|
||||
}
|
||||
}
|
||||
is FirTypeParameterSymbol -> {
|
||||
assert(qualifier.size == 1)
|
||||
symbol
|
||||
}
|
||||
else -> error("!")
|
||||
if (acceptedSymbol != null) {
|
||||
return@processClassifiersByNameWithSubstitution
|
||||
}
|
||||
|
||||
val resolvedSymbol = resolveSymbol(symbol, qualifier, qualifierResolver)
|
||||
|
||||
if (resolvedSymbol.isVisible(useSiteFile, containingDeclarations)) {
|
||||
acceptedSymbol = resolvedSymbol
|
||||
substitutor = substitutorFromScope
|
||||
} else {
|
||||
firstNonApplicable = resolvedSymbol
|
||||
}
|
||||
substitutor = substitutorFromScope
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptedSymbol == null) {
|
||||
acceptedSymbol = firstNonApplicable
|
||||
}
|
||||
|
||||
// TODO: Imports
|
||||
val resultSymbol: FirBasedSymbol<*>? = resolvedSymbol ?: qualifierResolver.resolveSymbol(qualifier)
|
||||
val resultSymbol: FirBasedSymbol<*>? = acceptedSymbol ?: qualifierResolver.resolveSymbol(qualifier)
|
||||
resultSymbol to substitutor
|
||||
}
|
||||
|
||||
@@ -377,18 +420,19 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
typeRef: FirTypeRef,
|
||||
scopeClassDeclaration: ScopeClassDeclaration,
|
||||
areBareTypesAllowed: Boolean,
|
||||
isOperandOfIsOperator: Boolean
|
||||
isOperandOfIsOperator: Boolean,
|
||||
useSiteFile: FirFile?,
|
||||
): ConeKotlinType {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> typeRef.type
|
||||
is FirUserTypeRef -> {
|
||||
val (symbol, substitutor) = resolveToSymbol(typeRef, scopeClassDeclaration.scopes)
|
||||
val (symbol, substitutor) = resolveToSymbol(typeRef, scopeClassDeclaration, useSiteFile)
|
||||
resolveUserType(
|
||||
typeRef,
|
||||
symbol,
|
||||
substitutor,
|
||||
areBareTypesAllowed,
|
||||
scopeClassDeclaration.topDeclaration,
|
||||
scopeClassDeclaration.containingDeclarations.lastOrNull(),
|
||||
isOperandOfIsOperator
|
||||
)
|
||||
}
|
||||
|
||||
+17
-2
@@ -73,7 +73,16 @@ class FirSpecificTypeResolverTransformer(
|
||||
val scopeOwnerLookupNames = data.scopes.flatMap { it.scopeOwnerLookupNames }
|
||||
session.lookupTracker?.recordTypeLookup(typeRef, scopeOwnerLookupNames, currentFile?.source)
|
||||
typeRef.transformChildren(this, data)
|
||||
return transformType(typeRef, typeResolver.resolveType(typeRef, data, areBareTypesAllowed, isOperandOfIsOperator))
|
||||
return transformType(
|
||||
typeRef,
|
||||
typeResolver.resolveType(
|
||||
typeRef,
|
||||
data,
|
||||
areBareTypesAllowed,
|
||||
isOperandOfIsOperator,
|
||||
currentFile,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
@@ -84,7 +93,13 @@ class FirSpecificTypeResolverTransformer(
|
||||
functionTypeRef.transformChildren(this, data)
|
||||
val scopeOwnerLookupNames = data.scopes.flatMap { it.scopeOwnerLookupNames }
|
||||
session.lookupTracker?.recordTypeLookup(functionTypeRef, scopeOwnerLookupNames, currentFile?.source)
|
||||
val resolvedType = typeResolver.resolveType(functionTypeRef, data, areBareTypesAllowed, isOperandOfIsOperator).takeIfAcceptable()
|
||||
val resolvedType = typeResolver.resolveType(
|
||||
functionTypeRef,
|
||||
data,
|
||||
areBareTypesAllowed,
|
||||
isOperandOfIsOperator,
|
||||
currentFile,
|
||||
).takeIfAcceptable()
|
||||
return if (resolvedType != null && resolvedType !is ConeClassErrorType) {
|
||||
buildResolvedTypeRef {
|
||||
source = functionTypeRef.source
|
||||
|
||||
+21
-5
@@ -84,13 +84,17 @@ fun <F : FirClassLikeDeclaration> F.runSupertypeResolvePhaseForLocalClass(
|
||||
currentScopeList: List<FirScope>,
|
||||
localClassesNavigationInfo: LocalClassesNavigationInfo,
|
||||
firProviderInterceptor: FirProviderInterceptor?,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
): F {
|
||||
val supertypeComputationSession = SupertypeComputationSession()
|
||||
val supertypeResolverVisitor = FirSupertypeResolverVisitor(
|
||||
session, supertypeComputationSession, scopeSession,
|
||||
currentScopeList.toPersistentList(),
|
||||
localClassesNavigationInfo,
|
||||
firProviderInterceptor
|
||||
firProviderInterceptor,
|
||||
useSiteFile,
|
||||
containingDeclarations,
|
||||
)
|
||||
|
||||
this.accept(supertypeResolverVisitor, null)
|
||||
@@ -204,10 +208,20 @@ open class FirSupertypeResolverVisitor(
|
||||
private val scopeForLocalClass: PersistentList<FirScope>? = null,
|
||||
private val localClassesNavigationInfo: LocalClassesNavigationInfo? = null,
|
||||
private val firProviderInterceptor: FirProviderInterceptor? = null,
|
||||
private val useSiteFile: FirFile? = null,
|
||||
containingDeclarations: List<FirDeclaration> = emptyList(),
|
||||
) : FirDefaultVisitor<Unit, Any?>() {
|
||||
private val supertypeGenerationExtensions = session.extensionService.supertypeGenerators
|
||||
private val classDeclarationsStack = ArrayDeque<FirRegularClass>()
|
||||
|
||||
init {
|
||||
containingDeclarations.forEach {
|
||||
if (it is FirRegularClass) {
|
||||
classDeclarationsStack.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? =
|
||||
if (firProviderInterceptor != null) firProviderInterceptor.getFirClassifierContainerFileIfAny(symbol)
|
||||
else session.firProvider.getFirClassifierContainerFileIfAny(symbol.classId)
|
||||
@@ -301,10 +315,12 @@ open class FirSupertypeResolverVisitor(
|
||||
val scopes = prepareScopes(classLikeDeclaration)
|
||||
|
||||
val transformer = FirSpecificTypeResolverTransformer(session)
|
||||
val resolvedTypesRefs = resolveSuperTypeRefs(
|
||||
transformer,
|
||||
ScopeClassDeclaration(scopes, classDeclarationsStack.lastOrNull())
|
||||
)
|
||||
val resolvedTypesRefs = transformer.withFile(useSiteFile) {
|
||||
resolveSuperTypeRefs(
|
||||
transformer,
|
||||
ScopeClassDeclaration(scopes, classDeclarationsStack)
|
||||
)
|
||||
}
|
||||
|
||||
supertypeComputationSession.storeSupertypes(classLikeDeclaration, resolvedTypesRefs)
|
||||
return resolvedTypesRefs
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ open class FirTypeResolveTransformer(
|
||||
return typeResolverTransformer.withFile(currentFile) {
|
||||
typeRef.transform(
|
||||
typeResolverTransformer,
|
||||
ScopeClassDeclaration(towerScope, classDeclarationsStack.lastOrNull())
|
||||
ScopeClassDeclaration(towerScope, classDeclarationsStack)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,5 +10,5 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
|
||||
data class ScopeClassDeclaration(
|
||||
val scopes: List<FirScope>,
|
||||
val topDeclaration: FirRegularClass?
|
||||
val containingDeclarations: List<FirRegularClass>
|
||||
)
|
||||
+1
-1
@@ -70,7 +70,7 @@ open class FirBodyResolveTransformer(
|
||||
typeRef,
|
||||
ScopeClassDeclaration(
|
||||
components.createCurrentScopeList(),
|
||||
context.topClassDeclaration
|
||||
context.containingClassDeclarations
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+3
-1
@@ -37,7 +37,9 @@ fun <F : FirClassLikeDeclaration> F.runAllPhasesForLocalClass(
|
||||
components.scopeSession,
|
||||
components.createCurrentScopeList(),
|
||||
localClassesNavigationInfo,
|
||||
firProviderInterceptor
|
||||
firProviderInterceptor,
|
||||
components.file,
|
||||
components.containingDeclarations,
|
||||
)
|
||||
runTypeResolvePhaseForLocalClass(
|
||||
components.session,
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ private class FirAnnotationResolveTransformer(
|
||||
): FirStatement {
|
||||
return annotation.transformAnnotationTypeRef(
|
||||
typeResolverTransformer,
|
||||
ScopeClassDeclaration(scopes, classDeclarationsStack.lastOrNull())
|
||||
ScopeClassDeclaration(scopes, classDeclarationsStack)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -14,5 +14,5 @@ package p1
|
||||
|
||||
import p2.*
|
||||
|
||||
val <!EXPOSED_PROPERTY_TYPE!>x<!>: X = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>X()<!>
|
||||
val x: X = X()
|
||||
val <!EXPOSED_PROPERTY_TYPE!>y<!>: Y = <!INVISIBLE_REFERENCE!>Y<!>()
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// FIR_IDENTICAL
|
||||
// MODULE: m1
|
||||
// FILE: f11.kt
|
||||
package api
|
||||
|
||||
interface ApplicabilityResult
|
||||
|
||||
// FILE: f12.kt
|
||||
package api
|
||||
|
||||
interface ArgumentMapping {
|
||||
fun highlightingApplicabilities(): ApplicabilityResult
|
||||
}
|
||||
|
||||
// MODULE: m2(m1)
|
||||
// FILE: f21.kt
|
||||
package impl
|
||||
|
||||
private data class ApplicabilityResult(val applicable: Boolean)
|
||||
|
||||
// FILE: f22.kt
|
||||
package impl
|
||||
|
||||
import api.*
|
||||
|
||||
class NullArgumentMapping : ArgumentMapping {
|
||||
// This is api.ApplicabilityResult
|
||||
override fun highlightingApplicabilities(): ApplicabilityResult = object : ApplicabilityResult {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// -- Module: <m1> --
|
||||
package
|
||||
|
||||
package api {
|
||||
|
||||
public interface ApplicabilityResult {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface ArgumentMapping {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract fun highlightingApplicabilities(): api.ApplicabilityResult
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
// -- Module: <m2> --
|
||||
package
|
||||
|
||||
package impl {
|
||||
|
||||
private final data class ApplicabilityResult {
|
||||
public constructor ApplicabilityResult(/*0*/ applicable: kotlin.Boolean)
|
||||
public final val applicable: kotlin.Boolean
|
||||
public final operator /*synthesized*/ fun component1(): kotlin.Boolean
|
||||
public final /*synthesized*/ fun copy(/*0*/ applicable: kotlin.Boolean = ...): impl.ApplicabilityResult
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class NullArgumentMapping : api.ArgumentMapping {
|
||||
public constructor NullArgumentMapping()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ fun highlightingApplicabilities(): api.ApplicabilityResult
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,6 +10,6 @@ package kotlin.sequences
|
||||
import p.*
|
||||
|
||||
interface I {
|
||||
val v1: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>FilteringSequence<!>
|
||||
val v1: FilteringSequence
|
||||
val <!EXPOSED_PROPERTY_TYPE!>v2<!>: IndexingSequence<String>
|
||||
}
|
||||
|
||||
Generated
+6
@@ -12483,6 +12483,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("InaccessiblePrivateInFile.kt")
|
||||
public void testInaccessiblePrivateInFile() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/imports/InaccessiblePrivateInFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invisibleFakeReferenceInImport.kt")
|
||||
public void testInvisibleFakeReferenceInImport() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user