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: https://github.com/flutter/flutter/issues/115704 --------- Co-authored-by: Andrew Kolos <andrewrkolos@gmail.com>
This commit is contained in:
parent
3de19db7d4
commit
74669e4bf1
@ -43,6 +43,7 @@ import 'src/commands/symbolize.dart';
|
||||
import 'src/commands/test.dart';
|
||||
import 'src/commands/update_packages.dart';
|
||||
import 'src/commands/upgrade.dart';
|
||||
import 'src/commands/widget_preview.dart';
|
||||
import 'src/devtools_launcher.dart';
|
||||
import 'src/features.dart';
|
||||
import 'src/globals.dart' as globals;
|
||||
@ -250,6 +251,7 @@ List<FlutterCommand> generateCommands({
|
||||
verbose: verbose,
|
||||
nativeAssetsBuilder: globals.nativeAssetsBuilder,
|
||||
),
|
||||
WidgetPreviewCommand(),
|
||||
UpgradeCommand(verboseHelp: verboseHelp),
|
||||
SymbolizeCommand(
|
||||
stdio: globals.stdio,
|
||||
|
@ -488,7 +488,7 @@ class Environment {
|
||||
/// The path to the package configuration file to use for compilation.
|
||||
///
|
||||
/// This is used by package:package_config to locate the actual package_config.json
|
||||
/// file. If not provided, defaults to `.dart_tool/package_config.json`.
|
||||
/// file. If not provided in tests, defaults to `.dart_tool/package_config.json`.
|
||||
final String packageConfigPath;
|
||||
|
||||
/// The `BUILD_DIR` environment variable.
|
||||
|
@ -35,10 +35,73 @@ const String kPlatformHelp =
|
||||
'When adding platforms to a plugin project, the pubspec.yaml will be updated with the requested platform. '
|
||||
'Adding desktop platforms requires the corresponding desktop config setting to be enabled.';
|
||||
|
||||
class CreateCommand extends CreateBase {
|
||||
CreateCommand({
|
||||
super.verboseHelp = false,
|
||||
}) {
|
||||
class CreateCommand extends FlutterCommand with CreateBase {
|
||||
CreateCommand({bool verboseHelp = false}) {
|
||||
addPubOptions();
|
||||
argParser.addFlag(
|
||||
'with-driver-test',
|
||||
help: '(deprecated) Historically, this added a flutter_driver dependency and generated a '
|
||||
'sample "flutter drive" test. Now it does nothing. Consider using the '
|
||||
'"integration_test" package: https://pub.dev/packages/integration_test',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addFlag(
|
||||
'overwrite',
|
||||
help: 'When performing operations, overwrite existing files.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'description',
|
||||
defaultsTo: 'A new Flutter project.',
|
||||
help:
|
||||
'The description to use for your new Flutter project. This string ends up in the pubspec.yaml file.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'org',
|
||||
defaultsTo: 'com.example',
|
||||
help:
|
||||
'The organization responsible for your new Flutter project, in reverse domain name notation. '
|
||||
'This string is used in Java package names and as prefix in the iOS bundle identifier.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'project-name',
|
||||
help:
|
||||
'The project name for this new Flutter project. This must be a valid dart package name.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'ios-language',
|
||||
abbr: 'i',
|
||||
defaultsTo: 'swift',
|
||||
allowed: <String>['objc', 'swift'],
|
||||
help: '(deprecated) The language to use for iOS-specific code, either Swift (recommended) or Objective-C (legacy).',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addOption(
|
||||
'android-language',
|
||||
abbr: 'a',
|
||||
defaultsTo: 'kotlin',
|
||||
allowed: <String>['java', 'kotlin'],
|
||||
help: 'The language to use for Android-specific code, either Kotlin (recommended) or Java (legacy).',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'skip-name-checks',
|
||||
help:
|
||||
'Allow the creation of applications and plugins with invalid names. '
|
||||
'This is only intended to enable testing of the tool itself.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addFlag(
|
||||
'implementation-tests',
|
||||
help:
|
||||
'Include implementation tests that verify the template functions correctly. '
|
||||
'This is only intended to enable testing of the tool itself.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addOption(
|
||||
'initial-create-revision',
|
||||
help: 'The Flutter SDK git commit hash to store in .migrate_config. This parameter is used by the tool '
|
||||
'internally and should generally not be used manually.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
addPlatformsOptions(customHelp: kPlatformHelp);
|
||||
argParser.addOption(
|
||||
'template',
|
||||
@ -437,12 +500,12 @@ class CreateCommand extends CreateBase {
|
||||
pubContext = PubContext.createPackage;
|
||||
}
|
||||
|
||||
if (boolArg('pub')) {
|
||||
if (shouldCallPubGet) {
|
||||
final FlutterProject project = FlutterProject.fromDirectory(relativeDir);
|
||||
await pub.get(
|
||||
context: pubContext,
|
||||
project: project,
|
||||
offline: boolArg('offline'),
|
||||
offline: offline,
|
||||
outputMode: PubOutputMode.summaryOnly,
|
||||
);
|
||||
// Setting `includeIos` etc to false as with FlutterProjectType.package
|
||||
|
@ -48,96 +48,15 @@ const String _kDefaultPlatformArgumentHelp =
|
||||
'Platform folders (e.g. android/) will be generated in the target project. '
|
||||
'Adding desktop platforms requires the corresponding desktop config setting to be enabled.';
|
||||
|
||||
/// Common behavior for `flutter create` commands.
|
||||
abstract class CreateBase extends FlutterCommand {
|
||||
CreateBase({
|
||||
required bool verboseHelp,
|
||||
}) {
|
||||
argParser.addFlag(
|
||||
'pub',
|
||||
defaultsTo: true,
|
||||
help:
|
||||
'Whether to run "flutter pub get" after the project has been created.',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'offline',
|
||||
help:
|
||||
'When "flutter pub get" is run by the create command, this indicates '
|
||||
'whether to run it in offline mode or not. In offline mode, it will need to '
|
||||
'have all dependencies already available in the pub cache to succeed.',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'with-driver-test',
|
||||
help: '(deprecated) Historically, this added a flutter_driver dependency and generated a '
|
||||
'sample "flutter drive" test. Now it does nothing. Consider using the '
|
||||
'"integration_test" package: https://pub.dev/packages/integration_test',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addFlag(
|
||||
'overwrite',
|
||||
help: 'When performing operations, overwrite existing files.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'description',
|
||||
defaultsTo: 'A new Flutter project.',
|
||||
help:
|
||||
'The description to use for your new Flutter project. This string ends up in the pubspec.yaml file.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'org',
|
||||
defaultsTo: 'com.example',
|
||||
help:
|
||||
'The organization responsible for your new Flutter project, in reverse domain name notation. '
|
||||
'This string is used in Java package names and as prefix in the iOS bundle identifier.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'project-name',
|
||||
help:
|
||||
'The project name for this new Flutter project. This must be a valid dart package name.',
|
||||
);
|
||||
argParser.addOption(
|
||||
'ios-language',
|
||||
abbr: 'i',
|
||||
defaultsTo: 'swift',
|
||||
allowed: <String>['objc', 'swift'],
|
||||
help: '(deprecated) The language to use for iOS-specific code, either Swift (recommended) or Objective-C (legacy).',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addOption(
|
||||
'android-language',
|
||||
abbr: 'a',
|
||||
defaultsTo: 'kotlin',
|
||||
allowed: <String>['java', 'kotlin'],
|
||||
help: 'The language to use for Android-specific code, either Kotlin (recommended) or Java (legacy).',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'skip-name-checks',
|
||||
help:
|
||||
'Allow the creation of applications and plugins with invalid names. '
|
||||
'This is only intended to enable testing of the tool itself.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addFlag(
|
||||
'implementation-tests',
|
||||
help:
|
||||
'Include implementation tests that verify the template functions correctly. '
|
||||
'This is only intended to enable testing of the tool itself.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addOption(
|
||||
'initial-create-revision',
|
||||
help: 'The Flutter SDK git commit hash to store in .migrate_config. This parameter is used by the tool '
|
||||
'internally and should generally not be used manually.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
}
|
||||
|
||||
/// Common behavior for `flutter create` and `flutter widget-preview start` commands.
|
||||
mixin CreateBase on FlutterCommand {
|
||||
/// Pattern for a Windows file system drive (e.g. "D:").
|
||||
///
|
||||
/// `dart:io` does not recognize strings matching this pattern as absolute
|
||||
/// paths, as they have no top level back-slash; however, users often specify
|
||||
/// this
|
||||
@visibleForTesting
|
||||
@protected
|
||||
static final RegExp kWindowsDrivePattern = RegExp(r'^[a-zA-Z]:$');
|
||||
|
||||
/// The output directory of the command.
|
||||
@ -162,6 +81,35 @@ abstract class CreateBase extends FlutterCommand {
|
||||
return globals.fs.path.normalize(projectDir.absolute.path);
|
||||
}
|
||||
|
||||
@protected
|
||||
bool get shouldCallPubGet {
|
||||
return boolArg('pub');
|
||||
}
|
||||
|
||||
@protected
|
||||
bool get offline {
|
||||
return boolArg('offline');
|
||||
}
|
||||
|
||||
/// Adds `--pub` and `--offline` options.
|
||||
@protected
|
||||
void addPubOptions() {
|
||||
argParser
|
||||
..addFlag(
|
||||
'pub',
|
||||
defaultsTo: true,
|
||||
help:
|
||||
'Whether to run "flutter pub get" after the project has been created.',
|
||||
)
|
||||
..addFlag(
|
||||
'offline',
|
||||
help:
|
||||
'When "flutter pub get" is run by the create command, this indicates '
|
||||
'whether to run it in offline mode or not. In offline mode, it will need to '
|
||||
'have all dependencies already available in the pub cache to succeed.',
|
||||
);
|
||||
}
|
||||
|
||||
/// Adds a `--platforms` argument.
|
||||
///
|
||||
/// The help message of the argument is replaced with `customHelp` if `customHelp` is not null.
|
||||
@ -558,7 +506,7 @@ abstract class CreateBase extends FlutterCommand {
|
||||
final bool windowsPlatform = templateContext['windows'] as bool? ?? false;
|
||||
final bool webPlatform = templateContext['web'] as bool? ?? false;
|
||||
|
||||
if (boolArg('pub')) {
|
||||
if (shouldCallPubGet) {
|
||||
final Environment environment = Environment(
|
||||
artifacts: globals.artifacts!,
|
||||
logger: globals.logger,
|
||||
|
149
packages/flutter_tools/lib/src/commands/widget_preview.dart
Normal file
149
packages/flutter_tools/lib/src/commands/widget_preview.dart
Normal file
@ -0,0 +1,149 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:args/args.dart';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../cache.dart';
|
||||
import '../dart/pub.dart';
|
||||
import '../globals.dart' as globals;
|
||||
import '../project.dart';
|
||||
import '../runner/flutter_command.dart';
|
||||
import 'create_base.dart';
|
||||
|
||||
class WidgetPreviewCommand extends FlutterCommand {
|
||||
WidgetPreviewCommand() {
|
||||
addSubcommand(WidgetPreviewStartCommand());
|
||||
addSubcommand(WidgetPreviewCleanCommand());
|
||||
}
|
||||
|
||||
@override
|
||||
String get description => 'Manage the widget preview environment.';
|
||||
|
||||
@override
|
||||
String get name => 'widget-preview';
|
||||
|
||||
@override
|
||||
String get category => FlutterCommandCategory.tools;
|
||||
|
||||
// TODO(bkonyi): show when --verbose is not provided when this feature is
|
||||
// ready to ship.
|
||||
@override
|
||||
bool get hidden => true;
|
||||
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async =>
|
||||
FlutterCommandResult.fail();
|
||||
}
|
||||
|
||||
/// Common utilities for the 'start' and 'clean' commands.
|
||||
mixin WidgetPreviewSubCommandMixin on FlutterCommand {
|
||||
FlutterProject getRootProject() {
|
||||
final ArgResults results = argResults!;
|
||||
final Directory projectDir;
|
||||
if (results.rest case <String>[final String directory]) {
|
||||
projectDir = globals.fs.directory(directory);
|
||||
if (!projectDir.existsSync()) {
|
||||
throwToolExit('Could not find ${projectDir.path}.');
|
||||
}
|
||||
} else if (results.rest.length > 1) {
|
||||
throwToolExit('Only one directory should be provided.');
|
||||
} else {
|
||||
projectDir = globals.fs.currentDirectory;
|
||||
}
|
||||
return validateFlutterProjectForPreview(projectDir);
|
||||
}
|
||||
|
||||
FlutterProject validateFlutterProjectForPreview(Directory directory) {
|
||||
globals.logger
|
||||
.printTrace('Verifying that ${directory.path} is a Flutter project.');
|
||||
final FlutterProject flutterProject =
|
||||
globals.projectFactory.fromDirectory(directory);
|
||||
if (!flutterProject.dartTool.existsSync()) {
|
||||
throwToolExit(
|
||||
'${flutterProject.directory.path} is not a valid Flutter project.',
|
||||
);
|
||||
}
|
||||
return flutterProject;
|
||||
}
|
||||
}
|
||||
|
||||
class WidgetPreviewStartCommand extends FlutterCommand
|
||||
with CreateBase, WidgetPreviewSubCommandMixin {
|
||||
WidgetPreviewStartCommand() {
|
||||
addPubOptions();
|
||||
}
|
||||
|
||||
@override
|
||||
String get description => 'Starts the widget preview environment.';
|
||||
|
||||
@override
|
||||
String get name => 'start';
|
||||
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
final FlutterProject rootProject = getRootProject();
|
||||
|
||||
// Check to see if a preview scaffold has already been generated. If not,
|
||||
// generate one.
|
||||
if (!rootProject.widgetPreviewScaffold.existsSync()) {
|
||||
globals.logger.printStatus(
|
||||
'Creating widget preview scaffolding at: ${rootProject.widgetPreviewScaffold.path}',
|
||||
);
|
||||
await generateApp(
|
||||
<String>['widget_preview_scaffold'],
|
||||
rootProject.widgetPreviewScaffold,
|
||||
createTemplateContext(
|
||||
organization: 'flutter',
|
||||
projectName: 'widget_preview_scaffold',
|
||||
titleCaseProjectName: 'Widget Preview Scaffold',
|
||||
flutterRoot: Cache.flutterRoot!,
|
||||
dartSdkVersionBounds: '^${globals.cache.dartSdkBuild}',
|
||||
linux: const LocalPlatform().isLinux,
|
||||
macos: const LocalPlatform().isMacOS,
|
||||
windows: const LocalPlatform().isWindows,
|
||||
),
|
||||
overwrite: true,
|
||||
generateMetadata: false,
|
||||
);
|
||||
|
||||
if (shouldCallPubGet) {
|
||||
await pub.get(
|
||||
context: PubContext.create,
|
||||
project: rootProject.widgetPreviewScaffoldProject,
|
||||
offline: offline,
|
||||
outputMode: PubOutputMode.summaryOnly,
|
||||
);
|
||||
}
|
||||
}
|
||||
return FlutterCommandResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
class WidgetPreviewCleanCommand extends FlutterCommand
|
||||
with WidgetPreviewSubCommandMixin {
|
||||
@override
|
||||
String get description => 'Cleans up widget preview state.';
|
||||
|
||||
@override
|
||||
String get name => 'clean';
|
||||
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
final Directory widgetPreviewScaffold =
|
||||
getRootProject().widgetPreviewScaffold;
|
||||
if (widgetPreviewScaffold.existsSync()) {
|
||||
final String scaffoldPath = widgetPreviewScaffold.path;
|
||||
globals.logger.printStatus(
|
||||
'Deleting widget preview scaffold at $scaffoldPath.',
|
||||
);
|
||||
widgetPreviewScaffold.deleteSync(recursive: true);
|
||||
} else {
|
||||
globals.logger.printStatus('Nothing to clean up.');
|
||||
}
|
||||
return FlutterCommandResult.success();
|
||||
}
|
||||
}
|
@ -229,6 +229,10 @@ class FlutterProject {
|
||||
/// The `.dart-tool` directory of this project.
|
||||
Directory get dartTool => directory.childDirectory('.dart_tool');
|
||||
|
||||
/// The location of the generated scaffolding project for hosting widget
|
||||
/// previews from this project.
|
||||
Directory get widgetPreviewScaffold => dartTool.childDirectory('widget_preview_scaffold');
|
||||
|
||||
/// The directory containing the generated code for this project.
|
||||
Directory get generated => directory
|
||||
.absolute
|
||||
@ -249,6 +253,12 @@ class FlutterProject {
|
||||
FlutterManifest.empty(logger: globals.logger),
|
||||
);
|
||||
|
||||
/// The generated scaffolding project for hosting widget previews from this
|
||||
/// project.
|
||||
FlutterProject get widgetPreviewScaffoldProject => FlutterProject.fromDirectory(
|
||||
widgetPreviewScaffold,
|
||||
);
|
||||
|
||||
/// True if this project is a Flutter module project.
|
||||
bool get isModule => manifest.isModule;
|
||||
|
||||
|
@ -372,6 +372,10 @@
|
||||
"templates/skeleton/test/unit_test.dart.tmpl",
|
||||
"templates/skeleton/test/widget_test.dart.tmpl",
|
||||
|
||||
"templates/widget_preview_scaffold/lib/main.dart.tmpl",
|
||||
"templates/widget_preview_scaffold/pubspec.yaml.tmpl",
|
||||
"templates/widget_preview_scaffold/README.md.tmpl",
|
||||
|
||||
"templates/xcode/ios/custom_application_bundle/Runner.xcworkspace.tmpl/contents.xcworkspacedata",
|
||||
"templates/xcode/ios/custom_application_bundle/Runner.xcworkspace.tmpl/xcshareddata/IDEWorkspaceChecks.plist",
|
||||
"templates/xcode/ios/custom_application_bundle/Runner.xcworkspace.tmpl/xcshareddata/WorkspaceSettings.xcsettings",
|
||||
|
@ -0,0 +1,4 @@
|
||||
# {{titleCaseProjectName}}
|
||||
|
||||
This project is generated by `flutter widget-preview` and is used to host Widgets
|
||||
to be previewed in the widget previewer.
|
@ -0,0 +1,7 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
Future<void> main() async {
|
||||
// TODO(bkonyi): implement.
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
name: {{projectName}}
|
||||
description: Scaffolding for Flutter Widget Previews
|
||||
publish_to: 'none'
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
sdk: {{dartSdkVersionBounds}}
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
@ -29,7 +29,6 @@ import 'package:flutter_tools/src/flutter_project_metadata.dart' show FlutterPro
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:flutter_tools/src/version.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:pubspec_parse/pubspec_parse.dart';
|
||||
import 'package:unified_analytics/unified_analytics.dart';
|
||||
@ -42,6 +41,7 @@ import '../../src/fake_http_client.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/pubspec_schema.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import 'utils/project_testing_utils.dart';
|
||||
|
||||
const String _kNoPlatformsMessage = "You've created a plugin project that doesn't yet support any platforms.\n";
|
||||
const String frameworkRevision = '12345678';
|
||||
@ -84,7 +84,7 @@ void main() {
|
||||
|
||||
setUpAll(() async {
|
||||
Cache.disableLocking();
|
||||
await _ensureFlutterToolsSnapshot();
|
||||
await ensureFlutterToolsSnapshot();
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
@ -109,7 +109,7 @@ void main() {
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
await _restoreFlutterToolsSnapshot();
|
||||
await restoreFlutterToolsSnapshot();
|
||||
});
|
||||
|
||||
test('createAndroidIdentifier emits a valid identifier', () {
|
||||
@ -2472,7 +2472,7 @@ void main() {
|
||||
await runner.run(<String>['create', '--no-pub', '--template=plugin', projectDir.path]);
|
||||
|
||||
await _getPackages(projectDir);
|
||||
await _analyzeProject(projectDir.path);
|
||||
await analyzeProject(projectDir.path);
|
||||
await _runFlutterTest(projectDir);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(),
|
||||
@ -2489,7 +2489,7 @@ void main() {
|
||||
final Directory exampleDir = projectDir.childDirectory('example');
|
||||
|
||||
await _getPackages(exampleDir);
|
||||
await _analyzeProject(exampleDir.path);
|
||||
await analyzeProject(exampleDir.path);
|
||||
await _runFlutterTest(exampleDir);
|
||||
});
|
||||
|
||||
@ -2554,7 +2554,7 @@ void main() {
|
||||
expect(logger.errorText, isNot(contains(_kNoPlatformsMessage)));
|
||||
|
||||
await _getPackages(projectDir);
|
||||
await _analyzeProject(projectDir.path);
|
||||
await analyzeProject(projectDir.path);
|
||||
await _runFlutterTest(projectDir);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
|
||||
@ -3603,7 +3603,7 @@ void main() {
|
||||
'$relativePath:31:26: use_full_hex_values_for_flutter_colors',
|
||||
];
|
||||
expect(expectedFailures.length, '// LINT:'.allMatches(toAnalyze.readAsStringSync()).length);
|
||||
await _analyzeProject(
|
||||
await analyzeProject(
|
||||
projectDir.path,
|
||||
expectedFailures: expectedFailures,
|
||||
);
|
||||
@ -4116,122 +4116,7 @@ Future<void> _createAndAnalyzeProject(
|
||||
unexpectedPaths: unexpectedPaths,
|
||||
expectedGitignoreLines: expectedGitignoreLines,
|
||||
);
|
||||
await _analyzeProject(dir.path);
|
||||
}
|
||||
|
||||
Future<void> _ensureFlutterToolsSnapshot() async {
|
||||
final String flutterToolsPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'bin',
|
||||
'flutter_tools.dart',
|
||||
));
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
));
|
||||
final String packageConfig = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'.dart_tool',
|
||||
'package_config.json'
|
||||
));
|
||||
|
||||
final File snapshotFile = globals.fs.file(flutterToolsSnapshotPath);
|
||||
if (snapshotFile.existsSync()) {
|
||||
snapshotFile.renameSync('$flutterToolsSnapshotPath.bak');
|
||||
}
|
||||
|
||||
final List<String> snapshotArgs = <String>[
|
||||
'--snapshot=$flutterToolsSnapshotPath',
|
||||
'--packages=$packageConfig',
|
||||
flutterToolsPath,
|
||||
];
|
||||
final ProcessResult snapshotResult = await Process.run(
|
||||
'../../bin/cache/dart-sdk/bin/dart',
|
||||
snapshotArgs,
|
||||
);
|
||||
printOnFailure('Results of generating snapshot:');
|
||||
printOnFailure(snapshotResult.stdout.toString());
|
||||
printOnFailure(snapshotResult.stderr.toString());
|
||||
expect(snapshotResult.exitCode, 0);
|
||||
}
|
||||
|
||||
Future<void> _restoreFlutterToolsSnapshot() async {
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
));
|
||||
|
||||
final File snapshotBackup = globals.fs.file('$flutterToolsSnapshotPath.bak');
|
||||
if (!snapshotBackup.existsSync()) {
|
||||
// No backup to restore.
|
||||
return;
|
||||
}
|
||||
|
||||
snapshotBackup.renameSync(flutterToolsSnapshotPath);
|
||||
}
|
||||
|
||||
Future<void> _analyzeProject(String workingDir, { List<String> expectedFailures = const <String>[] }) async {
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
));
|
||||
|
||||
final List<String> args = <String>[
|
||||
flutterToolsSnapshotPath,
|
||||
'analyze',
|
||||
];
|
||||
|
||||
final ProcessResult exec = await Process.run(
|
||||
globals.artifacts!.getArtifactPath(Artifact.engineDartBinary),
|
||||
args,
|
||||
workingDirectory: workingDir,
|
||||
);
|
||||
if (expectedFailures.isEmpty) {
|
||||
printOnFailure('Results of running analyzer:');
|
||||
printOnFailure(exec.stdout.toString());
|
||||
printOnFailure(exec.stderr.toString());
|
||||
expect(exec.exitCode, 0);
|
||||
return;
|
||||
}
|
||||
expect(exec.exitCode, isNot(0));
|
||||
String lineParser(String line) {
|
||||
try {
|
||||
final String analyzerSeparator = globals.platform.isWindows ? ' - ' : ' • ';
|
||||
final List<String> lineComponents = line.trim().split(analyzerSeparator);
|
||||
final String lintName = lineComponents.removeLast();
|
||||
final String location = lineComponents.removeLast();
|
||||
return '$location: $lintName';
|
||||
} on RangeError catch (err) {
|
||||
throw RangeError('Received "$err" while trying to parse: "$line".');
|
||||
}
|
||||
}
|
||||
final String stdout = exec.stdout.toString();
|
||||
final List<String> errors = <String>[];
|
||||
try {
|
||||
bool analyzeLineFound = false;
|
||||
const LineSplitter().convert(stdout).forEach((String line) {
|
||||
// Conditional to filter out any stdout from `pub get`
|
||||
if (!analyzeLineFound && line.startsWith('Analyzing')) {
|
||||
analyzeLineFound = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (analyzeLineFound && line.trim().isNotEmpty) {
|
||||
errors.add(lineParser(line.trim()));
|
||||
}
|
||||
});
|
||||
} on Exception catch (err) {
|
||||
fail('$err\n\nComplete STDOUT was:\n\n$stdout');
|
||||
}
|
||||
expect(errors, unorderedEquals(expectedFailures),
|
||||
reason: 'Failed with stdout:\n\n$stdout');
|
||||
await analyzeProject(dir.path);
|
||||
}
|
||||
|
||||
Future<void> _getPackages(Directory workingDir) async {
|
||||
@ -4285,35 +4170,7 @@ Future<void> _runFlutterTest(Directory workingDir, { String? target }) async {
|
||||
expect(exec.exitCode, 0);
|
||||
}
|
||||
|
||||
/// A ProcessManager that invokes a real process manager, but keeps
|
||||
/// track of all commands sent to it.
|
||||
class LoggingProcessManager extends LocalProcessManager {
|
||||
List<List<String>> commands = <List<String>>[];
|
||||
|
||||
@override
|
||||
Future<Process> start(
|
||||
List<Object> command, {
|
||||
String? workingDirectory,
|
||||
Map<String, String>? environment,
|
||||
bool includeParentEnvironment = true,
|
||||
bool runInShell = false,
|
||||
ProcessStartMode mode = ProcessStartMode.normal,
|
||||
}) {
|
||||
commands.add(command.map((Object arg) => arg.toString()).toList());
|
||||
return super.start(
|
||||
command,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: environment,
|
||||
includeParentEnvironment: includeParentEnvironment,
|
||||
runInShell: runInShell,
|
||||
mode: mode,
|
||||
);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
commands.clear();
|
||||
}
|
||||
}
|
||||
|
||||
String _getStringValueFromPlist({required File plistFile, String? key}) {
|
||||
final List<String> plist = plistFile.readAsLinesSync().map((String line) => line.trim()).toList();
|
||||
|
@ -0,0 +1,159 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:process/process.dart';
|
||||
|
||||
import '../../../src/test_flutter_command_runner.dart';
|
||||
|
||||
/// A ProcessManager that invokes a real process manager, but keeps
|
||||
/// track of all commands sent to it.
|
||||
class LoggingProcessManager extends LocalProcessManager {
|
||||
List<List<String>> commands = <List<String>>[];
|
||||
|
||||
@override
|
||||
Future<Process> start(
|
||||
List<Object> command, {
|
||||
String? workingDirectory,
|
||||
Map<String, String>? environment,
|
||||
bool includeParentEnvironment = true,
|
||||
bool runInShell = false,
|
||||
ProcessStartMode mode = ProcessStartMode.normal,
|
||||
}) {
|
||||
commands.add(command.map((Object arg) => arg.toString()).toList());
|
||||
return super.start(
|
||||
command,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: environment,
|
||||
includeParentEnvironment: includeParentEnvironment,
|
||||
runInShell: runInShell,
|
||||
mode: mode,
|
||||
);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
commands.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> analyzeProject(String workingDir, { List<String> expectedFailures = const <String>[] }) async {
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
));
|
||||
|
||||
final List<String> args = <String>[
|
||||
flutterToolsSnapshotPath,
|
||||
'analyze',
|
||||
];
|
||||
|
||||
final ProcessResult exec = await Process.run(
|
||||
globals.artifacts!.getArtifactPath(Artifact.engineDartBinary),
|
||||
args,
|
||||
workingDirectory: workingDir,
|
||||
);
|
||||
if (expectedFailures.isEmpty) {
|
||||
printOnFailure('Results of running analyzer:');
|
||||
printOnFailure(exec.stdout.toString());
|
||||
printOnFailure(exec.stderr.toString());
|
||||
expect(exec.exitCode, 0);
|
||||
return;
|
||||
}
|
||||
expect(exec.exitCode, isNot(0));
|
||||
String lineParser(String line) {
|
||||
try {
|
||||
final String analyzerSeparator = globals.platform.isWindows ? ' - ' : ' • ';
|
||||
final List<String> lineComponents = line.trim().split(analyzerSeparator);
|
||||
final String lintName = lineComponents.removeLast();
|
||||
final String location = lineComponents.removeLast();
|
||||
return '$location: $lintName';
|
||||
} on RangeError catch (err) {
|
||||
throw RangeError('Received "$err" while trying to parse: "$line".');
|
||||
}
|
||||
}
|
||||
final String stdout = exec.stdout.toString();
|
||||
final List<String> errors = <String>[];
|
||||
try {
|
||||
bool analyzeLineFound = false;
|
||||
const LineSplitter().convert(stdout).forEach((String line) {
|
||||
// Conditional to filter out any stdout from `pub get`
|
||||
if (!analyzeLineFound && line.startsWith('Analyzing')) {
|
||||
analyzeLineFound = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (analyzeLineFound && line.trim().isNotEmpty) {
|
||||
errors.add(lineParser(line.trim()));
|
||||
}
|
||||
});
|
||||
} on Exception catch (err) {
|
||||
fail('$err\n\nComplete STDOUT was:\n\n$stdout');
|
||||
}
|
||||
expect(errors, unorderedEquals(expectedFailures),
|
||||
reason: 'Failed with stdout:\n\n$stdout');
|
||||
}
|
||||
|
||||
|
||||
Future<void> ensureFlutterToolsSnapshot() async {
|
||||
final String flutterToolsPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'bin',
|
||||
'flutter_tools.dart',
|
||||
));
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
));
|
||||
final String packageConfig = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'.dart_tool',
|
||||
'package_config.json'
|
||||
));
|
||||
|
||||
final File snapshotFile = globals.fs.file(flutterToolsSnapshotPath);
|
||||
if (snapshotFile.existsSync()) {
|
||||
snapshotFile.renameSync('$flutterToolsSnapshotPath.bak');
|
||||
}
|
||||
|
||||
final List<String> snapshotArgs = <String>[
|
||||
'--snapshot=$flutterToolsSnapshotPath',
|
||||
'--packages=$packageConfig',
|
||||
flutterToolsPath,
|
||||
];
|
||||
final ProcessResult snapshotResult = await Process.run(
|
||||
'../../bin/cache/dart-sdk/bin/dart',
|
||||
snapshotArgs,
|
||||
);
|
||||
printOnFailure('Results of generating snapshot:');
|
||||
printOnFailure(snapshotResult.stdout.toString());
|
||||
printOnFailure(snapshotResult.stderr.toString());
|
||||
expect(snapshotResult.exitCode, 0);
|
||||
}
|
||||
|
||||
Future<void> restoreFlutterToolsSnapshot() async {
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
));
|
||||
|
||||
final File snapshotBackup = globals.fs.file('$flutterToolsSnapshotPath.bak');
|
||||
if (!snapshotBackup.existsSync()) {
|
||||
// No backup to restore.
|
||||
return;
|
||||
}
|
||||
|
||||
snapshotBackup.renameSync(flutterToolsSnapshotPath);
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:io' as io show IOOverrides;
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:file_testing/file_testing.dart';
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/commands/widget_preview.dart';
|
||||
import 'package:flutter_tools/src/dart/pub.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import 'utils/project_testing_utils.dart';
|
||||
|
||||
void main() {
|
||||
late Directory tempDir;
|
||||
late LoggingProcessManager loggingProcessManager;
|
||||
late FakeStdio mockStdio;
|
||||
|
||||
setUp(() {
|
||||
loggingProcessManager = LoggingProcessManager();
|
||||
tempDir = globals.fs.systemTempDirectory
|
||||
.createTempSync('flutter_tools_create_test.');
|
||||
mockStdio = FakeStdio();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
Future<String> createRootProject() async {
|
||||
return createProject(
|
||||
tempDir,
|
||||
arguments: <String>['--pub'],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> runWidgetPreviewCommand(List<String> arguments) async {
|
||||
final CommandRunner<void> runner = createTestCommandRunner(
|
||||
WidgetPreviewCommand(),
|
||||
);
|
||||
await runner.run(<String>['widget-preview', ...arguments]);
|
||||
}
|
||||
|
||||
Future<void> startWidgetPreview({
|
||||
required String? rootProjectPath,
|
||||
List<String>? arguments,
|
||||
}) async {
|
||||
await runWidgetPreviewCommand(
|
||||
<String>[
|
||||
'start',
|
||||
...?arguments,
|
||||
if (rootProjectPath != null) rootProjectPath,
|
||||
],
|
||||
);
|
||||
expect(
|
||||
globals.fs
|
||||
.directory(rootProjectPath ?? globals.fs.currentDirectory.path)
|
||||
.childDirectory('.dart_tool')
|
||||
.childDirectory('widget_preview_scaffold'),
|
||||
exists,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> cleanWidgetPreview({
|
||||
required String rootProjectPath,
|
||||
}) async {
|
||||
await runWidgetPreviewCommand(<String>['clean', rootProjectPath]);
|
||||
expect(
|
||||
globals.fs
|
||||
.directory(rootProjectPath)
|
||||
.childDirectory('.dart_tool')
|
||||
.childDirectory('widget_preview_scaffold'),
|
||||
isNot(exists),
|
||||
);
|
||||
}
|
||||
|
||||
group('flutter widget-preview', () {
|
||||
group('start exits if', () {
|
||||
testUsingContext(
|
||||
'given an invalid directory',
|
||||
() async {
|
||||
try {
|
||||
await runWidgetPreviewCommand(
|
||||
<String>[
|
||||
'start',
|
||||
'foo',
|
||||
],
|
||||
);
|
||||
fail(
|
||||
'Successfully executed with multiple project paths',
|
||||
);
|
||||
} on ToolExit catch (e) {
|
||||
expect(
|
||||
e.message,
|
||||
contains(
|
||||
'Could not find foo',
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'more than one project directory is provided',
|
||||
() async {
|
||||
try {
|
||||
await runWidgetPreviewCommand(
|
||||
<String>[
|
||||
'start',
|
||||
tempDir.path,
|
||||
tempDir.path,
|
||||
],
|
||||
);
|
||||
fail(
|
||||
'Successfully executed with multiple project paths',
|
||||
);
|
||||
} on ToolExit catch (e) {
|
||||
expect(
|
||||
e.message,
|
||||
contains(
|
||||
'Only one directory should be provided.',
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'run outside of a Flutter project directory',
|
||||
() async {
|
||||
try {
|
||||
await startWidgetPreview(rootProjectPath: tempDir.path);
|
||||
fail(
|
||||
'Successfully executed outside of a Flutter project directory',
|
||||
);
|
||||
} on ToolExit catch (e) {
|
||||
expect(
|
||||
e.message,
|
||||
contains(
|
||||
'${tempDir.path} is not a valid Flutter project.',
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext(
|
||||
'start creates .dart_tool/widget_preview_scaffold',
|
||||
() async {
|
||||
final String rootProjectPath = await createRootProject();
|
||||
await startWidgetPreview(rootProjectPath: rootProjectPath);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
Pub: () => Pub.test(
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
processManager: globals.processManager,
|
||||
usage: globals.flutterUsage,
|
||||
botDetector: globals.botDetector,
|
||||
platform: globals.platform,
|
||||
stdio: mockStdio,
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'start creates .dart_tool/widget_preview_scaffold in the CWD',
|
||||
() async {
|
||||
final String rootProjectPath = await createRootProject();
|
||||
await io.IOOverrides.runZoned<Future<void>>(
|
||||
() async {
|
||||
// Try to execute using the CWD.
|
||||
await startWidgetPreview(rootProjectPath: null);
|
||||
},
|
||||
getCurrentDirectory: () => globals.fs.directory(rootProjectPath),
|
||||
);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
Pub: () => Pub.test(
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
processManager: globals.processManager,
|
||||
usage: globals.flutterUsage,
|
||||
botDetector: globals.botDetector,
|
||||
platform: globals.platform,
|
||||
stdio: mockStdio,
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'clean deletes .dart_tool/widget_preview_scaffold',
|
||||
() async {
|
||||
final String rootProjectPath = await createRootProject();
|
||||
await startWidgetPreview(rootProjectPath: rootProjectPath);
|
||||
await cleanWidgetPreview(rootProjectPath: rootProjectPath);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
Pub: () => Pub.test(
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
processManager: globals.processManager,
|
||||
usage: globals.flutterUsage,
|
||||
botDetector: globals.botDetector,
|
||||
platform: globals.platform,
|
||||
stdio: mockStdio,
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'invokes pub in online and offline modes',
|
||||
() async {
|
||||
// Run pub online first in order to populate the pub cache.
|
||||
final String rootProjectPath = await createRootProject();
|
||||
loggingProcessManager.clear();
|
||||
|
||||
final RegExp dartCommand = RegExp(r'dart-sdk[\\/]bin[\\/]dart');
|
||||
|
||||
await startWidgetPreview(rootProjectPath: rootProjectPath);
|
||||
expect(
|
||||
loggingProcessManager.commands,
|
||||
contains(
|
||||
predicate(
|
||||
(List<String> c) =>
|
||||
dartCommand.hasMatch(c[0]) &&
|
||||
c[1].contains('pub') &&
|
||||
!c.contains('--offline'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await cleanWidgetPreview(rootProjectPath: rootProjectPath);
|
||||
|
||||
// Run pub offline.
|
||||
loggingProcessManager.clear();
|
||||
await startWidgetPreview(
|
||||
rootProjectPath: rootProjectPath,
|
||||
arguments: <String>['--pub', '--offline'],
|
||||
);
|
||||
|
||||
expect(
|
||||
loggingProcessManager.commands,
|
||||
contains(
|
||||
predicate(
|
||||
(List<String> c) =>
|
||||
dartCommand.hasMatch(c[0]) &&
|
||||
c[1].contains('pub') &&
|
||||
c.contains('--offline'),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => loggingProcessManager,
|
||||
Pub: () => Pub.test(
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
processManager: globals.processManager,
|
||||
usage: globals.flutterUsage,
|
||||
botDetector: globals.botDetector,
|
||||
platform: globals.platform,
|
||||
stdio: mockStdio,
|
||||
),
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -15,6 +15,7 @@ import 'package:flutter_tools/src/commands/create.dart';
|
||||
import 'package:flutter_tools/src/dart/pub.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
|
||||
import '../commands.shard/permeable/utils/project_testing_utils.dart';
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/test_flutter_command_runner.dart';
|
||||
@ -26,7 +27,7 @@ void main() {
|
||||
|
||||
setUpAll(() async {
|
||||
Cache.disableLocking();
|
||||
await _ensureFlutterToolsSnapshot();
|
||||
await ensureFlutterToolsSnapshot();
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
@ -40,7 +41,7 @@ void main() {
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
await _restoreFlutterToolsSnapshot();
|
||||
await restoreFlutterToolsSnapshot();
|
||||
});
|
||||
|
||||
testUsingContext('generated plugin registrant passes analysis', () async {
|
||||
@ -241,65 +242,6 @@ void main() {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _ensureFlutterToolsSnapshot() async {
|
||||
final String flutterToolsPath = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'bin',
|
||||
'flutter_tools.dart',
|
||||
));
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(
|
||||
globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
),
|
||||
);
|
||||
final String dotPackages = globals.fs.path.absolute(globals.fs.path.join(
|
||||
'.dart_tool/package_config.json',
|
||||
));
|
||||
|
||||
final File snapshotFile = globals.fs.file(flutterToolsSnapshotPath);
|
||||
if (snapshotFile.existsSync()) {
|
||||
snapshotFile.renameSync('$flutterToolsSnapshotPath.bak');
|
||||
}
|
||||
|
||||
final List<String> snapshotArgs = <String>[
|
||||
'--snapshot=$flutterToolsSnapshotPath',
|
||||
'--packages=$dotPackages',
|
||||
flutterToolsPath,
|
||||
];
|
||||
final ProcessResult snapshotResult = await Process.run(
|
||||
'../../bin/cache/dart-sdk/bin/dart',
|
||||
snapshotArgs,
|
||||
);
|
||||
printOnFailure('Output of dart ${snapshotArgs.join(" ")}:');
|
||||
printOnFailure(snapshotResult.stdout.toString());
|
||||
printOnFailure(snapshotResult.stderr.toString());
|
||||
expect(snapshotResult, const ProcessResultMatcher());
|
||||
}
|
||||
|
||||
Future<void> _restoreFlutterToolsSnapshot() async {
|
||||
final String flutterToolsSnapshotPath = globals.fs.path.absolute(
|
||||
globals.fs.path.join(
|
||||
'..',
|
||||
'..',
|
||||
'bin',
|
||||
'cache',
|
||||
'flutter_tools.snapshot',
|
||||
),
|
||||
);
|
||||
|
||||
final File snapshotBackup =
|
||||
globals.fs.file('$flutterToolsSnapshotPath.bak');
|
||||
if (!snapshotBackup.existsSync()) {
|
||||
// No backup to restore.
|
||||
return;
|
||||
}
|
||||
|
||||
snapshotBackup.renameSync(flutterToolsSnapshotPath);
|
||||
}
|
||||
|
||||
Future<void> _createProject(Directory dir, List<String> createArgs) async {
|
||||
Cache.flutterRoot = '../..';
|
||||
final CreateCommand command = CreateCommand();
|
||||
|
Loading…
x
Reference in New Issue
Block a user