Skip to content

Commit c001d51

Browse files
DanTupCommit Queue
authored and
Commit Queue
committed
[analyzer] Prioritize errors in analysis_options/pubspec errors when running "dart analyze"
This changes the (non-machine/json) output of "dart analyze" when there are errors in pubspec.yaml/analysis_options. Before: ``` Analyzing myapp... error • analysis_options.yaml:3:1 • Expected ':'. Parse errors in analysis_options.yaml may result in other incorrect diagnostics. • parse_error error • lib\main.dart:1:16 • A value of type 'Null' can't be returned from the function 'foo' because it has a return type of 'int'. • return_of_invalid_type 2 issues found. ``` After: ``` Analyzing myapp... Errors were found in pubspec.yaml or analysis_options.yaml which may result in other incorrect errors. error • analysis_options.yaml:3:1 • Expected ':'. Parse errors in analysis_options.yaml may result in other incorrect diagnostics. • parse_error Errors in other files that might be caused by those above. error • lib\main.dart:1:16 • A value of type 'Null' can't be returned from the function 'foo' because it has a return type of 'int'. • return_of_invalid_type 2 issues found. ``` Fixes #55987 Change-Id: I25ae7b200463f2cd3f2046ea9f5f8ddc5c62cc60 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/372080 Reviewed-by: Sam Rawlins <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 0c9067c commit c001d51

File tree

3 files changed

+135
-28
lines changed

3 files changed

+135
-28
lines changed

pkg/dartdev/lib/src/commands/analyze.dart

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ class AnalyzeCommand extends DartdevCommand {
119119
}
120120
}
121121

122+
/// Errors in analysis_options and pubspec.yaml will be reported first
123+
/// and a note that they might be the cause of other errors.
124+
final List<AnalysisError> priorityErrors = <AnalysisError>[];
122125
final List<AnalysisError> errors = <AnalysisError>[];
123126

124127
final machineFormat = args.option('format') == 'machine';
@@ -180,10 +183,19 @@ class AnalyzeCommand extends DartdevCommand {
180183
);
181184

182185
server.onErrors.listen((FileAnalysisErrors fileErrors) {
186+
var isPriorityFile = const {'analysis_options.yaml', 'pubspec.yaml'}
187+
.contains(path.basename(fileErrors.file));
188+
183189
// Record the issues found (but filter out to do comments unless they've
184190
// been upgraded from INFO).
185-
errors.addAll(fileErrors.errors.where((AnalysisError error) =>
186-
error.type != 'TODO' || error.severity != 'INFO'));
191+
for (var error in fileErrors.errors.where((AnalysisError error) =>
192+
error.type != 'TODO' || error.severity != 'INFO')) {
193+
if (isPriorityFile && error.severity == 'ERROR') {
194+
priorityErrors.add(error);
195+
} else {
196+
errors.add(error);
197+
}
198+
}
187199
});
188200

