Anonymous avatar Anonymous committed a49e48e

codeanalyze: added CustomLogicalLineFinder

Comments (0)

Files changed (2)

rope/base/codeanalyze.py

             self._min_ends[start] = min_end
 
 
+class CustomLogicalLineFinder(CachingLogicalLineFinder):
+    """A method object for finding the range of a statement"""
+
+    def __init__(self, lines, code):
+        self.code = code
+        super(CustomLogicalLineFinder, self).__init__(lines)
+        self.in_string = ''
+        self.open_count = 0
+        self.explicit_continuation = False
+
+    def _init_logicals(self):
+        size = self.lines.length()
+        self._starts = [False] * (size + 1)
+        self._ends = [False] * (size + 1)
+        i = 1
+        while i <= size:
+            while i <= size and self.lines.get_line(i).strip() == '':
+                i += 1
+            if i <= size:
+                self._starts[i] = True
+                self._analyze_line(i)
+                while (self.explicit_continuation
+                       or self.open_count or self.in_string):
+                    i += 1
+                    self._analyze_line(i)
+                self._ends[i] = True
+                i += 1
+
+    def _analyze_line(self, lineno):
+        current_line = self.lines.get_line(lineno)
+        for i, char in enumerate(current_line):
+            if char in '\'"':
+                if self.in_string == '':
+                    self.in_string = char
+                    if char * 3 == current_line[i:i + 3]:
+                        self.in_string = char * 3
+                elif self.in_string == current_line[i:i + len(self.in_string)] and \
+                     not (i > 0 and current_line[i - 1] == '\\' and
+                          not (i > 1 and current_line[i - 2:i] == '\\\\')):
+                    self.in_string = ''
+            if self.in_string != '':
+                continue
+            if char == '#':
+                break
+            if char in '([{':
+                self.open_count += 1
+            if char in ')]}':
+                self.open_count -= 1
+        if current_line and char != '#' and current_line.endswith('\\'):
+            self.explicit_continuation = True
+        else:
+            self.explicit_continuation = False
+
+
 class LogicalLineFinder(object):
 
     def __init__(self, lines):

ropetest/codeanalyzetest.py

 from rope.base import exceptions, ast
 from rope.base.codeanalyze import \
     (CachingLogicalLineFinder, SourceLinesAdapter, WordRangeFinder,
-     LogicalLineFinder, get_block_start, ASTLogicalLineFinder)
+     LogicalLineFinder, get_block_start, ASTLogicalLineFinder, CustomLogicalLineFinder)
 from ropetest import testutils
 
 
         line_finder = self._logical_finder(code)
         self.assertEquals([4, 5], list(line_finder.generate_starts(4)))
 
+    def test_logical_lines_for_else(self):
+        code = 'if True:\n    pass\nelse:\n    pass\n'
+        line_finder = self._logical_finder(code)
+        self.assertEquals([3, 4], list(line_finder.generate_starts(3)))
+
 class CachingLogicalLineFinderTest(LogicalLineFinderTest):
 
     def _logical_finder(self, code):
         node = ast.parse(code)
         return ASTLogicalLineFinder(node, SourceLinesAdapter(code))
 
+class ASTLogicalLineFinderTest(LogicalLineFinderTest):
+
+    def _logical_finder(self, code):
+        return CustomLogicalLineFinder(SourceLinesAdapter(code), code)
+
 
 def suite():
     result = unittest.TestSuite()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.