diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ClassMemberDeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ClassMemberDeclarationProvider.java index 6c522a6b46e..e23282ad946 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ClassMemberDeclarationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ClassMemberDeclarationProvider.java @@ -17,17 +17,13 @@ package org.jetbrains.jet.lang.resolve.lazy; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetClassObject; -import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo; /** * @author abreslav */ public interface ClassMemberDeclarationProvider extends DeclarationProvider { @NotNull - JetClassOrObject getOwnerClassOrObject(); + JetClassLikeInfo getOwnerInfo(); - @Nullable - JetClassObject getClassObject(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/FileBasedDeclarationProviderFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/FileBasedDeclarationProviderFactory.java index 2837d94cdd4..c7a83d371be 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/FileBasedDeclarationProviderFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/FileBasedDeclarationProviderFactory.java @@ -22,6 +22,7 @@ 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.name.FqName; import java.util.Collection; @@ -117,7 +118,8 @@ public class FileBasedDeclarationProviderFactory implements DeclarationProviderF throw new IllegalStateException("This factory doesn't know about this class: " + jetClassOrObject); } - ClassMemberDeclarationProvider provider = new PsiBasedClassMemberDeclarationProvider(jetClassOrObject); + ClassMemberDeclarationProvider provider = new PsiBasedClassMemberDeclarationProvider( + JetClassInfoUtil.createClassLikeInfo(jetClassOrObject)); classMemberDeclarationProviders.put(jetClassOrObject, 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 f718143ed4f..157492f3a33 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,19 +16,21 @@ package org.jetbrains.jet.lang.resolve.lazy; +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.JetClassLikeInfo; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; -import org.jetbrains.jet.lexer.JetTokens; import java.util.*; @@ -74,29 +76,14 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes this.typeConstructor = new LazyClassTypeConstructor(); - JetClassOrObject classOrObject = memberDeclarationProvider.getOwnerClassOrObject(); - this.kind = getClassKind(classOrObject); + JetClassLikeInfo classInfo = memberDeclarationProvider.getOwnerInfo(); + this.kind = classInfo.getClassKind(); Modality defaultModality = kind == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL; - JetModifierList modifierList = classOrObject.getModifierList(); + JetModifierList modifierList = classInfo.getModifierList(); this.modality = DescriptorResolver.resolveModalityFromModifiers(modifierList, defaultModality); this.visibility = DescriptorResolver.resolveVisibilityFromModifiers(modifierList); } - @NotNull - private static ClassKind getClassKind(@NotNull JetClassOrObject jetClassOrObject) { - if (jetClassOrObject instanceof JetClass) { - JetClass jetClass = (JetClass) jetClassOrObject; - if (jetClass.isTrait()) return ClassKind.TRAIT; - if (jetClass.hasModifier(JetTokens.ANNOTATION_KEYWORD)) return ClassKind.ANNOTATION_CLASS; - if (jetClass.hasModifier(JetTokens.ENUM_KEYWORD)) return ClassKind.ENUM_CLASS; - return ClassKind.CLASS; - } - if (jetClassOrObject instanceof JetObjectDeclaration) { - return ClassKind.OBJECT; - } - throw new IllegalArgumentException("Unknown class or object kind: " + jetClassOrObject); - } - @Override protected JetScope getScopeForMemberLookup() { return unsubstitutedMemberScope; @@ -112,7 +99,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes public JetScope getScopeForClassHeaderResolution() { if (scopeForClassHeaderResolution == null) { WritableScopeImpl scope = new WritableScopeImpl( - resolveSession.getResolutionScope(declarationProvider.getOwnerClassOrObject()), this, RedeclarationHandler.DO_NOTHING, "Class Header Resolution"); + resolveSession.getResolutionScope(declarationProvider.getOwnerInfo().getScopeAnchor()), this, RedeclarationHandler.DO_NOTHING, "Class Header Resolution"); for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) { scope.addClassifierDescriptor(typeParameterDescriptor); } @@ -177,16 +164,28 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes @Override public ClassDescriptor getClassObjectDescriptor() { if (!classObjectDescriptorResolved) { - JetClassObject classObject = declarationProvider.getClassObject(); + JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject(); + + ClassMemberDeclarationProvider classObjectMemberProvider = null; if (classObject != null) { JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration(); if (objectDeclaration != null) { - ClassMemberDeclarationProvider classMemberDeclarationProvider = resolveSession.getDeclarationProviderFactory() - .getClassMemberDeclarationProvider(objectDeclaration); - classObjectDescriptor = new LazyClassDescriptor(resolveSession, this, JetPsiUtil.NO_NAME_PROVIDED, - classMemberDeclarationProvider); + classObjectMemberProvider = resolveSession.getDeclarationProviderFactory() + .getClassMemberDeclarationProvider(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); + } + + + if (classObjectMemberProvider != null) { + classObjectDescriptor = new LazyClassDescriptor(resolveSession, this, JetPsiUtil.NO_NAME_PROVIDED, + classObjectMemberProvider); + } classObjectDescriptorResolved = true; } return classObjectDescriptor; @@ -222,12 +221,12 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes @Override public List getAnnotations() { if (annotations == null) { - JetClassOrObject classOrObject = declarationProvider.getOwnerClassOrObject(); - JetModifierList modifierList = classOrObject.getModifierList(); + JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); + JetModifierList modifierList = classInfo.getModifierList(); if (modifierList != null) { AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver(); annotations = annotationResolver - .resolveAnnotations(resolveSession.getResolutionScope(classOrObject), modifierList, resolveSession.getTrace()); + .resolveAnnotations(resolveSession.getResolutionScope(classInfo.getScopeAnchor()), modifierList, resolveSession.getTrace()); } else { annotations = Collections.emptyList(); @@ -255,20 +254,12 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes @Override public List getParameters() { if (parameters == null) { - JetClassOrObject declaration = declarationProvider.getOwnerClassOrObject(); - if (declaration instanceof JetClass) { - JetClass jetClass = (JetClass) declaration; + JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); + List typeParameters = classInfo.getTypeParameters(); + parameters = new ArrayList(typeParameters.size()); - List typeParameters = jetClass.getTypeParameters(); - parameters = new ArrayList(typeParameters.size()); - - for (int i = 0; i < typeParameters.size(); i++) { - parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i)); - } - } - else { - // It is an object declaration, no type parameters - parameters = Collections.emptyList(); + for (int i = 0; i < typeParameters.size(); i++) { + parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i)); } } return parameters; @@ -278,11 +269,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes @Override public Collection getSupertypes() { if (supertypes == null) { - JetClassOrObject declaration = declarationProvider.getOwnerClassOrObject(); - this.supertypes = resolveSession.getInjector().getDescriptorResolver() - .resolveSupertypes(getScopeForClassHeaderResolution(), - declaration, - resolveSession.getTrace()); + JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject(); + if (classOrObject == null) { + this.supertypes = Collections.emptyList(); + } + else { + this.supertypes = resolveSession.getInjector().getDescriptorResolver() + .resolveSupertypes(getScopeForClassHeaderResolution(), + classOrObject, + resolveSession.getTrace()); + } } return supertypes; } 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 1f7863c6337..3a1768824cc 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 @@ -18,49 +18,43 @@ package org.jetbrains.jet.lang.resolve.lazy; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo; /** * @author abreslav */ public class PsiBasedClassMemberDeclarationProvider extends AbstractPsiBasedDeclarationProvider implements ClassMemberDeclarationProvider { - private final JetClassOrObject classOrObject; - private JetClassObject jetClassObject; + private final JetClassLikeInfo classInfo; - public PsiBasedClassMemberDeclarationProvider(@NotNull JetClassOrObject classOrObject) { - this.classOrObject = classOrObject; + public PsiBasedClassMemberDeclarationProvider(@NotNull JetClassLikeInfo classInfo) { + this.classInfo = classInfo; } @NotNull @Override - public JetClassOrObject getOwnerClassOrObject() { - return classOrObject; + public JetClassLikeInfo getOwnerInfo() { + return classInfo; } @Override protected void doCreateIndex() { - for (JetDeclaration declaration : classOrObject.getDeclarations()) { + for (JetDeclaration declaration : classInfo.getDeclarations()) { if (declaration instanceof JetClassObject) { - jetClassObject = (JetClassObject) declaration; + // 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); } } - if (classOrObject instanceof JetClass) { - JetClass jetClass = (JetClass) classOrObject; - for (JetParameter parameter : jetClass.getPrimaryConstructorParameters()) { - if (parameter.getValOrVarNode() != null) { - putToIndex(parameter); - } + for (JetParameter parameter : classInfo.getPrimaryConstructorParameters()) { + if (parameter.getValOrVarNode() != null) { + putToIndex(parameter); } } } - - @Override - public JetClassObject getClassObject() { - createIndex(); - return jetClassObject; - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfo.java new file mode 100644 index 00000000000..03c10b3df65 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfo.java @@ -0,0 +1,61 @@ +/* + * 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 org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.List; + +/** + * @author abreslav + */ +public class JetClassInfo extends JetClassOrObjectInfo { + + protected JetClassInfo(@NotNull JetClass classOrObject) { + super(classOrObject); + } + + @Override + public JetClassObject getClassObject() { + return element.getClassObject(); + } + + @NotNull + @Override + public List getTypeParameters() { + return element.getTypeParameters(); + } + + @NotNull + @Override + public List getPrimaryConstructorParameters() { + return element.getPrimaryConstructorParameters(); + } + + @NotNull + @Override + public ClassKind getClassKind() { + if (element instanceof JetEnumEntry) return ClassKind.ENUM_ENTRY; + if (element.isTrait()) return ClassKind.TRAIT; + if (element.hasModifier(JetTokens.ANNOTATION_KEYWORD)) return ClassKind.ANNOTATION_CLASS; + if (element.hasModifier(JetTokens.ENUM_KEYWORD)) return ClassKind.ENUM_CLASS; + return ClassKind.CLASS; + } +} 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 new file mode 100644 index 00000000000..4eef50f6a88 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassInfoUtil.java @@ -0,0 +1,39 @@ +/* + * 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 org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetObjectDeclaration; + +/** + * @author abreslav + */ +public class JetClassInfoUtil { + public static JetClassLikeInfo createClassLikeInfo(@NotNull JetClassOrObject classOrObject) { + if (classOrObject instanceof JetClass) { + JetClass jetClass = (JetClass) classOrObject; + return new JetClassInfo(jetClass); + } + if (classOrObject instanceof JetObjectDeclaration) { + JetObjectDeclaration objectDeclaration = (JetObjectDeclaration) classOrObject; + return new JetObjectInfo(objectDeclaration); + } + throw new IllegalArgumentException("Unknown declaration type: " + classOrObject + classOrObject.getText()); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassLikeInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassLikeInfo.java new file mode 100644 index 00000000000..4d384d74286 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassLikeInfo.java @@ -0,0 +1,59 @@ +/* + * 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.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 java.util.List; + +/** + * @author abreslav + */ +public interface JetClassLikeInfo extends JetDeclarationContainer { + @NotNull + List getDelegationSpecifiers(); + + //@Nullable + //Name getNameAsName(); + + @Nullable + JetModifierList getModifierList(); + + @Nullable + JetClassObject getClassObject(); + + // This element is used to identify resolution scope for the class + @NotNull + PsiElement getScopeAnchor(); + + @Nullable + JetClassOrObject getCorrespondingClassOrObject(); + + @NotNull + List getTypeParameters(); + + @NotNull + List getPrimaryConstructorParameters(); + + @NotNull + ClassKind getClassKind(); + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassOrObjectInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassOrObjectInfo.java new file mode 100644 index 00000000000..e7def9bd668 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassOrObjectInfo.java @@ -0,0 +1,73 @@ +/* + * 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.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; +import org.jetbrains.jet.lang.psi.JetModifierList; + +import java.util.List; + +/** + * @author abreslav + */ +public abstract class JetClassOrObjectInfo implements JetClassLikeInfo { + protected final E element; + + protected JetClassOrObjectInfo(@NotNull E element) { + this.element = element; + } + + @Override + public JetClassOrObject getCorrespondingClassOrObject() { + return element; + } + + @Override + @NotNull + public List getDelegationSpecifiers() { + return element.getDelegationSpecifiers(); + } + + //@Override + //@Nullable + //public Name getNameAsName() { + // return element.getNameAsName(); + //} + + @Override + @Nullable + public JetModifierList getModifierList() { + return element.getModifierList(); + } + + @Override + @NotNull + public List getDeclarations() { + return element.getDeclarations(); + } + + @NotNull + @Override + public PsiElement getScopeAnchor() { + return element; + } +} 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 new file mode 100644 index 00000000000..6c08aa0ab63 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetObjectInfo.java @@ -0,0 +1,60 @@ +/* + * 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 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 java.util.Collections; +import java.util.List; + +/** + * @author abreslav + */ +public class JetObjectInfo extends JetClassOrObjectInfo { + + protected JetObjectInfo(@NotNull JetObjectDeclaration element) { + super(element); + } + + @Override + public JetClassObject getClassObject() { + 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.OBJECT; + } +}