Fixes PY-49, PY-33, partially fixes PY-32.

Provides test cases for PY-33 and (rudimentary) for PY-49 and PY-32.
This commit is contained in:
Dmitry Cheryasov
2008-08-21 12:14:33 +04:00
parent 0bdb534481
commit 1774933718
21 changed files with 310 additions and 66 deletions

View File

@@ -2,35 +2,45 @@ package com.jetbrains.python;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.parameterInfo.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.psi.*;
import static com.jetbrains.python.psi.PyCallExpression.*;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentList, PyFunction> {
public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentList, PyCallExpression.PyMarkedFunction> {
public boolean couldShowInLookup() {
return true;
}
public Object[] getParametersForLookup(final LookupElement item, final ParameterInfoContext context) {
return new Object[0]; //To change body of implemented methods use File | Settings | File Templates.
}
public Object[] getParametersForDocumentation(final PyFunction p, final ParameterInfoContext context) {
public Object[] getParametersForDocumentation(final PyCallExpression.PyMarkedFunction p, final ParameterInfoContext context) {
return new Object[0]; //To change body of implemented methods use File | Settings | File Templates.
}
public PyArgumentList findElementForParameterInfo(final CreateParameterInfoContext context) {
PyArgumentList result = findArgumentList(context);
if (result != null) {
PyCallExpression callExpression = PsiTreeUtil.getParentOfType(result, PyCallExpression.class);
PyCallExpression callExpression = result.getCallExpression(); /*PsiTreeUtil.getParentOfType(result, PyCallExpression.class);*/
if (callExpression == null) return null;
/*
boolean is_inst = callExpression.isByInstance();
PyElement callee = callExpression.resolveCallee();
if (callee instanceof PyClass) { // constructor call
final PyClass cls = (PyClass)callee;
callee = cls.findMethodByName("__init__");
is_inst |= true;
}
if (!(callee instanceof PyFunction)) return null;
PyFunction function = (PyFunction) callee;
context.setItemsToShow(new Object[] { function });
context.setItemsToShow(new Object[] { new PyCallExpression.PyMarkedFunction(function, is_inst) });
*/
context.setItemsToShow(new Object[] { callExpression.resolveCallee() });
}
return result;
}
@@ -64,15 +74,18 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
return true;
}
public void updateUI(final PyFunction p, final ParameterInfoUIContext context) {
final PyParameterList parameterList = p.getParameterList();
public void updateUI(final PyMarkedFunction p, final ParameterInfoUIContext context) {
final PyFunction py_function = p.getFunction();
if (py_function == null) return; // resolution failed
final PyParameterList parameterList = py_function.getParameterList();
final PyParameter[] params = parameterList.getParameters();
final int currentParameterIndex = context.getCurrentParameterIndex() >= 0 ? context.getCurrentParameterIndex():params.length;
int currentParameterIndex = context.getCurrentParameterIndex() >= 0 ? context.getCurrentParameterIndex():params.length;
int highlightStartOffset = -1;
int highlightEndOffset = -1;
StringBuilder signatureBuilder = new StringBuilder();
for(int i=0; i<params.length; i++) {
if (i == currentParameterIndex) {
highlightStartOffset = signatureBuilder.length();
@@ -80,6 +93,10 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
if (params [i].isPositionalContainer()) {
signatureBuilder.append("*");
}
else if (i == 0 && p.getFlags().contains(Flag.IMPLICIT_FIRST_ARG)) {
currentParameterIndex += 1;
continue;
}
else if (params [i].isKeywordContainer()) {
signatureBuilder.append("**");
}

View File

@@ -27,11 +27,16 @@ import org.jetbrains.annotations.Nullable;
* To change this template use File | Settings | File Templates.
*/
public interface PyArgumentList extends PyElement {
@NotNull PyExpression[] getArguments();
@Nullable PyKeywordArgument getKeywordArgument(String name);
@NotNull PyExpression[] getArguments();
@Nullable PyKeywordArgument getKeywordArgument(String name);
void addArgument(PyExpression arg);
void addArgumentFirst(PyExpression arg);
void addArgumentAfter(PyExpression argument, PyExpression afterThis);
@Nullable
PyCallExpression getCallExpression();
void addArgument(PyExpression arg);
void addArgumentFirst(PyExpression arg);
void addArgumentAfter(PyExpression argument, PyExpression afterThis);
}

View File

@@ -16,8 +16,11 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
/**
* Created by IntelliJ IDEA.
* User: yole
@@ -31,6 +34,62 @@ public interface PyCallExpression extends PyExpression {
void addArgument(PyExpression expression);
/**
* Resolves callee down to particular function (standalone, method, or constructor).
* Return's function part contains a function, never null.
* Return's flag part is true if the function call is qualified by an instance, or is a constructor call.
* Return is null if callee cannot be resolved.
*/
@Nullable
PyElement resolveCallee();
PyMarkedFunction resolveCallee();
/**
* @return true if the call is a method call qualified by class instance. <b>Note:</b> Constructor calls return false.
*/
//boolean isByInstance();
enum Flag {
/**
* First arg of the call is implicit, drop first parameter.
*/
IMPLICIT_FIRST_ARG,
/**
* Called function is decorated with @classmethod, first param is the class.
*/
CLASSMETHOD,
/**
* Called function is decorated with @staticmethod, first param is as in a regular function.
*/
STATICMETHOD
}
/**
* Couples function with a flag showing if it is being called as an instance method.
*/
class PyMarkedFunction {
PyFunction myFunction;
boolean myIsInstanceCall;
EnumSet<Flag> myFlags;
public PyMarkedFunction(@NotNull PyFunction function, EnumSet<Flag> flags) {
myFunction = function;
//myIsInstanceCall = instance;
myFlags = flags;
}
public PyFunction getFunction() {
return myFunction;
}
public EnumSet<Flag> getFlags() {
return myFlags;
}
/*
public boolean isInstanceCall() {
return myIsInstanceCall;
}
*/
}
}

View File

@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyClassStub;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,14 +41,14 @@ public interface PyClass extends PsiNamedElement, PyElement, NameDefiner, PyDocS
@Nullable
PsiElement[] getSuperClassElements();
@Nullable
@NotNull
PyClass[] getSuperClasses();
@NotNull
PyFunction[] getMethods();
@Nullable
PyFunction findMethodByName(@NotNull final String name);
PyFunction findMethodByName(@NotNull @NonNls final String name);
PyTargetExpression[] getClassAttributes();

View File

@@ -25,6 +25,7 @@ import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.psi.impl.PyScopeProcessor;
import com.jetbrains.python.psi.impl.ResolveImportUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,8 +38,11 @@ import java.util.*;
*/
public class PyResolveUtil {
private PyResolveUtil() {
}
@NotNull
@NotNull @NonNls
public static String getReadableRepr(PsiElement elt) {
if (elt == null) return "null!";
ASTNode node = elt.getNode();
@@ -47,13 +51,10 @@ public class PyResolveUtil {
String s = node.getText();
int cut_pos = s.indexOf('\n');
if (cut_pos < 0) cut_pos = s.length();
return s.substring(0, java.lang.Math.min(cut_pos, s.length()));
return s.substring(0, Math.min(cut_pos, s.length()));
}
}
private PyResolveUtil() {
}
/**
* Tries to find nearest parent that conceals nams definded inside it. Such elements are 'class' and 'def':
@@ -63,8 +64,7 @@ public class PyResolveUtil {
*/
@Nullable
public static PsiElement getConcealingParent(PsiElement elt) {
PsiElement top = PsiTreeUtil.getParentOfType(elt, PyClass.class, PyFunction.class);
return top;
return PsiTreeUtil.getParentOfType(elt, PyClass.class, PyFunction.class);
}
protected static PsiElement getInnermostChildOf(PsiElement elt) {
@@ -129,7 +129,7 @@ public class PyResolveUtil {
) {
seeker = getPrevNodeOf(seeker, NameDefiner.class);
}
// maybe we're under cap
// maybe we're under a cap
while (true) {
PsiElement local_cap = getConcealingParent(seeker);
if (
@@ -402,6 +402,10 @@ public class PyResolveUtil {
return variants.toArray(new LookupElement[variants.size()]);
}
public List<LookupElement> getResultList() {
return new ArrayList<LookupElement>(myVariants.values());
}
public boolean execute(PsiElement element, ResolveState substitutor) {
// TODO: refactor to look saner; much code duplication
if (element instanceof PsiNamedElement) {

View File

@@ -18,6 +18,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
@@ -224,6 +225,11 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
}
}
@Nullable
public PyCallExpression getCallExpression() {
return PsiTreeUtil.getParentOfType(this, PyCallExpression.class);
}
@SuppressWarnings({"SuspiciousMethodCalls"})
protected void deletePyChild(PyBaseElementImpl element) throws IncorrectOperationException {
if (Arrays.asList(getArguments()).contains(element)) {

View File

@@ -8,16 +8,21 @@ import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.Nullable;
import com.jetbrains.python.psi.types.PyClassType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
/**
* @author yole
*/
public class PyBuiltinCache {
public static final @NonNls String BUILTIN_FILE = "__builtin__.py";
public static PyBuiltinCache getInstance(Project project) {
return ServiceManager.getService(project, PyBuiltinCache.class);
}
@@ -31,7 +36,7 @@ public class PyBuiltinCache {
public PyFile getBuiltinsFile() {
if (myBuiltinsFile == null) {
final PsiFile[] builtinFiles = FilenameIndex.getFilesByName(myProject, "__builtin__.py", GlobalSearchScope.allScope(myProject));
final PsiFile[] builtinFiles = FilenameIndex.getFilesByName(myProject, BUILTIN_FILE, GlobalSearchScope.allScope(myProject));
if (builtinFiles.length == 1) {
myBuiltinsFile = (PyFile) builtinFiles [0];
}
@@ -40,11 +45,11 @@ public class PyBuiltinCache {
}
@Nullable
public PyClass getClass(String name) {
public PyClass getClass(@NonNls String name) {
PyFile builtinsFile = getBuiltinsFile();
if (builtinsFile != null) {
for(PsiElement element: builtinsFile.getChildren()) {
if (element instanceof PyClass && ((PyClass) element).getName().equals(name)) {
if (element instanceof PyClass && (name != null) && name.equals(((PyClass) element).getName())) {
return (PyClass) element;
}
}
@@ -52,17 +57,17 @@ public class PyBuiltinCache {
return null;
}
protected Map<String,PyClassType> myTypeCache = new HashMap<String,PyClassType>();
protected Map<String,PyClassType> myTypeCache = new HashMap<String, PyClassType>();
/**
@return
*/
@NotNull
protected PyClassType _getObjectType(String name) {
protected PyClassType _getObjectType(@NonNls String name) {
PyClassType val = myTypeCache.get(name);
if (val == null) {
PyClass cls = getClass(name);
val = new PyObjectType(cls);
val = new PyClassType(cls, false);
myTypeCache.put(name, val);
}
return val;

View File

@@ -18,11 +18,16 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
/**
* Created by IntelliJ IDEA.
@@ -32,6 +37,7 @@ import com.jetbrains.python.psi.types.PyType;
* To change this template use File | Settings | File Templates.
*/
public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpression {
public PyCallExpressionImpl(ASTNode astNode) {
super(astNode);
}
@@ -42,6 +48,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
}
@PsiCached
@Nullable
public PyExpression getCallee() {
//return PsiTreeUtil.getChildOfType(this, PyReferenceExpression.class); what we call can be whatever expr, not always a ref
return (PyExpression)getFirstChild();
@@ -49,7 +56,8 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
@PsiCached
public PyArgumentList getArgumentList() {
return PsiTreeUtil.getChildOfType(this, PyArgumentList.class);
PyArgumentList arglist = PsiTreeUtil.getChildOfType(this, PyArgumentList.class);
return arglist;
}
public void addArgument(PyExpression expression) {
@@ -63,11 +71,72 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
}
}
public PyElement resolveCallee() {
public PyMarkedFunction resolveCallee() {
PyExpression calleeReference = getCallee();
if (calleeReference != null) {
PsiReference cref = calleeReference.getReference();
if (cref != null) {
PyElement resolved = (PyElement) cref.resolve();
if (resolved != null) {
EnumSet<Flag> flags = EnumSet.noneOf(Flag.class);
//boolean is_inst = isByInstance();
if (isByInstance()) flags.add(Flag.IMPLICIT_FIRST_ARG);
if (resolved instanceof PyClass) { // constructor call
final PyClass cls = (PyClass)resolved;
resolved = cls.findMethodByName("__init__");
//is_inst |= true;
flags.add(Flag.IMPLICIT_FIRST_ARG);
}
if (resolved != null) {
// look for closest decorator
// TODO: look for all decorators
PsiElement parent = resolved.getParent();
if (parent instanceof PyDecoratedFunction) {
final PyDecoratedFunction decorated = (PyDecoratedFunction)parent;
PsiElement decorator = PsiTreeUtil.getChildOfType(decorated, PyReferenceExpression.class);
if (decorator != null) { // just in case
String deco_name = decorator.getText();
@NonNls final String STATICMETHOD = "staticmethod";
@NonNls final String CLASSMETHOD = "classmethod";
if (STATICMETHOD.equals(deco_name)) {
flags.add(Flag.STATICMETHOD);
flags.remove(Flag.IMPLICIT_FIRST_ARG);
}
else if (CLASSMETHOD.equals(deco_name)) {
flags.add(Flag.CLASSMETHOD);
}
// else could be custom decorator processing
}
}
}
if (!(resolved instanceof PyFunction)) return null; // omg, bogus __init__
return new PyMarkedFunction((PyFunction) resolved, flags);
}
}
}
return null;
}
public PyElement resolveCallee2() {
PyExpression calleeReference = getCallee();
return (PyElement) calleeReference.getReference().resolve();
}
protected boolean isByInstance() {
PyExpression callee = getCallee();
if (callee instanceof PyReferenceExpression) {
PyExpression qualifier = ((PyReferenceExpression)callee).getQualifier();
if (qualifier != null) {
PyType type = qualifier.getType();
if ((type instanceof PyClassType) && (!((PyClassType)type).isDefinition())) {
// we're calling an instance method of qualifier
return true;
}
}
}
return false;
}
@Override
public String toString() {
return "PyCallExpression: " + PyResolveUtil.getReadableRepr(getCallee()); //getCalledFunctionReference().getReferencedName();
@@ -78,8 +147,9 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
if (callee instanceof PyReferenceExpression) {
PsiElement target = ((PyReferenceExpression)callee).resolve();
if (target instanceof PyClass) {
return new PyClassType((PyClass) target);
return new PyClassType((PyClass) target, false); // we call a class name, that is, the constructor, we get an instance.
}
// TODO: look at well-known functions and their return types
return PyReferenceExpressionImpl.getReferenceTypeFromProviders(target);
}
return callee.getType();

View File

@@ -45,6 +45,9 @@ import java.util.List;
* To change this template use File | Settings | File Templates.
*/
public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implements PyClass {
public static final PyClass[] EMPTY_ARRAY = new PyClassImpl[0];
public PyClassImpl(ASTNode astNode) {
super(astNode);
}
@@ -110,7 +113,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
final PyExpression[] superExpressions = getSuperClassExpressions();
List<PsiElement> superClasses = new ArrayList<PsiElement>();
for(PyExpression expr: superExpressions) {
if (expr instanceof PyReferenceExpression && !PyNames.OBJECT.equals(expr.getText())) {
if (expr instanceof PyReferenceExpression) {
PyReferenceExpression ref = (PyReferenceExpression) expr;
final PsiElement result = ref.resolve();
if (result != null) {
@@ -121,6 +124,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return superClasses.toArray(new PsiElement[superClasses.size()]);
}
@NotNull
public PyClass[] getSuperClasses() {
PsiElement[] superClassElements = getSuperClassElements();
if (superClassElements != null) {
@@ -132,7 +136,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
}
return result.toArray(new PyClass[result.size()]);
}
return null;
return EMPTY_ARRAY;
}
@NotNull

View File

@@ -221,8 +221,8 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
public PyType getType() {
if (myType == null) {
PyClass the_class = PyBuiltinCache.getInstance(getProject()).getClass("object"); // really 'module', but it's nowhere to import from
if (the_class != null) myType = new PyClassType(the_class);
PyClass the_class = PyBuiltinCache.getInstance(getProject()).getClass("object"); // TODO: generate a skel for module
if (the_class != null) myType = new PyClassType(the_class, false); // 'module' is an instance of 'object'
}
return myType;
}

View File

@@ -17,10 +17,10 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.PsiElement;
import com.intellij.util.Icons;
import com.intellij.util.IncorrectOperationException;
import com.intellij.openapi.extensions.Extensions;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
@@ -112,10 +112,10 @@ public class PyParameterImpl extends PyPresentableElementImpl<PyParameterStub> i
final PyParameter[] params = parameterList.getParameters();
if (parameterList.getParent() instanceof PyFunction) {
PyFunction func = (PyFunction) parameterList.getParent();
if (params [0] == this) {
if (params [0] == this) { // must be 'self'
final PyClass containingClass = func.getContainingClass();
if (containingClass != null) {
return new PyClassType(containingClass);
return new PyClassType(containingClass, false); // TODO: check for @classmethod or @staticmethod node above us
}
}
for(PyTypeProvider provider: Extensions.getExtensions(PyTypeProvider.EP_NAME)) {

View File

@@ -338,7 +338,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
return ((PyExpression) target).getType();
}
if (target instanceof PyClass) {
return new PyClassType((PyClass) target);
return new PyClassType((PyClass) target, true);
}
if (target instanceof PsiDirectory) {
PsiFile file = ((PsiDirectory)target).findFile(ResolveImportUtil.INIT_PY);

View File

@@ -6,9 +6,8 @@ import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.PyResolveUtil;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -18,15 +17,36 @@ import java.util.*;
public class PyClassType implements PyType {
protected PyClass myClass;
public PyClassType(final PyClass source) {
protected boolean myIsDefinition;
/**
* Describes a class-based type. Since everyting in Python is an instance of some class, this type pretty much completes
* the type system :)
* Note that classes' and instances' member list can change during execution, so it is important to construct an instance of PyClassType
* right in the place of reference, so that such changes could possibly be accounted for.
* @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(final @Nullable PyClass source, boolean is_definition) {
myClass = source;
myIsDefinition = is_definition;
}
/**
* @return a PyClass which defined this type.
*/
@NotNull
public PyClass getPyClass() {
return myClass;
}
/**
* @return whether this type refers to an instance or a definition of the class.
*/
public boolean isDefinition() {
return myIsDefinition;
}
@Nullable
public PsiElement resolveMember(final String name) {
if (myClass == null) return null;
@@ -55,17 +75,24 @@ public class PyClassType implements PyType {
public Object[] getCompletionVariants(final PyReferenceExpression referenceExpression) {
final PyResolveUtil.VariantsProcessor processor = new PyResolveUtil.VariantsProcessor();
myClass.processDeclarations(processor, ResolveState.initial(), null, referenceExpression);
return processor.getResult();
List<Object> ret = new ArrayList<Object>();
ret.addAll(processor.getResultList());
for (PyClass ancestor : myClass.getSuperClasses()) {
ret.addAll(Arrays.asList((new PyClassType(ancestor, true)).getCompletionVariants(referenceExpression)));
}
return ret.toArray();
}
@NotNull
public Set<String> getPossibleInstanceMembers() {
Set<String> ret = new HashSet<String>();
/*
if (myClass != null) {
PyClassType otype = PyBuiltinCache.getInstance(myClass.getProject()).getObjectType();
ret.addAll(otype.getPossibleInstanceMembers());
}
// TODO: add our own ideas here, e.g. from methods other than constructor
*/
// TODO: add our own ideas here, e.g. from methods other than constructor
return Collections.unmodifiableSet(ret);
}

View File

@@ -16,7 +16,7 @@ import java.util.Set;
/**
* @author yole
*/
public class PyModuleType implements PyType {
public class PyModuleType implements PyType { // TODO: make it a PyClassType referring to builtins.___module
private PsiFile myModule;
protected static Set<String> ourPossibleFields;

View File

@@ -7,7 +7,7 @@ import com.jetbrains.python.psi.PyReferenceExpression;
/**
* @author yole
*/
public class PyNoneType implements PyType {
public class PyNoneType implements PyType { // TODO must extend ClassType. It's an honest instance.
public static final PyNoneType INSTANCE = new PyNoneType();
private PyNoneType() {

View File

@@ -1,14 +1,13 @@
package com.jetbrains.python.psi.types;
import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyReferenceExpression;
import org.jetbrains.annotations.NotNull;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import java.util.*;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
// TODO: eliminate this class
/**
* Represents Python 'object' type.
@@ -29,13 +28,9 @@ public class PyObjectType extends PyClassType implements PyType {
}
public PyObjectType(PyClass source) {
super(source);
super(source, false);
}
public Object[] getCompletionVariants(final PyReferenceExpression referenceExpression) {
return ArrayUtil.EMPTY_OBJECT_ARRAY; // TODO: implement
}
/**
* Sometimes we can make a reasonable guess that a name is an instance member while we cannot directly resolve it.
* All such guesses are listed by this method.

View File

@@ -3,9 +3,6 @@ package com.jetbrains.python.psi.types;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.PyReferenceExpression;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* @author yole

View File

@@ -0,0 +1,5 @@
class A:
def foo(self):
a = A()
A.f<ref>oo(a)

View File

@@ -0,0 +1,5 @@
class A:
def foo(self):
a = A()
a.f<ref>oo()

View File

@@ -0,0 +1,40 @@
package com.jetbrains.python;
import com.intellij.openapi.application.PathManager;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.ResolveTestCase;
import com.jetbrains.python.psi.PyCallExpression;
import java.util.EnumSet;
/**
* Tests callee resolution in PyCallExpressionImpl.
* User: dcheryasov
* Date: Aug 21, 2008
*/
public class PyResolveCalleeTest extends ResolveTestCase {
private PyCallExpression.PyMarkedFunction resolveCallee() throws Exception {
PsiReference ref = configureByFile(getTestName(false) + ".py");
PyCallExpression call = PsiTreeUtil.getParentOfType(ref.getElement(), PyCallExpression.class);
return call.resolveCallee();
}
public void testInstanceCall() throws Exception {
PyCallExpression.PyMarkedFunction resolved = resolveCallee();
assertNotNull(resolved.getFunction());
assertTrue(resolved.getFlags().equals(EnumSet.of(PyCallExpression.Flag.IMPLICIT_FIRST_ARG)));
}
public void testClassCall() throws Exception {
PyCallExpression.PyMarkedFunction resolved = resolveCallee();
assertNotNull(resolved.getFunction());
assertTrue(resolved.getFlags().equals(EnumSet.noneOf(PyCallExpression.Flag.class)));
}
@Override
protected String getTestDataPath() {
return PathManager.getHomePath() + "/plugins/python/testData/resolve/callee/";
}
}

View File

@@ -11,6 +11,10 @@ public class PythonHighlightingTest extends DaemonAnalyzerTestCase {
return PathManager.getHomePath() + "/plugins/python/testData/highlighting/";
}
public void testCallArgs() throws Exception {
doTest();
}
public void testImportInTry() throws Exception {
doTest();
}