Skip to content

Commit 74669e4

Browse files
bkonyiandrewkolos
andauthored
Add flutter widget-preview {start, clean} commands (#159510)
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: flutter/flutter#115704 --------- Co-authored-by: Andrew Kolos <andrewrkolos@gmail.com>
1 parent 3de19db commit 74669e4

File tree

14 files changed

+741
-304
lines changed

14 files changed

+741
-304
lines changed

packages/flutter_tools/lib/executable.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import 'src/commands/symbolize.dart';
4343
import 'src/commands/test.dart';
4444
import 'src/commands/update_packages.dart';
4545
import 'src/commands/upgrade.dart';
46+
import 'src/commands/widget_preview.dart';
4647
import 'src/devtools_launcher.dart';
4748
import 'src/features.dart';
4849
import 'src/globals.dart' as globals;
@@ -250,6 +251,7 @@ List<FlutterCommand> generateCommands({
250251
verbose: verbose,
251252
nativeAssetsBuilder: globals.nativeAssetsBuilder,
252253
),
254+
WidgetPreviewCommand(),
253255
UpgradeCommand(verboseHelp: verboseHelp),
254256
SymbolizeCommand(
255257
stdio: globals.stdio,

packages/flutter_tools/lib/src/build_system/build_system.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ class Environment {
488488
/// The path to the package configuration file to use for compilation.
489489
///
490490
/// This is used by package:package_config to locate the actual package_config.json
491-
/// file. If not provided, defaults to `.dart_tool/package_config.json`.
491+
/// file. If not provided in tests, defaults to `.dart_tool/package_config.json`.
492492
final String packageConfigPath;
493493

494494
/// The `BUILD_DIR` environment variable.

packages/flutter_tools/lib/src/commands/create.dart

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,73 @@ const String kPlatformHelp =
3535
'When adding platforms to a plugin project, the pubspec.yaml will be updated with the requested platform. '
3636
'Adding desktop platforms requires the corresponding desktop config setting to be enabled.';
3737

38-
class CreateCommand extends CreateBase {
39-
CreateCommand({
40-
super.verboseHelp = false,
41-
}) {
38+
class CreateCommand extends FlutterCommand with CreateBase {
39+
CreateCommand({bool verboseHelp = false}) {
40+
addPubOptions();
41+
argParser.addFlag(
42+
'with-driver-test',
43+
help: '(deprecated) Historically, this added a flutter_driver dependency and generated a '
44+
'sample "flutter drive" test. Now it does nothing. Consider using the '
45+
'"integration_test" package: https://pub.dev/packages/integration_test',
46+
hide: !verboseHelp,
47+
);
48+
argParser.addFlag(
49+
'overwrite',
50+
help: 'When performing operations, overwrite existing files.',
51+
);
52+
argParser.addOption(
53+
'description',
54+
defaultsTo: 'A new Flutter project.',
55+
help:
56+
'The description to use for your new Flutter project. This string ends up in the pubspec.yaml file.',
57+
);
58+
argParser.addOption(
59+
'org',
60+
defaultsTo: 'com.example',
61+
help:
62+
'The organization responsible for your new Flutter project, in reverse domain name notation. '
63+
'This string is used in Java package names and as prefix in the iOS bundle identifier.',
64+
);
65+
argParser.addOption(
66+
'project-name',
67+
help:
68+
'The project name for this new Flutter project. This must be a valid dart package name.',
69+
);
70+
argParser.addOption(
71+
'ios-language',
72+
abbr: 'i',
73+
defaultsTo: 'swift',
74+
allowed: <String>['objc', 'swift'],
75+
help: '(deprecated) The language to use for iOS-specific code, either Swift (recommended) or Objective-C (legacy).',
76+
hide: !verboseHelp,
77+
);
78+
argParser.addOption(
79+
'android-language',
80+
abbr: 'a',
81+
defaultsTo: 'kotlin',
82+
allowed: <String>['java', 'kotlin'],
83+
help: 'The language to use for Android-specific code, either Kotlin (recommended) or Java (legacy).',
84+
);
85+
argParser.addFlag(
86+
'skip-name-checks',
87+
help:
88+
'Allow the creation of applications and plugins with invalid names. '
89+
'This is only intended to enable testing of the tool itself.',
90+
hide: !verboseHelp,
91+
);
92+
argParser.addFlag(
93+
'implementation-tests',
94+
help:
95+
'Include implementation tests that verify the template functions correctly. '
96+
'This is only intended to enable testing of the tool itself.',
97+
hide: !verboseHelp,
98+
);
99+
argParser.addOption(
100+
'initial-create-revision',
101+
help: 'The Flutter SDK git commit hash to store in .migrate_config. This parameter is used by the tool '
102+
'internally and should generally not be used manually.',
103+
hide: !verboseHelp,
104+
);
42105
addPlatformsOptions(customHelp: kPlatformHelp);
43106
argParser.addOption(
44107
'template',
@@ -437,12 +500,12 @@ class CreateCommand extends CreateBase {
437500
pubContext = PubContext.createPackage;
438501
}
439502

440-
if (boolArg('pub')) {
503+
if (shouldCallPubGet) {
441504
final FlutterProject project = FlutterProject.fromDirectory(relativeDir);
442505
await pub.get(
443506
context: pubContext,
444507
project: project,
445-
offline: boolArg('offline'),
508+
offline: offline,
446509
outputMode: PubOutputMode.summaryOnly,
447510
);
448511
// Setting `includeIos` etc to false as with FlutterProjectType.package

packages/flutter_tools/lib/src/commands/create_base.dart

Lines changed: 33 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -48,96 +48,15 @@ const String _kDefaultPlatformArgumentHelp =
4848
'Platform folders (e.g. android/) will be generated in the target project. '
4949
'Adding desktop platforms requires the corresponding desktop config setting to be enabled.';
5050

51-
/// Common behavior for `flutter create` commands.
52-
abstract class CreateBase extends FlutterCommand {
53-
CreateBase({
54-
required bool verboseHelp,
55-
}) {
56-
argParser.addFlag(
57-
'pub',
58-
defaultsTo: true,
59-
help:
60-
'Whether to run "flutter pub get" after the project has been created.',
61-
);
62-
argParser.addFlag(
63-
'offline',
64-
help:
65-
'When "flutter pub get" is run by the create command, this indicates '
66-
'whether to run it in offline mode or not. In offline mode, it will need to '
67-
'have all dependencies already available in the pub cache to succeed.',
68-
);
69-
argParser.addFlag(
70-
'with-driver-test',
71-
help: '(deprecated) Historically, this added a flutter_driver dependency and generated a '
72-
'sample "flutter drive" test. Now it does nothing. Consider using the '
73-
'"integration_test" package: https://pub.dev/packages/integration_test',
74-
hide: !verboseHelp,
75-
);
76-
argParser.addFlag(
77-
'overwrite',
78-
help: 'When performing operations, overwrite existing files.',
79-
);
80-
argParser.addOption(
81-
'description',
82-
defaultsTo: 'A new Flutter project.',
83-
help:
84-
'The description to use for your new Flutter project. This string ends up in the pubspec.yaml file.',
85-
);
86-
argParser.addOption(
87-
'org',
88-
defaultsTo: 'com.example',
89-
help:
90-
'The organization responsible for your new Flutter project, in reverse domain name notation. '
91-
'This string is used in Java package names and as prefix in the iOS bundle identifier.',
92-
);
93-
argParser.addOption(
94-
'project-name',
95-
help:
96-
'The project name for this new Flutter project. This must be a valid dart package name.',
97-
);
98-
argParser.addOption(
99-
'ios-language',
100-
abbr: 'i',
101-
defaultsTo: 'swift',
102-
allowed: <String>['objc', 'swift'],
103-
help: '(deprecated) The language to use for iOS-specific code, either Swift (recommended) or Objective-C (legacy).',
104-
hide: !verboseHelp,
105-
);
106-
argParser.addOption(
107-
'android-language',
108-
abbr: 'a',
109-
defaultsTo: 'kotlin',
110-
allowed: <String>['java', 'kotlin'],
111-
help: 'The language to use for Android-specific code, either Kotlin (recommended) or Java (legacy).',
112-
);
113-
argParser.addFlag(
114-
'skip-name-checks',
115-
help:
116-
'Allow the creation of applications and plugins with invalid names. '
117-
'This is only intended to enable testing of the tool itself.',
118-
hide: !verboseHelp,
119-
);
120-
argParser.addFlag(
121-
'implementation-tests',
122-
help:
123-
'Include implementation tests that verify the template functions correctly. '
124-
'This is only intended to enable testing of the tool itself.',
125-
hide: !verboseHelp,
126-
);
127-
argParser.addOption(
128-
'initial-create-revision',
129-
help: 'The Flutter SDK git commit hash to store in .migrate_config. This parameter is used by the tool '
130-
'internally and should generally not be used manually.',
131-
hide: !verboseHelp,
132-
);
133-
}
134-
51+
/// Common behavior for `flutter create` and `flutter widget-preview start` commands.
52+
mixin CreateBase on FlutterCommand {
13553
/// Pattern for a Windows file system drive (e.g. "D:").
13654
///
13755
/// `dart:io` does not recognize strings matching this pattern as absolute
13856
/// paths, as they have no top level back-slash; however, users often specify
13957
/// this
14058
@visibleForTesting
59+
@protected
14160
static final RegExp kWindowsDrivePattern = RegExp(r'^[a-zA-Z]:$');
14261

14362
/// The output directory of the command.
@@ -162,6 +81,35 @@ abstract class CreateBase extends FlutterCommand {
16281
return globals.fs.path.normalize(projectDir.absolute.path);
16382
}
16483

84+
@protected
85+
bool get shouldCallPubGet {
86+
return boolArg('pub');
87+
}
88+
89+
@protected
90+
bool get offline {
91+
return boolArg('offline');
92+
}
93+
94+
/// Adds `--pub` and `--offline` options.
95+
@protected
96+
void addPubOptions() {
97+
argParser
98+
..addFlag(
99+
'pub',
100+
defaultsTo: true,
101+
help:
102+
'Whether to run "flutter pub get" after the project has been created.',
103+
)
104+
..addFlag(
105+
'offline',
106+
help:
107+
'When "flutter pub get" is run by the create command, this indicates '
108+
'whether to run it in offline mode or not. In offline mode, it will need to '
109+
'have all dependencies already available in the pub cache to succeed.',
110+
);
111+
}
112+
165113
/// Adds a `--platforms` argument.
166114
///
167115
/// The help message of the argument is replaced with `customHelp` if `customHelp` is not null.
@@ -558,7 +506,7 @@ abstract class CreateBase extends FlutterCommand {
558506
final bool windowsPlatform = templateContext['windows'] as bool? ?? false;
559507
final bool webPlatform = templateContext['web'] as bool? ?? false;
560508

561-
if (boolArg('pub')) {
509+
if (shouldCallPubGet) {
562510
final Environment environment = Environment(
563511
artifacts: globals.artifacts!,
564512
logger: globals.logger,

0 commit comments

Comments
 (0)