Exemple #1
0
def _follow_param(evaluator, params, index):
    try:
        key, values = list(params.unpack())[index]
    except IndexError:
        return []
    else:
        return iterable.unite(evaluator.eval_element(v) for v in values)
Exemple #2
0
def _follow_param(evaluator, params, index):
    try:
        key, values = list(params.unpack())[index]
    except IndexError:
        return []
    else:
        return iterable.unite(evaluator.eval_element(v) for v in values)
Exemple #3
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
                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':
                for i, t in enumerate(trailer.parent.children):
                    if t == 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, pr.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, (pr.Param, pr.Function, pr.Class)) and par.name is name:
            return [name]
        elif isinstance(stmt, pr.Import):
            return imports.ImportWrapper(self, name).follow(is_goto=True)

        scope = name.get_parent_scope()
        if pr.is_node(name.parent, 'trailer'):
            call = call_of_name(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:
            return self.find_types(scope,
                                   name,
                                   stmt.start_pos,
                                   search_global=True,
                                   is_goto=True)
Exemple #4
0
    def eval_element(self, element):
        if isinstance(element, iterable.AlreadyEvaluated):
            return list(element)
        elif isinstance(element, iterable.MergedNodes):
            return iterable.unite(self.eval_element(e) for e in element)

        debug.dbg('eval_element %s@%s', element, element.start_pos)
        if isinstance(element,
                      (pr.Name, pr.Literal)) or pr.is_node(element, 'atom'):
            return self._eval_atom(element)
        elif isinstance(element, pr.Keyword):
            # For False/True/None
            if element.value in ('False', 'True', 'None'):
                return [compiled.builtin.get_by_name(element.value)]
            else:
                return []
        elif element.isinstance(pr.Lambda):
            return [er.LambdaWrapper(self, element)]
        elif element.isinstance(er.LambdaWrapper):
            return [element]  # TODO this is no real evaluation.
        elif element.type == 'expr_stmt':
            return self.eval_statement(element)
        elif element.type == 'power':
            types = self._eval_atom(element.children[0])
            for trailer in element.children[1:]:
                if trailer == '**':  # has a power operation.
                    raise NotImplementedError
                types = self.eval_trailer(types, trailer)

            return types
        elif element.type in (
                'testlist_star_expr',
                'testlist',
        ):
            # The implicit tuple in statements.
            return [iterable.ImplicitTuple(self, element)]
        elif element.type in ('not_test', 'factor'):
            types = self.eval_element(element.children[-1])
            for operator in element.children[:-1]:
                types = list(precedence.factor_calculate(
                    self, types, operator))
            return types
        elif element.type == 'test':
            # `x if foo else y` case.
            return (self.eval_element(element.children[0]) +
                    self.eval_element(element.children[-1]))
        elif element.type == 'operator':
            # Must be an ellipsis, other operators are not evaluated.
            return []  # Ignore for now.
        elif element.type == 'dotted_name':
            types = self._eval_atom(element.children[0])
            for next_name in element.children[2::2]:
                types = list(
                    chain.from_iterable(
                        self.find_types(typ, next_name) for typ in types))
            return types
        else:
            return precedence.calculate_children(self, element.children)
Exemple #5
0
    def eval_element(self, element):
        if isinstance(element, iterable.AlreadyEvaluated):
            return list(element)
        elif isinstance(element, iterable.MergedNodes):
            return iterable.unite(self.eval_element(e) for e in element)

        debug.dbg('eval_element %s@%s', element, element.start_pos)
        if isinstance(element, (pr.Name, pr.Literal)) or pr.is_node(element, 'atom'):
            return self._eval_atom(element)
        elif isinstance(element, pr.Keyword):
            # For False/True/None
            if element.value in ('False', 'True', 'None'):
                return [compiled.builtin.get_by_name(element.value)]
            else:
                return []
        elif element.isinstance(pr.Lambda):
            return [er.LambdaWrapper(self, element)]
        elif element.isinstance(er.LambdaWrapper):
            return [element]  # TODO this is no real evaluation.
        elif element.type == 'expr_stmt':
            return self.eval_statement(element)
        elif element.type == 'power':
            types = self._eval_atom(element.children[0])
            for trailer in element.children[1:]:
                if trailer == '**':  # has a power operation.
                    raise NotImplementedError
                types = self.eval_trailer(types, trailer)

            return types
        elif element.type in ('testlist_star_expr', 'testlist',):
            # The implicit tuple in statements.
            return [iterable.ImplicitTuple(self, element)]
        elif element.type in ('not_test', 'factor'):
            types = self.eval_element(element.children[-1])
            for operator in element.children[:-1]:
                types = list(precedence.factor_calculate(self, types, operator))
            return types
        elif element.type == 'test':
            # `x if foo else y` case.
            return (self.eval_element(element.children[0]) +
                    self.eval_element(element.children[-1]))
        elif element.type == 'operator':
            # Must be an ellipsis, other operators are not evaluated.
            return []  # Ignore for now.
        elif element.type == 'dotted_name':
            types = self._eval_atom(element.children[0])
            for next_name in element.children[2::2]:
                types = list(chain.from_iterable(self.find_types(typ, next_name)
                                                 for typ in types))
            return types
        else:
            return precedence.calculate_children(self, element.children)
Exemple #6
0
    def get_return_types(self, check_yields=False):
        func = self.base

        if func.isinstance(LambdaWrapper):
            return self._evaluator.eval_element(self.children[-1])

        if func.listeners:
            # Feed the listeners, with the params.
            for listener in func.listeners:
                listener.execute(self._get_params())
            # If we do have listeners, that means that there's not a regular
            # execution ongoing. In this case Jedi is interested in the
            # inserted params, not in the actual execution of the function.
            return set()

        if check_yields:
            types = set()
            returns = self.yields
        else:
            returns = self.returns
            types = set(docstrings.find_return_types(self._evaluator, func))
            types |= set(pep0484.find_return_types(self._evaluator, func))

        for r in returns:
            check = flow_analysis.break_check(self._evaluator, self, r)
            if check is flow_analysis.UNREACHABLE:
                debug.dbg('Return unreachable: %s', r)
            else:
                if check_yields:
                    types |= iterable.unite(self._eval_yield(r))
                else:
                    types |= self._evaluator.eval_element(r.children[1])
            if check is flow_analysis.REACHABLE:
                debug.dbg('Return reachable: %s', r)
                break
        return types
    def get_return_types(self, check_yields=False):
        func = self.base

        if func.isinstance(LambdaWrapper):
            return self._evaluator.eval_element(self.children[-1])

        if func.listeners:
            # Feed the listeners, with the params.
            for listener in func.listeners:
                listener.execute(self._get_params())
            # If we do have listeners, that means that there's not a regular
            # execution ongoing. In this case Jedi is interested in the
            # inserted params, not in the actual execution of the function.
            return set()

        if check_yields:
            types = set()
            returns = self.yields
        else:
            returns = self.returns
            types = set(docstrings.find_return_types(self._evaluator, func))
            types |= set(pep0484.find_return_types(self._evaluator, func))

        for r in returns:
            check = flow_analysis.break_check(self._evaluator, self, r)
            if check is flow_analysis.UNREACHABLE:
                debug.dbg('Return unreachable: %s', r)
            else:
                if check_yields:
                    types |= iterable.unite(self._eval_yield(r))
                else:
                    types |= self._evaluator.eval_element(r.children[1])
            if check is flow_analysis.REACHABLE:
                debug.dbg('Return reachable: %s', r)
                break
        return types
Exemple #8
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)
Exemple #9
0
    def eval_element(self, element):
        if isinstance(element, iterable.AlreadyEvaluated):
            return set(element)
        elif isinstance(element, iterable.MergedNodes):
            return iterable.unite(self.eval_element(e) for e in element)

        if_stmt = element.get_parent_until(
            (tree.IfStmt, tree.ForStmt, tree.IsScope))
        predefined_if_name_dict = self.predefined_if_name_dict_dict.get(
            if_stmt)
        if predefined_if_name_dict is None and isinstance(
                if_stmt, tree.IfStmt):
            if_stmt_test = if_stmt.children[1]
            name_dicts = [{}]
            # If we already did a check, we don't want to do it again -> If
            # predefined_if_name_dict_dict is filled, we stop.
            # We don't want to check the if stmt itself, it's just about
            # the content.
            if element.start_pos > if_stmt_test.end_pos:
                # Now we need to check if the names in the if_stmt match the
                # names in the suite.
                if_names = helpers.get_names_of_node(if_stmt_test)
                element_names = helpers.get_names_of_node(element)
                str_element_names = [str(e) for e in element_names]
                if any(str(i) in str_element_names for i in if_names):
                    for if_name in if_names:
                        definitions = self.goto_definitions(if_name)
                        # Every name that has multiple different definitions
                        # causes the complexity to rise. The complexity should
                        # never fall below 1.
                        if len(definitions) > 1:
                            if len(name_dicts) * len(definitions) > 16:
                                debug.dbg(
                                    'Too many options for if branch evaluation %s.',
                                    if_stmt)
                                # There's only a certain amount of branches
                                # Jedi can evaluate, otherwise it will take to
                                # long.
                                name_dicts = [{}]
                                break

                            original_name_dicts = list(name_dicts)
                            name_dicts = []
                            for definition in definitions:
                                new_name_dicts = list(original_name_dicts)
                                for i, name_dict in enumerate(new_name_dicts):
                                    new_name_dicts[i] = name_dict.copy()
                                    new_name_dicts[i][str(if_name)] = [
                                        definition
                                    ]

                                name_dicts += new_name_dicts
                        else:
                            for name_dict in name_dicts:
                                name_dict[str(if_name)] = definitions
            if len(name_dicts) > 1:
                result = set()
                for name_dict in name_dicts:
                    self.predefined_if_name_dict_dict[if_stmt] = name_dict
                    try:
                        result |= self._eval_element_not_cached(element)
                    finally:
                        del self.predefined_if_name_dict_dict[if_stmt]
                return result
            else:
                return self._eval_element_if_evaluated(element)
                return self._eval_element_cached(element)
        else:
            if predefined_if_name_dict:
                return self._eval_element_not_cached(element)
            else:
                return self._eval_element_if_evaluated(element)
                return self._eval_element_cached(element)
