Blinking class object tests fixed

Now lazy descriptors for all class objects are retained by the owning class
This commit is contained in:
Andrey Breslav
2014-04-08 20:11:07 +04:00
parent e4e60bc377
commit a3638eacef
7 changed files with 73 additions and 32 deletions
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.TokenSet; import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -65,6 +64,12 @@ public class JetClassBody extends JetElementImplStub<PsiJetClassBodyStub> implem
return (JetClassObject) findChildByType(JetNodeTypes.CLASS_OBJECT); return (JetClassObject) findChildByType(JetNodeTypes.CLASS_OBJECT);
} }
@NotNull
public List<JetClassObject> getAllClassObjects() {
//noinspection unchecked
return (List) findChildrenByType(JetNodeTypes.CLASS_OBJECT);
}
@Nullable @Nullable
public PsiElement getRBrace() { public PsiElement getRBrace() {
ASTNode[] children = getNode().getChildren(TokenSet.create(JetTokens.RBRACE)); ASTNode[] children = getNode().getChildren(TokenSet.create(JetTokens.RBRACE));
@@ -22,7 +22,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function; import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import kotlin.Function0;
import kotlin.Function1; import kotlin.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -40,7 +39,6 @@ import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyScriptDescriptor; import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyScriptDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.renderer.DescriptorRenderer; import org.jetbrains.jet.renderer.DescriptorRenderer;
import org.jetbrains.jet.storage.*; import org.jetbrains.jet.storage.*;
@@ -299,7 +297,7 @@ public class ResolveSession implements KotlinCodeAnalyzer {
/*package*/ LazyClassDescriptor getClassObjectDescriptor(@NotNull JetClassObject classObject) { /*package*/ LazyClassDescriptor getClassObjectDescriptor(@NotNull JetClassObject classObject) {
JetClass aClass = PsiTreeUtil.getParentOfType(classObject, JetClass.class); JetClass aClass = PsiTreeUtil.getParentOfType(classObject, JetClass.class);
final LazyClassDescriptor parentClassDescriptor; LazyClassDescriptor parentClassDescriptor;
if (aClass != null) { if (aClass != null) {
parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(aClass); parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(aClass);
@@ -313,27 +311,11 @@ public class ResolveSession implements KotlinCodeAnalyzer {
// Activate resolution and writing to trace // Activate resolution and writing to trace
parentClassDescriptor.getClassObjectDescriptor(); parentClassDescriptor.getClassObjectDescriptor();
DeclarationDescriptor declaration = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classObject.getObjectDeclaration()); parentClassDescriptor.getDescriptorsForExtraClassObjects();
DeclarationDescriptor classObjectDescriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classObject.getObjectDeclaration());
assert classObjectDescriptor != null : "No descriptor found for " + JetPsiUtil.getElementTextWithContext(classObject);
if (declaration == null) { return (LazyClassDescriptor) classObjectDescriptor;
// It's possible that there are several class objects and another class object is taking part in lazy resolve. We still want to
// build descriptors for such class objects.
final JetClassLikeInfo classObjectInfo = parentClassDescriptor.getClassObjectInfo(classObject);
assert classObjectInfo != null :
String.format("Failed to find class object info for existent class object declaration: %s",
JetPsiUtil.getElementTextWithContext(classObject));
final Name name = SpecialNames.getClassObjectName(parentClassDescriptor.getName());
return storageManager.compute(new Function0<LazyClassDescriptor>() {
@Override
public LazyClassDescriptor invoke() {
// Create under lock to avoid premature access to published 'this'
return new LazyClassDescriptor(ResolveSession.this, parentClassDescriptor, name, classObjectInfo);
}
});
}
return (LazyClassDescriptor) declaration;
} }
@Override @Override
@@ -37,6 +37,10 @@ public interface JetClassLikeInfo extends JetDeclarationContainer {
@Nullable @Nullable
JetClassObject getClassObject(); JetClassObject getClassObject();
@NotNull
@ReadOnly
List<JetClassObject> getClassObjects();
// This element is used to identify resolution scope for the class // This element is used to identify resolution scope for the class
@NotNull @NotNull
PsiElement getScopeAnchor(); PsiElement getScopeAnchor();
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collections;
import java.util.List; import java.util.List;
public abstract class JetClassOrObjectInfo<E extends JetClassOrObject> implements JetClassLikeInfo { public abstract class JetClassOrObjectInfo<E extends JetClassOrObject> implements JetClassLikeInfo {
@@ -49,6 +50,16 @@ public abstract class JetClassOrObjectInfo<E extends JetClassOrObject> implement
return element.getDeclarations(); return element.getDeclarations();
} }
@NotNull
@Override
public List<JetClassObject> getClassObjects() {
JetClassBody body = element.getBody();
if (body == null) {
return Collections.emptyList();
}
return body.getAllClassObjects();
}
@NotNull @NotNull
@Override @Override
public PsiElement getScopeAnchor() { public PsiElement getScopeAnchor() {
@@ -21,11 +21,11 @@ import org.jetbrains.jet.lang.psi.JetParameter
import org.jetbrains.jet.lang.descriptors.ClassKind import org.jetbrains.jet.lang.descriptors.ClassKind
import org.jetbrains.jet.lang.psi.JetScript import org.jetbrains.jet.lang.psi.JetScript
import org.jetbrains.jet.lang.resolve.ScriptNameUtil import org.jetbrains.jet.lang.resolve.ScriptNameUtil
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.psi.JetNamedFunction import org.jetbrains.jet.lang.psi.JetNamedFunction
import org.jetbrains.jet.lang.psi.JetDeclaration import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.psi.JetCallableDeclaration import org.jetbrains.jet.lang.psi.JetCallableDeclaration
import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.psi.JetClassObject
public class JetScriptInfo( public class JetScriptInfo(
val script: JetScript val script: JetScript
@@ -34,6 +34,7 @@ public class JetScriptInfo(
override fun getContainingPackageFqName() = fqName.parent() override fun getContainingPackageFqName() = fqName.parent()
override fun getModifierList() = null override fun getModifierList() = null
override fun getClassObject() = null override fun getClassObject() = null
override fun getClassObjects() = listOf<JetClassObject>()
override fun getScopeAnchor() = script override fun getScopeAnchor() = script
override fun getCorrespondingClassOrObject() = null override fun getCorrespondingClassOrObject() = null
override fun getTypeParameters() = listOf<JetTypeParameter>() override fun getTypeParameters() = listOf<JetTypeParameter>()
@@ -60,6 +60,12 @@ public class SyntheticClassObjectInfo implements JetClassLikeInfo {
return null; return null;
} }
@NotNull
@Override
public List<JetClassObject> getClassObjects() {
return Collections.emptyList();
}
@NotNull @NotNull
@Override @Override
public PsiElement getScopeAnchor() { public PsiElement getScopeAnchor() {
@@ -22,16 +22,19 @@ import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import kotlin.Function0; import kotlin.Function0;
import kotlin.Function1; import kotlin.Function1;
import kotlin.Unit;
import kotlin.KotlinPackage; import kotlin.KotlinPackage;
import kotlin.Unit;
import org.jetbrains.annotations.Mutable; import org.jetbrains.annotations.Mutable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorBase; import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorBase;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver;
import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil; import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
import org.jetbrains.jet.lang.resolve.lazy.LazyEntity; import org.jetbrains.jet.lang.resolve.lazy.LazyEntity;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
@@ -46,6 +49,7 @@ import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor; import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
import org.jetbrains.jet.storage.NotNullLazyValue; import org.jetbrains.jet.storage.NotNullLazyValue;
import org.jetbrains.jet.storage.NullableLazyValue; import org.jetbrains.jet.storage.NullableLazyValue;
import org.jetbrains.jet.storage.StorageManager; import org.jetbrains.jet.storage.StorageManager;
@@ -78,6 +82,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private final Annotations annotations; private final Annotations annotations;
private final NullableLazyValue<ClassDescriptorWithResolutionScopes> classObjectDescriptor; private final NullableLazyValue<ClassDescriptorWithResolutionScopes> classObjectDescriptor;
private final MemoizedFunctionToNotNull<JetClassObject, ClassDescriptorWithResolutionScopes> extraClassObjectDescriptors;
private final LazyClassMemberScope unsubstitutedMemberScope; private final LazyClassMemberScope unsubstitutedMemberScope;
@@ -151,7 +156,13 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptorWithResolutionScopes>() { this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptorWithResolutionScopes>() {
@Override @Override
public ClassDescriptorWithResolutionScopes invoke() { public ClassDescriptorWithResolutionScopes invoke() {
return computeClassObjectDescriptor(); return computeClassObjectDescriptor(declarationProvider.getOwnerInfo().getClassObject());
}
});
this.extraClassObjectDescriptors = storageManager.createMemoizedFunction(new Function1<JetClassObject, ClassDescriptorWithResolutionScopes>() {
@Override
public ClassDescriptorWithResolutionScopes invoke(JetClassObject classObject) {
return computeClassObjectDescriptor(classObject);
} }
}); });
this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Function0<JetScope>() { this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Function0<JetScope>() {
@@ -305,10 +316,29 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
return classObjectDescriptor.invoke(); return classObjectDescriptor.invoke();
} }
@Nullable @NotNull
private ClassDescriptorWithResolutionScopes computeClassObjectDescriptor() { @ReadOnly
JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject(); public List<ClassDescriptor> getDescriptorsForExtraClassObjects() {
return KotlinPackage.map(
KotlinPackage.filter(
declarationProvider.getOwnerInfo().getClassObjects(),
new Function1<JetClassObject, Boolean>() {
@Override
public Boolean invoke(JetClassObject classObject) {
return classObject != declarationProvider.getOwnerInfo().getClassObject();
}
}),
new Function1<JetClassObject, ClassDescriptor>() {
@Override
public ClassDescriptor invoke(JetClassObject classObject) {
return extraClassObjectDescriptors.invoke(classObject);
}
}
);
}
@Nullable
private ClassDescriptorWithResolutionScopes computeClassObjectDescriptor(@Nullable JetClassObject classObject) {
JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject); JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject);
if (classObjectInfo != null) { if (classObjectInfo != null) {
return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo); return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo);
@@ -317,7 +347,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
} }
@Nullable @Nullable
public JetClassLikeInfo getClassObjectInfo(JetClassObject classObject) { private JetClassLikeInfo getClassObjectInfo(@Nullable JetClassObject classObject) {
if (classObject != null) { if (classObject != null) {
if (getKind() != ClassKind.CLASS && getKind() != ClassKind.TRAIT && getKind() != ClassKind.ANNOTATION_CLASS || isInner()) { if (getKind() != ClassKind.CLASS && getKind() != ClassKind.TRAIT && getKind() != ClassKind.ANNOTATION_CLASS || isInner()) {
resolveSession.getTrace().report(CLASS_OBJECT_NOT_ALLOWED.on(classObject)); resolveSession.getTrace().report(CLASS_OBJECT_NOT_ALLOWED.on(classObject));
@@ -381,6 +411,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
ForceResolveUtil.forceResolveAllContents(classObjectDescriptor); ForceResolveUtil.forceResolveAllContents(classObjectDescriptor);
} }
ForceResolveUtil.forceResolveAllContents(getDescriptorsForExtraClassObjects());
getClassObjectType(); getClassObjectType();
ForceResolveUtil.forceResolveAllContents(getConstructors()); ForceResolveUtil.forceResolveAllContents(getConstructors());
getContainingDeclaration(); getContainingDeclaration();