[flutter_tools] Format plugin example template to match dart format (#188382)
The plugin example app generated by `flutter create -t plugin` fails
`dart format`. The `example/lib/main.dart` it produces contains a line
that exceeds 80 columns:
```dart
platformVersion =
await _<plugin>Plugin.getPlatformVersion() ?? 'Unknown platform version';
```
This comes from the plugin-hook block in
`templates/app/lib/main.dart.tmpl`. #187443 formatted the `--empty`
block of this same file, but the plugin-hook block was left untouched.
This PR wraps the line after `??` to match `dart format`'s output, so
newly generated plugins are formatted out of the box.
I confirmed the other `flutter create` templates (app default +
`--empty`, module, package, plugin_ffi) are already clean, so this is
the last remaining template that failed formatting.
Fixes #175960.
Adds a regression test (`has correct content and formatting with plugin
template` in `create_test.dart`) that generates a plugin and asserts
every generated `.dart` file is already `dart format`-clean, mirroring
the existing app and module template formatting tests.
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities. (I used AI tooling for this change and have reviewed,
understood, and verified it.)
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
---------
Co-authored-by: Ben Konyi <bkonyi@google.com>diff --git a/packages/flutter_tools/templates/app/lib/main.dart.tmpl b/packages/flutter_tools/templates/app/lib/main.dart.tmpl
index 76eb18b..a23bfa4 100644
--- a/packages/flutter_tools/templates/app/lib/main.dart.tmpl
+++ b/packages/flutter_tools/templates/app/lib/main.dart.tmpl
@@ -18,12 +18,14 @@
{{/withEmptyMain}}
{{^withEmptyMain}}
{{#withPlatformChannelPluginHook}}
+
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:{{pluginProjectName}}/{{pluginProjectName}}.dart';
{{/withPlatformChannelPluginHook}}
{{#withFfi}}
+
import 'dart:async';
import 'package:{{pluginProjectName}}/{{pluginProjectName}}.dart' as {{pluginProjectName}};
@@ -176,7 +178,8 @@
// We also handle the message potentially returning null.
try {
platformVersion =
- await _{{pluginClassLowerCamelCase}}.getPlatformVersion() ?? 'Unknown platform version';
+ await _{{pluginClassLowerCamelCase}}.getPlatformVersion() ??
+ 'Unknown platform version';
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
diff --git a/packages/flutter_tools/templates/plugin/test/projectName_test.dart.tmpl b/packages/flutter_tools/templates/plugin/test/projectName_test.dart.tmpl
index 028b08f..2d8d972 100644
--- a/packages/flutter_tools/templates/plugin/test/projectName_test.dart.tmpl
+++ b/packages/flutter_tools/templates/plugin/test/projectName_test.dart.tmpl
@@ -12,7 +12,7 @@
}
void main() {
- final {{pluginDartClass}}Platform initialPlatform = {{pluginDartClass}}Platform.instance;
+ final initialPlatform = {{pluginDartClass}}Platform.instance;
test('$MethodChannel{{pluginDartClass}} is the default instance', () {
expect(initialPlatform, isInstanceOf<MethodChannel{{pluginDartClass}}>());
diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
index 59b683a..0772be2 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
@@ -1516,6 +1516,38 @@
expect(sdkMetaContents, contains('/bin/cache/dart-sdk/lib/core"'));
}, overrides: {FlutterVersion: () => fakeFlutterVersion, Platform: _kNoColorTerminalPlatform});
+ testUsingContext('has correct content and formatting with plugin template', () async {
+ final command = CreateCommand();
+ final CommandRunner<void> runner = createTestCommandRunner(command);
+
+ await runner.run(<String>[
+ 'create',
+ '--template=plugin',
+ '--no-pub',
+ '--org',
+ 'com.foo.bar',
+ projectDir.path,
+ ]);
+
+ // The generated plugin and its example app should already be formatted, so
+ // `flutter create -t plugin` output passes `dart format` out of the box.
+ // Regression test for https://github.com/flutter/flutter/issues/175960.
+ for (final FileSystemEntity file in projectDir.listSync(recursive: true)) {
+ if (file is File && file.path.endsWith('.dart')) {
+ final String original = file.readAsStringSync();
+
+ final Process process = await Process.start(
+ globals.artifacts!.getArtifactPath(Artifact.engineDartBinary),
+ <String>['format', '--output=show', file.path],
+ workingDirectory: projectDir.path,
+ );
+ final String formatted = await process.stdout.transform(utf8.decoder).join();
+
+ expect(formatted, contains(original), reason: file.path);
+ }
+ }
+ }, overrides: {FlutterVersion: () => fakeFlutterVersion, Platform: _kNoColorTerminalPlatform});
+
testUsingContext(
'has iOS development team with app template',
() async {