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 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
(...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2518 * The cache of libraries in which all results are valid. | 2518 * The cache of libraries in which all results are valid. |
2519 */ | 2519 */ |
2520 final Set<Source> librariesWithAllValidResults = new Set<Source>(); | 2520 final Set<Source> librariesWithAllValidResults = new Set<Source>(); |
2521 | 2521 |
2522 /** | 2522 /** |
2523 * The cache of libraries with all, but [HINTS] and [VERIFY_ERRORS] results | 2523 * The cache of libraries with all, but [HINTS] and [VERIFY_ERRORS] results |
2524 * are valid. | 2524 * are valid. |
2525 */ | 2525 */ |
2526 final Set<Source> libraryWithInvalidErrors = new Set<Source>(); | 2526 final Set<Source> libraryWithInvalidErrors = new Set<Source>(); |
2527 | 2527 |
| 2528 /** |
| 2529 * This set is cleared in every [gatherEnd], and [gatherChanges] uses it |
| 2530 * to find changes in every source only once per visit process. |
| 2531 */ |
| 2532 final Set<Source> currentVisitUnits = new Set<Source>(); |
| 2533 |
2528 DartDelta(Source source) : super(source); | 2534 DartDelta(Source source) : super(source); |
2529 | 2535 |
2530 /** | 2536 /** |
2531 * Add names that are changed in the given [references]. | 2537 * Add names that are changed in the given [references]. |
| 2538 * Return `true` if any change was added. |
2532 */ | 2539 */ |
2533 void addChangedElements(ReferencedNames references, Source refLibrary) { | 2540 bool addChangedElements(ReferencedNames references, Source refLibrary) { |
2534 bool hasProgress = true; | 2541 int numberOfChanges = 0; |
2535 while (hasProgress) { | 2542 int lastNumberOfChange = -1; |
2536 hasProgress = false; | 2543 while (numberOfChanges != lastNumberOfChange) { |
| 2544 lastNumberOfChange = numberOfChanges; |
2537 // Classes that extend changed classes are also changed. | 2545 // Classes that extend changed classes are also changed. |
2538 // If there is a delta for a superclass, use it for the subclass. | 2546 // If there is a delta for a superclass, use it for the subclass. |
2539 // Otherwise mark the subclass as "general name change". | 2547 // Otherwise mark the subclass as "general name change". |
2540 references.superToSubs.forEach((String superName, Set<String> subNames) { | 2548 references.superToSubs.forEach((String superName, Set<String> subNames) { |
2541 ClassElementDelta superDelta = changedClasses[superName]; | 2549 ClassElementDelta superDelta = changedClasses[superName]; |
2542 for (String subName in subNames) { | 2550 for (String subName in subNames) { |
2543 if (superDelta != null) { | 2551 if (superDelta != null) { |
2544 ClassElementDelta subDelta = changedClasses.putIfAbsent(subName, | 2552 ClassElementDelta subDelta = changedClasses.putIfAbsent(subName, |
2545 () => new ClassElementDelta(null, refLibrary, subName)); | 2553 () => new ClassElementDelta(null, refLibrary, subName)); |
2546 _log(() => '$subName in $refLibrary has delta because of its ' | 2554 _log(() => '$subName in $refLibrary has delta because of its ' |
2547 'superclass $superName has delta'); | 2555 'superclass $superName has delta'); |
2548 if (subDelta.superDeltas.add(superDelta)) { | 2556 if (subDelta.superDeltas.add(superDelta)) { |
2549 hasProgress = true; | 2557 numberOfChanges++; |
2550 } | 2558 } |
2551 } else if (isChanged(refLibrary, superName)) { | 2559 } else if (isChanged(refLibrary, superName)) { |
2552 if (nameChanged(refLibrary, subName)) { | 2560 if (nameChanged(refLibrary, subName)) { |
2553 _log(() => '$subName in $refLibrary is changed because its ' | 2561 _log(() => '$subName in $refLibrary is changed because its ' |
2554 'superclass $superName is changed'); | 2562 'superclass $superName is changed'); |
2555 hasProgress = true; | 2563 numberOfChanges++; |
2556 } | 2564 } |
2557 } | 2565 } |
2558 } | 2566 } |
2559 }); | 2567 }); |
2560 // If a user element uses a changed top-level element, then the user is | 2568 // If a user element uses a changed top-level element, then the user is |
2561 // also changed. Note that if a changed class with delta is used, this | 2569 // also changed. Note that if a changed class with delta is used, this |
2562 // does not make the user changed - classes with delta keep their | 2570 // does not make the user changed - classes with delta keep their |
2563 // original elements, so resolution of their names does not change. | 2571 // original elements, so resolution of their names does not change. |
2564 references.userToDependsOn.forEach((user, dependencies) { | 2572 references.userToDependsOn.forEach((user, dependencies) { |
2565 for (String dependency in dependencies) { | 2573 for (String dependency in dependencies) { |
2566 if (isChangedOrClassMember(refLibrary, dependency)) { | 2574 if (isChangedOrClassMember(refLibrary, dependency)) { |
2567 if (nameChanged(refLibrary, user)) { | 2575 if (nameChanged(refLibrary, user)) { |
2568 _log(() => '$user in $refLibrary is changed because ' | 2576 _log(() => '$user in $refLibrary is changed because ' |
2569 'of $dependency in $dependencies'); | 2577 'of $dependency in $dependencies'); |
2570 hasProgress = true; | 2578 numberOfChanges++; |
2571 } | 2579 } |
2572 } | 2580 } |
2573 } | 2581 } |
2574 }); | 2582 }); |
2575 } | 2583 } |
| 2584 return numberOfChanges != 0; |
2576 } | 2585 } |
2577 | 2586 |
2578 void classChanged(ClassElementDelta classDelta) { | 2587 void classChanged(ClassElementDelta classDelta) { |
2579 changedClasses[classDelta.name] = classDelta; | 2588 changedClasses[classDelta.name] = classDelta; |
2580 } | 2589 } |
2581 | 2590 |
2582 void elementChanged(Element element) { | 2591 void elementChanged(Element element) { |
2583 Source librarySource = element.library.source; | 2592 Source librarySource = element.library.source; |
2584 nameChanged(librarySource, element.name); | 2593 nameChanged(librarySource, element.name); |
2585 } | 2594 } |
2586 | 2595 |
| 2596 @override |
| 2597 bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target, |
| 2598 ResultDescriptor descriptor, Object value) { |
| 2599 // Prepare target source. |
| 2600 Source targetUnit = target.source; |
| 2601 Source targetLibrary = target.librarySource; |
| 2602 if (target is Source) { |
| 2603 if (context.getKindOf(target) == SourceKind.LIBRARY) { |
| 2604 targetLibrary = target; |
| 2605 } |
| 2606 } |
| 2607 // We don't know what to do with the given target. |
| 2608 if (targetUnit == null || targetUnit != targetLibrary) { |
| 2609 return false; |
| 2610 } |
| 2611 // Attempt to find new changed names for the unit only once. |
| 2612 if (!currentVisitUnits.add(targetUnit)) { |
| 2613 return false; |
| 2614 } |
| 2615 // Add changes. |
| 2616 ReferencedNames referencedNames = |
| 2617 context.getResult(targetUnit, REFERENCED_NAMES); |
| 2618 if (referencedNames == null) { |
| 2619 return false; |
| 2620 } |
| 2621 return addChangedElements(referencedNames, targetLibrary); |
| 2622 } |
| 2623 |
| 2624 @override |
| 2625 void gatherEnd() { |
| 2626 currentVisitUnits.clear(); |
| 2627 } |
| 2628 |
2587 bool hasAffectedHintsVerifyErrors( | 2629 bool hasAffectedHintsVerifyErrors( |
2588 ReferencedNames references, Source refLibrary) { | 2630 ReferencedNames references, Source refLibrary) { |
2589 for (String superName in references.superToSubs.keys) { | 2631 for (String superName in references.superToSubs.keys) { |
2590 if (isChangedOrClass(refLibrary, superName)) { | 2632 if (isChangedOrClass(refLibrary, superName)) { |
2591 _log(() => '$refLibrary hints/verify errors are affected because ' | 2633 _log(() => '$refLibrary hints/verify errors are affected because ' |
2592 '${references.superToSubs[superName]} subclasses $superName'); | 2634 '${references.superToSubs[superName]} subclasses $superName'); |
2593 return true; | 2635 return true; |
2594 } | 2636 } |
2595 } | 2637 } |
2596 return false; | 2638 return false; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2682 } | 2724 } |
2683 // Prepare target source. | 2725 // Prepare target source. |
2684 Source targetUnit = target.source; | 2726 Source targetUnit = target.source; |
2685 Source targetLibrary = target.librarySource; | 2727 Source targetLibrary = target.librarySource; |
2686 if (target is Source) { | 2728 if (target is Source) { |
2687 if (context.getKindOf(target) == SourceKind.LIBRARY) { | 2729 if (context.getKindOf(target) == SourceKind.LIBRARY) { |
2688 targetLibrary = target; | 2730 targetLibrary = target; |
2689 } | 2731 } |
2690 } | 2732 } |
2691 // We don't know what to do with the given target, invalidate it. | 2733 // We don't know what to do with the given target, invalidate it. |
2692 if (targetUnit == null) { | 2734 if (targetUnit == null || targetUnit != targetLibrary) { |
2693 return DeltaResult.INVALIDATE; | 2735 return DeltaResult.INVALIDATE; |
2694 } | 2736 } |
2695 // Keep results that don't change: any library. | 2737 // Keep results that don't change: any library. |
2696 if (_isTaskResult(ScanDartTask.DESCRIPTOR, descriptor) || | 2738 if (_isTaskResult(ScanDartTask.DESCRIPTOR, descriptor) || |
2697 _isTaskResult(ParseDartTask.DESCRIPTOR, descriptor) || | 2739 _isTaskResult(ParseDartTask.DESCRIPTOR, descriptor) || |
2698 _isTaskResult(BuildCompilationUnitElementTask.DESCRIPTOR, descriptor) || | 2740 _isTaskResult(BuildCompilationUnitElementTask.DESCRIPTOR, descriptor) || |
2699 _isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor) || | 2741 _isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor) || |
2700 _isTaskResult(BuildDirectiveElementsTask.DESCRIPTOR, descriptor) || | 2742 _isTaskResult(BuildDirectiveElementsTask.DESCRIPTOR, descriptor) || |
2701 _isTaskResult(ResolveDirectiveElementsTask.DESCRIPTOR, descriptor) || | 2743 _isTaskResult(ResolveDirectiveElementsTask.DESCRIPTOR, descriptor) || |
2702 _isTaskResult(BuildEnumMemberElementsTask.DESCRIPTOR, descriptor) || | 2744 _isTaskResult(BuildEnumMemberElementsTask.DESCRIPTOR, descriptor) || |
(...skipping 28 matching lines...) Expand all Loading... |
2731 return DeltaResult.INVALIDATE_NO_DELTA; | 2773 return DeltaResult.INVALIDATE_NO_DELTA; |
2732 } | 2774 } |
2733 return DeltaResult.KEEP_CONTINUE; | 2775 return DeltaResult.KEEP_CONTINUE; |
2734 } | 2776 } |
2735 // Compute the library result. | 2777 // Compute the library result. |
2736 ReferencedNames referencedNames = | 2778 ReferencedNames referencedNames = |
2737 context.getResult(targetUnit, REFERENCED_NAMES); | 2779 context.getResult(targetUnit, REFERENCED_NAMES); |
2738 if (referencedNames == null) { | 2780 if (referencedNames == null) { |
2739 return DeltaResult.INVALIDATE_NO_DELTA; | 2781 return DeltaResult.INVALIDATE_NO_DELTA; |
2740 } | 2782 } |
2741 addChangedElements(referencedNames, targetLibrary); | |
2742 if (hasAffectedReferences(referencedNames, targetLibrary)) { | 2783 if (hasAffectedReferences(referencedNames, targetLibrary)) { |
2743 librariesWithAllInvalidResults.add(targetLibrary); | 2784 librariesWithAllInvalidResults.add(targetLibrary); |
2744 return DeltaResult.INVALIDATE; | 2785 return DeltaResult.INVALIDATE; |
2745 } | 2786 } |
2746 if (hasAffectedHintsVerifyErrors(referencedNames, targetLibrary)) { | 2787 if (hasAffectedHintsVerifyErrors(referencedNames, targetLibrary)) { |
2747 libraryWithInvalidErrors.add(targetLibrary); | 2788 libraryWithInvalidErrors.add(targetLibrary); |
2748 return DeltaResult.KEEP_CONTINUE; | 2789 return DeltaResult.KEEP_CONTINUE; |
2749 } | 2790 } |
2750 librariesWithAllValidResults.add(targetLibrary); | 2791 librariesWithAllValidResults.add(targetLibrary); |
2751 return DeltaResult.STOP; | 2792 return DeltaResult.STOP; |
(...skipping 3729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6481 | 6522 |
6482 @override | 6523 @override |
6483 bool moveNext() { | 6524 bool moveNext() { |
6484 if (_newSources.isEmpty) { | 6525 if (_newSources.isEmpty) { |
6485 return false; | 6526 return false; |
6486 } | 6527 } |
6487 currentTarget = _newSources.removeLast(); | 6528 currentTarget = _newSources.removeLast(); |
6488 return true; | 6529 return true; |
6489 } | 6530 } |
6490 } | 6531 } |
OLD | NEW |