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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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