Index: tools/telemetry/third_party/rope/rope/base/pyscopes.py |
diff --git a/tools/telemetry/third_party/rope/rope/base/pyscopes.py b/tools/telemetry/third_party/rope/rope/base/pyscopes.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0bed19a92912ccda603e3f470ca48154c417bb59 |
--- /dev/null |
+++ b/tools/telemetry/third_party/rope/rope/base/pyscopes.py |
@@ -0,0 +1,314 @@ |
+import rope.base.builtins |
+import rope.base.codeanalyze |
+import rope.base.pynames |
+from rope.base import ast, exceptions, utils |
+ |
+ |
+class Scope(object): |
+ |
+ def __init__(self, pycore, pyobject, parent_scope): |
+ self.pycore = pycore |
+ self.pyobject = pyobject |
+ self.parent = parent_scope |
+ |
+ def get_names(self): |
+ """Return the names defined or imported in this scope""" |
+ return self.pyobject.get_attributes() |
+ |
+ def get_defined_names(self): |
+ """Return the names defined in this scope""" |
+ return self.pyobject._get_structural_attributes() |
+ |
+ def get_name(self, name): |
+ """Return name `PyName` defined in this scope""" |
+ if name not in self.get_names(): |
+ raise exceptions.NameNotFoundError('name %s not found' % name) |
+ return self.get_names()[name] |
+ |
+ def __getitem__(self, key): |
+ """The same as ``get_name(key)``""" |
+ return self.get_name(key) |
+ |
+ def __contains__(self, key): |
+ """The same as ``key in self.get_names()``""" |
+ return key in self.get_names() |
+ |
+ @utils.saveit |
+ def get_scopes(self): |
+ """Return the subscopes of this scope |
+ |
+ The returned scopes should be sorted by the order they appear. |
+ """ |
+ return self._create_scopes() |
+ |
+ def lookup(self, name): |
+ if name in self.get_names(): |
+ return self.get_names()[name] |
+ if self.parent is not None: |
+ return self.parent._propagated_lookup(name) |
+ return None |
+ |
+ def get_propagated_names(self): |
+ """Return the visible names of this scope |
+ |
+ Return the names defined in this scope that are visible from |
+ scopes containing this scope. This method returns the same |
+ dictionary returned by `get_names()` except for `ClassScope` |
+ which returns an empty dict. |
+ """ |
+ return self.get_names() |
+ |
+ def _propagated_lookup(self, name): |
+ if name in self.get_propagated_names(): |
+ return self.get_propagated_names()[name] |
+ if self.parent is not None: |
+ return self.parent._propagated_lookup(name) |
+ return None |
+ |
+ def _create_scopes(self): |
+ return [pydefined.get_scope() |
+ for pydefined in self.pyobject._get_defined_objects()] |
+ |
+ def _get_global_scope(self): |
+ current = self |
+ while current.parent is not None: |
+ current = current.parent |
+ return current |
+ |
+ def get_start(self): |
+ return self.pyobject.get_ast().lineno |
+ |
+ def get_body_start(self): |
+ body = self.pyobject.get_ast().body |
+ if body: |
+ return body[0].lineno |
+ return self.get_start() |
+ |
+ def get_end(self): |
+ pymodule = self._get_global_scope().pyobject |
+ return pymodule.logical_lines.logical_line_in(self.logical_end)[1] |
+ |
+ @utils.saveit |
+ def get_logical_end(self): |
+ global_scope = self._get_global_scope() |
+ return global_scope._scope_finder.find_scope_end(self) |
+ |
+ start = property(get_start) |
+ end = property(get_end) |
+ logical_end = property(get_logical_end) |
+ |
+ def get_kind(self): |
+ pass |
+ |
+ |
+class GlobalScope(Scope): |
+ |
+ def __init__(self, pycore, module): |
+ super(GlobalScope, self).__init__(pycore, module, None) |
+ self.names = module._get_concluded_data() |
+ |
+ def get_start(self): |
+ return 1 |
+ |
+ def get_kind(self): |
+ return 'Module' |
+ |
+ def get_name(self, name): |
+ try: |
+ return self.pyobject[name] |
+ except exceptions.AttributeNotFoundError: |
+ if name in self.builtin_names: |
+ return self.builtin_names[name] |
+ raise exceptions.NameNotFoundError('name %s not found' % name) |
+ |
+ def get_names(self): |
+ if self.names.get() is None: |
+ result = dict(self.builtin_names) |
+ result.update(super(GlobalScope, self).get_names()) |
+ self.names.set(result) |
+ return self.names.get() |
+ |
+ def get_inner_scope_for_line(self, lineno, indents=None): |
+ return self._scope_finder.get_holding_scope(self, lineno, indents) |
+ |
+ def get_inner_scope_for_offset(self, offset): |
+ return self._scope_finder.get_holding_scope_for_offset(self, offset) |
+ |
+ @property |
+ @utils.saveit |
+ def _scope_finder(self): |
+ return _HoldingScopeFinder(self.pyobject) |
+ |
+ @property |
+ def builtin_names(self): |
+ return rope.base.builtins.builtins.get_attributes() |
+ |
+ |
+class FunctionScope(Scope): |
+ |
+ def __init__(self, pycore, pyobject, visitor): |
+ super(FunctionScope, self).__init__(pycore, pyobject, |
+ pyobject.parent.get_scope()) |
+ self.names = None |
+ self.returned_asts = None |
+ self.is_generator = None |
+ self.defineds = None |
+ self.visitor = visitor |
+ |
+ def _get_names(self): |
+ if self.names is None: |
+ self._visit_function() |
+ return self.names |
+ |
+ def _visit_function(self): |
+ if self.names is None: |
+ new_visitor = self.visitor(self.pycore, self.pyobject) |
+ for n in ast.get_child_nodes(self.pyobject.get_ast()): |
+ ast.walk(n, new_visitor) |
+ self.names = new_visitor.names |
+ self.names.update(self.pyobject.get_parameters()) |
+ self.returned_asts = new_visitor.returned_asts |
+ self.is_generator = new_visitor.generator |
+ self.defineds = new_visitor.defineds |
+ |
+ def _get_returned_asts(self): |
+ if self.names is None: |
+ self._visit_function() |
+ return self.returned_asts |
+ |
+ def _is_generator(self): |
+ if self.is_generator is None: |
+ self._get_returned_asts() |
+ return self.is_generator |
+ |
+ def get_names(self): |
+ return self._get_names() |
+ |
+ def _create_scopes(self): |
+ if self.defineds is None: |
+ self._visit_function() |
+ return [pydefined.get_scope() for pydefined in self.defineds] |
+ |
+ def get_kind(self): |
+ return 'Function' |
+ |
+ def invalidate_data(self): |
+ for pyname in self.get_names().values(): |
+ if isinstance(pyname, (rope.base.pynames.AssignedName, |
+ rope.base.pynames.EvaluatedName)): |
+ pyname.invalidate() |
+ |
+ |
+class ClassScope(Scope): |
+ |
+ def __init__(self, pycore, pyobject): |
+ super(ClassScope, self).__init__(pycore, pyobject, |
+ pyobject.parent.get_scope()) |
+ |
+ def get_kind(self): |
+ return 'Class' |
+ |
+ def get_propagated_names(self): |
+ return {} |
+ |
+ |
+class _HoldingScopeFinder(object): |
+ |
+ def __init__(self, pymodule): |
+ self.pymodule = pymodule |
+ |
+ def get_indents(self, lineno): |
+ return rope.base.codeanalyze.count_line_indents( |
+ self.lines.get_line(lineno)) |
+ |
+ def _get_scope_indents(self, scope): |
+ return self.get_indents(scope.get_start()) |
+ |
+ def get_holding_scope(self, module_scope, lineno, line_indents=None): |
+ if line_indents is None: |
+ line_indents = self.get_indents(lineno) |
+ current_scope = module_scope |
+ new_scope = current_scope |
+ while new_scope is not None and \ |
+ (new_scope.get_kind() == 'Module' or |
+ self._get_scope_indents(new_scope) <= line_indents): |
+ current_scope = new_scope |
+ if current_scope.get_start() == lineno and \ |
+ current_scope.get_kind() != 'Module': |
+ return current_scope |
+ new_scope = None |
+ for scope in current_scope.get_scopes(): |
+ if scope.get_start() <= lineno: |
+ if lineno <= scope.get_end(): |
+ new_scope = scope |
+ break |
+ else: |
+ break |
+ return current_scope |
+ |
+ def _is_empty_line(self, lineno): |
+ line = self.lines.get_line(lineno) |
+ return line.strip() == '' or line.lstrip().startswith('#') |
+ |
+ def _get_body_indents(self, scope): |
+ return self.get_indents(scope.get_body_start()) |
+ |
+ def get_holding_scope_for_offset(self, scope, offset): |
+ return self.get_holding_scope( |
+ scope, self.lines.get_line_number(offset)) |
+ |
+ def find_scope_end(self, scope): |
+ if not scope.parent: |
+ return self.lines.length() |
+ end = scope.pyobject.get_ast().body[-1].lineno |
+ scope_start = self.pymodule.logical_lines.logical_line_in(scope.start) |
+ if scope_start[1] >= end: |
+ # handling one-liners |
+ body_indents = self._get_scope_indents(scope) + 4 |
+ else: |
+ body_indents = self._get_body_indents(scope) |
+ for l in self.logical_lines.generate_starts( |
+ min(end + 1, self.lines.length()), self.lines.length() + 1): |
+ if not self._is_empty_line(l): |
+ if self.get_indents(l) < body_indents: |
+ return end |
+ else: |
+ end = l |
+ return end |
+ |
+ @property |
+ def lines(self): |
+ return self.pymodule.lines |
+ |
+ @property |
+ def code(self): |
+ return self.pymodule.source_code |
+ |
+ @property |
+ def logical_lines(self): |
+ return self.pymodule.logical_lines |
+ |
+ |
+class TemporaryScope(Scope): |
+ """Currently used for list comprehensions and generator expressions |
+ |
+ These scopes do not appear in the `get_scopes()` method of their |
+ parent scopes. |
+ """ |
+ |
+ def __init__(self, pycore, parent_scope, names): |
+ super(TemporaryScope, self).__init__( |
+ pycore, parent_scope.pyobject, parent_scope) |
+ self.names = names |
+ |
+ def get_names(self): |
+ return self.names |
+ |
+ def get_defined_names(self): |
+ return self.names |
+ |
+ def _create_scopes(self): |
+ return [] |
+ |
+ def get_kind(self): |
+ return 'Temporary' |