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
|
// 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.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.10
|
|
||||||
|
|
||||||
library source_file_provider;
|
library source_file_provider;
|
||||||
|
|
||||||
import 'dart:async';
|
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 '../compiler_api.dart' as api;
|
||||||
import 'colors.dart' as colors;
|
import 'colors.dart' as colors;
|
||||||
import 'dart2js.dart' show AbortLeg;
|
|
||||||
import 'io/source_file.dart';
|
import 'io/source_file.dart';
|
||||||
|
|
||||||
abstract class SourceFileProvider implements api.CompilerInput {
|
abstract class SourceFileProvider implements api.CompilerInput {
|
||||||
bool isWindows = (Platform.operatingSystem == 'windows');
|
bool isWindows = (Platform.operatingSystem == 'windows');
|
||||||
Uri cwd = Uri.base;
|
Uri cwd = Uri.base;
|
||||||
Map<Uri, api.Input> utf8SourceFiles = <Uri, api.Input>{};
|
Map<Uri, SourceFile<List<int>>> utf8SourceFiles = {};
|
||||||
Map<Uri, api.Input> binarySourceFiles = <Uri, api.Input>{};
|
Map<Uri, api.Input<List<int>>> binarySourceFiles = {};
|
||||||
int dartCharactersRead = 0;
|
int dartCharactersRead = 0;
|
||||||
|
|
||||||
Future<api.Input<List<int>>> readBytesFromUri(
|
Future<api.Input<List<int>>> readBytesFromUri(
|
||||||
|
@ -29,7 +26,7 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
||||||
if (!resourceUri.isAbsolute) {
|
if (!resourceUri.isAbsolute) {
|
||||||
resourceUri = cwd.resolveUri(resourceUri);
|
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 (input != null) return Future.value(input);
|
||||||
|
|
||||||
if (resourceUri.isScheme('file')) {
|
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
|
/// 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
|
/// needs to report errors, dart2js will only find the location data if it
|
||||||
/// checks both caches.
|
/// checks both caches.
|
||||||
api.Input<List<int>> _loadInputFromCache(
|
api.Input<List<int>>? _loadInputFromCache(
|
||||||
Uri resourceUri, api.InputKind inputKind) {
|
Uri resourceUri, api.InputKind inputKind) {
|
||||||
switch (inputKind) {
|
switch (inputKind) {
|
||||||
case api.InputKind.UTF8:
|
case api.InputKind.UTF8:
|
||||||
var input = utf8SourceFiles[resourceUri];
|
api.Input<List<int>>? input = utf8SourceFiles[resourceUri];
|
||||||
if (input != null) return input;
|
if (input != null) return input;
|
||||||
input = binarySourceFiles[resourceUri];
|
input = binarySourceFiles[resourceUri];
|
||||||
if (input == null) return null;
|
if (input == null) return null;
|
||||||
|
@ -59,11 +56,10 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
||||||
case api.InputKind.binary:
|
case api.InputKind.binary:
|
||||||
return binarySourceFiles[resourceUri];
|
return binarySourceFiles[resourceUri];
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds [source] to the cache under the [resourceUri] key.
|
/// 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) {
|
Uri resourceUri, List<int> source, api.InputKind inputKind) {
|
||||||
switch (inputKind) {
|
switch (inputKind) {
|
||||||
case api.InputKind.UTF8:
|
case api.InputKind.UTF8:
|
||||||
|
@ -72,7 +68,6 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
||||||
case api.InputKind.binary:
|
case api.InputKind.binary:
|
||||||
return binarySourceFiles[resourceUri] = Binary(resourceUri, source);
|
return binarySourceFiles[resourceUri] = Binary(resourceUri, source);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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'));
|
assert(resourceUri.isScheme('file'));
|
||||||
List<int> source;
|
List<int> source;
|
||||||
try {
|
try {
|
||||||
source = readAll(resourceUri.toFilePath(),
|
source = readAll(resourceUri.toFilePath(),
|
||||||
zeroTerminated: inputKind == api.InputKind.UTF8);
|
zeroTerminated: inputKind == api.InputKind.UTF8);
|
||||||
} on FileSystemException catch (ex) {
|
} on FileSystemException catch (ex) {
|
||||||
String message = ex.osError?.message;
|
String? message = ex.osError?.message;
|
||||||
String detail = message != null ? ' ($message)' : '';
|
String detail = message != null ? ' ($message)' : '';
|
||||||
throw "Error reading '${relativizeUri(resourceUri)}' $detail";
|
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
|
/// Read [resourceUri] directly as a UTF-8 file. If reading fails, `null` is
|
||||||
/// returned.
|
/// returned.
|
||||||
api.Input readUtf8FromFileSyncForTesting(Uri resourceUri) {
|
api.Input<List<int>>? readUtf8FromFileSyncForTesting(Uri resourceUri) {
|
||||||
try {
|
try {
|
||||||
return _readFromFileSync(resourceUri, api.InputKind.UTF8);
|
return _readFromFileSync(resourceUri, api.InputKind.UTF8);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -125,18 +121,15 @@ abstract class SourceFileProvider implements api.CompilerInput {
|
||||||
|
|
||||||
relativizeUri(Uri uri) => fe.relativizeUri(cwd, uri, isWindows);
|
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);
|
return _loadInputFromCache(resourceUri, api.InputKind.UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<Uri> getSourceUris() {
|
Iterable<Uri> getSourceUris() {
|
||||||
Set<Uri> uris = Set<Uri>();
|
|
||||||
// Note: this includes also indirect sources that were used to create
|
// Note: this includes also indirect sources that were used to create
|
||||||
// `.dill` inputs to the compiler. This is OK, since this API is only
|
// `.dill` inputs to the compiler. This is OK, since this API is only
|
||||||
// used to calculate DEPS for gn build systems.
|
// used to calculate DEPS for gn build systems.
|
||||||
uris.addAll(utf8SourceFiles.keys);
|
return <Uri>{...utf8SourceFiles.keys, ...binarySourceFiles.keys};
|
||||||
uris.addAll(binarySourceFiles.keys);
|
|
||||||
return uris;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,16 +163,15 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
||||||
bool enableColors = false;
|
bool enableColors = false;
|
||||||
bool throwOnError = false;
|
bool throwOnError = false;
|
||||||
int throwOnErrorCount = 0;
|
int throwOnErrorCount = 0;
|
||||||
api.Diagnostic lastKind = null;
|
api.Diagnostic? lastKind = null;
|
||||||
int fatalCount = 0;
|
int fatalCount = 0;
|
||||||
|
|
||||||
final int FATAL = api.Diagnostic.CRASH.ordinal | api.Diagnostic.ERROR.ordinal;
|
final int FATAL = api.Diagnostic.CRASH.ordinal | api.Diagnostic.ERROR.ordinal;
|
||||||
final int INFO =
|
final int INFO =
|
||||||
api.Diagnostic.INFO.ordinal | api.Diagnostic.VERBOSE_INFO.ordinal;
|
api.Diagnostic.INFO.ordinal | api.Diagnostic.VERBOSE_INFO.ordinal;
|
||||||
|
|
||||||
FormattingDiagnosticHandler([SourceFileProvider provider])
|
FormattingDiagnosticHandler([SourceFileProvider? provider])
|
||||||
: this.provider =
|
: this.provider = provider ?? CompilerSourceFileProvider();
|
||||||
(provider == null) ? CompilerSourceFileProvider() : provider;
|
|
||||||
|
|
||||||
void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) {
|
void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) {
|
||||||
if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return;
|
if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return;
|
||||||
|
@ -209,7 +201,7 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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) {
|
api.Diagnostic kind) {
|
||||||
if (isAborting) return;
|
if (isAborting) return;
|
||||||
isAborting = (kind == api.Diagnostic.CRASH);
|
isAborting = (kind == api.Diagnostic.CRASH);
|
||||||
|
@ -253,29 +245,41 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
print('${color(message)}');
|
print('${color(message)}');
|
||||||
} else {
|
} else {
|
||||||
api.Input file = provider.getUtf8SourceFile(uri);
|
api.Input<List<int>>? file = provider.getUtf8SourceFile(uri);
|
||||||
if (file is SourceFile) {
|
if (file is SourceFile && begin != null && end != null) {
|
||||||
print(file.getLocationMessage(color(message), begin, end,
|
print((file as SourceFile)
|
||||||
colorize: color));
|
.getLocationMessage(color(message), begin, end, colorize: color));
|
||||||
} else {
|
} 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'
|
print('${provider.relativizeUri(uri)}$position:\n'
|
||||||
'${color(message)}');
|
'${color(message)}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) {
|
if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) {
|
||||||
isAborting = true;
|
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);
|
typedef MessageCallback = void Function(String message);
|
||||||
|
|
||||||
class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
||||||
final Uri out;
|
final Uri out;
|
||||||
final Uri sourceMapOut;
|
final Uri sourceMapOut;
|
||||||
final MessageCallback onInfo;
|
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;
|
final MessageCallback onFailure;
|
||||||
|
|
||||||
int totalCharactersWritten = 0;
|
int totalCharactersWritten = 0;
|
||||||
|
@ -286,7 +290,9 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
||||||
List<String> allOutputFiles = <String>[];
|
List<String> allOutputFiles = <String>[];
|
||||||
|
|
||||||
RandomAccessFileOutputProvider(this.out, this.sourceMapOut,
|
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 createUri(String name, String extension, api.OutputType type) {
|
||||||
Uri uri;
|
Uri uri;
|
||||||
|
@ -330,6 +336,7 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
onFailure('Unknown output type: $type');
|
onFailure('Unknown output type: $type');
|
||||||
|
throw StateError('unreachable');
|
||||||
}
|
}
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
@ -350,6 +357,8 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
||||||
.openSync(mode: FileMode.write);
|
.openSync(mode: FileMode.write);
|
||||||
} on FileSystemException catch (e) {
|
} on FileSystemException catch (e) {
|
||||||
onFailure('$e');
|
onFailure('$e');
|
||||||
|
// TODO(48820): Make onFailure return `Never`
|
||||||
|
throw StateError('unreachable');
|
||||||
}
|
}
|
||||||
|
|
||||||
allOutputFiles.add(fe.relativizeUri(Uri.base, uri, Platform.isWindows));
|
allOutputFiles.add(fe.relativizeUri(Uri.base, uri, Platform.isWindows));
|
||||||
|
@ -414,11 +423,13 @@ class RandomAccessFileOutputProvider implements api.CompilerOutput {
|
||||||
.openSync(mode: FileMode.write);
|
.openSync(mode: FileMode.write);
|
||||||
} on FileSystemException catch (e) {
|
} on FileSystemException catch (e) {
|
||||||
onFailure('$e');
|
onFailure('$e');
|
||||||
|
// TODO(48820): Make `onFailure` return `Never`.
|
||||||
|
throw StateError('unreachable');
|
||||||
}
|
}
|
||||||
|
|
||||||
int bytesWritten = 0;
|
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);
|
output.writeFromSync(data, start, end);
|
||||||
bytesWritten += (end ?? data.length) - start;
|
bytesWritten += (end ?? data.length) - start;
|
||||||
}
|
}
|
||||||
|
@ -439,7 +450,7 @@ class RandomAccessBinaryOutputSink implements api.BinaryOutputSink {
|
||||||
: output = File.fromUri(uri).openSync(mode: FileMode.write);
|
: output = File.fromUri(uri).openSync(mode: FileMode.write);
|
||||||
|
|
||||||
@override
|
@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);
|
output.writeFromSync(buffer, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,13 +474,13 @@ class _OutputSinkWrapper extends api.OutputSink {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BinaryOutputSinkWrapper extends api.BinaryOutputSink {
|
class _BinaryOutputSinkWrapper extends api.BinaryOutputSink {
|
||||||
void Function(List<int>, [int, int]) onWrite;
|
void Function(List<int>, [int, int?]) onWrite;
|
||||||
void Function() onClose;
|
void Function() onClose;
|
||||||
|
|
||||||
_BinaryOutputSinkWrapper(this.onWrite, this.onClose);
|
_BinaryOutputSinkWrapper(this.onWrite, this.onClose);
|
||||||
|
|
||||||
@override
|
@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);
|
onWrite(data, start, end);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -543,10 +554,10 @@ class BazelInputProvider extends SourceFileProvider {
|
||||||
}
|
}
|
||||||
switch (inputKind) {
|
switch (inputKind) {
|
||||||
case api.InputKind.UTF8:
|
case api.InputKind.UTF8:
|
||||||
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri];
|
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri]!;
|
||||||
break;
|
break;
|
||||||
case api.InputKind.binary:
|
case api.InputKind.binary:
|
||||||
binarySourceFiles[uri] = binarySourceFiles[resolvedUri];
|
binarySourceFiles[uri] = binarySourceFiles[resolvedUri]!;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,10 +601,10 @@ class MultiRootInputProvider extends SourceFileProvider {
|
||||||
await readBytesFromUri(resolvedUri, inputKind);
|
await readBytesFromUri(resolvedUri, inputKind);
|
||||||
switch (inputKind) {
|
switch (inputKind) {
|
||||||
case api.InputKind.UTF8:
|
case api.InputKind.UTF8:
|
||||||
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri];
|
utf8SourceFiles[uri] = utf8SourceFiles[resolvedUri]!;
|
||||||
break;
|
break;
|
||||||
case api.InputKind.binary:
|
case api.InputKind.binary:
|
||||||
binarySourceFiles[uri] = binarySourceFiles[resolvedUri];
|
binarySourceFiles[uri] = binarySourceFiles[resolvedUri]!;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -71,7 +71,8 @@ show<T>(ArgResults argResults, DataComputer<T> dataComputer,
|
||||||
if (show != null && !show.any((f) => '$fileUri'.endsWith(f))) {
|
if (show != null && !show.any((f) => '$fileUri'.endsWith(f))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SourceFile sourceFile = provider.readUtf8FromFileSyncForTesting(fileUri);
|
SourceFile<List<int>> sourceFile =
|
||||||
|
provider.readUtf8FromFileSyncForTesting(fileUri);
|
||||||
String sourceCode = sourceFile?.slowText();
|
String sourceCode = sourceFile?.slowText();
|
||||||
if (sourceCode == null) {
|
if (sourceCode == null) {
|
||||||
sourceCode = new File.fromUri(fileUri).readAsStringSync();
|
sourceCode = new File.fromUri(fileUri).readAsStringSync();
|
||||||
|
|
|
@ -104,7 +104,8 @@ class ProviderSourceFileManager implements SourceFileManager {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SourceFile getSourceFile(uri) {
|
SourceFile getSourceFile(uri) {
|
||||||
SourceFile sourceFile = sourceFileProvider.getUtf8SourceFile(uri);
|
SourceFile<List<int>> sourceFile =
|
||||||
|
sourceFileProvider.getUtf8SourceFile(uri);
|
||||||
sourceFile ??= sourceFileProvider.readUtf8FromFileSyncForTesting(uri);
|
sourceFile ??= sourceFileProvider.readUtf8FromFileSyncForTesting(uri);
|
||||||
if (sourceFile == null) {
|
if (sourceFile == null) {
|
||||||
sourceFile = outputProvider.getSourceFile(uri);
|
sourceFile = outputProvider.getSourceFile(uri);
|
||||||
|
|
Loading…
Reference in a new issue