Ejemplo n.º 1
0
def _check_isinstance_type(context, element, search_name):
    try:
        assert element.type in ('power', 'atom_expr')
        # this might be removed if we analyze and, etc
        assert len(element.children) == 2
        first, trailer = element.children
        assert first.type == 'name' and first.value == 'isinstance'
        assert trailer.type == 'trailer' and trailer.children[0] == '('
        assert len(trailer.children) == 3

        # arglist stuff
        arglist = trailer.children[1]
        args = TreeArguments(context.evaluator, context, arglist, trailer)
        param_list = list(args.unpack())
        # Disallow keyword arguments
        assert len(param_list) == 2
        (key1, lazy_context_object), (key2, lazy_context_cls) = param_list
        assert key1 is None and key2 is None
        call = helpers.call_of_leaf(search_name)
        is_instance_call = helpers.call_of_leaf(lazy_context_object.data)
        # Do a simple get_code comparison. They should just have the same code,
        # and everything will be all right.
        normalize = context.evaluator.grammar._normalize
        assert normalize(is_instance_call) == normalize(call)
    except AssertionError:
        return None

    context_set = NO_CONTEXTS
    for cls_or_tup in lazy_context_cls.infer():
        if isinstance(cls_or_tup, iterable.Sequence) and cls_or_tup.array_type == 'tuple':
            for lazy_context in cls_or_tup.py__iter__():
                context_set |= lazy_context.infer().execute_evaluated(context)
        else:
            context_set |= helpers.execute_evaluated(cls_or_tup)
    return context_set
Ejemplo n.º 2
0
def _check_isinstance_type(evaluator, element, search_name):
    try:
        assert element.type in ('power', 'atom_expr')
        # this might be removed if we analyze and, etc
        assert len(element.children) == 2
        first, trailer = element.children
        assert isinstance(first, tree.Name) and first.value == 'isinstance'
        assert trailer.type == 'trailer' and trailer.children[0] == '('
        assert len(trailer.children) == 3

        # arglist stuff
        arglist = trailer.children[1]
        args = param.Arguments(evaluator, arglist, trailer)
        lst = list(args.unpack())
        # Disallow keyword arguments
        assert len(lst) == 2 and lst[0][0] is None and lst[1][0] is None
        name = lst[0][1][0]  # first argument, values, first value
        # Do a simple get_code comparison. They should just have the same code,
        # and everything will be all right.
        classes = lst[1][1][0]
        call = helpers.call_of_leaf(search_name)
        assert name.get_code(normalized=True) == call.get_code(normalized=True)
    except AssertionError:
        return set()

    result = set()
    for cls_or_tup in evaluator.eval_element(classes):
        if isinstance(cls_or_tup,
                      iterable.Array) and cls_or_tup.type == 'tuple':
            for typ in unite(cls_or_tup.py__iter__()):
                result |= evaluator.execute(typ)
        else:
            result |= evaluator.execute(cls_or_tup)
    return result
Ejemplo n.º 3
0
def _check_isinstance_type(evaluator, element, search_name):
    try:
        assert element.type in ("power", "atom_expr")
        # this might be removed if we analyze and, etc
        assert len(element.children) == 2
        first, trailer = element.children
        assert isinstance(first, tree.Name) and first.value == "isinstance"
        assert trailer.type == "trailer" and trailer.children[0] == "("
        assert len(trailer.children) == 3

        # arglist stuff
        arglist = trailer.children[1]
        args = param.Arguments(evaluator, arglist, trailer)
        lst = list(args.unpack())
        # Disallow keyword arguments
        assert len(lst) == 2 and lst[0][0] is None and lst[1][0] is None
        name = lst[0][1][0]  # first argument, values, first value
        # Do a simple get_code comparison. They should just have the same code,
        # and everything will be all right.
        classes = lst[1][1][0]
        call = helpers.call_of_leaf(search_name)
        assert name.get_code(normalized=True) == call.get_code(normalized=True)
    except AssertionError:
        return set()

    result = set()
    for cls_or_tup in evaluator.eval_element(classes):
        if isinstance(cls_or_tup, iterable.Array) and cls_or_tup.type == "tuple":
            for typ in unite(cls_or_tup.py__iter__()):
                result |= evaluator.execute(typ)
        else:
            result |= evaluator.execute(cls_or_tup)
    return result
Ejemplo n.º 4
0
def test_call_of_leaf_in_brackets():
    s = dedent("""
    x = 1
    type(x)
    """)
    last_x = names(s, references=True, definitions=False)[-1]
    name = last_x._name

    call = helpers.call_of_leaf(name)
    assert call == name
