OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // Note: This test relies on LF line endings in the source file. | 5 // Note: This test relies on LF line endings in the source file. |
6 | 6 |
7 // Test that JS printer callbacks occur when expected. | 7 // Test that JS printer callbacks occur when expected. |
8 | 8 |
9 library js_ast.printer.callback_test; | 9 library js_ast.printer.callback_test; |
10 | 10 |
11 import 'package:js_ast/js_ast.dart'; | 11 import 'package:js_ast/js_ast.dart'; |
12 import 'package:unittest/unittest.dart'; | 12 import 'package:unittest/unittest.dart'; |
13 | 13 |
14 enum TestMode { | 14 enum TestMode { |
| 15 INPUT, |
15 NONE, | 16 NONE, |
16 ENTER, | 17 ENTER, |
17 DELIMITER, | 18 DELIMITER, |
18 EXIT, | 19 EXIT, |
19 } | 20 } |
20 | 21 |
21 const DATA = const [ | 22 class TestCase { |
22 const { | 23 final Map<TestMode, String> data; |
| 24 |
| 25 /// Map from template names to the inserted values. |
| 26 final Map<String, String> environment; |
| 27 |
| 28 const TestCase( |
| 29 this.data, |
| 30 [this.environment = const {}]); |
| 31 } |
| 32 |
| 33 const List<TestCase> DATA = const <TestCase>[ |
| 34 const TestCase(const { |
23 TestMode.NONE: """ | 35 TestMode.NONE: """ |
24 function(a, b) { | 36 function(a, b) { |
25 return null; | 37 return null; |
26 }""", | 38 }""", |
27 TestMode.ENTER: """ | 39 TestMode.ENTER: """ |
28 @0function(@1a, @2b) @3{ | 40 @0function(@1a, @2b) @3{ |
29 @4return @5null; | 41 @4return @5null; |
30 }""", | 42 }""", |
31 TestMode.DELIMITER: """ | 43 TestMode.DELIMITER: """ |
32 function(a, b) { | 44 function(a, b) { |
33 return null; | 45 return null; |
34 @0}""", | 46 @0}""", |
35 TestMode.EXIT: """ | 47 TestMode.EXIT: """ |
36 function(a@1, b@2) { | 48 function(a@1, b@2) { |
37 return null@5; | 49 return null@5; |
38 @4}@3@0""" | 50 @4}@3@0""" |
39 }, | 51 }), |
40 | 52 |
41 const { | 53 const TestCase(const { |
42 TestMode.NONE: """ | 54 TestMode.NONE: """ |
43 function() { | 55 function() { |
44 if (true) { | 56 if (true) { |
45 foo1(); | 57 foo1(); |
46 foo2(); | 58 foo2(); |
47 } else { | 59 } else if (false) { |
48 bar1(); | 60 bar1(); |
49 bar2(); | 61 bar2(); |
50 } | 62 } |
51 while (false) { | 63 while (false) { |
52 baz3(); | 64 baz3(); |
53 baz4(); | 65 baz4(); |
54 } | 66 } |
55 }""", | 67 }""", |
56 TestMode.ENTER: """ | 68 TestMode.ENTER: """ |
57 @0function() @1{ | 69 @0function() @1{ |
58 @2if (@3true) @4{ | 70 @2if (@3true) @4{ |
59 @5@6@7foo1(); | 71 @5@6@7foo1(); |
60 @8@9@10foo2(); | 72 @8@9@10foo2(); |
61 } else @11{ | 73 } else @11if (@12false) @13{ |
62 @12@13@14bar1(); | 74 @14@15@16bar1(); |
63 @15@16@17bar2(); | 75 @17@18@19bar2(); |
64 } | 76 } |
65 @18while (@19false) @20{ | 77 @20while (@21false) @22{ |
66 @21@22@23baz3(); | 78 @23@24@25baz3(); |
67 @24@25@26baz4(); | 79 @26@27@28baz4(); |
68 } | 80 } |
69 }""", | 81 }""", |
70 TestMode.DELIMITER: """ | 82 TestMode.DELIMITER: """ |
71 function() { | 83 function() { |
72 if (true) { | 84 if (true) { |
73 foo1(); | 85 foo1(); |
74 foo2(); | 86 foo2(); |
75 } else { | 87 } else if (false) { |
76 bar1(); | 88 bar1(); |
77 bar2(); | 89 bar2(); |
78 } | 90 } |
79 while (false) { | 91 while (false) { |
80 baz3(); | 92 baz3(); |
81 baz4(); | 93 baz4(); |
82 } | 94 } |
83 @0}""", | 95 @0}""", |
84 TestMode.EXIT: """ | 96 TestMode.EXIT: """ |
85 function() { | 97 function() { |
86 if (true@3) { | 98 if (true@3) { |
87 foo1@7()@6; | 99 foo1@7()@6; |
88 @5 foo2@10()@9; | 100 @5 foo2@10()@9; |
89 @8 }@4 else { | 101 @8 }@4 else if (false@12) { |
90 bar1@14()@13; | 102 bar1@16()@15; |
91 @12 bar2@17()@16; | 103 @14 bar2@19()@18; |
92 @15 }@11 | 104 @17 }@13 |
93 @2 while (false@19) { | 105 @11@2 while (false@21) { |
94 baz3@23()@22; | 106 baz3@25()@24; |
95 @21 baz4@26()@25; | 107 @23 baz4@28()@27; |
96 @24 }@20 | 108 @26 }@22 |
97 @18}@1@0""", | 109 @20}@1@0""", |
98 }, | 110 }), |
| 111 |
| 112 const TestCase(const { |
| 113 TestMode.NONE: """ |
| 114 function() { |
| 115 function foo() { |
| 116 } |
| 117 }""", |
| 118 TestMode.ENTER: """ |
| 119 @0function() @1{ |
| 120 @2@3function @4foo() @5{ |
| 121 } |
| 122 }""", |
| 123 TestMode.DELIMITER: """ |
| 124 function() { |
| 125 function foo() { |
| 126 @3} |
| 127 @0}""", |
| 128 TestMode.EXIT: """ |
| 129 function() { |
| 130 function foo@4() { |
| 131 }@5@3 |
| 132 @2}@1@0""" |
| 133 }), |
| 134 |
| 135 const TestCase(const { |
| 136 TestMode.INPUT: """ |
| 137 function() { |
| 138 a['b']; |
| 139 [1,, 2]; |
| 140 }""", |
| 141 TestMode.NONE: """ |
| 142 function() { |
| 143 a.b; |
| 144 [1,, 2]; |
| 145 }""", |
| 146 TestMode.ENTER: """ |
| 147 @0function() @1{ |
| 148 @2@3@4a.@5b; |
| 149 @6@7[@81,@9, @102]; |
| 150 }""", |
| 151 TestMode.DELIMITER: """ |
| 152 function() { |
| 153 a.b; |
| 154 [1,, 2]; |
| 155 @0}""", |
| 156 TestMode.EXIT: """ |
| 157 function() { |
| 158 a@4.b@5@3; |
| 159 @2 [1@8,,@9 2@10]@7; |
| 160 @6}@1@0""", |
| 161 }), |
| 162 |
| 163 const TestCase(const { |
| 164 TestMode.INPUT: "a.#nameTemplate", |
| 165 TestMode.NONE: "a.nameValue", |
| 166 TestMode.ENTER: "@0@1a.@2nameValue", |
| 167 TestMode.DELIMITER: "a.nameValue", |
| 168 TestMode.EXIT: "a@1.nameValue@2@0", |
| 169 }, const {'nameTemplate': 'nameValue'}), |
99 ]; | 170 ]; |
100 | 171 |
101 void check(Map<TestMode, String> map) { | 172 class FixedName extends Name { |
102 String code = map[TestMode.NONE]; | 173 final String name; |
| 174 |
| 175 FixedName(this.name); |
| 176 |
| 177 @override |
| 178 int compareTo(other) => 0; |
| 179 } |
| 180 |
| 181 void check(TestCase testCase) { |
| 182 Map<TestMode, String> map = testCase.data; |
| 183 String code = map[TestMode.INPUT]; |
| 184 if (code == null) { |
| 185 // Input is the same as output. |
| 186 code = map[TestMode.NONE]; |
| 187 } |
103 JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(); | 188 JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(); |
104 Node node = js.parseForeignJS(code).instantiate({}); | 189 Map arguments = {}; |
| 190 testCase.environment.forEach((String name, String value) { |
| 191 arguments[name] = new FixedName(value); |
| 192 }); |
| 193 Node node = js.parseForeignJS(code).instantiate(arguments); |
105 map.forEach((TestMode mode, String expectedOutput) { | 194 map.forEach((TestMode mode, String expectedOutput) { |
| 195 if (mode == TestMode.INPUT) return; |
106 Context context = new Context(mode); | 196 Context context = new Context(mode); |
107 new Printer(options, context).visit(node); | 197 new Printer(options, context).visit(node); |
108 expect(context.getText(), equals(expectedOutput), | 198 expect(context.getText(), equals(expectedOutput), |
109 reason: "Unexpected output for $code in $mode"); | 199 reason: "Unexpected output for $code in $mode"); |
110 }); | 200 }); |
111 } | 201 } |
112 | 202 |
113 class Context extends SimpleJavaScriptPrintingContext { | 203 class Context extends SimpleJavaScriptPrintingContext { |
114 final TestMode mode; | 204 final TestMode mode; |
115 final Map<Node, int> idMap = {}; | 205 final Map<Node, int> idMap = {}; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 if (offset < text.length) { | 244 if (offset < text.length) { |
155 sb.write(text.substring(offset)); | 245 sb.write(text.substring(offset)); |
156 } | 246 } |
157 return sb.toString(); | 247 return sb.toString(); |
158 } | 248 } |
159 } | 249 } |
160 | 250 |
161 void main() { | 251 void main() { |
162 DATA.forEach(check); | 252 DATA.forEach(check); |
163 } | 253 } |
OLD | NEW |