1. zjes
  2. rope_py3k

Commits

Ali Gholami Rudi  committed 2f80abf

Using WordRangeFinder.get_name_at

  • Participants
  • Parent commits 3d46bb8
  • Branches trunk

Comments (0)

Files changed (6)

File docs/workingon.txt

View file
  • Ignore whitespace
 Complete ``AClass(param).a_``
 =============================
 
-1. Find the statement
-2. Parse the statement
-3. Walk the statement
-
-Statements are: 
-1. Atoms
-2. Primaries and operators
-3. Simple statements
-4. Compound statements
-
-* WorkRangeFinder should return one string?
+* Deploying WordRangeFinder.get_name_at
+* WordRangeFinder.get_name_at to WordRangeFinder.get_expression_at
+* (a_statment + another_statment).an_attr
+* dictionaries
+* Triples
+* " some string
+* Comments
 
 * Names in strings or comments
 * Using ScopeNameFinder in _CodeCompletionCollector
   * Dividing week time; 5/7 for core and 2/7 for UI
 
 * The same pattern for module names; ~ing or ~ or ~er
+* New package structure
+  ::
+    rope/
+      core/
+        ...
+      ui/
+        ...
 

File rope/codeanalyze.py

View file
  • Ignore whitespace
     def __init__(self, source_code):
         self.source_code = source_code
     
-    def find_word_start(self, offset):
-        current_offset = offset - 1
+    def _find_word_start(self, offset):
+        current_offset = offset
         while current_offset >= 0 and (self.source_code[current_offset].isalnum() or
                                        self.source_code[current_offset] in '_'):
             current_offset -= 1;
         return current_offset + 1
     
-    def find_word_end(self, offset):
-        current_offset = offset
+    def _find_word_end(self, offset):
+        current_offset = offset + 1
         while current_offset < len(self.source_code) and \
               (self.source_code[current_offset].isalnum() or
                self.source_code[current_offset] in '_'):
             current_offset += 1;
-        return current_offset
+        return current_offset - 1
 
-    def _find_statement_start(self, offset):
-        current_offset = offset - 1
-        while current_offset >= 0 and (self.source_code[current_offset].isalnum() or
-                                       self.source_code[current_offset] in '_()\'"'):
-            current_offset -= 1;
-        return current_offset + 1
-    
     def _find_last_non_space_char(self, offset):
         current_offset = offset
         while current_offset >= 0 and self.source_code[current_offset] in ' \t\n':
         return current_offset
     
     def get_word_before(self, offset):
-        return self.source_code[self.find_word_start(offset):offset]
+        return self.source_code[self._find_word_start(offset - 1):offset]
     
     def get_word_at(self, offset):
-        return self.source_code[self.find_word_start(offset):self.find_word_end(offset)]
+        return self.source_code[self._find_word_start(offset - 1):self._find_word_end(offset - 1) + 1]
     
-    def get_name_list_before(self, offset):
-        result = []
+    def _find_string_start(self, offset):
+        kind = self.source_code[offset]
         current_offset = offset - 1
-        if current_offset < 0 or self.source_code[current_offset] in ' \t\n.':
-            result.append('')
-            current_offset = self._find_last_non_space_char(current_offset)
-            if current_offset >= 0 and self.source_code[current_offset] == '.':
-                current_offset -= 1
+        while self.source_code[current_offset] != kind:
+            current_offset -= 1
+        return current_offset
+    
+    def _find_parens_start(self, offset):
+        current_offset = self._find_last_non_space_char(offset - 1)
+        while current_offset >= 0 and self.source_code[current_offset] not in '[(':
+            if self.source_code[current_offset] in ':,':
+                pass
             else:
-                return result
-        while current_offset >= 0:
-            current_offset = self._find_last_non_space_char(current_offset)
-            if current_offset >= 0:
-                word_start = self.find_word_start(current_offset)
-                result.append(self.source_code[word_start:current_offset + 1])
-                current_offset = word_start - 1
-            current_offset = self._find_last_non_space_char(current_offset)
-            if current_offset >= 0 and self.source_code[current_offset] == '.':
-                current_offset -= 1
-            else:
-                break
-        result.reverse()
-        return result
+                current_offset = self._find_name_start(current_offset)
+            current_offset = self._find_last_non_space_char(current_offset - 1)
+        return current_offset
 
