`FLUTTER_CONVERT_TO_STATEFUL_WIDGET` to handle comments

Fixes #46254

Change-Id: Iefb1b422434529ef7ed672beedca95bb42f4fd18
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/212580
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
index 6c9e4d0..34ecd3a 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
@@ -92,8 +92,7 @@
             }
           }
         }
-      }
-      if (member is MethodDeclaration && !member.isStatic) {
+      } else if (member is MethodDeclaration && !member.isStatic) {
         nodesToMove.add(member);
         elementsToMove.add(member.declaredElement!);
       }
@@ -177,8 +176,9 @@
       for (var node in widgetClass.members) {
         if (nodesToMove.contains(node)) {
           if (replaceOffset == 0) {
-            var linesRange = utils.getLinesRange(range.node(node));
-            replaceOffset = linesRange.offset;
+            var comments = node.beginToken.precedingComments;
+            var start = comments ?? node;
+            replaceOffset = utils.getLineContentStart(start.offset);
           }
           if (node == buildMethod) {
             hasBuildMethod = true;
@@ -236,6 +236,14 @@
           if (writeEmptyLine) {
             builder.writeln();
           }
+
+          var comments = member.beginToken.precedingComments;
+          if (comments != null) {
+            var offset = utils.getLineContentStart(comments.offset);
+            var length = comments.end - offset;
+            builder.writeln(utils.getText(offset, length));
+          }
+
           var text = rewriteWidgetMemberReferences(member);
           builder.write(text);
           // Write empty lines between members, but not before the first.
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
index 02ce651..dfb00eb 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
@@ -27,6 +27,96 @@
     );
   }
 
+  Future<void> test_comment() async {
+    await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatelessWidget {
+  // something for a
+  final bool a = false;
+
+  const MyWidget();
+
+  // another for b
+  final bool b = true;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container();
+  }
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatefulWidget {
+
+  const MyWidget();
+
+  @override
+  State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+  // something for a
+  final bool a = false;
+
+  // another for b
+  final bool b = true;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container();
+  }
+}
+''');
+  }
+
+  Future<void> test_comment_documentation() async {
+    await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatelessWidget {
+  /// something for a
+  final bool a = false;
+
+  const MyWidget();
+
+  /// another for b
+  final bool b = true;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container();
+  }
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatefulWidget {
+
+  const MyWidget();
+
+  @override
+  State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+  /// something for a
+  final bool a = false;
+
+  /// another for b
+  final bool b = true;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container();
+  }
+}
+''');
+  }
+
   Future<void> test_empty() async {
     await resolveTestCode(r'''
 import 'package:flutter/material.dart';