linter: Use Diagnostic instead of deprecated AnalysisError

Work towards https://github.com/dart-lang/sdk/issues/60635

Change-Id: I225bcbe2c0033872b0349258f7f2135aab6a8d20
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426561
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Sam Rawlins
2025-05-05 15:44:14 -07:00
committed by Commit Queue
parent 81a7f3e131
commit 8aa021f31e
8 changed files with 71 additions and 67 deletions
@@ -2,18 +2,18 @@
// 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/error/error.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/source/line_info.dart';
/// The analysis errors and line info associated with a source.
class AnalysisErrorInfo {
/// The analysis diagnostics and line info associated with a source.
class DiagnosticInfo {
/// The analysis errors associated with a source, or `null` if there are no
/// errors.
final List<AnalysisError> errors;
final List<Diagnostic> diagnostics;
/// The line information associated with the errors, or `null` if there are no
/// errors.
final LineInfo lineInfo;
AnalysisErrorInfo(this.errors, this.lineInfo);
DiagnosticInfo(this.diagnostics, this.lineInfo);
}
@@ -28,7 +28,7 @@ class LintDriver {
LintDriver(this._options, this._resourceProvider);
Future<List<AnalysisErrorInfo>> analyze(Iterable<io.File> files) async {
Future<List<DiagnosticInfo>> analyze(Iterable<io.File> files) async {
AnalysisEngine.instance.instrumentationService = _StdInstrumentation();
var filesPaths =
@@ -50,14 +50,12 @@ class LintDriver {
_filesAnalyzed.addAll(filesPaths);
var result = <AnalysisErrorInfo>[];
var result = <DiagnosticInfo>[];
for (var path in _filesAnalyzed) {
var analysisSession = contextCollection.contextFor(path).currentSession;
var errorsResult = await analysisSession.getErrors(path);
if (errorsResult is ErrorsResult) {
result.add(
AnalysisErrorInfo(errorsResult.errors, errorsResult.lineInfo),
);
result.add(DiagnosticInfo(errorsResult.errors, errorsResult.lineInfo));
}
}
return result;
@@ -4,7 +4,7 @@
import 'dart:io';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart' as file_system;
import 'package:analyzer/file_system/physical_file_system.dart' as file_system;
@@ -29,7 +29,7 @@ Source _createSource(Uri uri) {
/// Dart source linter, only for package:linter's tools and tests.
class TestLinter implements AnalysisErrorListener {
final errors = <AnalysisError>[];
final errors = <Diagnostic>[];
final LinterOptions options;
final file_system.ResourceProvider _resourceProvider;
@@ -38,8 +38,8 @@ class TestLinter implements AnalysisErrorListener {
: _resourceProvider =
resourceProvider ?? file_system.PhysicalResourceProvider.INSTANCE;
Future<List<AnalysisErrorInfo>> lintFiles(List<File> files) async {
var errors = <AnalysisErrorInfo>[];
Future<List<DiagnosticInfo>> lintFiles(List<File> files) async {
var errors = <DiagnosticInfo>[];
var lintDriver = LintDriver(options, _resourceProvider);
errors.addAll(await lintDriver.analyze(files.where(isDartFile)));
for (var file in files.where(isPubspecFile)) {
@@ -76,5 +76,5 @@ class TestLinter implements AnalysisErrorListener {
}
@override
void onError(AnalysisError error) => errors.add(error);
void onError(Diagnostic error) => errors.add(error);
}
+4 -4
View File
@@ -2,7 +2,7 @@
// 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/error/error.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:linter/src/analyzer.dart';
import 'package:linter/src/test_utilities/analysis_error_info.dart';
import 'package:test/test.dart';
@@ -24,7 +24,7 @@ void defineTests() {
});
group('reporter', () {
late AnalysisErrorInfo info;
late DiagnosticInfo info;
late StringBuffer out;
late String sourcePath;
late ReportFormatter reporter;
@@ -46,14 +46,14 @@ var z = 33;
sourcePath = '${d.sandbox}/project/foo.dart';
var source = MockSource(sourcePath);
var error = AnalysisError.tmp(
var error = Diagnostic.tmp(
source: source,
offset: 10,
length: 3,
errorCode: code,
);
info = AnalysisErrorInfo([error], lineInfo);
info = DiagnosticInfo([error], lineInfo);
out = StringBuffer();
reporter = ReportFormatter([info], out)..write();
});
+22 -18
View File
@@ -5,6 +5,7 @@
import 'dart:convert' show json;
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
@@ -41,7 +42,7 @@ ExpectedDiagnostic error(
Pattern? messageContains,
}) => _ExpectedError(code, offset, length, messageContains: messageContains);
typedef DiagnosticMatcher = bool Function(AnalysisError error);
typedef DiagnosticMatcher = bool Function(Diagnostic diagnostic);
/// A description of a diagnostic that is expected to be reported.
class ExpectedDiagnostic {
@@ -70,16 +71,17 @@ class ExpectedDiagnostic {
}) : _messageContains = messageContains,
_correctionContains = correctionContains;
/// Whether the [error] matches this description of what it's expected to be.
bool matches(AnalysisError error) {
if (!_diagnosticMatcher(error)) return false;
if (error.offset != _offset) return false;
if (error.length != _length) return false;
if (_messageContains != null && !error.message.contains(_messageContains)) {
/// Whether the [diagnostic] matches this description of what it's expected to be.
bool matches(Diagnostic diagnostic) {
if (!_diagnosticMatcher(diagnostic)) return false;
if (diagnostic.offset != _offset) return false;
if (diagnostic.length != _length) return false;
if (_messageContains != null &&
!diagnostic.message.contains(_messageContains)) {
return false;
}
if (_correctionContains != null) {
var correctionMessage = error.correctionMessage;
var correctionMessage = diagnostic.correctionMessage;
if (correctionMessage == null ||
!correctionMessage.contains(_correctionContains)) {
return false;
@@ -202,7 +204,7 @@ class PubPackageResolutionTest extends _ContextResolutionTest {
) async {
addTestFile(content);
await resolveTestFile();
await _assertDiagnosticsIn(_errors, expectedDiagnostics);
await _assertDiagnosticsIn(_diagnostics, expectedDiagnostics);
}
/// Asserts that the number of diagnostics that have been gathered at [path]
@@ -215,7 +217,7 @@ class PubPackageResolutionTest extends _ContextResolutionTest {
List<ExpectedDiagnostic> expectedDiagnostics,
) async {
await _resolveFile(path);
await _assertDiagnosticsIn(_errors, expectedDiagnostics);
await _assertDiagnosticsIn(_diagnostics, expectedDiagnostics);
}
/// Asserts that the diagnostics for each `path` match those in the paired
@@ -334,15 +336,15 @@ class PubPackageResolutionTest extends _ContextResolutionTest {
writePackageConfig(path, configCopy);
}
/// Asserts that the diagnostics in [errors] match [expectedDiagnostics].
/// Asserts that the diagnostics in [diagnostics] match [expectedDiagnostics].
Future<void> _assertDiagnosticsIn(
List<AnalysisError> errors,
List<Diagnostic> diagnostics,
List<ExpectedDiagnostic> expectedDiagnostics,
) async {
//
// Match actual diagnostics to expected diagnostics.
//
var unmatchedActual = errors.toList();
var unmatchedActual = diagnostics.toList();
var unmatchedExpected = expectedDiagnostics.toList();
var actualIndex = 0;
while (actualIndex < unmatchedActual.length) {
@@ -414,10 +416,12 @@ class PubPackageResolutionTest extends _ContextResolutionTest {
}
}
if (buffer.isNotEmpty) {
errors.sort((first, second) => first.offset.compareTo(second.offset));
diagnostics.sort(
(first, second) => first.offset.compareTo(second.offset),
);
buffer.writeln();
buffer.writeln('To accept the current state, expect:');
for (var actual in errors) {
for (var actual in diagnostics) {
late String diagnosticKind;
Object? description;
if (actual.errorCode is LintCode) {
@@ -461,7 +465,7 @@ class PubPackageResolutionTest extends _ContextResolutionTest {
}
}
Future<List<AnalysisError>> _resolvePubspecFile(String content) async {
Future<List<Diagnostic>> _resolvePubspecFile(String content) async {
var path = convertPath(testPackagePubspecPath);
var pubspecRules = <LintRule, PubspecVisitor<Object?>>{};
for (var rule in Registry.ruleRegistry.where(
@@ -530,8 +534,8 @@ abstract class _ContextResolutionTest
List<String> get _collectionIncludedPaths;
/// The analysis errors that were computed during analysis.
List<AnalysisError> get _errors =>
/// The diagnostics that were computed during analysis.
List<Diagnostic> get _diagnostics =>
result.errors
.whereNot((e) => ignoredErrorCodes.any((c) => e.errorCode == c))
.toList();
+2 -2
View File
@@ -214,8 +214,8 @@ Future<void> writeBenchmarks(
out.writeTimings(stats, 0);
}
int _maxSeverity(List<AnalysisErrorInfo> infos) {
var filteredErrors = infos.expand((i) => i.errors);
int _maxSeverity(List<DiagnosticInfo> infos) {
var filteredErrors = infos.expand((i) => i.diagnostics);
return filteredErrors.fold(
0,
(value, e) => math.max(value, e.errorCode.errorSeverity.ordinal),
+8 -8
View File
@@ -6,7 +6,7 @@ import 'dart:io' as io;
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_options.dart';
@@ -32,7 +32,7 @@ Future<void> main() async {
var customChecks = [VisitRegisteredNodes(), NoSoloTests(), NoTrailingSpaces()];
Future<List<AnalysisError>> runChecks() async {
Future<List<Diagnostic>> runChecks() async {
var rules = path.normalize(
io.File(path.join('lib', 'src', 'rules')).absolute.path,
);
@@ -49,7 +49,7 @@ class Driver {
Driver(this.lints, {this.silent = true});
Future<List<AnalysisError>> analyze(List<String> sources) async {
Future<List<Diagnostic>> analyze(List<String> sources) async {
if (sources.isEmpty) {
_print('Specify one or more files and directories.');
return [];
@@ -60,7 +60,7 @@ class Driver {
return failedChecks;
}
Future<List<AnalysisError>> _analyzeFiles(
Future<List<Diagnostic>> _analyzeFiles(
ResourceProvider resourceProvider,
List<String> analysisRoots,
) async {
@@ -70,7 +70,7 @@ class Driver {
lints.forEach(Registry.ruleRegistry.registerLintRule);
// Track failures.
var failedChecks = <AnalysisError>{};
var failedChecks = <Diagnostic>{};
for (var root in analysisRoots) {
var collection = AnalysisContextCollection(
@@ -78,7 +78,7 @@ class Driver {
resourceProvider: resourceProvider,
);
var errors = <AnalysisErrorInfo>[];
var errors = <DiagnosticInfo>[];
for (var context in collection.contexts) {
// Add lints.
@@ -100,7 +100,7 @@ class Driver {
.where((e) => e.errorCode.name != 'TODO')
.toList();
if (filtered.isNotEmpty) {
errors.add(AnalysisErrorInfo(filtered, result.lineInfo));
errors.add(DiagnosticInfo(filtered, result.lineInfo));
}
}
} on Exception catch (e) {
@@ -113,7 +113,7 @@ class Driver {
ReportFormatter(errors, silent ? MockIOSink() : io.stdout).write();
for (var info in errors) {
failedChecks.addAll(info.errors);
failedChecks.addAll(info.diagnostics);
}
}
+22 -20
View File
@@ -5,15 +5,15 @@
import 'dart:io';
import 'dart:math';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:linter/src/test_utilities/analysis_error_info.dart';
String pluralize(String word, int count) =>
"$count ${count == 1 ? word : '${word}s'}";
String _getLineContents(int lineNumber, AnalysisError error) {
var path = error.source.fullName;
String _getLineContents(int lineNumber, Diagnostic diagnostic) {
var path = diagnostic.source.fullName;
var file = File(path);
String failureDetails;
if (!file.existsSync()) {
@@ -32,31 +32,31 @@ String _getLineContents(int lineNumber, AnalysisError error) {
class ReportFormatter {
final StringSink out;
final Iterable<AnalysisErrorInfo> errors;
final Iterable<DiagnosticInfo> errors;
int errorCount = 0;
ReportFormatter(this.errors, this.out);
/// Override to influence error sorting.
int compare(AnalysisError error1, AnalysisError error2) {
/// Override to influence diagnostic sorting.
int compare(Diagnostic diagnostic1, Diagnostic diagnostic2) {
// Severity.
var compare = error2.errorCode.errorSeverity.compareTo(
error1.errorCode.errorSeverity,
var compare = diagnostic2.errorCode.errorSeverity.compareTo(
diagnostic1.errorCode.errorSeverity,
);
if (compare != 0) {
return compare;
}
// Path.
compare = Comparable.compare(
error1.source.fullName.toLowerCase(),
error2.source.fullName.toLowerCase(),
diagnostic1.source.fullName.toLowerCase(),
diagnostic2.source.fullName.toLowerCase(),
);
if (compare != 0) {
return compare;
}
// Offset.
return error1.offset - error2.offset;
return diagnostic1.offset - diagnostic2.offset;
}
void write() {
@@ -66,38 +66,40 @@ class ReportFormatter {
}
void writeLint(
AnalysisError error, {
Diagnostic diagnostic, {
required int offset,
required int line,
required int column,
}) {
// test/engine_test.dart 452:9 [lint] DO name types using UpperCamelCase.
out
..write('${error.source.fullName} ')
..write('${diagnostic.source.fullName} ')
..write('$line:$column ')
..writeln('[${error.errorCode.type.displayName}] ${error.message}');
var contents = _getLineContents(line, error);
..writeln(
'[${diagnostic.errorCode.type.displayName}] ${diagnostic.message}',
);
var contents = _getLineContents(line, diagnostic);
out.writeln(contents);
var spaces = column - 1;
var arrows = max(1, min(error.length, contents.length - spaces));
var arrows = max(1, min(diagnostic.length, contents.length - spaces));
var result = '${" " * spaces}${"^" * arrows}';
out.writeln(result);
}
void _writeLint(AnalysisError error, LineInfo lineInfo) {
var offset = error.offset;
void _writeLint(Diagnostic diagnostic, LineInfo lineInfo) {
var offset = diagnostic.offset;
var location = lineInfo.getLocation(offset);
var line = location.lineNumber;
var column = location.columnNumber;
writeLint(error, offset: offset, column: column, line: line);
writeLint(diagnostic, offset: offset, column: column, line: line);
}
void _writeLints() {
for (var info in errors) {
for (var e in (info.errors.toList()..sort(compare))) {
for (var e in (info.diagnostics.toList()..sort(compare))) {
++errorCount;
_writeLint(e, info.lineInfo);
}