This is needed for a clearer understanding of the API: there is no ordering of changes in VersionedStorageChange
GitOrigin-RevId: 2a3800e216d81e87e836f8bd19708b5ba74f496a
Added a new Extension Point for corresponding quick fixes for "Statement without effect inspection." Added QF for Jupyter notebook case and Python file with cells. This QF splits cell just right after the statement without effect
^DS-4558 Fixed
Merge-request: IJ-MR-104455
Merged-by: Natalia Murycheva <natalia.murycheva@jetbrains.com>
GitOrigin-RevId: 7773895cf1ebd6d4e8d56b41e335ec8b97ca5d78
Rely on the fact that PsiScopeProcessor processes class attributes
in the order of their definition.
GitOrigin-RevId: 0b39b0c6002c75d2af3b4988d3aa095823b33cb8
Got rid of redundant inner classes and fields, removed repeated logic, used
more obvious control flow constructs.
GitOrigin-RevId: a04977afc8a0ceb213380b406e74e37dfc7cd49c
Namely, if substitution values were passed as non-literal value compatible with
collections.Mapping, use plain string concatenation. The existing condition for
that was wrong.
GitOrigin-RevId: b6e9b9c615d80aa7842f883086b3544e095d5f81
For everything else, e.g. d['key'] = {'foo': 42}, we cannot track subsequent
modifications of d['key'], such as d['key']['bar'] = 1, anyway. We need
a reference as a subscription operand, or a callee to make sure these mutating
operations are performed on the same value. It doesn't make sense to scan
through an entire containing scope looking for subscription expressions
and calls on such assignments targets.
GitOrigin-RevId: 8ebbcb73e43e5711cbe680da6936f3f1c4e54a55
Not doing it not only led to incorrect results, but also could cause serious
performance problems as in PY-59727 when we started recursively analyzing
assignments to a parent dict, producing gigantic hierarchies of nested
TypedDict types as a result.
Namely, each type we tried to infer a TypedDict for a dict literal
in the RHS of an assignment to another dict's key, like the following
d['key'] = {...}
we started to analyze all the modifications of "d" all over again, even though
they couldn't affect the type of the assigned literal. Doing that, we eventually
tried to infer the type of this literal again, and the recursion guard in
TypeEvalContext finally set off. But before that, we'd already constructed
a tree of TypedDicts with the depth roughly equal to the number of such
subscripted assignments to "d". For the user's example, such a TypedDict
contained millions of elements completely hanging our inspections.
GitOrigin-RevId: 5a17894d501086ed4d4ec6bdd8a17c1f05dd7bd5
It has revealed a bug (most likely stochastic) with mutating a cached tuple
type in PyCollectionTypeByModificationsProvider.
GitOrigin-RevId: 2e830ae5691acbc4855107d0a18dc81ad43ab3eb
It's always applied to Python-specific PSI elements. There is no need to do
a separate cast just to access methods of PsiElement.
GitOrigin-RevId: 481577fa8d2092df7884d6e611622f0bbd4d1e54
Namely, evaluate expressions in the list of base classes as regular
type hints in PyTypingTypeProvider. It allowed us to properly consider type
aliases, as previously used PyResolveUtil.resolveQualifiedNameInScope reached
only up to the first type alias not following assignment chains further to
class definitions.
It simultaneously made collecting type substitutions for generic classes simpler
since we don't need to replicate the logic of parsing subscription expressions
in type hints specifically for base class expressions and can instead
retrieve type arguments corresponding to expressions in brackets directly from
PyCollectionType.getElementTypes.
Since we process both subscription expressions and plain qualified names in
the list of base classes uniformly now, evaluating them all as type hints,
PyClassElementType.getSubscriptedSuperClassesStubLike also became obsolete.
GitOrigin-RevId: 8a2a45c1be0259ee62f82595289842f043ae02b2
This behavior is similar to how mypy and pyright handle overloads relying on
their definition order, where more specific signatures are supposed to precede
more general ones. The subtle difference is that in case of Any arguments,
pyright tries to find a common supertype for return types of all matching
overloads, mypy just returns Any, and we return a union of their return types.
For the time being, it keeps things simple and matches how we treated ambiguous
signatures before.
To make this work, I've had to revise how we handle name redefinitions in files.
Previously, we processed them in the reversed order to give priority to those
later in a file, which is natural for regular .py files. It doesn't make much
sense for .pyi stubs, though, as it's impossible to redefine a name there and
multiple definitions, e.g. overloads, are supposed to have equal precedence.
Now, we don't reverse the order of name definitions in .pyi stubs at all,
and in .py files we do that preserving the original order of overloads.
A side effect of it is that now we always navigate to the first overload
of a name in a .pyi stub, as opposed to the last, but it only seems more
logical and convenient.
On the other hand, when we handle overloads in .py files, we explicitly
assign to them a lower resolve rate to give precedence to implementations.
The only exception is that when there are no implementations we still want
to prefer the latest overload, so we put it into the results second time
with a higher rate. It messed up overloads order important for type inference,
so I've introduced a dedicated RATE_LIFTED_PY_FILE_OVERLOAD rate for such
results to filter them out later in PyCallExpressionHelper. I've also added
a named RATE_PY_FILE_OVERLOAD rate of other overloads in .py files to make
them more easily distinguishable from other resolve results with a low rate.
GitOrigin-RevId: e921654e47fe1fc5da047950b70775e342996757
Previously, we inferred tuple[Any, ...] for such parameters and then replaced it
with a PyParamSpecType in PyTypeCheckerInspection specifically for its checks.
However, inside the inspection we didn't have enough context information to
properly detect the right type parameter scope.
Now, PyParamSpecType is created for vararg parameters annotated with "P.args" and
"P.kwargs" directly in PyTypingTypeProvider, uniformly with other possible usages
of ParamSpec and with accurate scope checks.
This also changes how we handle unrecognized parameter type hints. Previously,
we returned null for them, delegating to other type providers, which could lead
to subtle bugs. Now, when a type hint is present, but can't be identified,
we return Any, thus ignoring any further sources of type information.
It was triggered in PyProtectedMemberInspectionTest.testMemberResolvedToStub
in particular, where we ignored an annotation containing a broken
forward reference to a containing class, proceeding to a nearby .pyi stub.
This was most likely an honest mistake, so I've updated the test data.
GitOrigin-RevId: 02945e756c5f9a8097360c3bcf3f1c5f267c02e4
The rest of the usages will be updated later on not to cause excess conflicts
with a few big features currently being developed.
Also removed a redundant constructor that can be replicated with
toInstance/toClass methods.
GitOrigin-RevId: d9af65d8ac865b1eb822607987f8195809f3ec23
Existing usages haven't been updated yet not to hinder the upcoming integration
of TypeVarTuple (PY-53105) and LiteralString (PY-58857) support.
GitOrigin-RevId: 16aafd07edfdc98dee0240dce7cd3383b5eb0b00
It's difficult to reason about how these should work with caching of
PyTypingTypeProvider.Context in TypeEvalContext.
Additionally, I fixed losing an already found TypeVar scope for "T" when
constructing a PyGenericType for "Type[T]". Previously, we did it all over again
for Type[T] in getTypeForResolvedElement at the moment where the corresponding
TypeVar declaration already wasn't at the top of the type alias stack, so it
started to cause EmptyStack exceptions after this change.
GitOrigin-RevId: b22f2ca0ccd12ad9a21294d6ba23574d839e813b
To restore the scope of type variables, it's easier to just pass the
corresponding PyReferenceExpression around. This expression stack didn't work
correctly in case of aliases anyway, as its bottom element pointed to the first
type hint where we started evaluation, not where a TypeVar reference actually
appeared.
GitOrigin-RevId: a887b7dbcd85bd37b029318f746fcaeddb59044c
The problem was caused by the recursive alias CoreSchema in pydantic-core, none
of our existing recursive type guards protected against.
Namely, pydantic_core.core_schema.CoreSchema alias referred to a number of
TypedDict declarations, many of which used CoreSchema in their own annotations.
Normally, the guard against recursive type aliases in PyTypingTypeProvider
should have caught that, but PyTypedDictType instances are constructed in
another provider and once we left PyTypingTypeProvider we lost the information
about already traversed type aliases, as this information is not preserved in a
regular TypeEvalContext instances.
The protection against recursive evaluation of types in TypeEvalContext, on the
other hand, did catch that, but because it intercepts recursive inference for
the same PyTypedElement and knows nothing about type aliases, so it happened
only when we tried to evaluate the type for the same TypedDict attribute twice.
Depending on the order of TypedDict references within the union type, for some
of them, it occurred only after we'd already traversed through all remaining
TypedDicts trying to build the union type for CoreSchema again for their
attributes. As a result, the size of the tree of these union types grew
exponentially, reaching 13 million elements and bringing our analysis to
its knees.
Ideally, we should have a single entry point in our API for all the computations
related to type hints that should take care of keeping the information about
type aliases. For now, as a workaround, I store the state of PyTypingTypeProvider
in a thread local cache per TypeEvalContext and restore it if we leave and then
get back to the same provider.
GitOrigin-RevId: 5a9b498fefa7dc275e3c4d7d265bdd07f846ad87
Because FieldTypeAndTotality used the default Object#equals, two PyTypedDictType
instances for the same definition were not considered equivalent.
GitOrigin-RevId: a241a5199200d5c54a3ae7121e3a417aa18b4ec8