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 library dart2js.constants.expressions.evaluate_test; | 5 library dart2js.constants.expressions.evaluate_test; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'package:async_helper/async_helper.dart'; | 8 import 'package:async_helper/async_helper.dart'; |
9 import 'package:expect/expect.dart'; | 9 import 'package:expect/expect.dart'; |
10 import 'package:compiler/src/constants/evaluation.dart'; | 10 import 'package:compiler/src/constants/evaluation.dart'; |
11 import 'package:compiler/src/constants/expressions.dart'; | 11 import 'package:compiler/src/constants/expressions.dart'; |
12 import 'package:compiler/src/constants/values.dart'; | 12 import 'package:compiler/src/constants/values.dart'; |
13 import 'package:compiler/src/constant_system_dart.dart'; | 13 import 'package:compiler/src/constant_system_dart.dart'; |
| 14 import 'package:compiler/src/core_types.dart'; |
14 import 'package:compiler/src/compiler.dart'; | 15 import 'package:compiler/src/compiler.dart'; |
| 16 import 'package:compiler/src/diagnostics/messages.dart'; |
| 17 import 'package:compiler/src/diagnostics/spannable.dart'; |
15 import 'package:compiler/src/elements/elements.dart'; | 18 import 'package:compiler/src/elements/elements.dart'; |
| 19 import 'package:compiler/src/elements/modelx.dart'; |
16 import 'memory_compiler.dart'; | 20 import 'memory_compiler.dart'; |
17 | 21 |
18 class TestData { | 22 class TestData { |
19 /// Declarations needed for the [constants]. | 23 /// Declarations needed for the [constants]. |
20 final String declarations; | 24 final String declarations; |
21 /// Tested constants. | 25 /// Tested constants. |
22 final List constants; | 26 final List constants; |
23 | 27 |
24 const TestData(this.declarations, this.constants); | 28 const TestData(this.declarations, this.constants); |
25 } | 29 } |
26 | 30 |
| 31 class ConstantResult { |
| 32 final String value; |
| 33 final errors; |
| 34 |
| 35 const ConstantResult(this.value, [this.errors]); |
| 36 } |
| 37 |
27 class ConstantData { | 38 class ConstantData { |
28 /// Source code for the constant expression. | 39 /// Source code for the constant expression. |
29 final String code; | 40 final String code; |
30 /// Map from environment to expected constant value as structured text. | 41 |
31 final Map<Map<String, String>, String> expectedValues; | 42 /// Constant value as structured text for the empty environment or a map from |
| 43 /// environment to either the expected constant value as structured text or |
| 44 /// a [ConstantResult]. |
| 45 final expectedResults; |
| 46 |
| 47 /// A [MessageKind] or a list of [MessageKind]s containing the error messages |
| 48 /// expected as the result of evaluating the constant under the empty |
| 49 /// environment. |
| 50 final expectedErrors; |
32 | 51 |
33 const ConstantData(this.code, | 52 const ConstantData(this.code, |
34 this.expectedValues); | 53 this.expectedResults, |
| 54 [this.expectedErrors]); |
| 55 } |
| 56 |
| 57 class EvaluationError { |
| 58 final MessageKind kind; |
| 59 final Map arguments; |
| 60 |
| 61 EvaluationError(this.kind, this.arguments); |
35 } | 62 } |
36 | 63 |
37 class MemoryEnvironment implements Environment { | 64 class MemoryEnvironment implements Environment { |
38 final Compiler compiler; | 65 final Compiler compiler; |
| 66 final Spannable spannable; |
39 final Map<String, String> env; | 67 final Map<String, String> env; |
| 68 final List<EvaluationError> errors = <EvaluationError>[]; |
40 | 69 |
41 MemoryEnvironment(this.compiler, | 70 MemoryEnvironment(this.compiler, |
| 71 this.spannable, |
42 [this.env = const <String, String>{}]); | 72 [this.env = const <String, String>{}]); |
43 | 73 |
44 @override | 74 @override |
45 String readFromEnvironment(String name) => env[name]; | 75 String readFromEnvironment(String name) => env[name]; |
| 76 |
| 77 @override |
| 78 CoreTypes get coreTypes => compiler.coreTypes; |
| 79 |
| 80 @override |
| 81 void reportError(ConstantExpression expression, |
| 82 MessageKind kind, |
| 83 Map arguments) { |
| 84 errors.add(new EvaluationError(kind, arguments)); |
| 85 compiler.reportError(spannable, kind, arguments); |
| 86 } |
| 87 |
| 88 @override |
| 89 ConstantValue evaluateConstructor( |
| 90 ConstructorElement constructor, |
| 91 ConstantValue evaluate()) { |
| 92 return evaluate(); |
| 93 } |
| 94 |
| 95 @override |
| 96 ConstantValue evaluateVariable( |
| 97 VariableElement variable, |
| 98 ConstantValue evaluate()) { |
| 99 return evaluate(); |
| 100 } |
46 } | 101 } |
47 | 102 |
48 const List<TestData> DATA = const [ | 103 const List<TestData> DATA = const [ |
49 const TestData('', const [ | 104 const TestData('', const [ |
50 const ConstantData('null', const { const {} : 'NullConstant' }), | 105 const ConstantData('null', 'NullConstant'), |
51 const ConstantData('false', const { const {} : 'BoolConstant(false)' }), | 106 const ConstantData('false', 'BoolConstant(false)'), |
52 const ConstantData('true', const { const {} : 'BoolConstant(true)' }), | 107 const ConstantData('true', 'BoolConstant(true)'), |
53 const ConstantData('0', const { const {} : 'IntConstant(0)' }), | 108 const ConstantData('0', 'IntConstant(0)'), |
54 const ConstantData('0.0', const { const {} : 'DoubleConstant(0.0)' }), | 109 const ConstantData('0.0', 'DoubleConstant(0.0)'), |
55 const ConstantData('"foo"', const { const {} : 'StringConstant("foo")' }), | 110 const ConstantData('"foo"', 'StringConstant("foo")'), |
56 const ConstantData('1 + 2', const { const {} : 'IntConstant(3)' }), | 111 const ConstantData('1 + 2', 'IntConstant(3)'), |
57 const ConstantData('-(1)', const { const {} : 'IntConstant(-1)' }), | 112 const ConstantData('-(1)', 'IntConstant(-1)'), |
58 const ConstantData('"foo".length', const { const {} : 'IntConstant(3)' }), | 113 const ConstantData('"foo".length', 'IntConstant(3)'), |
59 const ConstantData('identical(0, 1)', | 114 const ConstantData('identical(0, 1)', 'BoolConstant(false)'), |
60 const { const {} : 'BoolConstant(false)' }), | 115 const ConstantData('"a" "b"', 'StringConstant("ab")'), |
61 const ConstantData('"a" "b"', const { const {} : 'StringConstant("ab")' }), | 116 const ConstantData('identical', 'FunctionConstant(identical)'), |
62 const ConstantData('identical', | 117 const ConstantData('true ? 0 : 1', 'IntConstant(0)'), |
63 const { const {} : 'FunctionConstant(identical)' }), | 118 const ConstantData('true || false', 'BoolConstant(true)'), |
64 const ConstantData('true ? 0 : 1', const { const {} : 'IntConstant(0)' }), | 119 const ConstantData('true && false', 'BoolConstant(false)'), |
65 const ConstantData('proxy', | 120 const ConstantData('proxy', 'ConstructedConstant(_Proxy())'), |
66 const { const {} : 'ConstructedConstant(_Proxy())' }), | 121 //const ConstantData('Object', const { const {} : 'TypeConstant(Object)' }), |
67 const ConstantData('Object', const { const {} : 'TypeConstant(Object)' }), | |
68 const ConstantData('const [0, 1]', | 122 const ConstantData('const [0, 1]', |
69 const { const {} : 'ListConstant([IntConstant(0), IntConstant(1)])' }), | 123 'ListConstant([IntConstant(0), IntConstant(1)])'), |
70 const ConstantData('const <int>[0, 1]', const { | 124 const ConstantData('const <int>[0, 1]', |
71 const {} : 'ListConstant(<int>[IntConstant(0), IntConstant(1)])' }), | 125 'ListConstant(<int>[IntConstant(0), IntConstant(1)])'), |
72 const ConstantData('const {0: 1, 2: 3}', | 126 const ConstantData('const {0: 1, 2: 3}', |
73 const { const {} : | 127 'MapConstant({IntConstant(0): IntConstant(1), ' |
74 'MapConstant({IntConstant(0): IntConstant(1), ' | 128 'IntConstant(2): IntConstant(3)})'), |
75 'IntConstant(2): IntConstant(3)})' }), | |
76 const ConstantData('const <int, int>{0: 1, 2: 3}', | 129 const ConstantData('const <int, int>{0: 1, 2: 3}', |
77 const { const {} : | 130 'MapConstant(<int, int>{IntConstant(0): IntConstant(1), ' |
78 'MapConstant(<int, int>{IntConstant(0): IntConstant(1), ' | 131 'IntConstant(2): IntConstant(3)})'), |
79 'IntConstant(2): IntConstant(3)})' }), | 132 const ConstantData( |
| 133 'const bool.fromEnvironment("foo")', |
| 134 const { const {} : 'BoolConstant(false)', |
| 135 const {'foo': 'true'} : 'BoolConstant(true)'}), |
80 const ConstantData( | 136 const ConstantData( |
81 'const bool.fromEnvironment("foo", defaultValue: false)', | 137 'const bool.fromEnvironment("foo", defaultValue: false)', |
82 const { const {} : 'BoolConstant(false)', | 138 const { const {} : 'BoolConstant(false)', |
83 const {'foo': 'true'} : 'BoolConstant(true)'}), | 139 const {'foo': 'true'} : 'BoolConstant(true)'}), |
84 const ConstantData( | 140 const ConstantData( |
| 141 'const bool.fromEnvironment("foo", defaultValue: null)', |
| 142 const { const {} : 'NullConstant', |
| 143 const {'foo': 'false'} : 'BoolConstant(false)'}), |
| 144 const ConstantData( |
85 'const int.fromEnvironment("foo", defaultValue: 42)', | 145 'const int.fromEnvironment("foo", defaultValue: 42)', |
86 const { const {} : 'IntConstant(42)', | 146 const { const {} : 'IntConstant(42)', |
87 const {'foo': '87'} : 'IntConstant(87)'}), | 147 const {'foo': '87'} : 'IntConstant(87)'}), |
88 const ConstantData( | 148 const ConstantData( |
| 149 'const int.fromEnvironment("foo", defaultValue: null)', |
| 150 const { const {} : 'NullConstant', |
| 151 const {'foo': '87'} : 'IntConstant(87)'}), |
| 152 const ConstantData( |
89 'const String.fromEnvironment("foo", defaultValue: "bar")', | 153 'const String.fromEnvironment("foo", defaultValue: "bar")', |
90 const { const {} : 'StringConstant("bar")', | 154 const { const {} : 'StringConstant("bar")', |
91 const {'foo': 'foo'} : 'StringConstant("foo")'}), | 155 const {'foo': 'foo'} : 'StringConstant("foo")'}), |
| 156 const ConstantData( |
| 157 'const String.fromEnvironment("foo", defaultValue: null)', |
| 158 const { const {} : 'NullConstant', |
| 159 const {'foo': 'foo'} : 'StringConstant("foo")'}), |
92 ]), | 160 ]), |
93 const TestData(''' | 161 const TestData(''' |
94 const a = const bool.fromEnvironment("foo", defaultValue: true); | 162 const a = const bool.fromEnvironment("foo", defaultValue: true); |
95 const b = const int.fromEnvironment("bar", defaultValue: 42); | 163 const b = const int.fromEnvironment("bar", defaultValue: 42); |
96 | 164 |
97 class A { | 165 class A { |
98 const A(); | 166 const A(); |
99 } | 167 } |
100 class B { | 168 class B { |
101 final field1; | 169 final field1; |
102 const B(this.field1); | 170 const B(this.field1); |
103 } | 171 } |
104 class C extends B { | 172 class C extends B { |
105 final field2; | 173 final field2; |
106 const C({field1: 42, this.field2: false}) : super(field1); | 174 const C({field1: 42, this.field2: false}) : super(field1); |
107 const C.named([field = false]) : this(field1: field, field2: field); | 175 const C.named([field = false]) : this(field1: field, field2: field); |
108 } | 176 } |
109 ''', const [ | 177 ''', const [ |
110 const ConstantData('const Object()', | 178 const ConstantData('const Object()', |
111 const { const {} : 'ConstructedConstant(Object())' }), | 179 'ConstructedConstant(Object())'), |
112 const ConstantData('const A()', | 180 const ConstantData('const A()', |
113 const { const {} : 'ConstructedConstant(A())' }), | 181 'ConstructedConstant(A())'), |
114 const ConstantData('const B(0)', | 182 const ConstantData('const B(0)', |
115 const { const {} : 'ConstructedConstant(B(field1=IntConstant(0)))' }), | 183 'ConstructedConstant(B(field1=IntConstant(0)))'), |
116 const ConstantData('const B(const A())', | 184 const ConstantData('const B(const A())', |
117 const { const {} : | 185 'ConstructedConstant(B(field1=ConstructedConstant(A())))'), |
118 'ConstructedConstant(B(field1=ConstructedConstant(A())))' }), | 186 const ConstantData('const C()', |
119 const ConstantData('const C()', const { const {} : | 187 'ConstructedConstant(C(field2=BoolConstant(false),' |
120 'ConstructedConstant(C(field1=IntConstant(42),' | 188 'field1=IntConstant(42)))'), |
121 'field2=BoolConstant(false)))' }), | 189 const ConstantData('const C(field1: 87)', |
122 const ConstantData('const C(field1: 87)', const { const {} : | 190 'ConstructedConstant(C(field2=BoolConstant(false),' |
123 'ConstructedConstant(C(field1=IntConstant(87),' | 191 'field1=IntConstant(87)))'), |
124 'field2=BoolConstant(false)))' }), | 192 const ConstantData('const C(field2: true)', |
125 const ConstantData('const C(field2: true)', const { const {} : | 193 'ConstructedConstant(C(field2=BoolConstant(true),' |
126 'ConstructedConstant(C(field1=IntConstant(42),' | 194 'field1=IntConstant(42)))'), |
127 'field2=BoolConstant(true)))' }), | 195 const ConstantData('const C.named()', |
128 const ConstantData('const C.named()', const { const {} : | 196 'ConstructedConstant(C(field2=BoolConstant(false),' |
129 'ConstructedConstant(C(field1=BoolConstant(false),' | 197 'field1=BoolConstant(false)))'), |
130 'field2=BoolConstant(false)))' }), | 198 const ConstantData('const C.named(87)', |
131 const ConstantData('const C.named(87)', const { const {} : | 199 'ConstructedConstant(C(field2=IntConstant(87),' |
132 'ConstructedConstant(C(field1=IntConstant(87),' | 200 'field1=IntConstant(87)))'), |
133 'field2=IntConstant(87)))' }), | |
134 const ConstantData('const C(field1: a, field2: b)', const { | 201 const ConstantData('const C(field1: a, field2: b)', const { |
135 const {} : | 202 const {} : |
136 'ConstructedConstant(C(field1=BoolConstant(true),' | 203 'ConstructedConstant(C(field2=IntConstant(42),' |
137 'field2=IntConstant(42)))', | 204 'field1=BoolConstant(true)))', |
138 const {'foo': 'false', 'bar': '87'} : | 205 const {'foo': 'false', 'bar': '87'} : |
139 'ConstructedConstant(C(field1=BoolConstant(false),' | 206 'ConstructedConstant(C(field2=IntConstant(87),' |
140 'field2=IntConstant(87)))', }), | 207 'field1=BoolConstant(false)))', }), |
141 ]), | 208 ]), |
142 const TestData(''' | 209 const TestData(''' |
143 class A<T> implements B { | 210 class A<T> implements B { |
144 final field1; | 211 final field1; |
145 const A({this.field1:42}); | 212 const A({this.field1:42}); |
146 } | 213 } |
147 class B<S> implements C { | 214 class B<S> implements C { |
148 const factory B({field1}) = A<B<S>>; | 215 const factory B({field1}) = A<B<S>>; |
149 const factory B.named() = A<S>; | 216 const factory B.named() = A<S>; |
150 } | 217 } |
151 class C<U> { | 218 class C<U> { |
152 const factory C({field1}) = A<B<double>>; | 219 const factory C({field1}) = A<B<double>>; |
153 } | 220 } |
154 ''', const [ | 221 ''', const [ |
155 const ConstantData('const A()', | 222 const ConstantData('const A()', |
156 const { const {} : | 223 'ConstructedConstant(A<dynamic>(field1=IntConstant(42)))'), |
157 'ConstructedConstant(A<dynamic>(field1=IntConstant(42)))' }), | |
158 const ConstantData('const A<int>(field1: 87)', | 224 const ConstantData('const A<int>(field1: 87)', |
159 const { const {} : | 225 'ConstructedConstant(A<int>(field1=IntConstant(87)))'), |
160 'ConstructedConstant(A<int>(field1=IntConstant(87)))' }), | |
161 const ConstantData('const B()', | 226 const ConstantData('const B()', |
162 const { const {} : | 227 'ConstructedConstant(A<B<dynamic>>(field1=IntConstant(42)))'), |
163 'ConstructedConstant(A<B<dynamic>>(field1=IntConstant(42)))' }), | |
164 const ConstantData('const B<int>()', | 228 const ConstantData('const B<int>()', |
165 const { const {} : | 229 'ConstructedConstant(A<B<int>>(field1=IntConstant(42)))'), |
166 'ConstructedConstant(A<B<int>>(field1=IntConstant(42)))' }), | |
167 const ConstantData('const B<int>(field1: 87)', | 230 const ConstantData('const B<int>(field1: 87)', |
168 const { const {} : | 231 'ConstructedConstant(A<B<int>>(field1=IntConstant(87)))'), |
169 'ConstructedConstant(A<B<int>>(field1=IntConstant(87)))' }), | |
170 const ConstantData('const C<int>(field1: 87)', | 232 const ConstantData('const C<int>(field1: 87)', |
171 const { const {} : | 233 'ConstructedConstant(A<B<double>>(field1=IntConstant(87)))'), |
172 'ConstructedConstant(A<B<double>>(field1=IntConstant(87)))' }), | |
173 const ConstantData('const B<int>.named()', | 234 const ConstantData('const B<int>.named()', |
174 const { const {} : | 235 'ConstructedConstant(A<int>(field1=IntConstant(42)))'), |
175 'ConstructedConstant(A<int>(field1=IntConstant(42)))' }), | |
176 ]), | 236 ]), |
177 const TestData(''' | 237 const TestData(''' |
178 const c = const int.fromEnvironment("foo", defaultValue: 5); | 238 const c = const int.fromEnvironment("foo", defaultValue: 5); |
179 const d = const int.fromEnvironment("bar", defaultValue: 10); | 239 const d = const int.fromEnvironment("bar", defaultValue: 10); |
180 | 240 |
181 class A { | 241 class A { |
182 final field; | 242 final field; |
183 const A(a, b) : field = a + b; | 243 const A(a, b) : field = a + b; |
184 } | 244 } |
185 | 245 |
186 class B extends A { | 246 class B extends A { |
187 const B(a) : super(a, a * 2); | 247 const B(a) : super(a, a * 2); |
188 } | 248 } |
189 ''', const [ | 249 ''', const [ |
190 const ConstantData('const A(c, d)', const { | 250 const ConstantData('const A(c, d)', const { |
191 const {} : | 251 const {} : |
192 'ConstructedConstant(A(field=IntConstant(15)))', | 252 'ConstructedConstant(A(field=IntConstant(15)))', |
193 const {'foo': '7', 'bar': '11'} : | 253 const {'foo': '7', 'bar': '11'} : |
194 'ConstructedConstant(A(field=IntConstant(18)))', }), | 254 'ConstructedConstant(A(field=IntConstant(18)))', }), |
195 const ConstantData('const B(d)', const { | 255 const ConstantData('const B(d)', const { |
196 const {} : | 256 const {} : |
197 'ConstructedConstant(B(field=IntConstant(30)))', | 257 'ConstructedConstant(B(field=IntConstant(30)))', |
198 const {'bar': '42'} : | 258 const {'bar': '42'} : |
199 'ConstructedConstant(B(field=IntConstant(126)))', }), | 259 'ConstructedConstant(B(field=IntConstant(126)))', }), |
200 ]), | 260 ]), |
| 261 const TestData(''' |
| 262 class A { |
| 263 final x; |
| 264 final y; |
| 265 final z; |
| 266 final t; |
| 267 final u = 42; |
| 268 |
| 269 const A(this.z, tt) : y = 499, t = tt, x = 3; |
| 270 const A.named(z, this.t) : y = 400 + z, this.z = z, x = 3; |
| 271 const A.named2(t, z, y, x) : x = t, y = z, z = y, t = x; |
| 272 } |
| 273 ''', const [ |
| 274 const ConstantData( |
| 275 'const A.named(99, 100)', |
| 276 'ConstructedConstant(A(x=IntConstant(3),' |
| 277 'y=IntConstant(499),' |
| 278 'z=IntConstant(99),' |
| 279 't=IntConstant(100),' |
| 280 'u=IntConstant(42)))'), |
| 281 const ConstantData( |
| 282 'const A(99, 100)', |
| 283 'ConstructedConstant(A(x=IntConstant(3),' |
| 284 'y=IntConstant(499),' |
| 285 'z=IntConstant(99),' |
| 286 't=IntConstant(100),' |
| 287 'u=IntConstant(42)))'), |
| 288 ]), |
| 289 const TestData(''' |
| 290 const integer = const int.fromEnvironment("foo", defaultValue: 5); |
| 291 const string = const String.fromEnvironment("bar", defaultValue: "baz"); |
| 292 const boolean = const bool.fromEnvironment("baz", defaultValue: false); |
| 293 ''', const [ |
| 294 const ConstantData( |
| 295 r'"$integer $string $boolean"', |
| 296 'StringConstant("5 baz false")'), |
| 297 const ConstantData( |
| 298 '0 ? true : false', 'NonConstant', |
| 299 MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE), |
| 300 |
| 301 const ConstantData( |
| 302 'integer ? true : false', |
| 303 'NonConstant', |
| 304 MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE), |
| 305 |
| 306 const ConstantData(r'"${const []}"', 'NonConstant', |
| 307 MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE), |
| 308 const ConstantData(r'"${proxy}"', 'NonConstant', |
| 309 MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE), |
| 310 const ConstantData('0 + ""', 'NonConstant', |
| 311 MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE), |
| 312 const ConstantData('0 + string', 'NonConstant', |
| 313 MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE), |
| 314 const ConstantData('"" + 0', 'NonConstant', |
| 315 MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE), |
| 316 const ConstantData('string + 0', 'NonConstant', |
| 317 MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE), |
| 318 const ConstantData('true + ""', 'NonConstant', |
| 319 MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE), |
| 320 const ConstantData('boolean + string', 'NonConstant', |
| 321 MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE), |
| 322 const ConstantData('true + false', 'NonConstant', |
| 323 MessageKind.INVALID_CONSTANT_ADD_TYPES), |
| 324 const ConstantData('boolean + false', 'NonConstant', |
| 325 MessageKind.INVALID_CONSTANT_ADD_TYPES), |
| 326 const ConstantData('const [] == null', 'NonConstant', |
| 327 MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE), |
| 328 const ConstantData('proxy == null', 'NonConstant', |
| 329 MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE), |
| 330 const ConstantData('0 * ""', 'NonConstant', |
| 331 MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE), |
| 332 const ConstantData('0 * string', 'NonConstant', |
| 333 MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE), |
| 334 const ConstantData('0 % ""', 'NonConstant', |
| 335 MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE), |
| 336 const ConstantData('0 % string', 'NonConstant', |
| 337 MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE), |
| 338 const ConstantData('0 << ""', 'NonConstant', |
| 339 MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE), |
| 340 const ConstantData('0 << string', 'NonConstant', |
| 341 MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE), |
| 342 const ConstantData('null[0]', 'NonConstant', |
| 343 MessageKind.INVALID_CONSTANT_INDEX), |
| 344 const ConstantData('null ?? 0', 'NonConstant', |
| 345 MessageKind.INVALID_CONSTANT_IF_NULL), |
| 346 const ConstantData( |
| 347 'const bool.fromEnvironment(0)', |
| 348 'NonConstant', |
| 349 MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE), |
| 350 const ConstantData( |
| 351 'const bool.fromEnvironment(integer)', |
| 352 'NonConstant', |
| 353 MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE), |
| 354 const ConstantData( |
| 355 'const bool.fromEnvironment("baz", defaultValue: 0)', |
| 356 'NonConstant', |
| 357 MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE), |
| 358 const ConstantData( |
| 359 'const bool.fromEnvironment("baz", defaultValue: integer)', |
| 360 'NonConstant', |
| 361 MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE), |
| 362 const ConstantData( |
| 363 'const int.fromEnvironment(0)', |
| 364 'NonConstant', |
| 365 MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE), |
| 366 const ConstantData( |
| 367 'const int.fromEnvironment(integer)', |
| 368 'NonConstant', |
| 369 MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE), |
| 370 const ConstantData( |
| 371 'const int.fromEnvironment("baz", defaultValue: "")', |
| 372 'NonConstant', |
| 373 MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE), |
| 374 const ConstantData( |
| 375 'const int.fromEnvironment("baz", defaultValue: string)', |
| 376 'NonConstant', |
| 377 MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE), |
| 378 const ConstantData( |
| 379 'const String.fromEnvironment(0)', |
| 380 'NonConstant', |
| 381 MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE), |
| 382 const ConstantData( |
| 383 'const String.fromEnvironment(integer)', |
| 384 'NonConstant', |
| 385 MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE), |
| 386 const ConstantData( |
| 387 'const String.fromEnvironment("baz", defaultValue: 0)', |
| 388 'NonConstant', |
| 389 MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE), |
| 390 const ConstantData( |
| 391 'const String.fromEnvironment("baz", defaultValue: integer)', |
| 392 'NonConstant', |
| 393 MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE), |
| 394 const ConstantData('true || 0', 'NonConstant', |
| 395 MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE), |
| 396 const ConstantData('0 || true', 'NonConstant', |
| 397 MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE), |
| 398 const ConstantData('true || integer', 'NonConstant', |
| 399 MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE), |
| 400 const ConstantData('integer || true', 'NonConstant', |
| 401 MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE), |
| 402 const ConstantData('true && 0', 'NonConstant', |
| 403 MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE), |
| 404 const ConstantData('0 && true', 'NonConstant', |
| 405 MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE), |
| 406 const ConstantData('integer && true', 'NonConstant', |
| 407 MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE), |
| 408 const ConstantData('!0', 'NonConstant', |
| 409 MessageKind.INVALID_CONSTANT_NOT_TYPE), |
| 410 const ConstantData('!string', 'NonConstant', |
| 411 MessageKind.INVALID_CONSTANT_NOT_TYPE), |
| 412 const ConstantData('-("")', 'NonConstant', |
| 413 MessageKind.INVALID_CONSTANT_NEGATE_TYPE), |
| 414 const ConstantData('-(string)', 'NonConstant', |
| 415 MessageKind.INVALID_CONSTANT_NEGATE_TYPE), |
| 416 ]), |
201 ]; | 417 ]; |
202 | 418 |
203 main() { | 419 main() { |
204 asyncTest(() => Future.forEach(DATA, testData)); | 420 asyncTest(() => Future.forEach(DATA, testData)); |
205 } | 421 } |
206 | 422 |
207 Future testData(TestData data) async { | 423 Future testData(TestData data) async { |
208 StringBuffer sb = new StringBuffer(); | 424 StringBuffer sb = new StringBuffer(); |
209 sb.write('${data.declarations}\n'); | 425 sb.write('${data.declarations}\n'); |
210 Map constants = {}; | 426 Map constants = {}; |
211 data.constants.forEach((ConstantData constantData) { | 427 data.constants.forEach((ConstantData constantData) { |
212 String name = 'c${constants.length}'; | 428 String name = 'c${constants.length}'; |
213 sb.write('const $name = ${constantData.code};\n'); | 429 sb.write('const $name = ${constantData.code};\n'); |
214 constants[name] = constantData; | 430 constants[name] = constantData; |
215 }); | 431 }); |
216 sb.write('main() {}\n'); | 432 sb.write('main() {}\n'); |
217 String source = sb.toString(); | 433 String source = sb.toString(); |
| 434 DiagnosticCollector collector = new DiagnosticCollector(); |
218 CompilationResult result = await runCompiler( | 435 CompilationResult result = await runCompiler( |
219 memorySourceFiles: {'main.dart': source}, options: ['--analyze-all']); | 436 memorySourceFiles: {'main.dart': source}, |
| 437 diagnosticHandler: collector, |
| 438 options: ['--analyze-only']); |
220 Compiler compiler = result.compiler; | 439 Compiler compiler = result.compiler; |
| 440 Expect.isTrue(collector.errors.isEmpty, |
| 441 "Unexpected errors: ${collector.errors}"); |
| 442 Expect.isTrue(collector.warnings.isEmpty, |
| 443 "Unexpected warnings: ${collector.warnings}"); |
| 444 compiler.enqueuer.resolution.queueIsClosed = false; |
221 var library = compiler.mainApp; | 445 var library = compiler.mainApp; |
222 constants.forEach((String name, ConstantData data) { | 446 constants.forEach((String name, ConstantData data) { |
223 FieldElement field = library.localLookup(name); | 447 collector.clear(); |
| 448 FieldElementX field = library.localLookup(name); |
| 449 compiler.enqueuer.resolution.addToWorkList(field); |
| 450 compiler.processEnqueuerQueue(compiler.enqueuer.resolution); |
| 451 |
| 452 Expect.isNotNull(field.constantCache, |
| 453 "Expected non-null constant for field " |
| 454 "`$field = ${field.initializer}`."); |
224 ConstantExpression constant = field.constant; | 455 ConstantExpression constant = field.constant; |
225 data.expectedValues.forEach( | 456 Expect.isNotNull(constant, |
| 457 "Expected non-null constant for field " |
| 458 "`$field = ${field.initializer}`."); |
| 459 var expectedResults = data.expectedResults; |
| 460 if (expectedResults is String) { |
| 461 expectedResults = { const <String, String>{}: expectedResults}; |
| 462 } |
| 463 expectedResults.forEach( |
226 (Map<String, String> env, String expectedText) { | 464 (Map<String, String> env, String expectedText) { |
227 Environment environment = new MemoryEnvironment(compiler, env); | 465 Environment environment = |
| 466 new MemoryEnvironment( |
| 467 compiler, field/*.initializer*/, env); |
228 ConstantValue value = | 468 ConstantValue value = |
229 constant.evaluate(environment, DART_CONSTANT_SYSTEM); | 469 constant.evaluate(environment, DART_CONSTANT_SYSTEM); |
| 470 Expect.isNotNull(value, |
| 471 "Expected non-null value from evaluation of " |
| 472 "`${constant.getText()}`."); |
230 String valueText = value.toStructuredString(); | 473 String valueText = value.toStructuredString(); |
231 Expect.equals(expectedText, valueText, | 474 Expect.equals(expectedText, valueText, |
232 "Unexpected value '${valueText}' for contant " | 475 "Unexpected value '${valueText}' for contant " |
233 "`${constant.getText()}`, expected '${expectedText}'."); | 476 "`${constant.getText()}`, expected '${expectedText}'."); |
| 477 return; |
| 478 List<MessageKind> errors = |
| 479 collector.errors.map((m) => m.message.kind). |
| 480 where((k) { |
| 481 return k != MessageKind.NOT_ASSIGNABLE && |
| 482 k != MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
| 483 }).toList(); |
| 484 var expectedErrors = data.expectedErrors; |
| 485 if (expectedErrors != null) { |
| 486 if (expectedErrors is! List) { |
| 487 expectedErrors = [expectedErrors]; |
| 488 } |
| 489 Expect.listEquals(expectedErrors, errors, |
| 490 "Error mismatch for `$field = ${field.initializer}`:\n" |
| 491 "Expected: ${data.expectedErrors},\n" |
| 492 "Found: ${errors}."); |
| 493 } else { |
| 494 Expect.isTrue(errors.isEmpty, |
| 495 "Unexpected errors for `$field = ${field.initializer}`:\n" |
| 496 "Found: ${errors}."); |
| 497 } |
234 }); | 498 }); |
235 }); | 499 }); |
236 } | 500 } |
OLD | NEW |