Issue 57043. Fix infinite FileKind recursion when part references itself.

Bug: https://github.com/dart-lang/sdk/issues/57043
Change-Id: I8bde1d5f6b1d2eb9bd3e42ec74261d492e9303e7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/393906
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 1b6c850..c3e0b7f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -403,9 +403,15 @@
       return;
     }
 
-    for (var reference in file.referencingFiles) {
+    // Take referencing files, stop potential recursion.
+    var referencingFiles = file.referencingFiles;
+    file.referencingFiles = {};
+
+    // Iterate and restore.
+    for (var reference in referencingFiles) {
       reference.kind.disposeLibraryCycle();
     }
+    file.referencingFiles = referencingFiles;
   }
 
   bool hasPart(PartFileKind partKind) {
@@ -529,7 +535,7 @@
   bool isMacroPart = false;
 
   /// Files that reference this file.
-  final Set<FileState> referencingFiles = {};
+  Set<FileState> referencingFiles = {};
 
   /// The flag that shows whether the file has an error or warning that
   /// might be fixed by a change to another file.
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index bc6390e..2e468dd 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -3248,6 +3248,57 @@
 ''');
   }
 
+  test_newFile_partOfUri_cycle_importSelf() async {
+    // https://github.com/dart-lang/sdk/issues/57043
+
+    var a = newFile('$testPackageLibPath/a.dart', r'''
+part 'b.dart';
+''');
+
+    var b = newFile('$testPackageLibPath/b.dart', r'''
+part of 'a.dart';
+import '';
+''');
+
+    fileStateFor(a);
+    var b_state = fileStateFor(b);
+
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/a.dart
+    uri: package:test/a.dart
+    current
+      id: file_0
+      kind: library_0
+        libraryImports
+          library_2 dart:core synthetic
+        partIncludes
+          partOfUriKnown_1
+        fileKinds: library_0 partOfUriKnown_1
+        cycle_0
+          dependencies: dart:core
+          libraries: library_0
+          apiSignature_0
+      unlinkedKey: k00
+  /home/test/lib/b.dart
+    uri: package:test/b.dart
+    current
+      id: file_1
+      kind: partOfUriKnown_1
+        uriFile: file_0
+        library: library_0
+        libraryImports
+          notLibrary file_1
+      referencingFiles: file_0 file_1
+      unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+
+    // Should not recurse infinitely.
+    b_state.kind.disposeLibraryCycle();
+  }
+
   test_newFile_partOfUri_doesNotExist() async {
     var a = getFile('$testPackageLibPath/a.dart');