Index: pkg/analyzer/test/src/context/context_test.dart |
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart |
index d0ec5b2caf846d1904e2f845397d03d38a043542..39c3305c61212574de72fd36f8bf298aa0c57197 100644 |
--- a/pkg/analyzer/test/src/context/context_test.dart |
+++ b/pkg/analyzer/test/src/context/context_test.dart |
@@ -3499,6 +3499,175 @@ f(c(int p)) {} |
expect(parameterName.propagatedType, context.typeProvider.intType); |
} |
+ void test_sequence_compoundingResults_exportNamespace() { |
+ Source a = addSource( |
+ '/a.dart', |
+ r''' |
+class A<T> {} |
+'''); |
+ Source b = addSource( |
+ '/b.dart', |
+ r''' |
+export 'a.dart'; |
+'''); |
+ Source c = addSource( |
+ '/c.dart', |
+ r''' |
+import 'b.dart'; |
+main() { |
+ new A<int>(); |
+} |
+'''); |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(c).errors, isEmpty); |
+ // Update a.dart, so that `A<T>` has a type bound. |
+ // This should invalidate export namespace for b.dart. |
+ // Currently we invalidate the whole LIBRARY_ELEMENT4. |
+ // So, c.dart will see the new `A<T extends B>` and report an error. |
+ context.setContents( |
+ a, |
+ r''' |
+class A<T extends B> {} |
+class B {} |
+'''); |
+ _assertInvalid(b, LIBRARY_ELEMENT4); |
+ // Analyze and validate that a new error is reported. |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(c).errors, hasLength(1)); |
+ _assertValid(a, LIBRARY_ERRORS_READY); |
+ _assertValid(b, LIBRARY_ERRORS_READY); |
+ _assertValid(c, LIBRARY_ERRORS_READY); |
+ } |
+ |
+ void test_sequence_compoundingResults_invalidateButKeepDependency() { |
+ Source a = addSource( |
+ '/a.dart', |
+ r''' |
+import 'b.dart'; |
+class A {} |
+'''); |
+ Source b = addSource( |
+ '/b.dart', |
+ r''' |
+import 'a.dart'; |
+import 'c.dart'; |
+class B {} |
+'''); |
+ Source c = addSource( |
+ '/c.dart', |
+ r''' |
+class C {} |
+'''); |
+ Source d = addSource( |
+ '/d.dart', |
+ r''' |
+export 'b.dart'; |
+'''); |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(c).errors, isEmpty); |
+ // Update: a.dart (limited) and b.dart (limited). |
+ // This should invalidate LIBRARY_ELEMENT4 in d.dart, but it should be |
+ // done in a way that keep dependency of other results od d.dart on |
+ // LIBRARY_ELEMENT4 of d.dart, so that when we perform unlimited |
+ // invalidation of c.dart, this makes d.dart invalid. |
+ context.setContents( |
+ a, |
+ r''' |
+import 'b.dart'; |
+class A2 {} |
+'''); |
+ context.setContents( |
+ b, |
+ r''' |
+import 'a.dart'; |
+import 'c.dart'; |
+class B2 {} |
+'''); |
+ context.setContents( |
+ c, |
+ r''' |
+import 'dart:async'; |
+class C {} |
+'''); |
+ _assertInvalid(d, LIBRARY_ELEMENT4); |
+ _assertInvalid(d, LIBRARY_ERRORS_READY); |
+ // Analyze and validate that a new error is reported. |
+ _performPendingAnalysisTasks(); |
+ _assertValid(a, EXPORT_SOURCE_CLOSURE); |
+ _assertValid(b, EXPORT_SOURCE_CLOSURE); |
+ _assertValid(c, EXPORT_SOURCE_CLOSURE); |
+ _assertValid(d, EXPORT_SOURCE_CLOSURE); |
+ _assertValid(a, LIBRARY_ERRORS_READY); |
+ _assertValid(b, LIBRARY_ERRORS_READY); |
+ _assertValid(c, LIBRARY_ERRORS_READY); |
+ _assertValid(d, LIBRARY_ERRORS_READY); |
+ } |
+ |
+ void test_sequence_compoundingResults_resolvedTypeNames() { |
+ Source a = addSource( |
+ '/a.dart', |
+ r''' |
+class A {} |
+'''); |
+ Source b = addSource( |
+ '/b.dart', |
+ r''' |
+class B<T> { |
+ B(p); |
+} |
+'''); |
+ Source c = addSource( |
+ '/c.dart', |
+ r''' |
+export 'a.dart'; |
+export 'b.dart'; |
+'''); |
+ Source d = addSource( |
+ '/d.dart', |
+ r''' |
+import 'c.dart'; |
+main() { |
+ new B<int>(null); |
+} |
+'''); |
+ _performPendingAnalysisTasks(); |
+ // Update a.dart and b.dart |
+ // This should invalidate most results in a.dart and b.dart |
+ // |
+ // This should also invalidate "compounding" results in c.dart, such as |
+ // READY_LIBRARY_ELEMENT6, which represent a state of the whole source |
+ // closure, not a result of this single unit or a library. |
+ // |
+ // The reason is that although type names (RESOLVED_UNIT5) b.dart will be |
+ // eventually resolved and set into b.dart elements, it may happen |
+ // after we attempted to re-resolve c.dart, which created Member(s), and |
+ // attempts to use elements without types set. |
+ context.setContents( |
+ a, |
+ r''' |
+class A2 {} |
+'''); |
+ context.setContents( |
+ b, |
+ r''' |
+class B<T> { |
+ B(T p); |
+} |
+'''); |
+ _assertValidForChangedLibrary(a); |
+ _assertInvalid(a, LIBRARY_ERRORS_READY); |
+ _assertValidForChangedLibrary(b); |
+ _assertInvalid(b, LIBRARY_ERRORS_READY); |
+ _assertInvalid(c, READY_LIBRARY_ELEMENT6); |
+ _assertInvalid(c, READY_LIBRARY_ELEMENT7); |
+ // Analyze and validate that all results are valid. |
+ _performPendingAnalysisTasks(); |
+ _assertValid(a, LIBRARY_ERRORS_READY); |
+ _assertValid(b, LIBRARY_ERRORS_READY); |
+ _assertValid(c, LIBRARY_ERRORS_READY); |
+ _assertValid(d, LIBRARY_ERRORS_READY); |
+ } |
+ |
void test_sequence_dependenciesWithCycles() { |
Source a = addSource( |
'/a.dart', |
@@ -4315,10 +4484,13 @@ class A { |
} |
void _assertValidAllLibraryUnitResults(Source source, {Source library}) { |
+ library ??= source; |
for (ResultDescriptor<LibraryElement> result in LIBRARY_ELEMENT_RESULTS) { |
- _assertValid(source, result); |
+ if (result == LIBRARY_ELEMENT4) { |
+ continue; |
+ } |
+ _assertValid(library, result); |
} |
- library ??= source; |
LibrarySpecificUnit target = new LibrarySpecificUnit(library, source); |
for (ResultDescriptor<CompilationUnit> result in RESOLVED_UNIT_RESULTS) { |
_assertValid(target, result); |