Add test runner support for context messages without location information.
The CFE implementation of "why not promoted" functionality for
non-promotion of `this` doesn't associate the context message with any
location information, because there is no relevant location to cite.
For example, the output can look like this:
tests/language/why_not_promoted/this_error_test.dart:16:10: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
Try accessing using ?. instead.
this.isEven;
^^^^^^
Context: 'this' can't be promoted.
See http://dart.dev/go/non-promo-this
The test runner assumes that all messages have a location, so it
wasn't picking up on this context message at all. This CL avoids the
problem by having the test runner associate any location-less context
message with the error above it.
(Note that the analyzer doesn't have this problem; all of its context
messages have locations).
Change-Id: Ied52daa8b0090f28617e7d3784233aa44dcc897a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195301
Reviewed-by: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 5d8e490..779325c 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -1364,7 +1364,7 @@
/// The test runner only validates the first line of the message, and not the
/// suggested fixes.
static final _errorRegexp = RegExp(
- r"^([^:]+):(\d+):(\d+): (Context|Error|Warning): (.*)$",
+ r"^(?:([^:]+):(\d+):(\d+): )?(Context|Error|Warning): (.*)$",
multiLine: true);
FastaCommandOutput(
@@ -1398,11 +1398,27 @@
[List<StaticError> warnings]) {
StaticError previousError;
for (var match in regExp.allMatches(stdout)) {
- var line = int.parse(match.group(2));
- var column = int.parse(match.group(3));
+ var line = _parseNullableInt(match.group(2));
+ var column = _parseNullableInt(match.group(3));
var severity = match.group(4);
var message = match.group(5);
+ if (line == null) {
+ // No location information.
+ if (severity == 'Context' && previousError != null) {
+ // We can use the location information from the error message
+ line = previousError.line;
+ column = previousError.column;
+ } else {
+ // No good default location information, so disregard the error.
+ // TODO(45558): we should do something smarter here.
+ continue;
+ }
+ }
+ // Column information should have been present or it should have been
+ // filled in by the code above.
+ assert(column != null);
+
var error = StaticError(
severity == "Context" ? ErrorSource.context : errorSource, message,
line: line, column: column);
@@ -1426,6 +1442,15 @@
}
}
+ /// Same as `int.parse`, but allows nulls to simply pass through.
+ static int _parseNullableInt(String s) {
+ if (s == null) {
+ // ignore: avoid_returning_null
+ return null;
+ }
+ return int.parse(s);
+ }
+
/// Reported static errors, parsed from [stderr].
List<StaticError> get errors {
if (!_parsedErrors) {
diff --git a/tests/language/why_not_promoted/this_error_test.dart b/tests/language/why_not_promoted/this_error_test.dart
index 2d836ee..87d98c9 100644
--- a/tests/language/why_not_promoted/this_error_test.dart
+++ b/tests/language/why_not_promoted/this_error_test.dart
@@ -11,22 +11,22 @@
extension on int? {
extension_explicit_this() {
- // TODO(paulberry): get this to work with the CFE.
if (this == null) return;
this.isEven;
// ^^^^^^
-// [analyzer 2] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
-// [context 2] 'this' can't be promoted. See http://dart.dev/go/non-promo-this
-// [cfe] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
+// [analyzer 1] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
+// [context 1] 'this' can't be promoted. See http://dart.dev/go/non-promo-this
+// [cfe 3] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
+// [context 3] 'this' can't be promoted.
}
extension_implicit_this() {
- // TODO(paulberry): get this to work with the CFE.
if (this == null) return;
isEven;
// ^^^^^^
-// [analyzer 1] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
-// [context 1] 'this' can't be promoted. See http://dart.dev/go/non-promo-this
-// [cfe] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
+// [analyzer 2] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
+// [context 2] 'this' can't be promoted. See http://dart.dev/go/non-promo-this
+// [cfe 4] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
+// [context 4] 'this' can't be promoted.
}
}