Don't allow to use own nested classes when resolve header of (companion) object

This commit is contained in:
Zalim Bashorov
2015-12-14 16:44:55 +03:00
parent 38522f60ea
commit e9ea4cc953
12 changed files with 204 additions and 30 deletions
@@ -30,6 +30,9 @@ public interface ClassDescriptorWithResolutionScopes extends ClassDescriptor {
@NotNull @NotNull
LexicalScope getScopeForConstructorHeaderResolution(); LexicalScope getScopeForConstructorHeaderResolution();
@NotNull
LexicalScope getScopeForCompanionObjectHeaderResolution();
@NotNull @NotNull
LexicalScope getScopeForMemberDeclarationResolution(); LexicalScope getScopeForMemberDeclarationResolution();
@@ -60,17 +60,23 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
} }
if (parentDeclaration instanceof KtClassOrObject) { if (parentDeclaration instanceof KtClassOrObject) {
KtClassOrObject classOrObject = (KtClassOrObject) parentDeclaration; KtClassOrObject parentClassOrObject = (KtClassOrObject) parentDeclaration;
LazyClassDescriptor classDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(classOrObject, NoLookupLocation.WHEN_GET_DECLARATION_SCOPE); LazyClassDescriptor parentClassDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(parentClassOrObject, NoLookupLocation.WHEN_GET_DECLARATION_SCOPE);
if (ktDeclaration instanceof KtAnonymousInitializer || ktDeclaration instanceof KtProperty) { if (ktDeclaration instanceof KtAnonymousInitializer || ktDeclaration instanceof KtProperty) {
return classDescriptor.getScopeForInitializerResolution(); return parentClassDescriptor.getScopeForInitializerResolution();
}
if (ktDeclaration instanceof KtObjectDeclaration
|| (ktDeclaration instanceof KtClass && !((KtClass) ktDeclaration).isInner())) {
return classDescriptor.getScopeForStaticMemberDeclarationResolution();
} }
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 //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) { if (parentDeclaration instanceof KtScript) {
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors
import com.intellij.util.SmartList import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.*
@@ -47,17 +48,24 @@ class ClassResolutionScopesSupport(
scopeWithGenerics(scopeForStaticMemberDeclarationResolution()) scopeWithGenerics(scopeForStaticMemberDeclarationResolution())
} }
private val inheritanceScope: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) { private val inheritanceScopeWithoutMe: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) {
classDescriptor.getAllSuperclassesAndMeWithoutAny().asReversed().fold(getOuterScope()) { scope, currentClass -> classDescriptor.getAllSuperclassesWithoutAny().asReversed().fold(getOuterScope()) { scope, currentClass ->
createInheritanceScope(parent = scope, ownerDescriptor = classDescriptor, classDescriptor = 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 { public val scopeForMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue {
val scopeWithGenerics = scopeWithGenerics(inheritanceScope()) val scopeWithGenerics = scopeWithGenerics(inheritanceScopeWithMe())
LexicalScopeImpl(scopeWithGenerics, classDescriptor, true, classDescriptor.thisAsReceiverParameter, LexicalScopeImpl(scopeWithGenerics, classDescriptor, true, classDescriptor.thisAsReceiverParameter, LexicalScopeKind.CLASS_MEMBER_SCOPE)
LexicalScopeKind.CLASS_MEMBER_SCOPE)
} }
public val scopeForStaticMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) { public val scopeForStaticMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createThrowingLexicalScope) {
@@ -65,8 +73,7 @@ class ClassResolutionScopesSupport(
scopeForMemberDeclarationResolution() scopeForMemberDeclarationResolution()
} }
else { else {
LexicalScopeImpl(inheritanceScope(), classDescriptor, false, null, LexicalScopeImpl(inheritanceScopeWithMe(), classDescriptor, false, null, LexicalScopeKind.CLASS_STATIC_SCOPE)
LexicalScopeKind.CLASS_STATIC_SCOPE)
} }
} }
@@ -88,22 +95,24 @@ class ClassResolutionScopesSupport(
} }
public fun ClassDescriptor.getAllSuperclassesAndMeWithoutAny(): List<ClassDescriptor> { public fun ClassDescriptor.getAllSuperclassesWithoutAny(): List<ClassDescriptor> {
val superClassesAndMe = SmartList<ClassDescriptor>() val superClasses = SmartList<ClassDescriptor>()
var parent: ClassDescriptor? = this var parent: ClassDescriptor? = getSuperClassNotAny()
do {
superClassesAndMe.add(parent)
parent = parent!!.getSuperClassNotAny()
}
while(parent != null && parent != this) // possible recursion in inheritance
return superClassesAndMe // possible recursion in inheritance
while(parent != null && parent != this) {
superClasses.add(parent)
parent = parent.getSuperClassNotAny()
}
return superClasses
} }
private fun createInheritanceScope( private fun createInheritanceScope(
parent: LexicalScope, parent: LexicalScope,
ownerDescriptor: DeclarationDescriptor, ownerDescriptor: DeclarationDescriptor,
classDescriptor: ClassDescriptor classDescriptor: ClassDescriptor,
withCompanionObject: Boolean = true
): LexicalScope { ): LexicalScope {
val staticScopes = ArrayList<MemberScope>(3) val staticScopes = ArrayList<MemberScope>(3)
@@ -111,10 +120,19 @@ class ClassResolutionScopesSupport(
staticScopes.add(classDescriptor.staticScope) staticScopes.add(classDescriptor.staticScope)
staticScopes.add(classDescriptor.unsubstitutedInnerClassesScope) 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, return LexicalChainedScope(parent, ownerDescriptor, false,
classDescriptor.companionObjectDescriptor?.thisAsReceiverParameter, implicitReceiver,
LexicalScopeKind.CLASS_INHERITANCE, LexicalScopeKind.CLASS_INHERITANCE,
memberScopes = *staticScopes.toTypedArray(), isStaticScope = true) memberScopes = *staticScopes.toTypedArray(), isStaticScope = true)
} }
@@ -298,6 +298,12 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
return resolutionScopesSupport.getScopeForConstructorHeaderResolution().invoke(); return resolutionScopesSupport.getScopeForConstructorHeaderResolution().invoke();
} }
@Override
@NotNull
public LexicalScope getScopeForCompanionObjectHeaderResolution() {
return resolutionScopesSupport.getScopeForCompanionObjectHeaderResolution().invoke();
}
@Override @Override
@NotNull @NotNull
public LexicalScope getScopeForMemberDeclarationResolution() { public LexicalScope getScopeForMemberDeclarationResolution() {
@@ -63,6 +63,7 @@ enum class LexicalScopeKind(val withLocalDescriptors: Boolean) {
CLASS_STATIC_SCOPE(false), CLASS_STATIC_SCOPE(false),
CLASS_MEMBER_SCOPE(false), CLASS_MEMBER_SCOPE(false),
CLASS_INITIALIZER(true), CLASS_INITIALIZER(true),
COMPANION_OBJECT_HEADER(false),
DEFAULT_VALUE(true), DEFAULT_VALUE(true),
@@ -1,5 +1,5 @@
class Test { class Test {
@ClassObjectAnnotation <!UNRESOLVED_REFERENCE!>@ClassObjectAnnotation<!>
@NestedAnnotation @NestedAnnotation
companion object { companion object {
annotation class ClassObjectAnnotation annotation class ClassObjectAnnotation
@@ -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 hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String 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() private constructor Companion()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean 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 hashCode(): kotlin.Int
@@ -0,0 +1,25 @@
interface I<F, G>
val aImpl: A.Companion.Interface
get() = null!!
val bImpl: B.Companion.Interface
get() = null!!
interface A {
companion object : <!UNRESOLVED_REFERENCE!>Nested<!>(), <!UNRESOLVED_REFERENCE, DELEGATION_NOT_TO_INTERFACE!>Interface<!> by aImpl, I<<!UNRESOLVED_REFERENCE!>Nested<!>, <!UNRESOLVED_REFERENCE!>Interface<!>> {
class Nested
interface Interface
}
}
class B {
companion object : <!UNRESOLVED_REFERENCE!>Nested<!>(), <!UNRESOLVED_REFERENCE, DELEGATION_NOT_TO_INTERFACE!>Interface<!> by aImpl, I<<!UNRESOLVED_REFERENCE!>Nested<!>, <!UNRESOLVED_REFERENCE!>Interface<!>> {
class Nested
interface Interface
}
}
@@ -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</*0*/ F, /*1*/ G> {
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
}
@@ -0,0 +1,11 @@
interface I<F, G>
val aImpl: A.Interface
get() = null!!
object A : <!UNRESOLVED_REFERENCE!>Nested<!>(), <!UNRESOLVED_REFERENCE, DELEGATION_NOT_TO_INTERFACE!>Interface<!> by aImpl, I<<!UNRESOLVED_REFERENCE!>Nested<!>, <!UNRESOLVED_REFERENCE!>Interface<!>> {
class Nested
interface Interface
}
@@ -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</*0*/ F, /*1*/ G> {
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
}
@@ -14012,6 +14012,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName); 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") @TestMetadata("constructors.kt")
public void testConstructors() throws Exception { public void testConstructors() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/constructors.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/constructors.kt");
@@ -14024,6 +14030,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName); 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") @TestMetadata("simpleDelegation.kt")
public void testSimpleDelegation() throws Exception { public void testSimpleDelegation() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/simpleDelegation.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/classHeader/simpleDelegation.kt");