suites.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. from rope.base import ast
  2. def find_visible(node, lines):
  3. """Return the line which is visible from all `lines`"""
  4. root = ast_suite_tree(node)
  5. return find_visible_for_suite(root, lines)
  6. def find_visible_for_suite(root, lines):
  7. if len(lines) == 1:
  8. return lines[0]
  9. line1 = lines[0]
  10. line2 = find_visible_for_suite(root, lines[1:])
  11. suite1 = root.find_suite(line1)
  12. suite2 = root.find_suite(line2)
  13. def valid(suite):
  14. return suite is not None and not suite.ignored
  15. if valid(suite1) and not valid(suite2):
  16. return line1
  17. if not valid(suite1) and valid(suite2):
  18. return line2
  19. if not valid(suite1) and not valid(suite2):
  20. return None
  21. while suite1 != suite2 and suite1.parent != suite2.parent:
  22. if suite1._get_level() < suite2._get_level():
  23. line2 = suite2.get_start()
  24. suite2 = suite2.parent
  25. elif suite1._get_level() > suite2._get_level():
  26. line1 = suite1.get_start()
  27. suite1 = suite1.parent
  28. else:
  29. line1 = suite1.get_start()
  30. line2 = suite2.get_start()
  31. suite1 = suite1.parent
  32. suite2 = suite2.parent
  33. if suite1 == suite2:
  34. return min(line1, line2)
  35. return min(suite1.get_start(), suite2.get_start())
  36. def ast_suite_tree(node):
  37. if hasattr(node, 'lineno'):
  38. lineno = node.lineno
  39. else:
  40. lineno = 1
  41. return Suite(node.body, lineno)
  42. class Suite(object):
  43. def __init__(self, child_nodes, lineno, parent=None, ignored=False):
  44. self.parent = parent
  45. self.lineno = lineno
  46. self.child_nodes = child_nodes
  47. self._children = None
  48. self.ignored = ignored
  49. def get_start(self):
  50. if self.parent is None:
  51. if self.child_nodes:
  52. return self.local_start()
  53. else:
  54. return 1
  55. return self.lineno
  56. def get_children(self):
  57. if self._children is None:
  58. walker = _SuiteWalker(self)
  59. for child in self.child_nodes:
  60. ast.walk(child, walker)
  61. self._children = walker.suites
  62. return self._children
  63. def local_start(self):
  64. return self.child_nodes[0].lineno
  65. def local_end(self):
  66. end = self.child_nodes[-1].lineno
  67. if self.get_children():
  68. end = max(end, self.get_children()[-1].local_end())
  69. return end
  70. def find_suite(self, line):
  71. if line is None:
  72. return None
  73. for child in self.get_children():
  74. if child.local_start() <= line <= child.local_end():
  75. return child.find_suite(line)
  76. return self
  77. def _get_level(self):
  78. if self.parent is None:
  79. return 0
  80. return self.parent._get_level() + 1
  81. class _SuiteWalker(object):
  82. def __init__(self, suite):
  83. self.suite = suite
  84. self.suites = []
  85. def _If(self, node):
  86. self._add_if_like_node(node)
  87. def _For(self, node):
  88. self._add_if_like_node(node)
  89. def _While(self, node):
  90. self._add_if_like_node(node)
  91. def _With(self, node):
  92. self.suites.append(Suite(node.body, node.lineno, self.suite))
  93. def _TryFinally(self, node):
  94. if len(node.finalbody) == 1 and \
  95. isinstance(node.body[0], ast.TryExcept):
  96. self._TryExcept(node.body[0])
  97. else:
  98. self.suites.append(Suite(node.body, node.lineno, self.suite))
  99. self.suites.append(Suite(node.finalbody, node.lineno, self.suite))
  100. def _TryExcept(self, node):
  101. self.suites.append(Suite(node.body, node.lineno, self.suite))
  102. for handler in node.handlers:
  103. self.suites.append(Suite(handler.body, node.lineno, self.suite))
  104. if node.orelse:
  105. self.suites.append(Suite(node.orelse, node.lineno, self.suite))
  106. def _add_if_like_node(self, node):
  107. self.suites.append(Suite(node.body, node.lineno, self.suite))
  108. if node.orelse:
  109. self.suites.append(Suite(node.orelse, node.lineno, self.suite))
  110. def _FunctionDef(self, node):
  111. self.suites.append(Suite(node.body, node.lineno,
  112. self.suite, ignored=True))
  113. def _ClassDef(self, node):
  114. self.suites.append(Suite(node.body, node.lineno,
  115. self.suite, ignored=True))