astro-ghostcms/.pnpm-store/v3/files/0b/0a11909c19d46e635ed6c35a0e0...

138 lines
5.2 KiB
Plaintext

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SnapshotDocument = void 0;
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
const combine_1 = require("./combine");
class SnapshotDocument {
constructor(uri, languageId, version, text) {
this.snapshots = [];
this.document = vscode_languageserver_textdocument_1.TextDocument.create(uri, languageId, version, text);
this.resetChanges();
}
get uri() {
return this.document.uri;
}
get languageId() {
return this.document.languageId;
}
get version() {
return this.document.version;
}
get lineCount() {
return this.document.lineCount;
}
getText(range) {
return this.document.getText(range);
}
positionAt(offset) {
return this.document.positionAt(offset);
}
offsetAt(position) {
return this.document.offsetAt(position);
}
/**
* Update the document with the given content changes and version.
* If all changes is incremental, calculate the change range and add a new snapshot.
* Otherwise, reset the changes.
*/
update(contentChanges, version) {
if (contentChanges.every(change => 'range' in change)) {
const { minStart, oldLength, lengthDiff } = this.calculateChangeRange(contentChanges);
vscode_languageserver_textdocument_1.TextDocument.update(this.document, contentChanges, version);
this.snapshots.push({
changeRange: {
span: {
start: minStart,
length: oldLength,
},
newLength: oldLength + lengthDiff,
},
version,
ref: undefined,
});
}
else {
vscode_languageserver_textdocument_1.TextDocument.update(this.document, contentChanges, version);
this.resetChanges();
}
}
getSnapshot() {
this.clearUnreferencedVersions();
const lastChange = this.snapshots[this.snapshots.length - 1];
if (!lastChange.ref) {
const text = this.document.getText();
const changeRangeCache = new WeakMap();
const snapshot = {
getText: (start, end) => text.substring(start, end),
getLength: () => text.length,
getChangeRange: oldSnapshot => {
if (!changeRangeCache.has(oldSnapshot)) {
const oldIndex = this.snapshots.findIndex(change => change.ref?.deref() === oldSnapshot);
if (oldIndex >= 0) {
const start = oldIndex + 1;
const end = this.snapshots.indexOf(lastChange) + 1;
const changeRanges = this.snapshots
.slice(start, end)
.map(change => change.changeRange);
const changeRange = (0, combine_1.combineChangeRanges)(...changeRanges);
changeRangeCache.set(oldSnapshot, changeRange);
}
else {
changeRangeCache.set(oldSnapshot, undefined);
}
}
return changeRangeCache.get(oldSnapshot);
},
};
lastChange.ref = new WeakRef(snapshot);
}
return lastChange.ref.deref();
}
resetChanges() {
this.snapshots = [
{
changeRange: {
span: {
start: 0,
length: 0,
},
newLength: this.document.getText().length,
},
version: this.document.version,
ref: undefined,
}
];
}
/**
* Calculate the change range from the given content changes.
*/
calculateChangeRange(contentChanges) {
let lengthDiff = 0;
const starts = [];
const ends = [];
for (const contentChange of contentChanges) {
if (!('range' in contentChange)) {
continue;
}
const start = this.offsetAt(contentChange.range.start);
const length = contentChange.rangeLength ?? this.offsetAt(contentChange.range.end) - start;
const end = start + length;
starts.push(start);
ends.push(end);
lengthDiff += contentChange.text.length - length;
}
const minStart = Math.min(...starts);
const maxEnd = Math.max(...ends);
const oldLength = maxEnd - minStart;
return { minStart, oldLength, lengthDiff };
}
clearUnreferencedVersions() {
let firstReferencedIndex = 0;
while (firstReferencedIndex < this.snapshots.length - 1 && !this.snapshots[firstReferencedIndex].ref?.deref()) {
firstReferencedIndex++;
}
this.snapshots = this.snapshots.slice(firstReferencedIndex);
}
}
exports.SnapshotDocument = SnapshotDocument;
//# sourceMappingURL=snapshotDocument.js.map