Issue 35551. Invalidate library cycles of libraries when a part file API signature changes.

R=brianwilkerson@google.com, paulberry@google.com

Fixes https://github.com/dart-lang/sdk/issues/35551
Change-Id: If4db0907fc62bdd12f528fe1a61895f6a18ec210
Reviewed-on: https://dart-review.googlesource.com/c/90520
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index eb87535..e9526b0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -510,6 +510,15 @@
     //   Flush exported top-level declarations of all files.
     if (apiSignatureChanged) {
       _libraryCycle?.invalidate();
+
+      // If this is a part, invalidate the libraries.
+      var libraries = _fsState._partToLibraries[this];
+      if (libraries != null) {
+        for (var library in libraries) {
+          library.libraryCycle?.invalidate();
+        }
+      }
+
       for (FileState file in _fsState._uriToFile.values) {
         file._exportedTopLevelDeclarations = null;
       }
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index aef3c08..0970f26 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -2781,6 +2781,32 @@
     expect(_getTopLevelVarType(result.unit, 'b'), 'B');
   }
 
+  test_part_getResult_changePart_invalidatesLibraryCycle() async {
+    var a = convertPath('/test/lib/a.dart');
+    var b = convertPath('/test/lib/b.dart');
+    newFile(a, content: r'''
+import 'dart:async';
+part 'b.dart';
+''');
+    driver.addFile(a);
+
+    // Analyze the library without the part.
+    await driver.getResult(a);
+
+    // Create the part file.
+    // This should invalidate library file state (specifically the library
+    // cycle), so that we can re-link the library, and get new dependencies.
+    newFile(b, content: r'''
+part of 'a.dart';
+Future<int> f;
+''');
+    driver.changeFile(b);
+
+    // This should not crash.
+    var result = await driver.getResult(b);
+    expect(result.errors, isEmpty);
+  }
+
   test_part_getResult_noLibrary() async {
     var c = convertPath('/test/lib/c.dart');
     newFile(c, content: r'''