| // 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. | |
| /// API needed by `utils/front_end/summary_worker.dart`, a tool used to compute | |
| /// summaries in build systems like bazel, pub-build, and package-build. | |
| import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart' | |
| show DiagnosticMessageHandler; | |
| import 'package:kernel/kernel.dart' show Component, Library, dummyComponent; | |
| import 'package:kernel/target/targets.dart' show Target; | |
| import '../api_prototype/compiler_options.dart'; | |
| import '../api_prototype/experimental_flags.dart' show ExperimentalFlag; | |
| import '../api_prototype/file_system.dart' show FileSystem; | |
| import '../api_prototype/front_end.dart' show CompilerResult; | |
| import '../base/processed_options.dart' show ProcessedOptions; | |
| import '../kernel_generator_impl.dart' show generateKernel; | |
| import 'compiler_state.dart' show InitializedCompilerState; | |
| import 'modular_incremental_compilation.dart' | |
| as modular | |
| show initializeIncrementalCompiler; | |
| export 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart' | |
| show CfeDiagnosticMessage; | |
| export 'package:_fe_analyzer_shared/src/messages/severity.dart' | |
| show CfeSeverity; | |
| export '../api_prototype/compiler_options.dart' | |
| show parseExperimentalFlags, parseExperimentalArguments, Verbosity; | |
| export '../api_prototype/experimental_flags.dart' | |
| show ExperimentalFlag, parseExperimentalFlag; | |
| export '../api_prototype/standard_file_system.dart' show StandardFileSystem; | |
| export '../api_prototype/terminal_color_support.dart' | |
| show printDiagnosticMessage; | |
| export '../kernel/utils.dart' show serializeComponent; | |
| export 'compiler_state.dart' show InitializedCompilerState; | |
| /// Initializes the compiler for a modular build. | |
| /// | |
| /// Re-uses cached components from [oldState.workerInputCache], and reloads them | |
| /// as necessary based on [workerInputDigests]. | |
| Future<InitializedCompilerState> initializeIncrementalCompiler( | |
| InitializedCompilerState? oldState, | |
| Set<String> tags, | |
| Uri? sdkSummary, | |
| Uri? packagesFile, | |
| Uri? librariesSpecificationUri, | |
| List<Uri> additionalDillModules, | |
| Map<Uri, List<int>> workerInputDigests, | |
| Target target, | |
| FileSystem fileSystem, | |
| Iterable<String>? experiments, | |
| bool outlineOnly, | |
| Map<String, String> environmentDefines, { | |
| bool trackNeededDillLibraries = false, | |
| bool verbose = false, | |
| }) { | |
| List<Component> outputLoadedAdditionalDillModules = | |
| new List<Component>.filled(additionalDillModules.length, dummyComponent); | |
| Map<ExperimentalFlag, bool> experimentalFlags = parseExperimentalFlags( | |
| parseExperimentalArguments(experiments), | |
| onError: (e) => throw e, | |
| ); | |
| return modular.initializeIncrementalCompiler( | |
| oldState, | |
| tags, | |
| outputLoadedAdditionalDillModules, | |
| sdkSummary, | |
| packagesFile, | |
| librariesSpecificationUri, | |
| additionalDillModules, | |
| workerInputDigests, | |
| target, | |
| fileSystem: fileSystem, | |
| explicitExperimentalFlags: experimentalFlags, | |
| outlineOnly: outlineOnly, | |
| omitPlatform: true, | |
| trackNeededDillLibraries: trackNeededDillLibraries, | |
| environmentDefines: environmentDefines, | |
| verbose: verbose, | |
| ); | |
| } | |
| InitializedCompilerState initializeCompiler( | |
| InitializedCompilerState? oldState, | |
| Uri? sdkSummary, | |
| Uri? librariesSpecificationUri, | |
| Uri? packagesFile, | |
| List<Uri> additionalDillModules, | |
| Target target, | |
| FileSystem fileSystem, | |
| Iterable<String> experiments, | |
| Map<String, String>? environmentDefines, { | |
| bool verbose = false, | |
| }) { | |
| // TODO(sigmund): use incremental compiler when it supports our use case. | |
| // Note: it is common for the summary worker to invoke the compiler with the | |
| // same input summary URIs, but with different contents, so we'd need to be | |
| // able to track shas or modification time-stamps to be able to invalidate the | |
| // old state appropriately. | |
| CompilerOptions options = new CompilerOptions() | |
| ..sdkSummary = sdkSummary | |
| ..packagesFileUri = packagesFile | |
| ..librariesSpecificationUri = librariesSpecificationUri | |
| ..additionalDillModules = additionalDillModules | |
| ..target = target | |
| ..fileSystem = fileSystem | |
| ..environmentDefines = environmentDefines | |
| ..explicitExperimentalFlags = parseExperimentalFlags( | |
| parseExperimentalArguments(experiments), | |
| onError: (e) => throw e, | |
| ) | |
| ..verbose = verbose; | |
| ProcessedOptions processedOpts = new ProcessedOptions(options: options); | |
| return new InitializedCompilerState(options, processedOpts); | |
| } | |
| Future<CompilerResult> _compile( | |
| InitializedCompilerState compilerState, | |
| List<Uri> inputs, | |
| DiagnosticMessageHandler diagnosticMessageHandler, { | |
| bool? buildSummary, | |
| bool? buildComponent, | |
| bool includeOffsets = true, | |
| }) { | |
| buildSummary ??= true; | |
| buildComponent ??= true; | |
| CompilerOptions options = compilerState.options; | |
| options..onDiagnostic = diagnosticMessageHandler; | |
| ProcessedOptions processedOpts = compilerState.processedOpts; | |
| processedOpts.inputs.clear(); | |
| processedOpts.inputs.addAll(inputs); | |
| return generateKernel( | |
| processedOpts, | |
| buildSummary: buildSummary, | |
| buildComponent: buildComponent, | |
| includeOffsets: includeOffsets, | |
| ); | |
| } | |
| Future<List<int>?> compileSummary( | |
| InitializedCompilerState compilerState, | |
| List<Uri> inputs, | |
| DiagnosticMessageHandler diagnosticMessageHandler, { | |
| bool includeOffsets = false, | |
| }) async { | |
| CompilerResult result = await _compile( | |
| compilerState, | |
| inputs, | |
| diagnosticMessageHandler, | |
| buildSummary: true, | |
| buildComponent: false, | |
| includeOffsets: includeOffsets, | |
| ); | |
| return result.summary; | |
| } | |
| Future<Component?> compileComponent( | |
| InitializedCompilerState compilerState, | |
| List<Uri> inputs, | |
| DiagnosticMessageHandler diagnosticMessageHandler, { | |
| bool buildSummary = true, | |
| }) async { | |
| CompilerResult result = await _compile( | |
| compilerState, | |
| inputs, | |
| diagnosticMessageHandler, | |
| buildSummary: buildSummary, | |
| buildComponent: true, | |
| ); | |
| Component? component = result.component; | |
| if (component != null) { | |
| for (Library lib in component.libraries) { | |
| if (!inputs.contains(lib.importUri)) { | |
| // Excluding the library also means that their canonical names will not | |
| // be computed as part of serialization, so we need to do that | |
| // preemptively here to avoid errors when serializing references to | |
| // elements of these libraries. | |
| lib.bindCanonicalNames(component.root); | |
| } | |
| } | |
| } | |
| return component; | |
| } |