Skip to content

Commit 5259e1b

Browse files
authored
Add --empty to the flutter create command (#113873)
1 parent 3c2f500 commit 5259e1b

File tree

7 files changed

+98
-3
lines changed

7 files changed

+98
-3
lines changed

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

+25-3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ class CreateCommand extends CreateBase {
6565
'https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html',
6666
valueHelp: 'id',
6767
);
68+
argParser.addFlag(
69+
'empty',
70+
abbr: 'e',
71+
help: 'Specifies creating using an application template with a main.dart that is minimal, '
72+
'including no comments, as a starting point for a new application. Implies "--template=app".',
73+
);
6874
argParser.addOption(
6975
'list-samples',
7076
help: 'Specifies a JSON output file for a listing of Flutter code samples '
@@ -191,9 +197,17 @@ class CreateCommand extends CreateBase {
191197
return FlutterCommandResult.success();
192198
}
193199

200+
if (argResults!.wasParsed('empty') && argResults!.wasParsed('sample')) {
201+
throwToolExit(
202+
'Only one of --empty or --sample may be specified, not both.',
203+
exitCode: 2,
204+
);
205+
}
206+
194207
validateOutputDirectoryArg();
195208
String? sampleCode;
196209
final String? sampleArgument = stringArg('sample');
210+
final bool emptyArgument = boolArg('empty') ?? false;
197211
if (sampleArgument != null) {
198212
final String? templateArgument = stringArg('template');
199213
if (templateArgument != null && stringToProjectType(templateArgument) != FlutterProjectType.app) {
@@ -299,6 +313,7 @@ class CreateCommand extends CreateBase {
299313
flutterRoot: flutterRoot,
300314
withPlatformChannelPluginHook: generateMethodChannelsPlugin,
301315
withFfiPluginHook: generateFfiPlugin,
316+
withEmptyMain: emptyArgument,
302317
androidLanguage: stringArgDeprecated('android-language'),
303318
iosLanguage: stringArgDeprecated('ios-language'),
304319
iosDevelopmentTeam: developmentTeam,
@@ -411,11 +426,15 @@ class CreateCommand extends CreateBase {
411426
);
412427
}
413428
if (sampleCode != null) {
414-
generatedFileCount += _applySample(relativeDir, sampleCode);
429+
_applySample(relativeDir, sampleCode);
430+
}
431+
if (sampleCode != null || emptyArgument) {
432+
generatedFileCount += _removeTestDir(relativeDir);
415433
}
416434
globals.printStatus('Wrote $generatedFileCount files.');
417435
globals.printStatus('\nAll done!');
418-
final String application = sampleCode != null ? 'sample application' : 'application';
436+
final String application =
437+
'${emptyArgument ? 'empty' : ''}${sampleCode != null ? 'sample' : ''} application';
419438
if (generatePackage) {
420439
final String relativeMainPath = globals.fs.path.normalize(globals.fs.path.join(
421440
relativeDirPath,
@@ -657,10 +676,13 @@ Your $application code is in $relativeAppMain.
657676
// documentation website in sampleCode. Returns the difference in the number
658677
// of files after applying the sample, since it also deletes the application's
659678
// test directory (since the template's test doesn't apply to the sample).
660-
int _applySample(Directory directory, String sampleCode) {
679+
void _applySample(Directory directory, String sampleCode) {
661680
final File mainDartFile = directory.childDirectory('lib').childFile('main.dart');
662681
mainDartFile.createSync(recursive: true);
663682
mainDartFile.writeAsStringSync(sampleCode);
683+
}
684+
685+
int _removeTestDir(Directory directory) {
664686
final Directory testDir = directory.childDirectory('test');
665687
final List<FileSystemEntity> files = testDir.listSync(recursive: true);
666688
testDir.deleteSync(recursive: true);

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

+2
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ abstract class CreateBase extends FlutterCommand {
354354
String? gradleVersion,
355355
bool withPlatformChannelPluginHook = false,
356356
bool withFfiPluginHook = false,
357+
bool withEmptyMain = false,
357358
bool ios = false,
358359
bool android = false,
359360
bool web = false,
@@ -409,6 +410,7 @@ abstract class CreateBase extends FlutterCommand {
409410
'withFfiPluginHook': withFfiPluginHook,
410411
'withPlatformChannelPluginHook': withPlatformChannelPluginHook,
411412
'withPluginHook': withFfiPluginHook || withPlatformChannelPluginHook,
413+
'withEmptyMain': withEmptyMain,
412414
'androidLanguage': androidLanguage,
413415
'iosLanguage': iosLanguage,
414416
'hasIosDevelopmentTeam': iosDevelopmentTeam != null && iosDevelopmentTeam.isNotEmpty,

packages/flutter_tools/templates/app/README.md.tmpl

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# {{projectName}}
22

33
{{description}}
4+
{{^withEmptyMain}}
45

56
## Getting Started
67

@@ -14,3 +15,4 @@ A few resources to get you started if this is your first Flutter project:
1415
For help getting started with Flutter development, view the
1516
[online documentation](https://docs.flutter.dev/), which offers tutorials,
1617
samples, guidance on mobile development, and a full API reference.
18+
{{/withEmptyMain}}

packages/flutter_tools/templates/app/lib/main.dart.tmpl

+23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,26 @@
11
import 'package:flutter/material.dart';
2+
{{#withEmptyMain}}
3+
4+
void main() {
5+
runApp(const MainApp());
6+
}
7+
8+
class MainApp extends StatelessWidget {
9+
const MainApp({super.key});
10+
11+
@override
12+
Widget build(BuildContext context) {
13+
return const MaterialApp(
14+
home: Scaffold(
15+
body: Center(
16+
child: Text('Hello World!'),
17+
),
18+
),
19+
);
20+
}
21+
}
22+
{{/withEmptyMain}}
23+
{{^withEmptyMain}}
224
{{#withPlatformChannelPluginHook}}
325
import 'dart:async';
426

@@ -248,3 +270,4 @@ class _MyAppState extends State<MyApp> {
248270
}
249271
}
250272
{{/withFfiPluginHook}}
273+
{{/withEmptyMain}}

packages/flutter_tools/templates/app/pubspec.yaml.tmpl

+20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
name: {{projectName}}
22
description: {{description}}
3+
{{#withEmptyMain}}
4+
publish_to: 'none'
5+
version: 0.1.0
36

7+
environment:
8+
sdk: {{dartSdkVersionBounds}}
9+
10+
dependencies:
11+
flutter:
12+
sdk: flutter
13+
14+
dev_dependencies:
15+
flutter_test:
16+
sdk: flutter
17+
flutter_lints: ^2.0.0
18+
19+
flutter:
20+
uses-material-design: true
21+
{{/withEmptyMain}}
22+
{{^withEmptyMain}}
423
# The following line prevents the package from being accidentally published to
524
# pub.dev using `flutter pub publish`. This is preferred for private packages.
625
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
@@ -100,3 +119,4 @@ flutter:
100119
#
101120
# For details regarding fonts from package dependencies,
102121
# see https://flutter.dev/custom-fonts/#from-packages
122+
{{/withEmptyMain}}

packages/flutter_tools/templates/app_shared/analysis_options.yaml.tmpl

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{{^withEmptyMain}}
12
# This file configures the analyzer, which statically analyzes Dart code to
23
# check for errors, warnings, and lints.
34
#
@@ -7,7 +8,9 @@
78

89
# The following line activates a set of recommended lints for Flutter apps,
910
# packages, and plugins designed to encourage good coding practices.
11+
{{/withEmptyMain}}
1012
include: package:flutter_lints/flutter.yaml
13+
{{^withEmptyMain}}
1114

1215
linter:
1316
# The lint rules applied to this project can be customized in the
@@ -27,3 +30,4 @@ linter:
2730

2831
# Additional information about this file can be found at
2932
# https://dart.dev/guides/language/analysis-options
33+
{{/withEmptyMain}}

packages/flutter_tools/test/commands.shard/permeable/create_test.dart

+22
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,28 @@ void main() {
19441944
},
19451945
);
19461946

1947+
testUsingContext('can create an empty application project', () async {
1948+
await _createAndAnalyzeProject(
1949+
projectDir,
1950+
<String>['--no-pub', '--empty'],
1951+
<String>[
1952+
'lib/main.dart',
1953+
'flutter_project.iml',
1954+
'android/app/src/main/AndroidManifest.xml',
1955+
'ios/Flutter/AppFrameworkInfo.plist',
1956+
],
1957+
unexpectedPaths: <String>['test'],
1958+
);
1959+
expect(projectDir.childDirectory('lib').childFile('main.dart').readAsStringSync(),
1960+
contains("Text('Hello World!')"));
1961+
expect(projectDir.childDirectory('lib').childFile('main.dart').readAsStringSync(),
1962+
isNot(contains('int _counter')));
1963+
expect(projectDir.childFile('analysis_options.yaml').readAsStringSync(),
1964+
isNot(contains('#')));
1965+
expect(projectDir.childFile('README.md').readAsStringSync(),
1966+
isNot(contains('Getting Started')));
1967+
});
1968+
19471969
testUsingContext('can create a sample-based project', () async {
19481970
await _createAndAnalyzeProject(
19491971
projectDir,

0 commit comments

Comments
 (0)