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