mirror of
https://github.com/flutter/packages.git
synced 2025-06-17 10:58:42 +08:00
158 lines
5.2 KiB
Dart
158 lines
5.2 KiB
Dart
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io' as io;
|
|
|
|
import 'package:file/file.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:quiver/iterables.dart';
|
|
|
|
import 'common.dart';
|
|
|
|
const String _googleFormatterUrl =
|
|
'https://github.com/google/google-java-format/releases/download/google-java-format-1.3/google-java-format-1.3-all-deps.jar';
|
|
|
|
/// A command to format all package code.
|
|
class FormatCommand extends PluginCommand {
|
|
/// Creates an instance of the format command.
|
|
FormatCommand(
|
|
Directory packagesDir,
|
|
FileSystem fileSystem, {
|
|
ProcessRunner processRunner = const ProcessRunner(),
|
|
}) : super(packagesDir, fileSystem, processRunner: processRunner) {
|
|
argParser.addFlag('fail-on-change', hide: true);
|
|
argParser.addOption('clang-format',
|
|
defaultsTo: 'clang-format',
|
|
help: 'Path to executable of clang-format.');
|
|
}
|
|
|
|
@override
|
|
final String name = 'format';
|
|
|
|
@override
|
|
final String description =
|
|
'Formats the code of all packages (Java, Objective-C, C++, and Dart).\n\n'
|
|
'This command requires "git", "flutter" and "clang-format" v5 to be in '
|
|
'your path.';
|
|
|
|
@override
|
|
Future<void> run() async {
|
|
final String googleFormatterPath = await _getGoogleFormatterPath();
|
|
|
|
await _formatDart();
|
|
await _formatJava(googleFormatterPath);
|
|
await _formatCppAndObjectiveC();
|
|
|
|
if (argResults['fail-on-change'] == true) {
|
|
final bool modified = await _didModifyAnything();
|
|
if (modified) {
|
|
throw ToolExit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<bool> _didModifyAnything() async {
|
|
final io.ProcessResult modifiedFiles = await processRunner.run(
|
|
'git',
|
|
<String>['ls-files', '--modified'],
|
|
workingDir: packagesDir,
|
|
exitOnError: true,
|
|
logOnError: true,
|
|
);
|
|
|
|
print('\n\n');
|
|
|
|
final String stdout = modifiedFiles.stdout as String;
|
|
if (stdout.isEmpty) {
|
|
print('All files formatted correctly.');
|
|
return false;
|
|
}
|
|
|
|
print('These files are not formatted correctly (see diff below):');
|
|
LineSplitter.split(stdout).map((String line) => ' $line').forEach(print);
|
|
|
|
print('\nTo fix run "pub global activate flutter_plugin_tools && '
|
|
'pub global run flutter_plugin_tools format" or copy-paste '
|
|
'this command into your terminal:');
|
|
|
|
print('patch -p1 <<DONE');
|
|
final io.ProcessResult diff = await processRunner.run(
|
|
'git',
|
|
<String>['diff'],
|
|
workingDir: packagesDir,
|
|
exitOnError: true,
|
|
logOnError: true,
|
|
);
|
|
print(diff.stdout);
|
|
print('DONE');
|
|
return true;
|
|
}
|
|
|
|
Future<void> _formatCppAndObjectiveC() async {
|
|
print('Formatting all .cc, .cpp, .mm, .m, and .h files...');
|
|
final Iterable<String> allFiles = <String>[
|
|
...await _getFilesWithExtension('.h'),
|
|
...await _getFilesWithExtension('.m'),
|
|
...await _getFilesWithExtension('.mm'),
|
|
...await _getFilesWithExtension('.cc'),
|
|
...await _getFilesWithExtension('.cpp'),
|
|
];
|
|
// Split this into multiple invocations to avoid a
|
|
// 'ProcessException: Argument list too long'.
|
|
final Iterable<List<String>> batches = partition(allFiles, 100);
|
|
for (final List<String> batch in batches) {
|
|
await processRunner.runAndStream(argResults['clang-format'] as String,
|
|
<String>['-i', '--style=Google', ...batch],
|
|
workingDir: packagesDir, exitOnError: true);
|
|
}
|
|
}
|
|
|
|
Future<void> _formatJava(String googleFormatterPath) async {
|
|
print('Formatting all .java files...');
|
|
final Iterable<String> javaFiles = await _getFilesWithExtension('.java');
|
|
await processRunner.runAndStream('java',
|
|
<String>['-jar', googleFormatterPath, '--replace', ...javaFiles],
|
|
workingDir: packagesDir, exitOnError: true);
|
|
}
|
|
|
|
Future<void> _formatDart() async {
|
|
// This actually should be fine for non-Flutter Dart projects, no need to
|
|
// specifically shell out to dartfmt -w in that case.
|
|
print('Formatting all .dart files...');
|
|
final Iterable<String> dartFiles = await _getFilesWithExtension('.dart');
|
|
if (dartFiles.isEmpty) {
|
|
print(
|
|
'No .dart files to format. If you set the `--exclude` flag, most likey they were skipped');
|
|
} else {
|
|
await processRunner.runAndStream(
|
|
'flutter', <String>['format', ...dartFiles],
|
|
workingDir: packagesDir, exitOnError: true);
|
|
}
|
|
}
|
|
|
|
Future<List<String>> _getFilesWithExtension(String extension) async =>
|
|
getFiles()
|
|
.where((File file) => p.extension(file.path) == extension)
|
|
.map((File file) => file.path)
|
|
.toList();
|
|
|
|
Future<String> _getGoogleFormatterPath() async {
|
|
final String javaFormatterPath = p.join(
|
|
p.dirname(p.fromUri(io.Platform.script)),
|
|
'google-java-format-1.3-all-deps.jar');
|
|
final File javaFormatterFile = fileSystem.file(javaFormatterPath);
|
|
|
|
if (!javaFormatterFile.existsSync()) {
|
|
print('Downloading Google Java Format...');
|
|
final http.Response response = await http.get(_googleFormatterUrl);
|
|
javaFormatterFile.writeAsBytesSync(response.bodyBytes);
|
|
}
|
|
|
|
return javaFormatterPath;
|
|
}
|
|
}
|