From 26bd1ff189b58b77a27b08ec7fbab4a36d7a5254 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 12 Nov 2013 20:02:12 +0400 Subject: [PATCH] Change object resolution strategy in lazy resolve --- .../lazy/data/SyntheticClassObjectInfo.java | 110 ++++++++++++++++++ .../descriptors/AbstractLazyMemberScope.java | 20 ++-- .../lazy/descriptors/LazyClassDescriptor.java | 57 +++++---- .../AnnotationOnObject.txt | 6 +- .../UnresolvedAnnotationOnObject.txt | 5 +- .../WrongAnnotationArgsOnObject.txt | 5 +- .../namespaceComparator/objectInClass.txt | 6 +- .../namespaceComparator/objectMembers.txt | 7 +- .../packageLevelObject.txt | 6 +- .../testData/loadKotlin/class/NamedObject.txt | 9 +- .../loadKotlin/class/NamedObjectInClass.txt | 8 +- .../class/NamedObjectInClassObject.txt | 8 +- .../class/NamedObjectInNamedObject.txt | 14 ++- ...NamedObjectWithAnotherTopLevelProperty.txt | 8 +- .../jet/test/util/DescriptorValidator.java | 7 +- .../jet/lang/resolve/DescriptorUtils.java | 10 ++ 16 files changed, 226 insertions(+), 60 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/SyntheticClassObjectInfo.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/SyntheticClassObjectInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/SyntheticClassObjectInfo.java new file mode 100644 index 00000000000..be5208eeb38 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/SyntheticClassObjectInfo.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.lazy.data; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor; +import org.jetbrains.jet.lang.resolve.name.FqName; + +import java.util.Collections; +import java.util.List; + +public class SyntheticClassObjectInfo implements JetClassLikeInfo { + private final JetClassLikeInfo classInfo; + private final LazyClassDescriptor classDescriptor; + + public SyntheticClassObjectInfo(@NotNull JetClassLikeInfo classInfo, @NotNull LazyClassDescriptor classDescriptor) { + this.classInfo = classInfo; + this.classDescriptor = classDescriptor; + } + + @NotNull + public LazyClassDescriptor getClassDescriptor() { + return classDescriptor; + } + + + @NotNull + @Override + public FqName getContainingPackageFqName() { + return classInfo.getContainingPackageFqName(); + } + + @NotNull + @Override + public List getDelegationSpecifiers() { + return Collections.emptyList(); + } + + @Nullable + @Override + public JetModifierList getModifierList() { + return null; + } + + @Nullable + @Override + public JetClassObject getClassObject() { + return null; + } + + @NotNull + @Override + public PsiElement getScopeAnchor() { + return classInfo.getScopeAnchor(); + } + + @Nullable + @Override + public JetClassOrObject getCorrespondingClassOrObject() { + return null; + } + + @NotNull + @Override + public List getTypeParameters() { + return Collections.emptyList(); + } + + @NotNull + @Override + public List getPrimaryConstructorParameters() { + return Collections.emptyList(); + } + + @NotNull + @Override + public ClassKind getClassKind() { + return ClassKind.CLASS_OBJECT; + } + + @NotNull + @Override + public List getDeclarations() { + // There can be no declarations in a synthetic class object, all its members are fake overrides + return Collections.emptyList(); + } + + @Override + public String toString() { + return "class object of " + classInfo; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java index 9563341b86e..e9e6749a3ee 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java @@ -198,10 +198,10 @@ public abstract class AbstractLazyMemberScope classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name); for (JetClassOrObject classOrObjectDeclaration : classOrObjectDeclarations) { - if (declaresObjectOrEnumConstant(classOrObjectDeclaration)) { + if (classOrObjectDeclaration instanceof JetEnumEntry) { ClassDescriptor classifier = getObjectDescriptor(name); if (classifier == null) { throw new IllegalStateException("Object declaration " + name + " found in the DeclarationProvider " + declarationProvider + " but not in the scope " + this); @@ -259,25 +259,19 @@ public abstract class AbstractLazyMemberScope allSupertypes = resolveSession.getInjector().getDescriptorResolver() - .resolveSupertypes(getScopeForClassHeaderResolution(), - LazyClassDescriptor.this, classOrObject, - resolveSession.getTrace()); - return Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)); + JetClassLikeInfo info = declarationProvider.getOwnerInfo(); + if (info instanceof SyntheticClassObjectInfo) { + LazyClassDescriptor descriptor = ((SyntheticClassObjectInfo) info).getClassDescriptor(); + if (descriptor.getKind().isSingleton()) { + return Collections.singleton(descriptor.getDefaultType()); } } + + JetClassOrObject classOrObject = info.getCorrespondingClassOrObject(); + if (classOrObject == null) { + return Collections.emptyList(); + } + + List allSupertypes = resolveSession.getInjector().getDescriptorResolver() + .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject, + resolveSession.getTrace()); + + return Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)); } }, new Function1>() { @@ -472,12 +478,14 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc } } - private JetClassLikeInfo noEnumEntries(JetClassLikeInfo classLikeInfo) { - return new FilteringClassLikeInfo(resolveSession.getStorageManager(), classLikeInfo, Predicates.not(ONLY_ENUM_ENTRIES)); + @NotNull + private JetClassLikeInfo noEnumEntries() { + return new FilteringClassLikeInfo(resolveSession.getStorageManager(), originalClassInfo, Predicates.not(ONLY_ENUM_ENTRIES)); } - private JetClassLikeInfo enumClassObjectInfo(JetClassLikeInfo classLikeInfo) { - return new FilteringClassLikeInfo(resolveSession.getStorageManager(), classLikeInfo, ONLY_ENUM_ENTRIES) { + @NotNull + private JetClassLikeInfo enumClassObjectInfo() { + return new FilteringClassLikeInfo(resolveSession.getStorageManager(), originalClassInfo, ONLY_ENUM_ENTRIES) { @Override public JetClassOrObject getCorrespondingClassOrObject() { return null; @@ -503,6 +511,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc }; } + @NotNull private ScopeProvider getScopeProvider() { return resolveSession.getInjector().getScopeProvider(); } diff --git a/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt b/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt index 0a3cdf61f70..0b2f4fd3f59 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt @@ -1,7 +1,5 @@ package test -test.A(a = 12.toInt(): jet.Int, c = "Hello": jet.String) internal val SomeObject: test.SomeObject - internal final annotation class A : jet.Annotation { /*primary*/ public constructor A(/*0*/ a: jet.Int = ..., /*1*/ b: jet.String = ..., /*2*/ c: jet.String) internal final val a: jet.Int @@ -11,4 +9,8 @@ internal final annotation class A : jet.Annotation { test.A(a = 12.toInt(): jet.Int, c = "Hello": jet.String) internal object SomeObject { /*primary*/ private constructor SomeObject() + + public class object : test.SomeObject { + /*primary*/ private constructor () + } } diff --git a/compiler/testData/lazyResolve/namespaceComparator/UnresolvedAnnotationOnObject.txt b/compiler/testData/lazyResolve/namespaceComparator/UnresolvedAnnotationOnObject.txt index 85466a6eedf..5c571dc2c99 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/UnresolvedAnnotationOnObject.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/UnresolvedAnnotationOnObject.txt @@ -1,8 +1,11 @@ package test -[ERROR : Unresolved annotation type: BadAnnotation]() internal val SomeObject: test.SomeObject internal val some: test.SomeObject [ERROR : Unresolved annotation type: BadAnnotation]() internal object SomeObject { /*primary*/ private constructor SomeObject() + + public class object : test.SomeObject { + /*primary*/ private constructor () + } } diff --git a/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt b/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt index 6fe261ea1b2..511ebf05e49 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt @@ -1,6 +1,5 @@ package test -test.BadAnnotation(s = 1.toInt(): jet.Int) internal val SomeObject: test.SomeObject internal val some: test.SomeObject internal final annotation class BadAnnotation : jet.Annotation { @@ -9,4 +8,8 @@ internal final annotation class BadAnnotation : jet.Annotation { test.BadAnnotation(s = 1.toInt(): jet.Int) internal object SomeObject { /*primary*/ private constructor SomeObject() + + public class object : test.SomeObject { + /*primary*/ private constructor () + } } diff --git a/compiler/testData/lazyResolve/namespaceComparator/objectInClass.txt b/compiler/testData/lazyResolve/namespaceComparator/objectInClass.txt index f80c6629e15..9fb4e6663e2 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/objectInClass.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/objectInClass.txt @@ -2,10 +2,14 @@ package test internal final class A { /*primary*/ public constructor A() - internal final val B: test.A.B internal object B { /*primary*/ private constructor B() internal final fun foo(/*0*/ a: jet.Int): jet.String + + public class object : test.A.B { + /*primary*/ private constructor () + internal final override /*1*/ /*fake_override*/ fun foo(/*0*/ a: jet.Int): jet.String + } } } diff --git a/compiler/testData/lazyResolve/namespaceComparator/objectMembers.txt b/compiler/testData/lazyResolve/namespaceComparator/objectMembers.txt index d17a6bf0ff6..a6cefe3383e 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/objectMembers.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/objectMembers.txt @@ -1,8 +1,11 @@ package test -internal val SomeObject: test.SomeObject - internal object SomeObject { /*primary*/ private constructor SomeObject() internal final fun test(/*0*/ a: jet.Int): jet.Int + + public class object : test.SomeObject { + /*primary*/ private constructor () + internal final override /*1*/ /*fake_override*/ fun test(/*0*/ a: jet.Int): jet.Int + } } diff --git a/compiler/testData/lazyResolve/namespaceComparator/packageLevelObject.txt b/compiler/testData/lazyResolve/namespaceComparator/packageLevelObject.txt index 84daf01dfad..8dbaa3f8a94 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/packageLevelObject.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/packageLevelObject.txt @@ -1,7 +1,9 @@ package test -internal val Bar: test.Bar - internal object Bar { /*primary*/ private constructor Bar() + + public class object : test.Bar { + /*primary*/ private constructor () + } } diff --git a/compiler/testData/loadKotlin/class/NamedObject.txt b/compiler/testData/loadKotlin/class/NamedObject.txt index 8816a0db0d0..0178e1dc0f9 100644 --- a/compiler/testData/loadKotlin/class/NamedObject.txt +++ b/compiler/testData/loadKotlin/class/NamedObject.txt @@ -1,10 +1,15 @@ package test -public val Obj: test.Obj - public object Obj { /*primary*/ private constructor Obj() public final val v: jet.String public final fun (): jet.String public final fun f(): jet.String + + public class object : test.Obj { + /*primary*/ private constructor () + public final override /*1*/ /*fake_override*/ val v: jet.String + public final override /*1*/ /*fake_override*/ fun (): jet.String + public final override /*1*/ /*fake_override*/ fun f(): jet.String + } } diff --git a/compiler/testData/loadKotlin/class/NamedObjectInClass.txt b/compiler/testData/loadKotlin/class/NamedObjectInClass.txt index d34694c31c3..72a57deaefc 100644 --- a/compiler/testData/loadKotlin/class/NamedObjectInClass.txt +++ b/compiler/testData/loadKotlin/class/NamedObjectInClass.txt @@ -2,12 +2,18 @@ package test public final class Outer { /*primary*/ public constructor Outer() - public final val Obj: test.Outer.Obj public object Obj { /*primary*/ private constructor Obj() public final val v: jet.String public final fun (): jet.String public final fun f(): jet.String + + public class object : test.Outer.Obj { + /*primary*/ private constructor () + public final override /*1*/ /*fake_override*/ val v: jet.String + public final override /*1*/ /*fake_override*/ fun (): jet.String + public final override /*1*/ /*fake_override*/ fun f(): jet.String + } } } diff --git a/compiler/testData/loadKotlin/class/NamedObjectInClassObject.txt b/compiler/testData/loadKotlin/class/NamedObjectInClassObject.txt index f4e301dd811..1244d6d3c6f 100644 --- a/compiler/testData/loadKotlin/class/NamedObjectInClassObject.txt +++ b/compiler/testData/loadKotlin/class/NamedObjectInClassObject.txt @@ -5,13 +5,19 @@ public final class Outer { public class object { /*primary*/ private constructor () - public final val Obj: test.Outer.Obj public object Obj { /*primary*/ private constructor Obj() public final val v: jet.String public final fun (): jet.String public final fun f(): jet.String + + public class object : test.Outer.Obj { + /*primary*/ private constructor () + public final override /*1*/ /*fake_override*/ val v: jet.String + public final override /*1*/ /*fake_override*/ fun (): jet.String + public final override /*1*/ /*fake_override*/ fun f(): jet.String + } } } } diff --git a/compiler/testData/loadKotlin/class/NamedObjectInNamedObject.txt b/compiler/testData/loadKotlin/class/NamedObjectInNamedObject.txt index 752d4062237..1428c2f25c9 100644 --- a/compiler/testData/loadKotlin/class/NamedObjectInNamedObject.txt +++ b/compiler/testData/loadKotlin/class/NamedObjectInNamedObject.txt @@ -1,15 +1,23 @@ package test -public val Outer: test.Outer - public object Outer { /*primary*/ private constructor Outer() - public final val Obj: test.Outer.Obj + + public class object : test.Outer { + /*primary*/ private constructor () + } public object Obj { /*primary*/ private constructor Obj() public final val v: jet.String public final fun (): jet.String public final fun f(): jet.String + + public class object : test.Outer.Obj { + /*primary*/ private constructor () + public final override /*1*/ /*fake_override*/ val v: jet.String + public final override /*1*/ /*fake_override*/ fun (): jet.String + public final override /*1*/ /*fake_override*/ fun f(): jet.String + } } } diff --git a/compiler/testData/loadKotlin/class/NamedObjectWithAnotherTopLevelProperty.txt b/compiler/testData/loadKotlin/class/NamedObjectWithAnotherTopLevelProperty.txt index a6105fe5b43..a6406a1ff3a 100644 --- a/compiler/testData/loadKotlin/class/NamedObjectWithAnotherTopLevelProperty.txt +++ b/compiler/testData/loadKotlin/class/NamedObjectWithAnotherTopLevelProperty.txt @@ -1,6 +1,5 @@ package test -public val Obj: test.Obj internal val x: jet.Int internal fun (): jet.Int @@ -9,4 +8,11 @@ public object Obj { public final val v: jet.String public final fun (): jet.String public final fun f(): jet.String + + public class object : test.Obj { + /*primary*/ private constructor () + public final override /*1*/ /*fake_override*/ val v: jet.String + public final override /*1*/ /*fake_override*/ fun (): jet.String + public final override /*1*/ /*fake_override*/ fun f(): jet.String + } } diff --git a/compiler/tests/org/jetbrains/jet/test/util/DescriptorValidator.java b/compiler/tests/org/jetbrains/jet/test/util/DescriptorValidator.java index 8bb46e2ec8f..b189a77adba 100644 --- a/compiler/tests/org/jetbrains/jet/test/util/DescriptorValidator.java +++ b/compiler/tests/org/jetbrains/jet/test/util/DescriptorValidator.java @@ -396,12 +396,7 @@ public class DescriptorValidator { public Void visitClassDescriptor( ClassDescriptor descriptor, JetScope scope ) { - if (descriptor.getKind().isSingleton()) { - assertFound(scope, descriptor, scope.getObjectDescriptor(descriptor.getName())); - } - else { - assertFound(scope, descriptor, scope.getClassifier(descriptor.getName())); - } + assertFound(scope, descriptor, scope.getClassifier(descriptor.getName())); return null; } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 93542a6d641..589c476ad96 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -327,6 +327,16 @@ public class DescriptorUtils { return false; } + public static boolean isSyntheticClassObject(@NotNull DeclarationDescriptor descriptor) { + if (isClassObject(descriptor)) { + DeclarationDescriptor containing = descriptor.getContainingDeclaration(); + if (containing != null) { + return isEnumClass(containing) || isObject(containing) || isEnumEntry(containing); + } + } + return false; + } + @NotNull public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) { ClassKind classKind = classDescriptor.getKind();