Index: pkg/analyzer/lib/src/task/dart.dart |
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart |
index 51607a0f6bb2760b393be1437dfc90f1d4274c03..1991517ca84ba7ec679adfaeea012121978bd931 100644 |
--- a/pkg/analyzer/lib/src/task/dart.dart |
+++ b/pkg/analyzer/lib/src/task/dart.dart |
@@ -2525,15 +2525,23 @@ class DartDelta extends Delta { |
*/ |
final Set<Source> libraryWithInvalidErrors = new Set<Source>(); |
+ /** |
+ * This set is cleared in every [gatherEnd], and [gatherChanges] uses it |
+ * to find changes in every source only once per visit process. |
+ */ |
+ final Set<Source> currentVisitUnits = new Set<Source>(); |
+ |
DartDelta(Source source) : super(source); |
/** |
* Add names that are changed in the given [references]. |
+ * Return `true` if any change was added. |
*/ |
- void addChangedElements(ReferencedNames references, Source refLibrary) { |
- bool hasProgress = true; |
- while (hasProgress) { |
- hasProgress = false; |
+ bool addChangedElements(ReferencedNames references, Source refLibrary) { |
+ int numberOfChanges = 0; |
+ int lastNumberOfChange = -1; |
+ while (numberOfChanges != lastNumberOfChange) { |
+ lastNumberOfChange = numberOfChanges; |
// Classes that extend changed classes are also changed. |
// If there is a delta for a superclass, use it for the subclass. |
// Otherwise mark the subclass as "general name change". |
@@ -2546,13 +2554,13 @@ class DartDelta extends Delta { |
_log(() => '$subName in $refLibrary has delta because of its ' |
'superclass $superName has delta'); |
if (subDelta.superDeltas.add(superDelta)) { |
- hasProgress = true; |
+ numberOfChanges++; |
} |
} else if (isChanged(refLibrary, superName)) { |
if (nameChanged(refLibrary, subName)) { |
_log(() => '$subName in $refLibrary is changed because its ' |
'superclass $superName is changed'); |
- hasProgress = true; |
+ numberOfChanges++; |
} |
} |
} |
@@ -2567,12 +2575,13 @@ class DartDelta extends Delta { |
if (nameChanged(refLibrary, user)) { |
_log(() => '$user in $refLibrary is changed because ' |
'of $dependency in $dependencies'); |
- hasProgress = true; |
+ numberOfChanges++; |
} |
} |
} |
}); |
} |
+ return numberOfChanges != 0; |
} |
void classChanged(ClassElementDelta classDelta) { |
@@ -2584,6 +2593,39 @@ class DartDelta extends Delta { |
nameChanged(librarySource, element.name); |
} |
+ @override |
+ bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target, |
+ ResultDescriptor descriptor, Object value) { |
+ // Prepare target source. |
+ Source targetUnit = target.source; |
+ Source targetLibrary = target.librarySource; |
+ if (target is Source) { |
+ if (context.getKindOf(target) == SourceKind.LIBRARY) { |
+ targetLibrary = target; |
+ } |
+ } |
+ // We don't know what to do with the given target. |
+ if (targetUnit == null || targetUnit != targetLibrary) { |
+ return false; |
+ } |
+ // Attempt to find new changed names for the unit only once. |
+ if (!currentVisitUnits.add(targetUnit)) { |
+ return false; |
+ } |
+ // Add changes. |
+ ReferencedNames referencedNames = |
+ context.getResult(targetUnit, REFERENCED_NAMES); |
+ if (referencedNames == null) { |
+ return false; |
+ } |
+ return addChangedElements(referencedNames, targetLibrary); |
+ } |
+ |
+ @override |
+ void gatherEnd() { |
+ currentVisitUnits.clear(); |
+ } |
+ |
bool hasAffectedHintsVerifyErrors( |
ReferencedNames references, Source refLibrary) { |
for (String superName in references.superToSubs.keys) { |
@@ -2689,7 +2731,7 @@ class DartDelta extends Delta { |
} |
} |
// We don't know what to do with the given target, invalidate it. |
- if (targetUnit == null) { |
+ if (targetUnit == null || targetUnit != targetLibrary) { |
return DeltaResult.INVALIDATE; |
} |
// Keep results that don't change: any library. |
@@ -2738,7 +2780,6 @@ class DartDelta extends Delta { |
if (referencedNames == null) { |
return DeltaResult.INVALIDATE_NO_DELTA; |
} |
- addChangedElements(referencedNames, targetLibrary); |
if (hasAffectedReferences(referencedNames, targetLibrary)) { |
librariesWithAllInvalidResults.add(targetLibrary); |
return DeltaResult.INVALIDATE; |