Don't allow to use own nested classes when resolve header of (companion) object
This commit is contained in:
+3
@@ -30,6 +30,9 @@ public interface ClassDescriptorWithResolutionScopes extends ClassDescriptor {
|
||||
@NotNull
|
||||
LexicalScope getScopeForConstructorHeaderResolution();
|
||||
|
||||
@NotNull
|
||||
LexicalScope getScopeForCompanionObjectHeaderResolution();
|
||||
|
||||
@NotNull
|
||||
LexicalScope getScopeForMemberDeclarationResolution();
|
||||
|
||||
|
||||
+14
-8
@@ -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) {
|
||||
|
||||
+37
-19
@@ -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)
|
||||
}
|
||||
|
||||
+6
@@ -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
|
||||
|
||||
+25
@@ -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
|
||||
}
|
||||
}
|
||||
+63
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user