Ejemplo n.º 5
0
def _check_isinstance_type(context, element, search_name):
    try:
        assert element.type in ('power', 'atom_expr')
        # this might be removed if we analyze and, etc
        assert len(element.children) == 2
        first, trailer = element.children
        assert first.type == 'name' and first.value == 'isinstance'
        assert trailer.type == 'trailer' and trailer.children[0] == '('
        assert len(trailer.children) == 3

        # arglist stuff
        arglist = trailer.children[1]
        args = TreeArguments(context.evaluator, context, arglist, trailer)
        param_list = list(args.unpack())
        # Disallow keyword arguments
        assert len(param_list) == 2
        (key1, lazy_context_object), (key2, lazy_context_cls) = param_list
        assert key1 is None and key2 is None
        call = helpers.call_of_leaf(search_name)
        is_instance_call = helpers.call_of_leaf(lazy_context_object.data)
        # Do a simple get_code comparison. They should just have the same code,
        # and everything will be all right.
        normalize = context.evaluator.grammar._normalize
        assert normalize(is_instance_call) == normalize(call)
    except AssertionError:
        return None

    context_set = ContextSet()
    for cls_or_tup in lazy_context_cls.infer():
        if isinstance(cls_or_tup, iterable.AbstractIterable) and \
                cls_or_tup.array_type == 'tuple':
            for lazy_context in cls_or_tup.py__iter__():
                for context in lazy_context.infer():
                    context_set |= context.execute_evaluated()
        else:
            context_set |= cls_or_tup.execute_evaluated()
    return context_set
