Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/oi/soa.py
1428 views
import rope.base.ast1import rope.base.oi.soi2import rope.base.pynames3from rope.base import pyobjects, evaluate, astutils, arguments456def analyze_module(pycore, pymodule, should_analyze,7search_subscopes, followed_calls):8"""Analyze `pymodule` for static object inference910Analyzes scopes for collecting object information. The analysis11starts from inner scopes.1213"""14_analyze_node(pycore, pymodule, should_analyze,15search_subscopes, followed_calls)161718def _analyze_node(pycore, pydefined, should_analyze,19search_subscopes, followed_calls):20if search_subscopes(pydefined):21for scope in pydefined.get_scope().get_scopes():22_analyze_node(pycore, scope.pyobject, should_analyze,23search_subscopes, followed_calls)24if should_analyze(pydefined):25new_followed_calls = max(0, followed_calls - 1)26return_true = lambda pydefined: True27return_false = lambda pydefined: False28def _follow(pyfunction):29_analyze_node(pycore, pyfunction, return_true,30return_false, new_followed_calls)31if not followed_calls:32_follow = None33visitor = SOAVisitor(pycore, pydefined, _follow)34for child in rope.base.ast.get_child_nodes(pydefined.get_ast()):35rope.base.ast.walk(child, visitor)363738class SOAVisitor(object):3940def __init__(self, pycore, pydefined, follow_callback=None):41self.pycore = pycore42self.pymodule = pydefined.get_module()43self.scope = pydefined.get_scope()44self.follow = follow_callback4546def _FunctionDef(self, node):47pass4849def _ClassDef(self, node):50pass5152def _Call(self, node):53for child in rope.base.ast.get_child_nodes(node):54rope.base.ast.walk(child, self)55primary, pyname = evaluate.eval_node2(self.scope, node.func)56if pyname is None:57return58pyfunction = pyname.get_object()59if isinstance(pyfunction, pyobjects.AbstractFunction):60args = arguments.create_arguments(primary, pyfunction,61node, self.scope)62elif isinstance(pyfunction, pyobjects.PyClass):63pyclass = pyfunction64if '__init__' in pyfunction:65pyfunction = pyfunction['__init__'].get_object()66pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass))67args = self._args_with_self(primary, pyname, pyfunction, node)68elif '__call__' in pyfunction:69pyfunction = pyfunction['__call__'].get_object()70args = self._args_with_self(primary, pyname, pyfunction, node)71else:72return73self._call(pyfunction, args)7475def _args_with_self(self, primary, self_pyname, pyfunction, node):76base_args = arguments.create_arguments(primary, pyfunction,77node, self.scope)78return arguments.MixedArguments(self_pyname, base_args, self.scope)7980def _call(self, pyfunction, args):81if isinstance(pyfunction, pyobjects.PyFunction):82if self.follow is not None:83before = self._parameter_objects(pyfunction)84self.pycore.object_info.function_called(85pyfunction, args.get_arguments(pyfunction.get_param_names()))86pyfunction._set_parameter_pyobjects(None)87if self.follow is not None:88after = self._parameter_objects(pyfunction)89if after != before:90self.follow(pyfunction)91# XXX: Maybe we should not call every builtin function92if isinstance(pyfunction, rope.base.builtins.BuiltinFunction):93pyfunction.get_returned_object(args)9495def _parameter_objects(self, pyfunction):96result = []97for i in range(len(pyfunction.get_param_names(False))):98result.append(pyfunction.get_parameter(i))99return result100101def _Assign(self, node):102for child in rope.base.ast.get_child_nodes(node):103rope.base.ast.walk(child, self)104visitor = _SOAAssignVisitor()105nodes = []106for child in node.targets:107rope.base.ast.walk(child, visitor)108nodes.extend(visitor.nodes)109for subscript, levels in nodes:110instance = evaluate.eval_node(self.scope, subscript.value)111args_pynames = []112args_pynames.append(evaluate.eval_node(self.scope,113subscript.slice.value))114value = rope.base.oi.soi._infer_assignment(115rope.base.pynames.AssignmentValue(node.value, levels), self.pymodule)116args_pynames.append(rope.base.pynames.UnboundName(value))117if instance is not None and value is not None:118pyobject = instance.get_object()119if '__setitem__' in pyobject:120pyfunction = pyobject['__setitem__'].get_object()121args = arguments.ObjectArguments([instance] + args_pynames)122self._call(pyfunction, args)123# IDEA: handle `__setslice__`, too124125126class _SOAAssignVisitor(astutils._NodeNameCollector):127128def __init__(self):129super(_SOAAssignVisitor, self).__init__()130self.nodes = []131132def _added(self, node, levels):133if isinstance(node, rope.base.ast.Subscript) and \134isinstance(node.slice, rope.base.ast.Index):135self.nodes.append((node, levels))136137138