Class: Rigor::LanguageServer::BufferTable
- Inherits:
-
Object
- Object
- Rigor::LanguageServer::BufferTable
- Defined in:
- lib/rigor/language_server/buffer_table.rb
Overview
Per-session virtual file table. The LSP server maintains the canonical view of every open buffer here; analysis (slice 4+) reads from this table instead of disk so in-flight edits are reflected immediately.
Keyed by DocumentUri (LSP file://... URIs). Sync is INCREMENTAL (LSP
TextDocumentSyncKind::Incremental = 2): a didChange carries range edits which #apply_changes splices
into the held text through IncrementalSync. The full-text form (#change, and a contentChanges entry
with no range) stays supported — it is still legal under incremental sync and is what didOpen and a
client-side resync send.
Defined Under Namespace
Classes: Entry
Instance Method Summary collapse
- #[](uri) ⇒ Object
-
#apply_changes(uri:, changes:, version:) ⇒ Boolean
Applies a
textDocument/didChangepayload under INCREMENTAL sync. -
#change(uri:, bytes:, version:) ⇒ Object
Records a full-text
textDocument/didChange. -
#close(uri:) ⇒ Object
Records a
textDocument/didCloseevent. -
#desynchronization_reason(uri) ⇒ String?
Why
uriis desynchronised, for the log line; nil when it is in sync. -
#desynchronized?(uri) ⇒ Boolean
True when the last
didChangeforuricould not be applied, so the held text no longer matches the editor's. -
#dirty?(uri) ⇒ Boolean
True when
urihas unsaved changes. -
#initialize ⇒ BufferTable
constructor
A new instance of BufferTable.
-
#open(uri:, bytes:, version:) ⇒ Object
Records a
textDocument/didOpenevent. - #open?(uri) ⇒ Boolean
-
#save(uri:) ⇒ Object
Records a
textDocument/didSave. - #size ⇒ Object
- #uris ⇒ Object
Constructor Details
#initialize ⇒ BufferTable
Returns a new instance of BufferTable.
21 22 23 24 25 |
# File 'lib/rigor/language_server/buffer_table.rb', line 21 def initialize @entries = {} @desynchronized = {} @dirty = {} end |
Instance Method Details
#[](uri) ⇒ Object
101 102 103 |
# File 'lib/rigor/language_server/buffer_table.rb', line 101 def [](uri) @entries[uri] end |
#apply_changes(uri:, changes:, version:) ⇒ Boolean
Applies a textDocument/didChange payload under INCREMENTAL sync. Each entry of changes is applied
in order against the result of the previous one, per the LSP contract.
On success the entry is replaced with the spliced text at the new version. On failure — a malformed
change, or a range edit for a URI with no held buffer — the held text is left EXACTLY as it was and the
URI is marked desynchronised: the server's view and the editor's view have diverged, and every position
computed from the stale text would be wrong. Consumers check #desynchronized? and decline to answer
rather than answering wrongly; the mark clears on the next didOpen or full-text change.
55 56 57 58 59 60 61 62 63 64 |
# File 'lib/rigor/language_server/buffer_table.rb', line 55 def apply_changes(uri:, changes:, version:) text = IncrementalSync.apply_all(@entries[uri]&.bytes, changes) @desynchronized.delete(uri) @dirty[uri] = true @entries[uri] = Entry.new(uri: uri, bytes: text, version: version) true rescue IncrementalSync::UnappliableChange => e @desynchronized[uri] = e. false end |
#change(uri:, bytes:, version:) ⇒ Object
Records a full-text textDocument/didChange. The full new buffer text replaces the entry. If the
client sends a didChange for a URI that was never opened (spec violation), the entry is still
created — defensive.
39 40 41 42 43 |
# File 'lib/rigor/language_server/buffer_table.rb', line 39 def change(uri:, bytes:, version:) @desynchronized.delete(uri) @dirty[uri] = true @entries[uri] = Entry.new(uri: uri, bytes: bytes, version: version) end |
#close(uri:) ⇒ Object
Records a textDocument/didClose event. The entry is removed. Subsequent reads via #[] return nil.
78 79 80 81 82 |
# File 'lib/rigor/language_server/buffer_table.rb', line 78 def close(uri:) @desynchronized.delete(uri) @dirty.delete(uri) @entries.delete(uri) end |
#desynchronization_reason(uri) ⇒ String?
Returns why uri is desynchronised, for the log line; nil when it is in sync.
73 74 75 |
# File 'lib/rigor/language_server/buffer_table.rb', line 73 def desynchronization_reason(uri) @desynchronized[uri] end |
#desynchronized?(uri) ⇒ Boolean
Returns true when the last didChange for uri could not be applied, so the held text no
longer matches the editor's.
68 69 70 |
# File 'lib/rigor/language_server/buffer_table.rb', line 68 def desynchronized?(uri) @desynchronized.key?(uri) end |
#dirty?(uri) ⇒ Boolean
Returns true when uri has unsaved changes. A buffer that is dirty may only be published
from an analysis that bound ITS bytes — see the publish-set invariant in
docs/design/20260517-language-server.md.
97 98 99 |
# File 'lib/rigor/language_server/buffer_table.rb', line 97 def dirty?(uri) @dirty.key?(uri) end |
#open(uri:, bytes:, version:) ⇒ Object
Records a textDocument/didOpen event. Replaces any existing entry (LSP clients may re-open a
previously closed URI; the new version is authoritative) and clears any desynchronised mark — the
payload carries the client's full text, so the two views agree again.
30 31 32 33 34 |
# File 'lib/rigor/language_server/buffer_table.rb', line 30 def open(uri:, bytes:, version:) @desynchronized.delete(uri) @dirty.delete(uri) @entries[uri] = Entry.new(uri: uri, bytes: bytes, version: version) end |
#open?(uri) ⇒ Boolean
105 106 107 |
# File 'lib/rigor/language_server/buffer_table.rb', line 105 def open?(uri) @entries.key?(uri) end |
#save(uri:) ⇒ Object
Records a textDocument/didSave. The client has written the buffer, so the held text and the file on
disk agree again and the URI stops being dirty.
Dirtiness is the PROTOCOL's notion — "the client told us it changed and has not told us it saved" — not a byte comparison against disk. A comparison would look stricter and be weaker: it races with the editor's own write, and the server's truth is what the client notified.
90 91 92 |
# File 'lib/rigor/language_server/buffer_table.rb', line 90 def save(uri:) @dirty.delete(uri) end |
#size ⇒ Object
109 110 111 |
# File 'lib/rigor/language_server/buffer_table.rb', line 109 def size @entries.size end |
#uris ⇒ Object
113 114 115 |
# File 'lib/rigor/language_server/buffer_table.rb', line 113 def uris @entries.keys end |