PSI data abstract through JetClassInfo, to facilitate enum literal resolution

This commit is contained in:
Andrey Breslav
2012-06-15 12:15:27 +04:00
parent b3272feb63
commit 3fbe7a2c9b
9 changed files with 353 additions and 73 deletions
@@ -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();
}
@@ -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;
@@ -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<JetDeclaration> 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<AnnotationDescriptor> 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<TypeParameterDescriptor> getParameters() {
if (parameters == null) {
JetClassOrObject declaration = declarationProvider.getOwnerClassOrObject();
if (declaration instanceof JetClass) {
JetClass jetClass = (JetClass) declaration;
JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
List<JetTypeParameter> typeParameters = classInfo.getTypeParameters();
parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
List<JetTypeParameter> typeParameters = jetClass.getTypeParameters();
parameters = new ArrayList<TypeParameterDescriptor>(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<? extends JetType> 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;
}
@@ -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;
}
}
@@ -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<JetClass> {
protected JetClassInfo(@NotNull JetClass classOrObject) {
super(classOrObject);
}
@Override
public JetClassObject getClassObject() {
return element.getClassObject();
}
@NotNull
@Override
public List<JetTypeParameter> getTypeParameters() {
return element.getTypeParameters();
}
@NotNull
@Override
public List<? extends JetParameter> 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;
}
}
@@ -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());
}
}
@@ -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<JetDelegationSpecifier> 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<JetTypeParameter> getTypeParameters();
@NotNull
List<? extends JetParameter> getPrimaryConstructorParameters();
@NotNull
ClassKind getClassKind();
}
@@ -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<E extends JetClassOrObject> implements JetClassLikeInfo {
protected final E element;
protected JetClassOrObjectInfo(@NotNull E element) {
this.element = element;
}
@Override
public JetClassOrObject getCorrespondingClassOrObject() {
return element;
}
@Override
@NotNull
public List<JetDelegationSpecifier> getDelegationSpecifiers() {
return element.getDelegationSpecifiers();
}
//@Override
//@Nullable
//public Name getNameAsName() {
// return element.getNameAsName();
//}
@Override
@Nullable
public JetModifierList getModifierList() {
return element.getModifierList();
}
@Override
@NotNull
public List<JetDeclaration> getDeclarations() {
return element.getDeclarations();
}
@NotNull
@Override
public PsiElement getScopeAnchor() {
return element;
}
}
@@ -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<JetObjectDeclaration> {
protected JetObjectInfo(@NotNull JetObjectDeclaration element) {
super(element);
}
@Override
public JetClassObject getClassObject() {
return null;
}
@NotNull
@Override
public List<JetTypeParameter> getTypeParameters() {
return Collections.emptyList();
}
@NotNull
@Override
public List<? extends JetParameter> getPrimaryConstructorParameters() {
return Collections.emptyList();
}
@NotNull
@Override
public ClassKind getClassKind() {
return ClassKind.OBJECT;
}
}