PY-15222: manager is now callable
authorIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Fri, 9 Oct 2015 19:51:23 +0000 (22:51 +0300)
committerIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Thu, 22 Oct 2015 14:57:25 +0000 (17:57 +0300)
python/psi-api/src/com/jetbrains/python/psi/types/PyClassLikeType.java
python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java
python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java
python/src/com/jetbrains/python/psi/types/PyTypeUtil.java [moved from python/psi-api/src/com/jetbrains/python/psi/types/PyClassLikeTypeUtil.java with 71% similarity]

index 8a279c94e4fb6d22093cd8cbcd4f1affd569d6b9..4cf201e14652fbeffa16fe897fa653bbe06310a3 100644 (file)
@@ -49,12 +49,12 @@ public interface PyClassLikeType extends PyCallableType, PyWithAncestors {
   // TODO: Pull to PyType at next iteration
   /**
    * Visits all class members. This method is better then bare class since it uses type info and supports not only classes but
-   * class-like structures as well. Consider using user-friendly wrapper {@link PyClassLikeTypeUtil#getMembersOfType(PyClassLikeType, Class, TypeEvalContext)}
+   * class-like structures as well. Consider using user-friendly wrapper {@link PyTypeUtil#getMembersOfType(PyClassLikeType, Class, TypeEvalContext)}
    *
    * @param processor visitor
    * @param inherited call on parents too
    * @param context   context to be used to resolve types
-   * @see PyClassLikeTypeUtil#getMembersOfType(PyClassLikeType, Class, TypeEvalContext)
+   * @see PyTypeUtil#getMembersOfType(PyClassLikeType, Class, TypeEvalContext)
    */
   void visitMembers(@NotNull Processor<PsiElement> processor, boolean inherited, @NotNull TypeEvalContext context);
 
index 10dfe9ed464ea6d8edb84b09b6dcf0b1e4fa6ca5..042e115896c46b38190b27e8b702ca4455151ca6 100644 (file)
@@ -41,7 +41,7 @@ import com.jetbrains.python.psi.*;
 import com.jetbrains.python.psi.impl.PyFunctionBuilder;
 import com.jetbrains.python.psi.impl.PyPsiUtils;
 import com.jetbrains.python.psi.types.PyClassLikeType;
-import com.jetbrains.python.psi.types.PyClassLikeTypeUtil;
+import com.jetbrains.python.psi.types.PyTypeUtil;
 import com.jetbrains.python.psi.types.PyNoneType;
 import com.jetbrains.python.psi.types.TypeEvalContext;
 import org.jetbrains.annotations.NotNull;
@@ -333,7 +333,7 @@ public class PyOverrideImplementUtil {
     final PyClassLikeType type = PyUtil.as(context.getType(pyClass), PyClassLikeType.class);
 
     if (type != null) {
-      functions.addAll(PyClassLikeTypeUtil.getMembersOfType(type, PyFunction.class, context));
+      functions.addAll(PyTypeUtil.getMembersOfType(type, PyFunction.class, context));
     }
     return functions;
   }
index d4e7f9b1a7ba4e63f411b983298fb3dc16b807df..b31817cdf636954f0be38c7b81fad117a91bb3ee 100644 (file)
@@ -29,6 +29,7 @@ import com.jetbrains.python.psi.search.PySuperMethodsSearch;
 import com.jetbrains.python.psi.types.*;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -54,7 +55,7 @@ public class KeywordArgumentCompletionUtil {
 
         final PyUnionType unionType = PyUtil.as(context.getType(callee), PyUnionType.class);
         if (unionType != null) {
-          fetchCallablesFromUnion(ret, callExpr, unionType);
+          fetchCallablesFromUnion(ret, callExpr, unionType, context);
         }
       }
     }
