| 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
|
|
|