1 from parso.python import tree 2 3 from jedi import debug 4 from jedi.inference.cache import inference_state_method_cache, CachedMetaClass 5 from jedi.inference import compiled 6 from jedi.inference import recursion 7 from jedi.inference import docstrings 8 from jedi.inference import flow_analysis 9 from jedi.inference.signature import TreeSignature 10 from jedi.inference.filters import ParserTreeFilter, FunctionExecutionFilter, \ 11 AnonymousFunctionExecutionFilter 12 from jedi.inference.names import ValueName, AbstractNameDefinition, \ 13 AnonymousParamName, ParamName, NameWrapper 14 from jedi.inference.base_value import ContextualizedNode, NO_VALUES, \ 15 ValueSet, TreeValue, ValueWrapper 16 from jedi.inference.lazy_value import LazyKnownValues, LazyKnownValue, \ 17 LazyTreeValue 18 from jedi.inference.context import ValueContext, TreeContextMixin 19 from jedi.inference.value import iterable 20 from jedi import parser_utils 21 from jedi.inference.parser_cache import get_yield_exprs 22 from jedi.inference.helpers import values_from_qualified_names 23 from jedi.inference.gradual.generics import TupleGenericManager 24 25 26 class LambdaName(AbstractNameDefinition): 27 string_name = '<lambda>' 28 api_type = 'function' 29 30 def __init__(self, lambda_value): 31 self._lambda_value = lambda_value 32 self.parent_context = lambda_value.parent_context 33 34 @property 35 def start_pos(self): 36 return self._lambda_value.tree_node.start_pos 37 38 def infer(self): 39 return ValueSet([self._lambda_value]) 40 41 42 class FunctionAndClassBase(TreeValue): 43 def get_qualified_names(self): 44 if self.parent_context.is_class(): 45 n = self.parent_context.get_qualified_names() 46 if n is None: 47 # This means that the parent class lives within a function. 48 return None 49 return n + (self.py__name__(),) 50 elif self.parent_context.is_module(): 51 return (self.py__name__(),) 52 else: 53 return None 54 55 56 class FunctionMixin: 57 api_type = 'function' 58 59 def get_filters(self, origin_scope=None): 60 cls = self.py__class__() 61 for instance in cls.execute_with_values(): 62 yield from instance.get_filters(origin_scope=origin_scope) 63 64 def py__get__(self, instance, class_value): 65 from jedi.inference.value.instance import BoundMethod 66 if instance is None: 67 # Calling the Foo.bar results in the original bar function. 68 return ValueSet([self]) 69 return ValueSet([BoundMethod(instance, class_value.as_context(), self)]) 70 71 def get_param_names(self): 72 return [AnonymousParamName(self, param.name) 73 for param in self.tree_node.get_params()] 74 75 @property 76 def name(self): 77 if self.tree_node.type == 'lambdef': 78 return LambdaName(self) 79 return ValueName(self, self.tree_node.name) 80 81 def is_function(self): 82 return True 83 84 def py__name__(self): 85 return self.name.string_name 86 87 def get_type_hint(self, add_class_info=True): 88 return_annotation = self.tree_node.annotation 89 if return_annotation is None: 90 def param_name_to_str(n): 91 s = n.string_name 92 annotation = n.infer().get_type_hint() 93 if annotation is not None: 94 s += ': ' + annotation 95 if n.default_node is not None: 96 s += '=' + n.default_node.get_code(include_prefix=False) 97 return s 98 99 function_execution = self.as_context() 100 result = function_execution.infer() 101 return_hint = result.get_type_hint() 102 body = self.py__name__() + '(%s)' % ', '.join([ 103 param_name_to_str(n) 104 for n in function_execution.get_param_names() 105 ]) 106 if return_hint is None: 107 return body 108 else: 109 return_hint = return_annotation.get_code(include_prefix=False) 110 body = self.py__name__() + self.tree_node.children[2].get_code(include_prefix=False) 111 112 return body + ' -> ' + return_hint 113 114 def py__call__(self, arguments): 115 function_execution = self.as_context(arguments) 116 return function_execution.infer() 117 118 def _as_context(self, arguments=None): 119 if arguments is None: 120 return AnonymousFunctionExecution(self) 121 return FunctionExecutionContext(self, arguments) 122 123 def get_signatures(self): 124 return [TreeSignature(f) for f in self.get_signature_functions()] 125 126 127 class FunctionValue(FunctionMixin, FunctionAndClassBase, metaclass=CachedMetaClass): 128 @classmethod 129 def from_context(cls, context, tree_node): 130 def create(tree_node): 131 if context.is_class(): 132 return MethodValue( 133 context.inference_state, 134 context, 135 parent_context=parent_context, 136 tree_node=tree_node 137 ) 138 else: 139 return cls( 140 context.inference_state, 141 parent_context=parent_context, 142 tree_node=tree_node 143 ) 144 145 overloaded_funcs = list(_find_overload_functions(context, tree_node)) 146 147 parent_context = context 148 while parent_context.is_class() or parent_context.is_instance(): 149 parent_context = parent_context.parent_context 150 151 function = create(tree_node) 152 153 if overloaded_funcs: 154 return OverloadedFunctionValue( 155 function, 156 # Get them into the correct order: lower line first. 157 list(reversed([create(f) for f in overloaded_funcs])) 158 ) 159 return function 160 161 def py__class__(self): 162 c, = values_from_qualified_names(self.inference_state, 'types', 'FunctionType') 163 return c 164 165 def get_default_param_context(self): 166 return self.parent_context 167 168 def get_signature_functions(self): 169 return [self] 170 171 172 class FunctionNameInClass(NameWrapper): 173 def __init__(self, class_context, name): 174 super().__init__(name) 175 self._class_context = class_context 176 177 def get_defining_qualified_value(self): 178 return self._class_context.get_value() # Might be None. 179 180 181 class MethodValue(FunctionValue): 182 def __init__(self, inference_state, class_context, *args, **kwargs): 183 super().__init__(inference_state, *args, **kwargs) 184 self.class_context = class_context 185 186 def get_default_param_context(self): 187 return self.class_context 188 189 def get_qualified_names(self): 190 # Need to implement this, because the parent value of a method 191 # value is not the class value but the module. 192 names = self.class_context.get_qualified_names() 193 if names is None: 194 return None 195 return names + (self.py__name__(),) 196 197 @property 198 def name(self): 199 return FunctionNameInClass(self.class_context, super().name) 200 201 202 class BaseFunctionExecutionContext(ValueContext, TreeContextMixin): 203 def infer_annotations(self): 204 raise NotImplementedError 205 206 @inference_state_method_cache(default=NO_VALUES) 207 @recursion.execution_recursion_decorator() 208 def get_return_values(self, check_yields=False): 209 funcdef = self.tree_node 210 if funcdef.type == 'lambdef': 211 return self.infer_node(funcdef.children[-1]) 212 213 if check_yields: 214 value_set = NO_VALUES 215 returns = get_yield_exprs(self.inference_state, funcdef) 216 else: 217 value_set = self.infer_annotations() 218 if value_set: 219 # If there are annotations, prefer them over anything else. 220 # This will make it faster. 221 return value_set 222 value_set |= docstrings.infer_return_types(self._value) 223 returns = funcdef.iter_return_stmts() 224 225 for r in returns: 226 if check_yields: 227 value_set |= ValueSet.from_sets( 228 lazy_value.infer() 229 for lazy_value in self._get_yield_lazy_value(r) 230 ) 231 else: 232 check = flow_analysis.reachability_check(self, funcdef, r) 233 if check is flow_analysis.UNREACHABLE: 234 debug.dbg('Return unreachable: %s', r) 235 else: 236 try: 237 children = r.children 238 except AttributeError: 239 ctx = compiled.builtin_from_name(self.inference_state, 'None') 240 value_set |= ValueSet([ctx]) 241 else: 242 value_set |= self.infer_node(children[1]) 243 if check is flow_analysis.REACHABLE: 244 debug.dbg('Return reachable: %s', r) 245 break 246 return value_set 247 248 def _get_yield_lazy_value(self, yield_expr): 249 if yield_expr.type == 'keyword': 250 # `yield` just yields None. 251 ctx = compiled.builtin_from_name(self.inference_state, 'None') 252 yield LazyKnownValue(ctx) 253 return 254 255 node = yield_expr.children[1] 256 if node.type == 'yield_arg': # It must be a yield from. 257 cn = ContextualizedNode(self, node.children[1]) 258 yield from cn.infer().iterate(cn) 259 else: 260 yield LazyTreeValue(self, node) 261 262 @recursion.execution_recursion_decorator(default=iter([])) 263 def get_yield_lazy_values(self, is_async=False): 264 # TODO: if is_async, wrap yield statements in Awaitable/async_generator_asend 265 for_parents = [(y, tree.search_ancestor(y, 'for_stmt', 'funcdef', 266 'while_stmt', 'if_stmt')) 267 for y in get_yield_exprs(self.inference_state, self.tree_node)] 268 269 # Calculate if the yields are placed within the same for loop. 270 yields_order = [] 271 last_for_stmt = None 272 for yield_, for_stmt in for_parents: 273 # For really simple for loops we can predict the order. Otherwise 274 # we just ignore it. 275 parent = for_stmt.parent 276 if parent.type == 'suite': 277 parent = parent.parent 278 if for_stmt.type == 'for_stmt' and parent == self.tree_node \ 279 and parser_utils.for_stmt_defines_one_name(for_stmt): # Simplicity for now. 280 if for_stmt == last_for_stmt: 281 yields_order[-1][1].append(yield_) 282 else: 283 yields_order.append((for_stmt, [yield_])) 284 elif for_stmt == self.tree_node: 285 yields_order.append((None, [yield_])) 286 else: 287 types = self.get_return_values(check_yields=True) 288 if types: 289 yield LazyKnownValues(types, min=0, max=float('inf')) 290 return 291 last_for_stmt = for_stmt 292 293 for for_stmt, yields in yields_order: 294 if for_stmt is None: 295 # No for_stmt, just normal yields. 296 for yield_ in yields: 297 yield from self._get_yield_lazy_value(yield_) 298 else: 299 input_node = for_stmt.get_testlist() 300 cn = ContextualizedNode(self, input_node) 301 ordered = cn.infer().iterate(cn) 302 ordered = list(ordered) 303 for lazy_value in ordered: 304 dct = {str(for_stmt.children[1].value): lazy_value.infer()} 305 with self.predefine_names(for_stmt, dct): 306 for yield_in_same_for_stmt in yields: 307 yield from self._get_yield_lazy_value(yield_in_same_for_stmt) 308 309 def merge_yield_values(self, is_async=False): 310 return ValueSet.from_sets( 311 lazy_value.infer() 312 for lazy_value in self.get_yield_lazy_values() 313 ) 314 315 def is_generator(self): 316 return bool(get_yield_exprs(self.inference_state, self.tree_node)) 317 318 def infer(self): 319 """ 320 Created to be used by inheritance. 321 """ 322 inference_state = self.inference_state 323 is_coroutine = self.tree_node.parent.type in ('async_stmt', 'async_funcdef') 324 from jedi.inference.gradual.base import GenericClass 325 326 if is_coroutine: 327 if self.is_generator(): 328 async_generator_classes = inference_state.typing_module \ 329 .py__getattribute__('AsyncGenerator') 330 331 yield_values = self.merge_yield_values(is_async=True) 332 # The contravariant doesn't seem to be defined. 333 generics = (yield_values.py__class__(), NO_VALUES) 334 return ValueSet( 335 GenericClass(c, TupleGenericManager(generics)) 336 for c in async_generator_classes 337 ).execute_annotation() 338 else: 339 async_classes = inference_state.typing_module.py__getattribute__('Coroutine') 340 return_values = self.get_return_values() 341 # Only the first generic is relevant. 342 generics = (return_values.py__class__(), NO_VALUES, NO_VALUES) 343 return ValueSet( 344 GenericClass(c, TupleGenericManager(generics)) for c in async_classes 345 ).execute_annotation() 346 else: 347 # If there are annotations, prefer them over anything else. 348 if self.is_generator() and not self.infer_annotations(): 349 return ValueSet([iterable.Generator(inference_state, self)]) 350 else: 351 return self.get_return_values() 352 353 354 class FunctionExecutionContext(BaseFunctionExecutionContext): 355 def __init__(self, function_value, arguments): 356 super().__init__(function_value) 357 self._arguments = arguments 358 359 def get_filters(self, until_position=None, origin_scope=None): 360 yield FunctionExecutionFilter( 361 self, self._value, 362 until_position=until_position, 363 origin_scope=origin_scope, 364 arguments=self._arguments 365 ) 366 367 def infer_annotations(self): 368 from jedi.inference.gradual.annotation import infer_return_types 369 return infer_return_types(self._value, self._arguments) 370 371 def get_param_names(self): 372 return [ 373 ParamName(self._value, param.name, self._arguments) 374 for param in self._value.tree_node.get_params() 375 ] 376 377 378 class AnonymousFunctionExecution(BaseFunctionExecutionContext): 379 def infer_annotations(self): 380 # I don't think inferring anonymous executions is a big thing. 381 # Anonymous contexts are mostly there for the user to work in. ~ dave 382 return NO_VALUES 383 384 def get_filters(self, until_position=None, origin_scope=None): 385 yield AnonymousFunctionExecutionFilter( 386 self, self._value, 387 until_position=until_position, 388 origin_scope=origin_scope, 389 ) 390 391 def get_param_names(self): 392 return self._value.get_param_names() 393 394 395 class OverloadedFunctionValue(FunctionMixin, ValueWrapper): 396 def __init__(self, function, overloaded_functions): 397 super().__init__(function) 398 self._overloaded_functions = overloaded_functions 399 400 def py__call__(self, arguments): 401 debug.dbg("Execute overloaded function %s", self._wrapped_value, color='BLUE') 402 function_executions = [] 403 for signature in self.get_signatures(): 404 function_execution = signature.value.as_context(arguments) 405 function_executions.append(function_execution) 406 if signature.matches_signature(arguments): 407 return function_execution.infer() 408 409 if self.inference_state.is_analysis: 410 # In this case we want precision. 411 return NO_VALUES 412 return ValueSet.from_sets(fe.infer() for fe in function_executions) 413 414 def get_signature_functions(self): 415 return self._overloaded_functions 416 417 def get_type_hint(self, add_class_info=True): 418 return 'Union[%s]' % ', '.join(f.get_type_hint() for f in self._overloaded_functions) 419 420 421 def _find_overload_functions(context, tree_node): 422 def _is_overload_decorated(funcdef): 423 if funcdef.parent.type == 'decorated': 424 decorators = funcdef.parent.children[0] 425 if decorators.type == 'decorator': 426 decorators = [decorators] 427 else: 428 decorators = decorators.children 429 for decorator in decorators: 430 dotted_name = decorator.children[1] 431 if dotted_name.type == 'name' and dotted_name.value == 'overload': 432 # TODO check with values if it's the right overload 433 return True 434 return False 435 436 if tree_node.type == 'lambdef': 437 return 438 439 if _is_overload_decorated(tree_node): 440 yield tree_node 441 442 while True: 443 filter = ParserTreeFilter( 444 context, 445 until_position=tree_node.start_pos 446 ) 447 names = filter.get(tree_node.name.value) 448 assert isinstance(names, list) 449 if not names: 450 break 451 452 found = False 453 for name in names: 454 funcdef = name.tree_name.parent 455 if funcdef.type == 'funcdef' and _is_overload_decorated(funcdef): 456 tree_node = funcdef 457 found = True 458 yield funcdef 459 460 if not found: 461 break 462