From c9a64bd1d352b3c55e4a1a7dd9c3ac3c4ab0009f Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 4 Mar 2018 11:29:00 +0100 Subject: [PATCH] Globals should be looked up with the same priority as other defined nodes. --- jedi/evaluate/context/module.py | 16 +++++++++------- jedi/evaluate/filters.py | 26 +++++++++++++++++--------- test/completion/basic.py | 10 ++++++++++ 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/jedi/evaluate/context/module.py b/jedi/evaluate/context/module.py index a94758fc..4350dc89 100644 --- a/jedi/evaluate/context/module.py +++ b/jedi/evaluate/context/module.py @@ -7,7 +7,7 @@ from parso import python_bytes_to_unicode from jedi.evaluate.cache import evaluator_method_cache from jedi._compatibility import iter_modules from jedi.evaluate.filters import GlobalNameFilter, ContextNameMixin, \ - AbstractNameDefinition, ParserTreeFilter, DictFilter + AbstractNameDefinition, ParserTreeFilter, DictFilter, MergedFilter from jedi.evaluate import compiled from jedi.evaluate.base_context import TreeContext from jedi.evaluate.imports import SubModuleName, infer_import @@ -50,13 +50,15 @@ class ModuleContext(TreeContext): self._path = path def get_filters(self, search_global, until_position=None, origin_scope=None): - yield ParserTreeFilter( - self.evaluator, - context=self, - until_position=until_position, - origin_scope=origin_scope + yield MergedFilter( + ParserTreeFilter( + self.evaluator, + context=self, + until_position=until_position, + origin_scope=origin_scope + ), + GlobalNameFilter(self, self.tree_node), ) - yield GlobalNameFilter(self, self.tree_node) yield DictFilter(self._sub_modules_dict()) yield DictFilter(self._module_attributes_dict()) for star_module in self.star_imports(): diff --git a/jedi/evaluate/filters.py b/jedi/evaluate/filters.py index 73a08d4a..8e499a08 100644 --- a/jedi/evaluate/filters.py +++ b/jedi/evaluate/filters.py @@ -296,6 +296,17 @@ class DictFilter(AbstractFilter): return value +class MergedFilter(object): + def __init__(self, *filters): + self._filters = filters + + def get(self, name): + return [n for filter in self._filters for n in filter.get(name)] + + def values(self): + return [n for filter in self._filters for n in filter.values()] + + class _BuiltinMappedMethod(Context): """``Generator.__next__`` ``dict.values`` methods and so on.""" api_type = u'function' @@ -440,7 +451,7 @@ def get_global_filters(evaluator, context, until_position, origin_scope): >>> context = script._get_module().create_context(scope) >>> filters = list(get_global_filters(context.evaluator, context, (4, 0), None)) - First we get the names names from the function scope. + First we get the names from the function scope. >>> no_unicode_pprint(filters[0]) > @@ -449,24 +460,21 @@ def get_global_filters(evaluator, context, until_position, origin_scope): >>> filters[0]._until_position (4, 0) - Then it yields the names from one level "lower". In this example, this is + # global names -> there are none in our example. + Then it yields the name # global names -> there are none in our example.s from one level "lower". In this example, this is the module scope. As a side note, you can see, that the position in the filter is now None, because typically the whole module is loaded before the function is called. - >>> filters[1].values() # global names -> there are none in our example. + >>> list(filters[1].values()) # package modules -> Also empty. [] - >>> list(filters[2].values()) # package modules -> Also empty. - [] - >>> sorted(name.string_name for name in filters[3].values()) # Module attributes + >>> sorted(name.string_name for name in filters[2].values()) # Module attributes ['__doc__', '__file__', '__name__', '__package__'] - >>> print(filters[1]._until_position) - None Finally, it yields the builtin filter, if `include_builtin` is true (default). - >>> filters[4].values() #doctest: +ELLIPSIS + >>> filters[3].values() #doctest: +ELLIPSIS [, ...] """ from jedi.evaluate.context.function import FunctionExecutionContext diff --git a/test/completion/basic.py b/test/completion/basic.py index cfa18e6a..f3abe9a5 100644 --- a/test/completion/basic.py +++ b/test/completion/basic.py @@ -162,6 +162,16 @@ def funct2(): global_dict_var +global_var_predefined = None + +def init_global_var_predefined(): + global global_var_predefined + if global_var_predefined is None: + global_var_predefined = 3 + +#? int() None +global_var_predefined + # ----------------- # within docstrs # -----------------