From d3e54fd23ce8d195e25a3ba62e61839f7a83e13d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 24 Aug 2016 10:55:28 +0200 Subject: [PATCH] replace CodeSnippet-ctor with static factory method with fromTextMate, fromInternal, fromEmmet --- .../editor/common/modes/snippetsRegistry.ts | 2 - .../browser/defineKeybinding.ts | 2 +- .../editor/contrib/snippet/common/snippet.ts | 381 ++++++++++-------- .../snippet/test/common/snippet.test.ts | 203 +++++----- .../test/common/snippetController.test.ts | 10 +- .../suggest/browser/suggestController.ts | 2 +- .../contrib/suggest/browser/tabCompletion.ts | 2 +- .../electron-browser/snippetCompletion.ts | 2 +- src/vs/editor/node/textMate/TMSnippets.ts | 14 +- .../parts/emmet/node/editorAccessor.ts | 3 +- 10 files changed, 325 insertions(+), 296 deletions(-) diff --git a/src/vs/editor/common/modes/snippetsRegistry.ts b/src/vs/editor/common/modes/snippetsRegistry.ts index f9e96fbdac7..141f35fca2b 100644 --- a/src/vs/editor/common/modes/snippetsRegistry.ts +++ b/src/vs/editor/common/modes/snippetsRegistry.ts @@ -20,8 +20,6 @@ export interface ISnippetsRegistry { */ registerSnippets(modeId: string, snippets: ISnippet[], owner?: string): void; - - /** * Visit all snippets */ diff --git a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts index b2f9bcf3768..54868e0fefd 100644 --- a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts +++ b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts @@ -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 { diff --git a/src/vs/editor/contrib/snippet/common/snippet.ts b/src/vs/editor/contrib/snippet/common/snippet.ts index b35bc3f4573..6bfbd8ba6e7 100644 --- a/src/vs/editor/contrib/snippet/common/snippet.ts +++ b/src/vs/editor/contrib/snippet/common/snippet.ts @@ -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 = {}; @@ -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; } diff --git a/src/vs/editor/contrib/snippet/test/common/snippet.test.ts b/src/vs/editor/contrib/snippet/test/common/snippet.test.ts index 5c01d5e24fc..7b19212d582 100644 --- a/src/vs/editor/contrib/snippet/test/common/snippet.test.ts +++ b/src/vs/editor/contrib/snippet/test/common/snippet.test.ts @@ -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\');', '']); }); }); diff --git a/src/vs/editor/contrib/snippet/test/common/snippetController.test.ts b/src/vs/editor/contrib/snippet/test/common/snippetController.test.ts index 4ec71d6feea..d081aff108a 100644 --- a/src/vs/editor/contrib/snippet/test/common/snippetController.test.ts +++ b/src/vs/editor/contrib/snippet/test/common/snippetController.test.ts @@ -35,7 +35,7 @@ suite('SnippetController', () => { insertSpaces: false }); let snippetController = editor.registerAndInstantiateContribution(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); diff --git a/src/vs/editor/contrib/suggest/browser/suggestController.ts b/src/vs/editor/contrib/suggest/browser/suggestController.ts index 6ac21aac14a..cb4d921c6a2 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestController.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestController.ts @@ -85,7 +85,7 @@ export class SuggestController implements IEditorContribution { } SnippetController.get(this.editor).run( - new CodeSnippet(insertText), + CodeSnippet.fromInternal(insertText), overwriteBefore + columnDelta, overwriteAfter ); diff --git a/src/vs/editor/contrib/suggest/browser/tabCompletion.ts b/src/vs/editor/contrib/suggest/browser/tabCompletion.ts index 70e5fb9a353..e1620ceab5e 100644 --- a/src/vs/editor/contrib/suggest/browser/tabCompletion.ts +++ b/src/vs/editor/contrib/suggest/browser/tabCompletion.ts @@ -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 diff --git a/src/vs/editor/contrib/suggest/electron-browser/snippetCompletion.ts b/src/vs/editor/contrib/suggest/electron-browser/snippetCompletion.ts index 56036821d02..a8338aa08a2 100644 --- a/src/vs/editor/contrib/suggest/electron-browser/snippetCompletion.ts +++ b/src/vs/editor/contrib/suggest/electron-browser/snippetCompletion.ts @@ -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); } }); } diff --git a/src/vs/editor/node/textMate/TMSnippets.ts b/src/vs/editor/node/textMate/TMSnippets.ts index 559be67402b..8f3545ff845 100644 --- a/src/vs/editor/node/textMate/TMSnippets.ts +++ b/src/vs/editor/node/textMate/TMSnippets.ts @@ -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 + }); } }; diff --git a/src/vs/workbench/parts/emmet/node/editorAccessor.ts b/src/vs/workbench/parts/emmet/node/editorAccessor.ts index 763092061a7..2058ec1fa2f 100644 --- a/src/vs/workbench/parts/emmet/node/editorAccessor.ts +++ b/src/vs/workbench/parts/emmet/node/editorAccessor.ts @@ -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); } -- GitLab