189201
int pid = await server.start();
@@ -215,9 +227,9 @@ class AnalyzeCommand extends DartdevCommand {
215227

216228
progress?.finish(showTiming: true);
217229

218-
if (errors.isEmpty) {
230+
if (priorityErrors.isEmpty && errors.isEmpty) {
219231
if (jsonFormat) {
220-
emitJsonFormat(log, errors, usageInfo);
232+
emitJsonFormat(log, [], usageInfo);
221233
} else if (!machineFormat && !server.serverErrorReceived) {
222234
log.stdout('No issues found!');
223235
}
@@ -226,6 +238,7 @@ class AnalyzeCommand extends DartdevCommand {
226238
: _Result.success.exitCode;
227239
}
228240

241+
priorityErrors.sort();
229242
errors.sort();
230243

231244
if (machineFormat) {
@@ -235,21 +248,43 @@ class AnalyzeCommand extends DartdevCommand {
235248
} else {
236249
var relativeTo = targets.length == 1 ? targets.single : null;
237250

238-
emitDefaultFormat(
239-
log,
240-
errors,
241-
relativeToDir: relativeTo is io.File
242-
? relativeTo.parent
243-
: relativeTo as io.Directory?,
244-
verbose: verbose,
245-
);
251+
/// Helper to emit a set of errors.
252+
void emit(List<AnalysisError> errors) {
253+
emitDefaultFormat(
254+
log,
255+
errors,
256+
relativeToDir: relativeTo is io.File
257+
? relativeTo.parent
258+
: relativeTo as io.Directory?,
259+
verbose: verbose,
260+
);
261+
}
262+
263+
if (priorityErrors.isNotEmpty) {
264+
log.stdout('');
265+
log.stdout("Errors were found in 'pubspec.yaml' and/or "
266+
"'analysis_options.yaml' which might result in either invalid "
267+
'diagnostics being produced or valid diagnostics being missed.');
268+
269+
emit(priorityErrors);
270+
if (errors.isNotEmpty) {
271+
log.stdout('Errors in remaining files.');
272+
}
273+
}
274+
275+
if (errors.isNotEmpty) {
276+
emit(errors);
277+
}
278+
279+
final errorCount = priorityErrors.length + errors.length;
280+
log.stdout('$errorCount ${pluralize('issue', errorCount)} found.');
246281
}
247282

248283
bool hasErrors = false;
249284
bool hasWarnings = false;
250285
bool hasInfos = false;
251286

252-
for (final AnalysisError error in errors) {
287+
for (final AnalysisError error in priorityErrors.followedBy(errors)) {
253288
hasErrors |= error.isError;
254289
hasWarnings |= error.isWarning;
255290
hasInfos |= error.isInfo;
@@ -344,9 +379,6 @@ class AnalyzeCommand extends DartdevCommand {
344379
}
345380

346381
log.stdout('');
347-
348-
final errorCount = errors.length;
349-
log.stdout('$errorCount ${pluralize('issue', errorCount)} found.');
350382
}
351383

352384
@visibleForTesting

pkg/dartdev/test/commands/analyze_test.dart

Lines changed: 85 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -578,18 +578,91 @@ void f() {
578578
'hasFix': false
579579
};
580580

581-
test('default', () {
582-
final logger = TestLogger(false);
583-
final errors = [AnalysisError(sampleInfoJson)];
584-
585-
AnalyzeCommand.emitDefaultFormat(logger, errors);
586-
587-
expect(logger.stderrBuffer, isEmpty);
588-
final stdout = logger.stdoutBuffer.toString().trim();
589-
expect(stdout, contains('info'));
590-
expect(stdout, contains('lib${path.separator}test.dart:15:4'));
591-
expect(stdout, contains('Foo bar baz.'));
592-
expect(stdout, contains('dead_code'));
581+
group('default', () {
582+
test('emits correct format', () {
583+
final logger = TestLogger(false);
584+
final errors = [AnalysisError(sampleInfoJson)];
585+
586+
AnalyzeCommand.emitDefaultFormat(logger, errors);
587+
588+
expect(logger.stderrBuffer, isEmpty);
589+
final stdout = logger.stdoutBuffer.toString().trim();
590+
expect(stdout, contains('info'));
591+
expect(stdout, contains('lib${path.separator}test.dart:15:4'));
592+
expect(stdout, contains('Foo bar baz.'));
593+
expect(stdout, contains('dead_code'));
594+
});
595+
596+
test('prioritizes errors in analysis_options.yaml (with other errors)',
597+
() async {
598+
p = project(
599+
mainSrc: 'int get foo => null;\n',
600+
analysisOptions: 'include: package:lints/recommended.yaml\nf');
601+
var result = await p.runAnalyze([]);
602+
603+
expect(result.exitCode, 3);
604+
expect(result.stderr, isEmpty);
605+
606+
final stdout = result.stdout;
607+
final expectedOutput = '''
608+
Analyzing myapp...
609+
610+
Errors were found in 'pubspec.yaml' and/or 'analysis_options.yaml' which might result in either invalid diagnostics being produced or valid diagnostics being missed.
611+
612+
error - analysis_options.yaml:2:1 - Could not find expected ':' for simple key. - parse_error
613+
614+
Errors in remaining files.
615+
616+
error - lib${path.separator}main.dart:1:16 - A value of type 'Null' can't be returned from the function 'foo' because it has a return type of 'int'. - return_of_invalid_type
617+
618+
2 issues found.
619+
''';
620+
expect(stdout.trim(), expectedOutput.trim());
621+
});
622+
623+
test('prioritizes errors in analysis_options.yaml (without other errors)',
624+
() async {
625+
p = project(
626+
mainSrc: 'int get foo => 1;\n',
627+
analysisOptions: 'include: package:lints/recommended.yaml\nf');
628+
var result = await p.runAnalyze([]);
629+
630+
expect(result.exitCode, 3);
631+
expect(result.stderr, isEmpty);
632+
633+
final stdout = result.stdout;
634+
final expectedOutput = '''
635+
Analyzing myapp...
636+
637+
Errors were found in 'pubspec.yaml' and/or 'analysis_options.yaml' which might result in either invalid diagnostics being produced or valid diagnostics being missed.
638+
639+
error - analysis_options.yaml:2:1 - Could not find expected ':' for simple key. - parse_error
640+
641+
1 issue found.
642+
''';
643+
expect(stdout.trim(), expectedOutput.trim());
644+
});
645+
646+
test('does not prioritize warnings in analysis_options.yaml', () async {
647+
p = project(
648+
mainSrc: 'int get foo => null;\n',
649+
analysisOptions: 'include: package:lints/recommended.yaml');
650+
var result = await p.runAnalyze([]);
651+
652+
expect(result.exitCode, 3);
653+
expect(result.stderr, isEmpty);
654+
655+
final stdout = result.stdout;
656+
final expectedOutput = '''
657+
Analyzing myapp...
658+
659+
error - lib${path.separator}main.dart:1:16 - A value of type 'Null' can't be returned from the function 'foo' because it has a return type of 'int'. - return_of_invalid_type
660+
warning - analysis_options.yaml:1:10 - The include file 'package:lints/recommended.yaml' in '${p.analysisOptionsPath}' can't be found when analyzing '${p.dirPath}'. - include_file_not_found
661+
662+
2 issues found.
663+
''';
664+
expect(stdout.trim(), expectedOutput.trim());
665+
});
593666
});
594667

595668
group('json', () {

pkg/dartdev/test/utils.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class TestProject {
6464

6565
String get mainPath => path.join(dirPath, relativeFilePath);
6666

67+
String get analysisOptionsPath => path.join(dirPath, 'analysis_options.yaml');
68+
6769
String get packageConfigPath => path.join(
6870
dirPath,
6971
'.dart_tool',

0 commit comments

Comments
 (0)