(Some) DiagnosticMessages can be serialized to/from json.

This is needed to serialize and deserialize problems to dill and
re-issuing problems as needed.

Change-Id: Id22d1c86f43b1b08c5e5a4d133869075e9b0c100
Reviewed-on: https://dart-review.googlesource.com/c/91743
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
This commit is contained in:
Jens Johansen 2019-02-01 11:07:27 +00:00 committed by commit-bot@chromium.org
parent eb956a2516
commit 014124e763
6 changed files with 156 additions and 6 deletions

View file

@ -4,7 +4,8 @@
library front_end.diagnostic_message;
import '../fasta/fasta_codes.dart' show Code, FormattedMessage;
import '../fasta/fasta_codes.dart'
show Code, DiagnosticMessageFromJson, FormattedMessage;
import '../fasta/severity.dart' show Severity;
@ -38,7 +39,9 @@ abstract class DiagnosticMessage {
/// This method is subject to change.
Uri getMessageUri(DiagnosticMessage message) {
return message is FormattedMessage ? message.uri : null;
return message is FormattedMessage
? message.uri
: message is DiagnosticMessageFromJson ? message.uri : null;
}
/// This method is subject to change.

View file

@ -212,14 +212,17 @@ class ProcessedOptions {
if (CompilerContext.current.options.setExitCodeOnProblem) {
exitCode = 1;
}
(_raw.onDiagnostic ??
_defaultDiagnosticMessageHandler)(format(message, severity, context));
reportDiagnosticMessage(format(message, severity, context));
if (command_line_reporting.shouldThrowOn(severity)) {
throw new DebugAbort(
message.uri, message.charOffset, severity, StackTrace.current);
}
}
void reportDiagnosticMessage(DiagnosticMessage message) {
(_raw.onDiagnostic ?? _defaultDiagnosticMessageHandler)(message);
}
void _defaultDiagnosticMessageHandler(DiagnosticMessage message) {
printDiagnosticMessage(message, print);
}

View file

@ -4,7 +4,7 @@
library fasta.codes;
import 'dart:convert' show JsonEncoder;
import 'dart:convert' show JsonEncoder, json;
import 'package:kernel/ast.dart'
show Constant, DartType, demangleMixinApplicationName;
@ -185,10 +185,56 @@ class FormattedMessage implements DiagnosticMessage {
}
Map<String, Object> toJson() {
// The should be kept in sync with package:kernel/problems.md
// This should be kept in sync with package:kernel/problems.md
return <String, Object>{
"ansiFormatted": ansiFormatted.toList(),
"plainTextFormatted": plainTextFormatted.toList(),
"severity": severity.index,
"uri": uri.toString(),
};
}
String toJsonString() {
JsonEncoder encoder = new JsonEncoder.withIndent(" ");
return encoder.convert(this);
}
}
class DiagnosticMessageFromJson implements DiagnosticMessage {
@override
final Iterable<String> ansiFormatted;
@override
final Iterable<String> plainTextFormatted;
@override
final Severity severity;
final Uri uri;
DiagnosticMessageFromJson(
this.ansiFormatted, this.plainTextFormatted, this.severity, this.uri);
factory DiagnosticMessageFromJson.fromJson(String jsonString) {
Map<String, Object> decoded = json.decode(jsonString);
List<String> ansiFormatted =
new List<String>.from(decoded["ansiFormatted"]);
List<String> plainTextFormatted =
new List<String>.from(decoded["plainTextFormatted"]);
Severity severity = Severity.values[decoded["severity"]];
Uri uri = Uri.parse(decoded["uri"]);
return new DiagnosticMessageFromJson(
ansiFormatted, plainTextFormatted, severity, uri);
}
Map<String, Object> toJson() {
// This should be kept in sync with package:kernel/problems.md
return <String, Object>{
"ansiFormatted": ansiFormatted.toList(),
"plainTextFormatted": plainTextFormatted.toList(),
"severity": severity.index,
"uri": uri.toString(),
};
}

View file

@ -0,0 +1,69 @@
// Copyright (c) 2019, 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.
import 'package:front_end/src/api_prototype/diagnostic_message.dart'
show DiagnosticMessage, getMessageUri;
import 'package:front_end/src/fasta/fasta_codes.dart'
show DiagnosticMessageFromJson, FormattedMessage, LocatedMessage;
import 'package:front_end/src/fasta/severity.dart' show Severity;
/// Test that turning a message into json and back again retains the wanted
/// information.
main() {
for (int i = 0; i < Severity.values.length; i++) {
Severity severity = Severity.values[i];
LocatedMessage locatedMessage1 =
new LocatedMessage(Uri.parse("what:ever/fun_1.dart"), 117, 2, null);
FormattedMessage formattedMessage2 = new FormattedMessage(
null, "Formatted string #2", 13, 2, Severity.error, []);
FormattedMessage formattedMessage3 = new FormattedMessage(
null, "Formatted string #3", 313, 32, Severity.error, []);
FormattedMessage formattedMessage1 = new FormattedMessage(
locatedMessage1,
"Formatted string",
42,
86,
severity,
[formattedMessage2, formattedMessage3]);
DiagnosticMessageFromJson diagnosticMessageFromJson =
new DiagnosticMessageFromJson.fromJson(
formattedMessage1.toJsonString());
compareMessages(formattedMessage1, diagnosticMessageFromJson);
DiagnosticMessageFromJson diagnosticMessageFromJson2 =
new DiagnosticMessageFromJson.fromJson(
diagnosticMessageFromJson.toJsonString());
compareMessages(diagnosticMessageFromJson, diagnosticMessageFromJson2);
expect(diagnosticMessageFromJson2.toJsonString(),
formattedMessage1.toJsonString());
}
}
void compareMessages(DiagnosticMessage a, DiagnosticMessage b) {
List<String> list1 = a.ansiFormatted.toList();
List<String> list2 = b.ansiFormatted.toList();
expect(list1.length, list2.length);
for (int i = 0; i < list1.length; i++) {
expect(list1[i], list2[i]);
}
list1 = a.plainTextFormatted.toList();
list2 = b.plainTextFormatted.toList();
expect(list1.length, list2.length);
for (int i = 0; i < list1.length; i++) {
expect(list1[i], list2[i]);
}
expect(a.severity, b.severity);
expect(getMessageUri(a), getMessageUri(b));
}
void expect(Object actual, Object expect) {
if (expect != actual) throw "Expected $expect got $actual";
}

View file

@ -0,0 +1,23 @@
// Copyright (c) 2019, 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.
import 'package:front_end/src/fasta/severity.dart' show Severity;
/// Test that Severity has the expected indexes. Note that this is important
/// and shouldn't be changed lightly because we use it in serialization!
main() {
expect(Severity.context.index, 0);
expect(Severity.error.index, 1);
expect(Severity.internalProblem.index, 4);
expect(Severity.warning.index, 5);
expect(Severity.values[0], Severity.context);
expect(Severity.values[1], Severity.error);
expect(Severity.values[4], Severity.internalProblem);
expect(Severity.values[5], Severity.warning);
}
void expect(Object actual, Object expect) {
if (expect != actual) throw "Expected $expect got $actual";
}

View file

@ -10,9 +10,15 @@ Each string in the list is a json object consisting of these keys and values:
`ansiFormatted`: A list of strings the contain ansi formatted (for instance with
colors) problem-texts as reported by the compiler.
`plainTextFormatted`: A list of strings that contain formatted plaintext
problem-texts as reported by the compiler.
`severity`: An integer representing severity. This should match the index in
`package:front_end/src/fasta/severity.dart`.
`uri: A uri that this problems relates to.
These values are subject to change, but this file will be updated along with any
such changes. On the code-side these are defined in
`package:front_end/src/fasta/fasta_codes.dart`.