| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| // for details. 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:barback/barback.dart'; |
| import 'package:bazel_worker/bazel_worker.dart'; |
| |
| import 'common.dart'; |
| import 'errors.dart'; |
| import 'module.dart'; |
| import 'module_reader.dart'; |
| import 'scratch_space.dart'; |
| import 'workers.dart'; |
| |
| final String linkedSummaryExtension = '.linked.sum'; |
| final String unlinkedSummaryExtension = '.unlinked.sum'; |
| |
| /// Creates a linked summary for [module]. |
| /// |
| /// [unlinkedSummaryIds] should contain unlinked summaries for all transitive |
| /// deps of [module], and [scratchSpace] must have those files available as well |
| /// as the original Dart sources for this module. |
| /// |
| /// Synchronously returns a `Map<AssetId, Future<Asset>>` so that you can know |
| /// immediately what assets will be output. |
| Future<Asset> createLinkedSummary( |
| AssetId id, ModuleReader moduleReader, ScratchSpace scratchSpace, |
| {bool isRoot = false}) async { |
| assert(id.path.endsWith(linkedSummaryExtension)); |
| var module = await moduleReader.moduleFor(id); |
| var transitiveModuleDeps = await moduleReader.readTransitiveDeps(module); |
| var unlinkedSummaryIds = |
| transitiveModuleDeps.map((depId) => depId.unlinkedSummaryId).toSet(); |
| var allAssetIds = new Set<AssetId>() |
| ..addAll(module.assetIds) |
| ..addAll(unlinkedSummaryIds) |
| ..add(defaultAnalysisOptionsId); |
| await scratchSpace.ensureAssets(allAssetIds); |
| var summaryOutputFile = scratchSpace.fileFor(module.id.linkedSummaryId); |
| var request = new WorkRequest(); |
| // TODO(jakemac53): Diet parsing results in erroneous errors in later steps, |
| // but ideally we would do that (pass '--build-summary-only-diet'). |
| request.arguments.addAll([ |
| '--build-summary-only', |
| '--build-summary-output=${summaryOutputFile.path}', |
| '--strong', |
| ]); |
| // Add all the unlinked summaries as build summary inputs. |
| request.arguments.addAll(unlinkedSummaryIds.map((id) => |
| '--build-summary-unlinked-input=${scratchSpace.fileFor(id).path}')); |
| // Add the default analysis_options if not the root package. |
| if (!isRoot) { |
| request.arguments.add(defaultAnalysisOptionsArg(scratchSpace)); |
| } |
| // Add all the files to include in the linked summary bundle. |
| request.arguments.addAll(_analyzerSourceArgsForModule(module, scratchSpace)); |
| var response = await analyzerDriver.doWork(request); |
| if (response.exitCode == EXIT_CODE_ERROR) { |
| throw new AnalyzerSummaryException( |
| module.id.linkedSummaryId, response.output); |
| } |
| return new Asset.fromBytes( |
| module.id.linkedSummaryId, summaryOutputFile.readAsBytesSync()); |
| } |
| |
| /// Creates an unlinked summary at [id]. |
| Future<Asset> createUnlinkedSummary( |
| AssetId id, ModuleReader moduleReader, ScratchSpace scratchSpace, |
| {bool isRoot = false}) async { |
| assert(id.path.endsWith(unlinkedSummaryExtension)); |
| var module = await moduleReader.moduleFor(id); |
| await scratchSpace |
| .ensureAssets(module.assetIds.toSet()..add(defaultAnalysisOptionsId)); |
| var summaryOutputFile = scratchSpace.fileFor(module.id.unlinkedSummaryId); |
| var request = new WorkRequest(); |
| // TODO(jakemac53): Diet parsing results in erroneous errors later on today, |
| // but ideally we would do that (pass '--build-summary-only-diet'). |
| request.arguments.addAll([ |
| '--build-summary-only', |
| '--build-summary-only-unlinked', |
| '--build-summary-output=${summaryOutputFile.path}', |
| '--strong', |
| ]); |
| // Add the default analysis_options if not the root package. |
| if (!isRoot) { |
| request.arguments.add(defaultAnalysisOptionsArg(scratchSpace)); |
| } |
| // Add all the files to include in the unlinked summary bundle. |
| request.arguments.addAll(_analyzerSourceArgsForModule(module, scratchSpace)); |
| var response = await analyzerDriver.doWork(request); |
| if (response.exitCode == EXIT_CODE_ERROR) { |
| throw new AnalyzerSummaryException( |
| module.id.unlinkedSummaryId, response.output); |
| } |
| return new Asset.fromBytes( |
| module.id.unlinkedSummaryId, summaryOutputFile.readAsBytesSync()); |
| } |
| |
| Iterable<String> _analyzerSourceArgsForModule( |
| Module module, ScratchSpace scratchSpace) { |
| return module.assetIds.map((id) { |
| var uri = canonicalUriFor(id); |
| var file = scratchSpace.fileFor(id); |
| if (!uri.startsWith('package:')) { |
| uri = file.uri.toString(); |
| } |
| return '$uri|${file.path}'; |
| }); |
| } |