extract interface from PyClassType

This commit is contained in:
Dmitry Jemerov
2012-08-09 13:21:34 +02:00
parent ae18478861
commit 408b9e0116
22 changed files with 77 additions and 66 deletions
@@ -0,0 +1,22 @@
package com.jetbrains.python.psi.types;
import com.intellij.openapi.util.UserDataHolder;
import com.jetbrains.python.psi.PyClass;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyClassType extends PyCallableType, UserDataHolder {
@Nullable
PyClass getPyClass();
boolean isDefinition();
PyClassType toInstance();
@Nullable
String getClassQName();
boolean isValid();
}
@@ -8,7 +8,7 @@ import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.impl.PyElementImpl;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyClassTypeImpl;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
@@ -182,7 +182,7 @@ public class PyDynamicMember {
if (myTypeCallback != null) {
return myTypeCallback.fun(myContext);
}
return new PyClassType(myClass, !myResolveToInstance);
return new PyClassTypeImpl(myClass, !myResolveToInstance);
}
}
}
@@ -12,10 +12,7 @@ import com.jetbrains.python.psi.impl.PyElementImpl;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.types.PyCallableType;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,7 +23,7 @@ import java.util.List;
/**
* @author yole
*/
public class PyNamedTupleType extends PyClassType implements PyCallableType {
public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType {
private final String myName;
private final boolean myDefinition;
private final PsiElement myDeclaration;
@@ -9,10 +9,7 @@ import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyImportedModule;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.resolve.ResolveImportUtil;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyImportedModuleType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,7 +41,7 @@ public class DocStringTypeReference extends PsiReferenceBase<PsiElement> {
if (qname != null) {
qname = qname.append(cls.getName());
ElementManipulator<PyStringLiteralExpression> manipulator = ElementManipulators.getManipulator(e);
myType = new PyClassType(cls, false);
myType = new PyClassTypeImpl(cls, false);
return manipulator.handleContentChange(e, myFullRange, qname.toString());
}
}
@@ -389,7 +389,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return;
}
if (refex.getQualifier() != null) {
final PyClassType object_type = PyBuiltinCache.getInstance(node).getObjectType();
final PyClassTypeImpl object_type = (PyClassTypeImpl)PyBuiltinCache.getInstance(node).getObjectType();
if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refname)) return;
}
else {
@@ -446,7 +446,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return;
}
addCreateMemberFromUsageFixes(qtype, reference, ref_text, actions);
if (qtype instanceof PyClassType) {
if (qtype instanceof PyClassTypeImpl) {
if (reference instanceof PyOperatorReference) {
description = PyBundle.message("INSP.unresolved.operator.ref",
qtype.getName(), refname,
@@ -530,7 +530,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return true;
}
}
if (qtype instanceof PyClassType) {
if (qtype instanceof PyClassTypeImpl) {
PyClass cls = ((PyClassType)qtype).getPyClass();
if (cls != null) {
if (overridesGetAttr(cls)) {
@@ -562,7 +562,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
private static void addCreateMemberFromUsageFixes(PyType qtype, PsiReference reference, String refText, List<LocalQuickFix> actions) {
PsiElement element = reference.getElement();
if (qtype instanceof PyClassType) {
if (qtype instanceof PyClassTypeImpl) {
PyClass cls = ((PyClassType)qtype).getPyClass();
if (cls != null) {
if (!PyBuiltinCache.getInstance(element).hasInBuiltins(cls)) {
@@ -597,7 +597,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
PyExpression callexpr = ((PyAssignmentStatement)statement).getAssignedValue();
if (callexpr instanceof PyCallExpression) {
PyType type = myTypeEvalContext.getType(callexpr);
if (type != null && type instanceof PyClassType) {
if (type != null && type instanceof PyClassTypeImpl) {
String name = ((PyCallExpression)callexpr).getCallee().getText();
if (name != null && name.equals("property")) {
actions.add(new UnresolvedReferenceAddSelfQuickFix(refex));
@@ -41,10 +41,7 @@ import com.jetbrains.python.documentation.EpydocUtil;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyTupleType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.refactoring.classes.extractSuperclass.PyExtractSuperclassHelper;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -398,7 +395,7 @@ public class PyUtil {
if ("__class__".equals(attr_name)) {
PyType qual_type = context.getType(qualifier);
if (qual_type instanceof PyClassType) {
return new PyClassType(((PyClassType)qual_type).getPyClass(), true); // always as class, never instance
return new PyClassTypeImpl(((PyClassType)qual_type).getPyClass(), true); // always as class, never instance
}
}
else if ("__dict__".equals(attr_name)) {
@@ -23,10 +23,7 @@ import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PySequenceExpression;
import com.jetbrains.python.psi.resolve.PythonSdkPathCache;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyLiteralCollectionType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.PyUnionType;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -186,13 +183,13 @@ public class PyBuiltinCache {
/**
* Stores the most often used types, returned by getNNNType().
*/
private final Map<String, PyClassType> myTypeCache = new HashMap<String, PyClassType>();
private final Map<String, PyClassTypeImpl> myTypeCache = new HashMap<String, PyClassTypeImpl>();
private final Map<String, Ref<PyType>> myStdlibTypeCache = new HashMap<String, Ref<PyType>>();
private long myModStamp = -1;
@Nullable
public PyClassType getObjectType(@NonNls String name) {
PyClassType val;
public PyClassTypeImpl getObjectType(@NonNls String name) {
PyClassTypeImpl val;
synchronized (myTypeCache) {
if (myBuiltinsFile != null) {
if (myBuiltinsFile.getModificationStamp() != myModStamp) {
@@ -205,7 +202,7 @@ public class PyBuiltinCache {
if (val == null) {
PyClass cls = getClass(name);
if (cls != null) { // null may happen during testing
val = new PyClassType(cls, false);
val = new PyClassTypeImpl(cls, false);
val.assertValid(name);
synchronized (myTypeCache) {
myTypeCache.put(name, val);
@@ -158,7 +158,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
final PyType elementType = ((PyCollectionType)t).getElementType(context);
return new PyCollectionTypeImpl(cls, false, elementType);
}
return new PyClassType(cls, false);
return new PyClassTypeImpl(cls, false);
}
}
if (t != null && !(t instanceof PyNoneType)) {
@@ -172,7 +172,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
}
}
if (cls != null) {
return new PyClassType(cls, false);
return new PyClassTypeImpl(cls, false);
}
final PyType providedType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(target, context, this);
if (providedType != null) {
@@ -260,7 +260,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
if (secondClass != null && secondClass.isSubclass(firstClass)) {
final Iterator<PyClass> iterator = firstClass.iterateAncestorClasses().iterator();
if (iterator.hasNext()) {
return new PyClassType(iterator.next(), false); // super(Foo, self) has type of Foo, modulo __get__()
return new PyClassTypeImpl(iterator.next(), false); // super(Foo, self) has type of Foo, modulo __get__()
}
}
}
@@ -276,11 +276,11 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
final PyClass[] supers = pyClass.getSuperClasses();
if (supers.length > 0) {
if (supers.length == 1) {
return new PyClassType(supers[0], false);
return new PyClassTypeImpl(supers[0], false);
}
List<PyType> superTypes = new ArrayList<PyType>();
for (PyClass aSuper : supers) {
superTypes.add(new PyClassType(aSuper, false));
superTypes.add(new PyClassTypeImpl(aSuper, false));
}
return PyUnionType.union(superTypes);
}
@@ -25,7 +25,7 @@ import com.jetbrains.python.psi.stubs.PropertyStubStorage;
import com.jetbrains.python.psi.stubs.PyClassStub;
import com.jetbrains.python.psi.stubs.PyFunctionStub;
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyClassTypeImpl;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.toolbox.Maybe;
@@ -54,7 +54,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
@Override
public PyType getType(@NotNull TypeEvalContext context) {
return new PyClassType(this, true);
return new PyClassTypeImpl(this, true);
}
private class NewStyleCachedValueProvider implements CachedValueProvider<Boolean> {
@@ -208,7 +208,7 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
if (anno != null) {
PyClass pyClass = anno.resolveToClass();
if (pyClass != null) {
return new PyClassType(pyClass, false);
return new PyClassTypeImpl(pyClass, false);
}
}
}
@@ -173,7 +173,7 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl<PyNamedParame
if (initType != null && !(initType instanceof PyNoneType)) {
return initType;
}
return new PyClassType(containingClass, modifier == PyFunction.Modifier.CLASSMETHOD);
return new PyClassTypeImpl(containingClass, modifier == PyFunction.Modifier.CLASSMETHOD);
}
}
if (isKeywordContainer()) {
@@ -186,7 +186,7 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl<PyNamedParame
if (anno != null) {
final PyClass pyClass = anno.resolveToClass();
if (pyClass != null) {
return new PyClassType(pyClass, false);
return new PyClassTypeImpl(pyClass, false);
}
}
@@ -347,7 +347,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
if (exceptClass instanceof PyReferenceExpression) {
final PsiElement element = ((PyReferenceExpression)exceptClass).getReference().resolve();
if (element instanceof PyClass) {
return new PyClassType((PyClass) element, false);
return new PyClassTypeImpl((PyClass) element, false);
}
}
return null;
@@ -307,7 +307,7 @@ public class PyQualifiedReference extends PyReferenceImpl {
Collection<PyClass> classes = PyClassNameIndexInsensitive.find(className, getElement().getProject());
classes = filterByImports(classes, myElement.getContainingFile());
if (classes.size() == 1) {
final PyClassType classType = new PyClassType(classes.iterator().next(), false);
final PyClassType classType = new PyClassTypeImpl(classes.iterator().next(), false);
return getTypeCompletionVariants(myElement, classType);
}
}
@@ -14,6 +14,7 @@ public interface PyClassMembersProvider {
ExtensionPointName<PyClassMembersProvider> EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider");
Collection<PyDynamicMember> getMembers(PyClassType clazz);
@Nullable
PsiElement resolveMember(PyClassType clazz, String name);
}
@@ -32,7 +32,7 @@ import java.util.*;
/**
* @author yole
*/
public class PyClassType extends UserDataHolderBase implements PyCallableType {
public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
@Nullable protected final PyClass myClass;
protected final boolean myIsDefinition;
@@ -53,17 +53,17 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
* @param source PyClass which defines this type. For builtin or external classes, skeleton files contain the definitions.
* @param is_definition whether this type describes an instance or a definition of the class.
*/
public PyClassType(@Nullable PyClass source, boolean is_definition) {
public PyClassTypeImpl(@Nullable PyClass source, boolean is_definition) {
myClass = source != null ? CompletionUtil.getOriginalElement(source) : null;
myIsDefinition = is_definition;
}
public PyClassType(@NotNull Project project, String classQualifiedName, boolean isDefinition) {
public PyClassTypeImpl(@NotNull Project project, String classQualifiedName, boolean isDefinition) {
myClass = PyClassNameIndex.findClass(classQualifiedName, project);
myIsDefinition = isDefinition;
}
public <T> PyClassType withUserData(Key<T> key, T value) {
public <T> PyClassTypeImpl withUserData(Key<T> key, T value) {
putUserData(key, value);
return this;
}
@@ -71,7 +71,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
/**
* @return a PyClass which defined this type.
*/
@Nullable
@Override@Nullable
public PyClass getPyClass() {
return myClass;
}
@@ -79,15 +79,15 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
/**
* @return whether this type refers to an instance or a definition of the class.
*/
public boolean isDefinition() {
@Override public boolean isDefinition() {
return myIsDefinition;
}
public PyClassType toInstance() {
return myIsDefinition ? new PyClassType(myClass, false) : this;
@Override public PyClassType toInstance() {
return myIsDefinition ? new PyClassTypeImpl(myClass, false) : this;
}
@Nullable
@Override@Nullable
public String getClassQName() {
return myClass == null ? null : myClass.getQualifiedName();
}
@@ -148,7 +148,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
if (derived_class != null) {
final Iterator<PyClass> base_it = derived_class.iterateAncestorClasses().iterator();
if (base_it.hasNext()) {
return new PyClassType(base_it.next(), true).resolveMember(name, location, direction, resolveContext);
return new PyClassTypeImpl(base_it.next(), true).resolveMember(name, location, direction, resolveContext);
}
else {
return null; // no base classes = super() cannot proxy anything meaningful from a base class
@@ -202,7 +202,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
for (PyClassRef superClass : myClass.iterateAncestors()) {
final PyClass pyClass = superClass.getPyClass();
if (pyClass != null) {
PsiElement superMember = resolveByMembersProviders(new PyClassType(pyClass, isDefinition()), name);
PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name);
if (superMember != null) {
return ResolveResultList.to(superMember);
@@ -225,7 +225,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
if (metaclass instanceof PyReferenceExpression) {
final QualifiedResolveResult result = ((PyReferenceExpression)metaclass).followAssignmentsChain(PyResolveContext.noImplicits());
if (result.getElement() instanceof PyClass) {
return new PyClassType((PyClass)result.getElement(), false);
return new PyClassTypeImpl((PyClass)result.getElement(), false);
}
}
}
@@ -236,7 +236,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
if (isDefinition()) {
return new PyClassType(getPyClass(), false);
return new PyClassTypeImpl(getPyClass(), false);
}
return null;
}
@@ -392,7 +392,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
return;
}
for (PyClass ancestor : myClass.getSuperClasses()) {
Object[] ancestry = (new PyClassType(ancestor, myIsDefinition)).getCompletionVariants(name, expressionHook, context);
Object[] ancestry = (new PyClassTypeImpl(ancestor, myIsDefinition)).getCompletionVariants(name, expressionHook, context);
for (Object ob : ancestry) {
String inheritedName = ob.toString();
if (!namesAlready.contains(inheritedName) && !isClassPrivate(inheritedName)) {
@@ -448,7 +448,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PyClassType classType = (PyClassType)o;
PyClassTypeImpl classType = (PyClassTypeImpl)o;
if (myIsDefinition != classType.myIsDefinition) return false;
if (myClass != null ? !myClass.equals(classType.myClass) : classType.myClass != null) return false;
@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public class PyCollectionTypeImpl extends PyClassType implements PyCollectionType {
public class PyCollectionTypeImpl extends PyClassTypeImpl implements PyCollectionType {
private final PyType myElementType;
public PyCollectionTypeImpl(@Nullable PyClass source, boolean isDefinition, PyType elementType) {
@@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public class PyLiteralCollectionType extends PyClassType implements PyCollectionType {
public class PyLiteralCollectionType extends PyClassTypeImpl implements PyCollectionType {
private final PySequenceExpression mySequence;
public PyLiteralCollectionType(@Nullable PyClass source, boolean isDefinition, PySequenceExpression sequence) {
@@ -13,7 +13,7 @@ import java.util.Arrays;
/**
* @author yole
*/
public class PyTupleType extends PyClassType implements PySubscriptableType {
public class PyTupleType extends PyClassTypeImpl implements PySubscriptableType {
private final PyType[] myElementTypes;
public PyTupleType(PsiElement anchor, PyType[] elementTypes) {
@@ -169,7 +169,7 @@ public class PyTypeParser {
if (anchorFile instanceof PyFile) {
final PyClass aClass = ((PyFile)anchorFile).findTopLevelClass(type);
if (aClass != null) {
final PyType t = new PyClassType(aClass, false);
final PyType t = new PyClassTypeImpl(aClass, false);
types.put(whole, t);
return t;
}
@@ -195,7 +195,7 @@ public class PyTypeParser {
if (StringUtil.isJavaIdentifier(type)) {
final Collection<PyClass> classes = PyClassNameIndex.find(type, anchor.getProject(), true);
if (classes.size() == 1) {
final PyType t = new PyClassType(classes.iterator().next(), false);
final PyType t = new PyClassTypeImpl(classes.iterator().next(), false);
types.put(whole, t);
return t;
}
@@ -243,7 +243,7 @@ public class PyTypeParser {
final Collection<PyClass> classes = PyClassNameIndex.find(shortName, anchor.getProject(), true);
for (PyClass aClass : classes) {
if (qName.equals(aClass.getQualifiedName())) {
final PyType t = new PyClassType(aClass, false);
final PyType t = new PyClassTypeImpl(aClass, false);
types.put(classRange.shiftRight(offset), t);
fullRanges.put(t, whole);
return t;
@@ -253,7 +253,7 @@ public class PyTypeParser {
for (PyClass aClass : classes) {
final String name = aClass.getQualifiedName();
if (name != null && name.startsWith("_")) {
final PyType t = new PyClassType(aClass, false);
final PyType t = new PyClassTypeImpl(aClass, false);
types.put(classRange.shiftRight(offset), t);
fullRanges.put(t, whole);
return t;
@@ -49,7 +49,7 @@ public class PyTypeProviderBase implements PyTypeProvider {
@Override
public PyType getType(@Nullable PyQualifiedExpression callSite, @Nullable PyType qualifierType, TypeEvalContext context) {
if (qualifierType instanceof PyClassType) {
return new PyClassType(((PyClassType)qualifierType).getPyClass(), false);
return new PyClassTypeImpl(((PyClassType)qualifierType).getPyClass(), false);
}
return null;
}
@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author traff
*/
public class PyWeakClassType extends PyClassType implements PyWeakType {
public class PyWeakClassType extends PyClassTypeImpl implements PyWeakType {
public PyWeakClassType(@Nullable PyClass source, boolean is_definition) {
super(source, is_definition);
}