Unverified Commit 5259e1bc authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add --empty to the flutter create command (#113873)

parent 3c2f500b
...@@ -65,6 +65,12 @@ class CreateCommand extends CreateBase { ...@@ -65,6 +65,12 @@ class CreateCommand extends CreateBase {
'https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html', 'https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html',
valueHelp: 'id', valueHelp: 'id',
); );
argParser.addFlag(
'empty',
abbr: 'e',
help: 'Specifies creating using an application template with a main.dart that is minimal, '
'including no comments, as a starting point for a new application. Implies "--template=app".',
);
argParser.addOption( argParser.addOption(
'list-samples', 'list-samples',
help: 'Specifies a JSON output file for a listing of Flutter code samples ' help: 'Specifies a JSON output file for a listing of Flutter code samples '
...@@ -191,9 +197,17 @@ class CreateCommand extends CreateBase { ...@@ -191,9 +197,17 @@ class CreateCommand extends CreateBase {
return FlutterCommandResult.success(); return FlutterCommandResult.success();
} }
if (argResults!.wasParsed('empty') && argResults!.wasParsed('sample')) {
throwToolExit(
'Only one of --empty or --sample may be specified, not both.',
exitCode: 2,
);
}
validateOutputDirectoryArg(); validateOutputDirectoryArg();
String? sampleCode; String? sampleCode;
final String? sampleArgument = stringArg('sample'); final String? sampleArgument = stringArg('sample');
final bool emptyArgument = boolArg('empty') ?? false;
if (sampleArgument != null) { if (sampleArgument != null) {
final String? templateArgument = stringArg('template'); final String? templateArgument = stringArg('template');
if (templateArgument != null && stringToProjectType(templateArgument) != FlutterProjectType.app) { if (templateArgument != null && stringToProjectType(templateArgument) != FlutterProjectType.app) {
...@@ -299,6 +313,7 @@ class CreateCommand extends CreateBase { ...@@ -299,6 +313,7 @@ class CreateCommand extends CreateBase {
flutterRoot: flutterRoot, flutterRoot: flutterRoot,
withPlatformChannelPluginHook: generateMethodChannelsPlugin, withPlatformChannelPluginHook: generateMethodChannelsPlugin,
withFfiPluginHook: generateFfiPlugin, withFfiPluginHook: generateFfiPlugin,
withEmptyMain: emptyArgument,
androidLanguage: stringArgDeprecated('android-language'), androidLanguage: stringArgDeprecated('android-language'),
iosLanguage: stringArgDeprecated('ios-language'), iosLanguage: stringArgDeprecated('ios-language'),
iosDevelopmentTeam: developmentTeam, iosDevelopmentTeam: developmentTeam,
...@@ -411,11 +426,15 @@ class CreateCommand extends CreateBase { ...@@ -411,11 +426,15 @@ class CreateCommand extends CreateBase {
); );
} }
if (sampleCode != null) { if (sampleCode != null) {
generatedFileCount += _applySample(relativeDir, sampleCode); _applySample(relativeDir, sampleCode);
}
if (sampleCode != null || emptyArgument) {
generatedFileCount += _removeTestDir(relativeDir);
} }
globals.printStatus('Wrote $generatedFileCount files.'); globals.printStatus('Wrote $generatedFileCount files.');
globals.printStatus('\nAll done!'); globals.printStatus('\nAll done!');
final String application = sampleCode != null ? 'sample application' : 'application'; final String application =
'${emptyArgument ? 'empty' : ''}${sampleCode != null ? 'sample' : ''} application';
if (generatePackage) { if (generatePackage) {
final String relativeMainPath = globals.fs.path.normalize(globals.fs.path.join( final String relativeMainPath = globals.fs.path.normalize(globals.fs.path.join(
relativeDirPath, relativeDirPath,
...@@ -657,10 +676,13 @@ Your $application code is in $relativeAppMain. ...@@ -657,10 +676,13 @@ Your $application code is in $relativeAppMain.
// documentation website in sampleCode. Returns the difference in the number // documentation website in sampleCode. Returns the difference in the number
// of files after applying the sample, since it also deletes the application's // of files after applying the sample, since it also deletes the application's
// test directory (since the template's test doesn't apply to the sample). // test directory (since the template's test doesn't apply to the sample).
int _applySample(Directory directory, String sampleCode) { void _applySample(Directory directory, String sampleCode) {
final File mainDartFile = directory.childDirectory('lib').childFile('main.dart'); final File mainDartFile = directory.childDirectory('lib').childFile('main.dart');
mainDartFile.createSync(recursive: true); mainDartFile.createSync(recursive: true);
mainDartFile.writeAsStringSync(sampleCode); mainDartFile.writeAsStringSync(sampleCode);
}
int _removeTestDir(Directory directory) {
final Directory testDir = directory.childDirectory('test'); final Directory testDir = directory.childDirectory('test');
final List<FileSystemEntity> files = testDir.listSync(recursive: true); final List<FileSystemEntity> files = testDir.listSync(recursive: true);
testDir.deleteSync(recursive: true); testDir.deleteSync(recursive: true);
......
...@@ -354,6 +354,7 @@ abstract class CreateBase extends FlutterCommand { ...@@ -354,6 +354,7 @@ abstract class CreateBase extends FlutterCommand {
String? gradleVersion, String? gradleVersion,
bool withPlatformChannelPluginHook = false, bool withPlatformChannelPluginHook = false,
bool withFfiPluginHook = false, bool withFfiPluginHook = false,
bool withEmptyMain = false,
bool ios = false, bool ios = false,
bool android = false, bool android = false,
bool web = false, bool web = false,
...@@ -409,6 +410,7 @@ abstract class CreateBase extends FlutterCommand { ...@@ -409,6 +410,7 @@ abstract class CreateBase extends FlutterCommand {
'withFfiPluginHook': withFfiPluginHook, 'withFfiPluginHook': withFfiPluginHook,
'withPlatformChannelPluginHook': withPlatformChannelPluginHook, 'withPlatformChannelPluginHook': withPlatformChannelPluginHook,
'withPluginHook': withFfiPluginHook || withPlatformChannelPluginHook, 'withPluginHook': withFfiPluginHook || withPlatformChannelPluginHook,
'withEmptyMain': withEmptyMain,
'androidLanguage': androidLanguage, 'androidLanguage': androidLanguage,
'iosLanguage': iosLanguage, 'iosLanguage': iosLanguage,
'hasIosDevelopmentTeam': iosDevelopmentTeam != null && iosDevelopmentTeam.isNotEmpty, 'hasIosDevelopmentTeam': iosDevelopmentTeam != null && iosDevelopmentTeam.isNotEmpty,
......
# {{projectName}} # {{projectName}}
{{description}} {{description}}
{{^withEmptyMain}}
## Getting Started ## Getting Started
...@@ -14,3 +15,4 @@ A few resources to get you started if this is your first Flutter project: ...@@ -14,3 +15,4 @@ A few resources to get you started if this is your first Flutter project:
For help getting started with Flutter development, view the For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials, [online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference. samples, guidance on mobile development, and a full API reference.
{{/withEmptyMain}}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
{{#withEmptyMain}}
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('Hello World!'),
),
),
);
}
}
{{/withEmptyMain}}
{{^withEmptyMain}}
{{#withPlatformChannelPluginHook}} {{#withPlatformChannelPluginHook}}
import 'dart:async'; import 'dart:async';
...@@ -248,3 +270,4 @@ class _MyAppState extends State<MyApp> { ...@@ -248,3 +270,4 @@ class _MyAppState extends State<MyApp> {
} }
} }
{{/withFfiPluginHook}} {{/withFfiPluginHook}}
{{/withEmptyMain}}
name: {{projectName}} name: {{projectName}}
description: {{description}} description: {{description}}
{{#withEmptyMain}}
publish_to: 'none'
version: 0.1.0
environment:
sdk: {{dartSdkVersionBounds}}
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
{{/withEmptyMain}}
{{^withEmptyMain}}
# The following line prevents the package from being accidentally published to # The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages. # pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
...@@ -100,3 +119,4 @@ flutter: ...@@ -100,3 +119,4 @@ flutter:
# #
# For details regarding fonts from package dependencies, # For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages # see https://flutter.dev/custom-fonts/#from-packages
{{/withEmptyMain}}
{{^withEmptyMain}}
# This file configures the analyzer, which statically analyzes Dart code to # This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints. # check for errors, warnings, and lints.
# #
...@@ -7,7 +8,9 @@ ...@@ -7,7 +8,9 @@
# The following line activates a set of recommended lints for Flutter apps, # The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices. # packages, and plugins designed to encourage good coding practices.
{{/withEmptyMain}}
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
{{^withEmptyMain}}
linter: linter:
# The lint rules applied to this project can be customized in the # The lint rules applied to this project can be customized in the
...@@ -27,3 +30,4 @@ linter: ...@@ -27,3 +30,4 @@ linter:
# Additional information about this file can be found at # Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options # https://dart.dev/guides/language/analysis-options
{{/withEmptyMain}}
...@@ -1944,6 +1944,28 @@ void main() { ...@@ -1944,6 +1944,28 @@ void main() {
}, },
); );
testUsingContext('can create an empty application project', () async {
await _createAndAnalyzeProject(
projectDir,
<String>['--no-pub', '--empty'],
<String>[
'lib/main.dart',
'flutter_project.iml',
'android/app/src/main/AndroidManifest.xml',
'ios/Flutter/AppFrameworkInfo.plist',
],
unexpectedPaths: <String>['test'],
);
expect(projectDir.childDirectory('lib').childFile('main.dart').readAsStringSync(),
contains("Text('Hello World!')"));
expect(projectDir.childDirectory('lib').childFile('main.dart').readAsStringSync(),
isNot(contains('int _counter')));
expect(projectDir.childFile('analysis_options.yaml').readAsStringSync(),
isNot(contains('#')));
expect(projectDir.childFile('README.md').readAsStringSync(),
isNot(contains('Getting Started')));
});
testUsingContext('can create a sample-based project', () async { testUsingContext('can create a sample-based project', () async {
await _createAndAnalyzeProject( await _createAndAnalyzeProject(
projectDir, projectDir,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment