diff --git a/src/vs/editor/contrib/snippet/snippetParser.ts b/src/vs/editor/contrib/snippet/snippetParser.ts index 5273a9dee6a..b44c9fda3be 100644 --- a/src/vs/editor/contrib/snippet/snippetParser.ts +++ b/src/vs/editor/contrib/snippet/snippetParser.ts @@ -861,6 +861,14 @@ export class SnippetParser { if (this._accept(TokenType.Forwardslash)) { break; } + + let escaped: string; + if (escaped = this._accept(TokenType.Backslash, true)) { + escaped = this._accept(TokenType.Forwardslash, true) || escaped; + transform.appendChild(new Text(escaped)); + continue; + } + if (this._parseFormatString(transform) || this._parseAnything(transform)) { continue; } diff --git a/src/vs/editor/contrib/snippet/test/snippetParser.test.ts b/src/vs/editor/contrib/snippet/test/snippetParser.test.ts index 0c2fd49ad80..4ed94f7f584 100644 --- a/src/vs/editor/contrib/snippet/test/snippetParser.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetParser.test.ts @@ -244,6 +244,12 @@ suite('SnippetParser', () => { assertMarker('${TM_DIRECTORY/src\\//$1/}', Variable); }); + test('No way to escape forward slash in snippet format section #37562', function () { + assertMarker('${TM_SELECTED_TEXT/a/\\/$1/g}', Variable); + assertMarker('${TM_SELECTED_TEXT/a/in\\/$1ner/g}', Variable); + assertMarker('${TM_SELECTED_TEXT/a/end\\//g}', Variable); + }); + test('Parser, placeholder with choice', () => { assertTextAndMarker('${1|one,two,three|}', 'one', Placeholder);