Make extracted widgets follow Flutter style - const constructor and @required named parameters.

R=brianwilkerson@google.com, pquitslund@google.com

Bug: https://github.com/flutter/flutter-intellij/issues/2166
Change-Id: I28f548c8e814ac5b9585dd46fbb9a8f84f70f418
Reviewed-on: https://dart-review.googlesource.com/54066
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index 9d52193..d304a1c 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -41,6 +41,7 @@
   ClassElement classStatefulWidget;
   ClassElement classStatelessWidget;
   ClassElement classWidget;
+  PropertyAccessorElement accessorRequired;
 
   @override
   String name;
@@ -200,12 +201,22 @@
       return element;
     }
 
+    Future<PropertyAccessorElement> getAccessor(String uri, String name) async {
+      var element = await sessionHelper.getTopLevelPropertyAccessor(uri, name);
+      if (element == null) {
+        result.addFatalError("Unable to find 'required' in $uri");
+      }
+      return element;
+    }
+
     classBuildContext = await getClass('BuildContext');
     classKey = await getClass('Key');
     classStatelessWidget = await getClass('StatelessWidget');
     classStatefulWidget = await getClass('StatefulWidget');
     classWidget = await getClass('Widget');
 
+    accessorRequired = await getAccessor('package:meta/meta.dart', 'required');
+
     return result;
   }
 
