Anonymous avatar Anonymous committed 181bb62

occurrences: added Finder class

Comments (0)

Files changed (1)

rope/refactor/occurrences.py

 from rope.base import pynames, pyobjects, codeanalyze, evaluate
 
 
-class FilteredFinder(object):
-    """For finding occurrences of a name"""
+class Finder(object):
+    """For finding occurrences of a name
 
-    def __init__(self, pycore, name, pynames, only_calls=False,
-                 imports=True, unsure=None, docs=False):
+    The constructor takes a `filters` argument.  It should be a list
+    of functions that take a single argument.  For each possible
+    occurrence, these functions are called in order with the an
+    instance of `Occurrence`:
+
+      * If it returns `None` other filters are tried.
+      * If it returns `True`, the occurrence will be a match.
+      * If it returns `False`, the occurrence will be skipped.
+      * If all of the filters return `None`, it is skipped also.
+
+    """
+
+    def __init__(self, pycore, name, filters=[lambda o: True], docs=False):
         self.pycore = pycore
-        self.pynames = pynames
         self.name = name
-        self.only_calls = only_calls
-        self.imports = imports
-        self.unsure = unsure
-        self.occurrence_finder = _TextualFinder(name, docs=docs)
+        self.filters = filters
+        self._textual_finder = _TextualFinder(name, docs=docs)
 
     def find_occurrences(self, resource=None, pymodule=None):
         """Generate `Occurrence` instances"""
         tools = _OccurrenceToolsCreator(self.pycore, resource=resource,
                                         pymodule=pymodule)
-        for offset in self.occurrence_finder.find_offsets(tools.source_code):
+        for offset in self._textual_finder.find_offsets(tools.source_code):
             occurrence = Occurrence(tools, offset)
-            if self._is_a_match(occurrence):
-                yield occurrence
+            for filter in self.filters:
+                result = filter(occurrence)
+                if result is None:
+                    continue
+                if result:
+                    yield occurrence
+                else:
+                    break
 
-    def _is_a_match(self, occurrence):
+
+class PyNameFilter(object):
+    """For finding occurrences of a name"""
+
+    def __init__(self, pynames, only_calls=False, imports=True, unsure=None):
+        self.pynames = pynames
+        self.only_calls = only_calls
+        self.imports = imports
+        self.unsure = unsure
+
+    def __call__(self, occurrence):
         if self.only_calls and not occurrence.is_called():
             return False
         if not self.imports and occurrence.is_in_import_statement():
         return False
 
 
+class FilteredFinder(object):
+    """For finding occurrences of a name"""
+
+    def __init__(self, pycore, name, pynames, only_calls=False,
+                 imports=True, unsure=None, docs=False):
+        filters = [PyNameFilter(pynames, only_calls, imports, unsure)]
+        self.finder = Finder(pycore, name, filters=filters, docs=docs)
+
+    def find_occurrences(self, resource=None, pymodule=None):
+        """Generate `Occurrence` instances"""
+        return self.finder.find_occurrences(resource, pymodule)
+
+
 class Occurrence(object):
 
     def __init__(self, tools, offset):
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.