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; return false;
} }
let ranges: Range[] = []; let allPossibleSelections: Map<number, Range[]>;
let placeholderIndex: number = -1;
for (const snippet of this._snippets) { for (const snippet of this._snippets) {
const possibleSelections = snippet.computePossibleSelections(); const possibleSelections = snippet.computePossibleSelections();
@ -453,49 +452,58 @@ export class SnippetSession {
// for the first snippet find the placeholder (and its ranges) // for the first snippet find the placeholder (and its ranges)
// that contain at least one selection. for all remaining snippets // that contain at least one selection. for all remaining snippets
// the same placeholder (and their ranges) must be used. // the same placeholder (and their ranges) must be used.
if (placeholderIndex < 0) { if (!allPossibleSelections) {
allPossibleSelections = new Map<number, Range[]>();
possibleSelections.forEach((ranges, index) => { possibleSelections.forEach((ranges, index) => {
if (placeholderIndex >= 0) {
return;
}
ranges.sort(Range.compareRangesUsingStarts); ranges.sort(Range.compareRangesUsingStarts);
for (const selection of selections) { for (const selection of selections) {
if (ranges[0].containsRange(selection)) { if (ranges[0].containsRange(selection)) {
placeholderIndex = index; allPossibleSelections.set(index, []);
break; break;
} }
} }
}); });
} }
if (placeholderIndex < 0) { if (allPossibleSelections.size === 0) {
// return false if we couldn't associate a selection to // return false if we couldn't associate a selection to
// this (the first) snippet // this (the first) snippet
return false; 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) { // sort selections (and later placeholder-ranges). then walk both
// this means we started at a placeholder with N // arrays and make sure the placeholder-ranges contain the corresponding
// 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
// selection // selection
selections.sort(Range.compareRangesUsingStarts); selections.sort(Range.compareRangesUsingStarts);
ranges.sort(Range.compareRangesUsingStarts);
for (let i = 0; i < ranges.length; i++) { allPossibleSelections.forEach((ranges, index) => {
if (!ranges[i].containsRange(selections[i])) {
return false; 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)); assertSelections(editor, new Selection(2, 9, 2, 9), new Selection(1, 7, 1, 7));
assertContextKeys(contextKeys, true, false, true); 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);
});
}); });