Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: pkg/analyzer/lib/src/generated/constant.dart

Issue 1129563002: Create a class for evaluating const instance creation expressions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/incremental_resolver.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library engine.constant; 8 library engine.constant;
9 9
10 import 'dart:collection'; 10 import 'dart:collection';
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 SuperConstructorInvocation visitSuperConstructorInvocation( 179 SuperConstructorInvocation visitSuperConstructorInvocation(
180 SuperConstructorInvocation node) { 180 SuperConstructorInvocation node) {
181 SuperConstructorInvocation invocation = 181 SuperConstructorInvocation invocation =
182 super.visitSuperConstructorInvocation(node); 182 super.visitSuperConstructorInvocation(node);
183 invocation.staticElement = node.staticElement; 183 invocation.staticElement = node.staticElement;
184 return invocation; 184 return invocation;
185 } 185 }
186 } 186 }
187 187
188 /** 188 /**
189 * Helper class encapsulating the methods for evaluating constant instance
190 * constant instance creation expressions.
191 */
192 class ConstantEvaluationEngine {
193 /**
194 * Parameter to "fromEnvironment" methods that denotes the default value.
195 */
196 static String _DEFAULT_VALUE_PARAM = "defaultValue";
197
198 /**
199 * Source of RegExp matching any public identifier.
200 * From sdk/lib/internal/symbol.dart.
201 */
202 static String _PUBLIC_IDENTIFIER_RE =
203 "(?!${ConstantValueComputer._RESERVED_WORD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$ ]*";
204
205 /**
206 * RegExp that validates a non-empty non-private symbol.
207 * From sdk/lib/internal/symbol.dart.
208 */
209 static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
210 "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$ |[.](?!\$)))+?\$");
211
212 /**
213 * The type provider used to access the known types.
214 */
215 final TypeProvider typeProvider;
216
217 /**
218 * The set of variables declared on the command line using '-D'.
219 */
220 final DeclaredVariables _declaredVariables;
221
222 /**
223 * Validator used to verify correct dependency analysis when running unit
224 * tests.
225 */
226 final ConstantEvaluationValidator validator;
227
228 /**
229 * Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider]
230 * is used to access known types. [_declaredVariables] is the set of
231 * variables declared on the command line using '-D'. The [validator], if
232 * given, is used to verify correct dependency analysis when running unit
233 * tests.
234 */
235 ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
236 {ConstantEvaluationValidator validator})
237 : validator = validator != null
238 ? validator
239 : new ConstantEvaluationValidator_ForProduction();
240
241 /**
242 * Check that the arguments to a call to fromEnvironment() are correct. The
243 * [arguments] are the AST nodes of the arguments. The [argumentValues] are
244 * the values of the unnamed arguments. The [namedArgumentValues] are the
245 * values of the named arguments. The [expectedDefaultValueType] is the
246 * allowed type of the "defaultValue" parameter (if present). Note:
247 * "defaultValue" is always allowed to be null. Return `true` if the arguments
248 * are correct, `false` if there is an error.
249 */
250 bool checkFromEnvironmentArguments(NodeList<Expression> arguments,
251 List<DartObjectImpl> argumentValues,
252 HashMap<String, DartObjectImpl> namedArgumentValues,
253 InterfaceType expectedDefaultValueType) {
254 int argumentCount = arguments.length;
255 if (argumentCount < 1 || argumentCount > 2) {
256 return false;
257 }
258 if (arguments[0] is NamedExpression) {
259 return false;
260 }
261 if (!identical(argumentValues[0].type, typeProvider.stringType)) {
262 return false;
263 }
264 if (argumentCount == 2) {
265 if (arguments[1] is! NamedExpression) {
266 return false;
267 }
268 if (!((arguments[1] as NamedExpression).name.label.name ==
269 _DEFAULT_VALUE_PARAM)) {
270 return false;
271 }
272 ParameterizedType defaultValueType =
273 namedArgumentValues[_DEFAULT_VALUE_PARAM].type;
274 if (!(identical(defaultValueType, expectedDefaultValueType) ||
275 identical(defaultValueType, typeProvider.nullType))) {
276 return false;
277 }
278 }
279 return true;
280 }
281
282 /**
283 * Check that the arguments to a call to Symbol() are correct. The [arguments]
284 * are the AST nodes of the arguments. The [argumentValues] are the values of
285 * the unnamed arguments. The [namedArgumentValues] are the values of the
286 * named arguments. Return `true` if the arguments are correct, `false` if
287 * there is an error.
288 */
289 bool checkSymbolArguments(NodeList<Expression> arguments,
290 List<DartObjectImpl> argumentValues,
291 HashMap<String, DartObjectImpl> namedArgumentValues) {
292 if (arguments.length != 1) {
293 return false;
294 }
295 if (arguments[0] is NamedExpression) {
296 return false;
297 }
298 if (!identical(argumentValues[0].type, typeProvider.stringType)) {
299 return false;
300 }
301 String name = argumentValues[0].stringValue;
302 return isValidPublicSymbol(name);
303 }
304
305 /**
306 * Evaluate a call to fromEnvironment() on the bool, int, or String class. The
307 * [environmentValue] is the value fetched from the environment. The
308 * [builtInDefaultValue] is the value that should be used as the default if no
309 * "defaultValue" argument appears in [namedArgumentValues]. The
310 * [namedArgumentValues] are the values of the named parameters passed to
311 * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
312 * evaluated result.
313 */
314 DartObjectImpl computeValueFromEnvironment(DartObject environmentValue,
315 DartObjectImpl builtInDefaultValue,
316 HashMap<String, DartObjectImpl> namedArgumentValues) {
317 DartObjectImpl value = environmentValue as DartObjectImpl;
318 if (value.isUnknown || value.isNull) {
319 // The name either doesn't exist in the environment or we couldn't parse
320 // the corresponding value.
321 // If the code supplied an explicit default, use it.
322 if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
323 value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
324 } else if (value.isNull) {
325 // The code didn't supply an explicit default.
326 // The name exists in the environment but we couldn't parse the
327 // corresponding value.
328 // So use the built-in default value, because this is what the VM does.
329 value = builtInDefaultValue;
330 } else {
331 // The code didn't supply an explicit default.
332 // The name doesn't exist in the environment.
333 // The VM would use the built-in default value, but we don't want to do
334 // that for analysis because it's likely to lead to cascading errors.
335 // So just leave [value] in the unknown state.
336 }
337 }
338 return value;
339 }
340
341 DartObjectImpl evaluateConstructorCall(AstNode node,
342 NodeList<Expression> arguments, ConstructorElement constructor,
343 ConstantVisitor constantVisitor, ErrorReporter errorReporter) {
344 if (!_getConstructorBase(constructor).isCycleFree) {
345 // It's not safe to evaluate this constructor, so bail out.
346 // TODO(paulberry): ensure that a reasonable error message is produced
347 // in this case, as well as other cases involving constant expression
348 // circularities (e.g. "compile-time constant expression depends on
349 // itself")
350 return new DartObjectImpl.validWithUnknownValue(constructor.returnType);
351 }
352 int argumentCount = arguments.length;
353 List<DartObjectImpl> argumentValues =
354 new List<DartObjectImpl>(argumentCount);
355 List<Expression> argumentNodes = new List<Expression>(argumentCount);
356 HashMap<String, DartObjectImpl> namedArgumentValues =
357 new HashMap<String, DartObjectImpl>();
358 HashMap<String, NamedExpression> namedArgumentNodes =
359 new HashMap<String, NamedExpression>();
360 for (int i = 0; i < argumentCount; i++) {
361 Expression argument = arguments[i];
362 if (argument is NamedExpression) {
363 String name = argument.name.label.name;
364 namedArgumentValues[name] =
365 constantVisitor._valueOf(argument.expression);
366 namedArgumentNodes[name] = argument;
367 argumentValues[i] = typeProvider.nullObject;
368 } else {
369 argumentValues[i] = constantVisitor._valueOf(argument);
370 argumentNodes[i] = argument;
371 }
372 }
373 constructor = followConstantRedirectionChain(constructor);
374 InterfaceType definingClass = constructor.returnType as InterfaceType;
375 if (constructor.isFactory) {
376 // We couldn't find a non-factory constructor.
377 // See if it's because we reached an external const factory constructor
378 // that we can emulate.
379 if (constructor.name == "fromEnvironment") {
380 if (!checkFromEnvironmentArguments(
381 arguments, argumentValues, namedArgumentValues, definingClass)) {
382 errorReporter.reportErrorForNode(
383 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
384 return null;
385 }
386 String variableName =
387 argumentCount < 1 ? null : argumentValues[0].stringValue;
388 if (identical(definingClass, typeProvider.boolType)) {
389 DartObject valueFromEnvironment;
390 valueFromEnvironment =
391 _declaredVariables.getBool(typeProvider, variableName);
392 return computeValueFromEnvironment(valueFromEnvironment,
393 new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
394 namedArgumentValues);
395 } else if (identical(definingClass, typeProvider.intType)) {
396 DartObject valueFromEnvironment;
397 valueFromEnvironment =
398 _declaredVariables.getInt(typeProvider, variableName);
399 return computeValueFromEnvironment(valueFromEnvironment,
400 new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
401 namedArgumentValues);
402 } else if (identical(definingClass, typeProvider.stringType)) {
403 DartObject valueFromEnvironment;
404 valueFromEnvironment =
405 _declaredVariables.getString(typeProvider, variableName);
406 return computeValueFromEnvironment(valueFromEnvironment,
407 new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
408 namedArgumentValues);
409 }
410 } else if (constructor.name == "" &&
411 identical(definingClass, typeProvider.symbolType) &&
412 argumentCount == 1) {
413 if (!checkSymbolArguments(
414 arguments, argumentValues, namedArgumentValues)) {
415 errorReporter.reportErrorForNode(
416 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
417 return null;
418 }
419 String argumentValue = argumentValues[0].stringValue;
420 return new DartObjectImpl(
421 definingClass, new SymbolState(argumentValue));
422 }
423 // Either it's an external const factory constructor that we can't
424 // emulate, or an error occurred (a cycle, or a const constructor trying
425 // to delegate to a non-const constructor).
426 // In the former case, the best we can do is consider it an unknown value.
427 // In the latter case, the error has already been reported, so considering
428 // it an unknown value will suppress further errors.
429 return new DartObjectImpl.validWithUnknownValue(definingClass);
430 }
431 validator.beforeGetConstantInitializers(constructor);
432 ConstructorElementImpl constructorBase = _getConstructorBase(constructor);
433 List<ConstructorInitializer> initializers =
434 constructorBase.constantInitializers;
435 if (initializers == null) {
436 // This can happen in some cases where there are compile errors in the
437 // code being analyzed (for example if the code is trying to create a
438 // const instance using a non-const constructor, or the node we're
439 // visiting is involved in a cycle). The error has already been reported,
440 // so consider it an unknown value to suppress further errors.
441 return new DartObjectImpl.validWithUnknownValue(definingClass);
442 }
443 HashMap<String, DartObjectImpl> fieldMap =
444 new HashMap<String, DartObjectImpl>();
445 // Start with final fields that are initialized at their declaration site.
446 for (FieldElement field in constructor.enclosingElement.fields) {
447 if ((field.isFinal || field.isConst) &&
448 !field.isStatic &&
449 field is ConstFieldElementImpl) {
450 validator.beforeGetFieldEvaluationResult(field);
451 EvaluationResultImpl evaluationResult = field.evaluationResult;
452 DartType fieldType =
453 FieldMember.from(field, constructor.returnType).type;
454 DartObjectImpl fieldValue = evaluationResult.value;
455 if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
456 errorReporter.reportErrorForNode(
457 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMA TCH,
458 node, [fieldValue.type, field.name, fieldType]);
459 }
460 fieldMap[field.name] = evaluationResult.value;
461 }
462 }
463 // Now evaluate the constructor declaration.
464 HashMap<String, DartObjectImpl> parameterMap =
465 new HashMap<String, DartObjectImpl>();
466 List<ParameterElement> parameters = constructor.parameters;
467 int parameterCount = parameters.length;
468 for (int i = 0; i < parameterCount; i++) {
469 ParameterElement parameter = parameters[i];
470 ParameterElement baseParameter = parameter;
471 while (baseParameter is ParameterMember) {
472 baseParameter = (baseParameter as ParameterMember).baseElement;
473 }
474 DartObjectImpl argumentValue = null;
475 AstNode errorTarget = null;
476 if (baseParameter.parameterKind == ParameterKind.NAMED) {
477 argumentValue = namedArgumentValues[baseParameter.name];
478 errorTarget = namedArgumentNodes[baseParameter.name];
479 } else if (i < argumentCount) {
480 argumentValue = argumentValues[i];
481 errorTarget = argumentNodes[i];
482 }
483 if (errorTarget == null) {
484 // No argument node that we can direct error messages to, because we
485 // are handling an optional parameter that wasn't specified. So just
486 // direct error messages to the constructor call.
487 errorTarget = node;
488 }
489 if (argumentValue == null && baseParameter is ParameterElementImpl) {
490 // The parameter is an optional positional parameter for which no value
491 // was provided, so use the default value.
492 validator.beforeGetParameterDefault(baseParameter);
493 EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
494 if (evaluationResult == null) {
495 // No default was provided, so the default value is null.
496 argumentValue = typeProvider.nullObject;
497 } else if (evaluationResult.value != null) {
498 argumentValue = evaluationResult.value;
499 }
500 }
501 if (argumentValue != null) {
502 if (!runtimeTypeMatch(argumentValue, parameter.type)) {
503 errorReporter.reportErrorForNode(
504 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMA TCH,
505 errorTarget, [argumentValue.type, parameter.type]);
506 }
507 if (baseParameter.isInitializingFormal) {
508 FieldElement field = (parameter as FieldFormalParameterElement).field;
509 if (field != null) {
510 DartType fieldType = field.type;
511 if (fieldType != parameter.type) {
512 // We've already checked that the argument can be assigned to the
513 // parameter; we also need to check that it can be assigned to
514 // the field.
515 if (!runtimeTypeMatch(argumentValue, fieldType)) {
516 errorReporter.reportErrorForNode(
517 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE _MISMATCH,
518 errorTarget, [argumentValue.type, fieldType]);
519 }
520 }
521 String fieldName = field.name;
522 fieldMap[fieldName] = argumentValue;
523 }
524 } else {
525 String name = baseParameter.name;
526 parameterMap[name] = argumentValue;
527 }
528 }
529 }
530 ConstantVisitor initializerVisitor = new ConstantVisitor(
531 this, errorReporter, lexicalEnvironment: parameterMap);
532 String superName = null;
533 NodeList<Expression> superArguments = null;
534 for (ConstructorInitializer initializer in initializers) {
535 if (initializer is ConstructorFieldInitializer) {
536 ConstructorFieldInitializer constructorFieldInitializer = initializer;
537 Expression initializerExpression =
538 constructorFieldInitializer.expression;
539 DartObjectImpl evaluationResult =
540 initializerExpression.accept(initializerVisitor);
541 if (evaluationResult != null) {
542 String fieldName = constructorFieldInitializer.fieldName.name;
543 fieldMap[fieldName] = evaluationResult;
544 PropertyAccessorElement getter = definingClass.getGetter(fieldName);
545 if (getter != null) {
546 PropertyInducingElement field = getter.variable;
547 if (!runtimeTypeMatch(evaluationResult, field.type)) {
548 errorReporter.reportErrorForNode(
549 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_M ISMATCH,
550 node, [evaluationResult.type, fieldName, field.type]);
551 }
552 }
553 }
554 } else if (initializer is SuperConstructorInvocation) {
555 SuperConstructorInvocation superConstructorInvocation = initializer;
556 SimpleIdentifier name = superConstructorInvocation.constructorName;
557 if (name != null) {
558 superName = name.name;
559 }
560 superArguments = superConstructorInvocation.argumentList.arguments;
561 } else if (initializer is RedirectingConstructorInvocation) {
562 // This is a redirecting constructor, so just evaluate the constructor
563 // it redirects to.
564 ConstructorElement constructor = initializer.staticElement;
565 if (constructor != null && constructor.isConst) {
566 return evaluateConstructorCall(node,
567 initializer.argumentList.arguments, constructor,
568 initializerVisitor, errorReporter);
569 }
570 }
571 }
572 // Evaluate explicit or implicit call to super().
573 InterfaceType superclass = definingClass.superclass;
574 if (superclass != null && !superclass.isObject) {
575 ConstructorElement superConstructor =
576 superclass.lookUpConstructor(superName, constructor.library);
577 if (superConstructor != null) {
578 if (superArguments == null) {
579 superArguments = new NodeList<Expression>(null);
580 }
581 evaluateSuperConstructorCall(node, fieldMap, superConstructor,
582 superArguments, initializerVisitor, errorReporter);
583 }
584 }
585 return new DartObjectImpl(definingClass, new GenericState(fieldMap));
586 }
587
588 void evaluateSuperConstructorCall(AstNode node,
589 HashMap<String, DartObjectImpl> fieldMap,
590 ConstructorElement superConstructor, NodeList<Expression> superArguments,
591 ConstantVisitor initializerVisitor, ErrorReporter errorReporter) {
592 if (superConstructor != null && superConstructor.isConst) {
593 DartObjectImpl evaluationResult = evaluateConstructorCall(node,
594 superArguments, superConstructor, initializerVisitor, errorReporter);
595 if (evaluationResult != null) {
596 fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
597 }
598 }
599 }
600
601 /**
602 * Attempt to follow the chain of factory redirections until a constructor is
603 * reached which is not a const factory constructor. Return the constant
604 * constructor which terminates the chain of factory redirections, if the
605 * chain terminates. If there is a problem (e.g. a redirection can't be found,
606 * or a cycle is encountered), the chain will be followed as far as possible
607 * and then a const factory constructor will be returned.
608 */
609 ConstructorElement followConstantRedirectionChain(
610 ConstructorElement constructor) {
611 HashSet<ConstructorElement> constructorsVisited =
612 new HashSet<ConstructorElement>();
613 while (true) {
614 ConstructorElement redirectedConstructor =
615 getConstRedirectedConstructor(constructor);
616 if (redirectedConstructor == null) {
617 break;
618 } else {
619 ConstructorElement constructorBase = _getConstructorBase(constructor);
620 constructorsVisited.add(constructorBase);
621 ConstructorElement redirectedConstructorBase =
622 _getConstructorBase(redirectedConstructor);
623 if (constructorsVisited.contains(redirectedConstructorBase)) {
624 // Cycle in redirecting factory constructors--this is not allowed
625 // and is checked elsewhere--see
626 // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
627 break;
628 }
629 }
630 constructor = redirectedConstructor;
631 }
632 return constructor;
633 }
634
635 /**
636 * If [constructor] redirects to another const constructor, return the
637 * const constructor it redirects to. Otherwise return `null`.
638 */
639 ConstructorElement getConstRedirectedConstructor(
640 ConstructorElement constructor) {
641 if (!constructor.isFactory) {
642 return null;
643 }
644 if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
645 // The dart:core.Symbol has a const factory constructor that redirects
646 // to dart:_internal.Symbol. That in turn redirects to an external
647 // const constructor, which we won't be able to evaluate.
648 // So stop following the chain of redirections at dart:core.Symbol, and
649 // let [evaluateInstanceCreationExpression] handle it specially.
650 return null;
651 }
652 ConstructorElement redirectedConstructor =
653 constructor.redirectedConstructor;
654 if (redirectedConstructor == null) {
655 // This can happen if constructor is an external factory constructor.
656 return null;
657 }
658 if (!redirectedConstructor.isConst) {
659 // Delegating to a non-const constructor--this is not allowed (and
660 // is checked elsewhere--see
661 // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
662 return null;
663 }
664 return redirectedConstructor;
665 }
666
667 /**
668 * Check if the object [obj] matches the type [type] according to runtime type
669 * checking rules.
670 */
671 bool runtimeTypeMatch(DartObjectImpl obj, DartType type) {
672 if (obj.isNull) {
673 return true;
674 }
675 if (type.isUndefined) {
676 return false;
677 }
678 return obj.type.isSubtypeOf(type);
679 }
680
681 ConstructorElementImpl _getConstructorBase(ConstructorElement constructor) {
682 while (constructor is ConstructorMember) {
683 constructor = (constructor as ConstructorMember).baseElement;
684 }
685 return constructor;
686 }
687
688 /**
689 * Determine whether the given string is a valid name for a public symbol
690 * (i.e. whether it is allowed for a call to the Symbol constructor).
691 */
692 static bool isValidPublicSymbol(String name) => name.isEmpty ||
693 name == "void" ||
694 new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches();
695 }
696
697 /**
189 * Interface used by unit tests to verify correct dependency analysis during 698 * Interface used by unit tests to verify correct dependency analysis during
190 * constant evaluation. 699 * constant evaluation.
191 */ 700 */
192 abstract class ConstantEvaluationValidator { 701 abstract class ConstantEvaluationValidator {
193 /** 702 /**
194 * This method is called just before computing the constant value associated 703 * This method is called just before computing the constant value associated
195 * with [constNode]. Unit tests will override this method to introduce 704 * with [constNode]. Unit tests will override this method to introduce
196 * additional error checking. 705 * additional error checking.
197 */ 706 */
198 void beforeComputeValue(AstNode constNode); 707 void beforeComputeValue(AstNode constNode);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 /** 826 /**
318 * Initialize a newly created evaluator to evaluate expressions in the given 827 * Initialize a newly created evaluator to evaluate expressions in the given
319 * [source]. The [typeProvider] is the type provider used to access known 828 * [source]. The [typeProvider] is the type provider used to access known
320 * types. 829 * types.
321 */ 830 */
322 ConstantEvaluator(this._source, this._typeProvider); 831 ConstantEvaluator(this._source, this._typeProvider);
323 832
324 EvaluationResult evaluate(Expression expression) { 833 EvaluationResult evaluate(Expression expression) {
325 RecordingErrorListener errorListener = new RecordingErrorListener(); 834 RecordingErrorListener errorListener = new RecordingErrorListener();
326 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source); 835 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
327 DartObjectImpl result = 836 DartObjectImpl result = expression.accept(new ConstantVisitor(
328 expression.accept(new ConstantVisitor(_typeProvider, errorReporter)); 837 new ConstantEvaluationEngine(_typeProvider, new DeclaredVariables()),
838 errorReporter));
329 if (result != null) { 839 if (result != null) {
330 return EvaluationResult.forValue(result); 840 return EvaluationResult.forValue(result);
331 } 841 }
332 return EvaluationResult.forErrors(errorListener.errors); 842 return EvaluationResult.forErrors(errorListener.errors);
333 } 843 }
334 } 844 }
335 845
336 /** 846 /**
337 * A visitor used to traverse the AST structures of all of the compilation units 847 * A visitor used to traverse the AST structures of all of the compilation units
338 * being resolved and build tables of the constant variables, constant 848 * being resolved and build tables of the constant variables, constant
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 /** 946 /**
437 * An object used to compute the values of constant variables and constant 947 * An object used to compute the values of constant variables and constant
438 * constructor invocations in one or more compilation units. The expected usage 948 * constructor invocations in one or more compilation units. The expected usage
439 * pattern is for the compilation units to be added to this computer using the 949 * pattern is for the compilation units to be added to this computer using the
440 * method [add] and then for the method [computeValues] to be invoked exactly 950 * method [add] and then for the method [computeValues] to be invoked exactly
441 * once. Any use of an instance after invoking the method [computeValues] will 951 * once. Any use of an instance after invoking the method [computeValues] will
442 * result in unpredictable behavior. 952 * result in unpredictable behavior.
443 */ 953 */
444 class ConstantValueComputer { 954 class ConstantValueComputer {
445 /** 955 /**
446 * Parameter to "fromEnvironment" methods that denotes the default value.
447 */
448 static String _DEFAULT_VALUE_PARAM = "defaultValue";
449
450 /**
451 * Source of RegExp matching declarable operator names. 956 * Source of RegExp matching declarable operator names.
452 * From sdk/lib/internal/symbol.dart. 957 * From sdk/lib/internal/symbol.dart.
453 */ 958 */
454 static String _OPERATOR_RE = 959 static String _OPERATOR_RE =
455 "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)"; 960 "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
456 961
457 /** 962 /**
458 * Source of RegExp matching any public identifier.
459 * From sdk/lib/internal/symbol.dart.
460 */
461 static String _PUBLIC_IDENTIFIER_RE =
462 "(?!${ConstantValueComputer._RESERVED_WORD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$ ]*";
463
464 /**
465 * Source of RegExp matching Dart reserved words. 963 * Source of RegExp matching Dart reserved words.
466 * From sdk/lib/internal/symbol.dart. 964 * From sdk/lib/internal/symbol.dart.
467 */ 965 */
468 static String _RESERVED_WORD_RE = 966 static String _RESERVED_WORD_RE =
469 "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|e(?:ls e|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:up er|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))"; 967 "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|e(?:ls e|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:up er|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
470 968
471 /** 969 /**
472 * RegExp that validates a non-empty non-private symbol.
473 * From sdk/lib/internal/symbol.dart.
474 */
475 static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
476 "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$ |[.](?!\$)))+?\$");
477
478 /**
479 * The type provider used to access the known types.
480 */
481 final TypeProvider typeProvider;
482
483 /**
484 * Validator used to verify correct dependency analysis when running unit
485 * tests.
486 */
487 final ConstantEvaluationValidator validator;
488
489 /**
490 * The object used to find constant variables and constant constructor 970 * The object used to find constant variables and constant constructor
491 * invocations in the compilation units that were added. 971 * invocations in the compilation units that were added.
492 */ 972 */
493 ConstantFinder _constantFinder = new ConstantFinder(); 973 ConstantFinder _constantFinder = new ConstantFinder();
494 974
495 /** 975 /**
496 * A graph in which the nodes are the constants, and the edges are from each 976 * A graph in which the nodes are the constants, and the edges are from each
497 * constant to the other constants that are referenced by it. 977 * constant to the other constants that are referenced by it.
498 */ 978 */
499 DirectedGraph<AstNode> referenceGraph = new DirectedGraph<AstNode>(); 979 DirectedGraph<AstNode> referenceGraph = new DirectedGraph<AstNode>();
(...skipping 13 matching lines...) Expand all
513 * A collection of constant constructor invocations. 993 * A collection of constant constructor invocations.
514 */ 994 */
515 List<InstanceCreationExpression> _constructorInvocations; 995 List<InstanceCreationExpression> _constructorInvocations;
516 996
517 /** 997 /**
518 * A collection of annotations. 998 * A collection of annotations.
519 */ 999 */
520 List<Annotation> _annotations; 1000 List<Annotation> _annotations;
521 1001
522 /** 1002 /**
523 * The set of variables declared on the command line using '-D'. 1003 * The evaluation engine that does the work of evaluating instance creation
524 */ 1004 * expressions.
525 final DeclaredVariables _declaredVariables; 1005 */
1006 final ConstantEvaluationEngine evaluationEngine;
526 1007
527 /** 1008 /**
528 * Initialize a newly created constant value computer. The [typeProvider] is 1009 * Initialize a newly created constant value computer. The [typeProvider] is
529 * the type provider used to access known types. The [declaredVariables] is 1010 * the type provider used to access known types. The [declaredVariables] is
530 * the set of variables declared on the command line using '-D'. 1011 * the set of variables declared on the command line using '-D'.
531 */ 1012 */
532 ConstantValueComputer(this.typeProvider, this._declaredVariables, 1013 ConstantValueComputer(
1014 TypeProvider typeProvider, DeclaredVariables declaredVariables,
533 [ConstantEvaluationValidator validator]) 1015 [ConstantEvaluationValidator validator])
534 : validator = validator != null 1016 : evaluationEngine = new ConstantEvaluationEngine(
535 ? validator 1017 typeProvider, declaredVariables, validator: validator);
536 : new ConstantEvaluationValidator_ForProduction();
537 1018
538 /** 1019 /**
539 * Add the constants in the given compilation [unit] to the list of constants 1020 * Add the constants in the given compilation [unit] to the list of constants
540 * whose value needs to be computed. 1021 * whose value needs to be computed.
541 */ 1022 */
542 void add(CompilationUnit unit) { 1023 void add(CompilationUnit unit) {
543 unit.accept(_constantFinder); 1024 unit.accept(_constantFinder);
544 } 1025 }
545 1026
546 /** 1027 /**
547 * Compute values for all of the constants in the compilation units that were 1028 * Compute values for all of the constants in the compilation units that were
548 * added. 1029 * added.
549 */ 1030 */
550 void computeValues() { 1031 void computeValues() {
551 _variableDeclarationMap = _constantFinder.variableMap; 1032 _variableDeclarationMap = _constantFinder.variableMap;
552 constructorDeclarationMap = _constantFinder.constructorMap; 1033 constructorDeclarationMap = _constantFinder.constructorMap;
553 _constructorInvocations = _constantFinder.constructorInvocations; 1034 _constructorInvocations = _constantFinder.constructorInvocations;
554 _annotations = _constantFinder.annotations; 1035 _annotations = _constantFinder.annotations;
555 _variableDeclarationMap.values.forEach((VariableDeclaration declaration) { 1036 _variableDeclarationMap.values.forEach((VariableDeclaration declaration) {
556 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, 1037 ReferenceFinder referenceFinder = new ReferenceFinder(declaration,
557 referenceGraph, _variableDeclarationMap, constructorDeclarationMap); 1038 referenceGraph, _variableDeclarationMap, constructorDeclarationMap);
558 referenceGraph.addNode(declaration); 1039 referenceGraph.addNode(declaration);
559 declaration.initializer.accept(referenceFinder); 1040 declaration.initializer.accept(referenceFinder);
560 }); 1041 });
561 constructorDeclarationMap.forEach((ConstructorElementImpl element, 1042 constructorDeclarationMap.forEach((ConstructorElementImpl element,
562 ConstructorDeclaration declaration) { 1043 ConstructorDeclaration declaration) {
563 element.isCycleFree = false; 1044 element.isCycleFree = false;
564 ConstructorElement redirectedConstructor = 1045 ConstructorElement redirectedConstructor =
565 _getConstRedirectedConstructor(element); 1046 evaluationEngine.getConstRedirectedConstructor(element);
566 if (redirectedConstructor != null) { 1047 if (redirectedConstructor != null) {
567 ConstructorElement redirectedConstructorBase = 1048 ConstructorElement redirectedConstructorBase =
568 _getConstructorBase(redirectedConstructor); 1049 evaluationEngine._getConstructorBase(redirectedConstructor);
569 ConstructorDeclaration redirectedConstructorDeclaration = 1050 ConstructorDeclaration redirectedConstructorDeclaration =
570 findConstructorDeclaration(redirectedConstructorBase); 1051 findConstructorDeclaration(redirectedConstructorBase);
571 referenceGraph.addEdge(declaration, redirectedConstructorDeclaration); 1052 referenceGraph.addEdge(declaration, redirectedConstructorDeclaration);
572 return; 1053 return;
573 } 1054 }
574 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, 1055 ReferenceFinder referenceFinder = new ReferenceFinder(declaration,
575 referenceGraph, _variableDeclarationMap, constructorDeclarationMap); 1056 referenceGraph, _variableDeclarationMap, constructorDeclarationMap);
576 referenceGraph.addNode(declaration); 1057 referenceGraph.addNode(declaration);
577 bool superInvocationFound = false; 1058 bool superInvocationFound = false;
578 NodeList<ConstructorInitializer> initializers = declaration.initializers; 1059 NodeList<ConstructorInitializer> initializers = declaration.initializers;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 } 1132 }
652 // Since no constant can depend on an annotation, we don't waste time 1133 // Since no constant can depend on an annotation, we don't waste time
653 // including them in the topological sort. We just process all the 1134 // including them in the topological sort. We just process all the
654 // annotations after all other constants are finished. 1135 // annotations after all other constants are finished.
655 for (Annotation annotation in _annotations) { 1136 for (Annotation annotation in _annotations) {
656 _computeValueFor(annotation); 1137 _computeValueFor(annotation);
657 } 1138 }
658 } 1139 }
659 1140
660 ConstructorDeclaration findConstructorDeclaration( 1141 ConstructorDeclaration findConstructorDeclaration(
661 ConstructorElement constructor) => 1142 ConstructorElement constructor) => constructorDeclarationMap[
662 constructorDeclarationMap[_getConstructorBase(constructor)]; 1143 evaluationEngine._getConstructorBase(constructor)];
663 1144
664 VariableDeclaration findVariableDeclaration( 1145 VariableDeclaration findVariableDeclaration(
665 PotentiallyConstVariableElement variable) => 1146 PotentiallyConstVariableElement variable) =>
666 _variableDeclarationMap[variable]; 1147 _variableDeclarationMap[variable];
667 1148
668 /** 1149 /**
669 * Check that the arguments to a call to fromEnvironment() are correct. The
670 * [arguments] are the AST nodes of the arguments. The [argumentValues] are
671 * the values of the unnamed arguments. The [namedArgumentValues] are the
672 * values of the named arguments. The [expectedDefaultValueType] is the
673 * allowed type of the "defaultValue" parameter (if present). Note:
674 * "defaultValue" is always allowed to be null. Return `true` if the arguments
675 * are correct, `false` if there is an error.
676 */
677 bool _checkFromEnvironmentArguments(NodeList<Expression> arguments,
678 List<DartObjectImpl> argumentValues,
679 HashMap<String, DartObjectImpl> namedArgumentValues,
680 InterfaceType expectedDefaultValueType) {
681 int argumentCount = arguments.length;
682 if (argumentCount < 1 || argumentCount > 2) {
683 return false;
684 }
685 if (arguments[0] is NamedExpression) {
686 return false;
687 }
688 if (!identical(argumentValues[0].type, typeProvider.stringType)) {
689 return false;
690 }
691 if (argumentCount == 2) {
692 if (arguments[1] is! NamedExpression) {
693 return false;
694 }
695 if (!((arguments[1] as NamedExpression).name.label.name ==
696 _DEFAULT_VALUE_PARAM)) {
697 return false;
698 }
699 ParameterizedType defaultValueType =
700 namedArgumentValues[_DEFAULT_VALUE_PARAM].type;
701 if (!(identical(defaultValueType, expectedDefaultValueType) ||
702 identical(defaultValueType, typeProvider.nullType))) {
703 return false;
704 }
705 }
706 return true;
707 }
708
709 /**
710 * Check that the arguments to a call to Symbol() are correct. The [arguments]
711 * are the AST nodes of the arguments. The [argumentValues] are the values of
712 * the unnamed arguments. The [namedArgumentValues] are the values of the
713 * named arguments. Return `true` if the arguments are correct, `false` if
714 * there is an error.
715 */
716 bool _checkSymbolArguments(NodeList<Expression> arguments,
717 List<DartObjectImpl> argumentValues,
718 HashMap<String, DartObjectImpl> namedArgumentValues) {
719 if (arguments.length != 1) {
720 return false;
721 }
722 if (arguments[0] is NamedExpression) {
723 return false;
724 }
725 if (!identical(argumentValues[0].type, typeProvider.stringType)) {
726 return false;
727 }
728 String name = argumentValues[0].stringValue;
729 return isValidPublicSymbol(name);
730 }
731
732 /**
733 * Compute a value for the given [constNode]. 1150 * Compute a value for the given [constNode].
734 */ 1151 */
735 void _computeValueFor(AstNode constNode) { 1152 void _computeValueFor(AstNode constNode) {
736 validator.beforeComputeValue(constNode); 1153 evaluationEngine.validator.beforeComputeValue(constNode);
737 if (constNode is VariableDeclaration) { 1154 if (constNode is VariableDeclaration) {
738 VariableElement element = constNode.element; 1155 VariableElement element = constNode.element;
739 RecordingErrorListener errorListener = new RecordingErrorListener(); 1156 RecordingErrorListener errorListener = new RecordingErrorListener();
740 ErrorReporter errorReporter = 1157 ErrorReporter errorReporter =
741 new ErrorReporter(errorListener, element.source); 1158 new ErrorReporter(errorListener, element.source);
742 DartObjectImpl dartObject = 1159 DartObjectImpl dartObject =
743 (element as PotentiallyConstVariableElement).constantInitializer 1160 (element as PotentiallyConstVariableElement).constantInitializer
744 .accept(new ConstantVisitor(typeProvider, errorReporter, 1161 .accept(new ConstantVisitor(evaluationEngine, errorReporter));
745 validator: validator));
746 if (dartObject != null) { 1162 if (dartObject != null) {
747 if (!_runtimeTypeMatch(dartObject, element.type)) { 1163 if (!evaluationEngine.runtimeTypeMatch(dartObject, element.type)) {
748 errorReporter.reportErrorForElement( 1164 errorReporter.reportErrorForElement(
749 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, element, [ 1165 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, element, [
750 dartObject.type, 1166 dartObject.type,
751 element.type 1167 element.type
752 ]); 1168 ]);
753 } 1169 }
754 } 1170 }
755 (element as VariableElementImpl).evaluationResult = 1171 (element as VariableElementImpl).evaluationResult =
756 new EvaluationResultImpl.con2(dartObject, errorListener.errors); 1172 new EvaluationResultImpl.con2(dartObject, errorListener.errors);
757 } else if (constNode is InstanceCreationExpression) { 1173 } else if (constNode is InstanceCreationExpression) {
758 InstanceCreationExpression expression = constNode; 1174 InstanceCreationExpression expression = constNode;
759 ConstructorElement constructor = expression.staticElement; 1175 ConstructorElement constructor = expression.staticElement;
760 if (constructor == null) { 1176 if (constructor == null) {
761 // Couldn't resolve the constructor so we can't compute a value. 1177 // Couldn't resolve the constructor so we can't compute a value.
762 // No problem - the error has already been reported. 1178 // No problem - the error has already been reported.
763 // But we still need to store an evaluation result. 1179 // But we still need to store an evaluation result.
764 expression.constantHandle.evaluationResult = 1180 expression.constantHandle.evaluationResult =
765 new EvaluationResultImpl.con1(null); 1181 new EvaluationResultImpl.con1(null);
766 return; 1182 return;
767 } 1183 }
768 RecordingErrorListener errorListener = new RecordingErrorListener(); 1184 RecordingErrorListener errorListener = new RecordingErrorListener();
769 CompilationUnit sourceCompilationUnit = 1185 CompilationUnit sourceCompilationUnit =
770 expression.getAncestor((node) => node is CompilationUnit); 1186 expression.getAncestor((node) => node is CompilationUnit);
771 ErrorReporter errorReporter = new ErrorReporter( 1187 ErrorReporter errorReporter = new ErrorReporter(
772 errorListener, sourceCompilationUnit.element.source); 1188 errorListener, sourceCompilationUnit.element.source);
773 ConstantVisitor constantVisitor = new ConstantVisitor( 1189 ConstantVisitor constantVisitor =
774 typeProvider, errorReporter, validator: validator); 1190 new ConstantVisitor(evaluationEngine, errorReporter);
775 DartObjectImpl result = _evaluateConstructorCall(constNode, 1191 DartObjectImpl result = evaluationEngine.evaluateConstructorCall(
776 expression.argumentList.arguments, constructor, constantVisitor, 1192 constNode, expression.argumentList.arguments, constructor,
777 errorReporter); 1193 constantVisitor, errorReporter);
778 expression.constantHandle.evaluationResult = 1194 expression.constantHandle.evaluationResult =
779 new EvaluationResultImpl.con2(result, errorListener.errors); 1195 new EvaluationResultImpl.con2(result, errorListener.errors);
780 } else if (constNode is ConstructorDeclaration) { 1196 } else if (constNode is ConstructorDeclaration) {
781 // No evaluation needs to be done; constructor declarations are only in 1197 // No evaluation needs to be done; constructor declarations are only in
782 // the dependency graph to ensure that any constants referred to in 1198 // the dependency graph to ensure that any constants referred to in
783 // initializer lists and parameter defaults are evaluated before 1199 // initializer lists and parameter defaults are evaluated before
784 // invocations of the constructor. However we do need to annotate the 1200 // invocations of the constructor. However we do need to annotate the
785 // element as being free of constant evaluation cycles so that later code 1201 // element as being free of constant evaluation cycles so that later code
786 // will know that it is safe to evaluate. 1202 // will know that it is safe to evaluate.
787 ConstructorElementImpl constructor = constNode.element; 1203 ConstructorElementImpl constructor = constNode.element;
788 constructor.isCycleFree = true; 1204 constructor.isCycleFree = true;
789 } else if (constNode is FormalParameter) { 1205 } else if (constNode is FormalParameter) {
790 if (constNode is DefaultFormalParameter) { 1206 if (constNode is DefaultFormalParameter) {
791 DefaultFormalParameter parameter = constNode; 1207 DefaultFormalParameter parameter = constNode;
792 ParameterElement element = parameter.element; 1208 ParameterElement element = parameter.element;
793 Expression defaultValue = parameter.defaultValue; 1209 Expression defaultValue = parameter.defaultValue;
794 if (defaultValue != null) { 1210 if (defaultValue != null) {
795 RecordingErrorListener errorListener = new RecordingErrorListener(); 1211 RecordingErrorListener errorListener = new RecordingErrorListener();
796 ErrorReporter errorReporter = 1212 ErrorReporter errorReporter =
797 new ErrorReporter(errorListener, element.source); 1213 new ErrorReporter(errorListener, element.source);
798 DartObjectImpl dartObject = defaultValue.accept(new ConstantVisitor( 1214 DartObjectImpl dartObject = defaultValue
799 typeProvider, errorReporter, validator: validator)); 1215 .accept(new ConstantVisitor(evaluationEngine, errorReporter));
800 (element as ParameterElementImpl).evaluationResult = 1216 (element as ParameterElementImpl).evaluationResult =
801 new EvaluationResultImpl.con2(dartObject, errorListener.errors); 1217 new EvaluationResultImpl.con2(dartObject, errorListener.errors);
802 } 1218 }
803 } 1219 }
804 } else if (constNode is Annotation) { 1220 } else if (constNode is Annotation) {
805 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation; 1221 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation;
806 // elementAnnotation is null if the annotation couldn't be resolved, in 1222 // elementAnnotation is null if the annotation couldn't be resolved, in
807 // which case we skip it. 1223 // which case we skip it.
808 if (elementAnnotation != null) { 1224 if (elementAnnotation != null) {
809 Element element = elementAnnotation.element; 1225 Element element = elementAnnotation.element;
810 if (element is PropertyAccessorElement && 1226 if (element is PropertyAccessorElement &&
811 element.variable is VariableElementImpl) { 1227 element.variable is VariableElementImpl) {
812 // The annotation is a reference to a compile-time constant variable. 1228 // The annotation is a reference to a compile-time constant variable.
813 // Just copy the evaluation result. 1229 // Just copy the evaluation result.
814 VariableElementImpl variableElement = 1230 VariableElementImpl variableElement =
815 element.variable as VariableElementImpl; 1231 element.variable as VariableElementImpl;
816 elementAnnotation.evaluationResult = variableElement.evaluationResult; 1232 elementAnnotation.evaluationResult = variableElement.evaluationResult;
817 } else if (element is ConstructorElementImpl && 1233 } else if (element is ConstructorElementImpl &&
818 constNode.arguments != null) { 1234 constNode.arguments != null) {
819 RecordingErrorListener errorListener = new RecordingErrorListener(); 1235 RecordingErrorListener errorListener = new RecordingErrorListener();
820 CompilationUnit sourceCompilationUnit = 1236 CompilationUnit sourceCompilationUnit =
821 constNode.getAncestor((node) => node is CompilationUnit); 1237 constNode.getAncestor((node) => node is CompilationUnit);
822 ErrorReporter errorReporter = new ErrorReporter( 1238 ErrorReporter errorReporter = new ErrorReporter(
823 errorListener, sourceCompilationUnit.element.source); 1239 errorListener, sourceCompilationUnit.element.source);
824 ConstantVisitor constantVisitor = new ConstantVisitor( 1240 ConstantVisitor constantVisitor =
825 typeProvider, errorReporter, validator: validator); 1241 new ConstantVisitor(evaluationEngine, errorReporter);
826 DartObjectImpl result = _evaluateConstructorCall(constNode, 1242 DartObjectImpl result = evaluationEngine.evaluateConstructorCall(
827 constNode.arguments.arguments, element, constantVisitor, 1243 constNode, constNode.arguments.arguments, element,
828 errorReporter); 1244 constantVisitor, errorReporter);
829 elementAnnotation.evaluationResult = 1245 elementAnnotation.evaluationResult =
830 new EvaluationResultImpl.con2(result, errorListener.errors); 1246 new EvaluationResultImpl.con2(result, errorListener.errors);
831 } else { 1247 } else {
832 // This may happen for invalid code (e.g. failing to pass arguments 1248 // This may happen for invalid code (e.g. failing to pass arguments
833 // to an annotation which references a const constructor). The error 1249 // to an annotation which references a const constructor). The error
834 // is detected elsewhere, so just silently ignore it here. 1250 // is detected elsewhere, so just silently ignore it here.
835 elementAnnotation.evaluationResult = 1251 elementAnnotation.evaluationResult =
836 new EvaluationResultImpl.con1(null); 1252 new EvaluationResultImpl.con1(null);
837 } 1253 }
838 } 1254 }
839 } else { 1255 } else {
840 // Should not happen. 1256 // Should not happen.
841 AnalysisEngine.instance.logger.logError( 1257 AnalysisEngine.instance.logger.logError(
842 "Constant value computer trying to compute the value of a node which i s not a VariableDeclaration, InstanceCreationExpression, FormalParameter, or Con structorDeclaration"); 1258 "Constant value computer trying to compute the value of a node which i s not a VariableDeclaration, InstanceCreationExpression, FormalParameter, or Con structorDeclaration");
843 return; 1259 return;
844 } 1260 }
845 } 1261 }
846 1262
847 /** 1263 /**
848 * Evaluate a call to fromEnvironment() on the bool, int, or String class. The
849 * [environmentValue] is the value fetched from the environment. The
850 * [builtInDefaultValue] is the value that should be used as the default if no
851 * "defaultValue" argument appears in [namedArgumentValues]. The
852 * [namedArgumentValues] are the values of the named parameters passed to
853 * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
854 * evaluated result.
855 */
856 DartObjectImpl _computeValueFromEnvironment(DartObject environmentValue,
857 DartObjectImpl builtInDefaultValue,
858 HashMap<String, DartObjectImpl> namedArgumentValues) {
859 DartObjectImpl value = environmentValue as DartObjectImpl;
860 if (value.isUnknown || value.isNull) {
861 // The name either doesn't exist in the environment or we couldn't parse
862 // the corresponding value.
863 // If the code supplied an explicit default, use it.
864 if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
865 value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
866 } else if (value.isNull) {
867 // The code didn't supply an explicit default.
868 // The name exists in the environment but we couldn't parse the
869 // corresponding value.
870 // So use the built-in default value, because this is what the VM does.
871 value = builtInDefaultValue;
872 } else {
873 // The code didn't supply an explicit default.
874 // The name doesn't exist in the environment.
875 // The VM would use the built-in default value, but we don't want to do
876 // that for analysis because it's likely to lead to cascading errors.
877 // So just leave [value] in the unknown state.
878 }
879 }
880 return value;
881 }
882
883 DartObjectImpl _evaluateConstructorCall(AstNode node,
884 NodeList<Expression> arguments, ConstructorElement constructor,
885 ConstantVisitor constantVisitor, ErrorReporter errorReporter) {
886 if (!_getConstructorBase(constructor).isCycleFree) {
887 // It's not safe to evaluate this constructor, so bail out.
888 // TODO(paulberry): ensure that a reasonable error message is produced
889 // in this case, as well as other cases involving constant expression
890 // circularities (e.g. "compile-time constant expression depends on
891 // itself")
892 return new DartObjectImpl.validWithUnknownValue(constructor.returnType);
893 }
894 int argumentCount = arguments.length;
895 List<DartObjectImpl> argumentValues =
896 new List<DartObjectImpl>(argumentCount);
897 List<Expression> argumentNodes = new List<Expression>(argumentCount);
898 HashMap<String, DartObjectImpl> namedArgumentValues =
899 new HashMap<String, DartObjectImpl>();
900 HashMap<String, NamedExpression> namedArgumentNodes =
901 new HashMap<String, NamedExpression>();
902 for (int i = 0; i < argumentCount; i++) {
903 Expression argument = arguments[i];
904 if (argument is NamedExpression) {
905 String name = argument.name.label.name;
906 namedArgumentValues[name] =
907 constantVisitor._valueOf(argument.expression);
908 namedArgumentNodes[name] = argument;
909 argumentValues[i] = typeProvider.nullObject;
910 } else {
911 argumentValues[i] = constantVisitor._valueOf(argument);
912 argumentNodes[i] = argument;
913 }
914 }
915 constructor = _followConstantRedirectionChain(constructor);
916 InterfaceType definingClass = constructor.returnType as InterfaceType;
917 if (constructor.isFactory) {
918 // We couldn't find a non-factory constructor.
919 // See if it's because we reached an external const factory constructor
920 // that we can emulate.
921 if (constructor.name == "fromEnvironment") {
922 if (!_checkFromEnvironmentArguments(
923 arguments, argumentValues, namedArgumentValues, definingClass)) {
924 errorReporter.reportErrorForNode(
925 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
926 return null;
927 }
928 String variableName =
929 argumentCount < 1 ? null : argumentValues[0].stringValue;
930 if (identical(definingClass, typeProvider.boolType)) {
931 DartObject valueFromEnvironment;
932 valueFromEnvironment =
933 _declaredVariables.getBool(typeProvider, variableName);
934 return _computeValueFromEnvironment(valueFromEnvironment,
935 new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
936 namedArgumentValues);
937 } else if (identical(definingClass, typeProvider.intType)) {
938 DartObject valueFromEnvironment;
939 valueFromEnvironment =
940 _declaredVariables.getInt(typeProvider, variableName);
941 return _computeValueFromEnvironment(valueFromEnvironment,
942 new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
943 namedArgumentValues);
944 } else if (identical(definingClass, typeProvider.stringType)) {
945 DartObject valueFromEnvironment;
946 valueFromEnvironment =
947 _declaredVariables.getString(typeProvider, variableName);
948 return _computeValueFromEnvironment(valueFromEnvironment,
949 new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
950 namedArgumentValues);
951 }
952 } else if (constructor.name == "" &&
953 identical(definingClass, typeProvider.symbolType) &&
954 argumentCount == 1) {
955 if (!_checkSymbolArguments(
956 arguments, argumentValues, namedArgumentValues)) {
957 errorReporter.reportErrorForNode(
958 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
959 return null;
960 }
961 String argumentValue = argumentValues[0].stringValue;
962 return new DartObjectImpl(
963 definingClass, new SymbolState(argumentValue));
964 }
965 // Either it's an external const factory constructor that we can't
966 // emulate, or an error occurred (a cycle, or a const constructor trying
967 // to delegate to a non-const constructor).
968 // In the former case, the best we can do is consider it an unknown value.
969 // In the latter case, the error has already been reported, so considering
970 // it an unknown value will suppress further errors.
971 return new DartObjectImpl.validWithUnknownValue(definingClass);
972 }
973 validator.beforeGetConstantInitializers(constructor);
974 ConstructorElementImpl constructorBase = _getConstructorBase(constructor);
975 List<ConstructorInitializer> initializers =
976 constructorBase.constantInitializers;
977 if (initializers == null) {
978 // This can happen in some cases where there are compile errors in the
979 // code being analyzed (for example if the code is trying to create a
980 // const instance using a non-const constructor, or the node we're
981 // visiting is involved in a cycle). The error has already been reported,
982 // so consider it an unknown value to suppress further errors.
983 return new DartObjectImpl.validWithUnknownValue(definingClass);
984 }
985 HashMap<String, DartObjectImpl> fieldMap =
986 new HashMap<String, DartObjectImpl>();
987 // Start with final fields that are initialized at their declaration site.
988 for (FieldElement field in constructor.enclosingElement.fields) {
989 if ((field.isFinal || field.isConst) &&
990 !field.isStatic &&
991 field is ConstFieldElementImpl) {
992 validator.beforeGetFieldEvaluationResult(field);
993 EvaluationResultImpl evaluationResult = field.evaluationResult;
994 DartType fieldType =
995 FieldMember.from(field, constructor.returnType).type;
996 DartObjectImpl fieldValue = evaluationResult.value;
997 if (fieldValue != null && !_runtimeTypeMatch(fieldValue, fieldType)) {
998 errorReporter.reportErrorForNode(
999 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMA TCH,
1000 node, [fieldValue.type, field.name, fieldType]);
1001 }
1002 fieldMap[field.name] = evaluationResult.value;
1003 }
1004 }
1005 // Now evaluate the constructor declaration.
1006 HashMap<String, DartObjectImpl> parameterMap =
1007 new HashMap<String, DartObjectImpl>();
1008 List<ParameterElement> parameters = constructor.parameters;
1009 int parameterCount = parameters.length;
1010 for (int i = 0; i < parameterCount; i++) {
1011 ParameterElement parameter = parameters[i];
1012 ParameterElement baseParameter = parameter;
1013 while (baseParameter is ParameterMember) {
1014 baseParameter = (baseParameter as ParameterMember).baseElement;
1015 }
1016 DartObjectImpl argumentValue = null;
1017 AstNode errorTarget = null;
1018 if (baseParameter.parameterKind == ParameterKind.NAMED) {
1019 argumentValue = namedArgumentValues[baseParameter.name];
1020 errorTarget = namedArgumentNodes[baseParameter.name];
1021 } else if (i < argumentCount) {
1022 argumentValue = argumentValues[i];
1023 errorTarget = argumentNodes[i];
1024 }
1025 if (errorTarget == null) {
1026 // No argument node that we can direct error messages to, because we
1027 // are handling an optional parameter that wasn't specified. So just
1028 // direct error messages to the constructor call.
1029 errorTarget = node;
1030 }
1031 if (argumentValue == null && baseParameter is ParameterElementImpl) {
1032 // The parameter is an optional positional parameter for which no value
1033 // was provided, so use the default value.
1034 validator.beforeGetParameterDefault(baseParameter);
1035 EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
1036 if (evaluationResult == null) {
1037 // No default was provided, so the default value is null.
1038 argumentValue = typeProvider.nullObject;
1039 } else if (evaluationResult.value != null) {
1040 argumentValue = evaluationResult.value;
1041 }
1042 }
1043 if (argumentValue != null) {
1044 if (!_runtimeTypeMatch(argumentValue, parameter.type)) {
1045 errorReporter.reportErrorForNode(
1046 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMA TCH,
1047 errorTarget, [argumentValue.type, parameter.type]);
1048 }
1049 if (baseParameter.isInitializingFormal) {
1050 FieldElement field = (parameter as FieldFormalParameterElement).field;
1051 if (field != null) {
1052 DartType fieldType = field.type;
1053 if (fieldType != parameter.type) {
1054 // We've already checked that the argument can be assigned to the
1055 // parameter; we also need to check that it can be assigned to
1056 // the field.
1057 if (!_runtimeTypeMatch(argumentValue, fieldType)) {
1058 errorReporter.reportErrorForNode(
1059 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE _MISMATCH,
1060 errorTarget, [argumentValue.type, fieldType]);
1061 }
1062 }
1063 String fieldName = field.name;
1064 fieldMap[fieldName] = argumentValue;
1065 }
1066 } else {
1067 String name = baseParameter.name;
1068 parameterMap[name] = argumentValue;
1069 }
1070 }
1071 }
1072 ConstantVisitor initializerVisitor = new ConstantVisitor(
1073 typeProvider, errorReporter,
1074 validator: validator, lexicalEnvironment: parameterMap);
1075 String superName = null;
1076 NodeList<Expression> superArguments = null;
1077 for (ConstructorInitializer initializer in initializers) {
1078 if (initializer is ConstructorFieldInitializer) {
1079 ConstructorFieldInitializer constructorFieldInitializer = initializer;
1080 Expression initializerExpression =
1081 constructorFieldInitializer.expression;
1082 DartObjectImpl evaluationResult =
1083 initializerExpression.accept(initializerVisitor);
1084 if (evaluationResult != null) {
1085 String fieldName = constructorFieldInitializer.fieldName.name;
1086 fieldMap[fieldName] = evaluationResult;
1087 PropertyAccessorElement getter = definingClass.getGetter(fieldName);
1088 if (getter != null) {
1089 PropertyInducingElement field = getter.variable;
1090 if (!_runtimeTypeMatch(evaluationResult, field.type)) {
1091 errorReporter.reportErrorForNode(
1092 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_M ISMATCH,
1093 node, [evaluationResult.type, fieldName, field.type]);
1094 }
1095 }
1096 }
1097 } else if (initializer is SuperConstructorInvocation) {
1098 SuperConstructorInvocation superConstructorInvocation = initializer;
1099 SimpleIdentifier name = superConstructorInvocation.constructorName;
1100 if (name != null) {
1101 superName = name.name;
1102 }
1103 superArguments = superConstructorInvocation.argumentList.arguments;
1104 } else if (initializer is RedirectingConstructorInvocation) {
1105 // This is a redirecting constructor, so just evaluate the constructor
1106 // it redirects to.
1107 ConstructorElement constructor = initializer.staticElement;
1108 if (constructor != null && constructor.isConst) {
1109 return _evaluateConstructorCall(node,
1110 initializer.argumentList.arguments, constructor,
1111 initializerVisitor, errorReporter);
1112 }
1113 }
1114 }
1115 // Evaluate explicit or implicit call to super().
1116 InterfaceType superclass = definingClass.superclass;
1117 if (superclass != null && !superclass.isObject) {
1118 ConstructorElement superConstructor =
1119 superclass.lookUpConstructor(superName, constructor.library);
1120 if (superConstructor != null) {
1121 if (superArguments == null) {
1122 superArguments = new NodeList<Expression>(null);
1123 }
1124 _evaluateSuperConstructorCall(node, fieldMap, superConstructor,
1125 superArguments, initializerVisitor, errorReporter);
1126 }
1127 }
1128 return new DartObjectImpl(definingClass, new GenericState(fieldMap));
1129 }
1130
1131 void _evaluateSuperConstructorCall(AstNode node,
1132 HashMap<String, DartObjectImpl> fieldMap,
1133 ConstructorElement superConstructor, NodeList<Expression> superArguments,
1134 ConstantVisitor initializerVisitor, ErrorReporter errorReporter) {
1135 if (superConstructor != null && superConstructor.isConst) {
1136 DartObjectImpl evaluationResult = _evaluateConstructorCall(node,
1137 superArguments, superConstructor, initializerVisitor, errorReporter);
1138 if (evaluationResult != null) {
1139 fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
1140 }
1141 }
1142 }
1143
1144 /**
1145 * Attempt to follow the chain of factory redirections until a constructor is
1146 * reached which is not a const factory constructor. Return the constant
1147 * constructor which terminates the chain of factory redirections, if the
1148 * chain terminates. If there is a problem (e.g. a redirection can't be found,
1149 * or a cycle is encountered), the chain will be followed as far as possible
1150 * and then a const factory constructor will be returned.
1151 */
1152 ConstructorElement _followConstantRedirectionChain(
1153 ConstructorElement constructor) {
1154 HashSet<ConstructorElement> constructorsVisited =
1155 new HashSet<ConstructorElement>();
1156 while (true) {
1157 ConstructorElement redirectedConstructor =
1158 _getConstRedirectedConstructor(constructor);
1159 if (redirectedConstructor == null) {
1160 break;
1161 } else {
1162 ConstructorElement constructorBase = _getConstructorBase(constructor);
1163 constructorsVisited.add(constructorBase);
1164 ConstructorElement redirectedConstructorBase =
1165 _getConstructorBase(redirectedConstructor);
1166 if (constructorsVisited.contains(redirectedConstructorBase)) {
1167 // Cycle in redirecting factory constructors--this is not allowed
1168 // and is checked elsewhere--see
1169 // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
1170 break;
1171 }
1172 }
1173 constructor = redirectedConstructor;
1174 }
1175 return constructor;
1176 }
1177
1178 /**
1179 * Generate an error indicating that the given [constant] is not a valid 1264 * Generate an error indicating that the given [constant] is not a valid
1180 * compile-time constant because it references at least one of the constants 1265 * compile-time constant because it references at least one of the constants
1181 * in the given [cycle], each of which directly or indirectly references the 1266 * in the given [cycle], each of which directly or indirectly references the
1182 * constant. 1267 * constant.
1183 */ 1268 */
1184 void _generateCycleError(List<AstNode> cycle, AstNode constant) { 1269 void _generateCycleError(List<AstNode> cycle, AstNode constant) {
1185 // TODO(brianwilkerson) Implement this. 1270 // TODO(brianwilkerson) Implement this.
1186 } 1271 }
1187
1188 /**
1189 * If [constructor] redirects to another const constructor, return the
1190 * const constructor it redirects to. Otherwise return `null`.
1191 */
1192 ConstructorElement _getConstRedirectedConstructor(
1193 ConstructorElement constructor) {
1194 if (!constructor.isFactory) {
1195 return null;
1196 }
1197 if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
1198 // The dart:core.Symbol has a const factory constructor that redirects
1199 // to dart:_internal.Symbol. That in turn redirects to an external
1200 // const constructor, which we won't be able to evaluate.
1201 // So stop following the chain of redirections at dart:core.Symbol, and
1202 // let [evaluateInstanceCreationExpression] handle it specially.
1203 return null;
1204 }
1205 ConstructorElement redirectedConstructor =
1206 constructor.redirectedConstructor;
1207 if (redirectedConstructor == null) {
1208 // This can happen if constructor is an external factory constructor.
1209 return null;
1210 }
1211 if (!redirectedConstructor.isConst) {
1212 // Delegating to a non-const constructor--this is not allowed (and
1213 // is checked elsewhere--see
1214 // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
1215 return null;
1216 }
1217 return redirectedConstructor;
1218 }
1219
1220 ConstructorElementImpl _getConstructorBase(ConstructorElement constructor) {
1221 while (constructor is ConstructorMember) {
1222 constructor = (constructor as ConstructorMember).baseElement;
1223 }
1224 return constructor;
1225 }
1226
1227 /**
1228 * Check if the object [obj] matches the type [type] according to runtime type
1229 * checking rules.
1230 */
1231 bool _runtimeTypeMatch(DartObjectImpl obj, DartType type) {
1232 if (obj.isNull) {
1233 return true;
1234 }
1235 if (type.isUndefined) {
1236 return false;
1237 }
1238 return obj.type.isSubtypeOf(type);
1239 }
1240
1241 /**
1242 * Determine whether the given string is a valid name for a public symbol
1243 * (i.e. whether it is allowed for a call to the Symbol constructor).
1244 */
1245 static bool isValidPublicSymbol(String name) => name.isEmpty ||
1246 name == "void" ||
1247 new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches();
1248 } 1272 }
1249 1273
1250 /** 1274 /**
1251 * A visitor used to evaluate constant expressions to produce their compile-time 1275 * A visitor used to evaluate constant expressions to produce their compile-time
1252 * value. According to the Dart Language Specification: <blockquote> A constant 1276 * value. According to the Dart Language Specification: <blockquote> A constant
1253 * expression is one of the following: 1277 * expression is one of the following:
1254 * 1278 *
1255 * * A literal number. 1279 * * A literal number.
1256 * * A literal boolean. 1280 * * A literal boolean.
1257 * * A literal string where any interpolated expression is a compile-time 1281 * * A literal string where any interpolated expression is a compile-time
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1299 * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : 1323 * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
1300 * e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and 1324 * e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
1301 * <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i> 1325 * <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
1302 * evaluates to a boolean value. 1326 * evaluates to a boolean value.
1303 * </blockquote> 1327 * </blockquote>
1304 */ 1328 */
1305 class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> { 1329 class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
1306 /** 1330 /**
1307 * The type provider used to access the known types. 1331 * The type provider used to access the known types.
1308 */ 1332 */
1309 final TypeProvider _typeProvider; 1333 final ConstantEvaluationEngine evaluationEngine;
1310 1334
1311 final HashMap<String, DartObjectImpl> _lexicalEnvironment; 1335 final HashMap<String, DartObjectImpl> _lexicalEnvironment;
1312 1336
1313 /** 1337 /**
1314 * Validator used to verify correct dependency analysis when running unit
1315 * tests.
1316 */
1317 final ConstantEvaluationValidator validator;
1318
1319 /**
1320 * Error reporter that we use to report errors accumulated while computing the 1338 * Error reporter that we use to report errors accumulated while computing the
1321 * constant. 1339 * constant.
1322 */ 1340 */
1323 final ErrorReporter _errorReporter; 1341 final ErrorReporter _errorReporter;
1324 1342
1325 /** 1343 /**
1326 * Helper class used to compute constant values. 1344 * Helper class used to compute constant values.
1327 */ 1345 */
1328 DartObjectComputer _dartObjectComputer; 1346 DartObjectComputer _dartObjectComputer;
1329 1347
1330 /** 1348 /**
1331 * Initialize a newly created constant visitor. The [_typeProvider] is the 1349 * Initialize a newly created constant visitor. The [evaluationEngine] is
1332 * type provider used to access known types. The [lexicalEnvironment] is a 1350 * used to evaluate instance creation expressions. The [lexicalEnvironment]
1333 * map containing values which should override identifiers, or `null` if no 1351 * is a map containing values which should override identifiers, or `null` if
1334 * overriding is necessary. The [_errorReporter] is used to report errors 1352 * no overriding is necessary. The [_errorReporter] is used to report errors
1335 * found during evaluation. The [validator] is used by unit tests to verify 1353 * found during evaluation. The [validator] is used by unit tests to verify
1336 * correct dependency analysis. 1354 * correct dependency analysis.
1337 */ 1355 */
1338 ConstantVisitor(this._typeProvider, this._errorReporter, 1356 ConstantVisitor(this.evaluationEngine, this._errorReporter,
1339 {ConstantEvaluationValidator validator, 1357 {HashMap<String, DartObjectImpl> lexicalEnvironment})
1340 HashMap<String, DartObjectImpl> lexicalEnvironment}) 1358 : _lexicalEnvironment = lexicalEnvironment {
1341 : validator = validator != null
1342 ? validator
1343 : new ConstantEvaluationValidator_ForProduction(),
1344 _lexicalEnvironment = lexicalEnvironment {
1345 this._dartObjectComputer = 1359 this._dartObjectComputer =
1346 new DartObjectComputer(_errorReporter, _typeProvider); 1360 new DartObjectComputer(_errorReporter, evaluationEngine.typeProvider);
1347 } 1361 }
1348 1362
1363 /**
1364 * Convenience getter to gain access to the [evalationEngine]'s type
1365 * provider.
1366 */
1367 TypeProvider get _typeProvider => evaluationEngine.typeProvider;
1368
1349 @override 1369 @override
1350 DartObjectImpl visitAdjacentStrings(AdjacentStrings node) { 1370 DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
1351 DartObjectImpl result = null; 1371 DartObjectImpl result = null;
1352 for (StringLiteral string in node.strings) { 1372 for (StringLiteral string in node.strings) {
1353 if (result == null) { 1373 if (result == null) {
1354 result = string.accept(this); 1374 result = string.accept(this);
1355 } else { 1375 } else {
1356 result = 1376 result =
1357 _dartObjectComputer.concatenate(node, result, string.accept(this)); 1377 _dartObjectComputer.concatenate(node, result, string.accept(this));
1358 } 1378 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1466 new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value)); 1486 new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value));
1467 1487
1468 @override 1488 @override
1469 DartObjectImpl visitInstanceCreationExpression( 1489 DartObjectImpl visitInstanceCreationExpression(
1470 InstanceCreationExpression node) { 1490 InstanceCreationExpression node) {
1471 if (!node.isConst) { 1491 if (!node.isConst) {
1472 // TODO(brianwilkerson) Figure out which error to report. 1492 // TODO(brianwilkerson) Figure out which error to report.
1473 _error(node, null); 1493 _error(node, null);
1474 return null; 1494 return null;
1475 } 1495 }
1476 validator.beforeGetEvaluationResult(node); 1496 evaluationEngine.validator.beforeGetEvaluationResult(node);
1477 EvaluationResultImpl result = node.evaluationResult; 1497 EvaluationResultImpl result = node.evaluationResult;
1478 if (result != null) { 1498 if (result != null) {
1479 return result.value; 1499 return result.value;
1480 } 1500 }
1481 // TODO(brianwilkerson) Figure out which error to report. 1501 // TODO(brianwilkerson) Figure out which error to report.
1482 _error(node, null); 1502 _error(node, null);
1483 return null; 1503 return null;
1484 } 1504 }
1485 1505
1486 @override 1506 @override
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1730 * Return the constant value of the static constant represented by the given 1750 * Return the constant value of the static constant represented by the given
1731 * [element]. The [node] is the node to be used if an error needs to be 1751 * [element]. The [node] is the node to be used if an error needs to be
1732 * reported. 1752 * reported.
1733 */ 1753 */
1734 DartObjectImpl _getConstantValue(AstNode node, Element element) { 1754 DartObjectImpl _getConstantValue(AstNode node, Element element) {
1735 if (element is PropertyAccessorElement) { 1755 if (element is PropertyAccessorElement) {
1736 element = (element as PropertyAccessorElement).variable; 1756 element = (element as PropertyAccessorElement).variable;
1737 } 1757 }
1738 if (element is VariableElementImpl) { 1758 if (element is VariableElementImpl) {
1739 VariableElementImpl variableElementImpl = element; 1759 VariableElementImpl variableElementImpl = element;
1740 validator.beforeGetEvaluationResult(node); 1760 evaluationEngine.validator.beforeGetEvaluationResult(node);
1741 EvaluationResultImpl value = variableElementImpl.evaluationResult; 1761 EvaluationResultImpl value = variableElementImpl.evaluationResult;
1742 if (variableElementImpl.isConst && value != null) { 1762 if (variableElementImpl.isConst && value != null) {
1743 return value.value; 1763 return value.value;
1744 } 1764 }
1745 } else if (element is ExecutableElement) { 1765 } else if (element is ExecutableElement) {
1746 ExecutableElement function = element; 1766 ExecutableElement function = element;
1747 if (function.isStatic) { 1767 if (function.isStatic) {
1748 ParameterizedType functionType = function.type; 1768 ParameterizedType functionType = function.type;
1749 if (functionType == null) { 1769 if (functionType == null) {
1750 functionType = _typeProvider.functionType; 1770 functionType = _typeProvider.functionType;
(...skipping 3449 matching lines...) Expand 10 before | Expand all | Expand 10 after
5200 return BoolState.from(_element == rightElement); 5220 return BoolState.from(_element == rightElement);
5201 } else if (rightOperand is DynamicState) { 5221 } else if (rightOperand is DynamicState) {
5202 return BoolState.UNKNOWN_VALUE; 5222 return BoolState.UNKNOWN_VALUE;
5203 } 5223 }
5204 return BoolState.FALSE_STATE; 5224 return BoolState.FALSE_STATE;
5205 } 5225 }
5206 5226
5207 @override 5227 @override
5208 String toString() => _element == null ? "-unknown-" : _element.name; 5228 String toString() => _element == null ? "-unknown-" : _element.name;
5209 } 5229 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/incremental_resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698