blob: ebacbfc97854945fd733b7898c08292f354f744e [file] [log] [blame]
// Copyright (c) 2016, 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.
library fasta.target_implementation;
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:kernel/ast.dart' show Library, Source, Version;
import 'package:kernel/target/targets.dart' as backend show Target;
import '../base/processed_options.dart' show ProcessedOptions;
import 'builder/class_builder.dart';
import 'builder/library_builder.dart';
import 'builder/member_builder.dart';
import 'compiler_context.dart' show CompilerContext;
import 'loader.dart' show Loader;
import 'messages.dart' show FormattedMessage, LocatedMessage, Message;
import 'rewrite_severity.dart' show rewriteSeverity;
import 'target.dart' show Target;
import 'ticker.dart' show Ticker;
import 'uri_translator.dart' show UriTranslator;
import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
/// Provides the implementation details used by a loader for a target.
abstract class TargetImplementation extends Target {
final UriTranslator uriTranslator;
final backend.Target backendTarget;
final CompilerContext context = CompilerContext.current;
/// Shared with [CompilerContext].
final Map<Uri, Source> uriToSource = CompilerContext.current.uriToSource;
MemberBuilder cachedAbstractClassInstantiationError;
MemberBuilder cachedCompileTimeError;
MemberBuilder cachedDuplicatedFieldInitializerError;
MemberBuilder cachedNativeAnnotation;
final ProcessedOptions _options;
TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
: assert(ticker != null),
assert(uriTranslator != null),
assert(backendTarget != null),
_options = CompilerContext.current.options,
bool isExperimentEnabledInLibrary(ExperimentalFlag flag, Uri importUri) {
return _options.isExperimentEnabledInLibrary(flag, importUri);
Version getExperimentEnabledVersion(ExperimentalFlag flag) {
return _options.getExperimentEnabledVersion(flag);
bool isExperimentEnabledGlobally(ExperimentalFlag flag) {
return _options.isExperimentEnabledGlobally(flag);
/// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
/// already.
/// [fileUri] must not be null and is a URI that can be passed to FileSystem
/// to locate the corresponding file.
/// [origin] is non-null if the created library is a patch to [origin].
/// [packageUri] is the base uri for the package which the library belongs to.
/// For instance 'package:foo'.
/// This is used to associate libraries in for instance the 'bin' and 'test'
/// folders of a package source with the package uri of the 'lib' folder.
/// If the [packageUri] is `null` the package association of this library is
/// based on its [importUri].
/// For libraries with a 'package:' [importUri], the package path must match
/// the path in the [importUri]. For libraries with a 'dart:' [importUri] the
/// [packageUri] must be `null`.
LibraryBuilder createLibraryBuilder(
Uri uri,
Uri fileUri,
Uri packageUri,
covariant LibraryBuilder origin,
Library referencesFrom,
bool referenceIsPartOwner);
/// The class [cls] is involved in a cyclic definition. This method should
/// ensure that the cycle is broken, for example, by removing superclass and
/// implemented interfaces.
void breakCycle(ClassBuilder cls);
Uri translateUri(Uri uri) => uriTranslator.translate(uri);
/// Returns a reference to the constructor of
/// [AbstractClassInstantiationError] error. The constructor is expected to
/// accept a single argument of type String, which is the name of the
/// abstract class.
MemberBuilder getAbstractClassInstantiationError(Loader loader) {
if (cachedAbstractClassInstantiationError != null) {
return cachedAbstractClassInstantiationError;
return cachedAbstractClassInstantiationError =
/// Returns a reference to the constructor used for creating a compile-time
/// error. The constructor is expected to accept a single argument of type
/// String, which is the compile-time error message.
MemberBuilder getCompileTimeError(Loader loader) {
if (cachedCompileTimeError != null) return cachedCompileTimeError;
return cachedCompileTimeError = loader.coreLibrary
.getConstructor("_CompileTimeError", bypassLibraryPrivacy: true);
/// Returns a reference to the constructor used for creating a runtime error
/// when a final field is initialized twice. The constructor is expected to
/// accept a single argument which is the name of the field.
MemberBuilder getDuplicatedFieldInitializerError(Loader loader) {
if (cachedDuplicatedFieldInitializerError != null) {
return cachedDuplicatedFieldInitializerError;
return cachedDuplicatedFieldInitializerError = loader.coreLibrary
bypassLibraryPrivacy: true);
/// Returns a reference to the constructor used for creating `native`
/// annotations. The constructor is expected to accept a single argument of
/// type String, which is the name of the native method.
MemberBuilder getNativeAnnotation(Loader loader) {
if (cachedNativeAnnotation != null) return cachedNativeAnnotation;
LibraryBuilder internal ="dart:_internal"), -1,
accessor: loader.coreLibrary);
return cachedNativeAnnotation = internal.getConstructor("ExternalName");
void loadExtraRequiredLibraries(Loader loader) {
for (String uri in backendTarget.extraRequiredLibraries) {, 0, accessor: loader.coreLibrary);
if (context.compilingPlatform) {
for (String uri in backendTarget.extraRequiredLibrariesPlatform) {, 0, accessor: loader.coreLibrary);
void addSourceInformation(
Uri importUri, Uri fileUri, List<int> lineStarts, List<int> sourceCode);
void readPatchFiles(covariant LibraryBuilder library) {}
FormattedMessage createFormattedMessage(
Message message,
int charOffset,
int length,
Uri fileUri,
List<LocatedMessage> messageContext,
Severity severity) {
ProcessedOptions processedOptions = context.options;
return processedOptions.format(
message.withLocation(fileUri, charOffset, length),
Severity fixSeverity(Severity severity, Message message, Uri fileUri) {
severity ??= message.code.severity;
return rewriteSeverity(severity, message.code, fileUri);
String get currentSdkVersionString {
return CompilerContext.current.options.currentSdkVersion;
Version _currentSdkVersion;
Version get currentSdkVersion {
if (_currentSdkVersion != null) return _currentSdkVersion;
return _currentSdkVersion;
void _parseCurrentSdkVersion() {
bool good = false;
if (currentSdkVersionString != null) {
List<String> dotSeparatedParts = currentSdkVersionString.split(".");
if (dotSeparatedParts.length >= 2) {
_currentSdkVersion = new Version(int.tryParse(dotSeparatedParts[0]),
good = true;
if (!good) {
throw new StateError(
"Unparsable sdk version given: $currentSdkVersionString");
void releaseAncillaryResources();