mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
allow each instance of PyCallableType to tell whether it's actually callable or not; distinguish class definition and class instance for Java class types; correctly treat Java constructors as callable (PY-4269)
This commit is contained in:
@@ -7,9 +7,11 @@ import com.intellij.psi.ResolveState;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.python.psi.AccessDirection;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
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.PyCallableType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -20,11 +22,13 @@ import java.util.List;
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyJavaClassType implements PyType {
|
||||
public class PyJavaClassType implements PyCallableType {
|
||||
private final PsiClass myClass;
|
||||
private final boolean myDefinition;
|
||||
|
||||
public PyJavaClassType(final PsiClass aClass) {
|
||||
public PyJavaClassType(final PsiClass aClass, boolean definition) {
|
||||
myClass = aClass;
|
||||
myDefinition = definition;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -68,4 +72,18 @@ public class PyJavaClassType implements PyType {
|
||||
@Override
|
||||
public void assertValid(String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
return myDefinition;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
|
||||
if (myDefinition) {
|
||||
return new PyJavaClassType(myClass, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
|
||||
@Nullable
|
||||
public PyType getReferenceType(@NotNull final PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor) {
|
||||
if (referenceTarget instanceof PsiClass) {
|
||||
return new PyJavaClassType((PsiClass) referenceTarget);
|
||||
return new PyJavaClassType((PsiClass) referenceTarget, true);
|
||||
}
|
||||
if (referenceTarget instanceof PsiPackage) {
|
||||
return new PyJavaPackageType((PsiPackage) referenceTarget, anchor == null ? null : ModuleUtil.findModuleForPsiElement(anchor));
|
||||
@@ -44,7 +44,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
|
||||
final PsiClassType classType = (PsiClassType)type;
|
||||
final PsiClass psiClass = classType.resolve();
|
||||
if (psiClass != null) {
|
||||
return new PyJavaClassType(psiClass);
|
||||
return new PyJavaClassType(psiClass, false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -67,7 +67,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
|
||||
if (paramType instanceof PsiClassType) {
|
||||
final PsiClass psiClass = ((PsiClassType)paramType).resolve();
|
||||
if (psiClass != null) {
|
||||
superMethodParameterTypes.add(new PyJavaClassType(psiClass));
|
||||
superMethodParameterTypes.add(new PyJavaClassType(psiClass, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.jetbrains.jython;
|
||||
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import com.jetbrains.python.PythonTestUtil;
|
||||
import com.jetbrains.python.inspections.PyCallingNonCallableInspection;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyJythonHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testCallableJavaClass() {
|
||||
myFixture.configureByFile("callableJavaClass.py");
|
||||
myFixture.enableInspections(PyCallingNonCallableInspection.class);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return PythonTestUtil.getTestDataPath() + "/highlighting/jython/";
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author yole
|
||||
*/
|
||||
public interface PyCallableType extends PyType {
|
||||
/**
|
||||
* Returns true if the type is callable.
|
||||
*/
|
||||
boolean isCallable();
|
||||
|
||||
/**
|
||||
* Returns the type which is the result of calling an instance of this type.
|
||||
*
|
||||
|
||||
@@ -220,6 +220,21 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
return PyBuiltinCache.getInstance(myClass).getObjectType("type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
if (isDefinition()) {
|
||||
return true;
|
||||
}
|
||||
if (PyTypeChecker.isMethodType(this)) {
|
||||
return true;
|
||||
}
|
||||
final PyClass cls = getPyClass();
|
||||
if (PyABCUtil.isSubclass(cls, PyNames.CALLABLE)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
|
||||
|
||||
@@ -22,6 +22,11 @@ public class PyFunctionType implements PyCallableType {
|
||||
myCallable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
|
||||
|
||||
@@ -427,19 +427,6 @@ public class PyTypeChecker {
|
||||
if (type == null || type instanceof PyTypeReference) {
|
||||
return null;
|
||||
}
|
||||
else if (type instanceof PyClassType) {
|
||||
final PyClassType classType = (PyClassType)type;
|
||||
if (classType.isDefinition()) {
|
||||
return true;
|
||||
}
|
||||
if (isMethodType(classType)) {
|
||||
return true;
|
||||
}
|
||||
final PyClass cls = classType.getPyClass();
|
||||
if (PyABCUtil.isSubclass(cls, PyNames.CALLABLE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyUnionType) {
|
||||
Boolean result = true;
|
||||
for (PyType member : ((PyUnionType)type).getMembers()) {
|
||||
@@ -454,12 +441,12 @@ public class PyTypeChecker {
|
||||
return result;
|
||||
}
|
||||
else if (type instanceof PyCallableType) {
|
||||
return true;
|
||||
return ((PyCallableType) type).isCallable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isMethodType(@NotNull PyClassType type) {
|
||||
public static boolean isMethodType(@NotNull PyClassType type) {
|
||||
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(type.getPyClass());
|
||||
return type.equals(builtinCache.getClassMethodType()) || type.equals(builtinCache.getStaticMethodType());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
from java.util import ArrayList
|
||||
l = ArrayList()
|
||||
Reference in New Issue
Block a user