Version 2.16.0-11.0.dev

Merge commit 'ecdcde3a838e1c88c2d00df3b8d36a916b628b49' into 'dev'
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color.dart
new file mode 100644
index 0000000..07bf25b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2021, 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.
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/computer/computer_color.dart'
+    show ColorComputer, ColorReference;
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+
+/// Handles textDocument/documentColor requests.
+///
+/// This request is sent by the client to the server to request the locations
+/// of any colors in the document so that it can render color previews. If the
+/// editor has a color picker, it may also call textDocument/colorPresentation
+/// to obtain the code to insert when a new color is selected (see
+/// [DocumentColorPresentationHandler]).
+class DocumentColorHandler
+    extends MessageHandler<DocumentColorParams, List<ColorInformation>> {
+  DocumentColorHandler(LspAnalysisServer server) : super(server);
+  @override
+  Method get handlesMessage => Method.textDocument_documentColor;
+
+  @override
+  LspJsonHandler<DocumentColorParams> get jsonHandler =>
+      DocumentColorParams.jsonHandler;
+
+  @override
+  Future<ErrorOr<List<ColorInformation>>> handle(
+      DocumentColorParams params, CancellationToken token) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success([]);
+    }
+
+    final path = pathOfDoc(params.textDocument);
+    final unit = await path.mapResult(requireResolvedUnit);
+    return unit.mapResult((unit) => _getColors(unit));
+  }
+
+  ErrorOr<List<ColorInformation>> _getColors(ResolvedUnitResult unit) {
+    ColorInformation _toColorInformation(ColorReference reference) {
+      return ColorInformation(
+        range: toRange(unit.lineInfo, reference.offset, reference.length),
+        color: Color(
+          // LSP colors are decimal in the range 0-1 but our internal references
+          // are 0-255, so divide them.
+          alpha: reference.color.alpha / 255,
+          red: reference.color.red / 255,
+          green: reference.color.green / 255,
+          blue: reference.color.blue / 255,
+        ),
+      );
+    }
+
+    final computer = ColorComputer(unit);
+    final colors = computer.compute();
+    return success(colors.map(_toColorInformation).toList());
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart
new file mode 100644
index 0000000..52f09fb
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart
@@ -0,0 +1,122 @@
+// Copyright (c) 2021, 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.
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer/src/dart/analysis/session_helper.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+
+/// Handles textDocument/colorPresentation.
+///
+/// This request is sent by the client if it allowed the user to pick a color
+/// using a color picker (in a location returned by textDocument/documentColor)
+/// and needs a representation of this color, including the edits to insert it
+/// into the source file.
+class DocumentColorPresentationHandler
+    extends MessageHandler<ColorPresentationParams, List<ColorPresentation>> {
+  DocumentColorPresentationHandler(LspAnalysisServer server) : super(server);
+  @override
+  Method get handlesMessage => Method.textDocument_colorPresentation;
+
+  @override
+  LspJsonHandler<ColorPresentationParams> get jsonHandler =>
+      ColorPresentationParams.jsonHandler;
+
+  @override
+  Future<ErrorOr<List<ColorPresentation>>> handle(
+    ColorPresentationParams params,
+    CancellationToken token,
+  ) async {
+    if (!isDartDocument(params.textDocument)) {
+      return success([]);
+    }
+
+    final path = pathOfDoc(params.textDocument);
+    final unit = await path.mapResult(requireResolvedUnit);
+    return unit.mapResult((unit) => _getPresentations(params, unit));
+  }
+
+  /// Converts individual 0-255 ARGB values into a single int value as
+  /// 0xAARRGGBB as used by the dart:ui Color class.
+  int _colorValueForComponents(int alpha, int red, int green, int blue) {
+    return (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
+  }
+
+  /// Builds a list of valid color presentations for the requested color.
+  ///
+  /// Currently only a single presentation (`Color(0xAARRGGBB)`) is provided.
+  Future<ErrorOr<List<ColorPresentation>>> _getPresentations(
+    ColorPresentationParams params,
+    ResolvedUnitResult unit,
+  ) async {
+    // The values in LSP are decimals 0-1 so should be scaled up to 255 that
+    // we use internally.
+    final colorValue = _colorValueForComponents(
+      (params.color.alpha * 255).toInt(),
+      (params.color.red * 255).toInt(),
+      (params.color.green * 255).toInt(),
+      (params.color.blue * 255).toInt(),
+    );
+
+    final colorValueHex =
+        '0x${colorValue.toRadixString(16).toUpperCase().padLeft(8, '0')}';
+
+    final editStart = toOffset(unit.lineInfo, params.range.start);
+    final editEnd = toOffset(unit.lineInfo, params.range.end);
+
+    if (editStart.isError) return failure(editStart);
+    if (editEnd.isError) return failure(editEnd);
+
+    final editRange =
+        SourceRange(editStart.result, editEnd.result - editStart.result);
+
+    final sessionHelper = AnalysisSessionHelper(unit.session);
+    final flutter = Flutter.instance;
+    final colorType = await sessionHelper.getClass(flutter.widgetsUri, 'Color');
+    if (colorType == null) {
+      // If we can't find the class (perhaps because this isn't a Flutter
+      // project) we will not include any results. In theory the client should
+      // not be calling this request in that case.
+      return success([]);
+    }
+
+    final builder = ChangeBuilder(session: unit.session);
+    await builder.addDartFileEdit(unit.path, (builder) {
+      builder.addReplacement(editRange, (builder) {
+        builder.writeType(colorType.thisType);
+        builder.write('($colorValueHex)');
+      });
+    });
+
+    // We can only apply changes to the same file, so filter any change from the
+    // builder to only include this file, otherwise we may corrupt the users
+    // source (although hopefully we don't produce edits for other files).
+    final editsForThisFile = builder.sourceChange.edits
+        .where((edit) => edit.file == unit.path)
+        .expand((edit) => edit.edits)
+        .toList();
+
+    // LSP requires that we separate the main edit (changing the color code)
+    // from anything else (imports).
+    final mainEdit =
+        editsForThisFile.singleWhere((edit) => edit.offset == editRange.offset);
+    final otherEdits =
+        editsForThisFile.where((edit) => edit.offset != editRange.offset);
+
+    return success([
+      ColorPresentation(
+        label: 'Color($colorValueHex)',
+        textEdit: toTextEdit(unit.lineInfo, mainEdit),
+        additionalTextEdits:
+            otherEdits.map((edit) => toTextEdit(unit.lineInfo, edit)).toList(),
+      ),
+    ]);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index c0e413d..0d9eb19 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -15,6 +15,8 @@
 import 'package:analysis_server/src/lsp/handlers/handler_completion.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_completion_resolve.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_definition.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_document_color.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_document_color_presentation.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_document_highlights.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_document_symbols.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_execute_command.dart';
@@ -77,6 +79,8 @@
       server,
       server.initializationOptions.suggestFromUnimportedLibraries,
     ));
+    registerHandler(DocumentColorHandler(server));
+    registerHandler(DocumentColorPresentationHandler(server));
     registerHandler(CompletionResolveHandler(server));
     registerHandler(SignatureHelpHandler(server));
     registerHandler(DefinitionHandler(server));
diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
index 36bff9b..5a009f5 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -30,6 +30,7 @@
     Method.textDocument_signatureHelp,
     Method.textDocument_references,
     Method.textDocument_documentHighlight,
+    Method.textDocument_documentColor,
     Method.textDocument_formatting,
     Method.textDocument_onTypeFormatting,
     Method.textDocument_rangeFormatting,
@@ -52,6 +53,9 @@
   bool get codeActions =>
       _capabilities.textDocument?.foldingRange?.dynamicRegistration ?? false;
 
+  bool get colorProvider =>
+      _capabilities.textDocument?.colorProvider?.dynamicRegistration ?? false;
+
   bool get completion =>
       _capabilities.textDocument?.completion?.dynamicRegistration ?? false;
 
@@ -130,8 +134,15 @@
   Set<Registration> currentRegistrations = {};
   var _lastRegistrationId = 0;
 
-  ServerCapabilitiesComputer(this._server);
+  final dartFiles = DocumentFilter(language: 'dart', scheme: 'file');
+  final pubspecFile = DocumentFilter(
+      language: 'yaml', scheme: 'file', pattern: '**/pubspec.yaml');
+  final analysisOptionsFile = DocumentFilter(
+      language: 'yaml', scheme: 'file', pattern: '**/analysis_options.yaml');
+  final fixDataFile = DocumentFilter(
+      language: 'yaml', scheme: 'file', pattern: '**/lib/fix_data.yaml');
 
+  ServerCapabilitiesComputer(this._server);
   ServerCapabilities computeServerCapabilities(
       LspClientCapabilities clientCapabilities) {
     final codeActionLiteralSupport = clientCapabilities.literalCodeActions;
@@ -210,6 +221,11 @@
                   codeActionKinds: DartCodeActionKind.serverSupportedKinds,
                 ))
               : Either2<bool, CodeActionOptions>.t1(true),
+      colorProvider: dynamicRegistrations.colorProvider
+          ? null
+          : Either3<bool, DocumentColorOptions,
+                  DocumentColorRegistrationOptions>.t3(
+              DocumentColorRegistrationOptions(documentSelector: [dartFiles])),
       documentFormattingProvider: dynamicRegistrations.formatting
           ? null
           : Either2<bool, DocumentFormattingOptions>.t1(enableFormatter),
@@ -279,14 +295,6 @@
   /// support and it will be up to them to decide which file types they will
   /// send requests for.
   Future<void> performDynamicRegistration() async {
-    final dartFiles = DocumentFilter(language: 'dart', scheme: 'file');
-    final pubspecFile = DocumentFilter(
-        language: 'yaml', scheme: 'file', pattern: '**/pubspec.yaml');
-    final analysisOptionsFile = DocumentFilter(
-        language: 'yaml', scheme: 'file', pattern: '**/analysis_options.yaml');
-    final fixDataFile = DocumentFilter(
-        language: 'yaml', scheme: 'file', pattern: '**/lib/fix_data.yaml');
-
     final pluginTypes = _server.pluginManager.plugins
         .expand((plugin) => plugin.currentSession?.interestingFiles ?? const [])
         // All published plugins use something like `*.extension` as
@@ -410,6 +418,12 @@
       TextDocumentRegistrationOptions(documentSelector: fullySupportedTypes),
     );
     register(
+      dynamicRegistrations.colorProvider,
+      // This registration covers both documentColor and colorPresentation.
+      Method.textDocument_documentColor,
+      DocumentColorRegistrationOptions(documentSelector: [dartFiles]),
+    );
+    register(
       enableFormatter && dynamicRegistrations.formatting,
       Method.textDocument_formatting,
       TextDocumentRegistrationOptions(documentSelector: fullySupportedTypes),
diff --git a/pkg/analysis_server/test/lsp/document_color_test.dart b/pkg/analysis_server/test/lsp/document_color_test.dart
new file mode 100644
index 0000000..12dd16d
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/document_color_test.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2021, 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.
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DocumentColorTest);
+    defineReflectiveTests(DocumentColorPresentationTest);
+  });
+}
+
+@reflectiveTest
+class DocumentColorPresentationTest extends AbstractLspAnalysisServerTest {
+  @override
+  void setUp() {
+    super.setUp();
+    writePackageConfig(projectFolderPath, flutter: true);
+  }
+
+  Future<void> test_includesImportEdit() async {
+    // Create a file that doesn't already import the required library.
+    //
+    // We don't need a real color reference in the file right now, as we're
+    // calling colorPresentation directly to get the new code (and not fetching
+    // colors already in the file).
+    const content = '''
+const white = [[]];
+''';
+
+    const expectedMainEdit = '''
+const white = Color(0xFFFFFFFF);
+''';
+
+    const expectedAllEdits = '''
+import 'package:ui/ui.dart';
+
+const white = Color(0xFFFFFFFF);
+''';
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final colorPresentations = await getColorPresentation(
+      mainFileUri.toString(),
+      rangeFromMarkers(content),
+      Color(alpha: 1, red: 1, green: 1, blue: 1),
+    );
+    expect(colorPresentations, hasLength(1));
+
+    final colorPresentation = colorPresentations[0];
+    expect(colorPresentation.label, 'Color(0xFFFFFFFF)');
+
+    // Test the main edit just replaces the color.
+    final contentWithMainEdit = applyTextEdits(
+      withoutMarkers(content),
+      [colorPresentation.textEdit!],
+    );
+    expect(contentWithMainEdit, equals(expectedMainEdit));
+
+    // Test all of the edits also adds the import.
+    final contentWithAllEdits = applyTextEdits(
+      withoutMarkers(content),
+      [colorPresentation.textEdit!, ...colorPresentation.additionalTextEdits!],
+    );
+    expect(contentWithAllEdits, equals(expectedAllEdits));
+  }
+
+  Future<void> test_nonDartFile() async {
+    newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize();
+
+    final colors = await getColorPresentation(
+      pubspecFileUri.toString(),
+      startOfDocRange,
+      Color(alpha: 1, red: 1, green: 1, blue: 1),
+    );
+    expect(colors, isEmpty);
+  }
+
+  Future<void> test_simpleColor() async {
+    const content = '''
+    import 'package:flutter/material.dart';
+
+    const white = [[Color(0xFFFFFFFF)]];
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final colorPresentations = await getColorPresentation(
+      mainFileUri.toString(),
+      rangeFromMarkers(content),
+      // Send a different color to what's in the source to simulate the user
+      // having changed in the color picker. This is the one that we should be
+      // creating a presentation for, not the one in the source.
+      Color(alpha: 1, red: 1, green: 0, blue: 0),
+    );
+    expect(colorPresentations, hasLength(1));
+
+    final colorPresentation = colorPresentations[0];
+    expect(colorPresentation.label, 'Color(0xFFFF0000)');
+  }
+}
+
+@reflectiveTest
+class DocumentColorTest extends AbstractLspAnalysisServerTest {
+  @override
+  void setUp() {
+    super.setUp();
+    writePackageConfig(projectFolderPath, flutter: true);
+  }
+
+  Future<void> test_nonDartFile() async {
+    newFile(pubspecFilePath, content: simplePubspecContent);
+    await initialize();
+
+    final colors = await getDocumentColors(pubspecFileUri.toString());
+    expect(colors, isEmpty);
+  }
+
+  Future<void> test_simpleColor() async {
+    const content = '''
+    import 'package:flutter/material.dart';
+
+    const red = [[Colors.red]];
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final colors = await getDocumentColors(mainFileUri.toString());
+    expect(colors, hasLength(1));
+
+    final color = colors[0];
+    expect(color.range, rangeFromMarkers(content));
+    expect(color.color.alpha, equals(1));
+    expect(color.color.red, equals(1));
+    expect(color.color.green, equals(0));
+    expect(color.color.blue, equals(0));
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index b6bbc58..4d006be 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -230,6 +230,7 @@
     expect(initResult.capabilities.hoverProvider, isNotNull);
     expect(initResult.capabilities.signatureHelpProvider, isNotNull);
     expect(initResult.capabilities.referencesProvider, isNotNull);
+    expect(initResult.capabilities.colorProvider, isNotNull);
     expect(initResult.capabilities.documentHighlightProvider, isNotNull);
     expect(initResult.capabilities.documentFormattingProvider, isNotNull);
     expect(initResult.capabilities.documentOnTypeFormattingProvider, isNotNull);
@@ -289,6 +290,7 @@
     expect(initResult.capabilities.hoverProvider, isNull);
     expect(initResult.capabilities.signatureHelpProvider, isNull);
     expect(initResult.capabilities.referencesProvider, isNull);
+    expect(initResult.capabilities.colorProvider, isNull);
     expect(initResult.capabilities.documentHighlightProvider, isNull);
     expect(initResult.capabilities.documentFormattingProvider, isNull);
     expect(initResult.capabilities.documentOnTypeFormattingProvider, isNull);
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 6b8ba52..e46aa1b 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -284,6 +284,7 @@
       'references': {'dynamicRegistration': true},
       'documentHighlight': {'dynamicRegistration': true},
       'documentSymbol': {'dynamicRegistration': true},
+      'colorProvider': {'dynamicRegistration': true},
       'formatting': {'dynamicRegistration': true},
       'onTypeFormatting': {'dynamicRegistration': true},
       'rangeFormatting': {'dynamicRegistration': true},
@@ -1035,6 +1036,22 @@
     );
   }
 
