[html] use TextDocument.applyEdit

This commit is contained in:
Martin Aeschlimann 2018-03-15 15:22:44 +01:00
parent 4d78742a99
commit 7c5f344a2b
6 changed files with 10 additions and 102 deletions

View file

@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { applyEdits } from '../utils/edits';
import { TextDocument, Range, TextEdit, FormattingOptions, Position } from 'vscode-languageserver-types';
import { LanguageModes, Settings, LanguageModeRange } from './languageModes';
import { pushAll } from '../utils/arrays';
@ -57,7 +56,7 @@ export function format(languageModes: LanguageModes, document: TextDocument, for
// perform a html format and apply changes to a new document
let htmlMode = languageModes.getMode('html')!;
let htmlEdits = htmlMode.format!(document, formatRange, formattingOptions, settings);
let htmlFormattedContent = applyEdits(document, htmlEdits);
let htmlFormattedContent = TextDocument.applyEdits(document, htmlEdits);
let newDocument = TextDocument.create(document.uri + '.tmp', document.languageId, document.version, htmlFormattedContent);
try {
// run embedded formatters on html formatted content: - formatters see correct initial indent
@ -83,7 +82,7 @@ export function format(languageModes: LanguageModes, document: TextDocument, for
}
// apply all embedded format edits and create a single edit for all changes
let resultContent = applyEdits(newDocument, embeddedEdits);
let resultContent = TextDocument.applyEdits(newDocument, embeddedEdits);
let resultReplaceText = resultContent.substring(document.offsetAt(formatRange.start), resultContent.length - afterFormatRangeLength);
result.push(TextEdit.replace(formatRange, resultReplaceText));

View file

@ -10,7 +10,6 @@ import * as path from 'path';
import Uri from 'vscode-uri';
import { TextDocument, CompletionList, CompletionItemKind, } from 'vscode-languageserver-types';
import { getLanguageModes } from '../modes/languageModes';
import { applyEdits } from '../utils/edits';
import { getPathCompletionParticipant } from '../modes/pathCompletion';
import { WorkspaceFolder } from 'vscode-languageserver';
@ -43,7 +42,7 @@ suite('Completions', () => {
assert.equal(match.kind, expected.kind);
}
if (expected.resultText && match.textEdit) {
assert.equal(applyEdits(document, [match.textEdit]), expected.resultText);
assert.equal(TextDocument.applyEdits(document, [match.textEdit]), expected.resultText);
}
};

View file

@ -26,16 +26,16 @@ suite('Emmet Support', () => {
const document = TextDocument.create('test://test/test.' + syntax, syntax, 0, value);
const position = document.positionAt(offset);
const documentRegions = getLanguageModelCache<embeddedSupport.HTMLDocumentRegions>(10, 60, document => embeddedSupport.getDocumentRegions(htmlLanguageService, document));
const mode = syntax == 'html' ? getHTMLMode(htmlLanguageService) : getCSSMode(documentRegions);
const mode = syntax === 'html' ? getHTMLMode(htmlLanguageService) : getCSSMode(documentRegions);
const emmetCompletionList: CompletionList = {
isIncomplete: true,
items: undefined
}
mode.setCompletionParticipants([getEmmetCompletionParticipants(document, position, document.languageId, {}, emmetCompletionList)])
};
mode.setCompletionParticipants([getEmmetCompletionParticipants(document, position, document.languageId, {}, emmetCompletionList)]);
const list = mode.doComplete!(document, position);
assert.ok(list);
assert.ok(emmetCompletionList)
assert.ok(emmetCompletionList);
if (expectedProposal && expectedProposalDoc) {

View file

@ -10,7 +10,7 @@ import * as fs from 'fs';
import * as assert from 'assert';
import { getLanguageModes } from '../modes/languageModes';
import { TextDocument, Range, TextEdit, FormattingOptions } from 'vscode-languageserver-types';
import { TextDocument, Range, FormattingOptions } from 'vscode-languageserver-types';
import { format } from '../modes/formatting';
@ -41,7 +41,7 @@ suite('HTML Embedded Formatting', () => {
let result = format(languageModes, document, range, formatOptions, void 0, { css: true, javascript: true });
let actual = applyEdits(document, result);
let actual = TextDocument.applyEdits(document, result);
assert.equal(actual, expected, message);
}
@ -111,25 +111,4 @@ suite('HTML Embedded Formatting', () => {
assertFormat('<script src="/js/main.js"> </script>', '<script src="/js/main.js"> </script>');
});
});
function applyEdits(document: TextDocument, edits: TextEdit[]): string {
let text = document.getText();
let sortedEdits = edits.sort((a, b) => {
let startDiff = document.offsetAt(b.range.start) - document.offsetAt(a.range.start);
if (startDiff === 0) {
return document.offsetAt(b.range.end) - document.offsetAt(a.range.end);
}
return startDiff;
});
let lastOffset = text.length;
sortedEdits.forEach(e => {
let startOffset = document.offsetAt(e.range.start);
let endOffset = document.offsetAt(e.range.end);
assert.ok(startOffset <= endOffset);
assert.ok(endOffset <= lastOffset);
text = text.substring(0, startOffset) + e.newText + text.substring(endOffset, text.length);
lastOffset = startOffset;
});
return text;
}
});

View file

@ -1,37 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { applyEdits } from '../utils/edits';
import { TextDocument, TextEdit, Position, Range } from 'vscode-languageserver-types';
suite('Edits', () => {
test('inserts', function (): any {
let input = TextDocument.create('foo://bar/f', 'html', 0, '012345678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.insert(Position.create(0, 0), 'Hello')]), 'Hello012345678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.insert(Position.create(0, 1), 'Hello')]), '0Hello12345678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.insert(Position.create(0, 1), 'Hello'), TextEdit.insert(Position.create(0, 1), 'World')]), '0HelloWorld12345678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.insert(Position.create(0, 2), 'One'), TextEdit.insert(Position.create(0, 1), 'Hello'), TextEdit.insert(Position.create(0, 1), 'World'), TextEdit.insert(Position.create(0, 2), 'Two'), TextEdit.insert(Position.create(0, 2), 'Three')]), '0HelloWorld1OneTwoThree2345678901234567890123456789');
});
test('replace', function (): any {
let input = TextDocument.create('foo://bar/f', 'html', 0, '012345678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.replace(Range.create(Position.create(0, 3), Position.create(0, 6)), 'Hello')]), '012Hello678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.replace(Range.create(Position.create(0, 3), Position.create(0, 6)), 'Hello'), TextEdit.replace(Range.create(Position.create(0, 6), Position.create(0, 9)), 'World')]), '012HelloWorld901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.replace(Range.create(Position.create(0, 3), Position.create(0, 6)), 'Hello'), TextEdit.insert(Position.create(0, 6), 'World')]), '012HelloWorld678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.insert(Position.create(0, 6), 'World'), TextEdit.replace(Range.create(Position.create(0, 3), Position.create(0, 6)), 'Hello')]), '012HelloWorld678901234567890123456789');
assert.equal(applyEdits(input, [TextEdit.insert(Position.create(0, 3), 'World'), TextEdit.replace(Range.create(Position.create(0, 3), Position.create(0, 6)), 'Hello')]), '012WorldHello678901234567890123456789');
});
test('overlap', function (): any {
let input = TextDocument.create('foo://bar/f', 'html', 0, '012345678901234567890123456789');
assert.throws(_ => applyEdits(input, [TextEdit.replace(Range.create(Position.create(0, 3), Position.create(0, 6)), 'Hello'), TextEdit.insert(Position.create(0, 3), 'World')]));
assert.throws(_ => applyEdits(input, [TextEdit.replace(Range.create(Position.create(0, 3), Position.create(0, 6)), 'Hello'), TextEdit.insert(Position.create(0, 4), 'World')]));
});
});

View file

@ -1,32 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TextDocument, TextEdit } from 'vscode-languageserver-types';
import { mergeSort } from './arrays';
export function applyEdits(document: TextDocument, edits: TextEdit[]): string {
let text = document.getText();
let sortedEdits = mergeSort(edits, (a, b) => {
let diff = a.range.start.line - b.range.start.line;
if (diff === 0) {
return a.range.start.character - b.range.start.character;
}
return 0;
});
let lastModifiedOffset = text.length;
for (let i = sortedEdits.length - 1; i >= 0; i--) {
let e = sortedEdits[i];
let startOffset = document.offsetAt(e.range.start);
let endOffset = document.offsetAt(e.range.end);
if (endOffset <= lastModifiedOffset) {
text = text.substring(0, startOffset) + e.newText + text.substring(endOffset, text.length);
} else {
throw new Error('Ovelapping edit');
}
lastModifiedOffset = startOffset;
}
return text;
}