This PR contributes to https://github.com/flutter/flutter/issues/130459
### Description
- Updates `examples/api/lib/material/material_state/material_state_mouse_cursor.0.dart` to allow enable/disable `ListTile` in tests;
- Adds tests for `examples/api/lib/material/material_state/material_state_mouse_cursor.0.dart`.
Refactor docs testing suite in order to reduce testing logic in test.dart and allow for later implementing package:test onto the existing docs tests
Part of https://github.com/flutter/flutter/issues/145482
Refactor the analyze testing suite in order to reduce testing logic in test.dart and allow for later implementing package:test onto the existing analyze tests
Part of https://github.com/flutter/flutter/issues/145482
Refactor realm_checker suite in order to reduce testing logic in test.dart and allow for later implementing package:test onto the existing realm_checker tests
Part of https://github.com/flutter/flutter/issues/145482
*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
Starts creating metric files consistently for web, dart and flutter runners. It also starts creating the files in the temp folder instead of the checkout one.
Bug: https://github.com/flutter/flutter/issues/145793
Refactor flutter_plugins suite in order to reduce testing logic in test.dart and allow for later implementing package:test onto the existing flutter_plugins tests
Also update the test_test invocation of getFlutterPackagesVersion
Part of https://github.com/flutter/flutter/issues/145482
Shard tests present output inconsistently using the compact or extended reporter depending on the defaults of flutter test and dart test. To make the output consistent and simplify debugging of failures this PR is enabling the extended reporter for all the tests based on unit/integration test packages.
Bug: https://github.com/flutter/flutter/issues/145616
Refactor skp_generator_tests suite in order to reduce testing logic in test.dart and allow for later implementing package:test onto the existing skp_generator_tests tests
Part of https://github.com/flutter/flutter/issues/145482
Refactor web long running tests in order to reduce testing logic in test.dart, create a suite_runners directory and allow for later implementing package:test onto the existing tests
Part of https://github.com/flutter/flutter/issues/145482
This PR makes the static API of the `BackgroundIsolateBinaryMessenger` consistent between its web and IO implementations.
This way, multi-platform applications will compile for the web when using the `ensureInitialized` method (even though it'll throw at runtime, like the `instance` getter, because isolates are not supported on the web).
### Issues
* Fixes: https://github.com/flutter/flutter/issues/145260
Refactor add_to_app_life_cycle_tests in order to reduce testing logic in test.dart, create a suite_runners directory and allow for later implementing package:test onto add_to_app_life_cycle_tests
Part of https://github.com/flutter/flutter/issues/145482
When print is used inside tests its content is added to the test report as a string of unicode \u0000 making the test reporting parser fail. This PR cleans removes non json content every line of the report.
Bug: https://github.com/flutter/flutter/issues/145553
I did some local debugging but couldn't get an exact root cause on the flakiness of these tests. Running them locally, there are a lot of assertions and exceptions being thrown in console, so I think we need to figure out what's going on there, but we should disable these for now to unblock the tree.
`@visibleForOverriding` + `@protected` unfortunately does not catch the case where a `compute*` method was overridden in a subtype and the overide was called in that same type's implementation.
I did not add a `flutter_ignore` for this because it doesn't seem there will be false positives.
* Adds support for `flutter test --wasm`.
* The test compilation flow is a bit different now, so that it supports compilers other than DDC. Specifically, when we run a set of unit tests, we generate a "switchboard" main function that imports each unit test and runs the main function for a specific one based off of a value set by the JS bootstrapping code. This way, there is one compile step and the same compile output is invoked for each unit test file.
* Also, removes all references to `dart:html` from flutter/flutter.
* Adds CI steps for running the framework unit tests with dart2wasm+skwasm
* These steps are marked as `bringup: true`, so we don't know what kind of failures they will result in. Any failures they have will not block the tree at all yet while we're still in `bringup: true`. Once this PR is merged, I plan on looking at any failures and either fixing them or disabling them so we can get these CI steps running on presubmit.
This fixes https://github.com/flutter/flutter/issues/126692
This makes several changes to flutter web app bootstrapping.
* The build now produces a `flutter_bootstrap.js` file.
* By default, this file does the basic streamlined startup of a flutter app with the service worker settings and no user configuration.
* The user can also put a `flutter_bootstrap.js` file in the `web` subdirectory in the project directory which can have whatever custom bootstrapping logic they'd like to write instead. This file is also templated, and can use any of the tokens that can be used with the `index.html` (with the exception of `{{flutter_bootstrap_js}}`, see below).
* Introduced a few new templating tokens for `index.html`:
* `{{flutter_js}}` => inlines the entirety of `flutter.js`
* `{{flutter_service_worker_version}}` => replaced directly by the service worker version. This can be used instead of the script that sets the `serviceWorkerVersion` local variable that we used to have by default.
* `{{flutter_bootstrap_js}}` => inlines the entirety of `flutter_bootstrap.js` (this token obviously doesn't apply to `flutter_bootstrap.js` itself).
* Changed `IndexHtml` to be called `WebTemplate` instead, since it is used for more than just the index.html now.
* We now emit warnings at build time for certain deprecated flows:
* Warn on the old service worker version pattern (i.e.`(const|var) serviceWorkerVersion = null`) and recommends using `{{flutter_service_worker_version}}` token instead
* Warn on use of `FlutterLoader.loadEntrypoint` and recommend using `FlutterLoader.load` instead
* Warn on manual loading of `flutter_service_worker.js`.
* The default `index.html` on `flutter create` now uses an async script tag with `flutter_bootstrap.js`.
Reverts: flutter/flutter#144706
Initiated by: gspencergoog
Reason for reverting: This has broken the tree because some tests are still failing post completion. This particular one looks like it might have to do with a gold image not existing.
Original PR Author: goderbauer
Reviewed By: {Piinks}
This change reverts the following previous change:
A test was failing silently because of this (see https://github.com/flutter/flutter/issues/144353 and fixed in https://github.com/flutter/flutter/pull/144709). The failure went undetected for months. Ideally, this should have been a regular non-silent failure. This change makes that so. `package:test` can properly handle reported exceptions outside of test cases. With this change, the test fails as follows:
```
00:03 +82: Smoke test material/color_scheme/dynamic_content_color.0.dart
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() called after dispose(): _DynamicColorExampleState#1cd37(lifecycle state: defunct, not
mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in
the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error
can occur when code calls setState() from a timer or an animation callback.
The preferred solution is to cancel the timer or stop listening to the animation in the dispose()
callback. Another solution is to check the "mounted" property of this object before calling
setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is
retaining a reference to this State object after it has been removed from the tree. To avoid memory
leaks, consider breaking the reference to this object during dispose().
When the exception was thrown, this was the stack:
#0 State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1167:9)
#1 State.setState (package:flutter/src/widgets/framework.dart:1202:6)
#2 _DynamicColorExampleState._updateImage (package:flutter_api_samples/material/color_scheme/dynamic_content_color.0.dart:191:5)
<asynchronous suspension>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +81 -1: Smoke test material/context_menu/context_menu_controller.0.dart
00:03 +81 -1: Smoke test material/color_scheme/dynamic_content_color.0.dart [E]
Test failed. See exception logs above.
The test description was: Smoke test material/color_scheme/dynamic_content_color.0.dart
This test failed after it had already completed.
Make sure to use a matching library which informs the test runner
of pending async work.
```
A test was failing silently because of this (see
https://github.com/flutter/flutter/issues/144353 and fixed in
https://github.com/flutter/flutter/pull/144709). The failure went
undetected for months. Ideally, this should have been a regular
non-silent failure. This change makes that so. `package:test` can
properly handle reported exceptions outside of test cases. With this
change, the test fails as follows:
```
00:03 +82: Smoke test material/color_scheme/dynamic_content_color.0.dart
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() called after dispose(): _DynamicColorExampleState#1cd37(lifecycle state: defunct, not
mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in
the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error
can occur when code calls setState() from a timer or an animation callback.
The preferred solution is to cancel the timer or stop listening to the animation in the dispose()
callback. Another solution is to check the "mounted" property of this object before calling
setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is
retaining a reference to this State object after it has been removed from the tree. To avoid memory
leaks, consider breaking the reference to this object during dispose().
When the exception was thrown, this was the stack:
#0 State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1167:9)
#1 State.setState (package:flutter/src/widgets/framework.dart:1202:6)
#2 _DynamicColorExampleState._updateImage (package:flutter_api_samples/material/color_scheme/dynamic_content_color.0.dart:191:5)
<asynchronous suspension>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +81 -1: Smoke test material/context_menu/context_menu_controller.0.dart
00:03 +81 -1: Smoke test material/color_scheme/dynamic_content_color.0.dart [E]
Test failed. See exception logs above.
The test description was: Smoke test material/color_scheme/dynamic_content_color.0.dart
This test failed after it had already completed.
Make sure to use a matching library which informs the test runner
of pending async work.
```
Fix is in the second commit. The logic here went out of sync with the logic in the snippets generator from https://github.com/flutter/assets-for-api-docs, whose version was bumped as part of this change.
Reverts flutter/flutter#144329
Initiated by: goderbauer
Reason for reverting: broke postsubmit doc generation.
Original PR Author: goderbauer
Reviewed By: {devoncarew, HansMuller, gspencergoog}
This change reverts the following previous change:
Original Description:
Dartpad doesn't have a "master" channel anymore, it got renamed to "main". Sadly, specifying "master" is now falling back to "stable" which breaks some of our examples in the docs that require a more current Flutter version, e.g. https://main-api.flutter.dev/flutter/material/TextButton-class.html
Dartpad doesn't have a "master" channel anymore, it got renamed to "main". Sadly, specifying "master" is now falling back to "stable" which breaks some of our examples in the docs that require a more current Flutter version, e.g. https://main-api.flutter.dev/flutter/material/TextButton-class.html
Reverts flutter/flutter#143244
Initiated by: vashworth
Reason for reverting: Increased `flutter_framework_uncompressed_bytes` - see https://github.com/flutter/flutter/issues/144251
Original PR Author: vashworth
Reviewed By: {jmagman}
This change reverts the following previous change:
Original Description:
Replace `FlutterMacOS.framework` cached artifact with `FlutterMacOS.xcframework`. Also, update usage of `FlutterMacOS.framework` to use `FlutterMacOS.xcframework`.
Part of https://github.com/flutter/flutter/issues/126016.
Replace `FlutterMacOS.framework` cached artifact with `FlutterMacOS.xcframework`. Also, update usage of `FlutterMacOS.framework` to use `FlutterMacOS.xcframework`.
Part of https://github.com/flutter/flutter/issues/126016.
This pull request fixes#143803 by taking advantage of Dart's null-aware operators.
And unlike `switch` expressions ([9 PRs](https://github.com/flutter/flutter/pull/143634) and counting), the Flutter codebase is already fantastic when it comes to null-aware coding. After refactoring the entire repo, all the changes involving `?.` and `??` can fit into a single pull request.
Reland https://github.com/flutter/flutter/pull/141818 with a fix for a special case: If only `background` is specified for `TextButton.styleFrom` or `OutlinedButton.styleFrom` it applies the button's disabled state, i.e. as if the same value had been specified for disabledBackgroundColor.
The change relative to #141818 is the indicated line below:
```dart
final MaterialStateProperty<Color?>? backgroundColorProp = switch ((backgroundColor, disabledBackgroundColor)) {
(null, null) => null,
(_, null) => MaterialStatePropertyAll<Color?>(backgroundColor), // ADDED THIS LINE
(_, _) => _TextButtonDefaultColor(backgroundColor, disabledBackgroundColor),
};
```
This backwards incompatibility cropped up in an internal test, see internal Google issue b/323399158.
On the beta branch:
```
Verifying the code signature of /Users/m/Projects/flutter/bin/cache/artifacts/engine/ios-profile/extension_safe/Flutter.xcframework
Verifying the code signature of /Users/m/Projects/flutter/bin/cache/artifacts/engine/ios-profile/Flutter.xcframework
Verifying the code signature of /Users/m/Projects/flutter/bin/cache/artifacts/engine/ios/extension_safe/Flutter.xcframework
Verifying the code signature of /Users/m/Projects/flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework
Verifying the code signature of /Users/m/Projects/flutter/bin/cache/artifacts/engine/ios-release/extension_safe/Flutter.xcframework
Verifying the code signature of /Users/m/Projects/flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework
```
Fixes https://github.com/flutter/flutter/issues/140934
Reverts flutter/flutter#141818
Initiated by: XilaiZhang
This change reverts the following previous change:
Original Description:
Fixes https://github.com/flutter/flutter/issues/139456, https://github.com/flutter/flutter/issues/130335, https://github.com/flutter/flutter/issues/89563.
Two new properties have been added to ButtonStyle to make it possible to insert arbitrary state-dependent widgets in a button's background or foreground. These properties can be specified for an individual button, using the style parameter, or for all buttons using a button theme's style parameter.
The new ButtonStyle properties are `backgroundBuilder` and `foregroundBuilder` and their (function) types are:
```dart
typedef ButtonLayerBuilder = Widget Function(
BuildContext context,
Set<MaterialState> states,
Widget? child
);
```
The new builder functions are called whenever the button is built and the `states` parameter communicates the pressed/hovered/etc state fo the button.
## `backgroundBuilder`
Creates a widget that becomes the child of the button's Material and whose child is the rest of the button, including the button's `child` parameter. By default the returned widget is clipped to the Material's ButtonStyle.shape.
The `backgroundBuilder` can be used to add a gradient to the button's background. Here's an example that creates a yellow/orange gradient background:

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Because the background widget becomes the child of the button's Material, if it's opaque (as it is in this case) then it obscures the overlay highlights which are painted on the button's Material. To ensure that the highlights show through one can decorate the background with an `Ink` widget. This version also overrides the overlay color to be (shades of) red, because that makes the highlights look a little nicer with the yellow/orange background.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Now the button's overlay highlights are painted on the Ink widget. An Ink widget isn't needed if the background is sufficiently translucent. This version of the example creates a translucent backround widget.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Colors.orange.withOpacity(0.5),
Colors.yellow.withOpacity(0.5),
]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
One can also decorate the background with an image. In this example, the button's background is an burlap texture image. The foreground color has been changed to black to make the button's text a little clearer relative to the mottled brown backround.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.black,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(burlapUrl),
fit: BoxFit.cover,
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The background widget can depend on the `states` parameter. In this example the blue/orange gradient flips horizontally when the button is hovered/pressed.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The preceeding examples have not included a BoxDecoration border because ButtonStyle already supports `ButtonStyle.shape` and `ButtonStyle.side` parameters that can be uesd to define state-dependent borders. Borders defined with the ButtonStyle side parameter match the button's shape. To add a border that changes color when the button is hovered or pressed, one must specify the side property using `copyWith`, since there's no `styleFrom` shorthand for this case.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.indigo,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
).copyWith(
side: MaterialStateProperty.resolveWith<BorderSide?>((Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return BorderSide(width: 3, color: Colors.yellow);
}
return null; // defer to the default
}),
),
child: Text('Text Button'),
)
```
Although all of the examples have created a ButtonStyle locally and only applied it to one button, they could have configured the `ThemeData.textButtonTheme` instead and applied the style to all TextButtons. And, of course, all of this works for all of the ButtonStyleButton classes, not just TextButton.
## `foregroundBuilder`
Creates a Widget that contains the button's child parameter. The returned widget is clipped by the button's [ButtonStyle.shape] inset by the button's [ButtonStyle.padding] and aligned by the button's [ButtonStyle.alignment].
The `foregroundBuilder` can be used to wrap the button's child, e.g. with a border or a `ShaderMask` or as a state-dependent substitute for the child.
This example adds a border that's just applied to the child. The border only appears when the button is hovered/pressed.

```dart
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return DecoratedBox(
decoration: BoxDecoration(
border: states.contains(MaterialState.hovered)
? Border(bottom: BorderSide(color: colorScheme.primary))
: Border(), // essentially "no border"
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The foregroundBuilder can be used with `ShaderMask` to change the way the button's child is rendered. In this example the ShaderMask's gradient causes the button's child to fade out on top.

```dart
ElevatedButton(
onPressed: () { },
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: <Color>[
colorScheme.primary,
colorScheme.primaryContainer,
],
).createShader(bounds);
},
blendMode: BlendMode.srcATop,
child: child,
);
},
),
child: const Text('Elevated Button'),
)
```
A commonly requested configuration for butttons has the developer provide images, one for pressed/hovered/normal state. You can use the foregroundBuilder to create a button that fades between a normal image and another image when the button is pressed. In this case the foregroundBuilder doesn't use the child it's passed, even though we've provided the required TextButton child parameter.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final String url = states.contains(MaterialState.pressed) ? smiley2Url : smiley1Url;
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
In this example the button's default overlay appears when the button is hovered and pressed. Another image can be used to indicate the hovered state and the default overlay can be defeated by specifying `Colors.transparent` for the `overlayColor`:

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.transparent,
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
String url = states.contains(MaterialState.hovered) ? smiley3Url : smiley1Url;
if (states.contains(MaterialState.pressed)) {
url = smiley2Url;
}
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
Fixes https://github.com/flutter/flutter/issues/139456, https://github.com/flutter/flutter/issues/130335, https://github.com/flutter/flutter/issues/89563.
Two new properties have been added to ButtonStyle to make it possible to insert arbitrary state-dependent widgets in a button's background or foreground. These properties can be specified for an individual button, using the style parameter, or for all buttons using a button theme's style parameter.
The new ButtonStyle properties are `backgroundBuilder` and `foregroundBuilder` and their (function) types are:
```dart
typedef ButtonLayerBuilder = Widget Function(
BuildContext context,
Set<MaterialState> states,
Widget? child
);
```
The new builder functions are called whenever the button is built and the `states` parameter communicates the pressed/hovered/etc state fo the button.
## `backgroundBuilder`
Creates a widget that becomes the child of the button's Material and whose child is the rest of the button, including the button's `child` parameter. By default the returned widget is clipped to the Material's ButtonStyle.shape.
The `backgroundBuilder` can be used to add a gradient to the button's background. Here's an example that creates a yellow/orange gradient background:

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Because the background widget becomes the child of the button's Material, if it's opaque (as it is in this case) then it obscures the overlay highlights which are painted on the button's Material. To ensure that the highlights show through one can decorate the background with an `Ink` widget. This version also overrides the overlay color to be (shades of) red, because that makes the highlights look a little nicer with the yellow/orange background.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Now the button's overlay highlights are painted on the Ink widget. An Ink widget isn't needed if the background is sufficiently translucent. This version of the example creates a translucent backround widget.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Colors.orange.withOpacity(0.5),
Colors.yellow.withOpacity(0.5),
]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
One can also decorate the background with an image. In this example, the button's background is an burlap texture image. The foreground color has been changed to black to make the button's text a little clearer relative to the mottled brown backround.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.black,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(burlapUrl),
fit: BoxFit.cover,
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The background widget can depend on the `states` parameter. In this example the blue/orange gradient flips horizontally when the button is hovered/pressed.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The preceeding examples have not included a BoxDecoration border because ButtonStyle already supports `ButtonStyle.shape` and `ButtonStyle.side` parameters that can be uesd to define state-dependent borders. Borders defined with the ButtonStyle side parameter match the button's shape. To add a border that changes color when the button is hovered or pressed, one must specify the side property using `copyWith`, since there's no `styleFrom` shorthand for this case.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.indigo,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
).copyWith(
side: MaterialStateProperty.resolveWith<BorderSide?>((Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return BorderSide(width: 3, color: Colors.yellow);
}
return null; // defer to the default
}),
),
child: Text('Text Button'),
)
```
Although all of the examples have created a ButtonStyle locally and only applied it to one button, they could have configured the `ThemeData.textButtonTheme` instead and applied the style to all TextButtons. And, of course, all of this works for all of the ButtonStyleButton classes, not just TextButton.
## `foregroundBuilder`
Creates a Widget that contains the button's child parameter. The returned widget is clipped by the button's [ButtonStyle.shape] inset by the button's [ButtonStyle.padding] and aligned by the button's [ButtonStyle.alignment].
The `foregroundBuilder` can be used to wrap the button's child, e.g. with a border or a `ShaderMask` or as a state-dependent substitute for the child.
This example adds a border that's just applied to the child. The border only appears when the button is hovered/pressed.

```dart
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return DecoratedBox(
decoration: BoxDecoration(
border: states.contains(MaterialState.hovered)
? Border(bottom: BorderSide(color: colorScheme.primary))
: Border(), // essentially "no border"
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The foregroundBuilder can be used with `ShaderMask` to change the way the button's child is rendered. In this example the ShaderMask's gradient causes the button's child to fade out on top.

```dart
ElevatedButton(
onPressed: () { },
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: <Color>[
colorScheme.primary,
colorScheme.primaryContainer,
],
).createShader(bounds);
},
blendMode: BlendMode.srcATop,
child: child,
);
},
),
child: const Text('Elevated Button'),
)
```
A commonly requested configuration for butttons has the developer provide images, one for pressed/hovered/normal state. You can use the foregroundBuilder to create a button that fades between a normal image and another image when the button is pressed. In this case the foregroundBuilder doesn't use the child it's passed, even though we've provided the required TextButton child parameter.

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final String url = states.contains(MaterialState.pressed) ? smiley2Url : smiley1Url;
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
In this example the button's default overlay appears when the button is hovered and pressed. Another image can be used to indicate the hovered state and the default overlay can be defeated by specifying `Colors.transparent` for the `overlayColor`:

```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.transparent,
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
String url = states.contains(MaterialState.hovered) ? smiley3Url : smiley1Url;
if (states.contains(MaterialState.pressed)) {
url = smiley2Url;
}
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
- Unskip `text_style_test` for CanvasKit.
- Remove no longer necessary `kIsWeb` checks in a few tests.
This PR depends on https://github.com/flutter/engine/pull/49786, which rolled into the framework. If the engine PR needs to be reverted, this PR will need to be reverted too.
I continued [my mission](https://github.com/flutter/flutter/pull/141431) to find as many typos as I could. This time it's a smaller set than before.
There is no need for issues since it's a typo fix.
The migration of customer tests to sharded tests adds a step that checks out the current tip-of-tree of the framework repo, removing local changes. This does not work with monorepo testing, which modifies engine.version, and does not work with local testing of a branch.
The sharded tests should already be running with the correct checkout of the framework repo. If the REVISION environment variable is set, the framework checkout will still be reset to check out that revision.
These commands were migrated from the existing shell script to the sharded tester in
https://github.com/flutter/flutter/pull/138659
Bug: https://github.com/dart-lang/sdk/issues/51042
Fix and unskip the following CanvasKit tests:
- `test/painting/decoration_test.dart`
- `test/rendering/layers_test.dart`
- `test/widgets/app_overrides_test.dart`
Each error section is numbered, so you can all be sure you're talking about the same one.
A message is printed at the very end telling you how to find the error blocks in the verbose logs.
1. Move leak_tracker and leak_tracker_testing out of direct dependencies.
2. Move leak_tracker_flutter_testing from dev to prod dependencies for flutter_test
It is prerequisite for https://github.com/flutter/flutter/issues/135856
Pinning the package:web dependency constrains downstream packages from
using newer versions and making sure they support the version pinned in
Flutter. Since the usage of package:web in Flutter is light, we should
instead have a small shim like the engine and keep package:web as a dev
dependency only.
I did not include the `'// flutter_ignore_for_file: stopwatch (see analyze.dart)'` directive since it's currently not used, and adding that shouldn't be too difficult.
Tests for `app_bar.0`, `app_bar.1`, `app_bar.2`, `app_bar.3`, `sliver_app_bar.1` and `sliver_app_bar.4` were already present. But directory name was `appbar` rather than `app_bar`. I've renamed the directory to `app_bar` since example files uses that only.
Part of #130459
Reverts flutter/flutter#132985
Initiated by: christopherfujino
This change reverts the following previous change:
Original Description:
Provides support for conditional bundling of assets through the existing `--flavor` option for `flutter build` and `flutter run`. Closes https://github.com/flutter/flutter/issues/21682. Resolves https://github.com/flutter/flutter/issues/136092
## Change
Within the `assets` section pubspec.yaml, the user can now specify one or more `flavors` that an asset belongs to. Consider this example:
```yaml
# pubspec.yaml
flutter:
assets:
- assets/normal-asset.png
- path: assets/vanilla/ice-cream.png
flavors:
- vanilla
- path: assets/strawberry/ice-cream.png
flavors:
- strawberry
```
With this pubspec,
* `flutter run --flavor vanilla` will not include `assets/strawberry/ice-cream.png` in the build output.
* `flutter run --flavor strawberry` will not include `assets/vanilla/ice-cream.png`.
* `flutter run` will only include `assets/normal-asset.png`.
## Open questions
* Should this be supported for all platforms, or should this change be limited to ones with documented `--flavor` support (Android, iOS, and (implicitly) MacOS)? This PR currently only enables this feature for officially supported platforms.
## Design thoughts, what this PR does not do, etc.
### This does not provide an automatic mapping/resolution of asset keys/paths to others based on flavor at runtime.
The implementation in this PR represents a simplest approach. Notably, it does not give Flutter the ability to dynamically choose an asset based on flavor using a single asset key. For example, one can't use `Image.asset('config.json')` to dynamically choose between different "flavors" of `config.json` (such as `dev-flavor/config.json` or `prod-flavor/config.json`). However, a user could always implement such a mechanism in their project or in a library by examining the flavor at runtime.
### When multiple entries affect the same file and 1) at least one of these entries have a `flavors` list provided and 2) these lists are not equivalent, we always consider the manifest to be ambiguous and will throw a `ToolExit`.
<details>
For example, these manifests would all be considered ambiguous:
```yaml
assets:
- assets/
- path: assets/vanilla.png
flavors:
- vanilla
assets:
- path: assets/vanilla/
flavors:
- vanilla
- path: assets/vanilla/cherry.png
flavor:
- cherry
# Thinking towards the future where we might add glob/regex support and more conditions other than flavor:
assets:
- path: assets/vanilla/**
flavors:
- vanilla
- path: assets/**/ios/**
platforms:
- ios
# Ambiguous in the case of assets like "assets/vanilla/ios/icon.svg" since we
# don't know if flavor `vanilla` and platform `ios` should be combined using or-logic or and-logic.
```
See [this review comment thread](https://github.com/flutter/flutter/pull/132985#discussion_r1381909942) for the full story on how I arrived at this decision.
</details>
### This does not support Android's multidimensional flavors feature (in an intuitive way)
<details>
Conder this excerpt from a Flutter project's android/app/build.gradle file:
```groovy
android {
// ...
flavorDimensions "mode", "api"
productFlavors {
free {
dimension "mode"
applicationIdSuffix ".free"
}
premium {
dimension "mode"
applicationIdSuffix ".premium"
}
minApi23 {
dimension "api"
versionNameSuffix "-minApi23"
}
minApi21 {
dimension "api"
versionNameSuffix "-minApi21"
}
}
}
```
In this setup, the following values are valid `--flavor` are valid `freeMinApi21`, `freeMinApi23`, `premiumMinApi21`, and `premiumMinApi23`. We call these values "flavor combinations". Consider the following from the Android documentation[^1]:
> In addition to the source set directories you can create for each individual product flavor and build variant, you can also create source set directories for each combination of product flavors. For example, you can create and add Java sources to the src/demoMinApi24/java/ directory, and Gradle uses those sources only when building a variant that combines those two product flavors.
>
> Source sets you create for product flavor combinations have a higher priority than source sets that belong to each individual product flavor. To learn more about source sets and how Gradle merges resources, read the section about how to [create source sets](https://developer.android.com/build/build-variants#sourcesets).
This feature will not behave in this way. If a user utilizes this feature and also Android's multidimensional flavors feature, they will have to list out all flavor combinations that contain the flavor they want to limit an asset to:
```yaml
assets:
- assets/free/
flavors:
- freeMinApi21
- freeMinApi23
```
This is mostly due to a technical limitation in the hot-reload feature of `flutter run`. During a hot reload, the tool will try to update the asset bundle on the device, but the tool does not know the flavors contained within the flavor combination (that the user passes to `--flavor`). Gradle is the source of truth of what flavors were involved in the build, and `flutter run` currently does not access to that information since it's an implementation detail of the build process. We could bubble up this information, but it would require a nontrivial amount of engineering work, and it's unclear how desired this functionality is. It might not be worth implementing.
</details>
See https://flutter.dev/go/flavor-specific-assets for the (outdated) design document.
<summary>Pre-launch Checklist</summary>
</details>
[^1]: https://developer.android.com/build/build-variants#flavor-dimensions
Provides support for conditional bundling of assets through the existing `--flavor` option for `flutter build` and `flutter run`. Closes https://github.com/flutter/flutter/issues/21682. Resolves https://github.com/flutter/flutter/issues/136092
## Change
Within the `assets` section pubspec.yaml, the user can now specify one or more `flavors` that an asset belongs to. Consider this example:
```yaml
# pubspec.yaml
flutter:
assets:
- assets/normal-asset.png
- path: assets/vanilla/ice-cream.png
flavors:
- vanilla
- path: assets/strawberry/ice-cream.png
flavors:
- strawberry
```
With this pubspec,
* `flutter run --flavor vanilla` will not include `assets/strawberry/ice-cream.png` in the build output.
* `flutter run --flavor strawberry` will not include `assets/vanilla/ice-cream.png`.
* `flutter run` will only include `assets/normal-asset.png`.
## Open questions
* Should this be supported for all platforms, or should this change be limited to ones with documented `--flavor` support (Android, iOS, and (implicitly) MacOS)? This PR currently only enables this feature for officially supported platforms.
## Design thoughts, what this PR does not do, etc.
### This does not provide an automatic mapping/resolution of asset keys/paths to others based on flavor at runtime.
The implementation in this PR represents a simplest approach. Notably, it does not give Flutter the ability to dynamically choose an asset based on flavor using a single asset key. For example, one can't use `Image.asset('config.json')` to dynamically choose between different "flavors" of `config.json` (such as `dev-flavor/config.json` or `prod-flavor/config.json`). However, a user could always implement such a mechanism in their project or in a library by examining the flavor at runtime.
### When multiple entries affect the same file and 1) at least one of these entries have a `flavors` list provided and 2) these lists are not equivalent, we always consider the manifest to be ambiguous and will throw a `ToolExit`.
<details>
For example, these manifests would all be considered ambiguous:
```yaml
assets:
- assets/
- path: assets/vanilla.png
flavors:
- vanilla
assets:
- path: assets/vanilla/
flavors:
- vanilla
- path: assets/vanilla/cherry.png
flavor:
- cherry
# Thinking towards the future where we might add glob/regex support and more conditions other than flavor:
assets:
- path: assets/vanilla/**
flavors:
- vanilla
- path: assets/**/ios/**
platforms:
- ios
# Ambiguous in the case of assets like "assets/vanilla/ios/icon.svg" since we
# don't know if flavor `vanilla` and platform `ios` should be combined using or-logic or and-logic.
```
See [this review comment thread](https://github.com/flutter/flutter/pull/132985#discussion_r1381909942) for the full story on how I arrived at this decision.
</details>
### This does not support Android's multidimensional flavors feature (in an intuitive way)
<details>
Conder this excerpt from a Flutter project's android/app/build.gradle file:
```groovy
android {
// ...
flavorDimensions "mode", "api"
productFlavors {
free {
dimension "mode"
applicationIdSuffix ".free"
}
premium {
dimension "mode"
applicationIdSuffix ".premium"
}
minApi23 {
dimension "api"
versionNameSuffix "-minApi23"
}
minApi21 {
dimension "api"
versionNameSuffix "-minApi21"
}
}
}
```
In this setup, the following values are valid `--flavor` are valid `freeMinApi21`, `freeMinApi23`, `premiumMinApi21`, and `premiumMinApi23`. We call these values "flavor combinations". Consider the following from the Android documentation[^1]:
> In addition to the source set directories you can create for each individual product flavor and build variant, you can also create source set directories for each combination of product flavors. For example, you can create and add Java sources to the src/demoMinApi24/java/ directory, and Gradle uses those sources only when building a variant that combines those two product flavors.
>
> Source sets you create for product flavor combinations have a higher priority than source sets that belong to each individual product flavor. To learn more about source sets and how Gradle merges resources, read the section about how to [create source sets](https://developer.android.com/build/build-variants#sourcesets).
This feature will not behave in this way. If a user utilizes this feature and also Android's multidimensional flavors feature, they will have to list out all flavor combinations that contain the flavor they want to limit an asset to:
```yaml
assets:
- assets/free/
flavors:
- freeMinApi21
- freeMinApi23
```
This is mostly due to a technical limitation in the hot-reload feature of `flutter run`. During a hot reload, the tool will try to update the asset bundle on the device, but the tool does not know the flavors contained within the flavor combination (that the user passes to `--flavor`). Gradle is the source of truth of what flavors were involved in the build, and `flutter run` currently does not access to that information since it's an implementation detail of the build process. We could bubble up this information, but it would require a nontrivial amount of engineering work, and it's unclear how desired this functionality is. It might not be worth implementing.
</details>
See https://flutter.dev/go/flavor-specific-assets for the (outdated) design document.
<summary>Pre-launch Checklist</summary>
</details>
[^1]: https://developer.android.com/build/build-variants#flavor-dimensions
Write Tests for API Examples of `cupertino_text_field.0`, `data_table.0`, `icon_button.2` & `ink_well.0`
Note: test for `cupertino_text_field.0` was already there but it was named `cupertino_text_field.0.dart`. I renamed it to `cupertino_text_field.0_test.dart`.
Part of #130459
I plan to extend the prepare_package.dart script to upload the flutter preview device ([design doc](https://docs.google.com/document/d/1AzI-_Uk2v1LA2kKKFJ7gVD4xcakXJ6yVZiS5Ek6RHtg/edit#heading=h.byp03plw7mg9)).
However, given that that script is one large >1k line file, I decided to organize it into smaller libraries in this PR. There should be no behavioral change in this PR, this is a cleanup only. I made the following changes:
1. Created a //dev/bots/prepare_package/ directory to contain helper libraries
2. Moved everything but the `main()` function in //dev/bots/prepare_package.dart into one of 4 helper libraries under the new directory from step 1:
a. archive_creator.dart which contains the code that creates archive directory locally on disk
b. archive_publisher.dart which contains the code that uploads the archive to cloud storage
c. common.dart for shared constants and definitions
d. process_runner.dart for an abstraction over running sub-processes
3. Changed all definitions to `File` and `Directory` from `dart:io` to use the testable versions from `package:file`. This allowed me to use the `MemoryFileSystem` in the unit tests, rather than creating real temp file system directories.
Write Tests for API Examples of `snack_bar.0`, `elevated_button.0`, `stepper.0`, `radio.0`, `filled_button.0`, `outlined_button.0` & `card.0`
Part of #130459
I previously made a PR (#136140) that used `switch` expressions to make some parts of the Flutter codebase easier to understand. It was assigned to the framework team, and @christopherfujino let me know that it was too large to effectively review and recommended breaking it up into smaller pull requests.
Here's a PR that only targets files in the `dev/` directory. Hopefully this will be easier to work with!
(solves issue https://github.com/flutter/flutter/issues/136139)
This PR writes tests for a few of the API examples (not all), as requested in #130459. For the test names, I used the existing tests in the `api` folder as guide.
This version is needed so that dart:js_interop can move to extension
types. Also adds some code to handle some breaking changes:
- Body -> Response. Body was an IDL interface mixin type we exposed in
dart:html. Going forward, users should either use Request or Response.
- Casts to JSAny. These are temporary until we move package:web types to
extension types. Currently, package:web types can't implement JSObject
as JSObject will move to be an extension type itself.
Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com>
https://github.com/flutter/flutter/pull/138253 demonstrated that the tests for the textures example weren't actually running on CI. This changes the testing script to execute the tests for everything inside the `examples` directory.
## Description
This checks API doc strings for malformed links to examples. It prevents errors in capitalization, spacing, number of asterisks, etc. It won't catch all errors, because it needs to have a minimally indicative string to know that it even is trying to be a link to an example. At a minimum, the line needs to look like (literally, not as a regexp) `///*seecode.*` in order to be seen as a link to an example.
Separately, I'm going to add a check to the snippets tool that checks to make sure that an `{@tool}` block includes either a link to a sample file or a dart code block.
## Tests
- Added a test to make sure it catches some malformed links.
Fixes#119401
This PR is to:
* add `Card.filled` and `Card.outlined` factory methods so that we can use tokens for these two types of cards to generate default theme instead of providing hard-corded values in example.
* update card.2.dart example.
* add test file for card.2.dart example.
* fix some mismatch caused by editing the auto-generated defaults by hand in navigation_bar.dart and navigation_drawer.dart.
Analyzer's dependency on autosnapshotting causes issues.
Because every version of integration_test from sdk depends on leak_tracker from hosted and autosnapshotting depends on leak_tracker from path, integration_test from sdk is forbidden.
So, because autosnapshotting depends on integration_test from sdk, version solving failed.
## Description
This PR adds a `nonce` parameter to flutter.js' `loadEntrypoint` method.
When set, loadEntrypoint will add a `nonce` attribute to the `main.dart.js` script tag, which allows Flutter to run in environments slightly more restricted by CSP; those that don't add `'self'` as a valid source for `script-src`.
----
### CSP directive
After this change, the CSP directive for a Flutter Web index.html can be:
```
script-src 'nonce-YOUR_NONCE_VALUE' 'wasm-unsafe-eval';
font-src https://fonts.gstatic.com;
style-src 'nonce-YOUR_NONCE_VALUE';
```
When CSP is set via a `meta` tag (like in the test accompanying this change), and to use a service worker, the CSP needs an additional directive: [`worker-src 'self';`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/worker-src)
When CSP set via response headers, the CSP that applies to `flutter_service_worker.js` is determined by its response headers. See **Web Workers API > [Content security policy](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#content_security_policy)** in MDN.)
----
### Initialization
If the CSP is set to disallow `script-src 'self'`, a nonce needs to also be passed to `loadEntrypoint`:
```javascript
_flutter.loader.loadEntrypoint({
nonce: 'SOME_NONCE',
onEntrypointLoaded: (engineInitializer) async {
const appRunner = await engineInitializer.initializeEngine({
nonce: 'SOME_NONCE',
});
appRunner.runApp();
},
});
```
(`nonce` shows twice for now, because the entrypoint loader script doesn't have direct access to the `initializeEngine` call.)
----
## Tests
* Added a smoke test to ensure an app configured as described above starts.
## Issues
* Fixes https://github.com/flutter/flutter/issues/126977
These warnings/errors have been removed from dartdoc. Removing them from the flutter config as well.
Also fixes CI to actually test doc generation for all documented packages and on dartdoc config changes.
*Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.*
*List which issues are fixed by this PR. You must list at least one issue.*
- https://github.com/flutter/flutter/issues/128381
*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
Fixes https://github.com/flutter/flutter/issues/89683.
The changes to `getFlutterView` in `FlutterDeviceScreenshot` are the fix that was required, everything else was done to get tests running (such as re-generating some lockfiles and modifying the android manifest).
The code was all currently not unit tested, and there were no other easy examples to base these java unit tests off in flutter/flutter, so let me know if this approach to testing is wrong.
## Description
This re-lands #132353 with some additional options for keeping around the staging directory, so that the recipe for publishing docs can give those options and have the staging directory left around for deploying to the website.
Reverted in #132613
## Related Issues
- https://flutter-review.googlesource.com/c/recipes/+/49580
## Description
This cleans up a lot of issues with the API doc generation.
Here are the main changes:
- Rename `dartdoc.dart` to `create_api_docs.dart`
- Move the bulk of the operations out of `dev/bots/docs.sh` into `create_api_docs.dart`.
- Delete `dashing_postprocess.dart` and `java_and_objc.dart` and incorporate those operations into `create_api_docs.dart`.
- Refactor the doc generation into more understandable classes
- Bump the snippets tool version to 0.4.0 (the latest one)
- Centralize the information gathering about the Flutter repo into the new `FlutterInformation` class.
- Clean up the directory handling, and convert to using the `file` package for all file and directory paths.
- Add an `--output` option to docs.sh that specifies the location of the output ZIP file containing the docs.
- Defaults to placing the output in `dev/docs/api_docs.zip` (i.e. where the previous code generates the file).
- Moved all document generation into a temporary folder that is removed once the documents are generated, to avoid VSCode and other IDEs trying to index the thousands of HTML and JS files in the docs output.
- Updated pubspec dependencies.
## Tests
- Added tests for doc generation.
Migrate tests in flutter/flutter. Once the tests here and in `*_customer_testing` are migrated, the default value of the migration flag will be changed from false to true, making the rounding hack disabled by default.
Context: https://github.com/flutter/flutter/issues/131862
This PR injects a "realm" component to the storage base URL when the contents of the file `bin/internal/engine.realm` is non-empty.
As documented in the PR, when the realm is `flutter_archives_v2`, and `bin/internal/engine.version` contains the commit hash for a commit in a `flutter/engine` PR, then the artifacts pulled by the tool will be the artifacts built by the presubmit checks for the PR.
This works for everything but the following two cases:
1. Fuchsia artifacts are not uploaded to CIPD by the Fuchsia presubmit builds.
2. Web artifacts are not uploaded to gstatic by the web engine presubmit builds.
For (1), the flutter/flutter presubmit `fuchsia_precache` is driven by a shell script outside of the repo. It will fail when the `engine.version` and `engine.realm` don't point to a post-submit engine commit.
For (2), the flutter/flutter web presubmit tests that refer to artifacts in gstatic hang when the artifacts aren't found, so this PR skips them.