Support enum entries as members (not matching the eager resolve behavior)

This commit is contained in:
Andrey Breslav
2012-06-15 16:30:25 +04:00
parent c4484cf81d
commit 150b54a615
8 changed files with 183 additions and 48 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
import org.jetbrains.jet.lang.resolve.name.LabelName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -68,9 +69,8 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
if (object != classOrObjectDeclaration instanceof JetObjectDeclaration) return null;
ClassMemberDeclarationProvider classMemberDeclarationProvider =
resolveSession.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classOrObjectDeclaration);
ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name, classMemberDeclarationProvider);
ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name,
JetClassInfoUtil.createClassLikeInfo(classOrObjectDeclaration));
classDescriptors.put(name, classDescriptor);
allDescriptors.add(classDescriptor);
@@ -18,7 +18,7 @@ package org.jetbrains.jet.lang.resolve.lazy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.name.FqName;
/**
@@ -26,7 +26,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
*/
public interface DeclarationProviderFactory {
@NotNull
ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassOrObject jetClassOrObject);
ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassLikeInfo classLikeInfo);
@Nullable
PackageMemberDeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName);
@@ -19,10 +19,9 @@ package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.base.Predicate;
import com.google.common.collect.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collection;
@@ -39,7 +38,7 @@ public class FileBasedDeclarationProviderFactory implements DeclarationProviderF
private final Multimap<FqName, JetFile> filesByPackage = HashMultimap.create();
private final Set<FqName> declaredPackages = Sets.newHashSet();
private final Map<FqName, PackageMemberDeclarationProvider> packageDeclarationProviders = Maps.newHashMap();
private final Map<JetClassOrObject, ClassMemberDeclarationProvider> classMemberDeclarationProviders = Maps.newHashMap();
//private final Map<JetClassOrObject, ClassMemberDeclarationProvider> classMemberDeclarationProviders = Maps.newHashMap();
private boolean indexed = false;
@@ -104,23 +103,25 @@ public class FileBasedDeclarationProviderFactory implements DeclarationProviderF
@NotNull
@Override
public ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassOrObject jetClassOrObject) {
public ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassLikeInfo classLikeInfo) {
createIndex();
ClassMemberDeclarationProvider declarationProvider = classMemberDeclarationProviders.get(jetClassOrObject);
if (declarationProvider != null) {
return declarationProvider;
//JetClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
//if (classOrObject != null) {
// ClassMemberDeclarationProvider declarationProvider = classMemberDeclarationProviders.get(classOrObject);
// if (declarationProvider != null) {
// return declarationProvider;
// }
//}
if (!filesByPackage.containsKey(classLikeInfo.getContainingPackageFqName())) {
throw new IllegalStateException("This factory doesn't know about this class: " + classLikeInfo);
}
JetFile file = (JetFile) jetClassOrObject.getContainingFile();
if (!filesByPackage.containsKey(new FqName(file.getNamespaceHeader().getQualifiedName()))) {
throw new IllegalStateException("This factory doesn't know about this class: " + jetClassOrObject);
}
ClassMemberDeclarationProvider provider = new PsiBasedClassMemberDeclarationProvider(
JetClassInfoUtil.createClassLikeInfo(jetClassOrObject));
classMemberDeclarationProviders.put(jetClassOrObject, provider);
ClassMemberDeclarationProvider provider = new PsiBasedClassMemberDeclarationProvider(classLikeInfo);
//if (classOrObject != null) {
// classMemberDeclarationProviders.put(classOrObject, provider);
//}
return provider;
}
@@ -16,14 +16,16 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.lazy.data.FilteringClassLikeInfo;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.*;
@@ -39,7 +41,9 @@ import java.util.*;
*/
public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDescriptorFromSource {
private static final Predicate<Object> ONLY_ENUM_ENTIRES = Predicates.instanceOf(JetEnumEntry.class);
private final ResolveSession resolveSession;
private final JetClassLikeInfo originalClassInfo;
private final ClassMemberDeclarationProvider declarationProvider;
private final Name name;
@@ -65,21 +69,23 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
@NotNull ResolveSession resolveSession,
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull Name name,
@NotNull ClassMemberDeclarationProvider memberDeclarationProvider
@NotNull JetClassLikeInfo classLikeInfo
) {
this.declarationProvider = memberDeclarationProvider;
this.resolveSession = resolveSession;
this.originalClassInfo = classLikeInfo;
JetClassLikeInfo classLikeInfoForMembers =
classLikeInfo.getClassKind() != ClassKind.ENUM_CLASS ? classLikeInfo : noEnumEntries(classLikeInfo);
this.declarationProvider = resolveSession.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfoForMembers);
this.name = name;
this.containingDeclaration = containingDeclaration;
this.unsubstitutedMemberScope = new LazyClassMemberScope(resolveSession, memberDeclarationProvider, this);
this.unsubstitutedMemberScope = new LazyClassMemberScope(resolveSession, declarationProvider, this);
this.unsubstitutedInnerClassesScope = new InnerClassesScopeWrapper(unsubstitutedMemberScope);
this.typeConstructor = new LazyClassTypeConstructor();
JetClassLikeInfo classInfo = memberDeclarationProvider.getOwnerInfo();
this.kind = classInfo.getClassKind();
this.kind = classLikeInfo.getClassKind();
Modality defaultModality = kind == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL;
JetModifierList modifierList = classInfo.getModifierList();
JetModifierList modifierList = classLikeInfo.getModifierList();
this.modality = DescriptorResolver.resolveModalityFromModifiers(modifierList, defaultModality);
this.visibility = DescriptorResolver.resolveVisibilityFromModifiers(modifierList);
}
@@ -166,25 +172,25 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
if (!classObjectDescriptorResolved) {
JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject();
ClassMemberDeclarationProvider classObjectMemberProvider = null;
boolean isEnum = getKind() == ClassKind.ENUM_CLASS;
JetClassLikeInfo classObjectInfo = null;
if (classObject != null) {
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
if (objectDeclaration != null) {
classObjectMemberProvider = resolveSession.getDeclarationProviderFactory()
.getClassMemberDeclarationProvider(objectDeclaration);
classObjectInfo = JetClassInfoUtil.createClassLikeInfo(objectDeclaration);
}
}
else if (getKind() == ClassKind.ENUM_CLASS) {
// Enum classes always have class objects, and enum constants are their members
Collection<JetDeclaration> enumEntries =
Collections2.filter(declarationProvider.getAllDeclarations(), Predicates.instanceOf(JetEnumEntry.class));
classObjectMemberProvider = new PsiBasedClassMemberDeclarationProvider(null);
else {
if (isEnum) {
// Enum classes always have class objects, and enum constants are their members
classObjectInfo = onlyEnumEntries(originalClassInfo);
}
}
if (classObjectMemberProvider != null) {
classObjectDescriptor = new LazyClassDescriptor(resolveSession, this, JetPsiUtil.NO_NAME_PROVIDED,
classObjectMemberProvider);
if (classObjectInfo != null) {
classObjectDescriptor = new LazyClassDescriptor(resolveSession, this, isEnum ? Name.special("<class-object-for-" + getName() + ">") : JetPsiUtil.NO_NAME_PROVIDED,
classObjectInfo);
}
classObjectDescriptorResolved = true;
}
@@ -303,4 +309,19 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
return LazyClassDescriptor.this.getName().toString();
}
}
private static JetClassLikeInfo noEnumEntries(JetClassLikeInfo classLikeInfo) {
return new FilteringClassLikeInfo(classLikeInfo, Predicates.not(ONLY_ENUM_ENTIRES));
}
private static JetClassLikeInfo onlyEnumEntries(JetClassLikeInfo classLikeInfo) {
return new FilteringClassLikeInfo(classLikeInfo, ONLY_ENUM_ENTIRES) {
@NotNull
@Override
public ClassKind getClassKind() {
return ClassKind.OBJECT;
}
};
}
}
@@ -43,9 +43,6 @@ public class PsiBasedClassMemberDeclarationProvider extends AbstractPsiBasedDecl
if (declaration instanceof JetClassObject) {
// Do nothing, class object will be taken directly from the classInfo
}
else if (declaration instanceof JetEnumEntry) {
// Do nothing, entries are actually declared in the class object
}
else {
putToIndex(declaration);
}
@@ -0,0 +1,111 @@
/*
* Copyright 2010-2012 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.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
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.name.FqName;
import java.util.List;
/**
* @author abreslav
*/
public class FilteringClassLikeInfo implements JetClassLikeInfo {
private final JetClassLikeInfo delegate;
private final Predicate<? super JetDeclaration> declarationFilter;
private List<JetDeclaration> filteredDeclarations;
public FilteringClassLikeInfo(@NotNull JetClassLikeInfo delegate, @NotNull Predicate<? super JetDeclaration> declarationFilter) {
this.delegate = delegate;
this.declarationFilter = declarationFilter;
}
@NotNull
@Override
public FqName getContainingPackageFqName() {
return delegate.getContainingPackageFqName();
}
@Override
@NotNull
public List<JetDelegationSpecifier> getDelegationSpecifiers() {
return delegate.getDelegationSpecifiers();
}
@Override
@Nullable
public JetModifierList getModifierList() {
return delegate.getModifierList();
}
@Override
@Nullable
public JetClassObject getClassObject() {
return delegate.getClassObject();
}
@Override
@NotNull
public PsiElement getScopeAnchor() {
return delegate.getScopeAnchor();
}
@Override
@Nullable
public JetClassOrObject getCorrespondingClassOrObject() {
return delegate.getCorrespondingClassOrObject();
}
@Override
@NotNull
public List<JetTypeParameter> getTypeParameters() {
return delegate.getTypeParameters();
}
@Override
@NotNull
public List<? extends JetParameter> getPrimaryConstructorParameters() {
return delegate.getPrimaryConstructorParameters();
}
@Override
@NotNull
public ClassKind getClassKind() {
return delegate.getClassKind();
}
@Override
@NotNull
public List<JetDeclaration> getDeclarations() {
if (filteredDeclarations == null) {
filteredDeclarations = Lists.newArrayList(Collections2.filter(delegate.getDeclarations(), declarationFilter));
}
return filteredDeclarations;
}
@Override
public String toString() {
return "filtering " + delegate.toString();
}
}
@@ -19,13 +19,21 @@ 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;
/**
* @author abreslav
*/
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);
@@ -18,10 +18,7 @@ package org.jetbrains.jet.lang.resolve.lazy.data;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.psi.JetClassObject;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.jet.lang.psi.JetTypeParameter;
import org.jetbrains.jet.lang.psi.*;
import java.util.Collections;
import java.util.List;
@@ -29,9 +26,9 @@ import java.util.List;
/**
* @author abreslav
*/
public class JetObjectInfo extends JetClassOrObjectInfo<JetObjectDeclaration> {
public class JetObjectInfo extends JetClassOrObjectInfo<JetClassOrObject> {
protected JetObjectInfo(@NotNull JetObjectDeclaration element) {
protected JetObjectInfo(@NotNull JetClassOrObject element) {
super(element);
}