Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(507)

Unified Diff: tools/telemetry/third_party/rope/rope/contrib/fixsyntax.py

Issue 1132103009: Example of refactoring using rope library. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/third_party/rope/rope/contrib/fixsyntax.py
diff --git a/tools/telemetry/third_party/rope/rope/contrib/fixsyntax.py b/tools/telemetry/third_party/rope/rope/contrib/fixsyntax.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc45ad19b3458a3a0cacfad11492dac828e32312
--- /dev/null
+++ b/tools/telemetry/third_party/rope/rope/contrib/fixsyntax.py
@@ -0,0 +1,181 @@
+import rope.base.codeanalyze
+import rope.base.evaluate
+from rope.base import exceptions
+from rope.base import libutils
+from rope.base import utils
+from rope.base import worder
+from rope.base.codeanalyze import ArrayLinesAdapter, LogicalLineFinder
+
+
+class FixSyntax(object):
+
+ def __init__(self, project, code, resource, maxfixes=1):
+ self.project = project
+ self.code = code
+ self.resource = resource
+ self.maxfixes = maxfixes
+
+ @utils.saveit
+ def get_pymodule(self):
+ """Get a `PyModule`"""
+ msg = None
+ code = self.code
+ tries = 0
+ while True:
+ try:
+ if tries == 0 and self.resource is not None and \
+ self.resource.read() == code:
+ return self.project.get_pymodule(self.resource,
+ force_errors=True)
+ return libutils.get_string_module(
+ self.project, code, resource=self.resource,
+ force_errors=True)
+ except exceptions.ModuleSyntaxError as e:
+ if msg is None:
+ msg = '%s:%s %s' % (e.filename, e.lineno, e.message_)
+ if tries < self.maxfixes:
+ tries += 1
+ self.commenter.comment(e.lineno)
+ code = '\n'.join(self.commenter.lines)
+ else:
+ raise exceptions.ModuleSyntaxError(
+ e.filename, e.lineno,
+ 'Failed to fix error: {0}'.format(msg))
+
+ @property
+ @utils.saveit
+ def commenter(self):
+ return _Commenter(self.code)
+
+ def pyname_at(self, offset):
+ pymodule = self.get_pymodule()
+
+ def old_pyname():
+ word_finder = worder.Worder(self.code, True)
+ expression = word_finder.get_primary_at(offset)
+ expression = expression.replace('\\\n', ' ').replace('\n', ' ')
+ lineno = self.code.count('\n', 0, offset)
+ scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+ return rope.base.evaluate.eval_str(scope, expression)
+ new_code = pymodule.source_code
+
+ def new_pyname():
+ newoffset = self.commenter.transfered_offset(offset)
+ return rope.base.evaluate.eval_location(pymodule, newoffset)
+ if new_code.startswith(self.code[:offset + 1]):
+ return new_pyname()
+ result = old_pyname()
+ if result is None:
+ return new_pyname()
+ return result
+
+
+class _Commenter(object):
+
+ def __init__(self, code):
+ self.code = code
+ self.lines = self.code.split('\n')
+ self.lines.append('\n')
+ self.origs = range(len(self.lines) + 1)
+ self.diffs = [0] * (len(self.lines) + 1)
+
+ def comment(self, lineno):
+ start = _logical_start(self.lines, lineno, check_prev=True) - 1
+ # using self._get_stmt_end() instead of self._get_block_end()
+ # to lower commented lines
+ end = self._get_stmt_end(start)
+ indents = _get_line_indents(self.lines[start])
+ if 0 < start:
+ last_lineno = self._last_non_blank(start - 1)
+ last_line = self.lines[last_lineno]
+ if last_line.rstrip().endswith(':'):
+ indents = _get_line_indents(last_line) + 4
+ self._set(start, ' ' * indents + 'pass')
+ for line in range(start + 1, end + 1):
+ self._set(line, self.lines[start])
+ self._fix_incomplete_try_blocks(lineno, indents)
+
+ def transfered_offset(self, offset):
+ lineno = self.code.count('\n', 0, offset)
+ diff = sum(self.diffs[:lineno])
+ return offset + diff
+
+ def _last_non_blank(self, start):
+ while start > 0 and self.lines[start].strip() == '':
+ start -= 1
+ return start
+
+ def _get_block_end(self, lineno):
+ end_line = lineno
+ base_indents = _get_line_indents(self.lines[lineno])
+ for i in range(lineno + 1, len(self.lines)):
+ if _get_line_indents(self.lines[i]) >= base_indents:
+ end_line = i
+ else:
+ break
+ return end_line
+
+ def _get_stmt_end(self, lineno):
+ base_indents = _get_line_indents(self.lines[lineno])
+ for i in range(lineno + 1, len(self.lines)):
+ if _get_line_indents(self.lines[i]) <= base_indents:
+ return i - 1
+ return lineno
+
+ def _fix_incomplete_try_blocks(self, lineno, indents):
+ block_start = lineno
+ last_indents = indents
+ while block_start > 0:
+ block_start = rope.base.codeanalyze.get_block_start(
+ ArrayLinesAdapter(self.lines), block_start) - 1
+ if self.lines[block_start].strip().startswith('try:'):
+ indents = _get_line_indents(self.lines[block_start])
+ if indents > last_indents:
+ continue
+ last_indents = indents
+ block_end = self._find_matching_deindent(block_start)
+ line = self.lines[block_end].strip()
+ if not (line.startswith('finally:') or
+ line.startswith('except ') or
+ line.startswith('except:')):
+ self._insert(block_end, ' ' * indents + 'finally:')
+ self._insert(block_end + 1, ' ' * indents + ' pass')
+
+ def _find_matching_deindent(self, line_number):
+ indents = _get_line_indents(self.lines[line_number])
+ current_line = line_number + 1
+ while current_line < len(self.lines):
+ line = self.lines[current_line]
+ if not line.strip().startswith('#') and not line.strip() == '':
+ # HACK: We should have used logical lines here
+ if _get_line_indents(self.lines[current_line]) <= indents:
+ return current_line
+ current_line += 1
+ return len(self.lines) - 1
+
+ def _set(self, lineno, line):
+ self.diffs[self.origs[lineno]] += len(line) - len(self.lines[lineno])
+ self.lines[lineno] = line
+
+ def _insert(self, lineno, line):
+ self.diffs[self.origs[lineno]] += len(line) + 1
+ self.origs.insert(lineno, self.origs[lineno])
+ self.lines.insert(lineno, line)
+
+
+def _logical_start(lines, lineno, check_prev=False):
+ logical_finder = LogicalLineFinder(ArrayLinesAdapter(lines))
+ if check_prev:
+ prev = lineno - 1
+ while prev > 0:
+ start, end = logical_finder.logical_line_in(prev)
+ if end is None or start <= lineno < end:
+ return start
+ if start <= prev:
+ break
+ prev -= 1
+ return logical_finder.logical_line_in(lineno)[0]
+
+
+def _get_line_indents(line):
+ return rope.base.codeanalyze.count_line_indents(line)

Powered by Google App Engine
This is Rietveld 408576698