diff --git a/python/python-psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java b/python/python-psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java
index 8219e5d27d24..d2749be8c696 100644
--- a/python/python-psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java
+++ b/python/python-psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java
@@ -21,12 +21,14 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiCacheKey;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.Function;
+import com.intellij.util.ObjectUtils;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -72,9 +74,22 @@ public final class NameResolverTools {
return false;
}
+ /**
+ * Same as {@link #isName(PyElement, FQNamesProvider...)} for named elements, but only checks name.
+ * Aliases not supported, but much lighter that way
+ */
+ public static boolean isNameShortCut(@NotNull PyElement element, @NotNull FQNamesProvider... namesProviders) {
+ String name = element.getName();
+ if (name == null) {
+ return false;
+ }
+ return Arrays.stream(namesProviders).anyMatch(o -> getLastComponents(o).contains(name));
+ }
+
/**
* Checks if FQ element name is one of provided names. May be heavy.
* It is always better to use less accurate but lighter {@link #isCalleeShortCut(PyCallExpression, FQNamesProvider)}
+ * and {@link #isNameShortCut(PyElement, FQNamesProvider...)}
*
* @param element element to check
* @param namesProviders some enum that has one or more names
@@ -83,7 +98,8 @@ public final class NameResolverTools {
public static boolean isName(@NotNull final PyElement element, @NotNull final FQNamesProvider... namesProviders) {
assert element.isValid();
final Pair qualifiedAndClassName = RecursionManager.doPreventingRecursion(element, false,
- () -> QUALIFIED_AND_CLASS_NAME.getValue(element));
+ () -> QUALIFIED_AND_CLASS_NAME
+ .getValue(element));
LOG.assertTrue(qualifiedAndClassName != null);
//noinspection ConstantConditions
if (qualifiedAndClassName == null) return false;
@@ -119,7 +135,7 @@ public final class NameResolverTools {
}
/**
- * Same as {@link #isName(PyElement, FQNamesProvider...)} for call expr, but first checks name.
+ * Same as {@link #isName(PyElement, FQNamesProvider...)} for call expr, but only checks name.
* Aliases not supported, but much lighter that way
*
* @param call expr
@@ -127,7 +143,7 @@ public final class NameResolverTools {
* @return true if callee is correct
*/
public static boolean isCalleeShortCut(@NotNull final PyCallExpression call,
- @NotNull final FQNamesProvider function) {
+ @NotNull final FQNamesProvider... function) {
final PyExpression callee = call.getCallee();
if (callee == null) {
return false;
@@ -135,8 +151,7 @@ public final class NameResolverTools {
final String callableName = callee.getName();
- final Collection possibleNames = getLastComponents(function);
- return possibleNames.contains(callableName) && call.isCallee(function);
+ return Arrays.stream(function).anyMatch(o -> getLastComponents(o).contains(callableName));
}
@NotNull
@@ -178,6 +193,7 @@ public final class NameResolverTools {
/**
* Check if class has parent with some name
+ *
* @param child class to check
*/
public static boolean isSubclass(@NotNull final PyClass child,
@@ -205,7 +221,8 @@ public final class NameResolverTools {
@Override
public boolean value(final PsiElement element) {
if (element instanceof PyCallExpression) {
- return ((PyCallExpression)element).isCallee(myNameToSearch);
+ PyCallExpression callExpression = (PyCallExpression)element;
+ return isCalleeShortCut(callExpression, myNameToSearch);
}
return false;
}
diff --git a/python/python-psi-api/src/com/jetbrains/python/psi/PyCallExpression.java b/python/python-psi-api/src/com/jetbrains/python/psi/PyCallExpression.java
index a559e66ce1c4..8fa2a5bd4442 100644
--- a/python/python-psi-api/src/com/jetbrains/python/psi/PyCallExpression.java
+++ b/python/python-psi-api/src/com/jetbrains/python/psi/PyCallExpression.java
@@ -233,14 +233,17 @@ public interface PyCallExpression extends PyCallSiteExpression {
/**
* Checks if the qualified name of the callee matches any of the specified names provided by provider.
- * May be heavy.
- * Use {@link NameResolverTools#isCalleeShortCut(PyCallExpression, FQNamesProvider)}
- * if you can.
+ * May be heavy, and it is not recommended to use.
+ * Use {@link NameResolverTools#isCalleeShortCut(PyCallExpression, FQNamesProvider...)} or
+ * {@link com.jetbrains.extensions.python.PyCallExpressionExtKt#isCalleeName(PyCallExpression, FQNamesProvider...)}.
*
* @param name providers that provides one or more names to check
* @return true if matches, false otherwise
* @see com.jetbrains.python.nameResolver
+ * @see com.jetbrains.extensions.python.PyCallExpressionExtKt#isCalleeName(PyCallExpression, FQNamesProvider...)
+ * @deprecated use {@link com.jetbrains.extensions.python.PyCallExpressionExtKt#isCalleeName(PyCallExpression, FQNamesProvider...)}.
*/
+ @Deprecated
default boolean isCallee(@NotNull FQNamesProvider... name) {
final PyExpression callee = getCallee();
return callee instanceof PyReferenceExpression && NameResolverTools.isName(callee, name);
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEvaluator.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEvaluator.java
index c7cd4f8cdfea..237393ac4850 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEvaluator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEvaluator.java
@@ -23,6 +23,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonFQDNNames;
+import com.jetbrains.python.nameResolver.NameResolverTools;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import org.jetbrains.annotations.Contract;
@@ -302,7 +303,7 @@ public class PyEvaluator {
}
// Support dict([("k", "v")]) syntax
- if (myEnableResolve && expression.isCallee(PythonFQDNNames.DICT_CLASS)) {
+ if (myEnableResolve && NameResolverTools.isCalleeShortCut(expression, PythonFQDNNames.DICT_CLASS)) {
final Collection tuples = PsiTreeUtil.findChildrenOfType(expression, PyTupleExpression.class);
if (!tuples.isEmpty()) {
final Map