Version 2.11.0-222.0.dev

Merge commit 'ece17f73b0b1b15417d07e2dcbe79f4974f90ba0' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6234626..16ebe91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,13 @@
 
 Updated the Linter to `0.1.121`, which includes:
 
+#### Pub
+
+* New commands `pub add` and `pub remove` that adds and remove new dependencies 
+  to your `pubspec.yaml`.
+* `pub publish` will check your pubspec keys for likely typos.
+* `pub get` will print a warning if the resolution is mixed mode.
+
 # 0.1.121
 
 * Performance improvements to `always_use_package_imports`,
diff --git a/DEPS b/DEPS
index 46d8ac2..dcadfea 100644
--- a/DEPS
+++ b/DEPS
@@ -128,7 +128,7 @@
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_rev": "eedbd5fde84f9a1a8da643b475305a81841da599",
   "protobuf_rev": "3746c8fd3f2b0147623a8e3db89c3ff4330de760",
-  "pub_rev": "04e237f78b2302d7f20d0b362554425e8deb8add",
+  "pub_rev": "f0c7771b38155d3829a60d60b5dba2784b100811",
   "pub_semver_tag": "v1.4.4",
   "quiver-dart_tag": "246e754fe45cecb6aa5f3f13b4ed61037ff0d784",
   "resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 27abeb9..460fa5e 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -52,6 +52,8 @@
 /// A [ProgressToken] used for reporting progress when the server is analyzing.
 final analyzingProgressToken = Either2<num, String>.t2('ANALYZING');
 
+final emptyWorkspaceEdit = WorkspaceEdit();
+
 /// Constants for command IDs that are exchanged between LSP client/server.
 abstract class Commands {
   /// A list of all commands IDs that can be sent to the client to inform which
@@ -127,3 +129,9 @@
   ///   if it crashes 5 times in the last 180 seconds."
   static const ClientServerInconsistentState = ErrorCodes(-32099);
 }
