Example #1
0
def real_code(source):
    """Simplify `source` for analysis

    It replaces:

    * comments with spaces
    * strs with a new str filled with spaces
    * implicit and explicit continuations with spaces
    * tabs and semicolons with spaces

    The resulting code is a lot easier to analyze if we are interested
    only in offsets.
    """
    collector = codeanalyze.ChangeCollector(source)
    for start, end in ignored_regions(source):
        if source[start] == '#':
            replacement = ' ' * (end - start)
        else:
            replacement = '"%s"' % (' ' * (end - start - 2))
        collector.add_change(start, end, replacement)
    source = collector.get_changed() or source
    collector = codeanalyze.ChangeCollector(source)
    parens = 0
    for match in _parens.finditer(source):
        i = match.start()
        c = match.group()
        if c in '({[':
            parens += 1
        if c in ')}]':
            parens -= 1
        if c == '\n' and parens > 0:
            collector.add_change(i, i + 1, ' ')
    source = collector.get_changed() or source
    return source.replace('\\\n', '  ').replace('\t', ' ').replace(';', '\n')
Example #2
0
    def get_changes(
            self,
            dest_attr,
            new_name=None,
            resources=None,
            task_handle=taskhandle.NullTaskHandle(),
    ):
        """Return the changes needed for this refactoring

        Parameters:

        - `dest_attr`: the name of the destination attribute
        - `new_name`: the name of the new method; if `None` uses
          the old name
        - `resources` can be a list of `rope.base.resources.File` to
          apply this refactoring on.  If `None`, the restructuring
          will be applied to all python files.

        """
        changes = ChangeSet("Moving method <%s>" % self.method_name)
        if resources is None:
            resources = self.project.get_python_files()
        if new_name is None:
            new_name = self.get_method_name()
        resource1, start1, end1, new_content1 = self._get_changes_made_by_old_class(
            dest_attr, new_name)
        collector1 = codeanalyze.ChangeCollector(resource1.read())
        collector1.add_change(start1, end1, new_content1)

        resource2, start2, end2, new_content2 = self._get_changes_made_by_new_class(
            dest_attr, new_name)
        if resource1 == resource2:
            collector1.add_change(start2, end2, new_content2)
        else:
            collector2 = codeanalyze.ChangeCollector(resource2.read())
            collector2.add_change(start2, end2, new_content2)
            result = collector2.get_changed()
            import_tools = importutils.ImportTools(self.project)
            new_imports = self._get_used_imports(import_tools)
            if new_imports:
                goal_pymodule = libutils.get_string_module(
                    self.project, result, resource2)
                result = _add_imports_to_module(import_tools, goal_pymodule,
                                                new_imports)
            if resource2 in resources:
                changes.add_change(ChangeContents(resource2, result))

        if resource1 in resources:
            changes.add_change(
                ChangeContents(resource1, collector1.get_changed()))
        return changes
Example #3
0
def rename_in_module(occurrences_finder,
                     new_name,
                     resource=None,
                     pymodule=None,
                     replace_primary=False,
                     region=None,
                     reads=True,
                     writes=True):
    """Returns the changed source or `None` if there is no changes"""
    if resource is not None:
        source_code = resource.read()
    else:
        source_code = pymodule.source_code
    change_collector = codeanalyze.ChangeCollector(source_code)
    for occurrence in occurrences_finder.find_occurrences(resource, pymodule):
        if replace_primary and occurrence.is_a_fixed_primary():
            continue
        if replace_primary:
            start, end = occurrence.get_primary_range()
        else:
            start, end = occurrence.get_word_range()
        if (not reads and not occurrence.is_written()) or \
           (not writes and occurrence.is_written()):
            continue
        if region is None or region[0] <= start < region[1]:
            change_collector.add_change(start, end, new_name)
    return change_collector.get_changed()
