diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 359f7fde2c..11b9631048 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -68,8 +68,12 @@ Future _generateDocs() async { } Future _verifyInternationalizations() async { - final EvalResult genResult = await _evalCommand(dart, - [ '--preview-dart-2', path.join('dev', 'tools', 'gen_localizations.dart'), ], + final EvalResult genResult = await _evalCommand( + dart, + [ + '--preview-dart-2', + path.join('dev', 'tools', 'gen_localizations.dart'), + ], workingDirectory: flutterRoot, ); diff --git a/dev/devicelab/bin/tasks/gradle_plugin_test.dart b/dev/devicelab/bin/tasks/gradle_plugin_test.dart index 26830f880e..bbeb70f233 100644 --- a/dev/devicelab/bin/tasks/gradle_plugin_test.dart +++ b/dev/devicelab/bin/tasks/gradle_plugin_test.dart @@ -32,6 +32,14 @@ void main() async { return new TaskResult.failure(errorMessage); } + section('gradlew assembleDebug no-preview-dart-2'); + await project.runGradleTask('assembleDebug', options: ['-Ppreview-dart-2=false']); + errorMessage = _validateSnapshotDependency(project, + '${project.rootPath}/build/app/intermediates/flutter/debug/snapshot_blob.bin'); + if (errorMessage != null) { + return new TaskResult.failure(errorMessage); + } + section('gradlew assembleProfile'); await project.runGradleTask('assembleProfile'); diff --git a/dev/devicelab/bin/tasks/hot_mode_dev_cycle__benchmark_dart1.dart b/dev/devicelab/bin/tasks/hot_mode_dev_cycle__benchmark_dart1.dart new file mode 100644 index 0000000000..4d9767565b --- /dev/null +++ b/dev/devicelab/bin/tasks/hot_mode_dev_cycle__benchmark_dart1.dart @@ -0,0 +1,12 @@ +// Copyright (c) 2017 The Chromium 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:async'; + +import 'package:flutter_devicelab/tasks/hot_mode_tests.dart'; +import 'package:flutter_devicelab/framework/framework.dart'; + +Future main() async { + await task(createHotModeTest(isPreviewDart2: false)); +} diff --git a/dev/devicelab/bin/tasks/hot_mode_dev_cycle_ios__benchmark_dart1.dart b/dev/devicelab/bin/tasks/hot_mode_dev_cycle_ios__benchmark_dart1.dart new file mode 100644 index 0000000000..99c70d710e --- /dev/null +++ b/dev/devicelab/bin/tasks/hot_mode_dev_cycle_ios__benchmark_dart1.dart @@ -0,0 +1,14 @@ +// Copyright (c) 2018 The Chromium 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:async'; + +import 'package:flutter_devicelab/tasks/hot_mode_tests.dart'; +import 'package:flutter_devicelab/framework/framework.dart'; +import 'package:flutter_devicelab/framework/adb.dart'; + +Future main() async { + deviceOperatingSystem = DeviceOperatingSystem.ios; + await task(createHotModeTest(isPreviewDart2: false)); +} diff --git a/dev/devicelab/lib/tasks/hot_mode_tests.dart b/dev/devicelab/lib/tasks/hot_mode_tests.dart index 9913c2ba51..a710e80e41 100644 --- a/dev/devicelab/lib/tasks/hot_mode_tests.dart +++ b/dev/devicelab/lib/tasks/hot_mode_tests.dart @@ -16,7 +16,7 @@ import '../framework/utils.dart'; final Directory _editedFlutterGalleryDir = dir(path.join(Directory.systemTemp.path, 'edited_flutter_gallery')); final Directory flutterGalleryDir = dir(path.join(flutterDirectory.path, 'examples/flutter_gallery')); -TaskFunction createHotModeTest() { +TaskFunction createHotModeTest({ bool isPreviewDart2 = true }) { return () async { final Device device = await devices.workingDevice; await device.unlock(); @@ -25,6 +25,10 @@ TaskFunction createHotModeTest() { final List options = [ '--hot', '-d', device.deviceId, '--benchmark', '--verbose', '--resident' ]; + if (isPreviewDart2) + options.add('--preview-dart-2'); + else + options.add('--no-preview-dart-2'); setLocalEngineOptionIfNecessary(options); int hotReloadCount = 0; Map twoReloadsData; @@ -88,8 +92,8 @@ TaskFunction createHotModeTest() { } benchmarkFile.deleteSync(); - // start `flutter run` again to make sure it loads from the previous - // state; frontend loads up from previously generated kernel files. + // start `flutter run` again to make sure it loads from the previous state + // (in case of --preview-dart-2 frontend loads up from previously generated kernel files). { final Process process = await startProcess( path.join(flutterDirectory.path, 'bin', 'flutter'), diff --git a/dev/devicelab/lib/tasks/microbenchmarks.dart b/dev/devicelab/lib/tasks/microbenchmarks.dart index 15764c09ce..1d2a67a712 100644 --- a/dev/devicelab/lib/tasks/microbenchmarks.dart +++ b/dev/devicelab/lib/tasks/microbenchmarks.dart @@ -23,7 +23,7 @@ TaskFunction createMicrobenchmarkTask() { final Device device = await devices.workingDevice; await device.unlock(); - Future> _runMicrobench(String benchmarkPath) async { + Future> _runMicrobench(String benchmarkPath, {bool previewDart2 = true}) async { Future> _run() async { print('Running $benchmarkPath'); final Directory appDir = dir( @@ -38,6 +38,10 @@ TaskFunction createMicrobenchmarkTask() { '-d', device.deviceId, ]; + if (previewDart2) + options.add('--preview-dart-2'); + else + options.add('--no-preview-dart-2'); setLocalEngineOptionIfNecessary(options); options.add(benchmarkPath); return await _startFlutter( @@ -57,6 +61,26 @@ TaskFunction createMicrobenchmarkTask() { allResults.addAll(await _runMicrobench('lib/gestures/velocity_tracker_bench.dart')); allResults.addAll(await _runMicrobench('lib/stocks/animation_bench.dart')); + // Run micro-benchmarks once again in --no-preview-dart-2 mode. + // Append "_dart1" suffix to the result keys to distinguish them from + // the original results. + + void addDart1Results(Map benchmarkResults) { + benchmarkResults.forEach((String key, double result) { + allResults[key + '_dart1'] = result; + }); + } + + addDart1Results(await _runMicrobench( + 'lib/stocks/layout_bench.dart', previewDart2: false)); + addDart1Results(await _runMicrobench( + 'lib/stocks/layout_bench.dart', previewDart2: false)); + addDart1Results(await _runMicrobench( + 'lib/stocks/build_bench.dart', previewDart2: false)); + addDart1Results(await _runMicrobench( + 'lib/gestures/velocity_tracker_bench.dart', previewDart2: false)); + addDart1Results(await _runMicrobench( + 'lib/stocks/animation_bench.dart', previewDart2: false)); return new TaskResult.success(allResults, benchmarkScoreKeys: allResults.keys.toList()); }; } diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart index 3cb76dd346..34748de0ac 100644 --- a/dev/devicelab/lib/tasks/perf_tests.dart +++ b/dev/devicelab/lib/tasks/perf_tests.dart @@ -205,13 +205,23 @@ class CompileTest { final Map metrics = {} ..addAll(await _compileAot()) ..addAll(await _compileApp()) - ..addAll(await _compileDebug()); + ..addAll(await _compileDebug()) + ..addAll(_suffix(await _compileAot(previewDart2: false), '__dart1')) + ..addAll(_suffix(await _compileApp(previewDart2: false), '__dart1')) + ..addAll(_suffix(await _compileDebug(previewDart2: false), '__dart1')); return new TaskResult.success(metrics, benchmarkScoreKeys: metrics.keys.toList()); }); } - static Future> _compileAot() async { + static Map _suffix(Map map, String suffix) { + return new Map.fromIterables( + map.keys.map((String key) => '$key$suffix'), + map.values, + ); + } + + static Future> _compileAot({ bool previewDart2 = true }) async { // Generate blobs instead of assembly. await flutter('clean'); final Stopwatch watch = new Stopwatch()..start(); @@ -230,6 +240,10 @@ class CompileTest { options.add('android-arm'); break; } + if (previewDart2) + options.add('--preview-dart-2'); + else + options.add('--no-preview-dart-2'); setLocalEngineOptionIfNecessary(options); final String compileLog = await evalFlutter('build', options: options); watch.stop(); @@ -244,11 +258,15 @@ class CompileTest { return metrics; } - static Future> _compileApp() async { + static Future> _compileApp({ bool previewDart2 = true }) async { await flutter('clean'); final Stopwatch watch = new Stopwatch(); int releaseSizeInBytes; final List options = ['--release']; + if (previewDart2) + options.add('--preview-dart-2'); + else + options.add('--no-preview-dart-2'); setLocalEngineOptionIfNecessary(options); switch (deviceOperatingSystem) { case DeviceOperatingSystem.ios: @@ -281,10 +299,14 @@ class CompileTest { }; } - static Future> _compileDebug() async { + static Future> _compileDebug({ bool previewDart2 = true }) async { await flutter('clean'); final Stopwatch watch = new Stopwatch(); final List options = ['--debug']; + if (previewDart2) + options.add('--preview-dart-2'); + else + options.add('--no-preview-dart-2'); setLocalEngineOptionIfNecessary(options); switch (deviceOperatingSystem) { case DeviceOperatingSystem.ios: diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml index cee29b27bd..b7f18f3974 100644 --- a/dev/devicelab/manifest.yaml +++ b/dev/devicelab/manifest.yaml @@ -154,6 +154,21 @@ tasks: stage: devicelab required_agent_capabilities: ["mac/android"] + hot_mode_dev_cycle__benchmark_dart1: + description: > + Measures the performance of Dart VM hot patching feature under + --no-preview-dart-2 option, that disables Dart 2.0 frontend. + stage: devicelab + required_agent_capabilities: ["mac/android"] + + hot_mode_dev_cycle_ios__benchmark_dart1: + description: > + Measures the performance of Dart VM hot patching feature under + --no-preview-dart-2 option, that disables Dart 2.0 frontend. + stage: devicelab_ios + required_agent_capabilities: ["mac/ios"] + flaky: true + complex_layout_scroll_perf__memory: description: > Measures memory usage of the scroll performance test. diff --git a/packages/flutter_tools/bin/xcode_backend.sh b/packages/flutter_tools/bin/xcode_backend.sh index f94fcad639..e02083e383 100755 --- a/packages/flutter_tools/bin/xcode_backend.sh +++ b/packages/flutter_tools/bin/xcode_backend.sh @@ -102,6 +102,13 @@ BuildApp() { local_engine_flag="--local-engine=$LOCAL_ENGINE" fi + local preview_dart_2_flag="" + if [[ -n "$PREVIEW_DART_2" ]]; then + preview_dart_2_flag="--preview-dart-2" + else + preview_dart_2_flag="--no-preview-dart-2" + fi + local track_widget_creation_flag="" if [[ -n "$TRACK_WIDGET_CREATION" ]]; then track_widget_creation_flag="--track-widget-creation" @@ -120,6 +127,7 @@ BuildApp() { --${build_mode} \ --ios-arch="${archs}" \ ${local_engine_flag} \ + ${preview_dart_2_flag} \ ${track_widget_creation_flag} if [[ $? -ne 0 ]]; then @@ -159,10 +167,12 @@ BuildApp() { ${verbose_flag} \ build bundle \ --target="${target_path}" \ + --snapshot="${build_dir}/snapshot_blob.bin" \ --depfile="${build_dir}/snapshot_blob.bin.d" \ --asset-dir="${derived_dir}/flutter_assets" \ ${precompilation_flag} \ ${local_engine_flag} \ + ${preview_dart_2_flag} \ ${track_widget_creation_flag} if [[ $? -ne 0 ]]; then diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle index e933a96f04..6f14e9cf89 100644 --- a/packages/flutter_tools/gradle/flutter.gradle +++ b/packages/flutter_tools/gradle/flutter.gradle @@ -260,6 +260,10 @@ class FlutterPlugin implements Plugin { if (project.hasProperty('verbose')) { verboseValue = project.property('verbose').toBoolean() } + Boolean previewDart2Value = true + if (project.hasProperty('preview-dart-2')) { + previewDart2Value = project.property('preview-dart-2').toBoolean() + } String[] fileSystemRootsValue = null if (project.hasProperty('filesystem-roots')) { fileSystemRootsValue = project.property('filesystem-roots').split('\\|') @@ -311,6 +315,7 @@ class FlutterPlugin implements Plugin { localEngineSrcPath this.localEngineSrcPath targetPath target verbose verboseValue + previewDart2 previewDart2Value fileSystemRoots fileSystemRootsValue fileSystemScheme fileSystemSchemeValue trackWidgetCreation trackWidgetCreationValue @@ -355,6 +360,8 @@ abstract class BaseFlutterTask extends DefaultTask { @Optional @Input Boolean verbose @Optional @Input + Boolean previewDart2 + @Optional @Input String[] fileSystemRoots @Optional @Input String fileSystemScheme @@ -376,10 +383,12 @@ abstract class BaseFlutterTask extends DefaultTask { if (buildMode != 'debug') { // For AOT builds, include the gen_snapshot depfile. FileCollection depfiles = project.files("${intermediateDir}/snapshot.d") - // Include the kernel compiler depfile, since kernel compile is the - // first stage of AOT build in this mode, and it includes all the - // Dart sources. - depfiles += project.files("${intermediateDir}/kernel_compile.d") + if (previewDart2) { + // For Dart 2, also include the kernel compiler depfile, since + // kernel compile is the first stage of AOT build in this mode, + // and it includes all the Dart sources. + depfiles += project.files("${intermediateDir}/kernel_compile.d") + } return depfiles } return project.files("${intermediateDir}/snapshot_blob.bin.d") @@ -406,6 +415,11 @@ abstract class BaseFlutterTask extends DefaultTask { args "--target", targetPath args "--target-platform", "android-arm" args "--output-dir", "${intermediateDir}" + if (previewDart2) { + args "--preview-dart-2" + } else { + args "--no-preview-dart-2" + } if (trackWidgetCreation) { args "--track-widget-creation" } @@ -438,6 +452,11 @@ abstract class BaseFlutterTask extends DefaultTask { if (verbose) { args "--verbose" } + if (previewDart2) { + args "--preview-dart-2" + } else { + args "--no-preview-dart-2" + } if (fileSystemRoots != null) { for (root in fileSystemRoots) { args "--filesystem-root", root @@ -456,6 +475,9 @@ abstract class BaseFlutterTask extends DefaultTask { args "--precompiled" } else { args "--depfile", "${intermediateDir}/snapshot_blob.bin.d" + if (!previewDart2) { + args "--snapshot", "${intermediateDir}/snapshot_blob.bin" + } } args "--asset-dir", "${intermediateDir}/flutter_assets" } @@ -511,7 +533,9 @@ class FlutterTask extends BaseFlutterTask { // We have a dependencies file. Add a dependency on gen_snapshot as well, since the // snapshots have to be rebuilt if it changes. sources += readDependencies(project.file("${intermediateDir}/gen_snapshot.d")) - sources += readDependencies(project.file("${intermediateDir}/frontend_server.d")) + if (previewDart2) { + sources += readDependencies(project.file("${intermediateDir}/frontend_server.d")) + } if (localEngineSrcPath != null) { sources += project.files("$localEngineSrcPath/$localEngine") } diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart index 1dca022d8f..d4ef33f987 100644 --- a/packages/flutter_tools/lib/src/android/gradle.dart +++ b/packages/flutter_tools/lib/src/android/gradle.dart @@ -327,16 +327,21 @@ Future _buildGradleProjectV2(String gradle, BuildInfo buildInfo, String ta if (target != null) { command.add('-Ptarget=$target'); } - if (buildInfo.trackWidgetCreation) - command.add('-Ptrack-widget-creation=true'); - if (buildInfo.extraFrontEndOptions != null) - command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}'); - if (buildInfo.extraGenSnapshotOptions != null) - command.add('-Pextra-gen-snapshot-options=${buildInfo.extraGenSnapshotOptions}'); - if (buildInfo.fileSystemRoots != null && buildInfo.fileSystemRoots.isNotEmpty) - command.add('-Pfilesystem-roots=${buildInfo.fileSystemRoots.join('|')}'); - if (buildInfo.fileSystemScheme != null) - command.add('-Pfilesystem-scheme=${buildInfo.fileSystemScheme}'); + if (buildInfo.previewDart2) { + command.add('-Ppreview-dart-2=true'); + if (buildInfo.trackWidgetCreation) + command.add('-Ptrack-widget-creation=true'); + if (buildInfo.extraFrontEndOptions != null) + command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}'); + if (buildInfo.extraGenSnapshotOptions != null) + command.add('-Pextra-gen-snapshot-options=${buildInfo.extraGenSnapshotOptions}'); + if (buildInfo.fileSystemRoots != null && buildInfo.fileSystemRoots.isNotEmpty) + command.add('-Pfilesystem-roots=${buildInfo.fileSystemRoots.join('|')}'); + if (buildInfo.fileSystemScheme != null) + command.add('-Pfilesystem-scheme=${buildInfo.fileSystemScheme}'); + } else { + command.add('-Ppreview-dart-2=false'); + } if (buildInfo.buildSharedLibrary && androidSdk.ndk != null) { command.add('-Pbuild-shared-library=true'); } diff --git a/packages/flutter_tools/lib/src/base/build.dart b/packages/flutter_tools/lib/src/base/build.dart index 51303ef5db..d96be68e01 100644 --- a/packages/flutter_tools/lib/src/base/build.dart +++ b/packages/flutter_tools/lib/src/base/build.dart @@ -64,6 +64,70 @@ class GenSnapshot { } } +/// Dart snapshot builder. +/// +/// Builds Dart snapshots in one of three modes: +/// * Script snapshot: architecture-independent snapshot of a Dart script +/// and core libraries. +/// * AOT snapshot: architecture-specific ahead-of-time compiled snapshot +/// suitable for loading with `mmap`. +/// * Assembly AOT snapshot: architecture-specific ahead-of-time compile to +/// assembly suitable for compilation as a static or dynamic library. +class ScriptSnapshotter { + /// Builds an architecture-independent snapshot of the specified script. + Future build({ + @required String mainPath, + @required String snapshotPath, + @required String depfilePath, + @required String packagesPath + }) async { + final SnapshotType snapshotType = new SnapshotType(null, BuildMode.debug); + final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData); + final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData); + final List args = [ + '--snapshot_kind=script', + '--script_snapshot=$snapshotPath', + '--vm_snapshot_data=$vmSnapshotData', + '--isolate_snapshot_data=$isolateSnapshotData', + '--enable-mirrors=false', + mainPath, + ]; + + final Fingerprinter fingerprinter = new Fingerprinter( + fingerprintPath: '$depfilePath.fingerprint', + paths: [ + mainPath, + snapshotPath, + vmSnapshotData, + isolateSnapshotData, + ], + properties: { + 'buildMode': snapshotType.mode.toString(), + 'targetPlatform': snapshotType.platform?.toString() ?? '', + 'entryPoint': mainPath, + }, + depfilePaths: [depfilePath], + ); + if (await fingerprinter.doesFingerprintMatch()) { + printTrace('Skipping script snapshot build. Fingerprints match.'); + return 0; + } + + // Build the snapshot. + final int exitCode = await genSnapshot.run( + snapshotType: snapshotType, + packagesPath: packagesPath, + depfilePath: depfilePath, + additionalArgs: args, + ); + + if (exitCode != 0) + return exitCode; + await fingerprinter.writeFingerprint(); + return exitCode; + } +} + class AOTSnapshotter { /// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script. Future build({ @@ -72,6 +136,7 @@ class AOTSnapshotter { @required String mainPath, @required String packagesPath, @required String outputPath, + @required bool previewDart2, @required bool buildSharedLibrary, IOSArch iosArch, List extraGenSnapshotOptions = const [], @@ -127,10 +192,12 @@ class AOTSnapshotter { '--embedder_entry_points_manifest=$ioEntryPoints', '--dependencies=$depfilePath', ]; - genSnapshotArgs.addAll([ - '--reify-generic-functions', - '--strong', - ]); + if (previewDart2) { + genSnapshotArgs.addAll([ + '--reify-generic-functions', + '--strong', + ]); + } if (extraGenSnapshotOptions != null && extraGenSnapshotOptions.isNotEmpty) { printTrace('Extra gen_snapshot options: $extraGenSnapshotOptions'); genSnapshotArgs.addAll(extraGenSnapshotOptions); @@ -185,6 +252,7 @@ class AOTSnapshotter { 'buildMode': buildMode.toString(), 'targetPlatform': platform.toString(), 'entryPoint': mainPath, + 'dart2': previewDart2.toString(), 'sharedLib': buildSharedLibrary.toString(), 'extraGenSnapshotOptions': extraGenSnapshotOptions.join(' '), }, diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index e7f8b52c79..fbcab759a2 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart @@ -11,6 +11,7 @@ import 'globals.dart'; /// Information about a build to be performed or used. class BuildInfo { const BuildInfo(this.mode, this.flavor, { + this.previewDart2 = false, this.trackWidgetCreation = false, this.extraFrontEndOptions, this.extraGenSnapshotOptions, @@ -32,6 +33,9 @@ class BuildInfo { /// Mode-Flavor (e.g. Release-Paid). final String flavor; + /// Whether build should be done using Dart2 Frontend parser. + final bool previewDart2; + final List fileSystemRoots; final String fileSystemScheme; @@ -89,6 +93,7 @@ class BuildInfo { BuildInfo withTargetPlatform(TargetPlatform targetPlatform) => new BuildInfo(mode, flavor, + previewDart2: previewDart2, trackWidgetCreation: trackWidgetCreation, extraFrontEndOptions: extraFrontEndOptions, extraGenSnapshotOptions: extraGenSnapshotOptions, diff --git a/packages/flutter_tools/lib/src/bundle.dart b/packages/flutter_tools/lib/src/bundle.dart index 42f0687907..02a65101d4 100644 --- a/packages/flutter_tools/lib/src/bundle.dart +++ b/packages/flutter_tools/lib/src/bundle.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'artifacts.dart'; import 'asset.dart'; +import 'base/build.dart'; import 'base/common.dart'; import 'base/file_system.dart'; import 'build_info.dart'; @@ -23,6 +24,7 @@ String get defaultApplicationKernelPath => fs.path.join(getBuildDirectory(), 'ap const String defaultPrivateKeyPath = 'privatekey.der'; const String _kKernelKey = 'kernel_blob.bin'; +const String _kSnapshotKey = 'snapshot_blob.bin'; const String _kVMSnapshotData = 'vm_snapshot_data'; const String _kIsolateSnapshotData = 'isolate_snapshot_data'; const String _kDylibKey = 'libapp.so'; @@ -31,11 +33,13 @@ const String _kPlatformKernelKey = 'platform.dill'; Future build({ String mainPath = defaultMainPath, String manifestPath = defaultManifestPath, + String snapshotPath, String applicationKernelFilePath, String depfilePath, String privateKeyPath = defaultPrivateKeyPath, String assetDirPath, String packagesPath, + bool previewDart2 = false, bool precompiledSnapshot = false, bool reportLicensedPackages = false, bool trackWidgetCreation = false, @@ -43,13 +47,32 @@ Future build({ List fileSystemRoots, String fileSystemScheme, }) async { + snapshotPath ??= defaultSnapshotPath; depfilePath ??= defaultDepfilePath; assetDirPath ??= getAssetBuildDirectory(); packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath); applicationKernelFilePath ??= defaultApplicationKernelPath; + File snapshotFile; + + if (!precompiledSnapshot && !previewDart2) { + ensureDirectoryExists(snapshotPath); + + // In a precompiled snapshot, the instruction buffer contains script + // content equivalents + final int result = await new ScriptSnapshotter().build( + mainPath: mainPath, + snapshotPath: snapshotPath, + depfilePath: depfilePath, + packagesPath: packagesPath, + ); + if (result != 0) + throwToolExit('Failed to run the Flutter compiler. Exit code: $result', exitCode: result); + + snapshotFile = fs.file(snapshotPath); + } DevFSContent kernelContent; - if (!precompiledSnapshot) { + if (!precompiledSnapshot && previewDart2) { if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty) printTrace('Extra front-end options: $extraFrontEndOptions'); ensureDirectoryExists(applicationKernelFilePath); @@ -86,6 +109,7 @@ Future build({ await assemble( assetBundle: assets, kernelContent: kernelContent, + snapshotFile: snapshotFile, privateKeyPath: privateKeyPath, assetDirPath: assetDirPath, ); @@ -119,6 +143,7 @@ Future buildAssets({ Future assemble({ AssetBundle assetBundle, DevFSContent kernelContent, + File snapshotFile, File dylibFile, String privateKeyPath = defaultPrivateKeyPath, String assetDirPath, @@ -127,16 +152,21 @@ Future assemble({ printTrace('Building bundle'); final Map assetEntries = new Map.from(assetBundle.entries); + final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData); + final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData); if (kernelContent != null) { final String platformKernelDill = artifacts.getArtifactPath(Artifact.platformKernelDill); - final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData); - final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData); assetEntries[_kKernelKey] = kernelContent; assetEntries[_kPlatformKernelKey] = new DevFSFileContent(fs.file(platformKernelDill)); assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData)); assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData)); } + if (snapshotFile != null) { + assetEntries[_kSnapshotKey] = new DevFSFileContent(snapshotFile); + assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData)); + assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData)); + } if (dylibFile != null) assetEntries[_kDylibKey] = new DevFSFileContent(dylibFile); diff --git a/packages/flutter_tools/lib/src/commands/analyze.dart b/packages/flutter_tools/lib/src/commands/analyze.dart index 7941f799cd..42e8a326fb 100644 --- a/packages/flutter_tools/lib/src/commands/analyze.dart +++ b/packages/flutter_tools/lib/src/commands/analyze.dart @@ -26,6 +26,8 @@ class AnalyzeCommand extends FlutterCommand { argParser.addFlag('watch', help: 'Run analysis continuously, watching the filesystem for changes.', negatable: false); + argParser.addFlag('preview-dart-2', + defaultsTo: true, help: 'Preview Dart 2.0 functionality.'); argParser.addOption('write', valueHelp: 'file', help: 'Also output the results to a file. This is useful with --watch ' @@ -85,6 +87,7 @@ class AnalyzeCommand extends FlutterCommand { argResults, runner.getRepoRoots(), runner.getRepoPackages(), + previewDart2: argResults['preview-dart-2'], ).analyze(); } else { return new AnalyzeOnce( @@ -92,6 +95,7 @@ class AnalyzeCommand extends FlutterCommand { runner.getRepoRoots(), runner.getRepoPackages(), workingDirectory: workingDirectory, + previewDart2: argResults['preview-dart-2'], ).analyze(); } } diff --git a/packages/flutter_tools/lib/src/commands/analyze_continuously.dart b/packages/flutter_tools/lib/src/commands/analyze_continuously.dart index aad07d3369..a31eff324b 100644 --- a/packages/flutter_tools/lib/src/commands/analyze_continuously.dart +++ b/packages/flutter_tools/lib/src/commands/analyze_continuously.dart @@ -19,10 +19,13 @@ import '../globals.dart'; import 'analyze_base.dart'; class AnalyzeContinuously extends AnalyzeBase { - AnalyzeContinuously(ArgResults argResults, this.repoRoots, this.repoPackages) : super(argResults); + AnalyzeContinuously(ArgResults argResults, this.repoRoots, this.repoPackages, { + this.previewDart2 = false, + }) : super(argResults); final List repoRoots; final List repoPackages; + final bool previewDart2; String analysisTarget; bool firstAnalysis = true; @@ -57,7 +60,7 @@ class AnalyzeContinuously extends AnalyzeBase { final String sdkPath = argResults['dart-sdk'] ?? sdk.dartSdkPath; - final AnalysisServer server = new AnalysisServer(sdkPath, directories); + final AnalysisServer server = new AnalysisServer(sdkPath, directories, previewDart2: previewDart2); server.onAnalyzing.listen((bool isAnalyzing) => _handleAnalysisStatus(server, isAnalyzing)); server.onErrors.listen(_handleAnalysisErrors); diff --git a/packages/flutter_tools/lib/src/commands/analyze_once.dart b/packages/flutter_tools/lib/src/commands/analyze_once.dart index 3866596296..b8840a90ee 100644 --- a/packages/flutter_tools/lib/src/commands/analyze_once.dart +++ b/packages/flutter_tools/lib/src/commands/analyze_once.dart @@ -24,6 +24,7 @@ class AnalyzeOnce extends AnalyzeBase { this.repoRoots, this.repoPackages, { this.workingDirectory, + this.previewDart2 = false, }) : super(argResults); final List repoRoots; @@ -32,6 +33,8 @@ class AnalyzeOnce extends AnalyzeBase { /// The working directory for testing analysis using dartanalyzer. final Directory workingDirectory; + final bool previewDart2; + @override Future analyze() async { final String currentDirectory = @@ -88,6 +91,7 @@ class AnalyzeOnce extends AnalyzeBase { final AnalysisServer server = new AnalysisServer( sdkPath, directories.toList(), + previewDart2: previewDart2, ); StreamSubscription subscription; diff --git a/packages/flutter_tools/lib/src/commands/build_aot.dart b/packages/flutter_tools/lib/src/commands/build_aot.dart index bd4c3bf4db..2d9fe924c9 100644 --- a/packages/flutter_tools/lib/src/commands/build_aot.dart +++ b/packages/flutter_tools/lib/src/commands/build_aot.dart @@ -28,6 +28,11 @@ class BuildAotCommand extends BuildSubCommand { allowed: ['android-arm', 'android-arm64', 'ios'] ) ..addFlag('quiet', defaultsTo: false) + ..addFlag('preview-dart-2', + defaultsTo: true, + hide: !verboseHelp, + help: 'Preview Dart 2.0 functionality.', + ) ..addFlag('build-shared-library', negatable: false, defaultsTo: false, @@ -74,20 +79,23 @@ class BuildAotCommand extends BuildSubCommand { } final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory(); try { + final bool previewDart2 = argResults['preview-dart-2']; String mainPath = findMainDartFile(targetFile); final AOTSnapshotter snapshotter = new AOTSnapshotter(); - // Compile to kernel. - mainPath = await snapshotter.compileKernel( - platform: platform, - buildMode: buildMode, - mainPath: mainPath, - outputPath: outputPath, - extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions], - ); - if (mainPath == null) { - printError('Compiler terminated unexpectedly.'); - return; + // Compile to kernel, if Dart 2. + if (previewDart2) { + mainPath = await snapshotter.compileKernel( + platform: platform, + buildMode: buildMode, + mainPath: mainPath, + outputPath: outputPath, + extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions], + ); + if (mainPath == null) { + printError('Compiler terminated unexpectedly.'); + return; + } } // Build AOT snapshot. @@ -108,6 +116,7 @@ class BuildAotCommand extends BuildSubCommand { mainPath: mainPath, packagesPath: PackageMap.globalPackagesPath, outputPath: outputPath, + previewDart2: previewDart2, buildSharedLibrary: false, extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions], ).then((int buildExitCode) { @@ -134,6 +143,7 @@ class BuildAotCommand extends BuildSubCommand { mainPath: mainPath, packagesPath: PackageMap.globalPackagesPath, outputPath: outputPath, + previewDart2: previewDart2, buildSharedLibrary: argResults['build-shared-library'], extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions], ); diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart index 0c9ff1a4cb..e6e2cc54f3 100644 --- a/packages/flutter_tools/lib/src/commands/build_apk.dart +++ b/packages/flutter_tools/lib/src/commands/build_apk.dart @@ -17,6 +17,11 @@ class BuildApkCommand extends BuildSubCommand { usesBuildNameOption(); argParser + ..addFlag('preview-dart-2', + defaultsTo: true, + hide: !verboseHelp, + help: 'Preview Dart 2.0 functionality.', + ) ..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp) ..addFlag('build-shared-library', negatable: false, diff --git a/packages/flutter_tools/lib/src/commands/build_bundle.dart b/packages/flutter_tools/lib/src/commands/build_bundle.dart index 581bc165f8..811433414f 100644 --- a/packages/flutter_tools/lib/src/commands/build_bundle.dart +++ b/packages/flutter_tools/lib/src/commands/build_bundle.dart @@ -19,8 +19,14 @@ class BuildBundleCommand extends BuildSubCommand { ..addOption('asset-base', help: 'Ignored. Will be removed.', hide: !verboseHelp) ..addOption('manifest', defaultsTo: defaultManifestPath) ..addOption('private-key', defaultsTo: defaultPrivateKeyPath) + ..addOption('snapshot', defaultsTo: defaultSnapshotPath) ..addOption('depfile', defaultsTo: defaultDepfilePath) ..addOption('kernel-file', defaultsTo: defaultApplicationKernelPath) + ..addFlag('preview-dart-2', + defaultsTo: true, + hide: !verboseHelp, + help: 'Preview Dart 2.0 functionality.', + ) ..addFlag('track-widget-creation', hide: !verboseHelp, help: 'Track widget creation locations. Requires Dart 2.0 functionality.', @@ -66,10 +72,12 @@ class BuildBundleCommand extends BuildSubCommand { await build( mainPath: targetFile, manifestPath: argResults['manifest'], + snapshotPath: argResults['snapshot'], applicationKernelFilePath: argResults['kernel-file'], depfilePath: argResults['depfile'], privateKeyPath: argResults['private-key'], assetDirPath: argResults['asset-dir'], + previewDart2: argResults['preview-dart-2'], precompiledSnapshot: argResults['precompiled'], reportLicensedPackages: argResults['report-licensed-packages'], trackWidgetCreation: argResults['track-widget-creation'], diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart index db2fe23891..5196e1bf59 100644 --- a/packages/flutter_tools/lib/src/commands/build_ios.dart +++ b/packages/flutter_tools/lib/src/commands/build_ios.dart @@ -38,7 +38,11 @@ class BuildIOSCommand extends BuildSubCommand { ..addFlag('codesign', defaultsTo: true, help: 'Codesign the application bundle (only available on device builds).', - ); + ) + ..addFlag('preview-dart-2', + defaultsTo: true, + hide: !verboseHelp, + help: 'Preview Dart 2.0 functionality.'); } @override diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 050318c3c5..a675722990 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart @@ -334,6 +334,7 @@ class AppDomain extends Domain { final BuildInfo buildInfo = new BuildInfo( getBuildModeForName(mode) ?? BuildMode.debug, flavor, + previewDart2: _getBoolArg(args, 'preview-dart-2'), ); DebuggingOptions options; if (buildInfo.isRelease) { @@ -384,6 +385,7 @@ class AppDomain extends Domain { final FlutterDevice flutterDevice = new FlutterDevice( device, + previewDart2: options.buildInfo.previewDart2, trackWidgetCreation: trackWidgetCreation, dillOutputPath: dillOutputPath, ); diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart index 84d7312b5f..bec0e38530 100644 --- a/packages/flutter_tools/lib/src/commands/drive.dart +++ b/packages/flutter_tools/lib/src/commands/drive.dart @@ -62,7 +62,10 @@ class DriveCommand extends RunCommandBase { 'just before the extension, so e.g. if the target is "lib/main.dart", the\n' 'driver will be "test_driver/main_test.dart".', valueHelp: 'path', - ); + ) + ..addFlag('preview-dart-2', + defaultsTo: true, + help: 'Preview Dart 2.0 functionality.'); } @override @@ -120,7 +123,7 @@ class DriveCommand extends RunCommandBase { Cache.releaseLockEarly(); try { - await testRunner([testFile], observatoryUri); + await testRunner([testFile], observatoryUri, argResults['preview-dart-2']); } catch (error, stackTrace) { if (error is ToolExit) rethrow; @@ -272,20 +275,24 @@ Future _startApp(DriveCommand command) async { } /// Runs driver tests. -typedef Future TestRunner(List testArgs, String observatoryUri); +typedef Future TestRunner(List testArgs, String observatoryUri, bool previewDart2); TestRunner testRunner = _runTests; void restoreTestRunner() { testRunner = _runTests; } -Future _runTests(List testArgs, String observatoryUri) async { +Future _runTests(List testArgs, String observatoryUri, bool previewDart2) async { printTrace('Running driver tests.'); PackageMap.globalPackagesPath = fs.path.normalize(fs.path.absolute(PackageMap.globalPackagesPath)); final List args = testArgs.toList() ..add('--packages=${PackageMap.globalPackagesPath}') - ..add('-rexpanded') - ..add('--preview-dart-2'); + ..add('-rexpanded'); + if (previewDart2) { + args.add('--preview-dart-2'); + } else { + args.add('--no-preview-dart-2'); + } final String dartVmPath = fs.path.join(dartSdkPath, 'bin', 'dart'); final int result = await runCommandAndStreamOutput( diff --git a/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart b/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart index cd45e83428..17723c5275 100644 --- a/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart +++ b/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart @@ -53,6 +53,10 @@ class FuchsiaReloadCommand extends FlutterCommand { argParser.addOption('name-override', abbr: 'n', help: 'On-device name of the application binary.'); + argParser.addFlag('preview-dart-2', + abbr: '2', + defaultsTo: false, + help: 'Preview Dart 2.0 functionality.'); argParser.addOption('target', abbr: 't', defaultsTo: bundle.defaultMainPath, @@ -128,8 +132,13 @@ class FuchsiaReloadCommand extends FlutterCommand { final List observatoryUris = fullAddresses.map( (String a) => Uri.parse('http://$a') ).toList(); - final FuchsiaDevice device = new FuchsiaDevice(fullAddresses[0], name: _address); - final FlutterDevice flutterDevice = new FlutterDevice(device, trackWidgetCreation: false); + final FuchsiaDevice device = new FuchsiaDevice( + fullAddresses[0], name: _address); + final FlutterDevice flutterDevice = new FlutterDevice( + device, + trackWidgetCreation: false, + previewDart2: false, + ); flutterDevice.observatoryUris = observatoryUris; final HotRunner hotRunner = new HotRunner( [flutterDevice], diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 076502a3ee..2fb8efe00f 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -120,6 +120,11 @@ class RunCommand extends RunCommandBase { hide: !verboseHelp, help: 'Specify a pre-built application binary to use when running.', ) + ..addFlag('preview-dart-2', + defaultsTo: true, + hide: !verboseHelp, + help: 'Preview Dart 2.0 functionality.', + ) ..addFlag('track-widget-creation', hide: !verboseHelp, help: 'Track widget creation locations. Requires Dart 2.0 functionality.', @@ -342,6 +347,7 @@ class RunCommand extends RunCommandBase { final List flutterDevices = devices.map((Device device) { return new FlutterDevice( device, + previewDart2: argResults['preview-dart-2'], trackWidgetCreation: argResults['track-widget-creation'], dillOutputPath: argResults['output-dill'], fileSystemRoots: argResults['filesystem-root'], diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index 49320d1e39..a9252d27fc 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -68,6 +68,11 @@ class TestCommand extends FlutterCommand { help: 'Handle machine structured JSON command input\n' 'and provide output and progress in machine friendly format.', ) + ..addFlag('preview-dart-2', + defaultsTo: true, + hide: !verboseHelp, + help: 'Preview Dart 2.0 functionality.', + ) ..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp, @@ -218,6 +223,7 @@ class TestCommand extends FlutterCommand { startPaused: startPaused, ipv6: argResults['ipv6'], machine: machine, + previewDart2: argResults['preview-dart-2'], trackWidgetCreation: argResults['track-widget-creation'], updateGoldens: argResults['update-goldens'], ); diff --git a/packages/flutter_tools/lib/src/dart/analysis.dart b/packages/flutter_tools/lib/src/dart/analysis.dart index cbf0f2b0cb..65e6d10a47 100644 --- a/packages/flutter_tools/lib/src/dart/analysis.dart +++ b/packages/flutter_tools/lib/src/dart/analysis.dart @@ -13,10 +13,11 @@ import '../base/process_manager.dart'; import '../globals.dart'; class AnalysisServer { - AnalysisServer(this.sdkPath, this.directories); + AnalysisServer(this.sdkPath, this.directories, {this.previewDart2 = false}); final String sdkPath; final List directories; + final bool previewDart2; Process _process; final StreamController _analyzingController = @@ -34,9 +35,14 @@ class AnalysisServer { snapshot, '--sdk', sdkPath, - '--preview-dart-2', ]; + if (previewDart2) { + command.add('--preview-dart-2'); + } else { + command.add('--no-preview-dart-2'); + } + printTrace('dart ${command.skip(1).join(' ')}'); _process = await processManager.start(command); // This callback hookup can't throw. diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart index 9304faaccb..dce136c2a0 100644 --- a/packages/flutter_tools/lib/src/devfs.dart +++ b/packages/flutter_tools/lib/src/devfs.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:convert' show base64, utf8; import 'package:json_rpc_2/json_rpc_2.dart' as rpc; -import 'package:meta/meta.dart'; import 'asset.dart'; import 'base/context.dart'; @@ -402,14 +401,14 @@ class DevFS { /// /// Returns the number of bytes synced. Future update({ - @required String mainPath, + String mainPath, String target, AssetBundle bundle, DateTime firstBuildTime, bool bundleFirstUpload = false, bool bundleDirty = false, Set fileFilter, - @required ResidentCompiler generator, + ResidentCompiler generator, String dillOutputPath, bool fullRestart = false, String projectRootPath, @@ -425,9 +424,10 @@ class DevFS { await _scanDirectory(rootDirectory, recursive: true, fileFilter: fileFilter); + final bool previewDart2 = generator != null; if (fs.isFileSync(_packagesFilePath)) { printTrace('Scanning package files'); - await _scanPackages(fileFilter); + await _scanPackages(fileFilter, previewDart2); } if (bundle != null) { printTrace('Scanning asset files'); @@ -468,9 +468,10 @@ class DevFS { String archivePath; if (deviceUri.path.startsWith(assetBuildDirPrefix)) archivePath = deviceUri.path.substring(assetBuildDirPrefix.length); - // When doing full restart in, copy content so that isModified does not - // reset last check timestamp because we want to report all modified - // files to incremental compiler next time user does hot reload. + // When doing full restart in preview-dart-2 mode, copy content so + // that isModified does not reset last check timestamp because we + // want to report all modified files to incremental compiler next time + // user does hot reload. if (content.isModified || ((bundleDirty || bundleFirstUpload) && archivePath != null)) { dirtyEntries[deviceUri] = content; numBytes += content.size; @@ -478,24 +479,24 @@ class DevFS { assetPathsToEvict.add(archivePath); } }); - - // We run generator even if [dirtyEntries] was empty because we want to - // keep logic of accepting/rejecting generator's output simple: we must - // accept/reject generator's output after every [update] call. Incremental - // run with no changes is supposed to be fast (considering that it is - // initiated by user key press). - final List invalidatedFiles = []; - final Set filesUris = new Set(); - for (Uri uri in dirtyEntries.keys.toList()) { - if (!uri.path.startsWith(assetBuildDirPrefix)) { - final DevFSContent content = dirtyEntries[uri]; - if (content is DevFSFileContent) { - filesUris.add(uri); - invalidatedFiles.add(content.file.uri.toString()); - numBytes -= content.size; + if (previewDart2) { + // We run generator even if [dirtyEntries] was empty because we want + // to keep logic of accepting/rejecting generator's output simple: + // we must accept/reject generator's output after every [update] call. + // Incremental run with no changes is supposed to be fast (considering + // that it is initiated by user key press). + final List invalidatedFiles = []; + final Set filesUris = new Set(); + for (Uri uri in dirtyEntries.keys.toList()) { + if (!uri.path.startsWith(assetBuildDirPrefix)) { + final DevFSContent content = dirtyEntries[uri]; + if (content is DevFSFileContent) { + filesUris.add(uri); + invalidatedFiles.add(content.file.uri.toString()); + numBytes -= content.size; + } } } - // No need to send source files because all compilation is done on the // host and result of compilation is single kernel file. filesUris.forEach(dirtyEntries.remove); @@ -503,12 +504,10 @@ class DevFS { if (fullRestart) { generator.reset(); } - final CompilerOutput compilerOutput = await generator.recompile( - mainPath, - invalidatedFiles, - outputPath: dillOutputPath ?? fs.path.join(getBuildDirectory(), 'app.dill'), - packagesFilePath : _packagesFilePath, - ); + final CompilerOutput compilerOutput = + await generator.recompile(mainPath, invalidatedFiles, + outputPath: dillOutputPath ?? fs.path.join(getBuildDirectory(), 'app.dill'), + packagesFilePath : _packagesFilePath); final String compiledBinary = compilerOutput?.outputFilename; if (compiledBinary != null && compiledBinary.isNotEmpty) { final String entryUri = projectRootPath != null ? @@ -698,7 +697,7 @@ class DevFS { ); } - Future _scanPackages(Set fileFilter) async { + Future _scanPackages(Set fileFilter, bool previewDart2) async { StringBuffer sb; final PackageMap packageMap = new PackageMap(_packagesFilePath); @@ -731,6 +730,22 @@ class DevFS { sb.writeln('$packageName:$directoryUriOnDevice'); } } + if (previewDart2) { + // When in previewDart2 mode we don't update .packages-file entry + // so actual file will get invalidated in frontend. + // We don't need to synthesize device-correct .packages file because + // it is not going to be used on the device anyway - compilation + // is done on the host. + return; + } + if (sb != null) { + final DevFSContent content = _entries[fs.path.toUri('.packages')]; + if (content is DevFSStringContent && content.string == sb.toString()) { + content._exists = true; + return; + } + _entries[fs.path.toUri('.packages')] = new DevFSStringContent(sb.toString()); + } } } /// Converts a platform-specific file path to a platform-independent Uri path. diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart index 95395773c1..3d49c80582 100644 --- a/packages/flutter_tools/lib/src/ios/mac.dart +++ b/packages/flutter_tools/lib/src/ios/mac.dart @@ -246,6 +246,7 @@ Future buildXcodeProject({ projectPath: fs.currentDirectory.path, buildInfo: buildInfo, targetOverride: targetOverride, + previewDart2: buildInfo.previewDart2, ); if (hasPlugins()) { @@ -427,7 +428,7 @@ Future buildXcodeProject({ outputDir = expectedOutputDirectory.replaceFirst('/$configuration-', '/'); if (fs.isDirectorySync(outputDir)) { // Previous output directory might have incompatible artifacts - // (for example, kernel binary files produced from previous run). + // (for example, kernel binary files produced from previous `--preview-dart-2` run). fs.directory(outputDir).deleteSync(recursive: true); } copyDirectorySync(fs.directory(expectedOutputDirectory), fs.directory(outputDir)); diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart index 92d5f10035..edd34041a1 100644 --- a/packages/flutter_tools/lib/src/ios/simulators.dart +++ b/packages/flutter_tools/lib/src/ios/simulators.dart @@ -362,6 +362,7 @@ class IOSSimulator extends Device { // The build mode for the simulator is always debug. final BuildInfo debugBuildInfo = new BuildInfo(BuildMode.debug, buildInfo.flavor, + previewDart2: buildInfo.previewDart2, trackWidgetCreation: buildInfo.trackWidgetCreation, extraFrontEndOptions: buildInfo.extraFrontEndOptions, extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions, @@ -389,10 +390,12 @@ class IOSSimulator extends Device { } Future _sideloadUpdatedAssetsForInstalledApplicationBundle(ApplicationPackage app, BuildInfo buildInfo, String mainPath) { - // Run compiler to produce kernel file for the application. + // When running in previewDart2 mode, we still need to run compiler to + // produce kernel file for the application. return bundle.build( mainPath: mainPath, - precompiledSnapshot: false, + precompiledSnapshot: !buildInfo.previewDart2, + previewDart2: buildInfo.previewDart2, trackWidgetCreation: buildInfo.trackWidgetCreation, ); } diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 02cfd883ae..4dfd917ff6 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart @@ -42,6 +42,7 @@ Future generateXcodeProperties(String projectPath) async { projectPath: projectPath, buildInfo: BuildInfo.debug, targetOverride: bundle.defaultMainPath, + previewDart2: false, ); } } @@ -54,6 +55,7 @@ Future updateGeneratedXcodeProperties({ @required String projectPath, @required BuildInfo buildInfo, String targetOverride, + @required bool previewDart2, }) async { final StringBuffer localsBuffer = new StringBuffer(); @@ -111,6 +113,10 @@ Future updateGeneratedXcodeProperties({ localsBuffer.writeln('ARCHS=$arch'); } + if (previewDart2) { + localsBuffer.writeln('PREVIEW_DART_2=true'); + } + if (buildInfo.trackWidgetCreation) { localsBuffer.writeln('TRACK_WIDGET_CREATION=true'); } diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 158c7ec5e5..f6da760f2a 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -34,7 +34,7 @@ class FlutterDevice { List vmServices; DevFS devFS; ApplicationPackage package; - final ResidentCompiler generator; + ResidentCompiler generator; String dillOutputPath; List fileSystemRoots; String fileSystemScheme; @@ -42,15 +42,20 @@ class FlutterDevice { StreamSubscription _loggingSubscription; FlutterDevice(this.device, { + @required bool previewDart2, @required bool trackWidgetCreation, this.dillOutputPath, this.fileSystemRoots, this.fileSystemScheme, - }) : generator = new ResidentCompiler( - artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath), - trackWidgetCreation: trackWidgetCreation, - fileSystemRoots: fileSystemRoots, - fileSystemScheme: fileSystemScheme); + }) { + if (previewDart2) { + generator = new ResidentCompiler( + artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath), + trackWidgetCreation: trackWidgetCreation, + fileSystemRoots: fileSystemRoots, fileSystemScheme: fileSystemScheme + ); + } + } String viewFilter; @@ -407,9 +412,9 @@ class FlutterDevice { void updateReloadStatus(bool wasReloadSuccessful) { if (wasReloadSuccessful) - generator.accept(); + generator?.accept(); else - generator.reject(); + generator?.reject(); } } diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index a451d8aaff..9eeb8dfde3 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -412,11 +412,15 @@ class HotRunner extends ResidentRunner { } // We are now running from source. _runningFromSnapshot = false; - - await _launchFromDevFS('$mainPath.dill'); + final String launchPath = debuggingOptions.buildInfo.previewDart2 + ? mainPath + '.dill' + : mainPath; + await _launchFromDevFS(launchPath); restartTimer.stop(); - printTrace('Restart performed in ${getElapsedAsMilliseconds(restartTimer.elapsed)}.'); - + printTrace('Restart performed in ' + '${getElapsedAsMilliseconds(restartTimer.elapsed)}.'); + // We are now running from sources. + _runningFromSnapshot = false; _addBenchmarkData('hotRestartMillisecondsToFrame', restartTimer.elapsed.inMilliseconds); flutterUsage.sendEvent('hot', 'restart'); @@ -506,6 +510,14 @@ class HotRunner extends ResidentRunner { } } + String _uriToRelativePath(Uri uri) { + final String path = uri.toString(); + final String base = new Uri.file(projectRootPath).toString(); + if (path.startsWith(base)) + return path.substring(base.length + 1); + return path; + } + Future _reloadSources({ bool pause = false }) async { for (FlutterDevice device in flutterDevices) { for (FlutterView view in device.views) { @@ -525,6 +537,7 @@ class HotRunner extends ResidentRunner { // change from host path to a device path). Subsequent reloads will // not be affected, so we resume reporting reload times on the second // reload. + final bool reportUnused = !debuggingOptions.buildInfo.previewDart2; final bool shouldReportReloadTime = !_runningFromSnapshot; final Stopwatch reloadTimer = new Stopwatch()..start(); @@ -538,7 +551,10 @@ class HotRunner extends ResidentRunner { String reloadMessage; final Stopwatch vmReloadTimer = new Stopwatch()..start(); try { - final String entryPath = fs.path.relative('$mainPath.dill', from: projectRootPath); + final String entryPath = fs.path.relative( + debuggingOptions.buildInfo.previewDart2 ? mainPath + '.dill' : mainPath, + from: projectRootPath, + ); final Completer> retrieveFirstReloadReport = new Completer>(); int countExpectedReports = 0; @@ -550,7 +566,10 @@ class HotRunner extends ResidentRunner { } // List has one report per Flutter view. - final List>> reports = device.reloadSources(entryPath, pause: pause); + final List>> reports = device.reloadSources( + entryPath, + pause: pause + ); countExpectedReports += reports.length; Future.wait(reports).catchError((dynamic error) { return >[error]; @@ -618,8 +637,8 @@ class HotRunner extends ResidentRunner { } // We are now running from source. _runningFromSnapshot = false; - // Check if the isolate is paused. + final List reassembleViews = []; for (FlutterDevice device in flutterDevices) { for (FlutterView view in device.views) { @@ -680,9 +699,36 @@ class HotRunner extends ResidentRunner { shouldReportReloadTime) flutterUsage.sendTiming('hot', 'reload', reloadTimer.elapsed); + String unusedElementMessage; + if (reportUnused && !reassembleAndScheduleErrors && !reassembleTimedOut) { + final List>> unusedReports = + >>[]; + for (FlutterDevice device in flutterDevices) + unusedReports.add(device.unusedChangesInLastReload()); + final List unusedElements = []; + for (Future> unusedReport in unusedReports) + unusedElements.addAll(await unusedReport); + + if (unusedElements.isNotEmpty) { + final String restartCommand = hostIsIde ? '' : ' (by pressing "R")'; + unusedElementMessage = + 'Some program elements were changed during reload but did not run when the view was reassembled;\n' + 'you may need to restart the app$restartCommand for the changes to have an effect.'; + for (ProgramElement unusedElement in unusedElements) { + final String name = unusedElement.qualifiedName; + final String path = _uriToRelativePath(unusedElement.uri); + final int line = unusedElement.line; + final String description = line == null ? '$name ($path)' : '$name ($path:$line)'; + unusedElementMessage += '\n • $description'; + } + } + } + return new OperationResult( reassembleAndScheduleErrors ? 1 : OperationResult.ok.code, reloadMessage, + hintMessage: unusedElementMessage, + hintId: unusedElementMessage != null ? 'restartRecommended' : null, ); } diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 1cd2a5b125..ad85b9ce05 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -182,6 +182,10 @@ abstract class FlutterCommand extends Command { } BuildInfo getBuildInfo() { + final bool previewDart2 = argParser.options.containsKey('preview-dart-2') + ? argResults['preview-dart-2'] + : true; + TargetPlatform targetPlatform; if (argParser.options.containsKey('target-platform') && argResults['target-platform'] != 'default') { @@ -191,6 +195,10 @@ abstract class FlutterCommand extends Command { final bool trackWidgetCreation = argParser.options.containsKey('track-widget-creation') ? argResults['track-widget-creation'] : false; + if (trackWidgetCreation == true && previewDart2 == false) { + throw new UsageException( + '--track-widget-creation is valid only when --preview-dart-2 is specified.', null); + } int buildNumber; try { @@ -206,6 +214,7 @@ abstract class FlutterCommand extends Command { argParser.options.containsKey('flavor') ? argResults['flavor'] : null, + previewDart2: previewDart2, trackWidgetCreation: trackWidgetCreation, extraFrontEndOptions: argParser.options.containsKey(FlutterOptions.kExtraFrontEndOptions) ? argResults[FlutterOptions.kExtraFrontEndOptions] diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart index 2ea22361c0..81948aeb16 100644 --- a/packages/flutter_tools/lib/src/test/flutter_platform.dart +++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart @@ -67,6 +67,7 @@ void installHook({ bool enableObservatory = false, bool machine = false, bool startPaused = false, + bool previewDart2 = false, int port = 0, String precompiledDillPath, bool trackWidgetCreation = false, @@ -85,6 +86,7 @@ void installHook({ startPaused: startPaused, explicitObservatoryPort: observatoryPort, host: _kHosts[serverType], + previewDart2: previewDart2, port: port, precompiledDillPath: precompiledDillPath, trackWidgetCreation: trackWidgetCreation, @@ -304,6 +306,7 @@ class _FlutterPlatform extends PlatformPlugin { this.startPaused, this.explicitObservatoryPort, this.host, + this.previewDart2, this.port, this.precompiledDillPath, this.trackWidgetCreation, @@ -317,6 +320,7 @@ class _FlutterPlatform extends PlatformPlugin { final bool startPaused; final int explicitObservatoryPort; final InternetAddress host; + final bool previewDart2; final int port; final String precompiledDillPath; final bool trackWidgetCreation; @@ -404,15 +408,17 @@ class _FlutterPlatform extends PlatformPlugin { cancelOnError: true, ); - printTrace('test $ourTestCount: starting shell process'); + printTrace('test $ourTestCount: starting shell process${previewDart2? " in preview-dart-2 mode":""}'); + // [precompiledDillPath] can be set only if [previewDart2] is [true]. + assert(precompiledDillPath == null || previewDart2); // If a kernel file is given, then use that to launch the test. // Otherwise create a "listener" dart that invokes actual test. String mainDart = precompiledDillPath != null ? precompiledDillPath : _createListenerDart(finalizers, ourTestCount, testPath, server); - if (precompiledDillPath == null) { + if (previewDart2 && precompiledDillPath == null) { // Lazily instantiate compiler so it is built only if it is actually used. compiler ??= new _Compiler(trackWidgetCreation); mainDart = await compiler.compile(mainDart); @@ -669,6 +675,10 @@ class _FlutterPlatform extends PlatformPlugin { } String _getBundlePath(List<_Finalizer> finalizers, int ourTestCount) { + if (!previewDart2) { + return null; + } + if (precompiledDillPath != null) { return artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath); } diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart index b59ad182a6..384d64c3d1 100644 --- a/packages/flutter_tools/lib/src/test/runner.dart +++ b/packages/flutter_tools/lib/src/test/runner.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:args/command_runner.dart'; // ignore: implementation_imports import 'package:test/src/executable.dart' as test; @@ -28,10 +29,18 @@ Future runTests( bool startPaused = false, bool ipv6 = false, bool machine = false, + bool previewDart2 = false, bool trackWidgetCreation = false, bool updateGoldens = false, TestWatcher watcher, }) async { + if (trackWidgetCreation && !previewDart2) { + throw new UsageException( + '--track-widget-creation is valid only when --preview-dart-2 is specified.', + null, + ); + } + // Compute the command-line arguments for package:test. final List testArgs = []; if (!terminal.supportsColor) { @@ -78,6 +87,7 @@ Future runTests( machine: machine, startPaused: startPaused, serverType: serverType, + previewDart2: previewDart2, trackWidgetCreation: trackWidgetCreation, updateGoldens: updateGoldens, ); diff --git a/packages/flutter_tools/lib/src/tester/flutter_tester.dart b/packages/flutter_tools/lib/src/tester/flutter_tester.dart index c6bebb1e4d..53f67fafff 100644 --- a/packages/flutter_tools/lib/src/tester/flutter_tester.dart +++ b/packages/flutter_tools/lib/src/tester/flutter_tester.dart @@ -133,11 +133,20 @@ class FlutterTesterDevice extends Device { mainPath: mainPath, assetDirPath: assetDirPath, applicationKernelFilePath: applicationKernelFilePath, - precompiledSnapshot: false, + precompiledSnapshot: !buildInfo.previewDart2, + previewDart2: buildInfo.previewDart2, trackWidgetCreation: buildInfo.trackWidgetCreation, ); + if (buildInfo.previewDart2) { + mainPath = applicationKernelFilePath; + } + command.add('--flutter-assets-dir=$assetDirPath'); - command.add(applicationKernelFilePath); + + // TODO(scheglov): Either remove the check, or make it fail earlier. + if (mainPath != null) { + command.add(mainPath); + } try { printTrace(command.join(' ')); diff --git a/packages/flutter_tools/test/base/build_test.dart b/packages/flutter_tools/test/base/build_test.dart index f13a8a7f60..08b54b2f37 100644 --- a/packages/flutter_tools/test/base/build_test.dart +++ b/packages/flutter_tools/test/base/build_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:convert' show json; import 'package:file/memory.dart'; import 'package:flutter_tools/src/android/android_sdk.dart'; @@ -84,6 +85,199 @@ void main() { }); }); + group('Snapshotter - Script Snapshots', () { + const String kVersion = '123456abcdef'; + const String kIsolateSnapshotData = 'isolate_snapshot.bin'; + const String kVmSnapshotData = 'vm_isolate_snapshot.bin'; + + _FakeGenSnapshot genSnapshot; + MemoryFileSystem fs; + MockFlutterVersion mockVersion; + ScriptSnapshotter snapshotter; + MockArtifacts mockArtifacts; + + setUp(() { + fs = new MemoryFileSystem(); + fs.file(kIsolateSnapshotData).writeAsStringSync('snapshot data'); + fs.file(kVmSnapshotData).writeAsStringSync('vm data'); + genSnapshot = new _FakeGenSnapshot(); + genSnapshot.outputs = { + 'output.snapshot': '', + 'output.snapshot.d': 'output.snapshot.d : main.dart', + }; + mockVersion = new MockFlutterVersion(); + when(mockVersion.frameworkRevision).thenReturn(kVersion); + snapshotter = new ScriptSnapshotter(); + mockArtifacts = new MockArtifacts(); + when(mockArtifacts.getArtifactPath(Artifact.isolateSnapshotData)).thenReturn(kIsolateSnapshotData); + when(mockArtifacts.getArtifactPath(Artifact.vmSnapshotData)).thenReturn(kVmSnapshotData); + }); + + final Map contextOverrides = { + Artifacts: () => mockArtifacts, + FileSystem: () => fs, + FlutterVersion: () => mockVersion, + GenSnapshot: () => genSnapshot, + }; + + Future writeFingerprint({ Map files = const {} }) { + return fs.file('output.snapshot.d.fingerprint').writeAsString(json.encode({ + 'version': kVersion, + 'properties': { + 'buildMode': BuildMode.debug.toString(), + 'targetPlatform': '', + 'entryPoint': 'main.dart', + }, + 'files': { + kVmSnapshotData: '2ec34912477a46c03ddef07e8b909b46', + kIsolateSnapshotData: '621b3844bb7d4d17d2cfc5edf9a91c4c', + }..addAll(files), + })); + } + + void expectFingerprintHas({ + String entryPoint = 'main.dart', + Map checksums = const {}, + }) { + final Map jsonObject = json.decode(fs.file('output.snapshot.d.fingerprint').readAsStringSync()); + expect(jsonObject['properties']['entryPoint'], entryPoint); + expect(jsonObject['files'], hasLength(checksums.length + 2)); + checksums.forEach((String filePath, String checksum) { + expect(jsonObject['files'][filePath], checksum); + }); + expect(jsonObject['files'][kVmSnapshotData], '2ec34912477a46c03ddef07e8b909b46'); + expect(jsonObject['files'][kIsolateSnapshotData], '621b3844bb7d4d17d2cfc5edf9a91c4c'); + } + + testUsingContext('builds snapshot and fingerprint when no fingerprint is present', () async { + await fs.file('main.dart').writeAsString('void main() {}'); + await fs.file('output.snapshot').create(); + await fs.file('output.snapshot.d').writeAsString('snapshot : main.dart'); + await snapshotter.build( + mainPath: 'main.dart', + snapshotPath: 'output.snapshot', + depfilePath: 'output.snapshot.d', + packagesPath: '.packages', + ); + + expect(genSnapshot.callCount, 1); + expect(genSnapshot.snapshotType.platform, isNull); + expect(genSnapshot.snapshotType.mode, BuildMode.debug); + expect(genSnapshot.packagesPath, '.packages'); + expect(genSnapshot.depfilePath, 'output.snapshot.d'); + expect(genSnapshot.additionalArgs, [ + '--snapshot_kind=script', + '--script_snapshot=output.snapshot', + '--vm_snapshot_data=vm_isolate_snapshot.bin', + '--isolate_snapshot_data=isolate_snapshot.bin', + '--enable-mirrors=false', + 'main.dart', + ]); + expectFingerprintHas(checksums: { + 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }); + }, overrides: contextOverrides); + + testUsingContext('builds snapshot and fingerprint when fingerprints differ', () async { + await fs.file('main.dart').writeAsString('void main() {}'); + await fs.file('output.snapshot').create(); + await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart'); + await writeFingerprint(files: { + 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', + 'output.snapshot': 'deadbeef000b204e9800998ecaaaaa', + }); + await snapshotter.build( + mainPath: 'main.dart', + snapshotPath: 'output.snapshot', + depfilePath: 'output.snapshot.d', + packagesPath: '.packages', + ); + + expect(genSnapshot.callCount, 1); + expectFingerprintHas(checksums: { + 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }); + }, overrides: contextOverrides); + + testUsingContext('builds snapshot and fingerprint when fingerprints match but previous snapshot not present', () async { + await fs.file('main.dart').writeAsString('void main() {}'); + await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart'); + await writeFingerprint(files: { + 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }); + await snapshotter.build( + mainPath: 'main.dart', + snapshotPath: 'output.snapshot', + depfilePath: 'output.snapshot.d', + packagesPath: '.packages', + ); + + expect(genSnapshot.callCount, 1); + expectFingerprintHas(checksums: { + 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }); + }, overrides: contextOverrides); + + testUsingContext('builds snapshot and fingerprint when main entry point changes to other dependency', () async { + await fs.file('main.dart').writeAsString('import "other.dart";\nvoid main() {}'); + await fs.file('other.dart').writeAsString('import "main.dart";\nvoid main() {}'); + await fs.file('output.snapshot').create(); + await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart'); + await writeFingerprint(files: { + 'main.dart': 'bc096b33f14dde5e0ffaf93a1d03395c', + 'other.dart': 'e0c35f083f0ad76b2d87100ec678b516', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }); + genSnapshot.outputs = { + 'output.snapshot': '', + 'output.snapshot.d': 'output.snapshot : main.dart other.dart', + }; + + await snapshotter.build( + mainPath: 'other.dart', + snapshotPath: 'output.snapshot', + depfilePath: 'output.snapshot.d', + packagesPath: '.packages', + ); + + expect(genSnapshot.callCount, 1); + expectFingerprintHas( + entryPoint: 'other.dart', + checksums: { + 'main.dart': 'bc096b33f14dde5e0ffaf93a1d03395c', + 'other.dart': 'e0c35f083f0ad76b2d87100ec678b516', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }, + ); + }, overrides: contextOverrides); + + testUsingContext('skips snapshot when fingerprints match and previous snapshot is present', () async { + await fs.file('main.dart').writeAsString('void main() {}'); + await fs.file('output.snapshot').create(); + await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart'); + await writeFingerprint(files: { + 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }); + await snapshotter.build( + mainPath: 'main.dart', + snapshotPath: 'output.snapshot', + depfilePath: 'output.snapshot.d', + packagesPath: '.packages', + ); + + expect(genSnapshot.callCount, 0); + expectFingerprintHas(checksums: { + 'main.dart': '27f5ebf0f8c559b2af9419d190299a5e', + 'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e', + }); + }, overrides: contextOverrides); + }); + group('Snapshotter - iOS AOT', () { const String kVmEntrypoints = 'dart_vm_entry_points.txt'; const String kIoEntries = 'dart_io_entries.txt'; @@ -146,6 +340,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, ), isNot(equals(0))); }, overrides: contextOverrides); @@ -158,6 +353,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, ), isNot(0)); }, overrides: contextOverrides); @@ -170,6 +366,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, ), isNot(0)); }, overrides: contextOverrides); @@ -195,6 +392,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, iosArch: IOSArch.armv7, ); @@ -241,6 +439,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, iosArch: IOSArch.arm64, ); @@ -288,6 +487,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, ); expect(genSnapshotExitCode, 0); @@ -339,6 +539,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, ); expect(genSnapshotExitCode, 0); @@ -385,6 +586,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, iosArch: IOSArch.armv7, ); @@ -431,6 +633,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, iosArch: IOSArch.arm64, ); @@ -465,6 +668,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: true, + previewDart2: true, ); expect(genSnapshotExitCode, isNot(0)); @@ -496,6 +700,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, ); expect(genSnapshotExitCode, 0); @@ -547,6 +752,7 @@ void main() { packagesPath: '.packages', outputPath: outputPath, buildSharedLibrary: false, + previewDart2: true, ); expect(genSnapshotExitCode, 0); diff --git a/packages/flutter_tools/test/commands/analyze_continuously_test.dart b/packages/flutter_tools/test/commands/analyze_continuously_test.dart index 4166ae82fd..850efb9222 100644 --- a/packages/flutter_tools/test/commands/analyze_continuously_test.dart +++ b/packages/flutter_tools/test/commands/analyze_continuously_test.dart @@ -70,10 +70,10 @@ void main() { OperatingSystemUtils: () => os }); - testUsingContext('Returns no errors when source is error-free', () async { + testUsingContext('--preview-dart-2', () async { const String contents = "StringBuffer bar = StringBuffer('baz');"; tempDir.childFile('main.dart').writeAsStringSync(contents); - server = new AnalysisServer(dartSdkPath, [tempDir.path]); + server = new AnalysisServer(dartSdkPath, [tempDir.path], previewDart2: true); int errorCount = 0; final Future onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first; @@ -88,6 +88,25 @@ void main() { }, overrides: { OperatingSystemUtils: () => os }); + + testUsingContext('no --preview-dart-2 shows errors', () async { + const String contents = "StringBuffer bar = StringBuffer('baz');"; + tempDir.childFile('main.dart').writeAsStringSync(contents); + server = new AnalysisServer(dartSdkPath, [tempDir.path], previewDart2: false); + + int errorCount = 0; + final Future onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first; + server.onErrors.listen((FileAnalysisErrors errors) { + errorCount += errors.errors.length; + }); + + await server.start(); + await onDone; + + expect(errorCount, 1); + }, overrides: { + OperatingSystemUtils: () => os + }); } void _createSampleProject(Directory directory, { bool brokenCode = false }) { diff --git a/packages/flutter_tools/test/commands/analyze_once_test.dart b/packages/flutter_tools/test/commands/analyze_once_test.dart index 63c97d373c..e721ac64d1 100644 --- a/packages/flutter_tools/test/commands/analyze_once_test.dart +++ b/packages/flutter_tools/test/commands/analyze_once_test.dart @@ -168,7 +168,7 @@ void bar() { } }); - testUsingContext('returns no issues when source is error-free', () async { + testUsingContext('--preview-dart-2', () async { const String contents = ''' StringBuffer bar = StringBuffer('baz'); '''; @@ -179,13 +179,33 @@ StringBuffer bar = StringBuffer('baz'); try { await runCommand( command: new AnalyzeCommand(workingDirectory: fs.directory(tempDir)), - arguments: ['analyze'], + arguments: ['analyze', '--preview-dart-2'], statusTextContains: ['No issues found!'], ); } finally { tempDir.deleteSync(recursive: true); } }); + + testUsingContext('no --preview-dart-2 shows errors', () async { + const String contents = ''' +StringBuffer bar = StringBuffer('baz'); +'''; + + final Directory tempDir = fs.systemTempDirectory.createTempSync(); + tempDir.childFile('main.dart').writeAsStringSync(contents); + + try { + await runCommand( + command: new AnalyzeCommand(workingDirectory: fs.directory(tempDir)), + arguments: ['analyze', '--no-preview-dart-2'], + statusTextContains: ['1 issue found.'], + toolExit: true, + ); + } finally { + tempDir.deleteSync(recursive: true); + } + }); }); } diff --git a/packages/flutter_tools/test/commands/drive_test.dart b/packages/flutter_tools/test/commands/drive_test.dart index 1e656049e1..d5543b6f72 100644 --- a/packages/flutter_tools/test/commands/drive_test.dart +++ b/packages/flutter_tools/test/commands/drive_test.dart @@ -54,7 +54,7 @@ void main() { appStarter = (DriveCommand command) { throw 'Unexpected call to appStarter'; }; - testRunner = (List testArgs, String observatoryUri) { + testRunner = (List testArgs, String observatoryUri, bool previewDart2) { throw 'Unexpected call to testRunner'; }; appStopper = (DriveCommand command) { @@ -169,7 +169,7 @@ void main() { appStarter = expectAsync1((DriveCommand command) async { return new LaunchResult.succeeded(); }); - testRunner = expectAsync2((List testArgs, String observatoryUri) async { + testRunner = expectAsync3((List testArgs, String observatoryUri, bool previewDart2) async { expect(testArgs, [testFile]); return null; }); @@ -200,7 +200,7 @@ void main() { appStarter = expectAsync1((DriveCommand command) async { return new LaunchResult.succeeded(); }); - testRunner = (List testArgs, String observatoryUri) async { + testRunner = (List testArgs, String observatoryUri, bool previewDart2) async { throwToolExit(null, exitCode: 123); }; appStopper = expectAsync1((DriveCommand command) async { diff --git a/packages/flutter_tools/test/devfs_test.dart b/packages/flutter_tools/test/devfs_test.dart index 17097609a2..2f165a3ddc 100644 --- a/packages/flutter_tools/test/devfs_test.dart +++ b/packages/flutter_tools/test/devfs_test.dart @@ -11,7 +11,6 @@ import 'package:flutter_tools/src/asset.dart'; import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/build_info.dart'; -import 'package:flutter_tools/src/compile.dart'; import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/vmservice.dart'; import 'package:json_rpc_2/json_rpc_2.dart' as rpc; @@ -68,7 +67,6 @@ void main() { group('devfs local', () { final MockDevFSOperations devFSOperations = new MockDevFSOperations(); - final MockResidentCompiler residentCompiler = new MockResidentCompiler(); setUpAll(() { tempDir = _newTempDir(fs); @@ -91,13 +89,22 @@ void main() { devFSOperations.expectMessages(['create test']); expect(devFS.assetPathsToEvict, isEmpty); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + final int bytes = await devFS.update(); devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', + 'writeFile test .packages', + 'writeFile test lib/foo.txt', + 'writeFile test packages/somepkg/somefile.txt', ]); expect(devFS.assetPathsToEvict, isEmpty); - expect(bytes, 22); + final List packageSpecOnDevice = LineSplitter.split(utf8.decode( + await devFSOperations.devicePathToContent[fs.path.toUri('.packages')].contentsAsBytes() + )).toList(); + expect(packageSpecOnDevice, + unorderedEquals(['my_project:lib/', 'somepkg:packages/somepkg/']) + ); + + expect(bytes, 48); }, overrides: { FileSystem: () => fs, }); @@ -106,33 +113,48 @@ void main() { final File file = fs.file(fs.path.join(basePath, filePath2)); await file.parent.create(recursive: true); file.writeAsBytesSync([1, 2, 3, 4, 5, 6, 7]); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + final int bytes = await devFS.update(); devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', + 'writeFile test foo/bar.txt', ]); expect(devFS.assetPathsToEvict, isEmpty); - expect(bytes, 22); + expect(bytes, 7); + }, overrides: { + FileSystem: () => fs, + }); + + testUsingContext('add new file to local file system and preserve unusual file name casing', () async { + final String filePathWithUnusualCasing = fs.path.join('FooBar', 'TEST.txt'); + final File file = fs.file(fs.path.join(basePath, filePathWithUnusualCasing)); + await file.parent.create(recursive: true); + file.writeAsBytesSync([1, 2, 3, 4, 5, 6, 7]); + final int bytes = await devFS.update(); + devFSOperations.expectMessages([ + 'writeFile test FooBar/TEST.txt', + ]); + expect(devFS.assetPathsToEvict, isEmpty); + expect(bytes, 7); }, overrides: { FileSystem: () => fs, }); testUsingContext('modify existing file on local file system', () async { - await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + await devFS.update(); final File file = fs.file(fs.path.join(basePath, filePath)); // Set the last modified time to 5 seconds in the past. updateFileModificationTime(file.path, new DateTime.now(), -5); - int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + int bytes = await devFS.update(); devFSOperations.expectMessages([]); expect(devFS.assetPathsToEvict, isEmpty); expect(bytes, 0); await file.writeAsBytes([1, 2, 3, 4, 5, 6]); - bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + bytes = await devFS.update(); devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', + 'writeFile test lib/foo.txt', ]); expect(devFS.assetPathsToEvict, isEmpty); - expect(bytes, 22); + expect(bytes, 6); }, overrides: { FileSystem: () => fs, }); @@ -140,7 +162,7 @@ void main() { testUsingContext('delete a file from the local file system', () async { final File file = fs.file(fs.path.join(basePath, filePath)); await file.delete(); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + final int bytes = await devFS.update(); devFSOperations.expectMessages([ 'deleteFile test lib/foo.txt', ]); @@ -152,12 +174,13 @@ void main() { testUsingContext('add new package', () async { await _createPackage(fs, 'newpkg', 'anotherfile.txt'); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + final int bytes = await devFS.update(); devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', + 'writeFile test .packages', + 'writeFile test packages/newpkg/anotherfile.txt', ]); expect(devFS.assetPathsToEvict, isEmpty); - expect(bytes, 22); + expect(bytes, 69); }, overrides: { FileSystem: () => fs, }); @@ -178,65 +201,63 @@ void main() { .map((FileSystemEntity file) => canonicalizePath(file.path)) .toList()); } - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', fileFilter: fileFilter, generator: residentCompiler); + final int bytes = await devFS.update(fileFilter: fileFilter); devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', + 'writeFile test .packages', + 'writeFile test packages/doubleslashpkg/somefile.txt', ]); expect(devFS.assetPathsToEvict, isEmpty); - expect(bytes, 22); + expect(bytes, 109); }, overrides: { FileSystem: () => fs, }); testUsingContext('add an asset bundle', () async { assetBundle.entries['a.txt'] = new DevFSStringContent('abc'); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, bundleDirty: true, generator: residentCompiler); + final int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true); devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', 'writeFile test ${_inAssetBuildDirectory(fs, 'a.txt')}', ]); expect(devFS.assetPathsToEvict, unorderedMatches(['a.txt'])); devFS.assetPathsToEvict.clear(); - expect(bytes, 22 + 3); + expect(bytes, 3); }, overrides: { FileSystem: () => fs, }); testUsingContext('add a file to the asset bundle - bundleDirty', () async { assetBundle.entries['b.txt'] = new DevFSStringContent('abcd'); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, bundleDirty: true, generator: residentCompiler); + final int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true); // Expect entire asset bundle written because bundleDirty is true devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', 'writeFile test ${_inAssetBuildDirectory(fs, 'a.txt')}', 'writeFile test ${_inAssetBuildDirectory(fs, 'b.txt')}', ]); expect(devFS.assetPathsToEvict, unorderedMatches([ 'a.txt', 'b.txt'])); devFS.assetPathsToEvict.clear(); - expect(bytes, 22 + 7); + expect(bytes, 7); }, overrides: { FileSystem: () => fs, }); testUsingContext('add a file to the asset bundle', () async { assetBundle.entries['c.txt'] = new DevFSStringContent('12'); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, generator: residentCompiler); + final int bytes = await devFS.update(bundle: assetBundle); devFSOperations.expectMessages([ - 'writeFile test lib/foo.txt.dill', 'writeFile test ${_inAssetBuildDirectory(fs, 'c.txt')}', ]); expect(devFS.assetPathsToEvict, unorderedMatches([ 'c.txt'])); devFS.assetPathsToEvict.clear(); - expect(bytes, 22 + 2); + expect(bytes, 2); }, overrides: { FileSystem: () => fs, }); testUsingContext('delete a file from the asset bundle', () async { assetBundle.entries.remove('c.txt'); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, generator: residentCompiler); + final int bytes = await devFS.update(bundle: assetBundle); devFSOperations.expectMessages([ 'deleteFile test ${_inAssetBuildDirectory(fs, 'c.txt')}', ]); @@ -249,7 +270,7 @@ void main() { testUsingContext('delete all files from the asset bundle', () async { assetBundle.entries.clear(); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, bundleDirty: true, generator: residentCompiler); + final int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true); devFSOperations.expectMessages([ 'deleteFile test ${_inAssetBuildDirectory(fs, 'a.txt')}', 'deleteFile test ${_inAssetBuildDirectory(fs, 'b.txt')}', @@ -274,7 +295,6 @@ void main() { group('devfs remote', () { MockVMService vmService; - final MockResidentCompiler residentCompiler = new MockResidentCompiler(); setUpAll(() async { tempDir = _newTempDir(fs); @@ -301,12 +321,14 @@ void main() { vmService.expectMessages(['create test']); expect(devFS.assetPathsToEvict, isEmpty); - final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler); + final int bytes = await devFS.update(); vmService.expectMessages([ - 'writeFile test lib/foo.txt.dill', + 'writeFile test .packages', + 'writeFile test lib/foo.txt', + 'writeFile test packages/somepkg/somefile.txt', ]); expect(devFS.assetPathsToEvict, isEmpty); - expect(bytes, 22); + expect(bytes, 48); }, overrides: { FileSystem: () => fs, }); @@ -349,38 +371,6 @@ void main() { }); } -class MockResidentCompiler extends BasicMock implements ResidentCompiler { - @override - void accept() {} - - @override - void reject() {} - - @override - void reset() {} - - @override - Future shutdown() async {} - - @override - Future compileExpression( - String expression, - List definitions, - List typeDefinitions, - String libraryUri, - String klass, - bool isStatic - ) async { - return null; - } - @override - Future recompile(String mainPath, List invalidatedFiles, {String outputPath, String packagesFilePath}) async { - fs.file(outputPath).createSync(recursive: true); - fs.file(outputPath).writeAsStringSync('compiled_kernel_output'); - return new CompilerOutput(outputPath, 0); - } -} - class MockVMService extends BasicMock implements VMService { Uri _httpAddress; HttpServer _server; diff --git a/packages/flutter_tools/test/ios/xcodeproj_test.dart b/packages/flutter_tools/test/ios/xcodeproj_test.dart index 357e75dd20..31b1bccd43 100644 --- a/packages/flutter_tools/test/ios/xcodeproj_test.dart +++ b/packages/flutter_tools/test/ios/xcodeproj_test.dart @@ -284,10 +284,14 @@ Information about project "Runner": testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async { when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine'); when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm')); - const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, targetPlatform: TargetPlatform.ios); + const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, + previewDart2: true, + targetPlatform: TargetPlatform.ios, + ); await updateGeneratedXcodeProperties( projectPath: 'path/to/project', buildInfo: buildInfo, + previewDart2: true, ); final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); @@ -301,12 +305,14 @@ Information about project "Runner": when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine'); when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm')); const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, + previewDart2: true, trackWidgetCreation: true, targetPlatform: TargetPlatform.ios, ); await updateGeneratedXcodeProperties( projectPath: 'path/to/project', buildInfo: buildInfo, + previewDart2: true, ); final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); @@ -319,10 +325,14 @@ Information about project "Runner": testUsingOsxContext('does not set TRACK_WIDGET_CREATION when trackWidgetCreation is false', () async { when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine'); when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm')); - const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, targetPlatform: TargetPlatform.ios); + const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, + previewDart2: true, + targetPlatform: TargetPlatform.ios, + ); await updateGeneratedXcodeProperties( projectPath: 'path/to/project', buildInfo: buildInfo, + previewDart2: true, ); final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); @@ -335,10 +345,14 @@ Information about project "Runner": testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async { when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine'); when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile')); - const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, targetPlatform: TargetPlatform.ios); + const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, + previewDart2: true, + targetPlatform: TargetPlatform.ios, + ); await updateGeneratedXcodeProperties( projectPath: 'path/to/project', buildInfo: buildInfo, + previewDart2: true, ); final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); @@ -391,6 +405,7 @@ Information about project "Runner": projectPath: projectPath, buildInfo: buildInfo, targetOverride: bundle.defaultMainPath, + previewDart2: false, ); final String propertiesPath = fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig'); diff --git a/packages/flutter_tools/test/resident_runner_test.dart b/packages/flutter_tools/test/resident_runner_test.dart index 2007e450b6..ebe65cd8be 100644 --- a/packages/flutter_tools/test/resident_runner_test.dart +++ b/packages/flutter_tools/test/resident_runner_test.dart @@ -44,11 +44,14 @@ class TestRunner extends ResidentRunner { void main() { TestRunner createTestRunner() { - // TODO(jacobr): make these tests run with `trackWidgetCreation: true` as - // well as the default flags. + // TODO(jacobr): make these tests run with `previewDart2: true` and + // `trackWidgetCreation: true` as well as the default flags. + // Currently the TestRunner is not properly configured to be able to run + // with `previewDart2: true` due to missing resources. return new TestRunner( [new FlutterDevice( new MockDevice(), + previewDart2: false, trackWidgetCreation: false, )], ); diff --git a/packages/flutter_tools/test/tester/flutter_tester_test.dart b/packages/flutter_tools/test/tester/flutter_tester_test.dart index 4bfa70a0f8..af38a1ba9a 100644 --- a/packages/flutter_tools/test/tester/flutter_tester_test.dart +++ b/packages/flutter_tools/test/tester/flutter_tester_test.dart @@ -6,14 +6,11 @@ import 'dart:async'; import 'package:file/file.dart'; import 'package:file/memory.dart'; -import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/cache.dart'; -import 'package:flutter_tools/src/compile.dart'; import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/tester/flutter_tester.dart'; -import 'package:mockito/mockito.dart'; import 'package:process/process.dart'; import 'package:test/test.dart'; @@ -100,8 +97,6 @@ void main() { String projectPath; String mainPath; - MockArtifacts mockArtifacts; - MockKernelCompiler mockKernelCompiler; MockProcessManager mockProcessManager; MockProcess mockProcess; @@ -110,8 +105,6 @@ void main() { FileSystem: () => fs, Cache: () => new Cache(rootOverride: fs.directory(flutterRoot)), ProcessManager: () => mockProcessManager, - KernelCompiler: () => mockKernelCompiler, - Artifacts: () => mockArtifacts, }; setUp(() { @@ -129,13 +122,6 @@ void main() { mockProcessManager = new MockProcessManager(); mockProcessManager.processFactory = (List commands) => mockProcess; - - mockArtifacts = new MockArtifacts(); - final String artifactPath = fs.path.join(flutterRoot, 'artifact'); - fs.file(artifactPath).createSync(recursive: true); - when(mockArtifacts.getArtifactPath(any)).thenReturn(artifactPath); - - mockKernelCompiler = new MockKernelCompiler(); }); testUsingContext('not debug', () async { @@ -167,22 +153,6 @@ Hello! .codeUnits ])); - when(mockKernelCompiler.compile( - sdkRoot: any, - incrementalCompilerByteStorePath: any, - mainPath: any, - outputFilePath: any, - depFilePath: any, - trackWidgetCreation: any, - extraFrontEndOptions: any, - fileSystemRoots: any, - fileSystemScheme: any, - packagesPath: any, - )).thenAnswer((_) async { - fs.file('$mainPath.dill').createSync(recursive: true); - return new CompilerOutput('$mainPath.dill', 0); - }); - final LaunchResult result = await device.startApp(null, mainPath: mainPath, debuggingOptions: new DebuggingOptions.enabled( @@ -195,6 +165,3 @@ Hello! }); }); } - -class MockArtifacts extends Mock implements Artifacts {} -class MockKernelCompiler extends Mock implements KernelCompiler {}