Anonymous avatar Anonymous committed 02a5dff

Handling AssName in SimilarFinder, too

Comments (0)

Files changed (6)

docs/dev/issues.txt

 
 Suggestions and issues:
 
-* ``${*a}``: Match any statement
+* Where can wildcards appear?
 
-  The main reason for expression lists is matching `Stmt` nodes.  That
+  Although the names can appear in many places we limit that by
+  forcing the wildcards to appear only where `Name` and `AssName` can
+  appear.
+
+* ``${*a}``: Match any statement?
+
+  The main reason for statement lists is matching `Stmt` nodes.  That
   is::
 
     class A(object):
     class A(object):
         ${*a}
 
-* Matching names?
-* Assignment vs. reading
 * Efficiency
 
 
+Adding Name Checks
+------------------
+
+Now that we can match similar AST nodes, we can do our last move for
+making the examples in `a look into the future`_ section real.  I
+propose to add a `CheckingFinder`::
+
+  
+
+
 A Look Into The Future
 ----------------------
 
   # ``a = b`` to ``a.set(b)`` where the type of `a` is `type_pyclass`
   pattern = '${?a} = ${?b}'
   goal = '${?a}.set(${?b})'
-  constraints = {'?a.object.type': type_pyclass}
+  checks = {'?a.object.type': type_pyclass}
 
-  # ``a.set(b)`` to ``a = b`` where `set` is `method_pyname`
-  pattern = '${?a}.${set}(${?b})'
+  # ``a.set(b)`` to ``a = b`` where the type of `a` is `type_pyclass`
+  pattern = '${?a}.set(${?b})'
   goal = '${?a} = ${?b}'
-  constraints = {'set': method_pyname}
+  checks = {'?a.object.type': type_pyclass}
 
   # Can we use it for giving self assignment warnings?
   pattern = '${?a} = ${?b}'
-  constraints = {'?a': '?b'}
+  checks = {'?a': '?b'}
 
-  # I don't think rematching is interesting
+  # Rematching might be useful, too
   pattern = '${?x} = [${?a}, ${?a}]'
   goal = '${?x} = [${?a}] * 2'
 
-Suggestions:
-
-* Maybe `constraints` should be replaced with a python method that
-  gets the matched ASTs and returns True or False.
-* Rematching can be implemented by having a layer on top of AST
-  matcher.
-
 
 Patched AST
 ===========

docs/dev/workingon.txt

 Similar Finder
 ==============
 
-- `Match.get_ast()`
-- __rope__variable_normal_a
-- __rope__variable_any_a
+- Handling `AssName`
+- AssName should not matche Name
 
-* Handling multiple assigns
-* Handle assigns
-
-* Inserting common prefix when using codeassist
 * Only scanning selected region for matches
 * Changing patchedast only to patch a branch?
-* One failure in windows
+* One failure on windows!
 
 * Handling '<>' in patchedast
 
 
 UI and IDE:
 
+* Inserting common prefix when using codeassist
 * Renaming normal files, folders, modules, and packages in project tree view
 * Completion in module entries
 * Goto definition for ``"# comment.\na_var"``

rope/refactor/patchedast.py

         return self.source[i:j]
 
     def _get_number_pattern(self):
-        # We should handle integer, long_integer, others, imagnumber
-        # HACK: An approaximation does the job
+        # HACK: It is merely an approaximation and does the job
         integer = r'(0|0x)?[\da-fA-F]+[lL]?'
         return r'(%s(\.\d*)?|(\.\d+))([eE][-+]?\d*)?[jJ]?' % integer
 

rope/refactor/similarfinder.py

     """A class for finding similar expressions and statements"""
 
     def __init__(self, source, start=0, end=None):
-        self.source = source
         self.start = start
-        self.end = len(self.source)
+        self.end = len(source)
         if end is not None:
             self.end = end
-        self.ast = patchedast.get_patched_ast(self.source)
+        self.ast = patchedast.get_patched_ast(source)
 
     def get_matches(self, code):
