Version 2.15.0-297.0.dev

Merge commit 'c224cc2e0d4cd8fc536c21ee963a0254d18a27bb' into 'dev'
diff --git a/DEPS b/DEPS
index df4cc35..8c0e608 100644
--- a/DEPS
+++ b/DEPS
@@ -140,7 +140,7 @@
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
   "process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
   "protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
-  "pub_rev": "0035a40f25d027130c0314571da53ffafc6d973b",
+  "pub_rev": "96404e0749864c9fbf8b12e1d424e8078809e00a",
   "pub_semver_rev": "a43ad72fb6b7869607581b5fedcb186d1e74276a",
   "root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
diff --git a/docs/process/breaking-changes.md b/docs/process/breaking-changes.md
index 328c4c6..4ea8bda 100644
--- a/docs/process/breaking-changes.md
+++ b/docs/process/breaking-changes.md
@@ -65,8 +65,6 @@
 
   * Clear steps for mitigating the change.
 
-[TODO: Link to an issue template for this]
-
 * Email Dart Announce (`announce@dartlang.org`):
 
   * Subject: 'Breaking change [bug ID]: [short summary]'
@@ -78,7 +76,7 @@
   * A request that developers may leave comments in the linked issue, if this
     breaking change poses a severe problem.
 
-Once you have sent the announce email, please let @devoncarew know in order
+Once you have sent the announce email, please let devoncarew@ know in order
 to start the review and approval process.
 
 ### Step 2: Approval
@@ -120,7 +118,7 @@
   * The impact of the change was significantly larger than described in the
     breaking change announcement
 
-, then they may file a 'request for roll-back' using the following steps:
+Then they may file a 'request for roll-back' using the following steps:
 
 * Create an issue in the Dart SDK issue tracker labelled
   `roll-back-request` containing the following:
@@ -133,8 +131,6 @@
   * A link to the program that was affected, or another program that illustrated
     the same effect.
 
-[TODO: Link to an issue template for this]
-
 Upon receiving such an issue the Dart SDK team will either:
 
   * Roll-back the change, or
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 17f00da..4f6aaaa3 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -70,7 +70,7 @@
       var lineInfo = resolvedUnit.lineInfo;
       var offset = lineInfo.getOffsetOfLine(line) + column;
 
-      _dartCompletionRequest = DartCompletionRequest(
+      _dartCompletionRequest = DartCompletionRequest.forResolvedUnit(
         resolvedUnit: resolvedUnit,
         offset: offset,
       );
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 76a3f3b..6bf064f 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -329,7 +329,7 @@
         );
         performanceList.add(completionPerformance);
 
