ConvertToExpressionFunctionBody: no fix if comments are present

Bug: https://github.com/dart-lang/sdk/issues/29313
Change-Id: I1548ee3db0b8a00ba42c419c0748daeaab118d61
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/239360
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_expression_function_body.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_expression_function_body.dart
index c66c747..31d1539 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_expression_function_body.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_expression_function_body.dart
@@ -34,6 +34,13 @@
     if (body is! BlockFunctionBody || body.isGenerator) {
       return;
     }
+    if (body.keyword?.precedingComments != null ||
+        body.block.leftBracket.precedingComments != null ||
+        body.block.rightBracket.precedingComments != null) {
+      // TODO(https://github.com/dart-lang/sdk/issues/29313): Include comments
+      // in fixed output.
+      return;
+    }
     var parent = body.parent;
     if (parent is ConstructorDeclaration && parent.factoryKeyword == null) {
       return;
@@ -48,8 +55,31 @@
     Expression? returnExpression;
     if (onlyStatement is ReturnStatement) {
       returnExpression = onlyStatement.expression;
+      if (onlyStatement.returnKeyword.precedingComments != null) {
+        // TODO(https://github.com/dart-lang/sdk/issues/29313): Include comments
+        // in fixed output.
+        return;
+      }
+      // TODO(https://github.com/dart-lang/sdk/issues/29313): If there are
+      // comments after `return` keyword, before the expression, either return
+      // without offering a fix, or include the comments in the fixed output.
+
+      if (onlyStatement.semicolon.precedingComments != null) {
+        // TODO(https://github.com/dart-lang/sdk/issues/29313): Include
+        // comments in fixed output.
+        return;
+      }
     } else if (onlyStatement is ExpressionStatement) {
       returnExpression = onlyStatement.expression;
+      // TODO(https://github.com/dart-lang/sdk/issues/29313): If there are
+      // comments before the expression, either return without offering a fix,
+      // or include the comments in the fixed output.
+
+      if (onlyStatement.semicolon?.precedingComments != null) {
+        // TODO(https://github.com/dart-lang/sdk/issues/29313): Include comments
+        // in fixed output.
+        return;
+      }
     }
     if (returnExpression == null) {
       return;
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_expression_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_expression_body_test.dart
index fc5175e..10ba918 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_into_expression_body_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_expression_body_test.dart
@@ -73,6 +73,96 @@
 ''');
   }
 
+  Future<void> test_closure_hasBlockComment_afterReturnStatement() async {
+    await resolveTestCode('''
+setup(x) {}
+main() {
+  setup(() {
+    return 42;
+    // Comment.
+  });
+}
+''');
+    await assertNoAssistAt('return');
+  }
+
+  Future<void> test_closure_hasBlockComment_beforeReturnKeyword() async {
+    await resolveTestCode('''
+setup(x) {}
+main() {
+  setup(() {
+    // Comment.
+    return 42;
+  });
+}
+''');
+    await assertNoAssistAt('return');
+  }
+
+  Future<void> test_closure_hasBlockComment_multiple() async {
+    await resolveTestCode('''
+setup(x) {}
+main() {
+  setup(() {
+    // Comment.
+
+    // Comment 2.
+    return 42;
+  });
+}
+''');
+    await assertNoAssistAt('return');
+  }
+
+  Future<void> test_closure_hasInlineComment_beforeBodyKeyword() async {
+    await resolveTestCode('''
+setup(x) {}
+main() {
+  setup(() /* Comment. */ async {
+    return 42;
+  });
+}
+''');
+    await assertNoAssistAt('return');
+  }
+
+  Future<void> test_closure_hasInlineComment_beforeOpenBrace() async {
+    await resolveTestCode('''
+setup(x) {}
+main() {
+  setup(() /* Comment. */ {
+    return 42;
+  });
+}
+''');
+    await assertNoAssistAt('return');
+  }
+
+  Future<void> test_closure_hasInlineComment_beforeReturn() async {
+    await resolveTestCode('''
+setup(x) {}
+main() {
+  setup(() {
+    /* Comment. */
+    return 42;
+  });
+}
+''');
+    await assertNoAssistAt('return');
+  }
+
+  Future<void> test_closure_hasInlineComment_beforeReturnSemicolon() async {
+    await resolveTestCode('''
+setup(x) {}
+main() {
+  setup(() {
+    return  42 /* Comment. */;
+  });
+}
+''');
+    await assertNoAssistAt('return');
+  }
+
   Future<void> test_closure_voidExpression() async {
     await resolveTestCode('''
 setup(x) {}
@@ -156,12 +246,12 @@
   Future<void> test_method_onBlock() async {
     await resolveTestCode('''
 class A {
-  m() { // marker
+  m() {
     return 42;
   }
 }
 ''');
-    await assertHasAssistAt('{ // marker', '''
+    await assertHasAssistAt('m() {', '''
 class A {
   m() => 42;
 }