/
textEdit.ts
84 lines (76 loc) · 2.29 KB
/
textEdit.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import * as vscode from 'vscode-languageserver-types';
export function transform<T extends vscode.TextEdit | vscode.InsertReplaceEdit>(
textEdit: T,
getOtherRange: (range: vscode.Range) => vscode.Range | undefined,
document: vscode.TextDocument,
): T | undefined {
if (vscode.TextEdit.is(textEdit)) {
let range = getOtherRange(textEdit.range);
if (range) {
return {
...textEdit,
range,
};
};
const cover = tryRecover(getOtherRange, textEdit.range, textEdit.newText, document);
if (cover) {
return {
...textEdit,
range: cover.range,
newText: cover.newText,
};
}
}
else if (vscode.InsertReplaceEdit.is(textEdit)) {
const insert = getOtherRange(textEdit.insert);
const replace = insert ? getOtherRange(textEdit.replace) : undefined;
if (insert && replace) {
return {
...textEdit,
insert,
replace,
};
}
const recoverInsert = tryRecover(getOtherRange, textEdit.insert, textEdit.newText, document);
const recoverReplace = recoverInsert ? tryRecover(getOtherRange, textEdit.replace, textEdit.newText, document) : undefined;
if (recoverInsert && recoverReplace && recoverInsert.newText === recoverReplace.newText) {
return {
...textEdit,
insert: recoverInsert.range,
replace: recoverReplace.range,
newText: recoverInsert.newText,
};
}
}
}
/**
* update edit text from ". foo" to " foo"
* fix https://github.com/johnsoncodehk/volar/issues/2155
*/
function tryRecover(
getOtherRange: (range: vscode.Range) => vscode.Range | undefined,
replaceRange: vscode.Range,
newText: string,
document: vscode.TextDocument,
): vscode.TextEdit | undefined {
if (replaceRange.start.line === replaceRange.end.line && replaceRange.end.character > replaceRange.start.character) {
let character = replaceRange.start.character;
while (newText.length && replaceRange.end.character > character) {
const newStart = { line: replaceRange.start.line, character: replaceRange.start.character + 1 };
if (document.getText({ start: replaceRange.start, end: newStart }) === newText[0]) {
newText = newText.slice(1);
character++;
const otherRange = getOtherRange({ start: newStart, end: replaceRange.end });
if (otherRange) {
return {
newText,
range: otherRange,
};
}
}
else {
break;
}
}
}
}