add new features and fix bugs

This commit is contained in:
Christoph Brandau
2026-06-18 17:31:51 +02:00
parent 41f331d4c4
commit 3ad3847045
14 changed files with 988 additions and 171 deletions
+37 -52
View File
@@ -1,7 +1,7 @@
import enum
from typing import List
from tclint.syntax_tree import Visitor, QuotedWord, Command, BareWord
from tclint.commands import get_commands
from tclint.commands.plugins import PluginManager
import attrs
from common.load_data import standard_items
import lsprotocol.types as lsp
@@ -33,6 +33,7 @@ class Token:
TOKEN_TYPES = [
"keyword",
"comment",
"variable",
"function",
"operator",
@@ -46,10 +47,15 @@ TOKEN_TYPES = [
class _Highlighter(Visitor):
def __init__(self, plugins, custom_functions: dict[str : list[lsp.CompletionItem]]):
self._commands = get_commands(plugins)
self._commands = PluginManager().get_commands(plugins)
self._tokens = []
self.custom_functions = custom_functions
def _append_token(self, position, length: int, tok_type: str, modifiers: List[TokenModifier] | None = None):
if position is None or length <= 0:
return
self._tokens.append((position, length, tok_type, modifiers or []))
def _get_token_info(self, node):
"""Hilfsmethode um Token-Informationen aus verschiedenen Node-Typen zu extrahieren."""
if not hasattr(node, "pos"):
@@ -81,8 +87,18 @@ class _Highlighter(Visitor):
if not word.contents:
return
line, col = word.contents_pos
self._tokens.append(((line - 1, col - 1), len(word.contents), "string", []))
pass
self._append_token((line - 1, col - 1), len(word.contents), "string", [])
def visit_comment(self, comment):
if not hasattr(comment, "pos") or comment.pos is None or comment.end_pos is None:
return
start_line, start_col = comment.pos
end_line, end_col = comment.end_pos
if start_line != end_line:
return
self._append_token((start_line - 1, start_col - 1), end_col - start_col, "comment", [])
def visit_bare_word(self, word: BareWord):
# Intentionally do not classify bare words as functions here.
@@ -100,49 +116,32 @@ class _Highlighter(Visitor):
in_standard = any(item.label == name for item in standard_items.nx_procs)
if in_custom or in_standard:
line, col = routine.contents_pos
self._tokens.append((((line - 1, col - 1), len(name), "function", [])))
self._append_token((line - 1, col - 1), len(name), "function", [])
if routine.contents in {"global", "variable"}:
line, col = routine.contents_pos
self._append_token((line - 1, col - 1), len(routine.contents), "keyword", [])
for arg in command.args:
token_info = self._get_token_info(arg)
if token_info:
(arg_line, arg_col), length = token_info
self._append_token((arg_line, arg_col), length, "variable", [])
if routine.contents == "puts":
line, col = routine.contents_pos
self._tokens.append(
(
(
(line - 1, col - 1),
len(routine.contents),
"function",
[TokenModifier.builtin],
)
)
)
self._append_token((line - 1, col - 1), len(routine.contents), "function", [TokenModifier.builtin])
if routine.contents == "set" and command.args:
first_arg = command.args[0]
token_info = self._get_token_info(first_arg)
if token_info:
(line, col), length = token_info
self._tokens.append(
(
(
(line, col),
length,
"variable",
[TokenModifier.declaration],
)
)
)
self._append_token((line, col), length, "variable", [TokenModifier.declaration])
if routine.contents == "proc" and command.args:
first_arg = command.args[0]
if hasattr(first_arg, "pos") and hasattr(first_arg, "value"):
line, col = first_arg.pos
self._tokens.append(
(
(
(line - 1, col - 1),
len(first_arg.value),
"function",
[TokenModifier.declaration],
)
)
)
self._append_token((line - 1, col - 1), len(first_arg.value), "function", [TokenModifier.declaration])
if len(command.args) >= 2:
param_list = command.args[1]
@@ -153,33 +152,19 @@ class _Highlighter(Visitor):
# Parameter kann einfaches Wort sein
if hasattr(child, "value") and child.value is not None:
line, col = child.pos
self._tokens.append(
(
(line - 1, col - 1),
len(child.value),
"parameter",
[TokenModifier.declaration],
)
)
self._append_token((line - 1, col - 1), len(child.value), "parameter", [TokenModifier.declaration])
# Parameter mit Default-Wert ist meist eine List (z.B. {arg default})
elif hasattr(child, "children") and len(child.children) >= 1:
name_node = child.children[0]
if hasattr(name_node, "value") and hasattr(name_node, "pos"):
line, col = name_node.pos
self._tokens.append(
(
(line - 1, col - 1),
len(name_node.value),
"parameter",
[TokenModifier.declaration],
)
)
self._append_token((line - 1, col - 1), len(name_node.value), "parameter", [TokenModifier.declaration])
if routine.contents == "namespace" and command.args:
first_arg = command.args[1]
if hasattr(first_arg, "pos") and first_arg.value is not None:
line, col = first_arg.pos
self._tokens.append((((line - 1, col - 1), len(first_arg.value), "class", [])))
self._append_token((line - 1, col - 1), len(first_arg.value), "class", [])
def tokens(self) -> list[Token]:
"""Encode tokens as described in