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

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

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