cleanup use of build runner internals (#40045)


diff --git a/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart b/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart
index 60d8be3..4425a72 100644
--- a/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart
+++ b/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart
@@ -7,205 +7,74 @@
 import 'dart:io' as io; // ignore: dart_io_import
 
 import 'package:build/build.dart';
+import 'package:build_daemon/client.dart';
+import 'package:build_daemon/data/build_status.dart';
 import 'package:build_runner_core/build_runner_core.dart' as core;
-import 'package:build_runner_core/src/asset_graph/graph.dart';
-import 'package:build_runner_core/src/asset_graph/node.dart';
-import 'package:build_runner_core/src/generate/build_impl.dart';
-import 'package:build_runner_core/src/generate/options.dart';
 import 'package:glob/glob.dart';
-import 'package:logging/logging.dart';
-import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
-import 'package:watcher/watcher.dart';
 
-import '../artifacts.dart';
 import '../base/file_system.dart';
-import '../base/logger.dart';
-import '../base/platform.dart';
 import '../build_info.dart';
-import '../compile.dart';
 import '../convert.dart';
-import '../dart/package_map.dart';
-import '../globals.dart';
 import '../web/compile.dart';
-import 'build_script.dart';
+import 'web_fs.dart';
 
 /// A build_runner specific implementation of the [WebCompilationProxy].
 class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
   BuildRunnerWebCompilationProxy();
 
-  core.PackageGraph _packageGraph;
-  BuildImpl _builder;
-  PackageUriMapper _packageUriMapper;
-
   @override
   Future<bool> initialize({
     Directory projectDirectory,
     String testOutputDir,
     BuildMode mode,
+    String projectName
   }) async {
     // Create the .dart_tool directory if it doesn't exist.
-    projectDirectory.childDirectory('.dart_tool').createSync();
-    final Directory generatedDirectory = projectDirectory
+    projectDirectory
       .childDirectory('.dart_tool')
-      .childDirectory('build')
-      .childDirectory('generated');
-
-    // Override the generated output directory so this does not conflict with
-    // other build_runner output.
-    core.overrideGeneratedOutputDirectory('flutter_web');
-    _packageUriMapper = PackageUriMapper(
-        path.absolute('lib/main.dart'), PackageMap.globalPackagesPath, null, null);
-    _packageGraph = core.PackageGraph.forPath(projectDirectory.path);
-
-    final core.BuildEnvironment buildEnvironment = core.OverrideableEnvironment(
-        core.IOEnvironment(_packageGraph), onLog: (LogRecord record) {
-      if (record.level == Level.SEVERE || record.level == Level.SHOUT) {
-        printError(record.message);
-      } else {
-        printTrace(record.message);
-      }
-    }, reader: MultirootFileBasedAssetReader(_packageGraph, generatedDirectory));
-    final LogSubscription logSubscription = LogSubscription(
-      buildEnvironment,
-      verbose: false,
-      logLevel: Level.FINE,
-    );
-    final BuildOptions buildOptions = await BuildOptions.create(
-      logSubscription,
-      packageGraph: _packageGraph,
-      skipBuildScriptCheck: true,
-      trackPerformance: false,
-      deleteFilesByDefault: true,
-      enableLowResourcesMode: platform.environment['FLUTTER_LOW_RESOURCE_MODE']?.toLowerCase() == 'true',
-    );
-    final Set<core.BuildDirectory> buildDirs = <core.BuildDirectory>{
-      if (testOutputDir != null)
-        core.BuildDirectory(
-          'test',
-          outputLocation: core.OutputLocation(
-            testOutputDir,
-            useSymlinks: !platform.isWindows,
-          ),
-      ),
-    };
-    core.BuildResult result;
-    try {
-      result = await _runBuilder(
-        buildEnvironment,
-        buildOptions,
-        mode,
-        buildDirs,
-      );
-      return result.status == core.BuildStatus.success;
-    } on core.BuildConfigChangedException {
-      await _cleanAssets(projectDirectory);
-      result = await _runBuilder(
-        buildEnvironment,
-        buildOptions,
-        mode,
-        buildDirs,
-      );
-      return result.status == core.BuildStatus.success;
-    } on core.BuildScriptChangedException {
-      await _cleanAssets(projectDirectory);
-      result = await _runBuilder(
-        buildEnvironment,
-        buildOptions,
-        mode,
-        buildDirs,
-      );
-      return result.status == core.BuildStatus.success;
-    }
-  }
-
-  @override
-  Future<bool> invalidate({@required List<Uri> inputs}) async {
-    final Status status =
-        logger.startProgress('Recompiling sources...', timeout: null);
-    final Map<AssetId, ChangeType> updates = <AssetId, ChangeType>{};
-    for (Uri input in inputs) {
-      final AssetId assetId = AssetId.resolve(_packageUriMapper.map(input.toFilePath()).toString());
-      updates[assetId] = ChangeType.MODIFY;
-    }
-    core.BuildResult result;
-    try {
-      result = await _builder.run(updates);
-    } finally {
-      status.cancel();
-    }
-    return result.status == core.BuildStatus.success;
-  }
-
-  Future<core.BuildResult> _runBuilder(core.BuildEnvironment buildEnvironment, BuildOptions buildOptions, BuildMode buildMode, Set<core.BuildDirectory> buildDirs) async {
-    _builder = await BuildImpl.create(
-      buildOptions,
-      buildEnvironment,
-      builders,
-      <String, Map<String, dynamic>>{
-        'flutter_tools:ddc': <String, dynamic>{
-          'flutterWebSdk': artifacts.getArtifactPath(Artifact.flutterWebSdk),
-        },
-        'flutter_tools:entrypoint': <String, dynamic>{
-          'release': buildMode == BuildMode.release,
-          'flutterWebSdk': artifacts.getArtifactPath(Artifact.flutterWebSdk),
-          'profile': buildMode == BuildMode.profile,
-        },
-        'flutter_tools:test_entrypoint': <String, dynamic>{
-          'release': buildMode == BuildMode.release,
-          'profile': buildMode == BuildMode.profile,
-        },
-      },
-      isReleaseBuild: false,
-    );
-    return _builder.run(
-      const <AssetId, ChangeType>{},
-      buildDirs: buildDirs,
-    );
-  }
-
-  Future<void> _cleanAssets(Directory projectDirectory) async {
-    final File assetGraphFile = fs.file(core.assetGraphPath);
-    AssetGraph assetGraph;
-    try {
-      assetGraph = AssetGraph.deserialize(await assetGraphFile.readAsBytes());
-    } catch (_) {
-      printTrace('Failed to clean up asset graph.');
-    }
-    final core.PackageGraph packageGraph = core.PackageGraph.forThisPackage();
-    await _cleanUpSourceOutputs(assetGraph, packageGraph);
-    final Directory cacheDirectory = fs.directory(fs.path.join(
+      .createSync();
+    final BuildDaemonClient client = await buildDaemonCreator.startBuildDaemon(
       projectDirectory.path,
-      '.dart_tool',
-      'build',
-      'flutter_web',
-    ));
-    if (assetGraphFile.existsSync()) {
-      assetGraphFile.deleteSync();
+      release: mode == BuildMode.release,
+      profile: mode == BuildMode.profile,
+      hasPlugins: false,
+      includeTests: true,
+    );
+    client.startBuild();
+    bool success = true;
+    await for (BuildResults results in client.buildResults) {
+      final BuildResult result = results.results.firstWhere((BuildResult result) {
+        return result.target == 'web';
+      });
+      if (result.status == BuildStatus.failed) {
+        success = false;
+        break;
+      }
+      if (result.status == BuildStatus.succeeded) {
+        break;
+      }
     }
-    if (cacheDirectory.existsSync()) {
-      cacheDirectory.deleteSync(recursive: true);
-    }
-  }
+    if (success && testOutputDir != null) {
+      final Directory rootDirectory = projectDirectory
+        .childDirectory('.dart_tool')
+        .childDirectory('build')
+        .childDirectory('flutter_web');
 
-  Future<void> _cleanUpSourceOutputs(AssetGraph assetGraph, core.PackageGraph packageGraph) async {
-    final core.FileBasedAssetWriter writer = core.FileBasedAssetWriter(packageGraph);
-    if (assetGraph?.outputs == null) {
-      return;
-    }
-    for (AssetId id in assetGraph.outputs) {
-      if (id.package != packageGraph.root.name) {
-        continue;
+      final Iterable<Directory> childDirectories = rootDirectory
+        .listSync()
+        .whereType<Directory>();
+      for (Directory childDirectory in childDirectories) {
+        final String path = fs.path.join(testOutputDir, 'packages',
+            fs.path.basename(childDirectory.path));
+        copyDirectorySync(childDirectory.childDirectory('lib'), fs.directory(path));
       }
-      final GeneratedAssetNode node = assetGraph.get(id);
-      if (node.wasOutput) {
-        // Note that this does a file.exists check in the root package and
-        // only tries to delete the file if it exists. This way we only
-        // actually delete to_source outputs, without reading in the build
-        // actions.
-        await writer.delete(id);
-      }
+      final Directory outputDirectory = rootDirectory
+          .childDirectory(projectName)
+          .childDirectory('test');
+      copyDirectorySync(outputDirectory, fs.directory(fs.path.join(testOutputDir)));
     }
+    return success;
   }
 }
 
diff --git a/packages/flutter_tools/lib/src/build_runner/web_fs.dart b/packages/flutter_tools/lib/src/build_runner/web_fs.dart
index fa7aa71..36c3611 100644
--- a/packages/flutter_tools/lib/src/build_runner/web_fs.dart
+++ b/packages/flutter_tools/lib/src/build_runner/web_fs.dart
@@ -336,7 +336,12 @@
   static const String _ignoredLine3 = 'have your dependencies specified fully in your pubspec.yaml';
 
   /// Start a build daemon and register the web targets.
-  Future<BuildDaemonClient> startBuildDaemon(String workingDirectory, {bool release = false, bool profile = false, bool hasPlugins = false}) async {
+  Future<BuildDaemonClient> startBuildDaemon(String workingDirectory, {
+    bool release = false,
+    bool profile = false,
+    bool hasPlugins = false,
+    bool includeTests = false,
+  }) async {
     try {
       final BuildDaemonClient client = await _connectClient(
         workingDirectory,
@@ -344,7 +349,7 @@
         profile: profile,
         hasPlugins: hasPlugins,
       );
-      _registerBuildTargets(client);
+      _registerBuildTargets(client, includeTests);
       return client;
     } on OptionsSkew {
       throwToolExit(
@@ -357,6 +362,7 @@
 
   void _registerBuildTargets(
     BuildDaemonClient client,
+    bool includeTests,
   ) {
     final OutputLocation outputLocation = OutputLocation((OutputLocationBuilder b) => b
       ..output = ''
@@ -365,6 +371,11 @@
     client.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder b) => b
       ..target = 'web'
       ..outputLocation = outputLocation?.toBuilder()));
+    if (includeTests) {
+      client.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder b) => b
+        ..target = 'test'
+        ..outputLocation = outputLocation?.toBuilder()));
+    }
   }
 
   Future<BuildDaemonClient> _connectClient(
diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart
index a230b21..dc83d9b 100644
--- a/packages/flutter_tools/lib/src/test/runner.dart
+++ b/packages/flutter_tools/lib/src/test/runner.dart
@@ -69,6 +69,7 @@
     final bool result = await webCompilationProxy.initialize(
       projectDirectory: flutterProject.directory,
       testOutputDir: tempBuildDir,
+      projectName: flutterProject.manifest.appName,
     );
     if (!result) {
       throwToolExit('Failed to compile tests');
diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart
index 94bd2ac..f749851 100644
--- a/packages/flutter_tools/lib/src/web/compile.dart
+++ b/packages/flutter_tools/lib/src/web/compile.dart
@@ -31,6 +31,7 @@
     result = await webCompilationProxy.initialize(
       projectDirectory: FlutterProject.current().directory,
       mode: buildInfo.mode,
+      projectName: flutterProject.manifest.appName,
     );
     if (result) {
       // Places assets adjacent to the web stuff.
@@ -80,14 +81,10 @@
   /// the entrypoints for dart2js to later take over.
   Future<bool> initialize({
     @required Directory projectDirectory,
+    @required String projectName,
     String testOutputDir,
     BuildMode mode,
   }) async {
     throw UnimplementedError();
   }
-
-  /// Invalidate the source files in `inputs` and recompile them to JavaScript.
-  Future<void> invalidate({@required List<Uri> inputs}) async {
-    throw UnimplementedError();
-  }
 }
diff --git a/packages/flutter_tools/test/general.shard/commands/build_web_test.dart b/packages/flutter_tools/test/general.shard/commands/build_web_test.dart
index 6f2341a..dab520e 100644
--- a/packages/flutter_tools/test/general.shard/commands/build_web_test.dart
+++ b/packages/flutter_tools/test/general.shard/commands/build_web_test.dart
@@ -41,6 +41,7 @@
       fs.file(fs.path.join('web', 'index.html')).createSync(recursive: true);
       fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
       when(mockWebCompilationProxy.initialize(
+        projectName: anyNamed('projectName'),
         projectDirectory: anyNamed('projectDirectory'),
         mode: anyNamed('mode')
       )).thenAnswer((Invocation invocation) {