Example #1
0
 def _scope_copy(self, scope):
     raise NotImplementedError
     """ Copies a scope (e.g. `if foo:`) in an execution """
     if scope != self.base.base_func:
         # Just make sure the parents been copied.
         self._scope_copy(scope.parent)
         helpers.deep_ast_copy(scope, self._copy_dict)
Example #2
0
    def _eval_node(self, index=0):
        """
        The first part `x + 1` of the list comprehension:

            [x + 1 for x in foo]
        """
        comp_for = self._get_comp_for()
        # For nested comprehensions we need to search the last one.
        last_comp = list(comp_for.get_comp_fors())[-1]
        return helpers.deep_ast_copy(self._get_comprehension().children[index], parent=last_comp)
Example #3
0
 def _copy_list(self, lst):
     """
     Copies a list attribute of a parser Function. Copying is very
     expensive, because it is something like `copy.deepcopy`. However, these
     copied objects can be used for the executions, as if they were in the
     execution.
     """
     objects = []
     for element in lst:
         self._scope_copy(element.parent)
         copied = helpers.deep_ast_copy(element, self._copy_dict)
         objects.append(copied)
     return objects
    def __init__(self, evaluator, base, *args, **kwargs):
        super(FunctionExecution, self).__init__(evaluator, base, *args, **kwargs)
        self._copy_dict = {}
        funcdef = base.base_func
        if isinstance(funcdef, mixed.MixedObject):
            # The extra information in mixed is not needed anymore. We can just
            # unpack it and give it the tree object.
            funcdef = funcdef.definition

        # Just overwrite the old version. We don't need it anymore.
        funcdef = helpers.deep_ast_copy(funcdef, new_elements=self._copy_dict)
        for child in funcdef.children:
            if child.type not in ('operator', 'keyword'):
                # Not all nodes are properly copied by deep_ast_copy.
                child.parent = self
        self.children = funcdef.children
        self.names_dict = funcdef.names_dict
    def _eval_node(self, index=0):
        """
        The first part `x + 1` of the list comprehension:

            [x + 1 for x in foo]
        """
        comp_for = self._get_comp_for()
        # For nested comprehensions we need to search the last one.
        from jedi.evaluate.representation import InstanceElement
        node = self._get_comprehension().children[index]
        if isinstance(node, InstanceElement):
            # This seems to be a strange case that I haven't found a way to
            # write tests against. However since it's my new goal to get rid of
            # InstanceElement anyway, I don't care.
            node = node.var
        last_comp = list(comp_for.get_comp_fors())[-1]
        return helpers.deep_ast_copy(node, parent=last_comp)
Example #6
0
    def eval_node(self):
        """
        The first part `x + 1` of the list comprehension:

            [x + 1 for x in foo]
        """
        comprehension = self._atom.children[1]
        # For nested comprehensions we need to search the last one.
        last = comprehension.children[-1]
        last_comp = comprehension.children[1]
        while True:
            if isinstance(last, tree.CompFor):
                last_comp = last
            elif not tree.is_node(last, 'comp_if'):
                break
            last = last.children[-1]

        return helpers.deep_ast_copy(comprehension.children[0], parent=last_comp)
Example #7
0
 def __init__(self, evaluator, base, *args, **kwargs):
     super(FunctionExecution, self).__init__(evaluator, base, *args, **kwargs)
     self._copy_dict = {}
     new_func = helpers.deep_ast_copy(base.base_func, self, self._copy_dict)
     self.children = new_func.children
     self.names_dict = new_func.names_dict
