diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt index 6eecba54ea0..802239fb326 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.registerCheckersComponent import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider -import org.jetbrains.kotlin.fir.resolve.calls.jvm.registerJvmCallConflictResolverFactory import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.* @@ -38,8 +37,7 @@ class FirJavaModuleBasedSession private constructor( registerCommonComponents() registerResolveComponents() registerCheckersComponent() - registerJvmCallConflictResolverFactory() - registerJavaVisibilityChecker() + registerJavaSpecificComponents() val kotlinScopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSessionUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSessionUtils.kt new file mode 100644 index 00000000000..f4b1e1dadae --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSessionUtils.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 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.java + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.registerJvmEffectiveVisibilityResolver +import org.jetbrains.kotlin.fir.resolve.calls.jvm.registerJvmCallConflictResolverFactory + +fun FirSession.registerJavaSpecificComponents() { + registerJavaVisibilityChecker() + registerJvmCallConflictResolverFactory() + registerJvmEffectiveVisibilityResolver() +} diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/FirJvmEffectiveVisibilityResolver.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/FirJvmEffectiveVisibilityResolver.kt new file mode 100644 index 00000000000..d94c173ffe1 --- /dev/null +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/FirJvmEffectiveVisibilityResolver.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2020 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 + +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol + +class FirJvmEffectiveVisibilityResolver(session: FirSession) : FirEffectiveVisibilityResolverImpl(session) { + override fun computeEffectiveVisibility(visibility: Visibility, containerSymbol: FirClassLikeSymbol<*>?): FirEffectiveVisibility { + return when (visibility) { + JavaVisibilities.PackageVisibility -> FirEffectiveVisibilityImpl.PackagePrivate + else -> super.computeEffectiveVisibility(visibility, containerSymbol) + } + } +} + +fun FirSession.registerJvmEffectiveVisibilityResolver() { + register(FirEffectiveVisibilityResolver::class, FirJvmEffectiveVisibilityResolver(this)) +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt index 1dd4dfa3b2f..e5be0c59f5d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt @@ -12,18 +12,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.utils.addToStdlib.safeAs -class FirEffectiveVisibilityResolverImpl(private val session: FirSession) : FirEffectiveVisibilityResolver { - val cache = mutableMapOf() +open class FirEffectiveVisibilityResolverImpl(private val session: FirSession) : FirEffectiveVisibilityResolver() { + private val cache = mutableMapOf() - private fun FirElement.remember(effectiveVisibility: FirEffectiveVisibility): FirEffectiveVisibility { - val source = source - if (source != null) { - cache[source] = effectiveVisibility - } - return effectiveVisibility - } - - override fun resolveFor( + final override fun resolveFor( declaration: FirMemberDeclaration, containingDeclarations: List?, scopeSession: ScopeSession @@ -47,11 +39,37 @@ class FirEffectiveVisibilityResolverImpl(private val session: FirSession) : FirE } } - var selfEffectiveVisibility = visibility.firEffectiveVisibility(session, parentSymbol) + var selfEffectiveVisibility = computeEffectiveVisibility(visibility, parentSymbol) selfEffectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility) return declaration.remember(selfEffectiveVisibility) } + protected open fun computeEffectiveVisibility(visibility: Visibility, containerSymbol: FirClassLikeSymbol<*>?): FirEffectiveVisibility { + return visibility.normalize().forVisibility(containerSymbol) + } + + protected fun Visibility.forVisibility( + containerSymbol: FirClassLikeSymbol<*>? + ): FirEffectiveVisibility = + when (this) { + Visibilities.Private, Visibilities.PrivateToThis, Visibilities.InvisibleFake -> FirEffectiveVisibilityImpl.Private + Visibilities.Protected -> FirEffectiveVisibilityImpl.Protected(containerSymbol, session) + Visibilities.Internal -> FirEffectiveVisibilityImpl.Internal + Visibilities.Public -> FirEffectiveVisibilityImpl.Public + Visibilities.Local -> FirEffectiveVisibilityImpl.Local + Visibilities.Unknown -> FirEffectiveVisibilityImpl.Private + // NB: visibility must be already normalized here, so e.g. no JavaVisibilities are possible at this point + else -> error("Visibility $name is not allowed in forVisibility") + } + + private fun FirElement.remember(effectiveVisibility: FirEffectiveVisibility): FirEffectiveVisibility { + val source = source + if (source != null) { + cache[source] = effectiveVisibility + } + return effectiveVisibility + } + private fun FirMemberDeclaration.getParentInfo( containingDeclarations: List?, scopeSession: ScopeSession @@ -132,4 +150,4 @@ class FirEffectiveVisibilityResolverImpl(private val session: FirSession) : FirE return null } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityUtils.kt deleted file mode 100644 index 8c13643c226..00000000000 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityUtils.kt +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2010-2020 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 - -import org.jetbrains.kotlin.descriptors.RelationToType -import org.jetbrains.kotlin.fir.FirEffectiveVisibility.Permissiveness -import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl.* -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.resolve.declaredMemberScopeProvider -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider -import org.jetbrains.kotlin.fir.resolve.toSymbol -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.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.ConeKotlinTypeProjection -import org.jetbrains.kotlin.load.java.JavaVisibilities - -fun firEffectiveVisibility( - session: FirSession, - visibility: Visibility, - declaration: FirMemberDeclaration? -) = - visibility.forVisibility(session, declaration) - -fun FirRegularClass.firEffectiveVisibility(session: FirSession, checkPublishedApi: Boolean = false) = - firEffectiveVisibility(session, emptySet(), checkPublishedApi) - -fun Visibility.firEffectiveVisibility(session: FirSession, declaration: FirMemberDeclaration?): FirEffectiveVisibility = - firEffectiveVisibility(session, normalize(), declaration) - -fun Visibility.firEffectiveVisibility(session: FirSession, containerSymbol: FirClassLikeSymbol<*>?): FirEffectiveVisibility = when (this) { - JavaVisibilities.PACKAGE_VISIBILITY -> forVisibility(session, containerSymbol) - else -> normalize().forVisibility(session, containerSymbol) -} - -fun ConeKotlinType.leastPermissiveDescriptor(session: FirSession, base: FirEffectiveVisibility): DeclarationWithRelation? = - dependentDeclarations(session).leastPermissive(session, base) - -private fun lowerBound(vararg elements: FirEffectiveVisibility): FirEffectiveVisibility { - if (elements.size < 2) { - throw IllegalArgumentException("Number of elements must be greater than 1") - } - var result = elements[0] - for (el in elements) { - result = result.lowerBound(el) - } - return result -} - -private fun FirMemberDeclaration.containingClass(session: FirSession): FirRegularClass? { - val classId = when (this) { - is FirRegularClass -> symbol.classId.outerClassId - is FirCallableMemberDeclaration<*> -> symbol.callableId.classId - else -> null - } ?: return null - if (classId.isLocal) return null - return (session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass) - ?: (session.declaredMemberScopeProvider.getClassByClassId(classId) as? FirRegularClass) -} - -private fun FirClassLikeSymbol<*>.containingClass(session: FirSession): FirRegularClass? { - val classId = when (this) { - is FirRegularClassSymbol -> classId.outerClassId - is FirCallableSymbol<*> -> callableId.classId - else -> null - } ?: return null - if (classId.isLocal) return null - return (session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass) - ?: (session.declaredMemberScopeProvider.getClassByClassId(classId) as? FirRegularClass) -} - -private fun Visibility.forVisibility(session: FirSession, declaration: FirMemberDeclaration?) = - forVisibility(session, declaration?.containingClass(session)?.symbol) - -private fun Visibility.forVisibility( - session: FirSession, containerSymbol: FirClassLikeSymbol<*>? -): FirEffectiveVisibility = - when (this) { - Visibilities.Private, Visibilities.PrivateToThis, Visibilities.InvisibleFake -> Private - Visibilities.Protected -> Protected(containerSymbol, session) - Visibilities.Internal -> Internal - Visibilities.Public -> Public - Visibilities.Local -> Local - // NB: visibility must be already normalized here, so e.g. no JavaVisibilities are possible at this point - // TODO: else -> throw AssertionError("Visibility $name is not allowed in forVisibility") - JavaVisibilities.PACKAGE_VISIBILITY -> PackagePrivate - else -> Private - } - -class DeclarationWithRelation internal constructor(val declaration: FirMemberDeclaration, private val relation: RelationToType) { - fun firEffectiveVisibility(session: FirSession) = - declaration.visibility.firEffectiveVisibility(session, declaration) - - override fun toString(): String { - val name = when (declaration) { - is FirRegularClass -> declaration.name - is FirSimpleFunction -> declaration.name - is FirVariable<*> -> declaration.name - else -> "" - } - return "$relation $name" - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is DeclarationWithRelation) return false - if (declaration != other.declaration) return false - if (relation != other.relation) return false - return true - } - - override fun hashCode(): Int { - var result = declaration.hashCode() - result = 31 * result + relation.hashCode() - return result - } -} - -private fun FirMemberDeclaration.dependentDeclarations(session: FirSession, ownRelation: RelationToType): Set = - setOf(DeclarationWithRelation(this, ownRelation)) + - (this.containingClass(session)?.dependentDeclarations(session, ownRelation.containerRelation()) ?: emptySet()) - -private fun FirRegularClass.firEffectiveVisibility( - session: FirSession, classes: Set, checkPublishedApi: Boolean -): FirEffectiveVisibility = - if (this in classes) Public - else with(this.containingClass(session)) { - lowerBound( - visibility.firEffectiveVisibility(session, this@firEffectiveVisibility), - this?.firEffectiveVisibility(session, classes + this@firEffectiveVisibility, checkPublishedApi) ?: Public - ) - } - -// Should collect all dependent classifier descriptors, to get verbose diagnostic -private fun ConeKotlinType.dependentDeclarations(session: FirSession) = - dependentDeclarations(session, emptySet(), RelationToType.CONSTRUCTOR) - -private fun ConeKotlinType.dependentDeclarations( - session: FirSession, types: Set, ownRelation: RelationToType -): Set { - if (this in types) return emptySet() - val classLikeType = this as? ConeClassLikeType ?: return emptySet() - val lookupTag = classLikeType.lookupTag - val classSymbol = lookupTag.toSymbol(session) ?: return emptySet() - val ownDependent = (classSymbol.fir as? FirMemberDeclaration)?.dependentDeclarations(session, ownRelation) ?: emptySet() - val argumentDependent = classLikeType.typeArguments.mapNotNull { - (it as? ConeKotlinTypeProjection)?.type?.dependentDeclarations(session, types + this, RelationToType.ARGUMENT) - }.flatten() - return ownDependent + argumentDependent -} - -private fun Set.leastPermissive(session: FirSession, base: FirEffectiveVisibility): DeclarationWithRelation? { - for (declarationWithRelation in this) { - val currentVisibility = declarationWithRelation.firEffectiveVisibility(session) - when (currentVisibility.relation(base)) { - Permissiveness.LESS, Permissiveness.UNKNOWN -> { - return declarationWithRelation - } - else -> { - } - } - } - return null -} - diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirModuleBasedSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirModuleBasedSession.kt index 28d35d22ff5..a0975b9c772 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirModuleBasedSession.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirModuleBasedSession.kt @@ -19,5 +19,4 @@ abstract class FirModuleBasedSession( fun FirSession.registerResolveComponents() { register(FirQualifierResolver::class, FirQualifierResolverImpl(this)) register(FirTypeResolver::class, FirTypeResolverImpl(this)) - register(FirEffectiveVisibilityResolver::class, FirEffectiveVisibilityResolverImpl(this)) -} \ No newline at end of file +} 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 f31ddf255a6..d01a02ba0d4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -16,7 +16,6 @@ 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.types.ConeClassLikeType -import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 3d160b65a9c..ec339f784b3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -18,11 +18,9 @@ import org.jetbrains.kotlin.fir.resolve.inference.* import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolver.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolver.kt index 0bd358a135a..3f954cd6c2d 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolver.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolver.kt @@ -9,10 +9,10 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.resolve.ScopeSession -interface FirEffectiveVisibilityResolver : FirSessionComponent { - fun resolveFor( +abstract class FirEffectiveVisibilityResolver : FirSessionComponent { + abstract fun resolveFor( declaration: FirMemberDeclaration, containingDeclarations: List?, scopeSession: ScopeSession ): FirEffectiveVisibility -} \ No newline at end of file +} diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt index 43a07b5fcbf..cfd7bf13c51 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt @@ -15,8 +15,7 @@ import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.registerExtensions import org.jetbrains.kotlin.fir.java.JavaSymbolProvider -import org.jetbrains.kotlin.fir.java.registerJavaVisibilityChecker -import org.jetbrains.kotlin.fir.resolve.calls.jvm.registerJvmCallConflictResolverFactory +import org.jetbrains.kotlin.fir.java.registerJavaSpecificComponents import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider @@ -95,8 +94,7 @@ internal class FirIdeSourcesSession private constructor( } ) as FirSymbolProvider ) - registerJvmCallConflictResolverFactory() - registerJavaVisibilityChecker() + registerJavaSpecificComponents() extensionService.registerExtensions(BunchOfRegisteredExtensions.empty()) } }