skill-ls/skillls/types.py

67 lines
1.9 KiB
Python

from dataclasses import dataclass, field
from enum import Enum, auto
from lsprotocol.types import DocumentSymbol, Range, SymbolKind
URI = str
class NodeKind(Enum):
LET = "let"
PROCEDURE = "procedure"
PROC = "proc"
FOREACH = "foreach"
@dataclass
class Node:
node: str
kind: NodeKind
location: Range
children: list["Node"] = field(default_factory=list)
symbols: dict[str, DocumentSymbol] = field(default_factory=dict)
@property
def all_symbols(self) -> list[DocumentSymbol]:
return [
*self.symbols.values(),
*(sym for child in self.children for sym in child.all_symbols),
]
def should_contain(self, other: "Node") -> bool:
"""range based overlap check"""
start_after = (other.location.start.line > self.location.start.line) or (
(other.location.start.line == self.location.start.line)
and (other.location.start.character > self.location.start.character)
)
ends_before = (other.location.end.line < self.location.end.line) or (
(other.location.end.line == self.location.end.line)
and (other.location.end.character < self.location.start.character)
)
return start_after and ends_before
def add_child(self, new_child: "Node") -> None:
for existing_child in self.children:
if existing_child.should_contain(new_child):
existing_child.add_child(new_child)
break
else:
self.children.append(new_child)
def as_doc_symbol(self) -> DocumentSymbol:
return DocumentSymbol(
name=self.node,
kind=SymbolKind.Namespace,
range=self.location,
selection_range=self.location,
children=list(self.symbols.values())
+ [child.as_doc_symbol() for child in self.children],
)
@dataclass
class DocumentSymbols:
uri: str
tree: Node