init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
|
|
@ -0,0 +1,221 @@
|
|||
from rope.base import evaluate
|
||||
from rope.base import exceptions
|
||||
from rope.base import libutils
|
||||
from rope.base import pynames
|
||||
from rope.base import taskhandle
|
||||
from rope.base import utils
|
||||
from rope.base import worder
|
||||
from rope.base.change import ChangeSet, ChangeContents
|
||||
from rope.refactor import sourceutils, occurrences
|
||||
|
||||
|
||||
class EncapsulateField(object):
|
||||
def __init__(self, project, resource, offset):
|
||||
self.project = project
|
||||
self.name = worder.get_name_at(resource, offset)
|
||||
this_pymodule = self.project.get_pymodule(resource)
|
||||
self.pyname = evaluate.eval_location(this_pymodule, offset)
|
||||
if not self._is_an_attribute(self.pyname):
|
||||
raise exceptions.RefactoringError(
|
||||
"Encapsulate field should be performed on class attributes."
|
||||
)
|
||||
self.resource = self.pyname.get_definition_location()[0].get_resource()
|
||||
|
||||
def get_changes(
|
||||
self,
|
||||
getter=None,
|
||||
setter=None,
|
||||
resources=None,
|
||||
task_handle=taskhandle.NullTaskHandle(),
|
||||
):
|
||||
"""Get the changes this refactoring makes
|
||||
|
||||
If `getter` is not `None`, that will be the name of the
|
||||
getter, otherwise ``get_${field_name}`` will be used. The
|
||||
same is true for `setter` and if it is None set_${field_name} is
|
||||
used.
|
||||
|
||||
`resources` can be a list of `rope.base.resource.File` that
|
||||
the refactoring should be applied on; if `None` all python
|
||||
files in the project are searched.
|
||||
|
||||
"""
|
||||
if resources is None:
|
||||
resources = self.project.get_python_files()
|
||||
changes = ChangeSet("Encapsulate field <%s>" % self.name)
|
||||
job_set = task_handle.create_jobset("Collecting Changes", len(resources))
|
||||
if getter is None:
|
||||
getter = "get_" + self.name
|
||||
if setter is None:
|
||||
setter = "set_" + self.name
|
||||
renamer = GetterSetterRenameInModule(
|
||||
self.project, self.name, self.pyname, getter, setter
|
||||
)
|
||||
for file in resources:
|
||||
job_set.started_job(file.path)
|
||||
if file == self.resource:
|
||||
result = self._change_holding_module(changes, renamer, getter, setter)
|
||||
changes.add_change(ChangeContents(self.resource, result))
|
||||
else:
|
||||
result = renamer.get_changed_module(file)
|
||||
if result is not None:
|
||||
changes.add_change(ChangeContents(file, result))
|
||||
job_set.finished_job()
|
||||
return changes
|
||||
|
||||
def get_field_name(self):
|
||||
"""Get the name of the field to be encapsulated"""
|
||||
return self.name
|
||||
|
||||
def _is_an_attribute(self, pyname):
|
||||
if pyname is not None and isinstance(pyname, pynames.AssignedName):
|
||||
pymodule, lineno = self.pyname.get_definition_location()
|
||||
scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
|
||||
if scope.get_kind() == "Class":
|
||||
return pyname in scope.get_names().values()
|
||||
parent = scope.parent
|
||||
if parent is not None and parent.get_kind() == "Class":
|
||||
return pyname in parent.get_names().values()
|
||||
return False
|
||||
|
||||
def _get_defining_class_scope(self):
|
||||
defining_scope = self._get_defining_scope()
|
||||
if defining_scope.get_kind() == "Function":
|
||||
defining_scope = defining_scope.parent
|
||||
return defining_scope
|
||||
|
||||
def _get_defining_scope(self):
|
||||
pymodule, line = self.pyname.get_definition_location()
|
||||
return pymodule.get_scope().get_inner_scope_for_line(line)
|
||||
|
||||
def _change_holding_module(self, changes, renamer, getter, setter):
|
||||
pymodule = self.project.get_pymodule(self.resource)
|
||||
class_scope = self._get_defining_class_scope()
|
||||
defining_object = self._get_defining_scope().pyobject
|
||||
start, end = sourceutils.get_body_region(defining_object)
|
||||
|
||||
new_source = renamer.get_changed_module(
|
||||
pymodule=pymodule, skip_start=start, skip_end=end
|
||||
)
|
||||
if new_source is not None:
|
||||
pymodule = libutils.get_string_module(
|
||||
self.project, new_source, self.resource
|
||||
)
|
||||
class_scope = pymodule.get_scope().get_inner_scope_for_line(
|
||||
class_scope.get_start()
|
||||
)
|
||||
indents = sourceutils.get_indent(self.project) * " "
|
||||
getter = "def %s(self):\n%sreturn self.%s" % (getter, indents, self.name)
|
||||
setter = "def %s(self, value):\n%sself.%s = value" % (
|
||||
setter,
|
||||
indents,
|
||||
self.name,
|
||||
)
|
||||
new_source = sourceutils.add_methods(pymodule, class_scope, [getter, setter])
|
||||
return new_source
|
||||
|
||||
|
||||
class GetterSetterRenameInModule(object):
|
||||
def __init__(self, project, name, pyname, getter, setter):
|
||||
self.project = project
|
||||
self.name = name
|
||||
self.finder = occurrences.create_finder(project, name, pyname)
|
||||
self.getter = getter
|
||||
self.setter = setter
|
||||
|
||||
def get_changed_module(
|
||||
self, resource=None, pymodule=None, skip_start=0, skip_end=0
|
||||
):
|
||||
change_finder = _FindChangesForModule(
|
||||
self, resource, pymodule, skip_start, skip_end
|
||||
)
|
||||
return change_finder.get_changed_module()
|
||||
|
||||
|
||||
class _FindChangesForModule(object):
|
||||
def __init__(self, finder, resource, pymodule, skip_start, skip_end):
|
||||
self.project = finder.project
|
||||
self.finder = finder.finder
|
||||
self.getter = finder.getter
|
||||
self.setter = finder.setter
|
||||
self.resource = resource
|
||||
self.pymodule = pymodule
|
||||
self.last_modified = 0
|
||||
self.last_set = None
|
||||
self.set_index = None
|
||||
self.skip_start = skip_start
|
||||
self.skip_end = skip_end
|
||||
|
||||
def get_changed_module(self):
|
||||
result = []
|
||||
for occurrence in self.finder.find_occurrences(self.resource, self.pymodule):
|
||||
start, end = occurrence.get_word_range()
|
||||
if self.skip_start <= start < self.skip_end:
|
||||
continue
|
||||
self._manage_writes(start, result)
|
||||
result.append(self.source[self.last_modified : start])
|
||||
if self._is_assigned_in_a_tuple_assignment(occurrence):
|
||||
raise exceptions.RefactoringError(
|
||||
"Cannot handle tuple assignments in encapsulate field."
|
||||
)
|
||||
if occurrence.is_written():
|
||||
assignment_type = self.worder.get_assignment_type(start)
|
||||
if assignment_type == "=":
|
||||
result.append(self.setter + "(")
|
||||
else:
|
||||
var_name = (
|
||||
self.source[occurrence.get_primary_range()[0] : start]
|
||||
+ self.getter
|
||||
+ "()"
|
||||
)
|
||||
result.append(
|
||||
self.setter + "(" + var_name + " %s " % assignment_type[:-1]
|
||||
)
|
||||
current_line = self.lines.get_line_number(start)
|
||||
start_line, end_line = self.pymodule.logical_lines.logical_line_in(
|
||||
current_line
|
||||
)
|
||||
self.last_set = self.lines.get_line_end(end_line)
|
||||
end = self.source.index("=", end) + 1
|
||||
self.set_index = len(result)
|
||||
else:
|
||||
result.append(self.getter + "()")
|
||||
self.last_modified = end
|
||||
if self.last_modified != 0:
|
||||
self._manage_writes(len(self.source), result)
|
||||
result.append(self.source[self.last_modified :])
|
||||
return "".join(result)
|
||||
return None
|
||||
|
||||
def _manage_writes(self, offset, result):
|
||||
if self.last_set is not None and self.last_set <= offset:
|
||||
result.append(self.source[self.last_modified : self.last_set])
|
||||
set_value = "".join(result[self.set_index :]).strip()
|
||||
del result[self.set_index :]
|
||||
result.append(set_value + ")")
|
||||
self.last_modified = self.last_set
|
||||
self.last_set = None
|
||||
|
||||
def _is_assigned_in_a_tuple_assignment(self, occurrence):
|
||||
offset = occurrence.get_word_range()[0]
|
||||
return self.worder.is_assigned_in_a_tuple_assignment(offset)
|
||||
|
||||
@property
|
||||
@utils.saveit
|
||||
def source(self):
|
||||
if self.resource is not None:
|
||||
return self.resource.read()
|
||||
else:
|
||||
return self.pymodule.source_code
|
||||
|
||||
@property
|
||||
@utils.saveit
|
||||
def lines(self):
|
||||
if self.pymodule is None:
|
||||
self.pymodule = self.project.get_pymodule(self.resource)
|
||||
return self.pymodule.lines
|
||||
|
||||
@property
|
||||
@utils.saveit
|
||||
def worder(self):
|
||||
return worder.Worder(self.source)
|
||||
Loading…
Add table
Add a link
Reference in a new issue