| // 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:compiler/src/filenames.dart'; |
| import 'package:compiler/src/util/util.dart'; |
| import 'source_mapping_tester.dart'; |
| import 'sourcemap_helper.dart'; |
| import 'sourcemap_html_helper.dart'; |
| import 'sourcemap_html_templates.dart'; |
| |
| const String DEFAULT_OUTPUT_PATH = 'out.js.map.html'; |
| |
| main(List<String> arguments) async { |
| bool measure = false; |
| String outputPath = DEFAULT_OUTPUT_PATH; |
| Set<String> configurations = new Set<String>(); |
| Set<String> files = new Set<String>(); |
| 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 { |
| print("Unknown option '$argument'."); |
| return; |
| } |
| } else { |
| if (!parseArgument(argument, configurations, files)) { |
| return; |
| } |
| } |
| } |
| |
| if (configurations.isEmpty) { |
| configurations.addAll(TEST_CONFIGURATIONS.keys); |
| if (!measure) { |
| configurations.remove('old'); |
| } |
| } |
| if (files.isEmpty) { |
| files.addAll(TEST_FILES.keys); |
| } |
| |
| OutputConfigurations outputConfigurations = |
| new OutputConfigurations(configurations, files); |
| bool generateMultiConfigs = false; |
| if (outputPath != null) { |
| if (configurations.length > 1 || files.length > 1) { |
| for (String config in configurations) { |
| for (String file in files) { |
| 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, |
| files.first, |
| outputPath, |
| Uri.base.resolve(nativeToUriPath(outputPath))); |
| } |
| } |
| |
| List<Measurement> measurements = <Measurement>[]; |
| for (String config in configurations) { |
| List<String> options = TEST_CONFIGURATIONS[config]; |
| for (String file in files) { |
| Measurement measurement = await runTest( |
| config, TEST_FILES[file], options, |
| outputUri: outputConfigurations.getUri(config, file), |
| verbose: !measure); |
| measurements.add(measurement); |
| } |
| } |
| for (Measurement measurement in measurements) { |
| print(measurement); |
| } |
| if (generateMultiConfigs) { |
| outputMultiConfigs( |
| Uri.base.resolve(outputPath), |
| outputConfigurations); |
| } |
| } |
| |
| class OutputConfigurations implements Configurations { |
| final Iterable<String> configs; |
| final Iterable<String> files; |
| final Map<Pair, String> pathMap = {}; |
| final Map<Pair, Uri> uriMap = {}; |
| |
| OutputConfigurations(this.configs, this.files); |
| |
| void registerPathUri(String config, String file, String path, Uri uri) { |
| Pair key = new Pair(config, file); |
| pathMap[key] = path; |
| uriMap[key] = uri; |
| } |
| |
| Uri getUri(String config, String file) { |
| Pair key = new Pair(config, file); |
| return uriMap[key]; |
| } |
| |
| @override |
| String getPath(String config, String file) { |
| Pair key = new Pair(config, file); |
| return pathMap[key]; |
| } |
| } |
| |
| Future<Measurement> runTest( |
| String config, |
| String filename, |
| List<String> options, |
| {Uri outputUri, |
| bool verbose}) async { |
| TestResult result = |
| await runTests(config, filename, options, verbose: verbose); |
| if (outputUri != null) { |
| if (result.missingCodePointsMap.isNotEmpty) { |
| result.printMissingCodePoints(); |
| } |
| if (result.multipleNodesMap.isNotEmpty) { |
| result.printMultipleNodes(); |
| } |
| if (result.multipleOffsetsMap.isNotEmpty) { |
| result.printMultipleOffsets(); |
| } |
| createTraceSourceMapHtml(outputUri, result.processor, result.userInfoList); |
| } |
| return new 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); |
| |
| String toString() { |
| double percentage = 100 * missing / count; |
| return "Config '${config}', file: '${filename}': " |
| "$missing of $count ($percentage%) missing"; |
| } |
| } |