Index: tools/telemetry/third_party/rope/rope/refactor/wildcards.py |
diff --git a/tools/telemetry/third_party/rope/rope/refactor/wildcards.py b/tools/telemetry/third_party/rope/rope/refactor/wildcards.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..90040c794e261cac5e91dd1380f6d465931ba4a0 |
--- /dev/null |
+++ b/tools/telemetry/third_party/rope/rope/refactor/wildcards.py |
@@ -0,0 +1,178 @@ |
+from rope.base import ast, evaluate, builtins, pyobjects |
+from rope.refactor import patchedast, occurrences |
+ |
+ |
+class Wildcard(object): |
+ |
+ def get_name(self): |
+ """Return the name of this wildcard""" |
+ |
+ def matches(self, suspect, arg): |
+ """Return `True` if `suspect` matches this wildcard""" |
+ |
+ |
+class Suspect(object): |
+ |
+ def __init__(self, pymodule, node, name): |
+ self.name = name |
+ self.pymodule = pymodule |
+ self.node = node |
+ |
+ |
+class DefaultWildcard(object): |
+ """The default restructuring wildcard |
+ |
+ The argument passed to this wildcard is in the |
+ ``key1=value1,key2=value2,...`` format. Possible keys are: |
+ |
+ * name - for checking the reference |
+ * type - for checking the type |
+ * object - for checking the object |
+ * instance - for checking types but similar to builtin isinstance |
+ * exact - matching only occurrences with the same name as the wildcard |
+ * unsure - matching unsure occurrences |
+ |
+ """ |
+ |
+ def __init__(self, project): |
+ self.project = project |
+ |
+ def get_name(self): |
+ return 'default' |
+ |
+ def matches(self, suspect, arg=''): |
+ args = parse_arg(arg) |
+ |
+ if not self._check_exact(args, suspect): |
+ return False |
+ if not self._check_object(args, suspect): |
+ return False |
+ return True |
+ |
+ def _check_object(self, args, suspect): |
+ kind = None |
+ expected = None |
+ unsure = args.get('unsure', False) |
+ for check in ['name', 'object', 'type', 'instance']: |
+ if check in args: |
+ kind = check |
+ expected = args[check] |
+ if expected is not None: |
+ checker = _CheckObject(self.project, expected, |
+ kind, unsure=unsure) |
+ return checker(suspect.pymodule, suspect.node) |
+ return True |
+ |
+ def _check_exact(self, args, suspect): |
+ node = suspect.node |
+ if args.get('exact'): |
+ if not isinstance(node, ast.Name) or not node.id == suspect.name: |
+ return False |
+ else: |
+ if not isinstance(node, ast.expr): |
+ return False |
+ return True |
+ |
+ |
+def parse_arg(arg): |
+ if isinstance(arg, dict): |
+ return arg |
+ result = {} |
+ tokens = arg.split(',') |
+ for token in tokens: |
+ if '=' in token: |
+ parts = token.split('=', 1) |
+ result[parts[0].strip()] = parts[1].strip() |
+ else: |
+ result[token.strip()] = True |
+ return result |
+ |
+ |
+class _CheckObject(object): |
+ |
+ def __init__(self, project, expected, kind='object', unsure=False): |
+ self.project = project |
+ self.kind = kind |
+ self.unsure = unsure |
+ self.expected = self._evaluate(expected) |
+ |
+ def __call__(self, pymodule, node): |
+ pyname = self._evaluate_node(pymodule, node) |
+ if pyname is None or self.expected is None: |
+ return self.unsure |
+ if self._unsure_pyname(pyname, unbound=self.kind == 'name'): |
+ return True |
+ if self.kind == 'name': |
+ return self._same_pyname(self.expected, pyname) |
+ else: |
+ pyobject = pyname.get_object() |
+ if self.kind == 'object': |
+ objects = [pyobject] |
+ if self.kind == 'type': |
+ objects = [pyobject.get_type()] |
+ if self.kind == 'instance': |
+ objects = [pyobject] |
+ objects.extend(self._get_super_classes(pyobject)) |
+ objects.extend(self._get_super_classes(pyobject.get_type())) |
+ for pyobject in objects: |
+ if self._same_pyobject(self.expected.get_object(), pyobject): |
+ return True |
+ return False |
+ |
+ def _get_super_classes(self, pyobject): |
+ result = [] |
+ if isinstance(pyobject, pyobjects.AbstractClass): |
+ for superclass in pyobject.get_superclasses(): |
+ result.append(superclass) |
+ result.extend(self._get_super_classes(superclass)) |
+ return result |
+ |
+ def _same_pyobject(self, expected, pyobject): |
+ return expected == pyobject |
+ |
+ def _same_pyname(self, expected, pyname): |
+ return occurrences.same_pyname(expected, pyname) |
+ |
+ def _unsure_pyname(self, pyname, unbound=True): |
+ return self.unsure and occurrences.unsure_pyname(pyname, unbound) |
+ |
+ def _split_name(self, name): |
+ parts = name.split('.') |
+ expression, kind = parts[0], parts[-1] |
+ if len(parts) == 1: |
+ kind = 'name' |
+ return expression, kind |
+ |
+ def _evaluate_node(self, pymodule, node): |
+ scope = pymodule.get_scope().get_inner_scope_for_line(node.lineno) |
+ expression = node |
+ if isinstance(expression, ast.Name) and \ |
+ isinstance(expression.ctx, ast.Store): |
+ start, end = patchedast.node_region(expression) |
+ text = pymodule.source_code[start:end] |
+ return evaluate.eval_str(scope, text) |
+ else: |
+ return evaluate.eval_node(scope, expression) |
+ |
+ def _evaluate(self, code): |
+ attributes = code.split('.') |
+ pyname = None |
+ if attributes[0] in ('__builtin__', '__builtins__'): |
+ class _BuiltinsStub(object): |
+ def get_attribute(self, name): |
+ return builtins.builtins[name] |
+ |
+ def __getitem__(self, name): |
+ return builtins.builtins[name] |
+ |
+ def __contains__(self, name): |
+ return name in builtins.builtins |
+ pyobject = _BuiltinsStub() |
+ else: |
+ pyobject = self.project.get_module(attributes[0]) |
+ for attribute in attributes[1:]: |
+ pyname = pyobject[attribute] |
+ if pyname is None: |
+ return None |
+ pyobject = pyname.get_object() |
+ return pyname |