diff --git a/script/tool/lib/src/analyze_command.dart b/script/tool/lib/src/analyze_command.dart index 4810e3bbfc10..5fe1ee9e0929 100644 --- a/script/tool/lib/src/analyze_command.dart +++ b/script/tool/lib/src/analyze_command.dart @@ -323,6 +323,9 @@ class AnalyzeCommand extends PackageLoopingCommand { processRunner, platform, dartSdkPathOverride: _dartBinaryPath, + // 'get' and 'downgrade' resolve examples as well, so check + // those as well when deciding between `flutter` and `dart`. + recursiveFlutterCheck: true, ); } diff --git a/script/tool/lib/src/common/pub_utils.dart b/script/tool/lib/src/common/pub_utils.dart index adfeffc3f684..0f8aefb01c98 100644 --- a/script/tool/lib/src/common/pub_utils.dart +++ b/script/tool/lib/src/common/pub_utils.dart @@ -26,6 +26,7 @@ Future runPubGet( processRunner, platform, streamOutput: streamOutput, + recursiveFlutterCheck: true, ); } @@ -41,8 +42,14 @@ Future runPubCommand( Platform platform, { bool streamOutput = true, String? dartSdkPathOverride, + bool recursiveFlutterCheck = false, }) async { - final String command = _pubCommand(package, platform, dartSdkPathOverride: dartSdkPathOverride); + final String command = _pubCommand( + package, + platform, + dartSdkPathOverride: dartSdkPathOverride, + recursiveFlutterCheck: recursiveFlutterCheck, + ); final args = ['pub', ...commandArgs]; final int exitCode; if (streamOutput) { @@ -78,10 +85,24 @@ Future startPubCommand( ], workingDirectory: package.directory); } -String _pubCommand(RepositoryPackage package, Platform platform, {String? dartSdkPathOverride}) { +String _pubCommand( + RepositoryPackage package, + Platform platform, { + String? dartSdkPathOverride, + bool recursiveFlutterCheck = false, +}) { // Running `dart pub get` on a Flutter package can fail if a non-Flutter Dart // is first in the path, so use `flutter pub get` for any Flutter package. - return package.requiresFlutter() + bool useFlutter = package.requiresFlutter(); + if (!useFlutter && recursiveFlutterCheck) { + for (final RepositoryPackage example in package.getExamples()) { + if (example.requiresFlutter()) { + useFlutter = true; + break; + } + } + } + return useFlutter ? (platform.isWindows ? 'flutter.bat' : 'flutter') : (dartSdkPathOverride ?? 'dart'); } diff --git a/script/tool/test/analyze_command_test.dart b/script/tool/test/analyze_command_test.dart index fa5d742e90f0..7a45616a8325 100644 --- a/script/tool/test/analyze_command_test.dart +++ b/script/tool/test/analyze_command_test.dart @@ -175,6 +175,21 @@ void main() { ); }); + test('runs flutter pub get for non-Flutter packages with Flutter examples', () async { + final RepositoryPackage mainPackage = createFakePackage('a', packagesDir, examples: []); + createFakePackage('example', mainPackage.directory, examples: [], isFlutter: true); + + await runCapturingPrint(runner, ['analyze']); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall('flutter', const ['pub', 'get'], mainPackage.path), + ProcessCall('dart', const ['analyze', '--fatal-infos'], mainPackage.path), + ]), + ); + }); + test('passes lib/ directory with --lib-only', () async { final RepositoryPackage package = createFakePackage('a_package', packagesDir); @@ -254,16 +269,47 @@ void main() { }); test('downgrades first when requested', () async { - final RepositoryPackage plugin = createFakePlugin('a', packagesDir); + final RepositoryPackage package = createFakePackage('a', packagesDir); await runCapturingPrint(runner, ['analyze', '--downgrade']); expect( processRunner.recordedCalls, orderedEquals([ - ProcessCall('flutter', const ['pub', 'downgrade'], plugin.path), - ProcessCall('flutter', const ['pub', 'get'], plugin.path), - ProcessCall('dart', const ['analyze', '--fatal-infos'], plugin.path), + ProcessCall('dart', const ['pub', 'downgrade'], package.path), + ProcessCall('dart', const ['pub', 'get'], package.path), + ProcessCall('dart', const ['analyze', '--fatal-infos'], package.path), + ]), + ); + }); + + test('downgrades using flutter for Flutter packages', () async { + final RepositoryPackage package = createFakePackage('a', packagesDir, isFlutter: true); + + await runCapturingPrint(runner, ['analyze', '--downgrade']); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall('flutter', const ['pub', 'downgrade'], package.path), + ProcessCall('flutter', const ['pub', 'get'], package.path), + ProcessCall('dart', const ['analyze', '--fatal-infos'], package.path), + ]), + ); + }); + + test('downgrades using flutter for non-Flutter packages with Flutter examples', () async { + final RepositoryPackage package = createFakePackage('a', packagesDir, examples: []); + createFakePackage('example', package.directory, examples: [], isFlutter: true); + + await runCapturingPrint(runner, ['analyze', '--downgrade']); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall('flutter', const ['pub', 'downgrade'], package.path), + ProcessCall('flutter', const ['pub', 'get'], package.path), + ProcessCall('dart', const ['analyze', '--fatal-infos'], package.path), ]), ); }); diff --git a/script/tool/test/common/pub_utils_test.dart b/script/tool/test/common/pub_utils_test.dart index cfcfdf5f8c9d..97925a9572a4 100644 --- a/script/tool/test/common/pub_utils_test.dart +++ b/script/tool/test/common/pub_utils_test.dart @@ -17,7 +17,7 @@ void main() { (:packagesDir, :processRunner, gitProcessRunner: _, gitDir: _) = configureBaseCommandMocks(); }); - test('runs with Dart for a non-Flutter package by default', () async { + test('runs with Dart for a non-Flutter package', () async { final RepositoryPackage package = createFakePackage('a_package', packagesDir); final platform = MockPlatform(); @@ -31,7 +31,7 @@ void main() { ); }); - test('runs with Flutter for a Flutter package by default', () async { + test('runs with Flutter for a Flutter package', () async { final RepositoryPackage package = createFakePackage('a_package', packagesDir, isFlutter: true); final platform = MockPlatform(); @@ -45,6 +45,21 @@ void main() { ); }); + test('runs with Flutter for a non-Flutter package with a Flutter example', () async { + final RepositoryPackage package = createFakePackage('a_package', packagesDir, examples: []); + createFakePackage('example', package.directory, examples: [], isFlutter: true); + final platform = MockPlatform(); + + await runPubGet(package, processRunner, platform); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall('flutter', const ['pub', 'get'], package.path), + ]), + ); + }); + test('uses the correct Flutter command on Windows', () async { final RepositoryPackage package = createFakePackage('a_package', packagesDir, isFlutter: true); final platform = MockPlatform(isWindows: true);