diff --git a/pkg/vm/bin/gen_kernel.dart b/pkg/vm/bin/gen_kernel.dart index 6f1ff409189..2fc8bf6faa8 100644 --- a/pkg/vm/bin/gen_kernel.dart +++ b/pkg/vm/bin/gen_kernel.dart @@ -12,7 +12,7 @@ import 'package:kernel/kernel.dart' show Program; import 'package:kernel/src/tool/batch_util.dart' as batch_util; import 'package:kernel/target/targets.dart' show TargetFlags; import 'package:kernel/target/vm.dart' show VmTarget; -import 'package:vm/kernel_front_end.dart' show compileToKernel; +import 'package:vm/kernel_front_end.dart' show compileToKernel, ErrorDetector; final ArgParser _argParser = new ArgParser(allowTrailingOptions: true) ..addOption('platform', @@ -60,7 +60,7 @@ Future compile(List arguments) async { final bool strongMode = options['strong-mode']; final bool aot = options['aot']; - int errors = 0; + ErrorDetector errorDetector = new ErrorDetector(); final CompilerOptions compilerOptions = new CompilerOptions() ..strongMode = strongMode @@ -68,18 +68,13 @@ Future compile(List arguments) async { ..linkedDependencies = [Uri.base.resolve(platformKernel)] ..packagesFileUri = packages != null ? Uri.base.resolve(packages) : null ..reportMessages = true - ..onError = (CompilationMessage message) { - if ((message.severity != Severity.nit) && - (message.severity != Severity.warning)) { - ++errors; - } - }; + ..onError = errorDetector; Program program = await compileToKernel( Uri.base.resolve(filename), compilerOptions, aot: aot); - if ((errors > 0) || (program == null)) { + if (errorDetector.hasCompilationErrors || (program == null)) { return _compileTimeErrorExitCode; } diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart index 11506fcfe7e..d8b35ed9fd2 100644 --- a/pkg/vm/lib/kernel_front_end.dart +++ b/pkg/vm/lib/kernel_front_end.dart @@ -7,9 +7,13 @@ library vm.kernel_front_end; import 'dart:async'; -import 'package:front_end/src/api_prototype/compiler_options.dart'; +import 'package:front_end/src/api_prototype/compiler_options.dart' + show CompilerOptions, ErrorHandler; import 'package:front_end/src/api_prototype/kernel_generator.dart' show kernelForProgram; +import 'package:front_end/src/api_prototype/compilation_message.dart' + show CompilationMessage, Severity; +import 'package:front_end/src/fasta/severity.dart' show Severity; import 'package:kernel/ast.dart' show Program; import 'package:kernel/core_types.dart' show CoreTypes; @@ -23,9 +27,18 @@ import 'transformations/cha_devirtualization.dart' as chaDevirtualization /// Future compileToKernel(Uri source, CompilerOptions options, {bool aot: false}) async { + // Replace error handler to detect if there are compilation errors. + final errorDetector = + new ErrorDetector(previousErrorHandler: options.onError); + options.onError = errorDetector; + final program = await kernelForProgram(source, options); - if (aot && (program != null)) { + // Restore error handler (in case 'options' are reused). + options.onError = errorDetector.previousErrorHandler; + + // Run global transformations only if program is correct. + if (aot && (program != null) && !errorDetector.hasCompilationErrors) { _runGlobalTransformations(program, options.strongMode); } @@ -41,3 +54,19 @@ _runGlobalTransformations(Program program, bool strongMode) { chaDevirtualization.transformProgram(coreTypes, program); } } + +class ErrorDetector { + final ErrorHandler previousErrorHandler; + bool hasCompilationErrors = false; + + ErrorDetector({this.previousErrorHandler}); + + void call(CompilationMessage message) { + if ((message.severity != Severity.nit) && + (message.severity != Severity.warning)) { + hasCompilationErrors = true; + } + + previousErrorHandler?.call(message); + } +}