blob: 04ec18ce2690029fbf62e309ad7fc3d5e46f9887 [file] [log] [blame]
// Copyright (c) 2016, 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.
// @dart = 2.7
library dart2js.test.memory_compiler;
import 'dart:async';
import 'package:compiler/compiler_api.dart' as api
show CompilationResult, CompilerDiagnostics, CompilerOutput, Diagnostic;
import 'package:compiler/src/compiler.dart' show Compiler;
import 'package:compiler/src/common.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show Message;
import 'package:compiler/src/null_compiler_output.dart' show NullCompilerOutput;
import 'package:compiler/src/options.dart' show CompilerOptions;
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
import 'memory_source_file_helper.dart';
export 'output_collector.dart';
export 'package:compiler/compiler_api.dart' show CompilationResult;
export 'diagnostic_helper.dart';
String sdkPath = 'sdk/lib';
String sdkLibrariesSpecificationPath = '$sdkPath/libraries.json';
Uri sdkLibrariesSpecificationUri =
Uri.base.resolve(sdkLibrariesSpecificationPath);
Uri sdkPlatformBinariesUri = computePlatformBinariesLocation()
.resolve("dart2js_platform.dill")
.resolve('.');
String sdkPlatformBinariesPath = sdkPlatformBinariesUri.toString();
class MultiDiagnostics implements api.CompilerDiagnostics {
final List<api.CompilerDiagnostics> diagnosticsList;
const MultiDiagnostics([this.diagnosticsList = const []]);
@override
void report(covariant Message message, Uri uri, int begin, int end,
String text, api.Diagnostic kind) {
for (api.CompilerDiagnostics diagnostics in diagnosticsList) {
diagnostics.report(message, uri, begin, end, text, kind);
}
}
}
api.CompilerDiagnostics createCompilerDiagnostics(
api.CompilerDiagnostics diagnostics, SourceFileProvider provider,
{bool showDiagnostics: true, bool verbose: false}) {
api.CompilerDiagnostics handler = diagnostics;
if (showDiagnostics) {
if (diagnostics == null) {
handler = new FormattingDiagnosticHandler(provider)
..verbose = verbose
..autoReadFileUri = true;
} else {
var formattingHandler = new FormattingDiagnosticHandler(provider)
..verbose = verbose
..autoReadFileUri = true;
handler = new MultiDiagnostics([diagnostics, formattingHandler]);
}
} else if (diagnostics == null) {
handler = new MultiDiagnostics();
}
return handler;
}
// Cached kernel state.
fe.InitializedCompilerState kernelInitializedCompilerState;
/// memorySourceFiles can contain a map of string filename to string file
/// contents or string file name to binary file contents (hence the `dynamic`
/// type for the second parameter).
Future<api.CompilationResult> runCompiler(
{Map<String, dynamic> memorySourceFiles: const <String, dynamic>{},
Uri entryPoint,
api.CompilerDiagnostics diagnosticHandler,
api.CompilerOutput outputProvider,
List<String> options: const <String>[],
bool showDiagnostics: true,
Uri librariesSpecificationUri,
Uri packageConfig,
void beforeRun(Compiler compiler),
bool unsafeToTouchSourceFiles: false}) async {
if (entryPoint == null) {
entryPoint = Uri.parse('memory:main.dart');
}
Compiler compiler = compilerFor(
entryPoint: entryPoint,
memorySourceFiles: memorySourceFiles,
diagnosticHandler: diagnosticHandler,
outputProvider: outputProvider,
options: options,
showDiagnostics: showDiagnostics,
librariesSpecificationUri: librariesSpecificationUri,
packageConfig: packageConfig,
unsafeToTouchSourceFiles: unsafeToTouchSourceFiles);
if (beforeRun != null) {
beforeRun(compiler);
}
bool isSuccess = await compiler.run();
fe.InitializedCompilerState compilerState =
kernelInitializedCompilerState = compiler.initializedCompilerState;
return api.CompilationResult(compiler,
isSuccess: isSuccess, kernelInitializedCompilerState: compilerState);
}
Compiler compilerFor(
{Uri entryPoint,
Map<String, dynamic> memorySourceFiles: const <String, dynamic>{},
api.CompilerDiagnostics diagnosticHandler,
api.CompilerOutput outputProvider,
List<String> options: const <String>[],
bool showDiagnostics: true,
Uri librariesSpecificationUri,
Uri packageConfig,
bool unsafeToTouchSourceFiles: false}) {
retainDataForTesting = true;
librariesSpecificationUri ??= sdkLibrariesSpecificationUri;
if (packageConfig == null) {
if (Platform.packageConfig != null) {
packageConfig = Uri.base.resolve(Platform.packageConfig);
} else {
// The tests are run with the base directory as the SDK root
// so just use the .packages file there.
packageConfig = Uri.base.resolve('.packages');
}
}
// Create a local in case we end up cloning memorySourceFiles.
Map<String, dynamic> sources = memorySourceFiles;
// If soundNullSafety is not requested, then we prepend the opt out string to
// the memory files.
if (!options.contains(Flags.soundNullSafety) && !unsafeToTouchSourceFiles) {
// Map may be immutable so copy.
sources = {};
memorySourceFiles.forEach((k, v) => sources[k] = v);
RegExp optOutStr = RegExp(r"\/\/\s*@dart\s*=\s*2\.\d+");
for (var key in sources.keys) {
if (sources[key] is String && key.endsWith('.dart')) {
if (!optOutStr.hasMatch(sources[key])) {
sources[key] = '// @dart=2.7\n' + sources[key];
}
}
}
}
MemorySourceFileProvider provider;
provider = new MemorySourceFileProvider(sources);
diagnosticHandler = createCompilerDiagnostics(diagnosticHandler, provider,
showDiagnostics: showDiagnostics,
verbose: options.contains('-v') || options.contains('--verbose'));
if (outputProvider == null) {
outputProvider = const NullCompilerOutput();
}
CompilerOptions compilerOptions = CompilerOptions.parse(options,
librariesSpecificationUri: librariesSpecificationUri)
..entryUri = entryPoint
..environment = {}
..packageConfig = packageConfig;
compilerOptions.kernelInitializedCompilerState =
kernelInitializedCompilerState;
var compiler = new Compiler(
provider, outputProvider, diagnosticHandler, compilerOptions);
return compiler;
}
main() {
runCompiler(memorySourceFiles: {'main.dart': 'main() {}'});
}