提交 d3e54fd2 编写于 作者: J Johannes Rieken

replace CodeSnippet-ctor with static factory method with fromTextMate, fromInternal, fromEmmet

上级 067a747b
......@@ -20,8 +20,6 @@ export interface ISnippetsRegistry {
*/
registerSnippets(modeId: string, snippets: ISnippet[], owner?: string): void;
/**
* Visit all snippets
*/
......
......@@ -117,7 +117,7 @@ export class DefineKeybindingController implements editorCommon.IEditorContribut
snippetText = smartInsertInfo.prepend + snippetText + smartInsertInfo.append;
this._editor.setPosition(smartInsertInfo.position);
SnippetController.get(this._editor).run(new CodeSnippet(snippetText), 0, 0);
SnippetController.get(this._editor).run(CodeSnippet.fromInternal(snippetText), 0, 0);
}
private _onModel(): void {
......
......@@ -5,60 +5,29 @@
'use strict';
import * as collections from 'vs/base/common/collections';
import * as strings from 'vs/base/common/strings';
import {Range} from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
interface IParsedLinePlaceHolderInfo {
id: string;
value: string;
startColumn: number;
endColumn: number;
}
interface IParsedLine {
line: string;
placeHolders: IParsedLinePlaceHolderInfo[];
}
export interface IPlaceHolder {
id: string;
value: string;
occurences: editorCommon.IRange[];
}
export interface IIndentationNormalizer {
normalizeIndentation(str: string): string;
}
export interface ICodeSnippet {
lines: string[];
placeHolders: IPlaceHolder[];
finishPlaceHolderIndex: number;
}
export enum ExternalSnippetType {
TextMateSnippet,
EmmetSnippet
}
import * as collections from 'vs/base/common/collections';
export class CodeSnippet implements ICodeSnippet {
private _lastGeneratedId: number;
public lines: string[];
public placeHolders: IPlaceHolder[];
public finishPlaceHolderIndex: number;
static fromTextmate(template:string):CodeSnippet {
return TextMateSnippetParser.parse(template);
}
constructor(snippetTemplate: string) {
this.lines = [];
this.placeHolders = [];
this._lastGeneratedId = 0;
this.finishPlaceHolderIndex = -1;
static fromEmmet(template: string): CodeSnippet {
return EmmetSnippetParser.parse(template);
}
this.parseTemplate(snippetTemplate);
static fromInternal(template: string): CodeSnippet {
return InternalFormatSnippetParser.parse(template);
}
public lines: string[] = [];
public placeHolders: IPlaceHolder[] = [];
public finishPlaceHolderIndex: number = -1;
get isInsertOnly(): boolean {
return this.placeHolders.length === 0;
}
......@@ -80,6 +49,104 @@ export class CodeSnippet implements ICodeSnippet {
return true;
}
private extractLineIndentation(str: string, maxColumn: number = Number.MAX_VALUE): string {
var fullIndentation = strings.getLeadingWhitespace(str);
if (fullIndentation.length > maxColumn - 1) {
return fullIndentation.substring(0, maxColumn - 1);
}
return fullIndentation;
}
public bind(referenceLine: string, deltaLine: number, firstLineDeltaColumn: number, config: IIndentationNormalizer): ICodeSnippet {
var resultLines: string[] = [];
var resultPlaceHolders: IPlaceHolder[] = [];
var referenceIndentation = this.extractLineIndentation(referenceLine, firstLineDeltaColumn + 1);
var originalLine: string, originalLineIndentation: string, remainingLine: string, indentation: string;
var i: number, len: number, j: number, lenJ: number;
// Compute resultLines & keep deltaColumns as a reference for adjusting placeholders
var deltaColumns: number[] = [];
for (i = 0, len = this.lines.length; i < len; i++) {
originalLine = this.lines[i];
if (i === 0) {
deltaColumns[i + 1] = firstLineDeltaColumn;
resultLines[i] = originalLine;
} else {
originalLineIndentation = this.extractLineIndentation(originalLine);
remainingLine = originalLine.substr(originalLineIndentation.length);
indentation = config.normalizeIndentation(referenceIndentation + originalLineIndentation);
deltaColumns[i + 1] = indentation.length - originalLineIndentation.length;
resultLines[i] = indentation + remainingLine;
}
}
// Compute resultPlaceHolders
var originalPlaceHolder: IPlaceHolder, originalOccurence: editorCommon.IRange, resultOccurences: editorCommon.IRange[];
for (i = 0, len = this.placeHolders.length; i < len; i++) {
originalPlaceHolder = this.placeHolders[i];
resultOccurences = [];
for (j = 0, lenJ = originalPlaceHolder.occurences.length; j < lenJ; j++) {
originalOccurence = originalPlaceHolder.occurences[j];
resultOccurences.push({
startLineNumber: originalOccurence.startLineNumber + deltaLine,
startColumn: originalOccurence.startColumn + deltaColumns[originalOccurence.startLineNumber],
endLineNumber: originalOccurence.endLineNumber + deltaLine,
endColumn: originalOccurence.endColumn + deltaColumns[originalOccurence.endLineNumber]
});
}
resultPlaceHolders.push({
id: originalPlaceHolder.id,
value: originalPlaceHolder.value,
occurences: resultOccurences
});
}
return {
lines: resultLines,
placeHolders: resultPlaceHolders,
finishPlaceHolderIndex: this.finishPlaceHolderIndex
};
}
}
// --- parsing
interface ISnippetParser {
parse(input: string): CodeSnippet;
}
interface IParsedLinePlaceHolderInfo {
id: string;
value: string;
startColumn: number;
endColumn: number;
}
interface IParsedLine {
line: string;
placeHolders: IParsedLinePlaceHolderInfo[];
}
const InternalFormatSnippetParser = new class implements ISnippetParser {
private _lastGeneratedId: number;
private _snippet: CodeSnippet;
parse(template: string): CodeSnippet {
this._lastGeneratedId = 0;
this._snippet = new CodeSnippet();
this.parseTemplate(template);
return this._snippet;
}
private parseTemplate(template: string): void {
var placeHoldersMap: collections.IStringDictionary<IPlaceHolder> = {};
......@@ -105,19 +172,19 @@ export class CodeSnippet implements ICodeSnippet {
value: linePlaceHolder.value,
occurences: []
};
this.placeHolders.push(placeHolder);
this._snippet.placeHolders.push(placeHolder);
placeHoldersMap[linePlaceHolder.id] = placeHolder;
}
placeHolder.occurences.push(occurence);
}
this.lines.push(parsedLine.line);
this._snippet.lines.push(parsedLine.line);
}
// Named variables (e.g. {greeting} and {greeting:Hello}) are sorted first, followed by
// tab-stops and numeric variables (e.g. $1, $2, ${3:foo}) which are sorted in ascending order
this.placeHolders.sort((a, b) => {
this._snippet.placeHolders.sort((a, b) => {
let nonIntegerId = (v: IPlaceHolder) => !(/^\d+$/).test(v.id);
let isFinishPlaceHolder = (v: IPlaceHolder) => v.id === '' && v.value === '';
......@@ -144,8 +211,8 @@ export class CodeSnippet implements ICodeSnippet {
return Number(a.id) < Number(b.id) ? -1 : 1;
});
if (this.placeHolders.length > 0 && this.placeHolders[this.placeHolders.length - 1].value === '') {
this.finishPlaceHolderIndex = this.placeHolders.length - 1;
if (this._snippet.placeHolders.length > 0 && this._snippet.placeHolders[this._snippet.placeHolders.length - 1].value === '') {
this._snippet.finishPlaceHolderIndex = this._snippet.placeHolders.length - 1;
}
}
......@@ -253,147 +320,121 @@ export class CodeSnippet implements ICodeSnippet {
placeHolders: placeHolders
};
}
};
// This is used for both TextMate and Emmet
public static convertExternalSnippet(snippet: string, snippetType: ExternalSnippetType): string {
var openBraces = 0;
var convertedSnippet = '';
var i = 0;
var len = snippet.length;
const TextMateSnippetParser = new class implements ISnippetParser {
while (i < len) {
var restOfLine = snippet.substr(i);
parse(template: string): CodeSnippet {
template = _convertExternalSnippet(template, ExternalSnippetType.TextMateSnippet);
return InternalFormatSnippetParser.parse(template);
}
};
// Cursor tab stop
if (/^\$0/.test(restOfLine)) {
i += 2;
convertedSnippet += snippetType === ExternalSnippetType.EmmetSnippet ? '{{_}}' : '{{}}';
continue;
}
if (/^\$\{0\}/.test(restOfLine)) {
i += 4;
convertedSnippet += snippetType === ExternalSnippetType.EmmetSnippet ? '{{_}}' : '{{}}';
continue;
}
const EmmetSnippetParser = new class implements ISnippetParser {
// Tab stops
var matches = restOfLine.match(/^\$(\d+)/);
if (Array.isArray(matches) && matches.length === 2) {
i += 1 + matches[1].length;
convertedSnippet += '{{' + matches[1] + ':}}';
continue;
}
matches = restOfLine.match(/^\$\{(\d+)\}/);
if (Array.isArray(matches) && matches.length === 2) {
i += 3 + matches[1].length;
convertedSnippet += '{{' + matches[1] + ':}}';
continue;
}
parse(template: string): CodeSnippet {
template = _convertExternalSnippet(template, ExternalSnippetType.EmmetSnippet);
return InternalFormatSnippetParser.parse(template);
}
};
// Open brace patterns placeholder
if (/^\${/.test(restOfLine)) {
i += 2;
++openBraces;
convertedSnippet += '{{';
continue;
}
export enum ExternalSnippetType {
TextMateSnippet,
EmmetSnippet
}
// Close brace patterns placeholder
if (openBraces > 0 && /^}/.test(restOfLine)) {
i += 1;
--openBraces;
convertedSnippet += '}}';
continue;
}
// This is used for both TextMate and Emmet
function _convertExternalSnippet(snippet: string, snippetType: ExternalSnippetType): string {
var openBraces = 0;
var convertedSnippet = '';
var i = 0;
var len = snippet.length;
while (i < len) {
var restOfLine = snippet.substr(i);
// Cursor tab stop
if (/^\$0/.test(restOfLine)) {
i += 2;
convertedSnippet += snippetType === ExternalSnippetType.EmmetSnippet ? '{{_}}' : '{{}}';
continue;
}
if (/^\$\{0\}/.test(restOfLine)) {
i += 4;
convertedSnippet += snippetType === ExternalSnippetType.EmmetSnippet ? '{{_}}' : '{{}}';
continue;
}
// Escapes
if (/^\\./.test(restOfLine)) {
i += 2;
if (/^\\\$/.test(restOfLine)) {
convertedSnippet += '$';
} else {
convertedSnippet += restOfLine.substr(0, 2);
}
continue;
}
// Tab stops
var matches = restOfLine.match(/^\$(\d+)/);
if (Array.isArray(matches) && matches.length === 2) {
i += 1 + matches[1].length;
convertedSnippet += '{{' + matches[1] + ':}}';
continue;
}
matches = restOfLine.match(/^\$\{(\d+)\}/);
if (Array.isArray(matches) && matches.length === 2) {
i += 3 + matches[1].length;
convertedSnippet += '{{' + matches[1] + ':}}';
continue;
}
// Escape braces that don't belong to a placeholder
matches = restOfLine.match(/^({|})/);
if (Array.isArray(matches) && matches.length === 2) {
i += 1;
convertedSnippet += '\\' + matches[1];
continue;
}
// Open brace patterns placeholder
if (/^\${/.test(restOfLine)) {
i += 2;
++openBraces;
convertedSnippet += '{{';
continue;
}
// Close brace patterns placeholder
if (openBraces > 0 && /^}/.test(restOfLine)) {
i += 1;
convertedSnippet += restOfLine.charAt(0);
--openBraces;
convertedSnippet += '}}';
continue;
}
return convertedSnippet;
}
private extractLineIndentation(str: string, maxColumn: number = Number.MAX_VALUE): string {
var fullIndentation = strings.getLeadingWhitespace(str);
// Escapes
if (/^\\./.test(restOfLine)) {
i += 2;
if (/^\\\$/.test(restOfLine)) {
convertedSnippet += '$';
} else {
convertedSnippet += restOfLine.substr(0, 2);
}
continue;
}
if (fullIndentation.length > maxColumn - 1) {
return fullIndentation.substring(0, maxColumn - 1);
// Escape braces that don't belong to a placeholder
matches = restOfLine.match(/^({|})/);
if (Array.isArray(matches) && matches.length === 2) {
i += 1;
convertedSnippet += '\\' + matches[1];
continue;
}
return fullIndentation;
i += 1;
convertedSnippet += restOfLine.charAt(0);
}
public bind(referenceLine: string, deltaLine: number, firstLineDeltaColumn: number, config: IIndentationNormalizer): ICodeSnippet {
var resultLines: string[] = [];
var resultPlaceHolders: IPlaceHolder[] = [];
var referenceIndentation = this.extractLineIndentation(referenceLine, firstLineDeltaColumn + 1);
var originalLine: string, originalLineIndentation: string, remainingLine: string, indentation: string;
var i: number, len: number, j: number, lenJ: number;
// Compute resultLines & keep deltaColumns as a reference for adjusting placeholders
var deltaColumns: number[] = [];
for (i = 0, len = this.lines.length; i < len; i++) {
originalLine = this.lines[i];
if (i === 0) {
deltaColumns[i + 1] = firstLineDeltaColumn;
resultLines[i] = originalLine;
} else {
originalLineIndentation = this.extractLineIndentation(originalLine);
remainingLine = originalLine.substr(originalLineIndentation.length);
indentation = config.normalizeIndentation(referenceIndentation + originalLineIndentation);
deltaColumns[i + 1] = indentation.length - originalLineIndentation.length;
resultLines[i] = indentation + remainingLine;
}
}
return convertedSnippet;
};
// Compute resultPlaceHolders
var originalPlaceHolder: IPlaceHolder, originalOccurence: editorCommon.IRange, resultOccurences: editorCommon.IRange[];
for (i = 0, len = this.placeHolders.length; i < len; i++) {
originalPlaceHolder = this.placeHolders[i];
resultOccurences = [];
for (j = 0, lenJ = originalPlaceHolder.occurences.length; j < lenJ; j++) {
originalOccurence = originalPlaceHolder.occurences[j];
resultOccurences.push({
startLineNumber: originalOccurence.startLineNumber + deltaLine,
startColumn: originalOccurence.startColumn + deltaColumns[originalOccurence.startLineNumber],
endLineNumber: originalOccurence.endLineNumber + deltaLine,
endColumn: originalOccurence.endColumn + deltaColumns[originalOccurence.endLineNumber]
});
}
export interface IPlaceHolder {
id: string;
value: string;
occurences: editorCommon.IRange[];
}
resultPlaceHolders.push({
id: originalPlaceHolder.id,
value: originalPlaceHolder.value,
occurences: resultOccurences
});
}
export interface IIndentationNormalizer {
normalizeIndentation(str: string): string;
}
return {
lines: resultLines,
placeHolders: resultPlaceHolders,
finishPlaceHolderIndex: this.finishPlaceHolderIndex
};
}
export interface ICodeSnippet {
lines: string[];
placeHolders: IPlaceHolder[];
finishPlaceHolderIndex: number;
}
......@@ -6,85 +6,84 @@
import * as assert from 'assert';
import {Range} from 'vs/editor/common/core/range';
import {CodeSnippet, ExternalSnippetType} from 'vs/editor/contrib/snippet/common/snippet';
import {CodeSnippet} from 'vs/editor/contrib/snippet/common/snippet';
suite('Editor Contrib - Snippets', () => {
test('Support tab stop order', () => {
let external = 'finished:$0, second:${2:name}, first:$1, third:$3';
let internal = CodeSnippet.convertExternalSnippet(external, ExternalSnippetType.TextMateSnippet);
function assertInternalAndTextmate(internal: string, textmate: string, callback: (snippet: CodeSnippet) => any) {
assert.equal(internal, 'finished:{{}}, second:{{2:name}}, first:{{1:}}, third:{{3:}}');
callback(CodeSnippet.fromInternal(internal));
callback(CodeSnippet.fromTextmate(textmate));
}
let snippet = new CodeSnippet(internal);
test('Support tab stop order', () => {
assert.deepEqual(snippet.lines, ['finished:, second:name, first:, third:']);
assert.equal(snippet.placeHolders.length, 4);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].value, '');
assert.equal(snippet.placeHolders[1].id, '2');
assert.equal(snippet.placeHolders[1].value, 'name');
assert.equal(snippet.placeHolders[2].id, '3');
assert.equal(snippet.placeHolders[2].value, '');
assert.equal(snippet.placeHolders[3].id, '');
assert.equal(snippet.placeHolders[3].value, '');
assert.equal(snippet.finishPlaceHolderIndex, 3);
assertInternalAndTextmate(
'finished:{{}}, second:{{2:name}}, first:{{1:}}, third:{{3:}}',
'finished:$0, second:${2:name}, first:$1, third:$3',
snippet => {
assert.deepEqual(snippet.lines, ['finished:, second:name, first:, third:']);
assert.equal(snippet.placeHolders.length, 4);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].value, '');
assert.equal(snippet.placeHolders[1].id, '2');
assert.equal(snippet.placeHolders[1].value, 'name');
assert.equal(snippet.placeHolders[2].id, '3');
assert.equal(snippet.placeHolders[2].value, '');
assert.equal(snippet.placeHolders[3].id, '');
assert.equal(snippet.placeHolders[3].value, '');
assert.equal(snippet.finishPlaceHolderIndex, 3);
});
});
test('Support tab stop order with implicit finish', () => {
let external = 't2:$2, t1:$1';
let internal = CodeSnippet.convertExternalSnippet(external, ExternalSnippetType.TextMateSnippet);
assert.equal(internal, 't2:{{2:}}, t1:{{1:}}');
let snippet = new CodeSnippet(internal);
assert.deepEqual(snippet.lines, ['t2:, t1:']);
assert.equal(snippet.placeHolders.length, 2);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].value, '');
assert.equal(snippet.placeHolders[1].id, '2');
assert.equal(snippet.placeHolders[1].value, '');
assert.equal(snippet.finishPlaceHolderIndex, 1);
assertInternalAndTextmate(
't2:{{2:}}, t1:{{1:}}',
't2:$2, t1:$1',
snippet => {
assert.deepEqual(snippet.lines, ['t2:, t1:']);
assert.equal(snippet.placeHolders.length, 2);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].value, '');
assert.equal(snippet.placeHolders[1].id, '2');
assert.equal(snippet.placeHolders[1].value, '');
assert.equal(snippet.finishPlaceHolderIndex, 1);
});
});
test('Support tab stop order with no finish', () => {
let external = 't2:${2:second}, t3:${3:last}, t1:${1:first}';
let internal = CodeSnippet.convertExternalSnippet(external, ExternalSnippetType.TextMateSnippet);
assert.equal(internal, 't2:{{2:second}}, t3:{{3:last}}, t1:{{1:first}}');
let snippet = new CodeSnippet(internal);
assert.deepEqual(snippet.lines, ['t2:second, t3:last, t1:first']);
assert.equal(snippet.placeHolders.length, 3);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].value, 'first');
assert.equal(snippet.placeHolders[1].id, '2');
assert.equal(snippet.placeHolders[1].value, 'second');
assert.equal(snippet.placeHolders[2].id, '3');
assert.equal(snippet.placeHolders[2].value, 'last');
assert.equal(snippet.finishPlaceHolderIndex, -1);
assertInternalAndTextmate(
't2:{{2:second}}, t3:{{3:last}}, t1:{{1:first}}',
't2:${2:second}, t3:${3:last}, t1:${1:first}',
snippet => {
assert.deepEqual(snippet.lines, ['t2:second, t3:last, t1:first']);
assert.equal(snippet.placeHolders.length, 3);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].value, 'first');
assert.equal(snippet.placeHolders[1].id, '2');
assert.equal(snippet.placeHolders[1].value, 'second');
assert.equal(snippet.placeHolders[2].id, '3');
assert.equal(snippet.placeHolders[2].value, 'last');
assert.equal(snippet.finishPlaceHolderIndex, -1);
});
});
test('Support tab stop order wich does not affect named variable id\'s', () => {
let external = '${first}-${2}-${second}-${1}';
let internal = CodeSnippet.convertExternalSnippet(external, ExternalSnippetType.TextMateSnippet);
assert.equal(internal, '{{first}}-{{2:}}-{{second}}-{{1:}}');
let snippet = new CodeSnippet(internal);
assert.deepEqual(snippet.lines, ['first--second-']);
assert.equal(snippet.placeHolders.length, 4);
assert.equal(snippet.placeHolders[0].id, 'first');
assert.equal(snippet.placeHolders[1].id, 'second');
assert.equal(snippet.placeHolders[2].id, '1');
assert.equal(snippet.placeHolders[3].id, '2');
assertInternalAndTextmate(
'{{first}}-{{2:}}-{{second}}-{{1:}}',
'${first}-${2}-${second}-${1}',
snippet => {
assert.deepEqual(snippet.lines, ['first--second-']);
assert.equal(snippet.placeHolders.length, 4);
assert.equal(snippet.placeHolders[0].id, 'first');
assert.equal(snippet.placeHolders[1].id, 'second');
assert.equal(snippet.placeHolders[2].id, '1');
assert.equal(snippet.placeHolders[3].id, '2');
}
);
});
test('bug #17541:[snippets] Support default text in mirrors', () => {
......@@ -95,29 +94,27 @@ suite('Editor Contrib - Snippets', () => {
'end{$1}'
].join('\n');
var internal = CodeSnippet.convertExternalSnippet(external, ExternalSnippetType.TextMateSnippet);
assert.equal(internal, [
var internal = [
'begin\\{{{1:enumerate}}\\}',
'\t{{}}',
'end\\{{{1:}}\\}'
].join('\n'));
var snippet = new CodeSnippet(internal);
assert.deepEqual(snippet.lines, [
'begin{enumerate}',
'\t',
'end{enumerate}'
]);
assert.equal(snippet.placeHolders.length, 2);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].occurences.length, 2);
assert.deepEqual(snippet.placeHolders[0].occurences[0], new Range(1, 7, 1, 16));
assert.deepEqual(snippet.placeHolders[0].occurences[1], new Range(3, 5, 3, 14));
assert.equal(snippet.placeHolders[1].id, '');
assert.equal(snippet.placeHolders[1].occurences.length, 1);
assert.deepEqual(snippet.placeHolders[1].occurences[0], new Range(2, 2, 2, 2));
].join('\n');
assertInternalAndTextmate(internal, external, snippet => {
assert.deepEqual(snippet.lines, [
'begin{enumerate}',
'\t',
'end{enumerate}'
]);
assert.equal(snippet.placeHolders.length, 2);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].occurences.length, 2);
assert.deepEqual(snippet.placeHolders[0].occurences[0], new Range(1, 7, 1, 16));
assert.deepEqual(snippet.placeHolders[0].occurences[1], new Range(3, 5, 3, 14));
assert.equal(snippet.placeHolders[1].id, '');
assert.equal(snippet.placeHolders[1].occurences.length, 1);
assert.deepEqual(snippet.placeHolders[1].occurences[0], new Range(2, 2, 2, 2));
});
});
test('bug #17487:[snippets] four backslashes are required to get one backslash in the inserted text', () => {
......@@ -128,37 +125,35 @@ suite('Editor Contrib - Snippets', () => {
'\\end{$1}'
].join('\n');
var internal = CodeSnippet.convertExternalSnippet(external, ExternalSnippetType.TextMateSnippet);
assert.equal(internal, [
var internal = [
'\\begin\\{{{1:enumerate}}\\}',
'\t{{}}',
'\\end\\{{{1:}}\\}'
].join('\n'));
var snippet = new CodeSnippet(internal);
assert.deepEqual(snippet.lines, [
'\\begin{enumerate}',
'\t',
'\\end{enumerate}'
]);
assert.equal(snippet.placeHolders.length, 2);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].occurences.length, 2);
assert.deepEqual(snippet.placeHolders[0].occurences[0], new Range(1, 8, 1, 17));
assert.deepEqual(snippet.placeHolders[0].occurences[1], new Range(3, 6, 3, 15));
assert.equal(snippet.placeHolders[1].id, '');
assert.equal(snippet.placeHolders[1].occurences.length, 1);
assert.deepEqual(snippet.placeHolders[1].occurences[0], new Range(2, 2, 2, 2));
].join('\n');
assertInternalAndTextmate(internal, external, snippet => {
assert.deepEqual(snippet.lines, [
'\\begin{enumerate}',
'\t',
'\\end{enumerate}'
]);
assert.equal(snippet.placeHolders.length, 2);
assert.equal(snippet.placeHolders[0].id, '1');
assert.equal(snippet.placeHolders[0].occurences.length, 2);
assert.deepEqual(snippet.placeHolders[0].occurences[0], new Range(1, 8, 1, 17));
assert.deepEqual(snippet.placeHolders[0].occurences[1], new Range(3, 6, 3, 15));
assert.equal(snippet.placeHolders[1].id, '');
assert.equal(snippet.placeHolders[1].occurences.length, 1);
assert.deepEqual(snippet.placeHolders[1].occurences[0], new Range(2, 2, 2, 2));
});
});
test('issue #3552: Snippet Converted Not Working for literal Dollar Sign', () => {
let external = '\n\\$scope.\\$broadcast(\'scroll.infiniteScrollComplete\');\n';
let internal = CodeSnippet.convertExternalSnippet(external, ExternalSnippetType.TextMateSnippet);
assert.equal(internal, '\n$scope.$broadcast(\'scroll.infiniteScrollComplete\');\n');
let snippet = CodeSnippet.fromTextmate(external);
assert.equal(snippet.placeHolders.length, 0);
assert.deepEqual(snippet.lines, ['', '$scope.$broadcast(\'scroll.infiniteScrollComplete\');', '']);
});
});
......@@ -35,7 +35,7 @@ suite('SnippetController', () => {
insertSpaces: false
});
let snippetController = editor.registerAndInstantiateContribution<TestSnippetController>(TestSnippetController);
let codeSnippet = new CodeSnippet([
let codeSnippet = CodeSnippet.fromInternal([
'for (var {{index}}; {{index}} < {{array}}.length; {{index}}++) {',
'\tvar element = {{array}}[{{index}}];',
'\t{{}}',
......@@ -228,7 +228,7 @@ suite('SnippetController', () => {
new Selection(2, 1, 2, 1),
]);
codeSnippet = new CodeSnippet('foo{{}}');
codeSnippet = CodeSnippet.fromInternal('foo{{}}');
snippetController.run(codeSnippet, 0, 0, false);
assert.equal(editor.getSelections().length, 2);
......@@ -243,7 +243,7 @@ suite('SnippetController', () => {
new Selection(2, 1, 2, 1),
]);
codeSnippet = new CodeSnippet('foo{{}}bar');
codeSnippet = CodeSnippet.fromInternal('foo{{}}bar');
snippetController.run(codeSnippet, 0, 0, false);
assert.equal(editor.getSelections().length, 2);
......@@ -258,7 +258,7 @@ suite('SnippetController', () => {
new Selection(1, 5, 1, 5),
]);
codeSnippet = new CodeSnippet('foo{{}}bar');
codeSnippet = CodeSnippet.fromInternal('foo{{}}bar');
snippetController.run(codeSnippet, 0, 0, false);
assert.equal(editor.getSelections().length, 2);
......@@ -273,7 +273,7 @@ suite('SnippetController', () => {
new Selection(1, 5, 1, 5),
]);
codeSnippet = new CodeSnippet('foo\n{{}}\nbar');
codeSnippet = CodeSnippet.fromInternal('foo\n{{}}\nbar');
snippetController.run(codeSnippet, 0, 0, false);
assert.equal(editor.getSelections().length, 2);
......
......@@ -85,7 +85,7 @@ export class SuggestController implements IEditorContribution {
}
SnippetController.get(this.editor).run(
new CodeSnippet(insertText),
CodeSnippet.fromInternal(insertText),
overwriteBefore + columnDelta,
overwriteAfter
);
......
......@@ -66,7 +66,7 @@ class TabCompletionController implements editorCommon.IEditorContribution {
performSnippetCompletions(): void {
if (this._currentSnippets.length === 1) {
const snippet = this._currentSnippets[0];
const codeSnippet = new CodeSnippet(snippet.codeSnippet);
const codeSnippet = CodeSnippet.fromTextmate(snippet.codeSnippet);
this._snippetController.run(codeSnippet, snippet.prefix.length, 0);
// } else {
// todo@joh - show suggest widget with proposals
......
......@@ -49,7 +49,7 @@ class ShowSnippetsActions extends EditorAction {
return quickOpenService.pick(picks).then(pick => {
if (pick) {
SnippetController.get(editor).run(new CodeSnippet(pick.snippet.codeSnippet), 0, 0);
SnippetController.get(editor).run(CodeSnippet.fromTextmate(pick.snippet.codeSnippet), 0, 0);
}
});
}
......
......@@ -12,7 +12,6 @@ import {readFile} from 'vs/base/node/pfs';
import {IExtensionMessageCollector, ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry';
import {ISnippetsRegistry, Extensions, ISnippet} from 'vs/editor/common/modes/snippetsRegistry';
import {IModeService} from 'vs/editor/common/services/modeService';
import {CodeSnippet, ExternalSnippetType} from 'vs/editor/contrib/snippet/common/snippet';
import platform = require('vs/platform/platform');
export interface ISnippetsExtensionPoint {
......@@ -106,14 +105,11 @@ function parseSnippetFile(snippetFileContent: string): ISnippet[] {
}
if (typeof prefix === 'string' && typeof bodyStringOrArray === 'string') {
let codeSnippet = CodeSnippet.convertExternalSnippet(bodyStringOrArray, ExternalSnippetType.TextMateSnippet);
if (codeSnippet !== null) {
result.push({
prefix,
description: snippet['description'] || description,
codeSnippet
});
}
result.push({
prefix,
description: snippet['description'] || description,
codeSnippet: bodyStringOrArray
});
}
};
......
......@@ -87,8 +87,7 @@ export class EditorAccessor implements emmet.Editor {
}
let range = new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);
let snippet = snippets.CodeSnippet.convertExternalSnippet(value, snippets.ExternalSnippetType.EmmetSnippet);
let codeSnippet = new snippets.CodeSnippet(snippet);
let codeSnippet = snippets.CodeSnippet.fromEmmet(value);
SnippetController.get(this.editor).runWithReplaceRange(codeSnippet, range);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册