// 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.

// Checks and fixes format on files with changes.
//
// Run with --help for usage.

// TODO(gspencergoog): Support clang formatting on Windows.
// TODO(gspencergoog): Support Java formatting on Windows.

import 'dart:io';

import 'package:args/args.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:process/process.dart';
import 'package:process_runner/process_runner.dart';

class FormattingException implements Exception {
  FormattingException(this.message, [this.result]);

  final String message;
  final ProcessResult? result;

  int get exitCode => result?.exitCode ?? -1;

  @override
  String toString() {
    final StringBuffer output = StringBuffer(runtimeType.toString());
    output.write(': $message');
    final String? stderr = result?.stderr as String?;
    if (stderr?.isNotEmpty == true) {
      output.write(':\n$stderr');
    }
    return output.toString();
  }
}

enum MessageType {
  message,
  error,
  warning,
}

enum FormatCheck {
  clang,
  gn,
  java,
  python,
  whitespace,
}

FormatCheck nameToFormatCheck(String name) {
  switch (name) {
    case 'clang':
      return FormatCheck.clang;
    case 'gn':
      return FormatCheck.gn;
    case 'java':
      return FormatCheck.java;
    case 'python':
      return FormatCheck.python;
    case 'whitespace':
      return FormatCheck.whitespace;
    default:
      throw FormattingException('Unknown FormatCheck type $name');
  }
}

String formatCheckToName(FormatCheck check) {
  switch (check) {
    case FormatCheck.clang:
      return 'C++/ObjC';
    case FormatCheck.gn:
      return 'GN';
    case FormatCheck.java:
      return 'Java';
    case FormatCheck.python:
      return 'Python';
    case FormatCheck.whitespace:
      return 'Trailing whitespace';
  }
}

List<String> formatCheckNames() {
  List<FormatCheck> allowed;
  if (!Platform.isWindows) {
    allowed = FormatCheck.values;
  } else {
    allowed = <FormatCheck>[FormatCheck.gn, FormatCheck.whitespace];
  }
  return allowed
      .map<String>((FormatCheck check) => check.toString().replaceFirst('$FormatCheck.', ''))
      .toList();
}

Future<String> _runGit(
  List<String> args,
  ProcessRunner processRunner, {
  bool failOk = false,
}) async {
  final ProcessRunnerResult result = await processRunner.runProcess(
    <String>['git', ...args],
    failOk: failOk,
  );
  return result.stdout;
}

typedef MessageCallback = Function(String? message, {MessageType type});

/// Base class for format checkers.
///
/// Provides services that all format checkers need.
abstract class FormatChecker {
  FormatChecker({
    ProcessManager processManager = const LocalProcessManager(),
    required this.baseGitRef,
    required this.repoDir,
    required this.srcDir,
    this.allFiles = false,
    this.messageCallback,
  }) : _processRunner = ProcessRunner(
          defaultWorkingDirectory: repoDir,
          processManager: processManager,
        );

  /// Factory method that creates subclass format checkers based on the type of check.
  factory FormatChecker.ofType(
    FormatCheck check, {
    ProcessManager processManager = const LocalProcessManager(),
    required String baseGitRef,
    required Directory repoDir,
    required Directory srcDir,
    bool allFiles = false,
    MessageCallback? messageCallback,
  }) {
    switch (check) {
      case FormatCheck.clang:
        return ClangFormatChecker(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        );
      case FormatCheck.gn:
        return GnFormatChecker(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        );
      case FormatCheck.java:
        return JavaFormatChecker(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        );
      case FormatCheck.python:
        return PythonFormatChecker(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        );
      case FormatCheck.whitespace:
        return WhitespaceFormatChecker(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        );
    }
  }

  final ProcessRunner _processRunner;
  final Directory srcDir;
  final Directory repoDir;
  final bool allFiles;
  MessageCallback? messageCallback;
  final String baseGitRef;

  /// Override to provide format checking for a specific type.
  Future<bool> checkFormatting();

  /// Override to provide format fixing for a specific type.
  Future<bool> fixFormatting();

  @protected
  void message(String? string) => messageCallback?.call(string, type: MessageType.message);

  @protected
  void error(String string) => messageCallback?.call(string, type: MessageType.error);

