diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirProvider.kt index dcf21ee6cda..a2aaa54c578 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirProvider.kt @@ -28,9 +28,14 @@ abstract class FirProvider : FirSymbolProvider() { abstract fun getFirClassifierContainerFile(fqName: ClassId): FirFile + abstract fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? + fun getFirClassifierContainerFile(symbol: FirClassLikeSymbol<*>): FirFile = getFirClassifierContainerFile(symbol.classId) + fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? = + getFirClassifierContainerFileIfAny(symbol.classId) + abstract fun getFirCallableContainerFile(symbol: FirCallableSymbol<*>): FirFile? companion object { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index 75d1d6e73c0..6802de4ef55 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.render @@ -274,16 +275,74 @@ internal object CheckVisibility : CheckerStage() { } } + // 'local' isn't taken into account here + private fun ClassId.isSame(other: ClassId): Boolean = + packageFqName == other.packageFqName && relativeClassName == other.relativeClassName + private fun ImplicitReceiverStack.canSeePrivateMemberOf(ownerId: ClassId): Boolean { for (implicitReceiverValue in receiversAsReversed()) { if (implicitReceiverValue !is ImplicitDispatchReceiverValue) continue val boundSymbol = implicitReceiverValue.boundSymbol - if (boundSymbol.classId == ownerId) return true - if (boundSymbol is FirRegularClassSymbol && boundSymbol.fir.companionObject?.symbol?.classId == ownerId) return true + if (boundSymbol.classId.isSame(ownerId)) { + return true + } + if (boundSymbol is FirRegularClassSymbol && boundSymbol.fir.companionObject?.symbol?.classId?.isSame(ownerId) == true) { + return true + } } return false } + private fun FirRegularClassSymbol.canSeeProtectedMemberOf( + ownerId: ClassId, + session: FirSession, + visited: MutableSet + ): Boolean { + if (classId in visited) return false + visited += classId + if (classId.isSame(ownerId)) return true + val superTypes = fir.superConeTypes + for (superType in superTypes) { + val superTypeSymbol = superType.lookupTag.toSymbol(session) as? FirRegularClassSymbol ?: continue + if (superTypeSymbol.canSeeProtectedMemberOf(ownerId, session, visited)) return true + } + return false + } + + private fun ImplicitReceiverStack.canSeeProtectedMemberOf(ownerId: ClassId, session: FirSession): Boolean { + if (canSeePrivateMemberOf(ownerId)) return true + val visited = mutableSetOf() + for (implicitReceiverValue in receiversAsReversed()) { + if (implicitReceiverValue !is ImplicitDispatchReceiverValue) continue + val boundSymbol = implicitReceiverValue.boundSymbol + val superTypes = boundSymbol.fir.superConeTypes + for (superType in superTypes) { + val superTypeSymbol = superType.lookupTag.toSymbol(session) as? FirRegularClassSymbol ?: continue + if (superTypeSymbol.canSeeProtectedMemberOf(ownerId, session, visited)) return true + } + } + return false + } + + private fun AbstractFirBasedSymbol<*>.getOwnerId(): ClassId? { + return when (this) { + is FirClassLikeSymbol<*> -> { + val ownerId = classId.outerClassId + if (classId.isLocal) { + ownerId?.asLocal() ?: classId + } else { + ownerId + } + } + is FirCallableSymbol<*> -> { + callableId.classId + } + else -> { + throw AssertionError("Unsupported owner search for ${fir.javaClass}: ${fir.render()}") + } + } + } + private fun ClassId.asLocal(): ClassId = ClassId(packageFqName, relativeClassName, true) private suspend fun checkVisibility( @@ -294,69 +353,42 @@ internal object CheckVisibility : CheckerStage() { ): Boolean { val useSiteFile = callInfo.containingFile val implicitReceiverStack = callInfo.implicitReceiverStack + val session = callInfo.session + val provider = session.firProvider + val candidateFile = when (symbol) { + is FirClassLikeSymbol<*> -> provider.getFirClassifierContainerFileIfAny(symbol) + is FirCallableSymbol<*> -> provider.getFirCallableContainerFile(symbol) + else -> null + } + val ownerId = symbol.getOwnerId() val visible = when (declaration.visibility) { JavaVisibilities.PACKAGE_VISIBILITY -> { symbol.packageFqName() == useSiteFile.packageFqName } + Visibilities.INTERNAL -> { + declaration.session == callInfo.session + } Visibilities.PRIVATE, Visibilities.PRIVATE_TO_THIS -> { if (declaration.session == callInfo.session) { - val provider = callInfo.session.firProvider - when (symbol) { - is FirClassLikeSymbol<*> -> { - val classId = symbol.classId - val ownerId = classId.outerClassId - when { - classId.isLocal -> { - // Normally should not be here - implicitReceiverStack.canSeePrivateMemberOf(ownerId?.asLocal() ?: classId) - } - ownerId == null -> { - // Top-level: visible in file - provider.getFirClassifierContainerFile(classId) == useSiteFile - } - else -> { - // Member: visible inside parent class, including all its member classes - implicitReceiverStack.canSeePrivateMemberOf(ownerId) - } - } - } - is FirCallableSymbol<*> -> { - val candidateFile = provider.getFirCallableContainerFile(symbol) - val ownerId = symbol.callableId.classId - when { - candidateFile == null -> { - // Local - ownerId != null && implicitReceiverStack.canSeePrivateMemberOf(ownerId.asLocal()) - } - ownerId == null -> { - // Top-level: visible in file - candidateFile == useSiteFile - } - else -> { - // Member: visible inside parent class, including all its member classes - implicitReceiverStack.canSeePrivateMemberOf(ownerId) - } - } - } - else -> { - throw AssertionError("Unsupported visibility check for ${declaration.javaClass}: ${declaration.render()}") - } + if (ownerId == null) { + // Top-level: visible in file + candidateFile == useSiteFile + } else { + // Member: visible inside parent class, including all its member classes + implicitReceiverStack.canSeePrivateMemberOf(ownerId) } } else { false } } - Visibilities.INTERNAL -> { - declaration.session == callInfo.session - } Visibilities.PROTECTED -> { - true // TODO: Support protected visibility + ownerId != null && implicitReceiverStack.canSeeProtectedMemberOf(ownerId, session) } - JavaVisibilities.PROTECTED_AND_PACKAGE -> { + JavaVisibilities.PROTECTED_AND_PACKAGE, JavaVisibilities.PROTECTED_STATIC_VISIBILITY -> { if (symbol.packageFqName() == useSiteFile.packageFqName) { true } else { - true // TODO: Support protected visibility + ownerId != null && implicitReceiverStack.canSeeProtectedMemberOf(ownerId, session) } } else -> true diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt index f8677f67dbd..ee6899055f3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt @@ -47,6 +47,10 @@ class FirProviderImpl(val session: FirSession) : FirProvider() { return state.classifierContainerFileMap[fqName] ?: error("Couldn't find container for $fqName") } + override fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? { + return state.classifierContainerFileMap[fqName] + } + override fun getClassNamesInPackage(fqName: FqName): Set { return state.classesInPackage[fqName] ?: emptySet() } diff --git a/compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt b/compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt new file mode 100644 index 00000000000..9f77c959bb3 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt @@ -0,0 +1,34 @@ +open class Outer { + private class PrivateNested + private inner class PrivateInner + + protected class ProtectedNested + protected inner class ProtectedInner + + public class PublicNested + public inner class PublicInner +} + +class Derived : Outer() { + fun foo() { + Outer.PrivateNested() + super.PrivateInner() + + Outer.ProtectedNested() + super.ProtectedInner() + + Outer.PublicNested() + super.PublicInner() + } +} + +fun foo() { + Outer.PrivateNested() + Outer().PrivateInner() + + Outer.ProtectedNested() + Outer().ProtectedInner() + + Outer.PublicNested() + Outer().PublicInner() +} diff --git a/compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.txt b/compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.txt new file mode 100644 index 00000000000..6f90c6c44f0 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.txt @@ -0,0 +1,72 @@ +FILE: nestedVisibility.kt + public open class Outer : R|kotlin/Any| { + public constructor(): R|Outer| { + super() + } + + private final class PrivateNested : R|kotlin/Any| { + public constructor(): R|Outer.PrivateNested| { + super() + } + + } + + private final inner class PrivateInner : R|kotlin/Any| { + public constructor(): R|Outer.PrivateInner| { + super() + } + + } + + protected final class ProtectedNested : R|kotlin/Any| { + public constructor(): R|Outer.ProtectedNested| { + super() + } + + } + + protected final inner class ProtectedInner : R|kotlin/Any| { + public constructor(): R|Outer.ProtectedInner| { + super() + } + + } + + public final class PublicNested : R|kotlin/Any| { + public constructor(): R|Outer.PublicNested| { + super() + } + + } + + public final inner class PublicInner : R|kotlin/Any| { + public constructor(): R|Outer.PublicInner| { + super() + } + + } + + } + public final class Derived : R|Outer| { + public constructor(): R|Derived| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + Q|Outer|.#() + super.#() + Q|Outer|.R|/Outer.ProtectedNested.ProtectedNested|() + super.R|/Outer.ProtectedInner.ProtectedInner|() + Q|Outer|.R|/Outer.PublicNested.PublicNested|() + super.R|/Outer.PublicInner.PublicInner|() + } + + } + public final fun foo(): R|kotlin/Unit| { + Q|Outer|.#() + R|/Outer.Outer|().#() + Q|Outer|.#() + R|/Outer.Outer|().#() + Q|Outer|.R|/Outer.PublicNested.PublicNested|() + R|/Outer.Outer|().R|/Outer.PublicInner.PublicInner|() + } diff --git a/compiler/fir/resolve/testData/resolve/expresssions/protectedVisibility.kt b/compiler/fir/resolve/testData/resolve/expresssions/protectedVisibility.kt new file mode 100644 index 00000000000..b405cbbeb99 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/protectedVisibility.kt @@ -0,0 +1,54 @@ +open class Protected { + protected fun bar() {} + + fun baz() { + bar() + Nested().foo() + } + + inner class Inner { + fun foo() { + bar() + } + } + + protected open class Nested { + fun foo() { + bar() + } + + protected fun bar() {} + } +} + +class Derived : Protected() { + fun foo() { + bar() + Nested().foo() + Nested().bar() // hidden + } + + class NestedDerived : Nested() { + fun use() { + bar() + } + } +} + +fun test() { + Protected().baz() + Protected().Inner() + + Protected().bar() // hidden + Protected.Nested() // hidden +} + +open class Generic(val x: T) { + protected open fun foo(): T = x +} + +class DerivedGeneric : Generic() { + override fun foo(): Int { + return super.foo() + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/expresssions/protectedVisibility.txt b/compiler/fir/resolve/testData/resolve/expresssions/protectedVisibility.txt new file mode 100644 index 00000000000..705ff6774ce --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/protectedVisibility.txt @@ -0,0 +1,92 @@ +FILE: protectedVisibility.kt + public open class Protected : R|kotlin/Any| { + public constructor(): R|Protected| { + super() + } + + protected final fun bar(): R|kotlin/Unit| { + } + + public final fun baz(): R|kotlin/Unit| { + this@R|/Protected|.R|/Protected.bar|() + R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|() + } + + public final inner class Inner : R|kotlin/Any| { + public constructor(): R|Protected.Inner| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + this@R|/Protected|.R|/Protected.bar|() + } + + } + + protected open class Nested : R|kotlin/Any| { + public constructor(): R|Protected.Nested| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + this@R|/Protected.Nested|.R|/Protected.Nested.bar|() + } + + protected final fun bar(): R|kotlin/Unit| { + } + + } + + } + public final class Derived : R|Protected| { + public constructor(): R|Derived| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + this@R|/Protected|.R|/Protected.bar|() + R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|() + R|/Protected.Nested.Nested|().#() + } + + public final class NestedDerived : R|Protected.Nested| { + public constructor(): R|Derived.NestedDerived| { + super() + } + + public final fun use(): R|kotlin/Unit| { + this@R|/Protected.Nested|.R|/Protected.Nested.bar|() + } + + } + + } + public final fun test(): R|kotlin/Unit| { + R|/Protected.Protected|().R|/Protected.baz|() + R|/Protected.Protected|().R|/Protected.Inner.Inner|() + R|/Protected.Protected|().#() + Q|Protected|.#() + } + public open class Generic : R|kotlin/Any| { + public constructor(x: R|T|): R|Generic| { + super() + } + + public final val x: R|T| = R|/x| + public get(): R|T| + + protected open fun foo(): R|T| { + ^foo this@R|/Generic|.R|FakeOverride| + } + + } + public final class DerivedGeneric : R|Generic| { + public constructor(): R|DerivedGeneric| { + super|>() + } + + public final override fun foo(): R|kotlin/Int| { + ^foo super|>.R|FakeOverride|() + } + + } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.kt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.kt index da67497e796..7cf2553f8b8 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.kt +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.kt @@ -10,6 +10,8 @@ public class JavaClass { // FILE: test.kt +package some + fun test(jc: JavaClass) { - jc.field + jc.field } \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.txt index 711f4dbfe3d..b67221d566d 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/FieldAndGetter.txt @@ -1,4 +1,4 @@ FILE: test.kt public final fun test(jc: R|JavaClass|): R|kotlin/Unit| { - R|/jc|.# + R|/jc|.R|/JavaClass.field| } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/JavaVisibility2.kt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/JavaVisibility2.kt new file mode 100644 index 00000000000..bd143fb16da --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/JavaVisibility2.kt @@ -0,0 +1,62 @@ +// FILE: j/JavaPackageLocal.java +package j; + +public class JavaPackageLocal { + static void javaMPackage() {} + static int javaPPackage = 4; +} + +// FILE: j/JavaProtected.java +package j; + +public class JavaProtected { + protected static void javaMProtectedStatic() {} + protected static int javaPProtectedStatic = 4; + protected final int javaPProtectedPackage = 4; +} + +// FILE: k.kt +package k + +import j.JavaProtected +import j.JavaPackageLocal + +class A { + val p1 = JavaPackageLocal.javaPPackage + val p2 = JavaProtected.javaPProtectedStatic + val p3 = JavaProtected().javaPProtectedPackage + + fun test() { + JavaProtected.javaMProtectedStatic() + JavaPackageLocal.javaMPackage() + } +} + +class B : JavaProtected() { + val p1 = JavaPackageLocal.javaPPackage + val p2 = JavaProtected.javaPProtectedStatic + val p3 = javaPProtectedPackage + + fun test() { + JavaProtected.javaMProtectedStatic() + JavaPackageLocal.javaMPackage() + } +} + +// FILE: j.kt +package j + +import j.JavaProtected +import j.JavaPackageLocal + +class C { + val p1 = JavaPackageLocal.javaPPackage + val p2 = JavaProtected.javaPProtectedStatic + val p3 = JavaProtected().javaPProtectedPackage + + fun test() { + JavaProtected.javaMProtectedStatic() + JavaProtected.javaMProtectedStatic() + JavaPackageLocal.javaMPackage() + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/JavaVisibility2.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/JavaVisibility2.txt new file mode 100644 index 00000000000..978a421101f --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/JavaVisibility2.txt @@ -0,0 +1,63 @@ +FILE: k.kt + public final class A : R|kotlin/Any| { + public constructor(): R|k/A| { + super() + } + + public final val p1: = Q|j/JavaPackageLocal|.# + public get(): + + public final val p2: = Q|j/JavaProtected|.# + public get(): + + public final val p3: = R|j/JavaProtected.JavaProtected|().# + public get(): + + public final fun test(): R|kotlin/Unit| { + Q|j/JavaProtected|.#() + Q|j/JavaPackageLocal|.#() + } + + } + public final class B : R|j/JavaProtected| { + public constructor(): R|k/B| { + super() + } + + public final val p1: = Q|j/JavaPackageLocal|.# + public get(): + + public final val p2: R|kotlin/Int| = Q|j/JavaProtected|.R|j/JavaProtected.javaPProtectedStatic| + public get(): R|kotlin/Int| + + public final val p3: R|kotlin/Int| = this@R|j/JavaProtected|.R|j/JavaProtected.javaPProtectedPackage| + public get(): R|kotlin/Int| + + public final fun test(): R|kotlin/Unit| { + Q|j/JavaProtected|.R|j/JavaProtected.javaMProtectedStatic|() + Q|j/JavaPackageLocal|.#() + } + + } +FILE: j.kt + public final class C : R|kotlin/Any| { + public constructor(): R|j/C| { + super() + } + + public final val p1: R|kotlin/Int| = Q|j/JavaPackageLocal|.R|j/JavaPackageLocal.javaPPackage| + public get(): R|kotlin/Int| + + public final val p2: R|kotlin/Int| = Q|j/JavaProtected|.R|j/JavaProtected.javaPProtectedStatic| + public get(): R|kotlin/Int| + + public final val p3: R|kotlin/Int| = R|j/JavaProtected.JavaProtected|().R|j/JavaProtected.javaPProtectedPackage| + public get(): R|kotlin/Int| + + public final fun test(): R|kotlin/Unit| { + Q|j/JavaProtected|.R|j/JavaProtected.javaMProtectedStatic|() + Q|j/JavaProtected|.R|j/JavaProtected.javaMProtectedStatic|() + Q|j/JavaPackageLocal|.R|j/JavaPackageLocal.javaMPackage|() + } + + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index bac807efacf..3e869ee3d72 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -479,6 +479,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/expresssions/memberExtension.kt"); } + @TestMetadata("nestedVisibility.kt") + public void testNestedVisibility() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt"); + } + @TestMetadata("objectVsProperty.kt") public void testObjectVsProperty() throws Exception { runTest("compiler/fir/resolve/testData/resolve/expresssions/objectVsProperty.kt"); @@ -504,6 +509,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/expresssions/privateVisibility.kt"); } + @TestMetadata("protectedVisibility.kt") + public void testProtectedVisibility() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/expresssions/protectedVisibility.kt"); + } + @TestMetadata("qualifiedExpressions.kt") public void testQualifiedExpressions() throws Exception { runTest("compiler/fir/resolve/testData/resolve/expresssions/qualifiedExpressions.kt"); diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java index 299e57f9d50..1b142c5bf10 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java @@ -396,6 +396,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/FunctionTypeInJava.kt"); } + @TestMetadata("JavaVisibility2.kt") + public void testJavaVisibility2() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/JavaVisibility2.kt"); + } + @TestMetadata("KJKComplexHierarchy.kt") public void testKJKComplexHierarchy() throws Exception { runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/KJKComplexHierarchy.kt"); diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/IdeFirProvider.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/IdeFirProvider.kt index 475e28d654b..7c1ba8ac30e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/IdeFirProvider.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/IdeFirProvider.kt @@ -76,6 +76,11 @@ class IdeFirProvider( return cacheProvider.getFirClassifierContainerFile(fqName) } + override fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? { + getFirClassifierByFqName(fqName) + return cacheProvider.getFirClassifierContainerFileIfAny(fqName) + } + override fun getFirCallableContainerFile(symbol: FirCallableSymbol<*>): FirFile? { return cacheProvider.getFirCallableContainerFile(symbol) }