add more complex example

This commit is contained in:
AcerecA 2025-01-20 15:10:20 +01:00
parent a9ce78c1a3
commit 7b4f3b7119
2 changed files with 100 additions and 21 deletions

View File

@ -5,11 +5,11 @@ example2 = example
(
(let (some vars (default 0))
; ... some wall of text
"))"
"))\""
wqdqwf = '(doqwf)
var = 1.3
var = 231
qqvwv
cfunc()
)
)

View File

@ -1,17 +1,34 @@
from collections.abc import Generator
from logging import INFO, basicConfig, getLogger
from re import fullmatch
import re
from time import time
from lsprotocol.types import (
TEXT_DOCUMENT_DID_CHANGE,
TEXT_DOCUMENT_DID_OPEN,
TEXT_DOCUMENT_DID_SAVE,
TEXT_DOCUMENT_DOCUMENT_SYMBOL,
TEXT_DOCUMENT_HOVER,
TEXT_DOCUMENT_INLAY_HINT,
CompletionItem,
Diagnostic,
DiagnosticSeverity,
DidChangeTextDocumentParams,
DidOpenTextDocumentParams,
DidSaveTextDocumentParams,
DocumentSymbol,
DocumentSymbolParams,
Hover,
HoverParams,
InlayHint,
InlayHintParams,
MessageType,
Position,
Range,
)
from pygls.server import LanguageServer
from pygls.workspace import TextDocument
from skillls.parsing.iterative import IterativeParser, TokenParser
@ -24,35 +41,97 @@ basicConfig(filename="skillls.log", level=INFO)
cache: Cache[str, CompletionItem] = Cache()
logger = getLogger(__name__)
server = LanguageServer("skillls", "v0.1")
@server.feature(TEXT_DOCUMENT_DOCUMENT_SYMBOL)
def on_hover(params: DocumentSymbolParams) -> list[DocumentSymbol]:
server.workspace.remove_text_document(params.text_document.uri)
doc = server.workspace.get_text_document(params.text_document.uri)
t = TokenParser()
t.prepare_content(doc.source)
class SkillLanguageServer(LanguageServer):
def _diagnose_parens(self, doc: TextDocument) -> Generator[Diagnostic, None, None]:
open: list[tuple[int, int]] = []
in_str: bool = False
last = ""
for row, line in enumerate(doc.lines):
for col, char in enumerate(line):
match char:
case "(":
if not in_str:
open.append((row, col))
case ")":
if not in_str:
if len(open) > 0:
open.pop()
else:
yield (
Diagnostic(
Range(
Position(row, col),
Position(row, col),
),
"unopened ) encountered",
)
)
case '"':
if not (in_str and last == "\\"):
in_str = not in_str
case _:
last = char
return t._token_tree
last = char
if len(open) > 0:
for row, col in open:
yield (
Diagnostic(
Range(Position(row, col), Position(row, col)),
"unclosed ) encountered",
)
)
def _diagnose_cisms(self, doc: TextDocument) -> Generator[Diagnostic, None, None]:
for row, line in enumerate(doc.lines):
for col, char in enumerate(line):
if col > 0:
if fullmatch("\\w", line[col - 1]) and char == "(":
if m := re.match(r"\W+(\w+)$", line[:col]):
tok = m.group(1)
else:
tok = line[col - 1]
yield Diagnostic(
Range(
Position(row, col - len(tok)),
Position(row, col + 1),
),
f"c-ism detected: change to `( {tok}`",
DiagnosticSeverity.Warning,
)
def diagnose(self, doc: TextDocument) -> None:
diags: list[Diagnostic] = []
diags.extend(self._diagnose_parens(doc))
diags.extend(self._diagnose_cisms(doc))
self.publish_diagnostics(doc.uri, diags)
server = SkillLanguageServer("skillls", "v0.2")
@server.feature(TEXT_DOCUMENT_DID_OPEN)
def on_open(params: DidOpenTextDocumentParams) -> None:
def on_open(ls: SkillLanguageServer, 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()))
ls.diagnose(doc)
@server.feature(TEXT_DOCUMENT_DID_SAVE)
def on_save(params: DidSaveTextDocumentParams) -> None:
server.workspace.remove_text_document(params.text_document.uri)
@server.feature(TEXT_DOCUMENT_DID_CHANGE)
def on_save(ls: SkillLanguageServer, params: DidChangeTextDocumentParams) -> None:
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()))
ls.diagnose(doc)
@server.feature(TEXT_DOCUMENT_INLAY_HINT)
def inlay_hints(ls: SkillLanguageServer, params: InlayHintParams) -> list[InlayHint]:
hints: list[InlayHint] = []
return hints
def main():