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))
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)
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