feat(lsp): add incremental indexing and file ops support

Adds a thread-safe incremental index and snapshot API for LSP.
Introduces cache invalidation and file operation hooks for delete
and rename. This keeps indices in sync with disk changes.
Supports reindexing TCL files from disk when needed.

- Adds workspace file change handlers to sync indices on delete/rename.
- Introduces locking and snapshot helpers to safely access shared state.
- Refactors to invalidate caches on edits and reindex TCL files.
This commit is contained in:
Christoph Brandau
2026-08-17 08:45:09 +02:00
parent a39aee1b9d
commit f5bd79f067
5 changed files with 555 additions and 151 deletions
+1 -37
View File
@@ -18,7 +18,7 @@ class CompletionItems:
self._custom_functions.append(value)
class _Completion(Visitor):
class CompletionCollector(Visitor):
def __init__(self):
super().__init__()
self._custom_functions: list[lsp.CompletionItem] = []
@@ -32,10 +32,6 @@ class _Completion(Visitor):
def proc_signatures(self):
return self._proc_signatures
def reset(self):
self._custom_functions = []
self._proc_signatures = {}
def _append_unique(self, item: lsp.CompletionItem):
# Avoid duplicate labels within the same file scan
if not any(ci.label == item.label for ci in self._custom_functions):
@@ -90,35 +86,3 @@ class _Completion(Visitor):
clean_name = base_name[2:] # remove leading '::' for completion display
if clean_name not in BUILTIN_VAR_LABELS:
self._append_unique(lsp.CompletionItem(label=clean_name, kind=lsp.CompletionItemKind.Variable))
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()