示例#1
0
    def eval_statement(self, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `pr.ExprStmt`.
        """
        debug.dbg('eval_statement %s (%s)', stmt, seek_name)
        types = self.eval_element(stmt.get_rhs())

        if seek_name:
            types = finder.check_tuple_assignments(types, seek_name)

        first_operation = stmt.first_operation()
        if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement):  # TODO don't check for this.
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            parent = er.wrap(self, stmt.get_parent_scope())
            left = self.find_types(parent, name, stmt.start_pos, search_global=True)
            if isinstance(stmt.get_parent_until(pr.ForStmt), pr.ForStmt):
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable.
                for r in types:
                    left = precedence.calculate(self, left, operator, [r])
                types = left
            else:
                types = precedence.calculate(self, left, operator, types)
        debug.dbg('eval_statement result %s', types)
        return types
    def eval_statement(self, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `pr.ExprStmt`.
        """
        debug.dbg('eval_statement %s (%s)', stmt, seek_name)
        types = self.eval_element(stmt.get_rhs())

        if seek_name:
            types = finder.check_tuple_assignments(types, seek_name)

        first_operation = stmt.first_operation()
        if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement):  # TODO don't check for this.
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            parent = er.wrap(self, stmt.get_parent_scope())
            left = self.find_types(parent, name, stmt.start_pos, search_global=True)
            if isinstance(stmt.get_parent_until(pr.ForStmt), pr.ForStmt):
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable.
                for r in types:
                    left = precedence.calculate(self, left, operator, [r])
                types = left
            else:
                types = precedence.calculate(self, left, operator, types)
        debug.dbg('eval_statement result %s', types)
        return types
