2bb32ec55a
Change-Id: Ib1afd38a7d3694c2e5ed591132f41b147f76d75a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/427560 Reviewed-by: Stephen Adams <sra@google.com> Commit-Queue: Mayank Patke <fishythefish@google.com>
180 lines
5.1 KiB
Dart
180 lines
5.1 KiB
Dart
// Copyright (c) 2015, 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.
|
|
|
|
/// Visualization of source mappings generated and tested in
|
|
/// 'source_mapping_test.dart'.
|
|
|
|
library source_mapping.test.viewer;
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:_fe_analyzer_shared/src/util/filenames.dart';
|
|
|
|
import '../helpers/sourcemap_helper.dart';
|
|
import '../helpers/sourcemap_html_helper.dart';
|
|
import '../helpers/sourcemap_html_templates.dart';
|
|
import 'source_mapping_tester.dart';
|
|
|
|
const String DEFAULT_OUTPUT_PATH = 'out.js.map.html';
|
|
|
|
main(List<String> arguments) async {
|
|
bool measure = false;
|
|
bool missingOnly = false;
|
|
String outputPath = DEFAULT_OUTPUT_PATH;
|
|
Set<String> configurations = Set<String>();
|
|
Map<String, Uri> tests = <String, Uri>{};
|
|
for (String argument in arguments) {
|
|
if (argument.startsWith('-')) {
|
|
if (argument == '-m') {
|
|
// Measure instead of reporting the number of missing code points.
|
|
measure = true;
|
|
} else if (argument.startsWith('--out=')) {
|
|
// Generate visualization for the first configuration.
|
|
outputPath = argument.substring('--out='.length);
|
|
} else if (argument.startsWith('-o')) {
|
|
// Generate visualization for the first configuration.
|
|
outputPath = argument.substring('-o'.length);
|
|
} else if (argument == '--missing') {
|
|
missingOnly = true;
|
|
} else if (argument == '--file' || argument == '--exclude') {
|
|
// Handled by [parseArguments].
|
|
} else {
|
|
print("Unknown option '$argument'.");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!parseArguments(arguments, configurations, tests, measure: measure)) {
|
|
return;
|
|
}
|
|
|
|
OutputConfigurations outputConfigurations = OutputConfigurations(
|
|
configurations,
|
|
tests.keys,
|
|
);
|
|
bool generateMultiConfigs = false;
|
|
if (configurations.length > 1 || tests.length > 1) {
|
|
for (String config in configurations) {
|
|
for (String file in tests.keys) {
|
|
String path = '$outputPath.$config.$file';
|
|
Uri uri = Uri.base.resolve(nativeToUriPath(path));
|
|
outputConfigurations.registerPathUri(config, file, path, uri);
|
|
}
|
|
}
|
|
generateMultiConfigs = true;
|
|
} else {
|
|
outputConfigurations.registerPathUri(
|
|
configurations.first,
|
|
tests.keys.first,
|
|
outputPath,
|
|
Uri.base.resolve(nativeToUriPath(outputPath)),
|
|
);
|
|
}
|
|
|
|
List<Measurement> measurements = <Measurement>[];
|
|
for (String config in configurations) {
|
|
for (String file in tests.keys) {
|
|
List<String> options = TEST_CONFIGURATIONS[config]!;
|
|
Measurement measurement = await runTest(
|
|
config,
|
|
file,
|
|
tests[file]!,
|
|
options,
|
|
outputUri: outputConfigurations.getUri(config, file),
|
|
verbose: !measure,
|
|
missingOnly: missingOnly,
|
|
);
|
|
measurements.add(measurement);
|
|
}
|
|
}
|
|
for (Measurement measurement in measurements) {
|
|
print(measurement);
|
|
}
|
|
if (generateMultiConfigs) {
|
|
outputMultiConfigs(Uri.base.resolve(outputPath), outputConfigurations);
|
|
}
|
|
}
|
|
|
|
class OutputConfigurations implements Configurations {
|
|
@override
|
|
final Iterable<String> configs;
|
|
@override
|
|
final Iterable<String> files;
|
|
final Map<(String, String), String> pathMap = {};
|
|
final Map<(String, String), Uri> uriMap = {};
|
|
|
|
OutputConfigurations(this.configs, this.files);
|
|
|
|
void registerPathUri(String config, String file, String path, Uri uri) {
|
|
var key = (config, file);
|
|
pathMap[key] = path;
|
|
uriMap[key] = uri;
|
|
}
|
|
|
|
Uri? getUri(String config, String file) => uriMap[(config, file)];
|
|
|
|
@override
|
|
String getPath(String config, String file) => pathMap[(config, file)]!;
|
|
}
|
|
|
|
Future<Measurement> runTest(
|
|
String config,
|
|
String filename,
|
|
Uri uri,
|
|
List<String> options, {
|
|
Uri? outputUri,
|
|
required bool verbose,
|
|
bool missingOnly = false,
|
|
}) async {
|
|
TestResult result = await runTests(
|
|
config,
|
|
filename,
|
|
uri,
|
|
options,
|
|
verbose: verbose,
|
|
);
|
|
if (outputUri != null) {
|
|
if (result.missingCodePointsMap.isNotEmpty) {
|
|
result.printMissingCodePoints();
|
|
}
|
|
if (result.multipleNodesMap.isNotEmpty) {
|
|
result.printMultipleNodes();
|
|
}
|
|
if (result.multipleOffsetsMap.isNotEmpty) {
|
|
result.printMultipleOffsets();
|
|
}
|
|
List<SourceMapInfo> infoList = result.userInfoList;
|
|
if (missingOnly) {
|
|
infoList = infoList
|
|
.where((info) => result.missingCodePointsMap.containsKey(info))
|
|
.toList();
|
|
}
|
|
createTraceSourceMapHtml(outputUri, result.processor, infoList);
|
|
}
|
|
return Measurement(
|
|
config,
|
|
filename,
|
|
result.missingCodePointsMap.values.fold(0, (s, i) => s + i.length),
|
|
result.userInfoList.fold(0, (s, i) => s + i.codePoints.length),
|
|
);
|
|
}
|
|
|
|
class Measurement {
|
|
final String config;
|
|
final String filename;
|
|
|
|
final int missing;
|
|
final int count;
|
|
|
|
Measurement(this.config, this.filename, this.missing, this.count);
|
|
|
|
@override
|
|
String toString() {
|
|
double percentage = 100 * missing / count;
|
|
return "Config '${config}', file: '${filename}': "
|
|
"$missing of $count ($percentage%) missing";
|
|
}
|
|
}
|