Example #4
0
 def get_changes(self, classname=None, new_class_name=None):
     if new_class_name is not None:
         warnings.warn(
             "new_class_name parameter is deprecated; use classname",
             DeprecationWarning,
             stacklevel=2,
         )
         classname = new_class_name
     collector = codeanalyze.ChangeCollector(self.pymodule.source_code)
     start, end = sourceutils.get_body_region(self.pyfunction)
     indents = sourceutils.get_indents(
         self.pymodule.lines,
         self.pyfunction.get_scope().get_start()) + sourceutils.get_indent(
             self.project)
     new_contents = " " * indents + "return %s(%s)()\n" % (
         classname,
         ", ".join(self._get_parameter_names()),
     )
     collector.add_change(start, end, new_contents)
     insertion = self._get_class_insertion_point()
     collector.add_change(insertion, insertion,
                          "\n\n" + self.get_new_class(classname))
     changes = change.ChangeSet(
         "Replace method with method object refactoring")
     changes.add_change(
         change.ChangeContents(self.resource, collector.get_changed()))
     return changes
Example #5
0
 def substitute(self, mapping):
     collector = codeanalyze.ChangeCollector(self.template)
     for name, occurrences in self.names.items():
         for region in occurrences:
             collector.add_change(region[0], region[1], mapping[name])
     result = collector.get_changed()
     if result is None:
         return self.template
     return result
Example #6
0
 def extract(self):
     extract_info = self._collect_info()
     content = codeanalyze.ChangeCollector(self.info.source)
     definition = extract_info.definition
     lineno, indents = extract_info.definition_location
     offset = self.info.lines.get_line_start(lineno)
     indented = sourceutils.fix_indentation(definition, indents)
     content.add_change(offset, offset, indented)
     self._replace_occurrences(content, extract_info)
     return content.get_changed()
Example #7
0
 def get_changes(self, new_parameter):
     definition_info = functionutils.DefinitionInfo.read(self.pyfunction)
     definition_info.args_with_defaults.append((new_parameter, self._get_primary()))
     collector = codeanalyze.ChangeCollector(self.resource.read())
     header_start, header_end = self._get_header_offsets()
     body_start, body_end = sourceutils.get_body_region(self.pyfunction)
     collector.add_change(header_start, header_end, definition_info.to_string())
     self._change_function_occurrences(
         collector, body_start, body_end, new_parameter
     )
     changes = rope.base.change.ChangeSet("Introduce parameter <%s>" % new_parameter)
     change = rope.base.change.ChangeContents(self.resource, collector.get_changed())
     changes.add_change(change)
     return changes
Example #8
0
def make_pattern(code, variables):
    variables = set(variables)
    collector = codeanalyze.ChangeCollector(code)

    def does_match(node, name):
        return isinstance(node, ast.Name) and node.id == name

    finder = RawSimilarFinder(code, does_match=does_match)
    for variable in variables:
        for match in finder.get_matches('${%s}' % variable):
            start, end = match.get_region()
            collector.add_change(start, end, '${%s}' % variable)
    result = collector.get_changed()
    return result if result is not None else code
 def _get_node_text(self, node, force=False):
     if not force and node in self.matched_asts:
         return self._get_matched_text(self.matched_asts[node])
     start, end = patchedast.node_region(node)
     main_text = self.source[start:end]
     collector = codeanalyze.ChangeCollector(main_text)
     for node in self._get_nearest_roots(node):
         sub_start, sub_end = patchedast.node_region(node)
         collector.add_change(sub_start - start, sub_end - start,
                              self._get_node_text(node))
     result = collector.get_changed()
     if result is None:
         return main_text
     return result
