[cfe,dart2js,dartdev] Show null safety mode for `dart compile`
This adds a new messages kind 'info' to the CFE for showing general
information during compilation. A 'configuration' options is added
to `CompilerOptions` for telling the CFE how it is run.
The configuration 'compile' is added for when the CFE is invoked to
produces an "executable" as when running `dart compile`. When
configuration is set, the CFE emits an info message about the
null safety compilation mode.
Support for `dart compile exe` and `dart compile js` is added in this
CL. Support for `dart compile kernel|app-jit|aot` is not included.
In response to https://github.com/dart-lang/sdk/issues/44234
TEST=pkg/dartdev/test/commands/compile_test.dart
Change-Id: I08f51e2a3f5ad4841c4d703bcd266b7afb63c7c6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178982
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index d2ba523..31b5e0f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -988,6 +988,26 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCompilingWithSoundNullSafety =
+ messageCompilingWithSoundNullSafety;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCompilingWithSoundNullSafety = const MessageCode(
+ "CompilingWithSoundNullSafety",
+ severity: Severity.info,
+ message: r"""Compiling with sound null safety""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCompilingWithUnsoundNullSafety =
+ messageCompilingWithUnsoundNullSafety;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCompilingWithUnsoundNullSafety = const MessageCode(
+ "CompilingWithUnsoundNullSafety",
+ severity: Severity.info,
+ message: r"""Compiling with unsound null safety""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
String string,
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart b/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart
index 0358608..9818cca 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart
@@ -10,6 +10,7 @@
ignored,
internalProblem,
warning,
+ info,
}
const Map<String, String> severityEnumNames = const <String, String>{
@@ -18,6 +19,7 @@
'IGNORED': 'ignored',
'INTERNAL_PROBLEM': 'internalProblem',
'WARNING': 'warning',
+ 'INFO': 'info',
};
const Map<String, Severity> severityEnumValues = const <String, Severity>{
@@ -26,6 +28,7 @@
'IGNORED': Severity.ignored,
'INTERNAL_PROBLEM': Severity.internalProblem,
'WARNING': Severity.warning,
+ 'INFO': Severity.info,
};
const Map<Severity, String> severityPrefixes = const <Severity, String>{
@@ -33,6 +36,7 @@
Severity.internalProblem: "Internal problem",
Severity.warning: "Warning",
Severity.context: "Context",
+ Severity.info: "Info",
};
const Map<Severity, String> severityTexts = const <Severity, String>{
@@ -40,4 +44,5 @@
Severity.internalProblem: "internal problem",
Severity.warning: "warning",
Severity.context: "context",
+ Severity.info: "info",
};
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index c93d471..bf9f4a7 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -127,6 +127,8 @@
static const String conditionalDirectives = '--conditional-directives';
+ static const String cfeInvocationModes = '--cfe-invocation-modes';
+
// The syntax-only level of support for generic methods is included in the
// 1.50 milestone for Dart. It is not experimental, but also not permanent:
// a full implementation is expected in the future. Hence, the
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 05bf1ff..6faa855 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -726,9 +726,15 @@
reportDiagnosticInternal(message, infos, api.Diagnostic.HINT);
}
+ @override
+ void reportInfo(DiagnosticMessage message,
+ [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
+ reportDiagnosticInternal(message, infos, api.Diagnostic.INFO);
+ }
+
@deprecated
@override
- void reportInfo(Spannable node, MessageKind messageKind,
+ void reportInfoMessage(Spannable node, MessageKind messageKind,
[Map<String, String> arguments = const {}]) {
reportDiagnosticInternal(createMessage(node, messageKind, arguments),
const <DiagnosticMessage>[], api.Diagnostic.INFO);
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 5a69e20..c528dfb 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -544,6 +544,7 @@
new OptionHandler(Flags.useOldRti, passThrough),
new OptionHandler(Flags.testMode, passThrough),
new OptionHandler('${Flags.dumpSsa}=.+', passThrough),
+ new OptionHandler('${Flags.cfeInvocationModes}=.+', passThrough),
// Experimental features.
// We don't provide documentation for these yet.
diff --git a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
index 554e809..b009473 100644
--- a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
+++ b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
@@ -49,8 +49,11 @@
void reportHint(DiagnosticMessage message,
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
+ void reportInfo(DiagnosticMessage message,
+ [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
+
@deprecated
- void reportInfo(Spannable node, MessageKind errorCode,
+ void reportInfoMessage(Spannable node, MessageKind errorCode,
[Map<String, String> arguments = const {}]);
/// Set current element of this reporter to [element]. This is used for
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 3e82de2..691151c 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -581,7 +581,8 @@
OutputType.dumpInfo)
..add(jsonBuffer.toString())
..close();
- compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
+ compiler.reporter
+ .reportInfoMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
'text': "View the dumped .info.json file at "
"https://dart-lang.github.io/dump-info-visualizer"
});
@@ -592,7 +593,8 @@
Sink<List<int>> sink = new BinaryOutputSinkAdapter(compiler.outputProvider
.createBinarySink(compiler.options.outputUri.resolve(name)));
dump_info.encode(data, sink);
- compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
+ compiler.reporter
+ .reportInfoMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
'text': "Use `package:dart2js_info` to parse and process the dumped "
".info.data file."
});
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index bf34252..910485e9 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -90,8 +90,8 @@
/// Implementation of [reportHere]
_reportHere(DiagnosticReporter reporter, Spannable node, String debugMessage) {
- reporter
- .reportInfo(node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
+ reporter.reportInfoMessage(
+ node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
}
/// Set of tracked objects used by [track] and [ifTracked].
diff --git a/pkg/compiler/lib/src/kernel/front_end_adapter.dart b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
index 571f11f..25796fa 100644
--- a/pkg/compiler/lib/src/kernel/front_end_adapter.dart
+++ b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
@@ -116,6 +116,9 @@
case fe.Severity.warning:
reporter.reportWarning(mainMessage, infos);
break;
+ case fe.Severity.info:
+ reporter.reportInfo(mainMessage, infos);
+ break;
default:
throw new UnimplementedError('unhandled severity ${message.severity}');
}
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index d40a061..a44d5c5 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -170,7 +170,9 @@
explicitExperimentalFlags: _options.explicitExperimentalFlags,
nnbdMode: _options.useLegacySubtyping
? fe.NnbdMode.Weak
- : fe.NnbdMode.Strong);
+ : fe.NnbdMode.Strong,
+ invocationModes:
+ fe.InvocationMode.parseArguments(_options.cfeInvocationModes));
component = await fe.compile(initializedCompilerState, verbose,
fileSystem, onDiagnostic, resolvedUri);
if (component == null) return null;
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 6e86321..2e6ffe7 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -424,6 +424,17 @@
/// deserialize when using [readCodegenUri].
int codegenShards;
+ /// Arguments passed to the front end about how it is invoked.
+ ///
+ /// This is used to selectively emit certain messages depending on how the
+ /// CFE is invoked. For instance to emit a message about the null safety
+ /// compilation mode when compiling an executable.
+ ///
+ /// See `InvocationMode` in
+ /// `pkg/front_end/lib/src/api_prototype/compiler_options.dart` for all
+ /// possible options.
+ String cfeInvocationModes = '';
+
// -------------------------------------------------
// Options for deprecated features
// -------------------------------------------------
@@ -535,7 +546,9 @@
.._soundNullSafety = _hasOption(options, Flags.soundNullSafety)
.._noSoundNullSafety = _hasOption(options, Flags.noSoundNullSafety)
.._mergeFragmentsThreshold =
- _extractIntOption(options, '${Flags.mergeFragmentsThreshold}=');
+ _extractIntOption(options, '${Flags.mergeFragmentsThreshold}=')
+ ..cfeInvocationModes =
+ _extractStringOption(options, '${Flags.cfeInvocationModes}=', '');
}
void validate() {
diff --git a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
index 63d8596..0058660 100644
--- a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
+++ b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
@@ -48,9 +48,15 @@
}
@override
- void reportInfo(Spannable node, MessageKind errorCode,
+ void reportInfo(DiagnosticMessage message,
+ [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
+ reporter.reportInfo(message, infos);
+ }
+
+ @override
+ void reportInfoMessage(Spannable node, MessageKind errorCode,
[Map<String, String> arguments = const {}]) {
- reporter.reportInfo(node, errorCode, arguments);
+ reporter.reportInfoMessage(node, errorCode, arguments);
}
@override
diff --git a/pkg/dart2native/lib/dart2native.dart b/pkg/dart2native/lib/dart2native.dart
index 0139b24..a6d1deb 100644
--- a/pkg/dart2native/lib/dart2native.dart
+++ b/pkg/dart2native/lib/dart2native.dart
@@ -37,8 +37,14 @@
return Process.run('chmod', ['+x', outputFile]);
}
-Future generateAotKernel(String dart, String genKernel, String platformDill,
- String sourceFile, String kernelFile, String packages, List<String> defines,
+Future<ProcessResult> generateAotKernel(
+ String dart,
+ String genKernel,
+ String platformDill,
+ String sourceFile,
+ String kernelFile,
+ String packages,
+ List<String> defines,
{String enableExperiment = '',
List<String> extraGenKernelOptions = const []}) {
return Process.run(dart, [
diff --git a/pkg/dart2native/lib/generate.dart b/pkg/dart2native/lib/generate.dart
index eb70dcf..3579ec8 100644
--- a/pkg/dart2native/lib/generate.dart
+++ b/pkg/dart2native/lib/generate.dart
@@ -57,13 +57,24 @@
final String kernelFile = path.join(tempDir.path, 'kernel.dill');
final kernelResult = await generateAotKernel(Platform.executable, genKernel,
productPlatformDill, sourcePath, kernelFile, packages, defines,
- enableExperiment: enableExperiment);
+ enableExperiment: enableExperiment,
+ extraGenKernelOptions: ['--invocation-modes=compile']);
if (kernelResult.exitCode != 0) {
- stderr.writeln(kernelResult.stdout);
- stderr.writeln(kernelResult.stderr);
+ // We pipe both stdout and stderr to stderr because the CFE doesn't print
+ // errors to stderr. This unfortunately does emit info-only output in
+ // stderr, though.
+ stderr.write(kernelResult.stdout);
+ stderr.write(kernelResult.stderr);
await stderr.flush();
throw 'Generating AOT kernel dill failed!';
}
+ // Pipe info and warnings from the CFE to stdout since the compilation
+ // succeeded. Stderr should be empty but we pipe it to stderr for
+ // completeness.
+ stdout.write(kernelResult.stdout);
+ await stdout.flush();
+ stderr.write(kernelResult.stderr);
+ await stderr.flush();
if (verbose) {
print('Generating AOT snapshot.');
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 6edd82b..29c5b3e 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -98,6 +98,7 @@
'--libraries-spec=$librariesPath',
if (argResults.enabledExperiments.isNotEmpty)
"--enable-experiment=${argResults.enabledExperiments.join(',')}",
+ '--cfe-invocation-modes=compile',
...argResults.arguments,
],
packageConfigOverride: null);
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index f2f5f31..0921ddd 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -15,6 +15,10 @@
group('compile', defineCompileTests, timeout: longTimeout);
}
+const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
+const String unsoundNullSafetyMessage =
+ 'Info: Compiling with unsound null safety';
+
void defineCompileTests() {
// *** NOTE ***: These tests *must* be run with the `--use-sdk` option
// as they depend on a fully built SDK to resolve various snapshot files
@@ -201,4 +205,155 @@
expect(File(outFile).existsSync(), true,
reason: 'File not found: $outFile');
});
+
+ test('Compile exe with error', () {
+ final p = project(mainSrc: '''
+void main() {
+ int? i;
+ i.isEven;
+}
+''');
+ final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+ final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+ var result = p.runSync(
+ [
+ 'compile',
+ 'exe',
+ '-o',
+ outFile,
+ inFile,
+ ],
+ );
+
+ expect(result.stdout, isEmpty);
+ expect(result.stderr, contains('Error: '));
+ // The CFE doesn't print to stderr, so all output is piped to stderr, even
+ // including info-only output:
+ expect(result.stderr, contains(soundNullSafetyMessage));
+ expect(result.exitCode, compileErrorExitCode);
+ expect(File(outFile).existsSync(), false,
+ reason: 'File not found: $outFile');
+ });
+
+ test('Compile exe with warning', () {
+ final p = project(mainSrc: '''
+void main() {
+ int i = 0;
+ i?.isEven;
+}
+''');
+ final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+ final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+ var result = p.runSync(
+ [
+ 'compile',
+ 'exe',
+ '-o',
+ outFile,
+ inFile,
+ ],
+ );
+
+ expect(result.stdout, contains('Warning: '));
+ expect(result.stderr, isEmpty);
+ expect(result.exitCode, 0);
+ expect(File(outFile).existsSync(), true,
+ reason: 'File not found: $outFile');
+ });
+
+ test('Compile exe with sound null safety', () {
+ final p = project(mainSrc: '''void main() {}''');
+ final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+ final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+ var result = p.runSync(
+ [
+ 'compile',
+ 'exe',
+ '-o',
+ outFile,
+ inFile,
+ ],
+ );
+
+ expect(result.stdout, contains(soundNullSafetyMessage));
+ expect(result.stderr, isEmpty);
+ expect(result.exitCode, 0);
+ expect(File(outFile).existsSync(), true,
+ reason: 'File not found: $outFile');
+ });
+
+ test('Compile exe with unsound null safety', () {
+ final p = project(mainSrc: '''
+// @dart=2.9
+void main() {}
+''');
+ final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+ final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+ var result = p.runSync(
+ [
+ 'compile',
+ 'exe',
+ '-o',
+ outFile,
+ inFile,
+ ],
+ );
+
+ expect(result.stdout, contains(unsoundNullSafetyMessage));
+ expect(result.stderr, isEmpty);
+ expect(result.exitCode, 0);
+ expect(File(outFile).existsSync(), true,
+ reason: 'File not found: $outFile');
+ });
+
+ test('Compile JS with sound null safety', () {
+ final p = project(mainSrc: '''void main() {}''');
+ final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+ final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
+
+ var result = p.runSync(
+ [
+ 'compile',
+ 'js',
+ '-o',
+ outFile,
+ inFile,
+ ],
+ );
+
+ expect(result.stdout, contains(soundNullSafetyMessage));
+ expect(result.stderr, isEmpty);
+ expect(result.exitCode, 0);
+ expect(File(outFile).existsSync(), true,
+ reason: 'File not found: $outFile');
+ });
+
+ test('Compile JS with unsound null safety', () {
+ final p = project(mainSrc: '''
+// @dart=2.9
+void main() {}
+''');
+ final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+ final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
+
+ var result = p.runSync(
+ [
+ 'compile',
+ 'js',
+ '-o',
+ outFile,
+ inFile,
+ ],
+ );
+
+ expect(result.stdout, contains(unsoundNullSafetyMessage));
+ expect(result.stderr, isEmpty);
+ expect(result.exitCode, 0);
+ expect(File(outFile).existsSync(), true,
+ reason: 'File not found: $outFile');
+ });
}
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
index d90969a..74b352d 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -159,6 +159,7 @@
static List<String> errors = <String>[];
static List<String> warnings = <String>[];
+ static List<String> infos = <String>[];
/// Create the worker and load the sdk outlines.
static Future<ExpressionCompilerWorker> create({
@@ -188,7 +189,7 @@
..omitPlatform = true
..environmentDefines = environmentDefines
..explicitExperimentalFlags = explicitExperimentalFlags
- ..onDiagnostic = _onDiagnosticHandler(errors, warnings)
+ ..onDiagnostic = _onDiagnosticHandler(errors, warnings, infos)
..nnbdMode = soundNullSafety ? NnbdMode.Strong : NnbdMode.Weak
..verbose = verbose;
requestStream ??= stdin
@@ -275,6 +276,7 @@
errors.clear();
warnings.clear();
+ infos.clear();
var incrementalCompiler = IncrementalCompiler.forExpressionCompilationOnly(
CompilerContext(_processedOptions), component, /*resetTicker*/ false);
@@ -288,6 +290,7 @@
return {
'errors': errors,
'warnings': warnings,
+ 'infos': infos,
'compiledProcedure': null,
'succeeded': errors.isEmpty,
};
@@ -332,6 +335,7 @@
return {
'errors': errors,
'warnings': warnings,
+ 'infos': infos,
'compiledProcedure': compiledProcedure,
'succeeded': errors.isEmpty,
};
@@ -461,7 +465,7 @@
}
void Function(DiagnosticMessage) _onDiagnosticHandler(
- List<String> errors, List<String> warnings) =>
+ List<String> errors, List<String> warnings, List<String> infos) =>
(DiagnosticMessage message) {
switch (message.severity) {
case Severity.error:
@@ -471,6 +475,9 @@
case Severity.warning:
warnings.add(message.plainTextFormatted.join('\n'));
break;
+ case Severity.info:
+ infos.add(message.plainTextFormatted.join('\n'));
+ break;
case Severity.context:
case Severity.ignored:
throw 'Unexpected severity: ${message.severity}';
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
index a8af7506..501fe6d 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
@@ -255,6 +255,7 @@
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
+ 'infos': isEmpty,
'compiledProcedure': contains('return other;'),
})
]));
@@ -288,6 +289,7 @@
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
+ 'infos': isEmpty,
'compiledProcedure': contains('return formal;'),
})
]));
@@ -320,6 +322,7 @@
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
+ 'infos': isEmpty,
'compiledProcedure': contains('return count;'),
})
]));
@@ -354,6 +357,7 @@
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
+ 'infos': isEmpty,
'compiledProcedure': contains('return ret;'),
})
]));
@@ -387,6 +391,7 @@
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
+ 'infos': isEmpty,
'compiledProcedure':
contains('return new test_library.B.new().c().getNumber()'),
})
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 4b517ca..7639c95 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -256,6 +256,13 @@
/// compiling the platform dill.
bool emitDeps = true;
+ /// Set of invocation modes the describe how the compilation is performed.
+ ///
+ /// This used to selectively emit certain messages depending on how the
+ /// CFE is invoked. For instance to emit a message about the null safety
+ /// compilation mode when the modes includes [InvocationMode.compile].
+ Set<InvocationMode> invocationModes = {};
+
bool isExperimentEnabledByDefault(ExperimentalFlag flag) {
return flags.isExperimentEnabled(flag,
defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting);
@@ -344,6 +351,7 @@
if (nnbdMode != other.nnbdMode) return false;
if (currentSdkVersion != other.currentSdkVersion) return false;
if (emitDeps != other.emitDeps) return false;
+ if (!equalSets(invocationModes, other.invocationModes)) return false;
return true;
}
@@ -431,3 +439,44 @@
}
return flags;
}
+
+class InvocationMode {
+ /// This mode is used for when the CFE is invoked in order to compile an
+ /// executable.
+ ///
+ /// If used, a message about the null safety compilation mode will be emitted.
+ static const InvocationMode compile = const InvocationMode('compile');
+
+ final String name;
+
+ const InvocationMode(this.name);
+
+ /// Returns the set of information modes from a comma-separated list of
+ /// invocation mode names.
+ static Set<InvocationMode> parseArguments(String arg) {
+ Set<InvocationMode> result = {};
+ for (String name in arg.split(',')) {
+ if (name.isNotEmpty) {
+ InvocationMode mode = fromName(name);
+ if (mode == null) {
+ throw new UnsupportedError("Unknown invocation mode '$name'.");
+ } else {
+ result.add(mode);
+ }
+ }
+ }
+ return result;
+ }
+
+ /// Returns the [InvocationMode] with the given [name].
+ static InvocationMode fromName(String name) {
+ for (InvocationMode invocationMode in values) {
+ if (name == invocationMode.name) {
+ return invocationMode;
+ }
+ }
+ return null;
+ }
+
+ static const List<InvocationMode> values = const [compile];
+}
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index d7fba2e..9a102ac 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -18,7 +18,8 @@
import 'package:kernel/target/targets.dart' show Target;
-import '../api_prototype/compiler_options.dart' show CompilerOptions;
+import '../api_prototype/compiler_options.dart'
+ show CompilerOptions, InvocationMode;
import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
@@ -40,7 +41,7 @@
import 'compiler_state.dart' show InitializedCompilerState;
-import 'util.dart' show equalLists, equalMaps;
+import 'util.dart' show equalLists, equalMaps, equalSets;
export 'package:_fe_analyzer_shared/src/messages/codes.dart'
show LocatedMessage;
@@ -97,7 +98,11 @@
show relativizeUri;
export '../api_prototype/compiler_options.dart'
- show CompilerOptions, parseExperimentalFlags, parseExperimentalArguments;
+ show
+ CompilerOptions,
+ InvocationMode,
+ parseExperimentalFlags,
+ parseExperimentalArguments;
export '../api_prototype/experimental_flags.dart'
show defaultExperimentalFlags, ExperimentalFlag, isExperimentEnabled;
@@ -138,7 +143,8 @@
Uri packagesFileUri,
{Map<ExperimentalFlag, bool> explicitExperimentalFlags,
bool verify: false,
- NnbdMode nnbdMode}) {
+ NnbdMode nnbdMode,
+ Set<InvocationMode> invocationModes: const <InvocationMode>{}}) {
additionalDills.sort((a, b) => a.toString().compareTo(b.toString()));
// We don't check `target` because it doesn't support '==' and each
@@ -151,7 +157,8 @@
equalMaps(oldState.options.explicitExperimentalFlags,
explicitExperimentalFlags) &&
oldState.options.verify == verify &&
- oldState.options.nnbdMode == nnbdMode) {
+ oldState.options.nnbdMode == nnbdMode &&
+ equalSets(oldState.options.invocationModes, invocationModes)) {
return oldState;
}
@@ -161,7 +168,8 @@
..librariesSpecificationUri = librariesSpecificationUri
..packagesFileUri = packagesFileUri
..explicitExperimentalFlags = explicitExperimentalFlags
- ..verify = verify;
+ ..verify = verify
+ ..invocationModes = invocationModes;
if (nnbdMode != null) options.nnbdMode = nnbdMode;
ProcessedOptions processedOpts = new ProcessedOptions(options: options);
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 6e45bfc..65963f9 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -8,7 +8,11 @@
export 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
export '../api_prototype/compiler_options.dart'
- show CompilerOptions, parseExperimentalArguments, parseExperimentalFlags;
+ show
+ CompilerOptions,
+ InvocationMode,
+ parseExperimentalArguments,
+ parseExperimentalFlags;
export '../api_prototype/experimental_flags.dart'
show defaultExperimentalFlags, ExperimentalFlag;
diff --git a/pkg/front_end/lib/src/base/command_line_options.dart b/pkg/front_end/lib/src/base/command_line_options.dart
index a87824f..862187a 100644
--- a/pkg/front_end/lib/src/base/command_line_options.dart
+++ b/pkg/front_end/lib/src/base/command_line_options.dart
@@ -41,4 +41,6 @@
static const String verify = "--verify";
static const String verifySkipPlatform = "--verify-skip-platform";
static const String warnOnReachabilityCheck = "--warn-on-reachability-check";
+
+ static const String invocationModes = "--invocation-modes";
}
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 97f49f0..ec366d0 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -24,7 +24,7 @@
import 'package:package_config/package_config.dart';
import '../api_prototype/compiler_options.dart'
- show CompilerOptions, DiagnosticMessage;
+ show CompilerOptions, InvocationMode, DiagnosticMessage;
import '../api_prototype/experimental_flags.dart' as flags;
@@ -45,6 +45,8 @@
Message,
messageCantInferPackagesFromManyInputs,
messageCantInferPackagesFromPackageUri,
+ messageCompilingWithSoundNullSafety,
+ messageCompilingWithUnsoundNullSafety,
messageInternalProblemProvidedBothCompileSdkAndSdkSummary,
messageMissingInput,
noLength,
@@ -267,6 +269,25 @@
report(message.withoutLocation(), severity);
}
+ /// If `CompilerOptions.invocationModes` contains `InvocationMode.compile`, an
+ /// info message about the null safety compilation mode is emitted.
+ void reportNullSafetyCompilationModeInfo() {
+ if (_raw.invocationModes.contains(InvocationMode.compile)) {
+ switch (nnbdMode) {
+ case NnbdMode.Weak:
+ reportWithoutLocation(messageCompilingWithUnsoundNullSafety,
+ messageCompilingWithUnsoundNullSafety.severity);
+ break;
+ case NnbdMode.Strong:
+ reportWithoutLocation(messageCompilingWithSoundNullSafety,
+ messageCompilingWithSoundNullSafety.severity);
+ break;
+ case NnbdMode.Agnostic:
+ break;
+ }
+ }
+ }
+
/// Runs various validations checks on the input options. For instance,
/// if an option is a path to a file, it checks that the file exists.
Future<bool> validateOptions({bool errorOnMissingInput: true}) async {
diff --git a/pkg/front_end/lib/src/fasta/command_line_reporting.dart b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
index 1247aea..d8f6c95 100644
--- a/pkg/front_end/lib/src/fasta/command_line_reporting.dart
+++ b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
@@ -19,7 +19,7 @@
show $CARET, $SPACE, $TAB;
import 'package:_fe_analyzer_shared/src/util/colors.dart'
- show enableColors, green, magenta, red;
+ show enableColors, green, magenta, red, yellow;
import 'package:_fe_analyzer_shared/src/util/relativize.dart'
show isWindows, relativizeUri;
@@ -73,6 +73,11 @@
messageText = green(messageText);
break;
+ case Severity.info:
+ messageText = yellow(messageText);
+ break;
+
+ case Severity.ignored:
default:
return unhandled("$severity", "format", -1, null);
}
@@ -145,14 +150,15 @@
case Severity.error:
case Severity.internalProblem:
case Severity.context:
+ case Severity.info:
return false;
case Severity.warning:
return hideWarnings;
-
- default:
- return unhandled("$severity", "isHidden", -1, null);
+ case Severity.ignored:
+ return true;
}
+ return unhandled("$severity", "isHidden", -1, null);
}
/// Are problems of [severity] fatal? That is, should the compiler terminate
@@ -168,12 +174,12 @@
case Severity.warning:
return CompilerContext.current.options.throwOnWarningsForDebugging;
+ case Severity.info:
+ case Severity.ignored:
case Severity.context:
return false;
-
- default:
- return unhandled("$severity", "shouldThrowOn", -1, null);
}
+ return unhandled("$severity", "shouldThrowOn", -1, null);
}
bool isCompileTimeError(Severity severity) {
@@ -184,6 +190,7 @@
case Severity.warning:
case Severity.context:
+ case Severity.info:
return false;
case Severity.ignored:
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index ae668cb..d4ec55d 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -65,6 +65,7 @@
bool retainDataForTesting: false,
bool includeHierarchyAndCoreTypes: false}) async {
ProcessedOptions options = CompilerContext.current.options;
+ options.reportNullSafetyCompilationModeInfo();
FileSystem fs = options.fileSystem;
Loader sourceLoader;
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index afaa87e..794f307 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -69,6 +69,8 @@
CantUseSuperBoundedTypeForInstanceCreation/example: Fail
ClassInNullAwareReceiver/analyzerCode: Fail
ColonInPlaceOfIn/example: Fail
+CompilingWithSoundNullSafety/analyzerCode: Fail
+CompilingWithUnsoundNullSafety/analyzerCode: Fail
ConflictingModifiers/part_wrapped_script1: Fail
ConflictingModifiers/script1: Fail
ConflictsWithConstructor/example: Fail
@@ -172,6 +174,8 @@
DirectiveAfterDeclaration/part_wrapped_script2: Fail
DirectiveAfterDeclaration/script1: Fail
DirectiveAfterDeclaration/script2: Fail
+DuplicateDeferred/example: Fail
+DuplicatePrefix/example: Fail
DuplicatedDeclarationUse/analyzerCode: Fail # No corresponding analyzer code.
DuplicatedDeclarationUse/part_wrapped_script1: Fail
DuplicatedDeclarationUse/part_wrapped_script2: Fail
@@ -179,7 +183,6 @@
DuplicatedDeclarationUse/script2: Fail # Wrong error.
DuplicatedDefinition/analyzerCode: Fail
DuplicatedDefinition/example: Fail
-DuplicateDeferred/example: Fail
DuplicatedExport/part_wrapped_script: Fail # Exporting file in the (now) part.
DuplicatedExportInType/analyzerCode: Fail
DuplicatedExportInType/example: Fail
@@ -191,7 +194,6 @@
DuplicatedName/example: Fail
DuplicatedNamedArgument/example: Fail
DuplicatedParameterName/example: Fail
-DuplicatePrefix/example: Fail
Encoding/analyzerCode: Fail
EnumConstantSameNameAsEnclosing/example: Fail
EnumInstantiation/example: Fail
@@ -271,7 +273,6 @@
ExternalFactoryWithBody/script1: Fail
ExternalFieldConstructorInitializer/analyzerCode: Fail
ExternalFieldInitializer/analyzerCode: Fail
-ExtraneousModifier/part_wrapped_script1: Fail
ExtraneousModifier/part_wrapped_script10: Fail
ExtraneousModifier/part_wrapped_script11: Fail
ExtraneousModifier/part_wrapped_script12: Fail
@@ -280,8 +281,9 @@
ExtraneousModifier/part_wrapped_script17: Fail
ExtraneousModifier/part_wrapped_script18: Fail
ExtraneousModifier/part_wrapped_script19: Fail
-ExtraneousModifier/part_wrapped_script2: Fail
+ExtraneousModifier/part_wrapped_script1: Fail
ExtraneousModifier/part_wrapped_script20: Fail
+ExtraneousModifier/part_wrapped_script2: Fail
ExtraneousModifier/part_wrapped_script3: Fail
ExtraneousModifier/part_wrapped_script4: Fail
ExtraneousModifier/part_wrapped_script5: Fail
@@ -289,7 +291,6 @@
ExtraneousModifier/part_wrapped_script7: Fail
ExtraneousModifier/part_wrapped_script8: Fail
ExtraneousModifier/part_wrapped_script9: Fail
-ExtraneousModifier/script1: Fail
ExtraneousModifier/script10: Fail
ExtraneousModifier/script11: Fail
ExtraneousModifier/script12: Fail
@@ -298,8 +299,9 @@
ExtraneousModifier/script17: Fail
ExtraneousModifier/script18: Fail
ExtraneousModifier/script19: Fail
-ExtraneousModifier/script2: Fail
+ExtraneousModifier/script1: Fail
ExtraneousModifier/script20: Fail
+ExtraneousModifier/script2: Fail
ExtraneousModifier/script3: Fail
ExtraneousModifier/script4: Fail
ExtraneousModifier/script5: Fail
@@ -396,10 +398,10 @@
IncompatibleRedirecteeFunctionType/part_wrapped_script6: Fail
IncompatibleRedirecteeFunctionType/script6: Fail # Triggers multiple errors.
IncompatibleRedirecteeFunctionTypeWarning/example: Fail
-IncorrectTypeArgumentInferredWarning/example: Fail
IncorrectTypeArgumentInReturnTypeWarning/example: Fail
IncorrectTypeArgumentInSupertypeInferredWarning/example: Fail
IncorrectTypeArgumentInSupertypeWarning/example: Fail
+IncorrectTypeArgumentInferredWarning/example: Fail
IncorrectTypeArgumentQualifiedInferredWarning/example: Fail
IncorrectTypeArgumentQualifiedWarning/example: Fail
IncorrectTypeArgumentWarning/example: Fail
@@ -564,6 +566,9 @@
NeverValueWarning/analyzerCode: Fail
NeverValueWarning/example: Fail
NoFormals/example: Fail
+NoSuchNamedParameter/example: Fail
+NoUnnamedConstructorInObject/analyzerCode: Fail
+NoUnnamedConstructorInObject/example: Fail
NonAgnosticConstant/analyzerCode: Fail
NonAgnosticConstant/example: Fail
NonAsciiIdentifier/expression: Fail
@@ -571,6 +576,7 @@
NonConstConstructor/example: Fail
NonConstFactory/example: Fail
NonInstanceTypeVariableUse/example: Fail
+NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
NonNullableInNullAware/analyzerCode: Fail
NonNullableInNullAware/example: Fail
NonNullableNotAssignedError/analyzerCode: Fail
@@ -580,17 +586,14 @@
NonNullableOptOutExplicit/example: Fail
NonNullableOptOutImplicit/analyzerCode: Fail
NonNullableOptOutImplicit/example: Fail
-NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
NonPartOfDirectiveInPart/part_wrapped_script1: Fail
NonPartOfDirectiveInPart/script1: Fail
-NoSuchNamedParameter/example: Fail
NotAConstantExpression/example: Fail
-NotAnLvalue/example: Fail
NotAType/example: Fail
+NotAnLvalue/example: Fail
NotBinaryOperator/analyzerCode: Fail
NotConstantExpression/example: Fail
-NoUnnamedConstructorInObject/analyzerCode: Fail
-NoUnnamedConstructorInObject/example: Fail
+NullAwareCascadeOutOfOrder/example: Fail
NullableExpressionCallError/analyzerCode: Fail
NullableExpressionCallError/example: Fail
NullableExpressionCallWarning/analyzerCode: Fail
@@ -625,7 +628,6 @@
NullableTearoffError/example: Fail
NullableTearoffWarning/analyzerCode: Fail
NullableTearoffWarning/example: Fail
-NullAwareCascadeOutOfOrder/example: Fail
OperatorMinusParameterMismatch/example: Fail
OperatorParameterMismatch0/analyzerCode: Fail
OperatorParameterMismatch0/example: Fail
@@ -723,13 +725,13 @@
StrongWithWeakDillLibrary/spelling: Fail
SuperAsExpression/example: Fail
SuperAsIdentifier/example: Fail
+SuperNullAware/example: Fail
SuperclassHasNoDefaultConstructor/example: Fail
SuperclassHasNoGetter/example: Fail
SuperclassHasNoMethod/example: Fail
SuperclassHasNoSetter/example: Fail
SuperclassMethodArgumentMismatch/analyzerCode: Fail
SuperclassMethodArgumentMismatch/example: Fail
-SuperNullAware/example: Fail
SupertypeIsFunction/analyzerCode: Fail
SupertypeIsFunction/example: Fail
SupertypeIsIllegal/example: Fail
@@ -754,14 +756,14 @@
TypeArgumentMismatch/example: Fail
TypeArgumentsOnTypeVariable/part_wrapped_script1: Fail
TypeArgumentsOnTypeVariable/script1: Fail
+TypeNotFound/example: Fail
+TypeVariableDuplicatedName/example: Fail
+TypeVariableSameNameAsEnclosing/example: Fail
TypedefNotFunction/example: Fail
TypedefNotType/example: Fail # Feature not yet enabled by default.
TypedefNullableType/analyzerCode: Fail
TypedefTypeVariableNotConstructor/analyzerCode: Fail # Feature not yet enabled by default.
TypedefTypeVariableNotConstructor/example: Fail # Feature not yet enabled by default.
-TypeNotFound/example: Fail
-TypeVariableDuplicatedName/example: Fail
-TypeVariableSameNameAsEnclosing/example: Fail
UnexpectedToken/part_wrapped_script1: Fail
UnexpectedToken/script1: Fail
UnmatchedToken/part_wrapped_script1: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 390424e..9bb52f9 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -4936,3 +4936,18 @@
analyzerCode: UNEXPECTED_TOKEN
script:
- "late int x;"
+
+CompilingWithSoundNullSafety:
+ template: "Compiling with sound null safety"
+ configuration: nnbd-strong,compile
+ severity: INFO
+ script: |
+ main() {}
+
+CompilingWithUnsoundNullSafety:
+ template: "Compiling with unsound null safety"
+ configuration: nnbd-weak,compile
+ severity: INFO
+ script: |
+ // @dart=2.9
+ main() {}
diff --git a/pkg/front_end/test/fasta/messages_suite.dart b/pkg/front_end/test/fasta/messages_suite.dart
index 9a370f4..8e04b81 100644
--- a/pkg/front_end/test/fasta/messages_suite.dart
+++ b/pkg/front_end/test/fasta/messages_suite.dart
@@ -26,7 +26,7 @@
import "package:yaml/yaml.dart" show YamlList, YamlMap, YamlNode, loadYamlNode;
import 'package:front_end/src/api_prototype/compiler_options.dart'
- show CompilerOptions;
+ show CompilerOptions, InvocationMode;
import 'package:front_end/src/api_prototype/experimental_flags.dart'
show ExperimentalFlag;
@@ -70,8 +70,9 @@
class Configuration {
final NnbdMode nnbdMode;
+ final Set<InvocationMode> invocationModes;
- const Configuration(this.nnbdMode);
+ const Configuration(this.nnbdMode, this.invocationModes);
CompilerOptions apply(CompilerOptions options) {
if (nnbdMode != null) {
@@ -80,10 +81,12 @@
} else {
options.explicitExperimentalFlags[ExperimentalFlag.nonNullable] = false;
}
+ options.invocationModes = invocationModes;
return options;
}
- static const Configuration defaultConfiguration = const Configuration(null);
+ static const Configuration defaultConfiguration =
+ const Configuration(null, const {});
}
class MessageTestSuite extends ChainContext {
@@ -345,12 +348,25 @@
break;
case "configuration":
- if (value == "nnbd-weak") {
- configuration = const Configuration(NnbdMode.Weak);
- } else if (value == "nnbd-strong") {
- configuration = const Configuration(NnbdMode.Strong);
- } else {
- throw new ArgumentError("Unknown configuration '$value'.");
+ if (value is String) {
+ NnbdMode nnbdMode;
+ Set<InvocationMode> invocationModes = {};
+ for (String part in value.split(',')) {
+ if (part.isEmpty) continue;
+ if (part == "nnbd-weak") {
+ nnbdMode = NnbdMode.Weak;
+ } else if (part == "nnbd-strong") {
+ nnbdMode = NnbdMode.Strong;
+ } else {
+ InvocationMode invocationMode = InvocationMode.fromName(part);
+ if (invocationMode != null) {
+ invocationModes.add(invocationMode);
+ } else {
+ throw new ArgumentError("Unknown configuration '$part'.");
+ }
+ }
+ }
+ configuration = new Configuration(nnbdMode, invocationModes);
}
break;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index cfb9146..f719e36e 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -1014,6 +1014,7 @@
sdk's
seconds
sections
+selectively
selectors
semantically
semver
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index ed79435..9c275d4 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -198,6 +198,7 @@
Flags.warnOnReachabilityCheck: const BoolValue(false),
Flags.linkDependencies: const UriListValue(),
Flags.noDeps: const BoolValue(false),
+ Flags.invocationModes: const StringValue(),
"-D": const DefineValue(),
"-h": const AliasValue(Flags.help),
"--out": const AliasValue(Flags.output),
@@ -303,6 +304,8 @@
final List<Uri> linkDependencies = options[Flags.linkDependencies] ?? [];
+ final String invocationModes = options[Flags.invocationModes] ?? '';
+
if (nnbdStrongMode && nnbdWeakMode) {
return throw new CommandLineProblem.deprecated(
"Can't specify both '${Flags.nnbdStrongMode}' and "
@@ -353,7 +356,8 @@
..nnbdMode = nnbdMode
..additionalDills = linkDependencies
..emitDeps = !noDeps
- ..warnOnReachabilityCheck = warnOnReachabilityCheck;
+ ..warnOnReachabilityCheck = warnOnReachabilityCheck
+ ..invocationModes = InvocationMode.parseArguments(invocationModes);
if (programName == "compile_platform") {
if (arguments.length != 5) {
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 1aa2265..b05374d 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -357,6 +357,7 @@
Future<Uri> compile(
{bool omitPlatform: false, bool supportAdditionalDills: true}) async {
+ c.options.reportNullSafetyCompilationModeInfo();
KernelTarget kernelTarget =
await buildOutline(supportAdditionalDills: supportAdditionalDills);
Uri uri = c.options.output;
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 5b8a4eb..21d82f5 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -359,6 +359,7 @@
errors.addAll(message.plainTextFormatted);
break;
case Severity.warning:
+ case Severity.info:
printMessage = true;
break;
case Severity.context:
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 3a7d5f4..a0fc1de 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -126,6 +126,7 @@
errors.addAll(message.plainTextFormatted);
break;
case Severity.warning:
+ case Severity.info:
printMessage = !suppressWarnings;
break;
case Severity.context:
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index bd60735..a1fc45e 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -23,6 +23,7 @@
CompilerContext,
CompilerOptions,
CompilerResult,
+ InvocationMode,
DiagnosticMessage,
DiagnosticMessageHandler,
ExperimentalFlag,
@@ -127,6 +128,9 @@
args.addFlag('track-widget-creation',
help: 'Run a kernel transformer to track creation locations for widgets.',
defaultsTo: false);
+ args.addOption('invocation-modes',
+ help: 'Provides information to the front end about how it is invoked.',
+ defaultsTo: '');
}
/// Create ArgParser and populate it with options consumed by [runCompiler].
@@ -226,7 +230,9 @@
..onDiagnostic = (DiagnosticMessage m) {
errorDetector(m);
}
- ..embedSourceText = embedSources;
+ ..embedSourceText = embedSources
+ ..invocationModes =
+ InvocationMode.parseArguments(options['invocation-modes']);
if (nullSafety == null &&
compilerOptions.isExperimentEnabled(ExperimentalFlag.nonNullable)) {
@@ -496,7 +502,18 @@
void printCompilationMessages() {
final sortedUris = compilationMessages.keys.toList()
- ..sort((a, b) => '$a'.compareTo('$b'));
+ ..sort((a, b) {
+ // Sort messages without a corresponding uri before the location based
+ // messages, since these related to the whole compilation.
+ if (a != null && b != null) {
+ return '$a'.compareTo('$b');
+ } else if (a != null) {
+ return 1;
+ } else if (b != null) {
+ return -1;
+ }
+ return 0;
+ });
for (final Uri sourceUri in sortedUris) {
for (final DiagnosticMessage message in compilationMessages[sourceUri]) {
printDiagnosticMessage(message, print);