OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
Brian Wilkerson
2016/01/22 15:17:01
I've been keeping the original copyright when I mo
| |
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. | |
4 | |
5 library analyzer.test.generated.all_the_rest_test; | |
Brian Wilkerson
2016/01/22 15:17:01
"all_the_rest_test" --> "constant_test" (I'm surpr
skybrian
2016/01/22 20:46:32
Fixed.
| |
6 | |
7 import 'package:analyzer/dart/ast/ast.dart'; | |
8 import 'package:analyzer/dart/element/element.dart'; | |
9 import 'package:analyzer/dart/element/type.dart'; | |
10 import 'package:analyzer/src/dart/element/element.dart'; | |
11 import 'package:analyzer/src/generated/constant.dart'; | |
12 import 'package:analyzer/src/generated/engine.dart'; | |
13 import 'package:analyzer/src/generated/error.dart'; | |
14 import 'package:analyzer/src/generated/resolver.dart'; | |
15 import 'package:analyzer/src/generated/scanner.dart'; | |
16 import 'package:analyzer/src/generated/source.dart'; | |
17 import 'package:analyzer/src/generated/source_io.dart'; | |
18 import 'package:analyzer/src/generated/testing/ast_factory.dart'; | |
19 import 'package:analyzer/src/generated/testing/element_factory.dart'; | |
20 import 'package:analyzer/src/generated/testing/test_type_provider.dart'; | |
21 import 'package:analyzer/src/task/dart.dart'; | |
22 import 'package:path/path.dart'; | |
23 import 'package:unittest/unittest.dart'; | |
24 | |
25 import '../reflective_tests.dart'; | |
26 import '../utils.dart'; | |
27 import 'engine_test.dart'; | |
28 import 'resolver_test.dart'; | |
29 import 'test_support.dart'; | |
30 | |
31 main() { | |
32 initializeTestEnvironment(); | |
33 runReflectiveTests(ConstantEvaluatorTest); | |
34 runReflectiveTests(ConstantFinderTest); | |
35 runReflectiveTests(ConstantValueComputerTest); | |
36 runReflectiveTests(ConstantVisitorTest); | |
37 } | |
38 | |
39 /** | |
40 * Implementation of [ConstantEvaluationValidator] used during unit tests; | |
41 * verifies that any nodes referenced during constant evaluation are present in | |
42 * the dependency graph. | |
43 */ | |
44 class ConstantEvaluationValidator_ForTest | |
45 implements ConstantEvaluationValidator { | |
46 ConstantValueComputer computer; | |
47 | |
48 ConstantEvaluationTarget _nodeBeingEvaluated; | |
49 | |
50 @override | |
51 void beforeComputeValue(ConstantEvaluationTarget constant) { | |
52 _nodeBeingEvaluated = constant; | |
53 } | |
54 | |
55 @override | |
56 void beforeGetConstantInitializers(ConstructorElement constructor) { | |
57 // Make sure we properly recorded the dependency. | |
58 expect( | |
59 computer.referenceGraph.containsPath(_nodeBeingEvaluated, constructor), | |
60 isTrue); | |
61 } | |
62 | |
63 @override | |
64 void beforeGetEvaluationResult(ConstantEvaluationTarget constant) { | |
65 // Make sure we properly recorded the dependency. | |
66 expect(computer.referenceGraph.containsPath(_nodeBeingEvaluated, constant), | |
67 isTrue); | |
68 } | |
69 | |
70 @override | |
71 void beforeGetFieldEvaluationResult(FieldElementImpl field) { | |
72 // Make sure we properly recorded the dependency. | |
73 expect(computer.referenceGraph.containsPath(_nodeBeingEvaluated, field), | |
74 isTrue); | |
75 } | |
76 | |
77 @override | |
78 void beforeGetParameterDefault(ParameterElement parameter) { | |
79 // Make sure we properly recorded the dependency. | |
80 expect(computer.referenceGraph.containsPath(_nodeBeingEvaluated, parameter), | |
81 isTrue); | |
82 } | |
83 } | |
84 | |
85 @reflectiveTest | |
86 class ConstantEvaluatorTest extends ResolverTestCase { | |
87 void fail_constructor() { | |
88 EvaluationResult result = _getExpressionValue("?"); | |
89 expect(result.isValid, isTrue); | |
90 DartObject value = result.value; | |
91 expect(value, null); | |
92 } | |
93 | |
94 void fail_identifier_class() { | |
95 EvaluationResult result = _getExpressionValue("?"); | |
96 expect(result.isValid, isTrue); | |
97 DartObject value = result.value; | |
98 expect(value, null); | |
99 } | |
100 | |
101 void fail_identifier_function() { | |
102 EvaluationResult result = _getExpressionValue("?"); | |
103 expect(result.isValid, isTrue); | |
104 DartObject value = result.value; | |
105 expect(value, null); | |
106 } | |
107 | |
108 void fail_identifier_static() { | |
109 EvaluationResult result = _getExpressionValue("?"); | |
110 expect(result.isValid, isTrue); | |
111 DartObject value = result.value; | |
112 expect(value, null); | |
113 } | |
114 | |
115 void fail_identifier_staticMethod() { | |
116 EvaluationResult result = _getExpressionValue("?"); | |
117 expect(result.isValid, isTrue); | |
118 DartObject value = result.value; | |
119 expect(value, null); | |
120 } | |
121 | |
122 void fail_identifier_topLevel() { | |
123 EvaluationResult result = _getExpressionValue("?"); | |
124 expect(result.isValid, isTrue); | |
125 DartObject value = result.value; | |
126 expect(value, null); | |
127 } | |
128 | |
129 void fail_identifier_typeParameter() { | |
130 EvaluationResult result = _getExpressionValue("?"); | |
131 expect(result.isValid, isTrue); | |
132 DartObject value = result.value; | |
133 expect(value, null); | |
134 } | |
135 | |
136 void fail_prefixedIdentifier_invalid() { | |
137 EvaluationResult result = _getExpressionValue("?"); | |
138 expect(result.isValid, isTrue); | |
139 DartObject value = result.value; | |
140 expect(value, null); | |
141 } | |
142 | |
143 void fail_prefixedIdentifier_valid() { | |
144 EvaluationResult result = _getExpressionValue("?"); | |
145 expect(result.isValid, isTrue); | |
146 DartObject value = result.value; | |
147 expect(value, null); | |
148 } | |
149 | |
150 void fail_propertyAccess_invalid() { | |
151 EvaluationResult result = _getExpressionValue("?"); | |
152 expect(result.isValid, isTrue); | |
153 DartObject value = result.value; | |
154 expect(value, null); | |
155 } | |
156 | |
157 void fail_propertyAccess_valid() { | |
158 EvaluationResult result = _getExpressionValue("?"); | |
159 expect(result.isValid, isTrue); | |
160 DartObject value = result.value; | |
161 expect(value, null); | |
162 } | |
163 | |
164 void fail_simpleIdentifier_invalid() { | |
165 EvaluationResult result = _getExpressionValue("?"); | |
166 expect(result.isValid, isTrue); | |
167 DartObject value = result.value; | |
168 expect(value, null); | |
169 } | |
170 | |
171 void fail_simpleIdentifier_valid() { | |
172 EvaluationResult result = _getExpressionValue("?"); | |
173 expect(result.isValid, isTrue); | |
174 DartObject value = result.value; | |
175 expect(value, null); | |
176 } | |
177 | |
178 void test_bitAnd_int_int() { | |
179 _assertValue3(74 & 42, "74 & 42"); | |
180 } | |
181 | |
182 void test_bitNot() { | |
183 _assertValue3(~42, "~42"); | |
184 } | |
185 | |
186 void test_bitOr_int_int() { | |
187 _assertValue3(74 | 42, "74 | 42"); | |
188 } | |
189 | |
190 void test_bitXor_int_int() { | |
191 _assertValue3(74 ^ 42, "74 ^ 42"); | |
192 } | |
193 | |
194 void test_divide_double_double() { | |
195 _assertValue2(3.2 / 2.3, "3.2 / 2.3"); | |
196 } | |
197 | |
198 void test_divide_double_double_byZero() { | |
199 EvaluationResult result = _getExpressionValue("3.2 / 0.0"); | |
200 expect(result.isValid, isTrue); | |
201 DartObject value = result.value; | |
202 expect(value.type.name, "double"); | |
203 expect(value.toDoubleValue().isInfinite, isTrue); | |
204 } | |
205 | |
206 void test_divide_int_int() { | |
207 _assertValue2(1.5, "3 / 2"); | |
208 } | |
209 | |
210 void test_divide_int_int_byZero() { | |
211 EvaluationResult result = _getExpressionValue("3 / 0"); | |
212 expect(result.isValid, isTrue); | |
213 } | |
214 | |
215 void test_equal_boolean_boolean() { | |
216 _assertValue(false, "true == false"); | |
217 } | |
218 | |
219 void test_equal_int_int() { | |
220 _assertValue(false, "2 == 3"); | |
221 } | |
222 | |
223 void test_equal_invalidLeft() { | |
224 EvaluationResult result = _getExpressionValue("a == 3"); | |
225 expect(result.isValid, isFalse); | |
226 } | |
227 | |
228 void test_equal_invalidRight() { | |
229 EvaluationResult result = _getExpressionValue("2 == a"); | |
230 expect(result.isValid, isFalse); | |
231 } | |
232 | |
233 void test_equal_string_string() { | |
234 _assertValue(false, "'a' == 'b'"); | |
235 } | |
236 | |
237 void test_greaterThan_int_int() { | |
238 _assertValue(false, "2 > 3"); | |
239 } | |
240 | |
241 void test_greaterThanOrEqual_int_int() { | |
242 _assertValue(false, "2 >= 3"); | |
243 } | |
244 | |
245 void test_leftShift_int_int() { | |
246 _assertValue3(64, "16 << 2"); | |
247 } | |
248 | |
249 void test_lessThan_int_int() { | |
250 _assertValue(true, "2 < 3"); | |
251 } | |
252 | |
253 void test_lessThanOrEqual_int_int() { | |
254 _assertValue(true, "2 <= 3"); | |
255 } | |
256 | |
257 void test_literal_boolean_false() { | |
258 _assertValue(false, "false"); | |
259 } | |
260 | |
261 void test_literal_boolean_true() { | |
262 _assertValue(true, "true"); | |
263 } | |
264 | |
265 void test_literal_list() { | |
266 EvaluationResult result = _getExpressionValue("const ['a', 'b', 'c']"); | |
267 expect(result.isValid, isTrue); | |
268 } | |
269 | |
270 void test_literal_map() { | |
271 EvaluationResult result = | |
272 _getExpressionValue("const {'a' : 'm', 'b' : 'n', 'c' : 'o'}"); | |
273 expect(result.isValid, isTrue); | |
274 } | |
275 | |
276 void test_literal_null() { | |
277 EvaluationResult result = _getExpressionValue("null"); | |
278 expect(result.isValid, isTrue); | |
279 DartObject value = result.value; | |
280 expect(value.isNull, isTrue); | |
281 } | |
282 | |
283 void test_literal_number_double() { | |
284 _assertValue2(3.45, "3.45"); | |
285 } | |
286 | |
287 void test_literal_number_integer() { | |
288 _assertValue3(42, "42"); | |
289 } | |
290 | |
291 void test_literal_string_adjacent() { | |
292 _assertValue4("abcdef", "'abc' 'def'"); | |
293 } | |
294 | |
295 void test_literal_string_interpolation_invalid() { | |
296 EvaluationResult result = _getExpressionValue("'a\${f()}c'"); | |
297 expect(result.isValid, isFalse); | |
298 } | |
299 | |
300 void test_literal_string_interpolation_valid() { | |
301 _assertValue4("a3c", "'a\${3}c'"); | |
302 } | |
303 | |
304 void test_literal_string_simple() { | |
305 _assertValue4("abc", "'abc'"); | |
306 } | |
307 | |
308 void test_logicalAnd() { | |
309 _assertValue(false, "true && false"); | |
310 } | |
311 | |
312 void test_logicalNot() { | |
313 _assertValue(false, "!true"); | |
314 } | |
315 | |
316 void test_logicalOr() { | |
317 _assertValue(true, "true || false"); | |
318 } | |
319 | |
320 void test_minus_double_double() { | |
321 _assertValue2(3.2 - 2.3, "3.2 - 2.3"); | |
322 } | |
323 | |
324 void test_minus_int_int() { | |
325 _assertValue3(1, "3 - 2"); | |
326 } | |
327 | |
328 void test_negated_boolean() { | |
329 EvaluationResult result = _getExpressionValue("-true"); | |
330 expect(result.isValid, isFalse); | |
331 } | |
332 | |
333 void test_negated_double() { | |
334 _assertValue2(-42.3, "-42.3"); | |
335 } | |
336 | |
337 void test_negated_integer() { | |
338 _assertValue3(-42, "-42"); | |
339 } | |
340 | |
341 void test_notEqual_boolean_boolean() { | |
342 _assertValue(true, "true != false"); | |
343 } | |
344 | |
345 void test_notEqual_int_int() { | |
346 _assertValue(true, "2 != 3"); | |
347 } | |
348 | |
349 void test_notEqual_invalidLeft() { | |
350 EvaluationResult result = _getExpressionValue("a != 3"); | |
351 expect(result.isValid, isFalse); | |
352 } | |
353 | |
354 void test_notEqual_invalidRight() { | |
355 EvaluationResult result = _getExpressionValue("2 != a"); | |
356 expect(result.isValid, isFalse); | |
357 } | |
358 | |
359 void test_notEqual_string_string() { | |
360 _assertValue(true, "'a' != 'b'"); | |
361 } | |
362 | |
363 void test_parenthesizedExpression() { | |
364 _assertValue4("a", "('a')"); | |
365 } | |
366 | |
367 void test_plus_double_double() { | |
368 _assertValue2(2.3 + 3.2, "2.3 + 3.2"); | |
369 } | |
370 | |
371 void test_plus_int_int() { | |
372 _assertValue3(5, "2 + 3"); | |
373 } | |
374 | |
375 void test_plus_string_string() { | |
376 _assertValue4("ab", "'a' + 'b'"); | |
377 } | |
378 | |
379 void test_remainder_double_double() { | |
380 _assertValue2(3.2 % 2.3, "3.2 % 2.3"); | |
381 } | |
382 | |
383 void test_remainder_int_int() { | |
384 _assertValue3(2, "8 % 3"); | |
385 } | |
386 | |
387 void test_rightShift() { | |
388 _assertValue3(16, "64 >> 2"); | |
389 } | |
390 | |
391 void test_stringLength_complex() { | |
392 _assertValue3(6, "('qwe' + 'rty').length"); | |
393 } | |
394 | |
395 void test_stringLength_simple() { | |
396 _assertValue3(6, "'Dvorak'.length"); | |
397 } | |
398 | |
399 void test_times_double_double() { | |
400 _assertValue2(2.3 * 3.2, "2.3 * 3.2"); | |
401 } | |
402 | |
403 void test_times_int_int() { | |
404 _assertValue3(6, "2 * 3"); | |
405 } | |
406 | |
407 void test_truncatingDivide_double_double() { | |
408 _assertValue3(1, "3.2 ~/ 2.3"); | |
409 } | |
410 | |
411 void test_truncatingDivide_int_int() { | |
412 _assertValue3(3, "10 ~/ 3"); | |
413 } | |
414 | |
415 void _assertValue(bool expectedValue, String contents) { | |
416 EvaluationResult result = _getExpressionValue(contents); | |
417 DartObject value = result.value; | |
418 expect(value.type.name, "bool"); | |
419 expect(value.toBoolValue(), expectedValue); | |
420 } | |
421 | |
422 void _assertValue2(double expectedValue, String contents) { | |
423 EvaluationResult result = _getExpressionValue(contents); | |
424 expect(result.isValid, isTrue); | |
425 DartObject value = result.value; | |
426 expect(value.type.name, "double"); | |
427 expect(value.toDoubleValue(), expectedValue); | |
428 } | |
429 | |
430 void _assertValue3(int expectedValue, String contents) { | |
431 EvaluationResult result = _getExpressionValue(contents); | |
432 expect(result.isValid, isTrue); | |
433 DartObject value = result.value; | |
434 expect(value.type.name, "int"); | |
435 expect(value.toIntValue(), expectedValue); | |
436 } | |
437 | |
438 void _assertValue4(String expectedValue, String contents) { | |
439 EvaluationResult result = _getExpressionValue(contents); | |
440 DartObject value = result.value; | |
441 expect(value, isNotNull); | |
442 ParameterizedType type = value.type; | |
443 expect(type, isNotNull); | |
444 expect(type.name, "String"); | |
445 expect(value.toStringValue(), expectedValue); | |
446 } | |
447 | |
448 EvaluationResult _getExpressionValue(String contents) { | |
449 Source source = addSource("var x = $contents;"); | |
450 LibraryElement library = resolve2(source); | |
451 CompilationUnit unit = | |
452 analysisContext.resolveCompilationUnit(source, library); | |
453 expect(unit, isNotNull); | |
454 NodeList<CompilationUnitMember> declarations = unit.declarations; | |
455 expect(declarations, hasLength(1)); | |
456 CompilationUnitMember declaration = declarations[0]; | |
457 EngineTestCase.assertInstanceOf((obj) => obj is TopLevelVariableDeclaration, | |
458 TopLevelVariableDeclaration, declaration); | |
459 NodeList<VariableDeclaration> variables = | |
460 (declaration as TopLevelVariableDeclaration).variables.variables; | |
461 expect(variables, hasLength(1)); | |
462 ConstantEvaluator evaluator = new ConstantEvaluator( | |
463 source, analysisContext.typeProvider, | |
464 typeSystem: analysisContext.typeSystem); | |
465 return evaluator.evaluate(variables[0].initializer); | |
466 } | |
467 } | |
468 | |
469 @reflectiveTest | |
470 class ConstantFinderTest { | |
471 AstNode _node; | |
472 TypeProvider _typeProvider; | |
473 AnalysisContext _context; | |
474 Source _source; | |
475 | |
476 void setUp() { | |
477 _typeProvider = new TestTypeProvider(); | |
478 _context = new TestAnalysisContext_ConstantFinderTest(); | |
479 _source = new TestSource(); | |
480 } | |
481 | |
482 /** | |
483 * Test an annotation that consists solely of an identifier (and hence | |
484 * represents a reference to a compile-time constant variable). | |
485 */ | |
486 void test_visitAnnotation_constantVariable() { | |
487 _node = AstFactory.annotation(AstFactory.identifier3('x')); | |
488 expect(_findAnnotations(), contains(_node)); | |
489 } | |
490 | |
491 /** | |
492 * Test an annotation that represents the invocation of a constant | |
493 * constructor. | |
494 */ | |
495 void test_visitAnnotation_invocation() { | |
496 _node = AstFactory.annotation2( | |
497 AstFactory.identifier3('A'), null, AstFactory.argumentList()); | |
498 expect(_findAnnotations(), contains(_node)); | |
499 } | |
500 | |
501 void test_visitConstructorDeclaration_const() { | |
502 ConstructorElement element = _setupConstructorDeclaration("A", true); | |
503 expect(_findConstants(), contains(element)); | |
504 } | |
505 | |
506 void test_visitConstructorDeclaration_nonConst() { | |
507 _setupConstructorDeclaration("A", false); | |
508 expect(_findConstants(), isEmpty); | |
509 } | |
510 | |
511 void test_visitVariableDeclaration_const() { | |
512 VariableElement element = _setupVariableDeclaration("v", true, true); | |
513 expect(_findConstants(), contains(element)); | |
514 } | |
515 | |
516 void test_visitVariableDeclaration_final_inClass() { | |
517 _setupFieldDeclaration('C', 'f', Keyword.FINAL); | |
518 expect(_findConstants(), isEmpty); | |
519 } | |
520 | |
521 void test_visitVariableDeclaration_final_inClassWithConstConstructor() { | |
522 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL, | |
523 hasConstConstructor: true); | |
524 expect(_findConstants(), contains(field.element)); | |
525 } | |
526 | |
527 void test_visitVariableDeclaration_final_outsideClass() { | |
528 _setupVariableDeclaration('v', false, true, isFinal: true); | |
529 expect(_findConstants(), isEmpty); | |
530 } | |
531 | |
532 void test_visitVariableDeclaration_noInitializer() { | |
533 _setupVariableDeclaration("v", true, false); | |
534 expect(_findConstants(), isEmpty); | |
535 } | |
536 | |
537 void test_visitVariableDeclaration_nonConst() { | |
538 _setupVariableDeclaration("v", false, true); | |
539 expect(_findConstants(), isEmpty); | |
540 } | |
541 | |
542 void test_visitVariableDeclaration_static_const_inClass() { | |
543 VariableDeclaration field = | |
544 _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true); | |
545 expect(_findConstants(), contains(field.element)); | |
546 } | |
547 | |
548 void | |
549 test_visitVariableDeclaration_static_const_inClassWithConstConstructor() { | |
550 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST, | |
551 isStatic: true, hasConstConstructor: true); | |
552 expect(_findConstants(), contains(field.element)); | |
553 } | |
554 | |
555 void | |
556 test_visitVariableDeclaration_static_final_inClassWithConstConstructor() { | |
557 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL, | |
558 isStatic: true, hasConstConstructor: true); | |
559 expect(_findConstants(), isNot(contains(field.element))); | |
560 } | |
561 | |
562 void | |
563 test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstruc tor() { | |
564 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL, | |
565 isInitialized: false, hasConstConstructor: true); | |
566 expect(_findConstants(), isNot(contains(field.element))); | |
567 } | |
568 | |
569 void test_visitVariableDeclaration_uninitialized_static_const_inClass() { | |
570 _setupFieldDeclaration('C', 'f', Keyword.CONST, | |
571 isStatic: true, isInitialized: false); | |
572 expect(_findConstants(), isEmpty); | |
573 } | |
574 | |
575 List<Annotation> _findAnnotations() { | |
576 Set<Annotation> annotations = new Set<Annotation>(); | |
577 for (ConstantEvaluationTarget target in _findConstants()) { | |
578 if (target is ConstantEvaluationTarget_Annotation) { | |
579 expect(target.context, same(_context)); | |
580 expect(target.source, same(_source)); | |
581 annotations.add(target.annotation); | |
582 } | |
583 } | |
584 return new List<Annotation>.from(annotations); | |
585 } | |
586 | |
587 Set<ConstantEvaluationTarget> _findConstants() { | |
588 ConstantFinder finder = new ConstantFinder(_context, _source, _source); | |
589 _node.accept(finder); | |
590 Set<ConstantEvaluationTarget> constants = finder.constantsToCompute; | |
591 expect(constants, isNotNull); | |
592 return constants; | |
593 } | |
594 | |
595 ConstructorElement _setupConstructorDeclaration(String name, bool isConst) { | |
596 Keyword constKeyword = isConst ? Keyword.CONST : null; | |
597 ConstructorDeclaration constructorDeclaration = | |
598 AstFactory.constructorDeclaration2( | |
599 constKeyword, | |
600 null, | |
601 null, | |
602 name, | |
603 AstFactory.formalParameterList(), | |
604 null, | |
605 AstFactory.blockFunctionBody2()); | |
606 ClassElement classElement = ElementFactory.classElement2(name); | |
607 ConstructorElement element = | |
608 ElementFactory.constructorElement(classElement, name, isConst); | |
609 constructorDeclaration.element = element; | |
610 _node = constructorDeclaration; | |
611 return element; | |
612 } | |
613 | |
614 VariableDeclaration _setupFieldDeclaration( | |
615 String className, String fieldName, Keyword keyword, | |
616 {bool isInitialized: true, | |
617 bool isStatic: false, | |
618 bool hasConstConstructor: false}) { | |
619 VariableDeclaration variableDeclaration = isInitialized | |
620 ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0)) | |
621 : AstFactory.variableDeclaration(fieldName); | |
622 VariableElement fieldElement = ElementFactory.fieldElement( | |
623 fieldName, | |
624 isStatic, | |
625 keyword == Keyword.FINAL, | |
626 keyword == Keyword.CONST, | |
627 _typeProvider.intType); | |
628 variableDeclaration.name.staticElement = fieldElement; | |
629 FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2( | |
630 isStatic, keyword, <VariableDeclaration>[variableDeclaration]); | |
631 ClassDeclaration classDeclaration = | |
632 AstFactory.classDeclaration(null, className, null, null, null, null); | |
633 classDeclaration.members.add(fieldDeclaration); | |
634 _node = classDeclaration; | |
635 ClassElementImpl classElement = ElementFactory.classElement2(className); | |
636 classElement.fields = <FieldElement>[fieldElement]; | |
637 classDeclaration.name.staticElement = classElement; | |
638 if (hasConstConstructor) { | |
639 ConstructorDeclaration constructorDeclaration = | |
640 AstFactory.constructorDeclaration2( | |
641 Keyword.CONST, | |
642 null, | |
643 AstFactory.identifier3(className), | |
644 null, | |
645 AstFactory.formalParameterList(), | |
646 null, | |
647 AstFactory.blockFunctionBody2()); | |
648 classDeclaration.members.add(constructorDeclaration); | |
649 ConstructorElement constructorElement = | |
650 ElementFactory.constructorElement(classElement, '', true); | |
651 constructorDeclaration.element = constructorElement; | |
652 classElement.constructors = <ConstructorElement>[constructorElement]; | |
653 } else { | |
654 classElement.constructors = ConstructorElement.EMPTY_LIST; | |
655 } | |
656 return variableDeclaration; | |
657 } | |
658 | |
659 VariableElement _setupVariableDeclaration( | |
660 String name, bool isConst, bool isInitialized, | |
661 {isFinal: false}) { | |
662 VariableDeclaration variableDeclaration = isInitialized | |
663 ? AstFactory.variableDeclaration2(name, AstFactory.integer(0)) | |
664 : AstFactory.variableDeclaration(name); | |
665 SimpleIdentifier identifier = variableDeclaration.name; | |
666 VariableElement element = ElementFactory.localVariableElement(identifier); | |
667 identifier.staticElement = element; | |
668 Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null; | |
669 AstFactory.variableDeclarationList2(keyword, [variableDeclaration]); | |
670 _node = variableDeclaration; | |
671 return element; | |
672 } | |
673 } | |
674 | |
675 @reflectiveTest | |
676 class ConstantValueComputerTest extends ResolverTestCase { | |
677 void test_annotation_constConstructor() { | |
678 CompilationUnit compilationUnit = resolveSource(r''' | |
679 class A { | |
680 final int i; | |
681 const A(this.i); | |
682 } | |
683 | |
684 class C { | |
685 @A(5) | |
686 f() {} | |
687 } | |
688 '''); | |
689 EvaluationResultImpl result = | |
690 _evaluateAnnotation(compilationUnit, "C", "f"); | |
691 Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A'); | |
692 _assertIntField(annotationFields, 'i', 5); | |
693 } | |
694 | |
695 void test_annotation_constConstructor_named() { | |
696 CompilationUnit compilationUnit = resolveSource(r''' | |
697 class A { | |
698 final int i; | |
699 const A.named(this.i); | |
700 } | |
701 | |
702 class C { | |
703 @A.named(5) | |
704 f() {} | |
705 } | |
706 '''); | |
707 EvaluationResultImpl result = | |
708 _evaluateAnnotation(compilationUnit, "C", "f"); | |
709 Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A'); | |
710 _assertIntField(annotationFields, 'i', 5); | |
711 } | |
712 | |
713 void test_annotation_constConstructor_noArgs() { | |
714 // Failing to pass arguments to an annotation which is a constant | |
715 // constructor is illegal, but shouldn't crash analysis. | |
716 CompilationUnit compilationUnit = resolveSource(r''' | |
717 class A { | |
718 final int i; | |
719 const A(this.i); | |
720 } | |
721 | |
722 class C { | |
723 @A | |
724 f() {} | |
725 } | |
726 '''); | |
727 _evaluateAnnotation(compilationUnit, "C", "f"); | |
728 } | |
729 | |
730 void test_annotation_constConstructor_noArgs_named() { | |
731 // Failing to pass arguments to an annotation which is a constant | |
732 // constructor is illegal, but shouldn't crash analysis. | |
733 CompilationUnit compilationUnit = resolveSource(r''' | |
734 class A { | |
735 final int i; | |
736 const A.named(this.i); | |
737 } | |
738 | |
739 class C { | |
740 @A.named | |
741 f() {} | |
742 } | |
743 '''); | |
744 _evaluateAnnotation(compilationUnit, "C", "f"); | |
745 } | |
746 | |
747 void test_annotation_nonConstConstructor() { | |
748 // Calling a non-const constructor from an annotation that is illegal, but | |
749 // shouldn't crash analysis. | |
750 CompilationUnit compilationUnit = resolveSource(r''' | |
751 class A { | |
752 final int i; | |
753 A(this.i); | |
754 } | |
755 | |
756 class C { | |
757 @A(5) | |
758 f() {} | |
759 } | |
760 '''); | |
761 _evaluateAnnotation(compilationUnit, "C", "f"); | |
762 } | |
763 | |
764 void test_annotation_staticConst() { | |
765 CompilationUnit compilationUnit = resolveSource(r''' | |
766 class C { | |
767 static const int i = 5; | |
768 | |
769 @i | |
770 f() {} | |
771 } | |
772 '''); | |
773 EvaluationResultImpl result = | |
774 _evaluateAnnotation(compilationUnit, "C", "f"); | |
775 expect(_assertValidInt(result), 5); | |
776 } | |
777 | |
778 void test_annotation_staticConst_args() { | |
779 // Applying arguments to an annotation that is a static const is | |
780 // illegal, but shouldn't crash analysis. | |
781 CompilationUnit compilationUnit = resolveSource(r''' | |
782 class C { | |
783 static const int i = 5; | |
784 | |
785 @i(1) | |
786 f() {} | |
787 } | |
788 '''); | |
789 _evaluateAnnotation(compilationUnit, "C", "f"); | |
790 } | |
791 | |
792 void test_annotation_staticConst_otherClass() { | |
793 CompilationUnit compilationUnit = resolveSource(r''' | |
794 class A { | |
795 static const int i = 5; | |
796 } | |
797 | |
798 class C { | |
799 @A.i | |
800 f() {} | |
801 } | |
802 '''); | |
803 EvaluationResultImpl result = | |
804 _evaluateAnnotation(compilationUnit, "C", "f"); | |
805 expect(_assertValidInt(result), 5); | |
806 } | |
807 | |
808 void test_annotation_staticConst_otherClass_args() { | |
809 // Applying arguments to an annotation that is a static const is | |
810 // illegal, but shouldn't crash analysis. | |
811 CompilationUnit compilationUnit = resolveSource(r''' | |
812 class A { | |
813 static const int i = 5; | |
814 } | |
815 | |
816 class C { | |
817 @A.i(1) | |
818 f() {} | |
819 } | |
820 '''); | |
821 _evaluateAnnotation(compilationUnit, "C", "f"); | |
822 } | |
823 | |
824 void test_annotation_toplevelVariable() { | |
825 CompilationUnit compilationUnit = resolveSource(r''' | |
826 const int i = 5; | |
827 class C { | |
828 @i | |
829 f() {} | |
830 } | |
831 '''); | |
832 EvaluationResultImpl result = | |
833 _evaluateAnnotation(compilationUnit, "C", "f"); | |
834 expect(_assertValidInt(result), 5); | |
835 } | |
836 | |
837 void test_annotation_toplevelVariable_args() { | |
838 // Applying arguments to an annotation that is a toplevel variable is | |
839 // illegal, but shouldn't crash analysis. | |
840 CompilationUnit compilationUnit = resolveSource(r''' | |
841 const int i = 5; | |
842 class C { | |
843 @i(1) | |
844 f() {} | |
845 } | |
846 '''); | |
847 _evaluateAnnotation(compilationUnit, "C", "f"); | |
848 } | |
849 | |
850 void test_computeValues_cycle() { | |
851 TestLogger logger = new TestLogger(); | |
852 AnalysisEngine.instance.logger = logger; | |
853 try { | |
854 Source librarySource = addSource(r''' | |
855 const int a = c; | |
856 const int b = a; | |
857 const int c = b;'''); | |
858 LibraryElement libraryElement = resolve2(librarySource); | |
859 CompilationUnit unit = | |
860 analysisContext.resolveCompilationUnit(librarySource, libraryElement); | |
861 analysisContext.computeErrors(librarySource); | |
862 expect(unit, isNotNull); | |
863 ConstantValueComputer computer = _makeConstantValueComputer(); | |
864 computer.add(unit, librarySource, librarySource); | |
865 computer.computeValues(); | |
866 NodeList<CompilationUnitMember> members = unit.declarations; | |
867 expect(members, hasLength(3)); | |
868 _validate(false, (members[0] as TopLevelVariableDeclaration).variables); | |
869 _validate(false, (members[1] as TopLevelVariableDeclaration).variables); | |
870 _validate(false, (members[2] as TopLevelVariableDeclaration).variables); | |
871 } finally { | |
872 AnalysisEngine.instance.logger = Logger.NULL; | |
873 } | |
874 } | |
875 | |
876 void test_computeValues_dependentVariables() { | |
877 Source librarySource = addSource(r''' | |
878 const int b = a; | |
879 const int a = 0;'''); | |
880 LibraryElement libraryElement = resolve2(librarySource); | |
881 CompilationUnit unit = | |
882 analysisContext.resolveCompilationUnit(librarySource, libraryElement); | |
883 expect(unit, isNotNull); | |
884 ConstantValueComputer computer = _makeConstantValueComputer(); | |
885 computer.add(unit, librarySource, librarySource); | |
886 computer.computeValues(); | |
887 NodeList<CompilationUnitMember> members = unit.declarations; | |
888 expect(members, hasLength(2)); | |
889 _validate(true, (members[0] as TopLevelVariableDeclaration).variables); | |
890 _validate(true, (members[1] as TopLevelVariableDeclaration).variables); | |
891 } | |
892 | |
893 void test_computeValues_empty() { | |
894 ConstantValueComputer computer = _makeConstantValueComputer(); | |
895 computer.computeValues(); | |
896 } | |
897 | |
898 void test_computeValues_multipleSources() { | |
899 Source librarySource = addNamedSource( | |
900 "/lib.dart", | |
901 r''' | |
902 library lib; | |
903 part 'part.dart'; | |
904 const int c = b; | |
905 const int a = 0;'''); | |
906 Source partSource = addNamedSource( | |
907 "/part.dart", | |
908 r''' | |
909 part of lib; | |
910 const int b = a; | |
911 const int d = c;'''); | |
912 LibraryElement libraryElement = resolve2(librarySource); | |
913 CompilationUnit libraryUnit = | |
914 analysisContext.resolveCompilationUnit(librarySource, libraryElement); | |
915 expect(libraryUnit, isNotNull); | |
916 CompilationUnit partUnit = | |
917 analysisContext.resolveCompilationUnit(partSource, libraryElement); | |
918 expect(partUnit, isNotNull); | |
919 ConstantValueComputer computer = _makeConstantValueComputer(); | |
920 computer.add(libraryUnit, librarySource, librarySource); | |
921 computer.add(partUnit, partSource, librarySource); | |
922 computer.computeValues(); | |
923 NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations; | |
924 expect(libraryMembers, hasLength(2)); | |
925 _validate( | |
926 true, (libraryMembers[0] as TopLevelVariableDeclaration).variables); | |
927 _validate( | |
928 true, (libraryMembers[1] as TopLevelVariableDeclaration).variables); | |
929 NodeList<CompilationUnitMember> partMembers = libraryUnit.declarations; | |
930 expect(partMembers, hasLength(2)); | |
931 _validate(true, (partMembers[0] as TopLevelVariableDeclaration).variables); | |
932 _validate(true, (partMembers[1] as TopLevelVariableDeclaration).variables); | |
933 } | |
934 | |
935 void test_computeValues_singleVariable() { | |
936 Source librarySource = addSource("const int a = 0;"); | |
937 LibraryElement libraryElement = resolve2(librarySource); | |
938 CompilationUnit unit = | |
939 analysisContext.resolveCompilationUnit(librarySource, libraryElement); | |
940 expect(unit, isNotNull); | |
941 ConstantValueComputer computer = _makeConstantValueComputer(); | |
942 computer.add(unit, librarySource, librarySource); | |
943 computer.computeValues(); | |
944 NodeList<CompilationUnitMember> members = unit.declarations; | |
945 expect(members, hasLength(1)); | |
946 _validate(true, (members[0] as TopLevelVariableDeclaration).variables); | |
947 } | |
948 | |
949 void test_computeValues_value_depends_on_enum() { | |
950 Source librarySource = addSource(''' | |
951 enum E { id0, id1 } | |
952 const E e = E.id0; | |
953 '''); | |
954 LibraryElement libraryElement = resolve2(librarySource); | |
955 CompilationUnit unit = | |
956 analysisContext.resolveCompilationUnit(librarySource, libraryElement); | |
957 expect(unit, isNotNull); | |
958 ConstantValueComputer computer = _makeConstantValueComputer(); | |
959 computer.add(unit, librarySource, librarySource); | |
960 computer.computeValues(); | |
961 TopLevelVariableDeclaration declaration = unit.declarations | |
962 .firstWhere((member) => member is TopLevelVariableDeclaration); | |
963 _validate(true, declaration.variables); | |
964 } | |
965 | |
966 void test_dependencyOnConstructor() { | |
967 // x depends on "const A()" | |
968 _assertProperDependencies(r''' | |
969 class A { | |
970 const A(); | |
971 } | |
972 const x = const A();'''); | |
973 } | |
974 | |
975 void test_dependencyOnConstructorArgument() { | |
976 // "const A(x)" depends on x | |
977 _assertProperDependencies(r''' | |
978 class A { | |
979 const A(this.next); | |
980 final A next; | |
981 } | |
982 const A x = const A(null); | |
983 const A y = const A(x);'''); | |
984 } | |
985 | |
986 void test_dependencyOnConstructorArgument_unresolvedConstructor() { | |
987 // "const A.a(x)" depends on x even if the constructor A.a can't be found. | |
988 _assertProperDependencies( | |
989 r''' | |
990 class A { | |
991 } | |
992 const int x = 1; | |
993 const A y = const A.a(x);''', | |
994 [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]); | |
995 } | |
996 | |
997 void test_dependencyOnConstructorInitializer() { | |
998 // "const A()" depends on x | |
999 _assertProperDependencies(r''' | |
1000 const int x = 1; | |
1001 class A { | |
1002 const A() : v = x; | |
1003 final int v; | |
1004 }'''); | |
1005 } | |
1006 | |
1007 void test_dependencyOnExplicitSuperConstructor() { | |
1008 // b depends on B() depends on A() | |
1009 _assertProperDependencies(r''' | |
1010 class A { | |
1011 const A(this.x); | |
1012 final int x; | |
1013 } | |
1014 class B extends A { | |
1015 const B() : super(5); | |
1016 } | |
1017 const B b = const B();'''); | |
1018 } | |
1019 | |
1020 void test_dependencyOnExplicitSuperConstructorParameters() { | |
1021 // b depends on B() depends on i | |
1022 _assertProperDependencies(r''' | |
1023 class A { | |
1024 const A(this.x); | |
1025 final int x; | |
1026 } | |
1027 class B extends A { | |
1028 const B() : super(i); | |
1029 } | |
1030 const B b = const B(); | |
1031 const int i = 5;'''); | |
1032 } | |
1033 | |
1034 void test_dependencyOnFactoryRedirect() { | |
1035 // a depends on A.foo() depends on A.bar() | |
1036 _assertProperDependencies(r''' | |
1037 const A a = const A.foo(); | |
1038 class A { | |
1039 factory const A.foo() = A.bar; | |
1040 const A.bar(); | |
1041 }'''); | |
1042 } | |
1043 | |
1044 void test_dependencyOnFactoryRedirectWithTypeParams() { | |
1045 _assertProperDependencies(r''' | |
1046 class A { | |
1047 const factory A(var a) = B<int>; | |
1048 } | |
1049 | |
1050 class B<T> implements A { | |
1051 final T x; | |
1052 const B(this.x); | |
1053 } | |
1054 | |
1055 const A a = const A(10);'''); | |
1056 } | |
1057 | |
1058 void test_dependencyOnImplicitSuperConstructor() { | |
1059 // b depends on B() depends on A() | |
1060 _assertProperDependencies(r''' | |
1061 class A { | |
1062 const A() : x = 5; | |
1063 final int x; | |
1064 } | |
1065 class B extends A { | |
1066 const B(); | |
1067 } | |
1068 const B b = const B();'''); | |
1069 } | |
1070 | |
1071 void test_dependencyOnInitializedFinal() { | |
1072 // a depends on A() depends on A.x | |
1073 _assertProperDependencies(''' | |
1074 class A { | |
1075 const A(); | |
1076 final int x = 1; | |
1077 } | |
1078 const A a = const A(); | |
1079 '''); | |
1080 } | |
1081 | |
1082 void test_dependencyOnInitializedNonStaticConst() { | |
1083 // Even though non-static consts are not allowed by the language, we need | |
1084 // to handle them for error recovery purposes. | |
1085 // a depends on A() depends on A.x | |
1086 _assertProperDependencies( | |
1087 ''' | |
1088 class A { | |
1089 const A(); | |
1090 const int x = 1; | |
1091 } | |
1092 const A a = const A(); | |
1093 ''', | |
1094 [CompileTimeErrorCode.CONST_INSTANCE_FIELD]); | |
1095 } | |
1096 | |
1097 void test_dependencyOnNonFactoryRedirect() { | |
1098 // a depends on A.foo() depends on A.bar() | |
1099 _assertProperDependencies(r''' | |
1100 const A a = const A.foo(); | |
1101 class A { | |
1102 const A.foo() : this.bar(); | |
1103 const A.bar(); | |
1104 }'''); | |
1105 } | |
1106 | |
1107 void test_dependencyOnNonFactoryRedirect_arg() { | |
1108 // a depends on A.foo() depends on b | |
1109 _assertProperDependencies(r''' | |
1110 const A a = const A.foo(); | |
1111 const int b = 1; | |
1112 class A { | |
1113 const A.foo() : this.bar(b); | |
1114 const A.bar(x) : y = x; | |
1115 final int y; | |
1116 }'''); | |
1117 } | |
1118 | |
1119 void test_dependencyOnNonFactoryRedirect_defaultValue() { | |
1120 // a depends on A.foo() depends on A.bar() depends on b | |
1121 _assertProperDependencies(r''' | |
1122 const A a = const A.foo(); | |
1123 const int b = 1; | |
1124 class A { | |
1125 const A.foo() : this.bar(); | |
1126 const A.bar([x = b]) : y = x; | |
1127 final int y; | |
1128 }'''); | |
1129 } | |
1130 | |
1131 void test_dependencyOnNonFactoryRedirect_toMissing() { | |
1132 // a depends on A.foo() which depends on nothing, since A.bar() is | |
1133 // missing. | |
1134 _assertProperDependencies( | |
1135 r''' | |
1136 const A a = const A.foo(); | |
1137 class A { | |
1138 const A.foo() : this.bar(); | |
1139 }''', | |
1140 [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]); | |
1141 } | |
1142 | |
1143 void test_dependencyOnNonFactoryRedirect_toNonConst() { | |
1144 // a depends on A.foo() which depends on nothing, since A.bar() is | |
1145 // non-const. | |
1146 _assertProperDependencies(r''' | |
1147 const A a = const A.foo(); | |
1148 class A { | |
1149 const A.foo() : this.bar(); | |
1150 A.bar(); | |
1151 }'''); | |
1152 } | |
1153 | |
1154 void test_dependencyOnNonFactoryRedirect_unnamed() { | |
1155 // a depends on A.foo() depends on A() | |
1156 _assertProperDependencies(r''' | |
1157 const A a = const A.foo(); | |
1158 class A { | |
1159 const A.foo() : this(); | |
1160 const A(); | |
1161 }'''); | |
1162 } | |
1163 | |
1164 void test_dependencyOnOptionalParameterDefault() { | |
1165 // a depends on A() depends on B() | |
1166 _assertProperDependencies(r''' | |
1167 class A { | |
1168 const A([x = const B()]) : b = x; | |
1169 final B b; | |
1170 } | |
1171 class B { | |
1172 const B(); | |
1173 } | |
1174 const A a = const A();'''); | |
1175 } | |
1176 | |
1177 void test_dependencyOnVariable() { | |
1178 // x depends on y | |
1179 _assertProperDependencies(r''' | |
1180 const x = y + 1; | |
1181 const y = 2;'''); | |
1182 } | |
1183 | |
1184 void test_final_initialized_at_declaration() { | |
1185 CompilationUnit compilationUnit = resolveSource(''' | |
1186 class A { | |
1187 final int i = 123; | |
1188 const A(); | |
1189 } | |
1190 | |
1191 const A a = const A(); | |
1192 '''); | |
1193 EvaluationResultImpl result = | |
1194 _evaluateTopLevelVariable(compilationUnit, 'a'); | |
1195 Map<String, DartObjectImpl> fields = _assertType(result, "A"); | |
1196 expect(fields, hasLength(1)); | |
1197 _assertIntField(fields, "i", 123); | |
1198 } | |
1199 | |
1200 void test_fromEnvironment_bool_default_false() { | |
1201 expect(_assertValidBool(_check_fromEnvironment_bool(null, "false")), false); | |
1202 } | |
1203 | |
1204 void test_fromEnvironment_bool_default_overridden() { | |
1205 expect( | |
1206 _assertValidBool(_check_fromEnvironment_bool("false", "true")), false); | |
1207 } | |
1208 | |
1209 void test_fromEnvironment_bool_default_parseError() { | |
1210 expect(_assertValidBool(_check_fromEnvironment_bool("parseError", "true")), | |
1211 true); | |
1212 } | |
1213 | |
1214 void test_fromEnvironment_bool_default_true() { | |
1215 expect(_assertValidBool(_check_fromEnvironment_bool(null, "true")), true); | |
1216 } | |
1217 | |
1218 void test_fromEnvironment_bool_false() { | |
1219 expect(_assertValidBool(_check_fromEnvironment_bool("false", null)), false); | |
1220 } | |
1221 | |
1222 void test_fromEnvironment_bool_parseError() { | |
1223 expect(_assertValidBool(_check_fromEnvironment_bool("parseError", null)), | |
1224 false); | |
1225 } | |
1226 | |
1227 void test_fromEnvironment_bool_true() { | |
1228 expect(_assertValidBool(_check_fromEnvironment_bool("true", null)), true); | |
1229 } | |
1230 | |
1231 void test_fromEnvironment_bool_undeclared() { | |
1232 _assertValidUnknown(_check_fromEnvironment_bool(null, null)); | |
1233 } | |
1234 | |
1235 void test_fromEnvironment_int_default_overridden() { | |
1236 expect(_assertValidInt(_check_fromEnvironment_int("234", "123")), 234); | |
1237 } | |
1238 | |
1239 void test_fromEnvironment_int_default_parseError() { | |
1240 expect( | |
1241 _assertValidInt(_check_fromEnvironment_int("parseError", "123")), 123); | |
1242 } | |
1243 | |
1244 void test_fromEnvironment_int_default_undeclared() { | |
1245 expect(_assertValidInt(_check_fromEnvironment_int(null, "123")), 123); | |
1246 } | |
1247 | |
1248 void test_fromEnvironment_int_ok() { | |
1249 expect(_assertValidInt(_check_fromEnvironment_int("234", null)), 234); | |
1250 } | |
1251 | |
1252 void test_fromEnvironment_int_parseError() { | |
1253 _assertValidNull(_check_fromEnvironment_int("parseError", null)); | |
1254 } | |
1255 | |
1256 void test_fromEnvironment_int_parseError_nullDefault() { | |
1257 _assertValidNull(_check_fromEnvironment_int("parseError", "null")); | |
1258 } | |
1259 | |
1260 void test_fromEnvironment_int_undeclared() { | |
1261 _assertValidUnknown(_check_fromEnvironment_int(null, null)); | |
1262 } | |
1263 | |
1264 void test_fromEnvironment_int_undeclared_nullDefault() { | |
1265 _assertValidNull(_check_fromEnvironment_int(null, "null")); | |
1266 } | |
1267 | |
1268 void test_fromEnvironment_string_default_overridden() { | |
1269 expect(_assertValidString(_check_fromEnvironment_string("abc", "'def'")), | |
1270 "abc"); | |
1271 } | |
1272 | |
1273 void test_fromEnvironment_string_default_undeclared() { | |
1274 expect(_assertValidString(_check_fromEnvironment_string(null, "'def'")), | |
1275 "def"); | |
1276 } | |
1277 | |
1278 void test_fromEnvironment_string_empty() { | |
1279 expect(_assertValidString(_check_fromEnvironment_string("", null)), ""); | |
1280 } | |
1281 | |
1282 void test_fromEnvironment_string_ok() { | |
1283 expect( | |
1284 _assertValidString(_check_fromEnvironment_string("abc", null)), "abc"); | |
1285 } | |
1286 | |
1287 void test_fromEnvironment_string_undeclared() { | |
1288 _assertValidUnknown(_check_fromEnvironment_string(null, null)); | |
1289 } | |
1290 | |
1291 void test_fromEnvironment_string_undeclared_nullDefault() { | |
1292 _assertValidNull(_check_fromEnvironment_string(null, "null")); | |
1293 } | |
1294 | |
1295 void test_instanceCreationExpression_computedField() { | |
1296 CompilationUnit compilationUnit = resolveSource(r''' | |
1297 const foo = const A(4, 5); | |
1298 class A { | |
1299 const A(int i, int j) : k = 2 * i + j; | |
1300 final int k; | |
1301 }'''); | |
1302 EvaluationResultImpl result = | |
1303 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1304 Map<String, DartObjectImpl> fields = _assertType(result, "A"); | |
1305 expect(fields, hasLength(1)); | |
1306 _assertIntField(fields, "k", 13); | |
1307 } | |
1308 | |
1309 void | |
1310 test_instanceCreationExpression_computedField_namedOptionalWithDefault() { | |
1311 _checkInstanceCreationOptionalParams(false, true, true); | |
1312 } | |
1313 | |
1314 void | |
1315 test_instanceCreationExpression_computedField_namedOptionalWithoutDefault( ) { | |
1316 _checkInstanceCreationOptionalParams(false, true, false); | |
1317 } | |
1318 | |
1319 void | |
1320 test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() { | |
1321 _checkInstanceCreationOptionalParams(false, false, true); | |
1322 } | |
1323 | |
1324 void | |
1325 test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefaul t() { | |
1326 _checkInstanceCreationOptionalParams(false, false, false); | |
1327 } | |
1328 | |
1329 void test_instanceCreationExpression_computedField_usesConstConstructor() { | |
1330 CompilationUnit compilationUnit = resolveSource(r''' | |
1331 const foo = const A(3); | |
1332 class A { | |
1333 const A(int i) : b = const B(4); | |
1334 final int b; | |
1335 } | |
1336 class B { | |
1337 const B(this.k); | |
1338 final int k; | |
1339 }'''); | |
1340 EvaluationResultImpl result = | |
1341 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1342 Map<String, DartObjectImpl> fieldsOfA = _assertType(result, "A"); | |
1343 expect(fieldsOfA, hasLength(1)); | |
1344 Map<String, DartObjectImpl> fieldsOfB = | |
1345 _assertFieldType(fieldsOfA, "b", "B"); | |
1346 expect(fieldsOfB, hasLength(1)); | |
1347 _assertIntField(fieldsOfB, "k", 4); | |
1348 } | |
1349 | |
1350 void test_instanceCreationExpression_computedField_usesStaticConst() { | |
1351 CompilationUnit compilationUnit = resolveSource(r''' | |
1352 const foo = const A(3); | |
1353 class A { | |
1354 const A(int i) : k = i + B.bar; | |
1355 final int k; | |
1356 } | |
1357 class B { | |
1358 static const bar = 4; | |
1359 }'''); | |
1360 EvaluationResultImpl result = | |
1361 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1362 Map<String, DartObjectImpl> fields = _assertType(result, "A"); | |
1363 expect(fields, hasLength(1)); | |
1364 _assertIntField(fields, "k", 7); | |
1365 } | |
1366 | |
1367 void test_instanceCreationExpression_computedField_usesToplevelConst() { | |
1368 CompilationUnit compilationUnit = resolveSource(r''' | |
1369 const foo = const A(3); | |
1370 const bar = 4; | |
1371 class A { | |
1372 const A(int i) : k = i + bar; | |
1373 final int k; | |
1374 }'''); | |
1375 EvaluationResultImpl result = | |
1376 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1377 Map<String, DartObjectImpl> fields = _assertType(result, "A"); | |
1378 expect(fields, hasLength(1)); | |
1379 _assertIntField(fields, "k", 7); | |
1380 } | |
1381 | |
1382 void test_instanceCreationExpression_explicitSuper() { | |
1383 CompilationUnit compilationUnit = resolveSource(r''' | |
1384 const foo = const B(4, 5); | |
1385 class A { | |
1386 const A(this.x); | |
1387 final int x; | |
1388 } | |
1389 class B extends A { | |
1390 const B(int x, this.y) : super(x * 2); | |
1391 final int y; | |
1392 }'''); | |
1393 EvaluationResultImpl result = | |
1394 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1395 Map<String, DartObjectImpl> fields = _assertType(result, "B"); | |
1396 expect(fields, hasLength(2)); | |
1397 _assertIntField(fields, "y", 5); | |
1398 Map<String, DartObjectImpl> superclassFields = | |
1399 _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A"); | |
1400 expect(superclassFields, hasLength(1)); | |
1401 _assertIntField(superclassFields, "x", 8); | |
1402 } | |
1403 | |
1404 void test_instanceCreationExpression_fieldFormalParameter() { | |
1405 CompilationUnit compilationUnit = resolveSource(r''' | |
1406 const foo = const A(42); | |
1407 class A { | |
1408 int x; | |
1409 const A(this.x) | |
1410 }'''); | |
1411 EvaluationResultImpl result = | |
1412 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1413 Map<String, DartObjectImpl> fields = _assertType(result, "A"); | |
1414 expect(fields, hasLength(1)); | |
1415 _assertIntField(fields, "x", 42); | |
1416 } | |
1417 | |
1418 void | |
1419 test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefa ult() { | |
1420 _checkInstanceCreationOptionalParams(true, true, true); | |
1421 } | |
1422 | |
1423 void | |
1424 test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutD efault() { | |
1425 _checkInstanceCreationOptionalParams(true, true, false); | |
1426 } | |
1427 | |
1428 void | |
1429 test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDe fault() { | |
1430 _checkInstanceCreationOptionalParams(true, false, true); | |
1431 } | |
1432 | |
1433 void | |
1434 test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithou tDefault() { | |
1435 _checkInstanceCreationOptionalParams(true, false, false); | |
1436 } | |
1437 | |
1438 void test_instanceCreationExpression_implicitSuper() { | |
1439 CompilationUnit compilationUnit = resolveSource(r''' | |
1440 const foo = const B(4); | |
1441 class A { | |
1442 const A() : x = 3; | |
1443 final int x; | |
1444 } | |
1445 class B extends A { | |
1446 const B(this.y); | |
1447 final int y; | |
1448 }'''); | |
1449 EvaluationResultImpl result = | |
1450 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1451 Map<String, DartObjectImpl> fields = _assertType(result, "B"); | |
1452 expect(fields, hasLength(2)); | |
1453 _assertIntField(fields, "y", 4); | |
1454 Map<String, DartObjectImpl> superclassFields = | |
1455 _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A"); | |
1456 expect(superclassFields, hasLength(1)); | |
1457 _assertIntField(superclassFields, "x", 3); | |
1458 } | |
1459 | |
1460 void test_instanceCreationExpression_nonFactoryRedirect() { | |
1461 CompilationUnit compilationUnit = resolveSource(r''' | |
1462 const foo = const A.a1(); | |
1463 class A { | |
1464 const A.a1() : this.a2(); | |
1465 const A.a2() : x = 5; | |
1466 final int x; | |
1467 }'''); | |
1468 Map<String, DartObjectImpl> aFields = | |
1469 _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A"); | |
1470 _assertIntField(aFields, 'x', 5); | |
1471 } | |
1472 | |
1473 void test_instanceCreationExpression_nonFactoryRedirect_arg() { | |
1474 CompilationUnit compilationUnit = resolveSource(r''' | |
1475 const foo = const A.a1(1); | |
1476 class A { | |
1477 const A.a1(x) : this.a2(x + 100); | |
1478 const A.a2(x) : y = x + 10; | |
1479 final int y; | |
1480 }'''); | |
1481 Map<String, DartObjectImpl> aFields = | |
1482 _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A"); | |
1483 _assertIntField(aFields, 'y', 111); | |
1484 } | |
1485 | |
1486 void test_instanceCreationExpression_nonFactoryRedirect_cycle() { | |
1487 // It is an error to have a cycle in non-factory redirects; however, we | |
1488 // need to make sure that even if the error occurs, attempting to evaluate | |
1489 // the constant will terminate. | |
1490 CompilationUnit compilationUnit = resolveSource(r''' | |
1491 const foo = const A(); | |
1492 class A { | |
1493 const A() : this.b(); | |
1494 const A.b() : this(); | |
1495 }'''); | |
1496 _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo")); | |
1497 } | |
1498 | |
1499 void test_instanceCreationExpression_nonFactoryRedirect_defaultArg() { | |
1500 CompilationUnit compilationUnit = resolveSource(r''' | |
1501 const foo = const A.a1(); | |
1502 class A { | |
1503 const A.a1() : this.a2(); | |
1504 const A.a2([x = 100]) : y = x + 10; | |
1505 final int y; | |
1506 }'''); | |
1507 Map<String, DartObjectImpl> aFields = | |
1508 _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A"); | |
1509 _assertIntField(aFields, 'y', 110); | |
1510 } | |
1511 | |
1512 void test_instanceCreationExpression_nonFactoryRedirect_toMissing() { | |
1513 CompilationUnit compilationUnit = resolveSource(r''' | |
1514 const foo = const A.a1(); | |
1515 class A { | |
1516 const A.a1() : this.a2(); | |
1517 }'''); | |
1518 // We don't care what value foo evaluates to (since there is a compile | |
1519 // error), but we shouldn't crash, and we should figure | |
1520 // out that it evaluates to an instance of class A. | |
1521 _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A"); | |
1522 } | |
1523 | |
1524 void test_instanceCreationExpression_nonFactoryRedirect_toNonConst() { | |
1525 CompilationUnit compilationUnit = resolveSource(r''' | |
1526 const foo = const A.a1(); | |
1527 class A { | |
1528 const A.a1() : this.a2(); | |
1529 A.a2(); | |
1530 }'''); | |
1531 // We don't care what value foo evaluates to (since there is a compile | |
1532 // error), but we shouldn't crash, and we should figure | |
1533 // out that it evaluates to an instance of class A. | |
1534 _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A"); | |
1535 } | |
1536 | |
1537 void test_instanceCreationExpression_nonFactoryRedirect_unnamed() { | |
1538 CompilationUnit compilationUnit = resolveSource(r''' | |
1539 const foo = const A.a1(); | |
1540 class A { | |
1541 const A.a1() : this(); | |
1542 const A() : x = 5; | |
1543 final int x; | |
1544 }'''); | |
1545 Map<String, DartObjectImpl> aFields = | |
1546 _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A"); | |
1547 _assertIntField(aFields, 'x', 5); | |
1548 } | |
1549 | |
1550 void test_instanceCreationExpression_redirect() { | |
1551 CompilationUnit compilationUnit = resolveSource(r''' | |
1552 const foo = const A(); | |
1553 class A { | |
1554 const factory A() = B; | |
1555 } | |
1556 class B implements A { | |
1557 const B(); | |
1558 }'''); | |
1559 _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "B"); | |
1560 } | |
1561 | |
1562 void test_instanceCreationExpression_redirect_cycle() { | |
1563 // It is an error to have a cycle in factory redirects; however, we need | |
1564 // to make sure that even if the error occurs, attempting to evaluate the | |
1565 // constant will terminate. | |
1566 CompilationUnit compilationUnit = resolveSource(r''' | |
1567 const foo = const A(); | |
1568 class A { | |
1569 const factory A() = A.b; | |
1570 const factory A.b() = A; | |
1571 }'''); | |
1572 _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo")); | |
1573 } | |
1574 | |
1575 void test_instanceCreationExpression_redirect_extern() { | |
1576 CompilationUnit compilationUnit = resolveSource(r''' | |
1577 const foo = const A(); | |
1578 class A { | |
1579 external const factory A(); | |
1580 }'''); | |
1581 _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo")); | |
1582 } | |
1583 | |
1584 void test_instanceCreationExpression_redirect_nonConst() { | |
1585 // It is an error for a const factory constructor redirect to a non-const | |
1586 // constructor; however, we need to make sure that even if the error | |
1587 // attempting to evaluate the constant won't cause a crash. | |
1588 CompilationUnit compilationUnit = resolveSource(r''' | |
1589 const foo = const A(); | |
1590 class A { | |
1591 const factory A() = A.b; | |
1592 A.b(); | |
1593 }'''); | |
1594 _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo")); | |
1595 } | |
1596 | |
1597 void test_instanceCreationExpression_redirectWithTypeParams() { | |
1598 CompilationUnit compilationUnit = resolveSource(r''' | |
1599 class A { | |
1600 const factory A(var a) = B<int>; | |
1601 } | |
1602 | |
1603 class B<T> implements A { | |
1604 final T x; | |
1605 const B(this.x); | |
1606 } | |
1607 | |
1608 const A a = const A(10);'''); | |
1609 EvaluationResultImpl result = | |
1610 _evaluateTopLevelVariable(compilationUnit, "a"); | |
1611 Map<String, DartObjectImpl> fields = _assertType(result, "B<int>"); | |
1612 expect(fields, hasLength(1)); | |
1613 _assertIntField(fields, "x", 10); | |
1614 } | |
1615 | |
1616 void test_instanceCreationExpression_redirectWithTypeSubstitution() { | |
1617 // To evaluate the redirection of A<int>, | |
1618 // A's template argument (T=int) must be substituted | |
1619 // into B's template argument (B<U> where U=T) to get B<int>. | |
1620 CompilationUnit compilationUnit = resolveSource(r''' | |
1621 class A<T> { | |
1622 const factory A(var a) = B<T>; | |
1623 } | |
1624 | |
1625 class B<U> implements A { | |
1626 final U x; | |
1627 const B(this.x); | |
1628 } | |
1629 | |
1630 const A<int> a = const A<int>(10);'''); | |
1631 EvaluationResultImpl result = | |
1632 _evaluateTopLevelVariable(compilationUnit, "a"); | |
1633 Map<String, DartObjectImpl> fields = _assertType(result, "B<int>"); | |
1634 expect(fields, hasLength(1)); | |
1635 _assertIntField(fields, "x", 10); | |
1636 } | |
1637 | |
1638 void test_instanceCreationExpression_symbol() { | |
1639 CompilationUnit compilationUnit = | |
1640 resolveSource("const foo = const Symbol('a');"); | |
1641 EvaluationResultImpl evaluationResult = | |
1642 _evaluateTopLevelVariable(compilationUnit, "foo"); | |
1643 expect(evaluationResult.value, isNotNull); | |
1644 DartObjectImpl value = evaluationResult.value; | |
1645 expect(value.type, typeProvider.symbolType); | |
1646 expect(value.toSymbolValue(), "a"); | |
1647 } | |
1648 | |
1649 void test_instanceCreationExpression_withSupertypeParams_explicit() { | |
1650 _checkInstanceCreation_withSupertypeParams(true); | |
1651 } | |
1652 | |
1653 void test_instanceCreationExpression_withSupertypeParams_implicit() { | |
1654 _checkInstanceCreation_withSupertypeParams(false); | |
1655 } | |
1656 | |
1657 void test_instanceCreationExpression_withTypeParams() { | |
1658 CompilationUnit compilationUnit = resolveSource(r''' | |
1659 class C<E> { | |
1660 const C(); | |
1661 } | |
1662 const c_int = const C<int>(); | |
1663 const c_num = const C<num>();'''); | |
1664 EvaluationResultImpl c_int = | |
1665 _evaluateTopLevelVariable(compilationUnit, "c_int"); | |
1666 _assertType(c_int, "C<int>"); | |
1667 DartObjectImpl c_int_value = c_int.value; | |
1668 EvaluationResultImpl c_num = | |
1669 _evaluateTopLevelVariable(compilationUnit, "c_num"); | |
1670 _assertType(c_num, "C<num>"); | |
1671 DartObjectImpl c_num_value = c_num.value; | |
1672 expect(c_int_value == c_num_value, isFalse); | |
1673 } | |
1674 | |
1675 void test_isValidSymbol() { | |
1676 expect(ConstantEvaluationEngine.isValidPublicSymbol(""), isTrue); | |
1677 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo"), isTrue); | |
1678 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar"), isTrue); | |
1679 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$"), isTrue); | |
1680 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$bar"), isTrue); | |
1681 expect(ConstantEvaluationEngine.isValidPublicSymbol("iff"), isTrue); | |
1682 expect(ConstantEvaluationEngine.isValidPublicSymbol("gif"), isTrue); | |
1683 expect(ConstantEvaluationEngine.isValidPublicSymbol("if\$"), isTrue); | |
1684 expect(ConstantEvaluationEngine.isValidPublicSymbol("\$if"), isTrue); | |
1685 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo="), isTrue); | |
1686 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar="), isTrue); | |
1687 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.+"), isTrue); | |
1688 expect(ConstantEvaluationEngine.isValidPublicSymbol("void"), isTrue); | |
1689 expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo"), isFalse); | |
1690 expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo.bar"), isFalse); | |
1691 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo._bar"), isFalse); | |
1692 expect(ConstantEvaluationEngine.isValidPublicSymbol("if"), isFalse); | |
1693 expect(ConstantEvaluationEngine.isValidPublicSymbol("if.foo"), isFalse); | |
1694 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.if"), isFalse); | |
1695 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo=.bar"), isFalse); | |
1696 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo."), isFalse); | |
1697 expect(ConstantEvaluationEngine.isValidPublicSymbol("+.foo"), isFalse); | |
1698 expect(ConstantEvaluationEngine.isValidPublicSymbol("void.foo"), isFalse); | |
1699 expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.void"), isFalse); | |
1700 } | |
1701 | |
1702 void test_length_of_improperly_typed_string_expression() { | |
1703 // Since type annotations are ignored in unchecked mode, the improper | |
1704 // types on s1 and s2 shouldn't prevent us from evaluating i to | |
1705 // 'alpha'.length. | |
1706 CompilationUnit compilationUnit = resolveSource(''' | |
1707 const int s1 = 'alpha'; | |
1708 const int s2 = 'beta'; | |
1709 const int i = (true ? s1 : s2).length; | |
1710 '''); | |
1711 ConstTopLevelVariableElementImpl element = | |
1712 findTopLevelDeclaration(compilationUnit, 'i').element; | |
1713 EvaluationResultImpl result = element.evaluationResult; | |
1714 expect(_assertValidInt(result), 5); | |
1715 } | |
1716 | |
1717 void test_length_of_improperly_typed_string_identifier() { | |
1718 // Since type annotations are ignored in unchecked mode, the improper type | |
1719 // on s shouldn't prevent us from evaluating i to 'alpha'.length. | |
1720 CompilationUnit compilationUnit = resolveSource(''' | |
1721 const int s = 'alpha'; | |
1722 const int i = s.length; | |
1723 '''); | |
1724 ConstTopLevelVariableElementImpl element = | |
1725 findTopLevelDeclaration(compilationUnit, 'i').element; | |
1726 EvaluationResultImpl result = element.evaluationResult; | |
1727 expect(_assertValidInt(result), 5); | |
1728 } | |
1729 | |
1730 void test_non_static_const_initialized_at_declaration() { | |
1731 // Even though non-static consts are not allowed by the language, we need | |
1732 // to handle them for error recovery purposes. | |
1733 CompilationUnit compilationUnit = resolveSource(''' | |
1734 class A { | |
1735 const int i = 123; | |
1736 const A(); | |
1737 } | |
1738 | |
1739 const A a = const A(); | |
1740 '''); | |
1741 EvaluationResultImpl result = | |
1742 _evaluateTopLevelVariable(compilationUnit, 'a'); | |
1743 Map<String, DartObjectImpl> fields = _assertType(result, "A"); | |
1744 expect(fields, hasLength(1)); | |
1745 _assertIntField(fields, "i", 123); | |
1746 } | |
1747 | |
1748 void test_symbolLiteral_void() { | |
1749 CompilationUnit compilationUnit = | |
1750 resolveSource("const voidSymbol = #void;"); | |
1751 VariableDeclaration voidSymbol = | |
1752 findTopLevelDeclaration(compilationUnit, "voidSymbol"); | |
1753 EvaluationResultImpl voidSymbolResult = | |
1754 (voidSymbol.element as VariableElementImpl).evaluationResult; | |
1755 DartObjectImpl value = voidSymbolResult.value; | |
1756 expect(value.type, typeProvider.symbolType); | |
1757 expect(value.toSymbolValue(), "void"); | |
1758 } | |
1759 | |
1760 Map<String, DartObjectImpl> _assertFieldType( | |
1761 Map<String, DartObjectImpl> fields, | |
1762 String fieldName, | |
1763 String expectedType) { | |
1764 DartObjectImpl field = fields[fieldName]; | |
1765 expect(field.type.displayName, expectedType); | |
1766 return field.fields; | |
1767 } | |
1768 | |
1769 void _assertIntField( | |
1770 Map<String, DartObjectImpl> fields, String fieldName, int expectedValue) { | |
1771 DartObjectImpl field = fields[fieldName]; | |
1772 expect(field.type.name, "int"); | |
1773 expect(field.toIntValue(), expectedValue); | |
1774 } | |
1775 | |
1776 void _assertNullField(Map<String, DartObjectImpl> fields, String fieldName) { | |
1777 DartObjectImpl field = fields[fieldName]; | |
1778 expect(field.isNull, isTrue); | |
1779 } | |
1780 | |
1781 void _assertProperDependencies(String sourceText, | |
1782 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { | |
1783 Source source = addSource(sourceText); | |
1784 LibraryElement element = resolve2(source); | |
1785 CompilationUnit unit = | |
1786 analysisContext.resolveCompilationUnit(source, element); | |
1787 expect(unit, isNotNull); | |
1788 ConstantValueComputer computer = _makeConstantValueComputer(); | |
1789 computer.add(unit, source, source); | |
1790 computer.computeValues(); | |
1791 assertErrors(source, expectedErrorCodes); | |
1792 } | |
1793 | |
1794 Map<String, DartObjectImpl> _assertType( | |
1795 EvaluationResultImpl result, String typeName) { | |
1796 expect(result.value, isNotNull); | |
1797 DartObjectImpl value = result.value; | |
1798 expect(value.type.displayName, typeName); | |
1799 return value.fields; | |
1800 } | |
1801 | |
1802 bool _assertValidBool(EvaluationResultImpl result) { | |
1803 expect(result.value, isNotNull); | |
1804 DartObjectImpl value = result.value; | |
1805 expect(value.type, typeProvider.boolType); | |
1806 bool boolValue = value.toBoolValue(); | |
1807 expect(boolValue, isNotNull); | |
1808 return boolValue; | |
1809 } | |
1810 | |
1811 int _assertValidInt(EvaluationResultImpl result) { | |
1812 expect(result.value, isNotNull); | |
1813 DartObjectImpl value = result.value; | |
1814 expect(value.type, typeProvider.intType); | |
1815 return value.toIntValue(); | |
1816 } | |
1817 | |
1818 void _assertValidNull(EvaluationResultImpl result) { | |
1819 expect(result.value, isNotNull); | |
1820 DartObjectImpl value = result.value; | |
1821 expect(value.type, typeProvider.nullType); | |
1822 } | |
1823 | |
1824 String _assertValidString(EvaluationResultImpl result) { | |
1825 expect(result.value, isNotNull); | |
1826 DartObjectImpl value = result.value; | |
1827 expect(value.type, typeProvider.stringType); | |
1828 return value.toStringValue(); | |
1829 } | |
1830 | |
1831 void _assertValidUnknown(EvaluationResultImpl result) { | |
1832 expect(result.value, isNotNull); | |
1833 DartObjectImpl value = result.value; | |
1834 expect(value.isUnknown, isTrue); | |
1835 } | |
1836 | |
1837 EvaluationResultImpl _check_fromEnvironment_bool( | |
1838 String valueInEnvironment, String defaultExpr) { | |
1839 String envVarName = "x"; | |
1840 String varName = "foo"; | |
1841 if (valueInEnvironment != null) { | |
1842 analysisContext2.declaredVariables.define(envVarName, valueInEnvironment); | |
1843 } | |
1844 String defaultArg = | |
1845 defaultExpr == null ? "" : ", defaultValue: $defaultExpr"; | |
1846 CompilationUnit compilationUnit = resolveSource( | |
1847 "const $varName = const bool.fromEnvironment('$envVarName'$defaultArg);" ); | |
1848 return _evaluateTopLevelVariable(compilationUnit, varName); | |
1849 } | |
1850 | |
1851 EvaluationResultImpl _check_fromEnvironment_int( | |
1852 String valueInEnvironment, String defaultExpr) { | |
1853 String envVarName = "x"; | |
1854 String varName = "foo"; | |
1855 if (valueInEnvironment != null) { | |
1856 analysisContext2.declaredVariables.define(envVarName, valueInEnvironment); | |
1857 } | |
1858 String defaultArg = | |
1859 defaultExpr == null ? "" : ", defaultValue: $defaultExpr"; | |
1860 CompilationUnit compilationUnit = resolveSource( | |
1861 "const $varName = const int.fromEnvironment('$envVarName'$defaultArg);") ; | |
1862 return _evaluateTopLevelVariable(compilationUnit, varName); | |
1863 } | |
1864 | |
1865 EvaluationResultImpl _check_fromEnvironment_string( | |
1866 String valueInEnvironment, String defaultExpr) { | |
1867 String envVarName = "x"; | |
1868 String varName = "foo"; | |
1869 if (valueInEnvironment != null) { | |
1870 analysisContext2.declaredVariables.define(envVarName, valueInEnvironment); | |
1871 } | |
1872 String defaultArg = | |
1873 defaultExpr == null ? "" : ", defaultValue: $defaultExpr"; | |
1874 CompilationUnit compilationUnit = resolveSource( | |
1875 "const $varName = const String.fromEnvironment('$envVarName'$defaultArg) ;"); | |
1876 return _evaluateTopLevelVariable(compilationUnit, varName); | |
1877 } | |
1878 | |
1879 void _checkInstanceCreation_withSupertypeParams(bool isExplicit) { | |
1880 String superCall = isExplicit ? " : super()" : ""; | |
1881 CompilationUnit compilationUnit = resolveSource(""" | |
1882 class A<T> { | |
1883 const A(); | |
1884 } | |
1885 class B<T, U> extends A<T> { | |
1886 const B()$superCall; | |
1887 } | |
1888 class C<T, U> extends A<U> { | |
1889 const C()$superCall; | |
1890 } | |
1891 const b_int_num = const B<int, num>(); | |
1892 const c_int_num = const C<int, num>();"""); | |
1893 EvaluationResultImpl b_int_num = | |
1894 _evaluateTopLevelVariable(compilationUnit, "b_int_num"); | |
1895 Map<String, DartObjectImpl> b_int_num_fields = | |
1896 _assertType(b_int_num, "B<int, num>"); | |
1897 _assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>"); | |
1898 EvaluationResultImpl c_int_num = | |
1899 _evaluateTopLevelVariable(compilationUnit, "c_int_num"); | |
1900 Map<String, DartObjectImpl> c_int_num_fields = | |
1901 _assertType(c_int_num, "C<int, num>"); | |
1902 _assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>"); | |
1903 } | |
1904 | |
1905 void _checkInstanceCreationOptionalParams( | |
1906 bool isFieldFormal, bool isNamed, bool hasDefault) { | |
1907 String fieldName = "j"; | |
1908 String paramName = isFieldFormal ? fieldName : "i"; | |
1909 String formalParam = | |
1910 "${isFieldFormal ? "this." : "int "}$paramName${hasDefault ? " = 3" : "" }"; | |
1911 CompilationUnit compilationUnit = resolveSource(""" | |
1912 const x = const A(); | |
1913 const y = const A(${isNamed ? '$paramName: ' : ''}10); | |
1914 class A { | |
1915 const A(${isNamed ? "{$formalParam}" : "[$formalParam]"})${isFieldFormal ? "" : " : $fieldName = $paramName"}; | |
1916 final int $fieldName; | |
1917 }"""); | |
1918 EvaluationResultImpl x = _evaluateTopLevelVariable(compilationUnit, "x"); | |
1919 Map<String, DartObjectImpl> fieldsOfX = _assertType(x, "A"); | |
1920 expect(fieldsOfX, hasLength(1)); | |
1921 if (hasDefault) { | |
1922 _assertIntField(fieldsOfX, fieldName, 3); | |
1923 } else { | |
1924 _assertNullField(fieldsOfX, fieldName); | |
1925 } | |
1926 EvaluationResultImpl y = _evaluateTopLevelVariable(compilationUnit, "y"); | |
1927 Map<String, DartObjectImpl> fieldsOfY = _assertType(y, "A"); | |
1928 expect(fieldsOfY, hasLength(1)); | |
1929 _assertIntField(fieldsOfY, fieldName, 10); | |
1930 } | |
1931 | |
1932 /** | |
1933 * Search [compilationUnit] for a class named [className], containing a | |
1934 * method [methodName], with exactly one annotation. Return the constant | |
1935 * value of the annotation. | |
1936 */ | |
1937 EvaluationResultImpl _evaluateAnnotation( | |
1938 CompilationUnit compilationUnit, String className, String memberName) { | |
1939 for (CompilationUnitMember member in compilationUnit.declarations) { | |
1940 if (member is ClassDeclaration && member.name.name == className) { | |
1941 for (ClassMember classMember in member.members) { | |
1942 if (classMember is MethodDeclaration && | |
1943 classMember.name.name == memberName) { | |
1944 expect(classMember.metadata, hasLength(1)); | |
1945 ElementAnnotationImpl elementAnnotation = | |
1946 classMember.metadata[0].elementAnnotation; | |
1947 return elementAnnotation.evaluationResult; | |
1948 } | |
1949 } | |
1950 } | |
1951 } | |
1952 fail('Class member not found'); | |
1953 return null; | |
1954 } | |
1955 | |
1956 EvaluationResultImpl _evaluateTopLevelVariable( | |
1957 CompilationUnit compilationUnit, String name) { | |
1958 VariableDeclaration varDecl = | |
1959 findTopLevelDeclaration(compilationUnit, name); | |
1960 ConstTopLevelVariableElementImpl varElement = varDecl.element; | |
1961 return varElement.evaluationResult; | |
1962 } | |
1963 | |
1964 ConstantValueComputer _makeConstantValueComputer() { | |
1965 ConstantEvaluationValidator_ForTest validator = | |
1966 new ConstantEvaluationValidator_ForTest(); | |
1967 validator.computer = new ConstantValueComputer( | |
1968 analysisContext2, | |
1969 analysisContext2.typeProvider, | |
1970 analysisContext2.declaredVariables, | |
1971 validator, | |
1972 analysisContext2.typeSystem); | |
1973 return validator.computer; | |
1974 } | |
1975 | |
1976 void _validate(bool shouldBeValid, VariableDeclarationList declarationList) { | |
1977 for (VariableDeclaration declaration in declarationList.variables) { | |
1978 VariableElementImpl element = declaration.element as VariableElementImpl; | |
1979 expect(element, isNotNull); | |
1980 EvaluationResultImpl result = element.evaluationResult; | |
1981 if (shouldBeValid) { | |
1982 expect(result.value, isNotNull); | |
1983 } else { | |
1984 expect(result.value, isNull); | |
1985 } | |
1986 } | |
1987 } | |
1988 } | |
1989 | |
1990 @reflectiveTest | |
1991 class ConstantVisitorTest extends ResolverTestCase { | |
1992 void test_visitBinaryExpression_questionQuestion_notNull_notNull() { | |
1993 Expression left = AstFactory.string2('a'); | |
1994 Expression right = AstFactory.string2('b'); | |
1995 Expression expression = | |
1996 AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right); | |
1997 | |
1998 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
1999 ErrorReporter errorReporter = | |
2000 new ErrorReporter(errorListener, _dummySource()); | |
2001 DartObjectImpl result = _evaluate(expression, errorReporter); | |
2002 expect(result, isNotNull); | |
2003 expect(result.isNull, isFalse); | |
2004 expect(result.toStringValue(), 'a'); | |
2005 errorListener.assertNoErrors(); | |
2006 } | |
2007 | |
2008 void test_visitBinaryExpression_questionQuestion_null_notNull() { | |
2009 Expression left = AstFactory.nullLiteral(); | |
2010 Expression right = AstFactory.string2('b'); | |
2011 Expression expression = | |
2012 AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right); | |
2013 | |
2014 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2015 ErrorReporter errorReporter = | |
2016 new ErrorReporter(errorListener, _dummySource()); | |
2017 DartObjectImpl result = _evaluate(expression, errorReporter); | |
2018 expect(result, isNotNull); | |
2019 expect(result.isNull, isFalse); | |
2020 expect(result.toStringValue(), 'b'); | |
2021 errorListener.assertNoErrors(); | |
2022 } | |
2023 | |
2024 void test_visitBinaryExpression_questionQuestion_null_null() { | |
2025 Expression left = AstFactory.nullLiteral(); | |
2026 Expression right = AstFactory.nullLiteral(); | |
2027 Expression expression = | |
2028 AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right); | |
2029 | |
2030 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2031 ErrorReporter errorReporter = | |
2032 new ErrorReporter(errorListener, _dummySource()); | |
2033 DartObjectImpl result = _evaluate(expression, errorReporter); | |
2034 expect(result, isNotNull); | |
2035 expect(result.isNull, isTrue); | |
2036 errorListener.assertNoErrors(); | |
2037 } | |
2038 | |
2039 void test_visitConditionalExpression_false() { | |
2040 Expression thenExpression = AstFactory.integer(1); | |
2041 Expression elseExpression = AstFactory.integer(0); | |
2042 ConditionalExpression expression = AstFactory.conditionalExpression( | |
2043 AstFactory.booleanLiteral(false), thenExpression, elseExpression); | |
2044 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2045 ErrorReporter errorReporter = | |
2046 new ErrorReporter(errorListener, _dummySource()); | |
2047 _assertValue(0, _evaluate(expression, errorReporter)); | |
2048 errorListener.assertNoErrors(); | |
2049 } | |
2050 | |
2051 void test_visitConditionalExpression_nonBooleanCondition() { | |
2052 Expression thenExpression = AstFactory.integer(1); | |
2053 Expression elseExpression = AstFactory.integer(0); | |
2054 NullLiteral conditionExpression = AstFactory.nullLiteral(); | |
2055 ConditionalExpression expression = AstFactory.conditionalExpression( | |
2056 conditionExpression, thenExpression, elseExpression); | |
2057 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2058 ErrorReporter errorReporter = | |
2059 new ErrorReporter(errorListener, _dummySource()); | |
2060 DartObjectImpl result = _evaluate(expression, errorReporter); | |
2061 expect(result, isNull); | |
2062 errorListener | |
2063 .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]); | |
2064 } | |
2065 | |
2066 void test_visitConditionalExpression_nonConstantElse() { | |
2067 Expression thenExpression = AstFactory.integer(1); | |
2068 Expression elseExpression = AstFactory.identifier3("x"); | |
2069 ConditionalExpression expression = AstFactory.conditionalExpression( | |
2070 AstFactory.booleanLiteral(true), thenExpression, elseExpression); | |
2071 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2072 ErrorReporter errorReporter = | |
2073 new ErrorReporter(errorListener, _dummySource()); | |
2074 DartObjectImpl result = _evaluate(expression, errorReporter); | |
2075 expect(result, isNull); | |
2076 errorListener | |
2077 .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]); | |
2078 } | |
2079 | |
2080 void test_visitConditionalExpression_nonConstantThen() { | |
2081 Expression thenExpression = AstFactory.identifier3("x"); | |
2082 Expression elseExpression = AstFactory.integer(0); | |
2083 ConditionalExpression expression = AstFactory.conditionalExpression( | |
2084 AstFactory.booleanLiteral(true), thenExpression, elseExpression); | |
2085 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2086 ErrorReporter errorReporter = | |
2087 new ErrorReporter(errorListener, _dummySource()); | |
2088 DartObjectImpl result = _evaluate(expression, errorReporter); | |
2089 expect(result, isNull); | |
2090 errorListener | |
2091 .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]); | |
2092 } | |
2093 | |
2094 void test_visitConditionalExpression_true() { | |
2095 Expression thenExpression = AstFactory.integer(1); | |
2096 Expression elseExpression = AstFactory.integer(0); | |
2097 ConditionalExpression expression = AstFactory.conditionalExpression( | |
2098 AstFactory.booleanLiteral(true), thenExpression, elseExpression); | |
2099 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2100 ErrorReporter errorReporter = | |
2101 new ErrorReporter(errorListener, _dummySource()); | |
2102 _assertValue(1, _evaluate(expression, errorReporter)); | |
2103 errorListener.assertNoErrors(); | |
2104 } | |
2105 | |
2106 void test_visitSimpleIdentifier_className() { | |
2107 CompilationUnit compilationUnit = resolveSource(''' | |
2108 const a = C; | |
2109 class C {} | |
2110 '''); | |
2111 DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null); | |
2112 expect(result.type, typeProvider.typeType); | |
2113 expect(result.toTypeValue().name, 'C'); | |
2114 } | |
2115 | |
2116 void test_visitSimpleIdentifier_dynamic() { | |
2117 CompilationUnit compilationUnit = resolveSource(''' | |
2118 const a = dynamic; | |
2119 '''); | |
2120 DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null); | |
2121 expect(result.type, typeProvider.typeType); | |
2122 expect(result.toTypeValue(), typeProvider.dynamicType); | |
2123 } | |
2124 | |
2125 void test_visitSimpleIdentifier_inEnvironment() { | |
2126 CompilationUnit compilationUnit = resolveSource(r''' | |
2127 const a = b; | |
2128 const b = 3;'''); | |
2129 Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>(); | |
2130 DartObjectImpl six = | |
2131 new DartObjectImpl(typeProvider.intType, new IntState(6)); | |
2132 environment["b"] = six; | |
2133 _assertValue(6, _evaluateConstant(compilationUnit, "a", environment)); | |
2134 } | |
2135 | |
2136 void test_visitSimpleIdentifier_notInEnvironment() { | |
2137 CompilationUnit compilationUnit = resolveSource(r''' | |
2138 const a = b; | |
2139 const b = 3;'''); | |
2140 Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>(); | |
2141 DartObjectImpl six = | |
2142 new DartObjectImpl(typeProvider.intType, new IntState(6)); | |
2143 environment["c"] = six; | |
2144 _assertValue(3, _evaluateConstant(compilationUnit, "a", environment)); | |
2145 } | |
2146 | |
2147 void test_visitSimpleIdentifier_withoutEnvironment() { | |
2148 CompilationUnit compilationUnit = resolveSource(r''' | |
2149 const a = b; | |
2150 const b = 3;'''); | |
2151 _assertValue(3, _evaluateConstant(compilationUnit, "a", null)); | |
2152 } | |
2153 | |
2154 void _assertValue(int expectedValue, DartObjectImpl result) { | |
2155 expect(result, isNotNull); | |
2156 expect(result.type.name, "int"); | |
2157 expect(result.toIntValue(), expectedValue); | |
2158 } | |
2159 | |
2160 NonExistingSource _dummySource() { | |
2161 String path = '/test.dart'; | |
2162 return new NonExistingSource(path, toUri(path), UriKind.FILE_URI); | |
2163 } | |
2164 | |
2165 DartObjectImpl _evaluate(Expression expression, ErrorReporter errorReporter) { | |
2166 return expression.accept(new ConstantVisitor( | |
2167 new ConstantEvaluationEngine( | |
2168 new TestTypeProvider(), new DeclaredVariables(), | |
2169 typeSystem: new TypeSystemImpl()), | |
2170 errorReporter)); | |
2171 } | |
2172 | |
2173 DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name, | |
2174 Map<String, DartObjectImpl> lexicalEnvironment) { | |
2175 Source source = compilationUnit.element.source; | |
2176 Expression expression = | |
2177 findTopLevelConstantExpression(compilationUnit, name); | |
2178 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
2179 ErrorReporter errorReporter = new ErrorReporter(errorListener, source); | |
2180 DartObjectImpl result = expression.accept(new ConstantVisitor( | |
2181 new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(), | |
2182 typeSystem: typeSystem), | |
2183 errorReporter, | |
2184 lexicalEnvironment: lexicalEnvironment)); | |
2185 errorListener.assertNoErrors(); | |
2186 return result; | |
2187 } | |
2188 } | |
2189 | |
2190 class TestAnalysisContext_ConstantFinderTest extends TestAnalysisContext { | |
Brian Wilkerson
2016/01/22 15:17:01
Perhaps rename to something like ConstantFinderTes
skybrian
2016/01/22 20:46:32
Went with _TestAnalysisContext.
| |
2191 bool invoked = false; | |
Brian Wilkerson
2016/01/22 15:17:01
Looks like dead code.
skybrian
2016/01/22 20:46:32
Removed.
| |
2192 TestAnalysisContext_ConstantFinderTest(); | |
2193 | |
2194 @override | |
2195 InternalAnalysisContext getContextFor(Source source) { | |
2196 return this; | |
2197 } | |
2198 } | |
OLD | NEW |