refactor(lsp): cache analysis results and debounce diagnostics
build_and_puplish.yml / build_and_publish (release) Successful in 29s
build_and_puplish.yml / build_and_publish (release) Successful in 29s
This change adds cached and incremental analysis for the LSP server to improve responsiveness. The client now debounces diagnostic updates to avoid excessive recomputation. The server introduces per-document line caches and various caches for completions, inlay hints, and metadata to support faster, incremental updates. - Debounce diagnostics on text changes to reduce noise. - Add caches for completions, inlay hints, and metadata. - Introduce incremental analysis with per-document line caches.
This commit is contained in:
@@ -1,17 +1,17 @@
|
||||
import enum
|
||||
from typing import List
|
||||
from tclint.syntax_tree import Visitor, QuotedWord, Command, BareWord
|
||||
from tclint.commands.plugins import PluginManager
|
||||
|
||||
import attrs
|
||||
from common.load_data import standard_items
|
||||
import lsprotocol.types as lsp
|
||||
|
||||
from tclint.commands.plugins import PluginManager
|
||||
from tclint.syntax_tree import BareWord, Command, QuotedWord, Visitor
|
||||
|
||||
# Constructing a PluginManager scans entry points, and get_commands() rebuilds
|
||||
# the builtin command set on every call. Semantic tokens are requested often, so
|
||||
# cache the manager and the resolved commands per plugin set.
|
||||
_PLUGIN_MANAGER = None
|
||||
_COMMANDS_CACHE = {}
|
||||
_STANDARD_PROC_NAMES = frozenset(item.label for item in standard_items.nx_procs)
|
||||
|
||||
|
||||
def _load_commands(plugins):
|
||||
@@ -60,13 +60,23 @@ TOKEN_TYPES = [
|
||||
"string",
|
||||
"parameter",
|
||||
]
|
||||
TOKEN_TYPE_INDEX = {}
|
||||
for _token_index, _token_name in enumerate(TOKEN_TYPES):
|
||||
TOKEN_TYPE_INDEX.setdefault(_token_name, _token_index)
|
||||
|
||||
|
||||
class _Highlighter(Visitor):
|
||||
def __init__(self, plugins, custom_functions: dict[str : list[lsp.CompletionItem]]):
|
||||
def __init__(self, plugins, custom_functions):
|
||||
self._commands = _load_commands(plugins)
|
||||
self._tokens = []
|
||||
self.custom_functions = custom_functions
|
||||
if isinstance(custom_functions, dict):
|
||||
self._custom_function_names = frozenset(
|
||||
item.label
|
||||
for items in custom_functions.values()
|
||||
for item in items
|
||||
)
|
||||
else:
|
||||
self._custom_function_names = frozenset(custom_functions)
|
||||
|
||||
def _append_token(self, position, length: int, tok_type: str, modifiers: List[TokenModifier] | None = None):
|
||||
if position is None or length <= 0:
|
||||
@@ -129,9 +139,7 @@ class _Highlighter(Visitor):
|
||||
# Highlight functions (custom or standard) when used as the routine
|
||||
name = getattr(routine, "contents", None)
|
||||
if name:
|
||||
in_custom = any(item.label == name for items in self.custom_functions.values() for item in items)
|
||||
in_standard = any(item.label == name for item in standard_items.nx_procs)
|
||||
if in_custom or in_standard:
|
||||
if name in self._custom_function_names or name in _STANDARD_PROC_NAMES:
|
||||
line, col = routine.contents_pos
|
||||
self._append_token((line - 1, col - 1), len(name), "function", [])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user