-    def get_name_list_at(self, offset):
-        result = self.get_name_list_before(offset)
-        result[-1] = self.get_word_at(offset)
-        return result
+    def _find_atom_start(self, offset):
+        old_offset = offset
+        if self.source_code[offset] in '\n\t ':
+            offset = self._find_last_non_space_char(offset)
+        if self.source_code[offset] in '\'"':
+            return self._find_string_start(offset)
+        if self.source_code[offset] in ')]':
+            return self._find_parens_start(offset)
+        if self.source_code[offset].isalnum() or self.source_code[offset] == '_':
+            return self._find_word_start(offset)
+        return old_offset
 
+    def _find_name_start(self, offset):
+        current_offset = offset + 1
+        if self.source_code[offset] != '.':
+            current_offset = self._find_atom_start(offset)
+        while current_offset > 0 and \
+              self.source_code[self._find_last_non_space_char(current_offset - 1)] == '.':
+            current_offset = self._find_last_non_space_char(current_offset - 1)
+            current_offset = self._find_last_non_space_char(current_offset - 1)
+            if self.source_code[current_offset].isalnum() or self.source_code[current_offset] == '_':
+                current_offset = self._find_word_start(current_offset)
+            elif self.source_code[current_offset] in '\'"':
+                current_offset = self._find_string_start(current_offset)
+            elif self.source_code[current_offset] in ')]':
+                current_offset = self._find_parens_start(current_offset)
+                if current_offset == 0:
+                    break
+                current_offset = self._find_last_non_space_char(current_offset - 1)
+                if self.source_code[current_offset].isalnum() or \
+                   self.source_code[current_offset] == '_':
+                    current_offset = self._find_word_start(current_offset)
+                else:
+                    break
+        return current_offset
+    
     def get_name_at(self, offset):
-        return self.source_code[self.find_word_start(offset):self.find_word_end(offset)]
+        return self.source_code[self._find_name_start(offset - 1):
+                                self._find_word_end(offset - 1) + 1].strip()
+
+    def get_splitted_name_before(self, offset):
+        """returns expression, starting, starting_offset"""
+        if offset == 0:
+            return ('', '', 0)
+        word_start = self._find_atom_start(offset - 1)
+        real_start = self._find_name_start(offset - 1)
+        if self.source_code[word_start:offset].strip() == '':
+            word_start = offset
+        if self.source_code[real_start:offset].strip() == '':
+            real_start = offset
+        if real_start == word_start:
+            return ('', self.source_code[word_start:offset], word_start)
+        else:
+            if self.source_code[offset - 1] == '.':
+                return (self.source_code[real_start:offset - 1], '', offset)
+            last_dot_position = word_start
+            if self.source_code[word_start] != '.':
+                last_dot_position = self._find_last_non_space_char(word_start - 1)
+            last_char_position = self._find_last_non_space_char(last_dot_position - 1)
+            return (self.source_code[real_start:last_char_position + 1],
+                    self.source_code[word_start:offset], word_start)
+        
 
 
 class HoldingScopeFinder(object):
         self.word_finder = WordRangeFinder(source_code)
     
     def get_pyname_at(self, offset):
-        name_list = self.word_finder.get_name_list_at(offset)
+        name = self.word_finder.get_name_at(offset)
         lineno = self.scope_finder.get_location(offset)[0]
         holding_scope = self.scope_finder.get_holding_scope(self.module_scope, lineno)
-        result = self.get_pyname_in_scope(holding_scope, name_list)
+        result = self.get_pyname_in_scope(holding_scope, name)
         # This occurs if renaming a function parameter
         if result is None and lineno < len(self.lines):
             next_scope = self.scope_finder.get_holding_scope(self.module_scope, lineno + 1)
-            result = self.get_pyname_in_scope(next_scope, name_list)
+            result = self.get_pyname_in_scope(next_scope, name)
         return result
     
