optimze Server

This commit is contained in:
Christoph Brandau
2025-08-12 07:48:05 +02:00
parent c0635e48ea
commit 7263b6f530
2 changed files with 75 additions and 33 deletions
+42 -28
View File
@@ -9,6 +9,8 @@ import os
import pathlib import pathlib
import re import re
import sys import sys
import threading
from typing import Any, Optional from typing import Any, Optional
import operator import operator
from functools import reduce from functools import reduce
@@ -151,7 +153,9 @@ def inlay_hints(params: lsp.InlayHintParams):
if not GLOBAL_SETTINGS.get("inlayHint", False): if not GLOBAL_SETTINGS.get("inlayHint", False):
return [] return []
document = LSP_SERVER.workspace.get_text_document(params.text_document.uri) document = LSP_SERVER.workspace.get_text_document(params.text_document.uri)
tree = LSP_SERVER.parser.parse(document.source)
# Reuse cached AST
tree = LSP_SERVER.get_tree(document)
# Merge proc signatures across files and traverse once # Merge proc signatures across files and traverse once
merged_signatures = {} merged_signatures = {}
@@ -177,7 +181,8 @@ def semantic_tokens(params: lsp.SemanticTokensParams):
plugins = [] plugins = []
hl = _Highlighter(plugins, LSP_SERVER.poco_completion) hl = _Highlighter(plugins, LSP_SERVER.poco_completion)
tree = LSP_SERVER.parser.parse(document.source) # Reuse cached AST
tree = LSP_SERVER.get_tree(document)
tree.accept(hl, recurse=True) tree.accept(hl, recurse=True)
tokens = hl.tokens() tokens = hl.tokens()
@@ -407,33 +412,42 @@ def initialize(params: lsp.InitializeParams) -> lsp.InitializeResult:
@LSP_SERVER.feature(lsp.INITIALIZED) @LSP_SERVER.feature(lsp.INITIALIZED)
def initialized(params: lsp.InitializedParams): def initialized(_params: lsp.InitializedParams):
root = LSP_SERVER.workspace.root_path """Kick off background indexing to avoid blocking initialization."""
psc_files = get_all_psc_files(pathlib.Path(root))
for psc_file in psc_files:
poco_files = read_psc_file(psc_file)
for sourced_layer in poco_files:
completion.reset()
try:
file_root = pathlib.Path(root).joinpath(sourced_layer.subfolder if sourced_layer.subfolder else "")
for tcl_file in sourced_layer.files:
filepath = pathlib.Path(file_root).joinpath(f"{tcl_file}.tcl")
if not filepath.exists():
continue
completion.reset()
document = LSP_SERVER.workspace.get_text_document(filepath.as_uri()) # filepath.read_text(encoding="utf-8")
tree = LSP_SERVER.parser.parse(document.source)
tree.accept(completion, recurse=True)
remove_existing_items(completion.custom_functions, LSP_SERVER.poco_completion)
LSP_SERVER.poco_completion[str(filepath)] = completion.custom_functions
remove_shared_keys(LSP_SERVER.proc_signatures, completion.proc_signatures)
LSP_SERVER.proc_signatures[str(filepath)] = completion.proc_signatures
# Build proc docs for this file
from tools.proc_docs import build_proc_docs
LSP_SERVER.proc_docs[str(filepath)] = build_proc_docs(tree, document.source) def index_workspace():
except Exception as e: try:
log_to_output(f"Fehler beim Parsen von {filepath}: {e}") root = LSP_SERVER.workspace.root_path
log_to_output("Background indexing started...")
psc_files = get_all_psc_files(pathlib.Path(root))
for psc_file in psc_files:
poco_files = read_psc_file(psc_file)
for sourced_layer in poco_files:
completion.reset()
try:
file_root = pathlib.Path(root).joinpath(sourced_layer.subfolder if sourced_layer.subfolder else "")
for tcl_file in sourced_layer.files:
filepath = pathlib.Path(file_root).joinpath(f"{tcl_file}.tcl")
if not filepath.exists():
continue
completion.reset()
document = LSP_SERVER.workspace.get_text_document(filepath.as_uri())
tree = LSP_SERVER.parser.parse(document.source)
tree.accept(completion, recurse=True)
remove_existing_items(completion.custom_functions, LSP_SERVER.poco_completion)
LSP_SERVER.poco_completion[str(filepath)] = completion.custom_functions
remove_shared_keys(LSP_SERVER.proc_signatures, completion.proc_signatures)
LSP_SERVER.proc_signatures[str(filepath)] = completion.proc_signatures
from tools.proc_docs import build_proc_docs
LSP_SERVER.proc_docs[str(filepath)] = build_proc_docs(tree, document.source)
except Exception as e:
log_to_output(f"Fehler beim Parsen von {filepath}: {e}")
log_to_output("Background indexing completed.")
except Exception as e:
log_to_output(f"Background indexing failed: {e}")
threading.Thread(target=index_workspace, name="nxps-indexer", daemon=True).start()
@LSP_SERVER.feature(lsp.EXIT) @LSP_SERVER.feature(lsp.EXIT)
+33 -5
View File
@@ -26,6 +26,37 @@ class TclLanguageServer(server.LanguageServer):
self.poco_completion: dict = {} self.poco_completion: dict = {}
self.proc_signatures: dict = {} self.proc_signatures: dict = {}
self.proc_docs: dict = {} self.proc_docs: dict = {}
# Cache: (uri, version) -> (tree, violations)
self._ast_cache = {}
def get_tree(self, document: TextDocument):
key = (document.uri, document.version)
cached = self._ast_cache.get(key)
if cached:
return cached[0]
# Parse and cache
self.parser.violations = []
tree = self.parser.parse(document.source)
violations = list(self.parser.violations)
self._ast_cache[key] = (tree, violations)
return tree
def get_tree_and_violations(self, document: TextDocument):
key = (document.uri, document.version)
cached = self._ast_cache.get(key)
if cached:
return cached
# Parse and cache
self.parser.violations = []
tree = self.parser.parse(document.source)
violations = list(self.parser.violations)
self._ast_cache[key] = (tree, violations)
return tree, violations
def clear_cache_for_uri(self, uri: str):
to_delete = [k for k in self._ast_cache.keys() if k[0] == uri]
for k in to_delete:
del self._ast_cache[k]
def update_poco_completion_for_file(self, document: TextDocument): def update_poco_completion_for_file(self, document: TextDocument):
"""Update poco_completion for a specific file when it changes""" """Update poco_completion for a specific file when it changes"""
@@ -42,7 +73,7 @@ class TclLanguageServer(server.LanguageServer):
# Parse and extract new completion items # Parse and extract new completion items
completion.reset() completion.reset()
try: try:
tree = self.parser.parse(document.source) tree = self.get_tree(document)
tree.accept(completion, recurse=True) tree.accept(completion, recurse=True)
remove_existing_items(completion.custom_functions, self.poco_completion) remove_existing_items(completion.custom_functions, self.poco_completion)
self.poco_completion[filepath] = completion.custom_functions self.poco_completion[filepath] = completion.custom_functions
@@ -81,10 +112,7 @@ class TclLanguageServer(server.LanguageServer):
self, self,
document: TextDocument, document: TextDocument,
) -> List[Violation]: ) -> List[Violation]:
violations = [] tree, violations = self.get_tree_and_violations(document)
self.parser.violations = []
tree = self.parser.parse(document.source)
violations += self.parser.violations
for checker in checks.get_checkers(): for checker in checks.get_checkers():
violations += checker.check(document.source, tree) violations += checker.check(document.source, tree)
return violations return violations