def rename_identifier_JSON_version(src_code, id_name, new_id_name): obj = ast_extents.CodeAst(src_code) obj_json = obj.to_renderable_json(ignore_id=True) obj_dict = json.loads(obj_json) #print obj_json #print '---' outbuf = [] def render(o): if type(o) is dict: try: c = o["contents"] for elt in c: if type(elt) is dict: render(elt) else: assert type(elt) is unicode outbuf.append(elt) except KeyError: v = o["value"] assert type(v) is unicode # renamer: if o["type"] == 'Name' and v == id_name: outbuf.append(new_id_name) else: outbuf.append(v) render(obj_dict) return ''.join(outbuf)
def malkovich_renamer(src_code): obj = ast_extents.CodeAst(src_code) v = FindAllIdentifiersVisitor() v.visit(obj.ast_root) renamed_code = src_code for i in v.identifiers: renamed_code = rename_identifier(renamed_code, i, 'malkovich') return renamed_code
def rename_identifier(src_code, id_name, new_id_name): obj = ast_extents.CodeAst(src_code) new_codelines = obj.code_lines[:] # COPY the original list v = FindIdentifierVisitor(id_name) v.visit(obj.ast_root) lines = src_code #print 'id =', id_name # transform one line at a time, but remember that each replacement # can change subsequent indices by bloating them up (or shrinking) orig_len = len(id_name) new_len = len(new_id_name) delta_len = new_len - orig_len #print 'delta_len =', delta_len # Key: line number # Value: list of column numbers line_col_occurrences = defaultdict(list) for line, col in v.locs: line_col_occurrences[line].append(col) # sort columns so that we always traverse from left to right. # otherwise our index adjustment procedure won't work. for v in line_col_occurrences.values(): v.sort() # Key: line number # Value: column index delta line_col_index_deltas = defaultdict(int) for line in sorted(line_col_occurrences.keys()): #print #print 'LINE:', line, line_col_occurrences[line] for col in line_col_occurrences[line]: adjusted_col = col + line_col_index_deltas[line] orig_line = new_codelines[line] new_line = orig_line[:adjusted_col] + new_id_name + orig_line[ adjusted_col + orig_len:] new_codelines[line] = new_line # MUTATES obj.code_lines #print line, col, adjusted_col, '\t', new_line line_col_index_deltas[line] += delta_len assert new_codelines[0] == '' # sentinel new_codelines.pop(0) # pop it off return '\n'.join(new_codelines)
def cross_check_renamers(src_code): obj = ast_extents.CodeAst(src_code) v = FindAllIdentifiersVisitor() v.visit(obj.ast_root) renamed_with_regular = renamed_with_JSON = src_code # rename one variable at a time to repeating it three times for i in v.identifiers: renamed_with_regular = rename_identifier(renamed_with_regular, i, i + i + i) renamed_with_JSON = rename_identifier_JSON_version( renamed_with_JSON, i, i + i + i) assert renamed_with_regular == renamed_with_JSON # vital check! return renamed_with_regular