-        var completionRequest = DartCompletionRequest(
+        var completionRequest = DartCompletionRequest.forResolvedUnit(
           resolvedUnit: resolvedUnit,
           offset: offset,
           dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(
@@ -527,7 +527,7 @@
           return;
         }
 
-        var completionRequest = DartCompletionRequest(
+        var completionRequest = DartCompletionRequest.forResolvedUnit(
           resolvedUnit: resolvedUnit,
           offset: offset,
           dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index a2f6ea6..e0eedc4 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -69,7 +69,7 @@
       return RuntimeCompletionResult([], []);
     }
 
-    var dartRequest = DartCompletionRequest(
+    var dartRequest = DartCompletionRequest.forResolvedUnit(
       resolvedUnit: targetResult,
       offset: targetOffset,
     );
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index a4eb456..629101e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -215,7 +215,7 @@
         );
         server.performanceStats.completion.add(completionPerformance);
 
-        final completionRequest = DartCompletionRequest(
+        final completionRequest = DartCompletionRequest.forResolvedUnit(
           resolvedUnit: unit,
           offset: offset,
           dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(unit),
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 0789ea2..90da0ef 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -328,17 +328,22 @@
   bool _aborted = false;
 
   factory DartCompletionRequest({
-    required ResolvedUnitResult resolvedUnit,
+    required AnalysisSession analysisSession,
+    required String filePath,
+    required String fileContent,
+    required CompilationUnitElement unitElement,
+    required AstNode enclosingNode,
     required int offset,
     DartdocDirectiveInfo? dartdocDirectiveInfo,
     CompletionPreference completionPreference = CompletionPreference.insert,
     DocumentationCache? documentationCache,
   }) {
-    var target = CompletionTarget.forOffset(resolvedUnit.unit, offset);
+    var target = CompletionTarget.forOffset(enclosingNode, offset);
 
+    var libraryElement = unitElement.library;
     var featureComputer = FeatureComputer(
-      resolvedUnit.typeSystem,
-      resolvedUnit.typeProvider,
+      libraryElement.typeSystem,
+      libraryElement.typeProvider,
     );
 
     var contextType = featureComputer.computeContextType(
@@ -352,23 +357,43 @@
     }
 
     return DartCompletionRequest._(
-      analysisSession: resolvedUnit.session as AnalysisSessionImpl,
+      analysisSession: analysisSession as AnalysisSessionImpl,
       completionPreference: completionPreference,
-      content: resolvedUnit.content,
+      content: fileContent,
       contextType: contextType,
       dartdocDirectiveInfo: dartdocDirectiveInfo ?? DartdocDirectiveInfo(),
       documentationCache: documentationCache,
       featureComputer: featureComputer,
-      libraryElement: resolvedUnit.libraryElement,
+      libraryElement: libraryElement,
       offset: offset,
       opType: opType,
-      path: resolvedUnit.path,
+      path: filePath,
       replacementRange: target.computeReplacementRange(offset),
-      source: resolvedUnit.unit.declaredElement!.source,
+      source: unitElement.source,
       target: target,
     );
   }
 
+  factory DartCompletionRequest.forResolvedUnit({
+    required ResolvedUnitResult resolvedUnit,
+    required int offset,
+    DartdocDirectiveInfo? dartdocDirectiveInfo,
+    CompletionPreference completionPreference = CompletionPreference.insert,
+    DocumentationCache? documentationCache,
+  }) {
+    return DartCompletionRequest(
+      analysisSession: resolvedUnit.session,
+      filePath: resolvedUnit.path,
+      fileContent: resolvedUnit.content,
+      unitElement: resolvedUnit.unit.declaredElement!,
+      enclosingNode: resolvedUnit.unit,
+      offset: offset,
+      dartdocDirectiveInfo: dartdocDirectiveInfo,
+      completionPreference: completionPreference,
+      documentationCache: documentationCache,
+    );
+  }
+
   DartCompletionRequest._({
     required this.analysisSession,
     required this.completionPreference,
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
index 3708b48..e4438f2 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
@@ -2,15 +2,20 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:math' as math;
+
 import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/element/extensions.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/ignore_comments/ignore_info.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError, Element;
+import 'package:collection/collection.dart';
+import 'package:meta/meta_meta.dart';
 
 /// Organizer of imports (and other directives) in the [unit].
 class ImportOrganizer {
@@ -67,6 +72,13 @@
     var lineInfo = unit.lineInfo ?? LineInfo.fromContent(code);
     var hasLibraryDirective = false;
     var directives = <_DirectiveInfo>[];
+    // Track the end offset of any library-level comment/annotations that should
+    // remain at the top of the file regardless of whether it was attached to a
+    // directive that's moved/removed.
+    // Code up to this offset will be excluded from the comment/docs/annotation
+    // text for the computed DirectiveInfo and also its range for replacement
+    // in the document.
+    int? libraryDocsAndAnnotationsEndOffset;
     for (var directive in unit.directives) {
       if (directive is LibraryDirective) {
         hasLibraryDirective = true;
@@ -77,15 +89,60 @@
           var offset = directive.offset;
           var end = directive.end;
 
-          final leadingComment = getLeadingComment(unit, directive, lineInfo);
-          final trailingComment =
-              getTrailingComment(unit, directive, lineInfo, end);
+          final isPsuedoLibraryDirective = directive == unit.directives.first;
+          Annotation? lastLibraryAnnotation;
+          if (isPsuedoLibraryDirective) {
+            // Find the last library-level annotation that does not come
+            // after any non-library annotation. If there are already
+            // non-library annotations before library annotations, we will not
+            // try to correct those.
+            lastLibraryAnnotation = directive.metadata
+                .takeWhile(_isLibraryTargetAnnotation)
+                .lastOrNull;
+            if (lastLibraryAnnotation != null) {
+              libraryDocsAndAnnotationsEndOffset =
+                  lineInfo.getOffsetOfLineAfter(lastLibraryAnnotation.end);
+              // In the case of a blank line after the last library annotation
+              // we should include that in the library part. Otherwise it will
+              // be included in the top of the following directive and may
+              // result in an extra blank line in the annotation block if it
+              // is moved.
+              final nextLineOffset = lineInfo
+                  .getOffsetOfLineAfter(libraryDocsAndAnnotationsEndOffset);
+              if (code
+                  .substring(libraryDocsAndAnnotationsEndOffset, nextLineOffset)
+                  .trim()
+                  .isEmpty) {
+                libraryDocsAndAnnotationsEndOffset = nextLineOffset;
+              }
+            }
+          }
+
+          // Usually we look for leading comments on the directive. However if
+          // some library annotations were trimmed off, those comments are part
+          // of that and should not also be included here.
+          final leadingToken =
+              lastLibraryAnnotation == null ? directive.beginToken : null;
+          final leadingComment = leadingToken != null
+              ? getLeadingComment(unit, leadingToken, lineInfo)
+              : null;
+          final trailingComment = getTrailingComment(unit, directive, lineInfo);
+
+          /// Computes the offset to use for the start of directive-specific
+          /// code below taking into account code already included by
+          /// [libraryDocsAndAnnotationsEndOffset].
+          final clampedOffset = libraryDocsAndAnnotationsEndOffset == null
+              ? (int offset) => offset
+              : (int offset) =>
+                  math.max(libraryDocsAndAnnotationsEndOffset!, offset);
 
           String? leadingCommentText;
-          if (leadingComment != null) {
-            leadingCommentText =
-                code.substring(leadingComment.offset, directive.offset);
-            offset = leadingComment.offset;
+          if (leadingComment != null && leadingToken != null) {
+            offset = clampedOffset(leadingComment.offset);
+            leadingCommentText = code.substring(
+              offset,
+              clampedOffset(leadingToken.offset),
+            );
           }
           String? trailingCommentText;
           if (trailingComment != null) {
@@ -97,13 +154,33 @@
           var documentationComment = directive.documentationComment;
           if (documentationComment != null) {
             documentationText = code.substring(
-                documentationComment.offset, documentationComment.end);
+              clampedOffset(documentationComment.offset),
+              clampedOffset(documentationComment.end),
+            );
           }
           String? annotationText;
+          String? postAnnotationCommentText;
           var beginToken = directive.metadata.beginToken;
           var endToken = directive.metadata.endToken;
           if (beginToken != null && endToken != null) {
-            annotationText = code.substring(beginToken.offset, endToken.end);
+            var annotationOffset = clampedOffset(beginToken.offset);
+            var annotationEnd = clampedOffset(endToken.end);
+            if (annotationOffset != annotationEnd) {
+              annotationText = code.substring(
+                annotationOffset,
+                annotationEnd,
+              );
+            }
+            // Capture text between the end of the annotation and the directive
+            // text as there may be end-of line or line comments between.
+            // If not, this will capture the newline between the two, as it
+            // cannot be assumed there is a newline after annotationText because
+            // of the possibility of comments.
+            if (annotationEnd <
+                directive.firstTokenAfterCommentAndMetadata.offset) {
+              postAnnotationCommentText = code.substring(annotationEnd,
+                  directive.firstTokenAfterCommentAndMetadata.offset);
+            }
           }
           var text = code.substring(
               directive.firstTokenAfterCommentAndMetadata.offset,
@@ -116,9 +193,12 @@
               leadingCommentText,
               documentationText,
               annotationText,
+              postAnnotationCommentText,
               uriContent,
               trailingCommentText,
-              offset,
+              isPsuedoLibraryDirective
+                  ? (libraryDocsAndAnnotationsEndOffset ?? offset)
+                  : offset,
               end,
               text,
             ),
@@ -151,7 +231,7 @@
         sb.write(libraryDocumentationDirective.documentationText);
         sb.write(endOfLine);
       }
-      var currentPriority = directives.first.priority;
+      _DirectivePriority? currentPriority;
       for (var directiveInfo in directives) {
         if (!hasUnresolvedIdentifierError) {
           var directive = directiveInfo.directive;
@@ -160,7 +240,9 @@
           }
         }
         if (currentPriority != directiveInfo.priority) {
-          sb.write(endOfLine);
+          if (currentPriority != null) {
+            sb.write(endOfLine);
+          }
           currentPriority = directiveInfo.priority;
         }
         if (directiveInfo.leadingCommentText != null) {
@@ -173,7 +255,9 @@
         }
         if (directiveInfo.annotationText != null) {
           sb.write(directiveInfo.annotationText);
-          sb.write(endOfLine);
+        }
+        if (directiveInfo.postAnnotationCommentText != null) {
+          sb.write(directiveInfo.postAnnotationCommentText);
         }
         sb.write(directiveInfo.text);
         if (directiveInfo.trailingCommentText != null) {
@@ -230,7 +314,7 @@
   }
 
   /// Gets the first comment token considered to be the leading comment for this
-  /// directive.
+  /// token.
   ///
   /// Leading comments for the first directive in a file are considered library
   /// comments and not returned unless they contain blank lines, in which case
@@ -239,12 +323,12 @@
   /// '// ignore:' comment which should always be treated as attached to the
   /// import.
   static Token? getLeadingComment(
-      CompilationUnit unit, UriBasedDirective directive, LineInfo lineInfo) {
-    if (directive.beginToken.precedingComments == null) {
+      CompilationUnit unit, Token beginToken, LineInfo lineInfo) {
+    if (beginToken.precedingComments == null) {
       return null;
     }
 
-    Token? firstComment = directive.beginToken.precedingComments;
+    Token? firstComment = beginToken.precedingComments;
     var comment = firstComment;
     var nextComment = comment?.next;
     // Don't connect comments that have a blank line between them
@@ -274,7 +358,7 @@
     // Skip over any comments on the same line as the previous directive
     // as they will be attached to the end of it.
     var previousDirectiveLine =
-        lineInfo.getLocation(directive.beginToken.previous!.end).lineNumber;
+        lineInfo.getLocation(beginToken.previous!.end).lineNumber;
     comment = firstComment;
     while (comment != null &&
         previousDirectiveLine ==
@@ -289,9 +373,9 @@
   ///
   /// To be considered a trailing comment, the comment must be on the same line
   /// as the directive.
-  static Token? getTrailingComment(CompilationUnit unit,
-      UriBasedDirective directive, LineInfo lineInfo, int end) {
-    var line = lineInfo.getLocation(end).lineNumber;
+  static Token? getTrailingComment(
+      CompilationUnit unit, UriBasedDirective directive, LineInfo lineInfo) {
+    var line = lineInfo.getLocation(directive.end).lineNumber;
     Token? comment = directive.endToken.next!.precedingComments;
     while (comment != null) {
       if (lineInfo.getLocation(comment.offset).lineNumber == line) {
@@ -306,6 +390,10 @@
   /// '// ignore_for_file:' comment).
   static bool _isIgnoreComment(Token token) =>
       IgnoreInfo.IGNORE_MATCHER.matchAsPrefix(token.lexeme) != null;
+
+  static bool _isLibraryTargetAnnotation(Annotation annotation) =>
+      annotation.elementAnnotation?.targetKinds.contains(TargetKind.library) ??
+      false;
 }
 
 class _DirectiveInfo implements Comparable<_DirectiveInfo> {
@@ -314,6 +402,7 @@
   final String? leadingCommentText;
   final String? documentationText;
   final String? annotationText;
+  final String? postAnnotationCommentText;
   final String uri;
   final String? trailingCommentText;
 
@@ -332,6 +421,7 @@
     this.leadingCommentText,
     this.documentationText,
     this.annotationText,
+    this.postAnnotationCommentText,
     this.uri,
     this.trailingCommentText,
     this.offset,
diff --git a/pkg/analysis_server/test/mock_packages/meta/lib/meta_meta.dart b/pkg/analysis_server/test/mock_packages/meta/lib/meta_meta.dart
new file mode 100644
index 0000000..18902be
--- /dev/null
+++ b/pkg/analysis_server/test/mock_packages/meta/lib/meta_meta.dart
@@ -0,0 +1,123 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Annotations that describe the intended use of other annotations.
+library meta_meta;
+
+/// An annotation used on classes that are intended to be used as annotations
+/// to indicate the kinds of declarations and directives for which the
+/// annotation is appropriate.
+///
+/// The kinds are represented by the constants defined in [TargetKind].
+///
+/// Tools, such as the analyzer, can provide feedback if
+///
+/// * the annotation is associated with anything other than a class, where the
+///   class must be usable as an annotation (that is, contain at least one
+///   `const` constructor).
+/// * the annotated annotation is associated with anything other than the kinds
+///   of declarations listed as valid targets.
+@Target({TargetKind.classType})
+class Target {
+  /// The kinds of declarations with which the annotated annotation can be
+  /// associated.
+  final Set<TargetKind> kinds;
+
+  const Target(this.kinds);
+}
+
+/// An enumeration of the kinds of targets to which an annotation can be
+/// applied.
+enum TargetKind {
+  /// Indicates that an annotation is valid on any class declaration.
+  classType,
+
+  /// Indicates that an annotation is valid on any enum declaration.
+  enumType,
+
+  /// Indicates that an annotation is valid on any extension declaration.
+  extension,
+
+  /// Indicates that an annotation is valid on any field declaration, both
+  /// instance and static fields, whether it's in a class, mixin or extension.
+  field,
+
+  /// Indicates that an annotation is valid on any top-level function
+  /// declaration.
+  function,
+
+  /// Indicates that an annotation is valid on the first directive in a library,
+  /// whether that's a `library`, `import`, `export` or `part` directive. This
+  /// doesn't include the `part of` directive in a part file.
+  library,
+
+  /// Indicates that an annotation is valid on any getter declaration, both
+  /// instance or static getters, whether it's in a class, mixin, extension, or
+  /// at the top-level of a library.
+  getter,
+
+  /// Indicates that an annotation is valid on any method declaration, both
+  /// instance and static methods, whether it's in a class, mixin or extension.
+  method,
+
+  /// Indicates that an annotation is valid on any mixin declaration.
+  mixinType,
+
+  /// Indicates that an annotation is valid on any formal parameter declaration,
+  /// whether it's in a function, method, constructor, or closure.
+  parameter,
+
+  /// Indicates that an annotation is valid on any setter declaration, both
+  /// instance or static setters, whether it's in a class, mixin, extension, or
+  /// at the top-level of a library.
+  setter,
+
+  /// Indicates that an annotation is valid on any top-level variable
+  /// declaration.
+  topLevelVariable,
+
+  /// Indicates that an annotation is valid on any declaration that introduces a
+  /// type. This includes classes, enums, mixins and typedefs, but does not
+  /// include extensions because extensions don't introduce a type.
+  type,
+
+  /// Indicates that an annotation is valid on any typedef declaration.
+  typedefType,
+}
+
+extension TargetKindExtension on TargetKind {
+  /// Return a user visible string used to describe this target kind.
+  String get displayString {
+    switch (this) {
+      case TargetKind.classType:
+        return 'classes';
+      case TargetKind.enumType:
+        return 'enums';
+      case TargetKind.extension:
+        return 'extensions';
+      case TargetKind.field:
+        return 'fields';
+      case TargetKind.function:
+        return 'top-level functions';
+      case TargetKind.library:
+        return 'libraries';
+      case TargetKind.getter:
+        return 'getters';
+      case TargetKind.method:
+        return 'methods';
+      case TargetKind.mixinType:
+        return 'mixins';
+      case TargetKind.parameter:
+        return 'parameters';
+      case TargetKind.setter:
+        return 'setters';
+      case TargetKind.topLevelVariable:
+        return 'top-level variables';
+      case TargetKind.type:
+        return 'types (classes, enums, mixins, or typedefs)';
+      case TargetKind.typedefType:
+        return 'typedefs';
+    }
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index e5d3720..83312b9 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -531,7 +531,7 @@
     result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
 
     // Build the request
-    var request = DartCompletionRequest(
+    var request = DartCompletionRequest.forResolvedUnit(
       resolvedUnit: result,
       offset: completionOffset,
       dartdocDirectiveInfo: dartdocInfo,
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index c60efba..be920e7 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -52,7 +52,7 @@
     // Build the request
     var resolvedUnit =
         await session.getResolvedUnit(testFile) as ResolvedUnitResult;
-    request = DartCompletionRequest(
+    request = DartCompletionRequest.forResolvedUnit(
       resolvedUnit: resolvedUnit,
       offset: completionOffset,
     );
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index f28613f..160c31d 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -22,6 +22,12 @@
 class OrganizeDirectivesTest extends AbstractSingleUnitTest {
   late List<AnalysisError> testErrors;
 
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfig(meta: true);
+  }
+
   Future<void> test_docComment_beforeDirective_hasUnresolvedIdentifier() async {
     await _computeUnitAndErrors(r'''
 /// Library documentation comment A
@@ -682,6 +688,219 @@
 import 'package:b/a.dart';''');
   }
 
+  Future<void> test_sort_libraryAnnotation_movedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+// annotations
+import 'annotations.dart';
+
+// io
+import 'dart:io';
+''');
+    // Validate annotation is not moved with import.
+    _assertOrganize(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+// io
+import 'dart:io';
+
+// annotations
+import 'annotations.dart';
+''');
+  }
+
+  Future<void> test_sort_libraryAnnotation_removedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+// io
+import 'dart:io'; // unused
+// annotations
+import 'annotations.dart'; // used
+''');
+    // Validate annotation is not removed with import.
+    _assertOrganize(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+// annotations
+import 'annotations.dart'; // used
+''', removeUnused: true);
+  }
+
+  Future<void> test_sort_multipleAnnotation_movedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+@nonLibraryAnnotation
+import 'annotations.dart';
+@nonLibraryAnnotation
+import 'dart:io';
+''');
+    // Validate only the non-library annotation is moved with import.
+    _assertOrganize(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+@nonLibraryAnnotation
+import 'dart:io';
+
+@nonLibraryAnnotation
+import 'annotations.dart';
+''');
+  }
+
+  Future<void> test_sort_multipleAnnotation_removedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+@nonLibraryAnnotation
+import 'dart:io';
+@nonLibraryAnnotation
+import 'annotations.dart';
+''');
+    // Validate only the non-library annotation is removed with import.
+    _assertOrganize(r'''
+@libraryAnnotation
+@LibraryAnnotation()
+
+@nonLibraryAnnotation
+import 'annotations.dart';
+''', removeUnused: true);
+  }
+
+  Future<void> test_sort_multipleAnnotationWithComments_movedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+// lib1
+@libraryAnnotation // lib1
+// lib2
+@LibraryAnnotation() // lib2
+
+// nonLib on annotations import
+@nonLibraryAnnotation // nonLib on annotations import
+// annotations import
+import 'annotations.dart'; // annotations import
+// nonLib on io import
+@nonLibraryAnnotation // nonLib on io import
+// io import
+import 'dart:io'; // io import
+''');
+    // Validate only the non-library annotation is moved with import.
+    _assertOrganize(r'''
+// lib1
+@libraryAnnotation // lib1
+// lib2
+@LibraryAnnotation() // lib2
+
+// nonLib on io import
+@nonLibraryAnnotation // nonLib on io import
+// io import
+import 'dart:io'; // io import
+
+// nonLib on annotations import
+@nonLibraryAnnotation // nonLib on annotations import
+// annotations import
+import 'annotations.dart'; // annotations import
+''');
+  }
+
+  Future<void>
+      test_sort_multipleAnnotationWithComments_removedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+// lib1
+@libraryAnnotation // lib1
+// lib2
+@LibraryAnnotation() // lib2
+
+// nonLib on io import
+@nonLibraryAnnotation // nonLib on io import
+// io import
+import 'dart:io'; // io import
+// nonLib on annotations import
+@nonLibraryAnnotation // nonLib on annotations import
+// annotations import
+import 'annotations.dart'; // annotations import
+''');
+    // Validate only the non-library annotation is removed with import.
+    _assertOrganize(r'''
+// lib1
+@libraryAnnotation // lib1
+// lib2
+@LibraryAnnotation() // lib2
+
+// nonLib on annotations import
+@nonLibraryAnnotation // nonLib on annotations import
+// annotations import
+import 'annotations.dart'; // annotations import
+''', removeUnused: true);
+  }
+
+  Future<void> test_sort_nonLibraryAnnotation_movedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+@nonLibraryAnnotation
+import 'annotations.dart';
+
+import 'dart:io';
+''');
+    // Validate annotation is moved with import.
+    _assertOrganize(r'''
+import 'dart:io';
+
+@nonLibraryAnnotation
+import 'annotations.dart';
+''');
+  }
+
+  Future<void> test_sort_nonLibraryAnnotation_removedDirective() async {
+    await _addAnnotationsFile();
+    await _computeUnitAndErrors(r'''
+@nonLibraryAnnotation
+// io
+import 'dart:io'; // unused
+// annotations
+import 'annotations.dart'; // used
+''');
+    // Validate annotation is removed with import.
+    _assertOrganize(r'''
+// annotations
+import 'annotations.dart'; // used
+''', removeUnused: true);
+  }
+
+  Future<void> _addAnnotationsFile() async {
+    final annotationsFile = convertPath('/home/test/lib/annotations.dart');
+    const annotationsContent = '''
+import 'package:meta/meta_meta.dart';
+
+const libraryAnnotation = LibraryAnnotation();
+const nonLibraryAnnotation = NonLibraryAnnotation();
+
+@Target({TargetKind.library})
+class LibraryAnnotation {
+  const LibraryAnnotation();
+}
+
+@Target({TargetKind.classType})
+class NonLibraryAnnotation {
+  const NonLibraryAnnotation();
+}
+    ''';
+    addSource(annotationsFile, annotationsContent);
+  }
+
   void _assertOrganize(String expectedCode, {bool removeUnused = false}) {
     var organizer = ImportOrganizer(testCode, testUnit, testErrors,
         removeUnused: removeUnused);
diff --git a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
index 8c8bc43..9f66816 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
@@ -27,7 +27,7 @@
   }
 
   Future<CompletionSuggestion> forTopLevelFunction(String functionName) async {
-    var request = DartCompletionRequest(
+    var request = DartCompletionRequest.forResolvedUnit(
       resolvedUnit: testAnalysisResult,
       offset: 0,
     );
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index e0754be..2f7a688 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -99,7 +99,7 @@
           }
 
           timer.start();
-          var dartRequest = DartCompletionRequest(
+          var dartRequest = DartCompletionRequest.forResolvedUnit(
             resolvedUnit: result,
             offset: offset,
           );
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index b57a1f8..a6a9b85 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1368,7 +1368,7 @@
             {required MetricsSuggestionListener listener,
             required CompletionMetrics metrics}) async {
           var stopwatch = Stopwatch()..start();
-          var request = DartCompletionRequest(
+          var request = DartCompletionRequest.forResolvedUnit(
             resolvedUnit: resolvedUnitResult,
             offset: expectedCompletion.offset,
             documentationCache: documentationCache,
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index cc61b66..e87c02d 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -9,10 +9,10 @@
 
 ## Running the Server
 
-The analysis server snapshot is included in the `bin/snapshots` folder of the Dart SDK. Pass the `--lsp` flag to start the server in LSP mode and the `--client-id` and `--client-version` flags to identify your editor/plugin and version:
+Start the language server using the `dart language-server` command. Pass the `--client-id` and `--client-version` flags to identify your editor/plugin and version:
 
 ```
-dart bin/snapshots/analysis_server.dart.snapshot --lsp --client-id my-editor.my-plugin --client-version 1.2
+dart language-server --client-id my-editor.my-plugin --client-version 1.2
 ```
 
 Note: In LSP the client makes the first request so there is no obvious confirmation that the server is working correctly until the client sends an `initialize` request. Unlike standard JSON RPC, [LSP requires that headers are sent](https://microsoft.github.io/language-server-protocol/specification).
diff --git a/pkg/analyzer/lib/src/dart/element/extensions.dart b/pkg/analyzer/lib/src/dart/element/extensions.dart
index 6eaa94a..7037407 100644
--- a/pkg/analyzer/lib/src/dart/element/extensions.dart
+++ b/pkg/analyzer/lib/src/dart/element/extensions.dart
@@ -6,6 +6,58 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta_meta.dart';
+
+extension ElementAnnotationExtensions on ElementAnnotation {
+  static final Map<String, TargetKind> _targetKindsByName = {
+    for (final kind in TargetKind.values) kind.toString(): kind,
+  };
+
+  /// Return the target kinds defined for this [ElementAnnotation].
+  Set<TargetKind> get targetKinds {
+    final element = this.element;
+    ClassElement? classElement;
+    if (element is PropertyAccessorElement) {
+      if (element.isGetter) {
+        var type = element.returnType;
+        if (type is InterfaceType) {
+          classElement = type.element;
+        }
+      }
+    } else if (element is ConstructorElement) {
+      classElement = element.enclosingElement;
+    }
+    if (classElement == null) {
+      return const <TargetKind>{};
+    }
+    for (var annotation in classElement.metadata) {
+      if (annotation.isTarget) {
+        var value = annotation.computeConstantValue()!;
+        var kinds = <TargetKind>{};
+
+        for (var kindObject in value.getField('kinds')!.toSetValue()!) {
+          // We can't directly translate the index from the analyzed TargetKind
+          // constant to TargetKinds.values because the analyzer from the SDK
+          // may have been compiled with a different version of pkg:meta.
+          var index = kindObject.getField('index')!.toIntValue()!;
+          var targetKindClass =
+              (kindObject.type as InterfaceType).element as EnumElementImpl;
+          // Instead, map constants to their TargetKind by comparing getter
+          // names.
+          var getter = targetKindClass.constants[index];
+          var name = 'TargetKind.${getter.name}';
+
+          var foundTargetKind = _targetKindsByName[name];
+          if (foundTargetKind != null) {
+            kinds.add(foundTargetKind);
+          }
+        }
+        return kinds;
+      }
+    }
+    return const <TargetKind>{};
+  }
+}
 
 extension ElementExtension on Element {
   /// Return `true` if this element is an instance member of a class or mixin.
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 2e4ffc1..5468b6a 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -44,10 +44,6 @@
 class BestPracticesVerifier extends RecursiveAstVisitor<void> {
   static const String _TO_INT_METHOD_NAME = "toInt";
 
-  static final Map<String, TargetKind> _targetKindsByName = {
-    for (final kind in TargetKind.values) kind.toString(): kind,
-  };
-
   /// The class containing the AST nodes being visited, or `null` if we are not
   /// in the scope of a class.
   ClassElementImpl? _enclosingClass;
@@ -305,7 +301,7 @@
       }
     }
 
-    var kinds = _targetKindsFor(element);
+    var kinds = element.targetKinds;
     if (kinds.isNotEmpty) {
       if (!_isValidTarget(parent, kinds)) {
         var invokedElement = element.element!;
@@ -1717,51 +1713,6 @@
     return false;
   }
 
-  /// Return the target kinds defined for the given [annotation].
-  Set<TargetKind> _targetKindsFor(ElementAnnotation annotation) {
-    var element = annotation.element;
-    ClassElement? classElement;
-    if (element is PropertyAccessorElement) {
-      if (element.isGetter) {
-        var type = element.returnType;
-        if (type is InterfaceType) {
-          classElement = type.element;
-        }
-      }
-    } else if (element is ConstructorElement) {
-      classElement = element.enclosingElement;
-    }
-    if (classElement == null) {
-      return const <TargetKind>{};
-    }
-    for (var annotation in classElement.metadata) {
-      if (annotation.isTarget) {
-        var value = annotation.computeConstantValue()!;
-        var kinds = <TargetKind>{};
-
-        for (var kindObject in value.getField('kinds')!.toSetValue()!) {
-          // We can't directly translate the index from the analyzed TargetKind
-          // constant to TargetKinds.values because the analyzer from the SDK
-          // may have been compiled with a different version of pkg:meta.
-          var index = kindObject.getField('index')!.toIntValue()!;
-          var targetKindClass =
-              (kindObject.type as InterfaceType).element as EnumElementImpl;
-          // Instead, map constants to their TargetKind by comparing getter
-          // names.
-          var getter = targetKindClass.constants[index];
-          var name = 'TargetKind.${getter.name}';
-
-          var foundTargetKind = _targetKindsByName[name];
-          if (foundTargetKind != null) {
-            kinds.add(foundTargetKind);
-          }
-        }
-        return kinds;
-      }
-    }
-    return const <TargetKind>{};
-  }
-
   /// Checks for the passed as expression for the [HintCode.UNNECESSARY_CAST]
   /// hint code.
   ///
diff --git a/sdk/lib/convert/latin1.dart b/sdk/lib/convert/latin1.dart
index f396682..76b2dbd 100644
--- a/sdk/lib/convert/latin1.dart
+++ b/sdk/lib/convert/latin1.dart
@@ -63,12 +63,48 @@
 }
 
 /// This class converts strings of only ISO Latin-1 characters to bytes.
+///
+/// Example:
+/// ```dart
+/// final latin1Encoder = latin1.encoder;
+///
+/// const sample = 'àáâãäå';
+/// final encoded = latin1Encoder.convert(sample);
+/// print(encoded); // [224, 225, 226, 227, 228, 229]
+/// ```
 class Latin1Encoder extends _UnicodeSubsetEncoder {
   const Latin1Encoder() : super(_latin1Mask);
 }
 
 /// This class converts Latin-1 bytes (lists of unsigned 8-bit integers)
 /// to a string.
+///
+/// Example:
+/// ```dart
+/// final latin1Decoder = latin1.decoder;
+///
+/// const encodedBytes = [224, 225, 226, 227, 228, 229];
+/// final decoded = latin1Decoder.convert(encodedBytes);
+/// print(decoded); // àáâãäå
+///
+/// // Hexadecimal values as source
+/// const hexBytes = [0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5];
+/// final decodedHexBytes = latin1Decoder.convert(hexBytes);
+/// print(decodedHexBytes); // àáâãäå
+/// ```
+/// Throws a [FormatException] if the encoded input contains values that are
+/// not in the range 0 .. 255 and [allowInvalid] is false ( the default ).
+///
+/// If [allowInvalid] is true, invalid bytes are converted
+/// to Unicode Replacement character U+FFFD (�).
+///
+/// Example with `allowInvalid` set to true:
+/// ```dart
+/// const latin1Decoder = Latin1Decoder(allowInvalid: true);
+/// const encodedBytes = [300];
+/// final decoded = latin1Decoder.convert(encodedBytes);
+/// print(decoded); // �
+/// ```
 class Latin1Decoder extends _UnicodeSubsetDecoder {
   /// Instantiates a new [Latin1Decoder].
   ///
diff --git a/tools/VERSION b/tools/VERSION
index 7b162d3..786d33b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 296
+PRERELEASE 297
 PRERELEASE_PATCH 0
\ No newline at end of file