  @protected
  Future<String> runGit(List<String> args) async => _runGit(args, _processRunner);

  /// Converts a given raw string of code units to a stream that yields those
  /// code units.
  ///
  /// Uses to convert the stdout of a previous command into an input stream for
  /// the next command.
  @protected
  Stream<List<int>> codeUnitsAsStream(List<int>? input) async* {
    if (input != null) {
      yield input;
    }
  }

  @protected
  Future<bool> applyPatch(List<String> patches) async {
    final ProcessPool patchPool = ProcessPool(
      processRunner: _processRunner,
      printReport: namedReport('patch'),
    );
    final List<WorkerJob> jobs = patches.map<WorkerJob>((String patch) {
      return WorkerJob(
        <String>['patch', '-p0'],
        stdinRaw: codeUnitsAsStream(patch.codeUnits),
        failOk: true,
      );
    }).toList();
    final List<WorkerJob> completedJobs = await patchPool.runToCompletion(jobs);
    if (patchPool.failedJobs != 0) {
      error('${patchPool.failedJobs} patch${patchPool.failedJobs > 1 ? 'es' : ''} '
          'failed to apply.');
      completedJobs
          .where((WorkerJob job) => job.result.exitCode != 0)
          .map<String>((WorkerJob job) => job.result.output)
          .forEach(message);
    }
    return patchPool.failedJobs == 0;
  }

  /// Gets the list of files to operate on.
  ///
  /// If [allFiles] is true, then returns all git controlled files in the repo
  /// of the given types.
  ///
  /// If [allFiles] is false, then only return those files of the given types
  /// that have changed between the current working tree and the [baseGitRef].
  @protected
  Future<List<String>> getFileList(List<String> types) async {
    String output;
    if (allFiles) {
      output = await runGit(<String>[
        'ls-files',
        '--',
        ...types,
      ]);
    } else {
      output = await runGit(<String>[
        'diff',
        '-U0',
        '--no-color',
        '--diff-filter=d',
        '--name-only',
        baseGitRef,
        '--',
        ...types,
      ]);
    }
    return output.split('\n').where((String line) => line.isNotEmpty).toList();
  }

  /// Generates a reporting function to supply to ProcessRunner to use instead
  /// of the default reporting function.
  @protected
  ProcessPoolProgressReporter namedReport(String name) {
    return (int total, int completed, int inProgress, int pending, int failed) {
      final String percent =
          total == 0 ? '100' : ((100 * completed) ~/ total).toString().padLeft(3);
      final String completedStr = completed.toString().padLeft(3);
      final String totalStr = total.toString().padRight(3);
      final String inProgressStr = inProgress.toString().padLeft(2);
      final String pendingStr = pending.toString().padLeft(3);
      final String failedStr = failed.toString().padLeft(3);

      stderr.write('$name Jobs: $percent% done, '
          '$completedStr/$totalStr completed, '
          '$inProgressStr in progress, '
          '$pendingStr pending, '
          '$failedStr failed.${' ' * 20}\r');
    };
  }

  /// Clears the last printed report line so garbage isn't left on the terminal.
  @protected
  void reportDone() {
    stderr.write('\r${' ' * 100}\r');
  }
}

/// Checks and formats C++/ObjC files using clang-format.
class ClangFormatChecker extends FormatChecker {
  ClangFormatChecker({
    ProcessManager processManager = const LocalProcessManager(),
    required String baseGitRef,
    required Directory repoDir,
    required Directory srcDir,
    bool allFiles = false,
    MessageCallback? messageCallback,
  }) : super(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        ) {
    /*late*/ String clangOs;
    if (Platform.isLinux) {
      clangOs = 'linux-x64';
    } else if (Platform.isMacOS) {
      clangOs = 'mac-x64';
    } else {
      throw FormattingException(
          "Unknown operating system: don't know how to run clang-format here.");
    }
    clangFormat = File(
      path.join(
        srcDir.absolute.path,
        'buildtools',
        clangOs,
        'clang',
        'bin',
        'clang-format',
      ),
    );
  }

  late final File clangFormat;

  @override
  Future<bool> checkFormatting() async {
    final List<String> failures = await _getCFormatFailures();
    failures.map(stdout.writeln);
    return failures.isEmpty;
  }

