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
LexicalScope getScopeForConstructorHeaderResolution();
@NotNull
LexicalScope getScopeForCompanionObjectHeaderResolution();
@NotNull
LexicalScope getScopeForMemberDeclarationResolution();
@@ -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) {
@@ -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<ClassDescriptor> {
val superClassesAndMe = SmartList<ClassDescriptor>()
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<ClassDescriptor> {
val superClasses = SmartList<ClassDescriptor>()
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<MemberScope>(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)
}
@@ -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() {
@@ -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),
@@ -1,9 +1,9 @@
class Test {
@ClassObjectAnnotation
<!UNRESOLVED_REFERENCE!>@ClassObjectAnnotation<!>
@NestedAnnotation
companion object {
annotation class ClassObjectAnnotation
}
annotation class NestedAnnotation
}
}
@@ -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
@@ -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);
}
@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");