argument list inspection does not check implicitly resolved method calls

This commit is contained in:
Dmitry Jemerov
2010-04-15 17:40:33 +04:00
parent ae02b88fc8
commit 763d724b0b
26 changed files with 181 additions and 95 deletions
@@ -10,10 +10,7 @@ import com.intellij.util.ArrayUtil;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.stubs.PyFunctionNameIndex;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* @author yole
@@ -33,8 +30,9 @@ public class PyGotoSymbolContributor implements ChooseByNameContributor {
List<NavigationItem> symbols = new ArrayList<NavigationItem>();
symbols.addAll(PyClassNameIndex.find(name, project, scope));
symbols.addAll(StubIndex.getInstance().get(PyFunctionNameIndex.KEY, name, project, scope));
symbols.addAll(PyFunctionNameIndex.find(name, project, scope));
return symbols.toArray(new NavigationItem[symbols.size()]);
}
}
@@ -12,7 +12,9 @@ import com.jetbrains.python.psi.impl.PyCallExpressionHelper;
import com.jetbrains.python.psi.resolve.ResolveImportUtil;
import com.jetbrains.python.psi.resolve.SdkRootVisitor;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.toolbox.*;
import com.jetbrains.python.toolbox.ChainIterable;
import com.jetbrains.python.toolbox.FP;
import com.jetbrains.python.toolbox.SingleIterable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -259,7 +261,7 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
prolog_cat.addWith(TagSmall, $(PyBundle.message("QDOC.assigned.to.$0", element.getText())).add(BR));
reassignment_marked = true;
}
element = ((PyReferenceExpression)element).followAssignmentsChain();
element = ((PyReferenceExpression)element).followAssignmentsChain().getElement();
}
// it may be a call to a standard wrapper
if (element instanceof PyCallExpression) {
@@ -105,7 +105,7 @@ public class PyArgumentListInspection extends LocalInspectionTool {
public static void inspectPyArgumentList(PyArgumentList node, ProblemsHolder holder) {
PyArgumentList.AnalysisResult result = node.analyzeCall();
if (result != null) {
if (result != null && !result.isImplicitlyResolved()) {
for (Map.Entry<PyExpression, EnumSet<PyArgumentList.ArgFlag>> arg_entry : result.getArgumentFlags().entrySet()) {
EnumSet<PyArgumentList.ArgFlag> flags = arg_entry.getValue();
if (!flags.isEmpty()) { // something's wrong
@@ -138,9 +138,11 @@ public class PyArgumentListInspection extends LocalInspectionTool {
}
}
}
/*
else if (! node.getTextRange().isEmpty()) {
holder.registerProblem(node, PyBundle.message("INSP.cannot.analyze"), ProblemHighlightType.INFO);
}
*/
}
}
@@ -2,6 +2,7 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyBundle;
@@ -63,7 +64,7 @@ public class PyExceptClausesOrderInspection extends LocalInspectionTool{
for (PyExceptPart exceptPart : exceptParts) {
PyExpression exceptClass = exceptPart.getExceptClass();
if (exceptClass instanceof PyReferenceExpression) {
PyElement element = ((PyReferenceExpression) exceptClass).followAssignmentsChain();
PsiElement element = ((PyReferenceExpression) exceptClass).followAssignmentsChain().getElement();
if (element instanceof PyClass) {
PyClass pyClass = (PyClass)element;
if (exceptClasses.contains(pyClass)) {
@@ -103,7 +103,7 @@ public class PyStringFormatInspection extends LocalInspectionTool {
return 1;
}
else if (rightExpression instanceof PyReferenceExpression) {
PyElement pyElement = ((PyReferenceExpression)rightExpression).followAssignmentsChain();
PsiElement pyElement = ((PyReferenceExpression)rightExpression).followAssignmentsChain().getElement();
if (pyElement == null) {
return -1;
}
@@ -2,9 +2,13 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.PyCallExpression;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -58,8 +62,8 @@ public class PySuperArgumentsInspection extends LocalInspectionTool {
PyExpression[] arguments = node.getArguments();
if (arguments.length == 2) {
if (arguments[0] instanceof PyReferenceExpression && arguments[1] instanceof PyReferenceExpression) {
PyElement firstElement = ((PyReferenceExpression) arguments[0]).followAssignmentsChain();
PyElement secondElement = ((PyReferenceExpression) arguments[1]).followAssignmentsChain();
PsiElement firstElement = ((PyReferenceExpression) arguments[0]).followAssignmentsChain().getElement();
PsiElement secondElement = ((PyReferenceExpression) arguments[1]).followAssignmentsChain().getElement();
if (firstElement instanceof PyClass && secondElement instanceof PyClass) {
PyClass firstClass = (PyClass) firstElement;
PyClass secondClass = (PyClass) secondElement;
@@ -2,6 +2,7 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.*;
@@ -60,7 +61,7 @@ public class PyTupleItemAssignmentInspection extends LocalInspectionTool {
PySubscriptionExpression subscriptionExpression = (PySubscriptionExpression)targets[0];
if (subscriptionExpression.getOperand() instanceof PyReferenceExpression) {
PyReferenceExpression referenceExpression = (PyReferenceExpression)subscriptionExpression.getOperand();
PyElement element = referenceExpression.followAssignmentsChain();
PsiElement element = referenceExpression.followAssignmentsChain().getElement();
if (element instanceof PyExpression) {
PyExpression expression = (PyExpression)element;
PyType type = expression.getType();
@@ -11,7 +11,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.jetbrains.python.PyBundle;
@@ -170,7 +169,7 @@ public class PyUnresolvedReferencesInspection extends LocalInspectionTool {
GlobalSearchScope scope = ProjectScope.getAllScope(project);
List<PsiElement> symbols = new ArrayList<PsiElement>();
symbols.addAll(PyClassNameIndex.find(ref_text, project, scope));
symbols.addAll(StubIndex.getInstance().get(PyFunctionNameIndex.KEY, ref_text, project, scope));
symbols.addAll(PyFunctionNameIndex.find(ref_text, project));
// NOTE: possible CPU hog
if (symbols.size() > 0) {
if (fix == null) { // it might have been created in the previous scan, or not.
@@ -47,10 +47,11 @@ public interface PyArgumentList extends PyElement {
/**
* Result of analysis of argument list application to the callee.
* Contains neatly arranged lists and mappinga between arguments and parameters,
* Contains neatly arranged lists and mappings between arguments and parameters,
* including error diagnostics.
*/
interface AnalysisResult {
boolean isImplicitlyResolved();
/**
* @return A mapping parameter->argument for non-starred parameters (but includes starred argument).
@@ -53,11 +53,13 @@ public interface PyCallExpression extends PyExpression {
PyFunction myFunction;
EnumSet<PyFunction.Flag> myFlags;
int myImplicitOffset;
boolean myImplicitlyResolved;
public PyMarkedFunction(@NotNull PyFunction function, EnumSet<PyFunction.Flag> flags, int offset) {
public PyMarkedFunction(@NotNull PyFunction function, EnumSet<PyFunction.Flag> flags, int offset, boolean implicitlyResolved) {
myFunction = function;
myFlags = flags;
myImplicitOffset = offset;
myImplicitlyResolved = implicitlyResolved;
}
public PyFunction getFunction() {
@@ -77,6 +79,8 @@ public interface PyCallExpression extends PyExpression {
return myImplicitOffset;
}
public boolean isImplicitlyResolved() {
return myImplicitlyResolved;
}
}
}
@@ -1,6 +1,7 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.ResolveResult;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -18,8 +19,8 @@ public interface PyReferenceExpression extends PyQualifiedExpression {
* @return value that is assigned to this element via a chain of definite assignments, or null.
* <i>Note: will return null if the assignment chain ends in a target of a non-assignment statement such as 'for'.</i>
*/
@Nullable
PyElement followAssignmentsChain();
@NotNull
ResolveResult followAssignmentsChain();
@Nullable
PyQualifiedName asQualifiedName();
@@ -629,6 +629,10 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
my_marked_func = null;
}
public boolean isImplicitlyResolved() {
return my_marked_func == null ? false : my_marked_func.isImplicitlyResolved();
}
/**
* @return A mapping argument->parameter for non-starred arguments (but includes starred parameters).
*/
@@ -3,9 +3,10 @@ package com.jetbrains.python.psi.impl;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.ResolveResult;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.ImplicitResolveResult;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.Nullable;
@@ -76,7 +77,8 @@ public class PyCallExpressionHelper {
boolean is_constructor_call = false;
if (callee instanceof PyReferenceExpression) {
PyReferenceExpression ref = (PyReferenceExpression)callee;
PsiElement resolved = ref.followAssignmentsChain();
ResolveResult resolveResult = ref.followAssignmentsChain();
PsiElement resolved = resolveResult.getElement();
if (resolved instanceof PyClass) {
resolved = ((PyClass)resolved).findInitOrNew(true); // class to constructor call
is_constructor_call = true;
@@ -98,7 +100,8 @@ public class PyCallExpressionHelper {
if (! is_constructor_call && PyNames.NEW.equals(((PyFunction)resolved).getName())) {
implicit_offset = Math.min(implicit_offset-1, 0); // case of Class.__new__
}
return new PyCallExpression.PyMarkedFunction((PyFunction)resolved, flags, implicit_offset);
return new PyCallExpression.PyMarkedFunction((PyFunction)resolved, flags, implicit_offset,
resolveResult instanceof ImplicitResolveResult);
}
}
return null;
@@ -97,7 +97,7 @@ public class PyDecoratorImpl extends PyPresentableElementImpl<PyDecoratorStub> i
PyMarkedFunction callee = PyCallExpressionHelper.resolveCallee(this);
if (callee == null) return null;
if (! hasArgumentList()) {
callee = new PyMarkedFunction(callee.getFunction(), callee.getFlags(), callee.getImplicitOffset() + 1);
callee = new PyMarkedFunction(callee.getFunction(), callee.getFlags(), callee.getImplicitOffset() + 1, callee.isImplicitlyResolved());
}
return callee;
}
@@ -14,10 +14,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
import com.jetbrains.python.psi.resolve.ResolveImportUtil;
import com.jetbrains.python.psi.resolve.SdkRootVisitor;
import com.jetbrains.python.psi.resolve.VariantsProcessor;
import com.jetbrains.python.psi.resolve.*;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.NotNull;
@@ -6,7 +6,10 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.AssignmentCollectProcessor;
import com.jetbrains.python.psi.resolve.ImplicitResolveResult;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.stubs.PyFunctionNameIndex;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyModuleType;
import com.jetbrains.python.psi.types.PyType;
@@ -52,6 +55,14 @@ public class PyQualifiedReferenceImpl extends PyReferenceImpl {
PsiElement ref_elt = PyUtil.turnDirIntoInit(qualifierType.resolveMember(referencedName));
if (ref_elt != null) ret.poke(ref_elt, RatedResolveResult.RATE_NORMAL);
}
else {
final Collection<PyFunction> functions = PyFunctionNameIndex.find(referencedName, myElement.getProject());
for (PyFunction function : functions) {
if (function.getContainingClass() != null) {
ret.add(new ImplicitResolveResult(function));
}
}
}
// special case of __doc__
if ("__doc__".equals(referencedName)) {
PsiElement docstring = null;
@@ -3,11 +3,9 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
@@ -93,10 +91,10 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
}
@Nullable
public PyElement followAssignmentsChain() {
@NotNull
public ResolveResult followAssignmentsChain() {
PyReferenceExpression seeker = this;
PyElement ret = null;
ResolveResult ret = null;
SEARCH:
while (ret == null) {
ResolveResult[] targets = seeker.getReference().multiResolve(false);
@@ -108,15 +106,26 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
seeker = (PyReferenceExpression)assigned_from;
continue SEARCH;
}
else if (assigned_from != null) ret = assigned_from;
else if (assigned_from != null) ret = new PsiElementResolveResult(assigned_from);
}
else if (ret == null && elt instanceof PyElement) { // remember this result, but a further reference may be the next resolve result
ret = (PyElement)elt;
ret = target;
}
}
// all resolve results checked, reassignment not detected, nothing more to do
break;
}
if (ret == null) {
ret = new ResolveResult() {
public PsiElement getElement() {
return null;
}
public boolean isValidResult() {
return false;
}
};
}
return ret;
}
@@ -15,10 +15,7 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.SortedList;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.CollectProcessor;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
import com.jetbrains.python.psi.resolve.ResolveProcessor;
import com.jetbrains.python.psi.resolve.VariantsProcessor;
import com.jetbrains.python.psi.resolve.*;
import com.jetbrains.python.psi.types.PyModuleType;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.NotNull;
@@ -57,7 +54,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
@Nullable
public PsiElement resolve() {
final ResolveResult[] results = multiResolve(false);
return results.length >= 1 ? results[0].getElement() : null;
return results.length >= 1 && !(results [0] instanceof ImplicitResolveResult) ? results[0].getElement() : null;
}
private static final boolean USE_CACHE = true; // change to false in debug time to switch off caching
@@ -1,16 +1,11 @@
/*
* @author max
*/
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.io.PersistentStringEnumerator;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.util.io.StringRef;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyStubElementType;
@@ -20,6 +15,9 @@ import com.jetbrains.python.psi.stubs.PyFunctionStub;
import java.io.IOException;
/**
* @author max
*/
public class PyFunctionElementType extends PyStubElementType<PyFunctionStub, PyFunction> {
public PyFunctionElementType() {
super("FUNCTION_DECLARATION");
@@ -0,0 +1,28 @@
package com.jetbrains.python.psi.resolve;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public class ImplicitResolveResult implements RatedResolveResult {
@Nullable private final PsiElement myElement;
public ImplicitResolveResult(@Nullable final PsiElement element) {
myElement = element;
}
@Nullable
public PsiElement getElement() {
return myElement;
}
public boolean isValidResult() {
return false;
}
public int getRate() {
return RATE_LOW;
}
}
@@ -1,4 +1,4 @@
package com.jetbrains.python.psi;
package com.jetbrains.python.psi.resolve;
import com.intellij.psi.ResolveResult;
@@ -3,14 +3,28 @@
*/
package com.jetbrains.python.psi.stubs;
import com.intellij.openapi.project.Project;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import com.jetbrains.python.psi.PyFunction;
import java.util.Collection;
public class PyFunctionNameIndex extends StringStubIndexExtension<PyFunction> {
public static final StubIndexKey<String,PyFunction> KEY = StubIndexKey.createIndexKey("Py.function.shortName");
public StubIndexKey<String, PyFunction> getKey() {
return KEY;
}
public static Collection<PyFunction> find(String name, Project project, GlobalSearchScope scope) {
return StubIndex.getInstance().get(KEY, name, project, scope);
}
public static Collection<PyFunction> find(String name, Project project) {
return StubIndex.getInstance().get(KEY, name, project, ProjectScope.getAllScope(project));
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
class C:
def foo(self):
self.text = self.text.str<ref>ip()
self.text = self.text.str<ref>ip_naked()
@@ -0,0 +1,5 @@
class A:
def long_unique_identifier(self): pass
def foo(x):
x.long_unique_identif<ref>ier()
@@ -1,7 +1,3 @@
/*
* User: anna
* Date: 20-Feb-2008
*/
package com.jetbrains.python;
import com.intellij.psi.PsiElement;
@@ -13,34 +9,34 @@ import com.jetbrains.python.fixtures.PyResolveTestCase;
import com.jetbrains.python.psi.*;
public class PyResolveTest extends PyResolveTestCase {
private PsiElement resolve() throws Exception {
private PsiElement resolve() {
PsiReference ref = configureByFile("resolve/" + getTestName(false) + ".py");
return ref.resolve();
}
private ResolveResult[] multiResolve() throws Exception {
private ResolveResult[] multiResolve() {
PsiReference ref = configureByFile("resolve/" + getTestName(false) + ".py");
assertTrue(ref instanceof PsiPolyVariantReference);
return ((PsiPolyVariantReference)ref).multiResolve(false);
}
public void testClass() throws Exception {
public void testClass() {
PsiElement target = resolve();
assertTrue(target instanceof PyClass);
}
public void testFunc() throws Exception {
public void testFunc() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyFunction);
}
public void testToConstructor() throws Exception {
public void testToConstructor() {
PsiElement target = resolve();
assertTrue(target instanceof PyFunction);
assertEquals(((PyFunction)target).getName(), PyNames.INIT);
}
public void testToConstructorInherited() throws Exception {
public void testToConstructorInherited() {
ResolveResult[] targets = multiResolve();
assertEquals(targets.length, 2); // to class, to init
PsiElement elt;
@@ -59,7 +55,7 @@ public class PyResolveTest extends PyResolveTestCase {
}
// NOTE: maybe this test does not belong exactly here; still it's the best place currently.
public void testComplexCallee() throws Exception {
public void testComplexCallee() {
PsiElement targetElement = resolve();
PyExpression assigned = ((PyAssignmentStatement)targetElement.getContext()).getAssignedValue();
assertTrue(assigned instanceof PyCallExpression);
@@ -67,181 +63,186 @@ public class PyResolveTest extends PyResolveTestCase {
assertTrue(callee instanceof PySubscriptionExpression);
}
public void testVar() throws Exception {
public void testVar() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testDefaultInClass() throws Exception {
public void testDefaultInClass() {
PsiElement targetElement = resolve();
assertNotNull(targetElement);
assertTrue(targetElement instanceof PyTargetExpression);
assertEquals(((PyTargetExpression)targetElement).getName(), "FOO");
}
public void testQualifiedFunc() throws Exception {
public void testQualifiedFunc() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyFunction);
}
public void testQualifiedVar() throws Exception {
public void testQualifiedVar() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testQualifiedTarget() throws Exception {
public void testQualifiedTarget() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testQualifiedFalseTarget() throws Exception {
public void testQualifiedFalseTarget() {
PsiElement targetElement = resolve();
assertNull(targetElement);
}
public void testInnerFuncVar() throws Exception {
public void testInnerFuncVar() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testTupleInComprh() throws Exception {
public void testTupleInComprh() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testForStatement() throws Exception {
public void testForStatement() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testExceptClause() throws Exception {
public void testExceptClause() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testLookAhead() throws Exception {
public void testLookAhead() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testLookAheadCapped() throws Exception {
public void testLookAheadCapped() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testTryExceptElse() throws Exception {
public void testTryExceptElse() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testGlobal() throws Exception {
public void testGlobal() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
}
public void testLambda() throws Exception {
public void testLambda() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyNamedParameter);
}
public void testSuperField() throws Exception {
public void testSuperField() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testFieldInCondition() throws Exception {
public void testFieldInCondition() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testMultipleFields() throws Exception {
public void testMultipleFields() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testClassPeerMembers() throws Exception {
public void testClassPeerMembers() {
PsiElement target = resolve();
assertTrue(target instanceof PyFunction);
}
public void testTuple() throws Exception {
public void testTuple() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
}
public void testMultiTarget() throws Exception {
public void testMultiTarget() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
}
public void testMultiTargetTuple() throws Exception {
public void testMultiTargetTuple() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
assertNotNull(PsiTreeUtil.getParentOfType(targetElement, PyAssignmentStatement.class)); // it's deep in a tuple
}
public void testWithStatement() throws Exception {
public void testWithStatement() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
assertTrue(targetElement.getParent() instanceof PyWithItem);
}
public void testTupleInExcept() throws Exception {
public void testTupleInExcept() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
assertTrue(PsiTreeUtil.getParentOfType(targetElement, PyExceptPart.class) != null);
}
public void testDocStringClass() throws Exception {
public void testDocStringClass() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyStringLiteralExpression);
assertEquals("Docstring of class Foo", ((PyStringLiteralExpression)targetElement).getStringValue());
}
public void testDocStringInstance() throws Exception {
public void testDocStringInstance() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyStringLiteralExpression);
assertEquals("Docstring of class Foo", ((PyStringLiteralExpression)targetElement).getStringValue());
}
public void testDocStringFunction() throws Exception {
public void testDocStringFunction() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyStringLiteralExpression);
assertEquals("Docstring of function bar", ((PyStringLiteralExpression)targetElement).getStringValue());
}
public void testDocStringInvalid() throws Exception {
public void testDocStringInvalid() {
PsiElement targetElement = resolve();
assertNull(targetElement);
}
public void testFieldNotInInit() throws Exception {
public void testFieldNotInInit() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testClassIsNotMemberOfItself() throws Exception {
public void testClassIsNotMemberOfItself() {
PsiElement targetElement = resolve();
assertNull(targetElement);
}
public void testSuper() throws Exception {
public void testSuper() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyFunction);
assertEquals("A", ((PyFunction) targetElement).getContainingClass().getName());
}
public void testStackOverflow() throws Exception {
public void testStackOverflow() {
PsiElement targetElement = resolve();
assertNull(targetElement);
}
public void testProperty() throws Exception {
public void testProperty() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testTextBasedResolve() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyFunction);
}
}
@@ -18,12 +18,18 @@ import java.io.IOException;
public abstract class PyResolveTestCase extends PyLightFixtureTestCase {
@NonNls protected static final String MARKER = "<ref>";
protected PsiReference configureByFile(@TestDataFile final String filePath) throws Exception {
protected PsiReference configureByFile(@TestDataFile final String filePath) {
VirtualFile testDataRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(getTestDataPath()));
final VirtualFile file = testDataRoot.findFileByRelativePath(filePath);
assertNotNull(file);
String fileText = StringUtil.convertLineSeparators(VfsUtil.loadText(file));
String fileText;
try {
fileText = StringUtil.convertLineSeparators(VfsUtil.loadText(file));
}
catch (IOException e) {
throw new RuntimeException(e);
}
int offset = fileText.indexOf(MARKER);
assertTrue(offset >= 0);
fileText = fileText.substring(0, offset) + fileText.substring(offset + MARKER.length());