first cut of more minimal text edits

This commit is contained in:
Johannes Rieken 2016-08-08 18:44:36 +02:00
parent 58de2a3239
commit f4c18ebb73

View file

@ -6,6 +6,7 @@
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {ISequence, LcsDiff, IDiffChange} from 'vs/base/common/diff/diff';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import * as vscode from 'vscode';
@ -324,6 +325,18 @@ class QuickFixAdapter {
}
}
function createStringSequence(a: string): ISequence {
return {
getLength() { return a.length; },
getElementHash(pos: number) { return a[pos]; }
};
}
function stringDiff(a: string, b: string): IDiffChange[] {
return new LcsDiff(createStringSequence(a), createStringSequence(b)).ComputeDiff();
}
class DocumentFormattingAdapter {
private _documents: ExtHostDocuments;
@ -336,14 +349,46 @@ class DocumentFormattingAdapter {
provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
let doc = this._documents.getDocumentData(resource).document;
const {document, version} = this._documents.getDocumentData(resource);
return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(document, <any>options, token)).then(value => {
return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(doc, <any>options, token)).then(value => {
if (Array.isArray(value)) {
value = DocumentFormattingAdapter.minimizeTextEdits(document, version, value);
return value.map(TypeConverters.TextEdit.from);
}
});
}
// todo@joh find a better place for this
// todo@joh reuse in other places
static minimizeTextEdits(document: vscode.TextDocument, beforeVersion: number, edits: vscode.TextEdit[]): vscode.TextEdit[] {
if (document.version !== beforeVersion) {
return edits;
}
const result: vscode.TextEdit[] = [];
for (let i = 0; i < edits.length; i++) {
const original = document.getText(edits[i].range);
const modified = edits[i].newText;
const changes = stringDiff(original, modified);
if (changes.length <= 1) {
result.push(edits[i]);
continue;
}
for (let j = 0; j < changes.length; j++) {
const {originalStart, originalLength, modifiedStart, modifiedLength} = changes[j];
const range = new Range(<any> document.positionAt(originalStart), <any> document.positionAt(originalStart + originalLength));
const newText = modified.substr(modifiedStart, modifiedLength);
result.push({ range, newText });
}
}
return result;
}
}
class RangeFormattingAdapter {