예제 #1
0
    def get_positions_for(self, source, line, column):
        module_node = jedi_utils.parse_source(source)
        pos = (line, column)
        stmt = self._get_statement_for_position(module_node, pos)

        name = None
        if isinstance(stmt, tree.Name):
            name = stmt
        elif isinstance(stmt, tree.BaseNode):
            name = jedi_utils.get_name_of_position(stmt, pos)

        if not name:
            return set()

        # format usage positions as tkinter text widget indices
        return set((
            "%d.%d" % (usage.start_pos[0], usage.start_pos[1]),
            "%d.%d" %
            (usage.start_pos[0], usage.start_pos[1] + len(name.value)),
        ) for usage in self._find_usages(name, stmt))
예제 #2
0
def add_tags(text):
    source = text.get("1.0", "end")
    clear_tags(text)
    tree = jedi_utils.parse_source(source)

    print_tree(tree)
    last_line = 0
    last_col = 0

    def tag_tree(node):
        nonlocal last_line, last_col
        python_tree = jedi_utils.import_python_tree()

        if node.type == "simple_stmt" or isinstance(
                node, (python_tree.Flow, python_tree.Scope)):

            start_line, start_col = node.start_pos
            end_line, end_col = node.end_pos

            # Before dealing with this node,
            # handle the case, where last vertical tag was meant for
            # same column, but there were empty or comment lines between
            if start_col == last_col:
                for i in range(last_line + 1, start_line):
                    # NB! tag not visible when logically empty line
                    # doesn't have indent prefix
                    text.tag_add("ver_False_False",
                                 "%d.%d" % (i, last_col - 1),
                                 "%d.%d" % (i, last_col))
                    print("ver_False_False", "%d.%d" % (i, last_col - 1),
                          "%d.%d" % (i, last_col))

            print(node)

            # usually end_col is 0
            # exceptions: several statements on the same line (semicoloned statements)
            # also unclosed parens in if-header
            for lineno in range(start_line,
                                end_line if end_col == 0 else end_line + 1):

                top = lineno == start_line and lineno > 1
                bottom = False  # start_line == end_line-1

                # horizontal line (only for first or last line)
                if top or bottom:
                    text.tag_add(
                        "hor_%s_%s" % (top, bottom),
                        "%d.%d" % (lineno, start_col),
                        "%d.%d" % (lineno + 1 if end_col == 0 else lineno, 0),
                    )

                    print(
                        "hor_%s_%s" % (top, bottom),
                        "%d.%d" % (lineno, start_col),
                        "%d.%d" % (lineno + 1, 0),
                    )

                # vertical line (only for indented statements)
                # Note that I'm using start col for all lines
                # (statement's indent shouldn't decrease in continuation lines)
                if start_col > 0:
                    text.tag_add(
                        "ver_%s_%s" % (top, bottom),
                        "%d.%d" % (lineno, start_col - 1),
                        "%d.%d" % (lineno, start_col),
                    )
                    print(
                        "ver_%s_%s" % (top, bottom),
                        "%d.%d" % (lineno, start_col - 1),
                        "%d.%d" % (lineno, start_col),
                    )

                    last_line = lineno
                    last_col = start_col

        # Recurse
        if node.type != "simple_stmt" and hasattr(node, "children"):
            for child in node.children:
                tag_tree(child)

    tag_tree(tree)
예제 #3
0
    def get_positions(self):
        tree = jedi_utils.import_python_tree()

        locs = []

        def process_scope(scope):
            if isinstance(scope, tree.Function):
                # process all children after name node,
                # (otherwise name of global function will be marked as local def)
                local_names = set()
                global_names = set()
                for child in scope.children[2:]:
                    process_node(child, local_names, global_names)
            else:
                if hasattr(scope, "subscopes"):
                    for child in scope.subscopes:
                        process_scope(child)
                elif hasattr(scope, "children"):
                    for child in scope.children:
                        process_scope(child)

        def process_node(node, local_names, global_names):
            if isinstance(node, tree.GlobalStmt):
                global_names.update([n.value for n in node.get_global_names()])

            elif isinstance(node, tree.Name):
                if node.value in global_names:
                    return

                if node.is_definition():  # local def
                    locs.append(node)
                    local_names.add(node.value)
                elif node.value in local_names:  # use of local
                    locs.append(node)

            elif isinstance(node, tree.BaseNode):
                # ref: jedi/parser/grammar*.txt
                if node.type == "trailer" and node.children[0].value == ".":
                    # this is attribute
                    return

                if isinstance(node, tree.Function):
                    global_names = set(
                    )  # outer global statement doesn't have effect anymore

                for child in node.children:
                    process_node(child, local_names, global_names)

        source = self.text.get("1.0", "end")
        module = jedi_utils.parse_source(source)
        for child in module.children:
            if isinstance(child, tree.BaseNode) and jedi_utils.is_scope(child):
                process_scope(child)

        loc_pos = set((
            "%d.%d" % (usage.start_pos[0], usage.start_pos[1]),
            "%d.%d" %
            (usage.start_pos[0], usage.start_pos[1] + len(usage.value)),
        ) for usage in locs)

        return loc_pos