From d70d0913b20c38be06a2c3fa7d1a355bda4659fa Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Sat, 9 May 2020 17:50:46 -0700 Subject: [PATCH] Revert "[flutter_tools] integrate l10n tool into build/run (#56167)" (#56800) This reverts commit f865ac7e259d320d7e565f887f894f293a463782. --- .../lib/src/base/command_help.dart | 6 - .../src/build_runner/resident_web_runner.dart | 1 - .../lib/src/build_system/build_system.dart | 34 +-- .../lib/src/build_system/targets/dart.dart | 5 +- .../build_system/targets/localizations.dart | 272 ------------------ .../lib/src/build_system/targets/web.dart | 4 +- .../lib/src/resident_runner.dart | 43 +-- packages/flutter_tools/lib/src/run_hot.dart | 10 +- .../general.shard/base/command_help_test.dart | 4 - .../build_system/build_system_test.dart | 56 +--- .../targets/localizations_test.dart | 131 --------- .../general.shard/resident_runner_test.dart | 57 ---- .../test/integration.shard/gen_l10n_test.dart | 46 ++- .../test_data/gen_l10n_project.dart | 17 +- 14 files changed, 54 insertions(+), 632 deletions(-) delete mode 100644 packages/flutter_tools/lib/src/build_system/targets/localizations.dart delete mode 100644 packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart diff --git a/packages/flutter_tools/lib/src/base/command_help.dart b/packages/flutter_tools/lib/src/base/command_help.dart index 9d1f56d796e..8886659af23 100644 --- a/packages/flutter_tools/lib/src/base/command_help.dart +++ b/packages/flutter_tools/lib/src/base/command_help.dart @@ -88,12 +88,6 @@ class CommandHelp { 'Detach (terminate "flutter run" but leave application running).', ); - CommandHelpOption _g; - CommandHelpOption get g => _g ??= _makeOption( - 'g', - 'Run source code generators.' - ); - CommandHelpOption _h; CommandHelpOption get h => _h ??= _makeOption( 'h', diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart index 58b55be5bf0..b3cb71d210d 100644 --- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart @@ -486,7 +486,6 @@ class _ResidentWebRunner extends ResidentWebRunner { ); if (debuggingOptions.buildInfo.isDebug) { - await runSourceGenerators(); // Full restart is always false for web, since the extra recompile is wasteful. final UpdateFSReport report = await _updateDevFS(fullRestart: false); if (report.success) { diff --git a/packages/flutter_tools/lib/src/build_system/build_system.dart b/packages/flutter_tools/lib/src/build_system/build_system.dart index 0b336d47466..9103f8feb81 100644 --- a/packages/flutter_tools/lib/src/build_system/build_system.dart +++ b/packages/flutter_tools/lib/src/build_system/build_system.dart @@ -134,12 +134,6 @@ abstract class Target { /// A list of zero or more depfiles, located directly under {BUILD_DIR}. List get depfiles => const []; - /// Whether this target can be executed with the given [environment]. - /// - /// Returning `true` will cause [build] to be skipped. This is equivalent - /// to a build that produces no outputs. - bool canSkip(Environment environment) => false; - /// The action which performs this build step. Future build(Environment environment); @@ -760,26 +754,18 @@ class _BuildInstance { updateGraph(); return succeeded; } - // Clear old inputs. These will be replaced with new inputs/outputs - // after the target is run. In the case of a runtime skip, each list - // must be empty to ensure the previous outputs are purged. - node.inputs.clear(); - node.outputs.clear(); + logger.printTrace('${node.target.name}: Starting due to ${node.invalidatedReasons}'); + await node.target.build(environment); + logger.printTrace('${node.target.name}: Complete'); - // Check if we can skip via runtime dependencies. - final bool runtimeSkip = node.target.canSkip(environment); - if (runtimeSkip) { - logger.printTrace('Skipping target: ${node.target.name}'); - skipped = true; - } else { - logger.printTrace('${node.target.name}: Starting due to ${node.invalidatedReasons}'); - await node.target.build(environment); - logger.printTrace('${node.target.name}: Complete'); - node.inputs.addAll(node.target.resolveInputs(environment).sources); - node.outputs.addAll(node.target.resolveOutputs(environment).sources); - } + node.inputs + ..clear() + ..addAll(node.target.resolveInputs(environment).sources); + node.outputs + ..clear() + ..addAll(node.target.resolveOutputs(environment).sources); - // If we were missing the depfile, resolve input files after executing the + // If we were missing the depfile, resolve input files after executing the // target so that all file hashes are up to date on the next run. if (node.missingDepfile) { await fileCache.diffFileList(node.inputs); diff --git a/packages/flutter_tools/lib/src/build_system/targets/dart.dart b/packages/flutter_tools/lib/src/build_system/targets/dart.dart index a084fd77283..94ac5c4fc0b 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/dart.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/dart.dart @@ -17,7 +17,6 @@ import '../depfile.dart'; import '../exceptions.dart'; import 'assets.dart'; import 'icon_tree_shaker.dart'; -import 'localizations.dart'; /// The define to pass a [BuildMode]. const String kBuildMode = 'BuildMode'; @@ -184,9 +183,7 @@ class KernelSnapshot extends Target { ]; @override - List get dependencies => const [ - GenerateLocalizationsTarget(), - ]; + List get dependencies => []; @override Future build(Environment environment) async { diff --git a/packages/flutter_tools/lib/src/build_system/targets/localizations.dart b/packages/flutter_tools/lib/src/build_system/targets/localizations.dart deleted file mode 100644 index 95539e9204a..00000000000 --- a/packages/flutter_tools/lib/src/build_system/targets/localizations.dart +++ /dev/null @@ -1,272 +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 'package:meta/meta.dart'; -import 'package:process/process.dart'; -import 'package:yaml/yaml.dart'; - -import '../../artifacts.dart'; -import '../../base/file_system.dart'; -import '../../base/io.dart'; -import '../../base/logger.dart'; -import '../../convert.dart'; -import '../../globals.dart' as globals; -import '../build_system.dart'; -import '../depfile.dart'; - -const String _kDependenciesFileName = 'gen_l10n_inputs_and_outputs.json'; - -/// Run the localizations generation script with the configuration [options]. -Future generateLocalizations({ - @required LocalizationOptions options, - @required String flutterRoot, - @required FileSystem fileSystem, - @required ProcessManager processManager, - @required Logger logger, - @required Directory projectDir, - @required String dartBinaryPath, - @required Directory dependenciesDir, -}) async { - final String genL10nPath = fileSystem.path.join( - flutterRoot, - 'dev', - 'tools', - 'localization', - 'bin', - 'gen_l10n.dart', - ); - final ProcessResult result = await processManager.run([ - dartBinaryPath, - genL10nPath, - '--gen-inputs-and-outputs-list=${dependenciesDir.path}', - if (options.arbDirectory != null) - '--arb-dir=${options.arbDirectory.toFilePath()}', - if (options.templateArbFile != null) - '--template-arb-file=${options.templateArbFile.toFilePath()}', - if (options.outputLocalizationsFile != null) - '--output-localization-file=${options.outputLocalizationsFile.toFilePath()}', - if (options.untranslatedMessagesFile != null) - '--untranslated-messages-file=${options.untranslatedMessagesFile.toFilePath()}', - if (options.outputClass != null) - '--output-class=${options.outputClass}', - if (options.headerFile != null) - '--header-file=${options.headerFile.toFilePath()}', - if (options.header != null) - '--header=${options.header}', - if (options.deferredLoading != null) - '--use-deferred-loading', - if (options.preferredSupportedLocales != null) - '--preferred-supported-locales=${options.preferredSupportedLocales}', - ]); - if (result.exitCode != 0) { - logger.printError(result.stdout + result.stderr as String); - throw Exception(); - } -} - -/// A build step that runs the generate localizations script from -/// dev/tool/localizations. -class GenerateLocalizationsTarget extends Target { - const GenerateLocalizationsTarget(); - - @override - List get dependencies => []; - - @override - List get inputs => [ - // This is added as a convenience for developing the tool. - const Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/localizations.dart'), - // TODO(jonahwilliams): once https://github.com/flutter/flutter/issues/56321 is - // complete, we should add the artifact as a dependency here. Since the tool runs - // this code from source, looking up each dependency will be cumbersome. - ]; - - @override - String get name => 'gen_localizations'; - - @override - List get outputs => []; - - @override - List get depfiles => ['gen_localizations.d']; - - @override - bool canSkip(Environment environment) { - final File configFile = environment.projectDir.childFile('l10n.yaml'); - return !configFile.existsSync(); - } - - @override - Future build(Environment environment) async { - final File configFile = environment.projectDir.childFile('l10n.yaml'); - assert(configFile.existsSync()); - - final LocalizationOptions options = parseLocalizationsOptions( - file: configFile, - logger: globals.logger, - ); - final DepfileService depfileService = DepfileService( - logger: environment.logger, - fileSystem: environment.fileSystem, - ); - - await generateLocalizations( - fileSystem: environment.fileSystem, - flutterRoot: environment.flutterRootDir.path, - logger: environment.logger, - processManager: environment.processManager, - options: options, - projectDir: environment.projectDir, - dartBinaryPath: environment.artifacts - .getArtifactPath(Artifact.engineDartBinary), - dependenciesDir: environment.buildDir, - ); - final Map dependencies = json - .decode(environment.buildDir.childFile(_kDependenciesFileName).readAsStringSync()) as Map; - final Depfile depfile = Depfile( - [ - configFile, - for (dynamic inputFile in dependencies['inputs'] as List) - environment.fileSystem.file(inputFile) - ], - [ - for (dynamic outputFile in dependencies['outputs'] as List) - environment.fileSystem.file(outputFile) - ] - ); - depfileService.writeToFile( - depfile, - environment.buildDir.childFile('gen_localizations.d'), - ); - } -} - -/// Typed configuration from the localizations config file. -class LocalizationOptions { - const LocalizationOptions({ - this.arbDirectory, - this.templateArbFile, - this.outputLocalizationsFile, - this.untranslatedMessagesFile, - this.header, - this.outputClass, - this.preferredSupportedLocales, - this.headerFile, - this.deferredLoading, - }); - - /// The `--arb-dir` argument. - /// - /// The directory where all localization files should reside. - final Uri arbDirectory; - - /// The `--template-arb-file` argument. - /// - /// This URI is relative to [arbDirectory]. - final Uri templateArbFile; - - /// The `--output-localization-file` argument. - /// - /// This URI is relative to [arbDirectory]. - final Uri outputLocalizationsFile; - - /// The `--untranslated-messages-file` argument. - /// - /// This URI is relative to [arbDirectory]. - final Uri untranslatedMessagesFile; - - /// The `--header` argument. - /// - /// The header to prepend to the generated Dart localizations - final String header; - - /// The `--output-class` argument. - final String outputClass; - - /// The `--preferred-supported-locales` argument. - final String preferredSupportedLocales; - - /// The `--header-file` argument. - /// - /// A file containing the header to preprend to the generated - /// Dart localizations. - final Uri headerFile; - - /// The `--use-deferred-loading` argument. - /// - /// Whether to generate the Dart localization file with locales imported - /// as deferred. - final bool deferredLoading; -} - -/// Parse the localizations configuration options from [file]. -/// -/// Throws [Exception] if any of the contents are invalid. Returns a -/// [LocalizationOptions] with all fields as `null` if the config file exists -/// but is empty. -LocalizationOptions parseLocalizationsOptions({ - @required File file, - @required Logger logger, -}) { - final String contents = file.readAsStringSync(); - if (contents.trim().isEmpty) { - return const LocalizationOptions(); - } - final YamlNode yamlNode = loadYamlNode(file.readAsStringSync()); - if (yamlNode is! YamlMap) { - logger.printError('Expected ${file.path} to contain a map, instead was $yamlNode'); - throw Exception(); - } - final YamlMap yamlMap = yamlNode as YamlMap; - return LocalizationOptions( - arbDirectory: _tryReadUri(yamlMap, 'arb-dir', logger), - templateArbFile: _tryReadUri(yamlMap, 'template-arb-file', logger), - outputLocalizationsFile: _tryReadUri(yamlMap, 'output-localization-file', logger), - untranslatedMessagesFile: _tryReadUri(yamlMap, 'untranslated-messages-file', logger), - header: _tryReadString(yamlMap, 'header', logger), - outputClass: _tryReadString(yamlMap, 'output-class', logger), - preferredSupportedLocales: _tryReadString(yamlMap, 'preferred-supported-locales', logger), - headerFile: _tryReadUri(yamlMap, 'header-file', logger), - deferredLoading: _tryReadBool(yamlMap, 'use-deferred-loading', logger), - ); -} - -// Try to read a `bool` value or null from `yamlMap`, otherwise throw. -bool _tryReadBool(YamlMap yamlMap, String key, Logger logger) { - final Object value = yamlMap[key]; - if (value == null) { - return null; - } - if (value is! bool) { - logger.printError('Expected "$key" to have a bool value, instead was "$value"'); - throw Exception(); - } - return value as bool; -} - -// Try to read a `String` value or null from `yamlMap`, otherwise throw. -String _tryReadString(YamlMap yamlMap, String key, Logger logger) { - final Object value = yamlMap[key]; - if (value == null) { - return null; - } - if (value is! String) { - logger.printError('Expected "$key" to have a String value, instead was "$value"'); - throw Exception(); - } - return value as String; -} - -// Try to read a valid `Uri` or null from `yamlMap`, otherwise throw. -Uri _tryReadUri(YamlMap yamlMap, String key, Logger logger) { - final String value = _tryReadString(yamlMap, key, logger); - if (value == null) { - return null; - } - final Uri uri = Uri.tryParse(value); - if (uri == null) { - logger.printError('"$value" must be a relative file URI'); - } - return uri; -} diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart index 8e1cae6c219..e640ed2b463 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/web.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart @@ -15,7 +15,6 @@ import '../build_system.dart'; import '../depfile.dart'; import 'assets.dart'; import 'dart.dart'; -import 'localizations.dart'; /// Whether web builds should call the platform initialization logic. const String kInitializePlatform = 'InitializePlatform'; @@ -133,8 +132,7 @@ class Dart2JSTarget extends Target { @override List get dependencies => const [ - WebEntrypointTarget(), - GenerateLocalizationsTarget(), + WebEntrypointTarget() ]; @override diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 5cf1bb80254..d9d044db32f 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -4,10 +4,10 @@ import 'dart:async'; +import 'package:vm_service/vm_service.dart' as vm_service; import 'package:devtools_server/devtools_server.dart' as devtools_server; import 'package:meta/meta.dart'; import 'package:package_config/package_config.dart'; -import 'package:vm_service/vm_service.dart' as vm_service; import 'application_package.dart'; import 'artifacts.dart'; @@ -21,10 +21,7 @@ import 'base/signals.dart'; import 'base/terminal.dart'; import 'base/utils.dart'; import 'build_info.dart'; -import 'build_system/build_system.dart'; -import 'build_system/targets/localizations.dart'; import 'bundle.dart'; -import 'cache.dart'; import 'codegen.dart'; import 'compile.dart'; import 'convert.dart'; @@ -801,40 +798,6 @@ abstract class ResidentRunner { throw '${fullRestart ? 'Restart' : 'Reload'} is not supported in $mode mode'; } - - BuildResult _lastBuild; - Environment _environment; - Future runSourceGenerators() async { - _environment ??= Environment( - artifacts: globals.artifacts, - logger: globals.logger, - cacheDir: globals.cache.getRoot(), - engineVersion: globals.flutterVersion.engineRevision, - fileSystem: globals.fs, - flutterRootDir: globals.fs.directory(Cache.flutterRoot), - outputDir: globals.fs.directory(getBuildDirectory()), - processManager: globals.processManager, - projectDir: globals.fs.currentDirectory, - ); - globals.logger.printTrace('Starting incremental build...'); - _lastBuild = await globals.buildSystem.buildIncremental( - const GenerateLocalizationsTarget(), - _environment, - _lastBuild, - ); - if (!_lastBuild.success) { - for (final ExceptionMeasurement exceptionMeasurement in _lastBuild.exceptions.values) { - globals.logger.printError( - exceptionMeasurement.exception.toString(), - stackTrace: globals.logger.isVerbose - ? exceptionMeasurement.stackTrace - : null, - ); - } - } - globals.logger.printTrace('complete'); - } - /// Toggle whether canvaskit is being used for rendering, returning the new /// state. /// @@ -1235,7 +1198,6 @@ abstract class ResidentRunner { commandHelp.p.print(); commandHelp.o.print(); commandHelp.z.print(); - commandHelp.g.print(); } else { commandHelp.S.print(); commandHelp.U.print(); @@ -1373,9 +1335,6 @@ class TerminalHandler { case 'D': await residentRunner.detach(); return true; - case 'g': - await residentRunner.runSourceGenerators(); - return true; case 'h': case 'H': case '?': diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index 33bd40e30ba..3526131e5d8 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -7,8 +7,8 @@ import 'package:package_config/package_config.dart'; import 'package:vm_service/vm_service.dart' as vm_service; import 'package:meta/meta.dart'; import 'package:pool/pool.dart'; - import 'base/async_guard.dart'; + import 'base/context.dart'; import 'base/file_system.dart'; import 'base/logger.dart'; @@ -365,7 +365,6 @@ class HotRunner extends ResidentRunner { // build, reducing overall initialization time. This is safe because the first // invocation of the frontend server produces a full dill file that the // subsequent invocation in devfs will not overwrite. - await runSourceGenerators(); if (device.generator != null) { startupTasks.add( device.generator.recompile( @@ -675,10 +674,6 @@ class HotRunner extends ResidentRunner { emulator = false; } final Stopwatch timer = Stopwatch()..start(); - - // Run source generation if needed. - await runSourceGenerators(); - if (fullRestart) { final OperationResult result = await _fullRestartHelper( targetPlatform: targetPlatform, @@ -1195,7 +1190,7 @@ class ProjectFileInvalidator { static const String _pubCachePathWindows = 'Pub/Cache'; // As of writing, Dart supports up to 32 asynchronous I/O threads per - // isolate. We also want to avoid hitting platform limits on open file + // isolate. We also want to avoid hitting platform limits on open file // handles/descriptors. // // This value was chosen based on empirical tests scanning a set of @@ -1228,6 +1223,7 @@ class ProjectFileInvalidator { if (_isNotInPubCache(uri)) uri, ]; final List invalidatedFiles = []; + if (asyncScanning) { final Pool pool = Pool(_kMaxPendingStats); final List> waitList = >[]; diff --git a/packages/flutter_tools/test/general.shard/base/command_help_test.dart b/packages/flutter_tools/test/general.shard/base/command_help_test.dart index 40f7d01fca3..07ad962b6ed 100644 --- a/packages/flutter_tools/test/general.shard/base/command_help_test.dart +++ b/packages/flutter_tools/test/general.shard/base/command_help_test.dart @@ -57,7 +57,6 @@ void _testMessageLength({ expect(commandHelp.U.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.a.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.d.toString().length, lessThanOrEqualTo(expectedWidth)); - expect(commandHelp.g.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.h.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.i.toString().length, lessThanOrEqualTo(expectedWidth)); expect(commandHelp.k.toString().length, lessThanOrEqualTo(expectedWidth)); @@ -89,7 +88,6 @@ void main() { expect(commandHelp.U.toString(), startsWith('\x1B[1mU\x1B[22m')); expect(commandHelp.a.toString(), startsWith('\x1B[1ma\x1B[22m')); expect(commandHelp.d.toString(), startsWith('\x1B[1md\x1B[22m')); - expect(commandHelp.g.toString(), startsWith('\x1B[1mg\x1B[22m')); expect(commandHelp.h.toString(), startsWith('\x1B[1mh\x1B[22m')); expect(commandHelp.i.toString(), startsWith('\x1B[1mi\x1B[22m')); expect(commandHelp.o.toString(), startsWith('\x1B[1mo\x1B[22m')); @@ -166,7 +164,6 @@ void main() { expect(commandHelp.U.toString(), equals('\x1B[1mU\x1B[22m Dump accessibility tree in inverse hit test order. \x1B[1;30m(debugDumpSemantics)\x1B[39m')); expect(commandHelp.a.toString(), equals('\x1B[1ma\x1B[22m Toggle timeline events for all widget build methods. \x1B[1;30m(debugProfileWidgetBuilds)\x1B[39m')); expect(commandHelp.d.toString(), equals('\x1B[1md\x1B[22m Detach (terminate "flutter run" but leave application running).')); - expect(commandHelp.g.toString(), equals('\x1B[1mg\x1B[22m Run source code generators.')); expect(commandHelp.h.toString(), equals('\x1B[1mh\x1B[22m Repeat this help message.')); expect(commandHelp.i.toString(), equals('\x1B[1mi\x1B[22m Toggle widget inspector. \x1B[1;30m(WidgetsApp.showWidgetInspectorOverride)\x1B[39m')); expect(commandHelp.o.toString(), equals('\x1B[1mo\x1B[22m Simulate different operating systems. \x1B[1;30m(defaultTargetPlatform)\x1B[39m')); @@ -193,7 +190,6 @@ void main() { expect(commandHelp.U.toString(), equals('U Dump accessibility tree in inverse hit test order. (debugDumpSemantics)')); expect(commandHelp.a.toString(), equals('a Toggle timeline events for all widget build methods. (debugProfileWidgetBuilds)')); expect(commandHelp.d.toString(), equals('d Detach (terminate "flutter run" but leave application running).')); - expect(commandHelp.g.toString(), equals('g Run source code generators.')); expect(commandHelp.h.toString(), equals('h Repeat this help message.')); expect(commandHelp.i.toString(), equals('i Toggle widget inspector. (WidgetsApp.showWidgetInspectorOverride)')); expect(commandHelp.o.toString(), equals('o Simulate different operating systems. (defaultTargetPlatform)')); diff --git a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart index ecd6820db83..6128615805c 100644 --- a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart @@ -565,50 +565,6 @@ void main() { expect(fileSystem.file('output/debug'), isNot(exists)); expect(fileSystem.file('output/release'), exists); }); - - testWithoutContext('A target using canSkip can create a conditional output', () async { - final BuildSystem buildSystem = setUpBuildSystem(fileSystem); - final File bar = environment.buildDir.childFile('bar'); - final File foo = environment.buildDir.childFile('foo'); - - // The target will write a file `foo`, but only if `bar` already exists. - final TestTarget target = TestTarget( - (Environment environment) async { - foo.writeAsStringSync(bar.readAsStringSync()); - environment.buildDir - .childFile('example.d') - .writeAsStringSync('${foo.path}: ${bar.path}'); - }, - (Environment environment) { - return !environment.buildDir.childFile('bar').existsSync(); - } - ) - ..depfiles = const ['example.d']; - - // bar does not exist, there should be no inputs/outputs. - final BuildResult firstResult = await buildSystem.build(target, environment); - - expect(foo, isNot(exists)); - expect(firstResult.inputFiles, isEmpty); - expect(firstResult.outputFiles, isEmpty); - - // bar is created, the target should be able to run. - bar.writeAsStringSync('content-1'); - final BuildResult secondResult = await buildSystem.build(target, environment); - - expect(foo, exists); - expect(secondResult.inputFiles.map((File file) => file.path), [bar.path]); - expect(secondResult.outputFiles.map((File file) => file.path), [foo.path]); - - // bar is destroyed, foo is also deleted. - bar.deleteSync(); - final BuildResult thirdResult = await buildSystem.build(target, environment); - - expect(foo, isNot(exists)); - expect(thirdResult.inputFiles, isEmpty); - expect(thirdResult.outputFiles, isEmpty); - }); - } BuildSystem setUpBuildSystem(FileSystem fileSystem) { @@ -620,20 +576,10 @@ BuildSystem setUpBuildSystem(FileSystem fileSystem) { } class TestTarget extends Target { - TestTarget([this._build, this._canSkip]); + TestTarget([this._build]); final Future Function(Environment environment) _build; - final bool Function(Environment environment) _canSkip; - - @override - bool canSkip(Environment environment) { - if (_canSkip != null) { - return _canSkip(environment); - } - return super.canSkip(environment); - } - @override Future build(Environment environment) => _build(environment); diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart deleted file mode 100644 index ce781c3f9ac..00000000000 --- a/packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart +++ /dev/null @@ -1,131 +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 'package:file/memory.dart'; -import 'package:flutter_tools/src/base/file_system.dart'; -import 'package:flutter_tools/src/base/logger.dart'; -import 'package:flutter_tools/src/build_system/build_system.dart'; -import 'package:flutter_tools/src/build_system/targets/localizations.dart'; - -import '../../../src/common.dart'; -import '../../../src/context.dart'; - -void main() { - // Verifies that values are correctly passed through the localizations - // target, but does not validate them beyond the serialized data type. - testWithoutContext('generateLocalizations forwards arguments correctly', () async { - final FileSystem fileSystem = MemoryFileSystem.test(); - final Logger logger = BufferLogger.test(); - final FakeProcessManager processManager = FakeProcessManager.list([ - const FakeCommand( - command: [ - 'dart', - 'dev/tools/localization/bin/gen_l10n.dart', - '--gen-inputs-and-outputs-list=/', - '--arb-dir=arb', - '--template-arb-file=example.arb', - '--output-localization-file=bar', - '--untranslated-messages-file=untranslated', - '--output-class=Foo', - '--header-file=header', - '--header=HEADER', - '--use-deferred-loading', - '--preferred-supported-locales=en_US' - ], - ), - ]); - final Directory arbDirectory = fileSystem.directory('arb') - ..createSync(); - arbDirectory.childFile('foo.arb').createSync(); - arbDirectory.childFile('bar.arb').createSync(); - - final LocalizationOptions options = LocalizationOptions( - header: 'HEADER', - headerFile: Uri.file('header'), - arbDirectory: Uri.file('arb'), - deferredLoading: true, - outputClass: 'Foo', - outputLocalizationsFile: Uri.file('bar'), - preferredSupportedLocales: 'en_US', - templateArbFile: Uri.file('example.arb'), - untranslatedMessagesFile: Uri.file('untranslated'), - ); - await generateLocalizations( - options: options, - logger: logger, - fileSystem: fileSystem, - processManager: processManager, - projectDir: fileSystem.currentDirectory, - dartBinaryPath: 'dart', - flutterRoot: '', - dependenciesDir: fileSystem.currentDirectory, - ); - - expect(processManager.hasRemainingExpectations, false); - }); - - testWithoutContext('generateLocalizations is skipped if l10n.yaml does not exist.', () async { - final FileSystem fileSystem = MemoryFileSystem.test(); - final Environment environment = Environment.test( - fileSystem.currentDirectory, - artifacts: null, - fileSystem: fileSystem, - logger: BufferLogger.test(), - processManager: FakeProcessManager.any(), - ); - - expect(const GenerateLocalizationsTarget().canSkip(environment), true); - - environment.projectDir.childFile('l10n.yaml').createSync(); - - expect(const GenerateLocalizationsTarget().canSkip(environment), false); - }); - - testWithoutContext('parseLocalizationsOptions handles valid yaml configuration', () async { - final FileSystem fileSystem = MemoryFileSystem.test(); - final File configFile = fileSystem.file('l10n.yaml') - ..writeAsStringSync(''' -arb-dir: arb -template-arb-file: example.arb -output-localization-file: bar -untranslated-messages-file: untranslated -output-class: Foo -header-file: header -header: HEADER -use-deferred-loading: true -preferred-supported-locales: en_US -'''); - - final LocalizationOptions options = parseLocalizationsOptions( - file: configFile, - logger: BufferLogger.test(), - ); - - expect(options.arbDirectory, Uri.parse('arb')); - expect(options.templateArbFile, Uri.parse('example.arb')); - expect(options.outputLocalizationsFile, Uri.parse('bar')); - expect(options.untranslatedMessagesFile, Uri.parse('untranslated')); - expect(options.outputClass, 'Foo'); - expect(options.headerFile, Uri.parse('header')); - expect(options.header, 'HEADER'); - expect(options.deferredLoading, true); - expect(options.preferredSupportedLocales, 'en_US'); - }); - - testWithoutContext('parseLocalizationsOptions throws exception on invalid yaml configuration', () async { - final FileSystem fileSystem = MemoryFileSystem.test(); - final File configFile = fileSystem.file('l10n.yaml') - ..writeAsStringSync(''' -use-deferred-loading: string -'''); - - expect( - () => parseLocalizationsOptions( - file: configFile, - logger: BufferLogger.test(), - ), - throwsA(isA()), - ); - }); -} diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart index 2635ba66fb6..6757be6f7a0 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:flutter_tools/src/cache.dart'; import 'package:vm_service/vm_service.dart' as vm_service; import 'package:file/memory.dart'; import 'package:file_testing/file_testing.dart'; @@ -538,61 +537,6 @@ void main() { expect(cacheDill, isNot(exists)); })); - test('ResidentRunner can run source generation', () => testbed.run(() async { - final FakeProcessManager processManager = globals.processManager as FakeProcessManager; - final Directory dependencies = globals.fs.directory( - globals.fs.path.join('build', '6ec2559087977927717927ede0a147f1')); - processManager.addCommand(FakeCommand( - command: [ - globals.artifacts.getArtifactPath(Artifact.engineDartBinary), - globals.fs.path.join(Cache.flutterRoot, 'dev', 'tools', 'localization', 'bin', 'gen_l10n.dart'), - '--gen-inputs-and-outputs-list=${dependencies.absolute.path}', - ], - onRun: () { - dependencies - .childFile('gen_l10n_inputs_and_outputs.json') - ..createSync() - ..writeAsStringSync('{"inputs":[],"outputs":[]}'); - } - )); - globals.fs.file(globals.fs.path.join('lib', 'l10n', 'foo.arb')) - .createSync(recursive: true); - globals.fs.file('l10n.yaml').createSync(); - - await residentRunner.runSourceGenerators(); - - expect(testLogger.errorText, isEmpty); - }, overrides: { - ProcessManager: () => FakeProcessManager.list([]), - })); - - test('ResidentRunner can run source generation - generation fails', () => testbed.run(() async { - final FakeProcessManager processManager = globals.processManager as FakeProcessManager; - final Directory dependencies = globals.fs.directory( - globals.fs.path.join('build', '6ec2559087977927717927ede0a147f1')); - processManager.addCommand(FakeCommand( - command: [ - globals.artifacts.getArtifactPath(Artifact.engineDartBinary), - globals.fs.path.join(Cache.flutterRoot, 'dev', 'tools', 'localization', 'bin', 'gen_l10n.dart'), - '--gen-inputs-and-outputs-list=${dependencies.absolute.path}', - ], - exitCode: 1, - stderr: 'stderr' - )); - globals.fs.file(globals.fs.path.join('lib', 'l10n', 'foo.arb')) - .createSync(recursive: true); - globals.fs.file('l10n.yaml').createSync(); - - await residentRunner.runSourceGenerators(); - - expect(testLogger.errorText, allOf( - contains('stderr'), // Message from gen_l10n.dart - contains('Exception') // Message from build_system - )); - }, overrides: { - ProcessManager: () => FakeProcessManager.list([]), - })); - test('ResidentRunner printHelpDetails', () => testbed.run(() { fakeVmServiceHost = FakeVmServiceHost(requests: []); when(mockDevice.supportsHotRestart).thenReturn(true); @@ -629,7 +573,6 @@ void main() { commandHelp.p, commandHelp.o, commandHelp.z, - commandHelp.g, commandHelp.M, commandHelp.v, commandHelp.P, diff --git a/packages/flutter_tools/test/integration.shard/gen_l10n_test.dart b/packages/flutter_tools/test/integration.shard/gen_l10n_test.dart index 4696201d597..deda717fc30 100644 --- a/packages/flutter_tools/test/integration.shard/gen_l10n_test.dart +++ b/packages/flutter_tools/test/integration.shard/gen_l10n_test.dart @@ -6,14 +6,15 @@ import 'dart:async'; import 'package:file/file.dart'; import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/base/io.dart'; +import 'package:flutter_tools/src/globals.dart' as globals; +import 'package:process/process.dart'; import '../src/common.dart'; import 'test_data/gen_l10n_project.dart'; import 'test_driver.dart'; import 'test_utils.dart'; -final GenL10nProject project = GenL10nProject(); - // Verify that the code generated by gen_l10n executes correctly. // It can fail if gen_l10n produces a lib/l10n/app_localizations.dart that: // - Does not analyze cleanly. @@ -22,23 +23,50 @@ final GenL10nProject project = GenL10nProject(); // loaded workstation, so the test could time out on a heavily loaded bot. void main() { Directory tempDir; - FlutterRunTestDriver flutter; + final GenL10nProject _project = GenL10nProject(); + FlutterRunTestDriver _flutter; setUp(() async { tempDir = createResolvedTempDirectorySync('gen_l10n_test.'); + await _project.setUpIn(tempDir); + _flutter = FlutterRunTestDriver(tempDir); }); tearDown(() async { - await flutter.stop(); + await _flutter.stop(); tryToDelete(tempDir); }); + void runCommand(List command) { + final ProcessResult result = const LocalProcessManager().runSync( + command, + workingDirectory: tempDir.path, + environment: { 'FLUTTER_ROOT': getFlutterRoot() }, + ); + if (result.exitCode != 0) { + throw Exception('FAILED [${result.exitCode}]: ${command.join(' ')}\n${result.stderr}\n${result.stdout}'); + } + } + + void setUpAndRunGenL10n({List args}) { + // Get the intl packages before running gen_l10n. + final String flutterBin = globals.platform.isWindows ? 'flutter.bat' : 'flutter'; + final String flutterPath = globals.fs.path.join(getFlutterRoot(), 'bin', flutterBin); + runCommand([flutterPath, 'pub', 'get']); + + // Generate lib/l10n/app_localizations.dart + final String genL10nPath = globals.fs.path.join(getFlutterRoot(), 'dev', 'tools', 'localization', 'bin', 'gen_l10n.dart'); + final String dartBin = globals.platform.isWindows ? 'dart.exe' : 'dart'; + final String dartPath = globals.fs.path.join(getFlutterRoot(), 'bin', 'cache', 'dart-sdk', 'bin', dartBin); + runCommand([dartPath, genL10nPath, args?.join(' ')]); + } + Future runApp() async { // Run the app defined in GenL10nProject.main and wait for it to // send '#l10n END' to its stdout. final Completer l10nEnd = Completer(); final StringBuffer stdout = StringBuffer(); - final StreamSubscription subscription = flutter.stdout.listen((String line) { + final StreamSubscription subscription = _flutter.stdout.listen((String line) { if (line.contains('#l10n')) { stdout.writeln(line.substring(line.indexOf('#l10n'))); } @@ -46,7 +74,7 @@ void main() { l10nEnd.complete(); } }); - await flutter.run(); + await _flutter.run(); await l10nEnd.future; await subscription.cancel(); return stdout; @@ -152,15 +180,13 @@ void main() { } test('generated l10n classes produce expected localized strings', () async { - await project.setUpIn(tempDir); - flutter = FlutterRunTestDriver(tempDir); + setUpAndRunGenL10n(); final StringBuffer stdout = await runApp(); expectOutput(stdout); }); test('generated l10n classes produce expected localized strings with deferred loading', () async { - await project.setUpIn(tempDir, useDeferredLoading: true); - flutter = FlutterRunTestDriver(tempDir); + setUpAndRunGenL10n(args: ['--use-deferred-loading']); final StringBuffer stdout = await runApp(); expectOutput(stdout); }); diff --git a/packages/flutter_tools/test/integration.shard/test_data/gen_l10n_project.dart b/packages/flutter_tools/test/integration.shard/test_data/gen_l10n_project.dart index 233320566bc..e503c596852 100644 --- a/packages/flutter_tools/test/integration.shard/test_data/gen_l10n_project.dart +++ b/packages/flutter_tools/test/integration.shard/test_data/gen_l10n_project.dart @@ -7,16 +7,13 @@ import 'dart:async'; import 'package:file/file.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/globals.dart' as globals; -import 'package:meta/meta.dart'; import '../test_utils.dart'; import 'project.dart'; class GenL10nProject extends Project { @override - Future setUpIn(Directory dir, { - bool useDeferredLoading = false, - }) { + Future setUpIn(Directory dir) { this.dir = dir; writeFile(globals.fs.path.join(dir.path, 'lib', 'l10n', 'app_en.arb'), appEn); writeFile(globals.fs.path.join(dir.path, 'lib', 'l10n', 'app_en_CA.arb'), appEnCa); @@ -27,7 +24,6 @@ class GenL10nProject extends Project { writeFile(globals.fs.path.join(dir.path, 'lib', 'l10n', 'app_zh_Hant.arb'), appZhHant); writeFile(globals.fs.path.join(dir.path, 'lib', 'l10n', 'app_zh_Hans.arb'), appZhHans); writeFile(globals.fs.path.join(dir.path, 'lib', 'l10n', 'app_zh_Hant_TW.arb'), appZhHantTw); - writeFile(globals.fs.path.join(dir.path, 'l10n.yaml'), l10nYaml(useDeferredLoading: useDeferredLoading)); return super.setUpIn(dir); } @@ -565,15 +561,4 @@ void main() { "helloWorld": "台灣繁體你好世界" } '''; - - String l10nYaml({ - @required bool useDeferredLoading, - }) { - if (useDeferredLoading) { - return r''' -use-deferred-loading: false - '''; - } - return ''; - } }