mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 15:29:45 +00:00
Opt-in to generate code for compile-time error. Only supported for SSA.
BUG= R=karlklose@google.com Review URL: https://codereview.chromium.org//1167353003
This commit is contained in:
parent
dae0c0d6f0
commit
bac7481d3d
|
@ -88,6 +88,7 @@ class Compiler extends leg.Compiler {
|
|||
hasOption(options, '--enable-experimental-mirrors'),
|
||||
generateCodeWithCompileTimeErrors:
|
||||
hasOption(options, '--generate-code-with-compile-time-errors'),
|
||||
testMode: hasOption(options, '--test-mode'),
|
||||
allowNativeExtensions:
|
||||
hasOption(options, '--allow-native-extensions'),
|
||||
enableNullAwareOperators:
|
||||
|
|
|
@ -302,8 +302,6 @@ abstract class Backend {
|
|||
|
||||
List<CompilerTask> get tasks;
|
||||
|
||||
bool get canHandleCompilationFailed;
|
||||
|
||||
void onResolutionComplete() {}
|
||||
void onTypeInferenceComplete() {}
|
||||
|
||||
|
@ -314,9 +312,13 @@ abstract class Backend {
|
|||
bool classNeedsRti(ClassElement cls);
|
||||
bool methodNeedsRti(FunctionElement function);
|
||||
|
||||
/// Register deferred loading. Returns `true` if the backend supports deferred
|
||||
/// Enable compilation of code with compile time errors. Returns `true` if
|
||||
/// supported by the backend.
|
||||
bool enableCodegenWithErrorsIfSupported(Spannable node);
|
||||
|
||||
/// Enable deferred loading. Returns `true` if the backend supports deferred
|
||||
/// loading.
|
||||
bool registerDeferredLoading(Spannable node, Registry registry);
|
||||
bool enableDeferredLoadingIfSupported(Spannable node, Registry registry);
|
||||
|
||||
/// Called during codegen when [constant] has been used.
|
||||
void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
|
||||
|
@ -794,6 +796,9 @@ abstract class Compiler implements DiagnosticListener {
|
|||
/// Generate output even when there are compile-time errors.
|
||||
final bool generateCodeWithCompileTimeErrors;
|
||||
|
||||
/// The compiler is run from the build bot.
|
||||
final bool testMode;
|
||||
|
||||
bool disableInlining = false;
|
||||
|
||||
List<Uri> librariesToAnalyzeWhenRun;
|
||||
|
@ -1053,6 +1058,7 @@ abstract class Compiler implements DiagnosticListener {
|
|||
this.allowNativeExtensions: false,
|
||||
this.enableNullAwareOperators: false,
|
||||
this.generateCodeWithCompileTimeErrors: false,
|
||||
this.testMode: false,
|
||||
api.CompilerOutputProvider outputProvider,
|
||||
List<String> strips: const []})
|
||||
: this.disableTypeInferenceFlag =
|
||||
|
@ -1621,9 +1627,11 @@ abstract class Compiler implements DiagnosticListener {
|
|||
});
|
||||
}
|
||||
|
||||
// TODO(sigurdm): The dart backend should handle failed compilations.
|
||||
if (compilationFailed && !backend.canHandleCompilationFailed) {
|
||||
return;
|
||||
if (compilationFailed){
|
||||
if (!generateCodeWithCompileTimeErrors) return;
|
||||
if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (analyzeOnly) {
|
||||
|
@ -2159,7 +2167,14 @@ abstract class Compiler implements DiagnosticListener {
|
|||
}
|
||||
|
||||
EventSink<String> outputProvider(String name, String extension) {
|
||||
if (compilationFailed) return new NullSink('$name.$extension');
|
||||
if (compilationFailed) {
|
||||
if (!generateCodeWithCompileTimeErrors || testMode) {
|
||||
// Disable output in test mode: The build bot currently uses the time
|
||||
// stamp of the generated file to determine whether the output is
|
||||
// up-to-date.
|
||||
return new NullSink('$name.$extension');
|
||||
}
|
||||
}
|
||||
return userOutputProvider(name, extension);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -360,6 +360,7 @@ Future<api.CompilationResult> compile(List<String> argv) {
|
|||
}),
|
||||
new OptionHandler('--allow-native-extensions', setAllowNativeExtensions),
|
||||
new OptionHandler('--generate-code-with-compile-time-errors', passThrough),
|
||||
new OptionHandler('--test-mode', passThrough),
|
||||
|
||||
// The following three options must come last.
|
||||
new OptionHandler('-D.+=.*', addInEnvironment),
|
||||
|
|
|
@ -49,7 +49,13 @@ class DartBackend extends Backend {
|
|||
final Set<ClassElement> _userImplementedPlatformClasses =
|
||||
new Set<ClassElement>();
|
||||
|
||||
bool get canHandleCompilationFailed => false;
|
||||
bool enableCodegenWithErrorsIfSupported(Spannable node) {
|
||||
compiler.reportHint(node,
|
||||
MessageKind.GENERIC,
|
||||
{'text': "Generation of code with compile time errors is not "
|
||||
"supported for dart2dart."});
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether it is safe to remove type declarations from variables,
|
||||
|
@ -314,7 +320,7 @@ class DartBackend extends Backend {
|
|||
}
|
||||
|
||||
@override
|
||||
bool registerDeferredLoading(Spannable node, Registry registry) {
|
||||
bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) {
|
||||
// TODO(sigurdm): Implement deferred loading for dart2dart.
|
||||
compiler.reportWarning(node, MessageKind.DEFERRED_LIBRARY_DART_2_DART);
|
||||
return false;
|
||||
|
|
|
@ -776,7 +776,7 @@ class DeferredLoadTask extends CompilerTask {
|
|||
});
|
||||
}
|
||||
if (isProgramSplit) {
|
||||
isProgramSplit = compiler.backend.registerDeferredLoading(
|
||||
isProgramSplit = compiler.backend.enableDeferredLoadingIfSupported(
|
||||
lastDeferred, compiler.globalDependencies);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -608,8 +608,6 @@ class JavaScriptBackend extends Backend {
|
|||
|
||||
PatchResolverTask patchResolverTask;
|
||||
|
||||
bool get canHandleCompilationFailed => true;
|
||||
|
||||
bool enabledNoSuchMethod = false;
|
||||
|
||||
JavaScriptBackend(Compiler compiler,
|
||||
|
@ -2679,10 +2677,23 @@ class JavaScriptBackend extends Backend {
|
|||
}
|
||||
|
||||
@override
|
||||
bool registerDeferredLoading(Spannable node, Registry registry) {
|
||||
bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) {
|
||||
registerCheckDeferredIsLoaded(registry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
bool enableCodegenWithErrorsIfSupported(Spannable node) {
|
||||
if (compiler.useCpsIr) {
|
||||
compiler.reportHint(
|
||||
node,
|
||||
MessageKind.GENERIC,
|
||||
{'text': "Generation of code with compile time errors is currently "
|
||||
"not supported with the CPS IR."});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Handling of special annotations for tests.
|
||||
|
|
|
@ -64,7 +64,7 @@ runCompiler(String main, List<String> options,
|
|||
main() {
|
||||
runCompiler(
|
||||
"",
|
||||
[],
|
||||
['--generate-code-with-compile-time-errors'],
|
||||
(String code, List errors, List warnings) {
|
||||
Expect.isNotNull(code);
|
||||
Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
|
||||
|
@ -75,7 +75,7 @@ main() {
|
|||
|
||||
runCompiler(
|
||||
"main() {}",
|
||||
[],
|
||||
['--generate-code-with-compile-time-errors'],
|
||||
(String code, List errors, List warnings) {
|
||||
Expect.isNotNull(code);
|
||||
Expect.isTrue(errors.isEmpty);
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
// 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.
|
||||
|
||||
// Test that the compiler can generates code with compile time error according
|
||||
// to the compiler options.
|
||||
|
||||
library dart2js.test.import;
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/dart2jslib.dart';
|
||||
import 'package:compiler/src/dart_backend/dart_backend.dart';
|
||||
import 'package:compiler/src/js_backend/js_backend.dart';
|
||||
import 'memory_compiler.dart';
|
||||
import 'output_collector.dart';
|
||||
|
||||
const MEMORY_SOURCE_FILES = const {
|
||||
'main.dart': '''
|
||||
foo() {
|
||||
const list = [];
|
||||
}
|
||||
|
||||
main() {
|
||||
foo();
|
||||
}
|
||||
''',
|
||||
};
|
||||
|
||||
test(List<String> options,
|
||||
{bool expectedOutput,
|
||||
bool expectedCodeGenerated,
|
||||
bool expectHint: false}) async {
|
||||
DiagnosticCollector collector = new DiagnosticCollector();
|
||||
OutputCollector outputCollector = new OutputCollector();
|
||||
Compiler compiler = compilerFor(
|
||||
MEMORY_SOURCE_FILES,
|
||||
diagnosticHandler: collector,
|
||||
outputProvider: outputCollector,
|
||||
options: options);
|
||||
|
||||
return compiler.run(Uri.parse('memory:main.dart')).then(
|
||||
(bool success) {
|
||||
Expect.isFalse(
|
||||
success,
|
||||
"Expected compilation failure.");
|
||||
Expect.isTrue(
|
||||
collector.warnings.isEmpty,
|
||||
"Unexpected warnings: ${collector.warnings}");
|
||||
Expect.isFalse(
|
||||
collector.errors.isEmpty,
|
||||
"Expected compile-time errors.");
|
||||
Expect.equals(
|
||||
expectHint,
|
||||
collector.hints.isNotEmpty,
|
||||
"Unexpected hints: ${collector.warnings}");
|
||||
|
||||
bool isCodeGenerated;
|
||||
if (options.contains('--output-type=dart')) {
|
||||
DartBackend backend = compiler.backend;
|
||||
isCodeGenerated = backend.outputter.libraryInfo != null;
|
||||
} else {
|
||||
JavaScriptBackend backend = compiler.backend;
|
||||
isCodeGenerated = backend.generatedCode.isNotEmpty;
|
||||
}
|
||||
Expect.equals(
|
||||
expectedCodeGenerated,
|
||||
isCodeGenerated,
|
||||
expectedCodeGenerated
|
||||
? "Expected generated code for options $options."
|
||||
: "Expected no code generated for options $options.");
|
||||
Expect.equals(
|
||||
expectedOutput,
|
||||
outputCollector.outputMap.isNotEmpty,
|
||||
expectedOutput
|
||||
? "Expected output for options $options."
|
||||
: "Expected no output for options $options.");
|
||||
});
|
||||
}
|
||||
|
||||
void main() {
|
||||
asyncTest(() async {
|
||||
await test(
|
||||
[],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false);
|
||||
await test(
|
||||
['--test-mode'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false);
|
||||
await test(
|
||||
['--generate-code-with-compile-time-errors'],
|
||||
expectedCodeGenerated: true,
|
||||
expectedOutput: true);
|
||||
await test(
|
||||
['--generate-code-with-compile-time-errors', '--test-mode'],
|
||||
expectedCodeGenerated: true,
|
||||
expectedOutput: false);
|
||||
|
||||
await test(
|
||||
['--use-cps-ir'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false);
|
||||
await test(
|
||||
['--use-cps-ir', '--test-mode'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false);
|
||||
await test(
|
||||
['--use-cps-ir', '--generate-code-with-compile-time-errors'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false,
|
||||
expectHint: true);
|
||||
await test(
|
||||
['--use-cps-ir',
|
||||
'--generate-code-with-compile-time-errors',
|
||||
'--test-mode'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false,
|
||||
expectHint: true);
|
||||
|
||||
await test(
|
||||
['--output-type=dart'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false);
|
||||
await test(
|
||||
['--output-type=dart', '--test-mode'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false);
|
||||
await test(
|
||||
['--output-type=dart', '--generate-code-with-compile-time-errors'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false,
|
||||
expectHint: true);
|
||||
await test(
|
||||
['--output-type=dart',
|
||||
'--generate-code-with-compile-time-errors',
|
||||
'--test-mode'],
|
||||
expectedCodeGenerated: false,
|
||||
expectedOutput: false,
|
||||
expectHint: true);
|
||||
});
|
||||
}
|
|
@ -389,9 +389,9 @@ api.DiagnosticHandler createHandler(MockCompiler compiler, String text,
|
|||
sourceFile = compiler.sourceFiles[uri.toString()];
|
||||
}
|
||||
if (sourceFile != null && begin != null && end != null) {
|
||||
print(sourceFile.getLocationMessage(message, begin, end));
|
||||
print('${kind}: ${sourceFile.getLocationMessage(message, begin, end)}');
|
||||
} else {
|
||||
print(message);
|
||||
print('${kind}: $message');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2199,7 +2199,7 @@ class TestUtils {
|
|||
}
|
||||
String compiler = configuration["compiler"];
|
||||
if (compiler == "dart2js") {
|
||||
args = [];
|
||||
args = ['--generate-code-with-compile-time-errors', '--test-mode'];
|
||||
if (configuration["checked"]) {
|
||||
args.add('--enable-checked-mode');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue