Plugin.isDevDependency if exclusively in dev_dependencies (#157462)

Work towards https://github.com/flutter/flutter/issues/56591.

I explicitly want an LGTM from @andrewkolos @jmagman @jonahwilliams before merging.

---

After this PR, `<Plugin>.isDevDependency` is resolved based on the following logic, IFF:

- The plugin comes from a package _A_ listed in the app's package's `dev_dependencies: ...`
- The package _A_ is not a normal dependency of any transitive non-dev dependency of the app

See [`compute_dev_dependencies_test.dart`](51676093a3/packages/flutter_tools/test/general.shard/compute_dev_dependencies_test.dart) for probably the best specification of this behavior.

We (still) do not write the property to disk (i.e. it never makes it to `.flutter-plugins-dependencies`), so there is no impact to build artifacts at this time; that would come in a follow-up PR (and then follow-up follow-up PRs for the various build systems in both Gradle and Xcode to actually use that value to omit dependencies).

Some tests had to be updated; for the most part it was updating the default `ProcessManager` because a call to `dart pub deps --json` is now made in code that computes what plugins are available, but there should be no change in behavior.

_/cc @jonasfj @sigurdm for FYI only (we talked on an internal thread about this; see https://github.com/dart-lang/sdk/issues/56968)._

_/cc @camsim99 @cbracken @johnmccutchan for visibility on the change._
This commit is contained in:
Matan Lurey 2024-11-07 10:09:22 -08:00 committed by GitHub
parent bd65732cd2
commit 78cfc1ae9b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 959 additions and 153 deletions

View File

@ -459,7 +459,7 @@ class CreateCommand extends CreateBase {
macOSPlatform: includeMacos, macOSPlatform: includeMacos,
windowsPlatform: includeWindows, windowsPlatform: includeWindows,
webPlatform: includeWeb, webPlatform: includeWeb,
writeLegacyPluginsList: boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true), useImplicitPubspecResolution: boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true),
); );
} }
} }

View File

@ -386,14 +386,14 @@ class PackagesGetCommand extends FlutterCommand {
if (rootProject != null) { if (rootProject != null) {
// We need to regenerate the platform specific tooling for both the project // We need to regenerate the platform specific tooling for both the project
// itself and example(if present). // itself and example(if present).
final bool writeLegacyPluginsList = boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true); final bool useImplicitPubspecResolution = boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true);
await rootProject.regeneratePlatformSpecificTooling( await rootProject.regeneratePlatformSpecificTooling(
writeLegacyPluginsList: writeLegacyPluginsList, useImplicitPubspecResolution: useImplicitPubspecResolution,
); );
if (example && rootProject.hasExampleApp && rootProject.example.pubspecFile.existsSync()) { if (example && rootProject.hasExampleApp && rootProject.example.pubspecFile.existsSync()) {
final FlutterProject exampleProject = rootProject.example; final FlutterProject exampleProject = rootProject.example;
await exampleProject.regeneratePlatformSpecificTooling( await exampleProject.regeneratePlatformSpecificTooling(
writeLegacyPluginsList: writeLegacyPluginsList, useImplicitPubspecResolution: useImplicitPubspecResolution,
); );
} }
} }
@ -407,7 +407,7 @@ class PackagesGetCommand extends FlutterCommand {
return <Plugin>[]; return <Plugin>[];
} }
return findPlugins(rootProject, throwOnError: false); return findPlugins(rootProject, throwOnError: false, useImplicitPubspecResolution: boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true));
})(); })();
late final String? _androidEmbeddingVersion = _rootProject?.android.getEmbeddingVersion().toString().split('.').last; late final String? _androidEmbeddingVersion = _rootProject?.android.getEmbeddingVersion().toString().split('.').last;

View File

@ -0,0 +1,164 @@
// 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:process/process.dart';
import 'base/io.dart';
import 'base/logger.dart';
import 'convert.dart';
/// Returns dependencies of [project] that are _only_ used as `dev_dependency`.
///
/// That is, computes and returns a subset of dependencies, where the original
/// set is based on packages listed as [`dev_dependency`][dev_deps] in the
/// `pubspec.yaml` file, and removing packages from that set that appear as
/// dependencies (implicitly non-dev) in any non-dev package depended on.
Future<Set<String>> computeExclusiveDevDependencies(
ProcessManager processes, {
required Logger logger,
required String projectPath,
}) async {
final ProcessResult processResult = await processes.run(
<String>['dart', 'pub', 'deps', '--json'],
workingDirectory: projectPath,
);
Never fail([String? reason]) {
final Object? stdout = processResult.stdout;
if (stdout is String && stdout.isNotEmpty) {
logger.printTrace(stdout);
}
final String stderr = processResult.stderr.toString();
throw StateError(
'dart pub deps --json ${reason != null ? 'had unexpected output: $reason' : 'failed'}'
'${stderr.isNotEmpty ? '\n$stderr' : ''}',
);
}
// Guard against dart pub deps crashing.
final Map<String, Object?> jsonResult;
if (processResult.exitCode != 0 || processResult.stdout is! String) {
fail();
}
// Guard against dart pub deps having explicitly invalid output.
final String stdout;
try {
stdout = processResult.stdout as String;
// This is an indication that `FakeProcessManager.any` was used, which by
// contract emits exit code 0 and no output on either stdout or stderr. To
// avoid this code, we'd have to go and make this function injectable into
// every callsite and mock-it out manually, which at the time of this
// writing was 130+ unit test cases alone.
//
// So, this is the lesser of two evils.
if (stdout.isEmpty && processResult.stderr == '') {
return <String>{};
}
jsonResult = json.decode(stdout) as Map<String, Object?>;
} on FormatException catch (e) {
fail('$e');
}
List<T> asListOrFail<T>(Object? value, String name) {
if (value is! List<Object?>) {
fail('Expected field "$name" to be a list, got "$value"');
}
return <T>[
for (final Object? any in value)
if (any is T) any else fail('Expected element to be a $T, got "$any"')
];
}
// Parse the JSON roughly in the following format:
//
// ```json
// {
// "root": "my_app",
// "packages": [
// {
// "name": "my_app",
// "kind": "root",
// "dependencies": [
// "foo_plugin",
// "bar_plugin"
// ],
// "directDependencies": [
// "foo_plugin"
// ],
// "devDependencies": [
// "bar_plugin"
// ]
// }
// ]
// }
// ```
final List<Map<String, Object?>> packages = asListOrFail(
jsonResult['packages'],
'packages',
);
Map<String, Object?> packageWhere(
bool Function(Map<String, Object?>) test, {
required String reason,
}) {
return packages.firstWhere(test, orElse: () => fail(reason));
}
final Map<String, Object?> rootPackage = packageWhere(
(Map<String, Object?> package) => package['kind'] == 'root',
reason: 'A package with kind "root" was not found.',
);
// Start initially with every `devDependency` listed.
final Set<String> devDependencies = asListOrFail<String>(
rootPackage['devDependencies'],
'devDependencies',
).toSet();
// Then traverse and exclude non-dev dependencies that list that dependency.
//
// This avoids the pathalogical problem of using, say, `path_provider` in a
// package's dev_dependencies:, but a (non-dev) dependency using it as a
// standard dependency - in that case we would not want to report it is used
// as a dev dependency.
final Set<String> visited = <String>{};
void visitPackage(String packageName) {
final bool wasAlreadyVisited = !visited.add(packageName);
if (wasAlreadyVisited) {
return;
}
final Map<String, Object?> package = packageWhere(
(Map<String, Object?> package) => package['name'] == packageName,
reason: 'A package with name "$packageName" was not found',
);
// Do not traverse packages that themselves are dev dependencies.
if (package['kind'] == 'dev') {
return;
}
final List<String> directDependencies = asListOrFail(
package['directDependencies'],
'directDependencies',
);
// Remove any listed dependency from dev dependencies; it might have been
// a dev dependency for the app (root) package, but it is being used as a
// real dependency for a dependend on package, so we would not want to send
// a signal that the package can be ignored/removed.
devDependencies.removeAll(directDependencies);
// And continue visiting (visitPackage checks for circular loops).
directDependencies.forEach(visitPackage);
}
// Start with the root package.
visitPackage(rootPackage['name']! as String);
return devDependencies;
}

View File

@ -1,63 +0,0 @@
// 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:collection';
/// Parsing the output of "dart pub deps --json"
///
/// expected structure: {"name": "package name", "source": "hosted", "dependencies": [...]}
class DartDependencyPackage {
DartDependencyPackage({
required this.name,
required this.version,
required this.source,
required this.dependencies,
});
factory DartDependencyPackage.fromHashMap(dynamic packageInfo) {
if (packageInfo is! LinkedHashMap) {
return DartDependencyPackage(
name: '',
version: '',
source: '',
dependencies: <String>[],
);
}
return DartDependencyPackage(
name: packageInfo['name'] as String? ?? '',
version: packageInfo['version'] as String? ?? '',
source: packageInfo['source'] as String? ?? '',
dependencies: switch (packageInfo['dependencies'] as List<Object?>?) {
final List<Object?> list => list.map((Object? e) => '$e').toList(),
null => <String>[],
},
);
}
final String name;
final String version;
final String source;
final List<String> dependencies;
}
class DartPubJson {
DartPubJson(this._json);
final LinkedHashMap<String, dynamic> _json;
final List<DartDependencyPackage> _packages = <DartDependencyPackage>[];
List<DartDependencyPackage> get packages {
if (_packages.isNotEmpty) {
return _packages;
}
if (_json.containsKey('packages')) {
final List<dynamic> packagesInfo = _json['packages'] as List<dynamic>;
for (final dynamic info in packagesInfo) {
_packages.add(DartDependencyPackage.fromHashMap(info));
}
}
return _packages;
}
}

View File

