| // 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' show Future; |
| |
| import 'package:kernel/kernel.dart' show Component; |
| |
| import 'package:kernel/target/targets.dart' show Target; |
| |
| import '../api_prototype/compiler_options.dart' show CompilerOptions; |
| |
| import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler; |
| |
| import '../api_prototype/experimental_flags.dart' show ExperimentalFlag; |
| |
| import '../api_prototype/file_system.dart' show FileSystem; |
| |
| import '../base/processed_options.dart' show ProcessedOptions; |
| |
| import '../base/libraries_specification.dart' show LibrariesSpecification; |
| |
| import '../fasta/compiler_context.dart' show CompilerContext; |
| |
| import '../fasta/fasta_codes.dart' show messageMissingMain; |
| |
| import '../fasta/severity.dart' show Severity; |
| |
| import '../kernel_generator_impl.dart' show generateKernelInternal; |
| |
| import '../fasta/scanner.dart' show ErrorToken, StringToken, Token; |
| |
| import 'compiler_state.dart' show InitializedCompilerState; |
| |
| export '../api_prototype/compiler_options.dart' |
| show CompilerOptions, parseExperimentalFlags; |
| |
| export '../api_prototype/diagnostic_message.dart' |
| show |
| DiagnosticMessage, |
| getMessageCharOffset, |
| getMessageHeaderText, |
| getMessageLength, |
| getMessageRelatedInformation, |
| getMessageUri; |
| |
| export '../api_prototype/experimental_flags.dart' show ExperimentalFlag; |
| |
| export '../api_prototype/file_system.dart' |
| show FileSystem, FileSystemEntity, FileSystemException; |
| |
| export '../api_prototype/kernel_generator.dart' show kernelForProgram; |
| |
| export '../api_prototype/standard_file_system.dart' show DataFileSystemEntity; |
| |
| export '../compute_platform_binaries_location.dart' |
| show computePlatformBinariesLocation; |
| |
| export '../fasta/fasta_codes.dart' show LocatedMessage; |
| |
| export '../fasta/kernel/redirecting_factory_body.dart' |
| show RedirectingFactoryBody; |
| |
| export '../fasta/operator.dart' show operatorFromString; |
| |
| export '../fasta/parser/async_modifier.dart' show AsyncModifier; |
| |
| export '../fasta/scanner.dart' show isUserDefinableOperator, isMinusOperator; |
| |
| export '../fasta/scanner/characters.dart' |
| show |
| $$, |
| $0, |
| $9, |
| $A, |
| $BACKSLASH, |
| $CR, |
| $DEL, |
| $DQ, |
| $HASH, |
| $LF, |
| $LS, |
| $PS, |
| $TAB, |
| $Z, |
| $_, |
| $a, |
| $g, |
| $s, |
| $z; |
| |
| export '../fasta/severity.dart' show Severity; |
| |
| export '../fasta/util/link.dart' show Link, LinkBuilder; |
| |
| export '../fasta/util/link_implementation.dart' show LinkEntry; |
| |
| export '../fasta/util/relativize.dart' show relativizeUri; |
| |
| export 'compiler_state.dart' show InitializedCompilerState; |
| |
| void clearStringTokenCanonicalizer() { |
| // TODO(ahe): We should be able to remove this. Fasta should take care of |
| // clearing the cache when. |
| StringToken.canonicalizer.clear(); |
| } |
| |
| InitializedCompilerState initializeCompiler( |
| InitializedCompilerState oldState, |
| Target target, |
| Uri librariesSpecificationUri, |
| List<Uri> linkedDependencies, |
| Uri packagesFileUri, |
| {List<Uri> dependencies, |
| Map<ExperimentalFlag, bool> experimentalFlags}) { |
| bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) { |
| if (a == null || b == null) return a == b; |
| if (a.length != b.length) return false; |
| for (var flag in a.keys) { |
| if (!b.containsKey(flag) || a[flag] != b[flag]) return false; |
| } |
| return true; |
| } |
| |
| bool listEqual(List<Uri> a, List<Uri> b) { |
| if (a.length != b.length) return false; |
| for (int i = 0; i < a.length; ++i) { |
| if (a[i] != b[i]) return false; |
| } |
| return true; |
| } |
| |
| linkedDependencies.sort((a, b) => a.toString().compareTo(b.toString())); |
| |
| if (oldState != null && |
| oldState.options.packagesFileUri == packagesFileUri && |
| oldState.options.librariesSpecificationUri == librariesSpecificationUri && |
| listEqual(oldState.options.linkedDependencies, linkedDependencies) && |
| mapEqual(oldState.options.experimentalFlags, experimentalFlags)) { |
| return oldState; |
| } |
| |
| CompilerOptions options = new CompilerOptions() |
| ..target = target |
| ..legacyMode = target.legacyMode |
| ..linkedDependencies = linkedDependencies |
| ..librariesSpecificationUri = librariesSpecificationUri |
| ..packagesFileUri = packagesFileUri |
| ..experimentalFlags = experimentalFlags; |
| |
| ProcessedOptions processedOpts = new ProcessedOptions(options: options); |
| |
| return new InitializedCompilerState(options, processedOpts); |
| } |
| |
| Future<Component> compile( |
| InitializedCompilerState state, |
| bool verbose, |
| FileSystem fileSystem, |
| DiagnosticMessageHandler onDiagnostic, |
| Uri input) async { |
| CompilerOptions options = state.options; |
| options |
| ..onDiagnostic = onDiagnostic |
| ..verbose = verbose |
| ..fileSystem = fileSystem; |
| |
| ProcessedOptions processedOpts = state.processedOpts; |
| processedOpts.inputs.clear(); |
| processedOpts.inputs.add(input); |
| processedOpts.clearFileSystemCache(); |
| |
| var compilerResult = await CompilerContext.runWithOptions(processedOpts, |
| (CompilerContext context) async { |
| var compilerResult = await generateKernelInternal(); |
| Component component = compilerResult?.component; |
| if (component == null) return null; |
| if (component.mainMethod == null) { |
| context.options.report( |
| messageMissingMain.withLocation(input, -1, 0), Severity.error); |
| return null; |
| } |
| return compilerResult; |
| }); |
| |
| // Remove these parameters from [options] - they are no longer needed and |
| // retain state from the previous compile. (http://dartbug.com/33708) |
| options.onDiagnostic = null; |
| options.fileSystem = null; |
| return compilerResult?.component; |
| } |
| |
| Object tokenToString(Object value) { |
| // TODO(ahe): This method is most likely unnecessary. Dart2js doesn't see |
| // tokens anymore. |
| if (value is ErrorToken) { |
| // Shouldn't happen. |
| return value.assertionMessage.message; |
| } else if (value is Token) { |
| return value.lexeme; |
| } else { |
| return value; |
| } |
| } |
| |
| /// Retrieve the name of the libraries that are supported by [target] according |
| /// to the libraries specification [json] file. |
| /// |
| /// Dart2js uses these names to determine the value of library environment |
| /// constants, such as `const bool.fromEnvironment("dart.library.io")`. |
| // TODO(sigmund): refactor dart2js so that we can retrieve this data later in |
| // the compilation pipeline. At that point we can get it from the CFE |
| // results directly and completely hide the libraries specification file from |
| // dart2js. |
| // TODO(sigmund): delete after all constant evaluation is done in the CFE, as |
| // this data will no longer be needed on the dart2js side. |
| Iterable<String> getSupportedLibraryNames( |
| Uri librariesSpecificationUri, String json, String target) { |
| return LibrariesSpecification.parse(librariesSpecificationUri, json) |
| .specificationFor(target) |
| .allLibraries |
| .where((l) => l.isSupported) |
| .map((l) => l.name); |
| } |