def evaluate_goto_definition(evaluator, 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(leaf)

    node = None
    parent = leaf.parent
    if parent.type == 'atom':
        node = leaf.parent
    elif parent.type == 'trailer':
        node = call_of_leaf(leaf)

    if node is None:
        return []
    return evaluator.eval_element(node)
Ejemplo n.º 7
0
def evaluate_goto_definition(evaluator, 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(leaf)

    node = None
    parent = leaf.parent
    if parent.type == 'atom':
        node = leaf.parent
    elif parent.type == 'trailer':
        node = call_of_leaf(leaf)

    if node is None:
        return []
    return evaluator.eval_element(node)
Ejemplo n.º 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)
Ejemplo n.º 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 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)
Ejemplo n.º 10
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)
Ejemplo n.º 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)
    def _get_context_completions(self):
        """
        Analyzes the context that a completion is made in and decides what to
        return.

        Technically this works by generating a parser stack and analysing the
        current stack for possible grammar nodes.

        Possible enhancements:
        - global/nonlocal search global
        - yield from / raise from <- could be only exceptions/generators
        - In args: */**: no completion
        - In params (also lambda): no completion before =
        """

        grammar = self._evaluator.grammar

        try:
            self.stack = helpers.get_stack_at_position(
                grammar, self._code_lines, self._module, self._position
            )
        except helpers.OnErrorLeaf as e:
            self.stack = None
            if e.error_leaf.value == '.':
                # After ErrorLeaf's that are dots, we will not do any
                # completions since this probably just confuses the user.
                return []
            # If we don't have a context, just use global completion.

            return self._global_completions()

        allowed_keywords, allowed_tokens = \
            helpers.get_possible_completion_types(grammar, self.stack)

        completion_names = list(self._get_keyword_completion_names(allowed_keywords))

        if token.NAME in allowed_tokens:
            # This means that we actually have to do type inference.

            symbol_names = list(self.stack.get_node_names(grammar))

            nodes = list(self.stack.get_nodes())

            if "import_stmt" in symbol_names:
                level = 0
                only_modules = True
                level, names = self._parse_dotted_names(nodes)
                if "import_from" in symbol_names:
                    if 'import' in nodes:
                        only_modules = False
                else:
                    assert "import_name" in symbol_names

                completion_names += self._get_importer_names(
                    names,
                    level,
                    only_modules
                )
            elif nodes and nodes[-1] in ('as', 'def', 'class'):
                # No completions for ``with x as foo`` and ``import x as foo``.
                # Also true for defining names as a class or function.
                return list(self._get_class_context_completions(is_function=True))
            elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
                dot = self._module.get_leaf_for_position(self._position)
                atom_expr = call_of_leaf(dot.get_previous_leaf())
                completion_names += self._trailer_completions(atom_expr)
            else:
                completion_names += self._global_completions()
                completion_names += self._get_class_context_completions(is_function=False)

            if 'trailer' in symbol_names:
                call_signatures = self._call_signatures_method()
                completion_names += get_call_signature_param_names(call_signatures)

        return completion_names
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
def _check_array_additions(evaluator, compare_array, module, is_list):
    """
    Checks if a `Array` has "add" (append, insert, extend) statements:

    >>> a = [""]
    >>> a.append(1)
    """
    debug.dbg('Dynamic array search for %s' % compare_array, color='MAGENTA')
    if not settings.dynamic_array_additions or isinstance(
            module, compiled.CompiledObject):
        debug.dbg('Dynamic array search aborted.', color='MAGENTA')
        return set()

    def check_additions(arglist, add_name):
        params = list(param.Arguments(evaluator, arglist).unpack())
        result = set()
        if add_name in ['insert']:
            params = params[1:]
        if add_name in ['append', 'add', 'insert']:
            for key, nodes in params:
                result |= unite(evaluator.eval_element(node) for node in nodes)
        elif add_name in ['extend', 'update']:
            for key, nodes in params:
                for node in nodes:
                    types = evaluator.eval_element(node)
                    result |= py__iter__types(evaluator, types, node)
        return result

    from jedi.evaluate import representation as er, param

    def get_execution_parent(element):
        """ Used to get an Instance/FunctionExecution parent """
        if isinstance(element, Array):
            node = element.atom
        else:
            # Is an Instance with an
            # Arguments([AlreadyEvaluated([_ArrayInstance])]) inside
            # Yeah... I know... It's complicated ;-)
            node = list(element.var_args.argument_node[0])[0].var_args.trailer
        if isinstance(node, er.InstanceElement) or node is None:
            return node
        return node.get_parent_until(er.FunctionExecution)

    temp_param_add, settings.dynamic_params_for_other_modules = \
        settings.dynamic_params_for_other_modules, False

    search_names = ['append', 'extend', 'insert'
                    ] if is_list else ['add', 'update']
    comp_arr_parent = get_execution_parent(compare_array)

    added_types = set()
    for add_name in search_names:
        try:
            possible_names = module.used_names[add_name]
        except KeyError:
            continue
        else:
            for name in possible_names:
                # Check if the original scope is an execution. If it is, one
                # can search for the same statement, that is in the module
                # dict. Executions are somewhat special in jedi, since they
                # literally copy the contents of a function.
                if isinstance(comp_arr_parent, er.FunctionExecution):
                    if comp_arr_parent.start_pos < name.start_pos < comp_arr_parent.end_pos:
                        name = comp_arr_parent.name_for_position(
                            name.start_pos)
                    else:
                        # Don't check definitions that are not defined in the
                        # same function. This is not "proper" anyway. It also
                        # improves Jedi's speed for array lookups, since we
                        # don't have to check the whole source tree anymore.
                        continue
                trailer = name.parent
                power = trailer.parent
                trailer_pos = power.children.index(trailer)
                try:
                    execution_trailer = power.children[trailer_pos + 1]
                except IndexError:
                    continue
                else:
                    if execution_trailer.type != 'trailer' \
                            or execution_trailer.children[0] != '(' \
                            or execution_trailer.children[1] == ')':
                        continue
                power = helpers.call_of_leaf(name, cut_own_trailer=True)
                # InstanceElements are special, because they don't get copied,
                # but have this wrapper around them.
                if isinstance(comp_arr_parent, er.InstanceElement):
                    power = er.get_instance_el(evaluator,
                                               comp_arr_parent.instance, power)

                if evaluator.recursion_detector.push_stmt(power):
                    # Check for recursion. Possible by using 'extend' in
                    # combination with function calls.
                    continue
                try:
                    if compare_array in evaluator.eval_element(power):
                        # The arrays match. Now add the results
                        added_types |= check_additions(
                            execution_trailer.children[1], add_name)
                finally:
                    evaluator.recursion_detector.pop_stmt()
    # reset settings
    settings.dynamic_params_for_other_modules = temp_param_add
    debug.dbg('Dynamic array result %s' % added_types, color='MAGENTA')
    return added_types
Ejemplo n.º 15
0
    def _get_context_completions(self):
        """
        Analyzes the context that a completion is made in and decides what to
        return.

        Technically this works by generating a parser stack and analysing the
        current stack for possible grammar nodes.

        Possible enhancements:
        - global/nonlocal search global
        - yield from / raise from <- could be only exceptions/generators
        - In args: */**: no completion
        - In params (also lambda): no completion before =
        """

        grammar = self._evaluator.grammar

        try:
            stack = helpers.get_stack_at_position(
                grammar, self._code_lines, self._module, self._position
            )
        except helpers.OnErrorLeaf as e:
            if e.error_leaf.value == '.':
                # After ErrorLeaf's that are dots, we will not do any
                # completions since this probably just confuses the user.
                return []
            # If we don't have a context, just use global completion.
            return self._global_completions()

        allowed_keywords, allowed_tokens = \
            helpers.get_possible_completion_types(grammar, stack)

        completion_names = list(self._get_keyword_completion_names(allowed_keywords))

        if token.NAME in allowed_tokens:
            # This means that we actually have to do type inference.

            symbol_names = list(stack.get_node_names(grammar))

            nodes = list(stack.get_nodes())

            if "import_stmt" in symbol_names:
                level = 0
                only_modules = True
                level, names = self._parse_dotted_names(nodes)
                if "import_from" in symbol_names:
                    if 'import' in nodes:
                        only_modules = False
                else:
                    assert "import_name" in symbol_names

                completion_names += self._get_importer_names(
                    names,
                    level,
                    only_modules
                )
            elif nodes and nodes[-1] in ('as', 'def', 'class'):
                # No completions for ``with x as foo`` and ``import x as foo``.
                # Also true for defining names as a class or function.
                return []
            elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
                dot = self._module.get_leaf_for_position(self._position)
                atom_expr = call_of_leaf(dot.get_previous_leaf())
                completion_names += self._trailer_completions(atom_expr)
            else:
                completion_names += self._global_completions()

            if 'trailer' in symbol_names:
                call_signatures = self._call_signatures_method()
                completion_names += get_call_signature_param_names(call_signatures)

        return completion_names
