def complete_dict(module_context, code_lines, leaf, position, string, fuzzy): bracket_leaf = leaf if bracket_leaf != '[': bracket_leaf = leaf.get_previous_leaf() cut_end_quote = '' if string: cut_end_quote = get_quote_ending(string, code_lines, position, invert_result=True) if bracket_leaf == '[': if string is None and leaf is not bracket_leaf: string = cut_value_at_position(leaf, position) context = module_context.create_context(bracket_leaf) before_bracket_leaf = bracket_leaf.get_previous_leaf() if before_bracket_leaf.type in ('atom', 'trailer', 'name'): values = infer_call_of_leaf(context, before_bracket_leaf) return list( _completions_for_dicts( module_context.inference_state, values, '' if string is None else string, cut_end_quote, fuzzy=fuzzy, )) return []
def infer(self, context, name): def_ = name.get_definition(import_name_always=True) if def_ is not None: type_ = def_.type is_classdef = type_ == 'classdef' if is_classdef or type_ == 'funcdef': if is_classdef: c = ClassValue(self, context, name.parent) else: c = FunctionValue.from_context(context, name.parent) return ValueSet([c]) if type_ == 'expr_stmt': is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return infer_expr_stmt(context, def_, name) if type_ == 'for_stmt': container_types = context.infer_node(def_.children[3]) cn = ContextualizedNode(context, def_.children[3]) for_types = iterate_values(container_types, cn) n = TreeNameDefinition(context, name) return check_tuple_assignments(n, for_types) if type_ in ('import_from', 'import_name'): return imports.infer_import(context, name) if type_ == 'with_stmt': return tree_name_to_values(self, context, name) elif type_ == 'param': return context.py__getattribute__(name.value, position=name.end_pos) else: result = follow_error_node_imports_if_possible(context, name) if result is not None: return result return helpers.infer_call_of_leaf(context, name)
def _is_fixture(self, decorated): decorators = decorated.children[0] if decorators.type == 'decorators': decorators = decorators.children else: decorators = [decorators] for decorator in decorators: dotted_name = decorator.children[1] # A heuristic, this makes it faster. if 'fixture' in dotted_name.get_code(): if dotted_name.type == 'atom_expr': # Since Python3.9 a decorator does not have dotted names # anymore. last_trailer = dotted_name.children[-1] last_leaf = last_trailer.get_last_leaf() if last_leaf == ')': values = infer_call_of_leaf( self.parent_context, last_leaf, cut_own_trailer=True) else: values = self.parent_context.infer_node(dotted_name) else: values = self.parent_context.infer_node(dotted_name) for value in values: if value.name.get_qualified_names(include_module_names=True) \ == ('_pytest', 'fixtures', 'fixture'): return True return False
def _analysis(self): self._inference_state.is_analysis = True self._inference_state.analysis_modules = [self._module_node] module = self._get_module_context() try: for node in get_executable_nodes(self._module_node): context = module.create_context(node) if node.type in ('funcdef', 'classdef'): # Resolve the decorators. tree_name_to_values(self._inference_state, context, node.children[1]) elif isinstance(node, tree.Import): import_names = set(node.get_defined_names()) if node.is_nested(): import_names |= set(path[-1] for path in node.get_paths()) for n in import_names: imports.infer_import(context, n) elif node.type == 'expr_stmt': types = context.infer_node(node) for testlist in node.children[:-1:2]: # Iterate tuples. unpack_tuple_to_dict(context, types, testlist) else: if node.type == 'name': defs = self._inference_state.infer(context, node) else: defs = infer_call_of_leaf(context, node) try_iter_content(defs) self._inference_state.reset_recursion_limitations() ana = [a for a in self._inference_state.analysis if self.path == a.path] return sorted(set(ana), key=lambda x: x.line) finally: self._inference_state.is_analysis = False
def _trailer_completions(self, previous_leaf): user_value = get_user_context(self._module_context, self._position) inferred_context = self._module_context.create_context(previous_leaf) values = infer_call_of_leaf(inferred_context, previous_leaf) completion_names = [] debug.dbg('trailer completion values: %s', values, color='MAGENTA') for value in values: for filter in value.get_filters(origin_scope=user_value.tree_node): completion_names += filter.values() python_values = convert_values(values) for c in python_values: if c not in values: for filter in c.get_filters(origin_scope=user_value.tree_node): completion_names += filter.values() return completion_names
def _complete_trailer(self, previous_leaf): inferred_context = self._module_context.create_context(previous_leaf) values = infer_call_of_leaf(inferred_context, previous_leaf) debug.dbg('trailer completion values: %s', values, color='MAGENTA') # The cached name simply exists to make speed optimizations for certain # modules. cached_name = None if len(values) == 1: v, = values if v.is_module(): if len(v.string_names) == 1: module_name = v.string_names[0] if module_name in ('numpy', 'tensorflow', 'matplotlib', 'pandas'): cached_name = module_name return cached_name, self._complete_trailer_for_values(values)
def infer(inference_state, context, leaf): if leaf.type == 'name': return inference_state.infer(context, leaf) parent = leaf.parent definitions = NO_VALUES if parent.type == 'atom': # e.g. `(a + b)` definitions = context.infer_node(leaf.parent) elif parent.type == 'trailer': # e.g. `a()` definitions = infer_call_of_leaf(context, leaf) elif isinstance(leaf, tree.Literal): # e.g. `"foo"` or `1.0` return infer_atom(context, leaf) elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'): return get_string_value_set(inference_state) return definitions
def infer_goto_definition(inference_state, context, leaf): if leaf.type == 'name': # In case of a name we can just use goto_definition which does all the # magic itself. return inference_state.goto_definitions(context, leaf) parent = leaf.parent definitions = NO_VALUES if parent.type == 'atom': # e.g. `(a + b)` definitions = context.infer_node(leaf.parent) elif parent.type == 'trailer': # e.g. `a()` definitions = infer_call_of_leaf(context, leaf) elif isinstance(leaf, tree.Literal): # e.g. `"foo"` or `1.0` return infer_atom(context, leaf) elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'): return get_string_value_set(inference_state) return definitions
def _internal_check_array_additions(context, sequence): """ Checks if a `Array` has "add" (append, insert, extend) statements: >>> a = [""] >>> a.append(1) """ from jedi.inference import arguments debug.dbg('Dynamic array search for %s' % sequence, color='MAGENTA') module_context = context.get_root_context() if not settings.dynamic_array_additions or module_context.is_compiled(): debug.dbg('Dynamic array search aborted.', color='MAGENTA') return NO_VALUES def find_additions(context, arglist, add_name): params = list( arguments.TreeArguments(context.inference_state, context, arglist).unpack()) result = set() if add_name in ['insert']: params = params[1:] if add_name in ['append', 'add', 'insert']: for key, lazy_value in params: result.add(lazy_value) elif add_name in ['extend', 'update']: for key, lazy_value in params: result |= set(lazy_value.infer().iterate()) return result temp_param_add, settings.dynamic_params_for_other_modules = \ settings.dynamic_params_for_other_modules, False is_list = sequence.name.string_name == 'list' search_names = (['append', 'extend', 'insert'] if is_list else ['add', 'update']) added_types = set() for add_name in search_names: try: possible_names = module_context.tree_node.get_used_names( )[add_name] except KeyError: continue else: for name in possible_names: value_node = context.tree_node if not (value_node.start_pos < name.start_pos < value_node.end_pos): continue trailer = name.parent power = trailer.parent trailer_pos = power.children.index(trailer) try: execution_trailer = power.children[trailer_pos + 1] except IndexError: continue else: if execution_trailer.type != 'trailer' \ or execution_trailer.children[0] != '(' \ or execution_trailer.children[1] == ')': continue random_context = context.create_context(name) with recursion.execution_allowed(context.inference_state, power) as allowed: if allowed: found = infer_call_of_leaf(random_context, name, cut_own_trailer=True) if sequence in found: # The arrays match. Now add the results added_types |= find_additions( random_context, execution_trailer.children[1], add_name) # reset settings settings.dynamic_params_for_other_modules = temp_param_add debug.dbg('Dynamic array result %s' % added_types, color='MAGENTA') return added_types
def goto(self): context = self.parent_context name = self.tree_name definition = name.get_definition(import_name_always=True) if definition is not None: type_ = definition.type if type_ == 'expr_stmt': # Only take the parent, because if it's more complicated than just # a name it's something you can "goto" again. is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return [self] elif type_ in ('import_from', 'import_name'): from jedi.inference.imports import goto_import module_names = goto_import(context, name) return module_names else: return [self] else: from jedi.inference.imports import follow_error_node_imports_if_possible values = follow_error_node_imports_if_possible(context, name) if values is not None: return [value.name for value in values] par = name.parent node_type = par.type if node_type == 'argument' and par.children[1] == '=' and par.children[ 0] == name: # Named param goto. trailer = par.parent if trailer.type == 'arglist': trailer = trailer.parent if trailer.type != 'classdef': if trailer.type == 'decorator': value_set = context.infer_node(trailer.children[1]) else: i = trailer.parent.children.index(trailer) to_infer = trailer.parent.children[:i] if to_infer[0] == 'await': to_infer.pop(0) value_set = context.infer_node(to_infer[0]) from jedi.inference.syntax_tree import infer_trailer for trailer in to_infer[1:]: value_set = infer_trailer(context, value_set, trailer) param_names = [] for value in value_set: for signature in value.get_signatures(): for param_name in signature.get_param_names(): if param_name.string_name == name.value: param_names.append(param_name) return param_names elif node_type == 'dotted_name': # Is a decorator. index = par.children.index(name) if index > 0: new_dotted = deep_ast_copy(par) new_dotted.children[index - 1:] = [] values = context.infer_node(new_dotted) return unite( value.goto(name, name_context=context) for value in values) if node_type == 'trailer' and par.children[0] == '.': values = infer_call_of_leaf(context, name, cut_own_trailer=True) return values.goto(name, name_context=context) else: stmt = search_ancestor(name, 'expr_stmt', 'lambdef') or name if stmt.type == 'lambdef': stmt = name return context.goto(name, position=stmt.start_pos)
def _complete_trailer(self, previous_leaf): inferred_context = self._module_context.create_context(previous_leaf) values = infer_call_of_leaf(inferred_context, previous_leaf) debug.dbg('trailer completion values: %s', values, color='MAGENTA') return self._complete_trailer_for_values(values)