1- const BodyParser = require ( '../lib/snippet-body-parser' ) ;
1+ const SnippetParser = require ( '../lib/snippet-body-parser' ) ;
22
33describe ( "Snippet Body Parser" , ( ) => {
44 function expectMatch ( input , tree ) {
5- expect ( BodyParser . parse ( input ) ) . toEqual ( tree ) ;
5+ expect ( SnippetParser . parse ( input ) ) . toEqual ( tree ) ;
66 }
77
88 describe ( "tab stops" , ( ) => {
@@ -20,6 +20,14 @@ describe("Snippet Body Parser", () => {
2020 ] ) ;
2121 } ) ;
2222
23+ it ( "only allows non-negative integer stop numbers" , ( ) => {
24+ expectMatch ( "$99999" , [ { index : 99999 , content : [ ] } ] ) ;
25+ expectMatch ( "$-1" , [ "$-1" ] ) ;
26+ expectMatch ( "${-1}" , [ "${-1}" ] ) ;
27+ expectMatch ( "$1.5" , [ { index : 1 , content : [ ] } , ".5" ] ) ;
28+ expectMatch ( "${1.5}" , [ "${1.5}" ] ) ;
29+ } ) ;
30+
2331 describe ( "with placeholders" , ( ) => {
2432 it ( "allows placeholders to be arbitrary" , ( ) => {
2533 expectMatch ( "${1:${2}$foo${3|a,b|}}" , [
@@ -54,6 +62,20 @@ describe("Snippet Body Parser", () => {
5462 ] ) ;
5563 } ) ;
5664
65+ it ( "applies flags to the find regex" , ( ) => {
66+ expectMatch ( "${1/foo/bar/gimsuy}" , [
67+ {
68+ index : 1 ,
69+ transformation : {
70+ find : / f o o / gimsuy,
71+ replace : [
72+ "bar"
73+ ]
74+ }
75+ }
76+ ] ) ;
77+ } ) ;
78+
5779 it ( "does not parse invalid regex as transformations" , ( ) => {
5880 expectMatch ( "${1/foo/bar/a}" , [ "${1/foo/bar/a}" ] ) ; // invalid flag
5981 expectMatch ( "${1/fo)o$1/$bar/}" , [
@@ -85,20 +107,90 @@ describe("Snippet Body Parser", () => {
85107 "\\ar $\\{baz}" ,
86108 ] ) ;
87109 } ) ;
110+
111+ describe ( "naming" , ( ) => {
112+ it ( "only allows ASCII letters, numbers, and underscores in names" , ( ) => {
113+ expectMatch ( "$abc_123-not" , [ { variable : "abc_123" } , "-not" ] ) ;
114+ } ) ;
115+
116+ it ( "allows names to start with underscores" , ( ) => {
117+ expectMatch ( "$__properties" , [ { variable : "__properties" } ] ) ;
118+ } ) ;
119+
120+ it ( "doesn't allow names to start with a number" , ( ) => {
121+ expectMatch ( "$1foo" , [ { index : 1 , content : [ ] } , "foo" ] ) ;
122+ } ) ;
123+ } ) ;
124+
125+ describe ( "with placeholders" , ( ) => {
126+ it ( "allows placeholders to be arbitrary" , ( ) => {
127+ expectMatch ( "${foo:${2}$bar${3|a,b|}}" , [
128+ {
129+ variable : "foo" ,
130+ content : [
131+ { index : 2 , content : [ ] } ,
132+ { variable : "bar" } ,
133+ { index : 3 , choices : [ "a" , "b" ] } ,
134+ ]
135+ }
136+ ] ) ;
137+ } ) ;
138+
139+ it ( "allows escaping '}' in placeholders" , ( ) => {
140+ expectMatch ( "${foo:\\}}" , [ { variable : "foo" , content : [ "}" ] } ] ) ;
141+ } ) ;
142+ } ) ;
143+
144+ describe ( "with transformations" , ( ) => {
145+ it ( "parses simple transformations" , ( ) => {
146+ expectMatch ( "${var/foo/bar/}" , [
147+ {
148+ variable : "var" ,
149+ transformation : {
150+ find : / f o o / ,
151+ replace : [
152+ "bar"
153+ ]
154+ }
155+ }
156+ ] ) ;
157+ } ) ;
158+ } ) ;
88159 } ) ;
89160
90- it ( "parses snippets with no special behaviour as plain text" , ( ) => {
91- const plainSnippets = [
92- "foo $ bar" ,
93- "$% $ 1 ${/upcase} \n ${|world|} ${3foo}" ,
94- ] ;
161+ describe ( "choices" , ( ) => {
162+ it ( "parses choices" , ( ) => {
163+ expectMatch ( "${1|a,b,c|}" , [ { index : 1 , choices : [ "a" , "b" , "c" ] } ] ) ;
164+ } ) ;
165+
166+ it ( "skips empty choices" , ( ) => {
167+ expectMatch ( "${1||}" , [ "${1||}" ] ) ;
168+ } ) ;
169+
170+ it ( "skips escaped choices" , ( ) => {
171+ expectMatch ( "\\${1|a|}" , [ "${1|a|}" ] ) ;
172+ } ) ;
95173
96- for ( const plain of plainSnippets ) {
97- expectMatch ( plain , [ plain ] ) ;
98- }
174+ it ( "treats choice items as plain text" , ( ) => {
175+ expectMatch ( "${1|$2,$foo|}" , [ { index : 1 , choices : [ "$2" , "$foo" ] } ] ) ;
176+ } ) ;
177+
178+ it ( "only allows ',' and '|' to be escaped in choice text" , ( ) => {
179+ expectMatch ( "${1|a,b\\,c,d\\|},e\\$f|}" , [
180+ {
181+ index : 1 ,
182+ choices : [
183+ "a" ,
184+ "b,c" ,
185+ "d|}" ,
186+ "e\\$f"
187+ ]
188+ }
189+ ] ) ;
190+ } ) ;
99191 } ) ;
100192
101- describe ( "only escapes a select few characters" , ( ) => {
193+ describe ( "escaped characters" , ( ) => {
102194 const escapeTest = "\\$ \\\\ \\} \\% \\* \\, \\| \\{ \\n \\r \\:" ;
103195
104196 const escapeResolveTop = "$ \\ } \\% \\* \\, \\| \\{ \\n \\r \\:" ;
@@ -178,8 +270,7 @@ describe("Snippet Body Parser", () => {
178270 } ) ;
179271
180272 it ( "parses a snippet with transformations" , ( ) => {
181- const bodyTree = BodyParser . parse ( "<${1:p}>$0</${1/f/F/}>" ) ;
182- expect ( bodyTree ) . toEqual ( [
273+ expectMatch ( "<${1:p}>$0</${1/f/F/}>" , [
183274 '<' ,
184275 { index : 1 , content : [ 'p' ] } ,
185276 '>' ,
0 commit comments