Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/oi/soa.py
1428 views
1
import rope.base.ast
2
import rope.base.oi.soi
3
import rope.base.pynames
4
from rope.base import pyobjects, evaluate, astutils, arguments
5
6
7
def analyze_module(pycore, pymodule, should_analyze,
8
search_subscopes, followed_calls):
9
"""Analyze `pymodule` for static object inference
10
11
Analyzes scopes for collecting object information. The analysis
12
starts from inner scopes.
13
14
"""
15
_analyze_node(pycore, pymodule, should_analyze,
16
search_subscopes, followed_calls)
17
18
19
def _analyze_node(pycore, pydefined, should_analyze,
20
search_subscopes, followed_calls):
21
if search_subscopes(pydefined):
22
for scope in pydefined.get_scope().get_scopes():
23
_analyze_node(pycore, scope.pyobject, should_analyze,
24
search_subscopes, followed_calls)
25
if should_analyze(pydefined):
26
new_followed_calls = max(0, followed_calls - 1)
27
return_true = lambda pydefined: True
28
return_false = lambda pydefined: False
29
def _follow(pyfunction):
30
_analyze_node(pycore, pyfunction, return_true,
31
return_false, new_followed_calls)
32
if not followed_calls:
33
_follow = None
34
visitor = SOAVisitor(pycore, pydefined, _follow)
35
for child in rope.base.ast.get_child_nodes(pydefined.get_ast()):
36
rope.base.ast.walk(child, visitor)
37
38
39
class SOAVisitor(object):
40
41
def __init__(self, pycore, pydefined, follow_callback=None):
42
self.pycore = pycore
43
self.pymodule = pydefined.get_module()
44
self.scope = pydefined.get_scope()
45
self.follow = follow_callback
46
47
def _FunctionDef(self, node):
48
pass
49
50
def _ClassDef(self, node):
51
pass
52
53
def _Call(self, node):
54
for child in rope.base.ast.get_child_nodes(node):
55
rope.base.ast.walk(child, self)
56
primary, pyname = evaluate.eval_node2(self.scope, node.func)
57
if pyname is None:
58
return
59
pyfunction = pyname.get_object()
60
if isinstance(pyfunction, pyobjects.AbstractFunction):
61
args = arguments.create_arguments(primary, pyfunction,
62
node, self.scope)
63
elif isinstance(pyfunction, pyobjects.PyClass):
64
pyclass = pyfunction
65
if '__init__' in pyfunction:
66
pyfunction = pyfunction['__init__'].get_object()
67
pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass))
68
args = self._args_with_self(primary, pyname, pyfunction, node)
69
elif '__call__' in pyfunction:
70
pyfunction = pyfunction['__call__'].get_object()
71
args = self._args_with_self(primary, pyname, pyfunction, node)
72
else:
73
return
74
self._call(pyfunction, args)
75
76
def _args_with_self(self, primary, self_pyname, pyfunction, node):
77
base_args = arguments.create_arguments(primary, pyfunction,
78
node, self.scope)
79
return arguments.MixedArguments(self_pyname, base_args, self.scope)
80
81
def _call(self, pyfunction, args):
82
if isinstance(pyfunction, pyobjects.PyFunction):
83
if self.follow is not None:
84
before = self._parameter_objects(pyfunction)
85
self.pycore.object_info.function_called(
86
pyfunction, args.get_arguments(pyfunction.get_param_names()))
87
pyfunction._set_parameter_pyobjects(None)
88
if self.follow is not None:
89
after = self._parameter_objects(pyfunction)
90
if after != before:
91
self.follow(pyfunction)
92
# XXX: Maybe we should not call every builtin function
93
if isinstance(pyfunction, rope.base.builtins.BuiltinFunction):
94
pyfunction.get_returned_object(args)
95
96
def _parameter_objects(self, pyfunction):
97
result = []
98
for i in range(len(pyfunction.get_param_names(False))):
99
result.append(pyfunction.get_parameter(i))
100
return result
101
102
def _Assign(self, node):
103
for child in rope.base.ast.get_child_nodes(node):
104
rope.base.ast.walk(child, self)
105
visitor = _SOAAssignVisitor()
106
nodes = []
107
for child in node.targets:
108
rope.base.ast.walk(child, visitor)
109
nodes.extend(visitor.nodes)
110
for subscript, levels in nodes:
111
instance = evaluate.eval_node(self.scope, subscript.value)
112
args_pynames = []
113
args_pynames.append(evaluate.eval_node(self.scope,
114
subscript.slice.value))
115
value = rope.base.oi.soi._infer_assignment(
116
rope.base.pynames.AssignmentValue(node.value, levels), self.pymodule)
117
args_pynames.append(rope.base.pynames.UnboundName(value))
118
if instance is not None and value is not None:
119
pyobject = instance.get_object()
120
if '__setitem__' in pyobject:
121
pyfunction = pyobject['__setitem__'].get_object()
122
args = arguments.ObjectArguments([instance] + args_pynames)
123
self._call(pyfunction, args)
124
# IDEA: handle `__setslice__`, too
125
126
127
class _SOAAssignVisitor(astutils._NodeNameCollector):
128
129
def __init__(self):
130
super(_SOAAssignVisitor, self).__init__()
131
self.nodes = []
132
133
def _added(self, node, levels):
134
if isinstance(node, rope.base.ast.Subscript) and \
135
isinstance(node.slice, rope.base.ast.Index):
136
self.nodes.append((node, levels))
137
138