@@ -62,10 +63,11 @@ public class KeywordArgumentCompletionUtil {
 
   private static void fetchCallablesFromUnion(@NotNull final List<LookupElement> ret,
                                               @NotNull final PyCallExpression callExpr,
-                                              @NotNull final PyUnionType unionType) {
+                                              @NotNull final PyUnionType unionType,
+                                              @NotNull final TypeEvalContext context) {
     for (final PyType memberType : unionType.getMembers()) {
       if (memberType instanceof PyUnionType) {
-        fetchCallablesFromUnion(ret, callExpr, (PyUnionType)memberType);
+        fetchCallablesFromUnion(ret, callExpr, (PyUnionType)memberType, context);
       }
       if (memberType instanceof PyFunctionType) {
         final PyFunctionType type = (PyFunctionType)memberType;
@@ -73,9 +75,28 @@ public class KeywordArgumentCompletionUtil {
           addKeywordArgumentVariants(type.getCallable(), callExpr, ret);
         }
       }
+      if (memberType instanceof PyCallableType) {
+        final List<PyCallableParameter> callableParameters = ((PyCallableType)memberType).getParameters(context);
+        if (callableParameters != null) {
+          fetchCallablesFromCallableType(ret, callExpr, callableParameters);
+        }
+      }
     }
   }
 
+  private static void fetchCallablesFromCallableType(@NotNull final List<LookupElement> ret,
+                                                     @NotNull final PyCallExpression callExpr,
+                                                     @NotNull final Iterable<PyCallableParameter> callableParameters) {
+    final List<String> parameterNames = new ArrayList<String>();
+    for (final PyCallableParameter callableParameter : callableParameters) {
+      final String name = callableParameter.getName();
+      if (name != null) {
+        parameterNames.add(name);
+      }
+    }
+    addKeywordArgumentVariantsForCallable(callExpr, ret, parameterNames);
+  }
+
   public static void addKeywordArgumentVariants(PyCallable callable, PyCallExpression callExpr, final List<LookupElement> ret) {
     addKeywordArgumentVariants(callable, callExpr, ret, new HashSet<PyCallable>());
   }
@@ -88,24 +109,33 @@ public class KeywordArgumentCompletionUtil {
     visited.add(callable);
 
     final TypeEvalContext context = TypeEvalContext.codeCompletion(callable.getProject(), callable.getContainingFile());
+
     final List<PyParameter> parameters = PyUtil.getParameters(callable, context);
+    for (final PyParameter parameter : parameters) {
+      parameter.getName();
+    }
+
 
     if (callable instanceof PyFunction) {
       addKeywordArgumentVariantsForFunction(callExpr, ret, visited, (PyFunction)callable, parameters, context);
     }
     else {
-      addKeywordArgumentVariantsForCallable(callExpr, ret, parameters);
+      final Collection<String> parameterNames = new ArrayList<String>();
+      for (final PyParameter parameter : parameters) {
+        final String name = parameter.getName();
+        if (name != null) {
+          parameterNames.add(name);
+        }
+      }
+      addKeywordArgumentVariantsForCallable(callExpr, ret, parameterNames);
     }
   }
 
   private static void addKeywordArgumentVariantsForCallable(@NotNull final PyCallExpression callExpr,
                                                             @NotNull final List<LookupElement> ret,
-                                                            @NotNull final List<PyParameter> parameters) {
-    for (final PyParameter parameter : parameters) {
-      final String name = parameter.getName();
-      if (name != null && parameter.getAsNamed() != null) {
-        ret.add(PyUtil.createNamedParameterLookup(name, callExpr.getProject()));
-      }
+                                                            @NotNull final Collection<String> parameterNames) {
+    for (final String parameterName : parameterNames) {
+      ret.add(PyUtil.createNamedParameterLookup(parameterName, callExpr.getProject()));
     }
   }
 
index 8dd70935683b36754e123d4930b67442d5227466..3b92da74485e03d4f71b13b2b676f82821b13ed2 100644 (file)
@@ -20,7 +20,7 @@ import com.intellij.util.Processor;
 import com.intellij.util.QueryExecutor;
 import com.jetbrains.python.psi.*;
 import com.jetbrains.python.psi.types.PyClassLikeType;
-import com.jetbrains.python.psi.types.PyClassLikeTypeUtil;
+import com.jetbrains.python.psi.types.PyTypeUtil;
 import com.jetbrains.python.psi.types.TypeEvalContext;
 import org.jetbrains.annotations.NotNull;
 
@@ -68,7 +68,7 @@ public class PySuperMethodsSearchExecutor implements QueryExecutor<PsiElement, P
           // If super method still not found and we have context, we may use it to find method
           final PyClassLikeType classLikeType = PyUtil.as(context.getType(superClass), PyClassLikeType.class);
           if (classLikeType != null) {
-            for (PyFunction function : PyClassLikeTypeUtil.getMembersOfType(classLikeType, PyFunction.class, context)) {
+            for (final PyFunction function : PyTypeUtil.getMembersOfType(classLikeType, PyFunction.class, context)) {
               final String elemName = function.getName();
               if (elemName != null && elemName.equals(func.getName())) {
                 consumer.process(function);
similarity index 71%
rename from python/psi-api/src/com/jetbrains/python/psi/types/PyClassLikeTypeUtil.java
rename to python/src/com/jetbrains/python/psi/types/PyTypeUtil.java
index 263a8b367c042ab95ca17ce2315ecdb50b4a9aeb..7f7b3ba7384bbbe286e3344799af918d149fe419 100644 (file)
  */
 package com.jetbrains.python.psi.types;
 
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolder;
 import com.intellij.psi.PsiElement;
 import com.intellij.util.Processor;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
 /**
- * Tools and wrappers around {@link PyClassLikeType}
+ * Tools and wrappers around {@link PyType} inheritors
  *
  * @author Ilya.Kazakevich
  */
-public final class PyClassLikeTypeUtil {
-  private PyClassLikeTypeUtil() {
+public final class PyTypeUtil {
+  private PyTypeUtil() {
   }
 
   /**
@@ -60,4 +63,25 @@ public final class PyClassLikeTypeUtil {
     }, true, context);
     return result;
   }
+
+
+  // TODO: DOC
+  @Nullable
+  public static <T> T findData(@NotNull final PyType type, @NotNull final Key<T> key) {
+    if (type instanceof UserDataHolder) {
+      return ((UserDataHolder)type).getUserData(key);
+    }
+    if (type instanceof PyUnionType) {
+      for (final PyType memberType : ((PyUnionType)type).getMembers()) {
+        if (memberType == null) {
+          continue;
+        }
+        final T result = findData(memberType, key);
+        if (result != null) {
+          return result;
+        }
+      }
+    }
+    return null;
+  }
 }