@ -17,6 +17,7 @@ import 'base/platform.dart';
import 'base/template.dart'; import 'base/template.dart';
import 'base/version.dart'; import 'base/version.dart';
import 'cache.dart'; import 'cache.dart';
import 'compute_dev_dependencies.dart';
import 'convert.dart'; import 'convert.dart';
import 'dart/language_version.dart'; import 'dart/language_version.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
@ -40,8 +41,13 @@ Future<void> _renderTemplateToFile(
await file.writeAsString(renderedTemplate); await file.writeAsString(renderedTemplate);
} }
Future<Plugin?> _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependencies, Future<Plugin?> _pluginFromPackage(
{FileSystem? fileSystem}) async { String name,
Uri packageRoot,
Set<String> appDependencies, {
required Set<String> devDependencies,
FileSystem? fileSystem,
}) async {
final FileSystem fs = fileSystem ?? globals.fs; final FileSystem fs = fileSystem ?? globals.fs;
final File pubspecFile = fs.file(packageRoot.resolve('pubspec.yaml')); final File pubspecFile = fs.file(packageRoot.resolve('pubspec.yaml'));
if (!pubspecFile.existsSync()) { if (!pubspecFile.existsSync()) {
@ -76,10 +82,36 @@ Future<Plugin?> _pluginFromPackage(String name, Uri packageRoot, Set<String> app
dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()], dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()],
fileSystem: fs, fileSystem: fs,
appDependencies: appDependencies, appDependencies: appDependencies,
isDevDependency: devDependencies.contains(name),
); );
} }
Future<List<Plugin>> findPlugins(FlutterProject project, { bool throwOnError = true}) async { /// Returns a list of all plugins to be registered with the provided [project].
///
/// [useImplicitPubspecResolution] defines if legacy rules for traversing the
/// pub dependencies of a package implies, namely, that if `true`, all plugins
/// are assumed to be non-dev dependencies. Code that calls [findPlugins] in
/// order to obtain _other_ information about the plugins, such as whether a
/// plugin uses a specific language or platform can safely pass either `true`
/// or `false`; however a value of `false` _will_ cause `dart pub deps --json`
/// to trigger, which in turn could have other side-effects.
///
/// Please reach out to matanlurey@ if you find you need:
/// ```dart
/// useImplicitPubspecResolution: true
/// ```
///
/// ... in order for your code to function, as that path is being deprecated:
/// <https://flutter.dev/to/flutter-gen-deprecation>.
///
/// ---
///
/// If [throwOnError] is `true`, an empty package configuration is an error.
Future<List<Plugin>> findPlugins(
FlutterProject project, {
required bool useImplicitPubspecResolution,
bool throwOnError = true,
}) async {
final List<Plugin> plugins = <Plugin>[]; final List<Plugin> plugins = <Plugin>[];
final FileSystem fs = project.directory.fileSystem; final FileSystem fs = project.directory.fileSystem;
final File packageConfigFile = findPackageConfigFileOrDefault(project.directory); final File packageConfigFile = findPackageConfigFileOrDefault(project.directory);
@ -88,12 +120,26 @@ Future<List<Plugin>> findPlugins(FlutterProject project, { bool throwOnError = t
logger: globals.logger, logger: globals.logger,
throwOnError: throwOnError, throwOnError: throwOnError,
); );
final Set<String> devDependencies;
if (useImplicitPubspecResolution) {
// With --implicit-pubspec-resolution, we do not want to check for what
// plugins are dev dependencies and instead continue to assume the previous
// behavior (all plugins are non-dev dependencies).
devDependencies = <String>{};
} else {
devDependencies = await computeExclusiveDevDependencies(
globals.processManager,
logger: globals.logger,
projectPath: project.directory.path,
);
}
for (final Package package in packageConfig.packages) { for (final Package package in packageConfig.packages) {
final Uri packageRoot = package.packageUriRoot.resolve('..'); final Uri packageRoot = package.packageUriRoot.resolve('..');
final Plugin? plugin = await _pluginFromPackage( final Plugin? plugin = await _pluginFromPackage(
package.name, package.name,
packageRoot, packageRoot,
project.manifest.dependencies, project.manifest.dependencies,
devDependencies: devDependencies,
fileSystem: fs, fileSystem: fs,
); );
if (plugin != null) { if (plugin != null) {
@ -1010,14 +1056,14 @@ Future<void> refreshPluginsList(
bool iosPlatform = false, bool iosPlatform = false,
bool macOSPlatform = false, bool macOSPlatform = false,
bool forceCocoaPodsOnly = false, bool forceCocoaPodsOnly = false,
required bool writeLegacyPluginsList, required bool useImplicitPubspecResolution,
}) async { }) async {
final List<Plugin> plugins = await findPlugins(project); final List<Plugin> plugins = await findPlugins(project, useImplicitPubspecResolution: useImplicitPubspecResolution);
// Sort the plugins by name to keep ordering stable in generated files. // Sort the plugins by name to keep ordering stable in generated files.
plugins.sort((Plugin left, Plugin right) => left.name.compareTo(right.name)); plugins.sort((Plugin left, Plugin right) => left.name.compareTo(right.name));
// TODO(matanlurey): Remove once migration is complete. // TODO(matanlurey): Remove once migration is complete.
// Write the legacy plugin files to avoid breaking existing apps. // Write the legacy plugin files to avoid breaking existing apps.
final bool legacyChanged = writeLegacyPluginsList && _writeFlutterPluginsListLegacy(project, plugins); final bool legacyChanged = useImplicitPubspecResolution && _writeFlutterPluginsListLegacy(project, plugins);
final bool changed = _writeFlutterPluginsList( final bool changed = _writeFlutterPluginsList(
project, project,
@ -1055,7 +1101,7 @@ Future<void> injectBuildTimePluginFilesForWebPlatform(
FlutterProject project, { FlutterProject project, {
required Directory destination, required Directory destination,
}) async { }) async {
final List<Plugin> plugins = await findPlugins(project); final List<Plugin> plugins = await findPlugins(project, useImplicitPubspecResolution: true);
final Map<String, List<Plugin>> pluginsByPlatform = _resolvePluginImplementations(plugins, pluginResolutionType: _PluginResolutionType.nativeOrDart); final Map<String, List<Plugin>> pluginsByPlatform = _resolvePluginImplementations(plugins, pluginResolutionType: _PluginResolutionType.nativeOrDart);
await _writeWebPluginRegistrant(project, pluginsByPlatform[WebPlugin.kConfigKey]!, destination); await _writeWebPluginRegistrant(project, pluginsByPlatform[WebPlugin.kConfigKey]!, destination);
} }
@ -1074,6 +1120,7 @@ Future<void> injectBuildTimePluginFilesForWebPlatform(
/// Assumes [refreshPluginsList] has been called since last change to `pubspec.yaml`. /// Assumes [refreshPluginsList] has been called since last change to `pubspec.yaml`.
Future<void> injectPlugins( Future<void> injectPlugins(
FlutterProject project, { FlutterProject project, {
required bool useImplicitPubspecResolution,
bool androidPlatform = false, bool androidPlatform = false,
bool iosPlatform = false, bool iosPlatform = false,
bool linuxPlatform = false, bool linuxPlatform = false,
@ -1082,7 +1129,7 @@ Future<void> injectPlugins(
Iterable<String>? allowedPlugins, Iterable<String>? allowedPlugins,
DarwinDependencyManagement? darwinDependencyManagement, DarwinDependencyManagement? darwinDependencyManagement,
}) async { }) async {
final List<Plugin> plugins = await findPlugins(project); final List<Plugin> plugins = await findPlugins(project, useImplicitPubspecResolution: useImplicitPubspecResolution);
final Map<String, List<Plugin>> pluginsByPlatform = _resolvePluginImplementations(plugins, pluginResolutionType: _PluginResolutionType.nativeOrDart); final Map<String, List<Plugin>> pluginsByPlatform = _resolvePluginImplementations(plugins, pluginResolutionType: _PluginResolutionType.nativeOrDart);
if (androidPlatform) { if (androidPlatform) {
@ -1510,7 +1557,7 @@ Future<void> generateMainDartWithPluginRegistrant(
String currentMainUri, String currentMainUri,
File mainFile, File mainFile,
) async { ) async {
final List<Plugin> plugins = await findPlugins(rootProject); final List<Plugin> plugins = await findPlugins(rootProject, useImplicitPubspecResolution: true);
final List<PluginInterfaceResolution> resolutions = resolvePlatformImplementation( final List<PluginInterfaceResolution> resolutions = resolvePlatformImplementation(
plugins, plugins,
selectDartPluginsOnly: true, selectDartPluginsOnly: true,

View File

@ -938,7 +938,7 @@ Future<bool> _isPluginSwiftPackageOnly({
required String pluginName, required String pluginName,
required FileSystem fileSystem, required FileSystem fileSystem,
}) async { }) async {
final List<Plugin> plugins = await findPlugins(project); final List<Plugin> plugins = await findPlugins(project, useImplicitPubspecResolution: true);
final Plugin? matched = plugins final Plugin? matched = plugins
.where((Plugin plugin) => .where((Plugin plugin) =>
plugin.name.toLowerCase() == pluginName.toLowerCase() && plugin.name.toLowerCase() == pluginName.toLowerCase() &&

View File

@ -22,7 +22,9 @@ Future<void> processPodsIfNeeded(
// When using Swift Package Manager, the Podfile may not exist so if there // When using Swift Package Manager, the Podfile may not exist so if there
// isn't a Podfile, skip processing pods. // isn't a Podfile, skip processing pods.
if (project.usesSwiftPackageManager && !xcodeProject.podfile.existsSync() && !forceCocoaPodsOnly) { if (project.usesSwiftPackageManager &&
!xcodeProject.podfile.existsSync() &&
!forceCocoaPodsOnly) {
return; return;
} }
// Ensure that the plugin list is up to date, since hasPlugins relies on it. // Ensure that the plugin list is up to date, since hasPlugins relies on it.
@ -36,12 +38,13 @@ Future<void> processPodsIfNeeded(
// file being generated. A better long-term fix would be not to have a call to refreshPluginsList // file being generated. A better long-term fix would be not to have a call to refreshPluginsList
// at all, and instead have it implicitly run by the FlutterCommand instead. See // at all, and instead have it implicitly run by the FlutterCommand instead. See
// https://github.com/flutter/flutter/issues/157391 for details. // https://github.com/flutter/flutter/issues/157391 for details.
writeLegacyPluginsList: false, useImplicitPubspecResolution: false,
); );
// If there are no plugins and if the project is a not module with an existing // If there are no plugins and if the project is a not module with an existing
// podfile, skip processing pods // podfile, skip processing pods
if (!hasPlugins(project) && !(project.isModule && xcodeProject.podfile.existsSync())) { if (!hasPlugins(project) &&
!(project.isModule && xcodeProject.podfile.existsSync())) {
return; return;
} }
@ -66,7 +69,8 @@ Future<void> processPodsIfNeeded(
// If the Xcode project, Podfile, generated plugin Swift Package, or podhelper // If the Xcode project, Podfile, generated plugin Swift Package, or podhelper
// have changed since last run, pods should be updated. // have changed since last run, pods should be updated.
final Fingerprinter fingerprinter = Fingerprinter( final Fingerprinter fingerprinter = Fingerprinter(
fingerprintPath: globals.fs.path.join(buildDirectory, 'pod_inputs.fingerprint'), fingerprintPath:
globals.fs.path.join(buildDirectory, 'pod_inputs.fingerprint'),
paths: <String>[ paths: <String>[
xcodeProject.xcodeProjectInfoFile.path, xcodeProject.xcodeProjectInfoFile.path,
xcodeProject.podfile.path, xcodeProject.podfile.path,
@ -88,7 +92,8 @@ Future<void> processPodsIfNeeded(
xcodeProject: xcodeProject, xcodeProject: xcodeProject,
buildMode: buildMode, buildMode: buildMode,
dependenciesChanged: !fingerprinter.doesFingerprintMatch(), dependenciesChanged: !fingerprinter.doesFingerprintMatch(),
) ?? false; ) ??
false;
if (didPodInstall) { if (didPodInstall) {
fingerprinter.writeFingerprint(); fingerprinter.writeFingerprint();
} }

View File

@ -19,6 +19,7 @@ class Plugin {
this.flutterConstraint, this.flutterConstraint,
required this.dependencies, required this.dependencies,
required this.isDirectDependency, required this.isDirectDependency,
required this.isDevDependency,
this.implementsPackage, this.implementsPackage,
}); });
@ -68,6 +69,7 @@ class Plugin {
VersionConstraint? flutterConstraint, VersionConstraint? flutterConstraint,
List<String> dependencies, { List<String> dependencies, {
required FileSystem fileSystem, required FileSystem fileSystem,
required bool isDevDependency,
Set<String>? appDependencies, Set<String>? appDependencies,
}) { }) {
final List<String> errors = validatePluginYaml(pluginYaml); final List<String> errors = validatePluginYaml(pluginYaml);
@ -82,6 +84,7 @@ class Plugin {
flutterConstraint, flutterConstraint,
dependencies, dependencies,
fileSystem, fileSystem,
isDevDependency: isDevDependency,
appDependencies != null && appDependencies.contains(name), appDependencies != null && appDependencies.contains(name),
); );
} }
@ -92,6 +95,7 @@ class Plugin {
flutterConstraint, flutterConstraint,
dependencies, dependencies,
fileSystem, fileSystem,
isDevDependency: isDevDependency,
appDependencies != null && appDependencies.contains(name), appDependencies != null && appDependencies.contains(name),
); );
} }
@ -103,8 +107,9 @@ class Plugin {
VersionConstraint? flutterConstraint, VersionConstraint? flutterConstraint,
List<String> dependencies, List<String> dependencies,
FileSystem fileSystem, FileSystem fileSystem,
bool isDirectDependency, bool isDirectDependency, {
) { required bool isDevDependency,
}) {
assert (pluginYaml['platforms'] != null, 'Invalid multi-platform plugin specification $name.'); assert (pluginYaml['platforms'] != null, 'Invalid multi-platform plugin specification $name.');
final YamlMap platformsYaml = pluginYaml['platforms'] as YamlMap; final YamlMap platformsYaml = pluginYaml['platforms'] as YamlMap;
@ -184,6 +189,7 @@ class Plugin {
dependencies: dependencies, dependencies: dependencies,
isDirectDependency: isDirectDependency, isDirectDependency: isDirectDependency,
implementsPackage: pluginYaml['implements'] != null ? pluginYaml['implements'] as String : '', implementsPackage: pluginYaml['implements'] != null ? pluginYaml['implements'] as String : '',
isDevDependency: isDevDependency,
); );
} }
@ -194,8 +200,9 @@ class Plugin {
VersionConstraint? flutterConstraint, VersionConstraint? flutterConstraint,
List<String> dependencies, List<String> dependencies,
FileSystem fileSystem, FileSystem fileSystem,
bool isDirectDependency, bool isDirectDependency, {
) { required bool isDevDependency,
}) {
final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{}; final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{};
final String? pluginClass = (pluginYaml as Map<dynamic, dynamic>)['pluginClass'] as String?; final String? pluginClass = (pluginYaml as Map<dynamic, dynamic>)['pluginClass'] as String?;
if (pluginClass != null) { if (pluginClass != null) {
@ -227,6 +234,7 @@ class Plugin {
flutterConstraint: flutterConstraint, flutterConstraint: flutterConstraint,
dependencies: dependencies, dependencies: dependencies,
isDirectDependency: isDirectDependency, isDirectDependency: isDirectDependency,
isDevDependency: isDevDependency,
); );
} }
@ -407,6 +415,16 @@ class Plugin {
/// If [false], the plugin is a dependency of another plugin. /// If [false], the plugin is a dependency of another plugin.
final bool isDirectDependency; final bool isDirectDependency;
/// Whether this plugin is exclusively used as a dev dependency of the app.
///
/// If [false], the plugin is either:
/// - _Not_ a dev dependency
/// - _Not_ a dev dependency of some dependency that itself is not a dev
/// dependency
///
/// Dev dependencies are intended to be stripped out in release builds.
final bool isDevDependency;
/// Expected path to the plugin's Package.swift. Returns null if the plugin /// Expected path to the plugin's Package.swift. Returns null if the plugin
/// does not support the [platform] or the [platform] is not iOS or macOS. /// does not support the [platform] or the [platform] is not iOS or macOS.
String? pluginSwiftPackageManifestPath( String? pluginSwiftPackageManifestPath(

View File

@ -340,7 +340,7 @@ class FlutterProject {
Future<void> regeneratePlatformSpecificTooling({ Future<void> regeneratePlatformSpecificTooling({
DeprecationBehavior deprecationBehavior = DeprecationBehavior.none, DeprecationBehavior deprecationBehavior = DeprecationBehavior.none,
Iterable<String>? allowedPlugins, Iterable<String>? allowedPlugins,
required bool writeLegacyPluginsList, required bool useImplicitPubspecResolution,
}) async { }) async {
return ensureReadyForPlatformSpecificTooling( return ensureReadyForPlatformSpecificTooling(
androidPlatform: android.existsSync(), androidPlatform: android.existsSync(),
@ -353,7 +353,7 @@ class FlutterProject {
webPlatform: featureFlags.isWebEnabled && web.existsSync(), webPlatform: featureFlags.isWebEnabled && web.existsSync(),
deprecationBehavior: deprecationBehavior, deprecationBehavior: deprecationBehavior,
allowedPlugins: allowedPlugins, allowedPlugins: allowedPlugins,
writeLegacyPluginsList: writeLegacyPluginsList, useImplicitPubspecResolution: useImplicitPubspecResolution,
); );
} }
@ -368,7 +368,7 @@ class FlutterProject {
bool webPlatform = false, bool webPlatform = false,
DeprecationBehavior deprecationBehavior = DeprecationBehavior.none, DeprecationBehavior deprecationBehavior = DeprecationBehavior.none,
Iterable<String>? allowedPlugins, Iterable<String>? allowedPlugins,
required bool writeLegacyPluginsList, required bool useImplicitPubspecResolution,
}) async { }) async {
if (!directory.existsSync() || isPlugin) { if (!directory.existsSync() || isPlugin) {
return; return;
@ -377,7 +377,7 @@ class FlutterProject {
this, this,
iosPlatform: iosPlatform, iosPlatform: iosPlatform,
macOSPlatform: macOSPlatform, macOSPlatform: macOSPlatform,
writeLegacyPluginsList: writeLegacyPluginsList, useImplicitPubspecResolution: useImplicitPubspecResolution,
); );
if (androidPlatform) { if (androidPlatform) {
await android.ensureReadyForPlatformSpecificTooling(deprecationBehavior: deprecationBehavior); await android.ensureReadyForPlatformSpecificTooling(deprecationBehavior: deprecationBehavior);
@ -405,6 +405,7 @@ class FlutterProject {
macOSPlatform: macOSPlatform, macOSPlatform: macOSPlatform,
windowsPlatform: windowsPlatform, windowsPlatform: windowsPlatform,
allowedPlugins: allowedPlugins, allowedPlugins: allowedPlugins,
useImplicitPubspecResolution: useImplicitPubspecResolution,
); );
} }

View File

@ -1793,7 +1793,7 @@ Run 'flutter -h' (or 'flutter <command> -h') for available flutter commands and
} }
await project.regeneratePlatformSpecificTooling( await project.regeneratePlatformSpecificTooling(
allowedPlugins: allowedPlugins, allowedPlugins: allowedPlugins,
writeLegacyPluginsList: boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true), useImplicitPubspecResolution: boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true),
); );
if (reportNullSafety) { if (reportNullSafety) {
await _sendNullSafetyAnalyticsEvents(project); await _sendNullSafetyAnalyticsEvents(project);

View File

@ -75,7 +75,7 @@ class WebBuilder {
String? outputDirectoryPath, String? outputDirectoryPath,
}) async { }) async {
final bool hasWebPlugins = final bool hasWebPlugins =
(await findPlugins(flutterProject)).any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey)); (await findPlugins(flutterProject, useImplicitPubspecResolution: true)).any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
final Directory outputDirectory = outputDirectoryPath == null final Directory outputDirectory = outputDirectoryPath == null
? _fileSystem.directory(getWebBuildDirectory()) ? _fileSystem.directory(getWebBuildDirectory())
: _fileSystem.directory(outputDirectoryPath); : _fileSystem.directory(outputDirectoryPath);

View File

@ -114,6 +114,13 @@ void main() {
'xattr', '-r', '-d', 'com.apple.FinderInfo', '/', 'xattr', '-r', '-d', 'com.apple.FinderInfo', '/',
]); ]);
const FakeCommand dartPubDepsCommand = FakeCommand(command: <String>[
'dart',
'pub',
'deps',
'--json',
]);
FakeCommand setUpRsyncCommand({void Function(List<String> command)? onRun}) { FakeCommand setUpRsyncCommand({void Function(List<String> command)? onRun}) {
return FakeCommand( return FakeCommand(
command: const <String>[ command: const <String>[
@ -300,6 +307,7 @@ void main() {
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true);
}), }),
@ -323,6 +331,7 @@ void main() {
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true);
}), }),
@ -360,6 +369,7 @@ void main() {
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
disablePortPublication: true, disablePortPublication: true,
onRun: (_) { onRun: (_) {
@ -392,6 +402,7 @@ void main() {
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
onRun: (_) { onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true);
@ -416,6 +427,7 @@ void main() {
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(customNaming: true, onRun: (_) { setUpFakeXcodeBuildHandler(customNaming: true, onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true);
}), }),
@ -450,6 +462,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(deviceId: '1234', onRun: (_) { setUpFakeXcodeBuildHandler(deviceId: '1234', onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true);
}), }),
@ -480,6 +493,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(simulator: true, onRun: (_) { setUpFakeXcodeBuildHandler(simulator: true, onRun: (_) {
fileSystem.directory('build/ios/Debug-iphonesimulator/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Debug-iphonesimulator/Runner.app').createSync(recursive: true);
}), }),
@ -510,6 +524,7 @@ void main() {
createMinimalMockProjectFiles(); createMinimalMockProjectFiles();
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(verbose: true, onRun: (_) { setUpFakeXcodeBuildHandler(verbose: true, onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true);
}), }),
@ -538,6 +553,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true);
fileSystem.file('build/flutter_size_01/snapshot.arm64.json') fileSystem.file('build/flutter_size_01/snapshot.arm64.json')
@ -624,6 +640,7 @@ void main() {
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app') fileSystem.directory('build/ios/Release-iphoneos/Runner.app')
.createSync(recursive: true); .createSync(recursive: true);
@ -678,6 +695,7 @@ void main() {
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.directory('build/ios/Release-iphoneos/Runner.app') fileSystem.directory('build/ios/Release-iphoneos/Runner.app')
.createSync(recursive: true); .createSync(recursive: true);
@ -721,6 +739,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync();
}), }),
@ -756,6 +775,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync();
}, stdout: 'Lots of spew from Xcode', }, stdout: 'Lots of spew from Xcode',
@ -795,6 +815,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync();
}), }),
@ -833,6 +854,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1), setUpFakeXcodeBuildHandler(exitCode: 1),
setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), setUpXCResultCommand(stdout: kSampleResultJsonWithIssues),
setUpRsyncCommand(), setUpRsyncCommand(),
@ -865,6 +887,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync();
}), }),
@ -904,6 +927,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
onRun: (_) { onRun: (_) {
@ -943,6 +967,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync();
}), }),
@ -978,6 +1003,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
// Intentionally fail the first xcodebuild command with concurrent run failure message. // Intentionally fail the first xcodebuild command with concurrent run failure message.
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
@ -1025,6 +1051,7 @@ void main() {
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
stdout: ''' stdout: '''
@ -1066,6 +1093,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
onRun: (_) { onRun: (_) {
@ -1115,6 +1143,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
stdout: ''' stdout: '''
@ -1144,6 +1173,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
onRun: (_) { onRun: (_) {
@ -1181,6 +1211,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
onRun: (_) { onRun: (_) {
@ -1220,6 +1251,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
exitCode: 1, exitCode: 1,
onRun: (_) { onRun: (_) {
@ -1261,6 +1293,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
simulator: true, simulator: true,
exitCode: 1, exitCode: 1,
@ -1300,6 +1333,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
simulator: true, simulator: true,
exitCode: 1, exitCode: 1,
@ -1341,6 +1375,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
simulator: true, simulator: true,
exitCode: 1, exitCode: 1,
@ -1383,6 +1418,7 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
); );
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
simulator: true, simulator: true,
exitCode: 1, exitCode: 1,

View File

@ -140,6 +140,13 @@ void main() {
'xattr', '-r', '-d', 'com.apple.FinderInfo', '/', 'xattr', '-r', '-d', 'com.apple.FinderInfo', '/',
]); ]);
const FakeCommand dartPubDepsCommand = FakeCommand(command: <String>[
'dart',
'pub',
'deps',
'--json',
]);
FakeCommand setUpXCResultCommand({String stdout = '', void Function(List<String> command)? onRun}) { FakeCommand setUpXCResultCommand({String stdout = '', void Function(List<String> command)? onRun}) {
return FakeCommand( return FakeCommand(
command: const <String>[ command: const <String>[
@ -398,6 +405,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]); ]);
@ -429,6 +437,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist),
]); ]);
@ -475,6 +484,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist),
]); ]);
@ -521,6 +531,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist),
]); ]);
@ -566,6 +577,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]); ]);
@ -595,6 +607,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist),
]); ]);
@ -640,6 +653,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]); ]);
@ -668,6 +682,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: exportOptions.path), exportArchiveCommand(exportOptionsPlist: exportOptions.path),
]); ]);
@ -707,6 +722,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
const FakeCommand( const FakeCommand(
command: <String>[ command: <String>[
@ -762,6 +778,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand( exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist, exportOptionsPlist: _exportOptionsPlist,
@ -796,6 +813,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist),
]); ]);
@ -848,6 +866,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist),
]); ]);
@ -900,6 +919,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist, cachePlist: cachedExportOptionsPlist),
]); ]);
@ -951,6 +971,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(verbose: true), setUpFakeXcodeBuildHandler(verbose: true),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]); ]);
@ -980,6 +1001,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist), exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]); ]);
@ -1008,6 +1030,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
const FakeCommand( const FakeCommand(
command: <String>[ command: <String>[
'xcrun', 'xcrun',
@ -1060,6 +1083,7 @@ void main() {
); );
createMinimalMockProjectFiles(); createMinimalMockProjectFiles();
fakeProcessManager.addCommand(dartPubDepsCommand);
fakeProcessManager.addCommand(setUpFakeXcodeBuildHandler()); fakeProcessManager.addCommand(setUpFakeXcodeBuildHandler());
await expectToolExitLater( await expectToolExitLater(
createTestCommandRunner(command).run( createTestCommandRunner(command).run(
@ -1091,6 +1115,7 @@ void main() {
..writeAsBytesSync(List<int>.generate(10000, (int index) => 0)); ..writeAsBytesSync(List<int>.generate(10000, (int index) => 0));
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file('build/flutter_size_01/snapshot.arm64.json') fileSystem.file('build/flutter_size_01/snapshot.arm64.json')
..createSync(recursive: true) ..createSync(recursive: true)
@ -1146,6 +1171,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(), setUpFakeXcodeBuildHandler(),
exportArchiveCommand(), exportArchiveCommand(),
]); ]);
@ -1183,6 +1209,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
}), }),
@ -1217,6 +1244,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
}), }),
@ -1252,6 +1280,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
}), }),
@ -1289,6 +1318,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1), setUpFakeXcodeBuildHandler(exitCode: 1),
]); ]);
createMinimalMockProjectFiles(); createMinimalMockProjectFiles();
@ -1321,6 +1351,7 @@ void main() {
); );
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) { setUpFakeXcodeBuildHandler(exitCode: 1, onRun: (_) {
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync(); fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
}), }),
@ -1353,6 +1384,7 @@ void main() {
const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist'; const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true); fileSystem.file(plistPath).createSync(recursive: true);
}), }),
@ -1406,6 +1438,7 @@ void main() {
const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist'; const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true); fileSystem.file(plistPath).createSync(recursive: true);
}), }),
@ -1465,6 +1498,7 @@ void main() {
const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist'; const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true); fileSystem.file(plistPath).createSync(recursive: true);
}), }),
@ -1524,6 +1558,7 @@ void main() {
const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist'; const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true); fileSystem.file(plistPath).createSync(recursive: true);
}), }),
@ -1567,6 +1602,7 @@ void main() {
const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist'; const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true); fileSystem.file(plistPath).createSync(recursive: true);
}), }),
@ -1613,6 +1649,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(templateIconContentsJsonPath) fileSystem.file(templateIconContentsJsonPath)
..createSync(recursive: true) ..createSync(recursive: true)
@ -1695,6 +1732,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(templateIconContentsJsonPath) fileSystem.file(templateIconContentsJsonPath)
..createSync(recursive: true) ..createSync(recursive: true)
@ -1775,6 +1813,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(projectIconContentsJsonPath) fileSystem.file(projectIconContentsJsonPath)
..createSync(recursive: true) ..createSync(recursive: true)
@ -1837,6 +1876,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(projectIconContentsJsonPath) fileSystem.file(projectIconContentsJsonPath)
..createSync(recursive: true) ..createSync(recursive: true)
@ -1900,6 +1940,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(projectIconContentsJsonPath) fileSystem.file(projectIconContentsJsonPath)
..createSync(recursive: true) ..createSync(recursive: true)
@ -1962,6 +2003,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
// Uses unknown format version 123. // Uses unknown format version 123.
fileSystem.file(projectIconContentsJsonPath) fileSystem.file(projectIconContentsJsonPath)
@ -2034,6 +2076,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
// The following json contains examples of: // The following json contains examples of:
// - invalid size // - invalid size
@ -2139,6 +2182,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(templateLaunchImageContentsJsonPath) fileSystem.file(templateLaunchImageContentsJsonPath)
..createSync(recursive: true) ..createSync(recursive: true)
@ -2220,6 +2264,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
xattrCommand, xattrCommand,
dartPubDepsCommand,
setUpFakeXcodeBuildHandler(onRun: (_) { setUpFakeXcodeBuildHandler(onRun: (_) {
fileSystem.file(templateLaunchImageContentsJsonPath) fileSystem.file(templateLaunchImageContentsJsonPath)
..createSync(recursive: true) ..createSync(recursive: true)

View File

@ -105,6 +105,13 @@ void main() {
createCoreMockProjectFiles(); createCoreMockProjectFiles();
} }
const FakeCommand dartPubDepsCommand = FakeCommand(command: <String>[
'dart',
'pub',
'deps',
'--json',
]);
// Creates a FakeCommand for the xcodebuild call to build the app // Creates a FakeCommand for the xcodebuild call to build the app
// in the given configuration. // in the given configuration.
FakeCommand setUpFakeXcodeBuildHandler( FakeCommand setUpFakeXcodeBuildHandler(
@ -300,6 +307,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Debug'), setUpFakeXcodeBuildHandler('Debug'),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -325,6 +333,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Release'), setUpFakeXcodeBuildHandler('Release'),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -349,6 +358,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Debug'), setUpFakeXcodeBuildHandler('Debug'),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -373,6 +383,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Debug', verbose: true), setUpFakeXcodeBuildHandler('Debug', verbose: true),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -398,6 +409,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Profile'), setUpFakeXcodeBuildHandler('Profile'),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -423,6 +435,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Release'), setUpFakeXcodeBuildHandler('Release'),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -486,6 +499,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Release'), setUpFakeXcodeBuildHandler('Release'),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -504,6 +518,7 @@ STDERR STUFF
createMinimalMockProjectFiles(); createMinimalMockProjectFiles();
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
dartPubDepsCommand,
FakeCommand( FakeCommand(
command: <String>[ command: <String>[
'/usr/bin/env', '/usr/bin/env',
@ -577,6 +592,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler('Debug'), setUpFakeXcodeBuildHandler('Debug'),
]), ]),
Platform: () => macosPlatform, Platform: () => macosPlatform,
@ -648,6 +664,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
// we never generate code size snapshot here // we never generate code size snapshot here
setUpFakeXcodeBuildHandler('Release'), setUpFakeXcodeBuildHandler('Release'),
]), ]),
@ -682,6 +699,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
// These are generated by gen_snapshot because flutter assemble passes // These are generated by gen_snapshot because flutter assemble passes
// extra flags specifying this output path // extra flags specifying this output path
setUpFakeXcodeBuildHandler('Release', onRun: (_) { setUpFakeXcodeBuildHandler('Release', onRun: (_) {
@ -753,6 +771,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
'Debug', 'Debug',
additionalCommandArguements: <String>[ additionalCommandArguements: <String>[
@ -821,6 +840,7 @@ STDERR STUFF
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
dartPubDepsCommand,
setUpFakeXcodeBuildHandler( setUpFakeXcodeBuildHandler(
'Release', 'Release',
additionalCommandArguements: <String>[ additionalCommandArguements: <String>[

View File

@ -53,7 +53,7 @@ void main() {
fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true); fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true);
artifacts = Artifacts.test(fileSystem: fileSystem); artifacts = Artifacts.test(fileSystem: fileSystem);
logger = BufferLogger.test(); logger = BufferLogger.test();
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.any();
processUtils = ProcessUtils( processUtils = ProcessUtils(
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
@ -170,7 +170,7 @@ void main() {
Platform: () => fakePlatform, Platform: () => fakePlatform,
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => processManager,
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) { BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) {
expect(environment.defines, <String, String>{ expect(environment.defines, <String, String>{
'TargetFile': 'lib/main.dart', 'TargetFile': 'lib/main.dart',

View File

@ -180,6 +180,8 @@ void main() {
.childDirectory('flutter_build') .childDirectory('flutter_build')
.childFile('dart_plugin_registrant.dart'); .childFile('dart_plugin_registrant.dart');
expect(generatedMain.existsSync(), isFalse); expect(generatedMain.existsSync(), isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('regenerates dart_plugin_registrant.dart', () async { testUsingContext('regenerates dart_plugin_registrant.dart', () async {
@ -257,6 +259,8 @@ void main() {
'}\n' '}\n'
), ),
); );
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('removes dart_plugin_registrant.dart if plugins are removed from pubspec.yaml', () async { testUsingContext('removes dart_plugin_registrant.dart if plugins are removed from pubspec.yaml', () async {
@ -301,6 +305,8 @@ void main() {
await DartPluginRegistrantTarget.test(testProject).build(environment); await DartPluginRegistrantTarget.test(testProject).build(environment);
expect(generatedMain.existsSync(), isFalse); expect(generatedMain.existsSync(), isFalse);
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('target file is outside the current project package', () async { testUsingContext('target file is outside the current project package', () async {
@ -379,6 +385,8 @@ void main() {
'}\n' '}\n'
), ),
); );
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
}); });
}); });
} }

View File

@ -0,0 +1,426 @@
// 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:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/compute_dev_dependencies.dart';
import '../src/common.dart';
import '../src/fake_process_manager.dart';
// For all of these examples, imagine the following package structure:
//
// /
// /my_app
// pubspec.yaml
// /package_a
// pubspec.yaml
// /pacakge_b
// pubspec.yaml
// /package_c
// pubspec.yaml
void main() {
late BufferLogger logger;
setUp(() {
logger = BufferLogger.test();
});
test('no dev dependencies at all', () async {
// Simulates the following:
//
// # /my_app/pubspec.yaml
// name: my_app
// dependencies:
// package_a:
//
// # /package_a/pubspec.yaml
// name: package_a
// dependencies:
// package_b:
final ProcessManager processes = _dartPubDepsReturns('''
{
"root": "my_app",
"packages": [
{
"name": "my_app",
"kind": "root",
"dependencies": [
"package_a",
"package_b"
],
"directDependencies": [
"package_a"
],
"devDependencies": []
},
{
"name": "package_a",
"kind": "direct",
"dependencies": [
"package_b"
],
"directDependencies": [
"package_b"
]
},
{
"name": "package_b",
"kind": "transitive",
"dependencies": [],
"directDependencies": []
}
]
}''');
final Set<String> dependencies = await computeExclusiveDevDependencies(
processes,
projectPath: _fakeProjectPath,
logger: logger,
);
expect(
dependencies,
isEmpty,
reason: 'There are no dev_dependencies of "my_app".',
);
});
test('dev dependency', () async {
// Simulates the following:
//
// # /my_app/pubspec.yaml
// name: my_app
// dependencies:
// package_a:
//
// dev_dependencies:
// package_b:
//
// # /package_a/pubspec.yaml
// name: package_a
final ProcessManager processes = _dartPubDepsReturns('''
{
"root": "my_app",
"packages": [
{
"name": "my_app",
"kind": "root",
"dependencies": [
"package_a",
"package_b"
],
"directDependencies": [
"package_a"
],
"devDependencies": [
"package_b"
]
},
{
"name": "package_a",
"kind": "direct",
"dependencies": [],
"directDependencies": []
},
{
"name": "package_b",
"kind": "dev",
"dependencies": [],
"directDependencies": []
}
]
}''');
final Set<String> dependencies = await computeExclusiveDevDependencies(
processes,
projectPath: _fakeProjectPath,
logger: logger,
);
expect(
dependencies,
<String>{'package_b'},
reason: 'There is a single dev_dependency of my_app: package_b.',
);
});
test('dev used as a non-dev dependency transitively', () async {
// Simulates the following:
//
// # /my_app/pubspec.yaml
// name: my_app
// dependencies:
// package_a:
//
// dev_dependencies:
// package_b:
//
// # /package_a/pubspec.yaml
// name: package_a
// dependencies:
// package_b:
final ProcessManager processes = _dartPubDepsReturns('''
{
"root": "my_app",
"packages": [
{
"name": "my_app",
"kind": "root",
"dependencies": [
"package_a",
"package_b"
],
"directDependencies": [
"package_a"
],
"devDependencies": [
"package_b"
]
},
{
"name": "package_a",
"kind": "direct",
"dependencies": [
"package_b"
],
"directDependencies": [
"package_b"
]
},
{
"name": "package_b",
"kind": "dev",
"dependencies": [],
"directDependencies": []
}
]
}''');
final Set<String> dependencies = await computeExclusiveDevDependencies(
processes,
projectPath: _fakeProjectPath,
logger: logger,
);
expect(
dependencies,
isEmpty,
reason: 'There is a dev_dependency also used as a standard dependency',
);
});
test('combination of an included and excluded dev_dependency', () async {
// Simulates the following:
//
// # /my_app/pubspec.yaml
// name: my_app
// dependencies:
// package_a:
//
// dev_dependencies:
// package_b:
// package_c:
//
// # /package_a/pubspec.yaml
// name: package_a
// dependencies:
// package_b:
//
// # /package_b/pubspec.yaml
// name: package_b
//
// # /package_c/pubspec.yaml
// name: package_c
final ProcessManager processes = _dartPubDepsReturns('''
{
"root": "my_app",
"packages": [
{
"name": "my_app",
"kind": "root",
"dependencies": [
"package_a",
"package_b"
],
"directDependencies": [
"package_a"
],
"devDependencies": [
"package_b",
"package_c"
]
},
{
"name": "package_a",
"kind": "direct",
"dependencies": [
"package_b"
],
"directDependencies": [
"package_b"
]
},
{
"name": "package_b",
"kind": "dev",
"dependencies": [
"package_c"
],
"directDependencies": [
"package_c"
]
},
{
"name": "package_c",
"kind": "dev",
"dependencies": [],
"directDependencies": []
}
]
}''');
final Set<String> dependencies = await computeExclusiveDevDependencies(
processes,
projectPath: _fakeProjectPath,
logger: logger,
);
expect(
dependencies,
<String>{'package_c'},
reason: 'package_b is excluded but package_c should not',
);
});
test('throws and logs on non-zero exit code', () async {
final ProcessManager processes = _dartPubDepsFails(
'Bad thing',
exitCode: 1,
);
await expectLater(
computeExclusiveDevDependencies(
processes,
projectPath: _fakeProjectPath,
logger: logger,
),
throwsA(
isA<StateError>().having(
(StateError e) => e.message,
'message',
contains('dart pub deps --json failed'),
),
),
);
expect(logger.traceText, isEmpty);
});
test('throws and logs on unexpected output type', () async {
final ProcessManager processes = _dartPubDepsReturns(
'Not JSON haha!',
);
await expectLater(
computeExclusiveDevDependencies(
processes,
projectPath: _fakeProjectPath,
logger: logger,
),
throwsA(
isA<StateError>().having(
(StateError e) => e.message,
'message',
contains('dart pub deps --json had unexpected output'),
),
),
);
expect(logger.traceText, contains('Not JSON haha'));
});
test('throws and logs on invalid JSON', () async {
final ProcessManager processes = _dartPubDepsReturns('''
{
"root": "my_app",
"packages": [
{
"name": "my_app",
"kind": "root",
"dependencies": [
"package_a",
"package_b"
],
"directDependencies": [
1
],
"devDependencies": []
},
{
"name": "package_a",
"kind": "direct",
"dependencies": [
"package_b"
],
"directDependencies": [
"package_b"
]
},
{
"name": "package_b",
"kind": "transitive",
"dependencies": [],
"directDependencies": []
}
]
}''');
await expectLater(
computeExclusiveDevDependencies(
processes,
projectPath: _fakeProjectPath,
logger: logger,
),
throwsA(
isA<StateError>().having(
(StateError e) => e.message,
'message',
contains('dart pub deps --json had unexpected output'),
),
),
);
expect(
logger.traceText,
contains('"root": "my_app"'),
reason: 'Stdout should include the JSON blob',
);
});
}
const String _fakeProjectPath = '/path/to/project';
ProcessManager _dartPubDepsReturns(String dartPubDepsOutput) {
return FakeProcessManager.list(<FakeCommand>[
FakeCommand(
command: const <String>['dart', 'pub', 'deps', '--json'],
stdout: dartPubDepsOutput,
workingDirectory: _fakeProjectPath,
),
]);
}
ProcessManager _dartPubDepsFails(
String dartPubDepsError, {
required int exitCode,
}) {
return FakeProcessManager.list(<FakeCommand>[
FakeCommand(
command: const <String>['dart', 'pub', 'deps', '--json'],
exitCode: exitCode,
stderr: dartPubDepsError,
workingDirectory: _fakeProjectPath,
),
]);
}

View File

@ -64,6 +64,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -80,6 +81,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -130,6 +132,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -146,6 +149,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -183,6 +187,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -199,6 +204,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -245,6 +251,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -295,6 +302,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -329,6 +337,7 @@ void main() {
VersionConstraint.parse('>=2.10.0'), VersionConstraint.parse('>=2.10.0'),
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -362,6 +371,7 @@ void main() {
VersionConstraint.parse('>=2.11.0'), VersionConstraint.parse('>=2.11.0'),
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -411,6 +421,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
// Include three possible implementations, one before and one after // Include three possible implementations, one before and one after
@ -430,6 +441,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -446,6 +458,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -462,6 +475,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -496,6 +510,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -512,6 +527,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -549,6 +565,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -565,6 +582,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -581,6 +599,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -621,6 +640,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -637,6 +657,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -683,6 +704,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -699,6 +721,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -715,6 +738,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -757,6 +781,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -773,6 +798,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -810,6 +836,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -822,6 +849,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -856,6 +884,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -872,6 +901,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -899,6 +929,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -915,6 +946,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -952,6 +984,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -990,6 +1023,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -1006,6 +1040,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -1050,6 +1085,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -1066,6 +1102,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -1082,6 +1119,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -1098,6 +1136,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],
@ -1142,6 +1181,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
Plugin.fromYaml( Plugin.fromYaml(
@ -1158,6 +1198,7 @@ void main() {
null, null,
<String>[], <String>[],
fileSystem: fs, fileSystem: fs,
isDevDependency: false,
appDependencies: directDependencies, appDependencies: directDependencies,
), ),
], ],

View File

@ -69,6 +69,18 @@ const List<String> kRunReleaseArgs = <String>[
'COMPILER_INDEX_STORE_ENABLE=NO', 'COMPILER_INDEX_STORE_ENABLE=NO',
]; ];
// TODO(matanlurey): XCode builds call processPodsIfNeeded -> refreshPluginsList
// ... which in turn requires that `dart pub deps --json` is called in order to
// label which plugins are dependency plugins.
//
// Ideally processPodsIfNeeded should rely on the command (removing this call).
const List<String> kCheckDartPubDeps = <String> [
'dart',
'pub',
'deps',
'--json',
];
const String kConcurrentBuildErrorMessage = ''' const String kConcurrentBuildErrorMessage = '''
"/Developer/Xcode/DerivedData/foo/XCBuildData/build.db": "/Developer/Xcode/DerivedData/foo/XCBuildData/build.db":
database is locked database is locked
@ -132,6 +144,7 @@ void main() {
final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter', 'My Super Awesome App'); final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter', 'My Super Awesome App');
processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject))); processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
processManager.addCommand(const FakeCommand(command: kCheckDartPubDeps));
processManager.addCommand(const FakeCommand(command: kRunReleaseArgs)); processManager.addCommand(const FakeCommand(command: kRunReleaseArgs));
final LaunchResult launchResult = await iosDevice.startApp( final LaunchResult launchResult = await iosDevice.startApp(
@ -206,6 +219,7 @@ void main() {
fileSystem.directory('build/ios/Release-iphoneos/My Super Awesome App.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/My Super Awesome App.app').createSync(recursive: true);
processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject))); processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
processManager.addCommand(const FakeCommand(command: kCheckDartPubDeps));
processManager.addCommand(const FakeCommand(command: kRunReleaseArgs)); processManager.addCommand(const FakeCommand(command: kRunReleaseArgs));
processManager.addCommand(const FakeCommand(command: <String>[ processManager.addCommand(const FakeCommand(command: <String>[
'rsync', 'rsync',
@ -266,6 +280,7 @@ void main() {
fileSystem.directory('build/ios/Release-iphoneos/My Super Awesome App.app').createSync(recursive: true); fileSystem.directory('build/ios/Release-iphoneos/My Super Awesome App.app').createSync(recursive: true);
processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject))); processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
processManager.addCommand(const FakeCommand(command: kCheckDartPubDeps));
processManager.addCommand(const FakeCommand(command: <String>[ processManager.addCommand(const FakeCommand(command: <String>[
'xcrun', 'xcrun',
'xcodebuild', 'xcodebuild',

View File

@ -663,6 +663,8 @@ duplicate symbol '_$s29plugin_1_name23PluginNamePluginC9setDouble3key5valueySS_S
'Your project uses CocoaPods as a dependency manager, but the following plugin(s) ' 'Your project uses CocoaPods as a dependency manager, but the following plugin(s) '
'only support Swift Package Manager: plugin_1_name, plugin_2_name.' 'only support Swift Package Manager: plugin_1_name, plugin_2_name.'
)); ));
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
}); });
}); });

View File

@ -345,7 +345,7 @@ void main() {
..writeAsStringSync('Existing release config'); ..writeAsStringSync('Existing release config');
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.directory('project')); final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.directory('project'));
await injectPlugins(project, iosPlatform: true); await injectPlugins(project, iosPlatform: true, useImplicitPubspecResolution: true);
final String debugContents = projectUnderTest.ios.xcodeConfigFor('Debug').readAsStringSync(); final String debugContents = projectUnderTest.ios.xcodeConfigFor('Debug').readAsStringSync();
expect(debugContents, contains( expect(debugContents, contains(

View File

@ -27,6 +27,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -67,6 +68,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -117,6 +119,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -162,6 +165,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -210,6 +214,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -239,6 +244,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit( throwsToolExit(
@ -263,6 +269,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit( throwsToolExit(
@ -287,6 +294,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit( throwsToolExit(
@ -311,6 +319,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit( throwsToolExit(
@ -336,6 +345,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit( throwsToolExit(
@ -361,6 +371,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit(message: _kTestPluginName), throwsToolExit(message: _kTestPluginName),
@ -391,6 +402,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -423,6 +435,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -449,6 +462,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -473,6 +487,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit( throwsToolExit(
@ -495,6 +510,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -520,6 +536,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
); );
@ -538,6 +555,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit(message: 'Invalid "plugin" specification.'), throwsToolExit(message: 'Invalid "plugin" specification.'),
@ -556,6 +574,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit(message: 'Invalid "platforms" specification.'), throwsToolExit(message: 'Invalid "platforms" specification.'),
@ -576,6 +595,7 @@ void main() {
pluginYaml, pluginYaml,
null, null,
const <String>[], const <String>[],
isDevDependency: false,
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
throwsToolExit(message: 'Invalid "android" plugin specification.'), throwsToolExit(message: 'Invalid "android" plugin specification.'),

View File

@ -402,7 +402,7 @@ dependencies:
group('refreshPlugins', () { group('refreshPlugins', () {
testUsingContext('Refreshing the plugin list is a no-op when the plugins list stays empty', () async { testUsingContext('Refreshing the plugin list is a no-op when the plugins list stays empty', () async {
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(flutterProject.flutterPluginsFile.existsSync(), false); expect(flutterProject.flutterPluginsFile.existsSync(), false);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false);
@ -415,7 +415,7 @@ dependencies:
flutterProject.flutterPluginsFile.createSync(); flutterProject.flutterPluginsFile.createSync();
flutterProject.flutterPluginsDependenciesFile.createSync(); flutterProject.flutterPluginsDependenciesFile.createSync();
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(flutterProject.flutterPluginsFile.existsSync(), false); expect(flutterProject.flutterPluginsFile.existsSync(), false);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false);
@ -434,7 +434,7 @@ dependencies:
iosProject.testExists = true; iosProject.testExists = true;
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(flutterProject.flutterPluginsFile.existsSync(), true); expect(flutterProject.flutterPluginsFile.existsSync(), true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
@ -448,7 +448,7 @@ dependencies:
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('Opting out of writeLegacyPluginsList omits .flutter-plugins', () async { testUsingContext('Opting out of useImplicitPubspecResolution omits .flutter-plugins', () async {
createFakePlugins(fs, <String>[ createFakePlugins(fs, <String>[
'plugin_d', 'plugin_d',
'plugin_a', 'plugin_a',
@ -456,10 +456,13 @@ dependencies:
'/local_plugins/plugin_b', '/local_plugins/plugin_b',
]); ]);
await refreshPluginsList(flutterProject, writeLegacyPluginsList: false); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: false);
expect(flutterProject.flutterPluginsFile, isNot(exists)); expect(flutterProject.flutterPluginsFile, isNot(exists));
expect(flutterProject.flutterPluginsDependenciesFile, exists); expect(flutterProject.flutterPluginsDependenciesFile, exists);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext( testUsingContext(
@ -473,7 +476,7 @@ dependencies:
final DateTime dateCreated = DateTime(1970); final DateTime dateCreated = DateTime(1970);
systemClock.currentTime = dateCreated; systemClock.currentTime = dateCreated;
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
// Verify .flutter-plugins-dependencies is configured correctly. // Verify .flutter-plugins-dependencies is configured correctly.
expect(flutterProject.flutterPluginsFile.existsSync(), true); expect(flutterProject.flutterPluginsFile.existsSync(), true);
@ -583,7 +586,7 @@ dependencies:
final DateTime dateCreated = DateTime(1970); final DateTime dateCreated = DateTime(1970);
systemClock.currentTime = dateCreated; systemClock.currentTime = dateCreated;
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
final String pluginsString = flutterProject.flutterPluginsDependenciesFile.readAsStringSync(); final String pluginsString = flutterProject.flutterPluginsDependenciesFile.readAsStringSync();
@ -655,7 +658,7 @@ dependencies:
flutterProject.usesSwiftPackageManager = true; flutterProject.usesSwiftPackageManager = true;
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
final String pluginsString = flutterProject.flutterPluginsDependenciesFile final String pluginsString = flutterProject.flutterPluginsDependenciesFile
@ -692,7 +695,7 @@ dependencies:
flutterProject.usesSwiftPackageManager = true; flutterProject.usesSwiftPackageManager = true;
await refreshPluginsList(flutterProject, forceCocoaPodsOnly: true, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, forceCocoaPodsOnly: true, useImplicitPubspecResolution: true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
final String pluginsString = flutterProject.flutterPluginsDependenciesFile final String pluginsString = flutterProject.flutterPluginsDependenciesFile
@ -714,7 +717,7 @@ dependencies:
iosProject.testExists = true; iosProject.testExists = true;
macosProject.exists = true; macosProject.exists = true;
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true, useImplicitPubspecResolution: true);
expect(iosProject.podManifestLock.existsSync(), false); expect(iosProject.podManifestLock.existsSync(), false);
expect(macosProject.podManifestLock.existsSync(), false); expect(macosProject.podManifestLock.existsSync(), false);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -733,11 +736,11 @@ dependencies:
// Since there was no plugins list, the lock files will be invalidated. // Since there was no plugins list, the lock files will be invalidated.
// The second call is where the plugins list is compared to the existing one, and if there is no change, // The second call is where the plugins list is compared to the existing one, and if there is no change,
// the podfiles shouldn't be invalidated. // the podfiles shouldn't be invalidated.
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true, useImplicitPubspecResolution: true);
simulatePodInstallRun(iosProject); simulatePodInstallRun(iosProject);
simulatePodInstallRun(macosProject); simulatePodInstallRun(macosProject);
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(iosProject.podManifestLock.existsSync(), true); expect(iosProject.podManifestLock.existsSync(), true);
expect(macosProject.podManifestLock.existsSync(), true); expect(macosProject.podManifestLock.existsSync(), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -758,7 +761,7 @@ dependencies:
testUsingContext('Registrant uses new embedding if app uses new embedding', () async { testUsingContext('Registrant uses new embedding if app uses new embedding', () async {
androidProject.embeddingVersion = AndroidEmbeddingVersion.v2; androidProject.embeddingVersion = AndroidEmbeddingVersion.v2;
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
@ -781,7 +784,7 @@ dependencies:
await expectLater( await expectLater(
() async { () async {
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
}, },
throwsToolExit( throwsToolExit(
message: "The plugin `plugin1` doesn't have a main class defined in " message: "The plugin `plugin1` doesn't have a main class defined in "
@ -803,7 +806,7 @@ dependencies:
createDualSupportJavaPlugin4(); createDualSupportJavaPlugin4();
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
@ -824,7 +827,7 @@ dependencies:
flutterProject.isModule = true; flutterProject.isModule = true;
androidProject.embeddingVersion = AndroidEmbeddingVersion.v2; androidProject.embeddingVersion = AndroidEmbeddingVersion.v2;
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
@ -845,7 +848,7 @@ dependencies:
createNewJavaPlugin1(); createNewJavaPlugin1();
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
@ -866,7 +869,7 @@ dependencies:
createDualSupportJavaPlugin4(); createDualSupportJavaPlugin4();
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
@ -887,7 +890,7 @@ dependencies:
createDualSupportJavaPlugin4(); createDualSupportJavaPlugin4();
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
@ -905,7 +908,7 @@ dependencies:
testUsingContext('Does not throw when AndroidManifest.xml is not found', () async { testUsingContext('Does not throw when AndroidManifest.xml is not found', () async {
final File manifest = fs.file('AndroidManifest.xml'); final File manifest = fs.file('AndroidManifest.xml');
androidProject.appManifestFile = manifest; androidProject.appManifestFile = manifest;
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
@ -1015,7 +1018,7 @@ flutter:
dartPluginClass: SomePlugin dartPluginClass: SomePlugin
'''); ''');
await injectPlugins(flutterProject, androidPlatform: true); await injectPlugins(flutterProject, androidPlatform: true, useImplicitPubspecResolution: true);
final File registrantFile = androidProject.pluginRegistrantHost final File registrantFile = androidProject.pluginRegistrantHost
.childDirectory(fs.path.join('src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('src', 'main', 'java', 'io', 'flutter', 'plugins'))
@ -1044,6 +1047,7 @@ flutter:
flutterProject, flutterProject,
iosPlatform: true, iosPlatform: true,
darwinDependencyManagement: dependencyManagement, darwinDependencyManagement: dependencyManagement,
useImplicitPubspecResolution: true,
); );
final File registrantFile = iosProject.pluginRegistrantImplementation; final File registrantFile = iosProject.pluginRegistrantImplementation;
@ -1071,6 +1075,7 @@ flutter:
flutterProject, flutterProject,
macOSPlatform: true, macOSPlatform: true,
darwinDependencyManagement: dependencyManagement, darwinDependencyManagement: dependencyManagement,
useImplicitPubspecResolution: true,
); );
final File registrantFile = macosProject.managedDirectory.childFile('GeneratedPluginRegistrant.swift'); final File registrantFile = macosProject.managedDirectory.childFile('GeneratedPluginRegistrant.swift');
@ -1099,6 +1104,7 @@ flutter:
flutterProject, flutterProject,
macOSPlatform: true, macOSPlatform: true,
darwinDependencyManagement: dependencyManagement, darwinDependencyManagement: dependencyManagement,
useImplicitPubspecResolution: true,
); );
final File registrantFile = macosProject.managedDirectory.childFile('GeneratedPluginRegistrant.swift'); final File registrantFile = macosProject.managedDirectory.childFile('GeneratedPluginRegistrant.swift');
@ -1123,6 +1129,7 @@ flutter:
flutterProject, flutterProject,
macOSPlatform: true, macOSPlatform: true,
darwinDependencyManagement: dependencyManagement, darwinDependencyManagement: dependencyManagement,
useImplicitPubspecResolution: true,
); );
final File registrantFile = macosProject.managedDirectory.childFile('GeneratedPluginRegistrant.swift'); final File registrantFile = macosProject.managedDirectory.childFile('GeneratedPluginRegistrant.swift');
@ -1136,7 +1143,7 @@ flutter:
testUsingContext('Injecting creates generated Linux registrant', () async { testUsingContext('Injecting creates generated Linux registrant', () async {
createFakePlugin(fs); createFakePlugin(fs);
await injectPlugins(flutterProject, linuxPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, useImplicitPubspecResolution: true);
final File registrantHeader = linuxProject.managedDirectory.childFile('generated_plugin_registrant.h'); final File registrantHeader = linuxProject.managedDirectory.childFile('generated_plugin_registrant.h');
final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1185,7 +1192,7 @@ dependencies:
flutterProject.manifest = manifest; flutterProject.manifest = manifest;
await injectPlugins(flutterProject, linuxPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, useImplicitPubspecResolution: true);
final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1243,7 +1250,7 @@ dependencies:
flutterProject.manifest = manifest; flutterProject.manifest = manifest;
await injectPlugins(flutterProject, linuxPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, useImplicitPubspecResolution: true);
final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1266,7 +1273,7 @@ flutter:
dartPluginClass: SomePlugin dartPluginClass: SomePlugin
'''); ''');
await injectPlugins(flutterProject, linuxPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, useImplicitPubspecResolution: true);
final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1290,7 +1297,7 @@ flutter:
dartPluginClass: SomePlugin dartPluginClass: SomePlugin
'''); ''');
await injectPlugins(flutterProject, linuxPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, useImplicitPubspecResolution: true);
final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1305,7 +1312,7 @@ flutter:
testUsingContext('Injecting creates generated Linux plugin Cmake file', () async { testUsingContext('Injecting creates generated Linux plugin Cmake file', () async {
createFakePlugin(fs); createFakePlugin(fs);
await injectPlugins(flutterProject, linuxPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, useImplicitPubspecResolution: true);
final File pluginMakefile = linuxProject.generatedPluginCmakeFile; final File pluginMakefile = linuxProject.generatedPluginCmakeFile;
@ -1328,7 +1335,7 @@ flutter:
'/local_plugins/plugin_b', '/local_plugins/plugin_b',
]); ]);
await injectPlugins(flutterProject, linuxPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, useImplicitPubspecResolution: true);
final File pluginCmakeFile = linuxProject.generatedPluginCmakeFile; final File pluginCmakeFile = linuxProject.generatedPluginCmakeFile;
final File pluginRegistrant = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File pluginRegistrant = linuxProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1346,7 +1353,7 @@ flutter:
testUsingContext('Injecting creates generated Windows registrant', () async { testUsingContext('Injecting creates generated Windows registrant', () async {
createFakePlugin(fs); createFakePlugin(fs);
await injectPlugins(flutterProject, windowsPlatform: true); await injectPlugins(flutterProject, windowsPlatform: true, useImplicitPubspecResolution: true);
final File registrantHeader = windowsProject.managedDirectory.childFile('generated_plugin_registrant.h'); final File registrantHeader = windowsProject.managedDirectory.childFile('generated_plugin_registrant.h');
final File registrantImpl = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1370,7 +1377,7 @@ flutter:
dartPluginClass: SomePlugin dartPluginClass: SomePlugin
'''); ''');
await injectPlugins(flutterProject, windowsPlatform: true); await injectPlugins(flutterProject, windowsPlatform: true, useImplicitPubspecResolution: true);
final File registrantImpl = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1393,7 +1400,7 @@ flutter:
dartPluginClass: SomePlugin dartPluginClass: SomePlugin
'''); ''');
await injectPlugins(flutterProject, windowsPlatform: true); await injectPlugins(flutterProject, windowsPlatform: true, useImplicitPubspecResolution: true);
final File registrantImpl = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File registrantImpl = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1413,7 +1420,7 @@ flutter:
'/local_plugins/plugin_b', '/local_plugins/plugin_b',
]); ]);
await injectPlugins(flutterProject, windowsPlatform: true); await injectPlugins(flutterProject, windowsPlatform: true, useImplicitPubspecResolution: true);
final File pluginCmakeFile = windowsProject.generatedPluginCmakeFile; final File pluginCmakeFile = windowsProject.generatedPluginCmakeFile;
final File pluginRegistrant = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc'); final File pluginRegistrant = windowsProject.managedDirectory.childFile('generated_plugin_registrant.cc');
@ -1433,7 +1440,7 @@ flutter:
setUpProject(fsWindows); setUpProject(fsWindows);
createFakePlugin(fsWindows); createFakePlugin(fsWindows);
await injectPlugins(flutterProject, linuxPlatform: true, windowsPlatform: true); await injectPlugins(flutterProject, linuxPlatform: true, windowsPlatform: true, useImplicitPubspecResolution: true);
for (final CmakeBasedProject? project in <CmakeBasedProject?>[linuxProject, windowsProject]) { for (final CmakeBasedProject? project in <CmakeBasedProject?>[linuxProject, windowsProject]) {
final File pluginCmakefile = project!.generatedPluginCmakeFile; final File pluginCmakefile = project!.generatedPluginCmakeFile;
@ -1458,6 +1465,7 @@ flutter:
linuxPlatform: true, linuxPlatform: true,
windowsPlatform: true, windowsPlatform: true,
allowedPlugins: PreviewDevice.supportedPubPlugins, allowedPlugins: PreviewDevice.supportedPubPlugins,
useImplicitPubspecResolution: true,
), ),
throwsToolExit(message: ''' throwsToolExit(message: '''
The Flutter Preview device does not support the following plugins from your pubspec.yaml: The Flutter Preview device does not support the following plugins from your pubspec.yaml:
@ -1477,6 +1485,7 @@ The Flutter Preview device does not support the following plugins from your pubs
iosPlatform: true, iosPlatform: true,
macOSPlatform: true, macOSPlatform: true,
darwinDependencyManagement: dependencyManagement, darwinDependencyManagement: dependencyManagement,
useImplicitPubspecResolution: true,
); );
expect( expect(
dependencyManagement.setupPlatforms, dependencyManagement.setupPlatforms,
@ -1492,6 +1501,7 @@ The Flutter Preview device does not support the following plugins from your pubs
await injectPlugins( await injectPlugins(
flutterProject, flutterProject,
darwinDependencyManagement: dependencyManagement, darwinDependencyManagement: dependencyManagement,
useImplicitPubspecResolution: true,
); );
expect(dependencyManagement.setupPlatforms, <SupportedPlatform>[]); expect(dependencyManagement.setupPlatforms, <SupportedPlatform>[]);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -1511,7 +1521,7 @@ The Flutter Preview device does not support the following plugins from your pubs
linuxProject.exists = true; linuxProject.exists = true;
createFakePlugin(fs); createFakePlugin(fs);
// refreshPluginsList should call createPluginSymlinks. // refreshPluginsList should call createPluginSymlinks.
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(linuxProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true); expect(linuxProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -1524,7 +1534,7 @@ The Flutter Preview device does not support the following plugins from your pubs
windowsProject.exists = true; windowsProject.exists = true;
createFakePlugin(fs); createFakePlugin(fs);
// refreshPluginsList should call createPluginSymlinks. // refreshPluginsList should call createPluginSymlinks.
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
expect(windowsProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true); expect(windowsProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -1570,7 +1580,7 @@ The Flutter Preview device does not support the following plugins from your pubs
// refreshPluginsList should remove existing links and recreate on changes. // refreshPluginsList should remove existing links and recreate on changes.
createFakePlugin(fs); createFakePlugin(fs);
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
for (final File file in dummyFiles) { for (final File file in dummyFiles) {
expect(file.existsSync(), false); expect(file.existsSync(), false);
@ -1609,7 +1619,7 @@ The Flutter Preview device does not support the following plugins from your pubs
linuxProject.exists = true; linuxProject.exists = true;
windowsProject.exists = true; windowsProject.exists = true;
createFakePlugin(fs); createFakePlugin(fs);
await refreshPluginsList(flutterProject, writeLegacyPluginsList: true); await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
final List<Link> links = <Link>[ final List<Link> links = <Link>[
linuxProject.pluginSymlinkDirectory.childLink('some_plugin'), linuxProject.pluginSymlinkDirectory.childLink('some_plugin'),
@ -1708,6 +1718,7 @@ The Flutter Preview device does not support the following plugins from your pubs
}, },
dependencies: <String>[], dependencies: <String>[],
isDirectDependency: true, isDirectDependency: true,
isDevDependency: false,
); );
expect( expect(
@ -1733,6 +1744,7 @@ The Flutter Preview device does not support the following plugins from your pubs
}, },
dependencies: <String>[], dependencies: <String>[],
isDirectDependency: true, isDirectDependency: true,
isDevDependency: false,
); );
expect( expect(
@ -1757,6 +1769,7 @@ The Flutter Preview device does not support the following plugins from your pubs
}, },
dependencies: <String>[], dependencies: <String>[],
isDirectDependency: true, isDirectDependency: true,
isDevDependency: false,
); );
expect( expect(
@ -1786,6 +1799,7 @@ The Flutter Preview device does not support the following plugins from your pubs
}, },
dependencies: <String>[], dependencies: <String>[],
isDirectDependency: true, isDirectDependency: true,
isDevDependency: false,
); );
expect( expect(
@ -1811,6 +1825,7 @@ The Flutter Preview device does not support the following plugins from your pubs
}, },
dependencies: <String>[], dependencies: <String>[],
isDirectDependency: true, isDirectDependency: true,
isDevDependency: false,
); );
expect( expect(
@ -1835,6 +1850,7 @@ The Flutter Preview device does not support the following plugins from your pubs
}, },
dependencies: <String>[], dependencies: <String>[],
isDirectDependency: true, isDirectDependency: true,
isDevDependency: false,
); );
expect(plugin.pluginPodspecPath(fs, IOSPlugin.kConfigKey), isNull); expect(plugin.pluginPodspecPath(fs, IOSPlugin.kConfigKey), isNull);

View File

@ -141,12 +141,12 @@ void main() {
FlutterManifest.empty(logger: logger), FlutterManifest.empty(logger: logger),
FlutterManifest.empty(logger: logger), FlutterManifest.empty(logger: logger),
); );
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectNotExists(project.directory); expectNotExists(project.directory);
}); });
_testInMemory('does nothing in plugin or package root project', () async { _testInMemory('does nothing in plugin or package root project', () async {
final FlutterProject project = await aPluginProject(); final FlutterProject project = await aPluginProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectNotExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h')); expectNotExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h'));
expectNotExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app'))); expectNotExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app')));
expectNotExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig')); expectNotExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig'));
@ -158,7 +158,7 @@ void main() {
// that a project was a plugin, but shouldn't be as this creates false // that a project was a plugin, but shouldn't be as this creates false
// positives. // positives.
project.directory.childDirectory('example').createSync(); project.directory.childDirectory('example').createSync();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h')); expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h'));
expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app'))); expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app')));
expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig')); expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig'));
@ -166,22 +166,22 @@ void main() {
}); });
_testInMemory('injects plugins for iOS', () async { _testInMemory('injects plugins for iOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h')); expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h'));
}); });
_testInMemory('generates Xcode configuration for iOS', () async { _testInMemory('generates Xcode configuration for iOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig')); expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig'));
}); });
_testInMemory('injects plugins for Android', () async { _testInMemory('injects plugins for Android', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app'))); expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app')));
}); });
_testInMemory('updates local properties for Android', () async { _testInMemory('updates local properties for Android', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.android.hostAppGradleRoot.childFile('local.properties')); expectExists(project.android.hostAppGradleRoot.childFile('local.properties'));
}); });
_testInMemory('checkForDeprecation fails on invalid android app manifest file', () async { _testInMemory('checkForDeprecation fails on invalid android app manifest file', () async {
@ -224,18 +224,18 @@ void main() {
final FlutterProject project = await aPluginProject(); final FlutterProject project = await aPluginProject();
project.example.directory.deleteSync(); project.example.directory.deleteSync();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expect(testLogger.statusText, isNot(contains('https://github.com/flutter/flutter/blob/main/docs/platforms/android/Upgrading-pre-1.12-Android-projects.md'))); expect(testLogger.statusText, isNot(contains('https://github.com/flutter/flutter/blob/main/docs/platforms/android/Upgrading-pre-1.12-Android-projects.md')));
}); });
_testInMemory('updates local properties for Android', () async { _testInMemory('updates local properties for Android', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.android.hostAppGradleRoot.childFile('local.properties')); expectExists(project.android.hostAppGradleRoot.childFile('local.properties'));
}); });
testUsingContext('injects plugins for macOS', () async { testUsingContext('injects plugins for macOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.macos.managedDirectory.createSync(recursive: true); project.macos.managedDirectory.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.macos.pluginRegistrantImplementation); expectExists(project.macos.pluginRegistrantImplementation);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
@ -249,7 +249,7 @@ void main() {
testUsingContext('generates Xcode configuration for macOS', () async { testUsingContext('generates Xcode configuration for macOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.macos.managedDirectory.createSync(recursive: true); project.macos.managedDirectory.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.macos.generatedXcodePropertiesFile); expectExists(project.macos.generatedXcodePropertiesFile);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
@ -263,7 +263,7 @@ void main() {
testUsingContext('injects plugins for Linux', () async { testUsingContext('injects plugins for Linux', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.linux.cmakeFile.createSync(recursive: true); project.linux.cmakeFile.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.h')); expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.h'));
expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.cc')); expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.cc'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -278,7 +278,7 @@ void main() {
testUsingContext('injects plugins for Windows', () async { testUsingContext('injects plugins for Windows', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.windows.cmakeFile.createSync(recursive: true); project.windows.cmakeFile.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.h')); expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.h'));
expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.cc')); expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.cc'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -292,14 +292,14 @@ void main() {
}); });
_testInMemory('creates Android library in module', () async { _testInMemory('creates Android library in module', () async {
final FlutterProject project = await aModuleProject(); final FlutterProject project = await aModuleProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
expectExists(project.android.hostAppGradleRoot.childFile('settings.gradle')); expectExists(project.android.hostAppGradleRoot.childFile('settings.gradle'));
expectExists(project.android.hostAppGradleRoot.childFile('local.properties')); expectExists(project.android.hostAppGradleRoot.childFile('local.properties'));
expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('Flutter'))); expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('Flutter')));
}); });
_testInMemory('creates iOS pod in module', () async { _testInMemory('creates iOS pod in module', () async {
final FlutterProject project = await aModuleProject(); final FlutterProject project = await aModuleProject();
await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true); await project.regeneratePlatformSpecificTooling(useImplicitPubspecResolution: true);
final Directory flutter = project.ios.hostAppRoot.childDirectory('Flutter'); final Directory flutter = project.ios.hostAppRoot.childDirectory('Flutter');
expectExists(flutter.childFile('podhelper.rb')); expectExists(flutter.childFile('podhelper.rb'));
expectExists(flutter.childFile('flutter_export_environment.sh')); expectExists(flutter.childFile('flutter_export_environment.sh'));

View File

@ -637,7 +637,7 @@ void main() {
Pub: () => FakePub(), Pub: () => FakePub(),
Usage: () => usage, Usage: () => usage,
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => processManager, ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('use packagesPath to generate BuildInfo', () async { testUsingContext('use packagesPath to generate BuildInfo', () async {

View File

@ -139,6 +139,8 @@ void main() {
), ),
true, true,
); );
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('WebBuilder throws tool exit on failure', () async { testUsingContext('WebBuilder throws tool exit on failure', () async {
@ -178,5 +180,7 @@ void main() {
expect(logger.errorText, contains('Target hello failed: FormatException: illegal character in input string')); expect(logger.errorText, contains('Target hello failed: FormatException: illegal character in input string'));
expect(testUsage.timings, isEmpty); expect(testUsage.timings, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty); expect(fakeAnalytics.sentEvents, isEmpty);
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
}); });
} }

View File

@ -38,6 +38,7 @@ void main() {
}, },
dependencies: <String>[], dependencies: <String>[],
isDirectDependency: true, isDirectDependency: true,
isDevDependency: false,
), ),
], renderer); ], renderer);