  @override
  Future<bool> fixFormatting() async {
    message('Fixing C++/ObjC formatting...');
    final List<String> failures = await _getCFormatFailures(fixing: true);
    if (failures.isEmpty) {
      return true;
    }
    return applyPatch(failures);
  }

  Future<String> _getClangFormatVersion() async {
    final ProcessRunnerResult result =
        await _processRunner.runProcess(<String>[clangFormat.path, '--version']);
    return result.stdout.trim();
  }

  Future<List<String>> _getCFormatFailures({bool fixing = false}) async {
    message('Checking C++/ObjC formatting...');
    const List<String> clangFiletypes = <String>[
      '*.c',
      '*.cc',
      '*.cxx',
      '*.cpp',
      '*.h',
      '*.m',
      '*.mm',
    ];
    final List<String> files = await getFileList(clangFiletypes);
    if (files.isEmpty) {
      message('No C++/ObjC files with changes, skipping C++/ObjC format check.');
      return <String>[];
    }
    if (verbose) {
      message('Using ${await _getClangFormatVersion()}');
    }
    final List<WorkerJob> clangJobs = <WorkerJob>[];
    for (final String file in files) {
      if (file.trim().isEmpty) {
        continue;
      }
      clangJobs.add(WorkerJob(<String>[clangFormat.path, '--style=file', file.trim()]));
    }
    final ProcessPool clangPool = ProcessPool(
      processRunner: _processRunner,
      printReport: namedReport('clang-format'),
    );
    final Stream<WorkerJob> completedClangFormats = clangPool.startWorkers(clangJobs);
    final List<WorkerJob> diffJobs = <WorkerJob>[];
    await for (final WorkerJob completedJob in completedClangFormats) {
      if (completedJob.result.exitCode == 0) {
        diffJobs.add(
          WorkerJob(<String>['diff', '-u', completedJob.command.last, '-'],
              stdinRaw: codeUnitsAsStream(completedJob.result.stdoutRaw), failOk: true),
        );
      }
    }
    final ProcessPool diffPool = ProcessPool(
      processRunner: _processRunner,
      printReport: namedReport('diff'),
    );
    final List<WorkerJob> completedDiffs = await diffPool.runToCompletion(diffJobs);
    final Iterable<WorkerJob> failed = completedDiffs.where((WorkerJob job) {
      return job.result.exitCode != 0;
    });
    reportDone();
    if (failed.isNotEmpty) {
      final bool plural = failed.length > 1;
      if (fixing) {
        message('Fixing ${failed.length} C++/ObjC file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly.');
      } else {
        error('Found ${failed.length} C++/ObjC file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly.');
        stdout.writeln('To fix, run:');
        stdout.writeln();
        stdout.writeln('patch -p0 <<DONE');
        for (final WorkerJob job in failed) {
          stdout.write(job.result.stdout);
        }
        stdout.writeln('DONE');
        stdout.writeln();
      }
    } else {
      message('Completed checking ${diffJobs.length} C++/ObjC files with no formatting problems.');
    }
    return failed.map<String>((WorkerJob job) {
      return job.result.stdout;
    }).toList();
  }
}

/// Checks the format of Java files uing the Google Java format checker.
class JavaFormatChecker extends FormatChecker {
  JavaFormatChecker({
    ProcessManager processManager = const LocalProcessManager(),
    required String baseGitRef,
    required Directory repoDir,
    required Directory srcDir,
    bool allFiles = false,
    MessageCallback? messageCallback,
  }) : super(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        ) {
    googleJavaFormatJar = File(
      path.absolute(
        path.join(
          srcDir.absolute.path,
          'third_party',
          'android_tools',
          'google-java-format',
          'google-java-format-1.7-all-deps.jar',
        ),
      ),
    );
  }

  late final File googleJavaFormatJar;

  Future<String> _getGoogleJavaFormatVersion() async {
    final ProcessRunnerResult result = await _processRunner
        .runProcess(<String>['java', '-jar', googleJavaFormatJar.path, '--version']);
    return result.stderr.trim();
  }

  @override
  Future<bool> checkFormatting() async {
    final List<String> failures = await _getJavaFormatFailures();
    failures.map(stdout.writeln);
    return failures.isEmpty;
  }

