analyzer_testing: split assertDiagnosticsIn into multiple, overridable methods
Work towards https://github.com/dart-lang/sdk/issues/61271 Change-Id: I3732176b84fb0ce79d2de180e8fb32d76ea4a08c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/444361 Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
committed by
Commit Queue
parent
ca74ec517a
commit
69e9fd545f
@@ -5,8 +5,10 @@ package:analyzer_testing/analysis_rule/analysis_rule.dart:
|
||||
analysisRule (getter: String)
|
||||
assertNoPubspecDiagnostics (method: Future<void> Function(String))
|
||||
assertPubspecDiagnostics (method: Future<void> Function(String, List<ExpectedDiagnostic>))
|
||||
correctionMessage (method: String Function(List<Diagnostic>))
|
||||
lint (method: ExpectedDiagnostic Function(int, int, {Pattern? correctionContains, Pattern? messageContains, String? name}))
|
||||
setUp (method: void Function())
|
||||
unexpectedMessage (method: String Function(List<Diagnostic>))
|
||||
package:analyzer_testing/experiments/experiments.dart:
|
||||
experimentsForTests (static getter: List<String>)
|
||||
experimentsForTests= (static setter: List<String>)
|
||||
@@ -78,6 +80,8 @@ dart:core:
|
||||
int (referenced)
|
||||
package:_fe_analyzer_shared/src/base/errors.dart:
|
||||
DiagnosticCode (referenced)
|
||||
package:analyzer/diagnostic/diagnostic.dart:
|
||||
Diagnostic (referenced)
|
||||
package:analyzer/file_system/file_system.dart:
|
||||
File (referenced)
|
||||
Folder (referenced)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// 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 'dart:convert' show json;
|
||||
|
||||
import 'package:analyzer/analysis_rule/pubspec.dart';
|
||||
import 'package:analyzer/diagnostic/diagnostic.dart';
|
||||
import 'package:analyzer/error/error.dart';
|
||||
@@ -46,6 +48,28 @@ abstract class AnalysisRuleTest extends PubPackageResolutionTest {
|
||||
assertDiagnosticsIn(errors, expectedDiagnostics);
|
||||
}
|
||||
|
||||
@override
|
||||
String correctionMessage(List<Diagnostic> diagnostics) {
|
||||
var buffer = StringBuffer();
|
||||
diagnostics.sort((first, second) => first.offset.compareTo(second.offset));
|
||||
buffer.writeln();
|
||||
buffer.writeln('To accept the current state, expect:');
|
||||
for (var actual in diagnostics) {
|
||||
if (actual.diagnosticCode is LintCode) {
|
||||
buffer.write(' lint(');
|
||||
} else {
|
||||
buffer.write(' error(${actual.diagnosticCode}, ');
|
||||
}
|
||||
buffer.write('${actual.offset}, ${actual.length}');
|
||||
if (actual.diagnosticCode.name != analysisRule) {
|
||||
buffer.write(", name: '${actual.diagnosticCode.name}'");
|
||||
}
|
||||
buffer.writeln('),');
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/// Returns an "expected diagnostic" for [analysisRule] (or [name], if given)
|
||||
/// at [offset] and [length].
|
||||
///
|
||||
@@ -79,6 +103,25 @@ abstract class AnalysisRuleTest extends PubPackageResolutionTest {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String unexpectedMessage(List<Diagnostic> unmatchedActual) {
|
||||
var buffer = StringBuffer();
|
||||
if (buffer.isNotEmpty) {
|
||||
buffer.writeln();
|
||||
}
|
||||
buffer.writeln('Found but did not expect:');
|
||||
for (var actual in unmatchedActual) {
|
||||
buffer.write(' $analysisRule.${actual.diagnosticCode.name} [');
|
||||
buffer.write('${actual.offset}, ${actual.length}, ${actual.message}');
|
||||
if (actual.correctionMessage case Pattern correctionMessage) {
|
||||
buffer.write(', ');
|
||||
buffer.write(json.encode(correctionMessage));
|
||||
}
|
||||
buffer.writeln(']');
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
Future<List<Diagnostic>> _analyzePubspecFile(String content) async {
|
||||
var path = convertPath(testPackagePubspecPath);
|
||||
var pubspecRules = <AbstractAnalysisRule, PubspecVisitor<Object?>>{};
|
||||
|
||||
@@ -212,9 +212,7 @@ class PubPackageResolutionTest with MockPackagesMixin, ResourceProviderMixin {
|
||||
List<Diagnostic> diagnostics,
|
||||
List<ExpectedDiagnostic> expectedDiagnostics,
|
||||
) {
|
||||
//
|
||||
// Match actual diagnostics to expected diagnostics.
|
||||
//
|
||||
var unmatchedActual = diagnostics.toList();
|
||||
var unmatchedExpected = expectedDiagnostics.toList();
|
||||
var actualIndex = 0;
|
||||
@@ -236,99 +234,33 @@ class PubPackageResolutionTest with MockPackagesMixin, ResourceProviderMixin {
|
||||
actualIndex++;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Write the results.
|
||||
//
|
||||
|
||||
// Print the results to the terminal.
|
||||
var buffer = StringBuffer();
|
||||
if (unmatchedExpected.isNotEmpty) {
|
||||
buffer.writeln('Expected but did not find:');
|
||||
for (var expected in unmatchedExpected) {
|
||||
buffer.write(' ');
|
||||
if (expected is ExpectedError) {
|
||||
buffer.write(expected._code);
|
||||
}
|
||||
if (expected is ExpectedLint) {
|
||||
buffer.write(expected._lintName);
|
||||
}
|
||||
buffer.write(' [');
|
||||
buffer.write(expected._offset);
|
||||
buffer.write(', ');
|
||||
buffer.write(expected._length);
|
||||
if (expected._messageContains != null) {
|
||||
buffer.write(', messageContains: ');
|
||||
buffer.write(json.encode(expected._messageContains.toString()));
|
||||
}
|
||||
if (expected._correctionContains != null) {
|
||||
buffer.write(', correctionContains: ');
|
||||
buffer.write(json.encode(expected._correctionContains.toString()));
|
||||
}
|
||||
buffer.writeln(']');
|
||||
}
|
||||
buffer.write(missingExpectedMessage(unmatchedExpected));
|
||||
}
|
||||
if (unmatchedActual.isNotEmpty) {
|
||||
if (buffer.isNotEmpty) {
|
||||
buffer.writeln();
|
||||
}
|
||||
buffer.writeln('Found but did not expect:');
|
||||
for (var actual in unmatchedActual) {
|
||||
buffer.write(' ');
|
||||
buffer.write(actual.diagnosticCode);
|
||||
buffer.write(' [');
|
||||
buffer.write(actual.offset);
|
||||
buffer.write(', ');
|
||||
buffer.write(actual.length);
|
||||
buffer.write(', ');
|
||||
buffer.write(actual.message);
|
||||
if (actual.correctionMessage != null) {
|
||||
buffer.write(', ');
|
||||
buffer.write(json.encode(actual.correctionMessage));
|
||||
}
|
||||
buffer.writeln(']');
|
||||
}
|
||||
buffer.write(unexpectedMessage(unmatchedActual));
|
||||
}
|
||||
if (buffer.isNotEmpty) {
|
||||
diagnostics.sort(
|
||||
(first, second) => first.offset.compareTo(second.offset),
|
||||
);
|
||||
buffer.writeln();
|
||||
buffer.writeln('To accept the current state, expect:');
|
||||
for (var actual in diagnostics) {
|
||||
late String diagnosticKind;
|
||||
Object? description;
|
||||
if (actual.diagnosticCode is LintCode) {
|
||||
diagnosticKind = 'lint';
|
||||
} else {
|
||||
diagnosticKind = 'error';
|
||||
description = actual.diagnosticCode;
|
||||
}
|
||||
buffer.write(' $diagnosticKind(');
|
||||
if (description != null) {
|
||||
buffer.write(description);
|
||||
buffer.write(', ');
|
||||
}
|
||||
buffer.write(actual.offset);
|
||||
buffer.write(', ');
|
||||
buffer.write(actual.length);
|
||||
buffer.writeln('),');
|
||||
}
|
||||
if (unmatchedExpected.isNotEmpty || unmatchedActual.isNotEmpty) {
|
||||
buffer.write(correctionMessage(diagnostics));
|
||||
|
||||
if (dumpAstOnFailures) {
|
||||
buffer.writeln();
|
||||
buffer.writeln();
|
||||
try {
|
||||
var astSink = StringBuffer();
|
||||
|
||||
try {
|
||||
Spelunker(
|
||||
result.unit.toSource(),
|
||||
sink: astSink,
|
||||
sink: buffer,
|
||||
featureSet: result.unit.featureSet,
|
||||
).spelunk();
|
||||
buffer.write(astSink);
|
||||
buffer.writeln();
|
||||
// I hereby choose to catch this type.
|
||||
} on ArgumentError catch (_) {
|
||||
// Perhaps we encountered a parsing error while spelunking.
|
||||
}
|
||||
|
||||
buffer.writeln();
|
||||
}
|
||||
|
||||
fail(buffer.toString());
|
||||
@@ -371,6 +303,54 @@ class PubPackageResolutionTest with MockPackagesMixin, ResourceProviderMixin {
|
||||
Future<void> assertNoDiagnosticsInFile(String path) async =>
|
||||
assertDiagnosticsInFile(path, const []);
|
||||
|
||||
/// Text to display upon failure, which indicates possible corrections.
|
||||
@visibleForOverriding
|
||||
String correctionMessage(List<Diagnostic> diagnostics) {
|
||||
var buffer = StringBuffer();
|
||||
diagnostics.sort((first, second) => first.offset.compareTo(second.offset));
|
||||
buffer.writeln();
|
||||
buffer.writeln('To accept the current state, expect:');
|
||||
for (var actual in diagnostics) {
|
||||
if (actual.diagnosticCode is LintCode) {
|
||||
buffer.write(' lint(');
|
||||
} else {
|
||||
buffer.write(' error(${actual.diagnosticCode}, ');
|
||||
}
|
||||
buffer.write('${actual.offset}, ${actual.length}),');
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/// Text to display upon failure, indicating that [unmatchedExpected]
|
||||
/// diagnostics were expected, but not found.
|
||||
@visibleForOverriding
|
||||
String missingExpectedMessage(List<ExpectedDiagnostic> unmatchedExpected) {
|
||||
var buffer = StringBuffer();
|
||||
buffer.writeln('Expected but did not find:');
|
||||
for (var expected in unmatchedExpected) {
|
||||
buffer.write(' ');
|
||||
if (expected is ExpectedError) {
|
||||
buffer.write(expected._code);
|
||||
}
|
||||
if (expected is ExpectedLint) {
|
||||
buffer.write(expected._lintName);
|
||||
}
|
||||
buffer.write(' [${expected._offset}, ');
|
||||
buffer.write(expected._length);
|
||||
if (expected._messageContains case Pattern messageContains) {
|
||||
buffer.write(', messageContains: ');
|
||||
buffer.write(json.encode(messageContains.toString()));
|
||||
}
|
||||
if (expected._correctionContains case Pattern correctionContains) {
|
||||
buffer.write(', correctionContains: ');
|
||||
buffer.write(json.encode(correctionContains.toString()));
|
||||
}
|
||||
buffer.writeln(']');
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
File newFile(String path, String content) {
|
||||
if (_analysisContextCollection != null && !path.endsWith('.dart')) {
|
||||
@@ -414,6 +394,27 @@ class PubPackageResolutionTest with MockPackagesMixin, ResourceProviderMixin {
|
||||
_analysisContextCollection = null;
|
||||
}
|
||||
|
||||
/// Text to display upon failure, indicating that [unmatchedActual]
|
||||
/// diagnostics were found, but unexpected.
|
||||
@visibleForOverriding
|
||||
String unexpectedMessage(List<Diagnostic> unmatchedActual) {
|
||||
var buffer = StringBuffer();
|
||||
if (buffer.isNotEmpty) {
|
||||
buffer.writeln();
|
||||
}
|
||||
buffer.writeln('Found but did not expect:');
|
||||
for (var actual in unmatchedActual) {
|
||||
buffer.write(' ${actual.diagnosticCode} [');
|
||||
buffer.write('${actual.offset}, ${actual.length}, ${actual.message}');
|
||||
if (actual.correctionMessage case Pattern correctionMessage) {
|
||||
buffer.write(', ');
|
||||
buffer.write(json.encode(correctionMessage));
|
||||
}
|
||||
buffer.writeln(']');
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
void writePackageConfig(String path, PackageConfigFileBuilder config) {
|
||||
newFile(path, config.toContent(pathContext: pathContext));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user