mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[dart2js] migrate source_file_provider
This reapplies f740b500e2
The change is not that different from the original, except that a
few changes have landed in between to address the failure
encountered by the SDK roll last time. Namely, the map lookup on
`resolvedUri` is normalized, so that the lookup will always match
how the store operation is done, and hence will succeed when copying
cache entries between resolvedUri and uri (see also
https://dart-review.googlesource.com/c/sdk/+/250440).
Change-Id: Ic3ad778a3e9ea465b515de9800f296c71683970c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260081
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
76a4d351b8
commit
8bff8336a4
|
@ -2,8 +2,6 @@
|
|||
// 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.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
library source_file_provider;
|
||||
|
||||
import 'dart:async';
|
||||
|
@ -14,14 +12,13 @@ import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
|
|||
|
||||
import '../compiler_api.dart' as api;
|
||||
import 'colors.dart' as colors;
|
||||
import 'dart2js.dart' show AbortLeg;
|
||||
import 'io/source_file.dart';
|
||||
|
||||
abstract class SourceFileProvider implements api.CompilerInput {
|
||||
bool isWindows = (Platform.operatingSystem == 'windows');
|
||||
Uri cwd = Uri.base;
|
||||
Map<Uri, api.Input> utf8SourceFiles = <Uri, api.Input>{};
|
||||
Map<Uri, api.Input> binarySourceFiles = <Uri, api.Input>{};
|
||||
Map<Uri, SourceFile<List<int>>> utf8SourceFiles = {};
|
||||
Map<Uri, api.Input<List<int>>> binarySourceFiles = {};
|
||||
int dartCharactersRead = 0;
|
||||
|
||||
Future<api.Input<List<int>>> readBytesFromUri(
|
||||
|
@ -29,7 +26,7 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
|||
if (!resourceUri.isAbsolute) {
|
||||
resourceUri = cwd.resolveUri(resourceUri);
|
||||
}
|
||||
api.Input<List<int>> input = _loadInputFromCache(resourceUri, inputKind);
|
||||
api.Input<List<int>>? input = _loadInputFromCache(resourceUri, inputKind);
|
||||
if (input != null) return Future.value(input);
|
||||
|
||||
if (resourceUri.isScheme('file')) {
|
||||
|
@ -47,11 +44,11 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
|||
/// utf8, the CFE file system may read them as binary inputs. In case the CFE
|
||||
/// needs to report errors, dart2js will only find the location data if it
|
||||
/// checks both caches.
|
||||
api.Input<List<int>> _loadInputFromCache(
|
||||
api.Input<List<int>>? _loadInputFromCache(
|
||||
Uri resourceUri, api.InputKind inputKind) {
|
||||
switch (inputKind) {
|
||||
case api.InputKind.UTF8:
|
||||
var input = utf8SourceFiles[resourceUri];
|
||||
api.Input<List<int>>? input = utf8SourceFiles[resourceUri];
|
||||
if (input != null) return input;
|
||||
input = binarySourceFiles[resourceUri];
|
||||
if (input == null) return null;
|
||||
|
@ -59,11 +56,10 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
|||
case api.InputKind.binary:
|
||||
return binarySourceFiles[resourceUri];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Adds [source] to the cache under the [resourceUri] key.
|
||||
api.Input _storeSourceInCache(
|
||||
api.Input<List<int>> _storeSourceInCache(
|
||||
Uri resourceUri, List<int> source, api.InputKind inputKind) {
|
||||
switch (inputKind) {
|
||||
case api.InputKind.UTF8:
|
||||
|
@ -72,7 +68,6 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
|||
case api.InputKind.binary:
|
||||
return binarySourceFiles[resourceUri] = Binary(resourceUri, source);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -85,14 +80,15 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
|||
}
|
||||
}
|
||||
|
||||
api.Input _readFromFileSync(Uri resourceUri, api.InputKind inputKind) {
|
||||
api.Input<List<int>> _readFromFileSync(
|
||||
Uri resourceUri, api.InputKind inputKind) {
|
||||
assert(resourceUri.isScheme('file'));
|
||||
List<int> source;
|
||||
try {
|
||||
source = readAll(resourceUri.toFilePath(),
|
||||
zeroTerminated: inputKind == api.InputKind.UTF8);
|
||||
} on FileSystemException catch (ex) {
|
||||
String message = ex.osError?.message;
|
||||
String? message = ex.osError?.message;
|
||||
String detail = message != null ? ' ($message)' : '';
|
||||
throw "Error reading '${relativizeUri(resourceUri)}' $detail";
|
||||
}
|
||||
|
@ -102,7 +98,7 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
|||
|
||||
/// Read [resourceUri] directly as a UTF-8 file. If reading fails, `null` is
|
||||
/// returned.
|
||||
api.Input readUtf8FromFileSyncForTesting(Uri resourceUri) {
|
||||
api.Input<List<int>>? readUtf8FromFileSyncForTesting(Uri resourceUri) {
|
||||
try {
|
||||
return _readFromFileSync(resourceUri, api.InputKind.UTF8);
|
||||
} catch (e) {
|
||||
|
@ -125,18 +121,15 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
|||
|
||||
relativizeUri(Uri uri) => fe.relativizeUri(cwd, uri, isWindows);
|
||||
|
||||
SourceFile<List<int>> getUtf8SourceFile(Uri resourceUri) {
|
||||
api.Input<List<int>>? getUtf8SourceFile(Uri resourceUri) {
|
||||
return _loadInputFromCache(resourceUri, api.InputKind.UTF8);
|
||||
}
|
||||
|
||||
Iterable<Uri> getSourceUris() {
|
||||
Set<Uri> uris = Set<Uri>();
|
||||
// Note: this includes also indirect sources that were used to create
|
||||
// `.dill` inputs to the compiler. This is OK, since this API is only
|
||||
// used to calculate DEPS for gn build systems.
|
||||
uris.addAll(utf8SourceFiles.keys);
|
||||
uris.addAll(binarySourceFiles.keys);
|
||||
return uris;
|
||||
return <Uri>{...utf8SourceFiles.keys, ...binarySourceFiles.keys};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,16 +163,15 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
|||
bool enableColors = false;
|
||||
bool throwOnError = false;
|
||||
int throwOnErrorCount = 0;
|
||||
api.Diagnostic lastKind = null;
|
||||
api.Diagnostic? lastKind = null;
|
||||
int fatalCount = 0;
|
||||
|
||||
final int FATAL = api.Diagnostic.CRASH.ordinal | api.Diagnostic.ERROR.ordinal;
|
||||
final int INFO =
|
||||
api.Diagnostic.INFO.ordinal | api.Diagnostic.VERBOSE_INFO.ordinal;
|
||||
|
||||
FormattingDiagnosticHandler([SourceFileProvider provider])
|
||||
: this.provider =
|
||||
(provider == null) ? CompilerSourceFileProvider() : provider;
|
||||
FormattingDiagnosticHandler([SourceFileProvider? provider])
|
||||
: this.provider = provider ?? CompilerSourceFileProvider();
|
||||
|
||||
void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) {
|
||||
if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return;
|
||||
|
@ -209,7 +201,7 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
|||
}
|
||||
|
||||
@override
|
||||
void report(var code, Uri uri, int begin, int end, String message,
|
||||
void report(var code, Uri? uri, int? begin, int? end, String message,
|
||||
api.Diagnostic kind) {
|
||||
if (isAborting) return;
|
||||
isAborting = (kind == api.Diagnostic.CRASH);
|
||||
|
@ -253,29 +245,41 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
|||
if (uri == null) {
|
||||
print('${color(message)}');
|
||||
} else {
|
||||
api.Input file = provider.getUtf8SourceFile(uri);
|
||||
if (file is SourceFile) {
|
||||
print(file.getLocationMessage(color(message), begin, end,
|
||||
colorize: color));
|
||||
api.Input<List<int>>? file = provider.getUtf8SourceFile(uri);
|
||||
if (file is SourceFile && begin != null && end != null) {
|
||||
print((file as SourceFile)
|
||||
.getLocationMessage(color(message), begin, end, colorize: color));
|
||||
} else {
|
||||
String position = end - begin > 0 ? '@$begin+${end - begin}' : '';
|
||||
String position = begin != null && end != null && end - begin > 0
|
||||
? '@$begin+${end - begin}'
|
||||
: '';
|
||||
print('${provider.relativizeUri(uri)}$position:\n'
|
||||
'${color(message)}');
|
||||
}
|
||||
}
|
||||
if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) {
|
||||
isAborting = true;
|
||||
throw AbortLeg(message);
|
||||
throw _CompilationErrorError(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _CompilationErrorError {
|
||||
final message;
|
||||
_CompilationErrorError(this.message);
|
||||
@override
|
||||
toString() => 'Aborted due to --throw-on-error: $message';
|
||||
}
|
||||
|
||||
typedef MessageCallback = void Function(String message);
|
||||
|
||||
class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
||||
final Uri out;
|
||||
final Uri sourceMapOut;
|
||||
final MessageCallback onInfo;
|
||||
|
||||
// TODO(48820): Make [onFailure] return `Never`. The value passed in for the
|
||||
// real compiler exits. [onFailure] is not specified or faked in some tests.
|
||||
final MessageCallback onFailure;
|
||||
|
||||
int totalCharactersWritten = 0;
|
||||
|
@ -286,7 +290,9 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
|||
List<String> allOutputFiles = <String>[];
|
||||
|
||||
RandomAccessFileOutputProvider(this.out, this.sourceMapOut,
|
||||
{this.onInfo, this.onFailure});
|
||||
{this.onInfo = _ignore, this.onFailure = _ignore});
|
||||
|
||||
static void _ignore(String message) {}
|
||||
|
||||
Uri createUri(String name, String extension, api.OutputType type) {
|
||||
Uri uri;
|
||||
|
@ -330,6 +336,7 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
|||
break;
|
||||
default:
|
||||
onFailure('Unknown output type: $type');
|
||||
throw StateError('unreachable');
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
@ -350,6 +357,8 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
|||
.openSync(mode: FileMode.write);
|
||||
} on FileSystemException catch (e) {
|
||||
onFailure('$e');
|
||||
// TODO(48820): Make onFailure return `Never`
|
||||
throw StateError('unreachable');
|
||||
}
|
||||
|
||||
allOutputFiles.add(fe.relativizeUri(Uri.base, uri, Platform.isWindows));
|
||||
|
@ -414,11 +423,13 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
|||
.openSync(mode: FileMode.write);
|
||||
} on FileSystemException catch (e) {
|
||||
onFailure('$e');
|
||||
// TODO(48820): Make `onFailure` return `Never`.
|
||||
throw StateError('unreachable');
|
||||
}
|
||||
|
||||
int bytesWritten = 0;
|
||||
|
||||
void writeBytesSync(List<int> data, [int start = 0, int end]) {
|
||||
void writeBytesSync(List<int> data, [int start = 0, int? end]) {
|
||||
output.writeFromSync(data, start, end);
|
||||
bytesWritten += (end ?? data.length) - start;
|
||||
}
|
||||
|
@ -439,7 +450,7 @@ class RandomAccessBinaryOutputSink implements api.BinaryOutputSink {
|
|||
: output = File.fromUri(uri).openSync(mode: FileMode.write);
|
||||
|
||||
@override
|
||||
void write(List<int> buffer, [int start = 0, int end]) {
|
||||
void write(List<int> buffer, [int start = 0, int? end]) {
|
||||
output.writeFromSync(buffer, start, end);
|
||||
}
|
||||
|
||||
|
@ -463,13 +474,13 @@ class _OutputSinkWrapper extends api.OutputSink {
|
|||
}
|
||||
|
||||
class _BinaryOutputSinkWrapper extends api.BinaryOutputSink {
|
||||
void Function(List<int>, [int, int]) onWrite;
|
||||
void Function(List<int>, [int, int?]) onWrite;
|
||||
void Function() onClose;
|
||||
|
||||
_BinaryOutputSinkWrapper(this.onWrite, this.onClose);
|
||||
|
||||
@override
|
||||
void write(List<int> data, [int start = 0, int end]) =>
|
||||
void write(List<int> data, [int start = 0, int? end]) =>
|
||||
onWrite(data, start, end);
|
||||
|
||||
@override
|
||||
|
@ -543,10 +554,10 @@ class BazelInputProvider extends SourceFileProvider {
|
|||
}
|
||||
switch (inputKind) {
|
||||
case api.InputKind.UTF8:
|
||||
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri];
|
||||
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri]!;
|
||||
break;
|
||||
case api.InputKind.binary:
|
||||
binarySourceFiles[uri] = binarySourceFiles[resolvedUri];
|
||||
binarySourceFiles[uri] = binarySourceFiles[resolvedUri]!;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -590,10 +601,10 @@ class MultiRootInputProvider extends SourceFileProvider {
|
|||
await readBytesFromUri(resolvedUri, inputKind);
|
||||
switch (inputKind) {
|
||||
case api.InputKind.UTF8:
|
||||
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri];
|
||||
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri]!;
|
||||
break;
|
||||
case api.InputKind.binary:
|
||||
binarySourceFiles[uri] = binarySourceFiles[resolvedUri];
|
||||
binarySourceFiles[uri] = binarySourceFiles[resolvedUri]!;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -71,7 +71,8 @@ show<T>(ArgResults argResults, DataComputer<T> dataComputer,
|
|||
if (show != null && !show.any((f) => '$fileUri'.endsWith(f))) {
|
||||
continue;
|
||||
}
|
||||
SourceFile sourceFile = provider.readUtf8FromFileSyncForTesting(fileUri);
|
||||
SourceFile<List<int>> sourceFile =
|
||||
provider.readUtf8FromFileSyncForTesting(fileUri);
|
||||
String sourceCode = sourceFile?.slowText();
|
||||
if (sourceCode == null) {
|
||||
sourceCode = new File.fromUri(fileUri).readAsStringSync();
|
||||
|
|
|
@ -104,7 +104,8 @@ class ProviderSourceFileManager implements SourceFileManager {
|
|||
|
||||
@override
|
||||
SourceFile getSourceFile(uri) {
|
||||
SourceFile sourceFile = sourceFileProvider.getUtf8SourceFile(uri);
|
||||
SourceFile<List<int>> sourceFile =
|
||||
sourceFileProvider.getUtf8SourceFile(uri);
|
||||
sourceFile ??= sourceFileProvider.readUtf8FromFileSyncForTesting(uri);
|
||||
if (sourceFile == null) {
|
||||
sourceFile = outputProvider.getSourceFile(uri);
|
||||
|
|
Loading…
Reference in a new issue