+  Future<List<ColorPresentation>> getColorPresentation(
+      String fileUri, Range range, Color color) {
+    final request = makeRequest(
+      Method.textDocument_colorPresentation,
+      ColorPresentationParams(
+        textDocument: TextDocumentIdentifier(uri: fileUri),
+        range: range,
+        color: color,
+      ),
+    );
+    return expectSuccessfulResponseTo(
+      request,
+      _fromJsonList(ColorPresentation.fromJson),
+    );
+  }
+
   Future<List<CompletionItem>> getCompletion(Uri uri, Position pos,
       {CompletionContext? context}) {
     final request = makeRequest(
@@ -1093,6 +1110,19 @@
     return expectSuccessfulResponseTo(request, DartDiagnosticServer.fromJson);
   }
 
+  Future<List<ColorInformation>> getDocumentColors(String fileUri) {
+    final request = makeRequest(
+      Method.textDocument_documentColor,
+      DocumentColorParams(
+        textDocument: TextDocumentIdentifier(uri: fileUri),
+      ),
+    );
+    return expectSuccessfulResponseTo(
+      request,
+      _fromJsonList(ColorInformation.fromJson),
+    );
+  }
+
   Future<List<DocumentHighlight>?> getDocumentHighlights(
       Uri uri, Position pos) {
     final request = makeRequest(
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index 752d3f1..bd22081 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -20,6 +20,7 @@
 import 'definition_test.dart' as definition;
 import 'diagnostic_test.dart' as diagnostic;
 import 'document_changes_test.dart' as document_changes;
+import 'document_color_test.dart' as document_color;
 import 'document_highlights_test.dart' as document_highlights;
 import 'document_symbols_test.dart' as document_symbols;
 import 'file_modification_test.dart' as file_modification;
@@ -63,6 +64,7 @@
     document_changes.main();
     document_highlights.main();
     document_symbols.main();
+    document_color.main();
     file_modification.main();
     flutter_outline.main();
     folding.main();
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index e87c02d..ccf6e8a 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -101,8 +101,8 @@
 | codeLens/resolve | | | | | |
 | textDocument/documentLink | | | | | |
 | documentLink/resolve | | | | | |
-| textDocument/documentColor | | | | | |
-| textDocument/colorPresentation | | | | | |
+| textDocument/documentColor | ✅ | ✅ | | ✅ | ✅ |
+| textDocument/colorPresentation | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/formatting | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/rangeFormatting | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/onTypeFormatting | ✅ | ✅ | | ✅ | ✅ |
diff --git a/pkg/analyzer/lib/src/lint/pub.dart b/pkg/analyzer/lib/src/lint/pub.dart
index d68ecdf..86d7c17 100644
--- a/pkg/analyzer/lib/src/lint/pub.dart
+++ b/pkg/analyzer/lib/src/lint/pub.dart
@@ -52,17 +52,27 @@
 
 PSHost? _processHost(
     YamlScalar key, YamlNode v, ResourceProvider? resourceProvider) {
-  if (v is! YamlMap) {
-    return null;
+  if (v is YamlScalar) {
+    // dependencies:
+    //   mypkg:
+    //     hosted:  https://some-pub-server.com
+    //     version: ^1.2.3
+    _PSHost host = _PSHost(isShortForm: true);
+    host.token = _PSNode(key, resourceProvider);
+    host.url = _processScalar(key, v, resourceProvider);
+    return host;
   }
-  YamlMap hostMap = v;
-  // name: transmogrify
-  // url: http://your-package-server.com
-  _PSHost host = _PSHost();
-  host.token = _PSNode(key, resourceProvider);
-  host.name = _findEntry(hostMap, 'name', resourceProvider);
-  host.url = _findEntry(hostMap, 'url', resourceProvider);
-  return host;
+  if (v is YamlMap) {
+    YamlMap hostMap = v;
+    // name: transmogrify
+    // url: http://your-package-server.com
+    _PSHost host = _PSHost(isShortForm: false);
+    host.token = _PSNode(key, resourceProvider);
+    host.name = _findEntry(hostMap, 'name', resourceProvider);
+    host.url = _findEntry(hostMap, 'url', resourceProvider);
+    return host;
+  }
+  return null;
 }
 
 PSNodeList? _processList(
@@ -86,6 +96,16 @@
       _PSNode(key, resourceProvider), _PSNode(value, resourceProvider));
 }
 
+/// Representation of a key/value pair a map from package name to
+/// _package description_.
+///
+/// **Example** of a path-dependency:
+/// ```yaml
+/// dependencies:
+///   <name>:
+///     version: <version>
+///     path: <path>
+/// ```
 abstract class PSDependency {
   PSGitRepo? get git;
   PSHost? get host;
@@ -94,6 +114,8 @@
   PSEntry? get version;
 }
 
+/// Representation of the map from package name to _package description_ used
+/// under `dependencies`, `dev_dependencies` and `dependency_overrides`.
 abstract class PSDependencyList with IterableMixin<PSDependency> {}
 
 class PSEntry {
@@ -112,6 +134,33 @@
 }
 
 abstract class PSHost {
+  /// True, if _short-form_ for writing hosted-dependencies was used.
+  ///
+  /// **Example** of a hosted-dependency written in short-form:
+  /// ```yaml
+  /// dependencies:
+  ///   foo:
+  ///     hosted: https://some-pub-server.com
+  ///     version: ^1.2.3
+  /// ```
+  ///
+  /// The _long-form_ for writing the dependency given above is:
+  /// ```yaml
+  /// dependencies:
+  ///   foo:
+  ///     hosted:
+  ///       url: https://some-pub-server.com
+  ///       name: foo
+  ///     version: ^1.2.3
+  /// ```
+  ///
+  /// The short-form was added in Dart 2.15.0 because:
+  ///  * The `name` property just specifies the package name, which can be
+  ///    inferred from the context. So it is unnecessary to write it.
+  ///  * The nested object and `url` key becomes unnecessary when the `name`
+  ///    property is removed.
+  bool get isShortForm;
+
   PSEntry? get name;
   PSNode? get token;
   PSEntry? get url;
@@ -276,11 +325,19 @@
 
 class _PSHost implements PSHost {
   @override
-  PSNode? token;
+  bool isShortForm;
+
   @override
   PSEntry? name;
+
+  @override
+  PSNode? token;
+
   @override
   PSEntry? url;
+
+  _PSHost({required this.isShortForm});
+
   @override
   String toString() => '''
     $token:
diff --git a/pkg/analyzer/test/src/lint/pub_test.dart b/pkg/analyzer/test/src/lint/pub_test.dart
index 4e71879..6634c41 100644
--- a/pkg/analyzer/test/src/lint/pub_test.dart
+++ b/pkg/analyzer/test/src/lint/pub_test.dart
@@ -27,6 +27,13 @@
       name: transmogrify
       url: http://your-package-server.com
     version: '>=0.4.0 <1.0.0'
+  transmogrify_optional_name:
+    hosted:
+      url: http://your-package-server.com
+    version: '>=0.4.0 <1.0.0'
+  transmogrify_short_form:
+    hosted: http://your-package-server.com
+    version: '>=0.4.0 <1.0.0'
   analyzer: '0.24.0-dev.1'
   cli_util: '>=0.0.1 <0.1.0'
   semver: '>=0.2.0 <0.3.0'
@@ -108,6 +115,26 @@
         testValueSpan('name', host.name, startOffset: 243, endOffset: 255);
       });
 
+      group('hosted (optional name)', () {
+        PSDependency dep =
+            findDependency(ps.dependencies, name: 'transmogrify_optional_name');
+        PSHost host = dep.host!;
+        test('name', () => expect(host.name, isNull));
+        testValue('url', host.url, equals('http://your-package-server.com'));
+        testKeySpan('url', host.url, startOffset: 376, endOffset: 379);
+        testValueSpan('url', host.url, startOffset: 381, endOffset: 411);
+      });
+
+      group('hosted (short-form)', () {
+        PSDependency dep =
+            findDependency(ps.dependencies, name: 'transmogrify_short_form');
+        PSHost host = dep.host!;
+        test('name', () => expect(host.name, isNull));
+        testValue('url', host.url, equals('http://your-package-server.com'));
+        testKeySpan('url', host.url, startOffset: 473, endOffset: 479);
+        testValueSpan('url', host.url, startOffset: 481, endOffset: 511);
+      });
+
       group('git', () {
         PSDependency dep = findDependency(ps.dependencies, name: 'kittens');
         PSGitRepo git = dep.git!;
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index d871d5c..9d5dacc 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dart_internal
-version: 0.2.2
+version: 0.2.3
 repository: https://github.com/dart-lang/sdk/tree/master/pkg/dart_internal
 description: >-
   This package is not intended for wide use. It provides a temporary API to
@@ -9,4 +9,4 @@
 environment:
   # Restrict the upper bound so that we can remove support for this in a later
   # version of the SDK without it being a breaking change.
-  sdk: ">=2.12.0 <2.16.0"
+  sdk: ">=2.12.0 <2.17.0"
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index ba81acf..131d308 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -1124,6 +1124,7 @@
     for (var i = 0; i < mixinApplications.length; i++) {
       var m = mixinApplications[i];
       var mixinClass = m.isAnonymousMixin ? m.mixedInClass : m;
+      _declareBeforeUse(mixinClass);
       var mixinType =
           _hierarchy.getClassAsInstanceOf(c, mixinClass).asInterfaceType;
       var mixinName =
diff --git a/tests/language/mixin/regress_47645_test.dart b/tests/language/mixin/regress_47645_test.dart
new file mode 100644
index 0000000..4482a73
--- /dev/null
+++ b/tests/language/mixin/regress_47645_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2021, 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.
+
+import "package:expect/expect.dart";
+
+// Regression test for https://github.com/dart-lang/sdk/issues/47645.
+// To reproduce the issue the class declaration must appear before the mixin
+// declaration.
+class C<T> with M<C<T>> {}
+
+mixin M<T> {
+  bool fn() => true;
+}
+
+void main() {
+  var c = C<int>();
+  Expect.isTrue(c.fn());
+}
diff --git a/tests/language_2/mixin/regress_47645_test.dart b/tests/language_2/mixin/regress_47645_test.dart
new file mode 100644
index 0000000..27885e9
--- /dev/null
+++ b/tests/language_2/mixin/regress_47645_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2021, 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.
+
+// @dart = 2.9
+
+import "package:expect/expect.dart";
+
+// Regression test for https://github.com/dart-lang/sdk/issues/47645.
+// To reproduce the issue the class declaration must appear before the mixin
+// declaration.
+class C<T> with M<C<T>> {}
+
+mixin M<T> {
+  bool fn() => true;
+}
+
+void main() {
+  var c = C<int>();
+  Expect.isTrue(c.fn());
+}
diff --git a/tools/VERSION b/tools/VERSION
index 45b16ab..6a1784b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 10
+PRERELEASE 11
 PRERELEASE_PATCH 0
\ No newline at end of file