diff --git a/python/src/com/jetbrains/python/PyGotoSymbolContributor.java b/python/src/com/jetbrains/python/PyGotoSymbolContributor.java index 64b649b1a214..1e125f8c7099 100644 --- a/python/src/com/jetbrains/python/PyGotoSymbolContributor.java +++ b/python/src/com/jetbrains/python/PyGotoSymbolContributor.java @@ -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 symbols = new ArrayList(); 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()]); } + } diff --git a/python/src/com/jetbrains/python/PythonDocumentationProvider.java b/python/src/com/jetbrains/python/PythonDocumentationProvider.java index 0b050f993069..8b30b79f8fbc 100644 --- a/python/src/com/jetbrains/python/PythonDocumentationProvider.java +++ b/python/src/com/jetbrains/python/PythonDocumentationProvider.java @@ -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) { diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java index 1f3acdd0de5c..f080c2864ff7 100644 --- a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java @@ -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> arg_entry : result.getArgumentFlags().entrySet()) { EnumSet 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); } + */ } } diff --git a/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java b/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java index 69e3a916d316..d8fdbf4c3efc 100644 --- a/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyExceptClausesOrderInspection.java @@ -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)) { diff --git a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java index cacf88e4def2..beea94a1736c 100644 --- a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java @@ -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; } diff --git a/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java b/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java index 555b0a0d15f7..7543bdbb65f2 100644 --- a/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java +++ b/python/src/com/jetbrains/python/inspections/PySuperArgumentsInspection.java @@ -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; diff --git a/python/src/com/jetbrains/python/inspections/PyTupleItemAssignmentInspection.java b/python/src/com/jetbrains/python/inspections/PyTupleItemAssignmentInspection.java index 440d768dfed8..76420437fd3b 100644 --- a/python/src/com/jetbrains/python/inspections/PyTupleItemAssignmentInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyTupleItemAssignmentInspection.java @@ -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(); diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index 3c9971fe874c..3ff7d46c23e6 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -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 symbols = new ArrayList(); 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. diff --git a/python/src/com/jetbrains/python/psi/PyArgumentList.java b/python/src/com/jetbrains/python/psi/PyArgumentList.java index 4be23f339e8c..3fb208743be3 100644 --- a/python/src/com/jetbrains/python/psi/PyArgumentList.java +++ b/python/src/com/jetbrains/python/psi/PyArgumentList.java @@ -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). diff --git a/python/src/com/jetbrains/python/psi/PyCallExpression.java b/python/src/com/jetbrains/python/psi/PyCallExpression.java index 2ed97eba8c30..218ec725bac4 100644 --- a/python/src/com/jetbrains/python/psi/PyCallExpression.java +++ b/python/src/com/jetbrains/python/psi/PyCallExpression.java @@ -53,11 +53,13 @@ public interface PyCallExpression extends PyExpression { PyFunction myFunction; EnumSet myFlags; int myImplicitOffset; + boolean myImplicitlyResolved; - public PyMarkedFunction(@NotNull PyFunction function, EnumSet flags, int offset) { + public PyMarkedFunction(@NotNull PyFunction function, EnumSet 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; + } } - } diff --git a/python/src/com/jetbrains/python/psi/PyReferenceExpression.java b/python/src/com/jetbrains/python/psi/PyReferenceExpression.java index 76a98e16bf44..23f793d9738c 100644 --- a/python/src/com/jetbrains/python/psi/PyReferenceExpression.java +++ b/python/src/com/jetbrains/python/psi/PyReferenceExpression.java @@ -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. * Note: will return null if the assignment chain ends in a target of a non-assignment statement such as 'for'. */ - @Nullable - PyElement followAssignmentsChain(); + @NotNull + ResolveResult followAssignmentsChain(); @Nullable PyQualifiedName asQualifiedName(); diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java index 8e7110d9aece..421c1e08c883 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java @@ -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). */ diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java index 24525b168aed..733aeb03e9c4 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java @@ -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; diff --git a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java index 1e9e657ad43c..1f7c6e60d76f 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java @@ -97,7 +97,7 @@ public class PyDecoratorImpl extends PyPresentableElementImpl 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; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java index b62522980f06..806939bd35bf 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyImportReferenceImpl.java @@ -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; diff --git a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java index 72638e7ffbcf..8cb83b168a1b 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java @@ -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 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; diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index da8e44040379..188f0fe2977b 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -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; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java index 4a5fd07c3134..c8486971d3df 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java @@ -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 diff --git a/python/src/com/jetbrains/python/psi/impl/stubs/PyFunctionElementType.java b/python/src/com/jetbrains/python/psi/impl/stubs/PyFunctionElementType.java index f6f6b044ced2..5c95a52e3011 100644 --- a/python/src/com/jetbrains/python/psi/impl/stubs/PyFunctionElementType.java +++ b/python/src/com/jetbrains/python/psi/impl/stubs/PyFunctionElementType.java @@ -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 { public PyFunctionElementType() { super("FUNCTION_DECLARATION"); diff --git a/python/src/com/jetbrains/python/psi/resolve/ImplicitResolveResult.java b/python/src/com/jetbrains/python/psi/resolve/ImplicitResolveResult.java new file mode 100644 index 000000000000..67a6bb41eb84 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/resolve/ImplicitResolveResult.java @@ -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; + } +} diff --git a/python/src/com/jetbrains/python/psi/RatedResolveResult.java b/python/src/com/jetbrains/python/psi/resolve/RatedResolveResult.java similarity index 94% rename from python/src/com/jetbrains/python/psi/RatedResolveResult.java rename to python/src/com/jetbrains/python/psi/resolve/RatedResolveResult.java index 25f38fdcbb0c..2ecb2cc28fb3 100644 --- a/python/src/com/jetbrains/python/psi/RatedResolveResult.java +++ b/python/src/com/jetbrains/python/psi/resolve/RatedResolveResult.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.psi; +package com.jetbrains.python.psi.resolve; import com.intellij.psi.ResolveResult; diff --git a/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java index 242a550b2b56..e8bf6f5c6270 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java +++ b/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java @@ -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 { public static final StubIndexKey KEY = StubIndexKey.createIndexKey("Py.function.shortName"); public StubIndexKey getKey() { return KEY; } + + public static Collection find(String name, Project project, GlobalSearchScope scope) { + return StubIndex.getInstance().get(KEY, name, project, scope); + + } + public static Collection find(String name, Project project) { + return StubIndex.getInstance().get(KEY, name, project, ProjectScope.getAllScope(project)); + } } \ No newline at end of file diff --git a/python/testData/resolve/StackOverflow.py b/python/testData/resolve/StackOverflow.py index 2dfed2ac3995..f1742c86b23f 100644 --- a/python/testData/resolve/StackOverflow.py +++ b/python/testData/resolve/StackOverflow.py @@ -1,3 +1,3 @@ class C: def foo(self): - self.text = self.text.strip() + self.text = self.text.strip_naked() diff --git a/python/testData/resolve/TextBasedResolve.py b/python/testData/resolve/TextBasedResolve.py new file mode 100644 index 000000000000..0bae8e0092aa --- /dev/null +++ b/python/testData/resolve/TextBasedResolve.py @@ -0,0 +1,5 @@ +class A: + def long_unique_identifier(self): pass + +def foo(x): + x.long_unique_identifier() \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index 8cd4344a5225..a1c43c278166 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -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); + } } \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java index 6e8b62964096..02a8b716056e 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java +++ b/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java @@ -18,12 +18,18 @@ import java.io.IOException; public abstract class PyResolveTestCase extends PyLightFixtureTestCase { @NonNls protected static final String MARKER = ""; - 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());