1from abc import abstractmethod 2from inspect import Parameter 3from typing import Optional, Tuple 4 5from parso.tree import search_ancestor 6 7from jedi.parser_utils import find_statement_documentation, clean_scope_docstring 8from jedi.inference.utils import unite 9from jedi.inference.base_value import ValueSet, NO_VALUES 10from jedi.inference.cache import inference_state_method_cache 11from jedi.inference import docstrings 12from jedi.cache import memoize_method 13from jedi.inference.helpers import deep_ast_copy, infer_call_of_leaf 14from jedi.plugins import plugin_manager 15 16 17def _merge_name_docs(names): 18 doc = '' 19 for name in names: 20 if doc: 21 # In case we have multiple values, just return all of them 22 # separated by a few dashes. 23 doc += '\n' + '-' * 30 + '\n' 24 doc += name.py__doc__() 25 return doc 26 27 28class AbstractNameDefinition: 29 start_pos: Optional[Tuple[int, int]] = None 30 string_name: str 31 parent_context = None 32 tree_name = None 33 is_value_name = True 34 """ 35 Used for the Jedi API to know if it's a keyword or an actual name. 36 """ 37 38 @abstractmethod 39 def infer(self): 40 raise NotImplementedError 41 42 @abstractmethod 43 def goto(self): 44 # Typically names are already definitions and therefore a goto on that 45 # name will always result on itself. 46 return {self} 47 48 def get_qualified_names(self, include_module_names=False): 49 qualified_names = self._get_qualified_names() 50 if qualified_names is None or not include_module_names: 51 return qualified_names 52 53 module_names = self.get_root_context().string_names 54 if module_names is None: 55 return None 56 return module_names + qualified_names 57 58 def _get_qualified_names(self): 59 # By default, a name has no qualified names. 60 return None 61 62 def get_root_context(self): 63 return self.parent_context.get_root_context() 64 65 def get_public_name(self): 66 return self.string_name 67 68 def __repr__(self): 69 if self.start_pos is None: 70 return '<%s: string_name=%s>' % (self.__class__.__name__, self.string_name) 71 return '<%s: string_name=%s start_pos=%s>' % (self.__class__.__name__, 72 self.string_name, self.start_pos) 73 74 def is_import(self): 75 return False 76 77 def py__doc__(self): 78 return '' 79 80 @property 81 def api_type(self): 82 return self.parent_context.api_type 83 84 def get_defining_qualified_value(self): 85 """ 86 Returns either None or the value that is public and qualified. Won't 87 return a function, because a name in a function is never public. 88 """ 89 return None 90 91 92class AbstractArbitraryName(AbstractNameDefinition): 93 """ 94 When you e.g. want to complete dicts keys, you probably want to complete 95 string literals, which is not really a name, but for Jedi we use this 96 concept of Name for completions as well. 97 """ 98 is_value_name = False 99 100 def __init__(self, inference_state, string): 101 self.inference_state = inference_state 102 self.string_name = string 103 self.parent_context = inference_state.builtins_module 104 105 def infer(self): 106 return NO_VALUES 107 108 109class AbstractTreeName(AbstractNameDefinition): 110 def __init__(self, parent_context, tree_name): 111 self.parent_context = parent_context 112 self.tree_name = tree_name 113 114 def get_qualified_names(self, include_module_names=False): 115 import_node = search_ancestor(self.tree_name, 'import_name', 'import_from') 116 # For import nodes we cannot just have names, because it's very unclear 117 # how they would look like. For now we just ignore them in most cases. 118 # In case of level == 1, it works always, because it's like a submodule 119 # lookup. 120 if import_node is not None and not (import_node.level == 1 121 and self.get_root_context().get_value().is_package()): 122 # TODO improve the situation for when level is present. 123 if include_module_names and not import_node.level: 124 return tuple(n.value for n in import_node.get_path_for_name(self.tree_name)) 125 else: 126 return None 127 128 return super().get_qualified_names(include_module_names) 129 130 def _get_qualified_names(self): 131 parent_names = self.parent_context.get_qualified_names() 132 if parent_names is None: 133 return None 134 return parent_names + (self.tree_name.value,) 135 136 def get_defining_qualified_value(self): 137 if self.is_import(): 138 raise NotImplementedError("Shouldn't really happen, please report") 139 elif self.parent_context: 140 return self.parent_context.get_value() # Might be None 141 return None 142 143 def goto(self): 144 context = self.parent_context 145 name = self.tree_name 146 definition = name.get_definition(import_name_always=True) 147 if definition is not None: 148 type_ = definition.type 149 if type_ == 'expr_stmt': 150 # Only take the parent, because if it's more complicated than just 151 # a name it's something you can "goto" again. 152 is_simple_name = name.parent.type not in ('power', 'trailer') 153 if is_simple_name: 154 return [self] 155 elif type_ in ('import_from', 'import_name'): 156 from jedi.inference.imports import goto_import 157 module_names = goto_import(context, name) 158 return module_names 159 else: 160 return [self] 161 else: 162 from jedi.inference.imports import follow_error_node_imports_if_possible 163 values = follow_error_node_imports_if_possible(context, name) 164 if values is not None: 165 return [value.name for value in values] 166 167 par = name.parent 168 node_type = par.type 169 if node_type == 'argument' and par.children[1] == '=' and par.children[0] == name: 170 # Named param goto. 171 trailer = par.parent 172 if trailer.type == 'arglist': 173 trailer = trailer.parent 174 if trailer.type != 'classdef': 175 if trailer.type == 'decorator': 176 value_set = context.infer_node(trailer.children[1]) 177 else: 178 i = trailer.parent.children.index(trailer) 179 to_infer = trailer.parent.children[:i] 180 if to_infer[0] == 'await': 181 to_infer.pop(0) 182 value_set = context.infer_node(to_infer[0]) 183 from jedi.inference.syntax_tree import infer_trailer 184 for trailer in to_infer[1:]: 185 value_set = infer_trailer(context, value_set, trailer) 186 param_names = [] 187 for value in value_set: 188 for signature in value.get_signatures(): 189 for param_name in signature.get_param_names(): 190 if param_name.string_name == name.value: 191 param_names.append(param_name) 192 return param_names 193 elif node_type == 'dotted_name': # Is a decorator. 194 index = par.children.index(name) 195 if index > 0: 196 new_dotted = deep_ast_copy(par) 197 new_dotted.children[index - 1:] = [] 198 values = context.infer_node(new_dotted) 199 return unite( 200 value.goto(name, name_context=context) 201 for value in values 202 ) 203 204 if node_type == 'trailer' and par.children[0] == '.': 205 values = infer_call_of_leaf(context, name, cut_own_trailer=True) 206 return values.goto(name, name_context=context) 207 else: 208 stmt = search_ancestor( 209 name, 'expr_stmt', 'lambdef' 210 ) or name 211 if stmt.type == 'lambdef': 212 stmt = name 213 return context.goto(name, position=stmt.start_pos) 214 215 def is_import(self): 216 imp = search_ancestor(self.tree_name, 'import_from', 'import_name') 217 return imp is not None 218 219 @property 220 def string_name(self): 221 return self.tree_name.value 222 223 @property 224 def start_pos(self): 225 return self.tree_name.start_pos 226 227 228class ValueNameMixin: 229 def infer(self): 230 return ValueSet([self._value]) 231 232 def py__doc__(self): 233 doc = self._value.py__doc__() 234 if not doc and self._value.is_stub(): 235 from jedi.inference.gradual.conversion import convert_names 236 names = convert_names([self], prefer_stub_to_compiled=False) 237 if self not in names: 238 return _merge_name_docs(names) 239 return doc 240 241 def _get_qualified_names(self): 242 return self._value.get_qualified_names() 243 244 def get_root_context(self): 245 if self.parent_context is None: # A module 246 return self._value.as_context() 247 return super().get_root_context() 248 249 def get_defining_qualified_value(self): 250 context = self.parent_context 251 if context.is_module() or context.is_class(): 252 return self.parent_context.get_value() # Might be None 253 return None 254 255 @property 256 def api_type(self): 257 return self._value.api_type 258 259 260class ValueName(ValueNameMixin, AbstractTreeName): 261 def __init__(self, value, tree_name): 262 super().__init__(value.parent_context, tree_name) 263 self._value = value 264 265 def goto(self): 266 return ValueSet([self._value.name]) 267 268 269class TreeNameDefinition(AbstractTreeName): 270 _API_TYPES = dict( 271 import_name='module', 272 import_from='module', 273 funcdef='function', 274 param='param', 275 classdef='class', 276 ) 277 278 def infer(self): 279 # Refactor this, should probably be here. 280 from jedi.inference.syntax_tree import tree_name_to_values 281 return tree_name_to_values( 282 self.parent_context.inference_state, 283 self.parent_context, 284 self.tree_name 285 ) 286 287 @property 288 def api_type(self): 289 definition = self.tree_name.get_definition(import_name_always=True) 290 if definition is None: 291 return 'statement' 292 return self._API_TYPES.get(definition.type, 'statement') 293 294 def assignment_indexes(self): 295 """ 296 Returns an array of tuple(int, node) of the indexes that are used in 297 tuple assignments. 298 299 For example if the name is ``y`` in the following code:: 300 301 x, (y, z) = 2, '' 302 303 would result in ``[(1, xyz_node), (0, yz_node)]``. 304 305 When searching for b in the case ``a, *b, c = [...]`` it will return:: 306 307 [(slice(1, -1), abc_node)] 308 """ 309 indexes = [] 310 is_star_expr = False 311 node = self.tree_name.parent 312 compare = self.tree_name 313 while node is not None: 314 if node.type in ('testlist', 'testlist_comp', 'testlist_star_expr', 'exprlist'): 315 for i, child in enumerate(node.children): 316 if child == compare: 317 index = int(i / 2) 318 if is_star_expr: 319 from_end = int((len(node.children) - i) / 2) 320 index = slice(index, -from_end) 321 indexes.insert(0, (index, node)) 322 break 323 else: 324 raise LookupError("Couldn't find the assignment.") 325 is_star_expr = False 326 elif node.type == 'star_expr': 327 is_star_expr = True 328 elif node.type in ('expr_stmt', 'sync_comp_for'): 329 break 330 331 compare = node 332 node = node.parent 333 return indexes 334 335 @property 336 def inference_state(self): 337 # Used by the cache function below 338 return self.parent_context.inference_state 339 340 @inference_state_method_cache(default='') 341 def py__doc__(self): 342 api_type = self.api_type 343 if api_type in ('function', 'class'): 344 # Make sure the names are not TreeNameDefinitions anymore. 345 return clean_scope_docstring(self.tree_name.get_definition()) 346 347 if api_type == 'module': 348 names = self.goto() 349 if self not in names: 350 return _merge_name_docs(names) 351 352 if api_type == 'statement' and self.tree_name.is_definition(): 353 return find_statement_documentation(self.tree_name.get_definition()) 354 return '' 355 356 357class _ParamMixin: 358 def maybe_positional_argument(self, include_star=True): 359 options = [Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD] 360 if include_star: 361 options.append(Parameter.VAR_POSITIONAL) 362 return self.get_kind() in options 363 364 def maybe_keyword_argument(self, include_stars=True): 365 options = [Parameter.KEYWORD_ONLY, Parameter.POSITIONAL_OR_KEYWORD] 366 if include_stars: 367 options.append(Parameter.VAR_KEYWORD) 368 return self.get_kind() in options 369 370 def _kind_string(self): 371 kind = self.get_kind() 372 if kind == Parameter.VAR_POSITIONAL: # *args 373 return '*' 374 if kind == Parameter.VAR_KEYWORD: # **kwargs 375 return '**' 376 return '' 377 378 def get_qualified_names(self, include_module_names=False): 379 return None 380 381 382class ParamNameInterface(_ParamMixin): 383 api_type = 'param' 384 385 def get_kind(self): 386 raise NotImplementedError 387 388 def to_string(self): 389 raise NotImplementedError 390 391 def get_executed_param_name(self): 392 """ 393 For dealing with type inference and working around the graph, we 394 sometimes want to have the param name of the execution. This feels a 395 bit strange and we might have to refactor at some point. 396 397 For now however it exists to avoid infering params when we don't really 398 need them (e.g. when we can just instead use annotations. 399 """ 400 return None 401 402 @property 403 def star_count(self): 404 kind = self.get_kind() 405 if kind == Parameter.VAR_POSITIONAL: 406 return 1 407 if kind == Parameter.VAR_KEYWORD: 408 return 2 409 return 0 410 411 412class BaseTreeParamName(ParamNameInterface, AbstractTreeName): 413 annotation_node = None 414 default_node = None 415 416 def to_string(self): 417 output = self._kind_string() + self.get_public_name() 418 annotation = self.annotation_node 419 default = self.default_node 420 if annotation is not None: 421 output += ': ' + annotation.get_code(include_prefix=False) 422 if default is not None: 423 output += '=' + default.get_code(include_prefix=False) 424 return output 425 426 def get_public_name(self): 427 name = self.string_name 428 if name.startswith('__'): 429 # Params starting with __ are an equivalent to positional only 430 # variables in typeshed. 431 name = name[2:] 432 return name 433 434 def goto(self, **kwargs): 435 return [self] 436 437 438class _ActualTreeParamName(BaseTreeParamName): 439 def __init__(self, function_value, tree_name): 440 super().__init__( 441 function_value.get_default_param_context(), tree_name) 442 self.function_value = function_value 443 444 def _get_param_node(self): 445 return search_ancestor(self.tree_name, 'param') 446 447 @property 448 def annotation_node(self): 449 return self._get_param_node().annotation 450 451 def infer_annotation(self, execute_annotation=True, ignore_stars=False): 452 from jedi.inference.gradual.annotation import infer_param 453 values = infer_param( 454 self.function_value, self._get_param_node(), 455 ignore_stars=ignore_stars) 456 if execute_annotation: 457 values = values.execute_annotation() 458 return values 459 460 def infer_default(self): 461 node = self.default_node 462 if node is None: 463 return NO_VALUES 464 return self.parent_context.infer_node(node) 465 466 @property 467 def default_node(self): 468 return self._get_param_node().default 469 470 def get_kind(self): 471 tree_param = self._get_param_node() 472 if tree_param.star_count == 1: # *args 473 return Parameter.VAR_POSITIONAL 474 if tree_param.star_count == 2: # **kwargs 475 return Parameter.VAR_KEYWORD 476 477 # Params starting with __ are an equivalent to positional only 478 # variables in typeshed. 479 if tree_param.name.value.startswith('__'): 480 return Parameter.POSITIONAL_ONLY 481 482 parent = tree_param.parent 483 param_appeared = False 484 for p in parent.children: 485 if param_appeared: 486 if p == '/': 487 return Parameter.POSITIONAL_ONLY 488 else: 489 if p == '*': 490 return Parameter.KEYWORD_ONLY 491 if p.type == 'param': 492 if p.star_count: 493 return Parameter.KEYWORD_ONLY 494 if p == tree_param: 495 param_appeared = True 496 return Parameter.POSITIONAL_OR_KEYWORD 497 498 def infer(self): 499 values = self.infer_annotation() 500 if values: 501 return values 502 503 doc_params = docstrings.infer_param(self.function_value, self._get_param_node()) 504 return doc_params 505 506 507class AnonymousParamName(_ActualTreeParamName): 508 @plugin_manager.decorate(name='goto_anonymous_param') 509 def goto(self): 510 return super().goto() 511 512 @plugin_manager.decorate(name='infer_anonymous_param') 513 def infer(self): 514 values = super().infer() 515 if values: 516 return values 517 from jedi.inference.dynamic_params import dynamic_param_lookup 518 param = self._get_param_node() 519 values = dynamic_param_lookup(self.function_value, param.position_index) 520 if values: 521 return values 522 523 if param.star_count == 1: 524 from jedi.inference.value.iterable import FakeTuple 525 value = FakeTuple(self.function_value.inference_state, []) 526 elif param.star_count == 2: 527 from jedi.inference.value.iterable import FakeDict 528 value = FakeDict(self.function_value.inference_state, {}) 529 elif param.default is None: 530 return NO_VALUES 531 else: 532 return self.function_value.parent_context.infer_node(param.default) 533 return ValueSet({value}) 534 535 536class ParamName(_ActualTreeParamName): 537 def __init__(self, function_value, tree_name, arguments): 538 super().__init__(function_value, tree_name) 539 self.arguments = arguments 540 541 def infer(self): 542 values = super().infer() 543 if values: 544 return values 545 546 return self.get_executed_param_name().infer() 547 548 def get_executed_param_name(self): 549 from jedi.inference.param import get_executed_param_names 550 params_names = get_executed_param_names(self.function_value, self.arguments) 551 return params_names[self._get_param_node().position_index] 552 553 554class ParamNameWrapper(_ParamMixin): 555 def __init__(self, param_name): 556 self._wrapped_param_name = param_name 557 558 def __getattr__(self, name): 559 return getattr(self._wrapped_param_name, name) 560 561 def __repr__(self): 562 return '<%s: %s>' % (self.__class__.__name__, self._wrapped_param_name) 563 564 565class ImportName(AbstractNameDefinition): 566 start_pos = (1, 0) 567 _level = 0 568 569 def __init__(self, parent_context, string_name): 570 self._from_module_context = parent_context 571 self.string_name = string_name 572 573 def get_qualified_names(self, include_module_names=False): 574 if include_module_names: 575 if self._level: 576 assert self._level == 1, "Everything else is not supported for now" 577 module_names = self._from_module_context.string_names 578 if module_names is None: 579 return module_names 580 return module_names + (self.string_name,) 581 return (self.string_name,) 582 return () 583 584 @property 585 def parent_context(self): 586 m = self._from_module_context 587 import_values = self.infer() 588 if not import_values: 589 return m 590 # It's almost always possible to find the import or to not find it. The 591 # importing returns only one value, pretty much always. 592 return next(iter(import_values)).as_context() 593 594 @memoize_method 595 def infer(self): 596 from jedi.inference.imports import Importer 597 m = self._from_module_context 598 return Importer(m.inference_state, [self.string_name], m, level=self._level).follow() 599 600 def goto(self): 601 return [m.name for m in self.infer()] 602 603 @property 604 def api_type(self): 605 return 'module' 606 607 def py__doc__(self): 608 return _merge_name_docs(self.goto()) 609 610 611class SubModuleName(ImportName): 612 _level = 1 613 614 615class NameWrapper: 616 def __init__(self, wrapped_name): 617 self._wrapped_name = wrapped_name 618 619 def __getattr__(self, name): 620 return getattr(self._wrapped_name, name) 621 622 def __repr__(self): 623 return '%s(%s)' % (self.__class__.__name__, self._wrapped_name) 624 625 626class StubNameMixin: 627 def py__doc__(self): 628 from jedi.inference.gradual.conversion import convert_names 629 # Stubs are not complicated and we can just follow simple statements 630 # that have an equals in them, because they typically make something 631 # else public. See e.g. stubs for `requests`. 632 names = [self] 633 if self.api_type == 'statement' and '=' in self.tree_name.get_definition().children: 634 names = [v.name for v in self.infer()] 635 636 names = convert_names(names, prefer_stub_to_compiled=False) 637 if self in names: 638 return super().py__doc__() 639 else: 640 # We have signatures ourselves in stubs, so don't use signatures 641 # from the implementation. 642 return _merge_name_docs(names) 643 644 645# From here on down we make looking up the sys.version_info fast. 646class StubName(StubNameMixin, TreeNameDefinition): 647 def infer(self): 648 inferred = super().infer() 649 if self.string_name == 'version_info' and self.get_root_context().py__name__() == 'sys': 650 from jedi.inference.gradual.stub_value import VersionInfo 651 return ValueSet(VersionInfo(c) for c in inferred) 652 return inferred 653 654 655class ModuleName(ValueNameMixin, AbstractNameDefinition): 656 start_pos = 1, 0 657 658 def __init__(self, value, name): 659 self._value = value 660 self._name = name 661 662 @property 663 def string_name(self): 664 return self._name 665 666 667class StubModuleName(StubNameMixin, ModuleName): 668 pass 669