from logging import INFO, basicConfig, getLogger from pathlib import Path from time import time from lsprotocol.types import ( TEXT_DOCUMENT_DIAGNOSTIC, TEXT_DOCUMENT_DID_CHANGE, TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_DID_SAVE, TEXT_DOCUMENT_DOCUMENT_SYMBOL, TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS, CompletionItem, Diagnostic, DiagnosticSeverity, DidChangeTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, DocumentDiagnosticParams, DocumentDiagnosticReport, DocumentSymbol, DocumentSymbolParams, Position, Range, RelatedFullDocumentDiagnosticReport, ) from pygls.server import LanguageServer from parsimonious import Grammar, IncompleteParseError from skillls.parsing.iterative import IterativeParser from .cache import Cache from .parsing.tokenize import Locator, SkillVisitor URI = str basicConfig(filename="skillls.log", level=INFO) cache: Cache[str, CompletionItem] = Cache() logger = getLogger(__name__) server = LanguageServer("skillls", "v0.1") def parse(content: str): path = Path(__file__).parent / "grammar.peg" grammar = Grammar(path.read_text()) locator = Locator(content.split()) tree = grammar.parse(content) iv = SkillVisitor(locator) output = iv.visit(tree) return output # @server.feature(TEXT_DOCUMENT_DOCUMENT_SYMBOL) # def document_symbols(params: DocumentSymbolParams) -> list[DocumentSymbol]: # logger.warning("requested document symbols for %s", params.text_document.uri) # doc = server.workspace.get_text_document(params.text_document.uri) # try: # logger.warning(parse(doc.source)) # except IncompleteParseError as e: # server.publish_diagnostics( # params.text_document.uri, # [ # Diagnostic( # Range( # Position(e.line() - 1, e.column() - 1), # Position(len(doc.lines), 0), # ), # str(e), # severity=DiagnosticSeverity.Error, # ) # ], # ) # return [] # @server.feature(TEXT_DOCUMENT_DIAGNOSTIC) # def document_diagnostic(params: DocumentDiagnosticParams) -> DocumentDiagnosticReport: # doc = server.workspace.get_text_document(params.text_document.uri) # p = IterativeParser() # # parsed = (e for e in parse(doc.source) if isinstance(e, DocumentSymbol)) # # diags = [ # # Diagnostic(e.range, e.name, severity=DiagnosticSeverity.Error) for e in parsed # # ] # diags = p(doc.lines) # return RelatedFullDocumentDiagnosticReport(diags) @server.feature(TEXT_DOCUMENT_DID_OPEN) def on_open(params: DidOpenTextDocumentParams) -> None: doc = server.workspace.get_text_document(params.text_document.uri) p = IterativeParser() diags = p(doc.lines) server.publish_diagnostics(params.text_document.uri, diags, version=int(time())) @server.feature(TEXT_DOCUMENT_DID_SAVE) def on_save(params: DidSaveTextDocumentParams) -> None: server.workspace.remove_text_document(params.text_document.uri) doc = server.workspace.get_text_document(params.text_document.uri) p = IterativeParser() diags = p(doc.lines) logger.warning(doc.source) server.publish_diagnostics(params.text_document.uri, diags, version=int(time())) def main(): server.start_io() if __name__ == "__main__": file = Path(__file__).parent.parent / "examples" / "example.il" out = parse(file.read_text())