@singapore-editor/lsp-plugin 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -0
- package/dist/bufferSync.d.ts +12 -0
- package/dist/bufferSync.d.ts.map +1 -0
- package/dist/bufferSync.js +35 -0
- package/dist/bufferSync.js.map +1 -0
- package/dist/codeActions.d.ts +83 -0
- package/dist/codeActions.d.ts.map +1 -0
- package/dist/codeActions.js +294 -0
- package/dist/codeActions.js.map +1 -0
- package/dist/colorAlpha.d.ts +4 -0
- package/dist/colorAlpha.d.ts.map +1 -0
- package/dist/colorAlpha.js +28 -0
- package/dist/colorAlpha.js.map +1 -0
- package/dist/completion.d.ts +124 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +609 -0
- package/dist/completion.js.map +1 -0
- package/dist/completionCommit.d.ts +19 -0
- package/dist/completionCommit.d.ts.map +1 -0
- package/dist/completionCommit.js +57 -0
- package/dist/completionCommit.js.map +1 -0
- package/dist/completionController.d.ts +89 -0
- package/dist/completionController.d.ts.map +1 -0
- package/dist/completionController.js +376 -0
- package/dist/completionController.js.map +1 -0
- package/dist/completionProviders.d.ts +50 -0
- package/dist/completionProviders.d.ts.map +1 -0
- package/dist/completionProviders.js +64 -0
- package/dist/completionProviders.js.map +1 -0
- package/dist/connectionContext.d.ts +7 -0
- package/dist/connectionContext.d.ts.map +1 -0
- package/dist/definitionLinkController.d.ts +54 -0
- package/dist/definitionLinkController.d.ts.map +1 -0
- package/dist/definitionLinkController.js +221 -0
- package/dist/definitionLinkController.js.map +1 -0
- package/dist/definitionNavigation.d.ts +76 -0
- package/dist/definitionNavigation.d.ts.map +1 -0
- package/dist/definitionNavigation.js +143 -0
- package/dist/definitionNavigation.js.map +1 -0
- package/dist/diagnosticNotes.d.ts +7 -0
- package/dist/diagnosticNotes.d.ts.map +1 -0
- package/dist/diagnosticNotes.js +37 -0
- package/dist/diagnosticNotes.js.map +1 -0
- package/dist/diagnosticProjection.d.ts +31 -0
- package/dist/diagnosticProjection.d.ts.map +1 -0
- package/dist/diagnosticProjection.js +79 -0
- package/dist/diagnosticProjection.js.map +1 -0
- package/dist/diagnostics.d.ts +16 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +94 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/diagnosticsPresenter.d.ts +64 -0
- package/dist/diagnosticsPresenter.d.ts.map +1 -0
- package/dist/diagnosticsPresenter.js +305 -0
- package/dist/diagnosticsPresenter.js.map +1 -0
- package/dist/document.d.ts +69 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +190 -0
- package/dist/document.js.map +1 -0
- package/dist/documentHighlightController.d.ts +34 -0
- package/dist/documentHighlightController.d.ts.map +1 -0
- package/dist/documentHighlightController.js +101 -0
- package/dist/documentHighlightController.js.map +1 -0
- package/dist/documentSnapshot.d.ts +9 -0
- package/dist/documentSnapshot.d.ts.map +1 -0
- package/dist/documentSnapshot.js +31 -0
- package/dist/documentSnapshot.js.map +1 -0
- package/dist/documentSync.d.ts +53 -0
- package/dist/documentSync.d.ts.map +1 -0
- package/dist/documentSync.js +334 -0
- package/dist/documentSync.js.map +1 -0
- package/dist/documentSyncController.d.ts +26 -0
- package/dist/documentSyncController.d.ts.map +1 -0
- package/dist/documentSyncController.js +24 -0
- package/dist/documentSyncController.js.map +1 -0
- package/dist/formatOnType.d.ts +43 -0
- package/dist/formatOnType.d.ts.map +1 -0
- package/dist/formatOnType.js +198 -0
- package/dist/formatOnType.js.map +1 -0
- package/dist/formatting.d.ts +18 -0
- package/dist/formatting.d.ts.map +1 -0
- package/dist/formatting.js +52 -0
- package/dist/formatting.js.map +1 -0
- package/dist/fuzzyMatch.d.ts +22 -0
- package/dist/fuzzyMatch.d.ts.map +1 -0
- package/dist/fuzzyMatch.js +216 -0
- package/dist/fuzzyMatch.js.map +1 -0
- package/dist/hoverParticipant.d.ts +24 -0
- package/dist/hoverParticipant.d.ts.map +1 -0
- package/dist/hoverParticipant.js +156 -0
- package/dist/hoverParticipant.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/keyCommands.d.ts +19 -0
- package/dist/keyCommands.d.ts.map +1 -0
- package/dist/keyCommands.js +21 -0
- package/dist/keyCommands.js.map +1 -0
- package/dist/lane.d.ts +28 -0
- package/dist/lane.d.ts.map +1 -0
- package/dist/lane.js +138 -0
- package/dist/lane.js.map +1 -0
- package/dist/lspConnection.d.ts +94 -0
- package/dist/lspConnection.d.ts.map +1 -0
- package/dist/lspConnection.js +195 -0
- package/dist/lspConnection.js.map +1 -0
- package/dist/lspConnectionPool.d.ts +34 -0
- package/dist/lspConnectionPool.d.ts.map +1 -0
- package/dist/lspConnectionPool.js +255 -0
- package/dist/lspConnectionPool.js.map +1 -0
- package/dist/minimalEdits.d.ts +21 -0
- package/dist/minimalEdits.d.ts.map +1 -0
- package/dist/minimalEdits.js +181 -0
- package/dist/minimalEdits.js.map +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +38 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugin.d.ts +100 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +837 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugin.styles.d.ts +31 -0
- package/dist/plugin.styles.d.ts.map +1 -0
- package/dist/plugin.styles.js +102 -0
- package/dist/plugin.styles.js.map +1 -0
- package/dist/pluginTypes.d.ts +41 -0
- package/dist/pluginTypes.d.ts.map +1 -0
- package/dist/pluginTypes.js +0 -0
- package/dist/pullDiagnostics.d.ts +30 -0
- package/dist/pullDiagnostics.d.ts.map +1 -0
- package/dist/pullDiagnostics.js +94 -0
- package/dist/pullDiagnostics.js.map +1 -0
- package/dist/renameWidget.d.ts +30 -0
- package/dist/renameWidget.d.ts.map +1 -0
- package/dist/renameWidget.js +117 -0
- package/dist/renameWidget.js.map +1 -0
- package/dist/semanticTokenDecoder.d.ts +81 -0
- package/dist/semanticTokenDecoder.d.ts.map +1 -0
- package/dist/semanticTokenDecoder.js +132 -0
- package/dist/semanticTokenDecoder.js.map +1 -0
- package/dist/semanticTokens.d.ts +47 -0
- package/dist/semanticTokens.d.ts.map +1 -0
- package/dist/semanticTokens.js +68 -0
- package/dist/semanticTokens.js.map +1 -0
- package/dist/serverSet.d.ts +69 -0
- package/dist/serverSet.d.ts.map +1 -0
- package/dist/serverSet.js +331 -0
- package/dist/serverSet.js.map +1 -0
- package/dist/signatureHelp.d.ts +40 -0
- package/dist/signatureHelp.d.ts.map +1 -0
- package/dist/signatureHelp.js +108 -0
- package/dist/signatureHelp.js.map +1 -0
- package/dist/signatureHelpController.d.ts +52 -0
- package/dist/signatureHelpController.d.ts.map +1 -0
- package/dist/signatureHelpController.js +160 -0
- package/dist/signatureHelpController.js.map +1 -0
- package/dist/sourceText.d.ts +22 -0
- package/dist/sourceText.d.ts.map +1 -0
- package/dist/sourceText.js +70 -0
- package/dist/sourceText.js.map +1 -0
- package/dist/types.d.ts +238 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/viewDocumentSnapshot.d.ts +5 -0
- package/dist/viewDocumentSnapshot.d.ts.map +1 -0
- package/dist/viewDocumentSnapshot.js +12 -0
- package/dist/viewDocumentSnapshot.js.map +1 -0
- package/dist/websocket.d.ts +6 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +4 -0
- package/dist/workspaceEdit.d.ts +66 -0
- package/dist/workspaceEdit.d.ts.map +1 -0
- package/dist/workspaceEdit.js +276 -0
- package/dist/workspaceEdit.js.map +1 -0
- package/dist/workspaceEditProvenance.d.ts +5 -0
- package/dist/workspaceEditProvenance.d.ts.map +1 -0
- package/dist/workspaceEditProvenance.js +16 -0
- package/dist/workspaceEditProvenance.js.map +1 -0
- package/dist/workspaceTextEdits.d.ts +60 -0
- package/dist/workspaceTextEdits.d.ts.map +1 -0
- package/dist/workspaceTextEdits.js +395 -0
- package/dist/workspaceTextEdits.js.map +1 -0
- package/package.json +118 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { applyBatchToPieceTable, createDocumentTextSnapshot, diffPieceTableSnapshots, offsetToPoint, pieceTableSnapshotsHaveSameText, pointToOffset, prepareDocumentTransactionSequence, readPieceTableTextRange } from "@singapore-editor/core/document";
|
|
2
|
+
//#region src/workspaceTextEdits.ts
|
|
3
|
+
function prepareWorkspaceTextReplay(input) {
|
|
4
|
+
const targetFailure = targetGuardFailure(input.target);
|
|
5
|
+
if (targetFailure) return {
|
|
6
|
+
error: targetFailure,
|
|
7
|
+
ok: false
|
|
8
|
+
};
|
|
9
|
+
const state = initialReplayState(input);
|
|
10
|
+
const simulated = [];
|
|
11
|
+
for (const segment of input.segments) {
|
|
12
|
+
const result = simulateSegment(input, state, segment);
|
|
13
|
+
if (!result.ok) return result;
|
|
14
|
+
simulated.push(result.segment);
|
|
15
|
+
}
|
|
16
|
+
const effective = simulated.filter((segment) => segment.logicalRevisionCount > 0);
|
|
17
|
+
if (effective.length === 0) return {
|
|
18
|
+
ok: true,
|
|
19
|
+
segments: bindNoOpSegments(simulated, input.target.initialSnapshot.snapshot),
|
|
20
|
+
sequence: null
|
|
21
|
+
};
|
|
22
|
+
const sequence = prepareDocumentTransactionSequence(input.target.buffer, effective.map((segment) => sequenceInput(input.logicalRevisionScope, segment)));
|
|
23
|
+
if (!sequenceMatchesTarget(sequence, input.target)) return replayFailed("snapshot-drift", "Target buffer changed before replay was bound");
|
|
24
|
+
return {
|
|
25
|
+
ok: true,
|
|
26
|
+
segments: bindPreparedSegments(simulated, sequence),
|
|
27
|
+
sequence
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function targetGuardFailure(target) {
|
|
31
|
+
if (target.buffer.getRevision() !== target.expectedRevision) return failure("snapshot-drift", "Target buffer revision does not match the replay guard");
|
|
32
|
+
if (target.buffer.getSnapshot() !== target.initialSnapshot.snapshot) return failure("snapshot-drift", "Target buffer snapshot does not match the replay guard");
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function initialReplayState(input) {
|
|
36
|
+
const uri = input.segments[0]?.uri ?? null;
|
|
37
|
+
const provenance = uri ? exactProvenance(input.provenance, uri, input.target.initialSnapshot) : null;
|
|
38
|
+
const version = validProvenanceVersion(provenance) ? provenance.version : null;
|
|
39
|
+
return {
|
|
40
|
+
snapshot: input.target.initialSnapshot.snapshot,
|
|
41
|
+
textSnapshot: input.target.initialSnapshot,
|
|
42
|
+
uri,
|
|
43
|
+
version,
|
|
44
|
+
versionUri: version === null ? null : uri
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function simulateSegment(input, state, segment) {
|
|
48
|
+
enterSegmentUri(input.provenance, state, segment.uri);
|
|
49
|
+
const snapshotBefore = state.snapshot;
|
|
50
|
+
const textSnapshotBefore = state.textSnapshot;
|
|
51
|
+
const simulatedVersionBefore = state.version;
|
|
52
|
+
const steps = [];
|
|
53
|
+
let logicalRevisionCount = 0;
|
|
54
|
+
for (const entry of segment.operations) {
|
|
55
|
+
const result = simulateStep(input.provenance, state, segment, entry);
|
|
56
|
+
if (!result.ok) return result;
|
|
57
|
+
if (result.effective) logicalRevisionCount += 1;
|
|
58
|
+
steps.push(result.step);
|
|
59
|
+
}
|
|
60
|
+
canonicalizeSegmentSnapshot(state, steps, snapshotBefore, textSnapshotBefore);
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
segment: Object.freeze({
|
|
64
|
+
logicalRevisionCount,
|
|
65
|
+
segmentIndex: segment.segmentIndex,
|
|
66
|
+
simulatedVersionAfter: state.version,
|
|
67
|
+
simulatedVersionBefore,
|
|
68
|
+
snapshotAfter: state.snapshot,
|
|
69
|
+
snapshotBefore,
|
|
70
|
+
steps: Object.freeze(steps),
|
|
71
|
+
uri: segment.uri
|
|
72
|
+
})
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function enterSegmentUri(provenance, state, uri) {
|
|
76
|
+
if (state.uri === uri) return;
|
|
77
|
+
state.uri = uri;
|
|
78
|
+
state.versionUri = null;
|
|
79
|
+
const mapped = exactProvenance(provenance, uri, state.textSnapshot);
|
|
80
|
+
if (!validProvenanceVersion(mapped)) return;
|
|
81
|
+
if (state.version !== null && state.version !== mapped.version) return;
|
|
82
|
+
state.version = mapped.version;
|
|
83
|
+
state.versionUri = uri;
|
|
84
|
+
}
|
|
85
|
+
function simulateStep(provenance, state, segment, entry) {
|
|
86
|
+
if (entry.operation.uri !== segment.uri) return replayFailed("invalid-workspace-edit", "Text operation URI does not match its replay segment", entry.operationIndex);
|
|
87
|
+
const versionFailure = validateOperationVersion(provenance, state, entry);
|
|
88
|
+
if (versionFailure) return {
|
|
89
|
+
error: versionFailure,
|
|
90
|
+
ok: false
|
|
91
|
+
};
|
|
92
|
+
const converted = convertWorkspaceTextBatch(state.snapshot, entry.operation.edits, entry.operationIndex);
|
|
93
|
+
if (!converted.ok) return converted;
|
|
94
|
+
const snapshotBefore = state.snapshot;
|
|
95
|
+
const candidate = applyBatchToPieceTable(snapshotBefore, converted.value.applicationEdits);
|
|
96
|
+
const effective = !pieceTableSnapshotsHaveSameText(snapshotBefore, candidate);
|
|
97
|
+
state.snapshot = effective ? candidate : snapshotBefore;
|
|
98
|
+
if (effective) state.textSnapshot = createDocumentTextSnapshot(state.snapshot);
|
|
99
|
+
const versionAdvanceFailure = advanceSimulatedVersion(state, effective, entry.operationIndex);
|
|
100
|
+
if (versionAdvanceFailure) return {
|
|
101
|
+
error: versionAdvanceFailure,
|
|
102
|
+
ok: false
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
effective,
|
|
106
|
+
ok: true,
|
|
107
|
+
step: Object.freeze({
|
|
108
|
+
edits: converted.value.preparedEdits,
|
|
109
|
+
operationIndex: entry.operationIndex,
|
|
110
|
+
snapshotAfter: state.snapshot,
|
|
111
|
+
snapshotBefore,
|
|
112
|
+
uri: segment.uri
|
|
113
|
+
})
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function validateOperationVersion(provenance, state, entry) {
|
|
117
|
+
const declared = entry.operation.version;
|
|
118
|
+
if (declared === null) return null;
|
|
119
|
+
if (!Number.isSafeInteger(declared)) return failure("version-mismatch", "Text document version must be a safe integer", { operationIndex: entry.operationIndex });
|
|
120
|
+
const lineageFailure = establishVersionLineage(provenance, state, entry);
|
|
121
|
+
if (lineageFailure) return lineageFailure;
|
|
122
|
+
if (state.version === declared) return null;
|
|
123
|
+
return failure("version-mismatch", "Text document version does not match replay provenance", { operationIndex: entry.operationIndex });
|
|
124
|
+
}
|
|
125
|
+
function establishVersionLineage(provenance, state, entry) {
|
|
126
|
+
if (state.versionUri === entry.operation.uri && state.version !== null) return null;
|
|
127
|
+
const mapped = exactProvenance(provenance, entry.operation.uri, state.textSnapshot);
|
|
128
|
+
if (!validProvenanceVersion(mapped)) return failure("version-mismatch", "No exact lane provenance exists for this text snapshot", { operationIndex: entry.operationIndex });
|
|
129
|
+
if (state.version !== null && state.version !== mapped.version) return failure("version-mismatch", "URI provenance does not continue the simulated version", { operationIndex: entry.operationIndex });
|
|
130
|
+
state.version = mapped.version;
|
|
131
|
+
state.versionUri = entry.operation.uri;
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
function advanceSimulatedVersion(state, effective, operationIndex) {
|
|
135
|
+
if (!effective || state.version === null) return null;
|
|
136
|
+
if (!Number.isSafeInteger(state.version + 1)) return failure("version-mismatch", "Simulated text document version overflowed", { operationIndex });
|
|
137
|
+
state.version += 1;
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
function convertWorkspaceTextBatch(snapshot, edits, operationIndex) {
|
|
141
|
+
const converted = [];
|
|
142
|
+
for (let editIndex = 0; editIndex < edits.length; editIndex += 1) {
|
|
143
|
+
const result = convertWorkspaceTextEdit(snapshot, edits[editIndex], operationIndex, editIndex);
|
|
144
|
+
if (!result.ok) return result;
|
|
145
|
+
converted.push({
|
|
146
|
+
edit: result.value,
|
|
147
|
+
editIndex
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const sorted = converted.toSorted(compareIndexedEdits);
|
|
151
|
+
const conflict = textBatchConflict(sorted, operationIndex);
|
|
152
|
+
if (conflict) return {
|
|
153
|
+
error: conflict,
|
|
154
|
+
ok: false
|
|
155
|
+
};
|
|
156
|
+
const snapped = snapPreparedTextEdits(snapshot, sorted.filter(({ edit }) => edit.from !== edit.to || edit.text.length > 0), operationIndex);
|
|
157
|
+
if (!snapped.ok) return snapped;
|
|
158
|
+
return {
|
|
159
|
+
ok: true,
|
|
160
|
+
value: Object.freeze({
|
|
161
|
+
applicationEdits: Object.freeze(snapped.value.map(textEditWithoutAnnotation)),
|
|
162
|
+
preparedEdits: snapped.value
|
|
163
|
+
})
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function convertWorkspaceTextEdit(snapshot, edit, operationIndex, editIndex) {
|
|
167
|
+
const from = strictPositionOffset(snapshot, edit.range.start);
|
|
168
|
+
if (from === null) return invalidPosition(operationIndex, editIndex, "Invalid range start");
|
|
169
|
+
const to = strictPositionOffset(snapshot, edit.range.end);
|
|
170
|
+
if (to === null) return invalidPosition(operationIndex, editIndex, "Invalid range end");
|
|
171
|
+
if (from > to) return replayFailed("reversed-range", "Text edit range is reversed", operationIndex, editIndex);
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
value: Object.freeze({
|
|
175
|
+
...edit.annotationId === void 0 ? {} : { annotationId: edit.annotationId },
|
|
176
|
+
from,
|
|
177
|
+
text: normalizeInsertedText(edit.newText),
|
|
178
|
+
to
|
|
179
|
+
})
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function strictPositionOffset(snapshot, position) {
|
|
183
|
+
if (!Number.isInteger(position.line) || position.line < 0) return null;
|
|
184
|
+
if (!Number.isInteger(position.character) || position.character < 0) return null;
|
|
185
|
+
const offset = pointToOffset(snapshot, {
|
|
186
|
+
column: position.character,
|
|
187
|
+
row: position.line
|
|
188
|
+
});
|
|
189
|
+
const roundTrip = offsetToPoint(snapshot, offset);
|
|
190
|
+
if (roundTrip.row !== position.line || roundTrip.column !== position.character) return null;
|
|
191
|
+
return offset;
|
|
192
|
+
}
|
|
193
|
+
function textBatchConflict(edits, operationIndex) {
|
|
194
|
+
let previous = null;
|
|
195
|
+
for (const current of edits) {
|
|
196
|
+
const conflict = conflictWithPrevious(previous, current, operationIndex);
|
|
197
|
+
if (conflict) return conflict;
|
|
198
|
+
if (!previous || current.edit.to > previous.edit.to) previous = current;
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
function conflictWithPrevious(previous, current, operationIndex) {
|
|
203
|
+
if (!previous) return null;
|
|
204
|
+
const previousIsInsert = previous.edit.from === previous.edit.to;
|
|
205
|
+
const currentIsInsert = current.edit.from === current.edit.to;
|
|
206
|
+
if (previousIsInsert && currentIsInsert && previous.edit.from === current.edit.from) return failure("ambiguous-inserts", "Coincident inserts have no defined protocol order", {
|
|
207
|
+
editIndex: current.editIndex,
|
|
208
|
+
operationIndex
|
|
209
|
+
});
|
|
210
|
+
if (current.edit.from >= previous.edit.to) return null;
|
|
211
|
+
return failure("overlapping-edits", "Text edit ranges overlap", {
|
|
212
|
+
editIndex: current.editIndex,
|
|
213
|
+
operationIndex
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function snapPreparedTextEdits(snapshot, edits, operationIndex) {
|
|
217
|
+
const boundaries = batchBoundaryCounts(edits);
|
|
218
|
+
return mergeSnappedPreparedTextEdits(edits.map(({ edit, editIndex }) => ({
|
|
219
|
+
edit: snapPreparedTextEdit(snapshot, edit, boundaries),
|
|
220
|
+
editIndex
|
|
221
|
+
})), operationIndex);
|
|
222
|
+
}
|
|
223
|
+
function mergeSnappedPreparedTextEdits(edits, operationIndex) {
|
|
224
|
+
const merged = [];
|
|
225
|
+
for (const current of edits) {
|
|
226
|
+
const previous = merged.at(-1);
|
|
227
|
+
if (!previous || current.edit.from >= previous.to) {
|
|
228
|
+
merged.push(current.edit);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (previous.annotationId !== current.edit.annotationId) return replayFailed("overlapping-edits", "Surrogate snapping cannot merge edits with different annotation ids", operationIndex, current.editIndex);
|
|
232
|
+
merged[merged.length - 1] = Object.freeze({
|
|
233
|
+
...previous.annotationId === void 0 ? {} : { annotationId: previous.annotationId },
|
|
234
|
+
from: previous.from,
|
|
235
|
+
text: previous.text + current.edit.text,
|
|
236
|
+
to: Math.max(previous.to, current.edit.to)
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
ok: true,
|
|
241
|
+
value: Object.freeze(merged)
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function snapPreparedTextEdit(snapshot, edit, boundaries) {
|
|
245
|
+
const snapStart = orphansSurrogateAtStart(snapshot, edit, boundaries);
|
|
246
|
+
const snapEnd = orphansSurrogateAtEnd(snapshot, edit, boundaries);
|
|
247
|
+
if (!snapStart && !snapEnd) return edit;
|
|
248
|
+
const collapsed = edit.from === edit.to;
|
|
249
|
+
let from = edit.from;
|
|
250
|
+
let to = edit.to;
|
|
251
|
+
if (collapsed || snapStart) from -= 1;
|
|
252
|
+
if (collapsed) to -= 1;
|
|
253
|
+
if (!collapsed && snapEnd) to += 1;
|
|
254
|
+
return Object.freeze({
|
|
255
|
+
...edit,
|
|
256
|
+
from,
|
|
257
|
+
to
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
function orphansSurrogateAtStart(snapshot, edit, boundaries) {
|
|
261
|
+
if (!splitsSurrogatePair(snapshot, edit.from)) return false;
|
|
262
|
+
if ((boundaries.ends.get(edit.from) ?? 0) > 0) return false;
|
|
263
|
+
return !isLowSurrogate(edit.text.charCodeAt(0));
|
|
264
|
+
}
|
|
265
|
+
function orphansSurrogateAtEnd(snapshot, edit, boundaries) {
|
|
266
|
+
if (!splitsSurrogatePair(snapshot, edit.to)) return false;
|
|
267
|
+
if ((boundaries.starts.get(edit.to) ?? 0) > 0) return false;
|
|
268
|
+
return !isHighSurrogate(edit.text.charCodeAt(edit.text.length - 1));
|
|
269
|
+
}
|
|
270
|
+
function splitsSurrogatePair(snapshot, offset) {
|
|
271
|
+
if (offset <= 0 || offset >= snapshot.length) return false;
|
|
272
|
+
const pair = readPieceTableTextRange(snapshot, offset - 1, offset + 1);
|
|
273
|
+
return isHighSurrogate(pair.charCodeAt(0)) && isLowSurrogate(pair.charCodeAt(1));
|
|
274
|
+
}
|
|
275
|
+
function batchBoundaryCounts(edits) {
|
|
276
|
+
const starts = /* @__PURE__ */ new Map();
|
|
277
|
+
const ends = /* @__PURE__ */ new Map();
|
|
278
|
+
for (const { edit } of edits) {
|
|
279
|
+
if (edit.from === edit.to) continue;
|
|
280
|
+
starts.set(edit.from, (starts.get(edit.from) ?? 0) + 1);
|
|
281
|
+
ends.set(edit.to, (ends.get(edit.to) ?? 0) + 1);
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
ends,
|
|
285
|
+
starts
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function canonicalizeSegmentSnapshot(state, steps, snapshotBefore, textSnapshotBefore) {
|
|
289
|
+
if (!pieceTableSnapshotsHaveSameText(snapshotBefore, state.snapshot)) return;
|
|
290
|
+
state.snapshot = snapshotBefore;
|
|
291
|
+
state.textSnapshot = textSnapshotBefore;
|
|
292
|
+
const last = steps.at(-1);
|
|
293
|
+
if (!last) return;
|
|
294
|
+
steps[steps.length - 1] = Object.freeze({
|
|
295
|
+
...last,
|
|
296
|
+
snapshotAfter: snapshotBefore
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function sequenceInput(logicalRevisionScope, segment) {
|
|
300
|
+
const edit = diffPieceTableSnapshots(segment.snapshotBefore, segment.snapshotAfter);
|
|
301
|
+
return {
|
|
302
|
+
edits: edit ? [edit] : [],
|
|
303
|
+
logicalRevisionCount: segment.logicalRevisionCount,
|
|
304
|
+
logicalRevisionScope
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
function sequenceMatchesTarget(sequence, target) {
|
|
308
|
+
return sequence.expectedRevision === target.expectedRevision && sequence.snapshotBefore === target.initialSnapshot.snapshot;
|
|
309
|
+
}
|
|
310
|
+
function bindNoOpSegments(simulated, snapshot) {
|
|
311
|
+
return Object.freeze(simulated.map((segment) => bindSegment(segment, null, snapshot, snapshot)));
|
|
312
|
+
}
|
|
313
|
+
function bindPreparedSegments(simulated, sequence) {
|
|
314
|
+
const bound = [];
|
|
315
|
+
let sequenceSegmentIndex = 0;
|
|
316
|
+
let snapshot = sequence.snapshotBefore;
|
|
317
|
+
for (const segment of simulated) {
|
|
318
|
+
if (segment.logicalRevisionCount === 0) {
|
|
319
|
+
bound.push(bindSegment(segment, null, snapshot, snapshot));
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
const prepared = sequence.segments[sequenceSegmentIndex];
|
|
323
|
+
bound.push(bindSegment(segment, sequenceSegmentIndex, prepared.snapshotBefore, prepared.snapshotAfter));
|
|
324
|
+
snapshot = prepared.snapshotAfter;
|
|
325
|
+
sequenceSegmentIndex += 1;
|
|
326
|
+
}
|
|
327
|
+
return Object.freeze(bound);
|
|
328
|
+
}
|
|
329
|
+
function bindSegment(segment, sequenceSegmentIndex, snapshotBefore, snapshotAfter) {
|
|
330
|
+
return Object.freeze({
|
|
331
|
+
...segment,
|
|
332
|
+
sequenceSegmentIndex,
|
|
333
|
+
snapshotAfter,
|
|
334
|
+
snapshotBefore,
|
|
335
|
+
steps: bindStepBoundaries(segment.steps, snapshotBefore, snapshotAfter)
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
function bindStepBoundaries(steps, snapshotBefore, snapshotAfter) {
|
|
339
|
+
if (steps.length === 0) return steps;
|
|
340
|
+
const lastIndex = steps.length - 1;
|
|
341
|
+
return Object.freeze(steps.map((step, index) => Object.freeze({
|
|
342
|
+
...step,
|
|
343
|
+
snapshotAfter: index === lastIndex ? snapshotAfter : step.snapshotAfter,
|
|
344
|
+
snapshotBefore: index === 0 ? snapshotBefore : step.snapshotBefore
|
|
345
|
+
})));
|
|
346
|
+
}
|
|
347
|
+
function exactProvenance(provenance, uri, textSnapshot) {
|
|
348
|
+
return provenance.find((entry) => entry.uri === uri && entry.textSnapshot === textSnapshot) ?? null;
|
|
349
|
+
}
|
|
350
|
+
function validProvenanceVersion(provenance) {
|
|
351
|
+
return provenance !== null && Number.isSafeInteger(provenance.version);
|
|
352
|
+
}
|
|
353
|
+
function textEditWithoutAnnotation(edit) {
|
|
354
|
+
return Object.freeze({
|
|
355
|
+
from: edit.from,
|
|
356
|
+
text: edit.text,
|
|
357
|
+
to: edit.to
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function compareIndexedEdits(left, right) {
|
|
361
|
+
return left.edit.from - right.edit.from || left.edit.to - right.edit.to;
|
|
362
|
+
}
|
|
363
|
+
function normalizeInsertedText(text) {
|
|
364
|
+
return /[\r\u2028\u2029]/.test(text) ? text.replace(/\r\n|[\r\u2028\u2029]/g, "\n") : text;
|
|
365
|
+
}
|
|
366
|
+
function isHighSurrogate(code) {
|
|
367
|
+
return code >= 55296 && code <= 56319;
|
|
368
|
+
}
|
|
369
|
+
function isLowSurrogate(code) {
|
|
370
|
+
return code >= 56320 && code <= 57343;
|
|
371
|
+
}
|
|
372
|
+
function invalidPosition(operationIndex, editIndex, reason) {
|
|
373
|
+
return replayFailed("invalid-position", reason, operationIndex, editIndex);
|
|
374
|
+
}
|
|
375
|
+
function replayFailed(code, reason, operationIndex, editIndex) {
|
|
376
|
+
return {
|
|
377
|
+
error: failure(code, reason, {
|
|
378
|
+
editIndex,
|
|
379
|
+
operationIndex
|
|
380
|
+
}),
|
|
381
|
+
ok: false
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function failure(code, reason, indices = {}) {
|
|
385
|
+
return Object.freeze({
|
|
386
|
+
code,
|
|
387
|
+
reason,
|
|
388
|
+
...indices.operationIndex === void 0 ? {} : { operationIndex: indices.operationIndex },
|
|
389
|
+
...indices.editIndex === void 0 ? {} : { editIndex: indices.editIndex }
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
//#endregion
|
|
393
|
+
export { prepareWorkspaceTextReplay };
|
|
394
|
+
|
|
395
|
+
//# sourceMappingURL=workspaceTextEdits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceTextEdits.js","names":[],"sources":["../src/workspaceTextEdits.ts"],"sourcesContent":["import {\n applyBatchToPieceTable,\n createDocumentTextSnapshot,\n diffPieceTableSnapshots,\n offsetToPoint,\n pieceTableSnapshotsHaveSameText,\n pointToOffset,\n prepareDocumentTransactionSequence,\n readPieceTableTextRange,\n} from '@singapore-editor/core/document'\nimport type {\n DocumentLogicalRevisionScope,\n DocumentTextSnapshot,\n EditorTextBuffer,\n PieceTableSnapshot,\n PreparedDocumentTransactionSequence,\n TextEdit,\n TextSnapshot,\n} from '@singapore-editor/core/document'\n\nimport type { LspTextSnapshot } from '@singapore-editor/lsp'\n\nimport type {\n ParsedWorkspacePosition,\n ParsedWorkspaceTextEdit,\n WorkspaceEditFailure,\n WorkspaceEditFailureCode,\n WorkspaceEditOperation,\n} from './workspaceEdit'\n\nexport type WorkspaceTextDocumentProvenance = {\n readonly textSnapshot: LspTextSnapshot\n readonly uri: string\n readonly version: number\n}\n\nexport type WorkspaceTextReplaySegmentInput = {\n readonly operations: readonly {\n readonly operation: Extract<WorkspaceEditOperation, { kind: 'text-document' }>\n readonly operationIndex: number\n }[]\n readonly segmentIndex: number\n readonly uri: string\n}\n\nexport type WorkspaceTextReplayTarget = {\n readonly buffer: EditorTextBuffer\n readonly expectedRevision: number\n readonly initialSnapshot: DocumentTextSnapshot\n}\n\nexport type WorkspaceTextReplayInput = {\n readonly logicalRevisionScope: DocumentLogicalRevisionScope\n readonly provenance: readonly WorkspaceTextDocumentProvenance[]\n readonly segments: readonly WorkspaceTextReplaySegmentInput[]\n readonly target: WorkspaceTextReplayTarget\n}\n\nexport type PreparedWorkspaceTextEdit = TextEdit & {\n readonly annotationId?: string\n}\n\nexport type PreparedWorkspaceTextStep = {\n readonly edits: readonly PreparedWorkspaceTextEdit[]\n readonly operationIndex: number\n readonly snapshotAfter: PieceTableSnapshot\n readonly snapshotBefore: PieceTableSnapshot\n readonly uri: string\n}\n\nexport type PreparedWorkspaceTextSegment = {\n readonly logicalRevisionCount: number\n readonly segmentIndex: number\n readonly sequenceSegmentIndex: number | null\n readonly simulatedVersionAfter: number | null\n readonly simulatedVersionBefore: number | null\n readonly snapshotAfter: PieceTableSnapshot\n readonly snapshotBefore: PieceTableSnapshot\n readonly steps: readonly PreparedWorkspaceTextStep[]\n readonly uri: string\n}\n\nexport type PrepareWorkspaceTextReplayResult =\n | {\n readonly ok: true\n readonly segments: readonly PreparedWorkspaceTextSegment[]\n readonly sequence: PreparedDocumentTransactionSequence | null\n }\n | { readonly error: WorkspaceEditFailure; readonly ok: false }\n\ntype ReplayState = {\n snapshot: PieceTableSnapshot\n textSnapshot: TextSnapshot\n uri: string | null\n version: number | null\n versionUri: string | null\n}\n\ntype SimulatedWorkspaceTextSegment = Omit<PreparedWorkspaceTextSegment, 'sequenceSegmentIndex'>\n\ntype SimulateSegmentResult =\n | { readonly ok: true; readonly segment: SimulatedWorkspaceTextSegment }\n | { readonly error: WorkspaceEditFailure; readonly ok: false }\n\ntype SimulateStepResult =\n | {\n readonly effective: boolean\n readonly ok: true\n readonly step: PreparedWorkspaceTextStep\n }\n | { readonly error: WorkspaceEditFailure; readonly ok: false }\n\ntype ConvertedWorkspaceTextBatch = {\n readonly applicationEdits: readonly TextEdit[]\n readonly preparedEdits: readonly PreparedWorkspaceTextEdit[]\n}\n\ntype ConvertWorkspaceTextBatchResult =\n | { readonly ok: true; readonly value: ConvertedWorkspaceTextBatch }\n | { readonly error: WorkspaceEditFailure; readonly ok: false }\n\ntype SnapPreparedTextEditsResult =\n | { readonly ok: true; readonly value: readonly PreparedWorkspaceTextEdit[] }\n | { readonly error: WorkspaceEditFailure; readonly ok: false }\n\ntype IndexedPreparedWorkspaceTextEdit = {\n readonly edit: PreparedWorkspaceTextEdit\n readonly editIndex: number\n}\n\ntype BoundaryCounts = {\n readonly ends: ReadonlyMap<number, number>\n readonly starts: ReadonlyMap<number, number>\n}\n\nexport function prepareWorkspaceTextReplay(\n input: WorkspaceTextReplayInput,\n): PrepareWorkspaceTextReplayResult {\n const targetFailure = targetGuardFailure(input.target)\n if (targetFailure) return { error: targetFailure, ok: false }\n\n const state = initialReplayState(input)\n const simulated: SimulatedWorkspaceTextSegment[] = []\n for (const segment of input.segments) {\n const result = simulateSegment(input, state, segment)\n if (!result.ok) return result\n simulated.push(result.segment)\n }\n\n const effective = simulated.filter((segment) => segment.logicalRevisionCount > 0)\n if (effective.length === 0) {\n return {\n ok: true,\n segments: bindNoOpSegments(simulated, input.target.initialSnapshot.snapshot),\n sequence: null,\n }\n }\n\n const sequence = prepareDocumentTransactionSequence(\n input.target.buffer,\n effective.map((segment) => sequenceInput(input.logicalRevisionScope, segment)),\n )\n if (!sequenceMatchesTarget(sequence, input.target)) {\n return replayFailed('snapshot-drift', 'Target buffer changed before replay was bound')\n }\n\n return {\n ok: true,\n segments: bindPreparedSegments(simulated, sequence),\n sequence,\n }\n}\n\nfunction targetGuardFailure(target: WorkspaceTextReplayTarget): WorkspaceEditFailure | null {\n if (target.buffer.getRevision() !== target.expectedRevision) {\n return failure('snapshot-drift', 'Target buffer revision does not match the replay guard')\n }\n if (target.buffer.getSnapshot() !== target.initialSnapshot.snapshot) {\n return failure('snapshot-drift', 'Target buffer snapshot does not match the replay guard')\n }\n return null\n}\n\nfunction initialReplayState(input: WorkspaceTextReplayInput): ReplayState {\n const uri = input.segments[0]?.uri ?? null\n const provenance = uri\n ? exactProvenance(input.provenance, uri, input.target.initialSnapshot)\n : null\n const version = validProvenanceVersion(provenance) ? provenance.version : null\n return {\n snapshot: input.target.initialSnapshot.snapshot,\n textSnapshot: input.target.initialSnapshot,\n uri,\n version,\n versionUri: version === null ? null : uri,\n }\n}\n\nfunction simulateSegment(\n input: WorkspaceTextReplayInput,\n state: ReplayState,\n segment: WorkspaceTextReplaySegmentInput,\n): SimulateSegmentResult {\n enterSegmentUri(input.provenance, state, segment.uri)\n const snapshotBefore = state.snapshot\n const textSnapshotBefore = state.textSnapshot\n const simulatedVersionBefore = state.version\n const steps: PreparedWorkspaceTextStep[] = []\n let logicalRevisionCount = 0\n\n for (const entry of segment.operations) {\n const result = simulateStep(input.provenance, state, segment, entry)\n if (!result.ok) return result\n if (result.effective) logicalRevisionCount += 1\n steps.push(result.step)\n }\n\n canonicalizeSegmentSnapshot(state, steps, snapshotBefore, textSnapshotBefore)\n return {\n ok: true,\n segment: Object.freeze({\n logicalRevisionCount,\n segmentIndex: segment.segmentIndex,\n simulatedVersionAfter: state.version,\n simulatedVersionBefore,\n snapshotAfter: state.snapshot,\n snapshotBefore,\n steps: Object.freeze(steps),\n uri: segment.uri,\n }),\n }\n}\n\nfunction enterSegmentUri(\n provenance: readonly WorkspaceTextDocumentProvenance[],\n state: ReplayState,\n uri: string,\n): void {\n if (state.uri === uri) return\n state.uri = uri\n state.versionUri = null\n\n const mapped = exactProvenance(provenance, uri, state.textSnapshot)\n if (!validProvenanceVersion(mapped)) return\n if (state.version !== null && state.version !== mapped.version) return\n state.version = mapped.version\n state.versionUri = uri\n}\n\nfunction simulateStep(\n provenance: readonly WorkspaceTextDocumentProvenance[],\n state: ReplayState,\n segment: WorkspaceTextReplaySegmentInput,\n entry: WorkspaceTextReplaySegmentInput['operations'][number],\n): SimulateStepResult {\n if (entry.operation.uri !== segment.uri) {\n return replayFailed(\n 'invalid-workspace-edit',\n 'Text operation URI does not match its replay segment',\n entry.operationIndex,\n )\n }\n\n const versionFailure = validateOperationVersion(provenance, state, entry)\n if (versionFailure) return { error: versionFailure, ok: false }\n const converted = convertWorkspaceTextBatch(\n state.snapshot,\n entry.operation.edits,\n entry.operationIndex,\n )\n if (!converted.ok) return converted\n\n const snapshotBefore = state.snapshot\n const candidate = applyBatchToPieceTable(snapshotBefore, converted.value.applicationEdits)\n const effective = !pieceTableSnapshotsHaveSameText(snapshotBefore, candidate)\n state.snapshot = effective ? candidate : snapshotBefore\n if (effective) state.textSnapshot = createDocumentTextSnapshot(state.snapshot)\n\n const versionAdvanceFailure = advanceSimulatedVersion(state, effective, entry.operationIndex)\n if (versionAdvanceFailure) return { error: versionAdvanceFailure, ok: false }\n return {\n effective,\n ok: true,\n step: Object.freeze({\n edits: converted.value.preparedEdits,\n operationIndex: entry.operationIndex,\n snapshotAfter: state.snapshot,\n snapshotBefore,\n uri: segment.uri,\n }),\n }\n}\n\nfunction validateOperationVersion(\n provenance: readonly WorkspaceTextDocumentProvenance[],\n state: ReplayState,\n entry: WorkspaceTextReplaySegmentInput['operations'][number],\n): WorkspaceEditFailure | null {\n const declared = entry.operation.version\n if (declared === null) return null\n if (!Number.isSafeInteger(declared)) {\n return failure('version-mismatch', 'Text document version must be a safe integer', {\n operationIndex: entry.operationIndex,\n })\n }\n\n const lineageFailure = establishVersionLineage(provenance, state, entry)\n if (lineageFailure) return lineageFailure\n if (state.version === declared) return null\n return failure('version-mismatch', 'Text document version does not match replay provenance', {\n operationIndex: entry.operationIndex,\n })\n}\n\nfunction establishVersionLineage(\n provenance: readonly WorkspaceTextDocumentProvenance[],\n state: ReplayState,\n entry: WorkspaceTextReplaySegmentInput['operations'][number],\n): WorkspaceEditFailure | null {\n if (state.versionUri === entry.operation.uri && state.version !== null) return null\n\n const mapped = exactProvenance(provenance, entry.operation.uri, state.textSnapshot)\n if (!validProvenanceVersion(mapped)) {\n return failure('version-mismatch', 'No exact lane provenance exists for this text snapshot', {\n operationIndex: entry.operationIndex,\n })\n }\n if (state.version !== null && state.version !== mapped.version) {\n return failure('version-mismatch', 'URI provenance does not continue the simulated version', {\n operationIndex: entry.operationIndex,\n })\n }\n\n state.version = mapped.version\n state.versionUri = entry.operation.uri\n return null\n}\n\nfunction advanceSimulatedVersion(\n state: ReplayState,\n effective: boolean,\n operationIndex: number,\n): WorkspaceEditFailure | null {\n if (!effective || state.version === null) return null\n if (!Number.isSafeInteger(state.version + 1)) {\n return failure('version-mismatch', 'Simulated text document version overflowed', {\n operationIndex,\n })\n }\n state.version += 1\n return null\n}\n\nfunction convertWorkspaceTextBatch(\n snapshot: PieceTableSnapshot,\n edits: readonly ParsedWorkspaceTextEdit[],\n operationIndex: number,\n): ConvertWorkspaceTextBatchResult {\n const converted: IndexedPreparedWorkspaceTextEdit[] = []\n for (let editIndex = 0; editIndex < edits.length; editIndex += 1) {\n const result = convertWorkspaceTextEdit(snapshot, edits[editIndex]!, operationIndex, editIndex)\n if (!result.ok) return result\n converted.push({ edit: result.value, editIndex })\n }\n\n const sorted = converted.toSorted(compareIndexedEdits)\n const conflict = textBatchConflict(sorted, operationIndex)\n if (conflict) return { error: conflict, ok: false }\n\n const effective = sorted.filter(({ edit }) => edit.from !== edit.to || edit.text.length > 0)\n const snapped = snapPreparedTextEdits(snapshot, effective, operationIndex)\n if (!snapped.ok) return snapped\n\n return {\n ok: true,\n value: Object.freeze({\n applicationEdits: Object.freeze(snapped.value.map(textEditWithoutAnnotation)),\n preparedEdits: snapped.value,\n }),\n }\n}\n\nfunction convertWorkspaceTextEdit(\n snapshot: PieceTableSnapshot,\n edit: ParsedWorkspaceTextEdit,\n operationIndex: number,\n editIndex: number,\n):\n | { readonly ok: true; readonly value: PreparedWorkspaceTextEdit }\n | { readonly error: WorkspaceEditFailure; readonly ok: false } {\n const from = strictPositionOffset(snapshot, edit.range.start)\n if (from === null) return invalidPosition(operationIndex, editIndex, 'Invalid range start')\n const to = strictPositionOffset(snapshot, edit.range.end)\n if (to === null) return invalidPosition(operationIndex, editIndex, 'Invalid range end')\n if (from > to) {\n return replayFailed('reversed-range', 'Text edit range is reversed', operationIndex, editIndex)\n }\n\n return {\n ok: true,\n value: Object.freeze({\n ...(edit.annotationId === undefined ? {} : { annotationId: edit.annotationId }),\n from,\n text: normalizeInsertedText(edit.newText),\n to,\n }),\n }\n}\n\nfunction strictPositionOffset(\n snapshot: PieceTableSnapshot,\n position: ParsedWorkspacePosition,\n): number | null {\n if (!Number.isInteger(position.line) || position.line < 0) return null\n if (!Number.isInteger(position.character) || position.character < 0) return null\n\n const offset = pointToOffset(snapshot, { column: position.character, row: position.line })\n const roundTrip = offsetToPoint(snapshot, offset)\n if (roundTrip.row !== position.line || roundTrip.column !== position.character) return null\n return offset\n}\n\nfunction textBatchConflict(\n edits: readonly IndexedPreparedWorkspaceTextEdit[],\n operationIndex: number,\n): WorkspaceEditFailure | null {\n let previous: IndexedPreparedWorkspaceTextEdit | null = null\n for (const current of edits) {\n const conflict = conflictWithPrevious(previous, current, operationIndex)\n if (conflict) return conflict\n if (!previous || current.edit.to > previous.edit.to) previous = current\n }\n return null\n}\n\nfunction conflictWithPrevious(\n previous: IndexedPreparedWorkspaceTextEdit | null,\n current: IndexedPreparedWorkspaceTextEdit,\n operationIndex: number,\n): WorkspaceEditFailure | null {\n if (!previous) return null\n const previousIsInsert = previous.edit.from === previous.edit.to\n const currentIsInsert = current.edit.from === current.edit.to\n if (previousIsInsert && currentIsInsert && previous.edit.from === current.edit.from) {\n return failure('ambiguous-inserts', 'Coincident inserts have no defined protocol order', {\n editIndex: current.editIndex,\n operationIndex,\n })\n }\n if (current.edit.from >= previous.edit.to) return null\n return failure('overlapping-edits', 'Text edit ranges overlap', {\n editIndex: current.editIndex,\n operationIndex,\n })\n}\n\nfunction snapPreparedTextEdits(\n snapshot: PieceTableSnapshot,\n edits: readonly IndexedPreparedWorkspaceTextEdit[],\n operationIndex: number,\n): SnapPreparedTextEditsResult {\n const boundaries = batchBoundaryCounts(edits)\n const snapped = edits.map(({ edit, editIndex }) => ({\n edit: snapPreparedTextEdit(snapshot, edit, boundaries),\n editIndex,\n }))\n return mergeSnappedPreparedTextEdits(snapped, operationIndex)\n}\n\nfunction mergeSnappedPreparedTextEdits(\n edits: readonly IndexedPreparedWorkspaceTextEdit[],\n operationIndex: number,\n): SnapPreparedTextEditsResult {\n const merged: PreparedWorkspaceTextEdit[] = []\n for (const current of edits) {\n const previous = merged.at(-1)\n if (!previous || current.edit.from >= previous.to) {\n merged.push(current.edit)\n continue\n }\n if (previous.annotationId !== current.edit.annotationId) {\n return replayFailed(\n 'overlapping-edits',\n 'Surrogate snapping cannot merge edits with different annotation ids',\n operationIndex,\n current.editIndex,\n )\n }\n\n merged[merged.length - 1] = Object.freeze({\n ...(previous.annotationId === undefined ? {} : { annotationId: previous.annotationId }),\n from: previous.from,\n text: previous.text + current.edit.text,\n to: Math.max(previous.to, current.edit.to),\n })\n }\n return { ok: true, value: Object.freeze(merged) }\n}\n\nfunction snapPreparedTextEdit(\n snapshot: PieceTableSnapshot,\n edit: PreparedWorkspaceTextEdit,\n boundaries: BoundaryCounts,\n): PreparedWorkspaceTextEdit {\n const snapStart = orphansSurrogateAtStart(snapshot, edit, boundaries)\n const snapEnd = orphansSurrogateAtEnd(snapshot, edit, boundaries)\n if (!snapStart && !snapEnd) return edit\n\n const collapsed = edit.from === edit.to\n let from = edit.from\n let to = edit.to\n if (collapsed || snapStart) from -= 1\n if (collapsed) to -= 1\n if (!collapsed && snapEnd) to += 1\n return Object.freeze({ ...edit, from, to })\n}\n\nfunction orphansSurrogateAtStart(\n snapshot: PieceTableSnapshot,\n edit: PreparedWorkspaceTextEdit,\n boundaries: BoundaryCounts,\n): boolean {\n if (!splitsSurrogatePair(snapshot, edit.from)) return false\n if ((boundaries.ends.get(edit.from) ?? 0) > 0) return false\n return !isLowSurrogate(edit.text.charCodeAt(0))\n}\n\nfunction orphansSurrogateAtEnd(\n snapshot: PieceTableSnapshot,\n edit: PreparedWorkspaceTextEdit,\n boundaries: BoundaryCounts,\n): boolean {\n if (!splitsSurrogatePair(snapshot, edit.to)) return false\n if ((boundaries.starts.get(edit.to) ?? 0) > 0) return false\n return !isHighSurrogate(edit.text.charCodeAt(edit.text.length - 1))\n}\n\nfunction splitsSurrogatePair(snapshot: PieceTableSnapshot, offset: number): boolean {\n if (offset <= 0 || offset >= snapshot.length) return false\n const pair = readPieceTableTextRange(snapshot, offset - 1, offset + 1)\n return isHighSurrogate(pair.charCodeAt(0)) && isLowSurrogate(pair.charCodeAt(1))\n}\n\nfunction batchBoundaryCounts(edits: readonly IndexedPreparedWorkspaceTextEdit[]): BoundaryCounts {\n const starts = new Map<number, number>()\n const ends = new Map<number, number>()\n for (const { edit } of edits) {\n if (edit.from === edit.to) continue\n starts.set(edit.from, (starts.get(edit.from) ?? 0) + 1)\n ends.set(edit.to, (ends.get(edit.to) ?? 0) + 1)\n }\n return { ends, starts }\n}\n\nfunction canonicalizeSegmentSnapshot(\n state: ReplayState,\n steps: PreparedWorkspaceTextStep[],\n snapshotBefore: PieceTableSnapshot,\n textSnapshotBefore: TextSnapshot,\n): void {\n if (!pieceTableSnapshotsHaveSameText(snapshotBefore, state.snapshot)) return\n state.snapshot = snapshotBefore\n state.textSnapshot = textSnapshotBefore\n\n const last = steps.at(-1)\n if (!last) return\n steps[steps.length - 1] = Object.freeze({ ...last, snapshotAfter: snapshotBefore })\n}\n\nfunction sequenceInput(\n logicalRevisionScope: DocumentLogicalRevisionScope,\n segment: SimulatedWorkspaceTextSegment,\n) {\n const edit = diffPieceTableSnapshots(segment.snapshotBefore, segment.snapshotAfter)\n return {\n edits: edit ? [edit] : [],\n logicalRevisionCount: segment.logicalRevisionCount,\n logicalRevisionScope,\n }\n}\n\nfunction sequenceMatchesTarget(\n sequence: PreparedDocumentTransactionSequence,\n target: WorkspaceTextReplayTarget,\n): boolean {\n return (\n sequence.expectedRevision === target.expectedRevision &&\n sequence.snapshotBefore === target.initialSnapshot.snapshot\n )\n}\n\nfunction bindNoOpSegments(\n simulated: readonly SimulatedWorkspaceTextSegment[],\n snapshot: PieceTableSnapshot,\n): readonly PreparedWorkspaceTextSegment[] {\n return Object.freeze(simulated.map((segment) => bindSegment(segment, null, snapshot, snapshot)))\n}\n\nfunction bindPreparedSegments(\n simulated: readonly SimulatedWorkspaceTextSegment[],\n sequence: PreparedDocumentTransactionSequence,\n): readonly PreparedWorkspaceTextSegment[] {\n const bound: PreparedWorkspaceTextSegment[] = []\n let sequenceSegmentIndex = 0\n let snapshot = sequence.snapshotBefore\n for (const segment of simulated) {\n if (segment.logicalRevisionCount === 0) {\n bound.push(bindSegment(segment, null, snapshot, snapshot))\n continue\n }\n\n const prepared = sequence.segments[sequenceSegmentIndex]!\n bound.push(\n bindSegment(segment, sequenceSegmentIndex, prepared.snapshotBefore, prepared.snapshotAfter),\n )\n snapshot = prepared.snapshotAfter\n sequenceSegmentIndex += 1\n }\n return Object.freeze(bound)\n}\n\nfunction bindSegment(\n segment: SimulatedWorkspaceTextSegment,\n sequenceSegmentIndex: number | null,\n snapshotBefore: PieceTableSnapshot,\n snapshotAfter: PieceTableSnapshot,\n): PreparedWorkspaceTextSegment {\n return Object.freeze({\n ...segment,\n sequenceSegmentIndex,\n snapshotAfter,\n snapshotBefore,\n steps: bindStepBoundaries(segment.steps, snapshotBefore, snapshotAfter),\n })\n}\n\nfunction bindStepBoundaries(\n steps: readonly PreparedWorkspaceTextStep[],\n snapshotBefore: PieceTableSnapshot,\n snapshotAfter: PieceTableSnapshot,\n): readonly PreparedWorkspaceTextStep[] {\n if (steps.length === 0) return steps\n const lastIndex = steps.length - 1\n return Object.freeze(\n steps.map((step, index) =>\n Object.freeze({\n ...step,\n snapshotAfter: index === lastIndex ? snapshotAfter : step.snapshotAfter,\n snapshotBefore: index === 0 ? snapshotBefore : step.snapshotBefore,\n }),\n ),\n )\n}\n\nfunction exactProvenance(\n provenance: readonly WorkspaceTextDocumentProvenance[],\n uri: string,\n textSnapshot: TextSnapshot,\n): WorkspaceTextDocumentProvenance | null {\n return (\n provenance.find((entry) => entry.uri === uri && entry.textSnapshot === textSnapshot) ?? null\n )\n}\n\nfunction validProvenanceVersion(\n provenance: WorkspaceTextDocumentProvenance | null,\n): provenance is WorkspaceTextDocumentProvenance {\n return provenance !== null && Number.isSafeInteger(provenance.version)\n}\n\nfunction textEditWithoutAnnotation(edit: PreparedWorkspaceTextEdit): TextEdit {\n return Object.freeze({ from: edit.from, text: edit.text, to: edit.to })\n}\n\nfunction compareIndexedEdits(\n left: IndexedPreparedWorkspaceTextEdit,\n right: IndexedPreparedWorkspaceTextEdit,\n): number {\n return left.edit.from - right.edit.from || left.edit.to - right.edit.to\n}\n\nfunction normalizeInsertedText(text: string): string {\n return /[\\r\\u2028\\u2029]/.test(text) ? text.replace(/\\r\\n|[\\r\\u2028\\u2029]/g, '\\n') : text\n}\n\nfunction isHighSurrogate(code: number): boolean {\n return code >= 0xd800 && code <= 0xdbff\n}\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff\n}\n\nfunction invalidPosition(\n operationIndex: number,\n editIndex: number,\n reason: string,\n): { readonly error: WorkspaceEditFailure; readonly ok: false } {\n return replayFailed('invalid-position', reason, operationIndex, editIndex)\n}\n\nfunction replayFailed(\n code: WorkspaceEditFailureCode,\n reason: string,\n operationIndex?: number,\n editIndex?: number,\n): { readonly error: WorkspaceEditFailure; readonly ok: false } {\n return {\n error: failure(code, reason, { editIndex, operationIndex }),\n ok: false,\n }\n}\n\nfunction failure(\n code: WorkspaceEditFailureCode,\n reason: string,\n indices: { readonly editIndex?: number; readonly operationIndex?: number } = {},\n): WorkspaceEditFailure {\n return Object.freeze({\n code,\n reason,\n ...(indices.operationIndex === undefined ? {} : { operationIndex: indices.operationIndex }),\n ...(indices.editIndex === undefined ? {} : { editIndex: indices.editIndex }),\n })\n}\n"],"mappings":";;AAuIA,SAAgB,2BACd,OACkC;CAClC,MAAM,gBAAgB,mBAAmB,MAAM,MAAM;CACrD,IAAI,eAAe,OAAO;EAAE,OAAO;EAAe,IAAI;CAAM;CAE5D,MAAM,QAAQ,mBAAmB,KAAK;CACtC,MAAM,YAA6C,CAAC;CACpD,KAAK,MAAM,WAAW,MAAM,UAAU;EACpC,MAAM,SAAS,gBAAgB,OAAO,OAAO,OAAO;EACpD,IAAI,CAAC,OAAO,IAAI,OAAO;EACvB,UAAU,KAAK,OAAO,OAAO;CAC/B;CAEA,MAAM,YAAY,UAAU,QAAQ,YAAY,QAAQ,uBAAuB,CAAC;CAChF,IAAI,UAAU,WAAW,GACvB,OAAO;EACL,IAAI;EACJ,UAAU,iBAAiB,WAAW,MAAM,OAAO,gBAAgB,QAAQ;EAC3E,UAAU;CACZ;CAGF,MAAM,WAAW,mCACf,MAAM,OAAO,QACb,UAAU,KAAK,YAAY,cAAc,MAAM,sBAAsB,OAAO,CAAC,CAC/E;CACA,IAAI,CAAC,sBAAsB,UAAU,MAAM,MAAM,GAC/C,OAAO,aAAa,kBAAkB,+CAA+C;CAGvF,OAAO;EACL,IAAI;EACJ,UAAU,qBAAqB,WAAW,QAAQ;EAClD;CACF;AACF;AAEA,SAAS,mBAAmB,QAAgE;CAC1F,IAAI,OAAO,OAAO,YAAY,MAAM,OAAO,kBACzC,OAAO,QAAQ,kBAAkB,wDAAwD;CAE3F,IAAI,OAAO,OAAO,YAAY,MAAM,OAAO,gBAAgB,UACzD,OAAO,QAAQ,kBAAkB,wDAAwD;CAE3F,OAAO;AACT;AAEA,SAAS,mBAAmB,OAA8C;CACxE,MAAM,MAAM,MAAM,SAAS,EAAE,EAAE,OAAO;CACtC,MAAM,aAAa,MACf,gBAAgB,MAAM,YAAY,KAAK,MAAM,OAAO,eAAe,IACnE;CACJ,MAAM,UAAU,uBAAuB,UAAU,IAAI,WAAW,UAAU;CAC1E,OAAO;EACL,UAAU,MAAM,OAAO,gBAAgB;EACvC,cAAc,MAAM,OAAO;EAC3B;EACA;EACA,YAAY,YAAY,OAAO,OAAO;CACxC;AACF;AAEA,SAAS,gBACP,OACA,OACA,SACuB;CACvB,gBAAgB,MAAM,YAAY,OAAO,QAAQ,GAAG;CACpD,MAAM,iBAAiB,MAAM;CAC7B,MAAM,qBAAqB,MAAM;CACjC,MAAM,yBAAyB,MAAM;CACrC,MAAM,QAAqC,CAAC;CAC5C,IAAI,uBAAuB;CAE3B,KAAK,MAAM,SAAS,QAAQ,YAAY;EACtC,MAAM,SAAS,aAAa,MAAM,YAAY,OAAO,SAAS,KAAK;EACnE,IAAI,CAAC,OAAO,IAAI,OAAO;EACvB,IAAI,OAAO,WAAW,wBAAwB;EAC9C,MAAM,KAAK,OAAO,IAAI;CACxB;CAEA,4BAA4B,OAAO,OAAO,gBAAgB,kBAAkB;CAC5E,OAAO;EACL,IAAI;EACJ,SAAS,OAAO,OAAO;GACrB;GACA,cAAc,QAAQ;GACtB,uBAAuB,MAAM;GAC7B;GACA,eAAe,MAAM;GACrB;GACA,OAAO,OAAO,OAAO,KAAK;GAC1B,KAAK,QAAQ;EACf,CAAC;CACH;AACF;AAEA,SAAS,gBACP,YACA,OACA,KACM;CACN,IAAI,MAAM,QAAQ,KAAK;CACvB,MAAM,MAAM;CACZ,MAAM,aAAa;CAEnB,MAAM,SAAS,gBAAgB,YAAY,KAAK,MAAM,YAAY;CAClE,IAAI,CAAC,uBAAuB,MAAM,GAAG;CACrC,IAAI,MAAM,YAAY,QAAQ,MAAM,YAAY,OAAO,SAAS;CAChE,MAAM,UAAU,OAAO;CACvB,MAAM,aAAa;AACrB;AAEA,SAAS,aACP,YACA,OACA,SACA,OACoB;CACpB,IAAI,MAAM,UAAU,QAAQ,QAAQ,KAClC,OAAO,aACL,0BACA,wDACA,MAAM,cACR;CAGF,MAAM,iBAAiB,yBAAyB,YAAY,OAAO,KAAK;CACxE,IAAI,gBAAgB,OAAO;EAAE,OAAO;EAAgB,IAAI;CAAM;CAC9D,MAAM,YAAY,0BAChB,MAAM,UACN,MAAM,UAAU,OAChB,MAAM,cACR;CACA,IAAI,CAAC,UAAU,IAAI,OAAO;CAE1B,MAAM,iBAAiB,MAAM;CAC7B,MAAM,YAAY,uBAAuB,gBAAgB,UAAU,MAAM,gBAAgB;CACzF,MAAM,YAAY,CAAC,gCAAgC,gBAAgB,SAAS;CAC5E,MAAM,WAAW,YAAY,YAAY;CACzC,IAAI,WAAW,MAAM,eAAe,2BAA2B,MAAM,QAAQ;CAE7E,MAAM,wBAAwB,wBAAwB,OAAO,WAAW,MAAM,cAAc;CAC5F,IAAI,uBAAuB,OAAO;EAAE,OAAO;EAAuB,IAAI;CAAM;CAC5E,OAAO;EACL;EACA,IAAI;EACJ,MAAM,OAAO,OAAO;GAClB,OAAO,UAAU,MAAM;GACvB,gBAAgB,MAAM;GACtB,eAAe,MAAM;GACrB;GACA,KAAK,QAAQ;EACf,CAAC;CACH;AACF;AAEA,SAAS,yBACP,YACA,OACA,OAC6B;CAC7B,MAAM,WAAW,MAAM,UAAU;CACjC,IAAI,aAAa,MAAM,OAAO;CAC9B,IAAI,CAAC,OAAO,cAAc,QAAQ,GAChC,OAAO,QAAQ,oBAAoB,gDAAgD,EACjF,gBAAgB,MAAM,eACxB,CAAC;CAGH,MAAM,iBAAiB,wBAAwB,YAAY,OAAO,KAAK;CACvE,IAAI,gBAAgB,OAAO;CAC3B,IAAI,MAAM,YAAY,UAAU,OAAO;CACvC,OAAO,QAAQ,oBAAoB,0DAA0D,EAC3F,gBAAgB,MAAM,eACxB,CAAC;AACH;AAEA,SAAS,wBACP,YACA,OACA,OAC6B;CAC7B,IAAI,MAAM,eAAe,MAAM,UAAU,OAAO,MAAM,YAAY,MAAM,OAAO;CAE/E,MAAM,SAAS,gBAAgB,YAAY,MAAM,UAAU,KAAK,MAAM,YAAY;CAClF,IAAI,CAAC,uBAAuB,MAAM,GAChC,OAAO,QAAQ,oBAAoB,0DAA0D,EAC3F,gBAAgB,MAAM,eACxB,CAAC;CAEH,IAAI,MAAM,YAAY,QAAQ,MAAM,YAAY,OAAO,SACrD,OAAO,QAAQ,oBAAoB,0DAA0D,EAC3F,gBAAgB,MAAM,eACxB,CAAC;CAGH,MAAM,UAAU,OAAO;CACvB,MAAM,aAAa,MAAM,UAAU;CACnC,OAAO;AACT;AAEA,SAAS,wBACP,OACA,WACA,gBAC6B;CAC7B,IAAI,CAAC,aAAa,MAAM,YAAY,MAAM,OAAO;CACjD,IAAI,CAAC,OAAO,cAAc,MAAM,UAAU,CAAC,GACzC,OAAO,QAAQ,oBAAoB,8CAA8C,EAC/E,eACF,CAAC;CAEH,MAAM,WAAW;CACjB,OAAO;AACT;AAEA,SAAS,0BACP,UACA,OACA,gBACiC;CACjC,MAAM,YAAgD,CAAC;CACvD,KAAK,IAAI,YAAY,GAAG,YAAY,MAAM,QAAQ,aAAa,GAAG;EAChE,MAAM,SAAS,yBAAyB,UAAU,MAAM,YAAa,gBAAgB,SAAS;EAC9F,IAAI,CAAC,OAAO,IAAI,OAAO;EACvB,UAAU,KAAK;GAAE,MAAM,OAAO;GAAO;EAAU,CAAC;CAClD;CAEA,MAAM,SAAS,UAAU,SAAS,mBAAmB;CACrD,MAAM,WAAW,kBAAkB,QAAQ,cAAc;CACzD,IAAI,UAAU,OAAO;EAAE,OAAO;EAAU,IAAI;CAAM;CAGlD,MAAM,UAAU,sBAAsB,UADpB,OAAO,QAAQ,EAAE,WAAW,KAAK,SAAS,KAAK,MAAM,KAAK,KAAK,SAAS,CAC1C,GAAW,cAAc;CACzE,IAAI,CAAC,QAAQ,IAAI,OAAO;CAExB,OAAO;EACL,IAAI;EACJ,OAAO,OAAO,OAAO;GACnB,kBAAkB,OAAO,OAAO,QAAQ,MAAM,IAAI,yBAAyB,CAAC;GAC5E,eAAe,QAAQ;EACzB,CAAC;CACH;AACF;AAEA,SAAS,yBACP,UACA,MACA,gBACA,WAG+D;CAC/D,MAAM,OAAO,qBAAqB,UAAU,KAAK,MAAM,KAAK;CAC5D,IAAI,SAAS,MAAM,OAAO,gBAAgB,gBAAgB,WAAW,qBAAqB;CAC1F,MAAM,KAAK,qBAAqB,UAAU,KAAK,MAAM,GAAG;CACxD,IAAI,OAAO,MAAM,OAAO,gBAAgB,gBAAgB,WAAW,mBAAmB;CACtF,IAAI,OAAO,IACT,OAAO,aAAa,kBAAkB,+BAA+B,gBAAgB,SAAS;CAGhG,OAAO;EACL,IAAI;EACJ,OAAO,OAAO,OAAO;GACnB,GAAI,KAAK,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,KAAK,aAAa;GAC7E;GACA,MAAM,sBAAsB,KAAK,OAAO;GACxC;EACF,CAAC;CACH;AACF;AAEA,SAAS,qBACP,UACA,UACe;CACf,IAAI,CAAC,OAAO,UAAU,SAAS,IAAI,KAAK,SAAS,OAAO,GAAG,OAAO;CAClE,IAAI,CAAC,OAAO,UAAU,SAAS,SAAS,KAAK,SAAS,YAAY,GAAG,OAAO;CAE5E,MAAM,SAAS,cAAc,UAAU;EAAE,QAAQ,SAAS;EAAW,KAAK,SAAS;CAAK,CAAC;CACzF,MAAM,YAAY,cAAc,UAAU,MAAM;CAChD,IAAI,UAAU,QAAQ,SAAS,QAAQ,UAAU,WAAW,SAAS,WAAW,OAAO;CACvF,OAAO;AACT;AAEA,SAAS,kBACP,OACA,gBAC6B;CAC7B,IAAI,WAAoD;CACxD,KAAK,MAAM,WAAW,OAAO;EAC3B,MAAM,WAAW,qBAAqB,UAAU,SAAS,cAAc;EACvE,IAAI,UAAU,OAAO;EACrB,IAAI,CAAC,YAAY,QAAQ,KAAK,KAAK,SAAS,KAAK,IAAI,WAAW;CAClE;CACA,OAAO;AACT;AAEA,SAAS,qBACP,UACA,SACA,gBAC6B;CAC7B,IAAI,CAAC,UAAU,OAAO;CACtB,MAAM,mBAAmB,SAAS,KAAK,SAAS,SAAS,KAAK;CAC9D,MAAM,kBAAkB,QAAQ,KAAK,SAAS,QAAQ,KAAK;CAC3D,IAAI,oBAAoB,mBAAmB,SAAS,KAAK,SAAS,QAAQ,KAAK,MAC7E,OAAO,QAAQ,qBAAqB,qDAAqD;EACvF,WAAW,QAAQ;EACnB;CACF,CAAC;CAEH,IAAI,QAAQ,KAAK,QAAQ,SAAS,KAAK,IAAI,OAAO;CAClD,OAAO,QAAQ,qBAAqB,4BAA4B;EAC9D,WAAW,QAAQ;EACnB;CACF,CAAC;AACH;AAEA,SAAS,sBACP,UACA,OACA,gBAC6B;CAC7B,MAAM,aAAa,oBAAoB,KAAK;CAK5C,OAAO,8BAJS,MAAM,KAAK,EAAE,MAAM,iBAAiB;EAClD,MAAM,qBAAqB,UAAU,MAAM,UAAU;EACrD;CACF,EACqC,GAAS,cAAc;AAC9D;AAEA,SAAS,8BACP,OACA,gBAC6B;CAC7B,MAAM,SAAsC,CAAC;CAC7C,KAAK,MAAM,WAAW,OAAO;EAC3B,MAAM,WAAW,OAAO,GAAG,EAAE;EAC7B,IAAI,CAAC,YAAY,QAAQ,KAAK,QAAQ,SAAS,IAAI;GACjD,OAAO,KAAK,QAAQ,IAAI;GACxB;EACF;EACA,IAAI,SAAS,iBAAiB,QAAQ,KAAK,cACzC,OAAO,aACL,qBACA,uEACA,gBACA,QAAQ,SACV;EAGF,OAAO,OAAO,SAAS,KAAK,OAAO,OAAO;GACxC,GAAI,SAAS,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,SAAS,aAAa;GACrF,MAAM,SAAS;GACf,MAAM,SAAS,OAAO,QAAQ,KAAK;GACnC,IAAI,KAAK,IAAI,SAAS,IAAI,QAAQ,KAAK,EAAE;EAC3C,CAAC;CACH;CACA,OAAO;EAAE,IAAI;EAAM,OAAO,OAAO,OAAO,MAAM;CAAE;AAClD;AAEA,SAAS,qBACP,UACA,MACA,YAC2B;CAC3B,MAAM,YAAY,wBAAwB,UAAU,MAAM,UAAU;CACpE,MAAM,UAAU,sBAAsB,UAAU,MAAM,UAAU;CAChE,IAAI,CAAC,aAAa,CAAC,SAAS,OAAO;CAEnC,MAAM,YAAY,KAAK,SAAS,KAAK;CACrC,IAAI,OAAO,KAAK;CAChB,IAAI,KAAK,KAAK;CACd,IAAI,aAAa,WAAW,QAAQ;CACpC,IAAI,WAAW,MAAM;CACrB,IAAI,CAAC,aAAa,SAAS,MAAM;CACjC,OAAO,OAAO,OAAO;EAAE,GAAG;EAAM;EAAM;CAAG,CAAC;AAC5C;AAEA,SAAS,wBACP,UACA,MACA,YACS;CACT,IAAI,CAAC,oBAAoB,UAAU,KAAK,IAAI,GAAG,OAAO;CACtD,KAAK,WAAW,KAAK,IAAI,KAAK,IAAI,KAAK,KAAK,GAAG,OAAO;CACtD,OAAO,CAAC,eAAe,KAAK,KAAK,WAAW,CAAC,CAAC;AAChD;AAEA,SAAS,sBACP,UACA,MACA,YACS;CACT,IAAI,CAAC,oBAAoB,UAAU,KAAK,EAAE,GAAG,OAAO;CACpD,KAAK,WAAW,OAAO,IAAI,KAAK,EAAE,KAAK,KAAK,GAAG,OAAO;CACtD,OAAO,CAAC,gBAAgB,KAAK,KAAK,WAAW,KAAK,KAAK,SAAS,CAAC,CAAC;AACpE;AAEA,SAAS,oBAAoB,UAA8B,QAAyB;CAClF,IAAI,UAAU,KAAK,UAAU,SAAS,QAAQ,OAAO;CACrD,MAAM,OAAO,wBAAwB,UAAU,SAAS,GAAG,SAAS,CAAC;CACrE,OAAO,gBAAgB,KAAK,WAAW,CAAC,CAAC,KAAK,eAAe,KAAK,WAAW,CAAC,CAAC;AACjF;AAEA,SAAS,oBAAoB,OAAoE;CAC/F,MAAM,yBAAS,IAAI,IAAoB;CACvC,MAAM,uBAAO,IAAI,IAAoB;CACrC,KAAK,MAAM,EAAE,UAAU,OAAO;EAC5B,IAAI,KAAK,SAAS,KAAK,IAAI;EAC3B,OAAO,IAAI,KAAK,OAAO,OAAO,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;EACtD,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;CAChD;CACA,OAAO;EAAE;EAAM;CAAO;AACxB;AAEA,SAAS,4BACP,OACA,OACA,gBACA,oBACM;CACN,IAAI,CAAC,gCAAgC,gBAAgB,MAAM,QAAQ,GAAG;CACtE,MAAM,WAAW;CACjB,MAAM,eAAe;CAErB,MAAM,OAAO,MAAM,GAAG,EAAE;CACxB,IAAI,CAAC,MAAM;CACX,MAAM,MAAM,SAAS,KAAK,OAAO,OAAO;EAAE,GAAG;EAAM,eAAe;CAAe,CAAC;AACpF;AAEA,SAAS,cACP,sBACA,SACA;CACA,MAAM,OAAO,wBAAwB,QAAQ,gBAAgB,QAAQ,aAAa;CAClF,OAAO;EACL,OAAO,OAAO,CAAC,IAAI,IAAI,CAAC;EACxB,sBAAsB,QAAQ;EAC9B;CACF;AACF;AAEA,SAAS,sBACP,UACA,QACS;CACT,OACE,SAAS,qBAAqB,OAAO,oBACrC,SAAS,mBAAmB,OAAO,gBAAgB;AAEvD;AAEA,SAAS,iBACP,WACA,UACyC;CACzC,OAAO,OAAO,OAAO,UAAU,KAAK,YAAY,YAAY,SAAS,MAAM,UAAU,QAAQ,CAAC,CAAC;AACjG;AAEA,SAAS,qBACP,WACA,UACyC;CACzC,MAAM,QAAwC,CAAC;CAC/C,IAAI,uBAAuB;CAC3B,IAAI,WAAW,SAAS;CACxB,KAAK,MAAM,WAAW,WAAW;EAC/B,IAAI,QAAQ,yBAAyB,GAAG;GACtC,MAAM,KAAK,YAAY,SAAS,MAAM,UAAU,QAAQ,CAAC;GACzD;EACF;EAEA,MAAM,WAAW,SAAS,SAAS;EACnC,MAAM,KACJ,YAAY,SAAS,sBAAsB,SAAS,gBAAgB,SAAS,aAAa,CAC5F;EACA,WAAW,SAAS;EACpB,wBAAwB;CAC1B;CACA,OAAO,OAAO,OAAO,KAAK;AAC5B;AAEA,SAAS,YACP,SACA,sBACA,gBACA,eAC8B;CAC9B,OAAO,OAAO,OAAO;EACnB,GAAG;EACH;EACA;EACA;EACA,OAAO,mBAAmB,QAAQ,OAAO,gBAAgB,aAAa;CACxE,CAAC;AACH;AAEA,SAAS,mBACP,OACA,gBACA,eACsC;CACtC,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,YAAY,MAAM,SAAS;CACjC,OAAO,OAAO,OACZ,MAAM,KAAK,MAAM,UACf,OAAO,OAAO;EACZ,GAAG;EACH,eAAe,UAAU,YAAY,gBAAgB,KAAK;EAC1D,gBAAgB,UAAU,IAAI,iBAAiB,KAAK;CACtD,CAAC,CACH,CACF;AACF;AAEA,SAAS,gBACP,YACA,KACA,cACwC;CACxC,OACE,WAAW,MAAM,UAAU,MAAM,QAAQ,OAAO,MAAM,iBAAiB,YAAY,KAAK;AAE5F;AAEA,SAAS,uBACP,YAC+C;CAC/C,OAAO,eAAe,QAAQ,OAAO,cAAc,WAAW,OAAO;AACvE;AAEA,SAAS,0BAA0B,MAA2C;CAC5E,OAAO,OAAO,OAAO;EAAE,MAAM,KAAK;EAAM,MAAM,KAAK;EAAM,IAAI,KAAK;CAAG,CAAC;AACxE;AAEA,SAAS,oBACP,MACA,OACQ;CACR,OAAO,KAAK,KAAK,OAAO,MAAM,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM,KAAK;AACvE;AAEA,SAAS,sBAAsB,MAAsB;CACnD,OAAO,mBAAmB,KAAK,IAAI,IAAI,KAAK,QAAQ,0BAA0B,IAAI,IAAI;AACxF;AAEA,SAAS,gBAAgB,MAAuB;CAC9C,OAAO,QAAQ,SAAU,QAAQ;AACnC;AAEA,SAAS,eAAe,MAAuB;CAC7C,OAAO,QAAQ,SAAU,QAAQ;AACnC;AAEA,SAAS,gBACP,gBACA,WACA,QAC8D;CAC9D,OAAO,aAAa,oBAAoB,QAAQ,gBAAgB,SAAS;AAC3E;AAEA,SAAS,aACP,MACA,QACA,gBACA,WAC8D;CAC9D,OAAO;EACL,OAAO,QAAQ,MAAM,QAAQ;GAAE;GAAW;EAAe,CAAC;EAC1D,IAAI;CACN;AACF;AAEA,SAAS,QACP,MACA,QACA,UAA6E,CAAC,GACxD;CACtB,OAAO,OAAO,OAAO;EACnB;EACA;EACA,GAAI,QAAQ,mBAAmB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,QAAQ,eAAe;EACzF,GAAI,QAAQ,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;CAC5E,CAAC;AACH"}
|
package/package.json
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@singapore-editor/lsp-plugin",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"files": [
|
|
5
|
+
"README.md",
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"type": "module",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./completion": {
|
|
17
|
+
"types": "./dist/completion.d.ts",
|
|
18
|
+
"import": "./dist/completion.js",
|
|
19
|
+
"default": "./dist/completion.js"
|
|
20
|
+
},
|
|
21
|
+
"./completion-controller": {
|
|
22
|
+
"types": "./dist/completionController.d.ts",
|
|
23
|
+
"import": "./dist/completionController.js",
|
|
24
|
+
"default": "./dist/completionController.js"
|
|
25
|
+
},
|
|
26
|
+
"./definition-link-controller": {
|
|
27
|
+
"types": "./dist/definitionLinkController.d.ts",
|
|
28
|
+
"import": "./dist/definitionLinkController.js",
|
|
29
|
+
"default": "./dist/definitionLinkController.js"
|
|
30
|
+
},
|
|
31
|
+
"./definition-navigation": {
|
|
32
|
+
"types": "./dist/definitionNavigation.d.ts",
|
|
33
|
+
"import": "./dist/definitionNavigation.js",
|
|
34
|
+
"default": "./dist/definitionNavigation.js"
|
|
35
|
+
},
|
|
36
|
+
"./diagnostics": {
|
|
37
|
+
"types": "./dist/diagnostics.d.ts",
|
|
38
|
+
"import": "./dist/diagnostics.js",
|
|
39
|
+
"default": "./dist/diagnostics.js"
|
|
40
|
+
},
|
|
41
|
+
"./diagnostics-presenter": {
|
|
42
|
+
"types": "./dist/diagnosticsPresenter.d.ts",
|
|
43
|
+
"import": "./dist/diagnosticsPresenter.js",
|
|
44
|
+
"default": "./dist/diagnosticsPresenter.js"
|
|
45
|
+
},
|
|
46
|
+
"./document-sync": {
|
|
47
|
+
"types": "./dist/documentSync.d.ts",
|
|
48
|
+
"import": "./dist/documentSync.js",
|
|
49
|
+
"default": "./dist/documentSync.js"
|
|
50
|
+
},
|
|
51
|
+
"./document-sync-controller": {
|
|
52
|
+
"types": "./dist/documentSyncController.d.ts",
|
|
53
|
+
"import": "./dist/documentSyncController.js",
|
|
54
|
+
"default": "./dist/documentSyncController.js"
|
|
55
|
+
},
|
|
56
|
+
"./hover-participant": {
|
|
57
|
+
"types": "./dist/hoverParticipant.d.ts",
|
|
58
|
+
"import": "./dist/hoverParticipant.js",
|
|
59
|
+
"default": "./dist/hoverParticipant.js"
|
|
60
|
+
},
|
|
61
|
+
"./paths": {
|
|
62
|
+
"types": "./dist/paths.d.ts",
|
|
63
|
+
"import": "./dist/paths.js",
|
|
64
|
+
"default": "./dist/paths.js"
|
|
65
|
+
},
|
|
66
|
+
"./plugin-styles": {
|
|
67
|
+
"types": "./dist/plugin.styles.d.ts",
|
|
68
|
+
"import": "./dist/plugin.styles.js",
|
|
69
|
+
"default": "./dist/plugin.styles.js"
|
|
70
|
+
},
|
|
71
|
+
"./plugin-types": {
|
|
72
|
+
"types": "./dist/pluginTypes.d.ts",
|
|
73
|
+
"import": "./dist/pluginTypes.js",
|
|
74
|
+
"default": "./dist/pluginTypes.js"
|
|
75
|
+
},
|
|
76
|
+
"./websocket": {
|
|
77
|
+
"types": "./dist/websocket.d.ts",
|
|
78
|
+
"import": "./dist/websocket.js",
|
|
79
|
+
"default": "./dist/websocket.js"
|
|
80
|
+
},
|
|
81
|
+
"./workspace-edit": {
|
|
82
|
+
"types": "./dist/workspaceEdit.d.ts",
|
|
83
|
+
"import": "./dist/workspaceEdit.js",
|
|
84
|
+
"default": "./dist/workspaceEdit.js"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"publishConfig": {
|
|
88
|
+
"access": "public",
|
|
89
|
+
"registry": "https://registry.npmjs.org/"
|
|
90
|
+
},
|
|
91
|
+
"scripts": {
|
|
92
|
+
"build": "bun ../../scripts/build-package.ts",
|
|
93
|
+
"test": "vitest run --passWithNoTests",
|
|
94
|
+
"typecheck": "tsgo --noEmit",
|
|
95
|
+
"lint": "oxlint .",
|
|
96
|
+
"format": "oxfmt --write .",
|
|
97
|
+
"format:check": "oxfmt --check ."
|
|
98
|
+
},
|
|
99
|
+
"dependencies": {
|
|
100
|
+
"@singapore-editor/lsp": "0.1.1",
|
|
101
|
+
"@singapore-editor/plugin-ui": "0.1.0",
|
|
102
|
+
"vscode-languageserver-protocol": "^3.18.4"
|
|
103
|
+
},
|
|
104
|
+
"devDependencies": {
|
|
105
|
+
"@singapore-editor/core": "0.1.2",
|
|
106
|
+
"@singapore-editor/find": "0.1.1",
|
|
107
|
+
"@singapore-editor/scope-lines": "0.1.1",
|
|
108
|
+
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
109
|
+
"happy-dom": "^20.14.5",
|
|
110
|
+
"oxfmt": "0.70.0",
|
|
111
|
+
"oxlint": "1.85.0",
|
|
112
|
+
"typescript": "~6.0.3",
|
|
113
|
+
"vitest": "^5.0.2"
|
|
114
|
+
},
|
|
115
|
+
"peerDependencies": {
|
|
116
|
+
"@singapore-editor/core": "0.1.2"
|
|
117
|
+
}
|
|
118
|
+
}
|