blob: 2f7c91138a5023aa1e26cd150da56d4ddf221b6b [file]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_cli/src/fix/context.dart';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
/// Command line options for `dartfix`.
class Options {
final Context context;
List<String> targets;
bool force;
bool overwrite;
String sdkPath;
bool verbose;
Options(this.context);
static Options parse(List<String> args, Context context) {
Options options = new Options(context ?? new Context());
final parser = new ArgParser(allowTrailingOptions: true);
parser
..addFlag(overwriteOption,
abbr: 'w',
help: 'Overwrite files with the recommended changes.',
defaultsTo: false,
negatable: false)
..addFlag(forceOption,
abbr: 'f',
help: 'Apply the recommended changes even if there are errors.',
defaultsTo: false,
negatable: false)
..addFlag(_helpOption,
abbr: 'h',
help: 'Display this help message.',
defaultsTo: false,
negatable: false)
..addFlag(_verboseOption,
abbr: 'v',
defaultsTo: false,
help: 'Verbose output.',
negatable: false);
ArgResults results;
try {
results = parser.parse(args);
} on FormatException catch (e) {
context.stderr.writeln(e.message);
_showUsage(parser, context);
context.exit(15);
}
if (results[_helpOption] as bool) {
_showUsage(parser, context);
context.exit(1);
}
options._fromArgs(results);
// Infer the Dart SDK location
options.sdkPath = getSdkPath(args);
String sdkPath = options.sdkPath;
if (sdkPath == null) {
context.stderr.writeln('No Dart SDK found.');
_showUsage(parser, context);
}
if (!context.exists(sdkPath)) {
context.stderr.writeln('Invalid Dart SDK path: $sdkPath');
context.exit(15);
}
// Check for files and/or directories to analyze.
if (options.targets == null || options.targets.isEmpty) {
context.stderr
.writeln('Expected at least one file or directory to analyze.');
_showUsage(parser, context);
context.exit(15);
}
// Normalize and verify paths
options.targets =
options.targets.map<String>(options.makeAbsoluteAndNormalize).toList();
for (String target in options.targets) {
if (!context.isDirectory(target)) {
if (!context.exists(target)) {
context.stderr.writeln('Target does not exist: $target');
} else {
context.stderr.writeln('Expected directory, but found: $target');
}
_showUsage(parser, context);
context.exit(15);
}
}
if (options.verbose) {
context.print('Targets:');
for (String target in options.targets) {
context.print(' $target');
}
}
return options;
}
void _fromArgs(ArgResults results) {
targets = results.rest;
force = results[forceOption] as bool;
overwrite = results[overwriteOption] as bool;
verbose = results[_verboseOption] as bool;
}
String makeAbsoluteAndNormalize(String target) {
if (!path.isAbsolute(target)) {
target = path.join(context.workingDir, target);
}
return path.normalize(target);
}
static _showUsage(ArgParser parser, Context context) {
context.stderr
.writeln('Usage: $_binaryName [options...] <directory paths>');
context.stderr.writeln('');
context.stderr.writeln(parser.usage);
}
}
const _binaryName = 'dartfix';
const forceOption = 'force';
const _helpOption = 'help';
const overwriteOption = 'overwrite';
const _verboseOption = 'verbose';