import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
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.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
+import com.jetbrains.python.psi.types.PyFunctionType;
+import com.jetbrains.python.psi.types.PyType;
+import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
/**
* @author Ilya.Kazakevich
return null;
}
+ /**
+ * Same as {@link #isName(PyElement, FQNamesProvider...)} for call expr, but first checks name.
+ * Aliases not supported, but much lighter that way
+ *
+ * @param call expr
+ * @param function names to check
+ * @param context
+ * @return true if callee is correct
+ */
+ public static boolean isCalleeShortCut(@NotNull final PyCallExpression call,
+ @NotNull final FQNamesProvider function,
+ @Nullable final TypeEvalContext context) {
+ if (context == null) {
+ return call.isCallee(function);
+ }
+ final PyExpression callee = call.getCallee();
+ if (callee == null) {
+ return false;
+ }
+
+ final PyType calleeType = context.getType(callee);
+ if (!(calleeType instanceof PyFunctionType)) {
+ return false;
+ }
+ final PyCallable callable = ((PyFunctionType)calleeType).getCallable();
+ final String callableName = callable.getName();
+ if (callableName == null) {
+ return false;
+ }
+
+ final Set<String> possibleNames = new HashSet<String>();
+ for (final String lastComponent : getLastComponents(function)) {
+ possibleNames.add(lastComponent);
+ }
+ return possibleNames.contains(callableName) && call.isCallee(function);
+ }
+
+ @NotNull
+ private static List<String> getLastComponents(@NotNull final FQNamesProvider provider) {
+ final List<String> result = new ArrayList<String>();
+ for (final String name : provider.getNames()) {
+ final String component = QualifiedName.fromDottedString(name).getLastComponent();
+ if (component != null) {
+ result.add(component);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Checks if some string contains last component one of name
+ * @param text test to check
+ * @param names
+ */
+ public static boolean isContainsName(@NotNull final String text, @NotNull final FQNamesProvider names) {
+ for (final String lastComponent : getLastComponents(names)) {
+ if (text.contains(lastComponent)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * Checks if some file contains last component one of name
+ * @param file file to check
+ * @param names
+ */
+ public static boolean isContainsName(@NotNull final PsiFile file, @NotNull final FQNamesProvider names) {
+ return isContainsName(file.getText(), names);
+ }
+
/**
* Looks for call of some function
*/