def evaluate_call_of_leaf(context, leaf, cut_own_trailer=False): """ Creates a "call" node that consist of all ``trailer`` and ``power`` objects. E.g. if you call it with ``append``:: list([]).append(3) or None You would get a node with the content ``list([]).append`` back. This generates a copy of the original ast node. If you're using the leaf, e.g. the bracket `)` it will return ``list([])``. We use this function for two purposes. Given an expression ``bar.foo``, we may want to - infer the type of ``foo`` to offer completions after foo - infer the type of ``bar`` to be able to jump to the definition of foo The option ``cut_own_trailer`` must be set to true for the second purpose. """ trailer = leaf.parent if trailer.type == 'fstring': from jedi.evaluate import compiled return compiled.get_string_context_set(context.evaluator) # The leaf may not be the last or first child, because there exist three # different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples # we should not match anything more than x. if trailer.type != 'trailer' or leaf not in (trailer.children[0], trailer.children[-1]): if trailer.type == 'atom': return context.eval_node(trailer) return context.eval_node(leaf) power = trailer.parent index = power.children.index(trailer) if cut_own_trailer: cut = index else: cut = index + 1 if power.type == 'error_node': start = index while True: start -= 1 base = power.children[start] if base.type != 'trailer': break trailers = power.children[start + 1: index + 1] else: base = power.children[0] trailers = power.children[1:cut] if base == 'await': base = trailers[0] trailers = trailers[1:] values = context.eval_node(base) from jedi.evaluate.syntax_tree import eval_trailer for trailer in trailers: values = eval_trailer(context, values, trailer) return values
def evaluate_call_of_leaf(context, leaf, cut_own_trailer=False): """ Creates a "call" node that consist of all ``trailer`` and ``power`` objects. E.g. if you call it with ``append``:: list([]).append(3) or None You would get a node with the content ``list([]).append`` back. This generates a copy of the original ast node. If you're using the leaf, e.g. the bracket `)` it will return ``list([])``. We use this function for two purposes. Given an expression ``bar.foo``, we may want to - infer the type of ``foo`` to offer completions after foo - infer the type of ``bar`` to be able to jump to the definition of foo The option ``cut_own_trailer`` must be set to true for the second purpose. """ trailer = leaf.parent if trailer.type == 'fstring': from jedi.evaluate import compiled return compiled.get_string_context_set(context.evaluator) # The leaf may not be the last or first child, because there exist three # different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples # we should not match anything more than x. if trailer.type != 'trailer' or leaf not in (trailer.children[0], trailer.children[-1]): if trailer.type == 'atom': return context.eval_node(trailer) return context.eval_node(leaf) power = trailer.parent index = power.children.index(trailer) if cut_own_trailer: cut = index else: cut = index + 1 if power.type == 'error_node': start = index while True: start -= 1 base = power.children[start] if base.type != 'trailer': break trailers = power.children[start + 1: index + 1] else: base = power.children[0] trailers = power.children[1:cut] if base == 'await': base = trailers[0] trailers = trailers[1:] values = context.eval_node(base) from jedi.evaluate.syntax_tree import eval_trailer for trailer in trailers: values = eval_trailer(context, values, trailer) return values
def evaluate_goto_definition(evaluator, context, leaf, prefer_stubs=False): if leaf.type == 'name': # In case of a name we can just use goto_definition which does all the # magic itself. if prefer_stubs: return evaluator.goto_stub_definitions(context, leaf) else: return evaluator.goto_definitions(context, leaf) parent = leaf.parent definitions = NO_CONTEXTS if parent.type == 'atom': definitions = context.eval_node(leaf.parent) elif parent.type == 'trailer': definitions = evaluate_call_of_leaf(context, leaf) elif isinstance(leaf, tree.Literal): return eval_atom(context, leaf) elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'): return get_string_context_set(evaluator) if prefer_stubs: return definitions from jedi.evaluate.gradual.conversion import try_stubs_to_actual_context_set return try_stubs_to_actual_context_set( definitions, prefer_stub_to_compiled=True, )
def infer(self): if self._string_value is not None: s = self._string_value if self.parent_context.evaluator.environment.version_info.major == 2 \ and not isinstance(s, bytes): s = s.encode('utf-8') return ContextSet( [create_simple_object(self.parent_context.evaluator, s)]) return compiled.get_string_context_set(self.parent_context.evaluator)
def evaluate_goto_definition(evaluator, context, leaf): if leaf.type == 'name': # In case of a name we can just use goto_definition which does all the # magic itself. return evaluator.goto_definitions(context, leaf) parent = leaf.parent if parent.type == 'atom': return context.eval_node(leaf.parent) elif parent.type == 'trailer': return evaluate_call_of_leaf(context, leaf) elif isinstance(leaf, tree.Literal): return eval_atom(context, leaf) elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'): return get_string_context_set(evaluator) return []
def evaluate_goto_definition(evaluator, context, leaf): if leaf.type == 'name': # In case of a name we can just use goto_definition which does all the # magic itself. return evaluator.goto_definitions(context, leaf) parent = leaf.parent if parent.type == 'atom': return context.eval_node(leaf.parent) elif parent.type == 'trailer': return evaluate_call_of_leaf(context, leaf) elif isinstance(leaf, tree.Literal): return eval_atom(context, leaf) elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'): return get_string_context_set(evaluator) return []
def eval_atom(context, atom): """ Basically to process ``atom`` nodes. The parser sometimes doesn't generate the node (because it has just one child). In that case an atom might be a name or a literal as well. """ if atom.type == 'name': if atom.value in ('True', 'False', 'None'): # Python 2... return ContextSet( [compiled.builtin_from_name(context.evaluator, atom.value)]) # This is the first global lookup. stmt = tree.search_ancestor(atom, 'expr_stmt', 'lambdef') or atom if stmt.type == 'lambdef': stmt = atom position = stmt.start_pos if _is_annotation_name(atom): # Since Python 3.7 (with from __future__ import annotations), # annotations are essentially strings and can reference objects # that are defined further down in code. Therefore just set the # position to None, so the finder will not try to stop at a certain # position in the module. position = None return context.py__getattribute__(name_or_str=atom, position=position, search_global=True) elif atom.type == 'keyword': # For False/True/None if atom.value in ('False', 'True', 'None'): return ContextSet( [compiled.builtin_from_name(context.evaluator, atom.value)]) elif atom.value == 'print': # print e.g. could be evaluated like this in Python 2.7 return NO_CONTEXTS elif atom.value == 'yield': # Contrary to yield from, yield can just appear alone to return a # value when used with `.send()`. return NO_CONTEXTS assert False, 'Cannot evaluate the keyword %s' % atom elif isinstance(atom, tree.Literal): string = context.evaluator.compiled_subprocess.safe_literal_eval( atom.value) return ContextSet( [compiled.create_simple_object(context.evaluator, string)]) elif atom.type == 'strings': # Will be multiple string. context_set = eval_atom(context, atom.children[0]) for string in atom.children[1:]: right = eval_atom(context, string) context_set = _eval_comparison(context.evaluator, context, context_set, u'+', right) return context_set elif atom.type == 'fstring': return compiled.get_string_context_set(context.evaluator) else: c = atom.children # Parentheses without commas are not tuples. if c[0] == '(' and not len(c) == 2 \ and not(c[1].type == 'testlist_comp' and len(c[1].children) > 1): return context.eval_node(c[1]) try: comp_for = c[1].children[1] except (IndexError, AttributeError): pass else: if comp_for == ':': # Dict comprehensions have a colon at the 3rd index. try: comp_for = c[1].children[3] except IndexError: pass if comp_for.type in ('comp_for', 'sync_comp_for'): return ContextSet([ iterable.comprehension_from_atom(context.evaluator, context, atom) ]) # It's a dict/list/tuple literal. array_node = c[1] try: array_node_c = array_node.children except AttributeError: array_node_c = [] if c[0] == '{' and (array_node == '}' or ':' in array_node_c or '**' in array_node_c): context = iterable.DictLiteralContext(context.evaluator, context, atom) else: context = iterable.SequenceLiteralContext(context.evaluator, context, atom) return ContextSet([context])
def infer(self): return compiled.get_string_context_set(self.parent_context.evaluator)
def infer(self): return compiled.get_string_context_set(self.parent_context.evaluator)