| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.src.task.dart; | 5 library analyzer.src.task.dart; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:math' as math; | |
| 9 | 8 |
| 10 import 'package:analyzer/src/context/cache.dart'; | 9 import 'package:analyzer/src/context/cache.dart'; |
| 11 import 'package:analyzer/src/generated/ast.dart'; | 10 import 'package:analyzer/src/generated/ast.dart'; |
| 12 import 'package:analyzer/src/generated/constant.dart'; | 11 import 'package:analyzer/src/generated/constant.dart'; |
| 13 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
| 14 import 'package:analyzer/src/generated/engine.dart' | 13 import 'package:analyzer/src/generated/engine.dart' |
| 15 hide AnalysisCache, AnalysisTask; | 14 hide AnalysisCache, AnalysisTask; |
| 16 import 'package:analyzer/src/generated/error.dart'; | 15 import 'package:analyzer/src/generated/error.dart'; |
| 17 import 'package:analyzer/src/generated/error_verifier.dart'; | 16 import 'package:analyzer/src/generated/error_verifier.dart'; |
| 18 import 'package:analyzer/src/generated/java_engine.dart'; | 17 import 'package:analyzer/src/generated/java_engine.dart'; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 * | 51 * |
| 53 * The list will be empty if there were no errors, but will not be `null`. | 52 * The list will be empty if there were no errors, but will not be `null`. |
| 54 * | 53 * |
| 55 * The result is only available for [Source]s representing a library. | 54 * The result is only available for [Source]s representing a library. |
| 56 */ | 55 */ |
| 57 final ListResultDescriptor<AnalysisError> BUILD_LIBRARY_ERRORS = | 56 final ListResultDescriptor<AnalysisError> BUILD_LIBRARY_ERRORS = |
| 58 new ListResultDescriptor<AnalysisError>( | 57 new ListResultDescriptor<AnalysisError>( |
| 59 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS); | 58 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS); |
| 60 | 59 |
| 61 /** | 60 /** |
| 62 * The [ClassElement]s of a [Source] representing a Dart library. | |
| 63 * | |
| 64 * The list contains the elements for all of the classes defined in the library, | |
| 65 * not just those in the defining compilation unit. The list will be empty if | |
| 66 * there are no classes, but will not be `null`. | |
| 67 */ | |
| 68 final ListResultDescriptor<ClassElement> CLASS_ELEMENTS = | |
| 69 new ListResultDescriptor<ClassElement>('CLASS_ELEMENTS', null, | |
| 70 cachingPolicy: ELEMENT_CACHING_POLICY); | |
| 71 | |
| 72 /** | |
| 73 * A list of the [ConstantEvaluationTarget]s defined in a unit. This includes | 61 * A list of the [ConstantEvaluationTarget]s defined in a unit. This includes |
| 74 * constants defined at top level, statically inside classes, and local to | 62 * constants defined at top level, statically inside classes, and local to |
| 75 * functions, as well as constant constructors, annotations, and default values | 63 * functions, as well as constant constructors, annotations, and default values |
| 76 * of parameters to constant constructors. | 64 * of parameters to constant constructors. |
| 77 */ | 65 */ |
| 78 final ListResultDescriptor<ConstantEvaluationTarget> COMPILATION_UNIT_CONSTANTS
= | 66 final ListResultDescriptor<ConstantEvaluationTarget> COMPILATION_UNIT_CONSTANTS
= |
| 79 new ListResultDescriptor<ConstantEvaluationTarget>( | 67 new ListResultDescriptor<ConstantEvaluationTarget>( |
| 80 'COMPILATION_UNIT_CONSTANTS', null, | 68 'COMPILATION_UNIT_CONSTANTS', null, |
| 81 cachingPolicy: ELEMENT_CACHING_POLICY); | 69 cachingPolicy: ELEMENT_CACHING_POLICY); |
| 82 | 70 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 105 /** | 93 /** |
| 106 * A [ConstantEvaluationTarget] that has been successfully constant-evaluated. | 94 * A [ConstantEvaluationTarget] that has been successfully constant-evaluated. |
| 107 * | 95 * |
| 108 * TODO(paulberry): is ELEMENT_CACHING_POLICY the correct caching policy? | 96 * TODO(paulberry): is ELEMENT_CACHING_POLICY the correct caching policy? |
| 109 */ | 97 */ |
| 110 final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE = | 98 final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE = |
| 111 new ResultDescriptor<ConstantEvaluationTarget>('CONSTANT_VALUE', null, | 99 new ResultDescriptor<ConstantEvaluationTarget>('CONSTANT_VALUE', null, |
| 112 cachingPolicy: ELEMENT_CACHING_POLICY); | 100 cachingPolicy: ELEMENT_CACHING_POLICY); |
| 113 | 101 |
| 114 /** | 102 /** |
| 115 * The [ConstructorElement]s of a [ClassElement]. | |
| 116 */ | |
| 117 final ListResultDescriptor<ConstructorElement> CONSTRUCTORS = | |
| 118 new ListResultDescriptor<ConstructorElement>('CONSTRUCTORS', null); | |
| 119 | |
| 120 /** | |
| 121 * The errors produced while building a [ClassElement] constructors. | |
| 122 * | |
| 123 * The list will be empty if there were no errors, but will not be `null`. | |
| 124 * | |
| 125 * The result is only available for targets representing a [ClassElement]. | |
| 126 */ | |
| 127 final ListResultDescriptor<AnalysisError> CONSTRUCTORS_ERRORS = | |
| 128 new ListResultDescriptor<AnalysisError>( | |
| 129 'CONSTRUCTORS_ERRORS', AnalysisError.NO_ERRORS); | |
| 130 | |
| 131 /** | |
| 132 * The sources representing the libraries that include a given source as a part. | 103 * The sources representing the libraries that include a given source as a part. |
| 133 * | 104 * |
| 134 * The result is only available for [Source]s representing a compilation unit. | 105 * The result is only available for [Source]s representing a compilation unit. |
| 135 */ | 106 */ |
| 136 final ListResultDescriptor<Source> CONTAINING_LIBRARIES = | 107 final ListResultDescriptor<Source> CONTAINING_LIBRARIES = |
| 137 new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', Source.EMPTY_LIST); | 108 new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', Source.EMPTY_LIST); |
| 138 | 109 |
| 139 /** | 110 /** |
| 140 * The [ResultCachingPolicy] for [Element]s. | 111 * The [ResultCachingPolicy] for [Element]s. |
| 141 */ | 112 */ |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 * | 197 * |
| 227 * [LIBRARY_ELEMENT4] plus resolved types for every element. | 198 * [LIBRARY_ELEMENT4] plus resolved types for every element. |
| 228 * | 199 * |
| 229 * The result is only available for [Source]s representing a library. | 200 * The result is only available for [Source]s representing a library. |
| 230 */ | 201 */ |
| 231 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT5 = | 202 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT5 = |
| 232 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT5', null, | 203 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT5', null, |
| 233 cachingPolicy: ELEMENT_CACHING_POLICY); | 204 cachingPolicy: ELEMENT_CACHING_POLICY); |
| 234 | 205 |
| 235 /** | 206 /** |
| 236 * The partial [LibraryElement] associated with a library. | |
| 237 * | |
| 238 * [LIBRARY_ELEMENT5] plus resolved elements and types for all expressions. | |
| 239 * | |
| 240 * The result is only available for [Source]s representing a library. | |
| 241 */ | |
| 242 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT6 = | |
| 243 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT6', null, | |
| 244 cachingPolicy: ELEMENT_CACHING_POLICY); | |
| 245 | |
| 246 /** | |
| 247 * The flag specifying whether all analysis errors are computed in a specific | 207 * The flag specifying whether all analysis errors are computed in a specific |
| 248 * library. | 208 * library. |
| 249 * | 209 * |
| 250 * The result is only available for [Source]s representing a library. | 210 * The result is only available for [Source]s representing a library. |
| 251 */ | 211 */ |
| 252 final ResultDescriptor<bool> LIBRARY_ERRORS_READY = | 212 final ResultDescriptor<bool> LIBRARY_ERRORS_READY = |
| 253 new ResultDescriptor<bool>('LIBRARY_ERRORS_READY', false); | 213 new ResultDescriptor<bool>('LIBRARY_ERRORS_READY', false); |
| 254 | 214 |
| 255 /** | 215 /** |
| 256 * The analysis errors associated with a compilation unit in a specific library. | 216 * The analysis errors associated with a compilation unit in a specific library. |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 * but with duplications removed. | 380 * but with duplications removed. |
| 421 */ | 381 */ |
| 422 List<AnalysisError> removeDuplicateErrors(List<AnalysisError> errors) { | 382 List<AnalysisError> removeDuplicateErrors(List<AnalysisError> errors) { |
| 423 if (errors.isEmpty) { | 383 if (errors.isEmpty) { |
| 424 return errors; | 384 return errors; |
| 425 } | 385 } |
| 426 return errors.toSet().toList(); | 386 return errors.toSet().toList(); |
| 427 } | 387 } |
| 428 | 388 |
| 429 /** | 389 /** |
| 430 * A task that builds implicit constructors for a [ClassElement], or keeps | |
| 431 * the existing explicit constructors if the class has them. | |
| 432 */ | |
| 433 class BuildClassConstructorsTask extends SourceBasedAnalysisTask { | |
| 434 /** | |
| 435 * The name of the [CONSTRUCTORS] input for the superclass. | |
| 436 */ | |
| 437 static const String SUPER_CONSTRUCTORS = 'SUPER_CONSTRUCTORS'; | |
| 438 | |
| 439 /** | |
| 440 * The task descriptor describing this kind of task. | |
| 441 */ | |
| 442 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( | |
| 443 'BuildConstructorsForClassTask', createTask, buildInputs, | |
| 444 <ResultDescriptor>[CONSTRUCTORS, CONSTRUCTORS_ERRORS]); | |
| 445 | |
| 446 BuildClassConstructorsTask( | |
| 447 InternalAnalysisContext context, AnalysisTarget target) | |
| 448 : super(context, target); | |
| 449 | |
| 450 @override | |
| 451 TaskDescriptor get descriptor => DESCRIPTOR; | |
| 452 | |
| 453 @override | |
| 454 void internalPerform() { | |
| 455 List<AnalysisError> errors = <AnalysisError>[]; | |
| 456 // | |
| 457 // Prepare inputs. | |
| 458 // | |
| 459 ClassElementImpl classElement = this.target; | |
| 460 List<ConstructorElement> superConstructors = inputs[SUPER_CONSTRUCTORS]; | |
| 461 DartType superType = classElement.supertype; | |
| 462 if (superType == null) { | |
| 463 return; | |
| 464 } | |
| 465 // | |
| 466 // Shortcut for ClassElement(s) without implicit constructors. | |
| 467 // | |
| 468 if (superConstructors == null) { | |
| 469 outputs[CONSTRUCTORS] = classElement.constructors; | |
| 470 outputs[CONSTRUCTORS_ERRORS] = AnalysisError.NO_ERRORS; | |
| 471 return; | |
| 472 } | |
| 473 // | |
| 474 // ClassTypeAlias | |
| 475 // | |
| 476 if (classElement.isMixinApplication) { | |
| 477 List<ConstructorElement> implicitConstructors = | |
| 478 new List<ConstructorElement>(); | |
| 479 void callback(ConstructorElement explicitConstructor, | |
| 480 List<DartType> parameterTypes, List<DartType> argumentTypes) { | |
| 481 implicitConstructors.add(_createImplicitContructor(classElement.type, | |
| 482 explicitConstructor, parameterTypes, argumentTypes)); | |
| 483 } | |
| 484 if (_findForwardedConstructors(classElement, superType, callback)) { | |
| 485 if (implicitConstructors.isEmpty) { | |
| 486 errors.add(new AnalysisError(classElement.source, | |
| 487 classElement.nameOffset, classElement.name.length, | |
| 488 CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, | |
| 489 [superType.element.name])); | |
| 490 } else { | |
| 491 classElement.constructors = implicitConstructors; | |
| 492 } | |
| 493 } | |
| 494 outputs[CONSTRUCTORS] = classElement.constructors; | |
| 495 outputs[CONSTRUCTORS_ERRORS] = errors; | |
| 496 } | |
| 497 // | |
| 498 // ClassDeclaration | |
| 499 // | |
| 500 if (!classElement.isMixinApplication) { | |
| 501 bool constructorFound = false; | |
| 502 void callback(ConstructorElement explicitConstructor, | |
| 503 List<DartType> parameterTypes, List<DartType> argumentTypes) { | |
| 504 constructorFound = true; | |
| 505 } | |
| 506 if (_findForwardedConstructors(classElement, superType, callback) && | |
| 507 !constructorFound) { | |
| 508 SourceRange withRange = classElement.withClauseRange; | |
| 509 errors.add(new AnalysisError(classElement.source, withRange.offset, | |
| 510 withRange.length, CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, | |
| 511 [superType.element.name])); | |
| 512 classElement.mixinErrorsReported = true; | |
| 513 } | |
| 514 outputs[CONSTRUCTORS] = classElement.constructors; | |
| 515 outputs[CONSTRUCTORS_ERRORS] = errors; | |
| 516 } | |
| 517 } | |
| 518 | |
| 519 /** | |
| 520 * Return a map from the names of the inputs of this kind of task to the task | |
| 521 * input descriptors describing those inputs for a task with the | |
| 522 * given [classElement]. | |
| 523 */ | |
| 524 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { | |
| 525 ClassElement element = target; | |
| 526 Source librarySource = element.library.source; | |
| 527 DartType superType = element.supertype; | |
| 528 if (superType is InterfaceType) { | |
| 529 if (element.isMixinApplication || element.mixins.isNotEmpty) { | |
| 530 ClassElement superElement = superType.element; | |
| 531 return <String, TaskInput>{ | |
| 532 'libraryDep': LIBRARY_ELEMENT5.of(librarySource), | |
| 533 SUPER_CONSTRUCTORS: CONSTRUCTORS.of(superElement) | |
| 534 }; | |
| 535 } | |
| 536 } | |
| 537 // No implicit constructors. | |
| 538 // Depend on LIBRARY_ELEMENT5 for invalidation. | |
| 539 return <String, TaskInput>{ | |
| 540 'libraryDep': LIBRARY_ELEMENT5.of(librarySource) | |
| 541 }; | |
| 542 } | |
| 543 | |
| 544 /** | |
| 545 * Create a [BuildClassConstructorsTask] based on the given | |
| 546 * [target] in the given [context]. | |
| 547 */ | |
| 548 static BuildClassConstructorsTask createTask( | |
| 549 AnalysisContext context, AnalysisTarget target) { | |
| 550 return new BuildClassConstructorsTask(context, target); | |
| 551 } | |
| 552 | |
| 553 /** | |
| 554 * Create an implicit constructor that is copied from the given | |
| 555 * [explicitConstructor], but that is in the given class. | |
| 556 * | |
| 557 * [classType] - the class in which the implicit constructor is defined. | |
| 558 * [explicitConstructor] - the constructor on which the implicit constructor | |
| 559 * is modeled. | |
| 560 * [parameterTypes] - the types to be replaced when creating parameters. | |
| 561 * [argumentTypes] - the types with which the parameters are to be replaced. | |
| 562 */ | |
| 563 static ConstructorElement _createImplicitContructor(InterfaceType classType, | |
| 564 ConstructorElement explicitConstructor, List<DartType> parameterTypes, | |
| 565 List<DartType> argumentTypes) { | |
| 566 ConstructorElementImpl implicitConstructor = | |
| 567 new ConstructorElementImpl(explicitConstructor.name, -1); | |
| 568 implicitConstructor.synthetic = true; | |
| 569 implicitConstructor.redirectedConstructor = explicitConstructor; | |
| 570 implicitConstructor.const2 = explicitConstructor.isConst; | |
| 571 implicitConstructor.returnType = classType; | |
| 572 List<ParameterElement> explicitParameters = explicitConstructor.parameters; | |
| 573 int count = explicitParameters.length; | |
| 574 if (count > 0) { | |
| 575 List<ParameterElement> implicitParameters = | |
| 576 new List<ParameterElement>(count); | |
| 577 for (int i = 0; i < count; i++) { | |
| 578 ParameterElement explicitParameter = explicitParameters[i]; | |
| 579 ParameterElementImpl implicitParameter = | |
| 580 new ParameterElementImpl(explicitParameter.name, -1); | |
| 581 implicitParameter.const3 = explicitParameter.isConst; | |
| 582 implicitParameter.final2 = explicitParameter.isFinal; | |
| 583 implicitParameter.parameterKind = explicitParameter.parameterKind; | |
| 584 implicitParameter.synthetic = true; | |
| 585 implicitParameter.type = | |
| 586 explicitParameter.type.substitute2(argumentTypes, parameterTypes); | |
| 587 implicitParameters[i] = implicitParameter; | |
| 588 } | |
| 589 implicitConstructor.parameters = implicitParameters; | |
| 590 } | |
| 591 FunctionTypeImpl type = new FunctionTypeImpl(implicitConstructor); | |
| 592 type.typeArguments = classType.typeArguments; | |
| 593 implicitConstructor.type = type; | |
| 594 return implicitConstructor; | |
| 595 } | |
| 596 | |
| 597 /** | |
| 598 * Find all the constructors that should be forwarded from the given | |
| 599 * [superType], to the class or mixin application [classElement], | |
| 600 * and pass information about them to [callback]. | |
| 601 * | |
| 602 * Return `true` if some constructors were considered. (A `false` return value | |
| 603 * can only happen if the supeclass is a built-in type, in which case it | |
| 604 * can't be used as a mixin anyway). | |
| 605 */ | |
| 606 static bool _findForwardedConstructors(ClassElementImpl classElement, | |
| 607 InterfaceType superType, void callback( | |
| 608 ConstructorElement explicitConstructor, List<DartType> parameterTypes, | |
| 609 List<DartType> argumentTypes)) { | |
| 610 if (superType == null) { | |
| 611 return false; | |
| 612 } | |
| 613 ClassElement superclassElement = superType.element; | |
| 614 List<ConstructorElement> constructors = superclassElement.constructors; | |
| 615 int count = constructors.length; | |
| 616 if (count == 0) { | |
| 617 return false; | |
| 618 } | |
| 619 List<DartType> parameterTypes = | |
| 620 TypeParameterTypeImpl.getTypes(superType.typeParameters); | |
| 621 List<DartType> argumentTypes = _getArgumentTypes(superType, parameterTypes); | |
| 622 for (int i = 0; i < count; i++) { | |
| 623 ConstructorElement explicitConstructor = constructors[i]; | |
| 624 if (!explicitConstructor.isFactory && | |
| 625 classElement.isSuperConstructorAccessible(explicitConstructor)) { | |
| 626 callback(explicitConstructor, parameterTypes, argumentTypes); | |
| 627 } | |
| 628 } | |
| 629 return true; | |
| 630 } | |
| 631 | |
| 632 /** | |
| 633 * Return a list of argument types that corresponds to the [parameterTypes] | |
| 634 * and that are derived from the type arguments of the given [superType]. | |
| 635 */ | |
| 636 static List<DartType> _getArgumentTypes( | |
| 637 InterfaceType superType, List<DartType> parameterTypes) { | |
| 638 DynamicTypeImpl dynamic = DynamicTypeImpl.instance; | |
| 639 int parameterCount = parameterTypes.length; | |
| 640 List<DartType> types = new List<DartType>(parameterCount); | |
| 641 if (superType == null) { | |
| 642 types = new List<DartType>.filled(parameterCount, dynamic); | |
| 643 } else { | |
| 644 List<DartType> typeArguments = superType.typeArguments; | |
| 645 int argumentCount = math.min(typeArguments.length, parameterCount); | |
| 646 for (int i = 0; i < argumentCount; i++) { | |
| 647 types[i] = typeArguments[i]; | |
| 648 } | |
| 649 for (int i = argumentCount; i < parameterCount; i++) { | |
| 650 types[i] = dynamic; | |
| 651 } | |
| 652 } | |
| 653 return types; | |
| 654 } | |
| 655 } | |
| 656 | |
| 657 /** | |
| 658 * A task that builds a compilation unit element for a single compilation unit. | 390 * A task that builds a compilation unit element for a single compilation unit. |
| 659 */ | 391 */ |
| 660 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask { | 392 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask { |
| 661 /** | 393 /** |
| 662 * The name of the input whose value is the AST for the compilation unit. | 394 * The name of the input whose value is the AST for the compilation unit. |
| 663 */ | 395 */ |
| 664 static const String PARSED_UNIT_INPUT_NAME = 'PARSED_UNIT_INPUT_NAME'; | 396 static const String PARSED_UNIT_INPUT_NAME = 'PARSED_UNIT_INPUT_NAME'; |
| 665 | 397 |
| 666 /** | 398 /** |
| 667 * The task descriptor describing this kind of task. | 399 * The task descriptor describing this kind of task. |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1121 * Create a [BuildExportNamespaceTask] based on the given [target] in | 853 * Create a [BuildExportNamespaceTask] based on the given [target] in |
| 1122 * the given [context]. | 854 * the given [context]. |
| 1123 */ | 855 */ |
| 1124 static BuildExportNamespaceTask createTask( | 856 static BuildExportNamespaceTask createTask( |
| 1125 AnalysisContext context, AnalysisTarget target) { | 857 AnalysisContext context, AnalysisTarget target) { |
| 1126 return new BuildExportNamespaceTask(context, target); | 858 return new BuildExportNamespaceTask(context, target); |
| 1127 } | 859 } |
| 1128 } | 860 } |
| 1129 | 861 |
| 1130 /** | 862 /** |
| 1131 * This task builds [LIBRARY_ELEMENT6] by forcing building constructors for | |
| 1132 * all the classes of the defining and part units of a library. | |
| 1133 */ | |
| 1134 class BuildLibraryConstructorsTask extends SourceBasedAnalysisTask { | |
| 1135 /** | |
| 1136 * The name of the [LIBRARY_ELEMENT5] input. | |
| 1137 */ | |
| 1138 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; | |
| 1139 | |
| 1140 /** | |
| 1141 * The task descriptor describing this kind of task. | |
| 1142 */ | |
| 1143 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( | |
| 1144 'BuildLibraryConstructorsTask', createTask, buildInputs, | |
| 1145 <ResultDescriptor>[LIBRARY_ELEMENT6]); | |
| 1146 | |
| 1147 BuildLibraryConstructorsTask( | |
| 1148 InternalAnalysisContext context, AnalysisTarget target) | |
| 1149 : super(context, target); | |
| 1150 | |
| 1151 @override | |
| 1152 TaskDescriptor get descriptor => DESCRIPTOR; | |
| 1153 | |
| 1154 @override | |
| 1155 void internalPerform() { | |
| 1156 LibraryElement library = getRequiredInput(LIBRARY_INPUT); | |
| 1157 outputs[LIBRARY_ELEMENT6] = library; | |
| 1158 } | |
| 1159 | |
| 1160 /** | |
| 1161 * Return a map from the names of the inputs of this kind of task to the task | |
| 1162 * input descriptors describing those inputs for a task with the | |
| 1163 * given [target]. | |
| 1164 */ | |
| 1165 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { | |
| 1166 Source source = target; | |
| 1167 return <String, TaskInput>{ | |
| 1168 LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source), | |
| 1169 'resolvedConstructors': CLASS_ELEMENTS.of(source).toListOf(CONSTRUCTORS), | |
| 1170 }; | |
| 1171 } | |
| 1172 | |
| 1173 /** | |
| 1174 * Create a [BuildLibraryConstructorsTask] based on the given [target] in | |
| 1175 * the given [context]. | |
| 1176 */ | |
| 1177 static BuildLibraryConstructorsTask createTask( | |
| 1178 AnalysisContext context, AnalysisTarget target) { | |
| 1179 return new BuildLibraryConstructorsTask(context, target); | |
| 1180 } | |
| 1181 } | |
| 1182 | |
| 1183 /** | |
| 1184 * A task that builds a library element for a Dart library. | 863 * A task that builds a library element for a Dart library. |
| 1185 */ | 864 */ |
| 1186 class BuildLibraryElementTask extends SourceBasedAnalysisTask { | 865 class BuildLibraryElementTask extends SourceBasedAnalysisTask { |
| 1187 /** | 866 /** |
| 1188 * The name of the input whose value is the defining [RESOLVED_UNIT1]. | 867 * The name of the input whose value is the defining [RESOLVED_UNIT1]. |
| 1189 */ | 868 */ |
| 1190 static const String DEFINING_UNIT_INPUT = 'DEFINING_UNIT_INPUT'; | 869 static const String DEFINING_UNIT_INPUT = 'DEFINING_UNIT_INPUT'; |
| 1191 | 870 |
| 1192 /** | 871 /** |
| 1193 * The name of the input whose value is a list of built [RESOLVED_UNIT1]s | 872 * The name of the input whose value is a list of built [RESOLVED_UNIT1]s |
| 1194 * of the parts sourced by a library. | 873 * of the parts sourced by a library. |
| 1195 */ | 874 */ |
| 1196 static const String PARTS_UNIT_INPUT = 'PARTS_UNIT_INPUT'; | 875 static const String PARTS_UNIT_INPUT = 'PARTS_UNIT_INPUT'; |
| 1197 | 876 |
| 1198 /** | 877 /** |
| 1199 * The task descriptor describing this kind of task. | 878 * The task descriptor describing this kind of task. |
| 1200 */ | 879 */ |
| 1201 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( | 880 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| 1202 'BuildLibraryElementTask', createTask, buildInputs, <ResultDescriptor>[ | 881 'BuildLibraryElementTask', createTask, buildInputs, <ResultDescriptor>[ |
| 1203 BUILD_LIBRARY_ERRORS, | 882 BUILD_LIBRARY_ERRORS, |
| 1204 CLASS_ELEMENTS, | |
| 1205 LIBRARY_ELEMENT1, | 883 LIBRARY_ELEMENT1, |
| 1206 IS_LAUNCHABLE | 884 IS_LAUNCHABLE |
| 1207 ]); | 885 ]); |
| 1208 | 886 |
| 1209 /** | 887 /** |
| 1210 * The constant used as an unknown common library name in parts. | 888 * The constant used as an unknown common library name in parts. |
| 1211 */ | 889 */ |
| 1212 static const String _UNKNOWN_LIBRARY_NAME = 'unknown-library-name'; | 890 static const String _UNKNOWN_LIBRARY_NAME = 'unknown-library-name'; |
| 1213 | 891 |
| 1214 /** | 892 /** |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 libraryElement.definingCompilationUnit = definingCompilationUnitElement; | 1008 libraryElement.definingCompilationUnit = definingCompilationUnitElement; |
| 1331 libraryElement.entryPoint = entryPoint; | 1009 libraryElement.entryPoint = entryPoint; |
| 1332 libraryElement.parts = sourcedCompilationUnits; | 1010 libraryElement.parts = sourcedCompilationUnits; |
| 1333 for (Directive directive in directivesToResolve) { | 1011 for (Directive directive in directivesToResolve) { |
| 1334 directive.element = libraryElement; | 1012 directive.element = libraryElement; |
| 1335 } | 1013 } |
| 1336 if (sourcedCompilationUnits.isNotEmpty) { | 1014 if (sourcedCompilationUnits.isNotEmpty) { |
| 1337 _patchTopLevelAccessors(libraryElement); | 1015 _patchTopLevelAccessors(libraryElement); |
| 1338 } | 1016 } |
| 1339 // | 1017 // |
| 1340 // Prepare all class elements. | |
| 1341 // | |
| 1342 List<ClassElement> classElements = libraryElement.units | |
| 1343 .map((CompilationUnitElement unitElement) => unitElement.types) | |
| 1344 .expand((List<ClassElement> unitClassElements) => unitClassElements) | |
| 1345 .toList(); | |
| 1346 // | |
| 1347 // Record outputs. | 1018 // Record outputs. |
| 1348 // | 1019 // |
| 1349 outputs[BUILD_LIBRARY_ERRORS] = errors; | 1020 outputs[BUILD_LIBRARY_ERRORS] = errors; |
| 1350 outputs[CLASS_ELEMENTS] = classElements; | |
| 1351 outputs[LIBRARY_ELEMENT1] = libraryElement; | 1021 outputs[LIBRARY_ELEMENT1] = libraryElement; |
| 1352 outputs[IS_LAUNCHABLE] = entryPoint != null; | 1022 outputs[IS_LAUNCHABLE] = entryPoint != null; |
| 1353 } | 1023 } |
| 1354 | 1024 |
| 1355 /** | 1025 /** |
| 1356 * Add all of the non-synthetic [getters] and [setters] defined in the given | 1026 * Add all of the non-synthetic [getters] and [setters] defined in the given |
| 1357 * [unit] that have no corresponding accessor to one of the given collections. | 1027 * [unit] that have no corresponding accessor to one of the given collections. |
| 1358 */ | 1028 */ |
| 1359 void _collectAccessors(Map<String, PropertyAccessorElement> getters, | 1029 void _collectAccessors(Map<String, PropertyAccessorElement> getters, |
| 1360 List<PropertyAccessorElement> setters, CompilationUnitElement unit) { | 1030 List<PropertyAccessorElement> setters, CompilationUnitElement unit) { |
| (...skipping 1246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2607 */ | 2277 */ |
| 2608 static const String VARIABLE_REFERENCE_ERRORS_INPUT = | 2278 static const String VARIABLE_REFERENCE_ERRORS_INPUT = |
| 2609 'VARIABLE_REFERENCE_ERRORS'; | 2279 'VARIABLE_REFERENCE_ERRORS'; |
| 2610 | 2280 |
| 2611 /** | 2281 /** |
| 2612 * The name of the [VERIFY_ERRORS] input. | 2282 * The name of the [VERIFY_ERRORS] input. |
| 2613 */ | 2283 */ |
| 2614 static const String VERIFY_ERRORS_INPUT = 'VERIFY_ERRORS'; | 2284 static const String VERIFY_ERRORS_INPUT = 'VERIFY_ERRORS'; |
| 2615 | 2285 |
| 2616 /** | 2286 /** |
| 2617 * The name of the [CONSTRUCTORS_ERRORS] input. | |
| 2618 */ | |
| 2619 static const String CONSTRUCTORS_ERRORS_INPUT = 'CONSTRUCTORS_ERRORS'; | |
| 2620 | |
| 2621 /** | |
| 2622 * The task descriptor describing this kind of task. | 2287 * The task descriptor describing this kind of task. |
| 2623 */ | 2288 */ |
| 2624 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( | 2289 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| 2625 'LibraryUnitErrorsTask', createTask, buildInputs, | 2290 'LibraryUnitErrorsTask', createTask, buildInputs, |
| 2626 <ResultDescriptor>[LIBRARY_UNIT_ERRORS]); | 2291 <ResultDescriptor>[LIBRARY_UNIT_ERRORS]); |
| 2627 | 2292 |
| 2628 LibraryUnitErrorsTask(InternalAnalysisContext context, AnalysisTarget target) | 2293 LibraryUnitErrorsTask(InternalAnalysisContext context, AnalysisTarget target) |
| 2629 : super(context, target); | 2294 : super(context, target); |
| 2630 | 2295 |
| 2631 @override | 2296 @override |
| 2632 TaskDescriptor get descriptor => DESCRIPTOR; | 2297 TaskDescriptor get descriptor => DESCRIPTOR; |
| 2633 | 2298 |
| 2634 @override | 2299 @override |
| 2635 void internalPerform() { | 2300 void internalPerform() { |
| 2636 // | 2301 // |
| 2637 // Prepare inputs. | 2302 // Prepare inputs. |
| 2638 // | 2303 // |
| 2639 List<List<AnalysisError>> errorLists = <List<AnalysisError>>[]; | 2304 List<List<AnalysisError>> errorLists = <List<AnalysisError>>[]; |
| 2640 errorLists.addAll(getRequiredInput(CONSTRUCTORS_ERRORS_INPUT)); | |
| 2641 errorLists.add(getRequiredInput(HINTS_INPUT)); | 2305 errorLists.add(getRequiredInput(HINTS_INPUT)); |
| 2642 errorLists.add(getRequiredInput(RESOLVE_REFERENCES_ERRORS_INPUT)); | 2306 errorLists.add(getRequiredInput(RESOLVE_REFERENCES_ERRORS_INPUT)); |
| 2643 errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT)); | 2307 errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT)); |
| 2644 errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT)); | 2308 errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT)); |
| 2645 errorLists.add(getRequiredInput(VERIFY_ERRORS_INPUT)); | 2309 errorLists.add(getRequiredInput(VERIFY_ERRORS_INPUT)); |
| 2646 // | 2310 // |
| 2647 // Record outputs. | 2311 // Record outputs. |
| 2648 // | 2312 // |
| 2649 outputs[LIBRARY_UNIT_ERRORS] = AnalysisError.mergeLists(errorLists); | 2313 outputs[LIBRARY_UNIT_ERRORS] = AnalysisError.mergeLists(errorLists); |
| 2650 } | 2314 } |
| 2651 | 2315 |
| 2652 /** | 2316 /** |
| 2653 * Return a map from the names of the inputs of this kind of task to the task | 2317 * Return a map from the names of the inputs of this kind of task to the task |
| 2654 * input descriptors describing those inputs for a task with the | 2318 * input descriptors describing those inputs for a task with the |
| 2655 * given [unit]. | 2319 * given [unit]. |
| 2656 */ | 2320 */ |
| 2657 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { | 2321 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| 2658 LibrarySpecificUnit unit = target; | 2322 LibrarySpecificUnit unit = target; |
| 2659 return <String, TaskInput>{ | 2323 return <String, TaskInput>{ |
| 2660 CONSTRUCTORS_ERRORS_INPUT: COMPILATION_UNIT_ELEMENT | |
| 2661 .of(unit) | |
| 2662 .mappedToList((CompilationUnitElement element) => element.types) | |
| 2663 .toListOf(CONSTRUCTORS_ERRORS), | |
| 2664 HINTS_INPUT: HINTS.of(unit), | 2324 HINTS_INPUT: HINTS.of(unit), |
| 2665 RESOLVE_REFERENCES_ERRORS_INPUT: RESOLVE_REFERENCES_ERRORS.of(unit), | 2325 RESOLVE_REFERENCES_ERRORS_INPUT: RESOLVE_REFERENCES_ERRORS.of(unit), |
| 2666 RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit), | 2326 RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit), |
| 2667 VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit), | 2327 VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit), |
| 2668 VERIFY_ERRORS_INPUT: VERIFY_ERRORS.of(unit) | 2328 VERIFY_ERRORS_INPUT: VERIFY_ERRORS.of(unit) |
| 2669 }; | 2329 }; |
| 2670 } | 2330 } |
| 2671 | 2331 |
| 2672 /** | 2332 /** |
| 2673 * Create a [LibraryUnitErrorsTask] based on the given [target] in the given | 2333 * Create a [LibraryUnitErrorsTask] based on the given [target] in the given |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3003 } | 2663 } |
| 3004 } | 2664 } |
| 3005 } | 2665 } |
| 3006 | 2666 |
| 3007 /** | 2667 /** |
| 3008 * A task that finishes resolution by requesting [RESOLVED_UNIT_NO_CONSTANTS] fo
r every | 2668 * A task that finishes resolution by requesting [RESOLVED_UNIT_NO_CONSTANTS] fo
r every |
| 3009 * unit in the libraries closure and produces [LIBRARY_ELEMENT]. | 2669 * unit in the libraries closure and produces [LIBRARY_ELEMENT]. |
| 3010 */ | 2670 */ |
| 3011 class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { | 2671 class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { |
| 3012 /** | 2672 /** |
| 3013 * The name of the [LIBRARY_ELEMENT6] input. | 2673 * The name of the [LIBRARY_ELEMENT5] input. |
| 3014 */ | 2674 */ |
| 3015 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; | 2675 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; |
| 3016 | 2676 |
| 3017 /** | 2677 /** |
| 3018 * The name of the list of [RESOLVED_UNIT5] input. | 2678 * The name of the list of [RESOLVED_UNIT5] input. |
| 3019 */ | 2679 */ |
| 3020 static const String UNITS_INPUT = 'UNITS_INPUT'; | 2680 static const String UNITS_INPUT = 'UNITS_INPUT'; |
| 3021 | 2681 |
| 3022 /** | 2682 /** |
| 3023 * The task descriptor describing this kind of task. | 2683 * The task descriptor describing this kind of task. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3053 } | 2713 } |
| 3054 | 2714 |
| 3055 /** | 2715 /** |
| 3056 * Return a map from the names of the inputs of this kind of task to the task | 2716 * Return a map from the names of the inputs of this kind of task to the task |
| 3057 * input descriptors describing those inputs for a task with the | 2717 * input descriptors describing those inputs for a task with the |
| 3058 * given [target]. | 2718 * given [target]. |
| 3059 */ | 2719 */ |
| 3060 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { | 2720 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| 3061 Source source = target; | 2721 Source source = target; |
| 3062 return <String, TaskInput>{ | 2722 return <String, TaskInput>{ |
| 3063 LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source), | 2723 LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source), |
| 3064 UNITS_INPUT: UNITS.of(source).toList((Source unit) => | 2724 UNITS_INPUT: UNITS.of(source).toList((Source unit) => |
| 3065 RESOLVED_UNIT5.of(new LibrarySpecificUnit(source, unit))), | 2725 RESOLVED_UNIT5.of(new LibrarySpecificUnit(source, unit))), |
| 3066 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE | 2726 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE |
| 3067 .of(source) | 2727 .of(source) |
| 3068 .toMapOf(UNITS) | 2728 .toMapOf(UNITS) |
| 3069 .toFlattenList((Source library, Source unit) => | 2729 .toFlattenList((Source library, Source unit) => |
| 3070 RESOLVED_UNIT5.of(new LibrarySpecificUnit(library, unit))), | 2730 RESOLVED_UNIT5.of(new LibrarySpecificUnit(library, unit))), |
| 3071 }; | 2731 }; |
| 3072 } | 2732 } |
| 3073 | 2733 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3133 AnalysisContext context, AnalysisTarget target) { | 2793 AnalysisContext context, AnalysisTarget target) { |
| 3134 return new ResolveLibraryTypeNamesTask(context, target); | 2794 return new ResolveLibraryTypeNamesTask(context, target); |
| 3135 } | 2795 } |
| 3136 } | 2796 } |
| 3137 | 2797 |
| 3138 /** | 2798 /** |
| 3139 * A task that builds [RESOLVED_UNIT5] for a unit. | 2799 * A task that builds [RESOLVED_UNIT5] for a unit. |
| 3140 */ | 2800 */ |
| 3141 class ResolveUnitReferencesTask extends SourceBasedAnalysisTask { | 2801 class ResolveUnitReferencesTask extends SourceBasedAnalysisTask { |
| 3142 /** | 2802 /** |
| 3143 * The name of the [LIBRARY_ELEMENT6] input. | 2803 * The name of the [LIBRARY_ELEMENT5] input. |
| 3144 */ | 2804 */ |
| 3145 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; | 2805 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; |
| 3146 | 2806 |
| 3147 /** | 2807 /** |
| 3148 * The name of the [RESOLVED_UNIT4] input. | 2808 * The name of the [RESOLVED_UNIT4] input. |
| 3149 */ | 2809 */ |
| 3150 static const String UNIT_INPUT = 'UNIT_INPUT'; | 2810 static const String UNIT_INPUT = 'UNIT_INPUT'; |
| 3151 | 2811 |
| 3152 /** | 2812 /** |
| 3153 * The name of the [TYPE_PROVIDER] input. | 2813 * The name of the [TYPE_PROVIDER] input. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3199 /** | 2859 /** |
| 3200 * Return a map from the names of the inputs of this kind of task to the task | 2860 * Return a map from the names of the inputs of this kind of task to the task |
| 3201 * input descriptors describing those inputs for a task with the | 2861 * input descriptors describing those inputs for a task with the |
| 3202 * given [target]. | 2862 * given [target]. |
| 3203 */ | 2863 */ |
| 3204 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { | 2864 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| 3205 LibrarySpecificUnit unit = target; | 2865 LibrarySpecificUnit unit = target; |
| 3206 return <String, TaskInput>{ | 2866 return <String, TaskInput>{ |
| 3207 'fullyBuiltLibraryElements': IMPORT_EXPORT_SOURCE_CLOSURE | 2867 'fullyBuiltLibraryElements': IMPORT_EXPORT_SOURCE_CLOSURE |
| 3208 .of(unit.library) | 2868 .of(unit.library) |
| 3209 .toListOf(LIBRARY_ELEMENT6), | 2869 .toListOf(LIBRARY_ELEMENT5), |
| 3210 LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library), | 2870 LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library), |
| 3211 UNIT_INPUT: RESOLVED_UNIT4.of(unit), | 2871 UNIT_INPUT: RESOLVED_UNIT4.of(unit), |
| 3212 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request) | 2872 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request) |
| 3213 }; | 2873 }; |
| 3214 } | 2874 } |
| 3215 | 2875 |
| 3216 /** | 2876 /** |
| 3217 * Create a [ResolveUnitReferencesTask] based on the given [target] in | 2877 * Create a [ResolveUnitReferencesTask] based on the given [target] in |
| 3218 * the given [context]. | 2878 * the given [context]. |
| 3219 */ | 2879 */ |
| 3220 static ResolveUnitReferencesTask createTask( | 2880 static ResolveUnitReferencesTask createTask( |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3306 AnalysisContext context, AnalysisTarget target) { | 2966 AnalysisContext context, AnalysisTarget target) { |
| 3307 return new ResolveUnitTypeNamesTask(context, target); | 2967 return new ResolveUnitTypeNamesTask(context, target); |
| 3308 } | 2968 } |
| 3309 } | 2969 } |
| 3310 | 2970 |
| 3311 /** | 2971 /** |
| 3312 * A task that builds [RESOLVED_UNIT4] for a unit. | 2972 * A task that builds [RESOLVED_UNIT4] for a unit. |
| 3313 */ | 2973 */ |
| 3314 class ResolveVariableReferencesTask extends SourceBasedAnalysisTask { | 2974 class ResolveVariableReferencesTask extends SourceBasedAnalysisTask { |
| 3315 /** | 2975 /** |
| 3316 * The name of the [LIBRARY_ELEMENT6] input. | 2976 * The name of the [LIBRARY_ELEMENT1] input. |
| 3317 */ | 2977 */ |
| 3318 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; | 2978 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; |
| 3319 | 2979 |
| 3320 /** | 2980 /** |
| 3321 * The name of the [RESOLVED_UNIT3] input. | 2981 * The name of the [RESOLVED_UNIT3] input. |
| 3322 */ | 2982 */ |
| 3323 static const String UNIT_INPUT = 'UNIT_INPUT'; | 2983 static const String UNIT_INPUT = 'UNIT_INPUT'; |
| 3324 | 2984 |
| 3325 /** | 2985 /** |
| 3326 * The name of the [TYPE_PROVIDER] input. | 2986 * The name of the [TYPE_PROVIDER] input. |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3744 | 3404 |
| 3745 @override | 3405 @override |
| 3746 bool moveNext() { | 3406 bool moveNext() { |
| 3747 if (_newSources.isEmpty) { | 3407 if (_newSources.isEmpty) { |
| 3748 return false; | 3408 return false; |
| 3749 } | 3409 } |
| 3750 currentTarget = _newSources.removeLast(); | 3410 currentTarget = _newSources.removeLast(); |
| 3751 return true; | 3411 return true; |
| 3752 } | 3412 } |
| 3753 } | 3413 } |
| OLD | NEW |