diff --git a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
index dd7d70f929b2..3fe4555051ed 100644
--- a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
+++ b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
@@ -1,6 +1,6 @@
package com.jetbrains.python.intelliLang;
-import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiLanguageInjectionHost;
import com.jetbrains.python.patterns.PythonPatterns;
import com.jetbrains.python.psi.PyElement;
import org.intellij.plugins.intelliLang.inject.AbstractLanguageInjectionSupport;
@@ -26,7 +26,12 @@ public class PyLanguageInjectionSupport extends AbstractLanguageInjectionSupport
}
@Override
- public boolean useDefaultInjector(PsiElement host) {
+ public boolean isApplicableTo(PsiLanguageInjectionHost host) {
return host instanceof PyElement;
}
+
+ @Override
+ public boolean useDefaultInjector(PsiLanguageInjectionHost host) {
+ return true;
+ }
}
diff --git a/python/main_pycharm.iml b/python/main_pycharm.iml
index b05917390a2a..981f6a1ce273 100644
--- a/python/main_pycharm.iml
+++ b/python/main_pycharm.iml
@@ -47,6 +47,8 @@
+
+
diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java
index adbe3806074f..5a74a6e0f1a3 100644
--- a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java
+++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.impl;
-import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
@@ -12,6 +11,7 @@ import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.resolve.CompletionVariantsProcessor;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
+import com.jetbrains.python.psi.types.PyCallableParameter;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -101,7 +101,7 @@ public class PyJavaClassType implements PyClassLikeType {
@Nullable
@Override
- public List> getParameters(@NotNull TypeEvalContext context) {
+ public List getParameters(@NotNull TypeEvalContext context) {
return null;
}
diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java
index 3ef7355229b9..180ad2377503 100644
--- a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java
+++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.impl;
-import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.util.ArrayUtil;
@@ -10,6 +9,7 @@ import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
+import com.jetbrains.python.psi.types.PyCallableParameter;
import com.jetbrains.python.psi.types.PyCallableType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -42,7 +42,7 @@ public class PyJavaMethodType implements PyCallableType {
@Nullable
@Override
- public List> getParameters(@NotNull TypeEvalContext context) {
+ public List getParameters(@NotNull TypeEvalContext context) {
return null;
}
diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyDynamicMember.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyDynamicMember.java
index 3e5e117a30eb..7505d3a0ca07 100644
--- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyDynamicMember.java
+++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyDynamicMember.java
@@ -102,6 +102,11 @@ public class PyDynamicMember {
return this;
}
+ public PyDynamicMember toAssignment(String assignee) {
+ myPsiPath = new PyPsiPath.ToAssignment(myPsiPath, assignee);
+ return this;
+ }
+
public PyDynamicMember toPsiElement(final PsiElement psiElement) {
myPsiPath = new PyPsiPath() {
diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java
index c773926433a6..a9e96f7f8b3f 100644
--- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java
+++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyPsiPath.java
@@ -240,4 +240,43 @@ public abstract class PyPsiPath {
}
}
}
+
+ public static class ToAssignment extends PyPsiPath {
+ private final PyPsiPath myParent;
+ private final String myAssignee;
+
+ public ToAssignment(PyPsiPath parent, String assignee) {
+ myParent = parent;
+ myAssignee = assignee;
+ }
+
+ @Nullable
+ @Override
+ public PsiElement resolve(PsiElement context) {
+ PsiElement parent = myParent.resolve(context);
+ if (parent == null) {
+ return null;
+ }
+ AssignmentFinder finder = new AssignmentFinder(myAssignee);
+ parent.accept(finder);
+ return finder.myResult != null ? finder.myResult : parent;
+ }
+ }
+
+ private static class AssignmentFinder extends PyRecursiveElementVisitor {
+ private final String myAssignee;
+ private PsiElement myResult;
+
+ public AssignmentFinder(String assignee) {
+ myAssignee = assignee;
+ }
+
+ @Override
+ public void visitPyAssignmentStatement(PyAssignmentStatement node) {
+ PyExpression lhs = node.getLeftHandSideExpression();
+ if (lhs != null && myAssignee.equals(lhs.getText())) {
+ myResult = node;
+ }
+ }
+ }
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/Callable.java b/python/psi-api/src/com/jetbrains/python/psi/Callable.java
index 40505a9e1c04..c156564506a3 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/Callable.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/Callable.java
@@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable;
* @author dcheryasov
*/
-public interface Callable extends PyElement {
+public interface Callable extends PyTypedElement {
/**
* @return a list of parameters passed to this callable, possibly empty.
diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
index 38dfcac02dae..cc3452d52dc6 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
@@ -31,4 +31,7 @@ public interface PyTypeProvider {
@Nullable
PyType getContextManagerVariableType(PyClass contextManager, PyExpression withExpression, TypeEvalContext context);
+
+ @Nullable
+ PyType getCallableType(@NotNull Callable callable, @NotNull TypeEvalContext context);
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableParameter.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableParameter.java
new file mode 100644
index 000000000000..8df290cc9a41
--- /dev/null
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableParameter.java
@@ -0,0 +1,19 @@
+package com.jetbrains.python.psi.types;
+
+import com.jetbrains.python.psi.PyParameter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author vlan
+ */
+public interface PyCallableParameter {
+ @Nullable
+ String getName();
+
+ @Nullable
+ PyType getType(@NotNull TypeEvalContext context);
+
+ @Nullable
+ PyParameter getParameter();
+}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java
index 482df90af817..261a7eb443d2 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
-import com.intellij.openapi.util.Pair;
import com.jetbrains.python.psi.PyQualifiedExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,8 +31,8 @@ public interface PyCallableType extends PyType {
/**
* Returns the list of parameter types.
*
- * @return list of (name, type) pairs or null if not applicable. Name and type in pair may be null.
+ * @return list of parameter info null if not applicable.
*/
@Nullable
- List> getParameters(@NotNull TypeEvalContext context);
+ List getParameters(@NotNull TypeEvalContext context);
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java
index dd6b8c0eda59..672b37fffd0b 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java
@@ -13,8 +13,8 @@ import java.util.Collection;
public interface PyClassMembersProvider {
ExtensionPointName EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider");
- Collection getMembers(PyClassType clazz);
+ Collection getMembers(PyClassType clazz, @Nullable PsiElement location);
@Nullable
- PsiElement resolveMember(PyClassType clazz, String name);
+ PsiElement resolveMember(PyClassType clazz, String name, @Nullable PsiElement location);
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java
index 4420221c9d6e..ef91d4ef8ddb 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java
@@ -13,13 +13,13 @@ import java.util.Collections;
*/
public class PyClassMembersProviderBase implements PyClassMembersProvider {
@Override
- public Collection getMembers(PyClassType clazz) {
+ public Collection getMembers(PyClassType clazz, PsiElement location) {
return Collections.emptyList();
}
@Override
- public PsiElement resolveMember(PyClassType clazz, String name) {
- final Collection members = getMembers(clazz);
+ public PsiElement resolveMember(PyClassType clazz, String name, PsiElement location) {
+ final Collection members = getMembers(clazz, location);
return resolveMemberByName(members, clazz, name);
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
index 81988147bd01..aa23c396bab6 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
@@ -102,6 +102,12 @@ public class PyTypeProviderBase implements PyTypeProvider {
return null;
}
+ @Nullable
+ @Override
+ public PyType getCallableType(@NotNull Callable callable, @NotNull TypeEvalContext context) {
+ return null;
+ }
+
protected void registerSelfReturnType(String classQualifiedName, Collection methods) {
registerReturnType(classQualifiedName, methods, mySelfTypeCallback);
}
diff --git a/python/src/com/jetbrains/python/PyParameterInfoHandler.java b/python/src/com/jetbrains/python/PyParameterInfoHandler.java
index 9cff15d75fc2..ff567ffaa17f 100644
--- a/python/src/com/jetbrains/python/PyParameterInfoHandler.java
+++ b/python/src/com/jetbrains/python/PyParameterInfoHandler.java
@@ -10,6 +10,7 @@ import com.intellij.util.text.CharArrayUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.ParamHelper;
import com.jetbrains.python.psi.resolve.PyResolveContext;
+import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -110,12 +111,14 @@ public class PyParameterInfoHandler implements ParameterInfoHandler parameterList = Arrays.asList(callable.getParameterList().getParameters());
+ final List parameterList = PyUtil.getParameters(callable, typeEvalContext);
final List namedParameters = new ArrayList(parameterList.size());
// param -> hint index. indexes are not contiguous, because some hints are parentheses.
@@ -123,7 +126,7 @@ public class PyParameterInfoHandler implements ParameterInfoHandler flags. this includes flags for parens.
final Map> hintFlags = new HashMap>();
- final List hintsList = buildParameterListHint(callable, namedParameters, parameterToIndex, hintFlags);
+ final List hintsList = buildParameterListHint(parameterList, namedParameters, parameterToIndex, hintFlags);
final int currentParamOffset = context.getCurrentParameterIndex(); // in Python mode, we get an offset here, not an index!
@@ -268,19 +271,18 @@ public class PyParameterInfoHandler implements ParameterInfoHandler buildParameterListHint(@NotNull final Callable callable,
+ private static List buildParameterListHint(@NotNull List parameters,
@NotNull final List namedParameters,
@NotNull final Map parameterToIndex,
@NotNull final Map> hintFlags) {
-
final List hintsList = new ArrayList();
ParamHelper.walkDownParamArray(
- callable.getParameterList().getParameters(),
+ parameters.toArray(new PyParameter[parameters.size()]),
new ParamHelper.ParamWalker() {
public void enterTupleParameter(PyTupleParameter param, boolean first, boolean last) {
hintFlags.put(hintsList.size(), EnumSet.noneOf(ParameterInfoUIContextEx.Flag.class));
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java
index e2576e7c8a4f..231ea319bb1d 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java
@@ -1,6 +1,7 @@
package com.jetbrains.python.codeInsight.stdlib;
import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiElement;
import com.jetbrains.python.codeInsight.PyDynamicMember;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
@@ -21,7 +22,7 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase {
private Key> mySocketMembersKey = Key.create("socket.members");
@Override
- public Collection getMembers(PyClassType classType) {
+ public Collection getMembers(PyClassType classType, PsiElement location) {
PyClass clazz = classType.getPyClass();
final String qualifiedName = clazz.getQualifiedName();
if ("socket._socketobject".equals(qualifiedName)) {
diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsLineMarkerProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsLineMarkerProvider.java
index 624c67e7ce7a..1d538b219042 100644
--- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsLineMarkerProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsLineMarkerProvider.java
@@ -39,7 +39,7 @@ public class PyUserSkeletonsLineMarkerProvider implements LineMarkerProvider {
final PyElement skeleton = getUserSkeleton(element);
if (skeleton != null) {
result.add(new LineMarkerInfo(
- element, element.getTextRange(), ICON, Pass.VISIBLE_LINE_MARKERS,
+ element, element.getTextRange(), ICON, Pass.UPDATE_OVERRIDEN_MARKERS,
new Function() {
@Override
public String fun(PsiElement e) {
diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java
index f93b3b22978c..0a7d129b0018 100644
--- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java
@@ -46,4 +46,14 @@ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase {
}
return null;
}
+
+ @Nullable
+ @Override
+ public PyType getCallableType(@NotNull Callable callable, @NotNull TypeEvalContext context) {
+ final Callable callableSkeleton = PyUserSkeletonsUtil.getUserSkeleton(callable);
+ if (callableSkeleton != null) {
+ return context.getType(callableSkeleton);
+ }
+ return null;
+ }
}
diff --git a/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java b/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
index 8e6db24d6d8b..8e42abebebe8 100644
--- a/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
+++ b/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
@@ -2,14 +2,9 @@ package com.jetbrains.python.documentation;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyNames;
-import com.jetbrains.python.psi.Callable;
-import com.jetbrains.python.psi.PyNamedParameter;
-import com.jetbrains.python.psi.PyParameter;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.toolbox.ChainIterable;
import org.jetbrains.annotations.NotNull;
@@ -170,7 +165,10 @@ public class PyTypeModelBuilder {
final PyTupleType tupleType = (PyTupleType)elementType;
final int n = tupleType.getElementCount();
for (int i = 0; i < n; i++) {
- elementTypes.add(build(tupleType.getElementType(i), true));
+ final PyType t = tupleType.getElementType(i);
+ if (t != null) {
+ elementTypes.add(build(t, true));
+ }
}
}
else if (elementType != null) {
@@ -206,11 +204,11 @@ public class PyTypeModelBuilder {
private TypeModel build(@NotNull PyCallableType type) {
List parameterModels = null;
- final List> parameters = type.getParameters(myContext);
+ final List parameters = type.getParameters(myContext);
if (parameters != null) {
parameterModels = new ArrayList();
- for (Pair parameter : parameters) {
- parameterModels.add(new ParamType(parameter.getFirst(), build(parameter.getSecond(), true)));
+ for (PyCallableParameter parameter : parameters) {
+ parameterModels.add(new ParamType(parameter.getName(), build(parameter.getType(myContext), true)));
}
}
final PyType ret = type.getCallType(myContext, null);
@@ -218,27 +216,6 @@ public class PyTypeModelBuilder {
return new FunctionType(returnType, parameterModels);
}
- public TypeModel build(Callable callable) {
- final PyType returnType = callable.getReturnType(myContext, null);
- return new FunctionType(build(returnType, true), Collections2.transform(Lists.newArrayList(callable.getParameterList().getParameters()),
- new Function() {
- @Override
- public TypeModel apply(PyParameter p) {
- final PyNamedParameter np = p.getAsNamed();
- if (np != null) {
- TypeModel paramType = _(PyNames.UNKNOWN_TYPE);
- final PyType t = myContext.getType(np);
- if (t != null) {
- paramType = build(t, true);
- }
- final String name = PyFunctionType.getParameterName(np);
- return new ParamType(name, paramType);
- }
- return new ParamType(p.toString(), null);
- }
- }));
- }
-
private interface TypeVisitor {
void oneOf(OneOf oneOf);
diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
index 2133374f2bec..f9dfdfd352bf 100644
--- a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
+++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
@@ -15,9 +15,11 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.Function;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.console.PydevConsoleRunner;
@@ -122,7 +124,19 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
ChainIterable cat = new ChainIterable();
final String name = fun.getName();
cat.addItem("def ").addWith(func_name_wrapper, $(name));
- cat.addItem(escaper.apply(PyUtil.getReadableRepr(fun.getParameterList(), false)));
+ final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getContainingFile());
+ final List parameters = PyUtil.getParameters(fun, context);
+ final String paramStr = "(" +
+ StringUtil.join(parameters,
+ new Function() {
+ @Override
+ public String fun(PyParameter parameter) {
+ return PyUtil.getReadableRepr(parameter, false);
+ }
+ },
+ ", ") +
+ ")";
+ cat.addItem(escaper.apply(paramStr));
if (!PyNames.INIT.equals(name)) {
cat.addItem(escaper.apply("\nInferred type: "));
getTypeDescription(fun, cat);
@@ -157,16 +171,10 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
return String.format("Inferred type: %s", getTypeName(context.getType(element), context));
}
- public static String getTypeDescription(@NotNull PyFunction fun) {
- final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getContainingFile());
- PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
- return builder.build(fun).asString();
- }
-
public static void getTypeDescription(@NotNull PyFunction fun, ChainIterable body) {
final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getContainingFile());
PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
- builder.build(fun).toBodyWithLinks(body, fun);
+ builder.build(context.getType(fun), true).toBodyWithLinks(body, fun);
}
public static String getTypeName(@Nullable PyType type, @NotNull final TypeEvalContext context) {
@@ -552,27 +560,28 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
private static String generateContent(PyFunction function, String offset, String prefix, boolean checkReturn) {
//TODO: this code duplicates PyDocstringGenerator in some parts
- PyParameter[] list = function.getParameterList().getParameters();
- StringBuilder builder = new StringBuilder(offset);
+ final StringBuilder builder = new StringBuilder(offset);
+ final TypeEvalContext context = TypeEvalContext.userInitiated(function.getContainingFile());
PySignature signature = PySignatureCacheManager.getInstance(function.getProject()).findSignature(function);
- for (PyParameter p : list) {
- if (p.getText().equals(PyNames.CANONICAL_SELF) || p.getName() == null) {
+ for (PyParameter p : PyUtil.getParameters(function, context)) {
+ final String parameterName = p.getName();
+ if (p.getText().equals(PyNames.CANONICAL_SELF) || parameterName == null) {
continue;
}
- String argType = signature == null ? null : signature.getArgTypeQualifiedName(p.getName());
+ String argType = signature == null ? null : signature.getArgTypeQualifiedName(parameterName);
if (argType == null) {
builder.append(prefix);
builder.append("param ");
- builder.append(p.getName());
+ builder.append(parameterName);
builder.append(": ");
builder.append(offset);
}
if (PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB || argType != null) {
builder.append(prefix);
builder.append("type ");
- builder.append(p.getName());
+ builder.append(parameterName);
builder.append(": ");
if (signature != null) {
builder.append(PySignatureUtil.getShortestImportableName(function, argType));
diff --git a/python/src/com/jetbrains/python/findUsages/PyUsageTypeProvider.java b/python/src/com/jetbrains/python/findUsages/PyUsageTypeProvider.java
index 23a538cb632e..9114b10c3d84 100644
--- a/python/src/com/jetbrains/python/findUsages/PyUsageTypeProvider.java
+++ b/python/src/com/jetbrains/python/findUsages/PyUsageTypeProvider.java
@@ -74,7 +74,7 @@ public class PyUsageTypeProvider implements UsageTypeProviderEx {
}
@Nullable
- private static UsageType checkMatchingSignatureGroup(PyCallExpression call, UsageTarget[] targets, TypeEvalContext context) {
+ private static UsageType checkMatchingSignatureGroup(PyCallExpression call, UsageTarget[] targets, @NotNull TypeEvalContext context) {
if (targets.length == 1 && targets[0] instanceof PsiElementUsageTarget) {
final PsiElement element = ((PsiElementUsageTarget)targets[0]).getElement();
if (element instanceof PyFunction) {
diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
index 3c40839d3853..b6c5b7be30a2 100644
--- a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
@@ -57,16 +57,17 @@ public class PyArgumentListInspection extends PyInspection {
if (mkfunc != null && !mkfunc.isImplicitlyResolved()) {
Callable callable = mkfunc.getCallable();
int first_param_offset = mkfunc.getImplicitOffset();
- PyParameter[] params = callable.getParameterList().getParameters();
- PyNamedParameter alleged_first_param = params.length < first_param_offset ? null : params[first_param_offset-1].getAsNamed();
+ final List params = PyUtil.getParameters(callable, myTypeEvalContext);
+ final PyNamedParameter alleged_first_param = params.size() < first_param_offset ?
+ null : params.get(first_param_offset-1).getAsNamed();
if (alleged_first_param == null || alleged_first_param.isKeywordContainer()) {
// no parameters left to pass function implicitly, or wrong param type
registerProblem(deco, PyBundle.message("INSP.func.$0.lacks.first.arg", callable.getName())); // TODO: better names for anon lambdas
}
else {
// possible unfilled params
- for (int i=first_param_offset; i < params.length; i += 1) {
- PyNamedParameter par = params[i].getAsNamed();
+ for (int i=first_param_offset; i < params.size(); i += 1) {
+ PyNamedParameter par = params.get(i).getAsNamed();
// param tuples, non-starred or non-default won't do
if (par == null || (! par.isKeywordContainer() && ! par.isPositionalContainer() && !par.hasDefaultValue())) {
String par_name;
@@ -87,7 +88,7 @@ public class PyArgumentListInspection extends PyInspection {
public static void inspectPyArgumentList(PyArgumentList node, ProblemsHolder holder, final TypeEvalContext context, int implicitOffset) {
if (node.getParent() instanceof PyClass) return; // class Foo(object) is also an arg list
CallArgumentsMapping result = node.analyzeCall(PyResolveContext.noImplicits().withTypeEvalContext(context), implicitOffset);
- highlightIncorrectArguments(holder, result);
+ highlightIncorrectArguments(holder, result, context);
highlightMissingArguments(node, holder, result);
highlightStarArgumentTypeMismatch(node, holder, context);
}
@@ -96,7 +97,7 @@ public class PyArgumentListInspection extends PyInspection {
inspectPyArgumentList(node, holder, context, 0);
}
- private static void highlightIncorrectArguments(ProblemsHolder holder, CallArgumentsMapping result) {
+ private static void highlightIncorrectArguments(ProblemsHolder holder, CallArgumentsMapping result, @NotNull TypeEvalContext context) {
for (Map.Entry> argEntry : result.getArgumentFlags().entrySet()) {
EnumSet flags = argEntry.getValue();
if (!flags.isEmpty()) { // something's wrong
@@ -120,9 +121,9 @@ public class PyArgumentListInspection extends PyInspection {
final PyCallExpression.PyMarkedCallee markedCallee = result.getMarkedCallee();
String parameterName = null;
if (markedCallee != null) {
- final PyParameter[] parameters = markedCallee.getCallable().getParameterList().getParameters();
- for (int i = parameters.length - 1; i >= 0; --i) {
- final PyParameter param = parameters[i];
+ final List parameters = PyUtil.getParameters(markedCallee.getCallable(), context);
+ for (int i = parameters.size() - 1; i >= 0; --i) {
+ final PyParameter param = parameters.get(i);
if (param instanceof PyNamedParameter) {
final List unmappedParams = result.getUnmappedParams();
if (!((PyNamedParameter)param).isPositionalContainer() && !((PyNamedParameter)param).isKeywordContainer() &&
diff --git a/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java b/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java
index 72aca8cbd9a2..b2d557941f7b 100644
--- a/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyCallByClassInspection.java
@@ -12,6 +12,7 @@ import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
+import java.util.List;
import java.util.Map;
import static com.jetbrains.python.psi.PyFunction.Modifier.CLASSMETHOD;
@@ -77,9 +78,9 @@ public class PyCallByClassInspection extends PyInspection {
CallArgumentsMapping analysis = arglist.analyzeCall(resolveWithoutImplicits());
final PyCallExpression.PyMarkedCallee markedCallee = analysis.getMarkedCallee();
if (markedCallee != null && markedCallee.getModifier() != STATICMETHOD) {
- PyParameter[] params = markedCallee.getCallable().getParameterList().getParameters();
- if (params.length > 0 && params[0] instanceof PyNamedParameter) {
- PyNamedParameter first_param = (PyNamedParameter)params[0];
+ final List params = PyUtil.getParameters(markedCallee.getCallable(), myTypeEvalContext);
+ if (params.size() > 0 && params.get(0) instanceof PyNamedParameter) {
+ PyNamedParameter first_param = (PyNamedParameter)params.get(0);
for (Map.Entry entry : analysis.getPlainMappedParams().entrySet()) {
// we ignore *arg and **arg which we cannot analyze
if (entry.getValue() == first_param) {
diff --git a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
index 9002e762105f..757664c8915f 100644
--- a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
@@ -63,7 +63,7 @@ public class PyTypeCheckerInspection extends PyInspection {
final PyExpression source = node.getForPart().getSource();
if (source != null) {
final PyType type = myTypeEvalContext.getType(source);
- if (!PyTypeChecker.isUnknown(type) && !PyABCUtil.isSubtype(type, PyNames.ITERABLE)) {
+ if (type != null && !PyTypeChecker.isUnknown(type) && !PyABCUtil.isSubtype(type, PyNames.ITERABLE)) {
registerProblem(source, String.format("Expected 'collections.Iterable', got '%s' instead",
PythonDocumentationProvider.getTypeName(type, myTypeEvalContext)));
}
diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
index 71c0faac02a2..ac6a5cd69131 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
@@ -653,7 +653,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
if (isDecoratedAsDynamic(cls, true)) {
return true;
}
- if (hasUnresolvedDynamicMember((PyClassType)qtype, refText)) return true;
+ if (hasUnresolvedDynamicMember((PyClassType)qtype, reference, refText)) return true;
}
if (qtype instanceof CythonBuiltinType ||
(qtype instanceof CythonType && reference instanceof PyOperatorReference)) {
@@ -668,9 +668,11 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return false;
}
- private static boolean hasUnresolvedDynamicMember(@NotNull final PyClassType qtype, @NotNull final String refText) {
+ private static boolean hasUnresolvedDynamicMember(@NotNull final PyClassType qtype,
+ PsiReference reference,
+ @NotNull final String refText) {
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
- final Collection resolveResult = provider.getMembers(qtype);
+ final Collection resolveResult = provider.getMembers(qtype, reference.getElement());
for (PyDynamicMember member : resolveResult) {
if (member.getName().equals(refText)) return true;
}
diff --git a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java
index c4ab81b1eaa8..2f54b99a80b1 100644
--- a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java
+++ b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java
@@ -57,7 +57,8 @@ public class PyInstalledPackagesPanel extends InstalledPackagesPanel {
}
private Sdk getSelectedSdk() {
- return ((PyPackageManagementService) myPackageManagementService).getSdk();
+ PyPackageManagementService service = (PyPackageManagementService)myPackageManagementService;
+ return service != null ? service.getSdk() : null;
}
public void updateNotifications(@NotNull final Sdk selectedSdk) {
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 5ade1e62cdca..e1413a826059 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -1238,5 +1238,32 @@ public class PyUtil {
}
return element;
}
-}
+ @NotNull
+ public static List getParameters(@NotNull Callable callable, @NotNull TypeEvalContext context) {
+ PyType type = context.getType(callable);
+ if (type instanceof PyUnionType) {
+ type = ((PyUnionType)type).excludeNull();
+ }
+ if (type instanceof PyCallableType) {
+ final PyCallableType callableType = (PyCallableType)type;
+ final List callableTypeParameters = callableType.getParameters(context);
+ if (callableTypeParameters != null) {
+ boolean allParametersDefined = true;
+ final List parameters = new ArrayList();
+ for (PyCallableParameter callableParameter : callableTypeParameters) {
+ final PyParameter parameter = callableParameter.getParameter();
+ if (parameter == null) {
+ allParametersDefined = false;
+ break;
+ }
+ parameters.add(parameter);
+ }
+ if (allParametersDefined) {
+ return parameters;
+ }
+ }
+ }
+ return Arrays.asList(callable.getParameterList().getParameters());
+ }
+}
diff --git a/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java b/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
index e8cddd605855..7122f4c93bc2 100644
--- a/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
@@ -3,9 +3,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.psi.*;
-import com.jetbrains.python.psi.types.PyTupleType;
-import com.jetbrains.python.psi.types.PyType;
-import com.jetbrains.python.psi.types.TypeEvalContext;
+import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,7 +47,7 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
* @param resolved_callee what to map parameters of
* @param context optional shared type evaluator / cache.
*/
- public void mapArguments(PyCallExpression.PyMarkedCallee resolved_callee, @Nullable TypeEvalContext context) {
+ public void mapArguments(PyCallExpression.PyMarkedCallee resolved_callee, @NotNull TypeEvalContext context) {
PyExpression[] arguments = myArgumentList.getArguments();
myMarkedCallee = resolved_callee;
List unmatched_args = new LinkedList();
@@ -75,8 +73,8 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
}
}
}
+ final List parameters = PyUtil.getParameters(myMarkedCallee.getCallable(), context);
// prepare parameter slots
- final PyParameter[] parameters = myMarkedCallee.getCallable().getParameterList().getParameters();
Map slots = new LinkedHashMap();
PyNamedParameter kwd_par = null; // **param
PyNamedParameter tuple_par = null; // *param
@@ -109,8 +107,8 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
i += 1;
}
// rule out 'self' or other implicit params
- for (i=0; i < implicit_offset && i < parameters.length; i+=1) {
- slots.remove(parameters[i].getAsNamed());
+ for (i=0; i < implicit_offset && i < parameters.size(); i+=1) {
+ slots.remove(parameters.get(i).getAsNamed());
positional_index += 1;
}
// now params to the left of positional_index are positional.
@@ -125,8 +123,8 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
positional_bound = cnt;
break;
}
- if (cnt < parameters.length && cnt < positional_index) {
- final PyParameter par = parameters[cnt];
+ if (cnt < parameters.size() && cnt < positional_index) {
+ final PyParameter par = parameters.get(cnt);
PyNamedParameter n_par = par.getAsNamed();
if (n_par != null) {
cnt += 1;
@@ -203,14 +201,12 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
// map *arg to positional params if possible
boolean tuple_arg_not_exhausted = false;
boolean tuple_dup_found = false;
- if (cnt < parameters.length && cnt < positional_index && myTupleArg != null) {
+ if (cnt < parameters.size() && cnt < positional_index && myTupleArg != null) {
// check length of myTupleArg
PyType tuple_arg_type = null;
- if (context != null) {
- final PyExpression expression = PsiTreeUtil.getChildOfType(myTupleArg, PyExpression.class);
- if (expression != null) {
- tuple_arg_type = context.getType(expression);
- }
+ final PyExpression expression = PsiTreeUtil.getChildOfType(myTupleArg, PyExpression.class);
+ if (expression != null) {
+ tuple_arg_type = context.getType(expression);
}
int tuple_length;
boolean tuple_length_known;
@@ -223,8 +219,8 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
tuple_length_known = false;
}
int mapped_params_count = 0;
- while (cnt < parameters.length && cnt < positional_index && mapped_params_count < tuple_length) {
- PyParameter par = parameters[cnt];
+ while (cnt < parameters.size() && cnt < positional_index && mapped_params_count < tuple_length) {
+ PyParameter par = parameters.get(cnt);
if (par instanceof PySingleStarParameter) break;
PyNamedParameter n_par = par.getAsNamed();
if (slots.containsKey(n_par)) {
@@ -257,7 +253,7 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
if (
tuple_length_known && (mapped_params_count < tuple_length) || // not exhausted
mapped_params_count == 0 // unknown length must consume at least first param
- ) {
+ ) {
tuple_arg_not_exhausted = true;
}
}
@@ -336,7 +332,6 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
markArgument(arg, ArgFlag.IS_UNMAPPED);
}
}
-
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
index b9fa2e3be6c1..0a7addcb4f9c 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
@@ -3,6 +3,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -15,7 +16,10 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.*;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
-import com.jetbrains.python.*;
+import com.jetbrains.python.PyElementTypes;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.PyTokenTypes;
+import com.jetbrains.python.PythonDialectsTokenSetProvider;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
@@ -53,22 +57,16 @@ public class PyClassImpl extends PyPresentableElementImpl implement
private volatile Map myPropertyCache;
- private class CachedAncestorsProvider implements CachedValueProvider> {
- @Nullable private TypeEvalContext myCachedContext;
-
+ private class CachedAncestorsProvider implements ParameterizedCachedValueProvider, TypeEvalContext> {
@Nullable
@Override
- public Result> compute() {
- final TypeEvalContext context = myCachedContext != null ? myCachedContext : TypeEvalContext.codeInsightFallback();
+ public CachedValueProvider.Result> compute(@NotNull TypeEvalContext context) {
final List ancestorTypes = isNewStyleClass() ? getMROAncestorTypes(context) : getOldStyleAncestorTypes(context);
- return Result.create(ancestorTypes, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
- }
-
- private void setTypeEvalContext(@Nullable TypeEvalContext cachedContext) {
- myCachedContext = cachedContext;
+ return CachedValueProvider.Result.create(ancestorTypes, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
}
+ private final Key, TypeEvalContext>> myCachedValueKey = Key.create("cached ancestors");
private final CachedAncestorsProvider myCachedAncestorsProvider = new CachedAncestorsProvider();
@Override
@@ -1098,14 +1096,9 @@ public class PyClassImpl extends PyPresentableElementImpl implement
@NotNull
@Override
public List getAncestorTypes(@NotNull TypeEvalContext context) {
- myCachedAncestorsProvider.setTypeEvalContext(context);
- try {
- // TODO: Return different cached copies depending on the type eval context parameters
- return CachedValuesManager.getManager(getProject()).getCachedValue(this, myCachedAncestorsProvider);
- }
- finally {
- myCachedAncestorsProvider.setTypeEvalContext(null);
- }
+ // TODO: Return different cached copies depending on the type eval context parameters
+ final CachedValuesManager manager = CachedValuesManager.getManager(getProject());
+ return manager.getParameterizedCachedValue(this, myCachedValueKey, myCachedAncestorsProvider, false, context);
}
@NotNull
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
index 81392e382669..310641880a04 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
@@ -342,6 +342,12 @@ public class PyFunctionImpl extends PyPresentableElementImpl imp
@Override
public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
+ for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
+ final PyType type = provider.getCallableType(this, context);
+ if (type != null) {
+ return type;
+ }
+ }
final PyFunctionType type = new PyFunctionType(this);
if (getDecoratorList() != null) {
return PyUnionType.createWeakType(type);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
index fc31ce2e21a3..9bf0de63425e 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
@@ -1,6 +1,7 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
@@ -24,6 +25,12 @@ public class PyLambdaExpressionImpl extends PyElementImpl implements PyLambdaExp
}
public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
+ for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
+ final PyType type = provider.getCallableType(this, context);
+ if (type != null) {
+ return type;
+ }
+ }
return new PyFunctionType(this);
}
diff --git a/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java b/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java
index c97a4deffba3..e018a99d541f 100644
--- a/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java
+++ b/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java
@@ -11,6 +11,7 @@ import com.jetbrains.python.psi.impl.PyKeywordArgumentProvider;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
+import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -50,7 +51,11 @@ public class KeywordArgumentCompletionUtil {
visited.add(def);
boolean needSelf = def.getContainingClass() != null && def.getModifier() != PyFunction.Modifier.STATICMETHOD;
final KwArgParameterCollector collector = new KwArgParameterCollector(needSelf, ret);
- def.getParameterList().acceptChildren(collector);
+ final TypeEvalContext context = TypeEvalContext.userInitiated(def.getContainingFile());
+ final List parameters = PyUtil.getParameters(def, context);
+ for (PyParameter parameter : parameters) {
+ parameter.accept(collector);
+ }
if (collector.hasKwArgs()) {
for (PyKeywordArgumentProvider provider : Extensions.getExtensions(PyKeywordArgumentProvider.EP_NAME)) {
final List arguments = provider.getKeywordArguments(def, callExpr);
diff --git a/python/src/com/jetbrains/python/psi/types/PyCallableParameterImpl.java b/python/src/com/jetbrains/python/psi/types/PyCallableParameterImpl.java
new file mode 100644
index 000000000000..27dbf1bf8d35
--- /dev/null
+++ b/python/src/com/jetbrains/python/psi/types/PyCallableParameterImpl.java
@@ -0,0 +1,57 @@
+package com.jetbrains.python.psi.types;
+
+import com.jetbrains.python.psi.PyNamedParameter;
+import com.jetbrains.python.psi.PyParameter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author vlan
+ */
+public class PyCallableParameterImpl implements PyCallableParameter {
+ @Nullable private final String myName;
+ @Nullable private final PyType myType;
+ @Nullable private final PyParameter myElement;
+
+ public PyCallableParameterImpl(@Nullable String name, @Nullable PyType type) {
+ myName = name;
+ myType = type;
+ myElement = null;
+ }
+
+ public PyCallableParameterImpl(@Nullable PyParameter element) {
+ myName = null;
+ myType = null;
+ myElement = element;
+ }
+
+ @Nullable
+ @Override
+ public String getName() {
+ if (myName != null) {
+ return myName;
+ }
+ else if (myElement != null) {
+ return myElement.getName();
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PyType getType(@NotNull TypeEvalContext context) {
+ if (myType != null) {
+ return myType;
+ }
+ else if (myElement instanceof PyNamedParameter) {
+ return context.getType((PyNamedParameter)myElement);
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PyParameter getParameter() {
+ return myElement;
+ }
+}
diff --git a/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java
index 8b3cb754b437..c1483a2b446b 100644
--- a/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java
+++ b/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.ProcessingContext;
@@ -19,10 +18,10 @@ import java.util.List;
* @author vlan
*/
public class PyCallableTypeImpl implements PyCallableType {
- @Nullable private final List> myParameters;
+ @Nullable private final List myParameters;
@Nullable private final PyType myReturnType;
- public PyCallableTypeImpl(@Nullable List> parameters, @Nullable PyType returnType) {
+ public PyCallableTypeImpl(@Nullable List parameters, @Nullable PyType returnType) {
myParameters = parameters;
myReturnType = returnType;
}
@@ -40,7 +39,7 @@ public class PyCallableTypeImpl implements PyCallableType {
@Nullable
@Override
- public List> getParameters(@NotNull TypeEvalContext context) {
+ public List getParameters(@NotNull TypeEvalContext context) {
return myParameters;
}
@@ -61,16 +60,17 @@ public class PyCallableTypeImpl implements PyCallableType {
@Nullable
@Override
public String getName() {
+ final TypeEvalContext context = TypeEvalContext.codeInsightFallback();
return String.format("(%s) -> %s",
myParameters != null ?
StringUtil.join(myParameters,
- new Function, String>() {
+ new Function() {
@Override
- public String fun(Pair param) {
+ public String fun(PyCallableParameter param) {
if (param != null) {
final StringBuilder builder = new StringBuilder();
- final String name = param.getFirst();
- final PyType type = param.getSecond();
+ final String name = param.getName();
+ final PyType type = param.getType(context);
if (name != null) {
builder.append(name);
if (type != null) {
diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
index 446aba417165..046bb1fac020 100644
--- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
+++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
@@ -135,7 +135,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
@NotNull PyResolveContext resolveContext,
boolean inherited) {
final TypeEvalContext context = resolveContext.getTypeEvalContext();
- PsiElement classMember = resolveByOverridingMembersProviders(this, name); //overriding members provers have priority to normal resolve
+ PsiElement classMember = resolveByOverridingMembersProviders(this, name, location); //overriding members provers have priority to normal resolve
if (classMember != null) {
return ResolveResultList.to(classMember);
}
@@ -211,7 +211,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
if (inherited) {
- classMember = resolveByMembersProviders(this, name); //ask providers after real class introspection as providers have less priority
+ classMember = resolveByMembersProviders(this, name, location); //ask providers after real class introspection as providers have less priority
}
if (classMember != null) {
@@ -223,7 +223,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
if (type instanceof PyClassType) {
final PyClass pyClass = ((PyClassType)type).getPyClass();
if (pyClass != null) {
- PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name);
+ PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name, location);
if (superMember != null) {
return ResolveResultList.to(superMember);
@@ -279,7 +279,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
@Nullable
@Override
- public List> getParameters(@NotNull TypeEvalContext context) {
+ public List getParameters(@NotNull TypeEvalContext context) {
return null;
}
@@ -296,9 +296,9 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
@Nullable
- private static PsiElement resolveByMembersProviders(PyClassType aClass, String name) {
+ private static PsiElement resolveByMembersProviders(PyClassType aClass, String name, @Nullable PsiElement location) {
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
- final PsiElement resolveResult = provider.resolveMember(aClass, name);
+ final PsiElement resolveResult = provider.resolveMember(aClass, name, location);
if (resolveResult != null) return resolveResult;
}
@@ -306,10 +306,10 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
@Nullable
- private static PsiElement resolveByOverridingMembersProviders(PyClassType aClass, String name) {
+ private static PsiElement resolveByOverridingMembersProviders(PyClassType aClass, String name, @Nullable PsiElement location) {
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
if (provider instanceof PyOverridingClassMembersProvider) {
- final PsiElement resolveResult = provider.resolveMember(aClass, name);
+ final PsiElement resolveResult = provider.resolveMember(aClass, name, location);
if (resolveResult != null) return resolveResult;
}
}
@@ -361,7 +361,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
// from providers
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
- for (PyDynamicMember member : provider.getMembers(this)) {
+ for (PyDynamicMember member : provider.getMembers(this, location)) {
final String name = member.getName();
if (!namesAlready.contains(name)) {
LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(name).withIcon(member.getIcon()).withTypeText(getName());
diff --git a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
index 20072ba86284..43ef7ddcc3f7 100644
--- a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
-import com.intellij.openapi.util.Pair;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
@@ -37,13 +36,10 @@ public class PyFunctionType implements PyCallableType {
@Nullable
@Override
- public List> getParameters(@NotNull TypeEvalContext context) {
- final List> result = new ArrayList>();
+ public List getParameters(@NotNull TypeEvalContext context) {
+ final List result = new ArrayList();
for (PyParameter parameter : myCallable.getParameterList().getParameters()) {
- if (parameter instanceof PyNamedParameter) {
- final PyNamedParameter namedParameter = (PyNamedParameter)parameter;
- result.add(Pair.create(getParameterName(namedParameter), context.getType(namedParameter)));
- }
+ result.add(new PyCallableParameterImpl(parameter));
}
return result;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
index 4c3660dcbdb3..9cd26ffba127 100644
--- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
+++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
-import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
@@ -145,15 +144,15 @@ public class PyTypeChecker {
final PyCallableType expectedCallable = (PyCallableType)expected;
final PyCallableType actualCallable = (PyCallableType)actual;
if (expectedCallable.isCallable() && actualCallable.isCallable()) {
- final List> expectedParameters = expectedCallable.getParameters(context);
- final List> actualParameters = actualCallable.getParameters(context);
+ final List expectedParameters = expectedCallable.getParameters(context);
+ final List actualParameters = actualCallable.getParameters(context);
if (expectedParameters != null && actualParameters != null) {
final int size = Math.min(expectedParameters.size(), actualParameters.size());
for (int i = 0; i < size; i++) {
- final Pair expectedParam = expectedParameters.get(i);
- final Pair actualParam = actualParameters.get(i);
+ final PyCallableParameter expectedParam = expectedParameters.get(i);
+ final PyCallableParameter actualParam = actualParameters.get(i);
// TODO: Check named and star params, not only positional ones
- if (!match(expectedParam.getSecond(), actualParam.getSecond(), context, substitutions, recursive)) {
+ if (!match(expectedParam.getType(context), actualParam.getType(context), context, substitutions, recursive)) {
return false;
}
}
@@ -234,11 +233,11 @@ public class PyTypeChecker {
}
else if (type instanceof PyCallableType) {
final PyCallableType callable = (PyCallableType)type;
- final List> parameters = callable.getParameters(context);
+ final List parameters = callable.getParameters(context);
if (parameters != null) {
- for (Pair parameter : parameters) {
+ for (PyCallableParameter parameter : parameters) {
if (parameter != null) {
- collectGenerics(parameter.getSecond(), context, collected, visited);
+ collectGenerics(parameter.getType(context), context, collected, visited);
}
}
}
@@ -280,12 +279,16 @@ public class PyTypeChecker {
}
else if (type instanceof PyCallableType) {
final PyCallableType callable = (PyCallableType)type;
- List> substParams = null;
- final List> parameters = callable.getParameters(context);
+ List substParams = null;
+ final List parameters = callable.getParameters(context);
if (parameters != null) {
- substParams = new ArrayList>();
- for (Pair parameter : parameters) {
- substParams.add(Pair.create(parameter.getFirst(), substitute(parameter.getSecond(), substitutions, context)));
+ substParams = new ArrayList();
+ for (PyCallableParameter parameter : parameters) {
+ final PyType substType = substitute(parameter.getType(context), substitutions, context);
+ final PyCallableParameter subst = parameter.getParameter() != null ?
+ new PyCallableParameterImpl(parameter.getParameter()) :
+ new PyCallableParameterImpl(parameter.getName(), substType);
+ substParams.add(subst);
}
}
final PyType substResult = substitute(callable.getCallType(context, null), substitutions, context);
diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeParser.java b/python/src/com/jetbrains/python/psi/types/PyTypeParser.java
index 7aab2400b333..7150ab1413ae 100644
--- a/python/src/com/jetbrains/python/psi/types/PyTypeParser.java
+++ b/python/src/com/jetbrains/python/psi/types/PyTypeParser.java
@@ -230,7 +230,7 @@ public class PyTypeParser {
new Function>, ParseResult>, ParseResult>() {
@Override
public ParseResult fun(Pair>, ParseResult> value) {
- final List> parameters = new ArrayList>();
+ final List parameters = new ArrayList();
final ParseResult returnResult = value.getSecond();
ParseResult result;
final Pair> firstPair = value.getFirst();
@@ -238,10 +238,10 @@ public class PyTypeParser {
final ParseResult first = firstPair.getFirst();
final List second = firstPair.getSecond();
result = first;
- parameters.add(Pair.create(null, first.getType()));
+ parameters.add(new PyCallableParameterImpl((String)null, first.getType()));
for (ParseResult r : second) {
result = result.merge(r);
- parameters.add(Pair.create(null, r.getType()));
+ parameters.add(new PyCallableParameterImpl((String)null, r.getType()));
}
result = result.merge(returnResult);
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyUnionType.java b/python/src/com/jetbrains/python/psi/types/PyUnionType.java
index c69beca25529..ef6688bc5c61 100644
--- a/python/src/com/jetbrains/python/psi/types/PyUnionType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyUnionType.java
@@ -29,17 +29,17 @@ public class PyUnionType implements PyType {
@NotNull AccessDirection direction,
@NotNull PyResolveContext resolveContext) {
SmartList ret = new SmartList();
- boolean all_nulls = true;
+ boolean allNulls = true;
for (PyType member : myMembers) {
if (member != null) {
- List extends RatedResolveResult> result = member.resolveMember(name, null, direction, resolveContext);
+ List extends RatedResolveResult> result = member.resolveMember(name, location, direction, resolveContext);
if (result != null) {
- all_nulls = false;
+ allNulls = false;
ret.addAll(result);
}
}
}
- return all_nulls ? null : ret;
+ return allNulls ? null : ret;
}
public Object[] getCompletionVariants(String completionPrefix, PyExpression location, ProcessingContext context) {
diff --git a/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java b/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java
index c8c571764d5f..f7420b849b18 100644
--- a/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java
+++ b/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java
@@ -35,46 +35,12 @@ public abstract class FunctionalParserBase implements FunctionalParser FunctionalParser, T> token(@NotNull final T type, @Nullable final String text) {
- return new FunctionalParserBase, T>() {
- @NotNull
- @Override
- public Pair, State> parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- final int pos = state.getPos();
- if (pos >= tokens.size()) {
- throw new ParserException("No tokens left", state);
- }
- final Token token = tokens.get(pos);
- if (token.getType().equals(type) && (text == null || token.getText().equals(text))) {
- final int newPos = pos + 1;
- final State newState = new State(state, newPos, Math.max(newPos, state.getMax()));
- return Pair.create(token, newState);
- }
- final String expected = text != null ? String.format("Token(<%s>, \"%s\")", type, text) : String.format("Token(<%s>)", type);
- throw new ParserException(String.format("Expected %s, found %s", expected, token), state);
- }
- };
+ return new TokenParser(type, text);
}
@NotNull
public static FunctionalParser, T> many(@NotNull final FunctionalParser parser) {
- return new FunctionalParserBase, T>() {
- @NotNull
- @Override
- public Pair, State> parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- final List list = new ArrayList();
- try {
- //noinspection InfiniteLoopStatement
- while (true) {
- final Pair result = parser.parse(tokens, state);
- state = result.getSecond();
- list.add(result.getFirst());
- }
- }
- catch (ParserException e) {
- return Pair.create(list, new State(state, state.getPos(), e.getState().getMax()));
- }
- }
- };
+ return new ManyParser(parser);
}
@NotNull
@@ -98,45 +64,13 @@ public abstract class FunctionalParserBase implements FunctionalParser cached() {
- final FunctionalParser thisParser = this;
- return new FunctionalParserBase() {
- private Object myKey = null;
- private Map>> myCache = new HashMap>>();
-
- @NotNull
- @Override
- public Pair parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- if (myKey != state.getKey()) {
- myKey = state.getKey();
- myCache.clear();
- }
- final SoftReference> ref = myCache.get(state.getPos());
- if (ref != null) {
- final Pair cached = ref.get();
- if (cached != null) {
- return cached;
- }
- }
- final Pair result = thisParser.parse(tokens, state);
- myCache.put(state.getPos(), new SoftReference>(result));
- return result;
- }
- };
+ return new CachedParser(this);
}
@NotNull
@Override
public FunctionalParser, T> then(@NotNull final FunctionalParser parser) {
- final FunctionalParser thisParser = this;
- return new FunctionalParserBase, T>() {
- @NotNull
- @Override
- public Pair, State> parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- final Pair result1 = thisParser.parse(tokens, state);
- final Pair result2 = parser.parse(tokens, result1.getSecond());
- return Pair.create(Pair.create(result1.getFirst(), result2.getFirst()), result2.getSecond());
- }
- };
+ return new ThenParser(this, parser);
}
@NotNull
@@ -154,82 +88,227 @@ public abstract class FunctionalParserBase implements FunctionalParser or(@NotNull final FunctionalParser parser) {
- final FunctionalParserBase thisParser = this;
- return new FunctionalParserBase() {
- @NotNull
- @Override
- public Pair parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- try {
- return thisParser.parse(tokens, state);
- }
- catch (ParserException e) {
- return parser.parse(tokens, new State(state, state.getPos(), e.getState().getMax()));
- }
- }
- };
+ return new OrParser(this, parser);
}
@NotNull
@Override
public FunctionalParser map(@NotNull final Function f) {
- final FunctionalParserBase thisParser = this;
- return new FunctionalParserBase() {
- @NotNull
- @Override
- public Pair parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- final Pair result = thisParser.parse(tokens, state);
- return Pair.create(f.fun(result.getFirst()), result.getSecond());
- }
- };
+ return new MapParser(this, f);
}
@NotNull
private static FunctionalParser first(@NotNull final FunctionalParser, T> parser) {
- return new FunctionalParserBase() {
- @NotNull
- @Override
- public Pair parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- final Pair, State> result = parser.parse(tokens, state);
- return Pair.create(result.getFirst().getFirst(), result.getSecond());
- }
- };
+ return new FirstParser(parser);
}
@NotNull
private static FunctionalParser second(@NotNull final FunctionalParser, T> parser) {
- return new FunctionalParserBase() {
- @NotNull
- @Override
- public Pair parse(@NotNull List> tokens, @NotNull State state) throws ParserException {
- final Pair, State> result = parser.parse(tokens, state);
- return Pair.create(result.getFirst().getSecond(), result.getSecond());
- }
- };
+ return new SecondParser(parser);
}
@NotNull
private static FunctionalParser