evaluate.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. import rope.base.builtins
  2. import rope.base.pynames
  3. import rope.base.pyobjects
  4. from rope.base import ast, astutils, exceptions, pyobjects, arguments, worder
  5. BadIdentifierError = exceptions.BadIdentifierError
  6. def eval_location(pymodule, offset):
  7. """Find the pyname at the offset"""
  8. return eval_location2(pymodule, offset)[1]
  9. def eval_location2(pymodule, offset):
  10. """Find the primary and pyname at offset"""
  11. pyname_finder = ScopeNameFinder(pymodule)
  12. return pyname_finder.get_primary_and_pyname_at(offset)
  13. def eval_node(scope, node):
  14. """Evaluate a `ast.AST` node and return a PyName
  15. Return `None` if the expression cannot be evaluated.
  16. """
  17. return eval_node2(scope, node)[1]
  18. def eval_node2(scope, node):
  19. evaluator = StatementEvaluator(scope)
  20. ast.walk(node, evaluator)
  21. return evaluator.old_result, evaluator.result
  22. def eval_str(holding_scope, name):
  23. return eval_str2(holding_scope, name)[1]
  24. def eval_str2(holding_scope, name):
  25. try:
  26. # parenthesizing for handling cases like 'a_var.\nattr'
  27. node = ast.parse('(%s)' % name)
  28. except SyntaxError:
  29. raise BadIdentifierError('Not a resolvable python identifier selected.')
  30. return eval_node2(holding_scope, node)
  31. class ScopeNameFinder(object):
  32. def __init__(self, pymodule):
  33. self.module_scope = pymodule.get_scope()
  34. self.lines = pymodule.lines
  35. self.worder = worder.Worder(pymodule.source_code, True)
  36. def _is_defined_in_class_body(self, holding_scope, offset, lineno):
  37. if lineno == holding_scope.get_start() and \
  38. holding_scope.parent is not None and \
  39. holding_scope.parent.get_kind() == 'Class' and \
  40. self.worder.is_a_class_or_function_name_in_header(offset):
  41. return True
  42. if lineno != holding_scope.get_start() and \
  43. holding_scope.get_kind() == 'Class' and \
  44. self.worder.is_name_assigned_in_class_body(offset):
  45. return True
  46. return False
  47. def _is_function_name_in_function_header(self, scope, offset, lineno):
  48. if scope.get_start() <= lineno <= scope.get_body_start() and \
  49. scope.get_kind() == 'Function' and \
  50. self.worder.is_a_class_or_function_name_in_header(offset):
  51. return True
  52. return False
  53. def get_pyname_at(self, offset):
  54. return self.get_primary_and_pyname_at(offset)[1]
  55. def get_primary_and_pyname_at(self, offset):
  56. lineno = self.lines.get_line_number(offset)
  57. holding_scope = self.module_scope.get_inner_scope_for_line(lineno)
  58. # function keyword parameter
  59. if self.worder.is_function_keyword_parameter(offset):
  60. keyword_name = self.worder.get_word_at(offset)
  61. pyobject = self.get_enclosing_function(offset)
  62. if isinstance(pyobject, pyobjects.PyFunction):
  63. return (None, pyobject.get_parameters().get(keyword_name, None))
  64. # class body
  65. if self._is_defined_in_class_body(holding_scope, offset, lineno):
  66. class_scope = holding_scope
  67. if lineno == holding_scope.get_start():
  68. class_scope = holding_scope.parent
  69. name = self.worder.get_primary_at(offset).strip()
  70. try:
  71. return (None, class_scope.pyobject[name])
  72. except rope.base.exceptions.AttributeNotFoundError:
  73. return (None, None)
  74. # function header
  75. if self._is_function_name_in_function_header(holding_scope, offset, lineno):
  76. name = self.worder.get_primary_at(offset).strip()
  77. return (None, holding_scope.parent[name])
  78. # from statement module
  79. if self.worder.is_from_statement_module(offset):
  80. module = self.worder.get_primary_at(offset)
  81. module_pyname = self._find_module(module)
  82. return (None, module_pyname)
  83. if self.worder.is_from_aliased(offset):
  84. name = self.worder.get_from_aliased(offset)
  85. else:
  86. name = self.worder.get_primary_at(offset)
  87. return eval_str2(holding_scope, name)
  88. def get_enclosing_function(self, offset):
  89. function_parens = self.worder.find_parens_start_from_inside(offset)
  90. try:
  91. function_pyname = self.get_pyname_at(function_parens - 1)
  92. except BadIdentifierError:
  93. function_pyname = None
  94. if function_pyname is not None:
  95. pyobject = function_pyname.get_object()
  96. if isinstance(pyobject, pyobjects.AbstractFunction):
  97. return pyobject
  98. elif isinstance(pyobject, pyobjects.AbstractClass) and \
  99. '__init__' in pyobject:
  100. return pyobject['__init__'].get_object()
  101. elif '__call__' in pyobject:
  102. return pyobject['__call__'].get_object()
  103. return None
  104. def _find_module(self, module_name):
  105. dots = 0
  106. while module_name[dots] == '.':
  107. dots += 1
  108. return rope.base.pynames.ImportedModule(
  109. self.module_scope.pyobject, module_name[dots:], dots)
  110. class StatementEvaluator(object):
  111. def __init__(self, scope):
  112. self.scope = scope
  113. self.result = None
  114. self.old_result = None
  115. def _Name(self, node):
  116. self.result = self.scope.lookup(node.id)
  117. def _Attribute(self, node):
  118. pyname = eval_node(self.scope, node.value)
  119. if pyname is None:
  120. pyname = rope.base.pynames.UnboundName()
  121. self.old_result = pyname
  122. if pyname.get_object() != rope.base.pyobjects.get_unknown():
  123. try:
  124. self.result = pyname.get_object()[node.attr]
  125. except exceptions.AttributeNotFoundError:
  126. self.result = None
  127. def _Call(self, node):
  128. primary, pyobject = self._get_primary_and_object_for_node(node.func)
  129. if pyobject is None:
  130. return
  131. def _get_returned(pyobject):
  132. args = arguments.create_arguments(primary, pyobject,
  133. node, self.scope)
  134. return pyobject.get_returned_object(args)
  135. if isinstance(pyobject, rope.base.pyobjects.AbstractClass):
  136. result = None
  137. if '__new__' in pyobject:
  138. new_function = pyobject['__new__'].get_object()
  139. result = _get_returned(new_function)
  140. if result is None or \
  141. result == rope.base.pyobjects.get_unknown():
  142. result = rope.base.pyobjects.PyObject(pyobject)
  143. self.result = rope.base.pynames.UnboundName(pyobject=result)
  144. return
  145. pyfunction = None
  146. if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):
  147. pyfunction = pyobject
  148. elif '__call__' in pyobject:
  149. pyfunction = pyobject['__call__'].get_object()
  150. if pyfunction is not None:
  151. self.result = rope.base.pynames.UnboundName(
  152. pyobject=_get_returned(pyfunction))
  153. def _Str(self, node):
  154. self.result = rope.base.pynames.UnboundName(
  155. pyobject=rope.base.builtins.get_str())
  156. def _Num(self, node):
  157. type_name = type(node.n).__name__
  158. self.result = self._get_builtin_name(type_name)
  159. def _get_builtin_name(self, type_name):
  160. pytype = rope.base.builtins.builtins[type_name].get_object()
  161. return rope.base.pynames.UnboundName(
  162. rope.base.pyobjects.PyObject(pytype))
  163. def _BinOp(self, node):
  164. self.result = rope.base.pynames.UnboundName(
  165. self._get_object_for_node(node.left))
  166. def _BoolOp(self, node):
  167. pyobject = self._get_object_for_node(node.values[0])
  168. if pyobject is None:
  169. pyobject = self._get_object_for_node(node.values[1])
  170. self.result = rope.base.pynames.UnboundName(pyobject)
  171. def _Repr(self, node):
  172. self.result = self._get_builtin_name('str')
  173. def _UnaryOp(self, node):
  174. self.result = rope.base.pynames.UnboundName(
  175. self._get_object_for_node(node.operand))
  176. def _Compare(self, node):
  177. self.result = self._get_builtin_name('bool')
  178. def _Dict(self, node):
  179. keys = None
  180. values = None
  181. if node.keys:
  182. keys = self._get_object_for_node(node.keys[0])
  183. values = self._get_object_for_node(node.values[0])
  184. self.result = rope.base.pynames.UnboundName(
  185. pyobject=rope.base.builtins.get_dict(keys, values))
  186. def _List(self, node):
  187. holding = None
  188. if node.elts:
  189. holding = self._get_object_for_node(node.elts[0])
  190. self.result = rope.base.pynames.UnboundName(
  191. pyobject=rope.base.builtins.get_list(holding))
  192. def _ListComp(self, node):
  193. pyobject = self._what_does_comprehension_hold(node)
  194. self.result = rope.base.pynames.UnboundName(
  195. pyobject=rope.base.builtins.get_list(pyobject))
  196. def _GeneratorExp(self, node):
  197. pyobject = self._what_does_comprehension_hold(node)
  198. self.result = rope.base.pynames.UnboundName(
  199. pyobject=rope.base.builtins.get_iterator(pyobject))
  200. def _what_does_comprehension_hold(self, node):
  201. scope = self._make_comprehension_scope(node)
  202. pyname = eval_node(scope, node.elt)
  203. return pyname.get_object() if pyname is not None else None
  204. def _make_comprehension_scope(self, node):
  205. scope = self.scope
  206. module = scope.pyobject.get_module()
  207. names = {}
  208. for comp in node.generators:
  209. new_names = _get_evaluated_names(comp.target, comp.iter, module,
  210. '.__iter__().next()', node.lineno)
  211. names.update(new_names)
  212. return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names)
  213. def _Tuple(self, node):
  214. objects = []
  215. if len(node.elts) < 4:
  216. for stmt in node.elts:
  217. pyobject = self._get_object_for_node(stmt)
  218. objects.append(pyobject)
  219. else:
  220. objects.append(self._get_object_for_node(node.elts[0]))
  221. self.result = rope.base.pynames.UnboundName(
  222. pyobject=rope.base.builtins.get_tuple(*objects))
  223. def _get_object_for_node(self, stmt):
  224. pyname = eval_node(self.scope, stmt)
  225. pyobject = None
  226. if pyname is not None:
  227. pyobject = pyname.get_object()
  228. return pyobject
  229. def _get_primary_and_object_for_node(self, stmt):
  230. primary, pyname = eval_node2(self.scope, stmt)
  231. pyobject = None
  232. if pyname is not None:
  233. pyobject = pyname.get_object()
  234. return primary, pyobject
  235. def _Subscript(self, node):
  236. if isinstance(node.slice, ast.Index):
  237. self._call_function(node.value, '__getitem__',
  238. [node.slice.value])
  239. elif isinstance(node.slice, ast.Slice):
  240. self._call_function(node.value, '__getslice__')
  241. def _call_function(self, node, function_name, other_args=None):
  242. pyname = eval_node(self.scope, node)
  243. if pyname is not None:
  244. pyobject = pyname.get_object()
  245. else:
  246. return
  247. if function_name in pyobject:
  248. called = pyobject[function_name].get_object()
  249. if not called or not isinstance(called, pyobjects.AbstractFunction):
  250. return
  251. args = [node]
  252. if other_args:
  253. args += other_args
  254. arguments_ = arguments.Arguments(args, self.scope)
  255. self.result = rope.base.pynames.UnboundName(
  256. pyobject=called.get_returned_object(arguments_))
  257. def _Lambda(self, node):
  258. self.result = rope.base.pynames.UnboundName(
  259. pyobject=rope.base.builtins.Lambda(node, self.scope))
  260. def _get_evaluated_names(targets, assigned, module, evaluation, lineno):
  261. result = {}
  262. for name, levels in astutils.get_name_levels(targets):
  263. assignment = rope.base.pynames.AssignmentValue(assigned, levels,
  264. evaluation)
  265. # XXX: this module should not access `rope.base.pynamesdef`!
  266. pyname = rope.base.pynamesdef.AssignedName(lineno, module)
  267. pyname.assignments.append(assignment)
  268. result[name] = pyname
  269. return result