def visit_symbol(self, ctx: antlr4.ParserRuleContext, kind:int=SymbolKind.Variable, visit_children:bool=True): id_ctx = ctx.getChild(0, Parser.IdentifierContext) symbol = DocumentSymbol( name=id_ctx.start.text, kind=kind, range=Range( start=Position(ctx.start.line-1, ctx.start.column), end=Position(ctx.stop.line-1, ctx.stop.column) ), selection_range=Range( start=Position(id_ctx.start.line-1, id_ctx.start.column), end=Position(id_ctx.stop.line-1, id_ctx.stop.column) ), detail="", children=[], deprecated=False ) logging.debug(f"found symbol: {symbol.name}") self.scope.append(symbol) if visit_children: logging.debug(f"Visiting children of symbol: {symbol.name}") prev_scope = self.scope self.scope = symbol.children res = self.visitChildren(ctx) self.scope = prev_scope return res
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 lsp_document_symbols(names: List[Name]) -> List[DocumentSymbol]: """Get hierarchical symbols.""" _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), children=[], ) parent = name.parent() if parent is None or not parent in _name_lookup: results.append(symbol) else: _name_lookup[parent].children.append(symbol) # type: ignore _name_lookup[name] = symbol return results
def visitInstantiation(self, ctx:Parser.InstantiationContext): for child in ctx.getChildren(lambda x: isinstance(x, Parser.IdentifierContext)): symbol = DocumentSymbol( name=child.start.text, kind=SymbolKind.Variable, range=Range( start=Position(ctx.start.line-1, ctx.start.column), end=Position(ctx.stop.line-1, ctx.stop.column) ), selection_range=Range( start=Position(child.start.line-1, child.start.column), end=Position(child.stop.line-1, child.stop.column) ), detail="", children=[], deprecated=False ) logging.debug(f"found symbol: {symbol.name}") self.scope.append(symbol) return None