Try harder to be incremental in editContent

This commit is contained in:
Tony Garnock-Jones 2023-05-03 18:20:26 +03:00
parent 1f72baf3ad
commit aafb654687
1 changed files with 81 additions and 3 deletions

View File

@ -232,20 +232,98 @@ const boot: tslib.server.PluginModuleFactory = ({ typescript: ts }) => {
ts.createSourceFile = createSourceFile;
}
{
const oldUpdateSourceFile = ts.updateSourceFile;
function commonPrefixLength(a: string, b: string): number {
const limit = Math.min(a.length, b.length);
for (let i = 0; i < limit; i++) {
if (a[i] !== b[i]) return i;
}
return limit;
}
function commonSuffixLength(a: string, b: string): number {
const limit = Math.min(a.length, b.length);
for (let i = 0; i < limit; i++) {
if (a[a.length - i - 1] !== b[b.length - i - 1]) return i;
}
return limit;
}
function updateSourceFile(
sourceFile: ts.SourceFile,
newText: string,
textChangeRange: ts.TextChangeRange,
aggressiveChecks?: boolean,
): ts.SourceFile {
return withFileName(
sourceFile.fileName,
() => oldUpdateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks),
(fx) => {
const oldInfo = fx.info;
return expandFile(
sourceFile.fileName,
oldInfo.originalSource,
(newExpandedText) => {
const oldExpandedText = oldInfo.sourceFile.text;
if (oldExpandedText === newExpandedText) {
// console.log('updateSourceFile', 'no change');
return oldInfo.sourceFile;
} else {
const prefix = commonPrefixLength(oldExpandedText, newExpandedText);
const suffix =
commonSuffixLength(oldExpandedText.substring(prefix),
newExpandedText.substring(prefix));
const newChangeRange = {
span: {
start: prefix,
length: oldExpandedText.length - prefix - suffix,
},
newLength: newExpandedText.length - prefix - suffix,
} satisfies ts.TextChangeRange;
// console.log('updateSourceFile', JSON.stringify({
// oldSyndicateText: oldInfo.originalSource,
// newSyndicateText: newText,
// oldExpandedText,
// newExpandedText,
// oldLength: oldExpandedText.length,
// newLength: newExpandedText.length,
// oldChangeRange: textChangeRange,
// newChangeRange,
// prefix,
// suffix,
// }, void 0, 2));
return oldUpdateSourceFile(
sourceFile, newExpandedText, newChangeRange, aggressiveChecks);
}
});
});
}
ts.updateSourceFile = updateSourceFile;
}
{
const oldEditContent = ts.server.ScriptInfo.prototype.editContent;
ts.server.ScriptInfo.prototype.editContent =
function (start: number, end: number, newText: string): void {
// console.log('SyndicateScriptInfo.editContent', this.fileName, start, end, newText);
// console.log('SyndicateScriptInfo.editContent', JSON.stringify({
// fileName: this.fileName,
// start,
// end,
// newText,
// oldText: (this as any).textStorage.text ?? ["MISSING"],
// }, void 0, 2));
withFileName(this.fileName,
() => oldEditContent(start, end, newText),
() => oldEditContent.call(this, start, end, newText),
(fx) => {
const info = fx.info;
const revised = info.originalSource.substring(0, start) +
newText +
info.originalSource.substring(end);
info.originalSource = revised;
this.open(revised);
oldEditContent.call(this, start, end, newText);
});
};
}