forked from VimPlug/jedi
Refactor docstrings
This commit is contained in:
@@ -18,7 +18,8 @@ from jedi.inference import imports
|
|||||||
from jedi.inference.base_value import ValueSet
|
from jedi.inference.base_value import ValueSet
|
||||||
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
||||||
from jedi.inference.context import get_global_filters
|
from jedi.inference.context import get_global_filters
|
||||||
from jedi.inference.value import TreeInstance, ModuleValue
|
from jedi.inference.value import TreeInstance
|
||||||
|
from jedi.inference.docstring_utils import DocstringModule
|
||||||
from jedi.inference.names import ParamNameWrapper, SubModuleName
|
from jedi.inference.names import ParamNameWrapper, SubModuleName
|
||||||
from jedi.inference.gradual.conversion import convert_values, convert_names
|
from jedi.inference.gradual.conversion import convert_values, convert_names
|
||||||
from jedi.parser_utils import cut_value_at_position
|
from jedi.parser_utils import cut_value_at_position
|
||||||
@@ -462,12 +463,12 @@ class Completion:
|
|||||||
|
|
||||||
def _complete_code_lines(self, code_lines):
|
def _complete_code_lines(self, code_lines):
|
||||||
module_node = self._inference_state.grammar.parse(''.join(code_lines))
|
module_node = self._inference_state.grammar.parse(''.join(code_lines))
|
||||||
module_value = ModuleValue(
|
module_value = DocstringModule(
|
||||||
self._inference_state,
|
in_module_context=self._module_context,
|
||||||
module_node,
|
inference_state=self._inference_state,
|
||||||
|
module_node=module_node,
|
||||||
code_lines=code_lines,
|
code_lines=code_lines,
|
||||||
)
|
)
|
||||||
module_value.parent_context = self._module_context
|
|
||||||
return Completion(
|
return Completion(
|
||||||
self._inference_state,
|
self._inference_state,
|
||||||
module_value.as_context(),
|
module_value.as_context(),
|
||||||
|
|||||||
21
jedi/inference/docstring_utils.py
Normal file
21
jedi/inference/docstring_utils.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from jedi.inference.value import ModuleValue
|
||||||
|
from jedi.inference.context import ModuleContext
|
||||||
|
|
||||||
|
|
||||||
|
class DocstringModule(ModuleValue):
|
||||||
|
def __init__(self, in_module_context, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self._in_module_context = in_module_context
|
||||||
|
|
||||||
|
def _as_context(self):
|
||||||
|
return DocstringModuleContext(self, self._in_module_context)
|
||||||
|
|
||||||
|
|
||||||
|
class DocstringModuleContext(ModuleContext):
|
||||||
|
def __init__(self, module_value, in_module_context):
|
||||||
|
super().__init__(module_value)
|
||||||
|
self._in_module_context = in_module_context
|
||||||
|
|
||||||
|
def get_filters(self, origin_scope=None, until_position=None):
|
||||||
|
yield from super().get_filters(until_position=until_position)
|
||||||
|
yield from self._in_module_context.get_filters()
|
||||||
@@ -17,12 +17,10 @@ annotations.
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import warnings
|
import warnings
|
||||||
from textwrap import dedent
|
|
||||||
|
|
||||||
from parso import parse, ParserSyntaxError
|
from parso import parse, ParserSyntaxError
|
||||||
|
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.common import indent_block
|
|
||||||
from jedi.inference.cache import inference_state_method_cache
|
from jedi.inference.cache import inference_state_method_cache
|
||||||
from jedi.inference.base_value import iterator_to_value_set, ValueSet, \
|
from jedi.inference.base_value import iterator_to_value_set, ValueSet, \
|
||||||
NO_VALUES
|
NO_VALUES
|
||||||
@@ -182,52 +180,40 @@ def _strip_rst_role(type_str):
|
|||||||
|
|
||||||
|
|
||||||
def _infer_for_statement_string(module_context, string):
|
def _infer_for_statement_string(module_context, string):
|
||||||
code = dedent("""
|
|
||||||
def pseudo_docstring_stuff():
|
|
||||||
'''
|
|
||||||
Create a pseudo function for docstring statements.
|
|
||||||
Need this docstring so that if the below part is not valid Python this
|
|
||||||
is still a function.
|
|
||||||
'''
|
|
||||||
{}
|
|
||||||
""")
|
|
||||||
if string is None:
|
if string is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
for element in re.findall(r'((?:\w+\.)*\w+)\.', string):
|
potential_imports = re.findall(r'((?:\w+\.)*\w+)\.', string)
|
||||||
# Try to import module part in dotted name.
|
# Try to import module part in dotted name.
|
||||||
# (e.g., 'threading' in 'threading.Thread').
|
# (e.g., 'threading' in 'threading.Thread').
|
||||||
string = 'import %s\n' % element + string
|
imports = "\n".join(f"import {p}" for p in potential_imports)
|
||||||
|
string = f'{imports}\n{string}'
|
||||||
|
|
||||||
debug.dbg('Parse docstring code %s', string, color='BLUE')
|
debug.dbg('Parse docstring code %s', string, color='BLUE')
|
||||||
grammar = module_context.inference_state.grammar
|
grammar = module_context.inference_state.grammar
|
||||||
try:
|
try:
|
||||||
module = grammar.parse(code.format(indent_block(string)), error_recovery=False)
|
module = grammar.parse(string, error_recovery=False)
|
||||||
except ParserSyntaxError:
|
except ParserSyntaxError:
|
||||||
return []
|
return []
|
||||||
try:
|
try:
|
||||||
funcdef = next(module.iter_funcdefs())
|
# It's not the last item, because that's an end marker.
|
||||||
# First pick suite, then simple_stmt and then the node,
|
stmt = module.children[-2]
|
||||||
# which is also not the last item, because there's a newline.
|
|
||||||
stmt = funcdef.children[-1].children[-1].children[-2]
|
|
||||||
except (AttributeError, IndexError):
|
except (AttributeError, IndexError):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if stmt.type not in ('name', 'atom', 'atom_expr'):
|
if stmt.type not in ('name', 'atom', 'atom_expr'):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
from jedi.inference.value import FunctionValue
|
# Here we basically use a fake module that also uses the filters in
|
||||||
function_value = FunctionValue(
|
# the actual module.
|
||||||
module_context.inference_state,
|
from jedi.inference.docstring_utils import DocstringModule
|
||||||
module_context,
|
m = DocstringModule(
|
||||||
funcdef
|
in_module_context=module_context,
|
||||||
|
inference_state=module_context.inference_state,
|
||||||
|
module_node=module,
|
||||||
|
code_lines=[],
|
||||||
)
|
)
|
||||||
func_execution_context = function_value.as_context()
|
return list(_execute_types_in_stmt(m.as_context(), stmt))
|
||||||
# Use the module of the param.
|
|
||||||
# TODO this module is not the module of the param in case of a function
|
|
||||||
# call. In that case it's the module of the function call.
|
|
||||||
# stuffed with content from a function call.
|
|
||||||
return list(_execute_types_in_stmt(func_execution_context, stmt))
|
|
||||||
|
|
||||||
|
|
||||||
def _execute_types_in_stmt(module_context, stmt):
|
def _execute_types_in_stmt(module_context, stmt):
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ class FilterWrapper:
|
|||||||
|
|
||||||
|
|
||||||
def _get_definition_names(parso_cache_node, used_names, name_key):
|
def _get_definition_names(parso_cache_node, used_names, name_key):
|
||||||
|
if parso_cache_node is None:
|
||||||
|
names = used_names.get(name_key, ())
|
||||||
|
return tuple(name for name in names if name.is_definition(include_setitem=True))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for_module = _definition_name_cache[parso_cache_node]
|
for_module = _definition_name_cache[parso_cache_node]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -88,11 +92,16 @@ class _AbstractUsedNamesFilter(AbstractFilter):
|
|||||||
# used_names. However that also does not work, because it has a
|
# used_names. However that also does not work, because it has a
|
||||||
# reference from the module, which itself is referenced by any node
|
# reference from the module, which itself is referenced by any node
|
||||||
# through parents.
|
# through parents.
|
||||||
self._parso_cache_node = get_parso_cache_node(
|
path = module_context.py__file__()
|
||||||
module_context.inference_state.latest_grammar
|
if path is None:
|
||||||
if module_context.is_stub() else module_context.inference_state.grammar,
|
# If the path is None, there is no guarantee that parso caches it.
|
||||||
module_context.py__file__()
|
self._parso_cache_node = None
|
||||||
)
|
else:
|
||||||
|
self._parso_cache_node = get_parso_cache_node(
|
||||||
|
module_context.inference_state.latest_grammar
|
||||||
|
if module_context.is_stub() else module_context.inference_state.grammar,
|
||||||
|
path
|
||||||
|
)
|
||||||
self._used_names = module_context.tree_node.get_used_names()
|
self._used_names = module_context.tree_node.get_used_names()
|
||||||
self.parent_context = parent_context
|
self.parent_context = parent_context
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user