def parse_class_by_jedi_name(self, jedi_name: Name) -> ParsedClass: """ To parse a class definition by its Jedi Name. Args: jedi_name: the Jedi Name of the target class to parse Returns: The parsed class in ParsedClass """ # case of being the object class if jedi_name.full_name == 'builtins.object': return PARSED_OBJECT_CLASS # case of a class not defined by a recognised script, so external class if not jedi_name.module_path: return ParsedPackageClass(jedi_name) # case of a custom class definition, which should have a dot-separate # full name starting with the full name of the module/script, and its # type should be `class`. There is case that the first condition is # satisfied but the second not, like a type alias definition/assignment # has a type `statement`. # use `class_name.goto()[0]` to fetch the full content Jedi Name which # has the `full_name` field if jedi_name.goto()[0].full_name.startswith( jedi_name.module_name) and jedi_name.type == 'class': return ParsedCustomClass(jedi_name, self) else: return ParsedPackageClass(jedi_name)
def definition(correct, correct_start, path): should_be = set() for match in re.finditer('(?:[^ ]+)', correct): string = match.group(0) parser = grammar36.parse(string, start_symbol='eval_input', error_recovery=False) parser_utils.move(parser.get_root_node(), self.line_nr) node = parser.get_root_node() module_context = script._get_module_context() user_context = get_user_context(module_context, (self.line_nr, 0)) node.parent = user_context.tree_node results = convert_values(user_context.infer_node(node)) if not results: raise Exception('Could not resolve %s on line %s' % (match.string, self.line_nr - 1)) should_be |= set( Name(inference_state, r.name) for r in results) debug.dbg('Finished getting types', color='YELLOW') # Because the objects have different ids, `repr`, then compare. should = set(comparison(r) for r in should_be) return should
def lsp_symbol_information(name: Name) -> SymbolInformation: """Get LSP SymbolInformation from Jedi definition.""" return SymbolInformation( name=name.name, kind=get_lsp_symbol_type(name.type), location=lsp_location(name), container_name=name.parent(), )
def _document_symbol_range(name: Name) -> Range: """Get accurate full range of function. Thanks <https://github.com/CXuesong> from <https://github.com/palantir/python-language-server/pull/537/files> for the inspiration! Note: I add tons of extra space to make dictionary completions work. Jedi cuts off the end sometimes before the final function statement. This may be the cause of bugs at some point. """ start = name.get_definition_start_position() end = name.get_definition_end_position() if start is None or end is None: return lsp_range(name) (start_line, start_column) = start (end_line, end_column) = end return Range( start=Position(line=start_line - 1, character=start_column), end=Position(line=end_line - 1, character=end_column), )
def build_documentation(name: JediName) -> str: LOGGER.debug(f"name: {repr(name)}") try: module_name = name.module_name module_path = name.module_path type_ = name.type signature = (name._get_docstring_signature() if type_ in {"class", "function"} else "") docstring = name._get_docstring() except Exception as err: LOGGER.debug(err) return "" # header header = (f"module: <code>{module_name}</code>" if module_name and module_name != "__main__" else "") # title title = f"<h3>{type_} <strong><code>{name.name}</code></strong></h3>" # signature signature = (f"<p><code>{escape_characters(signature)}</code></p>" if signature else "") # body body = f"<p>{escape_characters(docstring)}</p>" if docstring else "" # footer footer = "" try: row, col = name.line, name.column # use one-based column index col += 1 module_path = (module_path if module_path and module_path != "__main__" else "") footer = f"<a href='{module_path}:{row}:{col}'>Go to definition</a>" except Exception as err: LOGGER.debug(err) result = "\n".join([ item for item in (header, title, signature, body, footer) if item ]) return f"<div>{result}</div>"
def _docstring_markdown(name: Name) -> str: doc = name.docstring() if not doc: return '' if name.type in ['class', 'function']: try: sig, doc = doc.split('\n\n', 1) except ValueError: sig = doc doc = False sig = f'```python\n{sig}\n```' if doc: return f'{sig}\n\n```\n{doc}\n```' return sig return f'```\n{doc}\n```'
def _is_original_class(class_name: Name, script_context: Name) -> bool: """ To check if a jedi Name is an originally defined class in a script. Args: class_name: the Name of the target class script_context: the context of the target script Returns: `True` if the class is an originally defined class or `False` otherwise """ if not script_context.module_name: return class_name.type == 'class' # use `class_name.goto()[0]` to fetch the full content Jedi Name which # has the `full_name` field return class_name.type == 'class' and \ class_name.goto()[0].full_name.startswith( script_context.module_name )
def _docstring(name: Name) -> str: return name.docstring()