Example #8
0
    def goto(self, context, 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 [TreeNameDefinition(context, name)]
            elif type_ == 'param':
                return [ParamName(context, name)]
            elif type_ in ('funcdef', 'classdef'):
                return [TreeNameDefinition(context, name)]
            elif type_ in ('import_from', 'import_name'):
                module_names = imports.infer_import(context,
                                                    name,
                                                    is_goto=True)
                return module_names
        else:
            contexts = self._follow_error_node_imports_if_possible(
                context, name)
            if contexts is not None:
                return [context.name for context in contexts]

        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':
                    context_set = context.eval_node(trailer.children[1])
                else:
                    i = trailer.parent.children.index(trailer)
                    to_evaluate = trailer.parent.children[:i]
                    if to_evaluate[0] == 'await':
                        to_evaluate.pop(0)
                    context_set = context.eval_node(to_evaluate[0])
                    for trailer in to_evaluate[1:]:
                        context_set = eval_trailer(context, context_set,
                                                   trailer)
                param_names = []
                for context in context_set:
                    for signature in context.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 = helpers.deep_ast_copy(par)
                new_dotted.children[index - 1:] = []
                values = context.eval_node(new_dotted)
                return unite(
                    value.py__getattribute__(
                        name, name_context=context, is_goto=True)
                    for value in values)

        if node_type == 'trailer' and par.children[0] == '.':
            values = helpers.evaluate_call_of_leaf(context,
                                                   name,
                                                   cut_own_trailer=True)
            return values.py__getattribute__(name,
                                             name_context=context,
                                             is_goto=True)
        else:
            stmt = tree.search_ancestor(name, 'expr_stmt', 'lambdef') or name
            if stmt.type == 'lambdef':
                stmt = name
            return context.py__getattribute__(name,
                                              position=stmt.start_pos,
                                              search_global=True,
                                              is_goto=True)
Example #9
0
    def goto(self, context, 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 [TreeNameDefinition(context, name)]
            elif type_ == 'param':
                return [ParamName(context, name)]
            elif type_ in ('funcdef', 'classdef'):
                return [TreeNameDefinition(context, name)]
            elif type_ in ('import_from', 'import_name'):
                module_names = imports.infer_import(context, name, is_goto=True)
                return module_names

        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':
                    context_set = context.eval_node(trailer.children[1])
                else:
                    i = trailer.parent.children.index(trailer)
                    to_evaluate = trailer.parent.children[:i]
                    if to_evaluate[0] == 'await':
                        to_evaluate.pop(0)
                    context_set = context.eval_node(to_evaluate[0])
                    for trailer in to_evaluate[1:]:
                        context_set = eval_trailer(context, context_set, trailer)
                param_names = []
                for context in context_set:
                    try:
                        get_param_names = context.get_param_names
                    except AttributeError:
                        pass
                    else:
                        for param_name in 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 = helpers.deep_ast_copy(par)
                new_dotted.children[index - 1:] = []
                values = context.eval_node(new_dotted)
                return unite(
                    value.py__getattribute__(name, name_context=context, is_goto=True)
                    for value in values
                )

        if node_type == 'trailer' and par.children[0] == '.':
            values = helpers.evaluate_call_of_leaf(context, name, cut_own_trailer=True)
            return unite(
                value.py__getattribute__(name, name_context=context, is_goto=True)
                for value in values
            )
        else:
            stmt = tree.search_ancestor(
                name, 'expr_stmt', 'lambdef'
            ) or name
            if stmt.type == 'lambdef':
                stmt = name
            return context.py__getattribute__(
                name,
                position=stmt.start_pos,
                search_global=True, is_goto=True
            )
Example #10
0
    def goto(self, name):
        def resolve_implicit_imports(names):
            for name in names:
                if isinstance(name.parent, helpers.FakeImport):
                    # Those are implicit imports.
                    s = imports.ImportWrapper(self, name)
                    for n in s.follow(is_goto=True):
                        yield n
                else:
                    yield name

        stmt = name.get_definition()
        par = name.parent
        if par.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':
                    types = self.eval_element(trailer.children[1])
                else:
                    i = trailer.parent.children.index(trailer)
                    to_evaluate = trailer.parent.children[:i]
                    types = self.eval_element(to_evaluate[0])
                    for trailer in to_evaluate[1:]:
                        types = self.eval_trailer(types, trailer)
                param_names = []
                for typ in types:
                    try:
                        params = typ.params
                    except AttributeError:
                        pass
                    else:
                        param_names += [
                            param.name for param in params
                            if param.name.value == name.value
                        ]
                return param_names
        elif isinstance(par,
                        tree.ExprStmt) and name in par.get_defined_names():
            # Only take the parent, because if it's more complicated than just
            # a name it's something you can "goto" again.
            return [name]
        elif isinstance(
                par,
            (tree.Param, tree.Function, tree.Class)) and par.name is name:
            return [name]
        elif isinstance(stmt, tree.Import):
            modules = imports.ImportWrapper(self, name).follow(is_goto=True)
            return list(resolve_implicit_imports(modules))
        elif par.type == 'dotted_name':  # Is a decorator.
            index = par.children.index(name)
            if index > 0:
                new_dotted = helpers.deep_ast_copy(par)
                new_dotted.children[index - 1:] = []
                types = self.eval_element(new_dotted)
                return resolve_implicit_imports(
                    iterable.unite(
                        self.find_types(typ, name, is_goto=True)
                        for typ in types))

        scope = name.get_parent_scope()
        if tree.is_node(par, 'trailer') and par.children[0] == '.':
            call = helpers.call_of_leaf(name, cut_own_trailer=True)
            types = self.eval_element(call)
            return resolve_implicit_imports(
                iterable.unite(
                    self.find_types(typ, name, is_goto=True) for typ in types))
        else:
            if stmt.type != 'expr_stmt':
                # We only need to adjust the start_pos for statements, because
                # there the name cannot be used.
                stmt = name
            return self.find_types(scope,
                                   name,
                                   stmt.start_pos,
                                   search_global=True,
                                   is_goto=True)
Example #11
0
    def goto(self, name):
        def resolve_implicit_imports(names):
            for name in names:
                if isinstance(name.parent, helpers.FakeImport):
                    # Those are implicit imports.
                    s = imports.ImportWrapper(self, name)
                    for n in s.follow(is_goto=True):
                        yield n
                else:
                    yield name

        stmt = name.get_definition()
        par = name.parent
        if par.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':
                    types = self.eval_element(trailer.children[1])
                else:
                    i = trailer.parent.children.index(trailer)
                    to_evaluate = trailer.parent.children[:i]
                    types = self.eval_element(to_evaluate[0])
                    for trailer in to_evaluate[1:]:
                        types = self.eval_trailer(types, trailer)
                param_names = []
                for typ in types:
                    try:
                        params = typ.params
                    except AttributeError:
                        pass
                    else:
                        param_names += [param.name for param in params
                                        if param.name.value == name.value]
                return param_names
        elif isinstance(par, tree.ExprStmt) and name in par.get_defined_names():
            # Only take the parent, because if it's more complicated than just
            # a name it's something you can "goto" again.
            return [name]
        elif isinstance(par, (tree.Param, tree.Function, tree.Class)) and par.name is name:
            return [name]
        elif isinstance(stmt, tree.Import):
            modules = imports.ImportWrapper(self, name).follow(is_goto=True)
            return list(resolve_implicit_imports(modules))
        elif par.type == 'dotted_name':  # Is a decorator.
            index = par.children.index(name)
            if index > 0:
                new_dotted = helpers.deep_ast_copy(par)
                new_dotted.children[index - 1:] = []
                types = self.eval_element(new_dotted)
                return resolve_implicit_imports(iterable.unite(
                    self.find_types(typ, name, is_goto=True) for typ in types
                ))

        scope = name.get_parent_scope()
        if tree.is_node(par, 'trailer') and par.children[0] == '.':
            call = helpers.call_of_leaf(name, cut_own_trailer=True)
            types = self.eval_element(call)
            return resolve_implicit_imports(iterable.unite(
                self.find_types(typ, name, is_goto=True) for typ in types
            ))
        else:
            if stmt.type != 'expr_stmt':
                # We only need to adjust the start_pos for statements, because
                # there the name cannot be used.
                stmt = name
            return self.find_types(scope, name, stmt.start_pos,
                                   search_global=True, is_goto=True)
Example #12
0
    def goto(self, context, name):
        stmt = name.get_definition()
        par = name.parent
        if par.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':
                    types = self.eval_element(context, trailer.children[1])
                else:
                    i = trailer.parent.children.index(trailer)
                    to_evaluate = trailer.parent.children[:i]
                    types = self.eval_element(context, to_evaluate[0])
                    for trailer in to_evaluate[1:]:
                        types = self.eval_trailer(context, types, trailer)
                param_names = []
                for typ in types:
                    try:
                        get_param_names = typ.get_param_names
                    except AttributeError:
                        pass
                    else:
                        for param_name in get_param_names():
                            if param_name.string_name == name.value:
                                param_names.append(param_name)
                return param_names
        elif par.type == 'expr_stmt' and name in par.get_defined_names():
            # Only take the parent, because if it's more complicated than just
            # a name it's something you can "goto" again.
            return [TreeNameDefinition(context, name)]
        elif par.type == 'param' and par.name:
            return [ParamName(context, name)]
        elif isinstance(par, (tree.Param, tree.Function, tree.Class)) and par.name is name:
            return [TreeNameDefinition(context, name)]
        elif isinstance(stmt, tree.Import):
            module_names = imports.infer_import(context, name, is_goto=True)
            return module_names
        elif par.type == 'dotted_name':  # Is a decorator.
            index = par.children.index(name)
            if index > 0:
                new_dotted = helpers.deep_ast_copy(par)
                new_dotted.children[index - 1:] = []
                values = self.eval_element(context, new_dotted)
                return unite(
                    value.py__getattribute__(name, name_context=context, is_goto=True)
                    for value in values
                )

        if par.type == 'trailer' and par.children[0] == '.':
            values = helpers.evaluate_call_of_leaf(context, name, cut_own_trailer=True)
            return unite(
                value.py__getattribute__(name, name_context=context, is_goto=True)
                for value in values
            )
        else:
            if stmt.type != 'expr_stmt':
                # We only need to adjust the start_pos for statements, because
                # there the name cannot be used.
                stmt = name
            return context.py__getattribute__(
                name,
                position=stmt.start_pos,
                search_global=True, is_goto=True
            )
Example #13
0
    def goto(self, stmt, call_path):
        if isinstance(stmt, pr.Import):
            # Nowhere to goto for aliases
            if stmt.alias == call_path[0]:
                return [call_path[0]]

            names = stmt.get_all_import_names()
            if stmt.alias:
                names = names[:-1]
            # Filter names that are after our Name
            removed_names = len(names) - names.index(call_path[0]) - 1
            i = imports.ImportWrapper(self, stmt, kill_count=removed_names,
                                      nested_resolve=True)
            return i.follow(is_goto=True)

        # Return the name defined in the call_path, if it's part of the
        # statement name definitions. Only return, if it's one name and one
        # name only. Otherwise it's a mixture between a definition and a
        # reference. In this case it's just a definition. So we stay on it.
        if len(call_path) == 1 and isinstance(call_path[0], pr.Name) \
                and call_path[0] in stmt.get_defined_names():
            # Named params should get resolved to their param definitions.
            if pr.Array.is_type(stmt.parent, pr.Array.TUPLE, pr.Array.NOARRAY) \
                    and stmt.parent.previous:
                call = deep_ast_copy(stmt.parent.previous)
                # We have made a copy, so we're fine to change it.
                call.next = None
                while call.previous is not None:
                    call = call.previous
                param_names = []
                named_param_name = stmt.get_defined_names()[0]
                for typ in self.eval_call(call):
                    if isinstance(typ, er.Class):
                        params = []
                        for init_method in typ.py__getattribute__('__init__'):
                            params += init_method.params
                    else:
                        params = typ.params
                    for param in params:
                        if unicode(param.get_name()) == unicode(named_param_name):
                            param_names.append(param.get_name())
                return param_names
            return [call_path[0]]

        scope = stmt.get_parent_scope()
        pos = stmt.start_pos
        first_part, search_name_part = call_path[:-1], call_path[-1]

        if first_part:
            scopes = self.eval_call_path(iter(first_part), scope, pos)
            search_global = False
            pos = None
        else:
            scopes = [scope]
            search_global = True

        follow_res = []
        for s in scopes:
            follow_res += self.find_types(s, search_name_part, pos,
                                          search_global=search_global, is_goto=True)
        return follow_res
Example #14
0
    def goto(self, context, name):
        stmt = name.get_definition()
        par = name.parent
        if par.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':
                    types = self.eval_element(context, trailer.children[1])
                else:
                    i = trailer.parent.children.index(trailer)
                    to_evaluate = trailer.parent.children[:i]
                    types = self.eval_element(context, to_evaluate[0])
                    for trailer in to_evaluate[1:]:
                        types = self.eval_trailer(context, types, trailer)
                param_names = []
                for typ in types:
                    try:
                        get_param_names = typ.get_param_names
                    except AttributeError:
                        pass
                    else:
                        for param_name in get_param_names():
                            if param_name.string_name == name.value:
                                param_names.append(param_name)
                return param_names
        elif par.type == 'expr_stmt' and name in par.get_defined_names():
            # Only take the parent, because if it's more complicated than just
            # a name it's something you can "goto" again.
            return [TreeNameDefinition(context, name)]
        elif par.type == 'param' and par.name:
            return [ParamName(context, name)]
        elif isinstance(
                par,
            (tree.Param, tree.Function, tree.Class)) and par.name is name:
            return [TreeNameDefinition(context, name)]
        elif isinstance(stmt, tree.Import):
            module_names = imports.infer_import(context, name, is_goto=True)
            return module_names
        elif par.type == 'dotted_name':  # Is a decorator.
            index = par.children.index(name)
            if index > 0:
                new_dotted = helpers.deep_ast_copy(par)
                new_dotted.children[index - 1:] = []
                values = self.eval_element(context, new_dotted)
                return unite(
                    value.py__getattribute__(
                        name, name_context=context, is_goto=True)
                    for value in values)

        if par.type == 'trailer' and par.children[0] == '.':
            values = helpers.evaluate_call_of_leaf(context,
                                                   name,
                                                   cut_own_trailer=True)
            return unite(
                value.py__getattribute__(
                    name, name_context=context, is_goto=True)
                for value in values)
        else:
            if stmt.type != 'expr_stmt':
                # We only need to adjust the start_pos for statements, because
                # there the name cannot be used.
                stmt = name
            return context.py__getattribute__(name,
                                              position=stmt.start_pos,
                                              search_global=True,
                                              is_goto=True)
Example #15
0
 def __init__(self, evaluator, base, *args, **kwargs):
     super(FunctionExecution, self).__init__(evaluator, base, *args, **kwargs)
     self._copy_dict = {}
     new_func = helpers.deep_ast_copy(base.base_func, self, self._copy_dict)
     self.children = new_func.children
     self.names_dict = new_func.names_dict
Example #16
0
 def _scope_copy(self, scope):
     """ Copies a scope (e.g. `if foo:`) in an execution """
     if scope != self.base.base_func:
         # Just make sure the parents been copied.
         self._scope_copy(scope.parent)
         helpers.deep_ast_copy(scope, self._copy_dict)