Display context messages in command-line analyzer output
Change-Id: I2b2f668ef738cf7801dbfdc77d070a8d8a473fe5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107303
Reviewed-by: Devon Carew <devoncarew@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 617bdf9..2d88a91 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -46,7 +46,7 @@
final Set<String> files = new Set<String>();
/// All [AnalysisErrorInfo]s in the analyzed library.
- final List<AnalysisErrorInfo> errorInfos = new List<AnalysisErrorInfo>();
+ final List<ErrorsResult> errorsResults = [];
/// If the file specified on the command line is part of a package, the name
/// of that package. Otherwise `null`. This allows us to analyze the file
@@ -108,8 +108,8 @@
/// Returns the maximal [ErrorSeverity] of the recorded errors.
ErrorSeverity computeMaxErrorSeverity() {
ErrorSeverity status = ErrorSeverity.NONE;
- for (AnalysisErrorInfo errorInfo in errorInfos) {
- for (AnalysisError error in errorInfo.errors) {
+ for (ErrorsResult result in errorsResults) {
+ for (AnalysisError error in result.errors) {
if (_defaultSeverityProcessor(error) == null) {
continue;
}
@@ -119,7 +119,7 @@
return status;
}
- /// Fills [errorInfos] using [files].
+ /// Fills [errorsResults] using [files].
Future<void> prepareErrors() async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
@@ -127,8 +127,7 @@
try {
for (String path in files) {
ErrorsResult errorsResult = await analysisDriver.getErrors(path);
- errorInfos.add(new AnalysisErrorInfoImpl(
- errorsResult.errors, errorsResult.lineInfo));
+ errorsResults.add(errorsResult);
}
} finally {
previous.makeCurrent();
@@ -145,7 +144,7 @@
/// Setup local fields such as the analysis context for analysis.
void setupForAnalysis() {
files.clear();
- errorInfos.clear();
+ errorsResults.clear();
Uri libraryUri = libraryFile.uri;
if (libraryUri.scheme == 'package' && libraryUri.pathSegments.length > 0) {
_selfPackageName = libraryUri.pathSegments[0];
@@ -170,7 +169,7 @@
// Print errors and performance numbers.
if (printMode == 1) {
- formatter.formatErrors(errorInfos);
+ formatter.formatErrors(errorsResults);
} else if (printMode == 2) {
_printColdPerf();
}
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index c50528d..dd86768 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -633,9 +633,7 @@
severityProcessor: severityProcessor);
for (Source source in explicitSources) {
var result = await analysisDriver.getErrors(source.fullName);
- var errorInfo =
- new AnalysisErrorInfoImpl(result.errors, result.lineInfo);
- formatter.formatErrors([errorInfo]);
+ formatter.formatErrors([result]);
}
formatter.flush();
if (!options.machineFormat) {
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index bd54543..9252730 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -23,8 +24,8 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart'
show PerformanceTag;
-import 'package:analyzer/src/plugin/resolver_provider.dart';
import 'package:analyzer/src/manifest/manifest_validator.dart';
+import 'package:analyzer/src/plugin/resolver_provider.dart';
import 'package:analyzer/src/pubspec/pubspec_validator.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/source/path_filter.dart';
@@ -350,7 +351,10 @@
LineInfo lineInfo = new LineInfo.fromContent(content);
List<AnalysisError> errors = analyzeAnalysisOptions(
file.createSource(), content, analysisDriver.sourceFactory);
- formatter.formatErrors([new AnalysisErrorInfoImpl(errors, lineInfo)]);
+ formatter.formatErrors([
+ ErrorsResultImpl(analysisDriver.currentSession, path, null,
+ lineInfo, false, errors)
+ ]);
for (AnalysisError error in errors) {
ErrorSeverity severity = determineProcessedSeverity(
error, options, analysisDriver.analysisOptions);
@@ -368,8 +372,10 @@
new PubspecValidator(resourceProvider, file.createSource());
LineInfo lineInfo = new LineInfo.fromContent(content);
List<AnalysisError> errors = validator.validate(node.nodes);
- formatter
- .formatErrors([new AnalysisErrorInfoImpl(errors, lineInfo)]);
+ formatter.formatErrors([
+ ErrorsResultImpl(analysisDriver.currentSession, path, null,
+ lineInfo, false, errors)
+ ]);
for (AnalysisError error in errors) {
ErrorSeverity severity = determineProcessedSeverity(
error, options, analysisDriver.analysisOptions);
@@ -388,8 +394,10 @@
LineInfo lineInfo = new LineInfo.fromContent(content);
List<AnalysisError> errors = validator.validate(
content, analysisDriver.analysisOptions.chromeOsManifestChecks);
- formatter
- .formatErrors([new AnalysisErrorInfoImpl(errors, lineInfo)]);
+ formatter.formatErrors([
+ ErrorsResultImpl(analysisDriver.currentSession, path, null,
+ lineInfo, false, errors)
+ ]);
for (AnalysisError error in errors) {
ErrorSeverity severity = determineProcessedSeverity(
error, options, analysisDriver.analysisOptions);
diff --git a/pkg/analyzer_cli/lib/src/error_formatter.dart b/pkg/analyzer_cli/lib/src/error_formatter.dart
index e6e61f4..51e1333 100644
--- a/pkg/analyzer_cli/lib/src/error_formatter.dart
+++ b/pkg/analyzer_cli/lib/src/error_formatter.dart
@@ -2,9 +2,10 @@
// 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/dart/analysis/results.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_cli/src/ansi.dart';
import 'package:analyzer_cli/src/options.dart';
@@ -109,6 +110,7 @@
final int line;
final int column;
final String message;
+ final List<ContextMessage> contextMessages;
final String errorCode;
final String correction;
final String url;
@@ -120,6 +122,7 @@
this.line,
this.column,
this.message,
+ this.contextMessages,
this.errorCode,
this.correction,
this.url,
@@ -161,6 +164,14 @@
}
}
+class ContextMessage {
+ final String filePath;
+ final String message;
+ final int line;
+ final int column;
+ ContextMessage(this.filePath, this.message, this.line, this.column);
+}
+
/// Helper for formatting [AnalysisError]s.
///
/// The two format options are a user consumable format and a machine consumable
@@ -181,19 +192,18 @@
void flush();
void formatError(
- Map<AnalysisError, LineInfo> errorToLine, AnalysisError error);
+ Map<AnalysisError, ErrorsResult> errorToLine, AnalysisError error);
- void formatErrors(List<AnalysisErrorInfo> errorInfos) {
- stats.unfilteredCount += errorInfos.length;
+ void formatErrors(List<ErrorsResult> results) {
+ stats.unfilteredCount += results.length;
List<AnalysisError> errors = new List<AnalysisError>();
- Map<AnalysisError, LineInfo> errorToLine =
- new Map<AnalysisError, LineInfo>();
- for (AnalysisErrorInfo errorInfo in errorInfos) {
- for (AnalysisError error in errorInfo.errors) {
+ Map<AnalysisError, ErrorsResult> errorToLine = {};
+ for (ErrorsResult result in results) {
+ for (AnalysisError error in result.errors) {
if (_computeSeverity(error) != null) {
errors.add(error);
- errorToLine[error] = errorInfo.lineInfo;
+ errorToLine[error] = result;
}
}
}
@@ -253,6 +263,11 @@
// If verbose, also print any associated correction and URL.
if (options.verbose) {
String padding = ' '.padLeft(error.severity.length + 2);
+ for (var message in error.contextMessages) {
+ out.write('$padding${message.message} ');
+ out.write('at ${message.filePath}');
+ out.writeln(':${message.line}:${message.column}');
+ }
if (error.correction != null) {
out.writeln('$padding${error.correction}');
}
@@ -267,9 +282,10 @@
}
void formatError(
- Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) {
+ Map<AnalysisError, ErrorsResult> errorToLine, AnalysisError error) {
Source source = error.source;
- var location = errorToLine[error].getLocation(error.offset);
+ var result = errorToLine[error];
+ var location = result.lineInfo.getLocation(error.offset);
ErrorSeverity severity = _severityProcessor(error);
@@ -300,6 +316,17 @@
} else {
sourcePath = _relative(source.fullName);
}
+ List<ContextMessage> contextMessages = [];
+ for (var message in error.contextMessages) {
+ var session = result.session.analysisContext;
+ if (session is DriverBasedAnalysisContext) {
+ LineInfo lineInfo =
+ session.driver.getFileSync(message.filePath)?.lineInfo;
+ var location = lineInfo.getLocation(message.offset);
+ contextMessages.add(ContextMessage(message.filePath, message.message,
+ location.lineNumber, location.columnNumber));
+ }
+ }
batchedErrors.add(new CLIError(
severity: errorType,
@@ -308,6 +335,7 @@
line: location.lineNumber,
column: location.columnNumber,
message: message,
+ contextMessages: contextMessages,
errorCode: error.errorCode.name.toLowerCase(),
correction: error.correction,
url: error.errorCode.url,
@@ -330,13 +358,13 @@
void flush() {}
void formatError(
- Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) {
+ Map<AnalysisError, ErrorsResult> errorToLine, AnalysisError error) {
// Ensure we don't over-report (#36062).
if (!_seenErrors.add(error)) {
return;
}
Source source = error.source;
- var location = errorToLine[error].getLocation(error.offset);
+ var location = errorToLine[error].lineInfo.getLocation(error.offset);
int length = error.length;
ErrorSeverity severity = _severityProcessor(error);
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart
index b5e5627..e65733c 100644
--- a/pkg/analyzer_cli/test/mocks.dart
+++ b/pkg/analyzer_cli/test/mocks.dart
@@ -31,7 +31,7 @@
MockAnalysisError(this.source, this.errorCode, this.offset, this.message);
@override
- List<DiagnosticMessage> get contextMessages => null;
+ List<DiagnosticMessage> get contextMessages => const [];
@override
String get correction => null;
diff --git a/pkg/analyzer_cli/test/reporter_test.dart b/pkg/analyzer_cli/test/reporter_test.dart
index 26d37ac..e7f359b 100644
--- a/pkg/analyzer_cli/test/reporter_test.dart
+++ b/pkg/analyzer_cli/test/reporter_test.dart
@@ -4,7 +4,7 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer_cli/src/ansi.dart' as ansi;
import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:test/test.dart' hide ErrorFormatter;
@@ -39,8 +39,8 @@
});
test('error', () {
- AnalysisErrorInfo error =
- mockError(ErrorType.SYNTACTIC_ERROR, ErrorSeverity.ERROR);
+ ErrorsResultImpl error =
+ mockResult(ErrorType.SYNTACTIC_ERROR, ErrorSeverity.ERROR);
reporter.formatErrors([error]);
reporter.flush();
@@ -49,7 +49,7 @@
});
test('hint', () {
- AnalysisErrorInfo error = mockError(ErrorType.HINT, ErrorSeverity.INFO);
+ ErrorsResultImpl error = mockResult(ErrorType.HINT, ErrorSeverity.INFO);
reporter.formatErrors([error]);
reporter.flush();
@@ -58,7 +58,7 @@
});
test('stats', () {
- AnalysisErrorInfo error = mockError(ErrorType.HINT, ErrorSeverity.INFO);
+ ErrorsResultImpl error = mockResult(ErrorType.HINT, ErrorSeverity.INFO);
reporter.formatErrors([error]);
reporter.flush();
stats.print(out);
@@ -70,7 +70,7 @@
});
}
-MockAnalysisErrorInfo mockError(ErrorType type, ErrorSeverity severity) {
+ErrorsResultImpl mockResult(ErrorType type, ErrorSeverity severity) {
// ErrorInfo
var location = new CharacterLocation(3, 3);
var lineInfo = new MockLineInfo(defaultLocation: location);
@@ -80,5 +80,6 @@
var source = new MockSource('/foo/bar/baz.dart');
var error = new MockAnalysisError(source, code, 20, 'MSG');
- return new MockAnalysisErrorInfo(lineInfo, [error]);
+ return ErrorsResultImpl(
+ null, source.fullName, null, lineInfo, false, [error]);
}