OLD | NEW |
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 library analyzer.src.dart.constant.evaluation; | 5 library analyzer.src.dart.constant.evaluation; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/context/declared_variables.dart'; | 9 import 'package:analyzer/context/declared_variables.dart'; |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 * The set of variables declared on the command line using '-D'. | 68 * The set of variables declared on the command line using '-D'. |
69 */ | 69 */ |
70 final DeclaredVariables _declaredVariables; | 70 final DeclaredVariables _declaredVariables; |
71 | 71 |
72 /** | 72 /** |
73 * Validator used to verify correct dependency analysis when running unit | 73 * Validator used to verify correct dependency analysis when running unit |
74 * tests. | 74 * tests. |
75 */ | 75 */ |
76 final ConstantEvaluationValidator validator; | 76 final ConstantEvaluationValidator validator; |
77 | 77 |
| 78 /** Whether we are running in strong mode. */ |
| 79 final bool strongMode; |
| 80 |
78 /** | 81 /** |
79 * Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider] | 82 * Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider] |
80 * is used to access known types. [_declaredVariables] is the set of | 83 * is used to access known types. [_declaredVariables] is the set of |
81 * variables declared on the command line using '-D'. The [validator], if | 84 * variables declared on the command line using '-D'. The [validator], if |
82 * given, is used to verify correct dependency analysis when running unit | 85 * given, is used to verify correct dependency analysis when running unit |
83 * tests. | 86 * tests. |
84 */ | 87 */ |
85 ConstantEvaluationEngine(this.typeProvider, this._declaredVariables, | 88 ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables, |
86 {ConstantEvaluationValidator validator, TypeSystem typeSystem}) | 89 {ConstantEvaluationValidator validator, TypeSystem typeSystem}) |
87 : validator = | 90 : typeProvider = typeProvider, |
| 91 strongMode = |
| 92 typeProvider.objectType.element.context.analysisOptions.strongMode, |
| 93 validator = |
88 validator ?? new ConstantEvaluationValidator_ForProduction(), | 94 validator ?? new ConstantEvaluationValidator_ForProduction(), |
89 typeSystem = typeSystem ?? new TypeSystemImpl(); | 95 typeSystem = typeSystem ?? new TypeSystemImpl(); |
90 | 96 |
91 /** | 97 /** |
92 * Check that the arguments to a call to fromEnvironment() are correct. The | 98 * Check that the arguments to a call to fromEnvironment() are correct. The |
93 * [arguments] are the AST nodes of the arguments. The [argumentValues] are | 99 * [arguments] are the AST nodes of the arguments. The [argumentValues] are |
94 * the values of the unnamed arguments. The [namedArgumentValues] are the | 100 * the values of the unnamed arguments. The [namedArgumentValues] are the |
95 * values of the named arguments. The [expectedDefaultValueType] is the | 101 * values of the named arguments. The [expectedDefaultValueType] is the |
96 * allowed type of the "defaultValue" parameter (if present). Note: | 102 * allowed type of the "defaultValue" parameter (if present). Note: |
97 * "defaultValue" is always allowed to be null. Return `true` if the arguments | 103 * "defaultValue" is always allowed to be null. Return `true` if the arguments |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 // The VM would use the built-in default value, but we don't want to do | 408 // The VM would use the built-in default value, but we don't want to do |
403 // that for analysis because it's likely to lead to cascading errors. | 409 // that for analysis because it's likely to lead to cascading errors. |
404 // So just leave [value] in the unknown state. | 410 // So just leave [value] in the unknown state. |
405 } | 411 } |
406 } | 412 } |
407 return value; | 413 return value; |
408 } | 414 } |
409 | 415 |
410 DartObjectImpl evaluateConstructorCall( | 416 DartObjectImpl evaluateConstructorCall( |
411 AstNode node, | 417 AstNode node, |
412 NodeList<Expression> arguments, | 418 List<Expression> arguments, |
413 ConstructorElement constructor, | 419 ConstructorElement constructor, |
414 ConstantVisitor constantVisitor, | 420 ConstantVisitor constantVisitor, |
415 ErrorReporter errorReporter) { | 421 ErrorReporter errorReporter) { |
416 if (!getConstructorImpl(constructor).isCycleFree) { | 422 if (!getConstructorImpl(constructor).isCycleFree) { |
417 // It's not safe to evaluate this constructor, so bail out. | 423 // It's not safe to evaluate this constructor, so bail out. |
418 // TODO(paulberry): ensure that a reasonable error message is produced | 424 // TODO(paulberry): ensure that a reasonable error message is produced |
419 // in this case, as well as other cases involving constant expression | 425 // in this case, as well as other cases involving constant expression |
420 // circularities (e.g. "compile-time constant expression depends on | 426 // circularities (e.g. "compile-time constant expression depends on |
421 // itself") | 427 // itself") |
422 return new DartObjectImpl.validWithUnknownValue(constructor.returnType); | 428 return new DartObjectImpl.validWithUnknownValue(constructor.returnType); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 List<ConstructorInitializer> initializers = | 514 List<ConstructorInitializer> initializers = |
509 constructorBase.constantInitializers; | 515 constructorBase.constantInitializers; |
510 if (initializers == null) { | 516 if (initializers == null) { |
511 // This can happen in some cases where there are compile errors in the | 517 // This can happen in some cases where there are compile errors in the |
512 // code being analyzed (for example if the code is trying to create a | 518 // code being analyzed (for example if the code is trying to create a |
513 // const instance using a non-const constructor, or the node we're | 519 // const instance using a non-const constructor, or the node we're |
514 // visiting is involved in a cycle). The error has already been reported, | 520 // visiting is involved in a cycle). The error has already been reported, |
515 // so consider it an unknown value to suppress further errors. | 521 // so consider it an unknown value to suppress further errors. |
516 return new DartObjectImpl.validWithUnknownValue(definingClass); | 522 return new DartObjectImpl.validWithUnknownValue(definingClass); |
517 } | 523 } |
518 HashMap<String, DartObjectImpl> fieldMap = | 524 |
519 new HashMap<String, DartObjectImpl>(); | 525 // In strong mode, we allow constants to have type arguments. |
| 526 // |
| 527 // They will be added to the lexical environment when evaluating |
| 528 // subexpressions. |
| 529 HashMap<String, DartObjectImpl> typeArgumentMap; |
| 530 if (strongMode) { |
| 531 // Instantiate the constructor with the in-scope type arguments. |
| 532 definingClass = constantVisitor.evaluateType(definingClass); |
| 533 constructor = ConstructorMember.from(constructorBase, definingClass); |
| 534 |
| 535 typeArgumentMap = new HashMap<String, DartObjectImpl>.fromIterables( |
| 536 definingClass.typeParameters.map((t) => t.name), |
| 537 definingClass.typeArguments.map(constantVisitor.typeConstant)); |
| 538 } |
| 539 |
| 540 var fieldMap = new HashMap<String, DartObjectImpl>(); |
| 541 var fieldInitVisitor = new ConstantVisitor(this, errorReporter, |
| 542 lexicalEnvironment: typeArgumentMap); |
520 // Start with final fields that are initialized at their declaration site. | 543 // Start with final fields that are initialized at their declaration site. |
521 for (FieldElement field in constructor.enclosingElement.fields) { | 544 List<FieldElement> fields = constructor.enclosingElement.fields; |
| 545 for (int i = 0; i < fields.length; i++) { |
| 546 FieldElement field = fields[i]; |
522 if ((field.isFinal || field.isConst) && | 547 if ((field.isFinal || field.isConst) && |
523 !field.isStatic && | 548 !field.isStatic && |
524 field is ConstFieldElementImpl) { | 549 field is ConstFieldElementImpl) { |
525 validator.beforeGetFieldEvaluationResult(field); | 550 validator.beforeGetFieldEvaluationResult(field); |
526 EvaluationResultImpl evaluationResult = field.evaluationResult; | 551 |
| 552 DartObjectImpl fieldValue; |
| 553 if (strongMode) { |
| 554 fieldValue = field.constantInitializer.accept(fieldInitVisitor); |
| 555 } else { |
| 556 fieldValue = field.evaluationResult?.value; |
| 557 } |
527 // It is possible that the evaluation result is null. | 558 // It is possible that the evaluation result is null. |
528 // This happens for example when we have duplicate fields. | 559 // This happens for example when we have duplicate fields. |
529 // class Test {final x = 1; final x = 2; const Test();} | 560 // class Test {final x = 1; final x = 2; const Test();} |
530 if (evaluationResult == null) { | 561 if (fieldValue == null) { |
531 continue; | 562 continue; |
532 } | 563 } |
533 // Match the value and the type. | 564 // Match the value and the type. |
534 DartType fieldType = | 565 DartType fieldType = |
535 FieldMember.from(field, constructor.returnType).type; | 566 FieldMember.from(field, constructor.returnType).type; |
536 DartObjectImpl fieldValue = evaluationResult.value; | |
537 if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) { | 567 if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) { |
538 errorReporter.reportErrorForNode( | 568 errorReporter.reportErrorForNode( |
539 CheckedModeCompileTimeErrorCode | 569 CheckedModeCompileTimeErrorCode |
540 .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, | 570 .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, |
541 node, | 571 node, |
542 [fieldValue.type, field.name, fieldType]); | 572 [fieldValue.type, field.name, fieldType]); |
543 } | 573 } |
544 fieldMap[field.name] = fieldValue; | 574 fieldMap[field.name] = fieldValue; |
545 } | 575 } |
546 } | 576 } |
547 // Now evaluate the constructor declaration. | 577 // Now evaluate the constructor declaration. |
548 HashMap<String, DartObjectImpl> parameterMap = | 578 HashMap<String, DartObjectImpl> parameterMap = |
549 new HashMap<String, DartObjectImpl>(); | 579 new HashMap<String, DartObjectImpl>(); |
550 List<ParameterElement> parameters = constructor.parameters; | 580 List<ParameterElement> parameters = constructor.parameters; |
551 int parameterCount = parameters.length; | 581 int parameterCount = parameters.length; |
| 582 |
552 for (int i = 0; i < parameterCount; i++) { | 583 for (int i = 0; i < parameterCount; i++) { |
553 ParameterElement parameter = parameters[i]; | 584 ParameterElement parameter = parameters[i]; |
554 ParameterElement baseParameter = parameter; | 585 ParameterElement baseParameter = parameter; |
555 while (baseParameter is ParameterMember) { | 586 while (baseParameter is ParameterMember) { |
556 baseParameter = (baseParameter as ParameterMember).baseElement; | 587 baseParameter = (baseParameter as ParameterMember).baseElement; |
557 } | 588 } |
558 DartObjectImpl argumentValue = null; | 589 DartObjectImpl argumentValue = null; |
559 AstNode errorTarget = null; | 590 AstNode errorTarget = null; |
560 if (baseParameter.parameterKind == ParameterKind.NAMED) { | 591 if (baseParameter.parameterKind == ParameterKind.NAMED) { |
561 argumentValue = namedArgumentValues[baseParameter.name]; | 592 argumentValue = namedArgumentValues[baseParameter.name]; |
562 errorTarget = namedArgumentNodes[baseParameter.name]; | 593 errorTarget = namedArgumentNodes[baseParameter.name]; |
563 } else if (i < argumentCount) { | 594 } else if (i < argumentCount) { |
564 argumentValue = argumentValues[i]; | 595 argumentValue = argumentValues[i]; |
565 errorTarget = argumentNodes[i]; | 596 errorTarget = argumentNodes[i]; |
566 } | 597 } |
567 if (errorTarget == null) { | 598 if (errorTarget == null) { |
568 // No argument node that we can direct error messages to, because we | 599 // No argument node that we can direct error messages to, because we |
569 // are handling an optional parameter that wasn't specified. So just | 600 // are handling an optional parameter that wasn't specified. So just |
570 // direct error messages to the constructor call. | 601 // direct error messages to the constructor call. |
571 errorTarget = node; | 602 errorTarget = node; |
572 } | 603 } |
573 if (argumentValue == null && baseParameter is ParameterElementImpl) { | 604 if (argumentValue == null && baseParameter is ParameterElementImpl) { |
574 // The parameter is an optional positional parameter for which no value | 605 // The parameter is an optional positional parameter for which no value |
575 // was provided, so use the default value. | 606 // was provided, so use the default value. |
576 validator.beforeGetParameterDefault(baseParameter); | 607 validator.beforeGetParameterDefault(baseParameter); |
577 EvaluationResultImpl evaluationResult = baseParameter.evaluationResult; | 608 if (strongMode && baseParameter is ConstVariableElement) { |
578 if (evaluationResult == null) { | 609 var defaultValue = |
579 // No default was provided, so the default value is null. | 610 (baseParameter as ConstVariableElement).constantInitializer; |
580 argumentValue = typeProvider.nullObject; | 611 if (defaultValue == null) { |
581 } else if (evaluationResult.value != null) { | 612 argumentValue = typeProvider.nullObject; |
582 argumentValue = evaluationResult.value; | 613 } else { |
| 614 argumentValue = defaultValue.accept(fieldInitVisitor); |
| 615 } |
| 616 } else { |
| 617 EvaluationResultImpl evaluationResult = |
| 618 baseParameter.evaluationResult; |
| 619 if (evaluationResult == null) { |
| 620 // No default was provided, so the default value is null. |
| 621 argumentValue = typeProvider.nullObject; |
| 622 } else if (evaluationResult.value != null) { |
| 623 argumentValue = evaluationResult.value; |
| 624 } |
583 } | 625 } |
584 } | 626 } |
585 if (argumentValue != null) { | 627 if (argumentValue != null) { |
586 if (!runtimeTypeMatch(argumentValue, parameter.type)) { | 628 if (!runtimeTypeMatch(argumentValue, parameter.type)) { |
587 errorReporter.reportErrorForNode( | 629 errorReporter.reportErrorForNode( |
588 CheckedModeCompileTimeErrorCode | 630 CheckedModeCompileTimeErrorCode |
589 .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | 631 .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
590 errorTarget, | 632 errorTarget, |
591 [argumentValue.type, parameter.type]); | 633 [argumentValue.type, parameter.type]); |
592 } | 634 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 } | 712 } |
671 // Evaluate explicit or implicit call to super(). | 713 // Evaluate explicit or implicit call to super(). |
672 InterfaceType superclass = definingClass.superclass; | 714 InterfaceType superclass = definingClass.superclass; |
673 if (superclass != null && !superclass.isObject) { | 715 if (superclass != null && !superclass.isObject) { |
674 ConstructorElement superConstructor = | 716 ConstructorElement superConstructor = |
675 superclass.lookUpConstructor(superName, constructor.library); | 717 superclass.lookUpConstructor(superName, constructor.library); |
676 if (superConstructor != null) { | 718 if (superConstructor != null) { |
677 if (superArguments == null) { | 719 if (superArguments == null) { |
678 superArguments = new NodeList<Expression>(null); | 720 superArguments = new NodeList<Expression>(null); |
679 } | 721 } |
| 722 |
680 evaluateSuperConstructorCall(node, fieldMap, superConstructor, | 723 evaluateSuperConstructorCall(node, fieldMap, superConstructor, |
681 superArguments, initializerVisitor, errorReporter); | 724 superArguments, initializerVisitor, errorReporter); |
682 } | 725 } |
683 } | 726 } |
684 return new DartObjectImpl(definingClass, new GenericState(fieldMap)); | 727 return new DartObjectImpl(definingClass, new GenericState(fieldMap)); |
685 } | 728 } |
686 | 729 |
687 void evaluateSuperConstructorCall( | 730 void evaluateSuperConstructorCall( |
688 AstNode node, | 731 AstNode node, |
689 HashMap<String, DartObjectImpl> fieldMap, | 732 HashMap<String, DartObjectImpl> fieldMap, |
690 ConstructorElement superConstructor, | 733 ConstructorElement superConstructor, |
691 NodeList<Expression> superArguments, | 734 List<Expression> superArguments, |
692 ConstantVisitor initializerVisitor, | 735 ConstantVisitor initializerVisitor, |
693 ErrorReporter errorReporter) { | 736 ErrorReporter errorReporter) { |
694 if (superConstructor != null && superConstructor.isConst) { | 737 if (superConstructor != null && superConstructor.isConst) { |
695 DartObjectImpl evaluationResult = evaluateConstructorCall(node, | 738 DartObjectImpl evaluationResult = evaluateConstructorCall(node, |
696 superArguments, superConstructor, initializerVisitor, errorReporter); | 739 superArguments, superConstructor, initializerVisitor, errorReporter); |
697 if (evaluationResult != null) { | 740 if (evaluationResult != null) { |
698 fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult; | 741 fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult; |
699 } | 742 } |
700 } | 743 } |
701 } | 744 } |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 // TODO(brianwilkerson) Figure out which error to report. | 1267 // TODO(brianwilkerson) Figure out which error to report. |
1225 _error(node, null); | 1268 _error(node, null); |
1226 return null; | 1269 return null; |
1227 } | 1270 } |
1228 ConstructorElement constructor = node.staticElement; | 1271 ConstructorElement constructor = node.staticElement; |
1229 if (constructor == null) { | 1272 if (constructor == null) { |
1230 // Couldn't resolve the constructor so we can't compute a value. No | 1273 // Couldn't resolve the constructor so we can't compute a value. No |
1231 // problem - the error has already been reported. | 1274 // problem - the error has already been reported. |
1232 return null; | 1275 return null; |
1233 } | 1276 } |
| 1277 |
1234 return evaluationEngine.evaluateConstructorCall( | 1278 return evaluationEngine.evaluateConstructorCall( |
1235 node, node.argumentList.arguments, constructor, this, _errorReporter); | 1279 node, node.argumentList.arguments, constructor, this, _errorReporter); |
1236 } | 1280 } |
1237 | 1281 |
1238 @override | 1282 @override |
1239 DartObjectImpl visitIntegerLiteral(IntegerLiteral node) => | 1283 DartObjectImpl visitIntegerLiteral(IntegerLiteral node) => |
1240 new DartObjectImpl(_typeProvider.intType, new IntState(node.value)); | 1284 new DartObjectImpl(_typeProvider.intType, new IntState(node.value)); |
1241 | 1285 |
1242 @override | 1286 @override |
1243 DartObjectImpl visitInterpolationExpression(InterpolationExpression node) { | 1287 DartObjectImpl visitInterpolationExpression(InterpolationExpression node) { |
(...skipping 23 matching lines...) Expand all Loading... |
1267 if (elementResult == null) { | 1311 if (elementResult == null) { |
1268 errorOccurred = true; | 1312 errorOccurred = true; |
1269 } else { | 1313 } else { |
1270 elements.add(elementResult); | 1314 elements.add(elementResult); |
1271 } | 1315 } |
1272 } | 1316 } |
1273 if (errorOccurred) { | 1317 if (errorOccurred) { |
1274 return null; | 1318 return null; |
1275 } | 1319 } |
1276 DartType elementType = _typeProvider.dynamicType; | 1320 DartType elementType = _typeProvider.dynamicType; |
1277 if (node.typeArguments != null && | 1321 NodeList<TypeName> typeArgs = node.typeArguments?.arguments; |
1278 node.typeArguments.arguments.length == 1) { | 1322 if (typeArgs?.length == 1) { |
1279 DartType type = node.typeArguments.arguments[0].type; | 1323 DartType type = visitTypeName(typeArgs[0]).toTypeValue(); |
1280 if (type != null) { | 1324 if (type != null) { |
1281 elementType = type; | 1325 elementType = type; |
1282 } | 1326 } |
1283 } | 1327 } |
1284 InterfaceType listType = _typeProvider.listType.instantiate([elementType]); | 1328 InterfaceType listType = _typeProvider.listType.instantiate([elementType]); |
1285 return new DartObjectImpl(listType, new ListState(elements)); | 1329 return new DartObjectImpl(listType, new ListState(elements)); |
1286 } | 1330 } |
1287 | 1331 |
1288 @override | 1332 @override |
1289 DartObjectImpl visitMapLiteral(MapLiteral node) { | 1333 DartObjectImpl visitMapLiteral(MapLiteral node) { |
(...skipping 12 matching lines...) Expand all Loading... |
1302 errorOccurred = true; | 1346 errorOccurred = true; |
1303 } else { | 1347 } else { |
1304 map[keyResult] = valueResult; | 1348 map[keyResult] = valueResult; |
1305 } | 1349 } |
1306 } | 1350 } |
1307 if (errorOccurred) { | 1351 if (errorOccurred) { |
1308 return null; | 1352 return null; |
1309 } | 1353 } |
1310 DartType keyType = _typeProvider.dynamicType; | 1354 DartType keyType = _typeProvider.dynamicType; |
1311 DartType valueType = _typeProvider.dynamicType; | 1355 DartType valueType = _typeProvider.dynamicType; |
1312 if (node.typeArguments != null && | 1356 NodeList<TypeName> typeArgs = node.typeArguments?.arguments; |
1313 node.typeArguments.arguments.length == 2) { | 1357 if (typeArgs?.length == 2) { |
1314 DartType keyTypeCandidate = node.typeArguments.arguments[0].type; | 1358 DartType keyTypeCandidate = visitTypeName(typeArgs[0]).toTypeValue(); |
1315 if (keyTypeCandidate != null) { | 1359 if (keyTypeCandidate != null) { |
1316 keyType = keyTypeCandidate; | 1360 keyType = keyTypeCandidate; |
1317 } | 1361 } |
1318 DartType valueTypeCandidate = node.typeArguments.arguments[1].type; | 1362 DartType valueTypeCandidate = visitTypeName(typeArgs[1]).toTypeValue(); |
1319 if (valueTypeCandidate != null) { | 1363 if (valueTypeCandidate != null) { |
1320 valueType = valueTypeCandidate; | 1364 valueType = valueTypeCandidate; |
1321 } | 1365 } |
1322 } | 1366 } |
1323 InterfaceType mapType = | 1367 InterfaceType mapType = |
1324 _typeProvider.mapType.instantiate([keyType, valueType]); | 1368 _typeProvider.mapType.instantiate([keyType, valueType]); |
1325 return new DartObjectImpl(mapType, new MapState(map)); | 1369 return new DartObjectImpl(mapType, new MapState(map)); |
1326 } | 1370 } |
1327 | 1371 |
1328 @override | 1372 @override |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 for (int i = 0; i < components.length; i++) { | 1502 for (int i = 0; i < components.length; i++) { |
1459 if (i > 0) { | 1503 if (i > 0) { |
1460 buffer.writeCharCode(0x2E); | 1504 buffer.writeCharCode(0x2E); |
1461 } | 1505 } |
1462 buffer.write(components[i].lexeme); | 1506 buffer.write(components[i].lexeme); |
1463 } | 1507 } |
1464 return new DartObjectImpl( | 1508 return new DartObjectImpl( |
1465 _typeProvider.symbolType, new SymbolState(buffer.toString())); | 1509 _typeProvider.symbolType, new SymbolState(buffer.toString())); |
1466 } | 1510 } |
1467 | 1511 |
| 1512 @override |
| 1513 DartObjectImpl visitTypeName(TypeName node) { |
| 1514 return typeConstant(evaluateType(node.type)); |
| 1515 } |
| 1516 |
| 1517 /** |
| 1518 * Given a [type], returns the constant value that contains that type value. |
| 1519 */ |
| 1520 DartObjectImpl typeConstant(DartType type) { |
| 1521 return new DartObjectImpl(_typeProvider.typeType, new TypeState(type)); |
| 1522 } |
| 1523 |
| 1524 /** |
| 1525 * Given a [type] that may contain free type variables, evaluate them against |
| 1526 * the current lexical environment and return the substituted type. |
| 1527 */ |
| 1528 DartType evaluateType(DartType type) { |
| 1529 if (type is TypeParameterType) { |
| 1530 String name = type.name; |
| 1531 if (_lexicalEnvironment != null) { |
| 1532 return _lexicalEnvironment[name]?.toTypeValue() ?? type; |
| 1533 } |
| 1534 return type; |
| 1535 } |
| 1536 if (type is ParameterizedType) { |
| 1537 List<DartType> typeArguments; |
| 1538 for (int i = 0; i < type.typeArguments.length; i++) { |
| 1539 DartType ta = type.typeArguments[i]; |
| 1540 DartType t = evaluateType(ta); |
| 1541 if (!identical(t, ta)) { |
| 1542 if (typeArguments == null) { |
| 1543 typeArguments = type.typeArguments.toList(growable: false); |
| 1544 } |
| 1545 typeArguments[i] = t; |
| 1546 } |
| 1547 } |
| 1548 if (typeArguments == null) return type; |
| 1549 return type.substitute2(typeArguments, type.typeArguments); |
| 1550 } |
| 1551 return type; |
| 1552 } |
| 1553 |
1468 /** | 1554 /** |
1469 * Create an error associated with the given [node]. The error will have the | 1555 * Create an error associated with the given [node]. The error will have the |
1470 * given error [code]. | 1556 * given error [code]. |
1471 */ | 1557 */ |
1472 void _error(AstNode node, ErrorCode code) { | 1558 void _error(AstNode node, ErrorCode code) { |
1473 _errorReporter.reportErrorForNode( | 1559 _errorReporter.reportErrorForNode( |
1474 code ?? CompileTimeErrorCode.INVALID_CONSTANT, node); | 1560 code ?? CompileTimeErrorCode.INVALID_CONSTANT, node); |
1475 } | 1561 } |
1476 | 1562 |
1477 /** | 1563 /** |
(...skipping 12 matching lines...) Expand all Loading... |
1490 } | 1576 } |
1491 } else if (variableElement is ExecutableElement) { | 1577 } else if (variableElement is ExecutableElement) { |
1492 ExecutableElement function = element; | 1578 ExecutableElement function = element; |
1493 if (function.isStatic) { | 1579 if (function.isStatic) { |
1494 ParameterizedType functionType = function.type; | 1580 ParameterizedType functionType = function.type; |
1495 if (functionType == null) { | 1581 if (functionType == null) { |
1496 functionType = _typeProvider.functionType; | 1582 functionType = _typeProvider.functionType; |
1497 } | 1583 } |
1498 return new DartObjectImpl(functionType, new FunctionState(function)); | 1584 return new DartObjectImpl(functionType, new FunctionState(function)); |
1499 } | 1585 } |
1500 } else if (variableElement is ClassElement || | 1586 } else if (variableElement is TypeDefiningElement) { |
1501 variableElement is FunctionTypeAliasElement || | 1587 return new DartObjectImpl( |
1502 variableElement is DynamicElementImpl) { | 1588 _typeProvider.typeType, new TypeState(variableElement.type)); |
1503 return new DartObjectImpl(_typeProvider.typeType, new TypeState(element)); | |
1504 } | 1589 } |
1505 // TODO(brianwilkerson) Figure out which error to report. | 1590 // TODO(brianwilkerson) Figure out which error to report. |
1506 _error(node, null); | 1591 _error(node, null); |
1507 return null; | 1592 return null; |
1508 } | 1593 } |
1509 | 1594 |
1510 /** | 1595 /** |
1511 * Return `true` if the given [targetResult] represents a string and the | 1596 * Return `true` if the given [targetResult] represents a string and the |
1512 * [identifier] is "length". | 1597 * [identifier] is "length". |
1513 */ | 1598 */ |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 } | 2069 } |
1985 | 2070 |
1986 @override | 2071 @override |
1987 String toString() { | 2072 String toString() { |
1988 if (value == null) { | 2073 if (value == null) { |
1989 return "error"; | 2074 return "error"; |
1990 } | 2075 } |
1991 return value.toString(); | 2076 return value.toString(); |
1992 } | 2077 } |
1993 } | 2078 } |
OLD | NEW |