+
+/// Strings used in user prompts (window/showMessageRequest).
+abstract class UserPromptActions {
+  static const String cancel = 'Cancel';
+  static const String renameAnyway = 'Rename Anyway';
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index a0daa67..7375cc2 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -126,7 +126,7 @@
       if (token.isCancellationRequested) {
         return cancelled();
       }
-      if (initStatus.hasError) {
+      if (initStatus.hasFatalError) {
         return error(
             ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
       }
@@ -144,9 +144,30 @@
       if (token.isCancellationRequested) {
         return cancelled();
       }
-      if (finalStatus.hasError) {
+      if (finalStatus.hasFatalError) {
         return error(
             ServerErrorCodes.RenameNotValid, finalStatus.problem.message, null);
+      } else if (finalStatus.hasError || finalStatus.hasWarning) {
+        // Ask the user whether to proceed with the rename.
+        final userChoice = await server.showUserPrompt(
+          MessageType.Warning,
+          finalStatus.message,
+          [
+            MessageActionItem(title: UserPromptActions.renameAnyway),
+            MessageActionItem(title: UserPromptActions.cancel),
+          ],
+        );
+
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
+        if (userChoice.title != UserPromptActions.renameAnyway) {
+          // Return an empty workspace edit response so we do not perform any
+          // rename, but also so we do not cause the client to show the user an
+          // error after they clicked cancel.
+          return success(emptyWorkspaceEdit);
+        }
       }
 
       // Compute the actual change.
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 85debf8..a2c0d16 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -599,6 +599,17 @@
     ));
   }
 
+  /// Shows the user a prompt with some actions to select using ShowMessageRequest.
+  Future<MessageActionItem> showUserPrompt(
+      MessageType type, String message, List<MessageActionItem> actions) async {
+    final response = await sendRequest(
+      Method.window_showMessageRequest,
+      ShowMessageRequestParams(type: type, message: message, actions: actions),
+    );
+
+    return MessageActionItem.fromJson(response.result);
+  }
+
   Future<void> shutdown() {
     // Defer closing the channel so that the shutdown response can be sent and
     // logged.
diff --git a/pkg/analysis_server/test/lsp/rename_test.dart b/pkg/analysis_server/test/lsp/rename_test.dart
index 41469c8..6c14e48 100644
--- a/pkg/analysis_server/test/lsp/rename_test.dart
+++ b/pkg/analysis_server/test/lsp/rename_test.dart
@@ -4,9 +4,11 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../tool/lsp_spec/matchers.dart';
 import 'server_abstract.dart';
 
 void main() {
@@ -130,6 +132,84 @@
         content, 'MyNewClass', expectedContent);
   }
 
+  Future<void> test_rename_duplicateName_applyAfterDocumentChanges() async {
+    // Perform a refactor that results in a prompt to the user, but then modify
+    // the document before accepting/rejecting to make the rename invalid.
+    const content = '''
+    class MyOtherClass {}
+    class MyClass {}
+    final a = n^ew MyClass();
+    ''';
+    final result = await _test_rename_prompt(
+      content,
+      'MyOtherClass',
+      expectedMessage:
+          'Library already declares class with name \'MyOtherClass\'.',
+      action: UserPromptActions.renameAnyway,
+      beforeResponding: () => replaceFile(999, mainFileUri, 'Updated content'),
+    );
+    expect(result.result, isNull);
+    expect(result.error, isNotNull);
+    expect(result.error, isResponseError(ErrorCodes.ContentModified));
+  }
+
+  Future<void> test_rename_duplicateName_applyAnyway() async {
+    const content = '''
+    class MyOtherClass {}
+    class MyClass {}
+    final a = n^ew MyClass();
+    ''';
+    const expectedContent = '''
+    class MyOtherClass {}
+    class MyOtherClass {}
+    final a = new MyOtherClass();
+    ''';
+    final response = await _test_rename_prompt(
+      content,
+      'MyOtherClass',
+      expectedMessage:
+          'Library already declares class with name \'MyOtherClass\'.',
+      action: UserPromptActions.renameAnyway,
+    );
+
+    if (response.error != null) {
+      throw response.error;
+    }
+
+    final result = WorkspaceEdit.fromJson(response.result);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyDocumentChanges(
+      contents,
+      result.documentChanges,
+    );
+    expect(contents[mainFilePath], equals(expectedContent));
+  }
+
+  Future<void> test_rename_duplicateName_reject() async {
+    const content = '''
+    class MyOtherClass {}
+    class MyClass {}
+    final a = n^ew MyClass();
+    ''';
+    final response = await _test_rename_prompt(
+      content,
+      'MyOtherClass',
+      expectedMessage:
+          'Library already declares class with name \'MyOtherClass\'.',
+      action: UserPromptActions.cancel,
+    );
+    // Expect a successful empty response if cancelled.
+    expect(response.error, isNull);
+    expect(
+      WorkspaceEdit.fromJson(response.result),
+      equals(emptyWorkspaceEdit),
+    );
+  }
+
   Future<void> test_rename_importPrefix() {
     const content = '''
     import 'dart:async' as myPr^efix;
@@ -237,17 +317,6 @@
     expect(error.message, contains('name must not contain'));
   }
 
-  Future<void> test_rename_rejectedForDuplicateName() async {
-    const content = '''
-    class MyOtherClass {}
-    class MyClass {}
-    final a = n^ew MyClass();
-    ''';
-    final error = await _test_rename_failure(content, 'MyOtherClass');
-    expect(error.code, equals(ServerErrorCodes.RenameNotValid));
-    expect(error.message, contains('already declares class with name'));
-  }
-
   Future<void> test_rename_rejectedForSameName() async {
     const content = '''
     class My^Class {}
@@ -413,6 +482,55 @@
     return result.error;
   }
 
+  /// Tests a rename that is expected to cause an error, which will trigger
+  /// a ShowMessageRequest from the server to the client to allow the refactor
+  /// to be continued or rejected.
+  Future<ResponseMessage> _test_rename_prompt(
+    String content,
+    String newName, {
+    @required String expectedMessage,
+    Future<void> Function() beforeResponding,
+    @required String action,
+    int openFileVersion = 222,
+    int renameRequestFileVersion = 222,
+  }) async {
+    await initialize(
+      workspaceCapabilities:
+          withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+    );
+    await openFile(mainFileUri, withoutMarkers(content),
+        version: openFileVersion);
+
+    // Expect the server to call us back with a ShowMessageRequest prompt about
+    // the errors for us to accept/reject.
+    return handleExpectedRequest(
+      Method.window_showMessageRequest,
+      ShowMessageRequestParams.fromJson,
+      () => renameRaw(
+        mainFileUri,
+        renameRequestFileVersion,
+        positionFromMarker(content),
+        newName,
+      ),
+      handler: (ShowMessageRequestParams params) async {
+        // Ensure the warning prompt is as expected.
+        expect(params.type, equals(MessageType.Warning));
+        expect(params.message, equals(expectedMessage));
+        expect(params.actions, hasLength(2));
+        expect(params.actions[0],
+            equals(MessageActionItem(title: UserPromptActions.renameAnyway)));
+        expect(params.actions[1],
+            equals(MessageActionItem(title: UserPromptActions.cancel)));
+
+        // Allow the test to run some code before we send the response.
+        await beforeResponding?.call();
+
+        // Respond to the request with the required action.
+        return MessageActionItem(title: action);
+      },
+    );
+  }
+
   Future<void> _test_rename_withDocumentChanges(
     String content,
     String newName,
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index d49ac6d..6ea2474 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -107,6 +108,10 @@
 
   /// Compute analysis results for all units of the library.
   Map<FileState, UnitAnalysisResult> analyzeSync() {
+    // Analyzer understands null safety, so it should set
+    // NullSafetyUnderstandingFlag.
+    assert(NullSafetyUnderstandingFlag.isEnabled);
+
     timerLibraryAnalyzer.start();
     Map<FileState, CompilationUnit> units = {};
 
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index df41c5e..3098758 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -7,7 +7,6 @@
 
 import 'package:analyzer/dart/analysis/context_locator.dart' as api;
 import 'package:analyzer/dart/analysis/declared_variables.dart';
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -179,7 +178,6 @@
 
   PackageBundleAssembler assembler;
 
-  final Map<String, ParsedUnitResult> inputParsedUnitResults = {};
   summary2.LinkedElementFactory elementFactory;
 
   // May be null.
@@ -249,13 +247,6 @@
       assembler = PackageBundleAssembler();
       if (_shouldOutputSummary) {
         await logger.runAsync('Build and write output summary', () async {
-          // Prepare all unlinked units.
-          await logger.runAsync('Prepare unlinked units', () async {
-            for (var src in explicitSources) {
-              await _prepareUnit('${src.uri}');
-            }
-          });
-
           // Build and assemble linked libraries.
           _computeLinkedLibraries2();
 
@@ -298,8 +289,8 @@
     });
   }
 
-  /// Use [elementFactory] filled with input summaries, and link prepared
-  /// [inputParsedUnitResults] to produce linked libraries in [assembler].
+  /// Use [elementFactory] filled with input summaries, and link libraries
+  /// in [explicitSources] to produce linked libraries in [assembler].
   void _computeLinkedLibraries2() {
     logger.run('Link output summary2', () {
       var inputLibraries = <summary2.LinkInputLibrary>[];
@@ -307,7 +298,7 @@
       for (var librarySource in explicitSources) {
         var path = librarySource.fullName;
 
-        var parseResult = inputParsedUnitResults[path];
+        var parseResult = analysisDriver.parseFileSync(path);
         if (parseResult == null) {
           throw ArgumentError('No parsed unit for $path');
         }
@@ -338,7 +329,7 @@
             }
 
             var partPath = partSource.fullName;
-            var partParseResult = inputParsedUnitResults[partPath];
+            var partParseResult = analysisDriver.parseFileSync(partPath);
             if (partParseResult == null) {
               throw ArgumentError('No parsed unit for part $partPath in $path');
             }
@@ -500,22 +491,6 @@
     return Packages.empty;
   }
 
-  /// Ensure that the parsed unit for [absoluteUri] is available.
-  ///
-  /// If the unit is in the input [summaryDataStore], do nothing.
-  Future<void> _prepareUnit(String absoluteUri) async {
-    // Parse the source and serialize its AST.
-    var uri = Uri.parse(absoluteUri);
-    var source = sourceFactory.forUri2(uri);
-    if (!source.exists()) {
-      // TODO(paulberry): we should report a warning/error because DDC
-      // compilations are unlikely to work.
-      return;
-    }
-    var result = await analysisDriver.parseFile(source.fullName);
-    inputParsedUnitResults[result.path] = result;
-  }
-
   /// Print errors for all explicit sources. If [outputPath] is supplied, output
   /// is sent to a new file at that path.
   Future<void> _printErrors({String outputPath}) async {
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index 1a68222b..2e6790d 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/sdk.dart';
@@ -223,9 +224,19 @@
   static const String cmdName = 'migrate';
 
   static const String cmdDescription =
-      'Perform a null safety migration on a project or package.'
-      '\n\nThe migration tool is in preview; see '
-      'https://dart.dev/go/null-safety-migration for a migration guide.';
+      'Perform a null safety migration on a project or package.';
+
+  static const String migrationGuideLink =
+      'See https://dart.dev/go/null-safety-migration for a migration guide.';
+
+  static const String preFlagFlipCaveat =
+      'Note: this tool is currently running on an SDK version where null '
+      'safety is not yet enabled by default. You may encounter issues in the '
+      'migration process - some aspects of the toolchain assume that they are '
+      'running on an SDK where null safety has been enabled by default.';
+
+  /// Return whether the SDK has null safety on by default.
+  static bool get nullSafetyOnByDefault => IsEnabledByDefault.non_nullable;
 
   final bool verbose;
 
@@ -247,7 +258,9 @@
   }
 
   @override
-  String get description => cmdDescription;
+  String get description => nullSafetyOnByDefault
+      ? '$cmdDescription\n\n$migrationGuideLink'
+      : '$cmdDescription\n\n$preFlagFlipCaveat\n\n$migrationGuideLink';
 
   @override
   String get invocation {
@@ -726,10 +739,17 @@
     logger.stdout('Migrating ${options.directory}');
     logger.stdout('');
 
+    if (!MigrateCommand.nullSafetyOnByDefault) {
+      logger.stdout(MigrateCommand.preFlagFlipCaveat);
+      logger.stdout('');
+    }
+
+    logger.stdout(MigrateCommand.migrationGuideLink);
+    logger.stdout('');
+
     if (hasMultipleAnalysisContext) {
-      logger
-          .stdout('Note: more than one project found; migrating the top-level '
-              'project.');
+      logger.stdout('Note: more than one project found; migrating the '
+          'top-level project.');
       logger.stdout('');
     }
 
diff --git a/tests/standalone/standalone_kernel.status b/tests/standalone/standalone_kernel.status
index bc9439c..1da02b7 100644
--- a/tests/standalone/standalone_kernel.status
+++ b/tests/standalone/standalone_kernel.status
@@ -108,5 +108,5 @@
 map_insert_remove_oom_test: Skip # Heap limit too low.
 no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
 
-[ $compiler != dartk && $compiler != dartkp || $compiler == dartkp && $system == windows ]
-entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
+[ $builder_tag == crossword || $compiler != dartk && $compiler != dartkp || $compiler == dartkp && $system == windows ]
+entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe. Cannot run in cross-word environment as native extension is not built.
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index cf0367e..939b834 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -109,5 +109,5 @@
 map_insert_remove_oom_test: Skip # Heap limit too low.
 no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
 
-[ $compiler != dartk && $compiler != dartkp || $compiler == dartkp && $system == windows ]
-entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
+[ $builder_tag == crossword || $compiler != dartk && $compiler != dartkp || $compiler == dartkp && $system == windows ]
+entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe. Cannot run in cross-word environment as native extension is not built.
diff --git a/tools/VERSION b/tools/VERSION
index ba84698..dade2bf 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 11
 PATCH 0
-PRERELEASE 221
+PRERELEASE 222
 PRERELEASE_PATCH 0
\ No newline at end of file