def f( params: DocumentSymbolParams ) -> Union[List[SymbolInformation], List[DocumentSymbol]]: symbol_info = SymbolInformation( name='symbol', kind=SymbolKind.Namespace, location=Location( uri='uri', range=Range( start=Position(line=0, character=0), end=Position(line=1, character=1), ), ), container_name='container', deprecated=False, ) document_symbol_inner = DocumentSymbol( name='inner_symbol', kind=SymbolKind.Number, range=Range( start=Position(line=0, character=0), end=Position(line=1, character=1), ), selection_range=Range( start=Position(line=0, character=0), end=Position(line=1, character=1), ), ) document_symbol = DocumentSymbol( name='symbol', kind=SymbolKind.Object, range=Range( start=Position(line=0, character=0), end=Position(line=10, character=10), ), selection_range=Range( start=Position(line=0, character=0), end=Position(line=10, character=10), ), detail='detail', children=[document_symbol_inner], deprecated=True, ) return { # type: ignore 'file://return.symbol_information_list': [symbol_info], 'file://return.document_symbol_list': [document_symbol], }.get(params.text_document.uri, None)
def lsp_document_symbols(names: List[Name]) -> List[DocumentSymbol]: """Get hierarchical symbols. We do some cleaning here. Names from scopes that aren't directly accessible with dot notation are removed from display. See comments inline for cleaning steps. """ _name_lookup: Dict[Name, DocumentSymbol] = {} results: List[DocumentSymbol] = [] for name in names: symbol = DocumentSymbol( name=name.name, kind=get_lsp_symbol_type(name.type), range=_document_symbol_range(name), selection_range=lsp_range(name), detail=name.description, children=[], ) parent = name.parent() if parent.type == "module": # add module-level variables to list results.append(symbol) if name.type == "class": # if they're a class, they can also be a namespace _name_lookup[name] = symbol elif ( parent.type == "class" and name.type == "function" and name.name in {"__init__"} ): # special case for __init__ method in class; names defined here symbol.kind = SymbolKind.Method parent_symbol = _name_lookup[parent] assert parent_symbol.children is not None parent_symbol.children.append(symbol) _name_lookup[name] = symbol elif parent not in _name_lookup: # unqualified names are not included in the tree continue elif name.is_side_effect() and name.get_line_code().strip().startswith( "self." ): # handle attribute creation on __init__ method symbol.kind = SymbolKind.Property parent_symbol = _name_lookup[parent] assert parent_symbol.children is not None parent_symbol.children.append(symbol) elif parent.type == "class": # children are added for class scopes if name.type == "function": # No way to identify @property decorated items. That said, as # far as code is concerned, @property-decorated items should be # considered "methods" since do more than just assign a value. symbol.kind = SymbolKind.Method else: symbol.kind = SymbolKind.Property parent_symbol = _name_lookup[parent] assert parent_symbol.children is not None parent_symbol.children.append(symbol) return results
def symbol( name: str, kind: SymbolKind, range: str, selection_range: str = "", children: Optional[List[DocumentSymbol]] = None, ) -> DocumentSymbol: """Helper for writing symbols.""" return DocumentSymbol( name=name, kind=kind, range=from_str(range), selection_range=from_str(selection_range or range), children=children or [], )
def push_symbol(self): symbol = DocumentSymbol( name="", kind=SymbolKind.String, range=Range( start=Position(line=1, character=0), end=Position(line=1, character=10), ), selection_range=Range( start=Position(line=1, character=0), end=Position(line=1, character=10), ), children=[], ) current_symbol = self.current_symbol if not current_symbol: self.symbols.append(symbol) else: current_symbol.children.append(symbol) self.symbol_stack.append(symbol) return symbol