update
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
from abc import ABC
|
||||
from collections.abc import Mapping
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import ClassVar
|
||||
|
||||
from lsprotocol.types import SymbolKind
|
||||
|
||||
|
||||
class SkillDataType(Enum):
|
||||
array = "a"
|
||||
"""array"""
|
||||
|
||||
ddUserType = "b"
|
||||
"""Boolean"""
|
||||
|
||||
opfcontext = "C"
|
||||
"""OPF Context"""
|
||||
|
||||
dbobject = "d"
|
||||
"""Cadence database object (CDBA)"""
|
||||
|
||||
envobj = "e"
|
||||
"""environment"""
|
||||
|
||||
flonum = "f"
|
||||
"""floating-point number"""
|
||||
|
||||
opffile = "F"
|
||||
"""OPF file ID"""
|
||||
|
||||
general = "g"
|
||||
"""any data type"""
|
||||
|
||||
nil = "g"
|
||||
""""""
|
||||
|
||||
dgbSpecIlUserType = "G"
|
||||
"""gdm spec"""
|
||||
|
||||
hdbobject = "h"
|
||||
"""hierarchical database configuration object"""
|
||||
|
||||
list = "l"
|
||||
"""linked list"""
|
||||
|
||||
nmpIlUserType = "m"
|
||||
"""nmpll user type"""
|
||||
|
||||
cdsEvalObject = "M"
|
||||
"""Cadence evaluation object"""
|
||||
|
||||
number = "n"
|
||||
"""integere of floating point number"""
|
||||
|
||||
userType = "o"
|
||||
"""user defined type (other)"""
|
||||
|
||||
port = "p"
|
||||
"""I/O port"""
|
||||
|
||||
gdmspecListIlUSerType = "q"
|
||||
""" gdm spec list"""
|
||||
|
||||
defstruct = "r"
|
||||
"""defstruct"""
|
||||
|
||||
rodObj = "R"
|
||||
"""relative object design (ROD) object"""
|
||||
|
||||
symbol = "s"
|
||||
"""symbol"""
|
||||
|
||||
stringSymbol = "S"
|
||||
"""symbol or character string"""
|
||||
|
||||
string = "t"
|
||||
"""character string (text)"""
|
||||
|
||||
function = "u"
|
||||
"""function object, either the name if a function (symbol) or a lambda function body (list)"""
|
||||
|
||||
funobj = "U"
|
||||
"""function object"""
|
||||
|
||||
hdbpath = "v"
|
||||
""""""
|
||||
|
||||
wtype = "w"
|
||||
"""window type"""
|
||||
|
||||
integer = "x"
|
||||
"""integer type"""
|
||||
|
||||
binary = "y"
|
||||
"""binary function"""
|
||||
|
||||
pointer = "&"
|
||||
"""pointer type"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Builtin(ABC):
|
||||
token: str
|
||||
kind: ClassVar[SymbolKind]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Variable(Builtin):
|
||||
kind: ClassVar[SymbolKind] = SymbolKind.Variable
|
||||
typ: SkillDataType
|
||||
default: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AnonymousVariable(Builtin):
|
||||
kind: ClassVar[SymbolKind] = SymbolKind.Variable
|
||||
typ: SkillDataType
|
||||
default: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Procedure(Builtin):
|
||||
kind: ClassVar[SymbolKind] = SymbolKind.Function
|
||||
args: Mapping[str, Variable] = field(default_factory=dict)
|
||||
rest: Variable | None = None
|
||||
kwargs: Mapping[str, Variable] | Mapping[str, AnonymousVariable] = field(
|
||||
default_factory=dict
|
||||
)
|
||||
"""list of ``Variable` if ``@key`` was used, and ``AnonymousVariable`` if ``@option`` was used"""
|
||||
ret: SkillDataType = SkillDataType.nil
|
||||
|
||||
@property
|
||||
def has_options(self) -> bool:
|
||||
return bool(self.kwargs) and isinstance(
|
||||
next(iter(self.kwargs.values())),
|
||||
AnonymousVariable,
|
||||
)
|
||||
|
||||
@property
|
||||
def has_keys(self) -> bool:
|
||||
return bool(self.kwargs) and isinstance(
|
||||
next(iter(self.kwargs.values())),
|
||||
Variable,
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
;; append
|
||||
append(
|
||||
l_list1
|
||||
l_list2
|
||||
) => l_result
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from collections.abc import Mapping
|
||||
|
||||
from .common import Procedure, SkillDataType, Variable
|
||||
|
||||
NUM = SkillDataType.number
|
||||
ANY = SkillDataType.general
|
||||
|
||||
|
||||
FUNCTIONS: Mapping[str, Procedure] = {
|
||||
"plus": Procedure(
|
||||
"plus",
|
||||
ret=NUM,
|
||||
args={
|
||||
"op1": Variable("op1", NUM),
|
||||
"op2": Variable("op2", NUM),
|
||||
},
|
||||
rest=Variable("op3", NUM),
|
||||
),
|
||||
}
|
||||
|
||||
FUNCTIONS["plus"]
|
||||
+134
-340
@@ -1,9 +1,12 @@
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Callable, Generator, Sequence
|
||||
from dataclasses import dataclass, field
|
||||
from difflib import Differ
|
||||
from itertools import chain
|
||||
from logging import INFO, basicConfig, debug, error, getLogger, info, warning
|
||||
from logging import DEBUG, INFO, basicConfig, debug, error, getLogger, info, warning
|
||||
from re import findall, finditer, fullmatch, match as rematch
|
||||
import re
|
||||
from time import time
|
||||
from cattrs import Converter
|
||||
from lsprotocol.types import (
|
||||
INLAY_HINT_RESOLVE,
|
||||
TEXT_DOCUMENT_DID_CHANGE,
|
||||
@@ -28,23 +31,37 @@ from lsprotocol.types import (
|
||||
InlayHintKind,
|
||||
InlayHintParams,
|
||||
MessageType,
|
||||
NotebookDocumentSyncOptions,
|
||||
Position,
|
||||
Range,
|
||||
SymbolKind,
|
||||
TextDocumentContentChangeEvent,
|
||||
TextDocumentContentChangeEvent_Type1,
|
||||
TextDocumentSyncKind,
|
||||
)
|
||||
|
||||
from pygls.protocol import LanguageServerProtocol, default_converter
|
||||
from tree_sitter_skill import language as skill_lang
|
||||
from tree_sitter import Language, Node, Parser, Query, Tree
|
||||
|
||||
from pygls.server import LanguageServer
|
||||
from pygls.workspace import TextDocument
|
||||
|
||||
from skillls.builtins.common import SkillDataType
|
||||
from skillls.parsing.iterative import IterativeParser, TokenParser
|
||||
|
||||
from .cache import Cache
|
||||
|
||||
SKILL_LANG = Language(skill_lang())
|
||||
SKILL_PARSER = Parser(SKILL_LANG)
|
||||
|
||||
|
||||
URI = str
|
||||
|
||||
basicConfig(filename="skillls.log", filemode="w", level=INFO)
|
||||
basicConfig(
|
||||
filename="skillls.log",
|
||||
filemode="w",
|
||||
level=DEBUG,
|
||||
format="%(asctime)s [%(levelname)s]: %(message)s",
|
||||
)
|
||||
logger = getLogger()
|
||||
cache: Cache[str, CompletionItem] = Cache()
|
||||
|
||||
|
||||
@@ -93,6 +110,19 @@ class LetEnvironment(Environment):
|
||||
locals: set[str] = field(default_factory=set)
|
||||
|
||||
|
||||
def offset_range(range: Range, lines: int, cols: int = 0) -> Range:
|
||||
return Range(
|
||||
Position(
|
||||
range.start.line + lines,
|
||||
range.start.character + cols,
|
||||
),
|
||||
Position(
|
||||
range.end.line + lines,
|
||||
range.end.character + cols,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# @dataclass(frozen=True)
|
||||
# class ProcEnvironment(Environment):
|
||||
@@ -111,363 +141,126 @@ class LetEnvironment(Environment):
|
||||
|
||||
|
||||
class SkillLanguageServer(LanguageServer):
|
||||
lets: list[DocumentSymbol] = []
|
||||
procs: list[DocumentSymbol] = []
|
||||
defs: list[DocumentSymbol] = []
|
||||
globals: list[DocumentSymbol] = []
|
||||
contents: dict[str, TextDocument]
|
||||
trees: dict[str, Tree]
|
||||
|
||||
@property
|
||||
def envs(self) -> tuple[DocumentSymbol, ...]:
|
||||
return (
|
||||
*self.procs,
|
||||
*self.lets,
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
version: str,
|
||||
loop=None,
|
||||
protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol,
|
||||
converter_factory: Callable[[], Converter] = default_converter,
|
||||
text_document_sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental,
|
||||
notebook_document_sync: NotebookDocumentSyncOptions | None = None,
|
||||
max_workers: int = 2,
|
||||
):
|
||||
super().__init__(
|
||||
name,
|
||||
version,
|
||||
loop,
|
||||
protocol_cls,
|
||||
converter_factory,
|
||||
text_document_sync_kind,
|
||||
notebook_document_sync,
|
||||
max_workers,
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
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 m in finditer(
|
||||
r"(?P<proc>procedure\s+|;.*)?([a-zA-Z_][a-zA-Z_0-9]+)\(", line
|
||||
):
|
||||
if not m.group("proc"):
|
||||
yield Diagnostic(
|
||||
Range(Position(row, m.start()), Position(row, m.end())),
|
||||
f"change `{m.group(2)}(` to `( {m.group(2)}`",
|
||||
DiagnosticSeverity.Hint,
|
||||
)
|
||||
|
||||
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)
|
||||
self.trees = {}
|
||||
self.contents = {}
|
||||
|
||||
def parse(self, doc: TextDocument) -> None:
|
||||
self.lets = []
|
||||
self._parse_let(doc.lines)
|
||||
self.procs = []
|
||||
self._parse_proc(doc.lines, doc.uri)
|
||||
self.globals = []
|
||||
self._parse_assigns(doc.lines)
|
||||
parsed = SKILL_PARSER.parse(doc.source.encode("utf8"), encoding="utf8")
|
||||
self.trees[doc.uri] = parsed
|
||||
self.contents[doc.uri] = doc
|
||||
|
||||
def _parse_assigns(self, lines: list[str]) -> None:
|
||||
for row, line in enumerate(lines):
|
||||
for found in finditer(
|
||||
r"\b([a-zA-Z_][a-zA-Z0-9_]*)((-|~)>[a-zA-Z_][a-zA-Z0-9_]*)?\s*=\s+",
|
||||
line,
|
||||
):
|
||||
token = found.group(1)
|
||||
token_range = Range(
|
||||
Position(row, found.start()),
|
||||
Position(row, found.start() + len(token)),
|
||||
def update(self, uri: str, changes: list[TextDocumentContentChangeEvent]) -> None:
|
||||
for change in changes:
|
||||
if isinstance(change, TextDocumentContentChangeEvent_Type1):
|
||||
logger.debug(f"updating {change.range}")
|
||||
change_fixed = TextDocumentContentChangeEvent_Type1(
|
||||
offset_range(change.range, -1),
|
||||
change.text,
|
||||
change.range_length,
|
||||
)
|
||||
old = self.contents[uri].lines
|
||||
self.contents[uri].apply_change(change)
|
||||
d = Differ()
|
||||
logger.debug("".join(d.compare(old, self.contents[uri].lines)))
|
||||
|
||||
else:
|
||||
pass
|
||||
|
||||
self.trees[uri] = SKILL_PARSER.parse(
|
||||
self.contents[uri].source.encode("utf8"),
|
||||
old_tree=self.trees[uri],
|
||||
)
|
||||
|
||||
def _get_leaves(self, node: Node) -> list[Node]:
|
||||
if node.children:
|
||||
return [l for child in node.children for l in self._get_leaves(child)]
|
||||
|
||||
return [node]
|
||||
|
||||
def _diagnose_errors(self, uri: str) -> list[Diagnostic]:
|
||||
diags: list[Diagnostic] = []
|
||||
q = SKILL_LANG.query("(ERROR) @error")
|
||||
nodes = (
|
||||
q.captures(self.trees[uri].root_node)["error"]
|
||||
if self.trees.get(uri)
|
||||
else []
|
||||
)
|
||||
|
||||
for node in nodes:
|
||||
if node.type == "ERROR":
|
||||
logger.error(node)
|
||||
logger.error(node.range)
|
||||
content = node.text.decode("utf8") if node.text else ""
|
||||
range = Range(
|
||||
Position(*node.range.start_point), Position(*node.range.end_point)
|
||||
)
|
||||
|
||||
if any(
|
||||
in_range(token_range.start, ns.range)
|
||||
and (token in (child.name for child in (ns.children or [])))
|
||||
for ns in chain(self.lets, self.procs)
|
||||
):
|
||||
pass
|
||||
if "UNEXPECTED" in str(node):
|
||||
msg = f"unexpected '{content}'"
|
||||
else:
|
||||
self.globals.append(
|
||||
DocumentSymbol(
|
||||
token, SymbolKind.Variable, token_range, token_range
|
||||
)
|
||||
)
|
||||
msg = str()
|
||||
|
||||
def _parse_let(self, lines: list[str]) -> None:
|
||||
active_let: DocumentSymbol
|
||||
for row, line in enumerate(lines):
|
||||
for found in finditer(r"(\(\s*let\s+|\blet\(\s+)\((.*)\)", line):
|
||||
start = Position(row, found.start())
|
||||
end = find_end(start, lines)
|
||||
children: list[DocumentSymbol] = []
|
||||
active_let = DocumentSymbol(
|
||||
"let",
|
||||
SymbolKind.Namespace,
|
||||
Range(start, end),
|
||||
Range(start, end),
|
||||
children=children,
|
||||
)
|
||||
self.lets.append(active_let)
|
||||
|
||||
offset = len(found.group(1)) + 3
|
||||
for local_var in finditer(
|
||||
r"([a-zA-Z_][a-zA-Z0-9_]*|\([a-zA-Z_][a-zA-Z0-9_]*\s+.+\))",
|
||||
found.group(2),
|
||||
):
|
||||
if local_var.group(1).startswith("("):
|
||||
if m := fullmatch(
|
||||
r"\(([a-zA-Z_][a-zA-Z0-9_]*)\s+.+\)",
|
||||
local_var.group(1),
|
||||
):
|
||||
children.append(
|
||||
DocumentSymbol(
|
||||
m.group(1),
|
||||
SymbolKind.Variable,
|
||||
Range(
|
||||
Position(row, offset + local_var.start() + 1),
|
||||
Position(
|
||||
row,
|
||||
offset
|
||||
+ local_var.start()
|
||||
+ 1
|
||||
+ len(m.string),
|
||||
),
|
||||
),
|
||||
Range(
|
||||
Position(row, offset + local_var.start() + 1),
|
||||
Position(
|
||||
row,
|
||||
offset
|
||||
+ local_var.start()
|
||||
+ 1
|
||||
+ len(m.group(1)),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
else:
|
||||
assert isinstance(active_let.children, list)
|
||||
active_let.children.append(
|
||||
DocumentSymbol(
|
||||
local_var.group(1),
|
||||
SymbolKind.Variable,
|
||||
Range(
|
||||
Position(row, offset + local_var.start()),
|
||||
Position(row, offset + local_var.end()),
|
||||
),
|
||||
Range(
|
||||
Position(row, offset + local_var.start()),
|
||||
Position(row, offset + local_var.end()),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
def _parse_proc(self, lines: list[str], uri: str) -> None:
|
||||
for row, line in enumerate(lines):
|
||||
for found in finditer(
|
||||
r"(\(\s*procedure|\bprocedure\()(\s+)([a-zA-Z_][a-zA-Z0-9_]*)\((.*)\)",
|
||||
line,
|
||||
):
|
||||
start = Position(row, found.start())
|
||||
end = find_end(start, lines)
|
||||
if "@option" in found.group(4) and "@key" in found.group(4):
|
||||
self.publish_diagnostics(
|
||||
uri,
|
||||
[
|
||||
Diagnostic(
|
||||
Range(start, Position(row, len(line))),
|
||||
"`@key` and `@option` used in same definition",
|
||||
severity=DiagnosticSeverity.Error,
|
||||
)
|
||||
],
|
||||
)
|
||||
return
|
||||
|
||||
args: list[DocumentSymbol] = []
|
||||
kwargs: list[DocumentSymbol] = []
|
||||
rest: list[DocumentSymbol] = []
|
||||
params_start = found.end() - len(found.group(4))
|
||||
warning(found.group(4))
|
||||
|
||||
for part in finditer(
|
||||
rf"(@(option|key)(\s\(\w+\s+.+\))+|@rest \w+|\"[{''.join(dt.value for dt in SkillDataType)}]+\"|(\w+\s*))",
|
||||
found.group(4),
|
||||
):
|
||||
info(part.group(1))
|
||||
if part.group(1).startswith("@rest"):
|
||||
rest_var_name = part.group(1).split()[1]
|
||||
rest_var_range = Range(
|
||||
Position(
|
||||
row,
|
||||
params_start + part.end() - len(rest_var_name),
|
||||
),
|
||||
Position(row, params_start + part.end()),
|
||||
)
|
||||
rest.append(
|
||||
DocumentSymbol(
|
||||
rest_var_name,
|
||||
kind=SymbolKind.Variable,
|
||||
range=rest_var_range,
|
||||
selection_range=rest_var_range,
|
||||
)
|
||||
)
|
||||
elif part.group(1).startswith("@"):
|
||||
for kwarg in finditer(r"(\((\w+)\s+[^\)]+\))", part.group(1)):
|
||||
kwargs.append(
|
||||
DocumentSymbol(
|
||||
kwarg.group(2),
|
||||
kind=SymbolKind.Variable,
|
||||
range=Range(
|
||||
Position(
|
||||
row,
|
||||
params_start + part.start() + kwarg.start(),
|
||||
),
|
||||
Position(
|
||||
row,
|
||||
params_start + part.start() + kwarg.end(),
|
||||
),
|
||||
),
|
||||
selection_range=Range(
|
||||
Position(
|
||||
row,
|
||||
params_start + part.start() + kwarg.start(),
|
||||
),
|
||||
Position(
|
||||
row,
|
||||
params_start
|
||||
+ part.start()
|
||||
+ kwarg.start()
|
||||
+ len(kwarg.group(2)),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
elif fullmatch(
|
||||
rf'"[{"".join(dt.value for dt in SkillDataType)}]+"',
|
||||
part.group(1),
|
||||
):
|
||||
if not (
|
||||
len(args) + len(kwargs) + len(rest)
|
||||
== len(part.group(1)) - 2
|
||||
):
|
||||
self.publish_diagnostics(
|
||||
uri,
|
||||
[
|
||||
Diagnostic(
|
||||
Range(start, Position(row, len(line))),
|
||||
"type info length mismatches number of arguments",
|
||||
severity=DiagnosticSeverity.Error,
|
||||
)
|
||||
],
|
||||
)
|
||||
return
|
||||
for char, arg in zip(
|
||||
part.group(1)[1:-1], chain(args, rest, kwargs)
|
||||
):
|
||||
typ = SkillDataType(char)
|
||||
arg.detail = f"{typ.value}_"
|
||||
break
|
||||
else:
|
||||
for arg in finditer(r"(\w+)", part.group(1)):
|
||||
arg_range = Range(
|
||||
Position(
|
||||
row,
|
||||
params_start + part.start() + arg.start() - 1,
|
||||
),
|
||||
Position(
|
||||
row,
|
||||
params_start + part.start() + arg.end() - 1,
|
||||
),
|
||||
)
|
||||
args.append(
|
||||
DocumentSymbol(
|
||||
arg.group(1),
|
||||
kind=SymbolKind.Variable,
|
||||
range=arg_range,
|
||||
selection_range=arg_range,
|
||||
)
|
||||
)
|
||||
|
||||
self.procs.append(
|
||||
DocumentSymbol(
|
||||
found.group(3),
|
||||
kind=SymbolKind.Function,
|
||||
range=Range(start, end),
|
||||
selection_range=Range(start, Position(row, len(line))),
|
||||
children=args + rest + kwargs,
|
||||
)
|
||||
diags.append(
|
||||
Diagnostic(
|
||||
range,
|
||||
msg,
|
||||
severity=DiagnosticSeverity.Error,
|
||||
),
|
||||
)
|
||||
|
||||
def _hint_let(self) -> Generator[InlayHint, None, None]:
|
||||
for let in self.lets:
|
||||
if let.children:
|
||||
for child in let.children:
|
||||
yield InlayHint(child.selection_range.end, "|l")
|
||||
return diags
|
||||
|
||||
def _hint_proc(self) -> Generator[InlayHint, None, None]:
|
||||
for proc in self.procs:
|
||||
warning(proc)
|
||||
if proc.children:
|
||||
for child in proc.children:
|
||||
yield InlayHint(child.selection_range.end, "|l")
|
||||
def diagnose(self, uri: str) -> list[Diagnostic]:
|
||||
diags: list[Diagnostic] = []
|
||||
|
||||
if child.detail:
|
||||
yield InlayHint(child.selection_range.start, child.detail)
|
||||
diags.extend(self._diagnose_errors(uri))
|
||||
|
||||
def _hint_globals(self) -> Generator[InlayHint, None, None]:
|
||||
for glbl in self.globals:
|
||||
yield InlayHint(glbl.selection_range.end, "|g")
|
||||
|
||||
def hint(self, doc: TextDocument, area: Range) -> list[InlayHint]:
|
||||
hints: list[InlayHint] = []
|
||||
hints.extend(self._hint_proc())
|
||||
hints.extend(self._hint_let())
|
||||
hints.extend(self._hint_globals())
|
||||
|
||||
return hints
|
||||
return diags
|
||||
|
||||
|
||||
server = SkillLanguageServer("skillls", "v0.3")
|
||||
|
||||
|
||||
@server.feature(TEXT_DOCUMENT_DID_SAVE)
|
||||
# @server.feature(TEXT_DOCUMENT_DID_SAVE)
|
||||
@server.feature(TEXT_DOCUMENT_DID_OPEN)
|
||||
@server.feature(TEXT_DOCUMENT_DID_CHANGE)
|
||||
def on_open(ls: SkillLanguageServer, params: DidSaveTextDocumentParams) -> None:
|
||||
doc = server.workspace.get_text_document(params.text_document.uri)
|
||||
if not ls.diagnose(doc):
|
||||
ls.parse(doc)
|
||||
ls.lsp.send_request_async(WORKSPACE_INLAY_HINT_REFRESH)
|
||||
ls.parse(doc)
|
||||
|
||||
diags = ls.diagnose(doc.uri)
|
||||
ls.publish_diagnostics(doc.uri, diags)
|
||||
|
||||
|
||||
@server.feature(TEXT_DOCUMENT_INLAY_HINT)
|
||||
def inlay_hints(ls: SkillLanguageServer, params: InlayHintParams) -> list[InlayHint]:
|
||||
doc = server.workspace.get_text_document(params.text_document.uri)
|
||||
return ls.hint(doc, params.range)
|
||||
@server.feature(TEXT_DOCUMENT_DID_CHANGE)
|
||||
def on_change(ls: SkillLanguageServer, params: DidChangeTextDocumentParams) -> None:
|
||||
ls.update(params.text_document.uri, changes=params.content_changes)
|
||||
|
||||
diags = ls.diagnose(params.text_document.uri)
|
||||
ls.publish_diagnostics(params.text_document.uri, diags)
|
||||
|
||||
|
||||
@server.feature(TEXT_DOCUMENT_DOCUMENT_SYMBOL)
|
||||
@@ -475,7 +268,8 @@ def doc_symbols(
|
||||
ls: SkillLanguageServer,
|
||||
params: DocumentSymbolParams,
|
||||
) -> list[DocumentSymbol]:
|
||||
return ls.procs + ls.lets + ls.defs + ls.globals
|
||||
# return ls.procs + ls.lets + ls.defs + ls.globals
|
||||
return []
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in New Issue
Block a user