From 2b8e05c9e6188ead362d7bbc9aa6da0766fdaef0 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 26 Feb 2026 21:55:31 -0800 Subject: [PATCH 1/3] [pigeon] Switch Indent class to manage all writes with a StringBuffer --- packages/pigeon/lib/src/ast_generator.dart | 3 +- .../pigeon/lib/src/dart/dart_generator.dart | 21 ++++++------- .../src/dart/proxy_api_generator_helper.dart | 30 +++++++++---------- packages/pigeon/lib/src/generator.dart | 4 ++- packages/pigeon/lib/src/generator_tools.dart | 28 ++++++++--------- .../pigeon/test/generator_tools_test.dart | 5 ++-- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/packages/pigeon/lib/src/ast_generator.dart b/packages/pigeon/lib/src/ast_generator.dart index 9081a094a086..877218337b97 100644 --- a/packages/pigeon/lib/src/ast_generator.dart +++ b/packages/pigeon/lib/src/ast_generator.dart @@ -7,7 +7,7 @@ import 'generator_tools.dart'; /// Writes the AST representation of [root] to [sink]. void generateAst(Root root, StringSink sink) { - final indent = Indent(sink); + final indent = Indent(); final output = root.toString(); var isFirst = true; for (final int ch in output.runes) { @@ -26,4 +26,5 @@ void generateAst(Root root, StringSink sink) { indent.add(chStr); } indent.addln(''); + sink.write(indent.toString()); } diff --git a/packages/pigeon/lib/src/dart/dart_generator.dart b/packages/pigeon/lib/src/dart/dart_generator.dart index a065f95e0af7..8fcd6e7df2c5 100644 --- a/packages/pigeon/lib/src/dart/dart_generator.dart +++ b/packages/pigeon/lib/src/dart/dart_generator.dart @@ -774,9 +774,9 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; ]) ..body = cb.Block.of( cb.Block((cb.BlockBuilder builder) { - final messageHandlerSink = StringBuffer(); + final messageHandlerIndent = Indent(); writeFlutterMethodMessageHandler( - Indent(messageHandlerSink), + messageHandlerIndent, name: 'removeStrongReferenceName', parameters: [ Parameter( @@ -805,7 +805,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; }, ); builder.statements.add( - cb.Code(messageHandlerSink.toString()), + cb.Code(messageHandlerIndent.toString()), ); }).statements, ); @@ -825,9 +825,9 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; ), ) ..body = cb.Block((cb.BlockBuilder builder) { - final messageCallSink = StringBuffer(); + final messageCallIndent = Indent(); writeHostMethodMessageCall( - Indent(messageCallSink), + messageCallIndent, addSuffixVariable: false, channelName: makeRemoveStrongReferenceChannelName( dartPackageName, @@ -844,7 +844,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; returnType: const TypeDeclaration.voidDeclaration(), ); builder.statements.addAll([ - cb.Code(messageCallSink.toString()), + cb.Code(messageCallIndent.toString()), ]); }); }), @@ -859,16 +859,16 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; '/// This is typically called after a hot restart.', ]) ..body = cb.Block((cb.BlockBuilder builder) { - final messageCallSink = StringBuffer(); + final messageCallIndent = Indent(); writeHostMethodMessageCall( - Indent(messageCallSink), + messageCallIndent, addSuffixVariable: false, channelName: makeClearChannelName(dartPackageName), parameters: [], returnType: const TypeDeclaration.voidDeclaration(), ); builder.statements.addAll([ - cb.Code(messageCallSink.toString()), + cb.Code(messageCallIndent.toString()), ]); }); }), @@ -1029,7 +1029,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; required String dartPackageName, required String dartOutputPackageName, }) { - final indent = Indent(sink); + final indent = Indent(); final String sourceOutPath = generatorOptions.dartOut ?? ''; final String testOutPath = generatorOptions.testOut ?? ''; _writeTestPrologue(generatorOptions, root, indent); @@ -1079,6 +1079,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; ); } } + sink.write(indent.toString()); } /// Writes file header to sink. diff --git a/packages/pigeon/lib/src/dart/proxy_api_generator_helper.dart b/packages/pigeon/lib/src/dart/proxy_api_generator_helper.dart index 6d86f52865db..9691b9b39b0b 100644 --- a/packages/pigeon/lib/src/dart/proxy_api_generator_helper.dart +++ b/packages/pigeon/lib/src/dart/proxy_api_generator_helper.dart @@ -461,9 +461,9 @@ Iterable constructors( const cb.Code('super.${classMemberNamePrefix}detached()'), ]) ..body = cb.Block((cb.BlockBuilder builder) { - final messageCallSink = StringBuffer(); + final messageCallIndent = Indent(); DartGenerator.writeHostMethodMessageCall( - Indent(messageCallSink), + messageCallIndent, addSuffixVariable: false, channelName: channelName, insideAsyncMethod: false, @@ -492,7 +492,7 @@ Iterable constructors( cb.Code( 'final BinaryMessenger? ${varNamePrefix}binaryMessenger = ${binaryMessengerParameter.name};', ), - cb.Code(messageCallSink.toString()), + cb.Code(messageCallIndent.toString()), ]); }); }); @@ -792,10 +792,10 @@ cb.Method setUpMessageHandlerMethod({ ], if (hasCallbackConstructor) ...cb.Block((cb.BlockBuilder builder) { - final messageHandlerSink = StringBuffer(); + final messageHandlerIndent = Indent(); const methodName = '${classMemberNamePrefix}newInstance'; DartGenerator.writeFlutterMethodMessageHandler( - Indent(messageHandlerSink), + messageHandlerIndent, name: methodName, parameters: [ Parameter( @@ -844,13 +844,13 @@ cb.Method setUpMessageHandlerMethod({ ')'; }, ); - builder.statements.add(cb.Code(messageHandlerSink.toString())); + builder.statements.add(cb.Code(messageHandlerIndent.toString())); }).statements, for (final Method method in flutterMethods) ...cb.Block((cb.BlockBuilder builder) { - final messageHandlerSink = StringBuffer(); + final messageHandlerIndent = Indent(); DartGenerator.writeFlutterMethodMessageHandler( - Indent(messageHandlerSink), + messageHandlerIndent, name: method.name, parameters: [ Parameter( @@ -885,7 +885,7 @@ cb.Method setUpMessageHandlerMethod({ return '($methodName ?? ${safeArgumentNames.first}.$methodName)$nullability.call(${safeArgumentNames.join(',')})'; }, ); - builder.statements.add(cb.Code(messageHandlerSink.toString())); + builder.statements.add(cb.Code(messageHandlerIndent.toString())); }).statements, ]), ); @@ -913,9 +913,9 @@ Iterable attachedFieldMethods( ..static = field.isStatic ..returns = cb.refer(type) ..body = cb.Block((cb.BlockBuilder builder) { - final messageCallSink = StringBuffer(); + final messageCallIndent = Indent(); DartGenerator.writeHostMethodMessageCall( - Indent(messageCallSink), + messageCallIndent, addSuffixVariable: false, channelName: makeChannelNameWithStrings( apiName: apiName, @@ -968,7 +968,7 @@ Iterable attachedFieldMethods( ), ], const cb.Code('() async {'), - cb.Code(messageCallSink.toString()), + cb.Code(messageCallIndent.toString()), const cb.Code('}();'), const cb.Code('return $instanceName;'), ]); @@ -1023,9 +1023,9 @@ Iterable hostMethods( ], ]) ..body = cb.Block((cb.BlockBuilder builder) { - final messageCallSink = StringBuffer(); + final messageCallIndent = Indent(); DartGenerator.writeHostMethodMessageCall( - Indent(messageCallSink), + messageCallIndent, addSuffixVariable: false, channelName: makeChannelNameWithStrings( apiName: apiName, @@ -1073,7 +1073,7 @@ Iterable hostMethods( const cb.Code( 'final BinaryMessenger? ${varNamePrefix}binaryMessenger = ${classMemberNamePrefix}binaryMessenger;', ), - cb.Code(messageCallSink.toString()), + cb.Code(messageCallIndent.toString()), ]); }), ); diff --git a/packages/pigeon/lib/src/generator.dart b/packages/pigeon/lib/src/generator.dart index 5495359d3e3c..e0c240b9b794 100644 --- a/packages/pigeon/lib/src/generator.dart +++ b/packages/pigeon/lib/src/generator.dart @@ -40,7 +40,7 @@ abstract class StructuredGenerator StringSink sink, { required String dartPackageName, }) { - final indent = Indent(sink); + final indent = Indent(); writeFilePrologue( generatorOptions, @@ -117,6 +117,8 @@ abstract class StructuredGenerator indent, dartPackageName: dartPackageName, ); + + sink.write(indent.toString()); } /// Adds specified headers to [indent]. diff --git a/packages/pigeon/lib/src/generator_tools.dart b/packages/pigeon/lib/src/generator_tools.dart index e639480246b1..bf5dddc5eac8 100644 --- a/packages/pigeon/lib/src/generator_tools.dart +++ b/packages/pigeon/lib/src/generator_tools.dart @@ -31,13 +31,13 @@ String readStdin() { /// True if the generator line number should be printed out at the end of newlines. bool debugGenerators = false; -/// A helper class for managing indentation, wrapping a [StringSink]. +/// A helper class for managing indentation, wrapping a [StringBuffer]. class Indent { - /// Constructor which takes a [StringSink] which this [Indent] will wrap. - Indent(this._sink); - int _count = 0; - final StringSink _sink; + final StringBuffer _buffer = StringBuffer(); + + @override + String toString() => _buffer.toString(); /// String used for newlines (ex "\n"). String get newline { @@ -119,13 +119,13 @@ class Indent { int nestCount = 1, }) { if (begin != null) { - _sink.write(begin + newline); + _buffer.write(begin + newline); } nest(nestCount, func); if (end != null && end.isNotEmpty) { - _sink.write(str() + end); + _buffer.write(str() + end); if (addTrailingNewline) { - _sink.write(newline); + _buffer.write(newline); } } } @@ -159,31 +159,31 @@ class Indent { /// Add [text] with indentation and a newline. void writeln(String text) { if (text.isEmpty) { - _sink.write(newline); + _buffer.write(newline); } else { - _sink.write(str() + text + newline); + _buffer.write(str() + text + newline); } } /// Add [text] with indentation. void write(String text) { - _sink.write(str() + text); + _buffer.write(str() + text); } /// Add [text] with a newline. void addln(String text) { - _sink.write(text + newline); + _buffer.write(text + newline); } /// Just adds [text]. void add(String text) { - _sink.write(text); + _buffer.write(text); } /// Adds [lines] number of newlines. void newln([int lines = 1]) { for (; lines > 0; lines--) { - _sink.write(newline); + _buffer.write(newline); } } } diff --git a/packages/pigeon/test/generator_tools_test.dart b/packages/pigeon/test/generator_tools_test.dart index 67e5f68fb1d8..183865f1e3f3 100644 --- a/packages/pigeon/test/generator_tools_test.dart +++ b/packages/pigeon/test/generator_tools_test.dart @@ -500,8 +500,7 @@ void main() { }); test('Indent.format trims indentation', () { - final buffer = StringBuffer(); - final indent = Indent(buffer); + final indent = Indent(); indent.format(''' void myMethod() { @@ -509,7 +508,7 @@ void main() { print('hello'); }'''); - expect(buffer.toString(), ''' + expect(indent.toString(), ''' void myMethod() { print('hello'); From 482f73f7843b63ce6a9d3194732fd5986e09a7ec Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Sun, 1 Mar 2026 09:59:27 -0800 Subject: [PATCH 2/3] CHANGELOG --- packages/pigeon/CHANGELOG.md | 6 ++++++ packages/pigeon/lib/src/generator_tools.dart | 2 +- packages/pigeon/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index 83727e1ecef0..b80a8e4ced9f 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,3 +1,9 @@ +## 26.1.10 + +* Dramatically reduce the number of File write operations sent to the operating + system during code-generation. This improves performance of IDEs and the Dart + analysis server. + ## 26.1.9 * [dart] Reduces much duplication in reply-handling code. diff --git a/packages/pigeon/lib/src/generator_tools.dart b/packages/pigeon/lib/src/generator_tools.dart index 37a7d148a133..406cf94f1556 100644 --- a/packages/pigeon/lib/src/generator_tools.dart +++ b/packages/pigeon/lib/src/generator_tools.dart @@ -15,7 +15,7 @@ import 'generator.dart'; /// The current version of pigeon. /// /// This must match the version in pubspec.yaml. -const String pigeonVersion = '26.1.9'; +const String pigeonVersion = '26.1.10'; /// Read all the content from [stdin] to a String. String readStdin() { diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index ede8e75399ec..e0e25734e32e 100644 --- a/packages/pigeon/pubspec.yaml +++ b/packages/pigeon/pubspec.yaml @@ -2,7 +2,7 @@ name: pigeon description: Code generator tool to make communication between Flutter and the host platform type-safe and easier. repository: https://github.com/flutter/packages/tree/main/packages/pigeon issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pigeon%22 -version: 26.1.9 # This must match the version in lib/src/generator_tools.dart +version: 26.1.10 # This must match the version in lib/src/generator_tools.dart environment: sdk: ^3.9.0 From 212ed48c9949652dcbb9833353fb5acf3cd79797 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 2 Mar 2026 11:07:30 -0800 Subject: [PATCH 3/3] feedback --- packages/pigeon/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index b80a8e4ced9f..27ebd2090661 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,6 +1,6 @@ ## 26.1.10 -* Dramatically reduce the number of File write operations sent to the operating +* Dramatically reduces the number of File write operations sent to the operating system during code-generation. This improves performance of IDEs and the Dart analysis server.