fix(vfs): stabilize file identity ingress#129
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This change moves file identity to the VFS ingress boundary and makes diagnostics publish against explicit document targets. Before this, the same physical file could enter through loader paths, LSP URIs, watcher paths, symlinks, different Windows spellings, or external diagnostic paths and keep inconsistent
FileId, root ownership, open-buffer, or diagnostic state. That made behavior depend on ingress order and path spelling.Previous Shape
flowchart TD Loader["Loader path"] --> VFS["VFS path map"] LSP["LSP URI path"] --> VFS Watcher["Watcher path"] --> VFS External["External diagnostics path"] --> VFS VFS --> FileId["FileId by first path spelling"] FileId --> FileSet["FileSet root classification"] FileId --> MemDocs["MemDocs by FileId"] FileId --> Diagnostics["Diagnostics cache by FileId"] MemDocs --> Version["Document version from current buffer"] VFS --> Uri["Primary VFS URI"] Version --> Publish["publishDiagnostics"] Uri --> PublishNew Shape
flowchart TD Loader["Loader path"] --> Identity["VFS identity service"] LSP["LSP URI path"] --> Identity Watcher["Watcher path"] --> Identity Save["Save/change/delete path"] --> Identity External["External diagnostics path"] --> Identity Identity --> FileId["Stable canonical FileId"] Identity --> Aliases["Alias evidence set"] FileId --> FileSet["Identity-aware file-set partition"] FileId --> MemDocs["One canonical analysis buffer"] Aliases --> OpenDocs["Open URI versions"] OpenDocs --> Targets["DiagnosticPublishTarget: FileId + URI + version"] Targets --> Cache["Diagnostics cache by FileId + URI"] Cache --> Publish["publishDiagnostics per open URI"]Flow Difference
sequenceDiagram participant Client participant VFS participant MemDocs participant Diagnostics Client->>VFS: didOpen(alias URI) VFS->>VFS: register alias evidence and resolve canonical FileId VFS->>MemDocs: map alias URI to canonical FileId MemDocs->>MemDocs: keep URI-local version MemDocs->>Diagnostics: refresh diagnostic targets for FileId Diagnostics->>Client: publish to every attached open URI target Client->>MemDocs: didClose(alias URI) MemDocs->>Diagnostics: refresh diagnostic targets for FileId Diagnostics->>Client: clear stale alias diagnosticsWhat Changed
FileIds into a stable owner and redirecting aliases instead of silently preserving split identity.MemDocsto keep one canonical analysis buffer perFileIdwhile tracking every open URI spelling with its own LSP version.didChangeatomic: invalid LSP ranges no longer advance URI versions or partially mutate document text.DiagnosticPublishTargetvalues so push diagnostics always use a matching(FileId, URI, version)tuple.(FileId, URI)and refreshes targets on both open and close, so alias documents receive diagnostics and stale alias diagnostics are cleared promptly.Alias Buffer Policy
This keeps the current one-analysis-buffer-per-physical-file model explicit. If the same physical file is opened through multiple URI spellings with matching text, those URIs share the canonical analysis buffer and keep URI-local versions. If an alias opens with divergent text, the URI remains tracked for close/version bookkeeping but is detached from the canonical analysis buffer. That avoids silently mixing edits from incompatible URI-local text states.
Benefits
FileIds for the same physical file across symlink, junction, case, verbatim path, and open-before-load scenarios.didChangeranges from creating version/text skew.Scope
This change closes the file-ingress, open-document, diagnostics-target, Qihe diagnostics freshness, and workspace reload transaction issues in this area. It does not replace the whole task runtime or external-process controller. Full external-process cancellation, temp workspace ownership, and log backpressure remain separate runtime/Qihe lifecycle work.
Validation
cargo test -p vfscargo test -p project-modelcargo test -p vizslacargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningsrustup run nightly cargo test --workspacegit diff --check