  @override
  Future<bool> fixFormatting() async {
    message('Fixing Java formatting...');
    final List<String> failures = await _getJavaFormatFailures(fixing: true);
    if (failures.isEmpty) {
      return true;
    }
    return applyPatch(failures);
  }

  Future<String> _getJavaVersion() async {
    final ProcessRunnerResult result =
        await _processRunner.runProcess(<String>['java', '-version']);
    return result.stderr.trim().split('\n')[0];
  }

  Future<List<String>> _getJavaFormatFailures({bool fixing = false}) async {
    message('Checking Java formatting...');
    final List<WorkerJob> formatJobs = <WorkerJob>[];
    final List<String> files = await getFileList(<String>['*.java']);
    if (files.isEmpty) {
      message('No Java files with changes, skipping Java format check.');
      return <String>[];
    }
    String javaVersion = '<unknown>';
    String javaFormatVersion = '<unknown>';
    try {
      javaVersion = await _getJavaVersion();
    } on ProcessRunnerException {
      error('Cannot run Java, skipping Java file formatting!');
      return const <String>[];
    }
    try {
      javaFormatVersion = await _getGoogleJavaFormatVersion();
    } on ProcessRunnerException {
      error('Cannot find google-java-format, skipping Java format check.');
      return const <String>[];
    }
    if (verbose) {
      message('Using $javaFormatVersion with Java $javaVersion');
    }
    for (final String file in files) {
      if (file.trim().isEmpty) {
        continue;
      }
      formatJobs.add(
        WorkerJob(
          <String>['java', '-jar', googleJavaFormatJar.path, file.trim()],
        ),
      );
    }
    final ProcessPool formatPool = ProcessPool(
      processRunner: _processRunner,
      printReport: namedReport('Java format'),
    );
    final Stream<WorkerJob> completedClangFormats = formatPool.startWorkers(formatJobs);
    final List<WorkerJob> diffJobs = <WorkerJob>[];
    await for (final WorkerJob completedJob in completedClangFormats) {
      if (completedJob.result.exitCode == 0) {
        diffJobs.add(
          WorkerJob(
            <String>['diff', '-u', completedJob.command.last, '-'],
            stdinRaw: codeUnitsAsStream(completedJob.result.stdoutRaw),
            failOk: true,
          ),
        );
      }
    }
    final ProcessPool diffPool = ProcessPool(
      processRunner: _processRunner,
      printReport: namedReport('diff'),
    );
    final List<WorkerJob> completedDiffs = await diffPool.runToCompletion(diffJobs);
    final Iterable<WorkerJob> failed = completedDiffs.where((WorkerJob job) {
      return job.result.exitCode != 0;
    });
    reportDone();
    if (failed.isNotEmpty) {
      final bool plural = failed.length > 1;
      if (fixing) {
        error('Fixing ${failed.length} Java file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly.');
      } else {
        error('Found ${failed.length} Java file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly.');
        stdout.writeln('To fix, run:');
        stdout.writeln();
        stdout.writeln('patch -p0 <<DONE');
        for (final WorkerJob job in failed) {
          stdout.write(job.result.stdout);
        }
        stdout.writeln('DONE');
        stdout.writeln();
      }
    } else {
      message('Completed checking ${diffJobs.length} Java files with no formatting problems.');
    }
    return failed.map<String>((WorkerJob job) {
      return job.result.stdout;
    }).toList();
  }
}

/// Checks the format of any BUILD.gn files using the "gn format" command.
class GnFormatChecker extends FormatChecker {
  GnFormatChecker({
    ProcessManager processManager = const LocalProcessManager(),
    required String baseGitRef,
    required Directory repoDir,
    required Directory srcDir,
    bool allFiles = false,
    MessageCallback? messageCallback,
  }) : super(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        ) {
    gnBinary = File(
      path.join(
        repoDir.absolute.path,
        'third_party',
        'gn',
        Platform.isWindows ? 'gn.exe' : 'gn',
      ),
    );
  }

  late final File gnBinary;

  @override
  Future<bool> checkFormatting() async {
    message('Checking GN formatting...');
    return (await _runGnCheck(fixing: false)) == 0;
  }