@@ -309,6 +320,38 @@
         name,
         superclass: classStatelessWidget.type,
         membersWriter: () {
+          // Add the constructor.
+          builder.write('  ');
+          builder.writeConstructorDeclaration(
+            name,
+            isConst: true,
+            parameterWriter: () {
+              builder.writeln('{');
+
+              // Add the required `key` parameter.
+              builder.write('    ');
+              builder.writeParameter('key', type: classKey.type);
+              builder.writeln(',');
+
+              // Add parameters for fields, local, and method parameters.
+              for (int i = 0; i < _parameters.length; i++) {
+                builder.write('    ');
+                builder.write('@');
+                builder.writeReference(accessorRequired);
+                builder.write(' this.');
+                builder.write(_parameters[i].name);
+                builder.writeln(',');
+              }
+
+              builder.write('  }');
+            },
+            initializerWriter: () {
+              builder.write('super(key: key)');
+            },
+          );
+          builder.writeln();
+          builder.writeln();
+
           // Add the fields for the parameters.
           if (_parameters.isNotEmpty) {
             for (var parameter in _parameters) {
@@ -320,32 +363,6 @@
             builder.writeln();
           }
 
-          // Add the constructor.
-          builder.write('  ');
-          builder.writeConstructorDeclaration(
-            name,
-            parameterWriter: () {
-              builder.write('{');
-
-              // Add the required `key` parameter.
-              builder.writeParameter('key', type: classKey.type);
-
-              // Add parameters for fields, local, and method parameters.
-              for (int i = 0; i < _parameters.length; i++) {
-                builder.write(', ');
-                builder.write('this.');
-                builder.write(_parameters[i].name);
-              }
-
-              builder.write('}');
-            },
-            initializerWriter: () {
-              builder.write('super(key: key)');
-            },
-          );
-          builder.writeln();
-          builder.writeln();
-
           // Widget build(BuildContext context) { ... }
           builder.writeln('  @override');
           builder.write('  ');
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index eb77a4a..3ee2c09 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -61,6 +61,7 @@
   bool get previewDart2 => driver.analysisOptions.previewDart2;
 
   void addFlutterPackage() {
+    addMetaPackageSource();
     Folder libFolder = configureFlutterPackage(resourceProvider);
     packageMap['flutter'] = [libFolder];
   }
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index 72e36b6..0cc4f57 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -3880,7 +3880,7 @@
   main() {
   var obj;
 // start
-    return new Row(children: [/*caret*/ new Transform()]);
+    return new Row(children: [/*caret*/ new Container()]);
 // end
   }
 }
@@ -3898,9 +3898,9 @@
     child: new Row(
 // start
       children: [/*caret*/
-        new Transform(),
-        new Transform(),
-        new AspectRatio(),
+        new Text('111'),
+        new Text('222'),
+        new Container(),
       ],
 // end
     ),
@@ -3917,9 +3917,9 @@
       children: [
         new widget(
           children: [/*caret*/
-            new Transform(),
-            new Transform(),
-            new AspectRatio(),
+            new Text('111'),
+            new Text('222'),
+            new Container(),
           ],
         ),
       ],
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 0e949bf..c607d0e 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -5893,9 +5893,8 @@
   return new Container(
     child: new Row(
       child: <Widget>[
-        new Transform(),
+        new Container(),
         null,
-        new AspectRatio(),
       ],
     ),
   );
@@ -5912,9 +5911,8 @@
   return new Container(
     child: new Row(
       child: [
-        new Transform(),
-        new ClipRect.rect(),
-        new AspectRatio(),
+        new Text('111'),
+        new Text('222'),
       ],
     ),
   );
@@ -5926,9 +5924,8 @@
   return new Container(
     child: new Row(
       children: <Widget>[
-        new Transform(),
-        new ClipRect.rect(),
-        new AspectRatio(),
+        new Text('111'),
+        new Text('222'),
       ],
     ),
   );
@@ -5944,9 +5941,8 @@
   return new Container(
     child: new Row(
       child: <Widget>[
-        new Transform(),
-        new ClipRect.rect(),
-        new AspectRatio(),
+        new Text('111'),
+        new Text('222'),
       ],
     ),
   );
@@ -5958,9 +5954,8 @@
   return new Container(
     child: new Row(
       children: <Widget>[
-        new Transform(),
-        new ClipRect.rect(),
-        new AspectRatio(),
+        new Text('111'),
+        new Text('222'),
       ],
     ),
   );
diff --git a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
index 4e8323b..d007bc6 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
@@ -130,7 +130,9 @@
 }
 
 class Test extends StatelessWidget {
-  Test({Key key}) : super(key: key);
+  const Test({
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -180,7 +182,9 @@
 }
 
 class Test extends StatelessWidget {
-  Test({Key key}) : super(key: key);
+  const Test({
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -215,7 +219,9 @@
 }
 
 class Test extends StatelessWidget {
-  Test({Key key}) : super(key: key);
+  const Test({
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -254,7 +260,9 @@
 }
 
 class Test extends StatelessWidget {
-  Test({Key key}) : super(key: key);
+  const Test({
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -358,9 +366,12 @@
 }
 
 class Test extends StatelessWidget {
-  final C c;
+  const Test({
+    Key key,
+    @required this.c,
+  }) : super(key: key);
 
-  Test({Key key, this.c}) : super(key: key);
+  final C c;
 
   @override
   Widget build(BuildContext context) {
@@ -408,7 +419,9 @@
 }
 
 class Test extends StatelessWidget {
-  Test({Key key}) : super(key: key);
+  const Test({
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -471,12 +484,17 @@
 }
 
 class Test extends StatelessWidget {
+  const Test({
+    Key key,
+    @required this.foo,
+    @required this.p1,
+    @required this.p2,
+  }) : super(key: key);
+
   final String foo;
   final String p1;
   final int p2;
 
-  Test({Key key, this.foo, this.p1, this.p2}) : super(key: key);
-
   @override
   Widget build(BuildContext context) {
     var a = new Text('$foo $p1');
@@ -538,12 +556,17 @@
 }
 
 class Test extends StatelessWidget {
+  const Test({
+    Key key,
+    @required this.foo,
+    @required this.p1,
+    @required this.p2,
+  }) : super(key: key);
+
   final String foo;
   final String p1;
   final int p2;
 
-  Test({Key key, this.foo, this.p1, this.p2}) : super(key: key);
-
   @override
   Widget build(BuildContext context) {
     var a = new Text('$foo $p1');
@@ -585,9 +608,12 @@
 }
 
 class Test extends StatelessWidget {
-  final String field;
+  const Test({
+    Key key,
+    @required this.field,
+  }) : super(key: key);
 
-  Test({Key key, this.field}) : super(key: key);
+  final String field;
 
   @override
   Widget build(BuildContext context) {
@@ -634,9 +660,12 @@
 }
 
 class Test extends StatelessWidget {
-  final C c;
+  const Test({
+    Key key,
+    @required this.c,
+  }) : super(key: key);
 
-  Test({Key key, this.c}) : super(key: key);
+  final C c;
 
   @override
   Widget build(BuildContext context) {
@@ -675,7 +704,9 @@
 }
 
 class Test extends StatelessWidget {
-  Test({Key key}) : super(key: key);
+  const Test({
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -779,9 +810,12 @@
 }
 
 class Test extends StatelessWidget {
-  final C c;
+  const Test({
+    Key key,
+    @required this.c,
+  }) : super(key: key);
 
-  Test({Key key, this.c}) : super(key: key);
+  final C c;
 
   @override
   Widget build(BuildContext context) {
@@ -842,9 +876,12 @@
 }
 
 class Test extends StatelessWidget {
-  final String local;
+  const Test({
+    Key key,
+    @required this.local,
+  }) : super(key: key);
 
-  Test({Key key, this.local}) : super(key: key);
+  final String local;
 
   @override
   Widget build(BuildContext context) {
@@ -914,11 +951,15 @@
 }
 
 class Test extends StatelessWidget {
+  const Test({
+    Key key,
+    @required this.field,
+    @required this.local,
+  }) : super(key: key);
+
   final String field;
   final String local;
 
-  Test({Key key, this.field, this.local}) : super(key: key);
-
   @override
   Widget build(BuildContext context) {
     return new Column(
diff --git a/pkg/analysis_server/test/src/utilities/flutter_util.dart b/pkg/analysis_server/test/src/utilities/flutter_util.dart
index b7bdb1b..83b5b82 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_util.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_util.dart
@@ -35,6 +35,13 @@
 export 'src/widgets/text.dart';
 ''');
 
+  newFile('$flutterPkgLibPath/foundation.dart', r'''
+export 'package:meta/meta.dart' show
+  required;
+
+export 'src/foundation/key.dart';
+''');
+
   void createSrcMaterial() {
     newFile('$flutterPkgLibPath/src/material/app_bar.dart', r'''
 import 'package:flutter/widgets.dart';
@@ -129,6 +136,28 @@
 ''');
   }
 
+  void createSrcFoundation() {
+    newFile('$flutterPkgLibPath/src/foundation/key.dart', r'''
+
+abstract class Key {
+  const factory Key(String value) = ValueKey<String>;
+
+  const Key._();
+}
+
+abstract class LocalKey extends Key {
+  const LocalKey() : super._();
+}
+
+
+class ValueKey<T> extends LocalKey {
+  final T value;
+
+  const ValueKey(this.value);
+}
+''');
+  }
+
   void createSrcWidgets() {
     newFile('$flutterPkgLibPath/src/widgets/basic.dart', r'''
 import 'framework.dart';
@@ -186,7 +215,7 @@
 class AspectRatio extends SingleChildRenderObjectWidget {
   const AspectRatio({
     Key key,
-    @required aspectRatio,
+    @required double aspectRatio,
     Widget child,
   });
 }
@@ -221,22 +250,17 @@
 ''');
 
     newFile('$flutterPkgLibPath/src/widgets/framework.dart', r'''
+import 'package:flutter/foundation.dart';
+
+export 'package:flutter/foundation.dart' show required;
+export 'package:flutter/foundation.dart' show Key, LocalKey, ValueKey;
+
 typedef void VoidCallback();
 
 abstract class BuildContext {
   Widget get widget;
 }
 
-abstract class Key {
-  const factory Key(String value) = ValueKey<String>;
-
-  const Key._();
-}
-
-abstract class LocalKey extends Key {
-  const LocalKey() : super._();
-}
-
 abstract class State<T extends StatefulWidget> {
   BuildContext get context => null;
 
@@ -261,12 +285,6 @@
   Widget build(BuildContext context) => null;
 }
 
-class ValueKey<T> extends LocalKey {
-  final T value;
-
-  const ValueKey(this.value);
-}
-
 class Widget {
   final Key key;
 
@@ -324,6 +342,7 @@
 ''');
   }
 
+  createSrcFoundation();
   createPainting();
   createRendering();
   createSrcWidgets();