mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
don't highlight Java methods as not callable (PY-9037)
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package com.jetbrains.python.psi.impl;
|
||||
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
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.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;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyJavaMethodType implements PyCallableType {
|
||||
private final PsiMethod myMethod;
|
||||
|
||||
public PyJavaMethodType(PsiMethod method) {
|
||||
myMethod = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
|
||||
return PyJavaTypeProvider.asPyType(myMethod.getReturnType());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getCompletionVariants(String completionPrefix, PyExpression location, ProcessingContext context) {
|
||||
return ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Java method(" + myMethod.getContainingClass().getQualifiedName() + "." + myMethod.getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin(TypeEvalContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertValid(String message) {
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
|
||||
}
|
||||
if (referenceTarget instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod) referenceTarget;
|
||||
return asPyType(method.getReturnType());
|
||||
return new PyJavaMethodType(method);
|
||||
}
|
||||
if (referenceTarget instanceof PsiField) {
|
||||
return asPyType(((PsiField)referenceTarget).getType());
|
||||
@@ -39,7 +39,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyType asPyType(PsiType type) {
|
||||
public static PyType asPyType(PsiType type) {
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClassType classType = (PsiClassType)type;
|
||||
final PsiClass psiClass = classType.resolve();
|
||||
|
||||
@@ -3,14 +3,23 @@ package com.jetbrains.jython;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import com.jetbrains.python.PythonTestUtil;
|
||||
import com.jetbrains.python.inspections.PyCallingNonCallableInspection;
|
||||
import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyJythonHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testCallableJavaClass() {
|
||||
myFixture.configureByFile("callableJavaClass.py");
|
||||
myFixture.enableInspections(PyCallingNonCallableInspection.class);
|
||||
doCallableTest();
|
||||
}
|
||||
|
||||
public void testCallableStaticMethod() {
|
||||
doCallableTest();
|
||||
}
|
||||
|
||||
private void doCallableTest() {
|
||||
myFixture.configureByFile(getTestName(false) + ".py");
|
||||
myFixture.enableInspections(PyCallingNonCallableInspection.class, PyUnresolvedReferencesInspection.class);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,16 +25,20 @@ import java.util.List;
|
||||
*/
|
||||
public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType {
|
||||
private final String myName;
|
||||
private final boolean myDefinition;
|
||||
|
||||
// 2 - namedtuple call itself
|
||||
// 1 - return type of namedtuple call, aka namedtuple class
|
||||
// 0 - namedtuple instance
|
||||
private final int myDefinitionLevel;
|
||||
private final PsiElement myDeclaration;
|
||||
private final List<String> myFields;
|
||||
|
||||
public PyNamedTupleType(PyClass tupleClass, PsiElement declaration, String name, List<String> fields, boolean isDefinition) {
|
||||
super(tupleClass, isDefinition);
|
||||
public PyNamedTupleType(PyClass tupleClass, PsiElement declaration, String name, List<String> fields, int definitionLevel) {
|
||||
super(tupleClass, definitionLevel > 0);
|
||||
myDeclaration = declaration;
|
||||
myFields = fields;
|
||||
myName = name;
|
||||
myDefinition = isDefinition;
|
||||
myDefinitionLevel = definitionLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,15 +79,15 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
|
||||
if (myDefinition) {
|
||||
return new PyNamedTupleType(myClass, myDeclaration, myName, myFields, false);
|
||||
if (myDefinitionLevel > 0) {
|
||||
return new PyNamedTupleType(myClass, myDeclaration, myName, myFields, myDefinitionLevel-1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PyClassType toInstance() {
|
||||
return myIsDefinition ? new PyNamedTupleType(myClass, myDeclaration, myName, myFields, false) : this;
|
||||
return myDefinitionLevel == 1 ? new PyNamedTupleType(myClass, myDeclaration, myName, myFields, 0) : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,7 +96,7 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PyType fromCall(PyCallExpression call) {
|
||||
public static PyType fromCall(PyCallExpression call, int level) {
|
||||
final String name = PyPsiUtils.strValue(call.getArgument(0, PyExpression.class));
|
||||
final PyExpression fieldNamesExpression = PyPsiUtils.flattenParens(call.getArgument(1, PyExpression.class));
|
||||
if (name == null || fieldNamesExpression == null) {
|
||||
@@ -111,7 +115,7 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
|
||||
if (fieldNames != null) {
|
||||
PyClass tuple = PyBuiltinCache.getInstance(call).getClass(PyNames.FAKE_NAMEDTUPLE);
|
||||
if (tuple != null) {
|
||||
return new PyNamedTupleType(tuple, call, name, fieldNames, true);
|
||||
return new PyNamedTupleType(tuple, call, name, fieldNames, level);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -58,7 +58,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
|
||||
if (callee != null) {
|
||||
final Callable callable = callee.getCallable();
|
||||
if (PyNames.COLLECTIONS_PY.equals(callable.getContainingFile().getName())) {
|
||||
return PyNamedTupleType.fromCall(call);
|
||||
return PyNamedTupleType.fromCall(call, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
|
||||
else if (referenceTarget instanceof PyFunction && anchor instanceof PyCallExpression) {
|
||||
if (PyNames.NAMEDTUPLE.equals(((PyFunction)referenceTarget).getName()) &&
|
||||
PyNames.COLLECTIONS_PY.equals(referenceTarget.getContainingFile().getName())) {
|
||||
return PyNamedTupleType.fromCall((PyCallExpression)anchor);
|
||||
return PyNamedTupleType.fromCall((PyCallExpression)anchor, 2);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -419,8 +419,8 @@ public class PyCallExpressionHelper {
|
||||
return new PyClassTypeImpl(cls, false);
|
||||
}
|
||||
final PyType providedType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(target, context, call);
|
||||
if (providedType != null) {
|
||||
return providedType;
|
||||
if (providedType instanceof PyCallableType) {
|
||||
return ((PyCallableType) providedType).getCallType(context, (PyReferenceExpression)callee);
|
||||
}
|
||||
if (target instanceof Callable) {
|
||||
final Callable callable = (Callable)target;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
from java.util import Collections
|
||||
|
||||
x = Collections.emptyList()
|
||||
s = x.size()
|
||||
Reference in New Issue
Block a user