Exemple #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)
Exemple #11
0
    def eval_element(self, element):
        if isinstance(element, iterable.AlreadyEvaluated):
            return set(element)
        elif isinstance(element, iterable.MergedNodes):
            return iterable.unite(self.eval_element(e) for e in element)

        if_stmt = element.get_parent_until((tree.IfStmt, tree.ForStmt, tree.IsScope))
        predefined_if_name_dict = self.predefined_if_name_dict_dict.get(if_stmt)
        if predefined_if_name_dict is None and isinstance(if_stmt, tree.IfStmt):
            if_stmt_test = if_stmt.children[1]
            name_dicts = [{}]
            # If we already did a check, we don't want to do it again -> If
            # predefined_if_name_dict_dict is filled, we stop.
            # We don't want to check the if stmt itself, it's just about
            # the content.
            if element.start_pos > if_stmt_test.end_pos:
                # Now we need to check if the names in the if_stmt match the
                # names in the suite.
                if_names = helpers.get_names_of_node(if_stmt_test)
                element_names = helpers.get_names_of_node(element)
                str_element_names = [str(e) for e in element_names]
                if any(str(i) in str_element_names for i in if_names):
                    for if_name in if_names:
                        definitions = self.goto_definitions(if_name)
                        # Every name that has multiple different definitions
                        # causes the complexity to rise. The complexity should
                        # never fall below 1.
                        if len(definitions) > 1:
                            if len(name_dicts) * len(definitions) > 16:
                                debug.dbg('Too many options for if branch evaluation %s.', if_stmt)
                                # There's only a certain amount of branches
                                # Jedi can evaluate, otherwise it will take to
                                # long.
                                name_dicts = [{}]
                                break

                            original_name_dicts = list(name_dicts)
                            name_dicts = []
                            for definition in definitions:
                                new_name_dicts = list(original_name_dicts)
                                for i, name_dict in enumerate(new_name_dicts):
                                    new_name_dicts[i] = name_dict.copy()
                                    new_name_dicts[i][str(if_name)] = [definition]

                                name_dicts += new_name_dicts
                        else:
                            for name_dict in name_dicts:
                                name_dict[str(if_name)] = definitions
            if len(name_dicts) > 1:
                result = set()
                for name_dict in name_dicts:
                    self.predefined_if_name_dict_dict[if_stmt] = name_dict
                    try:
                        result |= self._eval_element_not_cached(element)
                    finally:
                        del self.predefined_if_name_dict_dict[if_stmt]
                return result
            else:
                return self._eval_element_if_evaluated(element)
                return self._eval_element_cached(element)
        else:
            if predefined_if_name_dict:
                return self._eval_element_not_cached(element)
            else:
                return self._eval_element_if_evaluated(element)
                return self._eval_element_cached(element)