(conditionally) add trailing commas for wrapping streambuilders

Related to: https://github.com/dart-lang/sdk/issues/49541

Change-Id: Iba6ce96c12838ad23c035aca64dda233803fac32
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252866
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index 621744c..96a232c 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -9,6 +9,7 @@
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/dart/analysis/code_style_options.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -31,6 +32,10 @@
 
 /// An object that can compute a correction (fix or assist) in a Dart file.
 abstract class CorrectionProducer extends SingleCorrectionProducer {
+  /// Return the code style options for the current context.
+  CodeStyleOptions get codeStyleOptions =>
+      sessionHelper.session.analysisContext.analysisOptions.codeStyleOptions;
+
   /// Return the type for the class `bool` from `dart:core`.
   DartType get coreTypeBool => resolvedResult.typeProvider.boolType;
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_builder.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_builder.dart
index 838bc7b..db45429 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_builder.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_builder.dart
@@ -32,10 +32,6 @@
       return;
     }
 
-    var context = sessionHelper.session.analysisContext;
-    var addTrailingComma =
-        context.analysisOptions.codeStyleOptions.addTrailingCommas;
-
     await builder.addDartFileEdit(file, (builder) {
       builder.addReplacement(range.node(widgetExpr), (builder) {
         builder.writeReference(builderElement);
@@ -58,7 +54,7 @@
         builder.writeln(';');
 
         builder.write(indentNew1);
-        builder.writeln('}${addTrailingComma ? "," : ""}');
+        builder.writeln('}${codeStyleOptions.addTrailingCommas ? "," : ""}');
 
         builder.write(indentOld);
         builder.write(')');
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_stream_builder.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_stream_builder.dart
index ccab9e7..435448e 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_stream_builder.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_stream_builder.dart
@@ -59,7 +59,7 @@
         builder.writeln(';');
 
         builder.write(indentNew1);
-        builder.writeln('}');
+        builder.writeln('}${codeStyleOptions.addTrailingCommas ? "," : ""}');
 
         builder.write(indentOld);
         builder.write(')');
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_stream_builder_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_stream_builder_test.dart
index 389b609..29df717 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_stream_builder_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_stream_builder_test.dart
@@ -3,6 +3,7 @@
 // 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/linter/lint_names.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -62,4 +63,66 @@
 }
 ''');
   }
+
+  Future<void> test_trailingComma_disabled() async {
+    // No analysis options.
+    await resolveTestCode('''
+import 'package:flutter/widgets.dart';
+
+class TestWidget extends StatelessWidget {
+  const TestWidget({super.key});
+  @override
+  Widget build(BuildContext context) {
+    return const /*caret*/Text('hi');
+  }
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/widgets.dart';
+
+class TestWidget extends StatelessWidget {
+  const TestWidget({super.key});
+  @override
+  Widget build(BuildContext context) {
+    return StreamBuilder<Object>(
+      stream: null,
+      builder: (context, snapshot) {
+        return const Text('hi');
+      }
+    );
+  }
+}
+''');
+  }
+
+  Future<void> test_trailingComma_enabled() async {
+    createAnalysisOptionsFile(lints: [LintNames.require_trailing_commas]);
+    await resolveTestCode('''
+import 'package:flutter/widgets.dart';
+
+class TestWidget extends StatelessWidget {
+  const TestWidget({super.key});
+  @override
+  Widget build(BuildContext context) {
+    return const /*caret*/Text('hi');
+  }
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/widgets.dart';
+
+class TestWidget extends StatelessWidget {
+  const TestWidget({super.key});
+  @override
+  Widget build(BuildContext context) {
+    return StreamBuilder<Object>(
+      stream: null,
+      builder: (context, snapshot) {
+        return const Text('hi');
+      },
+    );
+  }
+}
+''');
+  }
 }