Otherwise, we end up with dozens of unintentionally public names such as "s", "i", "k"
even in the standard library (e.g. `this.s` or `pickletools.i`).
Ideally, we should rely on .pyi stubs and the content of `__all__` to offer only explicitly
exposed API, but not every module has any of those two, and it's not clear how to match
.py files and the corresponding .pyi stubs fast enough for completion.
GitOrigin-RevId: 163c472654e60ae63ff893142b8ddb9accc56393
Previously, such names were visible only on so-called "extended" completion,
activated when the hotkey for the basic completion was hit twice. The main reason
was that collecting such variants from indexes was a slow process, and we
didn't want to harm the responsiveness of completion for basic names.
Now it becomes possible thanks to a number of performance optimizations:
* Instead of using three separate indexes for classes, functions and variables,
we use one -- PyExportedModuleAttributeIndex. By definition, it includes only top-level
"importable" names, so we additionally save time by not filtering out irrelevant
entries. Also, it doesn't contain private definitions starting with an underscore.
It might bother some users, but given that the previous completion was used
extremely rarely, and the new one is going to be visible everywhere, it seems
that pruning unlikely entries as much as possible is a fare tradeoff. In the future,
we might enable them back on the "extended" completion if there is a demand.
Also, this index binds its keys to the project (`traceKeyHashToVirtualFileMapping`),
further eliminating useless index lookups.
* Thanks to the recent fixes in the platform (IJPL-265), it's now possible to
simultaneously iterate over all keys in an index and request values for a given key
without deadlocks, which is much faster than eagerly fetching all keys first.
* While scanning through all matching entries from indexes, we terminate
the lookup if the number of items exceeds the size of the lookup list.
We can further reduce this number by adjusting the "ide.completion.variant.limit"
registry value.
* Calculating expensive "canonical" import paths (e.g. "pkg.private.Name" is importable as
"pkg.Name") is offloaded to a background thread thanks to the `withExpensiveRenderer` API.
We still calculate these paths synchronously, though, for names whose raw qualified names
contain components starting with an underscore to decide whether these private names are
publicly re-exported and, hence, should be displayed.
The rest of the work has been put into reducing the number of entries on the list, e.g.
* The prefix under caret is now matched from the beginning of a name, e.g. `Bar<caret>`
matches `BarBaz`, but not `FooBar`.
* We don't suggest imported names clashing with those already available in scope.
* Some kinds of definitions are not suggested in specific contexts, e.g.
functions and variables are not suggested inside patterns and type hints.
* Nothing is suggested at the top-level of a class body, where dangling
reference expressions or calls are not normally expected.
Additionally, we don't suggest names from .pyi stubs at the moment, because
it pollutes the suggestion list with entries coming from the stubs for
third-party packages in Typeshed. We should probably enable them back once
we are able to properly disable Typeshed entries for not installed packages.
Some legacy forms of completion are left in the extended mode. In particular,
qualified names of classes are offered inside string literals only in this mode.
Also, module and package names are suggested only in the extended mode, because
top-level packages and modules are already suggested for the basic completion
by PyModuleNameCompletionContributor.
A few tests in PyClassNameCompletionTest were updated or removed entirely because
* we no longer suggest private names
* we no longer suggest names from private modules not re-exported in a public module
* we no longer suggest names clashing with those already available in scope
* prefix matching policy was changed to start at the beginning of an identifier
The whole feature can be disabled with the option "Suggest importable classes,
functions and variables in basic completion" in settings.
GitOrigin-RevId: 0787d42ce337b73b01a60f0bb7aa434fee43e659
The logic is similar to that for instance attributes. Top-level class
attributes and methods defined in the class body get the precedence,
followed by class attributes defined with assignments in @classmethods
unless the latter would resolve to the same assignments as in
cls.attr = cls.attr + 1
finally, we scan through all other class methods resolving the name
to the first definition inside one of them.
So far, I intentionally didn't expose such attributes in findClassAttribute()
or getClassAttributes() because users of these methods assume that
this API considers only attributes defined immediately in the class body.
Adding extra definitions from class methods might break these usages.
I had to update the inspection about typing.Final, because it relied
on the fact that resolve() on assignment targets on class objects can
lead only to those top-level class attributes, where type hints are normally
located, but now it can lead to assignments to a qualified attribute inside
a containing class method.
GitOrigin-RevId: 0ca5bdaa4efca127ac187e822a49df6795e1028a
Since disabling turned out to be controversial. Even in the ticket some users were
against this decision claiming that it heavily annotated code bases it might be necessary
to retain all annotations from inherited method signatures. We need to think of a better
solution for controlling this behavior on case-to-case basis.
GitOrigin-RevId: c68763f0cad23de8975085e9bc8a6fd99013de3b
I had to move addImports to PyClassRefactoringUtil because PySuperMethodCompletionContributor
resides in python-psi-impl and, thus, has no access to PyOverrideImplementUtil.
GitOrigin-RevId: cf2ac19da779977649144b2477bac3f8ae78bbcd
- when there are other keys present in the literal, use quotes from there
- when the literal is empty, use double quotes by default
- when there already are quotes, suggest just the key names
GitOrigin-RevId: 5f37cd25c0e47521e78a01ab84053571369b24a8
Test for PY-53200
Better tests for PY-53200
PY-53200 Removed unnecessary test.
`testMethodNamesDoNotDuplicateParameterList` renamed and moved closer to the corresponding ones
Removed test for method names in suggestions restored
GitOrigin-RevId: 51b0721190718c44810c16e198bad583c2af67d0
This way we further reduce the number of irrelevant completion items suggested
effectively in every expression context, e.g. not suggesting "parser" and
"calendar" modules for the "ar" prefix, only something like "argparse" or
"array". The same applies to the completion of attributes with unresolved
qualifiers.
GitOrigin-RevId: 7a58053c4744c3d0066c379a4f190ffd09bfabd1
By giving them an explicit priority lower than the default. Unfortunately,
it doesn't remedy the problem with short module names, such as "re" or "sys",
always being on top when they completely match the entered prefix.
At the moment this behavior is hard-coded in the platform and cannot be
altered by language plugins. It's not caused by the "liftShorter" classifier.
Also, explicitly prioritizing various lookup elements has become quite messy
and scattered across PyCompletionWeigher and specific contributors. It begs
to be refactored, but will be addressed separately.
GitOrigin-RevId: d6f6ad06f5d68f3de7b866b8240a95b785604649
By running the completion contributor for non-imported modules after everything
else, including the LegacyCompletionContributor offering names present in
the scope, and filtering out duplicate variants.
GitOrigin-RevId: 98982b2c33d1fc11d70b144de556a6825bd3febc
Both are implemented other the type of the corresponding class.
References resolve to any readable attribute of a class, however
some obviously wrong variants such as special "dunder" attributes
and methods are intentionally excluded from completion suggestions.
GitOrigin-RevId: 5edac14f47cba39840b15b0dd7f21e2e46077261
The problem itself was fixed together with PY-48219 by switching to types to
find possible attributes of a module/package.
GitOrigin-RevId: 587b1c96610375836417655f0feb74f38edb4c69
It allows to properly take into account .pyi stubs for module and packages and
find namespace packages in addition to ordinary Python packages as both of them
don't get into PyModuleNameIndex.
GitOrigin-RevId: 4afdf6d61e1f2e426ce65b0d04c6727caaeada2b
It gives more accurate results and allows to bypass the problem
of PyFile#iterateNames(), which limits the results by the content
of "__all__" (as the method is used to resolve names in star imports).
GitOrigin-RevId: b19604d9e25a738909a02a1d81e4716675417430
It's not enough to just prepend an arbitrary string with "f" to treat it like
a well-formed f-string. If its part following "IntellijIdeaRulezzz " placeholder
contains special characters, such as "&" in URLs, it can break parsing of
a generated fragment to the extent we are no longer able to recover a string
literal from it (it all gets treated as a single embedded expression).
Forcibly closing a started fragment with "} " seems sufficient to guard against
the subsequent string content.
GitOrigin-RevId: fe682511475b800f013ace5e6e52fca9286cd418
Previously, we accidentally offered immediate attributes of a module only right
after a dot in a non-imported qualified name (i.e., with an empty attribute name).
If a qualified name of a fuzzy variant matched that of a direct attribute, it went
unnoticed. However, if a name was non-trivially exported, as in case of
"_pytest.mark.structures.MARK_GEN" exported as "pytest.mark", its expected name,
as an attribute of pytest module, disappeared immediately as one started typing
anything past the dot in "pytest.".
GitOrigin-RevId: 5fbd7bd77fd1629f4d852b757d350cc182b991d7
Aliases were completed only when the prefix was a fully-typed alias, and it became useless without inserting a dot and calling PyUnresolvedModuleAttributeCompletionContributor afterwards
IJ-MR-6806
GitOrigin-RevId: fc5b5e91911bbc85bda4da0753ad8e6da69951cb
Namely, names such as "numpy.random._examples.numba.extending.numbacall" or
"numpy.testing._private.noseclasses.NumpyDoctest" should no longer be suggested,
unless they are also exported in a public package higher in the hierarchy.
It doesn't not affect definitions from internal modules that belong to project
sources, these are still offered in the lookup.
GitOrigin-RevId: 2be393f30bd7d9905a31bdbe8db101807c136617
Namely, their bundled dependencies and tests.
Common names of test and "vendored" roots were collected based on
a base Anaconda interpreter.
Filtration is done over a module/package qualified name in its closest root,
sharing some parts of the implementation with QualifiedNameFinder.
It's likely to also be utilized in the upcoming auto-importing completion
of qualified names.
To make the customization of a search scope easier to use and extend in
the future, I introduced PySearchScopeBuilder API that allows to build
a custom search scope, excluding some irrelevant parts of a Python SDK.
I also updated the set of known standard library tests.
"idlelib/testcode.py" was removed as the only file entry that is
found only in Python 3.3, which we no longer support.
GitOrigin-RevId: 6676c59011d51371639ce24a5ac5c5b56d6b13fb
Previously, we used the corresponding element's presentation for this purpose,
but it showed the shortest qualified name of its module, not necessarily the
"canonical" name that was actually used for importing. For instance, we could
have suggested `ndarray` from `numpy.core._multiarray_umath` but imported it
as `from numpy import ndarray`. It was both misleading and could have led to
duplicate entries for the same symbol among suggestions.
GitOrigin-RevId: abb350feeac9fd212d47dc0943442e0b16b21c9a