@@ -45,10 +45,10 @@ Future<void> main(List<String> arguments) async {
4545 dart = path.join (dartSdk, 'bin' , Platform .isWindows ? 'dart.exe' : 'dart' );
4646 pub = path.join (dartSdk, 'bin' , Platform .isWindows ? 'pub.bat' : 'pub' );
4747 print ('$clock STARTING ANALYSIS' );
48- try {
49- await run (arguments);
50- } on ExitException catch (error) {
51- error. apply ();
48+ await run (arguments);
49+ if (hasError) {
50+ print ( '$ clock ${ bold }Test failed.$ reset ' );
51+ reportErrorsAndExit ();
5252 }
5353 print ('$clock ${bold }Analysis successful.$reset ' );
5454}
@@ -60,17 +60,20 @@ String? _getDartSdkFromArguments(List<String> arguments) {
6060 for (int i = 0 ; i < arguments.length; i += 1 ) {
6161 if (arguments[i] == '--dart-sdk' ) {
6262 if (result != null ) {
63- exitWithError (< String > ['The --dart-sdk argument must not be used more than once.' ]);
63+ foundError (< String > ['The --dart-sdk argument must not be used more than once.' ]);
64+ return null ;
6465 }
6566 if (i + 1 < arguments.length) {
6667 result = arguments[i + 1 ];
6768 } else {
68- exitWithError (< String > ['--dart-sdk must be followed by a path.' ]);
69+ foundError (< String > ['--dart-sdk must be followed by a path.' ]);
70+ return null ;
6971 }
7072 }
7173 if (arguments[i].startsWith ('--dart-sdk=' )) {
7274 if (result != null ) {
73- exitWithError (< String > ['The --dart-sdk argument must not be used more than once.' ]);
75+ foundError (< String > ['The --dart-sdk argument must not be used more than once.' ]);
76+ return null ;
7477 }
7578 result = arguments[i].substring ('--dart-sdk=' .length);
7679 }
@@ -82,7 +85,7 @@ Future<void> run(List<String> arguments) async {
8285 bool assertsEnabled = false ;
8386 assert (() { assertsEnabled = true ; return true ; }());
8487 if (! assertsEnabled) {
85- exitWithError (< String > ['The analyze.dart script must be run with --enable-asserts.' ]);
88+ foundError (< String > ['The analyze.dart script must be run with --enable-asserts.' ]);
8689 }
8790
8891 print ('$clock No Double.clamp' );
@@ -268,7 +271,7 @@ Future<void> verifyNoDoubleClamp(String workingDirectory) async {
268271 }
269272 }
270273 if (errors.isNotEmpty) {
271- exitWithError (< String > [
274+ foundError (< String > [
272275 ...errors,
273276 '\n ${bold }See: https://github.com/flutter/flutter/pull/103559' ,
274277 ]);
@@ -315,7 +318,7 @@ Future<void> verifyToolTestsEndInTestDart(String workingDirectory) async {
315318 violations.add (file.path);
316319 }
317320 if (violations.isNotEmpty) {
318- exitWithError (< String > [
321+ foundError (< String > [
319322 '${bold }Found flutter_tools tests that do not end in `_test.dart`; these will not be run by the test runner$reset ' ,
320323 ...violations,
321324 ]);
@@ -354,7 +357,7 @@ Future<void> verifyNoSyncAsyncStar(String workingDirectory, {int minimumMatches
354357 }
355358 }
356359 if (errors.isNotEmpty) {
357- exitWithError (< String > [
360+ foundError (< String > [
358361 '${bold }Do not use sync*/async* methods. See https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#avoid-syncasync for details.$reset ' ,
359362 ...errors,
360363 ]);
@@ -420,7 +423,7 @@ Future<void> verifyGoldenTags(String workingDirectory, { int minimumMatches = 20
420423 }
421424 }
422425 if (errors.isNotEmpty) {
423- exitWithError (< String > [
426+ foundError (< String > [
424427 ...errors,
425428 '${bold }See: https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter$reset ' ,
426429 ]);
@@ -529,7 +532,7 @@ Future<void> verifyDeprecations(String workingDirectory, { int minimumMatches =
529532 }
530533 // Fail if any errors
531534 if (errors.isNotEmpty) {
532- exitWithError (< String > [
535+ foundError (< String > [
533536 ...errors,
534537 '${bold }See: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes$reset ' ,
535538 ]);
@@ -561,7 +564,7 @@ Future<void> verifyNoMissingLicense(String workingDirectory, { bool checkMinimum
561564 failed += await _verifyNoMissingLicenseForExtension (workingDirectory, 'xml' , overrideMinimumMatches ?? 1 , '<!-- ${_generateLicense ('' )} -->' , header: r'(<\?xml version="1.0" encoding="utf-8"\?>\n)?' );
562565 failed += await _verifyNoMissingLicenseForExtension (workingDirectory, 'frag' , overrideMinimumMatches ?? 1 , _generateLicense ('// ' ), header: r'#version 320 es(\n)+' );
563566 if (failed > 0 ) {
564- exitWithError (< String > ['License check failed.' ]);
567+ foundError (< String > ['License check failed.' ]);
565568 }
566569}
567570
@@ -670,7 +673,7 @@ Future<void> verifySkipTestComments(String workingDirectory) async {
670673
671674 // Fail if any errors
672675 if (errors.isNotEmpty) {
673- exitWithError (< String > [
676+ foundError (< String > [
674677 ...errors,
675678 '\n ${bold }See: https://github.com/flutter/flutter/wiki/Tree-hygiene#skipped-tests$reset ' ,
676679 ]);
@@ -700,7 +703,7 @@ Future<void> verifyNoTestImports(String workingDirectory) async {
700703 // Fail if any errors
701704 if (errors.isNotEmpty) {
702705 final String s = errors.length == 1 ? '' : 's' ;
703- exitWithError (< String > [
706+ foundError (< String > [
704707 '${bold }The following file$s import a test directly. Test utilities should be in their own file.$reset ' ,
705708 ...errors,
706709 ]);
@@ -769,7 +772,7 @@ Future<void> verifyNoBadImportsInFlutter(String workingDirectory) async {
769772 }
770773 // Fail if any errors
771774 if (errors.isNotEmpty) {
772- exitWithError (< String > [
775+ foundError (< String > [
773776 if (errors.length == 1 )
774777 '${bold }An error was detected when looking at import dependencies within the Flutter package:$reset '
775778 else
@@ -789,7 +792,7 @@ Future<void> verifyNoBadImportsInFlutterTools(String workingDirectory) async {
789792 }
790793 // Fail if any errors
791794 if (errors.isNotEmpty) {
792- exitWithError (< String > [
795+ foundError (< String > [
793796 if (errors.length == 1 )
794797 '${bold }An error was detected when looking at import dependencies within the flutter_tools package:$reset '
795798 else
@@ -814,7 +817,7 @@ Future<void> verifyIntegrationTestTimeouts(String workingDirectory) async {
814817 }
815818 }
816819 if (errors.isNotEmpty) {
817- exitWithError (< String > [
820+ foundError (< String > [
818821 if (errors.length == 1 )
819822 '${bold }An error was detected when looking at integration test timeouts:$reset '
820823 else
@@ -850,7 +853,7 @@ Future<void> verifyInternationalizations(String workingDirectory, String dartExe
850853 final String expectedCupertinoResult = await File (cupertinoLocalizationsFile).readAsString ();
851854
852855 if (materialGenResult.stdout.trim () != expectedMaterialResult.trim ()) {
853- exitWithError (< String > [
856+ foundError (< String > [
854857 '<<<<<<< $materialLocalizationsFile ' ,
855858 expectedMaterialResult.trim (),
856859 '=======' ,
@@ -862,7 +865,7 @@ Future<void> verifyInternationalizations(String workingDirectory, String dartExe
862865 ]);
863866 }
864867 if (cupertinoGenResult.stdout.trim () != expectedCupertinoResult.trim ()) {
865- exitWithError (< String > [
868+ foundError (< String > [
866869 '<<<<<<< $cupertinoLocalizationsFile ' ,
867870 expectedCupertinoResult.trim (),
868871 '=======' ,
@@ -893,7 +896,7 @@ Future<void> verifyNoCheckedMode(String workingDirectory) async {
893896 }
894897 }
895898 if (problems.isNotEmpty) {
896- exitWithError (problems);
899+ foundError (problems);
897900 }
898901}
899902
@@ -947,7 +950,7 @@ Future<void> verifyNoRuntimeTypeInToString(String workingDirectory) async {
947950 }
948951 }
949952 if (problems.isNotEmpty) {
950- exitWithError (problems);
953+ foundError (problems);
951954 }
952955}
953956
@@ -977,7 +980,7 @@ Future<void> verifyNoTrailingSpaces(String workingDirectory, { int minimumMatche
977980 }
978981 }
979982 if (problems.isNotEmpty) {
980- exitWithError (problems);
983+ foundError (problems);
981984 }
982985}
983986
@@ -1050,7 +1053,7 @@ Future<void> verifyIssueLinks(String workingDirectory) async {
10501053 }
10511054 assert (problems.isEmpty == suggestions.isEmpty);
10521055 if (problems.isNotEmpty) {
1053- exitWithError (< String > [
1056+ foundError (< String > [
10541057 ...problems,
10551058 ...suggestions,
10561059 ]);
@@ -1507,7 +1510,7 @@ Future<void> verifyNoBinaries(String workingDirectory, { Set<Hash256>? legacyBin
15071510 }
15081511 }
15091512 if (problems.isNotEmpty) {
1510- exitWithError (< String > [
1513+ foundError (< String > [
15111514 ...problems,
15121515 'All files in this repository must be UTF-8. In particular, images and other binaries' ,
15131516 'must not be checked into this repository. This is because we are very sensitive to the' ,
@@ -1545,7 +1548,7 @@ Future<List<File>> _gitFiles(String workingDirectory, {bool runSilently = true})
15451548 runSilently: runSilently,
15461549 );
15471550 if (evalResult.exitCode != 0 ) {
1548- exitWithError (< String > [
1551+ foundError (< String > [
15491552 'git ls-files failed with exit code ${evalResult .exitCode }' ,
15501553 '${bold }stdout:$reset ' ,
15511554 evalResult.stdout,
@@ -1671,7 +1674,7 @@ Future<EvalResult> _evalCommand(String executable, List<String> arguments, {
16711674
16721675 if (exitCode != 0 && ! allowNonZeroExit) {
16731676 stderr.write (result.stderr);
1674- exitWithError (< String > [
1677+ foundError (< String > [
16751678 '${bold }ERROR:$red Last command exited with $exitCode .$reset ' ,
16761679 '${bold }Command:$red $commandDescription $reset ' ,
16771680 '${bold }Relative working directory:$red $relativeWorkingDir $reset ' ,
@@ -1702,9 +1705,11 @@ Future<void> _checkConsumerDependencies() async {
17021705 '--directory=${path .join (flutterRoot , 'packages' , package )}' ,
17031706 ]);
17041707 if (result.exitCode != 0 ) {
1705- print (result.stdout as Object );
1706- print (result.stderr as Object );
1707- exit (result.exitCode);
1708+ foundError (< String > [
1709+ result.stdout.toString (),
1710+ result.stderr.toString (),
1711+ ]);
1712+ return ;
17081713 }
17091714 final Map <String , Object ?> rawJson = json.decode (result.stdout as String ) as Map <String , Object ?>;
17101715 final Map <String , Map <String , Object ?>> dependencyTree = < String , Map <String , Object ?>> {
@@ -1734,7 +1739,7 @@ Future<void> _checkConsumerDependencies() async {
17341739 String plural (int n, String s, String p) => n == 1 ? s : p;
17351740
17361741 if (added.isNotEmpty) {
1737- exitWithError (< String > [
1742+ foundError (< String > [
17381743 'The transitive closure of package dependencies contains ${plural (added .length , "a non-allowlisted package" , "non-allowlisted packages" )}:' ,
17391744 ' ${added .join (', ' )}' ,
17401745 'We strongly desire to keep the number of dependencies to a minimum and' ,
@@ -1745,7 +1750,7 @@ Future<void> _checkConsumerDependencies() async {
17451750 }
17461751
17471752 if (removed.isNotEmpty) {
1748- exitWithError (< String > [
1753+ foundError (< String > [
17491754 'Excellent news! ${plural (removed .length , "A package dependency has been removed!" , "Multiple package dependencies have been removed!" )}' ,
17501755 ' ${removed .join (', ' )}' ,
17511756 'To make sure we do not accidentally add ${plural (removed .length , "this dependency" , "these dependencies" )} back in the future,' ,
@@ -1778,7 +1783,7 @@ Future<void> verifyNullInitializedDebugExpensiveFields(String workingDirectory,
17781783 }
17791784
17801785 if (errors.isNotEmpty) {
1781- exitWithError (< String > [
1786+ foundError (< String > [
17821787 '${bold }ERROR: ${red }fields annotated with @_debugOnly must null initialize.$reset ' ,
17831788 'to ensure both the field and initializer are removed from profile/release mode.' ,
17841789 'These fields should be written as:\n ' ,
0 commit comments