Skip to content

Commit 5bb5129

Browse files
[tool] Adds a fix command (flutter#6512)
1 parent ab5e9e6 commit 5bb5129

4 files changed

Lines changed: 135 additions & 0 deletions

File tree

script/tool/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.11.1
2+
3+
* Adds a `fix` command to run `dart fix --apply` in target packages.
4+
15
## 0.11
26

37
* Renames `publish-plugin` to `publish`.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:file/file.dart';
8+
import 'package:platform/platform.dart';
9+
10+
import 'common/core.dart';
11+
import 'common/package_looping_command.dart';
12+
import 'common/process_runner.dart';
13+
import 'common/repository_package.dart';
14+
15+
/// A command to run Dart's "fix" command on packages.
16+
class FixCommand extends PackageLoopingCommand {
17+
/// Creates a fix command instance.
18+
FixCommand(
19+
Directory packagesDir, {
20+
ProcessRunner processRunner = const ProcessRunner(),
21+
Platform platform = const LocalPlatform(),
22+
}) : super(packagesDir, processRunner: processRunner, platform: platform);
23+
24+
@override
25+
final String name = 'fix';
26+
27+
@override
28+
final String description = 'Fixes packages using dart fix.\n\n'
29+
'This command requires "dart" and "flutter" to be in your path, and '
30+
'assumes that dependencies have already been fetched (e.g., by running '
31+
'the analyze command first).';
32+
33+
@override
34+
final bool hasLongOutput = false;
35+
36+
@override
37+
PackageLoopingType get packageLoopingType =>
38+
PackageLoopingType.includeAllSubpackages;
39+
40+
@override
41+
Future<PackageResult> runForPackage(RepositoryPackage package) async {
42+
final int exitCode = await processRunner.runAndStream(
43+
'dart', <String>['fix', '--apply'],
44+
workingDir: package.directory);
45+
if (exitCode != 0) {
46+
printError('Unable to automatically fix package.');
47+
return PackageResult.fail();
48+
}
49+
return PackageResult.success();
50+
}
51+
}

script/tool/lib/src/main.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'dependabot_check_command.dart';
1717
import 'drive_examples_command.dart';
1818
import 'federation_safety_check_command.dart';
1919
import 'firebase_test_lab_command.dart';
20+
import 'fix_command.dart';
2021
import 'format_command.dart';
2122
import 'license_check_command.dart';
2223
import 'lint_android_command.dart';
@@ -61,6 +62,7 @@ void main(List<String> args) {
6162
..addCommand(DriveExamplesCommand(packagesDir))
6263
..addCommand(FederationSafetyCheckCommand(packagesDir))
6364
..addCommand(FirebaseTestLabCommand(packagesDir))
65+
..addCommand(FixCommand(packagesDir))
6466
..addCommand(FormatCommand(packagesDir))
6567
..addCommand(LicenseCheckCommand(packagesDir))
6668
..addCommand(LintAndroidCommand(packagesDir))
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:io' as io;
6+
7+
import 'package:args/command_runner.dart';
8+
import 'package:file/file.dart';
9+
import 'package:file/memory.dart';
10+
import 'package:flutter_plugin_tools/src/common/core.dart';
11+
import 'package:flutter_plugin_tools/src/fix_command.dart';
12+
import 'package:test/test.dart';
13+
14+
import 'mocks.dart';
15+
import 'util.dart';
16+
17+
void main() {
18+
late FileSystem fileSystem;
19+
late MockPlatform mockPlatform;
20+
late Directory packagesDir;
21+
late RecordingProcessRunner processRunner;
22+
late CommandRunner<void> runner;
23+
24+
setUp(() {
25+
fileSystem = MemoryFileSystem();
26+
mockPlatform = MockPlatform();
27+
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
28+
processRunner = RecordingProcessRunner();
29+
final FixCommand command = FixCommand(
30+
packagesDir,
31+
processRunner: processRunner,
32+
platform: mockPlatform,
33+
);
34+
35+
runner = CommandRunner<void>('fix_command', 'Test for fix_command');
36+
runner.addCommand(command);
37+
});
38+
39+
test('runs fix in top-level packages and subpackages', () async {
40+
final RepositoryPackage package = createFakePackage('a', packagesDir);
41+
final RepositoryPackage plugin = createFakePlugin('b', packagesDir);
42+
43+
await runCapturingPrint(runner, <String>['fix']);
44+
45+
expect(
46+
processRunner.recordedCalls,
47+
orderedEquals(<ProcessCall>[
48+
ProcessCall('dart', const <String>['fix', '--apply'], package.path),
49+
ProcessCall('dart', const <String>['fix', '--apply'],
50+
package.getExamples().first.path),
51+
ProcessCall('dart', const <String>['fix', '--apply'], plugin.path),
52+
ProcessCall('dart', const <String>['fix', '--apply'],
53+
plugin.getExamples().first.path),
54+
]));
55+
});
56+
57+
test('fails if "dart fix" fails', () async {
58+
createFakePlugin('foo', packagesDir);
59+
60+
processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
61+
MockProcess(exitCode: 1),
62+
];
63+
64+
Error? commandError;
65+
final List<String> output = await runCapturingPrint(runner, <String>['fix'],
66+
errorHandler: (Error e) {
67+
commandError = e;
68+
});
69+
70+
expect(commandError, isA<ToolExit>());
71+
expect(
72+
output,
73+
containsAllInOrder(<Matcher>[
74+
contains('Unable to automatically fix package.'),
75+
]),
76+
);
77+
});
78+
}

0 commit comments

Comments
 (0)