d192492b09
The same functionality is available with `@RecordUse()` now. This CL renames all the implementation to refer to recorded uses instead of resource identifiers. These are only renames, there is no logical change. This CL keeps the implementation to be the pragma machinery. The pragmas.md has been updated to reflect that the pragma should not be used but that `RecordUse()` should be used instead. This CL does _not_ change the `--write-resources` command-line flag. We'll decide on some flag that works across all compiler backends in the future: https://github.com/dart-lang/native/issues/2939. This CL updates the documentation to talk about `@RecordUse()`. Change-Id: I7e80a54e627b77af16e27464320cf4a9703c05e6 Cq-Include-Trybots: luci.dart.try:pkg-linux-debug-try,pkg-linux-release-arm64-try,pkg-linux-release-try,pkg-mac-release-arm64-try,pkg-mac-release-try,pkg-win-release-arm64-try,pkg-win-release-try,dart2js-linux-chrome-try,dart2js-unit-linux-x64-release-try,dart2wasm-linux-jscm-chrome-try,dart2wasm-linux-optimized-jsc-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/471720 Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
281 lines
8.9 KiB
Dart
281 lines
8.9 KiB
Dart
// 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;
|
|
|
|
import 'dart:async';
|
|
import 'dart:typed_data';
|
|
|
|
// ignore: implementation_imports
|
|
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 << 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<Uint8List>> readFromUri(
|
|
Uri uri, {
|
|
InputKind inputKind = InputKind.utf8,
|
|
});
|
|
|
|
/// Register that [uri] should be an `InputKind.UTF8` input with the
|
|
/// given [source] 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, Uint8List 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,
|
|
|
|
/// Recorded usages of definitions (after tree-shaking).
|
|
recordedUses,
|
|
|
|
/// 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,
|
|
);
|
|
});
|
|
}
|