You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current architecture relies heavily on dynamic, on-the-fly Tree-sitter node traversal during LSP requests (such as Hover, DocumentSymbol, and the WorkspaceSymbol implementation).
FFI Overhead: Frequent cross-boundary calls (node.parent(), node.child(), node.kind()) accumulate substantial latency under the current_thread Tokio flavor.
Brittle Navigation & Features: Features like rename (highlighted in Feature request: rename messages from referenced site #129) are tightly coupled to strict AST parent-child grammar structures (message_name vs message_or_enum_type), making cross-reference features complex and error-prone to implement via direct AST iteration.
Redundant Parsing:WorkspaceSymbol currently rescans and reparses the entire workspace from scratch on every single user query (PR Add support for workspace symbols #95), which causes unnecessary CPU spikes and blocks the single-threaded async loop.
Proposed Solution
Transition from dynamic tree traversal to a Push-Based Document Meta-Model pattern. Instead of querying the AST on each user action, the server should map the AST into safe, native Rust structures once per file change using declarative Tree-sitter SCM queries.
Implement Name Resolution (FQN matching) to link references (like RPC arguments) to their definitions across different files. This completely decouples features like Rename and Go to Definition from raw AST node types.
Embed google/protobuf/descriptor.proto as a virtual built-in document to resolve standard options natively, while allowing overrides from local -I include flags.
Phase 4: Incremental Pipeline Optimization
Enable TextDocumentSyncKind::Incremental on the LSP side.
Update the model cache granularly using Tree-sitter's changed_ranges() diffing mechanism.
I would appreciate your feedback on this direction. If you find the approach acceptable, I can begin a deeper research and prepare reviewable PRs starting with Phase 1 (Meta-Model definition and Extractor logic).
Problem Statement
The current architecture relies heavily on dynamic, on-the-fly Tree-sitter node traversal during LSP requests (such as
Hover,DocumentSymbol, and theWorkspaceSymbolimplementation).protols/src/parser/mod.rs
Lines 32 to 36 in 5a532a1
This introduces several core limitations:
node.parent(),node.child(),node.kind()) accumulate substantial latency under thecurrent_threadTokio flavor.rename(highlighted in Feature request: rename messages from referenced site #129) are tightly coupled to strict AST parent-child grammar structures (message_namevsmessage_or_enum_type), making cross-reference features complex and error-prone to implement via direct AST iteration.WorkspaceSymbolcurrently rescans and reparses the entire workspace from scratch on every single user query (PR Add support for workspace symbols #95), which causes unnecessary CPU spikes and blocks the single-threaded async loop.Proposed Solution
Transition from dynamic tree traversal to a Push-Based Document Meta-Model pattern. Instead of querying the AST on each user action, the server should map the AST into safe, native Rust structures once per file change using declarative Tree-sitter SCM queries.
The Core Data Structure Concept
Strategic Implementation Plan
Phase 1: Internal Meta-Model & Single-Pass Extractor
METAMODEL_QUERY(SCM) to match all semantic entities (message,field, etc.) in a single execution pass.ProtoDocumentusing a context-stack approach to build parent-child relations natively in Rust without nested FFI calls.DocumentSymbolandHoverto pull directly from this Rust model.Phase 2: Global Memory Index (Instant Workspace Symbols)
workspace/symbolhandler.HashMap<Url, ProtoDocument>.workspace/symbolqueries a fast, pure-Rust substring match against the cached pool.Phase 3: Cross-File Resolution & Fallbacks (Fixes Feature request: rename messages from referenced site #129)
google/protobuf/descriptor.protoas a virtual built-in document to resolve standard options natively, while allowing overrides from local-Iinclude flags.Phase 4: Incremental Pipeline Optimization
TextDocumentSyncKind::Incrementalon the LSP side.changed_ranges()diffing mechanism.I would appreciate your feedback on this direction. If you find the approach acceptable, I can begin a deeper research and prepare reviewable PRs starting with Phase 1 (Meta-Model definition and Extractor logic).