|  | // Copyright (c) 2012, 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 compiler; | 
|  |  | 
|  | import 'dart:async'; | 
|  |  | 
|  | import 'package:front_end/src/api_unstable/dart2js.dart' as fe; | 
|  |  | 
|  | import 'src/compiler.dart'; | 
|  | import 'src/diagnostics/messages.dart'; | 
|  | import 'src/options.dart'; | 
|  |  | 
|  | /// Kind of diagnostics that the compiler can report. | 
|  | enum Diagnostic { | 
|  | /// An error as identified by the "Dart Programming Language | 
|  | /// Specification" [https://dart.dev/guides/language/spec]. | 
|  | /// | 
|  | /// Note: the compiler may still produce an executable result after | 
|  | /// reporting a compilation error. The specification says: | 
|  | /// | 
|  | /// "A compile-time error must be reported by a Dart compiler before | 
|  | /// the erroneous code is executed." and "If a compile-time error | 
|  | /// occurs within the code of a running isolate A, A is immediately | 
|  | /// suspended." | 
|  | /// | 
|  | /// This means that the compiler can generate code that when executed | 
|  | /// terminates execution. | 
|  | error('error'), | 
|  |  | 
|  | /// A warning as identified by the "Dart Programming Language | 
|  | /// Specification" [https://dart.dev/guides/language/spec]. | 
|  | warning('warning'), | 
|  |  | 
|  | /// Any other warning that is not covered by [warning]. | 
|  | hint('hint'), | 
|  |  | 
|  | /// Informational message about the compiler. | 
|  | info('info'), | 
|  |  | 
|  | /// Informational messages that shouldn't be printed unless | 
|  | /// explicitly requested by the user of a compiler. | 
|  | verboseInfo('verbose info'), | 
|  |  | 
|  | /// An internal error in the compiler. | 
|  | crash('crash'), | 
|  |  | 
|  | /// Additional information about the preceding non-info diagnostic from the | 
|  | /// compiler. | 
|  | /// | 
|  | /// For example, consider a duplicated definition. The compiler first emits a | 
|  | /// message about the duplicated definition, then emits an info message about | 
|  | /// the location of the existing definition. | 
|  | context('context'), | 
|  | ; | 
|  |  | 
|  | /// An [int] representation of this kind. The ordinals are designed | 
|  | /// to be used as bitsets. | 
|  | int get ordinal => 2 << this.index; | 
|  |  | 
|  | /// The name of this kind. | 
|  | final String name; | 
|  |  | 
|  | const Diagnostic(this.name); | 
|  |  | 
|  | @override | 
|  | String toString() => name; | 
|  | } | 
|  |  | 
|  | // Unless explicitly allowed, passing `null` for any argument to the | 
|  | // methods of library will result in an Error being thrown. | 
|  |  | 
|  | /// Input kinds used by [CompilerInput.readFromUri]. | 
|  | enum InputKind { | 
|  | /// Data is read as UTF8 either as a [String] or a zero-terminated | 
|  | /// `List<int>`. | 
|  | UTF8, | 
|  |  | 
|  | /// Data is read as bytes in a `List<int>`. | 
|  | binary, | 
|  | } | 
|  |  | 
|  | /// Interface for data read through [CompilerInput.readFromUri]. | 
|  | abstract class Input<T> { | 
|  | /// The URI from which data was read. | 
|  | Uri get uri; | 
|  |  | 
|  | /// The format of the read [data]. | 
|  | InputKind get inputKind; | 
|  |  | 
|  | /// The raw data read from [uri]. | 
|  | T get data; | 
|  |  | 
|  | /// Release any resources held by the input. After releasing, a call to `get | 
|  | /// data` will fail, and previously returned data may be invalid. | 
|  | void release(); | 
|  | } | 
|  |  | 
|  | /// Interface for providing the compiler with input. That is, Dart source files, | 
|  | /// package config files, etc. | 
|  | abstract class CompilerInput { | 
|  | /// Returns a future that completes to the source corresponding to [uri]. | 
|  | /// If an exception occurs, the future completes with this exception. | 
|  | /// | 
|  | /// If [inputKind] is `InputKind.UTF8` the source is represented as a | 
|  | /// zero-terminated list of encoded bytes. If the input kind is | 
|  | /// `InputKind.binary` the resulting list is the raw bytes from the input | 
|  | /// source. | 
|  | Future<Input<List<int>>> readFromUri(Uri uri, | 
|  | {InputKind inputKind = InputKind.UTF8}); | 
|  |  | 
|  | /// Register that [uri] should be an `InputKind.UTF8` input with the | 
|  | /// given [source] as its zero-terminated list of contents. | 
|  | /// | 
|  | /// If [uri] was read prior to this call, this registration has no effect, | 
|  | /// otherwise it is expected that a future [readFromUri] will return the | 
|  | /// contents provided here. | 
|  | /// | 
|  | /// The main purpose of this API is to assist in error reporting when | 
|  | /// compiling from kernel binary files. Binary files embed the contents | 
|  | /// of source files that may not be available on disk. By using these | 
|  | /// registered contents, dart2js will be able to provide accurate line/column | 
|  | /// information on an error. | 
|  | void registerUtf8ContentsForDiagnostics(Uri uri, List<int> source); | 
|  | } | 
|  |  | 
|  | /// Output types used in `CompilerOutput.createOutputSink`. | 
|  | enum OutputType { | 
|  | /// The main JavaScript output. | 
|  | js, | 
|  |  | 
|  | /// A deferred JavaScript output part. | 
|  | jsPart, | 
|  |  | 
|  | /// A source map for a JavaScript output. | 
|  | sourceMap, | 
|  |  | 
|  | /// Dump info output. | 
|  | dumpInfo, | 
|  |  | 
|  | /// Deferred map output. | 
|  | deferredMap, | 
|  |  | 
|  | /// Deferred load ids map output. | 
|  | deferredLoadIds, | 
|  |  | 
|  | /// Unused libraries output. | 
|  | dumpUnusedLibraries, | 
|  |  | 
|  | /// Resource identifiers output. | 
|  | resourceIdentifiers, | 
|  |  | 
|  | /// Implementation specific output used for debugging the compiler. | 
|  | debug, | 
|  | } | 
|  |  | 
|  | /// Sink interface used for generating output from the compiler. | 
|  | abstract class OutputSink implements Sink<String> { | 
|  | /// Adds [text] to the sink. | 
|  | @override | 
|  | void add(String text); | 
|  |  | 
|  | /// Closes the sink. | 
|  | @override | 
|  | void close(); | 
|  | } | 
|  |  | 
|  | /// Sink interface used for generating binary data from the compiler. | 
|  | abstract class BinaryOutputSink implements Sink<List<int>> { | 
|  | /// Writes indices [start] to [end] of [buffer] to the sink. | 
|  | @override | 
|  | void add(List<int> buffer, [int start = 0, int? end]); | 
|  |  | 
|  | /// Closes the sink. | 
|  | @override | 
|  | void close(); | 
|  | } | 
|  |  | 
|  | /// Interface for producing output from the compiler. That is, JavaScript target | 
|  | /// files, source map files, dump info files, etc. | 
|  | abstract class CompilerOutput { | 
|  | /// Returns an [OutputSink] that will serve as compiler output for the given | 
|  | /// component. | 
|  | /// | 
|  | /// Components are identified by [name], [extension], and [type]. By | 
|  | /// convention, the empty string `""` will represent the main output of the | 
|  | /// provided [type]. [name] and [extension] are otherwise suggestive. | 
|  | // TODO(johnniwinther): Replace [name] and [extension] with something like | 
|  | // [id] and [uri]. | 
|  | OutputSink createOutputSink(String name, String extension, OutputType type); | 
|  |  | 
|  | /// Returns an [BinaryOutputSink] that will serve as compiler output for the | 
|  | /// given URI. | 
|  | BinaryOutputSink createBinarySink(Uri uri); | 
|  | } | 
|  |  | 
|  | /// Interface for receiving diagnostic message from the compiler. That is, | 
|  | /// errors, warnings, hints, etc. | 
|  | abstract class CompilerDiagnostics { | 
|  | /// Invoked by the compiler to report diagnostics. If [uri] is `null`, so are | 
|  | /// [begin] and [end]. No other arguments may be `null`. If [uri] is not | 
|  | /// `null`, neither are [begin] and [end]. [uri] indicates the compilation | 
|  | /// unit from where the diagnostic originates. [begin] and [end] are | 
|  | /// zero-based character offsets from the beginning of the compilation unit. | 
|  | /// [message] is the diagnostic message, and [kind] indicates what | 
|  | /// kind of diagnostic it is. | 
|  | /// | 
|  | /// Experimental: [code] gives access to an id for the messages. Currently it | 
|  | /// is the [Message] used to create the diagnostic, if available, from which | 
|  | /// the [MessageKind] is accessible. | 
|  | void report(Message? code, Uri? uri, int? begin, int? end, String text, | 
|  | Diagnostic kind); | 
|  | } | 
|  |  | 
|  | /// Information resulting from the compilation. | 
|  | class CompilationResult { | 
|  | /// `true` if the compilation succeeded, that is, compilation didn't fail due | 
|  | /// to compile-time errors and/or internal errors. | 
|  | final bool isSuccess; | 
|  |  | 
|  | /// The compiler object used for the compilation. | 
|  | /// | 
|  | /// Note: The type of [compiler] is implementation dependent and may vary. | 
|  | /// Use only for debugging and testing. | 
|  | final Compiler? compiler; | 
|  |  | 
|  | /// Shared state between compilations. | 
|  | /// | 
|  | /// This is used to speed up batch mode. | 
|  | final fe.InitializedCompilerState? kernelInitializedCompilerState; | 
|  |  | 
|  | CompilationResult(this.compiler, | 
|  | {this.isSuccess = true, this.kernelInitializedCompilerState}); | 
|  | } | 
|  |  | 
|  | // Unless explicitly allowed, passing [:null:] for any argument to the | 
|  | // methods of library will result in an Error being thrown. | 
|  |  | 
|  | /// Returns a future that completes to a [CompilationResult] when the Dart | 
|  | /// sources in [options] have been compiled. | 
|  | /// | 
|  | /// The generated compiler output is obtained by providing a [compilerOutput]. | 
|  | /// | 
|  | /// If the compilation fails, the future's `CompilationResult.isSuccess` is | 
|  | /// `false` and [CompilerDiagnostics.report] on [compilerDiagnostics] | 
|  | /// is invoked at least once with `kind == Diagnostic.ERROR` or | 
|  | /// `kind == Diagnostic.CRASH`. | 
|  | Future<CompilationResult> compile( | 
|  | CompilerOptions compilerOptions, | 
|  | CompilerInput compilerInput, | 
|  | CompilerDiagnostics compilerDiagnostics, | 
|  | CompilerOutput compilerOutput) { | 
|  | var compiler = Compiler( | 
|  | compilerInput, compilerOutput, compilerDiagnostics, compilerOptions); | 
|  | return compiler.run().then((bool success) { | 
|  | return CompilationResult(compiler, | 
|  | isSuccess: success, | 
|  | kernelInitializedCompilerState: compiler.initializedCompilerState); | 
|  | }); | 
|  | } |