1# Astract Syntax Tree generation
2# ------------------------------
3
4# Recursively compare all values of enumerable properties of `expected` with
5# those of `actual`. Use `looseArray` helper function to skip array length
6# comparison.
7deepStrictIncludeExpectedProperties = (actual, expected) ->
8  eq actual.length, expected.length if expected instanceof Array and not expected.loose
9  for key, val of expected
10    if val? and typeof val is 'object'
11      fail "Property #{reset}#{key}#{red} expected, but was missing" unless actual[key]
12      deepStrictIncludeExpectedProperties actual[key], val
13    else
14      eq actual[key], val, """
15        Property #{reset}#{key}#{red}: expected #{reset}#{actual[key]}#{red} to equal #{reset}#{val}#{red}
16          Expected AST output to include:
17          #{reset}#{inspect expected}#{red}
18          but instead it was:
19          #{reset}#{inspect actual}#{red}
20      """
21  actual
22
23# Flag array for loose comparison. See reference to `.loose` in
24# `deepStrictIncludeExpectedProperties` above.
25looseArray = (arr) ->
26  Object.defineProperty arr, 'loose',
27    value: yes
28    enumerable: no
29  arr
30
31testAgainstExpected = (ast, expected) ->
32  if expected?
33    deepStrictIncludeExpectedProperties ast, expected
34  else
35    # Convenience for creating new tests; call `testExpression` with no second
36    # parameter to see what the current AST generation is for your input code.
37    console.log inspect ast
38
39testExpression = (code, expected) ->
40  ast = getAstExpression code
41  testAgainstExpected ast, expected
42
43testStatement = (code, expected) ->
44  ast = getAstStatement code
45  testAgainstExpected ast, expected
46
47testComments = (code, expected) ->
48  ast = getAstRoot code
49  testAgainstExpected ast.comments, expected
50
51test 'Confirm functionality of `deepStrictIncludeExpectedProperties`', ->
52  actual =
53    name: 'Name'
54    a:
55      b: 1
56      c: 2
57    x: [1, 2, 3]
58
59  check = (message, test, expected) ->
60    test (-> deepStrictIncludeExpectedProperties actual, expected), null, message
61
62  check 'Expected property does not match', throws,
63    name: '"Name"'
64
65  check 'Array length mismatch', throws,
66    x: [1, 2]
67
68  check 'Skip array length check', doesNotThrow,
69    x: looseArray [
70      1
71      2
72    ]
73
74  check 'Array length matches', doesNotThrow,
75    x: [1, 2, 3]
76
77  check 'Array prop mismatch', throws,
78    x: [3, 2, 1]
79
80  check 'Partial object comparison', doesNotThrow,
81    a:
82      c: 2
83    forbidden: undefined
84
85  check 'Actual has forbidden prop', throws,
86    a:
87      b: 1
88      c: undefined
89
90  check 'Check prop for existence only', doesNotThrow,
91    name: {}
92    a: {}
93    x: {}
94
95  check 'Prop is missing', throws,
96    missingProp: {}
97
98# Shorthand helpers for common AST patterns.
99
100EMPTY_BLOCK =
101  type: 'BlockStatement'
102  body: []
103  directives: []
104
105ID = (name, additionalProperties = {}) ->
106  Object.assign({
107    type: 'Identifier'
108    name
109  }, additionalProperties)
110
111NUMBER = (value) -> {
112  type: 'NumericLiteral'
113  value
114}
115
116STRING = (value) -> {
117  type: 'StringLiteral'
118  value
119}
120
121# Check each node type in the same order as they appear in `nodes.coffee`.
122# For nodes that have equivalents in Babel’s AST spec, we’re checking that
123# the type and properties match. When relevant, also check that values of
124# properties are as expected.
125
126test "AST as expected for Block node", ->
127  deepStrictIncludeExpectedProperties CoffeeScript.compile('a', ast: yes),
128    type: 'File'
129    program:
130      type: 'Program'
131      # sourceType: 'module'
132      body: [
133        type: 'ExpressionStatement'
134        expression:
135          type: 'Identifier'
136      ]
137      directives: []
138    comments: []
139
140  deepStrictIncludeExpectedProperties CoffeeScript.compile('# comment', ast: yes),
141    type: 'File'
142    program:
143      type: 'Program'
144      body: []
145      directives: []
146    comments: [
147      type: 'CommentLine'
148      value: ' comment'
149    ]
150
151  deepStrictIncludeExpectedProperties CoffeeScript.compile('', ast: yes),
152    type: 'File'
153    program:
154      type: 'Program'
155      body: []
156      directives: []
157
158  deepStrictIncludeExpectedProperties CoffeeScript.compile(' ', ast: yes),
159    type: 'File'
160    program:
161      type: 'Program'
162      body: []
163      directives: []
164
165test "AST as expected for NumberLiteral node", ->
166  testExpression '42',
167    type: 'NumericLiteral'
168    value: 42
169    extra:
170      rawValue: 42
171      raw: '42'
172
173  testExpression '0xE1',
174    type: 'NumericLiteral'
175    value: 225
176    extra:
177      rawValue: 225
178      raw: '0xE1'
179
180  testExpression '10_000',
181    type: 'NumericLiteral'
182    value: 10000
183    extra:
184      rawValue: 10000
185      raw: '10_000'
186
187  testExpression '1_2.34_5e6_7',
188    type: 'NumericLiteral'
189    value: 12.345e67
190    extra:
191      rawValue: 12.345e67
192      raw: '1_2.34_5e6_7'
193
194  testExpression '0o7_7_7',
195    type: 'NumericLiteral'
196    value: 0o777
197    extra:
198      rawValue: 0o777
199      raw: '0o7_7_7'
200
201  testExpression '42n',
202    type: 'BigIntLiteral'
203    value: '42'
204    extra:
205      rawValue: '42'
206      raw: '42n'
207
208  testExpression '2e3_08',
209    type: 'NumericLiteral'
210    value: Infinity
211    extra:
212      rawValue: Infinity
213      raw: '2e3_08'
214
215test "AST as expected for InfinityLiteral node", ->
216  testExpression 'Infinity',
217    type: 'Identifier'
218    name: 'Infinity'
219
220  testExpression '2e308',
221    type: 'NumericLiteral'
222    value: Infinity
223    extra:
224      raw: '2e308'
225      rawValue: Infinity
226
227test "AST as expected for NaNLiteral node", ->
228  testExpression 'NaN',
229    type: 'Identifier'
230    name: 'NaN'
231
232test "AST as expected for StringLiteral node", ->
233  # Just a standalone string literal would be treated as a directive,
234  # so embed the string literal in an enclosing expression (e.g. a call).
235  testExpression 'a "string cheese"',
236    type: 'CallExpression'
237    arguments: [
238      type: 'StringLiteral'
239      value: 'string cheese'
240      extra:
241        raw: '"string cheese"'
242    ]
243
244  testExpression "b 'cheese string'",
245    type: 'CallExpression'
246    arguments: [
247      type: 'StringLiteral'
248      value: 'cheese string'
249      extra:
250        raw: "'cheese string'"
251    ]
252
253  testExpression "'''heredoc'''",
254    type: 'TemplateLiteral'
255    expressions: []
256    quasis: [
257      type: 'TemplateElement'
258      value:
259        raw: 'heredoc'
260      tail: yes
261    ]
262    quote: "'''"
263
264test "AST as expected for PassthroughLiteral node", ->
265  code = 'const CONSTANT = "unreassignable!"'
266  testExpression "`#{code}`",
267    type: 'PassthroughLiteral'
268    value: code
269    here: no
270
271  code = '\nconst CONSTANT = "unreassignable!"\n'
272  testExpression "```#{code}```",
273    type: 'PassthroughLiteral'
274    value: code
275    here: yes
276
277  testExpression "``",
278    type: 'PassthroughLiteral'
279    value: ''
280    here: no
281
282  # escaped backticks
283  testExpression "`\\`abc\\``",
284    type: 'PassthroughLiteral'
285    value: '\\`abc\\`'
286    here: no
287
288test "AST as expected for IdentifierLiteral node", ->
289  testExpression 'id',
290    type: 'Identifier'
291    name: 'id'
292
293test "AST as expected for JSXTag node", ->
294  testExpression '<CSXY />',
295    type: 'JSXElement'
296    openingElement:
297      type: 'JSXOpeningElement'
298      name:
299        type: 'JSXIdentifier'
300        name: 'CSXY'
301      attributes: []
302      selfClosing: yes
303    closingElement: null
304    children: []
305
306  testExpression '<div></div>',
307    type: 'JSXElement'
308    openingElement:
309      type: 'JSXOpeningElement'
310      name:
311        type: 'JSXIdentifier'
312        name: 'div'
313      attributes: []
314      selfClosing: no
315    closingElement:
316      type: 'JSXClosingElement'
317      name:
318        type: 'JSXIdentifier'
319        name: 'div'
320    children: []
321
322  testExpression '<A.B />',
323    type: 'JSXElement'
324    openingElement:
325      type: 'JSXOpeningElement'
326      name:
327        type: 'JSXMemberExpression'
328        object:
329          type: 'JSXIdentifier'
330          name: 'A'
331        property:
332          type: 'JSXIdentifier'
333          name: 'B'
334      attributes: []
335      selfClosing: yes
336    closingElement: null
337    children: []
338
339  testExpression '<Tag.Name.Here></Tag.Name.Here>',
340    type: 'JSXElement'
341    openingElement:
342      type: 'JSXOpeningElement'
343      name:
344        type: 'JSXMemberExpression'
345        object:
346          type: 'JSXMemberExpression'
347          object:
348            type: 'JSXIdentifier'
349            name: 'Tag'
350          property:
351            type: 'JSXIdentifier'
352            name: 'Name'
353        property:
354          type: 'JSXIdentifier'
355          name: 'Here'
356      attributes: []
357      selfClosing: no
358    closingElement:
359      type: 'JSXClosingElement'
360      name:
361        type: 'JSXMemberExpression'
362        object:
363          type: 'JSXMemberExpression'
364          object:
365            type: 'JSXIdentifier'
366            name: 'Tag'
367          property:
368            type: 'JSXIdentifier'
369            name: 'Name'
370        property:
371          type: 'JSXIdentifier'
372          name: 'Here'
373    children: []
374
375  testExpression '<></>',
376    type: 'JSXFragment'
377    openingFragment:
378      type: 'JSXOpeningFragment'
379    closingFragment:
380      type: 'JSXClosingFragment'
381    children: []
382
383  testExpression '<div a b="c" d={e} {...f} />',
384    type: 'JSXElement'
385    openingElement:
386      type: 'JSXOpeningElement'
387      name:
388        type: 'JSXIdentifier'
389        name: 'div'
390      attributes: [
391        type: 'JSXAttribute'
392        name:
393          type: 'JSXIdentifier'
394          name: 'a'
395      ,
396        type: 'JSXAttribute'
397        name:
398          type: 'JSXIdentifier'
399          name: 'b'
400        value:
401          type: 'StringLiteral'
402          value: 'c'
403      ,
404        type: 'JSXAttribute'
405        name:
406          type: 'JSXIdentifier'
407          name: 'd'
408        value:
409          type: 'JSXExpressionContainer'
410          expression:
411            type: 'Identifier'
412            name: 'e'
413      ,
414        type: 'JSXSpreadAttribute'
415        argument:
416          type: 'Identifier'
417          name: 'f'
418        postfix: no
419      ]
420      selfClosing: yes
421    closingElement: null
422    children: []
423
424  testExpression '<div {f...} />',
425    type: 'JSXElement'
426    openingElement:
427      type: 'JSXOpeningElement'
428      attributes: [
429        type: 'JSXSpreadAttribute'
430        argument:
431          type: 'Identifier'
432          name: 'f'
433        postfix: yes
434      ]
435
436  testExpression '<div>abc</div>',
437    type: 'JSXElement'
438    openingElement:
439      type: 'JSXOpeningElement'
440      name:
441        type: 'JSXIdentifier'
442        name: 'div'
443      attributes: []
444      selfClosing: no
445    closingElement:
446      type: 'JSXClosingElement'
447      name:
448        type: 'JSXIdentifier'
449        name: 'div'
450    children: [
451      type: 'JSXText'
452      extra:
453        raw: 'abc'
454      value: 'abc'
455    ]
456
457  testExpression '''
458    <a>
459      {b}
460      <c />
461    </a>
462  ''',
463    type: 'JSXElement'
464    openingElement:
465      type: 'JSXOpeningElement'
466      name:
467        type: 'JSXIdentifier'
468        name: 'a'
469      attributes: []
470      selfClosing: no
471    closingElement:
472      type: 'JSXClosingElement'
473      name:
474        type: 'JSXIdentifier'
475        name: 'a'
476    children: [
477      type: 'JSXText'
478      extra:
479        raw: '\n  '
480      value: '\n  '
481    ,
482      type: 'JSXExpressionContainer'
483      expression: ID 'b'
484    ,
485      type: 'JSXText'
486      extra:
487        raw: '\n  '
488      value: '\n  '
489    ,
490      type: 'JSXElement'
491      openingElement:
492        type: 'JSXOpeningElement'
493        name:
494          type: 'JSXIdentifier'
495          name: 'c'
496        selfClosing: true
497      closingElement: null
498      children: []
499    ,
500      type: 'JSXText'
501      extra:
502        raw: '\n'
503      value: '\n'
504    ]
505
506  testExpression '<>abc{}</>',
507    type: 'JSXFragment'
508    openingFragment:
509      type: 'JSXOpeningFragment'
510    closingFragment:
511      type: 'JSXClosingFragment'
512    children: [
513      type: 'JSXText'
514      extra:
515        raw: 'abc'
516      value: 'abc'
517    ,
518      type: 'JSXExpressionContainer'
519      expression:
520        type: 'JSXEmptyExpression'
521    ]
522
523  testExpression '''
524    <a>{<b />}</a>
525  ''',
526    type: 'JSXElement'
527    openingElement:
528      type: 'JSXOpeningElement'
529      name:
530        type: 'JSXIdentifier'
531        name: 'a'
532      attributes: []
533      selfClosing: no
534    closingElement:
535      type: 'JSXClosingElement'
536      name:
537        type: 'JSXIdentifier'
538        name: 'a'
539    children: [
540      type: 'JSXExpressionContainer'
541      expression:
542        type: 'JSXElement'
543        openingElement:
544          type: 'JSXOpeningElement'
545          name:
546            type: 'JSXIdentifier'
547            name: 'b'
548          selfClosing: true
549        closingElement: null
550        children: []
551    ]
552
553  testExpression '''
554    <div>{
555      # comment
556    }</div>
557  ''',
558    type: 'JSXElement'
559    openingElement:
560      type: 'JSXOpeningElement'
561      name:
562        type: 'JSXIdentifier'
563        name: 'div'
564      attributes: []
565      selfClosing: no
566    closingElement:
567      type: 'JSXClosingElement'
568      name:
569        type: 'JSXIdentifier'
570        name: 'div'
571    children: [
572      type: 'JSXExpressionContainer'
573      expression:
574        type: 'JSXEmptyExpression'
575    ]
576
577  testExpression '''
578    <div>{### here ###}</div>
579  ''',
580    type: 'JSXElement'
581    openingElement:
582      type: 'JSXOpeningElement'
583      name:
584        type: 'JSXIdentifier'
585        name: 'div'
586      attributes: []
587      selfClosing: no
588    closingElement:
589      type: 'JSXClosingElement'
590      name:
591        type: 'JSXIdentifier'
592        name: 'div'
593    children: [
594      type: 'JSXExpressionContainer'
595      expression:
596        type: 'JSXEmptyExpression'
597    ]
598
599  testExpression '<div:a b:c />',
600    type: 'JSXElement'
601    openingElement:
602      type: 'JSXOpeningElement'
603      name:
604        type: 'JSXNamespacedName'
605        namespace:
606          type: 'JSXIdentifier'
607          name: 'div'
608        name:
609          type: 'JSXIdentifier'
610          name: 'a'
611      attributes: [
612        type: 'JSXAttribute'
613        name:
614          type: 'JSXNamespacedName'
615          namespace:
616            type: 'JSXIdentifier'
617            name: 'b'
618          name:
619            type: 'JSXIdentifier'
620            name: 'c'
621      ]
622      selfClosing: yes
623
624  testExpression '''
625    <div:a>
626      {b}
627    </div:a>
628  ''',
629    type: 'JSXElement'
630    openingElement:
631      type: 'JSXOpeningElement'
632      name:
633        type: 'JSXNamespacedName'
634        namespace:
635          type: 'JSXIdentifier'
636          name: 'div'
637        name:
638          type: 'JSXIdentifier'
639          name: 'a'
640    closingElement:
641      type: 'JSXClosingElement'
642      name:
643        type: 'JSXNamespacedName'
644        namespace:
645          type: 'JSXIdentifier'
646          name: 'div'
647        name:
648          type: 'JSXIdentifier'
649          name: 'a'
650
651  testExpression '''
652    <div b={
653      c
654      d
655    } />
656  ''',
657    type: 'JSXElement'
658    openingElement:
659      attributes: [
660        value:
661          type: 'JSXExpressionContainer'
662          expression:
663            type: 'BlockStatement'
664            body: [
665              type: 'ExpressionStatement'
666            ,
667              type: 'ExpressionStatement'
668              expression:
669                returns: yes
670            ]
671      ]
672
673test "AST as expected for ComputedPropertyName node", ->
674  testExpression '[fn]: ->',
675    type: 'ObjectExpression'
676    properties: [
677      type: 'ObjectProperty'
678      key:
679        type: 'Identifier'
680        name: 'fn'
681      value:
682        type: 'FunctionExpression'
683      computed: yes
684      shorthand: no
685      method: no
686    ]
687    implicit: yes
688
689  testExpression '[a]: b',
690    type: 'ObjectExpression'
691    properties: [
692      type: 'ObjectProperty'
693      key:
694        type: 'Identifier'
695        name: 'a'
696      value:
697        type: 'Identifier'
698        name: 'b'
699      computed: yes
700      shorthand: no
701      method: no
702    ]
703    implicit: yes
704
705test "AST as expected for StatementLiteral node", ->
706  testStatement 'break',
707    type: 'BreakStatement'
708
709  testStatement 'continue',
710    type: 'ContinueStatement'
711
712  testStatement 'debugger',
713    type: 'DebuggerStatement'
714
715test "AST as expected for ThisLiteral node", ->
716  testExpression 'this',
717    type: 'ThisExpression'
718    shorthand: no
719
720  testExpression '@',
721    type: 'ThisExpression'
722    shorthand: yes
723
724  testExpression '@b',
725    type: 'MemberExpression'
726    object:
727      type: 'ThisExpression'
728      shorthand: yes
729    property: ID 'b'
730
731  testExpression 'this.b',
732    type: 'MemberExpression'
733    object:
734      type: 'ThisExpression'
735      shorthand: no
736    property: ID 'b'
737
738test "AST as expected for UndefinedLiteral node", ->
739  testExpression 'undefined',
740    type: 'Identifier'
741    name: 'undefined'
742
743test "AST as expected for NullLiteral node", ->
744  testExpression 'null',
745    type: 'NullLiteral'
746
747test "AST as expected for BooleanLiteral node", ->
748  testExpression 'true',
749    type: 'BooleanLiteral'
750    value: true
751    name: 'true'
752
753  testExpression 'off',
754    type: 'BooleanLiteral'
755    value: false
756    name: 'off'
757
758  testExpression 'yes',
759    type: 'BooleanLiteral'
760    value: true
761    name: 'yes'
762
763test "AST as expected for Return node", ->
764  testStatement 'return no',
765    type: 'ReturnStatement'
766    argument:
767      type: 'BooleanLiteral'
768
769  testExpression '''
770    (a, b) ->
771      return a + b
772  ''',
773    type: 'FunctionExpression'
774    body:
775      type: 'BlockStatement'
776      body: [
777        type: 'ReturnStatement'
778        argument:
779          type: 'BinaryExpression'
780      ]
781
782  testExpression '-> return',
783    type: 'FunctionExpression'
784    body:
785      type: 'BlockStatement'
786      body: [
787        type: 'ReturnStatement'
788        argument: null
789      ]
790
791test "AST as expected for YieldReturn node", ->
792  testExpression '-> yield return 1',
793    type: 'FunctionExpression'
794    body:
795      type: 'BlockStatement'
796      body: [
797        type: 'ExpressionStatement'
798        expression:
799          type: 'YieldExpression'
800          argument:
801            type: 'ReturnStatement'
802            argument: NUMBER 1
803          delegate: no
804      ]
805
806test "AST as expected for AwaitReturn node", ->
807  testExpression '-> await return 2',
808    type: 'FunctionExpression'
809    body:
810      type: 'BlockStatement'
811      body: [
812        type: 'ExpressionStatement'
813        expression:
814          type: 'AwaitExpression'
815          argument:
816            type: 'ReturnStatement'
817            argument: NUMBER 2
818      ]
819
820test "AST as expected for Call node", ->
821  testExpression 'fn()',
822    type: 'CallExpression'
823    callee:
824      type: 'Identifier'
825      name: 'fn'
826    arguments: []
827    optional: no
828    implicit: no
829    returns: undefined
830
831  testExpression 'new Date()',
832    type: 'NewExpression'
833    callee:
834      type: 'Identifier'
835      name: 'Date'
836    arguments: []
837    optional: no
838    implicit: no
839
840  testExpression 'new Date?()',
841    type: 'NewExpression'
842    callee:
843      type: 'Identifier'
844      name: 'Date'
845    arguments: []
846    optional: yes
847    implicit: no
848
849  testExpression 'new Old',
850    type: 'NewExpression'
851    callee:
852      type: 'Identifier'
853      name: 'Old'
854    arguments: []
855    optional: no
856    implicit: no
857
858  testExpression 'new Old(1)',
859    type: 'NewExpression'
860    callee:
861      type: 'Identifier'
862      name: 'Old'
863    arguments: [
864      type: 'NumericLiteral'
865      value: 1
866    ]
867    optional: no
868    implicit: no
869
870  testExpression 'new Old 1',
871    type: 'NewExpression'
872    callee:
873      type: 'Identifier'
874      name: 'Old'
875    arguments: [
876      type: 'NumericLiteral'
877      value: 1
878    ]
879    optional: no
880    implicit: yes
881
882  testExpression 'maybe?()',
883    type: 'OptionalCallExpression'
884    optional: yes
885    implicit: no
886
887  testExpression 'maybe?(1 + 1)',
888    type: 'OptionalCallExpression'
889    arguments: [
890      type: 'BinaryExpression'
891    ]
892    optional: yes
893    implicit: no
894
895  testExpression 'maybe? 1 + 1',
896    type: 'OptionalCallExpression'
897    arguments: [
898      type: 'BinaryExpression'
899    ]
900    optional: yes
901    implicit: yes
902
903  testExpression 'goDo this, that',
904    type: 'CallExpression'
905    arguments: [
906      type: 'ThisExpression'
907    ,
908      type: 'Identifier'
909      name: 'that'
910    ]
911    implicit: yes
912    optional: no
913
914  testExpression 'a?().b',
915    type: 'OptionalMemberExpression'
916    object:
917      type: 'OptionalCallExpression'
918      optional: yes
919    optional: no
920
921  testExpression 'a?.b.c()',
922    type: 'OptionalCallExpression'
923    callee:
924      type: 'OptionalMemberExpression'
925      object:
926        type: 'OptionalMemberExpression'
927        optional: yes
928      optional: no
929    optional: no
930
931  testExpression 'a?.b?()',
932    type: 'OptionalCallExpression'
933    callee:
934      type: 'OptionalMemberExpression'
935      optional: yes
936    optional: yes
937
938  testExpression 'a?().b?()',
939    type: 'OptionalCallExpression'
940    callee:
941      type: 'OptionalMemberExpression'
942      optional: no
943      object:
944        type: 'OptionalCallExpression'
945        optional: yes
946    optional: yes
947
948  testExpression 'a().b?()',
949    type: 'OptionalCallExpression'
950    callee:
951      type: 'MemberExpression'
952      optional: no
953      object:
954        type: 'CallExpression'
955        optional: no
956    optional: yes
957
958  testExpression 'a?().b()',
959    type: 'OptionalCallExpression'
960    callee:
961      type: 'OptionalMemberExpression'
962      optional: no
963      object:
964        type: 'OptionalCallExpression'
965        optional: yes
966    optional: no
967
968test "AST as expected for SuperCall node", ->
969  testStatement 'class child extends parent then constructor: -> super()',
970    type: 'ClassDeclaration'
971    body:
972      type: 'ClassBody'
973      body: [
974        body:
975          type: 'BlockStatement'
976          body: [
977            type: 'ExpressionStatement'
978            expression:
979              type: 'CallExpression'
980              callee:
981                type: 'Super'
982          ]
983      ]
984
985test "AST as expected for Super node", ->
986  testStatement 'class child extends parent then func: -> super.prop',
987    type: 'ClassDeclaration'
988    body:
989      type: 'ClassBody'
990      body: [
991        body:
992          type: 'BlockStatement'
993          body: [
994            type: 'ExpressionStatement'
995            expression:
996              type: 'MemberExpression'
997              object:
998                type: 'Super'
999              property: ID 'prop'
1000              computed: no
1001          ]
1002      ]
1003
1004  testStatement '''
1005    class child extends parent
1006      func: ->
1007        super[prop]()
1008  ''',
1009    type: 'ClassDeclaration'
1010    body:
1011      type: 'ClassBody'
1012      body: [
1013        body:
1014          type: 'BlockStatement'
1015          body: [
1016            type: 'ExpressionStatement'
1017            expression:
1018              type: 'CallExpression'
1019              callee:
1020                type: 'MemberExpression'
1021                object:
1022                  type: 'Super'
1023                property: ID 'prop'
1024                computed: yes
1025          ]
1026      ]
1027
1028test "AST as expected for RegexWithInterpolations node", ->
1029  testExpression '///^#{flavor}script$///',
1030    type: 'InterpolatedRegExpLiteral'
1031    interpolatedPattern:
1032      type: 'TemplateLiteral'
1033      expressions: [
1034        ID 'flavor'
1035      ]
1036      quasis: [
1037        type: 'TemplateElement'
1038        value:
1039          raw: '^'
1040        tail: no
1041      ,
1042        type: 'TemplateElement'
1043        value:
1044          raw: 'script$'
1045        tail: yes
1046      ]
1047      quote: '///'
1048    flags: ''
1049
1050  testExpression '''
1051    ///
1052      a
1053      #{b}///ig
1054  ''',
1055    type: 'InterpolatedRegExpLiteral'
1056    interpolatedPattern:
1057      type: 'TemplateLiteral'
1058      expressions: [
1059        ID 'b'
1060      ]
1061      quasis: [
1062        type: 'TemplateElement'
1063        value:
1064          raw: '\n  a\n  '
1065        tail: no
1066      ,
1067        type: 'TemplateElement'
1068        value:
1069          raw: ''
1070        tail: yes
1071      ]
1072      quote: '///'
1073    flags: 'ig'
1074
1075  testExpression '''
1076    ///
1077      a # first
1078      #{b} ### second ###
1079    ///ig
1080  ''',
1081    type: 'InterpolatedRegExpLiteral'
1082    interpolatedPattern:
1083      type: 'TemplateLiteral'
1084      expressions: [
1085        ID 'b'
1086      ]
1087      quasis: [
1088        type: 'TemplateElement'
1089        value:
1090          raw: '\n  a # first\n  '
1091        tail: no
1092      ,
1093        type: 'TemplateElement'
1094        value:
1095          raw: ' ### second ###\n'
1096        tail: yes
1097      ]
1098      quote: '///'
1099    flags: 'ig'
1100    comments: [
1101      type: 'CommentLine'
1102      value: ' first'
1103    ,
1104      type: 'CommentBlock'
1105      value: ' second '
1106    ]
1107
1108test "AST as expected for TaggedTemplateCall node", ->
1109  testExpression 'func"tagged"',
1110    type: 'TaggedTemplateExpression'
1111    tag: ID 'func'
1112    quasi:
1113      type: 'TemplateLiteral'
1114      expressions: []
1115      quasis: [
1116        type: 'TemplateElement'
1117        value:
1118          raw: 'tagged'
1119        tail: yes
1120      ]
1121
1122  testExpression 'a"b#{c}"',
1123    type: 'TaggedTemplateExpression'
1124    tag: ID 'a'
1125    quasi:
1126      type: 'TemplateLiteral'
1127      expressions: [
1128        ID 'c'
1129      ]
1130      quasis: [
1131        type: 'TemplateElement'
1132        value:
1133          raw: 'b'
1134        tail: no
1135      ,
1136        type: 'TemplateElement'
1137        value:
1138          raw: ''
1139        tail: yes
1140      ]
1141
1142  testExpression '''
1143    a"""
1144      b#{c}
1145    """
1146  ''',
1147    type: 'TaggedTemplateExpression'
1148    tag: ID 'a'
1149    quasi:
1150      type: 'TemplateLiteral'
1151      expressions: [
1152        ID 'c'
1153      ]
1154      quasis: [
1155        type: 'TemplateElement'
1156        value:
1157          raw: '\n  b'
1158        tail: no
1159      ,
1160        type: 'TemplateElement'
1161        value:
1162          raw: '\n'
1163        tail: yes
1164      ]
1165
1166  testExpression """
1167    a'''
1168      b
1169    '''
1170  """,
1171    type: 'TaggedTemplateExpression'
1172    tag: ID 'a'
1173    quasi:
1174      type: 'TemplateLiteral'
1175      expressions: []
1176      quasis: [
1177        type: 'TemplateElement'
1178        value:
1179          raw: '\n  b\n'
1180        tail: yes
1181      ]
1182
1183test "AST as expected for Access node", ->
1184  testExpression 'obj.prop',
1185    type: 'MemberExpression'
1186    object:
1187      type: 'Identifier'
1188      name: 'obj'
1189    property:
1190      type: 'Identifier'
1191      name: 'prop'
1192    computed: no
1193    optional: no
1194    shorthand: no
1195
1196  testExpression 'obj?.prop',
1197    type: 'OptionalMemberExpression'
1198    object:
1199      type: 'Identifier'
1200      name: 'obj'
1201    property:
1202      type: 'Identifier'
1203      name: 'prop'
1204    computed: no
1205    optional: yes
1206    shorthand: no
1207
1208  testExpression 'a::b',
1209    type: 'MemberExpression'
1210    object:
1211      type: 'MemberExpression'
1212      object:
1213        type: 'Identifier'
1214        name: 'a'
1215      property:
1216        type: 'Identifier'
1217        name: 'prototype'
1218      computed: no
1219      optional: no
1220      shorthand: yes
1221    property:
1222      type: 'Identifier'
1223      name: 'b'
1224    computed: no
1225    optional: no
1226    shorthand: no
1227
1228  testExpression 'a.prototype.b',
1229    type: 'MemberExpression'
1230    object:
1231      type: 'MemberExpression'
1232      object:
1233        type: 'Identifier'
1234        name: 'a'
1235      property:
1236        type: 'Identifier'
1237        name: 'prototype'
1238      computed: no
1239      optional: no
1240      shorthand: no
1241    property:
1242      type: 'Identifier'
1243      name: 'b'
1244    computed: no
1245    optional: no
1246    shorthand: no
1247
1248  testExpression 'a?.b.c',
1249    type: 'OptionalMemberExpression'
1250    object:
1251      type: 'OptionalMemberExpression'
1252      object:
1253        type: 'Identifier'
1254        name: 'a'
1255      property:
1256        type: 'Identifier'
1257        name: 'b'
1258      computed: no
1259      optional: yes
1260      shorthand: no
1261    property:
1262      type: 'Identifier'
1263      name: 'c'
1264    computed: no
1265    optional: no
1266    shorthand: no
1267
1268test "AST as expected for Index node", ->
1269  testExpression 'a[b]',
1270    type: 'MemberExpression'
1271    object:
1272      type: 'Identifier'
1273      name: 'a'
1274    property:
1275      type: 'Identifier'
1276      name: 'b'
1277    computed: yes
1278    optional: no
1279    shorthand: no
1280
1281  testExpression 'a?[b]',
1282    type: 'OptionalMemberExpression'
1283    object:
1284      type: 'Identifier'
1285      name: 'a'
1286    property:
1287      type: 'Identifier'
1288      name: 'b'
1289    computed: yes
1290    optional: yes
1291    shorthand: no
1292
1293  testExpression 'a::[b]',
1294    type: 'MemberExpression'
1295    object:
1296      type: 'MemberExpression'
1297      object:
1298        type: 'Identifier'
1299        name: 'a'
1300      property:
1301        type: 'Identifier'
1302        name: 'prototype'
1303      computed: no
1304      optional: no
1305      shorthand: yes
1306    property:
1307      type: 'Identifier'
1308      name: 'b'
1309    computed: yes
1310    optional: no
1311    shorthand: no
1312
1313  testExpression 'a[b][3]',
1314    type: 'MemberExpression'
1315    object:
1316      type: 'MemberExpression'
1317      object:
1318        type: 'Identifier'
1319        name: 'a'
1320      property:
1321        type: 'Identifier'
1322        name: 'b'
1323      computed: yes
1324      optional: no
1325      shorthand: no
1326    property:
1327      type: 'NumericLiteral'
1328      value: 3
1329    computed: yes
1330    optional: no
1331    shorthand: no
1332
1333  testExpression 'a[if b then c]',
1334    type: 'MemberExpression'
1335    object: ID 'a'
1336    property:
1337      type: 'ConditionalExpression'
1338      test: ID 'b'
1339      consequent: ID 'c'
1340    computed: yes
1341    optional: no
1342    shorthand: no
1343
1344test "AST as expected for Range node", ->
1345  testExpression '[x..y]',
1346    type: 'Range'
1347    exclusive: no
1348    from:
1349      name: 'x'
1350    to:
1351      name: 'y'
1352
1353  testExpression '[4...2]',
1354    type: 'Range'
1355    exclusive: yes
1356    from:
1357      value: 4
1358    to:
1359      value: 2
1360
1361test "AST as expected for Slice node", ->
1362  testExpression 'x[..y]',
1363    property:
1364      type: 'Range'
1365      exclusive: no
1366      from: null
1367      to:
1368        name: 'y'
1369
1370  testExpression 'x[y...]',
1371    property:
1372      type: 'Range'
1373      exclusive: yes
1374      from:
1375        name: 'y'
1376      to: null
1377
1378  testExpression 'x[...]',
1379    property:
1380      type: 'Range'
1381      exclusive: yes
1382      from: null
1383      to: null
1384
1385  testExpression '"abc"[...2]',
1386    type: 'MemberExpression'
1387    property:
1388      type: 'Range'
1389      from: null
1390      to:
1391        type: 'NumericLiteral'
1392        value: 2
1393      exclusive: yes
1394    computed: yes
1395    optional: no
1396    shorthand: no
1397
1398  testExpression 'x[...][a..][b...][..c][...d]',
1399    type: 'MemberExpression'
1400    object:
1401      type: 'MemberExpression'
1402      object:
1403        type: 'MemberExpression'
1404        object:
1405          type: 'MemberExpression'
1406          object:
1407            type: 'MemberExpression'
1408            property:
1409              type: 'Range'
1410              from: null
1411              to: null
1412              exclusive: yes
1413          property:
1414            type: 'Range'
1415            from:
1416              name: 'a'
1417            to: null
1418            exclusive: no
1419        property:
1420          type: 'Range'
1421          from:
1422            name: 'b'
1423          to: null
1424          exclusive: yes
1425      property:
1426        type: 'Range'
1427        from: null
1428        to:
1429          name: 'c'
1430        exclusive: no
1431    property:
1432      type: 'Range'
1433      from: null
1434      to:
1435        name: 'd'
1436      exclusive: yes
1437
1438test "AST as expected for Obj node", ->
1439  testExpression "{a: 1, b, [c], @d, [e()]: f, 'g': 2, ...h, i...}",
1440    type: 'ObjectExpression'
1441    properties: [
1442      type: 'ObjectProperty'
1443      key:
1444        type: 'Identifier'
1445        name: 'a'
1446      value:
1447        type: 'NumericLiteral'
1448        value: 1
1449      computed: no
1450      shorthand: no
1451    ,
1452      type: 'ObjectProperty'
1453      key:
1454        type: 'Identifier'
1455        name: 'b'
1456      value:
1457        type: 'Identifier'
1458        name: 'b'
1459      computed: no
1460      shorthand: yes
1461    ,
1462      type: 'ObjectProperty'
1463      key:
1464        type: 'Identifier'
1465        name: 'c'
1466      value:
1467        type: 'Identifier'
1468        name: 'c'
1469      computed: yes
1470      shorthand: yes
1471    ,
1472      type: 'ObjectProperty'
1473      key:
1474        type: 'MemberExpression'
1475        object:
1476          type: 'ThisExpression'
1477        property:
1478          type: 'Identifier'
1479          name: 'd'
1480      value:
1481        type: 'MemberExpression'
1482        object:
1483          type: 'ThisExpression'
1484        property:
1485          type: 'Identifier'
1486          name: 'd'
1487      computed: no
1488      shorthand: yes
1489    ,
1490      type: 'ObjectProperty'
1491      key:
1492        type: 'CallExpression'
1493        callee:
1494          type: 'Identifier'
1495          name: 'e'
1496        arguments: []
1497      value:
1498        type: 'Identifier'
1499        name: 'f'
1500      computed: yes
1501      shorthand: no
1502    ,
1503      type: 'ObjectProperty'
1504      key:
1505        type: 'StringLiteral'
1506        value: 'g'
1507      value:
1508        type: 'NumericLiteral'
1509        value: 2
1510      computed: no
1511      shorthand: no
1512    ,
1513      type: 'SpreadElement'
1514      argument:
1515        type: 'Identifier'
1516        name: 'h'
1517      postfix: no
1518    ,
1519      type: 'SpreadElement'
1520      argument:
1521        type: 'Identifier'
1522        name: 'i'
1523      postfix: yes
1524    ]
1525    implicit: no
1526
1527  testExpression 'a: 1',
1528    type: 'ObjectExpression'
1529    properties: [
1530      type: 'ObjectProperty'
1531      key:
1532        type: 'Identifier'
1533        name: 'a'
1534      value:
1535        type: 'NumericLiteral'
1536        value: 1
1537      shorthand: no
1538      computed: no
1539    ]
1540    implicit: yes
1541
1542  testExpression '''
1543    a:
1544      if b then c
1545  ''',
1546    type: 'ObjectExpression'
1547    properties: [
1548      type: 'ObjectProperty'
1549      key: ID 'a'
1550      value:
1551        type: 'ConditionalExpression'
1552        test: ID 'b'
1553        consequent: ID 'c'
1554    ]
1555    implicit: yes
1556
1557  testExpression '''
1558    a:
1559      c if b
1560  ''',
1561    type: 'ObjectExpression'
1562    properties: [
1563      type: 'ObjectProperty'
1564      key: ID 'a'
1565      value:
1566        type: 'ConditionalExpression'
1567        test: ID 'b'
1568        consequent: ID 'c'
1569    ]
1570    implicit: yes
1571
1572  testExpression '"#{a}": 1',
1573    type: 'ObjectExpression'
1574    properties: [
1575      type: 'ObjectProperty'
1576      key:
1577        type: 'TemplateLiteral'
1578        expressions: [
1579          ID 'a'
1580        ]
1581      value:
1582        type: 'NumericLiteral'
1583        value: 1
1584      shorthand: no
1585      computed: yes
1586    ]
1587    implicit: yes
1588
1589test "AST as expected for Arr node", ->
1590  testExpression '[]',
1591    type: 'ArrayExpression'
1592    elements: []
1593
1594  testExpression '[3, tables, !1]',
1595    type: 'ArrayExpression'
1596    elements: [
1597      {value: 3}
1598      {name: 'tables'}
1599      {operator: '!'}
1600    ]
1601
1602test "AST as expected for Class node", ->
1603  testStatement 'class Klass',
1604    type: 'ClassDeclaration'
1605    id: ID 'Klass', declaration: yes
1606    superClass: null
1607    body:
1608      type: 'ClassBody'
1609      body: []
1610
1611  testStatement 'class child extends parent',
1612    type: 'ClassDeclaration'
1613    id: ID 'child', declaration: yes
1614    superClass: ID 'parent', declaration: no
1615    body:
1616      type: 'ClassBody'
1617      body: []
1618
1619  testStatement 'class Klass then constructor: -> @a = 1',
1620    type: 'ClassDeclaration'
1621    id: ID 'Klass', declaration: yes
1622    superClass: null
1623    body:
1624      type: 'ClassBody'
1625      body: [
1626        type: 'ClassMethod'
1627        static: no
1628        key: ID 'constructor', declaration: no
1629        computed: no
1630        kind: 'constructor'
1631        id: null
1632        generator: no
1633        async: no
1634        params: []
1635        body:
1636          type: 'BlockStatement'
1637          body: [
1638            type: 'ExpressionStatement'
1639            expression:
1640              type: 'AssignmentExpression'
1641              returns: undefined
1642          ]
1643        bound: no
1644      ]
1645
1646  testExpression '''
1647    a = class A
1648      b: ->
1649        c
1650      d: =>
1651        e
1652  ''',
1653    type: 'AssignmentExpression'
1654    right:
1655      type: 'ClassExpression'
1656      id: ID 'A', declaration: yes
1657      superClass: null
1658      body:
1659        type: 'ClassBody'
1660        body: [
1661          type: 'ClassMethod'
1662          static: no
1663          key: ID 'b'
1664          computed: no
1665          kind: 'method'
1666          id: null
1667          generator: no
1668          async: no
1669          params: []
1670          body:
1671            type: 'BlockStatement'
1672            body: [
1673              type: 'ExpressionStatement'
1674              expression: ID 'c', returns: yes
1675            ]
1676          operator: ':'
1677          bound: no
1678        ,
1679          type: 'ClassMethod'
1680          static: no
1681          key: ID 'd'
1682          computed: no
1683          kind: 'method'
1684          id: null
1685          generator: no
1686          async: no
1687          params: []
1688          body:
1689            type: 'BlockStatement'
1690            body: [
1691              type: 'ExpressionStatement'
1692              expression: ID 'e'
1693            ]
1694          operator: ':'
1695          bound: yes
1696        ]
1697
1698  testStatement '''
1699    class A
1700      @b: ->
1701      @c = =>
1702      @d: 1
1703      @e = 2
1704      j = 5
1705      A.f = 3
1706      A.g = ->
1707      this.h = ->
1708      this.i = 4
1709  ''',
1710    type: 'ClassDeclaration'
1711    id: ID 'A', declaration: yes
1712    superClass: null
1713    body:
1714      type: 'ClassBody'
1715      body: [
1716        type: 'ClassMethod'
1717        static: yes
1718        key: ID 'b'
1719        computed: no
1720        kind: 'method'
1721        id: null
1722        generator: no
1723        async: no
1724        params: []
1725        body: EMPTY_BLOCK
1726        operator: ':'
1727        staticClassName:
1728          type: 'ThisExpression'
1729          shorthand: yes
1730        bound: no
1731      ,
1732        type: 'ClassMethod'
1733        static: yes
1734        key: ID 'c'
1735        computed: no
1736        kind: 'method'
1737        id: null
1738        generator: no
1739        async: no
1740        params: []
1741        body: EMPTY_BLOCK
1742        operator: '='
1743        staticClassName:
1744          type: 'ThisExpression'
1745          shorthand: yes
1746        bound: yes
1747      ,
1748        type: 'ClassProperty'
1749        static: yes
1750        key: ID 'd'
1751        computed: no
1752        value: NUMBER 1
1753        operator: ':'
1754        staticClassName:
1755          type: 'ThisExpression'
1756          shorthand: yes
1757      ,
1758        type: 'ClassProperty'
1759        static: yes
1760        key: ID 'e'
1761        computed: no
1762        value: NUMBER 2
1763        operator: '='
1764        staticClassName:
1765          type: 'ThisExpression'
1766          shorthand: yes
1767      ,
1768        type: 'ExpressionStatement'
1769        expression:
1770          type: 'AssignmentExpression'
1771          left: ID 'j', declaration: yes
1772          right: NUMBER 5
1773      ,
1774        type: 'ClassProperty'
1775        static: yes
1776        key: ID 'f'
1777        computed: no
1778        value: NUMBER 3
1779        operator: '='
1780        staticClassName: ID 'A'
1781      ,
1782        type: 'ClassMethod'
1783        static: yes
1784        key: ID 'g'
1785        computed: no
1786        kind: 'method'
1787        id: null
1788        generator: no
1789        async: no
1790        params: []
1791        body: EMPTY_BLOCK
1792        operator: '='
1793        staticClassName: ID 'A'
1794        bound: no
1795      ,
1796        type: 'ClassMethod'
1797        static: yes
1798        key: ID 'h'
1799        computed: no
1800        kind: 'method'
1801        id: null
1802        generator: no
1803        async: no
1804        params: []
1805        body: EMPTY_BLOCK
1806        operator: '='
1807        staticClassName:
1808          type: 'ThisExpression'
1809          shorthand: no
1810        bound: no
1811      ,
1812        type: 'ClassProperty'
1813        static: yes
1814        key: ID 'i'
1815        computed: no
1816        value: NUMBER 4
1817        operator: '='
1818        staticClassName:
1819          type: 'ThisExpression'
1820          shorthand: no
1821      ]
1822
1823  testStatement '''
1824    class A
1825      b: 1
1826      [c]: 2
1827      [d]: ->
1828      @[e]: ->
1829      @[f]: 3
1830  ''',
1831    type: 'ClassDeclaration'
1832    id: ID 'A', declaration: yes
1833    superClass: null
1834    body:
1835      type: 'ClassBody'
1836      body: [
1837        type: 'ClassPrototypeProperty'
1838        key: ID 'b', declaration: no
1839        value: NUMBER 1
1840        computed: no
1841      ,
1842        type: 'ClassPrototypeProperty'
1843        key: ID 'c'
1844        value: NUMBER 2
1845        computed: yes
1846      ,
1847        type: 'ClassMethod'
1848        static: no
1849        key: ID 'd'
1850        computed: yes
1851        kind: 'method'
1852        id: null
1853        generator: no
1854        async: no
1855        params: []
1856        body: EMPTY_BLOCK
1857        operator: ':'
1858        bound: no
1859      ,
1860        type: 'ClassMethod'
1861        static: yes
1862        key: ID 'e'
1863        computed: yes
1864        kind: 'method'
1865        id: null
1866        generator: no
1867        async: no
1868        params: []
1869        body: EMPTY_BLOCK
1870        operator: ':'
1871        bound: no
1872        staticClassName:
1873          type: 'ThisExpression'
1874          shorthand: yes
1875      ,
1876        type: 'ClassProperty'
1877        static: yes
1878        key: ID 'f'
1879        computed: yes
1880        value: NUMBER 3
1881        operator: ':'
1882        staticClassName:
1883          type: 'ThisExpression'
1884          shorthand: yes
1885      ]
1886
1887  testStatement '''
1888    class A
1889      @[b] = ->
1890      "#{c}": ->
1891      @[d] = 1
1892      [e]: 2
1893      "#{f}": 3
1894      @[g]: 4
1895  ''',
1896    type: 'ClassDeclaration'
1897    body:
1898      body: [
1899        type: 'ClassMethod'
1900        computed: yes
1901      ,
1902        type: 'ClassMethod'
1903        computed: yes
1904      ,
1905        type: 'ClassProperty'
1906        computed: yes
1907      ,
1908        type: 'ClassPrototypeProperty'
1909        computed: yes
1910      ,
1911        type: 'ClassPrototypeProperty'
1912        computed: yes
1913      ,
1914        type: 'ClassProperty'
1915        computed: yes
1916      ]
1917
1918  testStatement '''
1919    class A.b
1920  ''',
1921    type: 'ClassDeclaration'
1922    id:
1923      type: 'MemberExpression'
1924      object: ID 'A', declaration: no
1925      property: ID 'b', declaration: no
1926
1927  testStatement '''
1928    class A
1929      'constructor': ->
1930  ''',
1931    type: 'ClassDeclaration'
1932    body:
1933      type: 'ClassBody'
1934      body: [
1935        type: 'ClassMethod'
1936        static: no
1937        key:
1938          type: 'StringLiteral'
1939        computed: no
1940        kind: 'constructor'
1941        id: null
1942        generator: no
1943        async: no
1944        params: []
1945        body: EMPTY_BLOCK
1946        bound: no
1947      ]
1948
1949
1950test "AST as expected for ModuleDeclaration node", ->
1951  testStatement 'export {X}',
1952    type: 'ExportNamedDeclaration'
1953    declaration: null
1954    specifiers: [
1955      type: 'ExportSpecifier'
1956      local:
1957        type: 'Identifier'
1958        name: 'X'
1959        declaration: no
1960      exported:
1961        type: 'Identifier'
1962        name: 'X'
1963        declaration: no
1964    ]
1965    source: null
1966    exportKind: 'value'
1967
1968  testStatement 'import X from "."',
1969    type: 'ImportDeclaration'
1970    specifiers: [
1971      type: 'ImportDefaultSpecifier'
1972      local:
1973        type: 'Identifier'
1974        name: 'X'
1975        declaration: no
1976    ]
1977    importKind: 'value'
1978    source:
1979      type: 'StringLiteral'
1980      value: '.'
1981
1982test "AST as expected for ImportDeclaration node", ->
1983  testStatement 'import React, {Component} from "react"',
1984    type: 'ImportDeclaration'
1985    specifiers: [
1986      type: 'ImportDefaultSpecifier'
1987      local:
1988        type: 'Identifier'
1989        name: 'React'
1990        declaration: no
1991    ,
1992      type: 'ImportSpecifier'
1993      imported:
1994        type: 'Identifier'
1995        name: 'Component'
1996        declaration: no
1997      importKind: null
1998      local:
1999        type: 'Identifier'
2000        name: 'Component'
2001        declaration: no
2002    ]
2003    importKind: 'value'
2004    source:
2005      type: 'StringLiteral'
2006      value: 'react'
2007      extra:
2008        raw: '"react"'
2009
2010test "AST as expected for ExportNamedDeclaration node", ->
2011  testStatement 'export {}',
2012    type: 'ExportNamedDeclaration'
2013    declaration: null
2014    specifiers: []
2015    source: null
2016    exportKind: 'value'
2017
2018  testStatement 'export fn = ->',
2019    type: 'ExportNamedDeclaration'
2020    declaration:
2021      type: 'AssignmentExpression'
2022      left:
2023        type: 'Identifier'
2024        declaration: yes
2025      right:
2026        type: 'FunctionExpression'
2027    specifiers: []
2028    source: null
2029    exportKind: 'value'
2030
2031  testStatement 'export class A',
2032    type: 'ExportNamedDeclaration'
2033    declaration:
2034      type: 'ClassDeclaration'
2035      id: ID 'A', declaration: yes
2036      superClass: null
2037      body:
2038        type: 'ClassBody'
2039        body: []
2040    specifiers: []
2041    source: null
2042    exportKind: 'value'
2043
2044  testStatement 'export {x as y, z as default}',
2045    type: 'ExportNamedDeclaration'
2046    declaration: null
2047    specifiers: [
2048      type: 'ExportSpecifier'
2049      local:
2050        type: 'Identifier'
2051        name: 'x'
2052        declaration: no
2053      exported:
2054        type: 'Identifier'
2055        name: 'y'
2056        declaration: no
2057    ,
2058      type: 'ExportSpecifier'
2059      local:
2060        type: 'Identifier'
2061        name: 'z'
2062        declaration: no
2063      exported:
2064        type: 'Identifier'
2065        name: 'default'
2066        declaration: no
2067    ]
2068    source: null
2069    exportKind: 'value'
2070
2071  testStatement 'export {default, default as b} from "./abc"',
2072    type: 'ExportNamedDeclaration'
2073    declaration: null
2074    specifiers: [
2075      type: 'ExportSpecifier'
2076      local:
2077        type: 'Identifier'
2078        name: 'default'
2079        declaration: no
2080      exported:
2081        type: 'Identifier'
2082        name: 'default'
2083        declaration: no
2084    ,
2085      type: 'ExportSpecifier'
2086      local:
2087        type: 'Identifier'
2088        name: 'default'
2089        declaration: no
2090      exported:
2091        type: 'Identifier'
2092        name: 'b'
2093        declaration: no
2094    ]
2095    source:
2096      type: 'StringLiteral'
2097      value: './abc'
2098      extra:
2099        raw: '"./abc"'
2100    exportKind: 'value'
2101
2102test "AST as expected for ExportDefaultDeclaration node", ->
2103  testStatement 'export default class',
2104    type: 'ExportDefaultDeclaration'
2105    declaration:
2106      type: 'ClassDeclaration'
2107
2108  testStatement 'export default "abc"',
2109    type: 'ExportDefaultDeclaration'
2110    declaration:
2111      type: 'StringLiteral'
2112      value: 'abc'
2113      extra:
2114        raw: '"abc"'
2115
2116  testStatement 'export default a = b',
2117    type: 'ExportDefaultDeclaration'
2118    declaration:
2119      type: 'AssignmentExpression'
2120      left: ID 'a', declaration: yes
2121      right: ID 'b', declaration: no
2122
2123test "AST as expected for ExportAllDeclaration node", ->
2124  testStatement 'export * from "module-name"',
2125    type: 'ExportAllDeclaration'
2126    source:
2127      type: 'StringLiteral'
2128      value: 'module-name'
2129      extra:
2130        raw: '"module-name"'
2131    exportKind: 'value'
2132
2133test "AST as expected for ExportSpecifierList node", ->
2134  testStatement 'export {a, b, c}',
2135    type: 'ExportNamedDeclaration'
2136    declaration: null
2137    specifiers: [
2138      type: 'ExportSpecifier'
2139      local:
2140        type: 'Identifier'
2141        name: 'a'
2142        declaration: no
2143      exported:
2144        type: 'Identifier'
2145        name: 'a'
2146        declaration: no
2147    ,
2148      type: 'ExportSpecifier'
2149      local:
2150        type: 'Identifier'
2151        name: 'b'
2152        declaration: no
2153      exported:
2154        type: 'Identifier'
2155        name: 'b'
2156        declaration: no
2157    ,
2158      type: 'ExportSpecifier'
2159      local:
2160        type: 'Identifier'
2161        name: 'c'
2162        declaration: no
2163      exported:
2164        type: 'Identifier'
2165        name: 'c'
2166        declaration: no
2167    ]
2168
2169test "AST as expected for ImportDefaultSpecifier node", ->
2170  testStatement 'import React from "react"',
2171    type: 'ImportDeclaration'
2172    specifiers: [
2173      type: 'ImportDefaultSpecifier'
2174      local:
2175        type: 'Identifier'
2176        name: 'React'
2177        declaration: no
2178    ]
2179    importKind: 'value'
2180    source:
2181      type: 'StringLiteral'
2182      value: 'react'
2183
2184test "AST as expected for ImportNamespaceSpecifier node", ->
2185  testStatement 'import * as React from "react"',
2186    type: 'ImportDeclaration'
2187    specifiers: [
2188      type: 'ImportNamespaceSpecifier'
2189      local:
2190        type: 'Identifier'
2191        name: 'React'
2192        declaration: no
2193    ]
2194    importKind: 'value'
2195    source:
2196      type: 'StringLiteral'
2197      value: 'react'
2198
2199  testStatement 'import React, * as ReactStar from "react"',
2200    type: 'ImportDeclaration'
2201    specifiers: [
2202      type: 'ImportDefaultSpecifier'
2203      local:
2204        type: 'Identifier'
2205        name: 'React'
2206        declaration: no
2207    ,
2208      type: 'ImportNamespaceSpecifier'
2209      local:
2210        type: 'Identifier'
2211        name: 'ReactStar'
2212        declaration: no
2213    ]
2214    importKind: 'value'
2215    source:
2216      type: 'StringLiteral'
2217      value: 'react'
2218
2219test "AST as expected for Assign node", ->
2220  testExpression 'a = b',
2221    type: 'AssignmentExpression'
2222    left:
2223      type: 'Identifier'
2224      name: 'a'
2225      declaration: yes
2226    right:
2227      type: 'Identifier'
2228      name: 'b'
2229      declaration: no
2230    operator: '='
2231
2232  testExpression 'a += b',
2233    type: 'AssignmentExpression'
2234    left:
2235      type: 'Identifier'
2236      name: 'a'
2237      declaration: no
2238    right:
2239      type: 'Identifier'
2240      name: 'b'
2241      declaration: no
2242    operator: '+='
2243
2244  testExpression '[@a = 2, {b: {c = 3} = {}, d...}, ...e] = f',
2245    type: 'AssignmentExpression'
2246    left:
2247      type: 'ArrayPattern'
2248      elements: [
2249        type: 'AssignmentPattern'
2250        left:
2251          type: 'MemberExpression'
2252          object:
2253            type: 'ThisExpression'
2254          property:
2255            name: 'a'
2256            declaration: no
2257        right:
2258          type: 'NumericLiteral'
2259      ,
2260        type: 'ObjectPattern'
2261        properties: [
2262          type: 'ObjectProperty'
2263          key:
2264            name: 'b'
2265            declaration: no
2266          value:
2267            type: 'AssignmentPattern'
2268            left:
2269              type: 'ObjectPattern'
2270              properties: [
2271                type: 'ObjectProperty'
2272                key:
2273                  name: 'c'
2274                value:
2275                  type: 'AssignmentPattern'
2276                  left:
2277                    name: 'c'
2278                    declaration: yes
2279                  right:
2280                    value: 3
2281                shorthand: yes
2282              ]
2283            right:
2284              type: 'ObjectExpression'
2285              properties: []
2286        ,
2287          type: 'RestElement'
2288          argument:
2289            name: 'd'
2290            declaration: yes
2291          postfix: yes
2292        ]
2293      ,
2294        type: 'RestElement'
2295        argument:
2296          name: 'e'
2297          declaration: yes
2298        postfix: no
2299      ]
2300    right:
2301      name: 'f'
2302
2303  testExpression '{a: [...b]} = c',
2304    type: 'AssignmentExpression'
2305    left:
2306      type: 'ObjectPattern'
2307      properties: [
2308        type: 'ObjectProperty'
2309        key:
2310          name: 'a'
2311          declaration: no
2312        value:
2313          type: 'ArrayPattern'
2314          elements: [
2315            type: 'RestElement'
2316            argument:
2317              name: 'b'
2318              declaration: yes
2319          ]
2320      ]
2321    right:
2322      name: 'c'
2323      declaration: no
2324
2325  testExpression '(a = 1; a ?= b)',
2326    type: 'SequenceExpression'
2327    expressions: [
2328      type: 'AssignmentExpression'
2329    ,
2330      type: 'AssignmentExpression'
2331      left:
2332        type: 'Identifier'
2333        name: 'a'
2334        declaration: no
2335      right:
2336        type: 'Identifier'
2337        name: 'b'
2338        declaration: no
2339      operator: '?='
2340    ]
2341
2342  testExpression '[a..., b] = c',
2343    type: 'AssignmentExpression'
2344    left:
2345      type: 'ArrayPattern'
2346      elements: [
2347        type: 'RestElement'
2348        argument: ID 'a', declaration: yes
2349        postfix: yes
2350      ,
2351        ID 'b'
2352      ]
2353    right:
2354      ID 'c'
2355
2356  testExpression '[] = c',
2357    type: 'AssignmentExpression'
2358    left:
2359      type: 'ArrayPattern'
2360      elements: []
2361    right:
2362      ID 'c'
2363
2364  testExpression '{{a...}...} = b',
2365    type: 'AssignmentExpression'
2366    left:
2367      type: 'ObjectPattern'
2368      properties: [
2369        type: 'RestElement'
2370        argument:
2371          type: 'ObjectPattern'
2372          properties: [
2373            type: 'RestElement'
2374            argument: ID 'a'
2375          ]
2376        postfix: yes
2377      ]
2378    right: ID 'b'
2379
2380  testExpression '{a..., b} = c',
2381    type: 'AssignmentExpression'
2382    left:
2383      type: 'ObjectPattern'
2384      properties: [
2385        type: 'RestElement'
2386        argument: ID 'a'
2387        postfix: yes
2388      ,
2389        type: 'ObjectProperty'
2390      ]
2391    right: ID 'c'
2392
2393  testExpression '{a.b...} = c',
2394    type: 'AssignmentExpression'
2395    left:
2396      type: 'ObjectPattern'
2397      properties: [
2398        type: 'RestElement'
2399        argument:
2400          type: 'MemberExpression'
2401        postfix: yes
2402      ]
2403    right: ID 'c'
2404
2405  testExpression '{{a}...} = b',
2406    type: 'AssignmentExpression'
2407    left:
2408      type: 'ObjectPattern'
2409      properties: [
2410        type: 'RestElement'
2411        argument:
2412          type: 'ObjectPattern'
2413          properties: [
2414            type: 'ObjectProperty'
2415            shorthand: yes
2416          ]
2417        postfix: yes
2418      ]
2419    right: ID 'b'
2420
2421  testExpression '[u, [v, ...w, x], ...{...y}, z] = a',
2422    left:
2423      type: 'ArrayPattern'
2424
2425  testExpression '{...{a: [...b, c]}} = d',
2426    left:
2427      type: 'ObjectPattern'
2428
2429  testExpression '{"#{a}": b} = c',
2430    left:
2431      type: 'ObjectPattern'
2432      properties: [
2433        type: 'ObjectProperty'
2434        key:
2435          type: 'TemplateLiteral'
2436          expressions: [
2437            ID 'a'
2438          ]
2439        computed: yes
2440      ]
2441
2442test "AST as expected for Code node", ->
2443  testExpression '=>',
2444    type: 'ArrowFunctionExpression'
2445    params: []
2446    body: EMPTY_BLOCK
2447    generator: no
2448    async: no
2449    id: null
2450    hasIndentedBody: no
2451
2452  testExpression '''
2453    (a, b = 1) ->
2454      c
2455      d()
2456  ''',
2457    type: 'FunctionExpression'
2458    params: [
2459      type: 'Identifier'
2460      name: 'a'
2461      declaration: no
2462    ,
2463      type: 'AssignmentPattern'
2464      left:
2465        type: 'Identifier'
2466        name: 'b'
2467        declaration: no
2468      right:
2469        type: 'NumericLiteral'
2470        value: 1
2471    ]
2472    body:
2473      type: 'BlockStatement'
2474      body: [
2475        type: 'ExpressionStatement'
2476        expression:
2477          type: 'Identifier'
2478          name: 'c'
2479      ,
2480        type: 'ExpressionStatement'
2481        expression:
2482          type: 'CallExpression'
2483          returns: yes
2484      ]
2485      directives: []
2486    generator: no
2487    async: no
2488    id: null
2489    hasIndentedBody: yes
2490
2491  testExpression '({a}) ->',
2492    type: 'FunctionExpression'
2493    params: [
2494      type: 'ObjectPattern'
2495      properties: [
2496        type: 'ObjectProperty'
2497        key: ID 'a', declaration: no
2498        value: ID 'a', declaration: no
2499        shorthand: yes
2500      ]
2501    ]
2502    body: EMPTY_BLOCK
2503    generator: no
2504    async: no
2505    id: null
2506
2507  testExpression '([a]) ->',
2508    type: 'FunctionExpression'
2509    params: [
2510      type: 'ArrayPattern'
2511      elements: [
2512        ID 'a', declaration: no
2513      ]
2514    ]
2515    body: EMPTY_BLOCK
2516    generator: no
2517    async: no
2518    id: null
2519
2520  testExpression '({a = 1} = {}) ->',
2521    type: 'FunctionExpression'
2522    params: [
2523      type: 'AssignmentPattern'
2524      left:
2525        type: 'ObjectPattern'
2526        properties: [
2527          type: 'ObjectProperty'
2528          key: ID 'a', declaration: no
2529          value:
2530            type: 'AssignmentPattern'
2531            left: ID 'a', declaration: no
2532            right: NUMBER(1)
2533          shorthand: yes
2534        ]
2535      right:
2536        type: 'ObjectExpression'
2537        properties: []
2538    ]
2539    body: EMPTY_BLOCK
2540    generator: no
2541    async: no
2542    id: null
2543
2544  testExpression '([a = 1] = []) ->',
2545    type: 'FunctionExpression'
2546    params: [
2547      type: 'AssignmentPattern'
2548      left:
2549        type: 'ArrayPattern'
2550        elements: [
2551          type: 'AssignmentPattern'
2552          left: ID 'a', declaration: no
2553          right: NUMBER(1)
2554        ]
2555      right:
2556        type: 'ArrayExpression'
2557        elements: []
2558    ]
2559    body: EMPTY_BLOCK
2560    generator: no
2561    async: no
2562    id: null
2563
2564  testExpression '() ->',
2565    type: 'FunctionExpression'
2566    params: []
2567    body: EMPTY_BLOCK
2568    generator: no
2569    async: no
2570    id: null
2571
2572  testExpression '(@a) ->',
2573    type: 'FunctionExpression'
2574    params: [
2575      type: 'MemberExpression'
2576      object:
2577        type: 'ThisExpression'
2578        shorthand: yes
2579      property: ID 'a', declaration: no
2580    ]
2581    body: EMPTY_BLOCK
2582    generator: no
2583    async: no
2584    id: null
2585
2586  testExpression '(@a = 1) ->',
2587    type: 'FunctionExpression'
2588    params: [
2589      type: 'AssignmentPattern'
2590      left:
2591        type: 'MemberExpression'
2592      right: NUMBER 1
2593    ]
2594    body: EMPTY_BLOCK
2595    generator: no
2596    async: no
2597    id: null
2598
2599  testExpression '({@a}) ->',
2600    type: 'FunctionExpression'
2601    params: [
2602      type: 'ObjectPattern'
2603      properties: [
2604        type: 'ObjectProperty'
2605        key:
2606          type: 'MemberExpression'
2607        value:
2608          type: 'MemberExpression'
2609        shorthand: yes
2610        computed: no
2611      ]
2612    ]
2613    body: EMPTY_BLOCK
2614    generator: no
2615    async: no
2616    id: null
2617
2618  testExpression '({[a]}) ->',
2619    type: 'FunctionExpression'
2620    params: [
2621      type: 'ObjectPattern'
2622      properties: [
2623        type: 'ObjectProperty'
2624        key:   ID 'a', declaration: no
2625        value: ID 'a', declaration: no
2626        shorthand: yes
2627        computed: yes
2628      ]
2629    ]
2630    body: EMPTY_BLOCK
2631    generator: no
2632    async: no
2633    id: null
2634
2635  testExpression '(...a) ->',
2636    type: 'FunctionExpression'
2637    params: [
2638      type: 'RestElement'
2639      argument: ID 'a', declaration: no
2640      postfix: no
2641    ]
2642    body: EMPTY_BLOCK
2643    generator: no
2644    async: no
2645    id: null
2646
2647  testExpression '(a...) ->',
2648    type: 'FunctionExpression'
2649    params: [
2650      type: 'RestElement'
2651      argument: ID 'a'
2652      postfix: yes
2653    ]
2654    body: EMPTY_BLOCK
2655    generator: no
2656    async: no
2657    id: null
2658
2659  testExpression '(..., a) ->',
2660    type: 'FunctionExpression'
2661    params: [
2662      type: 'RestElement'
2663      argument: null
2664    ,
2665      ID 'a'
2666    ]
2667    body: EMPTY_BLOCK
2668    generator: no
2669    async: no
2670    id: null
2671
2672  testExpression '-> a',
2673    type: 'FunctionExpression'
2674    params: []
2675    body:
2676      type: 'BlockStatement'
2677      body: [
2678        type: 'ExpressionStatement'
2679        expression: ID 'a', returns: yes
2680      ]
2681    generator: no
2682    async: no
2683    id: null
2684    hasIndentedBody: no
2685
2686  testExpression '-> await 3',
2687    type: 'FunctionExpression'
2688    params: []
2689    body:
2690      type: 'BlockStatement'
2691      body: [
2692        type: 'ExpressionStatement'
2693        expression:
2694          type: 'AwaitExpression'
2695          argument: NUMBER 3
2696          returns: yes
2697      ]
2698    generator: no
2699    async: yes
2700    id: null
2701
2702  testExpression '-> yield 4',
2703    type: 'FunctionExpression'
2704    params: []
2705    body:
2706      type: 'BlockStatement'
2707      body: [
2708        type: 'ExpressionStatement'
2709        expression:
2710          type: 'YieldExpression'
2711          argument: NUMBER 4
2712          delegate: no
2713      ]
2714    generator: yes
2715    async: no
2716    id: null
2717
2718  testExpression '-> yield',
2719    type: 'FunctionExpression'
2720    params: []
2721    body:
2722      type: 'BlockStatement'
2723      body: [
2724        type: 'ExpressionStatement'
2725        expression:
2726          type: 'YieldExpression'
2727          argument: null
2728          delegate: no
2729      ]
2730    generator: yes
2731    async: no
2732    id: null
2733
2734  testExpression '(a) -> a = 1',
2735    type: 'FunctionExpression'
2736    body:
2737      type: 'BlockStatement'
2738      body: [
2739        type: 'ExpressionStatement'
2740        expression:
2741          type: 'AssignmentExpression'
2742          left:
2743            ID 'a', declaration: no
2744      ]
2745
2746  testExpression '(...a) -> a = 1',
2747    type: 'FunctionExpression'
2748    body:
2749      type: 'BlockStatement'
2750      body: [
2751        type: 'ExpressionStatement'
2752        expression:
2753          type: 'AssignmentExpression'
2754          left:
2755            ID 'a', declaration: no
2756      ]
2757
2758  testExpression '({a}) -> a = 1',
2759    type: 'FunctionExpression'
2760    body:
2761      type: 'BlockStatement'
2762      body: [
2763        type: 'ExpressionStatement'
2764        expression:
2765          type: 'AssignmentExpression'
2766          left:
2767            ID 'a', declaration: no
2768      ]
2769
2770  testExpression '([a]) -> a = 1',
2771    type: 'FunctionExpression'
2772    body:
2773      type: 'BlockStatement'
2774      body: [
2775        type: 'ExpressionStatement'
2776        expression:
2777          type: 'AssignmentExpression'
2778          left:
2779            ID 'a', declaration: no
2780      ]
2781
2782  testExpression '(a = 1) -> a = 1',
2783    type: 'FunctionExpression'
2784    body:
2785      type: 'BlockStatement'
2786      body: [
2787        type: 'ExpressionStatement'
2788        expression:
2789          type: 'AssignmentExpression'
2790          left:
2791            ID 'a', declaration: no
2792      ]
2793    generator: no
2794    async: no
2795    id: null
2796
2797  testExpression '({a} = 1) -> a = 1',
2798    type: 'FunctionExpression'
2799    body:
2800      type: 'BlockStatement'
2801      body: [
2802        type: 'ExpressionStatement'
2803        expression:
2804          type: 'AssignmentExpression'
2805          left:
2806            ID 'a', declaration: no
2807      ]
2808    generator: no
2809    async: no
2810    id: null
2811
2812test "AST as expected for Splat node", ->
2813  testExpression '[a...]',
2814    type: 'ArrayExpression'
2815    elements: [
2816      type: 'SpreadElement'
2817      argument:
2818        type: 'Identifier'
2819        name: 'a'
2820        declaration: no
2821      postfix: yes
2822    ]
2823
2824  testExpression '[b, ...c]',
2825    type: 'ArrayExpression'
2826    elements: [
2827      name: 'b'
2828      declaration: no
2829    ,
2830      type: 'SpreadElement'
2831      argument:
2832        type: 'Identifier'
2833        name: 'c'
2834        declaration: no
2835      postfix: no
2836    ]
2837
2838test "AST as expected for Expansion node", ->
2839  testExpression '(..., b) ->',
2840    type: 'FunctionExpression'
2841    params: [
2842      type: 'RestElement'
2843      argument: null
2844    ,
2845      ID 'b'
2846    ]
2847
2848  testExpression '[..., b] = c',
2849    type: 'AssignmentExpression'
2850    left:
2851      type: 'ArrayPattern'
2852      elements: [
2853        type: 'RestElement'
2854        argument: null
2855      ,
2856        type: 'Identifier'
2857      ]
2858
2859test "AST as expected for Elision node", ->
2860  testExpression '[,,,a,,,b]',
2861    type: 'ArrayExpression'
2862    elements: [
2863      null, null, null
2864      name: 'a'
2865      null, null
2866      name: 'b'
2867    ]
2868
2869  testExpression '[,,,a,,,b] = "asdfqwer"',
2870    type: 'AssignmentExpression'
2871    left:
2872      type: 'ArrayPattern'
2873      elements: [
2874        null, null, null
2875      ,
2876        type: 'Identifier'
2877        name: 'a'
2878      ,
2879        null, null
2880      ,
2881        type: 'Identifier'
2882        name: 'b'
2883      ]
2884    right:
2885      type: 'StringLiteral'
2886      value: 'asdfqwer'
2887
2888test "AST as expected for While node", ->
2889  testStatement 'loop 1',
2890    type: 'WhileStatement'
2891    test:
2892      type: 'BooleanLiteral'
2893      value: true
2894    body:
2895      type: 'BlockStatement'
2896      body: [
2897        type: 'ExpressionStatement'
2898        expression: NUMBER 1
2899      ]
2900    guard: null
2901    inverted: no
2902    postfix: no
2903    loop: yes
2904
2905  testStatement 'while 1 < 2 then',
2906    type: 'WhileStatement'
2907    test:
2908      type: 'BinaryExpression'
2909    body:
2910      type: 'BlockStatement'
2911      body: []
2912    guard: null
2913    inverted: no
2914    postfix: no
2915    loop: no
2916
2917  testStatement 'while 1 < 2 then fn()',
2918    type: 'WhileStatement'
2919    test:
2920      type: 'BinaryExpression'
2921    body:
2922      type: 'BlockStatement'
2923      body: [
2924        type: 'ExpressionStatement'
2925        expression:
2926          type: 'CallExpression'
2927      ]
2928    guard: null
2929    inverted: no
2930    postfix: no
2931    loop: no
2932
2933  testStatement '''
2934    x() until y
2935  ''',
2936    type: 'WhileStatement'
2937    test: ID 'y'
2938    body:
2939      type: 'BlockStatement'
2940      body: [
2941        type: 'ExpressionStatement'
2942        expression:
2943          type: 'CallExpression'
2944          returns: undefined
2945      ]
2946    guard: null
2947    inverted: yes
2948    postfix: yes
2949    loop: no
2950
2951  testStatement '''
2952    until x when y
2953      z++
2954  ''',
2955    type: 'WhileStatement'
2956    test: ID 'x'
2957    body:
2958      type: 'BlockStatement'
2959      body: [
2960        type: 'ExpressionStatement'
2961        expression:
2962          type: 'UpdateExpression'
2963      ]
2964    guard: ID 'y'
2965    inverted: yes
2966    postfix: no
2967    loop: no
2968
2969  testStatement '''
2970    x while y when z
2971  ''',
2972    type: 'WhileStatement'
2973    test: ID 'y'
2974    body:
2975      type: 'BlockStatement'
2976      body: [
2977        type: 'ExpressionStatement'
2978        expression: ID 'x'
2979      ]
2980    guard: ID 'z'
2981    inverted: no
2982    postfix: yes
2983    loop: no
2984
2985  testStatement '''
2986    loop
2987      a()
2988      b++
2989  ''',
2990    type: 'WhileStatement'
2991    test:
2992      type: 'BooleanLiteral'
2993    body:
2994      type: 'BlockStatement'
2995      body: [
2996        type: 'ExpressionStatement'
2997        expression:
2998          type: 'CallExpression'
2999      ,
3000        type: 'ExpressionStatement'
3001        expression:
3002          type: 'UpdateExpression'
3003      ]
3004    guard: null
3005    inverted: no
3006    postfix: no
3007    loop: yes
3008
3009  testExpression '''
3010    x = (z() while y)
3011  ''',
3012    type: 'AssignmentExpression'
3013    right:
3014      type: 'WhileStatement'
3015      body:
3016        type: 'BlockStatement'
3017        body: [
3018          type: 'ExpressionStatement'
3019          expression:
3020            type: 'CallExpression'
3021            returns: yes
3022        ]
3023
3024test "AST as expected for Op node", ->
3025  testExpression 'a <= 2',
3026    type: 'BinaryExpression'
3027    operator: '<='
3028    left:
3029      type: 'Identifier'
3030      name: 'a'
3031    right:
3032      type: 'NumericLiteral'
3033      value: 2
3034
3035  testExpression 'a is 2',
3036    type: 'BinaryExpression'
3037    operator: 'is'
3038    left:
3039      type: 'Identifier'
3040      name: 'a'
3041    right:
3042      type: 'NumericLiteral'
3043      value: 2
3044
3045  testExpression 'a // 2',
3046    type: 'BinaryExpression'
3047    operator: '//'
3048    left:
3049      type: 'Identifier'
3050      name: 'a'
3051    right:
3052      type: 'NumericLiteral'
3053      value: 2
3054
3055  testExpression 'a << 2',
3056    type: 'BinaryExpression'
3057    operator: '<<'
3058    left:
3059      type: 'Identifier'
3060      name: 'a'
3061    right:
3062      type: 'NumericLiteral'
3063      value: 2
3064
3065  testExpression 'typeof x',
3066    type: 'UnaryExpression'
3067    operator: 'typeof'
3068    prefix: yes
3069    argument:
3070      type: 'Identifier'
3071      name: 'x'
3072
3073  testExpression 'delete x.y',
3074    type: 'UnaryExpression'
3075    operator: 'delete'
3076    prefix: yes
3077    argument:
3078      type: 'MemberExpression'
3079
3080  testExpression 'do x',
3081    type: 'UnaryExpression'
3082    operator: 'do'
3083    prefix: yes
3084    argument:
3085      type: 'Identifier'
3086      name: 'x'
3087
3088  testExpression 'do ->',
3089    type: 'UnaryExpression'
3090    operator: 'do'
3091    prefix: yes
3092    argument:
3093      type: 'FunctionExpression'
3094
3095  testExpression '!x',
3096    type: 'UnaryExpression'
3097    operator: '!'
3098    prefix: yes
3099    argument:
3100      type: 'Identifier'
3101      name: 'x'
3102
3103  testExpression 'not x',
3104    type: 'UnaryExpression'
3105    operator: 'not'
3106    prefix: yes
3107    argument:
3108      type: 'Identifier'
3109      name: 'x'
3110
3111  testExpression '--x',
3112    type: 'UpdateExpression'
3113    operator: '--'
3114    prefix: yes
3115    argument:
3116      type: 'Identifier'
3117      name: 'x'
3118
3119  testExpression 'x++',
3120    type: 'UpdateExpression'
3121    operator: '++'
3122    prefix: no
3123    argument:
3124      type: 'Identifier'
3125      name: 'x'
3126
3127  testExpression 'x && y',
3128    type: 'LogicalExpression'
3129    operator: '&&'
3130    left:
3131      type: 'Identifier'
3132      name: 'x'
3133    right:
3134      type: 'Identifier'
3135      name: 'y'
3136
3137  testExpression 'x or y',
3138    type: 'LogicalExpression'
3139    operator: 'or'
3140    left:
3141      type: 'Identifier'
3142      name: 'x'
3143    right:
3144      type: 'Identifier'
3145      name: 'y'
3146
3147  testExpression 'x ? y',
3148    type: 'LogicalExpression'
3149    operator: '?'
3150    left:
3151      type: 'Identifier'
3152      name: 'x'
3153    right:
3154      type: 'Identifier'
3155      name: 'y'
3156
3157  testExpression 'x in y',
3158    type: 'BinaryExpression'
3159    operator: 'in'
3160    left:
3161      type: 'Identifier'
3162      name: 'x'
3163    right:
3164      type: 'Identifier'
3165      name: 'y'
3166
3167  testExpression 'x not in y',
3168    type: 'BinaryExpression'
3169    operator: 'not in'
3170    left:
3171      type: 'Identifier'
3172      name: 'x'
3173    right:
3174      type: 'Identifier'
3175      name: 'y'
3176
3177  testExpression 'x + y * z',
3178    type: 'BinaryExpression'
3179    operator: '+'
3180    left:
3181      type: 'Identifier'
3182      name: 'x'
3183    right:
3184      type: 'BinaryExpression'
3185      operator: '*'
3186      left:
3187        type: 'Identifier'
3188        name: 'y'
3189      right:
3190        type: 'Identifier'
3191        name: 'z'
3192
3193  testExpression '(x + y) * z',
3194    type: 'BinaryExpression'
3195    operator: '*'
3196    left:
3197      type: 'BinaryExpression'
3198      operator: '+'
3199      left:
3200        type: 'Identifier'
3201        name: 'x'
3202      right:
3203        type: 'Identifier'
3204        name: 'y'
3205    right:
3206      type: 'Identifier'
3207      name: 'z'
3208
3209test "AST as expected for Try node", ->
3210  testStatement 'try cappuccino',
3211    type: 'TryStatement'
3212    block:
3213      type: 'BlockStatement'
3214      body: [
3215        type: 'ExpressionStatement'
3216        expression:
3217          type: 'Identifier'
3218          name: 'cappuccino'
3219      ]
3220    handler: null
3221    finalizer: null
3222
3223  testStatement '''
3224    try
3225      x = 1
3226      y()
3227    catch e
3228      d()
3229    finally
3230      f + g
3231  ''',
3232    type: 'TryStatement'
3233    block:
3234      type: 'BlockStatement'
3235      body: [
3236        type: 'ExpressionStatement'
3237        expression:
3238          type: 'AssignmentExpression'
3239      ,
3240        type: 'ExpressionStatement'
3241        expression:
3242          type: 'CallExpression'
3243      ]
3244    handler:
3245      type: 'CatchClause'
3246      param:
3247        type: 'Identifier'
3248        name: 'e'
3249        declaration: yes
3250      body:
3251        type: 'BlockStatement'
3252        body: [
3253          type: 'ExpressionStatement'
3254          expression:
3255            type: 'CallExpression'
3256        ]
3257    finalizer:
3258      type: 'BlockStatement'
3259      body: [
3260        type: 'ExpressionStatement'
3261        expression:
3262          type: 'BinaryExpression'
3263      ]
3264
3265  testStatement '''
3266    try
3267    catch
3268    finally
3269  ''',
3270    type: 'TryStatement'
3271    block:
3272      type: 'BlockStatement'
3273      body: []
3274    handler:
3275      type: 'CatchClause'
3276      param: null
3277      body:
3278        type: 'BlockStatement'
3279        body: []
3280    finalizer:
3281      type: 'BlockStatement'
3282      body: []
3283
3284  testStatement '''
3285    try
3286    catch {e}
3287      f
3288  ''',
3289    type: 'TryStatement'
3290    block:
3291      type: 'BlockStatement'
3292      body: []
3293    handler:
3294      type: 'CatchClause'
3295      param:
3296        type: 'ObjectPattern'
3297        properties: [
3298          type: 'ObjectProperty'
3299          key: ID 'e', declaration: no
3300          value: ID 'e', declaration: yes
3301        ]
3302      body:
3303        type: 'BlockStatement'
3304        body: [
3305          type: 'ExpressionStatement'
3306        ]
3307    finalizer: null
3308
3309test "AST as expected for Throw node", ->
3310  testStatement 'throw new BallError "catch"',
3311    type: 'ThrowStatement'
3312    argument:
3313      type: 'NewExpression'
3314
3315test "AST as expected for Existence node", ->
3316  testExpression 'Ghosts?',
3317    type: 'UnaryExpression',
3318    argument:
3319      name: 'Ghosts'
3320    operator: '?'
3321    prefix: no
3322
3323test "AST as expected for Parens node", ->
3324  testExpression '(hmmmmm)',
3325    type: 'Identifier'
3326    name: 'hmmmmm'
3327
3328  testExpression '(a + b) / c',
3329    type: 'BinaryExpression'
3330    operator: '/'
3331    left:
3332      type: 'BinaryExpression'
3333      operator: '+'
3334      left: ID 'a'
3335      right: ID 'b'
3336    right: ID 'c'
3337
3338  testExpression '(((1)))',
3339    type: 'NumericLiteral'
3340    value: 1
3341
3342test "AST as expected for StringWithInterpolations node", ->
3343  testExpression '"a#{b}c"',
3344    type: 'TemplateLiteral'
3345    expressions: [
3346      ID 'b'
3347    ]
3348    quasis: [
3349      type: 'TemplateElement'
3350      value:
3351        raw: 'a'
3352      tail: no
3353    ,
3354      type: 'TemplateElement'
3355      value:
3356        raw: 'c'
3357      tail: yes
3358    ]
3359    quote: '"'
3360
3361  testExpression '"""a#{b}c"""',
3362    type: 'TemplateLiteral'
3363    expressions: [
3364      ID 'b'
3365    ]
3366    quasis: [
3367      type: 'TemplateElement'
3368      value:
3369        raw: 'a'
3370      tail: no
3371    ,
3372      type: 'TemplateElement'
3373      value:
3374        raw: 'c'
3375      tail: yes
3376    ]
3377    quote: '"""'
3378
3379  testExpression '"#{b}"',
3380    type: 'TemplateLiteral'
3381    expressions: [
3382      ID 'b'
3383    ]
3384    quasis: [
3385      type: 'TemplateElement'
3386      value:
3387        raw: ''
3388      tail: no
3389    ,
3390      type: 'TemplateElement'
3391      value:
3392        raw: ''
3393      tail: yes
3394    ]
3395    quote: '"'
3396
3397  testExpression '''
3398    " a
3399      #{b}
3400      c
3401    "
3402  ''',
3403    type: 'TemplateLiteral'
3404    expressions: [
3405      ID 'b'
3406    ]
3407    quasis: [
3408      type: 'TemplateElement'
3409      value:
3410        raw: ' a\n  '
3411      tail: no
3412    ,
3413      type: 'TemplateElement'
3414      value:
3415        raw: '\n  c\n'
3416      tail: yes
3417    ]
3418    quote: '"'
3419
3420  testExpression '''
3421    """
3422      a
3423        b#{
3424        c
3425      }d
3426    """
3427  ''',
3428    type: 'TemplateLiteral'
3429    expressions: [
3430      ID 'c'
3431    ]
3432    quasis: [
3433      type: 'TemplateElement'
3434      value:
3435        raw: '\n  a\n    b'
3436      tail: no
3437    ,
3438      type: 'TemplateElement'
3439      value:
3440        raw: 'd\n'
3441      tail: yes
3442    ]
3443    quote: '"""'
3444
3445  # empty interpolation
3446  testExpression '"#{}"',
3447    type: 'TemplateLiteral'
3448    expressions: [
3449      type: 'EmptyInterpolation'
3450    ]
3451    quasis: [
3452      type: 'TemplateElement'
3453      value:
3454        raw: ''
3455      tail: no
3456    ,
3457      type: 'TemplateElement'
3458      value:
3459        raw: ''
3460      tail: yes
3461    ]
3462    quote: '"'
3463
3464  testExpression '''
3465    "#{
3466      # comment
3467     }"
3468    ''',
3469    type: 'TemplateLiteral'
3470    expressions: [
3471      type: 'EmptyInterpolation'
3472    ]
3473    quasis: [
3474      type: 'TemplateElement'
3475      value:
3476        raw: ''
3477      tail: no
3478    ,
3479      type: 'TemplateElement'
3480      value:
3481        raw: ''
3482      tail: yes
3483    ]
3484    quote: '"'
3485
3486  testExpression '"#{ ### here ### }"',
3487    type: 'TemplateLiteral'
3488    expressions: [
3489      type: 'EmptyInterpolation'
3490    ]
3491    quasis: [
3492      type: 'TemplateElement'
3493      value:
3494        raw: ''
3495      tail: no
3496    ,
3497      type: 'TemplateElement'
3498      value:
3499        raw: ''
3500      tail: yes
3501    ]
3502    quote: '"'
3503
3504  testExpression '''
3505    a "#{
3506      b
3507      c
3508    }"
3509  ''',
3510    type: 'CallExpression'
3511    arguments: [
3512      type: 'TemplateLiteral'
3513      expressions: [
3514        type: 'BlockStatement'
3515        body: [
3516          type: 'ExpressionStatement'
3517        ,
3518          type: 'ExpressionStatement'
3519          expression:
3520            returns: yes
3521        ]
3522      ]
3523    ]
3524
3525test "AST as expected for For node", ->
3526  testStatement 'for x, i in arr when x? then return',
3527    type: 'For'
3528    name: ID 'x', declaration: yes
3529    index: ID 'i', declaration: yes
3530    guard:
3531      type: 'UnaryExpression'
3532    source: ID 'arr', declaration: no
3533    body:
3534      type: 'BlockStatement'
3535      body: [
3536        type: 'ReturnStatement'
3537      ]
3538    style: 'in'
3539    own: no
3540    postfix: no
3541    await: no
3542    step: null
3543
3544  testStatement 'for k, v of obj then return',
3545    type: 'For'
3546    name: ID 'v', declaration: yes
3547    index: ID 'k', declaration: yes
3548    guard: null
3549    source: ID 'obj', declaration: no
3550    body:
3551      type: 'BlockStatement'
3552      body: [
3553        type: 'ReturnStatement'
3554      ]
3555    style: 'of'
3556    own: no
3557    postfix: no
3558    await: no
3559    step: null
3560
3561  testStatement 'for x from iterable then',
3562    type: 'For'
3563    name: ID 'x', declaration: yes
3564    index: null
3565    guard: null
3566    body: EMPTY_BLOCK
3567    source: ID 'iterable', declaration: no
3568    style: 'from'
3569    own: no
3570    postfix: no
3571    await: no
3572    step: null
3573
3574  testStatement 'for i in [0...42] by step when not (i % 2) then',
3575    type: 'For'
3576    name: ID 'i', declaration: yes
3577    index: null
3578    body: EMPTY_BLOCK
3579    source:
3580      type: 'Range'
3581    guard:
3582      type: 'UnaryExpression'
3583    step: ID 'step', declaration: no
3584    style: 'in'
3585    own: no
3586    postfix: no
3587    await: no
3588
3589  testExpression 'a = (x for x in y)',
3590    type: 'AssignmentExpression'
3591    right:
3592      type: 'For'
3593      name: ID 'x', declaration: yes
3594      index: null
3595      body:
3596        type: 'BlockStatement'
3597        body: [
3598          type: 'ExpressionStatement'
3599          expression: ID 'x', declaration: no, returns: yes
3600        ]
3601      source: ID 'y', declaration: no
3602      guard: null
3603      step: null
3604      style: 'in'
3605      own: no
3606      postfix: yes
3607      await: no
3608
3609  testStatement 'x for [0...1]',
3610    type: 'For'
3611    name: null
3612    index: null
3613    body:
3614      type: 'BlockStatement'
3615      body: [
3616        type: 'ExpressionStatement'
3617        expression: ID 'x', declaration: no, returns: undefined
3618      ]
3619    source:
3620      type: 'Range'
3621    guard: null
3622    step: null
3623    style: 'range'
3624    own: no
3625    postfix: yes
3626    await: no
3627
3628  testStatement '''
3629    for own x, y of z
3630      c()
3631      d
3632  ''',
3633    type: 'For'
3634    name: ID 'y', declaration: yes
3635    index: ID 'x', declaration: yes
3636    body:
3637      type: 'BlockStatement'
3638      body: [
3639        type: 'ExpressionStatement'
3640        expression:
3641          type: 'CallExpression'
3642          returns: undefined
3643      ,
3644        type: 'ExpressionStatement'
3645        expression: ID 'd', declaration: no, returns: undefined
3646      ]
3647    source: ID 'z', declaration: no
3648    guard: null
3649    step: null
3650    style: 'of'
3651    own: yes
3652    postfix: no
3653    await: no
3654
3655  testExpression '''
3656    ->
3657      for await x from y
3658        z
3659  ''',
3660    type: 'FunctionExpression'
3661    body:
3662      type: 'BlockStatement'
3663      body: [
3664        type: 'For'
3665        name: ID 'x', declaration: yes
3666        index: null
3667        body:
3668          type: 'BlockStatement'
3669          body: [
3670            type: 'ExpressionStatement'
3671            expression: ID 'z', declaration: no, returns: yes
3672          ]
3673        source: ID 'y', declaration: no
3674        guard: null
3675        step: null
3676        style: 'from'
3677        own: no
3678        postfix: no
3679        await: yes
3680      ]
3681
3682  testStatement '''
3683    for {x} in y
3684      z
3685  ''',
3686    type: 'For'
3687    name:
3688      type: 'ObjectPattern'
3689      properties: [
3690        type: 'ObjectProperty'
3691        key: ID 'x', declaration: no
3692        value: ID 'x', declaration: yes
3693        shorthand: yes
3694        computed: no
3695      ]
3696    index: null
3697    body:
3698      type: 'BlockStatement'
3699      body: [
3700        type: 'ExpressionStatement'
3701        expression: ID 'z'
3702      ]
3703    source: ID 'y'
3704    guard: null
3705    step: null
3706    style: 'in'
3707    postfix: no
3708    await: no
3709
3710  testStatement '''
3711    for [x] in y
3712      z
3713  ''',
3714    type: 'For'
3715    name:
3716      type: 'ArrayPattern'
3717      elements: [
3718        ID 'x', declaration: yes
3719      ]
3720    index: null
3721    body:
3722      type: 'BlockStatement'
3723      body: [
3724        type: 'ExpressionStatement'
3725        expression: ID 'z'
3726      ]
3727    source: ID 'y'
3728    guard: null
3729    step: null
3730    style: 'in'
3731    postfix: no
3732    await: no
3733
3734  testStatement '''
3735    for [x..., y] in z
3736      y()
3737  ''',
3738    type: 'For'
3739    name:
3740      type: 'ArrayPattern'
3741
3742test "AST as expected for Switch node", ->
3743  testStatement '''
3744    switch x
3745      when a then a
3746      when b, c then c
3747      else 42
3748  ''',
3749    type: 'SwitchStatement'
3750    discriminant:
3751      type: 'Identifier'
3752      name: 'x'
3753    cases: [
3754      type: 'SwitchCase'
3755      test:
3756        type: 'Identifier'
3757        name: 'a'
3758      consequent: [
3759        type: 'ExpressionStatement'
3760        expression:
3761          type: 'Identifier'
3762          name: 'a'
3763      ]
3764      trailing: yes
3765    ,
3766      type: 'SwitchCase'
3767      test:
3768        type: 'Identifier'
3769        name: 'b'
3770      consequent: []
3771      trailing: no
3772    ,
3773      type: 'SwitchCase'
3774      test:
3775        type: 'Identifier'
3776        name: 'c'
3777      consequent: [
3778        type: 'ExpressionStatement'
3779        expression:
3780          type: 'Identifier'
3781          name: 'c'
3782      ]
3783      trailing: yes
3784    ,
3785      type: 'SwitchCase'
3786      test: null
3787      consequent: [
3788        type: 'ExpressionStatement'
3789        expression:
3790          type: 'NumericLiteral'
3791          value: 42
3792      ]
3793    ]
3794
3795  testStatement '''
3796    switch
3797      when some(condition)
3798        doSomething()
3799        andThenSomethingElse
3800  ''',
3801    type: 'SwitchStatement'
3802    discriminant: null
3803    cases: [
3804      type: 'SwitchCase'
3805      test:
3806        type: 'CallExpression'
3807      consequent: [
3808        type: 'ExpressionStatement'
3809        expression:
3810          type: 'CallExpression'
3811      ,
3812        type: 'ExpressionStatement'
3813        expression:
3814          type: 'Identifier'
3815      ]
3816      trailing: yes
3817    ]
3818
3819  testStatement '''
3820    switch a
3821      when 1, 2, 3, 4
3822        b
3823      else
3824        c
3825        d
3826  ''',
3827    type: 'SwitchStatement'
3828    discriminant:
3829      type: 'Identifier'
3830    cases: [
3831      type: 'SwitchCase'
3832      test:
3833        type: 'NumericLiteral'
3834        value: 1
3835      consequent: []
3836      trailing: no
3837    ,
3838      type: 'SwitchCase'
3839      test:
3840        type: 'NumericLiteral'
3841        value: 2
3842      consequent: []
3843      trailing: no
3844    ,
3845      type: 'SwitchCase'
3846      test:
3847        type: 'NumericLiteral'
3848        value: 3
3849      consequent: []
3850      trailing: no
3851    ,
3852      type: 'SwitchCase'
3853      test:
3854        type: 'NumericLiteral'
3855        value: 4
3856      consequent: [
3857        type: 'ExpressionStatement'
3858        expression:
3859          type: 'Identifier'
3860      ]
3861      trailing: yes
3862    ,
3863      type: 'SwitchCase'
3864      test: null
3865      consequent: [
3866        type: 'ExpressionStatement'
3867        expression:
3868          type: 'Identifier'
3869      ,
3870        type: 'ExpressionStatement'
3871        expression:
3872          type: 'Identifier'
3873      ]
3874    ]
3875
3876test "AST as expected for If node", ->
3877  testStatement 'if maybe then yes',
3878    type: 'IfStatement'
3879    test: ID 'maybe'
3880    consequent:
3881      type: 'BlockStatement'
3882      body: [
3883        type: 'ExpressionStatement'
3884        expression:
3885          type: 'BooleanLiteral'
3886      ]
3887    alternate: null
3888    postfix: no
3889    inverted: no
3890
3891  testStatement 'yes if maybe',
3892    type: 'IfStatement'
3893    test: ID 'maybe'
3894    consequent:
3895      type: 'BlockStatement'
3896      body: [
3897        type: 'ExpressionStatement'
3898        expression:
3899          type: 'BooleanLiteral'
3900      ]
3901    alternate: null
3902    postfix: yes
3903    inverted: no
3904
3905  testStatement 'unless x then x else if y then y else z',
3906    type: 'IfStatement'
3907    test: ID 'x'
3908    consequent:
3909      type: 'BlockStatement'
3910      body: [
3911        type: 'ExpressionStatement'
3912        expression: ID 'x'
3913      ]
3914    alternate:
3915      type: 'IfStatement'
3916      test: ID 'y'
3917      consequent:
3918        type: 'BlockStatement'
3919        body: [
3920          type: 'ExpressionStatement'
3921          expression: ID 'y'
3922        ]
3923      alternate:
3924        type: 'BlockStatement'
3925        body: [
3926          type: 'ExpressionStatement'
3927          expression: ID 'z'
3928        ]
3929      postfix: no
3930      inverted: no
3931    postfix: no
3932    inverted: yes
3933
3934  testStatement '''
3935    if a
3936      b
3937    else
3938      if c
3939        d
3940  ''',
3941    type: 'IfStatement'
3942    test: ID 'a'
3943    consequent:
3944      type: 'BlockStatement'
3945      body: [
3946        type: 'ExpressionStatement'
3947        expression: ID 'b'
3948      ]
3949    alternate:
3950      type: 'BlockStatement'
3951      body: [
3952        type: 'IfStatement'
3953        test: ID 'c'
3954        consequent:
3955          type: 'BlockStatement'
3956          body: [
3957            type: 'ExpressionStatement'
3958            expression: ID 'd'
3959          ]
3960        alternate: null
3961        postfix: no
3962        inverted: no
3963      ]
3964    postfix: no
3965    inverted: no
3966
3967  testExpression '''
3968    a =
3969      if b then c else if d then e
3970  ''',
3971    type: 'AssignmentExpression'
3972    right:
3973      type: 'ConditionalExpression'
3974      test: ID 'b'
3975      consequent: ID 'c'
3976      alternate:
3977        type: 'ConditionalExpression'
3978        test: ID 'd'
3979        consequent: ID 'e'
3980        alternate: null
3981        postfix: no
3982        inverted: no
3983      postfix: no
3984      inverted: no
3985
3986  testExpression '''
3987    f(
3988      if b
3989        c
3990        d
3991    )
3992  ''',
3993    type: 'CallExpression'
3994    arguments: [
3995      type: 'ConditionalExpression'
3996      test: ID 'b'
3997      consequent:
3998        type: 'BlockStatement'
3999        body: [
4000          type: 'ExpressionStatement'
4001          expression:
4002            ID 'c'
4003        ,
4004          type: 'ExpressionStatement'
4005          expression:
4006            ID 'd'
4007        ]
4008      alternate: null
4009      postfix: no
4010      inverted: no
4011    ]
4012
4013  testStatement 'a unless b',
4014    type: 'IfStatement'
4015    test: ID 'b'
4016    consequent:
4017      type: 'BlockStatement'
4018      body: [
4019        type: 'ExpressionStatement'
4020        expression: ID 'a'
4021      ]
4022    alternate: null
4023    postfix: yes
4024    inverted: yes
4025
4026  testExpression '''
4027    f(
4028      if b
4029        c
4030      else
4031        d
4032    )
4033  ''',
4034      type: 'CallExpression'
4035      arguments: [
4036        type: 'ConditionalExpression'
4037        test: ID 'b'
4038        consequent: ID 'c'
4039        alternate: ID 'd'
4040        postfix: no
4041        inverted: no
4042      ]
4043
4044test "AST as expected for `new.target` MetaProperty node", ->
4045  testExpression '''
4046    -> new.target
4047  ''',
4048    type: 'FunctionExpression'
4049    body:
4050      type: 'BlockStatement'
4051      body: [
4052        type: 'ExpressionStatement'
4053        expression:
4054          type: 'MetaProperty'
4055          meta: ID 'new'
4056          property: ID 'target'
4057      ]
4058
4059  testExpression '''
4060    -> new.target.name
4061  ''',
4062    type: 'FunctionExpression'
4063    body:
4064      type: 'BlockStatement'
4065      body: [
4066        type: 'ExpressionStatement'
4067        expression:
4068          type: 'MemberExpression'
4069          object:
4070            type: 'MetaProperty'
4071            meta: ID 'new'
4072            property: ID 'target'
4073          property: ID 'name'
4074          computed: no
4075      ]
4076
4077test "AST as expected for `import.meta` MetaProperty node", ->
4078  testExpression '''
4079    import.meta
4080  ''',
4081    type: 'MetaProperty'
4082    meta: ID 'import'
4083    property: ID 'meta'
4084
4085  testExpression '''
4086    import.meta.name
4087  ''',
4088    type: 'MemberExpression'
4089    object:
4090      type: 'MetaProperty'
4091      meta: ID 'import'
4092      property: ID 'meta'
4093    property: ID 'name'
4094    computed: no
4095
4096test "AST as expected for dynamic import", ->
4097  testExpression '''
4098    import('a')
4099  ''',
4100    type: 'CallExpression'
4101    callee:
4102      type: 'Import'
4103    arguments: [STRING 'a']
4104
4105test "AST as expected for RegexLiteral node", ->
4106  testExpression '/a/ig',
4107    type: 'RegExpLiteral'
4108    pattern: 'a'
4109    originalPattern: 'a'
4110    flags: 'ig'
4111    delimiter: '/'
4112    value: undefined
4113    extra:
4114      raw: "/a/ig"
4115      originalRaw: "/a/ig"
4116      rawValue: undefined
4117
4118  testExpression '''
4119    ///
4120      a
4121    ///i
4122  ''',
4123    type: 'RegExpLiteral'
4124    pattern: 'a'
4125    originalPattern: '\n  a\n'
4126    flags: 'i'
4127    delimiter: '///'
4128    value: undefined
4129    extra:
4130      raw: "/a/i"
4131      originalRaw: "///\n  a\n///i"
4132      rawValue: undefined
4133
4134  testExpression '/a\\w\\u1111\\u{11111}/',
4135    type: 'RegExpLiteral'
4136    pattern: 'a\\w\\u1111\\ud804\\udd11'
4137    originalPattern: 'a\\w\\u1111\\u{11111}'
4138    flags: ''
4139    delimiter: '/'
4140    value: undefined
4141    extra:
4142      raw: "/a\\w\\u1111\\ud804\\udd11/"
4143      originalRaw: "/a\\w\\u1111\\u{11111}/"
4144      rawValue: undefined
4145
4146  testExpression '''
4147    ///
4148      a
4149      \\w\\u1111\\u{11111}
4150    ///
4151  ''',
4152    type: 'RegExpLiteral'
4153    pattern: 'a\\w\\u1111\\ud804\\udd11'
4154    originalPattern: '\n  a\n  \\w\\u1111\\u{11111}\n'
4155    flags: ''
4156    delimiter: '///'
4157    value: undefined
4158    extra:
4159      raw: "/a\\w\\u1111\\ud804\\udd11/"
4160      originalRaw: "///\n  a\n  \\w\\u1111\\u{11111}\n///"
4161      rawValue: undefined
4162
4163  testExpression '''
4164    ///
4165      /
4166      (.+)
4167      /
4168    ///
4169  ''',
4170    type: 'RegExpLiteral'
4171    pattern: '\\/(.+)\\/'
4172    originalPattern: '\n  /\n  (.+)\n  /\n'
4173    flags: ''
4174    delimiter: '///'
4175    value: undefined
4176    extra:
4177      raw: "/\\/(.+)\\//"
4178      originalRaw: "///\n  /\n  (.+)\n  /\n///"
4179      rawValue: undefined
4180
4181  testExpression '''
4182    ///
4183      a # first
4184      b ### second ###
4185    ///
4186  ''',
4187    type: 'RegExpLiteral'
4188    pattern: 'ab'
4189    originalPattern: '\n  a # first\n  b ### second ###\n'
4190    comments: [
4191      type: 'CommentLine'
4192      value: ' first'
4193    ,
4194      type: 'CommentBlock'
4195      value: ' second '
4196    ]
4197
4198test "AST as expected for directives", ->
4199  deepStrictIncludeExpectedProperties CoffeeScript.compile('''
4200    'directive 1'
4201    'use strict'
4202    f()
4203  ''', ast: yes),
4204    type: 'File'
4205    program:
4206      type: 'Program'
4207      body: [
4208        type: 'ExpressionStatement'
4209        expression:
4210          type: 'CallExpression'
4211      ]
4212      directives: [
4213        type: 'Directive'
4214        value:
4215          type: 'DirectiveLiteral'
4216          value: 'directive 1'
4217          extra:
4218            raw: "'directive 1'"
4219      ,
4220        type: 'Directive'
4221        value:
4222          type: 'DirectiveLiteral'
4223          value: 'use strict'
4224          extra:
4225            raw: "'use strict'"
4226      ]
4227
4228  testExpression '''
4229    ->
4230      'use strict'
4231      f()
4232      'not a directive'
4233      g
4234  ''',
4235    type: 'FunctionExpression'
4236    body:
4237      type: 'BlockStatement'
4238      body: [
4239        type: 'ExpressionStatement'
4240        expression:
4241          type: 'CallExpression'
4242      ,
4243        type: 'ExpressionStatement'
4244        expression: STRING 'not a directive'
4245      ,
4246        type: 'ExpressionStatement'
4247        expression: ID 'g'
4248      ]
4249      directives: [
4250        type: 'Directive'
4251        value:
4252          type: 'DirectiveLiteral'
4253          value: 'use strict'
4254          extra:
4255            raw: "'use strict'"
4256      ]
4257
4258  testExpression '''
4259    ->
4260      "not a directive because it's implicitly returned"
4261  ''',
4262    type: 'FunctionExpression'
4263    body:
4264      type: 'BlockStatement'
4265      body: [
4266        type: 'ExpressionStatement'
4267        expression: STRING "not a directive because it's implicitly returned"
4268      ]
4269      directives: []
4270
4271  deepStrictIncludeExpectedProperties CoffeeScript.compile('''
4272    'use strict'
4273  ''', ast: yes),
4274    type: 'File'
4275    program:
4276      type: 'Program'
4277      body: []
4278      directives: [
4279        type: 'Directive'
4280        value:
4281          type: 'DirectiveLiteral'
4282          value: 'use strict'
4283          extra:
4284            raw: "'use strict'"
4285      ]
4286
4287  testStatement '''
4288    class A
4289      'classes can have directives too'
4290      a: ->
4291  ''',
4292    type: 'ClassDeclaration'
4293    body:
4294      type: 'ClassBody'
4295      body: [
4296        type: 'ClassMethod'
4297      ]
4298      directives: [
4299        type: 'Directive'
4300        value:
4301          type: 'DirectiveLiteral'
4302          value: 'classes can have directives too'
4303      ]
4304
4305  testStatement '''
4306    if a
4307      "but other blocks can't"
4308      b
4309  ''',
4310    type: 'IfStatement'
4311    consequent:
4312      type: 'BlockStatement'
4313      body: [
4314        type: 'ExpressionStatement'
4315        expression: STRING "but other blocks can't"
4316      ,
4317        type: 'ExpressionStatement'
4318        expression: ID 'b'
4319      ]
4320      directives: []
4321
4322  testExpression '''
4323    ->
4324      """not a directive"""
4325      b
4326  ''',
4327    type: 'FunctionExpression'
4328    body:
4329      type: 'BlockStatement'
4330      body: [
4331        type: 'ExpressionStatement'
4332        expression:
4333          type: 'TemplateLiteral'
4334      ,
4335        type: 'ExpressionStatement'
4336        expression: ID 'b'
4337      ]
4338      directives: []
4339
4340  testExpression '''
4341    ->
4342      # leading comment
4343      'use strict'
4344      b
4345  ''',
4346    type: 'FunctionExpression'
4347    body:
4348      type: 'BlockStatement'
4349      body: [
4350        type: 'ExpressionStatement'
4351        expression: ID 'b'
4352      ]
4353      directives: [
4354        type: 'Directive'
4355        value:
4356          type: 'DirectiveLiteral'
4357          value: 'use strict'
4358          extra:
4359            raw: "'use strict'"
4360      ]
4361
4362test "AST as expected for comments", ->
4363  testComments '''
4364    a # simple line comment
4365  ''', [
4366    type: 'CommentLine'
4367    value: ' simple line comment'
4368  ]
4369
4370  testComments '''
4371    a ### simple here comment ###
4372  ''', [
4373    type: 'CommentBlock'
4374    value: ' simple here comment '
4375  ]
4376
4377  testComments '''
4378    # just a line comment
4379  ''', [
4380    type: 'CommentLine'
4381    value: ' just a line comment'
4382  ]
4383
4384  testComments '''
4385    ### just a here comment ###
4386  ''', [
4387    type: 'CommentBlock'
4388    value: ' just a here comment '
4389  ]
4390
4391  testComments '''
4392    "#{
4393      # empty interpolation line comment
4394     }"
4395  ''', [
4396    type: 'CommentLine'
4397    value: ' empty interpolation line comment'
4398  ]
4399
4400  testComments '''
4401    "#{
4402      ### empty interpolation block comment ###
4403     }"
4404  ''', [
4405    type: 'CommentBlock'
4406    value: ' empty interpolation block comment '
4407  ]
4408
4409  testComments '''
4410    # multiple line comments
4411    # on consecutive lines
4412  ''', [
4413    type: 'CommentLine'
4414    value: ' multiple line comments'
4415  ,
4416    type: 'CommentLine'
4417    value: ' on consecutive lines'
4418  ]
4419
4420  testComments '''
4421    # multiple line comments
4422
4423    # with blank line
4424  ''', [
4425    type: 'CommentLine'
4426    value: ' multiple line comments'
4427  ,
4428    type: 'CommentLine'
4429    value: ' with blank line'
4430  ]
4431
4432  testComments '''
4433    #no whitespace line comment
4434  ''', [
4435    type: 'CommentLine'
4436    value: 'no whitespace line comment'
4437  ]
4438
4439  testComments '''
4440    ###no whitespace here comment###
4441  ''', [
4442    type: 'CommentBlock'
4443    value: 'no whitespace here comment'
4444  ]
4445
4446  testComments '''
4447    ###
4448    # multiline
4449    # here comment
4450    ###
4451  ''', [
4452    type: 'CommentBlock'
4453    value: '\n# multiline\n# here comment\n'
4454  ]
4455
4456  testComments '''
4457    if b
4458      ###
4459      # multiline
4460      # indented here comment
4461      ###
4462      c
4463  ''', [
4464    type: 'CommentBlock'
4465    value: '\n  # multiline\n  # indented here comment\n  '
4466  ]
4467
4468  testComments '''
4469    if foo
4470      ;
4471      ### empty ###
4472  ''', [
4473    type: 'CommentBlock'
4474    value: ' empty '
4475  ]
4476
4477test "AST as expected for chained comparisons", ->
4478  testExpression '''
4479    a < b < c
4480  ''',
4481    type: 'ChainedComparison'
4482    operands: [
4483      ID 'a'
4484      ID 'b'
4485      ID 'c'
4486    ]
4487    operators: [
4488      '<'
4489      '<'
4490    ]
4491
4492  testExpression '''
4493    a isnt b is c isnt d
4494  ''',
4495    type: 'ChainedComparison'
4496    operands: [
4497      ID 'a'
4498      ID 'b'
4499      ID 'c'
4500      ID 'd'
4501    ]
4502    operators: [
4503      'isnt'
4504      'is'
4505      'isnt'
4506    ]
4507
4508  testExpression '''
4509    a >= b < c
4510  ''',
4511    type: 'ChainedComparison'
4512    operands: [
4513      ID 'a'
4514      ID 'b'
4515      ID 'c'
4516    ]
4517    operators: [
4518      '>='
4519      '<'
4520    ]
4521
4522test "AST as expected for Sequence", ->
4523  testExpression '''
4524    (a; b)
4525  ''',
4526    type: 'SequenceExpression'
4527    expressions: [
4528      ID 'a'
4529      ID 'b'
4530    ]
4531
4532  testExpression '''
4533    (a; b)""
4534  ''',
4535    type: 'TaggedTemplateExpression'
4536    tag:
4537      type: 'SequenceExpression'
4538      expressions: [
4539        ID 'a'
4540        ID 'b'
4541      ]
4542