示例#3
0
    def eval_statement(self, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `tree.ExprStmt`.
        """
        debug.dbg('eval_statement %s (%s)', stmt, seek_name)
        rhs = stmt.get_rhs()
        types = self.eval_element(rhs)

        if seek_name:
            types = finder.check_tuple_assignments(self, types, seek_name)

        first_operation = stmt.first_operation()
        if first_operation not in ('=', None) and not isinstance(
                stmt, er.InstanceElement
        ) and first_operation.type == 'operator':  # TODO don't check for this. id:458 gh:459
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            parent = self.wrap(stmt.get_parent_scope())
            left = self.find_types(parent,
                                   name,
                                   stmt.start_pos,
                                   search_global=True)

            for_stmt = stmt.get_parent_until(tree.ForStmt)
            if isinstance(for_stmt, tree.ForStmt) and types \
                    and for_stmt.defines_one_name():
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable. Also only do it, if the variable is not a tuple.
                node = for_stmt.get_input_node()
                for_iterables = self.eval_element(node)
                ordered = list(iterable.py__iter__(self, for_iterables, node))

                for index_types in ordered:
                    dct = {str(for_stmt.children[1]): index_types}
                    self.predefined_if_name_dict_dict[for_stmt] = dct
                    t = self.eval_element(rhs)
                    left = precedence.calculate(self, left, operator, t)
                types = left
                if ordered:
                    # If there are no for entries, we cannot iterate and the
                    # types are defined by += entries. Therefore the for loop
                    # is never called.
                    del self.predefined_if_name_dict_dict[for_stmt]
            else:
                types = precedence.calculate(self, left, operator, types)
        debug.dbg('eval_statement result %s', types)
        return types
示例#4
0
    def eval_statement(self, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `tree.ExprStmt`.
        """
        debug.dbg("eval_statement %s (%s)", stmt, seek_name)
        rhs = stmt.get_rhs()
        types = self.eval_element(rhs)

        if seek_name:
            types = finder.check_tuple_assignments(self, types, seek_name)

        first_operation = stmt.first_operation()
        if first_operation not in ("=", None) and not isinstance(
            stmt, er.InstanceElement
        ):  # TODO don't check for this.
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            parent = self.wrap(stmt.get_parent_scope())
            left = self.find_types(parent, name, stmt.start_pos, search_global=True)

            for_stmt = stmt.get_parent_until(tree.ForStmt)
            if isinstance(for_stmt, tree.ForStmt) and types and for_stmt.defines_one_name():
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable. Also only do it, if the variable is not a tuple.
                node = for_stmt.get_input_node()
                for_iterables = self.eval_element(node)
                ordered = list(iterable.py__iter__(self, for_iterables, node))

                for index_types in ordered:
                    dct = {str(for_stmt.children[1]): index_types}
                    self.predefined_if_name_dict_dict[for_stmt] = dct
                    t = self.eval_element(rhs)
                    left = precedence.calculate(self, left, operator, t)
                types = left
                if ordered:
                    # If there are no for entries, we cannot iterate and the
                    # types are defined by += entries. Therefore the for loop
                    # is never called.
                    del self.predefined_if_name_dict_dict[for_stmt]
            else:
                types = precedence.calculate(self, left, operator, types)
        debug.dbg("eval_statement result %s", types)
        return types
示例#5
0
    def _eval_stmt(self, context, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `tree.ExprStmt`.
        """
        debug.dbg('eval_statement %s (%s)', stmt, seek_name)
        rhs = stmt.get_rhs()
        types = self.eval_element(context, rhs)

        if seek_name:
            c_node = ContextualizedName(context, seek_name)
            types = finder.check_tuple_assignments(self, c_node, types)

        first_operation = stmt.first_operation()
        if first_operation not in (
                '=', None) and first_operation.type == 'operator':
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            left = context.py__getattribute__(name,
                                              position=stmt.start_pos,
                                              search_global=True)

            for_stmt = tree.search_ancestor(stmt, 'for_stmt')
            if for_stmt is not None and for_stmt.type == 'for_stmt' and types \
                    and for_stmt.defines_one_name():
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable. Also only do it, if the variable is not a tuple.
                node = for_stmt.get_input_node()
                cn = ContextualizedNode(context, node)
                ordered = list(iterable.py__iter__(self, cn.infer(), cn))

                for lazy_context in ordered:
                    dct = {str(for_stmt.children[1]): lazy_context.infer()}
                    with helpers.predefine_names(context, for_stmt, dct):
                        t = self.eval_element(context, rhs)
                        left = precedence.calculate(self, context, left,
                                                    operator, t)
                types = left
            else:
                types = precedence.calculate(self, context, left, operator,
                                             types)
        debug.dbg('eval_statement result %s', types)
        return types
示例#6
0
    def goto_definitions(self, name):
        def_ = name.get_definition()
        is_simple_name = name.parent.type not in ("power", "trailer")
        if is_simple_name:
            if name.parent.type in ("file_input", "classdef", "funcdef"):
                return [self.wrap(name.parent)]
            if def_.type == "expr_stmt" and name in def_.get_defined_names():
                return self.eval_statement(def_, name)
            elif def_.type == "for_stmt":
                container_types = self.eval_element(def_.children[3])
                for_types = iterable.py__iter__types(self, container_types, def_.children[3])
                return finder.check_tuple_assignments(self, for_types, name)
            elif def_.type in ("import_from", "import_name"):
                return imports.ImportWrapper(self, name).follow()

        call = helpers.call_of_leaf(name)
        return self.eval_element(call)
示例#7
0
    def _eval_stmt(self, context, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `tree.ExprStmt`.
        """
        debug.dbg('eval_statement %s (%s)', stmt, seek_name)
        rhs = stmt.get_rhs()
        types = self.eval_element(context, rhs)

        if seek_name:
            c_node = ContextualizedName(context, seek_name)
            types = finder.check_tuple_assignments(self, c_node, types)

        first_operation = stmt.first_operation()
        if first_operation not in ('=', None) and first_operation.type == 'operator':
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            left = context.py__getattribute__(
                name, position=stmt.start_pos, search_global=True)

            for_stmt = tree.search_ancestor(stmt, 'for_stmt')
            if for_stmt is not None and for_stmt.type == 'for_stmt' and types \
                    and for_stmt.defines_one_name():
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable. Also only do it, if the variable is not a tuple.
                node = for_stmt.get_input_node()
                cn = ContextualizedNode(context, node)
                ordered = list(iterable.py__iter__(self, cn.infer(), cn))

                for lazy_context in ordered:
                    dct = {str(for_stmt.children[1]): lazy_context.infer()}
                    with helpers.predefine_names(context, for_stmt, dct):
                        t = self.eval_element(context, rhs)
                        left = precedence.calculate(self, context, left, operator, t)
                types = left
            else:
                types = precedence.calculate(self, context, left, operator, types)
        debug.dbg('eval_statement result %s', types)
        return types
示例#8
0
    def goto_definitions(self, name):
        def_ = name.get_definition()
        is_simple_name = name.parent.type not in ('power', 'trailer')
        if is_simple_name:
            if name.parent.type in ('file_input', 'classdef', 'funcdef'):
                return [self.wrap(name.parent)]
            if def_.type == 'expr_stmt' and name in def_.get_defined_names():
                return self.eval_statement(def_, name)
            elif def_.type == 'for_stmt':
                container_types = self.eval_element(def_.children[3])
                for_types = iterable.py__iter__types(self, container_types,
                                                     def_.children[3])
                return finder.check_tuple_assignments(self, for_types, name)
            elif def_.type in ('import_from', 'import_name'):
                return imports.ImportWrapper(self, name).follow()

        call = helpers.call_of_leaf(name)
        return self.eval_element(call)
示例#9
0
    def goto_definitions(self, name):
        def_ = name.get_definition()
        is_simple_name = name.parent.type not in ('power', 'trailer')
        if is_simple_name:
            if name.parent.type == 'classdef' and name.parent.name == name:
                return [self.wrap(name.parent)]
            if name.parent.type in ('file_input', 'funcdef'):
                return [self.wrap(name.parent)]
            if def_.type == 'expr_stmt' and name in def_.get_defined_names():
                return self.eval_statement(def_, name)
            elif def_.type == 'for_stmt':
                container_types = self.eval_element(def_.children[3])
                for_types = iterable.py__iter__types(self, container_types, def_.children[3])
                return finder.check_tuple_assignments(self, for_types, name)
            elif def_.type in ('import_from', 'import_name'):
                return imports.ImportWrapper(self, name).follow()

        call = helpers.call_of_leaf(name)
        return self.eval_element(call)
示例#10
0
    def goto_definitions(self, context, name):
        def_ = name.get_definition()
        is_simple_name = name.parent.type not in ('power', 'trailer')
        if is_simple_name:
            if name.parent.type == 'classdef' and name.parent.name == name:
                return [er.ClassContext(self, name.parent, context)]
            elif name.parent.type == 'funcdef':
                return [er.FunctionContext(self, context, name.parent)]
            elif name.parent.type == 'file_input':
                raise NotImplementedError
            if def_.type == 'expr_stmt' and name in def_.get_defined_names():
                return self.eval_statement(context, def_, name)
            elif def_.type == 'for_stmt':
                container_types = self.eval_element(context, def_.children[3])
                for_types = iterable.py__iter__types(self, container_types,
                                                     def_.children[3])
                return finder.check_tuple_assignments(self, for_types, name)
            elif def_.type in ('import_from', 'import_name'):
                return imports.infer_import(context, name)

        return helpers.evaluate_call_of_leaf(context, name)
示例#11
0
    def goto_definitions(self, context, name):
        def_ = name.get_definition()
        is_simple_name = name.parent.type not in ('power', 'trailer')
        if is_simple_name:
            if name.parent.type == 'classdef' and name.parent.name == name:
                return [er.ClassContext(self, name.parent, context)]
            elif name.parent.type == 'funcdef':
                return [er.FunctionContext(self, context, name.parent)]
            elif name.parent.type == 'file_input':
                raise NotImplementedError
            if def_.type == 'expr_stmt' and name in def_.get_defined_names():
                return self.eval_statement(context, def_, name)
            elif def_.type == 'for_stmt':
                container_types = self.eval_element(context, def_.children[3])
                cn = ContextualizedNode(context, def_.children[3])
                for_types = iterable.py__iter__types(self, container_types, cn)
                c_node = ContextualizedName(context, name)
                return finder.check_tuple_assignments(self, c_node, for_types)
            elif def_.type in ('import_from', 'import_name'):
                return imports.infer_import(context, name)

        return helpers.evaluate_call_of_leaf(context, name)
示例#12
0
    def goto_definitions(self, context, name):
        def_ = name.get_definition(import_name_always=True)
        if def_ is not None:
            type_ = def_.type
            if type_ == 'classdef':
                return [er.ClassContext(self, name.parent, context)]
            elif type_ == 'funcdef':
                return [er.FunctionContext(self, context, name.parent)]

            if type_ == 'expr_stmt':
                is_simple_name = name.parent.type not in ('power', 'trailer')
                if is_simple_name:
                    return self.eval_statement(context, def_, name)
            if type_ == 'for_stmt':
                container_types = self.eval_element(context, def_.children[3])
                cn = ContextualizedNode(context, def_.children[3])
                for_types = iterable.py__iter__types(self, container_types, cn)
                c_node = ContextualizedName(context, name)
                return finder.check_tuple_assignments(self, c_node, for_types)
            if type_ in ('import_from', 'import_name'):
                return imports.infer_import(context, name)

        return helpers.evaluate_call_of_leaf(context, name)