  @override
  Future<bool> fixFormatting() async {
    message('Fixing GN formatting...');
    await _runGnCheck(fixing: true);
    // The GN script shouldn't fail when fixing errors.
    return true;
  }

  Future<int> _runGnCheck({required bool fixing}) async {
    final List<String> filesToCheck = await getFileList(<String>['*.gn', '*.gni']);

    final List<String> cmd = <String>[
      gnBinary.path,
      'format',
      if (!fixing) '--dry-run',
    ];
    final List<WorkerJob> jobs = <WorkerJob>[];
    for (final String file in filesToCheck) {
      jobs.add(WorkerJob(<String>[...cmd, file]));
    }
    final ProcessPool gnPool = ProcessPool(
      processRunner: _processRunner,
      printReport: namedReport('gn format'),
    );
    final List<WorkerJob> completedJobs = await gnPool.runToCompletion(jobs);
    reportDone();
    final List<String> incorrect = <String>[];
    for (final WorkerJob job in completedJobs) {
      if (job.result.exitCode == 2) {
        incorrect.add('  ${job.command.last}');
      }
      if (job.result.exitCode == 1) {
        // GN has exit code 1 if it had some problem formatting/checking the
        // file.
        throw FormattingException(
          'Unable to format ${job.command.last}:\n${job.result.output}',
        );
      }
    }
    if (incorrect.isNotEmpty) {
      final bool plural = incorrect.length > 1;
      if (fixing) {
        message('Fixed ${incorrect.length} GN file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly.');
      } else {
        error('Found ${incorrect.length} GN file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly:');
        incorrect.forEach(stderr.writeln);
      }
    } else {
      message('All GN files formatted correctly.');
    }
    return incorrect.length;
  }
}

/// Checks the format of any .py files using the "yapf" command.
class PythonFormatChecker extends FormatChecker {
  PythonFormatChecker({
    ProcessManager processManager = const LocalProcessManager(),
    required String baseGitRef,
    required Directory repoDir,
    required Directory srcDir,
    bool allFiles = false,
    MessageCallback? messageCallback,
  }) : super(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        ) {
    yapfBin = File(path.join(
      repoDir.absolute.path,
      'tools',
      'yapf.sh',
    ));
    _yapfStyle = File(path.join(
      repoDir.absolute.path,
      '.style.yapf',
    ));
  }

  late final File yapfBin;
  late final File _yapfStyle;

  @override
  Future<bool> checkFormatting() async {
    message('Checking Python formatting...');
    return (await _runYapfCheck(fixing: false)) == 0;
  }

  @override
  Future<bool> fixFormatting() async {
    message('Fixing Python formatting...');
    await _runYapfCheck(fixing: true);
    // The yapf script shouldn't fail when fixing errors.
    return true;
  }

  Future<int> _runYapfCheck({required bool fixing}) async {
    final List<String> filesToCheck = <String>[
      ...await getFileList(<String>['*.py']),
      // Always include flutter/tools/gn.
      '${repoDir.path}/tools/gn',
    ];

    final List<String> cmd = <String>[
      yapfBin.path,
      '--style', _yapfStyle.path,
      if (!fixing) '--diff',
      if (fixing) '--in-place',
    ];
    final List<WorkerJob> jobs = <WorkerJob>[];
    for (final String file in filesToCheck) {
      jobs.add(WorkerJob(<String>[...cmd, file]));
    }
    final ProcessPool yapfPool = ProcessPool(
      processRunner: _processRunner,
      printReport: namedReport('python format'),
    );
    final List<WorkerJob> completedJobs = await yapfPool.runToCompletion(jobs);
    reportDone();
    final List<String> incorrect = <String>[];
    for (final WorkerJob job in completedJobs) {
      if (job.result.exitCode == 1) {
        incorrect.add('  ${job.command.last}\n${job.result.output}');
      }
    }
    if (incorrect.isNotEmpty) {
      final bool plural = incorrect.length > 1;
      if (fixing) {
        message('Fixed ${incorrect.length} python file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly.');
      } else {
        error('Found ${incorrect.length} python file${plural ? 's' : ''}'
            ' which ${plural ? 'were' : 'was'} formatted incorrectly:');
        incorrect.forEach(stderr.writeln);
      }
    } else {
      message('All python files formatted correctly.');
    }
    return incorrect.length;
  }
}

