diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index 6afdd88cd05..89a13e748fb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -51,7 +51,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa scope: LexicalScope, trace: BindingTrace ): ClassifierDescriptor? { - if (userType.qualifier == null) { // optimization for non-qualified types + if (userType.qualifier == null && !userType.startWithPackage) { // optimization for non-qualified types return userType.referenceExpression?.let { val classifier = scope.getClassifier(it.getReferencedNameAsName(), KotlinLookupLocation(it)) storageResult(trace, it, listOfNotNull(classifier), scope.ownerDescriptor) @@ -65,14 +65,14 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa resolveToPackageOrClass(qualifierPartList, module, trace, scope.ownerDescriptor) return null } - assert(qualifierPartList.size() > 1) { + assert(qualifierPartList.size() >= 1) { "Too short qualifier list for user type $userType : ${qualifierPartList.joinToString()}" } val qualifier = resolveToPackageOrClass( qualifierPartList.subList(0, qualifierPartList.size() - 1), module, trace, scope.ownerDescriptor, firstPartResolver = { - if (userType.isAbsoluteInRootPackage) { + if (userType.startWithPackage) { null } else { @@ -91,6 +91,16 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa return classifier } + private val JetUserType.startWithPackage: Boolean + get() { + var firstPart = this + while (firstPart.qualifier != null) { + firstPart = firstPart.qualifier!! + } + return firstPart.isAbsoluteInRootPackage + } + + private fun JetUserType.asQualifierPartList(): Pair, Boolean> { var hasError = false val result = SmartList() diff --git a/compiler/testData/diagnostics/tests/qualifiedExpression/PackageKeyword.kt b/compiler/testData/diagnostics/tests/qualifiedExpression/PackageKeyword.kt new file mode 100644 index 00000000000..84ef8c0cb1c --- /dev/null +++ b/compiler/testData/diagnostics/tests/qualifiedExpression/PackageKeyword.kt @@ -0,0 +1,94 @@ +// MODULE: m1 +// FILE: a.kt +package a.b + +class c { + fun ab_c() {} +} + +fun ab_fun() {} + +// MODULE: m2 +// FILE: b.kt +package a + +fun a_fun() {} + +class b { + fun a_b() {} + + class c { + fun a_bc() {} + } +} + +// FILE: b2.kt +class x { + fun top_x() {} +} + + +// MODULE: m3(m1, m2) +// FILE: c.kt +package some + +class a { + class b { + fun _ab() {} + class c { + fun _abc() {} + } + } + fun _a() {} +} + +class x { + fun _x() {} +} + +fun test(a_b: package.a.b) { + a_b.a_b() + a_b._ab() + + package.a.a_fun() // todo + + val a_b2 = package.a.b() + a_b2.a_b() // todo + a_b2._ab() + +} + +fun test2(ab_c: package.a.b.c) { + ab_c.ab_c() + + val ab_c2 = package.a.b.c() + ab_c2.ab_c() + ab_c2.a_bc() +} + +fun test3(top_x: package.x) { + top_x.top_x() + + val top_x2 = package.x() + top_x2.top_x() // todo + top_x2._x() +} + +// FILE: c2.kt +package other + +object a { + object b { + fun _ab() {} + } + fun _a() {} +} + + +fun test(a: a) { + package.a.a_fun() // todo + package.a._a() // todo + + package.a.b.ab_fun() // todo + package.a.b._ab() // todo +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/qualifiedExpression/PackageKeyword.txt b/compiler/testData/diagnostics/tests/qualifiedExpression/PackageKeyword.txt new file mode 100644 index 00000000000..7821e6a6d0d --- /dev/null +++ b/compiler/testData/diagnostics/tests/qualifiedExpression/PackageKeyword.txt @@ -0,0 +1,133 @@ +// -- Module: -- +package + +package a { + + package a.b { + public fun ab_fun(): kotlin.Unit + + public final class c { + public constructor c() + public final fun ab_c(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } +} + + +// -- Module: -- +package + +public final class x { + public constructor x() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final fun top_x(): kotlin.Unit +} + +package a { + public fun a_fun(): kotlin.Unit + + public final class b { + public constructor b() + public final fun a_b(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class c { + public constructor c() + public final fun a_bc(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } +} + + +// -- Module: -- +package + +public final class x { + // -- Module: -- +} + +package a { + public fun a_fun(): kotlin.Unit + + public final class b { + // -- Module: -- + } + + package a.b { + public fun ab_fun(): kotlin.Unit + + public final class c { + // -- Module: -- + } + } +} + +package other { + public fun test(/*0*/ a: other.a): kotlin.Unit + + public object a { + private constructor a() + public final fun _a(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object b { + private constructor b() + public final fun _ab(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } +} + +package some { + public fun test(/*0*/ a_b: a.b): kotlin.Unit + public fun test2(/*0*/ ab_c: a.b.c): kotlin.Unit + public fun test3(/*0*/ top_x: x): kotlin.Unit + + public final class a { + public constructor a() + public final fun _a(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class b { + public constructor b() + public final fun _ab(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class c { + public constructor c() + public final fun _abc(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + } + + public final class x { + public constructor x() + public final fun _x(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + + diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 1008788cb18..2d8b0afc953 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -11037,6 +11037,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("PackageKeyword.kt") + public void testPackageKeyword() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/qualifiedExpression/PackageKeyword.kt"); + doTest(fileName); + } + @TestMetadata("PackageVsClass.kt") public void testPackageVsClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/qualifiedExpression/PackageVsClass.kt");