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

Side by Side Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 2834773003: Remove the limited invalidation feature. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/standard_resolution_map.dart'; 10 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
(...skipping 25 matching lines...) Expand all
36 import 'package:analyzer/src/generated/parser.dart'; 36 import 'package:analyzer/src/generated/parser.dart';
37 import 'package:analyzer/src/generated/resolver.dart'; 37 import 'package:analyzer/src/generated/resolver.dart';
38 import 'package:analyzer/src/generated/sdk.dart'; 38 import 'package:analyzer/src/generated/sdk.dart';
39 import 'package:analyzer/src/generated/source.dart'; 39 import 'package:analyzer/src/generated/source.dart';
40 import 'package:analyzer/src/generated/utilities_dart.dart'; 40 import 'package:analyzer/src/generated/utilities_dart.dart';
41 import 'package:analyzer/src/plugin/engine_plugin.dart'; 41 import 'package:analyzer/src/plugin/engine_plugin.dart';
42 import 'package:analyzer/src/services/lint.dart'; 42 import 'package:analyzer/src/services/lint.dart';
43 import 'package:analyzer/src/task/driver.dart'; 43 import 'package:analyzer/src/task/driver.dart';
44 import 'package:analyzer/src/task/general.dart'; 44 import 'package:analyzer/src/task/general.dart';
45 import 'package:analyzer/src/task/html.dart'; 45 import 'package:analyzer/src/task/html.dart';
46 import 'package:analyzer/src/task/incremental_element_builder.dart';
47 import 'package:analyzer/src/task/inputs.dart'; 46 import 'package:analyzer/src/task/inputs.dart';
48 import 'package:analyzer/src/task/model.dart'; 47 import 'package:analyzer/src/task/model.dart';
49 import 'package:analyzer/src/task/strong/checker.dart'; 48 import 'package:analyzer/src/task/strong/checker.dart';
50 import 'package:analyzer/src/task/strong_mode.dart'; 49 import 'package:analyzer/src/task/strong_mode.dart';
51 import 'package:analyzer/task/dart.dart'; 50 import 'package:analyzer/task/dart.dart';
52 import 'package:analyzer/task/general.dart'; 51 import 'package:analyzer/task/general.dart';
53 import 'package:analyzer/task/model.dart'; 52 import 'package:analyzer/task/model.dart';
54 53
55 /** 54 /**
56 * The [ResultCachingPolicy] for ASTs. 55 * The [ResultCachingPolicy] for ASTs.
(...skipping 2402 matching lines...) Expand 10 before | Expand all | Expand 10 after
2459 * Create a [ContainingLibrariesTask] based on the given [target] in the given 2458 * Create a [ContainingLibrariesTask] based on the given [target] in the given
2460 * [context]. 2459 * [context].
2461 */ 2460 */
2462 static ContainingLibrariesTask createTask( 2461 static ContainingLibrariesTask createTask(
2463 AnalysisContext context, AnalysisTarget target) { 2462 AnalysisContext context, AnalysisTarget target) {
2464 return new ContainingLibrariesTask(context, target); 2463 return new ContainingLibrariesTask(context, target);
2465 } 2464 }
2466 } 2465 }
2467 2466
2468 /** 2467 /**
2469 * The description for a change in a Dart source.
2470 */
2471 class DartDelta extends Delta {
2472 final Set<String> changedNames = new Set<String>();
2473 final Map<Source, Set<String>> changedPrivateNames = <Source, Set<String>>{};
2474
2475 final Map<String, ClassElementDelta> changedClasses =
2476 <String, ClassElementDelta>{};
2477
2478 /**
2479 * The cache of libraries in which all results are invalid.
2480 */
2481 final Set<Source> librariesWithAllInvalidResults = new Set<Source>();
2482
2483 /**
2484 * The cache of libraries in which all results are valid.
2485 */
2486 final Set<Source> librariesWithAllValidResults = new Set<Source>();
2487
2488 /**
2489 * The cache of libraries with all, but [HINTS] and [VERIFY_ERRORS] results
2490 * are valid.
2491 */
2492 final Set<Source> libraryWithInvalidErrors = new Set<Source>();
2493
2494 /**
2495 * This set is cleared in every [gatherEnd], and [gatherChanges] uses it
2496 * to find changes in every source only once per visit process.
2497 */
2498 final Set<Source> currentVisitUnits = new Set<Source>();
2499
2500 DartDelta(Source source) : super(source);
2501
2502 @override
2503 bool get shouldGatherChanges => true;
2504
2505 /**
2506 * Add names that are changed in the given [references].
2507 * Return `true` if any change was added.
2508 */
2509 bool addChangedElements(ReferencedNames references, Source refLibrary) {
2510 int numberOfChanges = 0;
2511 int lastNumberOfChange = -1;
2512 while (numberOfChanges != lastNumberOfChange) {
2513 lastNumberOfChange = numberOfChanges;
2514 // Classes that extend changed classes are also changed.
2515 // If there is a delta for a superclass, use it for the subclass.
2516 // Otherwise mark the subclass as "general name change".
2517 references.superToSubs.forEach((String superName, Set<String> subNames) {
2518 ClassElementDelta superDelta = changedClasses[superName];
2519 for (String subName in subNames) {
2520 if (superDelta != null) {
2521 ClassElementDelta subDelta = changedClasses.putIfAbsent(subName,
2522 () => new ClassElementDelta(null, refLibrary, subName));
2523 _log(() => '$subName in $refLibrary has delta because of its '
2524 'superclass $superName has delta');
2525 if (subDelta.superDeltas.add(superDelta)) {
2526 numberOfChanges++;
2527 }
2528 } else if (isChanged(refLibrary, superName)) {
2529 if (nameChanged(refLibrary, subName)) {
2530 _log(() => '$subName in $refLibrary is changed because its '
2531 'superclass $superName is changed');
2532 numberOfChanges++;
2533 }
2534 }
2535 }
2536 });
2537 // If a user element uses a changed top-level element, then the user is
2538 // also changed. Note that if a changed class with delta is used, this
2539 // does not make the user changed - classes with delta keep their
2540 // original elements, so resolution of their names does not change.
2541 references.userToDependsOn.forEach((user, dependencies) {
2542 for (String dependency in dependencies) {
2543 if (isChangedOrClassMember(refLibrary, dependency)) {
2544 if (nameChanged(refLibrary, user)) {
2545 _log(() => '$user in $refLibrary is changed because '
2546 'of $dependency in $dependencies');
2547 numberOfChanges++;
2548 }
2549 }
2550 }
2551 });
2552 }
2553 return numberOfChanges != 0;
2554 }
2555
2556 void classChanged(ClassElementDelta classDelta) {
2557 changedClasses[classDelta.name] = classDelta;
2558 }
2559
2560 void elementChanged(Element element) {
2561 Source librarySource = element.library.source;
2562 nameChanged(librarySource, element.name);
2563 }
2564
2565 @override
2566 bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target,
2567 ResultDescriptor descriptor, Object value) {
2568 // Prepare target source.
2569 Source targetUnit = target.source;
2570 Source targetLibrary = target.librarySource;
2571 if (target is Source) {
2572 if (context.getKindOf(target) == SourceKind.LIBRARY) {
2573 targetLibrary = target;
2574 }
2575 }
2576 // We don't know what to do with the given target.
2577 if (targetUnit == null || targetUnit != targetLibrary) {
2578 return false;
2579 }
2580 // Attempt to find new changed names for the unit only once.
2581 if (!currentVisitUnits.add(targetUnit)) {
2582 return false;
2583 }
2584 // Add changes.
2585 ReferencedNames referencedNames =
2586 context.getResult(targetUnit, REFERENCED_NAMES);
2587 if (referencedNames == null) {
2588 return false;
2589 }
2590 return addChangedElements(referencedNames, targetLibrary);
2591 }
2592
2593 @override
2594 void gatherEnd() {
2595 currentVisitUnits.clear();
2596 }
2597
2598 bool hasAffectedHintsVerifyErrors(
2599 ReferencedNames references, Source refLibrary) {
2600 for (String superName in references.superToSubs.keys) {
2601 if (isChangedOrClass(refLibrary, superName)) {
2602 _log(() => '$refLibrary hints/verify errors are affected because '
2603 '${references.superToSubs[superName]} subclasses $superName');
2604 return true;
2605 }
2606 }
2607 for (String name in references.names) {
2608 ClassElementDelta classDelta = changedClasses[name];
2609 if (classDelta != null && classDelta.hasAnnotationChanges) {
2610 _log(() => '$refLibrary hints/verify errors are affected because '
2611 '$name has a class delta with annotation changes');
2612 return true;
2613 }
2614 }
2615 return false;
2616 }
2617
2618 bool hasAffectedReferences(ReferencedNames references, Source refLibrary) {
2619 // Resolution must be performed when a referenced element changes.
2620 for (String name in references.names) {
2621 if (isChangedOrClassMember(refLibrary, name)) {
2622 _log(() => '$refLibrary is affected by $name');
2623 return true;
2624 }
2625 }
2626 // Resolution must be performed when the unnamed constructor of
2627 // an instantiated class is added/changed/removed.
2628 // TODO(scheglov) Use only instantiations with default constructor.
2629 for (String name in references.instantiatedNames) {
2630 for (ClassElementDelta classDelta in changedClasses.values) {
2631 if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
2632 _log(() =>
2633 '$refLibrary is affected by the default constructor of $name');
2634 return true;
2635 }
2636 }
2637 }
2638 for (String name in references.extendedUsedUnnamedConstructorNames) {
2639 for (ClassElementDelta classDelta in changedClasses.values) {
2640 if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
2641 _log(() =>
2642 '$refLibrary is affected by the default constructor of $name');
2643 return true;
2644 }
2645 }
2646 }
2647 return false;
2648 }
2649
2650 /**
2651 * Return `true` if the given [name], used in a unit of the [librarySource],
2652 * is affected by a changed top-level element, excluding classes.
2653 */
2654 bool isChanged(Source librarySource, String name) {
2655 if (_isPrivateName(name)) {
2656 if (changedPrivateNames[librarySource]?.contains(name) ?? false) {
2657 return true;
2658 }
2659 }
2660 return changedNames.contains(name);
2661 }
2662
2663 /**
2664 * Return `true` if the given [name], used in a unit of the [librarySource],
2665 * is affected by a changed top-level element or a class.
2666 */
2667 bool isChangedOrClass(Source librarySource, String name) {
2668 if (isChanged(librarySource, name)) {
2669 return true;
2670 }
2671 return changedClasses[name] != null;
2672 }
2673
2674 /**
2675 * Return `true` if the given [name], used in a unit of the [librarySource],
2676 * is affected by a changed top-level element or a class member.
2677 */
2678 bool isChangedOrClassMember(Source librarySource, String name) {
2679 if (isChanged(librarySource, name)) {
2680 return true;
2681 }
2682 // TODO(scheglov) Optimize this.
2683 for (ClassElementDelta classDelta in changedClasses.values) {
2684 if (classDelta.hasChanges(librarySource, name)) {
2685 return true;
2686 }
2687 }
2688 return false;
2689 }
2690
2691 /**
2692 * Register the fact that the given [name], defined in the [librarySource]
2693 * is changed. Return `true` if the [name] is a new name, not yet registered.
2694 */
2695 bool nameChanged(Source librarySource, String name) {
2696 if (_isPrivateName(name)) {
2697 return changedPrivateNames
2698 .putIfAbsent(librarySource, () => new Set<String>())
2699 .add(name);
2700 } else {
2701 return changedNames.add(name);
2702 }
2703 }
2704
2705 @override
2706 DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
2707 ResultDescriptor descriptor, Object value) {
2708 // Always invalidate compounding results.
2709 if (descriptor == LIBRARY_ELEMENT4 ||
2710 descriptor == READY_LIBRARY_ELEMENT6 ||
2711 descriptor == READY_LIBRARY_ELEMENT7) {
2712 return DeltaResult.INVALIDATE_KEEP_DEPENDENCIES;
2713 }
2714 // Prepare target source.
2715 Source targetUnit = target.source;
2716 Source targetLibrary = target.librarySource;
2717 if (target is Source) {
2718 if (context.getKindOf(target) == SourceKind.LIBRARY) {
2719 targetLibrary = target;
2720 }
2721 }
2722 // We don't know what to do with the given target, invalidate it.
2723 if (targetUnit == null || targetUnit != targetLibrary) {
2724 return DeltaResult.INVALIDATE;
2725 }
2726 // Keep results that don't change: any library.
2727 if (_isTaskResult(ScanDartTask.DESCRIPTOR, descriptor) ||
2728 _isTaskResult(ParseDartTask.DESCRIPTOR, descriptor) ||
2729 _isTaskResult(BuildCompilationUnitElementTask.DESCRIPTOR, descriptor) ||
2730 _isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor) ||
2731 _isTaskResult(BuildDirectiveElementsTask.DESCRIPTOR, descriptor) ||
2732 _isTaskResult(ResolveDirectiveElementsTask.DESCRIPTOR, descriptor) ||
2733 _isTaskResult(BuildEnumMemberElementsTask.DESCRIPTOR, descriptor) ||
2734 _isTaskResult(BuildSourceExportClosureTask.DESCRIPTOR, descriptor) ||
2735 _isTaskResult(ReadyLibraryElement2Task.DESCRIPTOR, descriptor) ||
2736 _isTaskResult(ComputeLibraryCycleTask.DESCRIPTOR, descriptor)) {
2737 return DeltaResult.KEEP_CONTINUE;
2738 }
2739 // Keep results that don't change: changed library.
2740 if (targetUnit == source) {
2741 return DeltaResult.INVALIDATE;
2742 }
2743 // Keep results that don't change: dependent library.
2744 if (targetUnit != source) {
2745 if (_isTaskResult(BuildPublicNamespaceTask.DESCRIPTOR, descriptor)) {
2746 return DeltaResult.KEEP_CONTINUE;
2747 }
2748 }
2749 // Handle in-library results only for now.
2750 if (targetLibrary != null) {
2751 // Use cached library results.
2752 if (librariesWithAllInvalidResults.contains(targetLibrary)) {
2753 return DeltaResult.INVALIDATE;
2754 }
2755 if (librariesWithAllValidResults.contains(targetLibrary)) {
2756 return DeltaResult.KEEP_CONTINUE;
2757 }
2758 // The library is almost, but not completely valid.
2759 // Some error results are invalid.
2760 if (libraryWithInvalidErrors.contains(targetLibrary)) {
2761 if (descriptor == HINTS || descriptor == VERIFY_ERRORS) {
2762 return DeltaResult.INVALIDATE_NO_DELTA;
2763 }
2764 return DeltaResult.KEEP_CONTINUE;
2765 }
2766 // Compute the library result.
2767 ReferencedNames referencedNames =
2768 context.getResult(targetUnit, REFERENCED_NAMES);
2769 if (referencedNames == null) {
2770 return DeltaResult.INVALIDATE_NO_DELTA;
2771 }
2772 if (hasAffectedReferences(referencedNames, targetLibrary)) {
2773 librariesWithAllInvalidResults.add(targetLibrary);
2774 return DeltaResult.INVALIDATE;
2775 }
2776 if (hasAffectedHintsVerifyErrors(referencedNames, targetLibrary)) {
2777 libraryWithInvalidErrors.add(targetLibrary);
2778 return DeltaResult.KEEP_CONTINUE;
2779 }
2780 librariesWithAllValidResults.add(targetLibrary);
2781 return DeltaResult.KEEP_CONTINUE;
2782 }
2783 // We don't know what to do with the given target, invalidate it.
2784 return DeltaResult.INVALIDATE;
2785 }
2786
2787 void _log(String getMessage()) {
2788 // String message = getMessage();
2789 // print(message);
2790 }
2791
2792 static bool _isPrivateName(String name) => name.startsWith('_');
2793
2794 static bool _isTaskResult(
2795 TaskDescriptor taskDescriptor, ResultDescriptor result) {
2796 return taskDescriptor.results.contains(result);
2797 }
2798 }
2799
2800 /**
2801 * A task that merges all of the errors for a single source into a single list 2468 * A task that merges all of the errors for a single source into a single list
2802 * of errors. 2469 * of errors.
2803 */ 2470 */
2804 class DartErrorsTask extends SourceBasedAnalysisTask { 2471 class DartErrorsTask extends SourceBasedAnalysisTask {
2805 /** 2472 /**
2806 * The task descriptor describing this kind of task. 2473 * The task descriptor describing this kind of task.
2807 */ 2474 */
2808 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask', 2475 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
2809 createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]); 2476 createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
2810 2477
(...skipping 3775 matching lines...) Expand 10 before | Expand all | Expand 10 after
6586 6253
6587 @override 6254 @override
6588 bool moveNext() { 6255 bool moveNext() {
6589 if (_newSources.isEmpty) { 6256 if (_newSources.isEmpty) {
6590 return false; 6257 return false;
6591 } 6258 }
6592 currentTarget = _newSources.removeLast(); 6259 currentTarget = _newSources.removeLast();
6593 return true; 6260 return true;
6594 } 6261 }
6595 } 6262 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/engine.dart ('k') | pkg/analyzer/lib/src/task/incremental_element_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698