This commit is contained in:
Johannes Rieken 2018-01-29 10:12:17 +01:00
parent 6eaed2d20d
commit f13654c5a5
2 changed files with 46 additions and 24 deletions

View file

@ -444,8 +444,7 @@ export class SnippetSession {
return false;
}
let ranges: Range[] = [];
let placeholderIndex: number = -1;
let allPossibleSelections: Map<number, Range[]>;
for (const snippet of this._snippets) {
const possibleSelections = snippet.computePossibleSelections();
@ -453,49 +452,58 @@ export class SnippetSession {
// for the first snippet find the placeholder (and its ranges)
// that contain at least one selection. for all remaining snippets
// the same placeholder (and their ranges) must be used.
if (placeholderIndex < 0) {
if (!allPossibleSelections) {
allPossibleSelections = new Map<number, Range[]>();
possibleSelections.forEach((ranges, index) => {
if (placeholderIndex >= 0) {
return;
}
ranges.sort(Range.compareRangesUsingStarts);
for (const selection of selections) {
if (ranges[0].containsRange(selection)) {
placeholderIndex = index;
allPossibleSelections.set(index, []);
break;
}
}
});
}
if (placeholderIndex < 0) {
if (allPossibleSelections.size === 0) {
// return false if we couldn't associate a selection to
// this (the first) snippet
return false;
}
ranges.push(...possibleSelections.get(placeholderIndex));
// add selections from 'this' snippet so that we know all
// selections for this placeholder
allPossibleSelections.forEach((array, index) => {
array.push(...possibleSelections.get(index));
});
}
if (selections.length !== ranges.length) {
// this means we started at a placeholder with N
// ranges and new have M (N > M) selections.
// So (at least) one placeholder is without selection -> cancel
return false;
}
// also sort (placeholder)-ranges. then walk both arrays and
// make sure the placeholder-ranges contain the corresponding
// sort selections (and later placeholder-ranges). then walk both
// arrays and make sure the placeholder-ranges contain the corresponding
// selection
selections.sort(Range.compareRangesUsingStarts);
ranges.sort(Range.compareRangesUsingStarts);
for (let i = 0; i < ranges.length; i++) {
if (!ranges[i].containsRange(selections[i])) {
return false;
allPossibleSelections.forEach((ranges, index) => {
if (ranges.length !== selections.length) {
allPossibleSelections.delete(index);
return;
}
}
return true;
ranges.sort(Range.compareRangesUsingStarts);
for (let i = 0; i < ranges.length; i++) {
if (!ranges[i].containsRange(selections[i])) {
allPossibleSelections.delete(index);
return;
}
}
});
// from all possible selections we have deleted those
// that don't match with the current selection. if we don't
// have any left, we don't have a selection anymore
return allPossibleSelections.size > 0;
}
}

View file

@ -303,4 +303,18 @@ suite('SnippetController2', function () {
assertSelections(editor, new Selection(2, 9, 2, 9), new Selection(1, 7, 1, 7));
assertContextKeys(contextKeys, true, false, true);
});
test('“Nested” snippets terminating abruptly in VSCode 1.19.2. #42012', function () {
const ctrl = new SnippetController2(editor, logService, contextKeys);
model.setValue('');
editor.setSelection(new Selection(1, 1, 1, 1));
ctrl.insert('var ${2:${1:name}} = ${1:name} + 1;${0}');
assertSelections(editor, new Selection(1, 5, 1, 9), new Selection(1, 12, 1, 16));
assertContextKeys(contextKeys, true, false, true);
ctrl.next();
assertContextKeys(contextKeys, true, true, true);
});
});