finder.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. """
  2. Searching for names with given scope and name. This is very central in Jedi and
  3. Python. The name resolution is quite complicated with descripter,
  4. ``__getattribute__``, ``__getattr__``, ``global``, etc.
  5. If you want to understand name resolution, please read the first few chapters
  6. in http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/.
  7. Flow checks
  8. +++++++++++
  9. Flow checks are not really mature. There's only a check for ``isinstance``. It
  10. would check whether a flow has the form of ``if isinstance(a, type_or_tuple)``.
  11. Unfortunately every other thing is being ignored (e.g. a == '' would be easy to
  12. check for -> a is a string). There's big potential in these checks.
  13. """
  14. from parso.tree import search_ancestor
  15. from parso.python.tree import Name
  16. from jedi import settings
  17. from jedi.inference.arguments import TreeArguments
  18. from jedi.inference.value import iterable
  19. from jedi.inference.base_value import NO_VALUES
  20. from jedi.parser_utils import is_scope
  21. def filter_name(filters, name_or_str):
  22. """
  23. Searches names that are defined in a scope (the different
  24. ``filters``), until a name fits.
  25. """
  26. string_name = name_or_str.value if isinstance(name_or_str, Name) else name_or_str
  27. names = []
  28. for filter in filters:
  29. names = filter.get(string_name)
  30. if names:
  31. break
  32. return list(_remove_del_stmt(names))
  33. def _remove_del_stmt(names):
  34. # Catch del statements and remove them from results.
  35. for name in names:
  36. if name.tree_name is not None:
  37. definition = name.tree_name.get_definition()
  38. if definition is not None and definition.type == 'del_stmt':
  39. continue
  40. yield name
  41. def check_flow_information(value, flow, search_name, pos):
  42. """ Try to find out the type of a variable just with the information that
  43. is given by the flows: e.g. It is also responsible for assert checks.::
  44. if isinstance(k, str):
  45. k. # <- completion here
  46. ensures that `k` is a string.
  47. """
  48. if not settings.dynamic_flow_information:
  49. return None
  50. result = None
  51. if is_scope(flow):
  52. # Check for asserts.
  53. module_node = flow.get_root_node()
  54. try:
  55. names = module_node.get_used_names()[search_name.value]
  56. except KeyError:
  57. return None
  58. names = reversed([
  59. n for n in names
  60. if flow.start_pos <= n.start_pos < (pos or flow.end_pos)
  61. ])
  62. for name in names:
  63. ass = search_ancestor(name, 'assert_stmt')
  64. if ass is not None:
  65. result = _check_isinstance_type(value, ass.assertion, search_name)
  66. if result is not None:
  67. return result
  68. if flow.type in ('if_stmt', 'while_stmt'):
  69. potential_ifs = [c for c in flow.children[1::4] if c != ':']
  70. for if_test in reversed(potential_ifs):
  71. if search_name.start_pos > if_test.end_pos:
  72. return _check_isinstance_type(value, if_test, search_name)
  73. return result
  74. def _get_isinstance_trailer_arglist(node):
  75. if node.type in ('power', 'atom_expr') and len(node.children) == 2:
  76. # This might be removed if we analyze and, etc
  77. first, trailer = node.children
  78. if first.type == 'name' and first.value == 'isinstance' \
  79. and trailer.type == 'trailer' and trailer.children[0] == '(':
  80. return trailer
  81. return None
  82. def _check_isinstance_type(value, node, search_name):
  83. lazy_cls = None
  84. trailer = _get_isinstance_trailer_arglist(node)
  85. if trailer is not None and len(trailer.children) == 3:
  86. arglist = trailer.children[1]
  87. args = TreeArguments(value.inference_state, value, arglist, trailer)
  88. param_list = list(args.unpack())
  89. # Disallow keyword arguments
  90. if len(param_list) == 2 and len(arglist.children) == 3:
  91. (key1, _), (key2, lazy_value_cls) = param_list
  92. if key1 is None and key2 is None:
  93. call = _get_call_string(search_name)
  94. is_instance_call = _get_call_string(arglist.children[0])
  95. # Do a simple get_code comparison of the strings . They should
  96. # just have the same code, and everything will be all right.
  97. # There are ways that this is not correct, if some stuff is
  98. # redefined in between. However here we don't care, because
  99. # it's a heuristic that works pretty well.
  100. if call == is_instance_call:
  101. lazy_cls = lazy_value_cls
  102. if lazy_cls is None:
  103. return None
  104. value_set = NO_VALUES
  105. for cls_or_tup in lazy_cls.infer():
  106. if isinstance(cls_or_tup, iterable.Sequence) and cls_or_tup.array_type == 'tuple':
  107. for lazy_value in cls_or_tup.py__iter__():
  108. value_set |= lazy_value.infer().execute_with_values()
  109. else:
  110. value_set |= cls_or_tup.execute_with_values()
  111. return value_set
  112. def _get_call_string(node):
  113. if node.parent.type == 'atom_expr':
  114. return _get_call_string(node.parent)
  115. code = ''
  116. leaf = node.get_first_leaf()
  117. end = node.get_last_leaf().end_pos
  118. while leaf.start_pos < end:
  119. code += leaf.value
  120. leaf = leaf.get_next_leaf()
  121. return code