add functions to completion

This commit is contained in:
Christoph Brandau
2025-08-06 15:26:53 +02:00
parent f5c61267e3
commit 6bded783a1
5 changed files with 86 additions and 78 deletions
+42 -8
View File
@@ -1,5 +1,6 @@
from tclint.syntax_tree import Visitor, Command, BareWord, List
import lsprotocol.types as lsp
from common.load_data import standard_items
class CompletionItems:
@@ -38,14 +39,18 @@ class _Completion(Visitor):
if routine.contents == "proc" and command.args:
first_arg = command.args[0]
if hasattr(first_arg, "value") and not any(
item.label == first_arg.value for item in self._custom_functions
):
self._custom_functions.append(
lsp.CompletionItem(
label=first_arg.value, kind=lsp.CompletionItemKind.Function
)
)
if not first_arg.value:
return
if any(item.label == first_arg.value for item in standard_items.nx_procs):
return
try:
self._custom_functions.remove(first_arg.value)
except ValueError:
pass
self._custom_functions.append(lsp.CompletionItem(label=first_arg.value, kind=lsp.CompletionItemKind.Function))
if len(command.args) < 2:
return
@@ -65,4 +70,33 @@ class _Completion(Visitor):
self._proc_signatures[first_arg.value] = param_names
def remove_existing_items(items: list[lsp.CompletionItem], store: dict) -> None:
"""
Entfernt alle CompletionItems aus dem store, deren label in der items-Liste vorkommt.
Änderungen erfolgen in-place.
"""
labels_to_remove = {item.label for item in items}
for key in list(store.keys()):
filtered = [ci for ci in store[key] if ci.label not in labels_to_remove]
if filtered:
store[key] = filtered
else:
del store[key]
def remove_shared_keys(nested_dict: dict[str, dict[str, list]], flat_dict: dict[str, list]) -> None:
"""
Entfernt alle Keys aus nested_dict[file][func], wenn func auch in flat_dict vorhanden ist.
Änderungen erfolgen in-place.
"""
for file_path, func_dict in list(nested_dict.items()):
for func_name in list(func_dict.keys()):
if func_name in flat_dict:
del nested_dict[file_path][func_name]
if not nested_dict[file_path]:
del nested_dict[file_path]
completion = _Completion()
+15 -22
View File
@@ -5,6 +5,7 @@ from tclint.commands import get_commands
import attrs
from common.load_data import standard_items
from tools.completion_items import completion
import lsprotocol.types as lsp
class TokenModifier(enum.IntFlag):
@@ -40,10 +41,10 @@ TOKEN_TYPES = [
class _Highlighter(Visitor):
def __init__(self, plugins, log_to_output):
def __init__(self, plugins, custom_functions: dict[str : list[lsp.CompletionItem]]):
self._commands = get_commands(plugins)
self._tokens = []
self.log_to_output = log_to_output
self.custom_functions = custom_functions
def _get_token_info(self, node):
"""Hilfsmethode um Token-Informationen aus verschiedenen Node-Typen zu extrahieren."""
@@ -58,11 +59,7 @@ class _Highlighter(Visitor):
# CompoundBareWord: versuche erstes Segment
if hasattr(node, "children") and node.children:
first_segment = node.children[0]
if (
hasattr(first_segment, "value")
and first_segment.value is not None
and hasattr(first_segment, "pos")
):
if hasattr(first_segment, "value") and first_segment.value is not None and hasattr(first_segment, "pos"):
line, col = first_segment.pos
return (line - 1, col - 1), len(first_segment.value)
@@ -84,13 +81,15 @@ class _Highlighter(Visitor):
pass
def visit_bare_word(self, word: BareWord):
if any(item.label == word.value for item in standard_items.nx_procs) or any(
item.label == word.value for item in completion.custom_functions
):
name = word.value
in_standard = any(item.label == name for item in standard_items.nx_procs)
in_custom = any(item.label == name for items in self.custom_functions.values() for item in items)
if in_standard or in_custom:
line, col = word.pos
self._tokens.append(
(((line - 1, col - 1), len(word.value), "function", []))
)
self._tokens.append((((line - 1, col - 1), len(name), "function", [])))
def visit_command(self, command: Command):
routine = command.routine
@@ -158,9 +157,7 @@ class _Highlighter(Visitor):
# 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"
):
if hasattr(name_node, "value") and hasattr(name_node, "pos"):
line, col = name_node.pos
self._tokens.append(
(
@@ -174,9 +171,7 @@ class _Highlighter(Visitor):
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._tokens.append((((line - 1, col - 1), len(first_arg.value), "class", [])))
def tokens(self) -> list[Token]:
"""Encode tokens as described in
@@ -185,9 +180,7 @@ class _Highlighter(Visitor):
tokens = []
last_line = 0
last_col = 0
for (line, col), length, tok_type, tok_modifier in sorted(
self._tokens, key=lambda x: x[0]
):
for (line, col), length, tok_type, tok_modifier in sorted(self._tokens, key=lambda x: x[0]):
line_delta = line - last_line
col_delta = col
if line == last_line: