mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-24930 Fixed: False negative: no parameter info when implicitly calling __call__
Update PyCallExpressionHelper to support a case when callee resolves to call expression and this call expression returns class with `__call__`.
This commit is contained in:
@@ -196,7 +196,9 @@ public class PyCallExpressionHelper {
|
||||
function -> new ClarifiedResolveResult(resolveResult, function, null, true));
|
||||
}
|
||||
else if (resolved instanceof PyCallExpression) { // foo = classmethod(foo)
|
||||
final Pair<String, PyFunction> wrapperInfo = interpretAsModifierWrappingCall((PyCallExpression)resolved);
|
||||
final PyCallExpression resolvedCall = (PyCallExpression)resolved;
|
||||
|
||||
final Pair<String, PyFunction> wrapperInfo = interpretAsModifierWrappingCall(resolvedCall);
|
||||
if (wrapperInfo != null) {
|
||||
final String wrapperName = wrapperInfo.getFirst();
|
||||
final PyFunction.Modifier wrappedModifier = PyNames.CLASSMETHOD.equals(wrapperName)
|
||||
@@ -208,6 +210,22 @@ public class PyCallExpressionHelper {
|
||||
final ClarifiedResolveResult result = new ClarifiedResolveResult(resolveResult, wrapperInfo.getSecond(), wrappedModifier, false);
|
||||
return Collections.singletonList(result);
|
||||
}
|
||||
else {
|
||||
final PyType resolvedCallType = resolveContext.getTypeEvalContext().getType(resolvedCall);
|
||||
if (resolvedCallType instanceof PyClassLikeType) {
|
||||
final List<? extends RatedResolveResult> dunderCall =
|
||||
((PyClassLikeType)resolvedCallType).resolveMember(PyNames.CALL, resolvedCall, AccessDirection.READ, resolveContext, true);
|
||||
|
||||
if (!ContainerUtil.isEmpty(dunderCall)) {
|
||||
return StreamEx
|
||||
.of(dunderCall)
|
||||
.map(RatedResolveResult::getElement)
|
||||
.nonNull()
|
||||
.map(element -> new ClarifiedResolveResult(resolveResult, element, null, false))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resolved instanceof PyFunction) {
|
||||
final PyFunction function = (PyFunction)resolved;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo:
|
||||
def __call__(self, arg: int):
|
||||
return arg
|
||||
|
||||
bar = Foo()
|
||||
bar.__call__(<warning descr="Parameter 'arg' unfilled">)</warning>
|
||||
bar(<warning descr="Parameter 'arg' unfilled">)</warning>
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo:
|
||||
def __call__(self, arg: int):
|
||||
return arg
|
||||
|
||||
bar = Foo()
|
||||
bar.__call__(<warning descr="Expected type 'int', got 'str' instead">"s"</warning>)
|
||||
bar(<warning descr="Expected type 'int', got 'str' instead">"s"</warning>)
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo:
|
||||
def __call__(self, arg: int):
|
||||
return arg
|
||||
|
||||
bar = Foo()
|
||||
bar.__call__(<arg1>)
|
||||
bar(<arg2>)
|
||||
@@ -696,6 +696,18 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
// PY-24930
|
||||
public void testCallOperator() {
|
||||
runWithLanguageLevel(
|
||||
LanguageLevel.PYTHON35,
|
||||
() -> {
|
||||
for (int offset : StreamEx.of(loadTest(2).values()).map(PsiElement::getTextOffset)) {
|
||||
feignCtrlP(offset).check("self: Foo, arg: int", new String[]{"arg: int"}, new String[]{"self: Foo, "});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Imitates pressing of Ctrl+P; fails if results are not as expected.
|
||||
* @param offset offset of 'cursor' where Ctrl+P is pressed.
|
||||
|
||||
@@ -317,6 +317,11 @@ public class PyArgumentListInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-24930
|
||||
public void testCallOperator() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON35, this::doTest);
|
||||
}
|
||||
|
||||
private void doMultiFileTest() {
|
||||
final String folderPath = "inspections/PyArgumentListInspection/" + getTestName(false) + "/";
|
||||
|
||||
|
||||
@@ -417,4 +417,9 @@ public class PyTypeCheckerInspectionTest extends PyTestCase {
|
||||
public void testPromotingBytearrayToStrAndUnicode() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-24930
|
||||
public void testCallOperator() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON35, this::doTest);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user