[FIR] Improve INVISIBLE_REFERENCE message

Report the nearest invisible containing declaration in cases where
the declaration itself is visible.

#KT-53820 Fixed
This commit is contained in:
Kirill Rakhman
2023-06-19 15:02:57 +02:00
committed by Space Team
parent 6a073e0b17
commit 911e62257a
24 changed files with 237 additions and 98 deletions
@@ -256,6 +256,8 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
add(FirErrors.INVISIBLE_REFERENCE) { firDiagnostic -> add(FirErrors.INVISIBLE_REFERENCE) { firDiagnostic ->
InvisibleReferenceImpl( InvisibleReferenceImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a), firSymbolBuilder.buildSymbol(firDiagnostic.a),
firDiagnostic.b,
firDiagnostic.c,
firDiagnostic as KtPsiDiagnostic, firDiagnostic as KtPsiDiagnostic,
token, token,
) )
@@ -220,6 +220,8 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
interface InvisibleReference : KtFirDiagnostic<PsiElement> { interface InvisibleReference : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = InvisibleReference::class override val diagnosticClass get() = InvisibleReference::class
val reference: KtSymbol val reference: KtSymbol
val visible: Visibility
val containingDeclaration: ClassId?
} }
interface UnresolvedReference : KtFirDiagnostic<PsiElement> { interface UnresolvedReference : KtFirDiagnostic<PsiElement> {
@@ -248,6 +248,8 @@ internal class InvisibleSetterImpl(
internal class InvisibleReferenceImpl( internal class InvisibleReferenceImpl(
override val reference: KtSymbol, override val reference: KtSymbol,
override val visible: Visibility,
override val containingDeclaration: ClassId?,
firDiagnostic: KtPsiDiagnostic, firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken, token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.InvisibleReference ) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.InvisibleReference
@@ -17,4 +17,4 @@ KtErrorCallInfo:
typeArgumentsMapping = {} typeArgumentsMapping = {}
argumentMapping = {} argumentMapping = {}
] ]
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol fun foo(): Unit is invisible> diagnostic = ERROR<INVISIBLE_REFERENCE: Cannot access 'fun foo(): Unit': it is private in '/A'>
@@ -16,7 +16,7 @@ KtInapplicableCallCandidateInfo:
isInBestCandidates = false isInBestCandidates = false
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol constructor(p: String): A is invisible> diagnostic = ERROR<INVISIBLE_REFERENCE: Cannot access 'constructor(p: String): A': it is private in '/A'>
candidate = KtDelegatedConstructorCall: candidate = KtDelegatedConstructorCall:
kind = SUPER_CALL kind = SUPER_CALL
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -1,5 +1,5 @@
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol fun foo(): Unit is invisible> diagnostic = ERROR<INVISIBLE_REFERENCE: Cannot access 'fun foo(): Unit': it is private in '/A'>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = false isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -53,7 +53,7 @@ FILE: nestedVisibility.kt
} }
public final fun foo(): R|kotlin/Unit| { public final fun foo(): R|kotlin/Unit| {
Q|Outer|.R|/Outer.PrivateNested.PrivateNested<HIDDEN: /Outer.PrivateNested.PrivateNested is invisible>#|() Q|Outer|.R|/Outer.PrivateNested.PrivateNested<HIDDEN: Outer.PrivateNested is invisible>#|()
this@R|/Derived|.super<R|Outer|>.R|/Outer.PrivateInner.PrivateInner<HIDDEN: /Outer.PrivateInner.PrivateInner is invisible>#|() this@R|/Derived|.super<R|Outer|>.R|/Outer.PrivateInner.PrivateInner<HIDDEN: /Outer.PrivateInner.PrivateInner is invisible>#|()
Q|Outer|.R|/Outer.ProtectedNested.ProtectedNested|() Q|Outer|.R|/Outer.ProtectedNested.ProtectedNested|()
this@R|/Derived|.super<R|Outer|>.R|/Outer.ProtectedInner.ProtectedInner|() this@R|/Derived|.super<R|Outer|>.R|/Outer.ProtectedInner.ProtectedInner|()
@@ -63,9 +63,9 @@ FILE: nestedVisibility.kt
} }
public final fun foo(): R|kotlin/Unit| { public final fun foo(): R|kotlin/Unit| {
Q|Outer|.R|/Outer.PrivateNested.PrivateNested<HIDDEN: /Outer.PrivateNested.PrivateNested is invisible>#|() Q|Outer|.R|/Outer.PrivateNested.PrivateNested<HIDDEN: Outer.PrivateNested is invisible>#|()
R|/Outer.Outer|().R|/Outer.PrivateInner.PrivateInner<HIDDEN: /Outer.PrivateInner.PrivateInner is invisible>#|() R|/Outer.Outer|().R|/Outer.PrivateInner.PrivateInner<HIDDEN: /Outer.PrivateInner.PrivateInner is invisible>#|()
Q|Outer|.R|/Outer.ProtectedNested.ProtectedNested<HIDDEN: /Outer.ProtectedNested.ProtectedNested is invisible>#|() Q|Outer|.R|/Outer.ProtectedNested.ProtectedNested<HIDDEN: Outer.ProtectedNested is invisible>#|()
R|/Outer.Outer|().R|/Outer.ProtectedInner.ProtectedInner<HIDDEN: /Outer.ProtectedInner.ProtectedInner is invisible>#|() R|/Outer.Outer|().R|/Outer.ProtectedInner.ProtectedInner<HIDDEN: /Outer.ProtectedInner.ProtectedInner is invisible>#|()
Q|Outer|.R|/Outer.PublicNested.PublicNested|() Q|Outer|.R|/Outer.PublicNested.PublicNested|()
R|/Outer.Outer|().R|/Outer.PublicInner.PublicInner|() R|/Outer.Outer|().R|/Outer.PublicInner.PublicInner|()
@@ -96,11 +96,11 @@ FILE: first.kt
R|/Private.Private|().R|/Private.baz|() R|/Private.Private|().R|/Private.baz|()
R|/Private.Private|().R|/Private.Inner.Inner|() R|/Private.Private|().R|/Private.Inner.Inner|()
R|/Private.Private|().R|/Private.bar<HIDDEN: /Private.bar is invisible>#|() R|/Private.Private|().R|/Private.bar<HIDDEN: /Private.bar is invisible>#|()
Q|Private|.R|/Private.Nested.Nested<HIDDEN: /Private.Nested.Nested is invisible>#|() Q|Private|.R|/Private.Nested.Nested<HIDDEN: Private.Nested is invisible>#|()
Q|Private|.R|/Private.Companion.fromCompanion<HIDDEN: /Private.Companion.fromCompanion is invisible>#|() Q|Private|.R|/Private.Companion.fromCompanion<HIDDEN: /Private.Companion.fromCompanion is invisible>#|()
} }
FILE: second.kt FILE: second.kt
public final fun secondTest(): R|kotlin/Unit| { public final fun secondTest(): R|kotlin/Unit| {
R|/foo<HIDDEN: /foo is invisible>#|() R|/foo<HIDDEN: /foo is invisible>#|()
R|/Private.Private<HIDDEN: /Private.Private is invisible>#|() R|/Private.Private<HIDDEN: Private is invisible>#|()
} }
@@ -80,7 +80,7 @@ FILE: protectedVisibility.kt
R|/Protected.Protected|().R|/Protected.baz|() R|/Protected.Protected|().R|/Protected.baz|()
R|/Protected.Protected|().R|/Protected.Inner.Inner|() R|/Protected.Protected|().R|/Protected.Inner.Inner|()
R|/Protected.Protected|().R|/Protected.bar<HIDDEN: /Protected.bar is invisible>#|() R|/Protected.Protected|().R|/Protected.bar<HIDDEN: /Protected.bar is invisible>#|()
Q|Protected|.R|/Protected.Nested.Nested<HIDDEN: /Protected.Nested.Nested is invisible>#|() Q|Protected|.R|/Protected.Nested.Nested<HIDDEN: Protected.Nested is invisible>#|()
} }
public open class Generic<T> : R|kotlin/Any| { public open class Generic<T> : R|kotlin/Any| {
public constructor<T>(x: R|T|): R|Generic<T>| { public constructor<T>(x: R|T|): R|Generic<T>| {
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -103,6 +104,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val UNRESOLVED by object : DiagnosticGroup("Unresolved") { val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
val INVISIBLE_REFERENCE by error<PsiElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) { val INVISIBLE_REFERENCE by error<PsiElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("reference") parameter<Symbol>("reference")
parameter<Visibility>("visible")
parameter<ClassId?>("containingDeclaration")
} }
val UNRESOLVED_REFERENCE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) { val UNRESOLVED_REFERENCE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
parameter<String>("reference") parameter<String>("reference")
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -147,7 +148,7 @@ object FirErrors {
val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
// Unresolved // Unresolved
val INVISIBLE_REFERENCE by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val INVISIBLE_REFERENCE by error3<PsiElement, FirBasedSymbol<*>, Visibility, ClassId?>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val UNRESOLVED_REFERENCE by error1<PsiElement, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val UNRESOLVED_REFERENCE by error1<PsiElement, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val UNRESOLVED_LABEL by error0<PsiElement>(SourceElementPositioningStrategies.LABEL) val UNRESOLVED_LABEL by error0<PsiElement>(SourceElementPositioningStrategies.LABEL)
val DESERIALIZATION_ERROR by error0<PsiElement>() val DESERIALIZATION_ERROR by error0<PsiElement>()
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.toInvisibleReferenceDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
@@ -176,12 +177,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
} }
} }
is ConeVisibilityError -> { is ConeVisibilityError -> {
reporter.reportOn( reporter.report(diagnostic.symbol.toInvisibleReferenceDiagnostic(property.source), context)
property.source,
FirErrors.INVISIBLE_REFERENCE,
diagnostic.symbol,
context,
)
} }
else -> error("Unhandled error during a component function call") else -> error("Unhandled error during a component function call")
} }
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirDeprecationChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirDeprecationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.toInvisibleReferenceDiagnostic
import org.jetbrains.kotlin.fir.analysis.getSourceForImportSegment import org.jetbrains.kotlin.fir.analysis.getSourceForImportSegment
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
@@ -75,7 +76,7 @@ object FirImportsChecker : FirFileChecker() {
fun reportInvisibleParentClasses(classSymbol: FirRegularClassSymbol, depth: Int) { fun reportInvisibleParentClasses(classSymbol: FirRegularClassSymbol, depth: Int) {
if (!classSymbol.fir.isVisible(context)) { if (!classSymbol.fir.isVisible(context)) {
val source = import.getSourceForImportSegment(indexFromLast = depth) val source = import.getSourceForImportSegment(indexFromLast = depth)
reporter.reportOn(source, FirErrors.INVISIBLE_REFERENCE, classSymbol, context) reporter.report(classSymbol.toInvisibleReferenceDiagnostic(source), context)
} }
classSymbol.classId.outerClassId?.resolveToClass(context)?.let { reportInvisibleParentClasses(it, depth + 1) } classSymbol.classId.outerClassId?.resolveToClass(context)?.let { reportInvisibleParentClasses(it, depth + 1) }
@@ -87,7 +88,7 @@ object FirImportsChecker : FirFileChecker() {
ImportStatus.OK -> return ImportStatus.OK -> return
is ImportStatus.Invisible -> { is ImportStatus.Invisible -> {
val source = import.getSourceForImportSegment(0) val source = import.getSourceForImportSegment(0)
reporter.reportOn(source, FirErrors.INVISIBLE_REFERENCE, status.symbol, context) reporter.report(status.symbol.toInvisibleReferenceDiagnostic(source), context)
} }
else -> { else -> {
val classId = parentClassSymbol.classId.createNestedClassId(importedName) val classId = parentClassSymbol.classId.createNestedClassId(importedName)
@@ -128,7 +129,7 @@ object FirImportsChecker : FirFileChecker() {
resolvedDeclaration?.let { resolvedDeclaration?.let {
val source = import.getSourceForImportSegment(0) ?: import.source val source = import.getSourceForImportSegment(0) ?: import.source
reporter.reportOn(source, FirErrors.INVISIBLE_REFERENCE, it.symbol, context) reporter.report(it.symbol.toInvisibleReferenceDiagnostic(source), context)
return return
} }
@@ -6,10 +6,9 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.toInvisibleReferenceDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.expressions.FirErrorResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirErrorResolvedQualifier
@@ -45,7 +44,7 @@ object FirVisibilityQualifierChecker : FirResolvedQualifierChecker() {
) )
) { ) {
if (expression !is FirErrorResolvedQualifier || expression.diagnostic !is ConeVisibilityError) { if (expression !is FirErrorResolvedQualifier || expression.diagnostic !is ConeVisibilityError) {
reporter.reportOn(expression.source, FirErrors.INVISIBLE_REFERENCE, symbol, context) reporter.report(symbol.toInvisibleReferenceDiagnostic(expression.source), context)
} }
return return
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.renderReadableWithFqNames import org.jetbrains.kotlin.fir.types.renderReadableWithFqNames
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
object FirDiagnosticRenderers { object FirDiagnosticRenderers {
@OptIn(SymbolInternals::class) @OptIn(SymbolInternals::class)
@@ -148,7 +149,10 @@ object FirDiagnosticRenderers {
} }
val NAME_OF_CONTAINING_DECLARATION_OR_FILE = Renderer { symbol: CallableId -> val NAME_OF_CONTAINING_DECLARATION_OR_FILE = Renderer { symbol: CallableId ->
val classId = symbol.classId NAME_OF_DECLARATION_OR_FILE.render(symbol.classId)
}
val NAME_OF_DECLARATION_OR_FILE = Renderer { classId: ClassId? ->
if (classId == null) { if (classId == null) {
"file" "file"
} else { } else {
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FUNC
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS_ON_NEWLINE_WITH_INDENT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS_ON_NEWLINE_WITH_INDENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.MODULE_DATA import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.MODULE_DATA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME_OF_CONTAINING_DECLARATION_OR_FILE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME_OF_CONTAINING_DECLARATION_OR_FILE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME_OF_DECLARATION_OR_FILE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_COLLECTION_OF_TYPES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_COLLECTION_OF_TYPES
@@ -704,7 +705,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(NULL_FOR_NONNULL_TYPE, "Null can not be a value of a non-null type") map.put(NULL_FOR_NONNULL_TYPE, "Null can not be a value of a non-null type")
// Unresolved // Unresolved
map.put(INVISIBLE_REFERENCE, "Symbol {0} is invisible", SYMBOL) map.put(INVISIBLE_REFERENCE, "Cannot access ''{0}'': it is {1} in {2}", SYMBOL, VISIBILITY, NAME_OF_DECLARATION_OR_FILE)
map.put( map.put(
INVISIBLE_SETTER, INVISIBLE_SETTER,
"Cannot access ''{0}'': it is {1} in {2}", "Cannot access ''{0}'': it is {1} in {2}",
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isInfix import org.jetbrains.kotlin.fir.declarations.utils.isInfix
import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isOperator import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.diagnostics.*
@@ -27,6 +28,7 @@ import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPo
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstraintPosition import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeLambdaArgumentConstraintPosition import org.jetbrains.kotlin.fir.resolve.inference.model.ConeLambdaArgumentConstraintPosition
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
@@ -40,6 +42,7 @@ import org.jetbrains.kotlin.types.EmptyIntersectionTypeKind
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
private fun ConeDiagnostic.toKtDiagnostic( private fun ConeDiagnostic.toKtDiagnostic(
source: KtSourceElement, source: KtSourceElement,
@@ -73,7 +76,7 @@ private fun ConeDiagnostic.toKtDiagnostic(
) )
} }
is ConeVisibilityError -> FirErrors.INVISIBLE_REFERENCE.createOn(source, this.symbol) is ConeVisibilityError -> symbol.toInvisibleReferenceDiagnostic(source)
is ConeInapplicableWrongReceiver -> FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER.createOn(source, this.candidateSymbols) is ConeInapplicableWrongReceiver -> FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER.createOn(source, this.candidateSymbols)
is ConeNoCompanionObject -> FirErrors.NO_COMPANION_OBJECT.createOn(source, this.candidateSymbol as FirClassLikeSymbol<*>) is ConeNoCompanionObject -> FirErrors.NO_COMPANION_OBJECT.createOn(source, this.candidateSymbol as FirClassLikeSymbol<*>)
is ConeAmbiguityError -> when { is ConeAmbiguityError -> when {
@@ -150,6 +153,12 @@ private fun ConeDiagnostic.toKtDiagnostic(
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}") else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
} }
fun FirBasedSymbol<*>.toInvisibleReferenceDiagnostic(source: KtSourceElement?): KtDiagnostic? = when (val symbol = this) {
is FirCallableSymbol<*> -> FirErrors.INVISIBLE_REFERENCE.createOn(source, symbol, symbol.visibility, symbol.callableId.classId)
is FirClassLikeSymbol<*> -> FirErrors.INVISIBLE_REFERENCE.createOn(source, symbol, symbol.visibility, symbol.classId.outerClassId)
else -> shouldNotBeCalled("Unexpected receiver $javaClass")
}
fun ConeDiagnostic.toFirDiagnostics( fun ConeDiagnostic.toFirDiagnostics(
session: FirSession, session: FirSession,
source: KtSourceElement, source: KtSourceElement,
@@ -130,13 +130,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
supertypeSupplier supertypeSupplier
) )
} }
val parentClass = declaration.containingNonLocalClass( return declaration.parentDeclarationSequence(session, dispatchReceiver, containingDeclarations, supertypeSupplier)?.all { parent ->
session,
dispatchReceiver,
containingDeclarations,
supertypeSupplier
) ?: return true
return generateSequence(parentClass) { it.containingNonLocalClass(session) }.all { parent ->
isSpecificDeclarationVisible( isSpecificDeclarationVisible(
parent, parent,
session, session,
@@ -146,7 +140,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
isCallToPropertySetter, isCallToPropertySetter,
supertypeSupplier supertypeSupplier
) )
} } ?: true
} }
fun isVisibleForOverriding( fun isVisibleForOverriding(
@@ -169,51 +163,6 @@ abstract class FirVisibilityChecker : FirSessionComponent {
else -> platformOverrideVisibilityCheck(symbolFromDerivedClass, candidateInBaseClass.symbol, candidateInBaseClass.visibility) else -> platformOverrideVisibilityCheck(symbolFromDerivedClass, candidateInBaseClass.symbol, candidateInBaseClass.visibility)
} }
private fun FirMemberDeclaration.containingNonLocalClass(
session: FirSession,
dispatchReceiver: FirExpression?,
containingUseSiteDeclarations: List<FirDeclaration>,
supertypeSupplier: SupertypeSupplier
): FirClassLikeDeclaration? {
return when (this) {
is FirCallableDeclaration -> {
if (dispatchReceiver != null) {
val baseReceiverType = dispatchReceiverClassTypeOrNull()
if (baseReceiverType != null) {
dispatchReceiver.typeRef.coneType.findClassRepresentation(baseReceiverType, session)?.toSymbol(session)?.fir?.let {
return it
}
}
}
val containingLookupTag = this.containingClassLookupTag()
val containingClass = containingLookupTag?.toSymbol(session)?.fir
if (isStatic && containingClass != null) {
containingUseSiteDeclarations.firstNotNullOfOrNull {
if (it !is FirClass) return@firstNotNullOfOrNull null
it.takeIf { it.isSubclassOf(containingLookupTag, session, isStrict = false, supertypeSupplier) }
}?.let { return it }
}
containingClass
}
is FirClassLikeDeclaration -> containingNonLocalClass(session)
}
}
private fun FirClassLikeDeclaration.containingNonLocalClass(session: FirSession): FirClassLikeDeclaration? {
return when (this) {
is FirClass -> {
if (isLocal) return null
this.classId.outerClassId?.let { session.symbolProvider.getClassLikeSymbolByClassId(it)?.fir }
}
// Currently, type aliases are only top-level
is FirTypeAlias -> null
}
}
private fun isSpecificDeclarationVisible( private fun isSpecificDeclarationVisible(
declaration: FirMemberDeclaration, declaration: FirMemberDeclaration,
session: FirSession, session: FirSession,
@@ -521,3 +470,65 @@ fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? {
fun FirBasedSymbol<*>.isVariableOrNamedFunction(): Boolean { fun FirBasedSymbol<*>.isVariableOrNamedFunction(): Boolean {
return this is FirVariableSymbol || this is FirNamedFunctionSymbol || this is FirPropertyAccessorSymbol return this is FirVariableSymbol || this is FirNamedFunctionSymbol || this is FirPropertyAccessorSymbol
} }
fun FirMemberDeclaration.parentDeclarationSequence(
session: FirSession,
dispatchReceiver: FirExpression?,
containingDeclarations: List<FirDeclaration>,
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default,
): Sequence<FirClassLikeDeclaration>? {
val parentClass = containingNonLocalClass(
session,
dispatchReceiver,
containingDeclarations,
supertypeSupplier
) ?: return null
return generateSequence(parentClass) { it.containingNonLocalClass(session) }
}
private fun FirMemberDeclaration.containingNonLocalClass(
session: FirSession,
dispatchReceiver: FirExpression?,
containingUseSiteDeclarations: List<FirDeclaration>,
supertypeSupplier: SupertypeSupplier
): FirClassLikeDeclaration? {
return when (this) {
is FirCallableDeclaration -> {
if (dispatchReceiver != null) {
val baseReceiverType = dispatchReceiverClassTypeOrNull()
if (baseReceiverType != null) {
dispatchReceiver.typeRef.coneType.findClassRepresentation(baseReceiverType, session)?.toSymbol(session)?.fir?.let {
return it
}
}
}
val containingLookupTag = this.containingClassLookupTag()
val containingClass = containingLookupTag?.toSymbol(session)?.fir
if (isStatic && containingClass != null) {
containingUseSiteDeclarations.firstNotNullOfOrNull {
if (it !is FirClass) return@firstNotNullOfOrNull null
it.takeIf { it.isSubclassOf(containingLookupTag, session, isStrict = false, supertypeSupplier) }
}?.let { return it }
}
containingClass
}
is FirClassLikeDeclaration -> containingNonLocalClass(session)
}
}
private fun FirClassLikeDeclaration.containingNonLocalClass(session: FirSession): FirClassLikeDeclaration? {
return when (this) {
is FirClass -> {
if (isLocal) return null
this.classId.outerClassId?.let { session.symbolProvider.getClassLikeSymbolByClassId(it)?.fir }
}
// Currently, type aliases are only top-level
is FirTypeAlias -> null
}
}
@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference
import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.FirPropertyWithExplicitBackingFieldResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
import org.jetbrains.kotlin.fir.resolve.dfa.PropertyStability import org.jetbrains.kotlin.fir.resolve.dfa.PropertyStability
import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
@@ -193,7 +190,7 @@ fun BodyResolveComponents.buildResolvedQualifierForClass(
typeArgumentsForQualifier: List<FirTypeProjection> = emptyList(), typeArgumentsForQualifier: List<FirTypeProjection> = emptyList(),
diagnostic: ConeDiagnostic? = null, diagnostic: ConeDiagnostic? = null,
nonFatalDiagnostics: List<ConeDiagnostic> = emptyList(), nonFatalDiagnostics: List<ConeDiagnostic> = emptyList(),
annotations: List<FirAnnotation> = emptyList() annotations: List<FirAnnotation> = emptyList(),
): FirResolvedQualifier { ): FirResolvedQualifier {
val classId = regularClass.classId val classId = regularClass.classId
@@ -370,7 +367,7 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: FirBasedSymbol<*>, make
} }
fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo( fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
qualifiedAccessExpression: FirQualifiedAccessExpression qualifiedAccessExpression: FirQualifiedAccessExpression,
): FirExpression { ): FirExpression {
val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression) val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression)
?: return qualifiedAccessExpression ?: return qualifiedAccessExpression
@@ -379,7 +376,7 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
} }
fun BodyResolveComponents.transformWhenSubjectExpressionUsingSmartcastInfo( fun BodyResolveComponents.transformWhenSubjectExpressionUsingSmartcastInfo(
whenSubjectExpression: FirWhenSubjectExpression whenSubjectExpression: FirWhenSubjectExpression,
): FirExpression { ): FirExpression {
val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(whenSubjectExpression) val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(whenSubjectExpression)
?: return whenSubjectExpression ?: return whenSubjectExpression
@@ -388,7 +385,7 @@ fun BodyResolveComponents.transformWhenSubjectExpressionUsingSmartcastInfo(
} }
fun BodyResolveComponents.transformDesugaredAssignmentValueUsingSmartcastInfo( fun BodyResolveComponents.transformDesugaredAssignmentValueUsingSmartcastInfo(
expression: FirDesugaredAssignmentValueReferenceExpression expression: FirDesugaredAssignmentValueReferenceExpression,
): FirExpression { ): FirExpression {
val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(expression.expressionRef.value) val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(expression.expressionRef.value)
?: return expression ?: return expression
@@ -410,7 +407,7 @@ private fun FirSmartCastExpressionBuilder.applyResultTypeRef() {
private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSmartcastInfo( private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSmartcastInfo(
expression: T, expression: T,
stability: PropertyStability, stability: PropertyStability,
typesFromSmartCast: MutableList<ConeKotlinType> typesFromSmartCast: MutableList<ConeKotlinType>,
): FirSmartCastExpression? { ): FirSmartCastExpression? {
val smartcastStability = stability.impliedSmartcastStability val smartcastStability = stability.impliedSmartcastStability
?: if (dataFlowAnalyzer.isAccessToUnstableLocalVariable(expression)) { ?: if (dataFlowAnalyzer.isAccessToUnstableLocalVariable(expression)) {
@@ -477,7 +474,7 @@ private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSm
fun FirCheckedSafeCallSubject.propagateTypeFromOriginalReceiver( fun FirCheckedSafeCallSubject.propagateTypeFromOriginalReceiver(
nullableReceiverExpression: FirExpression, nullableReceiverExpression: FirExpression,
session: FirSession, session: FirSession,
file: FirFile file: FirFile,
) { ) {
// If the receiver expression is smartcast to `null`, it would have `Nothing?` as its type, which may not have members called by user // If the receiver expression is smartcast to `null`, it would have `Nothing?` as its type, which may not have members called by user
// code. Hence, we fallback to the type before intersecting with `Nothing?`. // code. Hence, we fallback to the type before intersecting with `Nothing?`.
@@ -555,7 +552,7 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(
session: FirSession, session: FirSession,
// NB: with originScope given this function will try to find overridden declaration with allowed parameter names // NB: with originScope given this function will try to find overridden declaration with allowed parameter names
// for intersection/substitution overrides // for intersection/substitution overrides
originScope: FirTypeScope? = null originScope: FirTypeScope? = null,
): ForbiddenNamedArgumentsTarget? { ): ForbiddenNamedArgumentsTarget? {
if (hasStableParameterNames) return null if (hasStableParameterNames) return null
@@ -602,11 +599,36 @@ fun FirExpression?.isIntegerLiteralOrOperatorCall(): Boolean {
fun createConeDiagnosticForCandidateWithError( fun createConeDiagnosticForCandidateWithError(
applicability: CandidateApplicability, applicability: CandidateApplicability,
candidate: Candidate candidate: Candidate,
): ConeDiagnostic { ): ConeDiagnostic {
return when (applicability) { return when (applicability) {
CandidateApplicability.HIDDEN -> ConeHiddenCandidateError(candidate) CandidateApplicability.HIDDEN -> ConeHiddenCandidateError(candidate)
CandidateApplicability.K2_VISIBILITY_ERROR -> ConeVisibilityError(candidate.symbol) CandidateApplicability.K2_VISIBILITY_ERROR -> {
val session = candidate.callInfo.session
val declaration = candidate.symbol.fir
if (declaration is FirMemberDeclaration &&
session.visibilityChecker.isVisible(declaration, candidate, skipCheckForContainingClassVisibility = true)
) {
// We can have declarations that are visible by themselves, but some containing declaration is invisible.
// We report the nearest invisible containing declaration, otherwise we'll get a confusing diagnostic like
// Cannot access 'foo', it is public in 'Bar'.
declaration
.parentDeclarationSequence(session, candidate.dispatchReceiver, candidate.callInfo.containingDeclarations)
?.firstOrNull {
!session.visibilityChecker.isVisible(
it,
session,
candidate.callInfo.containingFile,
candidate.callInfo.containingDeclarations,
dispatchReceiver = null,
skipCheckForContainingClassVisibility = true,
)
}?.let {
return ConeVisibilityError(it.symbol)
}
}
ConeVisibilityError(candidate.symbol)
}
CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER -> ConeInapplicableWrongReceiver(listOf(candidate)) CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER -> ConeInapplicableWrongReceiver(listOf(candidate))
CandidateApplicability.K2_NO_COMPANION_OBJECT -> ConeNoCompanionObject(candidate) CandidateApplicability.K2_NO_COMPANION_OBJECT -> ConeNoCompanionObject(candidate)
else -> ConeInapplicableCandidateError(applicability, candidate) else -> ConeInapplicableCandidateError(applicability, candidate)
@@ -29,7 +29,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun FirVisibilityChecker.isVisible( fun FirVisibilityChecker.isVisible(
declaration: FirMemberDeclaration, declaration: FirMemberDeclaration,
callInfo: CallInfo, callInfo: CallInfo,
dispatchReceiver: FirExpression? dispatchReceiver: FirExpression?,
skipCheckForContainingClassVisibility: Boolean = false,
): Boolean { ): Boolean {
val staticQualifierForCallable = runIf( val staticQualifierForCallable = runIf(
declaration is FirCallableDeclaration && declaration is FirCallableDeclaration &&
@@ -50,28 +51,30 @@ fun FirVisibilityChecker.isVisible(
callInfo.containingDeclarations, callInfo.containingDeclarations,
dispatchReceiver, dispatchReceiver,
staticQualifierClassForCallable = staticQualifierForCallable, staticQualifierClassForCallable = staticQualifierForCallable,
isCallToPropertySetter = callInfo.callSite is FirVariableAssignment isCallToPropertySetter = callInfo.callSite is FirVariableAssignment,
skipCheckForContainingClassVisibility = skipCheckForContainingClassVisibility,
) )
} }
fun FirVisibilityChecker.isVisible( fun FirVisibilityChecker.isVisible(
declaration: FirMemberDeclaration, declaration: FirMemberDeclaration,
candidate: Candidate candidate: Candidate,
skipCheckForContainingClassVisibility: Boolean = false,
): Boolean { ): Boolean {
val callInfo = candidate.callInfo val callInfo = candidate.callInfo
if (!isVisible(declaration, callInfo, candidate.dispatchReceiver)) { if (!isVisible(declaration, callInfo, candidate.dispatchReceiver, skipCheckForContainingClassVisibility)) {
val dispatchReceiverWithoutSmartCastType = val dispatchReceiverWithoutSmartCastType =
removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiver, candidate.callInfo.session) ?: return false removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiver, candidate.callInfo.session) ?: return false
if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType)) return false if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType, skipCheckForContainingClassVisibility)) return false
candidate.dispatchReceiver = dispatchReceiverWithoutSmartCastType candidate.dispatchReceiver = dispatchReceiverWithoutSmartCastType
} }
val backingField = declaration.getBackingFieldIfApplicable() val backingField = declaration.getBackingFieldIfApplicable()
if (backingField != null) { if (backingField != null) {
candidate.hasVisibleBackingField = isVisible(backingField, callInfo, candidate.dispatchReceiver) candidate.hasVisibleBackingField = isVisible(backingField, callInfo, candidate.dispatchReceiver, skipCheckForContainingClassVisibility)
} }
return true return true
@@ -0,0 +1,46 @@
/b.kt:34:10: error: cannot access 'B': it is private in file
import a.B
^
/b.kt:35:10: error: cannot access 'B': it is private in file
import a.B.Companion.bar
^
/b.kt:37:12: error: cannot access 'Companion': it is private in 'C'
import a.C.Companion.baz
^
/b.kt:38:10: error: cannot access 'D': it is private in file
import a.D
^
/b.kt:39:10: error: cannot access 'D': it is private in file
import a.D.Companion.quux
^
/b.kt:39:12: error: cannot access 'Companion': it is private in 'D'
import a.D.Companion.quux
^
/b.kt:43:7: error: cannot access 'B': it is private in file
f(B)
^
/b.kt:44:7: error: cannot access 'Companion': it is private in 'C'
f(C)
^
/b.kt:45:7: error: cannot access 'Companion': it is private in 'D'
f(D)
^
/b.kt:48:5: error: cannot access 'B': it is private in file
B.bar()
^
/b.kt:48:7: error: cannot access 'B': it is private in file
B.bar()
^
/b.kt:49:7: error: cannot access 'Companion': it is private in 'C'
C.baz()
^
/b.kt:50:5: error: cannot access 'D': it is private in file
D.quux()
^
/b.kt:50:7: error: cannot access 'Companion': it is private in 'D'
D.quux()
^
/b.kt:53:9: error: cannot access 'Companion': it is private in 'C'
a.C.baz()
^
@@ -0,0 +1,27 @@
/b.kt:(96,97): error: Cannot access 'class B : Any': it is private in file
/b.kt:(107,108): error: Cannot access 'class B : Any': it is private in file
/b.kt:(145,154): error: Cannot access 'companion object Companion : Any': it is private in 'a/C'
/b.kt:(168,169): error: Cannot access 'class D : Any': it is private in file
/b.kt:(179,180): error: Cannot access 'class D : Any': it is private in file
/b.kt:(181,190): error: Cannot access 'companion object Companion : Any': it is private in 'a/D'
/b.kt:(225,226): error: Cannot access 'class B : Any': it is private in file
/b.kt:(243,244): error: Cannot access 'class D : Any': it is private in file
/b.kt:(263,264): error: Cannot access 'class B : Any': it is private in file
/b.kt:(265,268): error: Cannot access 'class B : Any': it is private in file
/b.kt:(277,280): error: Cannot access 'companion object Companion : Any': it is private in 'a/C'
/b.kt:(287,288): error: Cannot access 'class D : Any': it is private in file
/b.kt:(289,293): error: Cannot access 'companion object Companion : Any': it is private in 'a/D'
/b.kt:(319,322): error: Cannot access 'companion object Companion : Any': it is private in 'a/C'
@@ -1,3 +1,4 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
//FILE:a.kt //FILE:a.kt
package a package a
@@ -29,9 +30,13 @@ private class D {
package b package b
import a.A import a.A
import a.A.Companion.foo
import a.<!INVISIBLE_REFERENCE!>B<!> import a.<!INVISIBLE_REFERENCE!>B<!>
import a.<!INVISIBLE_REFERENCE!>B<!>.Companion.bar
import a.C import a.C
import a.C.<!INVISIBLE_REFERENCE!>Companion<!>.baz
import a.<!INVISIBLE_REFERENCE!>D<!> import a.<!INVISIBLE_REFERENCE!>D<!>
import a.<!INVISIBLE_REFERENCE!>D<!>.<!INVISIBLE_REFERENCE!>Companion<!>.quux
fun test() { fun test() {
f(A) f(A)
@@ -1,3 +1,4 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
//FILE:a.kt //FILE:a.kt
package a package a
@@ -29,9 +30,13 @@ private class D {
package b package b
import a.A import a.A
import a.A.Companion.foo
import a.<!INVISIBLE_REFERENCE!>B<!> import a.<!INVISIBLE_REFERENCE!>B<!>
import a.<!INVISIBLE_REFERENCE!>B<!>.Companion.bar
import a.C import a.C
import a.C.<!INVISIBLE_REFERENCE!>Companion<!>.baz
import a.<!INVISIBLE_REFERENCE!>D<!> import a.<!INVISIBLE_REFERENCE!>D<!>
import a.<!INVISIBLE_REFERENCE!>D<!>.<!INVISIBLE_REFERENCE!>Companion<!>.quux
fun test() { fun test() {
f(A) f(A)