Version 2.14.0-299.0.dev

Merge commit '72d8a215e715b5373bcdddf5f6e384a031f602c6' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_remove_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_remove_widget.dart
index 9818245..596a3f5 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_remove_widget.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_remove_widget.dart
@@ -4,15 +4,30 @@
 
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
 
 class FlutterRemoveWidget extends CorrectionProducer {
   @override
   AssistKind get assistKind => DartAssistKind.FLUTTER_REMOVE_WIDGET;
 
+  /// todo(pq): find out why overlapping edits are not being applied (and enable)
+  @override
+  bool get canBeAppliedInBulk => false;
+
+  @override
+  bool get canBeAppliedToFile => false;
+
+  @override
+  FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_CONTAINER;
+
+  @override
+  FixKind? get multiFixKind => DartFixKind.REMOVE_UNNECESSARY_CONTAINER_MULTI;
+
   @override
   Future<void> compute(ChangeBuilder builder) async {
     var widgetCreation = flutter.identifyNewExpression(node);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_container_with_sized_box.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_container_with_sized_box.dart
new file mode 100644
index 0000000..08c9126
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_container_with_sized_box.dart
@@ -0,0 +1,39 @@
+// 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/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ReplaceContainerWithSizedBox extends CorrectionProducer {
+  @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
+  FixKind get fixKind => DartFixKind.REPLACE_CONTAINER_WITH_SIZED_BOX;
+
+  @override
+  FixKind? get multiFixKind =>
+      DartFixKind.REPLACE_CONTAINER_WITH_SIZED_BOX_MULTI;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    final diagnostic = this.diagnostic;
+    if (diagnostic is AnalysisError) {
+      await builder.addDartFileEdit(file, (builder) {
+        builder.addSimpleReplacement(range.error(diagnostic), 'SizedBox');
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static ReplaceContainerWithSizedBox newInstance() =>
+      ReplaceContainerWithSizedBox();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index c8c725d..1ab5812 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -606,6 +606,14 @@
       'dart.fix.remove.unnecessaryNew.multi',
       DartFixKindPriority.IN_FILE,
       'Remove unnecessary new keywords everywhere in file');
+  static const REMOVE_UNNECESSARY_CONTAINER = FixKind(
+      'dart.fix.remove.unnecessaryContainer',
+      DartFixKindPriority.DEFAULT,
+      "Remove unnecessary 'Container'");
+  static const REMOVE_UNNECESSARY_CONTAINER_MULTI = FixKind(
+      'dart.fix.remove.unnecessaryContainer.multi',
+      DartFixKindPriority.IN_FILE,
+      "Remove unnecessary 'Container's in file");
   static const REMOVE_UNNECESSARY_PARENTHESES = FixKind(
       'dart.fix.remove.unnecessaryParentheses',
       DartFixKindPriority.DEFAULT,
@@ -734,6 +742,14 @@
       'dart.fix.replace.returnTypeFuture',
       DartFixKindPriority.DEFAULT,
       "Return 'Future' from 'async' function");
+  static const REPLACE_CONTAINER_WITH_SIZED_BOX = FixKind(
+      'dart.fix.replace.containerWithSizedBox',
+      DartFixKindPriority.DEFAULT,
+      "Replace with 'SizedBox'");
+  static const REPLACE_CONTAINER_WITH_SIZED_BOX_MULTI = FixKind(
+      'dart.fix.replace.containerWithSizedBox.multi',
+      DartFixKindPriority.DEFAULT,
+      "Replace with 'SizedBox' everywhere in file");
   static const REPLACE_VAR_WITH_DYNAMIC = FixKind(
       'dart.fix.replace.varWithDynamic',
       DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index f35e02b..c04be05 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -77,6 +77,7 @@
 import 'package:analysis_server/src/services/correction/dart/create_setter.dart';
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/dart/extend_class_for_mixin.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_remove_widget.dart';
 import 'package:analysis_server/src/services/correction/dart/ignore_diagnostic.dart';
 import 'package:analysis_server/src/services/correction/dart/import_library.dart';
 import 'package:analysis_server/src/services/correction/dart/inline_invocation.dart';
@@ -134,6 +135,7 @@
 import 'package:analysis_server/src/services/correction/dart/replace_boolean_with_bool.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_cascade_with_dot.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_colon_with_equals.dart';
+import 'package:analysis_server/src/services/correction/dart/replace_container_with_sized_box.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_final_with_const.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_final_with_var.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_new_with_const.dart';
@@ -378,6 +380,9 @@
       // TODO(brianwilkerson) Consider applying in bulk.
       RemoveUnusedParameter.newInstance,
     ],
+    LintNames.avoid_unnecessary_containers: [
+      FlutterRemoveWidget.newInstance,
+    ],
     LintNames.await_only_futures: [
       RemoveAwait.newInstance,
     ],
@@ -520,6 +525,9 @@
     LintNames.prefer_void_to_null: [
       ReplaceNullWithVoid.newInstance,
     ],
+    LintNames.sized_box_for_whitespace: [
+      ReplaceContainerWithSizedBox.newInstance,
+    ],
     LintNames.slash_for_doc_comments: [
       ConvertDocumentationIntoLine.newInstance,
     ],
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 87d349c..2d61eacc 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -36,6 +36,8 @@
   static const String avoid_unused_constructor_parameters =
       'avoid_unused_constructor_parameters';
   static const String await_only_futures = 'await_only_futures';
+  static const String avoid_unnecessary_containers =
+      'avoid_unnecessary_containers';
   static const String curly_braces_in_flow_control_structures =
       'curly_braces_in_flow_control_structures';
   static const String diagnostic_describe_all_properties =
@@ -96,6 +98,7 @@
   static const String prefer_typing_uninitialized_variables =
       'prefer_typing_uninitialized_variables';
   static const String prefer_void_to_null = 'prefer_void_to_null';
+  static const String sized_box_for_whitespace = 'sized_box_for_whitespace';
   static const String slash_for_doc_comments = 'slash_for_doc_comments';
   static const String sort_child_properties_last = 'sort_child_properties_last';
   static const String sort_constructors_first = 'sort_constructors_first';
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart
index f6ed88f..b4571e7 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart
@@ -3,14 +3,20 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../fix/fix_processor.dart';
 import 'assist_processor.dart';
 
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(FlutterRemoveWidgetTest);
+    defineReflectiveTests(RemoveContainerTest);
+    defineReflectiveTests(RemoveContainerBulkTest);
   });
 }
 
@@ -235,3 +241,101 @@
 ''');
   }
 }
+
+@reflectiveTest
+class RemoveContainerBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.avoid_unnecessary_containers;
+
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfig(
+      flutter: true,
+    );
+  }
+
+  @FailingTest(reason: 'nested row container not being removed')
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return Container(
+      child: Row(
+        children: [
+          Text('...'),
+          Container(
+            child: Row(
+              children: [
+                 Text('...'),
+              ],
+            ),
+          )  
+        ],
+      )
+  );
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return Row(
+    children: [
+      Text('...'),
+      Row(
+        children: [
+          Text('...'),
+        ],
+      )
+    ],
+  );
+}
+''');
+  }
+}
+
+@reflectiveTest
+class RemoveContainerTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_CONTAINER;
+
+  @override
+  String get lintCode => LintNames.avoid_unnecessary_containers;
+
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfig(
+      flutter: true,
+    );
+  }
+
+  Future<void> test_simple() async {
+    await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return Container(
+      child: Row(
+        children: [
+          Text('...'),
+        ],
+      )
+  );
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return Row(
+    children: [
+      Text('...'),
+    ],
+  );
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_container_with_sized_box_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_container_with_sized_box_test.dart
new file mode 100644
index 0000000..009c386
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_container_with_sized_box_test.dart
@@ -0,0 +1,102 @@
+// 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/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceContainedWithSizedBoxTest);
+    defineReflectiveTests(ReplaceContainedWithSizedBoxMultiTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceContainedWithSizedBoxMultiTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.sized_box_for_whitespace;
+
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfig(
+      flutter: true,
+    );
+  }
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return Container(
+    width: 10,
+    child: 
+      Container(
+        width: 10,
+        child: Row(),
+      ),
+  );
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return SizedBox(
+    width: 10,
+    child: 
+      SizedBox(
+        width: 10,
+        child: Row(),
+      ),
+  );
+}
+''');
+  }
+}
+
+@reflectiveTest
+class ReplaceContainedWithSizedBoxTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REPLACE_CONTAINER_WITH_SIZED_BOX;
+
+  @override
+  String get lintCode => LintNames.sized_box_for_whitespace;
+
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfig(
+      flutter: true,
+    );
+  }
+
+  Future<void> test_simple() async {
+    await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return Container(
+    width: 10,
+    child: Row(),
+  );
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+
+Widget buildRow() {
+  return SizedBox(
+    width: 10,
+    child: Row(),
+  );
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index fec18cc..6178199 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -160,6 +160,8 @@
 import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool;
 import 'replace_cascade_with_dot_test.dart' as replace_cascade_with_dot;
 import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
+import 'replace_container_with_sized_box_test.dart'
+    as replace_container_with_sized_box;
 import 'replace_final_with_const_test.dart' as replace_final_with_const;
 import 'replace_final_with_var_test.dart' as replace_final_with_var;
 import 'replace_new_with_const_test.dart' as replace_new_with_const;
@@ -331,6 +333,7 @@
     replace_boolean_with_bool.main();
     replace_cascade_with_dot.main();
     replace_colon_with_equals.main();
+    replace_container_with_sized_box.main();
     replace_final_with_const.main();
     replace_final_with_var.main();
     replace_new_with_const.main();
diff --git a/tests/language/generic/super_bounded_types_error_test.dart b/tests/language/generic/super_bounded_types_error_test.dart
index 63434cd..5f523bc 100644
--- a/tests/language/generic/super_bounded_types_error_test.dart
+++ b/tests/language/generic/super_bounded_types_error_test.dart
@@ -3135,20 +3135,10 @@
 // [analyzer] unspecified
 //                         ^
 // [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
-    var fsource = toF(source);
-//  ^
-// [analyzer] unspecified
-//      ^
-// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
-//                ^
-// [analyzer] unspecified
-// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
-    F<AinvCyclicCoBound<FinvCyclicCoBound<Function(Never)>, Function(Never)>>
-//  ^
-// [analyzer] unspecified
-        target = fsource;
-//      ^
-// [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(Y)' of the type variable 'Y' on 'AinvCyclicCoBound'.
+
+    // We do not use `source` in further tests, because the type of `source`
+    // is an error, and we do not generally test error-on-error situations.
   }
 }
 
@@ -3156,32 +3146,13 @@
   void f(B<AinvCyclicCoBound> source) {
 //       ^
 // [analyzer] unspecified
-//         ^
-// [analyzer] unspecified
 //                            ^
 // [cfe] Type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
-//                            ^
 // [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
-    var fsource = toF(source);
-//  ^
-// [analyzer] unspecified
-//      ^
-// [cfe] Inferred type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
-//      ^
-// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
-//                ^
-// [analyzer] unspecified
-// [cfe] Inferred type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
-//                ^
-// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
-    F<B<AinvCyclicCoBound<FinvCyclicCoBound<Function(Never)>, Function(Never)>>>
-//  ^
-// [analyzer] unspecified
-        target = fsource;
-//      ^
-// [cfe] Type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
-//      ^
-// [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(Y)' of the type variable 'Y' on 'AinvCyclicCoBound'.
+
+    // We do not use `source` in further tests, because the type of `source`
+    // is an error, and we do not generally test error-on-error situations.
   }
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index ca8974c..3dfa234 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 298
+PRERELEASE 299
 PRERELEASE_PATCH 0
\ No newline at end of file