Add test_runner support for // [spec_parser] comments

This CL adds support to the test runner for the test outcome
expectation syntax that uses `// [...]` to indicate which diagnostic
we should expect with the given tool. Currently, `...` is `analyzer`
when testing the analyzer and `cfe` when testing the common front end.
After landing this CL, it also supports `// [spec_parser]`.

This change would allow us to migrate several tests from the multi-test
format (like `code; //# 01: compile-time error`) to the new format, in
particular tests with intentional syntax errors.

Change-Id: I5dd2560a873eb7433d3e07aa8f393e83c51b28e7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/501161
Reviewed-by: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Erik Ernst <eernst@google.com>
This commit is contained in:
Erik Ernst
2026-05-07 03:00:53 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent f78d831de7
commit 4d964c4804
2 changed files with 53 additions and 4 deletions
+48 -3
View File
@@ -812,7 +812,7 @@ class CompareAnalyzerCfeCommandOutput extends CommandOutput {
}
}
class SpecParseCommandOutput extends CommandOutput {
class SpecParseCommandOutput extends CommandOutput with _StaticErrorOutput {
SpecParseCommandOutput(
Command command,
int exitCode,
@@ -840,10 +840,54 @@ class SpecParseCommandOutput extends CommandOutput {
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
if (truncatedOutput) return Expectation.truncatedOutput;
if (hasSyntaxError) return Expectation.syntaxError;
if (exitCode != 0) return Expectation.syntaxError;
if (testCase.testFile.isStaticErrorTest) {
return _validateExpectedErrors(testCase);
}
if (hasSyntaxError || exitCode != 0) return Expectation.syntaxError;
return Expectation.pass;
}
/// Parses the ANTLR parser's diagnostic output.
///
/// For example: `void main() {(}` in 'foo.dart' yields
/// Syntax error in foo.dart:
/// line 1:14 no viable alternative at input '(}'
/// Parsing failed
///
/// The 'Syntax error' line is emitted once for each file with
/// a syntax error, and each error gets a 'line ...' message.
@override
void _parseErrors() {
var output = decodeUtf8(stderr);
var lines = output.split('\n');
String? currentPath;
var processCommand = command as ProcessCommand;
var fallbackPath = processCommand.arguments.firstWhere(
(arg) => arg.endsWith('.dart'),
orElse: () => '',
);
for (var line in lines) {
if (_pathRegExp.firstMatch(line) case var match?) {
currentPath = match[1];
} else if (_errorRegExp.firstMatch(line) case var match?) {
var lineNum = int.parse(match[1]!);
var column = int.parse(match[2]!) + 1; // ANTLR is 0-based.
var message = match[3]!;
addError(
StaticError(
ErrorSource.specParser,
message,
path: currentPath ?? fallbackPath,
line: lineNum,
column: column,
),
);
}
}
}
static final RegExp _pathRegExp = .new(r"^Syntax error in (.*):$");
static final RegExp _errorRegExp = .new(r"^line (\d+):(\d+) (.*)$");
}
class VMCommandOutput extends CommandOutput with _UnittestSuiteMessagesMixin {
@@ -1537,6 +1581,7 @@ mixin _StaticErrorOutput on CommandOutput {
Compiler.dart2wasm: ErrorSource.web,
Compiler.ddc: ErrorSource.web,
Compiler.fasta: ErrorSource.cfe,
Compiler.specParser: ErrorSource.specParser,
}[testCase.configuration.compiler]!;
var expected = testCase.testFile.expectedErrors.where(
+5 -1
View File
@@ -12,6 +12,7 @@ import 'test_file.dart';
class ErrorSource {
static const analyzer = ErrorSource._("analyzer");
static const cfe = ErrorSource._("CFE", marker: "cfe");
static const specParser = ErrorSource._("spec_parser");
static const web = ErrorSource._("web");
/// Pseudo-front end for context messages.
@@ -21,7 +22,7 @@ class ErrorSource {
///
/// The order is significant here. In static error tests, error expectations
/// must be in this order for consistency.
static const all = [analyzer, cfe, web];
static const all = [analyzer, cfe, specParser, web];
/// Gets the source whose lowercase name is [name] or `null` if no source
/// with that name could be found.
@@ -453,6 +454,9 @@ class StaticError implements Comparable<StaticError> {
// TODO(rnystrom): If the web compilers report warnings, encode that in
// the message somehow and then look for it here.
return false;
case ErrorSource.specParser:
// The spec parser does not report warnings.
return false;
default:
break;
}