@immutable
class _GrepResult {
  const _GrepResult(this.file, [this.hits = const <String>[], this.lineNumbers = const <int>[]]);
  bool get isEmpty => hits.isEmpty && lineNumbers.isEmpty;
  final File file;
  final List<String> hits;
  final List<int> lineNumbers;
}

/// Checks for trailing whitspace in Dart files.
class WhitespaceFormatChecker extends FormatChecker {
  WhitespaceFormatChecker({
    ProcessManager processManager = const LocalProcessManager(),
    required String baseGitRef,
    required Directory repoDir,
    required Directory srcDir,
    bool allFiles = false,
    MessageCallback? messageCallback,
  }) : super(
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: allFiles,
          messageCallback: messageCallback,
        );

  @override
  Future<bool> checkFormatting() async {
    final List<File> failures = await _getWhitespaceFailures();
    return failures.isEmpty;
  }

  static final RegExp trailingWsRegEx = RegExp(r'[ \t]+$', multiLine: true);

  @override
  Future<bool> fixFormatting() async {
    final List<File> failures = await _getWhitespaceFailures();
    if (failures.isNotEmpty) {
      for (final File file in failures) {
        stderr.writeln('Fixing $file');
        String contents = file.readAsStringSync();
        contents = contents.replaceAll(trailingWsRegEx, '');
        file.writeAsStringSync(contents);
      }
    }
    return true;
  }

  static _GrepResult _hasTrailingWhitespace(File file) {
    final List<String> hits = <String>[];
    final List<int> lineNumbers = <int>[];
    int lineNumber = 0;
    for (final String line in file.readAsLinesSync()) {
      if (trailingWsRegEx.hasMatch(line)) {
        hits.add(line);
        lineNumbers.add(lineNumber);
      }
      lineNumber++;
    }
    if (hits.isEmpty) {
      return _GrepResult(file);
    }
    return _GrepResult(file, hits, lineNumbers);
  }

  Iterable<_GrepResult> _whereHasTrailingWhitespace(Iterable<File> files) {
    return files.map(_hasTrailingWhitespace);
  }

  Future<List<File>> _getWhitespaceFailures() async {
    final List<String> files = await getFileList(<String>[
      '*.c',
      '*.cc',
      '*.cpp',
      '*.cxx',
      '*.dart',
      '*.gn',
      '*.gni',
      '*.gradle',
      '*.h',
      '*.java',
      '*.json',
      '*.m',
      '*.mm',
      '*.py',
      '*.sh',
      '*.yaml',
    ]);
    if (files.isEmpty) {
      message('No files that differ, skipping whitespace check.');
      return <File>[];
    }
    message('Checking for trailing whitespace on ${files.length} source '
        'file${files.length > 1 ? 's' : ''}...');

    final ProcessPoolProgressReporter reporter = namedReport('whitespace');
    final List<_GrepResult> found = <_GrepResult>[];
    final int total = files.length;
    int completed = 0;
    int inProgress = Platform.numberOfProcessors;
    int pending = total;
    int failed = 0;
    for (final _GrepResult result in _whereHasTrailingWhitespace(
      files.map<File>(
        (String file) => File(
          path.join(repoDir.absolute.path, file),
        ),
      ),
    )) {
      if (result.isEmpty) {
        completed++;
      } else {
        failed++;
        found.add(result);
      }
      pending--;
      inProgress = pending < Platform.numberOfProcessors ? pending : Platform.numberOfProcessors;
      reporter(total, completed, inProgress, pending, failed);
    }
    reportDone();
    if (found.isNotEmpty) {
      error('Whitespace check failed. The following files have trailing spaces:');
      for (final _GrepResult result in found) {
        for (int i = 0; i < result.hits.length; ++i) {
          message('  ${result.file.path}:${result.lineNumbers[i]}:${result.hits[i]}');
        }
      }
    } else {
      message('No trailing whitespace found.');
    }
    return found.map<File>((_GrepResult result) => result.file).toList();
  }
}

