diff --git a/python/build/plugin-list.txt b/python/build/plugin-list.txt
index f2b7f745fa40..ba236d36d374 100644
--- a/python/build/plugin-list.txt
+++ b/python/build/plugin-list.txt
@@ -49,3 +49,4 @@ pycharm-flask
pycharm-numpy
textmate
restClient
+puppet
diff --git a/python/build/pycharm_build.gant b/python/build/pycharm_build.gant
index e79ce5e2e7ca..e7800220bb48 100644
--- a/python/build/pycharm_build.gant
+++ b/python/build/pycharm_build.gant
@@ -179,6 +179,7 @@ private layoutPlugins(layouts) {
include(name: "joni.jar")
}
}
+ layouts.layoutPlugin("puppet")
}
layouts.layoutPlugins()
diff --git a/python/rest/resources/META-INF/plugin.xml b/python/rest/resources/META-INF/plugin.xml
index d1aef1edb89a..656f4da72986 100644
--- a/python/rest/resources/META-INF/plugin.xml
+++ b/python/rest/resources/META-INF/plugin.xml
@@ -3,8 +3,8 @@
org.jetbrains.plugins.rest
This plugin enables support for reStructuredText files (*.rst)
JetBrains
- 122.SNAPSHOT
-
+ 126.SNAPSHOT
+
com.intellij.modules.lang
diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index e3f137ad6ddb..83a8d36a4e72 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -319,6 +319,7 @@
+
diff --git a/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestFinder.java b/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestFinder.java
index 1ec7b07be12e..88abc81cf1e4 100644
--- a/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestFinder.java
+++ b/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestFinder.java
@@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.regex.Pattern;
/**
* User : catherine
@@ -37,19 +36,18 @@ public class PyTestFinder implements TestFinder {
PyDocStringOwner source = findSourceElement(element);
if (source == null) return Collections.emptySet();
- String klassName = source.getName();
- Pattern pattern = Pattern.compile(".*" + klassName + ".*");
+ String sourceName = source.getName();
List> classesWithProximities = new ArrayList>();
if (source instanceof PyClass) {
Collection names = PyClassNameIndex.allKeys(element.getProject());
for (String eachName : names) {
- if (pattern.matcher(eachName).matches()) {
+ if (eachName.contains(sourceName)) {
for (PyClass eachClass : PyClassNameIndex.find(eachName, element.getProject(), GlobalSearchScope.projectScope(element.getProject()))) {
if (PythonUnitTestUtil.isTestCaseClass(eachClass) || PythonDocTestUtil.isDocTestClass(eachClass)) {
classesWithProximities.add(
- new Pair(eachClass, TestFinderHelper.calcTestNameProximity(klassName, eachName)));
+ new Pair(eachClass, TestFinderHelper.calcTestNameProximity(sourceName, eachName)));
}
}
}
@@ -58,12 +56,12 @@ public class PyTestFinder implements TestFinder {
else {
Collection names = PyFunctionNameIndex.allKeys(element.getProject());
for (String eachName : names) {
- if (pattern.matcher(eachName).matches()) {
+ if (eachName.contains(sourceName)) {
for (PyFunction eachFunction : PyFunctionNameIndex.find(eachName, element.getProject(), GlobalSearchScope.projectScope(element.getProject()))) {
if (PythonUnitTestUtil.isTestCaseFunction(
eachFunction) || PythonDocTestUtil.isDocTestFunction(eachFunction)) {
classesWithProximities.add(
- new Pair(eachFunction, TestFinderHelper.calcTestNameProximity(klassName, eachName)));
+ new Pair(eachFunction, TestFinderHelper.calcTestNameProximity(sourceName, eachName)));
}
}
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index b55852641e6d..4ddbb6ce2e16 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -41,10 +41,9 @@ import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IJSwingUtilities;
-import com.intellij.util.io.IOUtil;
import com.intellij.util.net.NetUtils;
import com.intellij.util.ui.UIUtil;
-import com.jetbrains.django.run.Runner;
+import com.jetbrains.django.run.ProcessRunner;
import com.intellij.remotesdk.RemoteSdkData;
import com.intellij.remotesdk.RemoteSshProcess;
import com.jetbrains.python.PythonHelpersLocator;
@@ -247,7 +246,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory remotePorts = getRemotePortsFromProcess(remoteProcess);
diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationEntryEditor.form b/python/src/com/jetbrains/python/documentation/PythonDocumentationEntryEditor.form
index 2525a95b1a82..efb3316f1401 100644
--- a/python/src/com/jetbrains/python/documentation/PythonDocumentationEntryEditor.form
+++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationEntryEditor.form
@@ -36,7 +36,7 @@
-
+
diff --git a/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java b/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java
index 150afaf00188..c492a80438f8 100644
--- a/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java
@@ -49,11 +49,7 @@ public class PyCallingNonCallableInspection extends PyInspection {
final PyExpression callee = decorator.getCallee();
checkCallable(decorator, callee, null);
if (decorator.hasArgumentList()) {
- final Callable callable = decorator.resolveCalleeFunction(resolveWithoutImplicits());
- if (callable != null) {
- final PyReferenceExpression callSite = callee instanceof PyReferenceExpression ? (PyReferenceExpression)callee : null;
- checkCallable(decorator, null, callable.getReturnType(myTypeEvalContext, callSite));
- }
+ checkCallable(decorator, decorator, null);
}
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyShadowingBuiltinsInspection.java b/python/src/com/jetbrains/python/inspections/PyShadowingBuiltinsInspection.java
new file mode 100644
index 000000000000..a4c6be4edb59
--- /dev/null
+++ b/python/src/com/jetbrains/python/inspections/PyShadowingBuiltinsInspection.java
@@ -0,0 +1,68 @@
+package com.jetbrains.python.inspections;
+
+import com.intellij.codeInspection.LocalInspectionToolSession;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiNameIdentifierOwner;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.impl.PyBuiltinCache;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Warns about shadowing built-in names.
+ *
+ * TODO: Merge into PyRedeclarationInspection and detect all shadowed names
+ *
+ * @author vlan
+ */
+public class PyShadowingBuiltinsInspection extends PyInspection {
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
+ boolean isOnTheFly,
+ @NotNull LocalInspectionToolSession session) {
+ return new Visitor(holder, session);
+ }
+
+ private static class Visitor extends PyInspectionVisitor {
+ public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
+ super(holder, session);
+ }
+
+ @Override
+ public void visitPyClass(@NotNull PyClass node) {
+ processElement(node);
+ }
+
+ @Override
+ public void visitPyFunction(@NotNull PyFunction node) {
+ if (node.getContainingClass() == null) {
+ processElement(node);
+ }
+ }
+
+ @Override
+ public void visitPyNamedParameter(@NotNull PyNamedParameter node) {
+ processElement(node);
+ }
+
+ @Override
+ public void visitPyTargetExpression(@NotNull PyTargetExpression node) {
+ processElement(node);
+ }
+
+ private void processElement(@NotNull PsiNameIdentifierOwner element) {
+ final String name = element.getName();
+ if (name != null) {
+ final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
+ final PsiElement builtin = builtinCache.getByName(name);
+ if (builtin != null && !PyUtil.inSameFile(builtin, element)) {
+ final PsiElement identifier = element.getNameIdentifier();
+ registerProblem(identifier != null ? identifier : element, "Shadows a built-in with the same name");
+ }
+ }
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
index 0da76c514fce..8be02c241f58 100644
--- a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
@@ -64,7 +64,7 @@ public class PyTypeCheckerInspection extends PyInspection {
final Map substitutions = new LinkedHashMap();
final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCallSite(callSite, myTypeEvalContext);
if (results != null) {
- substitutions.putAll(PyTypeChecker.collectCallGenerics(results.getFunction(), results.getReceiver(), myTypeEvalContext));
+ substitutions.putAll(PyTypeChecker.collectCallGenerics(results.getCallable(), results.getReceiver(), myTypeEvalContext));
for (Map.Entry entry : results.getArguments().entrySet()) {
final PyNamedParameter p = entry.getValue();
if (p.isPositionalContainer() || p.isKeywordContainer()) {
diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
index bb7993ec14fb..b12c5a4371fe 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
@@ -672,8 +672,8 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return true;
}
if (qtype instanceof PyFunctionType) {
- final PyFunction function = ((PyFunctionType)qtype).getFunction();
- if (function.getDecoratorList() != null) {
+ final Callable callable = ((PyFunctionType)qtype).getCallable();
+ if (callable instanceof PyFunction && ((PyFunction)callable).getDecoratorList() != null) {
return true;
}
}
diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
index 5f1bd463deb6..d14376d3707f 100644
--- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
+++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.remotesdk.RemoteCredentials;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.SystemProperties;
@@ -627,7 +628,7 @@ public class PyPackageManagerImpl extends PyPackageManager {
private String getHelperPath(String helper) {
String helperPath;
final SdkAdditionalData sdkData = mySdk.getSdkAdditionalData();
- if (sdkData instanceof RemoteSdkData) {
+ if (sdkData instanceof RemoteCredentials) {
final RemoteSdkData remoteSdkData = (RemoteSdkData)sdkData;
helperPath = new RemoteFile(remoteSdkData.getHelpersPath(),
helper).getPath();
@@ -644,7 +645,7 @@ public class PyPackageManagerImpl extends PyPackageManager {
@Nullable String workingDir)
throws PyExternalProcessException {
final SdkAdditionalData sdkData = mySdk.getSdkAdditionalData();
- if (sdkData instanceof RemoteSdkData) { //remote interpreter
+ if (sdkData instanceof RemoteCredentials) { //remote interpreter
final RemoteSdkData remoteSdkData = (RemoteSdkData)sdkData;
final PythonRemoteInterpreterManager manager = PythonRemoteInterpreterManager.getInstance();
if (manager != null) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java
index 86623f87eb9f..1b5e21df8f3a 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java
@@ -111,7 +111,7 @@ public class PyBinaryExpressionImpl extends PyElementImpl implements PyBinaryExp
public PyType getType(@NotNull TypeEvalContext context) {
final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCall(this, context);
if (results != null) {
- final PyType type = results.getFunction().getReturnType(context, this);
+ final PyType type = results.getCallable().getReturnType(context, this);
if (!PyTypeChecker.isUnknown(type) && !(type instanceof PyNoneType)) {
return type;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java
index 944a95fdaa67..11f4d999e220 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java
@@ -347,7 +347,7 @@ public class PyBuiltinCache {
return true;
}
else if (type instanceof PyFunctionType) {
- return ((PyFunctionType)type).getFunction().isValid();
+ return ((PyFunctionType)type).getCallable().isValid();
}
return true;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
index 9a4741a072b0..aea70b28e570 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
@@ -1,13 +1,17 @@
package com.jetbrains.python.psi.impl;
+import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.ResolveResult;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import com.jetbrains.python.psi.types.*;
+import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -337,4 +341,199 @@ public class PyCallExpressionHelper {
}
return null;
}
+
+ public static PyType getCallType(@NotNull PyCallExpression call, @NotNull TypeEvalContext context) {
+ if (!TypeEvalStack.mayEvaluate(call)) {
+ return null;
+ }
+ try {
+ PyExpression callee = call.getCallee();
+ if (callee instanceof PyReferenceExpression) {
+ // hardwired special cases
+ if (PyNames.SUPER.equals(callee.getText())) {
+ final Maybe superCallType = getSuperCallType(call, context);
+ if (superCallType.isDefined()) {
+ return superCallType.value();
+ }
+ }
+ if ("type".equals(callee.getText())) {
+ final PyExpression[] args = call.getArguments();
+ if (args.length == 1) {
+ final PyExpression arg = args[0];
+ final PyType argType = arg.getType(context);
+ if (argType instanceof PyClassType) {
+ final PyClassType classType = (PyClassType)argType;
+ if (!classType.isDefinition()) {
+ final PyClass cls = classType.getPyClass();
+ return cls.getType(context);
+ }
+ }
+ else {
+ return null;
+ }
+ }
+ }
+ // normal cases
+ final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
+ ResolveResult[] targets = ((PyReferenceExpression)callee).getReference(resolveContext).multiResolve(false);
+ if (targets.length > 0) {
+ PsiElement target = targets[0].getElement();
+ if (target == null) {
+ return null;
+ }
+ PyClass cls = null;
+ PyFunction init = null;
+ if (target instanceof PyClass) {
+ cls = (PyClass)target;
+ init = cls.findInitOrNew(true);
+ }
+ else if (target instanceof PyFunction) {
+ final PyFunction f = (PyFunction)target;
+ if (PyNames.INIT.equals(f.getName())) {
+ init = f;
+ cls = f.getContainingClass();
+ }
+ }
+ if (init != null) {
+ final PyType t = init.getReturnType(context, (PyReferenceExpression)callee);
+ if (cls != null) {
+ if (init.getContainingClass() != cls) {
+ if (t instanceof PyCollectionType) {
+ final PyType elementType = ((PyCollectionType)t).getElementType(context);
+ return new PyCollectionTypeImpl(cls, false, elementType);
+ }
+ return new PyClassTypeImpl(cls, false);
+ }
+ }
+ if (t != null && !(t instanceof PyNoneType)) {
+ if (t instanceof PyTypeReference) {
+ PyType resolved = ((PyTypeReference)t).resolve(callee, context);
+ if (resolved == null && cls != null) {
+ return PyUnionType.createWeakType(new PyClassTypeImpl(cls, false));
+ }
+ }
+ return t;
+ }
+ }
+ if (cls != null) {
+ return new PyClassTypeImpl(cls, false);
+ }
+ final PyType providedType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(target, context, call);
+ if (providedType != null) {
+ if (providedType instanceof PyClassType) {
+ return ((PyClassType)providedType).toInstance();
+ }
+ return providedType;
+ }
+ if (target instanceof Callable) {
+ final Callable callable = (Callable)target;
+ PyType returnType = callable.getReturnType(context, (PyReferenceExpression)callee);
+ if (returnType != null) {
+ return returnType;
+ }
+ return new PyReturnTypeReference(callable);
+ }
+ }
+ }
+ if (callee == null) {
+ return null;
+ }
+ else {
+ final PyType type = context.getType(callee);
+ if (type instanceof PyCallableType) {
+ final PyQualifiedExpression callSite = callee instanceof PyQualifiedExpression ? (PyQualifiedExpression)callee : null;
+ return ((PyCallableType) type).getCallType(context, callSite);
+ }
+ return null;
+ }
+ }
+ finally {
+ TypeEvalStack.evaluated(call);
+ }
+ }
+
+ @NotNull
+ private static Maybe getSuperCallType(@NotNull PyCallExpression call, TypeEvalContext context) {
+ final PyExpression callee = call.getCallee();
+ if (callee instanceof PyReferenceExpression) {
+ PsiElement must_be_super_init = ((PyReferenceExpression)callee).getReference().resolve();
+ if (must_be_super_init instanceof PyFunction) {
+ PyClass must_be_super = ((PyFunction)must_be_super_init).getContainingClass();
+ if (must_be_super == PyBuiltinCache.getInstance(call).getClass(PyNames.SUPER)) {
+ PyArgumentList arglist = call.getArgumentList();
+ if (arglist != null) {
+ final PyClass containingClass = PsiTreeUtil.getParentOfType(call, PyClass.class);
+ PyExpression[] args = arglist.getArguments();
+ if (args.length > 1) {
+ PyExpression first_arg = args[0];
+ if (first_arg instanceof PyReferenceExpression) {
+ final PyReferenceExpression firstArgRef = (PyReferenceExpression)first_arg;
+ final PyExpression qualifier = firstArgRef.getQualifier();
+ if (qualifier != null && PyNames.CLASS.equals(firstArgRef.getReferencedName())) {
+ final PsiReference qRef = qualifier.getReference();
+ final PsiElement element = qRef == null ? null : qRef.resolve();
+ if (element instanceof PyParameter) {
+ final PyParameterList parameterList = PsiTreeUtil.getParentOfType(element, PyParameterList.class);
+ if (parameterList != null && element == parameterList.getParameters()[0]) {
+ return new Maybe(getSuperCallTypeForArguments(context, containingClass, args[1]));
+ }
+ }
+ }
+ PsiElement possible_class = firstArgRef.getReference().resolve();
+ if (possible_class instanceof PyClass && ((PyClass)possible_class).isNewStyleClass()) {
+ final PyClass first_class = (PyClass)possible_class;
+ return new Maybe(getSuperCallTypeForArguments(context, first_class, args[1]));
+ }
+ }
+ }
+ else if (((PyFile)call.getContainingFile()).getLanguageLevel().isPy3K() && containingClass != null) {
+ return new Maybe(getSuperClassUnionType(containingClass));
+ }
+ }
+ }
+ }
+ }
+ return new Maybe();
+ }
+
+ @Nullable
+ private static PyType getSuperCallTypeForArguments(TypeEvalContext context, PyClass firstClass, PyExpression second_arg) {
+ // check 2nd argument, too; it should be an instance
+ if (second_arg != null) {
+ PyType second_type = context.getType(second_arg);
+ if (second_type instanceof PyClassType) {
+ // imitate isinstance(second_arg, possible_class)
+ PyClass secondClass = ((PyClassType)second_type).getPyClass();
+ if (CompletionUtil.getOriginalOrSelf(firstClass) == secondClass) {
+ return getSuperClassUnionType(firstClass);
+ }
+ if (secondClass.isSubclass(firstClass)) {
+ final Iterator iterator = firstClass.iterateAncestorClasses().iterator();
+ if (iterator.hasNext()) {
+ return new PyClassTypeImpl(iterator.next(), false); // super(Foo, self) has type of Foo, modulo __get__()
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyType getSuperClassUnionType(@NotNull PyClass pyClass) {
+ // TODO: this is closer to being correct than simply taking first superclass type but still not entirely correct;
+ // super can also delegate to sibling types
+ // TODO handle __mro__ here
+ final PyClass[] supers = pyClass.getSuperClasses();
+ if (supers.length > 0) {
+ if (supers.length == 1) {
+ return new PyClassTypeImpl(supers[0], false);
+ }
+ List superTypes = new ArrayList();
+ for (PyClass aSuper : supers) {
+ superTypes.add(new PyClassTypeImpl(aSuper, false));
+ }
+ return PyUnionType.union(superTypes);
+ }
+ return null;
+ }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java
index c67fdbb1efa6..b8d0fcb1cb0f 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java
@@ -1,23 +1,14 @@
package com.jetbrains.python.psi.impl;
-import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiReference;
-import com.intellij.psi.ResolveResult;
import com.intellij.psi.util.PsiTreeUtil;
-import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.types.*;
-import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
/**
* @author yole
*/
@@ -97,194 +88,6 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
}
public PyType getType(@NotNull TypeEvalContext context) {
- if (!TypeEvalStack.mayEvaluate(this)) {
- return null;
- }
- try {
- PyExpression callee = getCallee();
- if (callee instanceof PyReferenceExpression) {
- // hardwired special cases
- if (PyNames.SUPER.equals(callee.getText())) {
- final Maybe superCallType = getSuperCallType(callee, context);
- if (superCallType.isDefined()) {
- return superCallType.value();
- }
- }
- if ("type".equals(callee.getText())) {
- final PyExpression[] args = getArguments();
- if (args.length == 1) {
- final PyExpression arg = args[0];
- final PyType argType = arg.getType(context);
- if (argType instanceof PyClassType) {
- final PyClassType classType = (PyClassType)argType;
- if (!classType.isDefinition()) {
- final PyClass cls = classType.getPyClass();
- return cls.getType(context);
- }
- }
- else {
- return null;
- }
- }
- }
- // normal cases
- final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
- ResolveResult[] targets = ((PyReferenceExpression)callee).getReference(resolveContext).multiResolve(false);
- if (targets.length > 0) {
- PsiElement target = targets[0].getElement();
- if (target == null) {
- return null;
- }
- PyClass cls = null;
- PyFunction init = null;
- if (target instanceof PyClass) {
- cls = (PyClass)target;
- init = cls.findInitOrNew(true);
- }
- else if (target instanceof PyFunction) {
- final PyFunction f = (PyFunction)target;
- if (PyNames.INIT.equals(f.getName())) {
- init = f;
- cls = f.getContainingClass();
- }
- }
- if (init != null) {
- final PyType t = init.getReturnType(context, (PyReferenceExpression)callee);
- if (cls != null) {
- if (init.getContainingClass() != cls) {
- if (t instanceof PyCollectionType) {
- final PyType elementType = ((PyCollectionType)t).getElementType(context);
- return new PyCollectionTypeImpl(cls, false, elementType);
- }
- return new PyClassTypeImpl(cls, false);
- }
- }
- if (t != null && !(t instanceof PyNoneType)) {
- if (t instanceof PyTypeReference) {
- PyType resolved = ((PyTypeReference)t).resolve(callee, context);
- if (resolved == null && cls != null) {
- return PyUnionType.createWeakType(new PyClassTypeImpl(cls, false));
- }
- }
- return t;
- }
- }
- if (cls != null) {
- return new PyClassTypeImpl(cls, false);
- }
- final PyType providedType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(target, context, this);
- if (providedType != null) {
- if (providedType instanceof PyClassType) {
- return ((PyClassType)providedType).toInstance();
- }
- return providedType;
- }
- if (target instanceof Callable) {
- final Callable callable = (Callable)target;
- PyType returnType = callable.getReturnType(context, (PyReferenceExpression)callee);
- if (returnType != null) {
- return returnType;
- }
- return new PyReturnTypeReference(callable);
- }
- }
- }
- if (callee == null) {
- return null;
- }
- else {
- final PyType type = context.getType(callee);
- if (type instanceof PyCallableType) {
- final PyQualifiedExpression callSite = callee instanceof PyQualifiedExpression ? (PyQualifiedExpression)callee : null;
- return ((PyCallableType) type).getCallType(context, callSite);
- }
- return null;
- }
- }
- finally {
- TypeEvalStack.evaluated(this);
- }
- }
-
- @NotNull
- private Maybe getSuperCallType(PyExpression callee, TypeEvalContext context) {
- PsiElement must_be_super_init = ((PyReferenceExpression)callee).getReference().resolve();
- if (must_be_super_init instanceof PyFunction) {
- PyClass must_be_super = ((PyFunction)must_be_super_init).getContainingClass();
- if (must_be_super == PyBuiltinCache.getInstance(this).getClass(PyNames.SUPER)) {
- PyArgumentList arglist = getArgumentList();
- if (arglist != null) {
- final PyClass containingClass = PsiTreeUtil.getParentOfType(this, PyClass.class);
- PyExpression[] args = arglist.getArguments();
- if (args.length > 1) {
- PyExpression first_arg = args[0];
- if (first_arg instanceof PyReferenceExpression) {
- final PyReferenceExpression firstArgRef = (PyReferenceExpression)first_arg;
- final PyExpression qualifier = firstArgRef.getQualifier();
- if (qualifier != null && PyNames.CLASS.equals(firstArgRef.getReferencedName())) {
- final PsiReference qRef = qualifier.getReference();
- final PsiElement element = qRef == null ? null : qRef.resolve();
- if (element instanceof PyParameter) {
- final PyParameterList parameterList = PsiTreeUtil.getParentOfType(element, PyParameterList.class);
- if (parameterList != null && element == parameterList.getParameters()[0]) {
- return new Maybe(getSuperCallType(context, containingClass, args[1]));
- }
- }
- }
- PsiElement possible_class = firstArgRef.getReference().resolve();
- if (possible_class instanceof PyClass && ((PyClass)possible_class).isNewStyleClass()) {
- final PyClass first_class = (PyClass)possible_class;
- return new Maybe(getSuperCallType(context, first_class, args[1]));
- }
- }
- }
- else if (((PyFile)getContainingFile()).getLanguageLevel().isPy3K() && containingClass != null) {
- return new Maybe(getSuperClassUnionType(containingClass));
- }
- }
- }
- }
- return new Maybe();
- }
-
- @Nullable
- private static PyType getSuperCallType(TypeEvalContext context, PyClass firstClass, PyExpression second_arg) {
- // check 2nd argument, too; it should be an instance
- if (second_arg != null) {
- PyType second_type = context.getType(second_arg);
- if (second_type instanceof PyClassType) {
- // imitate isinstance(second_arg, possible_class)
- PyClass secondClass = ((PyClassType)second_type).getPyClass();
- if (CompletionUtil.getOriginalOrSelf(firstClass) == secondClass) {
- return getSuperClassUnionType(firstClass);
- }
- if (secondClass.isSubclass(firstClass)) {
- final Iterator iterator = firstClass.iterateAncestorClasses().iterator();
- if (iterator.hasNext()) {
- return new PyClassTypeImpl(iterator.next(), false); // super(Foo, self) has type of Foo, modulo __get__()
- }
- }
- }
- }
- return null;
- }
-
- @Nullable
- private static PyType getSuperClassUnionType(@NotNull PyClass pyClass) {
- // TODO: this is closer to being correct than simply taking first superclass type but still not entirely correct;
- // super can also delegate to sibling types
- // TODO handle __mro__ here
- final PyClass[] supers = pyClass.getSuperClasses();
- if (supers.length > 0) {
- if (supers.length == 1) {
- return new PyClassTypeImpl(supers[0], false);
- }
- List superTypes = new ArrayList();
- for (PyClass aSuper : supers) {
- superTypes.add(new PyClassTypeImpl(aSuper, false));
- }
- return PyUnionType.union(superTypes);
- }
- return null;
+ return PyCallExpressionHelper.getCallType(this, context);
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
index f26a3e48d8a7..b0c5d37004bd 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
@@ -166,8 +166,7 @@ public class PyDecoratorImpl extends StubBasedPsiElementBase im
}
}
- // TODO: create a custom version of public PyType getType()
public PyType getType(@NotNull TypeEvalContext context) {
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return PyCallExpressionHelper.getCallType(this, context);
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
index ee02c122cd01..27380a9928fd 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
@@ -5,6 +5,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.psi.*;
+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;
@@ -23,7 +24,7 @@ public class PyLambdaExpressionImpl extends PyElementImpl implements PyLambdaExp
}
public PyType getType(@NotNull TypeEvalContext context) {
- return null;
+ return new PyFunctionType(this);
}
@NotNull
diff --git a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
index 4db67f09ecf7..e66c3a7069bf 100644
--- a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
@@ -1,10 +1,7 @@
package com.jetbrains.python.psi.types;
import com.intellij.util.ProcessingContext;
-import com.jetbrains.python.psi.AccessDirection;
-import com.jetbrains.python.psi.PyExpression;
-import com.jetbrains.python.psi.PyFunction;
-import com.jetbrains.python.psi.PyQualifiedExpression;
+import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import org.jetbrains.annotations.NotNull;
@@ -14,23 +11,21 @@ import java.util.Collections;
import java.util.List;
/**
- * Type of a particular function that is represented as a {@link PyFunction} in the PSI tree.
- *
- * TODO: Maybe this class should extend PyClassType and have a Python mock class for type 'function' in the __builtins__.
+ * Type of a particular function that is represented as a {@link Callable} in the PSI tree.
*
* @author vlan
*/
public class PyFunctionType implements PyCallableType {
- @NotNull private final PyFunction myFunction;
+ @NotNull private final Callable myCallable;
- public PyFunctionType(@NotNull PyFunction function) {
- myFunction = function;
+ public PyFunctionType(@NotNull Callable callable) {
+ myCallable = callable;
}
@Nullable
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
- return myFunction.getReturnType(context, callSite);
+ return myCallable.getReturnType(context, callSite);
}
@Override
@@ -61,7 +56,7 @@ public class PyFunctionType implements PyCallableType {
}
@NotNull
- public PyFunction getFunction() {
- return myFunction;
+ public Callable getCallable() {
+ return myCallable;
}
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
index 64bc291843d6..1ca378328788 100644
--- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
+++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
@@ -269,7 +269,7 @@ public class PyTypeChecker {
}
@NotNull
- public static Map collectCallGenerics(@NotNull PyFunction function, @Nullable PyExpression receiver,
+ public static Map collectCallGenerics(@NotNull Callable callable, @Nullable PyExpression receiver,
@NotNull TypeEvalContext context) {
final Map substitutions = new LinkedHashMap();
// Collect generic params of object type
@@ -279,7 +279,7 @@ public class PyTypeChecker {
for (PyGenericType t : generics) {
substitutions.put(t, t);
}
- final PyClass cls = function.getContainingClass();
+ final PyClass cls = (callable instanceof PyFunction) ? ((PyFunction)callable).getContainingClass() : null;
if (cls != null) {
final PyFunction init = cls.findInitOrNew(true);
// Unify generics in constructor
@@ -346,17 +346,17 @@ public class PyTypeChecker {
if (!(type instanceof PyFunctionType)) {
return null;
}
- final PyFunction function = ((PyFunctionType)type).getFunction();
+ final Callable callable = ((PyFunctionType)type).getCallable();
final boolean isRight = PyNames.isRightOperatorName(typedElement.getName());
final PyExpression arg = isRight ? expr.getLeftExpression() : expr.getRightExpression();
final PyExpression receiver = isRight ? expr.getRightExpression() : expr.getLeftExpression();
- final PyParameter[] parameters = function.getParameterList().getParameters();
+ final PyParameter[] parameters = callable.getParameterList().getParameters();
if (parameters.length >= 2) {
final PyNamedParameter param = parameters[1].getAsNamed();
if (arg != null && param != null) {
final Map arguments = new LinkedHashMap();
arguments.put(arg, param);
- final AnalyzeCallResults results = new AnalyzeCallResults(function, receiver, arguments);
+ final AnalyzeCallResults results = new AnalyzeCallResults(callable, receiver, arguments);
if (firstResults == null) {
firstResults = results;
}
@@ -382,8 +382,8 @@ public class PyTypeChecker {
if (resolved instanceof PyTypedElement) {
final PyType type = ((PyTypedElement)resolved).getType(context);
if (type instanceof PyFunctionType) {
- final PyFunction function = ((PyFunctionType)type).getFunction();
- final PyParameter[] parameters = function.getParameterList().getParameters();
+ final Callable callable = ((PyFunctionType)type).getCallable();
+ final PyParameter[] parameters = callable.getParameterList().getParameters();
if (parameters.length == 2) {
final PyNamedParameter param = parameters[1].getAsNamed();
if (param != null) {
@@ -391,7 +391,7 @@ public class PyTypeChecker {
final PyExpression arg = expr.getIndexExpression();
if (arg != null) {
arguments.put(arg, param);
- return new AnalyzeCallResults(function, expr.getOperand(), arguments);
+ return new AnalyzeCallResults(callable, expr.getOperand(), arguments);
}
}
}
@@ -423,20 +423,20 @@ public class PyTypeChecker {
}
public static class AnalyzeCallResults {
- @NotNull private final PyFunction myFunction;
+ @NotNull private final Callable myCallable;
@Nullable private final PyExpression myReceiver;
@NotNull private final Map myArguments;
- public AnalyzeCallResults(@NotNull PyFunction function, @Nullable PyExpression receiver,
+ public AnalyzeCallResults(@NotNull Callable callable, @Nullable PyExpression receiver,
@NotNull Map arguments) {
- myFunction = function;
+ myCallable = callable;
myReceiver = receiver;
myArguments = arguments;
}
@NotNull
- public PyFunction getFunction() {
- return myFunction;
+ public Callable getCallable() {
+ return myCallable;
}
@Nullable
diff --git a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java
index da130ac8253f..a10ad75c16a6 100644
--- a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java
+++ b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java
@@ -11,6 +11,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remotesdk.RemoteCredentials;
import com.intellij.remotesdk.RemoteInterpreterException;
import com.intellij.remotesdk.RemoteSdkData;
import com.intellij.remotesdk.RemoteSshProcess;
diff --git a/python/src/com/jetbrains/python/sdk/PySdkUtil.java b/python/src/com/jetbrains/python/sdk/PySdkUtil.java
index 1b3b6a0d2101..e046208c72c6 100644
--- a/python/src/com/jetbrains/python/sdk/PySdkUtil.java
+++ b/python/src/com/jetbrains/python/sdk/PySdkUtil.java
@@ -6,9 +6,9 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.remotesdk.RemoteCredentials;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
-import com.intellij.remotesdk.RemoteSdkData;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -204,6 +204,6 @@ public class PySdkUtil {
}
public static boolean isRemote(@Nullable Sdk sdk) {
- return sdk != null && sdk.getSdkAdditionalData() instanceof RemoteSdkData;
+ return sdk != null && sdk.getSdkAdditionalData() instanceof RemoteCredentials;
}
}
diff --git a/python/testData/inspections/PyCallingNonCallableInspection/callableClassDecorator.py b/python/testData/inspections/PyCallingNonCallableInspection/callableClassDecorator.py
new file mode 100644
index 000000000000..86aca9f75301
--- /dev/null
+++ b/python/testData/inspections/PyCallingNonCallableInspection/callableClassDecorator.py
@@ -0,0 +1,15 @@
+class D(object):
+ def __init__(self, attribute, value):
+ pass
+
+ def __call__(self, cls):
+ return cls
+
+
+@D("value", 42)
+class C(object):
+ pass
+
+
+a = C()
+print(a.value)
\ No newline at end of file
diff --git a/python/testData/inspections/PyShadowingBuiltinsInspection/test.py b/python/testData/inspections/PyShadowingBuiltinsInspection/test.py
new file mode 100644
index 000000000000..ca25df4a2a04
--- /dev/null
+++ b/python/testData/inspections/PyShadowingBuiltinsInspection/test.py
@@ -0,0 +1,23 @@
+import float
+from foo import float
+from bar import baz as float
+
+def test1(x, len, file=None):
+ foo = 2
+ list = []
+ for int in range(10):
+ print(int)
+ range = []
+ return [int for int in range(10)]
+
+
+def list():
+ pass
+
+
+class list(object):
+ def foo(self):
+ pass
+
+ def list(self):
+ pass
diff --git a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
index e67beab8c461..04e875dd6ac5 100644
--- a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
@@ -306,4 +306,9 @@ public class PythonInspectionsTest extends PyTestCase {
public void testPyDecoratorInspection() { //PY-3348
doHighlightingTest(PyDecoratorInspection.class);
}
+
+ // PY-5807
+ public void testPyShadowingBuiltinsInspection() {
+ doHighlightingTest(PyShadowingBuiltinsInspection.class);
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyCallingNonCallableInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyCallingNonCallableInspectionTest.java
index 8f8441c2367c..3c2cf2a1cf5e 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyCallingNonCallableInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyCallingNonCallableInspectionTest.java
@@ -59,6 +59,11 @@ public class PyCallingNonCallableInspectionTest extends PyTestCase {
doTest();
}
+ // PY-5905
+ public void testCallableClassDecorator() {
+ doTest();
+ }
+
private void doTest() {
setLanguageLevel(LanguageLevel.PYTHON27);
try {