-    def get_pyname_in_scope(self, holding_scope, name_list):
-        ast = compiler.parse('.'.join(name_list))
+    def get_pyname_in_scope(self, holding_scope, name):
+        ast = compiler.parse(name)
         result = _StatementEvaluator.get_statement_result(holding_scope, ast)
         return result
 

File rope/codeassist.py

View file
  • Ignore whitespace
 
 class _CodeCompletionCollector(object):
 
-    def __init__(self, project, source_code, offset, starting):
+    def __init__(self, project, source_code, offset, expression, starting):
         self.project = project
+        self.expression = expression
         self.starting = starting
         self.pycore = self.project.get_pycore()
         self.lines = source_code.split('\n')
     def _get_dotted_completions(self, module_scope, holding_scope):
         result = {}
         pyname_finder = ScopeNameFinder(self.source_code, module_scope)
-        element = pyname_finder.get_pyname_in_scope(holding_scope, self.starting[:-1])
+        element = pyname_finder.get_pyname_in_scope(holding_scope, self.expression)
         if element is not None:
             for name, pyname in element.get_attributes().iteritems():
-                if name.startswith(self.starting[-1]) or self.starting[-1] == '':
+                if name.startswith(self.starting) or self.starting == '':
                     result[name] = CompletionProposal(name, 'attribute')
         return result
 
         if scope.parent != None:
             self._get_undotted_completions(scope.parent, result)
         for name, pyname in scope.get_names().iteritems():
-            if name.startswith(self.starting[0]):
+            if name.startswith(self.starting):
                 from rope.pycore import PyObject
                 kind = 'local'
                 if scope.get_kind() == 'Module':
         current_scope = module_scope
         result = {}
         inner_scope = self._find_inner_holding_scope(module_scope)
-        if len(self.starting) > 1:
+        if self.expression.strip() != '':
             result.update(self._get_dotted_completions(module_scope, inner_scope))
         else:
             self._get_undotted_completions(inner_scope, result)
                 result.append(template)
         return result
 
-    def _get_code_completions(self, source_code, offset, starting):
-        collector = _CodeCompletionCollector(self.project, source_code, offset, starting)
+    def _get_code_completions(self, source_code, offset, expression, starting):
+        collector = _CodeCompletionCollector(self.project, source_code,
+                                             offset, expression, starting)
         return collector.get_code_completions()
 
     def assist(self, source_code, offset):
         if offset > len(source_code):
             return Proposals()
         word_finder = WordRangeFinder(source_code)
-        starting_offset = word_finder.find_word_start(offset)
-        starting = word_finder.get_name_list_before(offset)
-        completions = self._get_code_completions(source_code, offset, starting)
+        expression, starting, starting_offset = word_finder.get_splitted_name_before(offset)
+        completions = self._get_code_completions(source_code, offset, expression, starting)
         templates = []
-        if len(starting) == 1 and len(starting[0]) > 0:
-            completions.update(self._get_matching_builtins(starting[0]))
-            completions.update(self._get_matching_keywords(starting[0]))
-            templates = self._get_template_proposals(starting[0])
+        if expression.strip() == '' and starting.strip() != '':
+            completions.update(self._get_matching_builtins(starting))
+            completions.update(self._get_matching_keywords(starting))
+            templates = self._get_template_proposals(starting)
         return Proposals(completions.values(), templates,
                          starting_offset)
 

File rope/refactoring.py

View file
  • Ignore whitespace
         result = []
         module_scope = self.pycore.get_string_scope(source_code)
         word_finder = WordRangeFinder(source_code)
-        old_name = '.'.join(word_finder.get_name_list_at(offset))
+        old_name = word_finder.get_name_at(offset)
         pyname_finder = ScopeNameFinder(source_code, module_scope)
         old_pyname = pyname_finder.get_pyname_at(offset)
         if old_pyname is None:

File ropetest/codeanalyzetest.py

View file
  • Ignore whitespace
 
     def test_inside_parans(self):
         word_finder = WordRangeFinder('a_func(a_var)')