Future<String> _getDiffBaseRevision(ProcessManager processManager, Directory repoDir) async {
  final ProcessRunner processRunner = ProcessRunner(
    defaultWorkingDirectory: repoDir,
    processManager: processManager,
  );
  String upstream = 'upstream';
  final String upstreamUrl = await _runGit(
    <String>['remote', 'get-url', upstream],
    processRunner,
    failOk: true,
  );
  if (upstreamUrl.isEmpty) {
    upstream = 'origin';
  }
  await _runGit(<String>['fetch', upstream, 'main'], processRunner);
  String result = '';
  try {
    // This is the preferred command to use, but developer checkouts often do
    // not have a clear fork point, so we fall back to just the regular
    // merge-base in that case.
    result = await _runGit(
      <String>['merge-base', '--fork-point', 'FETCH_HEAD', 'HEAD'],
      processRunner,
    );
  } on ProcessRunnerException {
    result = await _runGit(<String>['merge-base', 'FETCH_HEAD', 'HEAD'], processRunner);
  }
  return result.trim();
}

void _usage(ArgParser parser, {int exitCode = 1}) {
  stderr.writeln('format.dart [--help] [--fix] [--all-files] '
      '[--check <${formatCheckNames().join('|')}>]');
  stderr.writeln(parser.usage);
  exit(exitCode);
}

bool verbose = false;

Future<int> main(List<String> arguments) async {
  final ArgParser parser = ArgParser();
  parser.addFlag('help', help: 'Print help.', abbr: 'h');
  parser.addFlag('fix',
      abbr: 'f',
      help: 'Instead of just checking for formatting errors, fix them in place.',
      defaultsTo: false);
  parser.addFlag('all-files',
      abbr: 'a',
      help: 'Instead of just checking for formatting errors in changed files, '
          'check for them in all files.',
      defaultsTo: false);
  parser.addMultiOption('check',
      abbr: 'c',
      allowed: formatCheckNames(),
      defaultsTo: formatCheckNames(),
      help: 'Specifies which checks will be performed. Defaults to all checks. '
          'May be specified more than once to perform multiple types of checks. '
          'On Windows, only whitespace and gn checks are currently supported.');
  parser.addFlag('verbose', help: 'Print verbose output.', defaultsTo: verbose);

  late final ArgResults options;
  try {
    options = parser.parse(arguments);
  } on FormatException catch (e) {
    stderr.writeln('ERROR: $e');
    _usage(parser, exitCode: 0);
  }

  verbose = options['verbose'] as bool;

  if (options['help'] as bool) {
    _usage(parser, exitCode: 0);
  }

  final File script = File.fromUri(Platform.script).absolute;
  final Directory repoDir = script.parent.parent.parent;
  final Directory srcDir = repoDir.parent;
  if (verbose) {
    stderr.writeln('Repo: $repoDir');
    stderr.writeln('Src: $srcDir');
  }

  void message(String? message, {MessageType type = MessageType.message}) {
    message ??= '';
    switch (type) {
      case MessageType.message:
        stderr.writeln(message);
        break;
      case MessageType.error:
        stderr.writeln('ERROR: $message');
        break;
      case MessageType.warning:
        stderr.writeln('WARNING: $message');
        break;
    }
  }

  const ProcessManager processManager = LocalProcessManager();
  final String baseGitRef = await _getDiffBaseRevision(processManager, repoDir);

  bool result = true;
  final List<String> checks = options['check'] as List<String>;
  try {
    for (final String checkName in checks) {
      final FormatCheck check = nameToFormatCheck(checkName);
      final String humanCheckName = formatCheckToName(check);
      final FormatChecker checker = FormatChecker.ofType(check,
          processManager: processManager,
          baseGitRef: baseGitRef,
          repoDir: repoDir,
          srcDir: srcDir,
          allFiles: options['all-files'] as bool,
          messageCallback: message);
      bool stepResult;
      if (options['fix'] as bool) {
        message('Fixing any $humanCheckName format problems');
        stepResult = await checker.fixFormatting();
        if (!stepResult) {
          message('Unable to apply $humanCheckName format fixes.');
        }
      } else {
        message('Performing $humanCheckName format check');
        stepResult = await checker.checkFormatting();
        if (!stepResult) {
          message('Found $humanCheckName format problems.');
        }
      }
      result = result && stepResult;
    }
  } on FormattingException catch (e) {
    message('ERROR: $e', type: MessageType.error);
  }

  exit(result ? 0 : 1);
}
