This change makes the detection of `@Preview(...)` annotations more
robust by converting the analyzer AST directly to generated code rather
than simply copying and pasting the original source. This allows for
proper handling of the following cases WRT import prefixing:
- The use of `const`
- String interpolation
- Other uses of constant variables in non-trivial contexts
- Etc.
<!-- start_original_pr_link -->
Reverts: flutter/flutter#166698
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: jonahwilliams
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: tests are timing out in presubmit
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: bkonyi
<!-- end_original_pr_author -->
<!-- start_reviewers -->
Reviewed By: {jyameo}
<!-- end_reviewers -->
<!-- start_revert_body -->
This change reverts the following previous change:
This will eventually be used as the main communication channel between
the widget preview scaffold, the Flutter tool, and other developer
tooling (e.g., IDEs).
Fixes#166417
<!-- end_revert_body -->
Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
This will eventually be used as the main communication channel between
the widget preview scaffold, the Flutter tool, and other developer
tooling (e.g., IDEs).
Fixes#166417
This change reworks how users define previews in their code, expands the
number of valid 'functions' that can be used to create previews, and
allows for specifying a 'wrapper' function to wrap the previewed widget
with
The `WidgetPreview` class has been removed from the framework, with its
properties being added to the `Preview` annotation class instead to
remove some boilerplate from the preview declaration workflow.
Before:
```dart
@Preview()
List<WidgetPreview> previews() => <WidgetPreview>[
WidgetPreview(
name: 'Top-level preview',
child: Text('Foo'),
),
];
```
After:
```dart
@Preview(name: 'Top-level preview')
Widget previews() => Text('Foo');
```
Previews can now be defined using top-level functions, constructors and
factories which take no arguments, and static methods within classes:
Examples:
```dart
@Preview(name: 'Top-level preview')
Widget previews() => Text('Foo');
class MyWidget extends StatelessWidget {
@Preview(name: 'Constructor preview')
MyWidget.preview();
@Preview(name: 'Factory preview')
factory MyWidget.factoryPreview() => MyWidget.preview();
@Preview(name: 'Static preview')
static Widget previewStatic() => Text('Static');
@override
Widget build(BuildContext context) {
return Text('MyWidget');
}
}
```
Users can also provide a `wrapper` function with the signature `Widget
Function(Widget)` to easily wrap previewed widget with shared
bootstrapping logic.
Example:
```dart
Widget testWrapper(Widget child) {
return Provider<int>.value(
value: 42,
child: child,
);
}
@Preview(name: 'Preview with wrapper', wrapper: testWrapper)
Widget preview() {
return Text('Attributes');
}
```
Which is effectively the same as:
```dart
@Preview(name: 'Preview with wrapper')
Widget preview() {
return Provider<int>.value(
value: 42,
child: Text('Attributes'),
);
}
```
Finally, for situations where a `BuildContext` is needed, users can
return a `WidgetBuilder` from their preview function:
```dart
@Preview('Builder preview')
WidgetBuilder builderPreview() {
return (BuildContext context) {
// TODO: retrieve state from context.
return Text('Foo');
};
}
```
With this change, `flutter widget-preview start` will launch a working
widget preview environment that can render previews from a target
project.
Also fixes an issue where `--offline` wasn't being respected by some pub
operations.
This also wires up the preview detector to trigger hot reloads when new
previews are detected or previews are removed.
Note: while this change results in lib/generated_preview.dart being
generated and updated, it's not currently referenced by lib/main.dart
and the preview environment will render a black screen.
---------
Co-authored-by: Andrew Kolos <andrewrkolos@gmail.com>
<!-- start_original_pr_link -->
Reverts: flutter/flutter#161911
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: matanlurey
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: Mid-air collision with another Flutter tool
update.
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: bkonyi
<!-- end_original_pr_author -->
<!-- start_reviewers -->
Reviewed By: {andrewkolos}
<!-- end_reviewers -->
<!-- start_revert_body -->
This change reverts the following previous change:
`flutter widget-preview start` will now look for functions annotated
with `@Preview()` within the developer's project. These functions will
be used to generate
`.dart_tool/widget_preview_scaffold/lib/generated_preview.dart`, which
inserts the returned value from each preview function into a
`List<WidgetPreview>` returned from a `previews()` method that is
invoked by the widget preview scaffold root.
**Example generated_preview.dart:**
```dart
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:foo/foo.dart' as _i1;
import 'package:foo/src/bar.dart' as _i2;
import 'package:widget_preview/widget_preview.dart';
List<WidgetPreview> previews() => [_i1.preview(), _i2.barPreview1(), _i2.barPreview2()];
```
<!-- end_revert_body -->
Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
`flutter widget-preview start` will now look for functions annotated
with `@Preview()` within the developer's project. These functions will
be used to generate
`.dart_tool/widget_preview_scaffold/lib/generated_preview.dart`, which
inserts the returned value from each preview function into a
`List<WidgetPreview>` returned from a `previews()` method that is
invoked by the widget preview scaffold root.
**Example generated_preview.dart:**
```dart
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:foo/foo.dart' as _i1;
import 'package:foo/src/bar.dart' as _i2;
import 'package:widget_preview/widget_preview.dart';
List<WidgetPreview> previews() => [_i1.preview(), _i2.barPreview1(), _i2.barPreview2()];
```
This auto-formats all *.dart files in the repository outside of the
`engine` subdirectory and enforces that these files stay formatted with
a presubmit check.
**Reviewers:** Please carefully review all the commits except for the
one titled "formatted". The "formatted" commit was auto-generated by
running `dev/tools/format.sh -a -f`. The other commits were hand-crafted
to prepare the repo for the formatting change. I recommend reviewing the
commits one-by-one via the "Commits" tab and avoiding Github's "Files
changed" tab as it will likely slow down your browser because of the
size of this PR.
---------
Co-authored-by: Kate Lovett <katelovett@google.com>
Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
This is the initial tooling work for Flutter Widget Previews, adding two
commands: `flutter widget-preview start` and `flutter widget-preview
clean`.
The `start` command currently only checks to see if
`.dart_tool/widget_preview_scaffold/` exists and creates a new Flutter
project using the widget_preview_scaffold template if one isn't found.
The widget_preview_scaffold template currently only contains some
placeholder files and will be updated to include additional code
required by the scaffold.
The `clean` command simply deletes `.dart_tool/widget_preview_scaffold/`
if it's found.
This change also includes some refactoring of the `create` command in
order to share some project creation logic without requiring `flutter
widget-preview start` to spawn a new process simply to run `flutter
create -t widget_preview .dart_tool/widget_preview_scaffold`.
Related issue: https://github.com/flutter/flutter/issues/115704
---------
Co-authored-by: Andrew Kolos <andrewrkolos@gmail.com>