Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Commit cebceda

Browse files
Remove implicit g flag from snippet transformations
Breaks backward-compatibility, but fixes a bug because this was never supposed to work this way.
1 parent d0c574a commit cebceda

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

lib/snippet-body.pegjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ variableContentChar = !variable char:('\\}' / [^}]) { return char; }
6363
escapedForwardSlash = pair:'\\/' { return pair; }
6464

6565
// A pattern and replacement for a transformed tab stop.
66-
transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[imy]* {
67-
let reFind = new RegExp(find.join(''), flags.join('') + 'g');
66+
transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[gimy]* {
67+
let reFind = new RegExp(find.join(''), flags.join(''));
6868
return { find: reFind, replace: replace[0] };
6969
}
7070

spec/body-parser-spec.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,19 @@ the quick brown $1fox \${2:jumped \${3:over}
6666

6767
it("parses a snippet with transformations", () => {
6868
const bodyTree = BodyParser.parse("<${1:p}>$0</${1/f/F/}>");
69+
expect(bodyTree).toEqual([
70+
'<',
71+
{index: 1, content: ['p']},
72+
'>',
73+
{index: 0, content: []},
74+
'</',
75+
{index: 1, content: [], substitution: {find: /f/, replace: ['F']}},
76+
'>'
77+
]);
78+
});
79+
80+
it("parses a snippet with transformations and a global flag", () => {
81+
const bodyTree = BodyParser.parse("<${1:p}>$0</${1/f/F/g}>");
6982
expect(bodyTree).toEqual([
7083
'<',
7184
{index: 1, content: ['p']},
@@ -78,7 +91,7 @@ the quick brown $1fox \${2:jumped \${3:over}
7891
});
7992

8093
it("parses a snippet with multiple tab stops with transformations", () => {
81-
const bodyTree = BodyParser.parse("${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2");
94+
const bodyTree = BodyParser.parse("${1:placeholder} ${1/(.)/\\u$1/g} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2");
8295
expect(bodyTree).toEqual([
8396
{index: 1, content: ['placeholder']},
8497
' ',
@@ -102,7 +115,7 @@ the quick brown $1fox \${2:jumped \${3:over}
102115
index: 2,
103116
content: [],
104117
substitution: {
105-
find: /^(.*)$/g,
118+
find: /^(.*)$/,
106119
replace: [
107120
{escape: 'L'},
108121
{backreference: 1}
@@ -116,7 +129,7 @@ the quick brown $1fox \${2:jumped \${3:over}
116129

117130

118131
it("parses a snippet with transformations and mirrors", () => {
119-
const bodyTree = BodyParser.parse("${1:placeholder}\n${1/(.)/\\u$1/}\n$1");
132+
const bodyTree = BodyParser.parse("${1:placeholder}\n${1/(.)/\\u$1/g}\n$1");
120133
expect(bodyTree).toEqual([
121134
{index: 1, content: ['placeholder']},
122135
'\n',
@@ -148,7 +161,7 @@ the quick brown $1fox \${2:jumped \${3:over}
148161
index: 1,
149162
content: [],
150163
substitution: {
151-
find: /(.)(.*)/g,
164+
find: /(.)(.*)/,
152165
replace: [
153166
{escape: 'u'},
154167
{backreference: 1},
@@ -174,7 +187,7 @@ the quick brown $1fox \${2:jumped \${3:over}
174187
index: 1,
175188
content: [],
176189
substitution: {
177-
find: /(.)\/(.*)/g,
190+
find: /(.)\/(.*)/,
178191
replace: [
179192
{escape: 'u'},
180193
{backreference: 1},

spec/snippets-spec.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,27 +265,27 @@ third tabstop $3\
265265
},
266266
"transform with non-transforming mirrors": {
267267
prefix: "t13",
268-
body: "${1:placeholder}\n${1/(.)/\\u$1/}\n$1"
268+
body: "${1:placeholder}\n${1/(.)/\\u$1/g}\n$1"
269269
},
270270
"multiple tab stops, some with transforms and some without": {
271271
prefix: "t14",
272-
body: "${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2"
272+
body: "${1:placeholder} ${1/(.)/\\u$1/g} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2"
273273
},
274274
"has a transformed tab stop without a corresponding ordinary tab stop": {
275275
prefix: 't15',
276-
body: "${1/(.)/\\u$1/} & $2"
276+
body: "${1/(.)/\\u$1/g} & $2"
277277
},
278278
"has a transformed tab stop that occurs before the corresponding ordinary tab stop": {
279279
prefix: 't16',
280-
body: "& ${1/(.)/\\u$1/} & ${1:q}"
280+
body: "& ${1/(.)/\\u$1/g} & ${1:q}"
281281
},
282282
"has a placeholder that mirrors another tab stop's content": {
283283
prefix: 't17',
284284
body: "$4console.${3:log}('${2:uh $1}', $1);$0"
285285
},
286286
"has a transformed tab stop such that it is possible to move the cursor between the ordinary tab stop and its transformed version without an intermediate step": {
287287
prefix: 't18',
288-
body: '// $1\n// ${1/./=/}'
288+
body: '// $1\n// ${1/./=/g}'
289289
},
290290
"has two tab stops adjacent to one another": {
291291
prefix: 't19',
@@ -294,6 +294,14 @@ third tabstop $3\
294294
"has several adjacent tab stops, one of which has a placeholder with reference to another tab stop at its edge": {
295295
prefix: 't20',
296296
body: '${1:foo}${2:bar}${3:baz $1}$4'
297+
},
298+
"banner without global flag": {
299+
prefix: "bannerWrong",
300+
body: "// $1\n// ${1/./=/}"
301+
},
302+
"banner with globalFlag": {
303+
prefix: "bannerCorrect",
304+
body: "// $1\n// ${1/./=/g}"
297305
}
298306
}
299307
});
@@ -904,6 +912,28 @@ foo\
904912
});
905913
});
906914

915+
describe("when the snippet contains a transformation without a global flag", () => {
916+
it("should transform only the first character", () => {
917+
editor.setText('bannerWrong');
918+
editor.setCursorScreenPosition([0, 11]);
919+
simulateTabKeyEvent();
920+
expect(editor.getText()).toBe("// \n// ");
921+
editor.insertText('TEST');
922+
expect(editor.getText()).toBe("// TEST\n// =EST");
923+
});
924+
});
925+
926+
describe("when the snippet contains a transformation with a global flag", () => {
927+
it("should transform all characters", () => {
928+
editor.setText('bannerCorrect');
929+
editor.setCursorScreenPosition([0, 13]);
930+
simulateTabKeyEvent();
931+
expect(editor.getText()).toBe("// \n// ");
932+
editor.insertText('TEST');
933+
expect(editor.getText()).toBe("// TEST\n// ====");
934+
});
935+
});
936+
907937
describe("when the snippet contains multiple tab stops, some with transformations and some without", () => {
908938
it("does not get confused", () => {
909939
editor.setText('t14');

0 commit comments

Comments
 (0)