-        self.assertEquals(['a_v'], word_finder.get_name_list_before(10))
+        self.assertEquals('a_var', word_finder.get_name_at(10))
 
     def test_simple_names(self):
         word_finder = WordRangeFinder('a_var = 10')
         word_finder = WordRangeFinder('sample_function()')
         self.assertEquals('sample_function', word_finder.get_name_at(10))
     
-    # TODO: make it pass
-    def xxx_test_attribute_accesses(self):
+    def test_attribute_accesses(self):
         word_finder = WordRangeFinder('a_var.an_attr')
         self.assertEquals('a_var.an_attr', word_finder.get_name_at(10))
     
-    # TODO: make it pass
-    def xxx_test_strings(self):
+    def test_strings(self):
         word_finder = WordRangeFinder('"a string".split()')
-        self.assertEquals(['"a string"', 'split'], word_finder.get_name_list_at(14))
+        self.assertEquals('"a string".split', word_finder.get_name_at(14))
 
-    # TODO: make it pass
-    def xxx_test_function_calls(self):
-        word_finder = WordRangeFinder('file("test.txt").read()')
-        self.assertEquals(['file("afile.txt")', 'read'], word_finder.get_name_list_at(18))
+    def test_function_calls(self):
+        word_finder = WordRangeFinder('file("afile.txt").read()')
+        self.assertEquals('file("afile.txt").read', word_finder.get_name_at(18))
+
+    def test_parens(self):
+        word_finder = WordRangeFinder('("afile.txt").split()')
+        self.assertEquals('("afile.txt").split', word_finder.get_name_at(18))
+
+    def test_function_with_no_param(self):
+        word_finder = WordRangeFinder('AClass().a_func()')
+        self.assertEquals('AClass().a_func', word_finder.get_name_at(12))
+
+    def test_function_with_multiple_param(self):
+        word_finder = WordRangeFinder('AClass(a_param, another_param, "a string").a_func()')
+        self.assertEquals('AClass(a_param, another_param, "a string").a_func',
+                          word_finder.get_name_at(44))
+    
+    def test_param_expressions(self):
+        word_finder = WordRangeFinder('AClass(an_object.an_attr).a_func()')
+        self.assertEquals('an_object.an_attr', word_finder.get_name_at(20))
+
+    def test_string_parens(self):
+        word_finder = WordRangeFinder('a_func("(").an_attr')
+        self.assertEquals('a_func("(").an_attr', word_finder.get_name_at(16))
+
+    def test_extra_spaces(self):
+        word_finder = WordRangeFinder('a_func  (  "(" ) .   an_attr')
+        self.assertEquals('a_func  (  "(" ) .   an_attr', word_finder.get_name_at(26))
+
+    def test_splitted_name(self):
+        word_finder = WordRangeFinder('an_object.an_attr')
+        self.assertEquals(('an_object', 'an_at', 10), word_finder.get_splitted_name_before(15))
+
+    def test_empty_splitted_name(self):
+        word_finder = WordRangeFinder('an_attr')
+        self.assertEquals(('', 'an_at', 0), word_finder.get_splitted_name_before(5))
+
+    def test_empty_splitted_name2(self):
+        word_finder = WordRangeFinder('an_object.')
+        self.assertEquals(('an_object', '', 10), word_finder.get_splitted_name_before(10))
+
+    def test_empty_splitted_name3(self):
+        word_finder = WordRangeFinder('')
+        self.assertEquals(('', '', 0), word_finder.get_splitted_name_before(0))
+
+    def test_empty_splitted_name4(self):
+        word_finder = WordRangeFinder('a_var = ')
+        self.assertEquals(('', '', 8), word_finder.get_splitted_name_before(8))
 
 
 def suite():

File ropetest/codeassisttest.py

View file
  • Ignore whitespace
                           lambda: self.assist.assist(code, len(code)))
     
     def test_ignoring_errors_in_current_line(self):
-        code = 'def my_func():    return 2\nt = '
+        code = 'def my_func():\n    return 2\nt = '
         result = self.assist.assist(code, len(code))
         self.assert_completion_in_result('my_func', 'global', result)