feat(navigation): add symbol index and LSP navigation features
The changes introduce a Tcl symbol index powering LSP navigation features across the workspace. A navigation API exposes snapshots and update hooks, enabling goto-definition, references, and rename using the index. Background indexing now watches Tcl files and rebuilds the index to stay in sync. - Add Tcl symbol index and navigation snapshot API - Wire go-to-definition, references, and rename using the index - Watch Tcl files and refresh the index in the background
This commit is contained in:
@@ -15,6 +15,7 @@ from tclint.violations import Violation
|
||||
from tools import checks, parser
|
||||
from tools.completion_items import CompletionCollector
|
||||
from tools.formatter import NxFormatter as Formatter
|
||||
from tools.navigation import FileSymbolIndex, build_file_symbol_index
|
||||
from tools.proc_docs import build_proc_docs
|
||||
|
||||
|
||||
@@ -31,6 +32,7 @@ class TclLanguageServer(server.LanguageServer):
|
||||
self.poco_completion: dict = {}
|
||||
self.proc_signatures: dict = {}
|
||||
self.proc_docs: dict = {}
|
||||
self.navigation_indexes: dict[str, FileSymbolIndex] = {}
|
||||
# Cache: (uri, version) -> (tree, violations)
|
||||
self._ast_cache = {}
|
||||
self._parser_lock = threading.RLock()
|
||||
@@ -115,6 +117,11 @@ class TclLanguageServer(server.LanguageServer):
|
||||
with self._index_lock:
|
||||
return self.diagnostics.get(uri)
|
||||
|
||||
def navigation_snapshot(self) -> dict[str, FileSymbolIndex]:
|
||||
"""Return an immutable snapshot of the workspace symbol indexes."""
|
||||
with self._index_lock:
|
||||
return dict(self.navigation_indexes)
|
||||
|
||||
def _begin_index_update(self, filepath: str, version: int | None) -> int | None:
|
||||
with self._index_lock:
|
||||
indexed_version = self._index_versions.get(filepath)
|
||||
@@ -140,6 +147,7 @@ class TclLanguageServer(server.LanguageServer):
|
||||
self.poco_completion.pop(filepath, None)
|
||||
self.proc_signatures.pop(filepath, None)
|
||||
self.proc_docs.pop(filepath, None)
|
||||
self.navigation_indexes.pop(filepath, None)
|
||||
|
||||
def indexed_paths_under_uri(self, uri: str) -> list[pathlib.Path]:
|
||||
target = pathlib.Path(uris.to_fs_path(uri))
|
||||
@@ -147,6 +155,7 @@ class TclLanguageServer(server.LanguageServer):
|
||||
indexed_paths = set(self.poco_completion)
|
||||
indexed_paths.update(self.proc_signatures)
|
||||
indexed_paths.update(self.proc_docs)
|
||||
indexed_paths.update(self.navigation_indexes)
|
||||
indexed_paths.update(self._index_tokens)
|
||||
return [
|
||||
pathlib.Path(path)
|
||||
@@ -163,6 +172,7 @@ class TclLanguageServer(server.LanguageServer):
|
||||
self.poco_completion,
|
||||
self.proc_signatures,
|
||||
self.proc_docs,
|
||||
self.navigation_indexes,
|
||||
self._index_tokens,
|
||||
self._index_versions,
|
||||
):
|
||||
@@ -212,6 +222,9 @@ class TclLanguageServer(server.LanguageServer):
|
||||
)
|
||||
tree.accept(collector, recurse=True)
|
||||
docs = build_proc_docs(tree, document.source)
|
||||
navigation_index = build_file_symbol_index(
|
||||
filepath, document.uri, tree
|
||||
)
|
||||
except Exception as e:
|
||||
logging.debug(f"Error parsing {filepath}: {e}")
|
||||
self._discard_index_update(filepath, token)
|
||||
@@ -227,6 +240,7 @@ class TclLanguageServer(server.LanguageServer):
|
||||
self.poco_completion[filepath] = list(collector.custom_functions)
|
||||
self.proc_signatures[filepath] = dict(collector.proc_signatures)
|
||||
self.proc_docs[filepath] = docs
|
||||
self.navigation_indexes[filepath] = navigation_index
|
||||
return True
|
||||
|
||||
def format(
|
||||
|
||||
Reference in New Issue
Block a user