+        """Search for `code` in source and return a list of `Match`\es
+
+        `code` can contain wildcards.  ``${name}`` matches normal
+        names and ``${?name} can match any expression.  They can
+        only appear in `compiler.ast.Name` and `compiler.ast.AssName`.
+        You can use `Match.get_ast()` for getting the node that has
+        matched a given pattern.
+        """
         wanted = self._create_pattern(code)
         matches = _ASTMatcher(self.ast, wanted).find_matches()
         for match in matches:
     def _create_pattern(self, expression):
         expression = self._replace_wildcards(expression)
         ast = compiler.parse(expression)
-        # Module.Stmt
+        # Getting Module.Stmt.nodes
         nodes = ast.node.nodes
         if len(nodes) == 1 and isinstance(nodes[0], compiler.ast.Discard):
-            # Discard
+            # Getting Discard.expr
             wanted = nodes[0].expr
         else:
             wanted = nodes
                     self.matches.append(StatementMatch(current_stmts, mapping))
 
     def _match_nodes(self, expected, node, mapping):
-        if isinstance(expected, compiler.ast.Name):
+        if isinstance(expected, (compiler.ast.Name, compiler.ast.AssName)):
            if self.ropevar.is_normal(expected.name):
                return self._match_normal_var(expected, node, mapping)
            if self.ropevar.is_any(expected.name):
         return True
 
     def _match_normal_var(self, node1, node2, mapping):
-        if isinstance(node2, compiler.ast.Name) and \
+        if node2.__class__ == node1.__class__ and \
            self.ropevar.get_base(node1.name) == node2.name:
             mapping[self.ropevar.get_base(node1.name)] = node2
             return True
         self.template = template
         self._find_names()
 
-    def get_names(self):
-        return self.names.keys()
-
     def _find_names(self):
         self.names = {}
         for match in _Template._get_pattern().finditer(self.template):
                     self.names[name] = []
                 self.names[name].append((start, end))
 
-    @classmethod
-    def _get_pattern(cls):
-        if cls._match_pattern is None:
-            pattern = codeanalyze.get_comment_pattern() + '|' + \
-                      codeanalyze.get_string_pattern() + '|' + \
-                      r'(?P<name>\$\{\S*\})'
-            cls._match_pattern = re.compile(pattern)
-        return cls._match_pattern
-
-    _match_pattern = None
+    def get_names(self):
+        return self.names.keys()
 
     def substitute(self, mapping):
         collector = sourceutils.ChangeCollector(self.template)
             return self.template
         return result
 
+    _match_pattern = None
+
+    @classmethod
+    def _get_pattern(cls):
+        if cls._match_pattern is None:
+            pattern = codeanalyze.get_comment_pattern() + '|' + \
+                      codeanalyze.get_string_pattern() + '|' + \
+                      r'(?P<name>\$\{\S*\})'
+            cls._match_pattern = re.compile(pattern)
+        return cls._match_pattern
+
 
 class _RopeVariable(object):
     """Transform and identify rope inserted wildcards"""

ropetest/refactor/__init__.py

     result.addTests(unittest.makeSuite(IntroduceParameterTest))
     result.addTests(unittest.makeSuite(ropetest.refactor.
                                        importutilstest.ImportUtilsTest))
-    result.addTests(similarfindertest.suite()))
+    result.addTests(similarfindertest.suite())
     result.addTests(unittest.makeSuite(TaskHandleTest))
     return result
 

ropetest/refactor/similarfindertest.py

         result = list(finder.get_matches('b = ${?x} + ${?x}'))
         self.assertEquals(0, len(result))
 
+    def test_matching_normal_names_and_assname(self):
+        source = 'a = 1\n'
+        finder = similarfinder.SimilarFinder(source)
+        result = list(finder.get_matches('${a} = 1'))
+        self.assertEquals('a', result[0].get_ast('a').name)
+
+    def test_matching_normal_names_and_assname(self):
+        source = 'a = 1\n'
+        finder = similarfinder.SimilarFinder(source)
+        result = list(finder.get_matches('${a}'))
+        self.assertEquals(0, len(result))
+
 
 class TemplateTest(unittest.TestCase):
 
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.