diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java index 91913c2e728..d241774f38a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java @@ -30,6 +30,9 @@ public interface ClassDescriptorWithResolutionScopes extends ClassDescriptor { @NotNull LexicalScope getScopeForConstructorHeaderResolution(); + @NotNull + LexicalScope getScopeForCompanionObjectHeaderResolution(); + @NotNull LexicalScope getScopeForMemberDeclarationResolution(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java index a52959bb6b7..0b9285ba065 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java @@ -60,17 +60,23 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider { } if (parentDeclaration instanceof KtClassOrObject) { - KtClassOrObject classOrObject = (KtClassOrObject) parentDeclaration; - LazyClassDescriptor classDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(classOrObject, NoLookupLocation.WHEN_GET_DECLARATION_SCOPE); + KtClassOrObject parentClassOrObject = (KtClassOrObject) parentDeclaration; + LazyClassDescriptor parentClassDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(parentClassOrObject, NoLookupLocation.WHEN_GET_DECLARATION_SCOPE); + if (ktDeclaration instanceof KtAnonymousInitializer || ktDeclaration instanceof KtProperty) { - return classDescriptor.getScopeForInitializerResolution(); - } - if (ktDeclaration instanceof KtObjectDeclaration - || (ktDeclaration instanceof KtClass && !((KtClass) ktDeclaration).isInner())) { - return classDescriptor.getScopeForStaticMemberDeclarationResolution(); + return parentClassDescriptor.getScopeForInitializerResolution(); } - return classDescriptor.getScopeForMemberDeclarationResolution(); + if (ktDeclaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) ktDeclaration).isCompanion()) { + return parentClassDescriptor.getScopeForCompanionObjectHeaderResolution(); + } + + if (ktDeclaration instanceof KtObjectDeclaration || + ktDeclaration instanceof KtClass && !((KtClass) ktDeclaration).isInner()) { + return parentClassDescriptor.getScopeForStaticMemberDeclarationResolution(); + } + + return parentClassDescriptor.getScopeForMemberDeclarationResolution(); } //TODO: this is not how it works for classes and for exact parity we can try to use the code above if (parentDeclaration instanceof KtScript) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt index 476ca077939..903215fa42b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors import com.intellij.util.SmartList import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.scopes.* @@ -47,17 +48,24 @@ class ClassResolutionScopesSupport( scopeWithGenerics(scopeForStaticMemberDeclarationResolution()) } - private val inheritanceScope: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) { - classDescriptor.getAllSuperclassesAndMeWithoutAny().asReversed().fold(getOuterScope()) { scope, currentClass -> + private val inheritanceScopeWithoutMe: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) { + classDescriptor.getAllSuperclassesWithoutAny().asReversed().fold(getOuterScope()) { scope, currentClass -> createInheritanceScope(parent = scope, ownerDescriptor = classDescriptor, classDescriptor = currentClass) } } + private val inheritanceScopeWithMe: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) { + createInheritanceScope(parent = inheritanceScopeWithoutMe(), ownerDescriptor = classDescriptor, classDescriptor = classDescriptor) + } + + public val scopeForCompanionObjectHeaderResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) { + val inheritanceScope = createInheritanceScope(inheritanceScopeWithoutMe(), classDescriptor, classDescriptor, withCompanionObject = false) + LexicalScopeImpl(inheritanceScope, classDescriptor, false, null, LexicalScopeKind.COMPANION_OBJECT_HEADER) + } public val scopeForMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue { - val scopeWithGenerics = scopeWithGenerics(inheritanceScope()) - LexicalScopeImpl(scopeWithGenerics, classDescriptor, true, classDescriptor.thisAsReceiverParameter, - LexicalScopeKind.CLASS_MEMBER_SCOPE) + val scopeWithGenerics = scopeWithGenerics(inheritanceScopeWithMe()) + LexicalScopeImpl(scopeWithGenerics, classDescriptor, true, classDescriptor.thisAsReceiverParameter, LexicalScopeKind.CLASS_MEMBER_SCOPE) } public val scopeForStaticMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) { @@ -65,8 +73,7 @@ class ClassResolutionScopesSupport( scopeForMemberDeclarationResolution() } else { - LexicalScopeImpl(inheritanceScope(), classDescriptor, false, null, - LexicalScopeKind.CLASS_STATIC_SCOPE) + LexicalScopeImpl(inheritanceScopeWithMe(), classDescriptor, false, null, LexicalScopeKind.CLASS_STATIC_SCOPE) } } @@ -88,22 +95,24 @@ class ClassResolutionScopesSupport( } - public fun ClassDescriptor.getAllSuperclassesAndMeWithoutAny(): List { - val superClassesAndMe = SmartList() - var parent: ClassDescriptor? = this - do { - superClassesAndMe.add(parent) - parent = parent!!.getSuperClassNotAny() - } - while(parent != null && parent != this) // possible recursion in inheritance + public fun ClassDescriptor.getAllSuperclassesWithoutAny(): List { + val superClasses = SmartList() + var parent: ClassDescriptor? = getSuperClassNotAny() - return superClassesAndMe + // possible recursion in inheritance + while(parent != null && parent != this) { + superClasses.add(parent) + parent = parent.getSuperClassNotAny() + } + + return superClasses } private fun createInheritanceScope( parent: LexicalScope, ownerDescriptor: DeclarationDescriptor, - classDescriptor: ClassDescriptor + classDescriptor: ClassDescriptor, + withCompanionObject: Boolean = true ): LexicalScope { val staticScopes = ArrayList(3) @@ -111,10 +120,19 @@ class ClassResolutionScopesSupport( staticScopes.add(classDescriptor.staticScope) staticScopes.add(classDescriptor.unsubstitutedInnerClassesScope) - staticScopes.addIfNotNull(classDescriptor.companionObjectDescriptor?.unsubstitutedInnerClassesScope) + + val implicitReceiver: ReceiverParameterDescriptor? + + if (withCompanionObject) { + staticScopes.addIfNotNull(classDescriptor.companionObjectDescriptor?.unsubstitutedInnerClassesScope) + implicitReceiver = classDescriptor.companionObjectDescriptor?.thisAsReceiverParameter + } + else { + implicitReceiver = null + } return LexicalChainedScope(parent, ownerDescriptor, false, - classDescriptor.companionObjectDescriptor?.thisAsReceiverParameter, + implicitReceiver, LexicalScopeKind.CLASS_INHERITANCE, memberScopes = *staticScopes.toTypedArray(), isStaticScope = true) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 40b603a7994..20da5e1912c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -298,6 +298,12 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes return resolutionScopesSupport.getScopeForConstructorHeaderResolution().invoke(); } + @Override + @NotNull + public LexicalScope getScopeForCompanionObjectHeaderResolution() { + return resolutionScopesSupport.getScopeForCompanionObjectHeaderResolution().invoke(); + } + @Override @NotNull public LexicalScope getScopeForMemberDeclarationResolution() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt index 528a261b0cf..d09c3fe0254 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt @@ -63,6 +63,7 @@ enum class LexicalScopeKind(val withLocalDescriptors: Boolean) { CLASS_STATIC_SCOPE(false), CLASS_MEMBER_SCOPE(false), CLASS_INITIALIZER(true), + COMPANION_OBJECT_HEADER(false), DEFAULT_VALUE(true), diff --git a/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.kt b/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.kt index 411bc4b8899..892648677a2 100644 --- a/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.kt +++ b/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.kt @@ -1,9 +1,9 @@ class Test { - @ClassObjectAnnotation + @ClassObjectAnnotation @NestedAnnotation companion object { annotation class ClassObjectAnnotation } annotation class NestedAnnotation -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt b/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt index df68c4f4140..ca324a6c3f3 100644 --- a/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt +++ b/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt @@ -6,7 +6,7 @@ public final class Test { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - @Test.Companion.ClassObjectAnnotation() @Test.NestedAnnotation() public companion object Companion { + @[ERROR : ClassObjectAnnotation]() @Test.NestedAnnotation() public companion object Companion { private constructor Companion() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.kt b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.kt new file mode 100644 index 00000000000..7feba245f29 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.kt @@ -0,0 +1,25 @@ +interface I + +val aImpl: A.Companion.Interface + get() = null!! + +val bImpl: B.Companion.Interface + get() = null!! + +interface A { + companion object : Nested(), Interface by aImpl, I<Nested, Interface> { + + class Nested + + interface Interface + } +} + +class B { + companion object : Nested(), Interface by aImpl, I<Nested, Interface> { + + class Nested + + interface Interface + } +} diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.txt b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.txt new file mode 100644 index 00000000000..99849da3a86 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.txt @@ -0,0 +1,63 @@ +package + +public val aImpl: A.Companion.Interface +public val bImpl: B.Companion.Interface + +public interface A { + 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 companion object Companion : I<[ERROR : Nested], [ERROR : Interface]> { + private constructor Companion() + 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 interface Interface { + 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 Nested { + public constructor Nested() + 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 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 companion object Companion : I<[ERROR : Nested], [ERROR : Interface]> { + private constructor Companion() + 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 interface Interface { + 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 Nested { + public constructor Nested() + 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 interface I { + 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/testData/diagnostics/tests/scopes/classHeader/objectParents.kt b/compiler/testData/diagnostics/tests/scopes/classHeader/objectParents.kt new file mode 100644 index 00000000000..80bc769e6b7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/objectParents.kt @@ -0,0 +1,11 @@ +interface I + +val aImpl: A.Interface + get() = null!! + +object A : Nested(), Interface by aImpl, I<Nested, Interface> { + + class Nested + + interface Interface +} diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/objectParents.txt b/compiler/testData/diagnostics/tests/scopes/classHeader/objectParents.txt new file mode 100644 index 00000000000..8a394cd03c7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/objectParents.txt @@ -0,0 +1,29 @@ +package + +public val aImpl: A.Interface + +public object A : I<[ERROR : Nested], [ERROR : Interface]> { + private constructor A() + 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 interface Interface { + 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 Nested { + public constructor Nested() + 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 interface I { + 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/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0e562648459..70a8f43d485 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -14012,6 +14012,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("companionObjectParents.kt") + public void testCompanionObjectParents() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.kt"); + doTest(fileName); + } + @TestMetadata("constructors.kt") public void testConstructors() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/constructors.kt"); @@ -14024,6 +14030,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("objectParents.kt") + public void testObjectParents() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/objectParents.kt"); + doTest(fileName); + } + @TestMetadata("simpleDelegation.kt") public void testSimpleDelegation() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/simpleDelegation.kt");