CQ. Use more inline expected diagnostics.

Change-Id: I83743fee43718133df71dd33093056543dc83094
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/510482
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov
2026-06-10 10:57:43 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent e4ef831dfc
commit 8267ce6fff
3 changed files with 117 additions and 67 deletions
@@ -5,6 +5,7 @@
import 'dart:convert';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -19,6 +20,7 @@ import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/workspace/blaze.dart';
import 'package:analyzer_testing/resource_provider_mixin.dart';
import 'package:analyzer_testing/src/expected_diagnostics.dart';
import 'package:analyzer_utilities/testing/tree_string_sink.dart';
import 'package:crypto/crypto.dart';
import 'package:linter/src/rules.dart';
@@ -67,6 +69,24 @@ class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
newFile(testFile.path, content);
}
void addTestFileWithDiagnosticExpectations(String code) {
var cleanCode = removeDiagnosticExpectations(code);
addTestFile(cleanCode);
}
void assertDiagnosticsInCode(String code, List<Diagnostic> diagnostics) {
var cleanCode = removeDiagnosticExpectations(code);
var actual = updateExpectedDiagnostics(
content: cleanCode,
actualDiagnostics: diagnostics,
);
if (actual != code) {
NodeTextExpectationsCollector.add(actual);
printPrettyDiff(code, actual);
fail('See the difference above.');
}
}
void assertStateString(String expected) {
var buffer = StringBuffer();
printer.AnalyzerStatePrinter(
@@ -88,6 +108,11 @@ class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
}
}
Future<void> assertTestErrorsWithDiagnostics(String code) async {
var result = await fileResolver.getErrors2(path: testFile.path);
assertDiagnosticsInCode(code, result.diagnostics);
}
/// Create a new [FileResolver] into [fileResolver].
///
/// We do this the first time, and to test reusing results from [byteStore].
@@ -110,8 +135,11 @@ class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
);
}
Future<ErrorsResult> getTestErrors() {
return fileResolver.getErrors2(path: testFile.path);
Future<ErrorsResult> getErrorsWithDiagnostics(File file, String code) async {
modifyFile2(file, removeDiagnosticExpectations(code));
var result = await fileResolver.getErrors2(path: file.path);
assertDiagnosticsInCode(code, result.diagnostics);
return result;
}
@override
@@ -8,7 +8,6 @@ import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/micro/resolve_file.dart';
import 'package:analyzer/src/dart/micro/utils.dart';
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -1362,41 +1361,35 @@ void f(int? a) {
}
test_getErrors() async {
addTestFile(r'''
var result = await getErrorsWithDiagnostics(testFile, r'''
var a = b;
// ^
// [diag.undefinedIdentifier] Undefined name 'b'.
var foo = 0;
''');
var result = await getTestErrors();
expect(result.path, convertPath('/workspace/dart/test/lib/test.dart'));
expect(result.uri.toString(), 'package:dart.test/test.dart');
assertErrorsInList(result.diagnostics, [
error(diag.undefinedIdentifier, 8, 1),
]);
expect(result.lineInfo.lineStarts, [0, 11, 24]);
}
test_getErrors_docImports() async {
newFile('$testPackageLibPath/a.dart', '');
var b = newFile('$testPackageLibPath/b.dart', r'''
var b = getFile('$testPackageLibPath/b.dart');
await getErrorsWithDiagnostics(b, r'''
/// @docImport 'a.dart';
library;
''');
var errorsResult = await fileResolver.getErrors2(path: b.path);
assertErrorsInList(errorsResult.diagnostics, []);
}
test_getErrors_library() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
var a = getFile('$testPackageLibPath/a.dart');
await getErrorsWithDiagnostics(a, r'''
var a = 42
// ^^
// [diag.expectedToken] Expected to find ';'.
''');
var errorsResult = await fileResolver.getErrors2(path: a.path);
assertErrorsInList(errorsResult.diagnostics, [
error(diag.expectedToken, 8, 2),
]);
}
test_getErrors_part_hasLibrary() async {
@@ -1404,35 +1397,45 @@ var a = 42
part 'b.dart';
''');
var b = newFile('$testPackageLibPath/b.dart', r'''
var b = getFile('$testPackageLibPath/b.dart');
await getErrorsWithDiagnostics(b, r'''
part of 'a.dart';
var a = 42
// ^^
// [diag.expectedToken] Expected to find ';'.
''');
var errorsResult = await fileResolver.getErrors2(path: b.path);
assertErrorsInList(errorsResult.diagnostics, [
error(diag.expectedToken, 26, 2),
]);
}
test_getErrors_reuse() async {
addTestFile('var a = b;');
var unresolvedB = r'''
var a = b;
// ^
// [diag.undefinedIdentifier] Undefined name 'b'.
''';
var unresolvedC = r'''
var a = c;
// ^
// [diag.undefinedIdentifier] Undefined name 'c'.
''';
addTestFileWithDiagnosticExpectations(unresolvedB);
// No resolved files yet.
_assertResolvedFiles([]);
// No cached, will resolve once.
expect((await getTestErrors()).diagnostics, hasLength(1));
await assertTestErrorsWithDiagnostics(unresolvedB);
_assertResolvedFiles([testFile]);
// Has cached, will be not resolved again.
expect((await getTestErrors()).diagnostics, hasLength(1));
await assertTestErrorsWithDiagnostics(unresolvedB);
_assertResolvedFiles([]);
// Change the file, will be resolved again.
addTestFile('var a = c;');
addTestFileWithDiagnosticExpectations(unresolvedC);
fileResolver.changeFiles([testFile.path]);
expect((await getTestErrors()).diagnostics, hasLength(1));
await assertTestErrorsWithDiagnostics(unresolvedC);
_assertResolvedFiles([testFile]);
}
@@ -1441,20 +1444,31 @@ var a = 42
var a = 0;
''');
addTestFile(r'''
var testCodeWhenAIsInt = r'''
import 'a.dart';
var b = a.foo;
''');
// ^^^
// [diag.undefinedGetter] The getter 'foo' isn't defined for the type 'int'.
''';
var testCodeWhenAIsDouble = r'''
import 'a.dart';
var b = a.foo;
// ^^^
// [diag.undefinedGetter] The getter 'foo' isn't defined for the type 'double'.
''';
addTestFileWithDiagnosticExpectations(testCodeWhenAIsInt);
// No resolved files yet.
_assertResolvedFiles([]);
// No cached, will resolve once.
expect((await getTestErrors()).diagnostics, hasLength(1));
await assertTestErrorsWithDiagnostics(testCodeWhenAIsInt);
_assertResolvedFiles([testFile]);
// Has cached, will be not resolved again.
expect((await getTestErrors()).diagnostics, hasLength(1));
await assertTestErrorsWithDiagnostics(testCodeWhenAIsInt);
_assertResolvedFiles([]);
// Change the dependency.
@@ -1464,7 +1478,7 @@ var b = a.foo;
var a = 4.2;
''');
fileResolver.changeFiles([a.path]);
expect((await getTestErrors()).diagnostics, hasLength(1));
await assertTestErrorsWithDiagnostics(testCodeWhenAIsDouble);
_assertResolvedFiles([testFile]);
}
@@ -1789,12 +1803,15 @@ byteStore
1: [k00, k02, k03, k04, k05, k06, k07]
''');
var result = await getTestErrors();
var result = await fileResolver.getErrors2(path: testFile.path);
expect(result.path, testFile.path);
expect(result.uri.toString(), 'package:dart.test/test.dart');
assertErrorsInList(result.diagnostics, [
error(diag.undefinedIdentifier, 8, 1),
]);
assertDiagnosticsInCode(r'''
var a = b;
// ^
// [diag.undefinedIdentifier] Undefined name 'b'.
var foo = 0;
''', result.diagnostics);
expect(result.lineInfo.lineStarts, [0, 11, 24]);
// We created the library element for the test file, using the reader.
@@ -2,9 +2,6 @@
// 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:analyzer/src/diagnostic/diagnostic.dart' as diag;
import 'package:analyzer_testing/analysis_rule/analysis_rule.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/context_collection_resolution.dart';
@@ -224,7 +221,19 @@ const C = 5 + D;
test_CastError_intToDouble_constructor_importAnalyzedAfter() async {
// See dartbug.com/35993
var other = newFile('$testPackageLibPath/other.dart', '''
var other = getFile('$testPackageLibPath/other.dart');
await resolveFilesWithDiagnostics({
testFile: r'''
import 'other.dart';
void main() {
const foo = Foo(1);
const bar = Bar.some();
print("$foo, $bar");
}
''',
other: r'''
class Foo {
final double value;
@@ -237,23 +246,17 @@ class Bar {
const Bar(this.value);
const Bar.some() : this(const Foo(1));
}''');
await resolveTestCodeWithDiagnostics(r'''
import 'other.dart';
void main() {
const foo = Foo(1);
const bar = Bar.some();
print("$foo, $bar");
}
''');
var otherFileResult = await resolveFile(other);
expect(otherFileResult.diagnostics, isEmpty);
''',
});
}
test_CastError_intToDouble_constructor_importAnalyzedBefore() async {
// See dartbug.com/35993
var other = newFile('$testPackageLibPath/other.dart', '''
var other = getFile('$testPackageLibPath/other.dart');
await resolveFilesWithDiagnostics({
other: r'''
class Foo {
final double value;
@@ -266,8 +269,9 @@ class Bar {
const Bar(this.value);
const Bar.some() : this(const Foo(1));
}''');
await resolveTestCodeWithDiagnostics(r'''
}
''',
testFile: r'''
import 'other.dart';
void main() {
@@ -275,20 +279,24 @@ void main() {
const bar = Bar.some();
print("$foo, $bar");
}
''');
var otherFileResult = await resolveFile(other);
expect(otherFileResult.diagnostics, isEmpty);
''',
});
}
test_default_constructor_arg_empty_map_import() async {
var other = newFile('$testPackageLibPath/other.dart', '''
var other = getFile('$testPackageLibPath/other.dart');
await resolveFilesWithDiagnostics({
other: r'''
class C {
final Map<String, int> m;
const C({this.m = const <String, int>{}})
: assert(m != null);
// ^^^^^^^
// [diag.unnecessaryNullComparisonNeverNullTrue] The operand can't be 'null', so the condition is always 'true'.
}
''');
await resolveTestCodeWithDiagnostics(r'''
''',
testFile: r'''
import 'other.dart';
main() {
@@ -296,11 +304,8 @@ main() {
// ^
// [diag.unusedLocalVariable] The value of the local variable 'c' isn't used.
}
''');
var otherFileResult = await resolveFile(other);
assertErrorsInList(otherFileResult.diagnostics, [
error(diag.unnecessaryNullComparisonNeverNullTrue, 97, 7),
]);
''',
});
}
test_enum_constructor_initializer_asExpression() async {