diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java index 4635435e692..5daadd96668 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java @@ -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 filesByPackage = HashMultimap.create(); private final Set declaredPackages = Sets.newHashSet(); private final Map packageDeclarationProviders = Maps.newHashMap(); - private final Map classMemberDeclarationProviders = Maps.newHashMap(); + //private final Map 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; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java index 157492f3a33..7608c685226 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java @@ -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 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 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("") : 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; + } + }; + } + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/PsiBasedClassMemberDeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/PsiBasedClassMemberDeclarationProvider.java index 3a1768824cc..6f21d79784d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/PsiBasedClassMemberDeclarationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/PsiBasedClassMemberDeclarationProvider.java @@ -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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/FilteringClassLikeInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/FilteringClassLikeInfo.java new file mode 100644 index 00000000000..5a42ab75733 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/FilteringClassLikeInfo.java @@ -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 declarationFilter; + private List filteredDeclarations; + + public FilteringClassLikeInfo(@NotNull JetClassLikeInfo delegate, @NotNull Predicate declarationFilter) { + this.delegate = delegate; + this.declarationFilter = declarationFilter; + } + + @NotNull + @Override + public FqName getContainingPackageFqName() { + return delegate.getContainingPackageFqName(); + } + + @Override + @NotNull + public List 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 getTypeParameters() { + return delegate.getTypeParameters(); + } + + @Override + @NotNull + public List getPrimaryConstructorParameters() { + return delegate.getPrimaryConstructorParameters(); + } + + @Override + @NotNull + public ClassKind getClassKind() { + return delegate.getClassKind(); + } + + @Override + @NotNull + public List getDeclarations() { + if (filteredDeclarations == null) { + filteredDeclarations = Lists.newArrayList(Collections2.filter(delegate.getDeclarations(), declarationFilter)); + } + return filteredDeclarations; + } + + @Override + public String toString() { + return "filtering " + delegate.toString(); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfoUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfoUtil.java index 4eef50f6a88..095799389b3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfoUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfoUtil.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetObjectInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetObjectInfo.java index 6c08aa0ab63..7ed92ee3966 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetObjectInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetObjectInfo.java @@ -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 { +public class JetObjectInfo extends JetClassOrObjectInfo { - protected JetObjectInfo(@NotNull JetObjectDeclaration element) { + protected JetObjectInfo(@NotNull JetClassOrObject element) { super(element); }