PY-17356: shortcuts added to make inspections faster
authorIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Tue, 3 Nov 2015 23:48:29 +0000 (02:48 +0300)
committerIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Fri, 6 Nov 2015 20:56:23 +0000 (23:56 +0300)
python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java

index b9cbbaec50618a867fae6fd2144a7321288e8b6b..5118d2cd9edc288c1878e48632f4ab210471247b 100644 (file)
@@ -18,19 +18,22 @@ package com.jetbrains.python.nameResolver;
 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
@@ -103,6 +106,77 @@ public final class NameResolverTools {
     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
    */