PY-80564 Fp "Local variable might be referenced before assignment" when returning a comprehension in `try/except`
PY-80733 Fp "Local variable might be referenced before assignment" for `try/except` with a `break` inside a loop
Merge-request: IJ-MR-162320
Merged-by: Aleksandr Govenko <aleksandr.govenko@jetbrains.com>
GitOrigin-RevId: f3e5d76e1fb15e2951d395fa27768269e4d0cb8f
PySliceExpression is replaced by PySubscriptionExpression in AST.
PySliceItem is returned by PySubscriptionExpression.getIndexExpression(). For that purpose PySliceItem is now a PyExpression of type `builtins.slice`.
GitOrigin-RevId: 9aa8de13ef7c51741e248317c5264b3a06ffb9bf
When there is no `finally` in try-except statement, use transparent exit instruction to tie all normal exits from try-, else- and except- parts to the next instruction
Merge-request: IJ-MR-158265
Merged-by: Aleksandr Govenko <aleksandr.govenko@jetbrains.com>
GitOrigin-RevId: 734581b732a1a558b72811fdda977c470d045cc9
Added a new CFG instruction to indicate implicit raise after finally block. Also added PyDataFlow as an future entry point for DFA.
Merge-request: IJ-MR-155798
Merged-by: Aleksandr Govenko <aleksandr.govenko@jetbrains.com>
GitOrigin-RevId: db63ba632c48235cc51b8e64869d21f5bcfc2d1c
Added PyWithContextExitInstruction that works as 'except' node in try-except statements, but for 'with context-manager' statements. This allows to see when it can recover from exception by checking the type of `contextlib.AbstractContextManager`
Merge-request: IJ-MR-152213
Merged-by: Aleksandr Govenko <aleksandr.govenko@jetbrains.com>
GitOrigin-RevId: fd5a139de31d47136cc86b4a7e090a20b73b8744
Updated PyFunction to account for implicit 'return None' statements when inferring return statement types.
It affected return type inference of PyFunction.
Fixed a failing test related to formatted strings.
Added a quick fix to make all return statements explicit.
Updated the CFG to include PyPassStatements, enabling detection of exit points in empty functions.
Simplified PyMakeFunctionReturnTypeQuickFix to independently infer function types and handle required imports. Currently, it does not support specifying custom suggested types.
Merge-request: IJ-MR-148719
Merged-by: Aleksandr Govenko <aleksandr.govenko@jetbrains.com>
GitOrigin-RevId: 9f58961f9eb70e4f9dbba7359f5aafdfd392b7e2
typing.Generic is a magical class that can be specified in any position
in the list of base classes, not affecting the MRO consistency. It's done by
the custom __mro_entries__ implementation in typing._BaseGenericAlias (Python < 3.12),
which skips this Generic entry if there are other generic classes following
it on the list of superclasses. Namely, it's possible to do the following:
```
class Base(Generic[T]):
pass
class MyClass(Generic[T], Base[T]):
pass
```
which would cause a TypeError for regular classes. Since it broke our implementation
of the C3 algorithm in PyClassImpl.getMROAncestorTypes, we now special-case it by
always moving typing.Generic to the very end of the base class list while constructing
MRO.
See https://github.com/python/cpython/blob/3.11/Lib/typing.py#L1298 for a pure-Python
version of typing._BaseGenericAlias.__mro_entries__ and a relevant discussion in
https://github.com/python/cpython/issues/106102.
GitOrigin-RevId: e7d765193d532ab8457133e8fb5ad06840d89225
This way they have access to type parameters of these functions, and PyReferenceImpl.getResultsFromProcessor
can properly perform flow-sensitive resolve for them now that READ instructions for expressions
inside annotations and WRITE instructions for type parameters are in the same CFG. It allowed to
remove all the special logic for type parameters from PyReferenceImpl as well as from
PyUnboundLocalVariableInspection.
I had to special-case these annotations in PyResolveUtil.scopeCrawlUp, though, to "lift" their
original scope back from what ScopeUtil.getScopeOwner returns, making names defined in a class scope,
e.g., nested classes, visible to them.
GitOrigin-RevId: b2e78211565300dbcd7c2e2b246a7a8e14bb0e8f
Both of these are evaluated in the outer scope, e.g., in a scope of a containing class or a module,
with the corresponding instructions already processed there, and were duplicated in the CFG
of function bodies.
GitOrigin-RevId: 4460cbef6446a311f0ab15ffe3407bfbb73286e2
Functions annotated with `NoReturn` and `Never` now taken into account in the Control Flow Graph building process, and the code after calling such functions is treated as unreachable.
Merge-request: IJ-MR-105973
Merged-by: Daniil Kalinin <Daniil.Kalinin@jetbrains.com>
GitOrigin-RevId: ef5840ae6e593498fc334dc9bd2daadccebf2b13
Control flow now abrupts on `exit()` and `pytest.fail()` calls
Control flow now abrupts only if class which contains `self.fail()` call contains case-insensitive "test" word in the name
Merge-request: IJ-MR-96165
Merged-by: Daniil Kalinin <Daniil.Kalinin@jetbrains.com>
GitOrigin-RevId: ea173fdb72a10a373cd95f266ea7589e36545f30
In case of syntactic ambiguity with previous versions of the grammar, such as
"with (expr)" or "with (expr1, expr2)", PyWithStatement is still parsed as
having its own parentheses, not a parenthesized expression or a tuple as
a single context expression. The latter case, even though syntactically legal,
is still reported by the compatibility inspection in Python <3.9.
These changes also include proper formatter and editing support (e.g. not
inserting backslashes on line breaks inside parentheses), as well as
Complete Current Statement, which now takes possible parentheses into account
while inserting a missing colon.
The changes in the formatter are somewhat ad-hoc, intended to minimize the effect
on other constructs. "With" statement is somewhat special in the sense that it's
the first compound statement (having a statement list) with its own list-like
part in parentheses.
Existing tests on with statement processing were expanded and uniformly named.
Co-authored-by: Semyon Proshev <semyon.proshev@jetbrains.com>
GitOrigin-RevId: 15c33e97f177e81b5ed23891063555df016feb05
Not stopping at a statement break token and continuing recovery until a colon,
we considered the subsequent well-formed case clause to be a part of an error
message about a missing pattern, thus, moving the caret to its colon.
GitOrigin-RevId: f4ee0e12876960e989de3dee89925b65e3cf2339
I introduced a new type of CFG instructions, similar to ConditionalInstruction,
called RefutablePatternInstruction. The idea is that every pattern that can
possibly fail to match is surrounded with a pair of such instructions, helping
to describe how the control flow moves in each case. The PEP calls the opposite
type of patterns that always match "irrefutable", hence the name. We need these
synthetic instructions because otherwise some refutable patterns such as literal
ones (e.g. "42") don't leave any nodes in the graph. Incorporating the information
about irrefutable patterns right into the graph allows catching cases such
as "wildcard/name capture makes remaining patterns unreachable", both in OR
patterns and independent case clauses.
GitOrigin-RevId: beebe1890a6a824b188e6954a2c92f7ec52079e0
Previously, it used an odd convention with lowercased names of test data
files (with nothing separating individual words), which made adding new tests
quite tedious.
Also, I removed the test data "exit.py" as it wasn't used by any test.
GitOrigin-RevId: 92b1963c67ed01977f5b7ad020984056c9fe045d
It's weird, however, that Python implementation might query fixers for elements
that are at completely different lines with the caret as in the originally
reported case. This confusing and error-prone behavior needs to be revised
separately.
GitOrigin-RevId: 1f48fe0e0936fb2007022dfc889c44ad32e1eaf0
It works by automatically inserting a trailing comma before a line break in
multiline collection literals. Additionally, a colon is inserted between a key
and a value in dict literals.
Because of the language ambiguity regarding syntax of some incomplete collection
literals, colon is not inserted after the first key of a dict literal
(it's indistinguishable from a set literal with one item), and comma is not
inserted after the first item of a parenthesized tuple (it's indistinguishable
from a parenthesized expression).
The idea was taken from such implementation of Complete Current Statement for
JSON.
GitOrigin-RevId: 49ff9857d8c12476bfa9aacaed0b49faa99810fd
- treat deletion by slice and subscription expressions as read access
- delete instruction in dataflow only inserted for PyReferenceExpression
GitOrigin-RevId: 72ae5e964a1e287e007dabb8f41433b284523a02
self is inserted for methods that are not class-/staticmethod
cls is inserted for classmethod
empty parameter list for staticmethod
GitOrigin-RevId: 9743ae50c89c069b8123b8b6eb26fb841dd1f5b2