Lazy resolve of enum entries

This commit is contained in:
Andrey Breslav
2012-06-25 17:59:30 +02:00
parent a76e7f6d56
commit 2c688a5e3c
6 changed files with 101 additions and 43 deletions
@@ -150,10 +150,6 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
.resolveObjectDeclaration(thisDescriptor, objectDeclaration, classifier, resolveSession.getTrace());
result.add(propertyDescriptor);
}
else if (classOrObjectDeclaration instanceof JetEnumEntry) {
JetEnumEntry jetEnumEntry = (JetEnumEntry) classOrObjectDeclaration;
throw new UnsupportedOperationException("Enums are not supported yet: " + jetEnumEntry + " " + jetEnumEntry.getText());
}
getNonDeclaredProperties(name, result);
@@ -198,7 +194,14 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
for (JetDeclaration declaration : declarationProvider.getAllDeclarations()) {
if (declaration instanceof JetClassOrObject) {
if (declaration instanceof JetEnumEntry) {
JetEnumEntry jetEnumEntry = (JetEnumEntry) declaration;
Name name = jetEnumEntry.getNameAsName();
if (name != null) {
getProperties(name);
}
}
else if (declaration instanceof JetClassOrObject) {
JetClassOrObject classOrObject = (JetClassOrObject) declaration;
Name name = classOrObject.getNameAsName();
if (name != null) {
@@ -316,11 +316,22 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private static JetClassLikeInfo onlyEnumEntries(JetClassLikeInfo classLikeInfo) {
return new FilteringClassLikeInfo(classLikeInfo, ONLY_ENUM_ENTIRES) {
@Override
public JetClassOrObject getCorrespondingClassOrObject() {
return null;
}
@NotNull
@Override
public ClassKind getClassKind() {
return ClassKind.OBJECT;
}
@NotNull
@Override
public List<? extends JetParameter> getPrimaryConstructorParameters() {
return Collections.emptyList();
}
};
}
@@ -22,11 +22,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
@@ -72,7 +73,10 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
new OverrideResolver.DescriptorSink() {
@Override
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
assert exactDescriptorClass.isInstance(fakeOverride) : "Wrong descriptor type in an override: " + fakeOverride + " while expecting " + exactDescriptorClass.getSimpleName();
assert exactDescriptorClass.isInstance(fakeOverride) : "Wrong descriptor type in an override: " +
fakeOverride +
" while expecting " +
exactDescriptorClass.getSimpleName();
//noinspection unchecked
result.add((D) fakeOverride);
}
@@ -83,7 +87,8 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
JetDeclaration declaration = (JetDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(),
fromCurrent);
assert declaration != null : "fromCurrent can not be a fake override";
trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().getName()));
trace.report(Errors.CONFLICTING_OVERLOADS
.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().getName()));
}
}
);
@@ -131,31 +136,47 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
@Override
@SuppressWarnings("unchecked")
protected void getNonDeclaredProperties(@NotNull Name name, @NotNull final Set<VariableDescriptor> result) {
JetClassOrObject classOrObject = declarationProvider.getOwnerClassOrObject();
if (classOrObject instanceof JetClass) {
JetClass jetClass = (JetClass) classOrObject;
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
ConstructorDescriptor primaryConstructor = getPrimaryConstructor();
if (primaryConstructor != null) {
List<ValueParameterDescriptor> valueParameterDescriptors = primaryConstructor.getValueParameters();
List<JetParameter> primaryConstructorParameters = jetClass.getPrimaryConstructorParameters();
assert valueParameterDescriptors.size() == primaryConstructorParameters.size();
for (ValueParameterDescriptor valueParameterDescriptor : valueParameterDescriptors) {
JetParameter parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex());
if (parameter.getValOrVarNode() != null && name.equals(parameter.getNameAsName())) {
PropertyDescriptor propertyDescriptor =
resolveSession.getInjector().getDescriptorResolver().resolvePrimaryConstructorParameterToAProperty(
thisDescriptor,
valueParameterDescriptor,
thisDescriptor.getScopeForClassHeaderResolution(),
parameter, resolveSession.getTrace()
);
result.add(propertyDescriptor);
}
// From primary constructor parameters
ConstructorDescriptor primaryConstructor = getPrimaryConstructor();
if (primaryConstructor != null) {
List<ValueParameterDescriptor> valueParameterDescriptors = primaryConstructor.getValueParameters();
List<? extends JetParameter> primaryConstructorParameters = classInfo.getPrimaryConstructorParameters();
assert valueParameterDescriptors.size() == primaryConstructorParameters.size() : "From descriptor: " + valueParameterDescriptors.size() + " but from PSI: " + primaryConstructorParameters.size();
for (ValueParameterDescriptor valueParameterDescriptor : valueParameterDescriptors) {
JetParameter parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex());
if (parameter.getValOrVarNode() != null && name.equals(parameter.getNameAsName())) {
PropertyDescriptor propertyDescriptor =
resolveSession.getInjector().getDescriptorResolver().resolvePrimaryConstructorParameterToAProperty(
thisDescriptor,
valueParameterDescriptor,
thisDescriptor.getScopeForClassHeaderResolution(),
parameter, resolveSession.getTrace()
);
result.add(propertyDescriptor);
}
}
}
// Enum entries
JetClassOrObject classOrObjectDeclaration = declarationProvider.getClassOrObjectDeclaration(name);
if (classOrObjectDeclaration instanceof JetEnumEntry) {
// TODO: This code seems to be wrong, but it mimics the present behavior of eager resolve
JetEnumEntry jetEnumEntry = (JetEnumEntry) classOrObjectDeclaration;
if (!jetEnumEntry.hasPrimaryConstructor()) {
VariableDescriptor propertyDescriptor = resolveSession.getInjector().getDescriptorResolver()
.resolveObjectDeclarationAsPropertyDescriptor(thisDescriptor,
jetEnumEntry,
resolveSession.getClassDescriptor(jetEnumEntry),
resolveSession.getTrace());
result.add(propertyDescriptor);
}
}
// Members from supertypes
Collection<PropertyDescriptor> fromSupertypes = Lists.newArrayList();
for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
fromSupertypes.addAll((Set) supertype.getMemberScope().getProperties(name));
@@ -198,12 +219,13 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
@Nullable
public ConstructorDescriptor getPrimaryConstructor() {
if (!primaryConstructorResolved) {
if (EnumSet.of(ClassKind.CLASS, ClassKind.ANNOTATION_CLASS, ClassKind.OBJECT).contains(thisDescriptor.getKind())) {
JetClassOrObject classOrObject = declarationProvider.getOwnerClassOrObject();
if (classOrObject instanceof JetClass) {
if (EnumSet.of(ClassKind.CLASS, ClassKind.ANNOTATION_CLASS, ClassKind.OBJECT, ClassKind.ENUM_CLASS).contains(thisDescriptor.getKind())) {
JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
if (thisDescriptor.getKind() != ClassKind.OBJECT) {
JetClass jetClass = (JetClass) classOrObject;
ConstructorDescriptorImpl constructor = resolveSession.getInjector().getDescriptorResolver()
.resolvePrimaryConstructorDescriptor(thisDescriptor.getScopeForClassHeaderResolution(), thisDescriptor,
.resolvePrimaryConstructorDescriptor(thisDescriptor.getScopeForClassHeaderResolution(),
thisDescriptor,
jetClass,
resolveSession.getTrace());
primaryConstructor = constructor;
@@ -16,6 +16,7 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.collect.Maps;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -28,6 +29,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -35,6 +37,7 @@ import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
@@ -49,6 +52,8 @@ public class ResolveSession {
private final InjectorForLazyResolve injector;
private final ModuleConfiguration moduleConfiguration;
private final Map<JetEnumEntry, ClassDescriptor> enumEntryClassDescriptorCache = Maps.newHashMap();
public ResolveSession(
@NotNull Project project,
@NotNull ModuleDescriptor rootDescriptor,
@@ -98,6 +103,10 @@ public class ResolveSession {
@NotNull
public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) {
if (classOrObject instanceof JetEnumEntry) {
JetEnumEntry enumEntry = (JetEnumEntry) classOrObject;
return getEnumEntryClassDescriptor(enumEntry);
}
if (classOrObject.getParent() instanceof JetClassObject) {
return getClassObjectDescriptor((JetClassObject) classOrObject.getParent());
}
@@ -108,6 +117,23 @@ public class ResolveSession {
return (ClassDescriptor) classifier;
}
@NotNull
private ClassDescriptor getEnumEntryClassDescriptor(@NotNull JetEnumEntry jetEnumEntry) {
ClassDescriptor classDescriptor = enumEntryClassDescriptorCache.get(jetEnumEntry);
if (classDescriptor != null) {
return classDescriptor;
}
DeclarationDescriptor containingDeclaration = getInjector().getScopeProvider().getResolutionScopeForDeclaration(jetEnumEntry)
.getContainingDeclaration();
LazyClassDescriptor newClassDescriptor = new LazyClassDescriptor(this,
containingDeclaration,
jetEnumEntry.getNameAsName(),
JetClassInfoUtil.createClassLikeInfo(jetEnumEntry));
enumEntryClassDescriptorCache.put(jetEnumEntry, newClassDescriptor);
return newClassDescriptor;
}
/*package*/ LazyClassDescriptor getClassObjectDescriptor(JetClassObject classObject) {
LazyClassDescriptor classDescriptor = (LazyClassDescriptor) getClassDescriptor(PsiTreeUtil.getParentOfType(classObject, JetClass.class));
LazyClassDescriptor classObjectDescriptor = (LazyClassDescriptor) classDescriptor.getClassObjectDescriptor();
@@ -86,6 +86,9 @@ public class ScopeProvider {
if (parentDeclaration instanceof JetClassOrObject) {
JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration;
LazyClassDescriptor classDescriptor = (LazyClassDescriptor) resolveSession.getClassDescriptor(classOrObject);
if (jetDeclaration instanceof JetEnumEntry) {
return ((LazyClassDescriptor) classDescriptor.getClassObjectDescriptor()).getScopeForMemberDeclarationResolution();
}
return classDescriptor.getScopeForMemberDeclarationResolution();
}
else if (parentDeclaration instanceof JetClassObject) {
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.lazy.data;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetEnumEntry;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
/**
@@ -28,12 +27,6 @@ import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
public class JetClassInfoUtil {
public static JetClassLikeInfo createClassLikeInfo(@NotNull JetClassOrObject classOrObject) {
if (classOrObject instanceof JetEnumEntry) {
JetEnumEntry jetEnumEntry = (JetEnumEntry) classOrObject;
if (!jetEnumEntry.hasPrimaryConstructor()) {
return new JetObjectInfo(jetEnumEntry);
}
}
if (classOrObject instanceof JetClass) {
JetClass jetClass = (JetClass) classOrObject;
return new JetClassInfo(jetClass);