Example #10
0
def real_code(source):
    """Simplify `source` for analysis

    It replaces:

    * comments with spaces
    * strs with a new str filled with spaces
    * implicit and explicit continuations with spaces
    * tabs and semicolons with spaces

    The resulting code is a lot easier to analyze if we are interested
    only in offsets.
    """
    collector = codeanalyze.ChangeCollector(source)
    for start, end, matchgroups in ignored_regions(source):
        if source[start] == "#":
            replacement = " " * (end - start)
        elif "f" in matchgroups.get("prefix", "").lower():
            replacement = None
        else:
            replacement = '"%s"' % (" " * (end - start - 2))
        if replacement is not None:
            collector.add_change(start, end, replacement)
    source = collector.get_changed() or source
    collector = codeanalyze.ChangeCollector(source)
    parens = 0
    for match in _parens.finditer(source):
        i = match.start()
        c = match.group()
        if c in "({[":
            parens += 1
        if c in ")}]":
            parens -= 1
        if c == "\n" and parens > 0:
            collector.add_change(i, i + 1, " ")
    source = collector.get_changed() or source
    return source.replace("\\\n", "  ").replace("\t", " ").replace(";", "\n")
 def get_changed_module(self):
     source = self.resource.read()
     change_collector = codeanalyze.ChangeCollector(source)
     if self.replacement is not None:
         change_collector.add_change(self.skip_start, self.skip_end,
                                     self.replacement)
     for occurrence in self.occurrence_finder.find_occurrences(self.resource):
         start, end = occurrence.get_primary_range()
         if self.skip_start <= start < self.skip_end:
             self.handle.occurred_inside_skip(change_collector, occurrence)
         else:
             self.handle.occurred_outside_skip(change_collector, occurrence)
     result = change_collector.get_changed()
     if result is not None and result != source:
         return result
Example #12
0
    def get_changes(self):
        changes = change.ChangeSet('Generate %s <%s>' %
                                   (self._get_element_kind(), self.name))
        indents = self.info.get_scope_indents()
        blanks = self.info.get_blank_lines()
        base_definition = sourceutils.fix_indentation(self._get_element(), indents)
        definition = '\n' * blanks[0] + base_definition + '\n' * blanks[1]

        resource = self.info.get_insertion_resource()
        start, end = self.info.get_insertion_offsets()

        collector = codeanalyze.ChangeCollector(resource.read())
        collector.add_change(start, end, definition)
        changes.add_change(change.ChangeContents(
                           resource, collector.get_changed()))
        return changes
 def get_changed(self):
     if self._is_expression():
         result = self._get_node_text(self.ast)
         if result == self.source:
             return None
         return result
     else:
         collector = codeanalyze.ChangeCollector(self.source)
         last_end = -1
         for match in self.matches:
             start, end = match.get_region()
             if start < last_end:
                 if not self._is_expression():
                     continue
             last_end = end
             replacement = self._get_matched_text(match)
             collector.add_change(start, end, replacement)
         return collector.get_changed()
Example #14
0
 def get_changed_module(self):
     word_finder = worder.Worder(self.source)
     change_collector = codeanalyze.ChangeCollector(self.source)
     for occurrence in self.occurrence_finder.find_occurrences(
             self.resource):
         if not occurrence.is_called() and not occurrence.is_defined():
             continue
         start, end = occurrence.get_primary_range()
         begin_parens, end_parens = word_finder.get_word_parens_range(end -
                                                                      1)
         if occurrence.is_called():
             primary, pyname = occurrence.get_primary_and_pyname()
             changed_call = self.call_changer.change_call(
                 primary, pyname, self.source[start:end_parens])
         else:
             changed_call = self.call_changer.change_definition(
                 self.source[start:end_parens])
         if changed_call is not None:
             change_collector.add_change(start, end_parens, changed_call)
     return change_collector.get_changed()
Example #15
0
    def get_changes(self):
        changes = change.ChangeSet("Generate %s <%s>" %
                                   (self._get_element_kind(), self.name))
        indents = self.info.get_scope_indents()
        blanks = self.info.get_blank_lines()
        base_definition = sourceutils.fix_indentation(self._get_element(),
                                                      indents)
        definition = "\n" * blanks[0] + base_definition + "\n" * blanks[1]

        resource = self.info.get_insertion_resource()
        start, end = self.info.get_insertion_offsets()

        collector = codeanalyze.ChangeCollector(resource.read())
        collector.add_change(start, end, definition)
        changes.add_change(
            change.ChangeContents(resource, collector.get_changed()))
        if self.goal_resource:
            relative_import = _add_relative_import_to_module(
                self.project, self.resource, self.goal_resource, self.name)
            changes.add_change(relative_import)
        return changes