1
0
forked from VimPlug/jedi
Files
jedi-fork/jedi/refactoring.py
2013-01-06 17:35:55 +01:00

118 lines
4.0 KiB
Python

""" Introduce refactoring """
import modules
import difflib
import helpers
class Refactoring(object):
def __init__(self, change_dct):
"""
:param change_dct: dict(old_path=(new_path, old_lines, new_lines))
"""
self.change_dct = change_dct
def old_files(self):
dct = {}
for old_path, (new_path, old_l, new_l) in self.change_dct.items():
dct[new_path] = '\n'.join(new_l)
return dct
def new_files(self):
dct = {}
for old_path, (new_path, old_l, new_l) in self.change_dct.items():
dct[new_path] = '\n'.join(new_l)
return dct
def diff(self):
texts = []
for old_path, (new_path, old_l, new_l) in self.change_dct.items():
if old_path:
udiff = difflib.unified_diff(old_l, new_l)
else:
udiff = difflib.unified_diff(old_l, new_l, old_path, new_path)
texts.append('\n'.join(udiff))
return '\n'.join(texts)
def rename(script, new_name):
""" The `args` / `kwargs` params are the same as in `api.Script`.
:param operation: The refactoring operation to execute.
:type operation: str
:type source: str
:return: list of changed lines/changed files
"""
dct = {}
def process(path, old_lines, new_lines):
if new_lines is not None: # goto next file, save last
dct[path] = path, old_lines, new_lines
old_names = script.related_names()
order = sorted(old_names, key=lambda x: (x.module_path, x.start_pos),
reverse=True)
current_path = object()
new_lines = old_lines = None
for name in order:
if name.in_builtin_module():
continue
if current_path != name.module_path:
current_path = name.module_path
process(current_path, old_lines, new_lines)
if current_path is not None:
# None means take the source that is a normal param.
with open(current_path) as f:
source = f.read()
new_lines = modules.source_to_unicode(source).splitlines()
old_lines = new_lines[:]
nr, indent = name.start_pos
line = new_lines[nr - 1]
new_lines[nr - 1] = line[:indent] + new_name + \
line[indent + len(name.name_part):]
process(current_path, old_lines, new_lines)
return Refactoring(dct)
def extract(script, new_name):
""" The `args` / `kwargs` params are the same as in `api.Script`.
:param operation: The refactoring operation to execute.
:type operation: str
:type source: str
:return: list of changed lines/changed files
"""
new_lines = modules.source_to_unicode(script.source).splitlines()
old_lines = new_lines[:]
user_stmt = script._parser.user_stmt
# TODO care for multiline extracts
dct = {}
if user_stmt:
indent = user_stmt.start_pos[0]
pos = script.pos
line_index = pos[0] - 1
import parsing
assert isinstance(user_stmt, parsing.Statement)
call, index, stop = helpers.scan_array_for_pos(
user_stmt.get_assignment_calls(), pos)
assert isinstance(call, parsing.Call)
exe = call.execution
if exe:
s = exe.start_pos[0], exe.start_pos[1] + 1
positions = [s] + call.execution.arr_el_pos + [exe.end_pos]
start_pos = positions[index]
end_pos = positions[index + 1][0], positions[index + 1][1] - 1
text = new_lines[start_pos[0] - 1][start_pos[1]:end_pos[1]]
for l in range(start_pos[0], end_pos[0] - 1):
text
new_lines[start_pos[0]:end_pos[0]-1]
text = user_stmt.start_pos[1], user_stmt.end_pos[1]
new = "%s%s = %s" % (' ' * indent, new_name, text)
new_lines.insert(line_index, new)
dct[script.source_path] = script.source_path, old_lines, new_lines
return Refactoring(dct)