| Index: tools/telemetry/third_party/rope/rope/base/oi/soi.py
|
| diff --git a/tools/telemetry/third_party/rope/rope/base/oi/soi.py b/tools/telemetry/third_party/rope/rope/base/oi/soi.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5a11b5efdf30b218a926e54e4051151a4025f91a
|
| --- /dev/null
|
| +++ b/tools/telemetry/third_party/rope/rope/base/oi/soi.py
|
| @@ -0,0 +1,197 @@
|
| +"""A module for inferring objects
|
| +
|
| +For more information see the documentation in `rope.base.oi`
|
| +package.
|
| +
|
| +"""
|
| +import rope.base.builtins
|
| +import rope.base.pynames
|
| +import rope.base.pyobjects
|
| +from rope.base import evaluate, utils, arguments
|
| +
|
| +
|
| +_ignore_inferred = utils.ignore_exception(
|
| + rope.base.pyobjects.IsBeingInferredError)
|
| +
|
| +
|
| +@_ignore_inferred
|
| +def infer_returned_object(pyfunction, args):
|
| + """Infer the `PyObject` this `PyFunction` returns after calling"""
|
| + object_info = pyfunction.pycore.object_info
|
| + result = object_info.get_exact_returned(pyfunction, args)
|
| + if result is not None:
|
| + return result
|
| + result = _infer_returned(pyfunction, args)
|
| + if result is not None:
|
| + if args and pyfunction.get_module().get_resource() is not None:
|
| + params = args.get_arguments(
|
| + pyfunction.get_param_names(special_args=False))
|
| + object_info.function_called(pyfunction, params, result)
|
| + return result
|
| + return object_info.get_returned(pyfunction, args)
|
| +
|
| +
|
| +@_ignore_inferred
|
| +def infer_parameter_objects(pyfunction):
|
| + """Infer the `PyObject`\s of parameters of this `PyFunction`"""
|
| + object_info = pyfunction.pycore.object_info
|
| + result = object_info.get_parameter_objects(pyfunction)
|
| + if result is None:
|
| + result = _parameter_objects(pyfunction)
|
| + _handle_first_parameter(pyfunction, result)
|
| + return result
|
| +
|
| +
|
| +def _handle_first_parameter(pyobject, parameters):
|
| + kind = pyobject.get_kind()
|
| + if parameters is None or kind not in ['method', 'classmethod']:
|
| + pass
|
| + if not parameters:
|
| + if not pyobject.get_param_names(special_args=False):
|
| + return
|
| + parameters.append(rope.base.pyobjects.get_unknown())
|
| + if kind == 'method':
|
| + parameters[0] = rope.base.pyobjects.PyObject(pyobject.parent)
|
| + if kind == 'classmethod':
|
| + parameters[0] = pyobject.parent
|
| +
|
| +
|
| +@_ignore_inferred
|
| +def infer_assigned_object(pyname):
|
| + if not pyname.assignments:
|
| + return
|
| + for assignment in reversed(pyname.assignments):
|
| + result = _infer_assignment(assignment, pyname.module)
|
| + if result is not None:
|
| + return result
|
| +
|
| +
|
| +def get_passed_objects(pyfunction, parameter_index):
|
| + object_info = pyfunction.pycore.object_info
|
| + result = object_info.get_passed_objects(pyfunction,
|
| + parameter_index)
|
| + if not result:
|
| + statically_inferred = _parameter_objects(pyfunction)
|
| + if len(statically_inferred) > parameter_index:
|
| + result.append(statically_inferred[parameter_index])
|
| + return result
|
| +
|
| +
|
| +def _infer_returned(pyobject, args):
|
| + if args:
|
| + # HACK: Setting parameter objects manually
|
| + # This is not thread safe and might cause problems if `args`
|
| + # does not come from a good call site
|
| + pyobject.get_scope().invalidate_data()
|
| + pyobject._set_parameter_pyobjects(
|
| + args.get_arguments(pyobject.get_param_names(special_args=False)))
|
| + scope = pyobject.get_scope()
|
| + if not scope._get_returned_asts():
|
| + return
|
| + maxtries = 3
|
| + for returned_node in reversed(scope._get_returned_asts()[-maxtries:]):
|
| + try:
|
| + resulting_pyname = evaluate.eval_node(scope, returned_node)
|
| + if resulting_pyname is None:
|
| + continue
|
| + pyobject = resulting_pyname.get_object()
|
| + if pyobject == rope.base.pyobjects.get_unknown():
|
| + continue
|
| + if not scope._is_generator():
|
| + return pyobject
|
| + else:
|
| + return rope.base.builtins.get_generator(pyobject)
|
| + except rope.base.pyobjects.IsBeingInferredError:
|
| + pass
|
| +
|
| +
|
| +def _parameter_objects(pyobject):
|
| + params = pyobject.get_param_names(special_args=False)
|
| + return [rope.base.pyobjects.get_unknown()] * len(params)
|
| +
|
| +# handling `rope.base.pynames.AssignmentValue`
|
| +
|
| +
|
| +@_ignore_inferred
|
| +def _infer_assignment(assignment, pymodule):
|
| + result = _follow_pyname(assignment, pymodule)
|
| + if result is None:
|
| + return None
|
| + pyname, pyobject = result
|
| + pyobject = _follow_evaluations(assignment, pyname, pyobject)
|
| + if pyobject is None:
|
| + return None
|
| + return _follow_levels(assignment, pyobject)
|
| +
|
| +
|
| +def _follow_levels(assignment, pyobject):
|
| + for index in assignment.levels:
|
| + if isinstance(pyobject.get_type(), rope.base.builtins.Tuple):
|
| + holdings = pyobject.get_type().get_holding_objects()
|
| + if holdings:
|
| + pyobject = holdings[min(len(holdings) - 1, index)]
|
| + else:
|
| + pyobject = None
|
| + elif isinstance(pyobject.get_type(), rope.base.builtins.List):
|
| + pyobject = pyobject.get_type().holding
|
| + else:
|
| + pyobject = None
|
| + if pyobject is None:
|
| + break
|
| + return pyobject
|
| +
|
| +
|
| +@_ignore_inferred
|
| +def _follow_pyname(assignment, pymodule, lineno=None):
|
| + assign_node = assignment.ast_node
|
| + if lineno is None:
|
| + lineno = _get_lineno_for_node(assign_node)
|
| + holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
|
| + pyname = evaluate.eval_node(holding_scope, assign_node)
|
| + if pyname is not None:
|
| + result = pyname.get_object()
|
| + if isinstance(result.get_type(), rope.base.builtins.Property) and \
|
| + holding_scope.get_kind() == 'Class':
|
| + arg = rope.base.pynames.UnboundName(
|
| + rope.base.pyobjects.PyObject(holding_scope.pyobject))
|
| + return pyname, result.get_type().get_property_object(
|
| + arguments.ObjectArguments([arg]))
|
| + return pyname, result
|
| +
|
| +
|
| +@_ignore_inferred
|
| +def _follow_evaluations(assignment, pyname, pyobject):
|
| + new_pyname = pyname
|
| + tokens = assignment.evaluation.split('.')
|
| + for token in tokens:
|
| + call = token.endswith('()')
|
| + if call:
|
| + token = token[:-2]
|
| + if token:
|
| + pyname = new_pyname
|
| + new_pyname = _get_attribute(pyobject, token)
|
| + if new_pyname is not None:
|
| + pyobject = new_pyname.get_object()
|
| + if pyobject is not None and call:
|
| + if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):
|
| + args = arguments.ObjectArguments([pyname])
|
| + pyobject = pyobject.get_returned_object(args)
|
| + else:
|
| + pyobject = None
|
| + if pyobject is None:
|
| + break
|
| + if pyobject is not None and assignment.assign_type:
|
| + return rope.base.pyobjects.PyObject(pyobject)
|
| + return pyobject
|
| +
|
| +
|
| +def _get_lineno_for_node(assign_node):
|
| + if hasattr(assign_node, 'lineno') and \
|
| + assign_node.lineno is not None:
|
| + return assign_node.lineno
|
| + return 1
|
| +
|
| +
|
| +def _get_attribute(pyobject, name):
|
| + if pyobject is not None and name in pyobject:
|
| + return pyobject[name]
|
|
|