Index: tools/telemetry/third_party/rope/rope/refactor/functionutils.py |
diff --git a/tools/telemetry/third_party/rope/rope/refactor/functionutils.py b/tools/telemetry/third_party/rope/rope/refactor/functionutils.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..58baf9174fd9bec2f18849063f832847103cfdea |
--- /dev/null |
+++ b/tools/telemetry/third_party/rope/rope/refactor/functionutils.py |
@@ -0,0 +1,222 @@ |
+import rope.base.exceptions |
+import rope.base.pyobjects |
+from rope.base.builtins import Lambda |
+from rope.base import worder |
+ |
+ |
+class DefinitionInfo(object): |
+ |
+ def __init__(self, function_name, is_method, args_with_defaults, |
+ args_arg, keywords_arg): |
+ self.function_name = function_name |
+ self.is_method = is_method |
+ self.args_with_defaults = args_with_defaults |
+ self.args_arg = args_arg |
+ self.keywords_arg = keywords_arg |
+ |
+ def to_string(self): |
+ return '%s(%s)' % (self.function_name, self.arguments_to_string()) |
+ |
+ def arguments_to_string(self, from_index=0): |
+ params = [] |
+ for arg, default in self.args_with_defaults: |
+ if default is not None: |
+ params.append('%s=%s' % (arg, default)) |
+ else: |
+ params.append(arg) |
+ if self.args_arg is not None: |
+ params.append('*' + self.args_arg) |
+ if self.keywords_arg: |
+ params.append('**' + self.keywords_arg) |
+ return ', '.join(params[from_index:]) |
+ |
+ @staticmethod |
+ def _read(pyfunction, code): |
+ kind = pyfunction.get_kind() |
+ is_method = kind == 'method' |
+ is_lambda = kind == 'lambda' |
+ info = _FunctionParser(code, is_method, is_lambda) |
+ args, keywords = info.get_parameters() |
+ args_arg = None |
+ keywords_arg = None |
+ if args and args[-1].startswith('**'): |
+ keywords_arg = args[-1][2:] |
+ del args[-1] |
+ if args and args[-1].startswith('*'): |
+ args_arg = args[-1][1:] |
+ del args[-1] |
+ args_with_defaults = [(name, None) for name in args] |
+ args_with_defaults.extend(keywords) |
+ return DefinitionInfo(info.get_function_name(), is_method, |
+ args_with_defaults, args_arg, keywords_arg) |
+ |
+ @staticmethod |
+ def read(pyfunction): |
+ pymodule = pyfunction.get_module() |
+ word_finder = worder.Worder(pymodule.source_code) |
+ lineno = pyfunction.get_ast().lineno |
+ start = pymodule.lines.get_line_start(lineno) |
+ if isinstance(pyfunction, Lambda): |
+ call = word_finder.get_lambda_and_args(start) |
+ else: |
+ call = word_finder.get_function_and_args_in_header(start) |
+ return DefinitionInfo._read(pyfunction, call) |
+ |
+ |
+class CallInfo(object): |
+ |
+ def __init__(self, function_name, args, keywords, args_arg, |
+ keywords_arg, implicit_arg, constructor): |
+ self.function_name = function_name |
+ self.args = args |
+ self.keywords = keywords |
+ self.args_arg = args_arg |
+ self.keywords_arg = keywords_arg |
+ self.implicit_arg = implicit_arg |
+ self.constructor = constructor |
+ |
+ def to_string(self): |
+ function = self.function_name |
+ if self.implicit_arg: |
+ function = self.args[0] + '.' + self.function_name |
+ params = [] |
+ start = 0 |
+ if self.implicit_arg or self.constructor: |
+ start = 1 |
+ if self.args[start:]: |
+ params.extend(self.args[start:]) |
+ if self.keywords: |
+ params.extend(['%s=%s' % (name, value) |
+ for name, value in self.keywords]) |
+ if self.args_arg is not None: |
+ params.append('*' + self.args_arg) |
+ if self.keywords_arg: |
+ params.append('**' + self.keywords_arg) |
+ return '%s(%s)' % (function, ', '.join(params)) |
+ |
+ @staticmethod |
+ def read(primary, pyname, definition_info, code): |
+ is_method_call = CallInfo._is_method_call(primary, pyname) |
+ is_constructor = CallInfo._is_class(pyname) |
+ is_classmethod = CallInfo._is_classmethod(pyname) |
+ info = _FunctionParser(code, is_method_call or is_classmethod) |
+ args, keywords = info.get_parameters() |
+ args_arg = None |
+ keywords_arg = None |
+ if args and args[-1].startswith('**'): |
+ keywords_arg = args[-1][2:] |
+ del args[-1] |
+ if args and args[-1].startswith('*'): |
+ args_arg = args[-1][1:] |
+ del args[-1] |
+ if is_constructor: |
+ args.insert(0, definition_info.args_with_defaults[0][0]) |
+ return CallInfo(info.get_function_name(), args, keywords, args_arg, |
+ keywords_arg, is_method_call or is_classmethod, |
+ is_constructor) |
+ |
+ @staticmethod |
+ def _is_method_call(primary, pyname): |
+ return primary is not None and \ |
+ isinstance(primary.get_object().get_type(), |
+ rope.base.pyobjects.PyClass) and \ |
+ CallInfo._is_method(pyname) |
+ |
+ @staticmethod |
+ def _is_class(pyname): |
+ return pyname is not None and \ |
+ isinstance(pyname.get_object(), |
+ rope.base.pyobjects.PyClass) |
+ |
+ @staticmethod |
+ def _is_method(pyname): |
+ if pyname is not None and \ |
+ isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction): |
+ return pyname.get_object().get_kind() == 'method' |
+ return False |
+ |
+ @staticmethod |
+ def _is_classmethod(pyname): |
+ if pyname is not None and \ |
+ isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction): |
+ return pyname.get_object().get_kind() == 'classmethod' |
+ return False |
+ |
+ |
+class ArgumentMapping(object): |
+ |
+ def __init__(self, definition_info, call_info): |
+ self.call_info = call_info |
+ self.param_dict = {} |
+ self.keyword_args = [] |
+ self.args_arg = [] |
+ for index, value in enumerate(call_info.args): |
+ if index < len(definition_info.args_with_defaults): |
+ name = definition_info.args_with_defaults[index][0] |
+ self.param_dict[name] = value |
+ else: |
+ self.args_arg.append(value) |
+ for name, value in call_info.keywords: |
+ index = -1 |
+ for pair in definition_info.args_with_defaults: |
+ if pair[0] == name: |
+ self.param_dict[name] = value |
+ break |
+ else: |
+ self.keyword_args.append((name, value)) |
+ |
+ def to_call_info(self, definition_info): |
+ args = [] |
+ keywords = [] |
+ for index in range(len(definition_info.args_with_defaults)): |
+ name = definition_info.args_with_defaults[index][0] |
+ if name in self.param_dict: |
+ args.append(self.param_dict[name]) |
+ else: |
+ for i in range(index, len(definition_info.args_with_defaults)): |
+ name = definition_info.args_with_defaults[i][0] |
+ if name in self.param_dict: |
+ keywords.append((name, self.param_dict[name])) |
+ break |
+ args.extend(self.args_arg) |
+ keywords.extend(self.keyword_args) |
+ return CallInfo(self.call_info.function_name, args, keywords, |
+ self.call_info.args_arg, self.call_info.keywords_arg, |
+ self.call_info.implicit_arg, |
+ self.call_info.constructor) |
+ |
+ |
+class _FunctionParser(object): |
+ |
+ def __init__(self, call, implicit_arg, is_lambda=False): |
+ self.call = call |
+ self.implicit_arg = implicit_arg |
+ self.word_finder = worder.Worder(self.call) |
+ if is_lambda: |
+ self.last_parens = self.call.rindex(':') |
+ else: |
+ self.last_parens = self.call.rindex(')') |
+ self.first_parens = self.word_finder._find_parens_start( |
+ self.last_parens) |
+ |
+ def get_parameters(self): |
+ args, keywords = self.word_finder.get_parameters(self.first_parens, |
+ self.last_parens) |
+ if self.is_called_as_a_method(): |
+ instance = self.call[:self.call.rindex('.', 0, self.first_parens)] |
+ args.insert(0, instance.strip()) |
+ return args, keywords |
+ |
+ def get_instance(self): |
+ if self.is_called_as_a_method(): |
+ return self.word_finder.get_primary_at( |
+ self.call.rindex('.', 0, self.first_parens) - 1) |
+ |
+ def get_function_name(self): |
+ if self.is_called_as_a_method(): |
+ return self.word_finder.get_word_at(self.first_parens - 1) |
+ else: |
+ return self.word_finder.get_primary_at(self.first_parens - 1) |
+ |
+ def is_called_as_a_method(self): |
+ return self.implicit_arg and '.' in self.call[:self.first_parens] |