mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
argument list inspection does not check implicitly resolved method calls
This commit is contained in:
@@ -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
-1
@@ -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,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());
|
||||
|
||||
Reference in New Issue
Block a user