Summarize the context messages in diagnostics
Change-Id: Id03e778cf9bebe9be61d9ded601408121b891097
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107102
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 7c1fa00..d11d395 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -837,12 +837,14 @@
* Initialize a newly created analysis error with given values.
*/
AnalysisError.forValues(this.source, int offset, int length, this.errorCode,
- String message, this._correction) {
+ String message, this._correction,
+ {List<DiagnosticMessage> contextMessages}) {
_problemMessage = new DiagnosticMessageImpl(
filePath: source?.fullName,
length: length,
message: message,
offset: offset);
+ _contextMessages = contextMessages;
}
List<DiagnosticMessage> get contextMessages => _contextMessages ?? const [];
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index ead50fe5..3ce5fe3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -12,6 +12,7 @@
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart' show LibraryElement;
+import 'package:analyzer/diagnostic/diagnostic.dart' as diagnostic;
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/exception/exception.dart';
@@ -29,6 +30,7 @@
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/analysis/status.dart';
import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
+import 'package:analyzer/src/diagnostic/diagnostic.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart'
show
@@ -94,7 +96,7 @@
/**
* The version of data format, should be incremented on every format change.
*/
- static const int DATA_VERSION = 83;
+ static const int DATA_VERSION = 84;
/**
* The number of exception contexts allowed to write. Once this field is
@@ -1717,13 +1719,25 @@
AnalysisEngine.instance.instrumentationService
.logError('No error code for "$error" in "$file"');
} else {
+ List<DiagnosticMessageImpl> contextMessages;
+ if (error.contextMessages.isNotEmpty) {
+ contextMessages = <DiagnosticMessageImpl>[];
+ for (var message in error.contextMessages) {
+ contextMessages.add(DiagnosticMessageImpl(
+ filePath: message.filePath,
+ length: message.length,
+ message: message.message,
+ offset: message.offset));
+ }
+ }
errors.add(new AnalysisError.forValues(
file.source,
error.offset,
error.length,
errorCode,
error.message,
- error.correction.isEmpty ? null : error.correction));
+ error.correction.isEmpty ? null : error.correction,
+ contextMessages: contextMessages));
}
}
return errors;
@@ -1814,14 +1828,26 @@
? indexUnit(resolvedUnit)
: new AnalysisDriverUnitIndexBuilder();
return new AnalysisDriverResolvedUnitBuilder(
- errors: errors
- .map((error) => new AnalysisDriverUnitErrorBuilder(
- offset: error.offset,
- length: error.length,
- uniqueName: error.errorCode.uniqueName,
- message: error.message,
- correction: error.correction))
- .toList(),
+ errors: errors.map((error) {
+ List<DiagnosticMessageBuilder> contextMessages;
+ if (error.contextMessages != null) {
+ contextMessages = <DiagnosticMessageBuilder>[];
+ for (var message in error.contextMessages) {
+ contextMessages.add(DiagnosticMessageBuilder(
+ filePath: message.filePath,
+ length: message.length,
+ message: message.message,
+ offset: message.offset));
+ }
+ }
+ return new AnalysisDriverUnitErrorBuilder(
+ offset: error.offset,
+ length: error.length,
+ uniqueName: error.errorCode.uniqueName,
+ message: error.message,
+ correction: error.correction,
+ contextMessages: contextMessages);
+ }).toList(),
index: index)
.toBuffer();
}
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 5c6d947..6ac4f35 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -887,6 +887,7 @@
class AnalysisDriverUnitErrorBuilder extends Object
with _AnalysisDriverUnitErrorMixin
implements idl.AnalysisDriverUnitError {
+ List<DiagnosticMessageBuilder> _contextMessages;
String _correction;
int _length;
String _message;
@@ -894,6 +895,15 @@
String _uniqueName;
@override
+ List<DiagnosticMessageBuilder> get contextMessages =>
+ _contextMessages ??= <DiagnosticMessageBuilder>[];
+
+ /// The context messages associated with the error.
+ set contextMessages(List<DiagnosticMessageBuilder> value) {
+ this._contextMessages = value;
+ }
+
+ @override
String get correction => _correction ??= '';
/// The optional correction hint for the error.
@@ -936,19 +946,23 @@
}
AnalysisDriverUnitErrorBuilder(
- {String correction,
+ {List<DiagnosticMessageBuilder> contextMessages,
+ String correction,
int length,
String message,
int offset,
String uniqueName})
- : _correction = correction,
+ : _contextMessages = contextMessages,
+ _correction = correction,
_length = length,
_message = message,
_offset = offset,
_uniqueName = uniqueName;
/// Flush [informative] data recursively.
- void flushInformative() {}
+ void flushInformative() {
+ _contextMessages?.forEach((b) => b.flushInformative());
+ }
/// Accumulate non-[informative] data into [signature].
void collectApiSignature(api_sig.ApiSignature signature) {
@@ -957,12 +971,25 @@
signature.addString(this._uniqueName ?? '');
signature.addString(this._message ?? '');
signature.addString(this._correction ?? '');
+ if (this._contextMessages == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._contextMessages.length);
+ for (var x in this._contextMessages) {
+ x?.collectApiSignature(signature);
+ }
+ }
}
fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_contextMessages;
fb.Offset offset_correction;
fb.Offset offset_message;
fb.Offset offset_uniqueName;
+ if (!(_contextMessages == null || _contextMessages.isEmpty)) {
+ offset_contextMessages = fbBuilder
+ .writeList(_contextMessages.map((b) => b.finish(fbBuilder)).toList());
+ }
if (_correction != null) {
offset_correction = fbBuilder.writeString(_correction);
}
@@ -973,6 +1000,9 @@
offset_uniqueName = fbBuilder.writeString(_uniqueName);
}
fbBuilder.startTable();
+ if (offset_contextMessages != null) {
+ fbBuilder.addOffset(5, offset_contextMessages);
+ }
if (offset_correction != null) {
fbBuilder.addOffset(4, offset_correction);
}
@@ -1009,6 +1039,7 @@
_AnalysisDriverUnitErrorImpl(this._bc, this._bcOffset);
+ List<idl.DiagnosticMessage> _contextMessages;
String _correction;
int _length;
String _message;
@@ -1016,6 +1047,14 @@
String _uniqueName;
@override
+ List<idl.DiagnosticMessage> get contextMessages {
+ _contextMessages ??= const fb.ListReader<idl.DiagnosticMessage>(
+ const _DiagnosticMessageReader())
+ .vTableGet(_bc, _bcOffset, 5, const <idl.DiagnosticMessage>[]);
+ return _contextMessages;
+ }
+
+ @override
String get correction {
_correction ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 4, '');
return _correction;
@@ -1051,6 +1090,9 @@
@override
Map<String, Object> toJson() {
Map<String, Object> _result = <String, Object>{};
+ if (contextMessages.isNotEmpty)
+ _result["contextMessages"] =
+ contextMessages.map((_value) => _value.toJson()).toList();
if (correction != '') _result["correction"] = correction;
if (length != 0) _result["length"] = length;
if (message != '') _result["message"] = message;
@@ -1061,6 +1103,7 @@
@override
Map<String, Object> toMap() => {
+ "contextMessages": contextMessages,
"correction": correction,
"length": length,
"message": message,
@@ -3526,6 +3569,162 @@
String toString() => convert.json.encode(toJson());
}
+class DiagnosticMessageBuilder extends Object
+ with _DiagnosticMessageMixin
+ implements idl.DiagnosticMessage {
+ String _filePath;
+ int _length;
+ String _message;
+ int _offset;
+
+ @override
+ String get filePath => _filePath ??= '';
+
+ /// The absolute and normalized path of the file associated with this message.
+ set filePath(String value) {
+ this._filePath = value;
+ }
+
+ @override
+ int get length => _length ??= 0;
+
+ /// The length of the source range associated with this message.
+ set length(int value) {
+ assert(value == null || value >= 0);
+ this._length = value;
+ }
+
+ @override
+ String get message => _message ??= '';
+
+ /// The text of the message.
+ set message(String value) {
+ this._message = value;
+ }
+
+ @override
+ int get offset => _offset ??= 0;
+
+ /// The zero-based offset from the start of the file to the beginning of the
+ /// source range associated with this message.
+ set offset(int value) {
+ assert(value == null || value >= 0);
+ this._offset = value;
+ }
+
+ DiagnosticMessageBuilder(
+ {String filePath, int length, String message, int offset})
+ : _filePath = filePath,
+ _length = length,
+ _message = message,
+ _offset = offset;
+
+ /// Flush [informative] data recursively.
+ void flushInformative() {}
+
+ /// Accumulate non-[informative] data into [signature].
+ void collectApiSignature(api_sig.ApiSignature signature) {
+ signature.addString(this._filePath ?? '');
+ signature.addInt(this._length ?? 0);
+ signature.addString(this._message ?? '');
+ signature.addInt(this._offset ?? 0);
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_filePath;
+ fb.Offset offset_message;
+ if (_filePath != null) {
+ offset_filePath = fbBuilder.writeString(_filePath);
+ }
+ if (_message != null) {
+ offset_message = fbBuilder.writeString(_message);
+ }
+ fbBuilder.startTable();
+ if (offset_filePath != null) {
+ fbBuilder.addOffset(0, offset_filePath);
+ }
+ if (_length != null && _length != 0) {
+ fbBuilder.addUint32(1, _length);
+ }
+ if (offset_message != null) {
+ fbBuilder.addOffset(2, offset_message);
+ }
+ if (_offset != null && _offset != 0) {
+ fbBuilder.addUint32(3, _offset);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+class _DiagnosticMessageReader extends fb.TableReader<_DiagnosticMessageImpl> {
+ const _DiagnosticMessageReader();
+
+ @override
+ _DiagnosticMessageImpl createObject(fb.BufferContext bc, int offset) =>
+ new _DiagnosticMessageImpl(bc, offset);
+}
+
+class _DiagnosticMessageImpl extends Object
+ with _DiagnosticMessageMixin
+ implements idl.DiagnosticMessage {
+ final fb.BufferContext _bc;
+ final int _bcOffset;
+
+ _DiagnosticMessageImpl(this._bc, this._bcOffset);
+
+ String _filePath;
+ int _length;
+ String _message;
+ int _offset;
+
+ @override
+ String get filePath {
+ _filePath ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+ return _filePath;
+ }
+
+ @override
+ int get length {
+ _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
+ return _length;
+ }
+
+ @override
+ String get message {
+ _message ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
+ return _message;
+ }
+
+ @override
+ int get offset {
+ _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
+ return _offset;
+ }
+}
+
+abstract class _DiagnosticMessageMixin implements idl.DiagnosticMessage {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ if (filePath != '') _result["filePath"] = filePath;
+ if (length != 0) _result["length"] = length;
+ if (message != '') _result["message"] = message;
+ if (offset != 0) _result["offset"] = offset;
+ return _result;
+ }
+
+ @override
+ Map<String, Object> toMap() => {
+ "filePath": filePath,
+ "length": length,
+ "message": message,
+ "offset": offset,
+ };
+
+ @override
+ String toString() => convert.json.encode(toJson());
+}
+
class DirectiveInfoBuilder extends Object
with _DirectiveInfoMixin
implements idl.DirectiveInfo {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index caaf7d3..e6aca08 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1455,6 +1455,9 @@
/// Information about an error in a resolved unit.
table AnalysisDriverUnitError {
+ /// The context messages associated with the error.
+ contextMessages:[DiagnosticMessage] (id: 5);
+
/// The optional correction hint for the error.
correction:string (id: 4);
@@ -1689,6 +1692,21 @@
offset:uint (id: 0);
}
+table DiagnosticMessage {
+ /// The absolute and normalized path of the file associated with this message.
+ filePath:string (id: 0);
+
+ /// The length of the source range associated with this message.
+ length:uint (id: 1);
+
+ /// The text of the message.
+ message:string (id: 2);
+
+ /// The zero-based offset from the start of the file to the beginning of the
+ /// source range associated with this message.
+ offset:uint (id: 3);
+}
+
/// Information about the Dartdoc directives in an [AvailableFile].
table DirectiveInfo {
/// The names of the defined templates.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 1034e2b..394c448 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -118,6 +118,10 @@
/// Information about an error in a resolved unit.
abstract class AnalysisDriverUnitError extends base.SummaryClass {
+ /// The context messages associated with the error.
+ @Id(5)
+ List<DiagnosticMessage> get contextMessages;
+
/// The optional correction hint for the error.
@Id(4)
String get correction;
@@ -444,6 +448,25 @@
int get offset;
}
+abstract class DiagnosticMessage extends base.SummaryClass {
+ /// The absolute and normalized path of the file associated with this message.
+ @Id(0)
+ String get filePath;
+
+ /// The length of the source range associated with this message.
+ @Id(1)
+ int get length;
+
+ /// The text of the message.
+ @Id(2)
+ String get message;
+
+ /// The zero-based offset from the start of the file to the beginning of the
+ /// source range associated with this message.
+ @Id(3)
+ int get offset;
+}
+
/// Information about the Dartdoc directives in an [AvailableFile].
abstract class DirectiveInfo extends base.SummaryClass {
/// The names of the defined templates.