blob: 0ee8f98aefdcc724af509d5191f04d0d7e40cfd8 [file] [log] [blame]
// Copyright (c) 2017, 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.
/// Common compiler options and helper functions used for testing.
library front_end.testing.compiler_options_common;
import 'package:kernel/ast.dart' show Library, Component;
import '../api_prototype/front_end.dart'
show
CompilerOptions,
CompilerResult,
kernelForModule,
kernelForProgramInternal,
summaryFor;
import '../api_prototype/memory_file_system.dart'
show MemoryFileSystem, MemoryFileSystemEntity;
import '../compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
import '../fasta/hybrid_file_system.dart' show HybridFileSystem;
/// Generate kernel for a script.
///
/// [scriptOrSources] can be a String, in which case it is the script to be
/// compiled, or a Map containing source files. In which case, this function
/// compiles the entry whose name is [fileName].
///
/// Wraps [kernelForProgram] with some default testing options (see [setup]).
Future<CompilerResult?> compileScript(dynamic scriptOrSources,
{String fileName: 'main.dart',
List<String> additionalDills: const [],
CompilerOptions? options,
bool retainDataForTesting: false,
bool requireMain: true}) async {
options ??= new CompilerOptions();
Map<String, dynamic> sources;
if (scriptOrSources is String) {
sources = {fileName: scriptOrSources};
} else {
assert(scriptOrSources is Map);
sources = scriptOrSources;
}
await setup(options, sources, additionalDills: additionalDills);
return await kernelForProgramInternal(toTestUri(fileName), options,
retainDataForTesting: retainDataForTesting, requireMain: requireMain);
}
/// Generate a component for a modular compilation unit.
///
/// Wraps [kernelForModule] with some default testing options (see [setup]).
Future<Component?> compileUnit(
List<String> inputs, Map<String, dynamic> sources,
{List<String> additionalDills: const [], CompilerOptions? options}) async {
options ??= new CompilerOptions();
await setup(options, sources, additionalDills: additionalDills);
return (await kernelForModule(inputs.map(toTestUri).toList(), options))
.component;
}
/// Generate a summary for a modular compilation unit.
///
/// Wraps [summaryFor] with some default testing options (see [setup]).
Future<List<int>?> summarize(List<String> inputs, Map<String, dynamic> sources,
{List<String> additionalDills: const [],
CompilerOptions? options,
bool truncate: false}) async {
options ??= new CompilerOptions();
await setup(options, sources, additionalDills: additionalDills);
return await summaryFor(inputs.map(toTestUri).toList(), options,
truncate: truncate);
}
/// Defines a default set of options for testing:
///
/// * create a hybrid file system that stores [sources] in memory but allows
/// access to the physical file system to load the SDK. [sources] can
/// contain either source files (value is [String]) or .dill files (value
/// is [List<int>]).
///
/// * define an empty .packages file (if one isn't defined in sources)
///
/// * specify the location of the sdk summaries.
Future<Null> setup(CompilerOptions options, Map<String, dynamic> sources,
{List<String> additionalDills: const []}) async {
MemoryFileSystem fs = new MemoryFileSystem(_defaultDir);
sources.forEach((name, data) {
MemoryFileSystemEntity entity = fs.entityForUri(toTestUri(name));
if (data is String) {
entity.writeAsStringSync(data);
} else {
entity.writeAsBytesSync(data);
}
});
MemoryFileSystemEntity dotPackagesFile =
fs.entityForUri(toTestUri('.packages'));
if (!await dotPackagesFile.exists()) dotPackagesFile.writeAsStringSync('');
fs
.entityForUri(invalidCoreLibsSpecUri)
.writeAsStringSync(_invalidLibrariesSpec);
options
..verify = true
..fileSystem = new HybridFileSystem(fs)
..additionalDills = additionalDills.map(toTestUri).toList();
if (options.packagesFileUri == null) {
options.packagesFileUri = toTestUri('.packages');
}
if (options.sdkSummary == null) {
options.sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
}
}
/// A fake absolute directory used as the root of a memory-file system in the
/// helpers above.
Uri _defaultDir = Uri.parse('org-dartlang-test:///a/b/c/');
/// Convert relative file paths into an absolute Uri as expected by the test
/// helpers above.
Uri toTestUri(String relativePath) => _defaultDir.resolve(relativePath);
/// Uri to a libraries specification file that purposely provides
/// invalid Uris to dart:core and dart:async. Used by tests that want to ensure
/// that the sdk libraries are not loaded from sources, but read from a .dill
/// file.
Uri invalidCoreLibsSpecUri = toTestUri('invalid_sdk_libraries.json');
String _invalidLibrariesSpec = '''
{
"vm": {
"libraries": {
"core": {"uri": "/non_existing_file/core.dart"},
"async": {"uri": "/non_existing_file/async.dart"}
}
}
}
''';
bool isDartCoreLibrary(Library lib) => isDartCore(lib.importUri);
bool isDartCore(Uri uri) => uri.scheme == 'dart' && uri.path == 'core';
/// Find a library in [component] whose Uri ends with the given [suffix]
Library findLibrary(Component component, String suffix) {
return component.libraries
.firstWhere((lib) => lib.importUri.path.endsWith(suffix));
}