diff --git a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionParameterType.kt b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionParameterType.kt index b2deaa3dc3f..8ef3a57267c 100644 --- a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionParameterType.kt +++ b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionParameterType.kt @@ -3,7 +3,7 @@ class A { } class B { - fun foo(value: A.AInner) { + fun foo(value: A.AInner) { } } diff --git a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionReturnType.kt b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionReturnType.kt index 6e081a5c914..6d55e5f9233 100644 --- a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionReturnType.kt +++ b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionReturnType.kt @@ -5,7 +5,7 @@ class A { } abstract class B { - fun foo(str: String): A.InnerA + fun foo(str: String): A.InnerA } private enum class Some { diff --git a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedPropertyType.kt b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedPropertyType.kt index 79568459bb7..f21ace347e3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedPropertyType.kt +++ b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedPropertyType.kt @@ -17,7 +17,7 @@ class Property { var var1: String var var2: String var var3: Int - var var4: A.AInnerPrivate + var var4: A.AInnerPrivate var var5: A.AInnerPublic - var var6: A.AInnerProtectedEnum + var var6: A.AInnerProtectedEnum } diff --git a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedSupertype.kt b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedSupertype.kt index 5177fb499e3..3b73f5eba39 100644 --- a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedSupertype.kt +++ b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedSupertype.kt @@ -46,7 +46,7 @@ class Test3 : C.CPublicI, A.AProtectedI { +class Test4 : E, A.AProtectedI { } diff --git a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt index 6be2753e91a..0c2f697ca2f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt +++ b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt @@ -2,7 +2,7 @@ class A { private inner class Inner } class B { - typealias AInner = A.Inner + typealias AInner = A.Inner inner class Inner } @@ -10,7 +10,7 @@ class C { typealias BInner = B.Inner } -typealias AInner0 = A.Inner +typealias AInner0 = A.Inner typealias BInner0 = B.Inner private typealias MyString = String diff --git a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeParameters.kt b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeParameters.kt index 3c242d65565..1bfb260b009 100644 --- a/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeParameters.kt +++ b/compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeParameters.kt @@ -15,7 +15,7 @@ public class Test1A> public class Test2 // invalid, D is protected -public class Test3C.D> +public class Test3C.D> // valid, B is internal internal class Test4 @@ -32,4 +32,4 @@ public class Container : C { } // invalid, A is private, B is internal, D is protected -public interface Test8A, P: B, F: C, N: C.D, M: E> +public interface Test8A, P: B, F: C, N: C.D, M: E> diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index f02eff96a2d..95ee0ae05f5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -91,6 +91,7 @@ private fun ConeDiagnostic.toKtDiagnostic( ) } + is ConeTypeVisibilityError -> symbol.toInvisibleReferenceDiagnostic(smallestUnresolvablePrefix.last().source) is ConeVisibilityError -> symbol.toInvisibleReferenceDiagnostic(source) is ConeInapplicableWrongReceiver -> FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER.createOn(source, this.candidateSymbols) is ConeNoCompanionObject -> FirErrors.NO_COMPANION_OBJECT.createOn(source, this.candidateSymbol as FirClassLikeSymbol<*>) @@ -175,7 +176,7 @@ private val KtFakeSourceElementKind.canBeIgnored: Boolean get() = this == KtFakeSourceElementKind.DelegatingConstructorCall || this == KtFakeSourceElementKind.ErrorTypeRef -fun FirBasedSymbol<*>.toInvisibleReferenceDiagnostic(source: KtSourceElement?): KtDiagnostic? = when (val symbol = this) { +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") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt index 811ccd16903..b13f4674823 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt @@ -20,8 +20,10 @@ import org.jetbrains.kotlin.fir.recordTypeLookup import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.FirTypeResolutionResult import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeTypeVisibilityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedTypeQualifierError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedDefaultValueInFunctionType +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeVisibilityError import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.typeResolver @@ -148,16 +150,10 @@ class FirSpecificTypeResolverTransformer( ): FirResolvedTypeRef { return when { resolvedType is ConeErrorType -> { - buildErrorType(typeRef, resolvedType, scopeClassDeclaration) + buildErrorType(typeRef, resolvedType, resolvedType.diagnostic, scopeClassDeclaration) } diagnostic != null -> { - buildErrorTypeRef { - source = typeRef.source - this.diagnostic = diagnostic - type = resolvedType - delegatedTypeRef = typeRef - partiallyResolvedTypeRef = tryCalculatingPartiallyResolvedTypeRef(typeRef, scopeClassDeclaration) - } + buildErrorType(typeRef, resolvedType, diagnostic, scopeClassDeclaration) } else -> { buildResolvedTypeRef { @@ -172,11 +168,11 @@ class FirSpecificTypeResolverTransformer( private fun buildErrorType( typeRef: FirTypeRef, - resolvedType: ConeErrorType, + resolvedType: ConeKotlinType, + diagnostic: ConeDiagnostic, scopeClassDeclaration: ScopeClassDeclaration, ): FirErrorTypeRef { return buildErrorTypeRef { - var diagnostic = resolvedType.diagnostic val typeRefSourceKind = typeRef.source?.kind val diagnosticSource = (diagnostic as? ConeUnexpectedTypeArgumentsError)?.source @@ -192,22 +188,45 @@ class FirSpecificTypeResolverTransformer( delegatedTypeRef = typeRef type = resolvedType + val partiallyResolvedTypeRef = tryCalculatingPartiallyResolvedTypeRef(typeRef, scopeClassDeclaration) this.partiallyResolvedTypeRef = partiallyResolvedTypeRef - if (diagnostic is ConeUnresolvedTypeQualifierError) { - val totalQualifierCount = diagnostic.qualifiers.size - val resolvedQualifierCount = (partiallyResolvedTypeRef?.delegatedTypeRef as? FirUserTypeRef)?.qualifier?.size - ?: calculatePartiallyResolvablePackageSegments(diagnostic.qualifiers) - - val unresolvedQualifierCount = totalQualifierCount - resolvedQualifierCount - - if (unresolvedQualifierCount > 1) { - diagnostic = ConeUnresolvedTypeQualifierError(diagnostic.qualifiers.dropLast(unresolvedQualifierCount - 1), false) + this.diagnostic = when { + diagnostic is ConeUnresolvedTypeQualifierError -> { + ConeUnresolvedTypeQualifierError(smallestUnresolvablePrefix(diagnostic.qualifiers, partiallyResolvedTypeRef), diagnostic.isNullable) } + diagnostic is ConeVisibilityError && typeRef is FirUserTypeRef -> { + ConeTypeVisibilityError(diagnostic.symbol, smallestUnresolvablePrefix(typeRef.qualifier, partiallyResolvedTypeRef)) + } + else -> diagnostic } + } + } - this.diagnostic = diagnostic + /** + * Returns the smallest non-resolvable prefix of the given [qualifiers]. + * + * Examples: + * + * - Given `A.B.C` and `A.B` can be resolved, then `A.B.C` will be returned + * - Given `A.B.C` and `A` cannot be resolved, then `A` will be returned + * - Given `a.b.C` and package `a` exists but package `a.b` doesn't exist, `a.b.` will be returned. + */ + private fun smallestUnresolvablePrefix( + qualifiers: List, + partiallyResolvedTypeRef: FirResolvedTypeRef?, + ): List { + val totalQualifierCount = qualifiers.size + val resolvedQualifierCount = (partiallyResolvedTypeRef?.delegatedTypeRef as? FirUserTypeRef)?.qualifier?.size + ?: calculatePartiallyResolvablePackageSegments(qualifiers) + + val unresolvedQualifierCount = totalQualifierCount - resolvedQualifierCount + + return if (unresolvedQualifierCount > 1) { + qualifiers.dropLast(unresolvedQualifierCount - 1) + } else { + qualifiers } } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt index 58bff5ba96b..139db9f9489 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt @@ -104,12 +104,17 @@ class ConeHiddenCandidateError( override val reason: String get() = "HIDDEN: ${describeSymbol(candidateSymbol)} is deprecated with DeprecationLevel.HIDDEN" } -class ConeVisibilityError( +open class ConeVisibilityError( override val symbol: FirBasedSymbol<*> ) : ConeDiagnosticWithSymbol> { override val reason: String get() = "HIDDEN: ${describeSymbol(symbol)} is invisible" } +class ConeTypeVisibilityError( + symbol: FirBasedSymbol<*>, + val smallestUnresolvablePrefix: List, +) : ConeVisibilityError(symbol) + class ConeInapplicableWrongReceiver(override val candidates: Collection) : ConeDiagnosticWithCandidates { override val reason: String get() = "None of the following candidates is applicable because of receiver type mismatch: ${ diff --git a/compiler/testData/diagnostics/tests/imports/ImportProtectedClass.fir.kt b/compiler/testData/diagnostics/tests/imports/ImportProtectedClass.fir.kt deleted file mode 100644 index db91b0b2d13..00000000000 --- a/compiler/testData/diagnostics/tests/imports/ImportProtectedClass.fir.kt +++ /dev/null @@ -1,14 +0,0 @@ -package p - -import p.Foo.Nested - -open class Foo { - protected class Nested -} - -class Bar: Foo() { - protected fun foo(): Nested? = null -} - -private fun foo(): Nested? = null -private fun bar(): p.Foo.Nested? = null diff --git a/compiler/testData/diagnostics/tests/imports/ImportProtectedClass.kt b/compiler/testData/diagnostics/tests/imports/ImportProtectedClass.kt index 6bf844c4a54..dc713edb926 100644 --- a/compiler/testData/diagnostics/tests/imports/ImportProtectedClass.kt +++ b/compiler/testData/diagnostics/tests/imports/ImportProtectedClass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL package p import p.Foo.Nested diff --git a/compiler/testData/diagnostics/tests/inference/upperBounds/typeParameterAsUpperBound.fir.kt b/compiler/testData/diagnostics/tests/inference/upperBounds/typeParameterAsUpperBound.fir.kt index a2b6bafc8fd..495db2b5221 100644 --- a/compiler/testData/diagnostics/tests/inference/upperBounds/typeParameterAsUpperBound.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/upperBounds/typeParameterAsUpperBound.fir.kt @@ -1,7 +1,7 @@ // !CHECK_TYPE -@kotlin.internal.InlineOnly +@kotlin.internal.InlineOnly public inline fun C.ifEmpty(f: () -> R): R where C : Collection<*>, C : R = if (isEmpty()) f() else this public fun listOf(t: T): List = TODO() diff --git a/compiler/testData/diagnostics/tests/j+k/innerNestedClassFromJava.fir.kt b/compiler/testData/diagnostics/tests/j+k/innerNestedClassFromJava.fir.kt deleted file mode 100644 index e3d7761ea36..00000000000 --- a/compiler/testData/diagnostics/tests/j+k/innerNestedClassFromJava.fir.kt +++ /dev/null @@ -1,32 +0,0 @@ -// FILE: a/M.java -package a; - -public class M { - public class Inner { - - } - - public static class Nested { - - } - - private class PrInner { - - } - - private static class PrNested { - - } -} - -// FILE: b.kt -package b - -fun f() { - val c1: a.M.Inner - val c2: a.M.Nested - val c3: a.M.PrInner - val c4: a.M.PrNested - -} - diff --git a/compiler/testData/diagnostics/tests/j+k/innerNestedClassFromJava.kt b/compiler/testData/diagnostics/tests/j+k/innerNestedClassFromJava.kt index 923172be7ef..86f174c3c75 100644 --- a/compiler/testData/diagnostics/tests/j+k/innerNestedClassFromJava.kt +++ b/compiler/testData/diagnostics/tests/j+k/innerNestedClassFromJava.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: a/M.java package a; diff --git a/compiler/testData/diagnostics/tests/javac/imports/ImportProtectedClass.fir.kt b/compiler/testData/diagnostics/tests/javac/imports/ImportProtectedClass.fir.kt deleted file mode 100644 index e7a90ee7eea..00000000000 --- a/compiler/testData/diagnostics/tests/javac/imports/ImportProtectedClass.fir.kt +++ /dev/null @@ -1,19 +0,0 @@ -// FILE: p/Foo.java -package p; - -public class Foo { - protected static class Nested {} -} - -// FILE: foo.kt -package a - -import p.Foo -import p.Foo.Nested - -class Bar : Foo() { - protected fun foo(): Nested? = null -} - -private fun foo(): Nested? = null -private fun bar(): p.Foo.Nested? = null diff --git a/compiler/testData/diagnostics/tests/javac/imports/ImportProtectedClass.kt b/compiler/testData/diagnostics/tests/javac/imports/ImportProtectedClass.kt index dc03ff8bacc..7ecc1a59f89 100644 --- a/compiler/testData/diagnostics/tests/javac/imports/ImportProtectedClass.kt +++ b/compiler/testData/diagnostics/tests/javac/imports/ImportProtectedClass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: p/Foo.java package p; diff --git a/compiler/testData/diagnostics/tests/javac/imports/PackagePrivateAndPublicNested.fir.kt b/compiler/testData/diagnostics/tests/javac/imports/PackagePrivateAndPublicNested.fir.kt index 815933fc70a..656372ee20a 100644 --- a/compiler/testData/diagnostics/tests/javac/imports/PackagePrivateAndPublicNested.fir.kt +++ b/compiler/testData/diagnostics/tests/javac/imports/PackagePrivateAndPublicNested.fir.kt @@ -16,4 +16,4 @@ class Bar : Foo } private fun foo(): Nested? = null -private fun bar(): p.Foo.Nested? = null +private fun bar(): p.Foo.Nested? = null diff --git a/compiler/testData/diagnostics/tests/scopes/visibility2.fir.kt b/compiler/testData/diagnostics/tests/scopes/visibility2.fir.kt index ffc1b97e7f9..2a80c5ca121 100644 --- a/compiler/testData/diagnostics/tests/scopes/visibility2.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/visibility2.fir.kt @@ -30,7 +30,7 @@ fun test() { foo() val u : A = A() - val a : java.util.Arrays.ArrayList; + val a : java.util.Arrays.ArrayList; val po = PO } diff --git a/compiler/testData/diagnostics/tests/typealias/constructorCallThroughPrivateAlias.fir.kt b/compiler/testData/diagnostics/tests/typealias/constructorCallThroughPrivateAlias.fir.kt index 5a0ce6f54ec..e7d069200ac 100644 --- a/compiler/testData/diagnostics/tests/typealias/constructorCallThroughPrivateAlias.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/constructorCallThroughPrivateAlias.fir.kt @@ -30,5 +30,5 @@ fun baz() { a.A3("") checkType { _() } - val x: a.A2 = B("") // A2 is unresolved because it's private in file, OK + val x: a.A2 = B("") // A2 is unresolved because it's private in file, OK } diff --git a/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt b/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt index 28c60a6d60e..5b245a25ea2 100644 --- a/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt @@ -6,7 +6,7 @@ private class C { private typealias TA = C private val test1: C = C() -private val test1co: C.Companion = C +private val test1co: C.Companion = C private val test2: TA = TA() private val test2co = TA diff --git a/compiler/testData/diagnostics/tests/typealias/privateInFile.ll.kt b/compiler/testData/diagnostics/tests/typealias/privateInFile.ll.kt index 9bde9499a62..143587ec2dd 100644 --- a/compiler/testData/diagnostics/tests/typealias/privateInFile.ll.kt +++ b/compiler/testData/diagnostics/tests/typealias/privateInFile.ll.kt @@ -18,7 +18,7 @@ private val test2co = TA // FILE: file2.kt private val test1: C = C() -private val test1co: C.Companion = C +private val test1co: C.Companion = C private val test2: TA = TA() private val test2co = TA diff --git a/compiler/testData/diagnostics/tests/visibility/privateDeclarationInAnotherFile.fir.kt b/compiler/testData/diagnostics/tests/visibility/privateDeclarationInAnotherFile.fir.kt index c48e92be8f4..771d7686fa6 100644 --- a/compiler/testData/diagnostics/tests/visibility/privateDeclarationInAnotherFile.fir.kt +++ b/compiler/testData/diagnostics/tests/visibility/privateDeclarationInAnotherFile.fir.kt @@ -8,6 +8,6 @@ private class Private { import Private.Public -private fun test_1(x: Private.Public, y: Public) { +private fun test_1(x: Private.Public, y: Public) { } diff --git a/compiler/testData/diagnostics/testsWithStdLib/InaccessibleInternalClass.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/InaccessibleInternalClass.fir.kt deleted file mode 100644 index eed901d7436..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/InaccessibleInternalClass.fir.kt +++ /dev/null @@ -1,15 +0,0 @@ -// SKIP_TXT -// FILE: a.kt -package p - -class FilteringSequence - -// FILE: b.kt -package kotlin.sequences - -import p.* - -interface I { - val v1: FilteringSequence - val v2: IndexingSequence -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/InaccessibleInternalClass.kt b/compiler/testData/diagnostics/testsWithStdLib/InaccessibleInternalClass.kt index 1ddb1aebd9c..e3aff1f7023 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/InaccessibleInternalClass.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/InaccessibleInternalClass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // SKIP_TXT // FILE: a.kt package p