Version 2.14.0-277.0.dev

Merge commit 'e75d26b76c13349847e93b5883f4d941119996e2' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
index b577fba..e033fca 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
@@ -22,11 +22,15 @@
   /// open parenthesis. If [insertIdentifier] is true, then a synthetic
   /// identifier is included between the open and close parenthesis.
   Token insertParens(Token token, bool includeIdentifier) {
-    // Assert that the token is not eof, though allow an eof-token if the offset
+    // Throw if the token is eof, though allow an eof-token if the offset
     // is negative. The last part is because [syntheticPreviousToken] sometimes
     // creates eof tokens that aren't the real eof-token that has a negative
     // offset (which wouldn't be valid for the real eof).
-    assert(!token.isEof || token.offset < 0);
+    if (!(!token.isEof || token.offset < 0)) {
+      // Inserting here could cause a infinite loop. We prefer to crash.
+      throw 'Internal Error: Rewriting at eof.';
+    }
+
     Token next = token.next!;
     int offset = next.charOffset;
     BeginToken leftParen =
@@ -49,11 +53,15 @@
 
   /// Insert [newToken] after [token] and return [newToken].
   Token insertToken(Token token, Token newToken) {
-    // Assert that the token is not eof, though allow an eof-token if the offset
+    // Throw if the token is eof, though allow an eof-token if the offset
     // is negative. The last part is because [syntheticPreviousToken] sometimes
     // creates eof tokens that aren't the real eof-token that has a negative
     // offset (which wouldn't be valid for the real eof).
-    assert(!token.isEof || token.offset < 0);
+    if (!(!token.isEof || token.offset < 0)) {
+      // Inserting here could cause a infinite loop. We prefer to crash.
+      throw 'Internal Error: Rewriting at eof.';
+    }
+
     _setNext(newToken, token.next!);
 
     // A no-op rewriter could skip this step.
@@ -65,11 +73,15 @@
   /// Move [endGroup] (a synthetic `)`, `]`, or `}` token) and associated
   /// error token after [token] in the token stream and return [endGroup].
   Token moveSynthetic(Token token, Token endGroup) {
-    // Assert that the token is not eof, though allow an eof-token if the offset
+    // Throw if the token is eof, though allow an eof-token if the offset
     // is negative. The last part is because [syntheticPreviousToken] sometimes
     // creates eof tokens that aren't the real eof-token that has a negative
     // offset (which wouldn't be valid for the real eof).
-    assert(!token.isEof || token.offset < 0);
+    if (!(!token.isEof || token.offset < 0)) {
+      // Inserting here could cause a infinite loop. We prefer to crash.
+      throw 'Internal Error: Rewriting at eof.';
+    }
+
     // ignore:unnecessary_null_comparison
     assert(endGroup.beforeSynthetic != null);
     if (token == endGroup) return endGroup;
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 832c3ee..79bc69f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -239,6 +239,9 @@
   /// TODO(scheglov) We probably should tie it into the session.
   LibraryContext? _libraryContext;
 
+  /// Whether `dart:core` has been transitively discovered.
+  bool _hasDartCoreDiscovered = false;
+
   /// This function is invoked when the current session is about to be discarded.
   /// The argument represents the path of the resource causing the session
   /// to be discarded or `null` if there are multiple or this is unknown.
@@ -972,6 +975,11 @@
       return;
     }
 
+    if (!_hasDartCoreDiscovered) {
+      _hasDartCoreDiscovered = true;
+      _discoverDartCore();
+    }
+
     // Analyze a requested file.
     if (_requestedFiles.isNotEmpty) {
       String path = _requestedFiles.keys.first;
@@ -1585,6 +1593,29 @@
     _discoverAvailableFilesTask ??= _DiscoverAvailableFilesTask(this);
   }
 
+  /// When we look at a part that has a `part of name;` directive, we
+  /// usually don't know the library (in contrast to `part of uri;`).
+  /// So, we have no choice than to resolve this part as its own library.
+  /// TODO(scheglov) Maybe just return an error result instead?
+  ///
+  /// But parts of `dart:xyz` libraries are special. The reason is that
+  /// `dart:core` is always implicitly imported. So, when we start building
+  /// the library cycle of such "part as a library", we discover `dart:core`,
+  /// and see that it contains our part. So, we don't add it as a library on
+  /// its own. But have already committed that it is a library. This causes
+  /// an exception in `LinkedElementFactory`.
+  ///
+  /// The current workaround for this is to discover `dart:core` before any
+  /// analysis.
+  void _discoverDartCore() {
+    _fsState.getFileForUri(Uri.parse('dart:core')).map(
+      (file) {
+        file?.transitiveFiles;
+      },
+      (externalLibrary) {},
+    );
+  }
+
   void _fillSalt() {
     _fillSaltForUnlinked();
     _fillSaltForElements();
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index a970cf4..dee0e8e 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1545,6 +1545,13 @@
     expect(result.errors, isEmpty);
   }
 
+  test_getResult_dartAsyncPart() async {
+    var path = convertPath('/sdk/lib/async/stream.dart');
+    var result = await driver.getResultValid(path);
+    expect(result.path, path);
+    expect(result.unit, isNotNull);
+  }
+
   test_getResult_doesNotExist() async {
     var a = convertPath('/test/lib/a.dart');
 
diff --git a/tools/VERSION b/tools/VERSION
index a619ee9..e6616ec 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 276
+PRERELEASE 277
 PRERELEASE_PATCH 0
\ No newline at end of file