Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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,
    )
Exemple #4
0
 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)
Exemple #5
0
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 []
Exemple #6
0
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 []
Exemple #7
0
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])
Exemple #8
0
 def infer(self):
     return compiled.get_string_context_set(self.parent_context.evaluator)
Exemple #9
0
 def infer(self):
     return compiled.get_string_context_set(self.parent_context.evaluator)