Ejemplo n.º 16
0
def _check_array_additions(evaluator, compare_array, module, is_list):
    """
    Checks if a `Array` has "add" (append, insert, extend) statements:

    >>> a = [""]
    >>> a.append(1)
    """
    debug.dbg('Dynamic array search for %s' % compare_array, color='MAGENTA')
    if not settings.dynamic_array_additions or isinstance(module, compiled.CompiledObject):
        debug.dbg('Dynamic array search aborted.', color='MAGENTA')
        return set()

    def check_additions(arglist, add_name):
        params = list(param.Arguments(evaluator, arglist).unpack())
        result = set()
        if add_name in ['insert']:
            params = params[1:]
        if add_name in ['append', 'add', 'insert']:
            for key, nodes in params:
                result |= unite(evaluator.eval_element(node) for node in nodes)
        elif add_name in ['extend', 'update']:
            for key, nodes in params:
                for node in nodes:
                    types = evaluator.eval_element(node)
                    result |= py__iter__types(evaluator, types, node)
        return result

    from jedi.evaluate import representation as er, param

    def get_execution_parent(element):
        """ Used to get an Instance/FunctionExecution parent """
        if isinstance(element, Array):
            node = element.atom
        else:
            # Is an Instance with an
            # Arguments([AlreadyEvaluated([_ArrayInstance])]) inside
            # Yeah... I know... It's complicated ;-)
            node = list(element.var_args.argument_node[0])[0].var_args.trailer
        if isinstance(node, er.InstanceElement):
            return node
        return node.get_parent_until(er.FunctionExecution)

    temp_param_add, settings.dynamic_params_for_other_modules = \
        settings.dynamic_params_for_other_modules, False

    search_names = ['append', 'extend', 'insert'] if is_list else ['add', 'update']
    comp_arr_parent = get_execution_parent(compare_array)

    added_types = set()
    for add_name in search_names:
        try:
            possible_names = module.used_names[add_name]
        except KeyError:
            continue
        else:
            for name in possible_names:
                # Check if the original scope is an execution. If it is, one
                # can search for the same statement, that is in the module
                # dict. Executions are somewhat special in jedi, since they
                # literally copy the contents of a function.
                if isinstance(comp_arr_parent, er.FunctionExecution):
                    if comp_arr_parent.start_pos < name.start_pos < comp_arr_parent.end_pos:
                        name = comp_arr_parent.name_for_position(name.start_pos)
                    else:
                        # Don't check definitions that are not defined in the
                        # same function. This is not "proper" anyway. It also
                        # improves Jedi's speed for array lookups, since we
                        # don't have to check the whole source tree anymore.
                        continue
                trailer = name.parent
                power = trailer.parent
                trailer_pos = power.children.index(trailer)
                try:
                    execution_trailer = power.children[trailer_pos + 1]
                except IndexError:
                    continue
                else:
                    if execution_trailer.type != 'trailer' \
                            or execution_trailer.children[0] != '(' \
                            or execution_trailer.children[1] == ')':
                        continue
                power = helpers.call_of_leaf(name, cut_own_trailer=True)
                # InstanceElements are special, because they don't get copied,
                # but have this wrapper around them.
                if isinstance(comp_arr_parent, er.InstanceElement):
                    power = er.get_instance_el(evaluator, comp_arr_parent.instance, power)

                if evaluator.recursion_detector.push_stmt(power):
                    # Check for recursion. Possible by using 'extend' in
                    # combination with function calls.
                    continue
                if compare_array in evaluator.eval_element(power):
                    # The arrays match. Now add the results
                    added_types |= check_additions(execution_trailer.children[1], add_name)

                evaluator.recursion_detector.pop_stmt()
    # reset settings
    settings.dynamic_params_for_other_modules = temp_param_add
    debug.dbg('Dynamic array result %s' % added_types, color='MAGENTA')
    return added_types