mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
Make return type weak for functions decorated with unknown decorator (PY-28626)
Or decorator that could change return type.
This commit is contained in:
@@ -67,10 +67,7 @@ public class PyNoneFunctionAssignmentInspection extends PyInspection {
|
||||
}
|
||||
if (callable instanceof PyFunction) {
|
||||
final PyFunction function = (PyFunction)callable;
|
||||
// Currently we don't infer types returned by decorators
|
||||
if (hasInheritors(function) ||
|
||||
PyKnownDecoratorUtil.hasUnknownOrChangingReturnTypeDecorator(function, myTypeEvalContext) ||
|
||||
PyKnownDecoratorUtil.hasAbstractDecorator(function, myTypeEvalContext)) {
|
||||
if (hasInheritors(function) || PyKnownDecoratorUtil.hasAbstractDecorator(function, myTypeEvalContext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,12 @@ public class PyKnownDecoratorUtil {
|
||||
|
||||
public static boolean hasUnknownOrChangingReturnTypeDecorator(@NotNull PyDecoratable decoratable, @NotNull TypeEvalContext context) {
|
||||
final List<KnownDecorator> decorators = getKnownDecorators(decoratable, context);
|
||||
return !allDecoratorsAreKnown(decoratable, decorators) || decorators.contains(UNITTEST_MOCK_PATCH);
|
||||
|
||||
if (!allDecoratorsAreKnown(decoratable, decorators)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ContainerUtil.exists(decorators, d -> d == UNITTEST_MOCK_PATCH || d == CONTEXTLIB_CONTEXTMANAGER);
|
||||
}
|
||||
|
||||
public static boolean hasUnknownOrUpdatingAttributesDecorator(@NotNull PyDecoratable decoratable, @NotNull TypeEvalContext context) {
|
||||
|
||||
@@ -217,6 +217,10 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
|
||||
}
|
||||
}
|
||||
|
||||
if (getProperty() == null && PyKnownDecoratorUtil.hasUnknownOrChangingReturnTypeDecorator(this, context)) {
|
||||
inferredType = PyUnionType.createWeakType(inferredType);
|
||||
}
|
||||
|
||||
return PyTypingTypeProvider.toAsyncIfNeeded(this, inferredType);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
@contextmanager
|
||||
def mycm():
|
||||
pass
|
||||
yield
|
||||
pass
|
||||
|
||||
|
||||
@mycm()
|
||||
def decorated_func():
|
||||
pass
|
||||
@@ -0,0 +1,2 @@
|
||||
def contextmanager(func):
|
||||
pass
|
||||
@@ -1,3 +1,6 @@
|
||||
from abc import abstractmethod
|
||||
|
||||
|
||||
class Abstract(object):
|
||||
|
||||
@abstractmethod
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
from abc import abstractmethod
|
||||
|
||||
|
||||
class Abstract(object):
|
||||
|
||||
@abstractmethod
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
@decorator1, @decorator2
|
||||
def foo(param)
|
||||
Inferred type: (param: Any) -> None
|
||||
Inferred type: (param: Any) -> Optional[Any]
|
||||
@@ -1,3 +1,3 @@
|
||||
@decorator
|
||||
def foo(param)
|
||||
Inferred type: (param: Any) -> None
|
||||
Inferred type: (param: Any) -> Optional[Any]
|
||||
@@ -1 +1 @@
|
||||
<html><body><code>@<i>decorator1</i><br>@<i>decorator2</i><br>def <b>foo</b>(param)<br>Inferred type: (param: Any) -> None</code></body></html>
|
||||
<html><body><code>@<i>decorator1</i><br>@<i>decorator2</i><br>def <b>foo</b>(param)<br>Inferred type: (param: Any) -> Optional[Any]</code></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><code><small>class <a href="psi_element://#class#">Foo</a></small><br><br>@<i>deco</i><br>def <b>meth</b>(self)<br>Inferred type: (self: <a href="psi_element://#typename#Foo">Foo</a>) -> None<br><br>Doc of meth.<br></code></body></html>
|
||||
<html><body><code><small>class <a href="psi_element://#class#">Foo</a></small><br><br>@<i>deco</i><br>def <b>meth</b>(self)<br>Inferred type: (self: <a href="psi_element://#typename#Foo">Foo</a>) -> Optional[Any]<br><br>Doc of meth.<br></code></body></html>
|
||||
@@ -1 +1 @@
|
||||
<html><body><code>@<i>decorator</i><br>def <b>foo</b>(param)<br>Inferred type: (param: Any) -> None</code></body></html>
|
||||
<html><body><code>@<i>decorator</i><br>def <b>foo</b>(param)<br>Inferred type: (param: Any) -> Optional[Any]</code></body></html>
|
||||
@@ -108,6 +108,11 @@ public class PyCallingNonCallableInspectionTest extends PyInspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-28626
|
||||
public void testFunctionDecoratedAsContextManager() {
|
||||
doMultiFileTest();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Class<? extends PyInspection> getInspectionClass() {
|
||||
|
||||
Reference in New Issue
Block a user