
â¦k settings the show build settings xcode command can only accept one of the target or scheme flag. Therefore I make them optional.
352 lines
12 KiB
Dart
352 lines
12 KiB
Dart
// Copyright 2014 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 'package:meta/meta.dart';
|
|
import 'package:process/process.dart';
|
|
|
|
import '../artifacts.dart';
|
|
import '../base/common.dart';
|
|
import '../base/file_system.dart';
|
|
import '../base/logger.dart';
|
|
import '../base/platform.dart';
|
|
import '../base/terminal.dart';
|
|
import '../project.dart';
|
|
import '../project_validator.dart';
|
|
import '../runner/flutter_command.dart';
|
|
import 'analyze_base.dart';
|
|
import 'analyze_continuously.dart';
|
|
import 'analyze_once.dart';
|
|
import 'android_analyze.dart';
|
|
import 'ios_analyze.dart';
|
|
import 'validate_project.dart';
|
|
|
|
class AnalyzeCommand extends FlutterCommand {
|
|
AnalyzeCommand({
|
|
bool verboseHelp = false,
|
|
this.workingDirectory,
|
|
required FileSystem fileSystem,
|
|
required Platform platform,
|
|
required Terminal terminal,
|
|
required Logger logger,
|
|
required ProcessManager processManager,
|
|
required Artifacts artifacts,
|
|
required List<ProjectValidator> allProjectValidators,
|
|
required bool suppressAnalytics,
|
|
}) : _artifacts = artifacts,
|
|
_fileSystem = fileSystem,
|
|
_processManager = processManager,
|
|
_logger = logger,
|
|
_terminal = terminal,
|
|
_allProjectValidators = allProjectValidators,
|
|
_platform = platform,
|
|
_suppressAnalytics = suppressAnalytics {
|
|
argParser.addFlag('flutter-repo',
|
|
negatable: false,
|
|
help: 'Include all the examples and tests from the Flutter repository.',
|
|
hide: !verboseHelp);
|
|
argParser.addFlag('current-package',
|
|
help: 'Analyze the current project, if applicable.', defaultsTo: true);
|
|
argParser.addFlag('dartdocs',
|
|
negatable: false,
|
|
help: '(deprecated) List every public member that is lacking documentation. '
|
|
'This command will be removed in a future version of Flutter.',
|
|
hide: !verboseHelp);
|
|
argParser.addFlag('watch',
|
|
help: 'Run analysis continuously, watching the filesystem for changes.',
|
|
negatable: false);
|
|
argParser.addOption('write',
|
|
valueHelp: 'file',
|
|
help: 'Also output the results to a file. This is useful with "--watch" '
|
|
'if you want a file to always contain the latest results.');
|
|
argParser.addOption('dart-sdk',
|
|
valueHelp: 'path-to-sdk',
|
|
help: 'The path to the Dart SDK.',
|
|
hide: !verboseHelp);
|
|
argParser.addOption('protocol-traffic-log',
|
|
valueHelp: 'path-to-protocol-traffic-log',
|
|
help: 'The path to write the request and response protocol. This is '
|
|
'only intended to be used for debugging the tooling.',
|
|
hide: !verboseHelp);
|
|
argParser.addFlag('suggestions',
|
|
help: 'Show suggestions about the current flutter project.'
|
|
);
|
|
argParser.addFlag('machine',
|
|
negatable: false,
|
|
help: 'Dumps a JSON with a subset of relevant data about the tool, project, '
|
|
'and environment.',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
// Hidden option to enable a benchmarking mode.
|
|
argParser.addFlag('benchmark',
|
|
negatable: false,
|
|
hide: !verboseHelp,
|
|
help: 'Also output the analysis time.');
|
|
|
|
usesPubOption();
|
|
|
|
// Not used by analyze --watch
|
|
argParser.addFlag('congratulate',
|
|
help: 'Show output even when there are no errors, warnings, hints, or lints. '
|
|
'Ignored if "--watch" is specified.',
|
|
defaultsTo: true);
|
|
argParser.addFlag('preamble',
|
|
defaultsTo: true,
|
|
help: 'When analyzing the flutter repository, display the number of '
|
|
'files that will be analyzed.\n'
|
|
'Ignored if "--watch" is specified.');
|
|
argParser.addFlag('fatal-infos',
|
|
help: 'Treat info level issues as fatal.',
|
|
defaultsTo: true);
|
|
argParser.addFlag('fatal-warnings',
|
|
help: 'Treat warning level issues as fatal.',
|
|
defaultsTo: true);
|
|
|
|
argParser.addFlag('android',
|
|
negatable: false,
|
|
help: 'Analyze Android sub-project. Used by internal tools only.',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
argParser.addFlag('ios',
|
|
negatable: false,
|
|
help: 'Analyze iOS Xcode sub-project. Used by internal tools only.',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
if (verboseHelp) {
|
|
argParser.addSeparator('Usage: flutter analyze --android [arguments]');
|
|
}
|
|
|
|
argParser.addFlag('list-build-variants',
|
|
negatable: false,
|
|
help: 'Print out a list of available build variants for the '
|
|
'Android sub-project.',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
argParser.addFlag('output-app-link-settings',
|
|
negatable: false,
|
|
help: 'Output a JSON with Android app link settings into a file. '
|
|
'The "--build-variant" must also be set.',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
argParser.addOption('build-variant',
|
|
help: 'Sets the Android build variant to be analyzed.',
|
|
valueHelp: 'build variant',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
if (verboseHelp) {
|
|
argParser.addSeparator('Usage: flutter analyze --ios [arguments]');
|
|
}
|
|
|
|
argParser.addFlag('list-build-options',
|
|
help: 'Print out a list of available build options for the '
|
|
'iOS Xcode sub-project.',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
argParser.addFlag('output-universal-link-settings',
|
|
negatable: false,
|
|
help: 'Output a JSON with iOS Xcode universal link settings into a file. '
|
|
'The "--configuration" and "--target" must be set.',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
argParser.addOption('configuration',
|
|
help: 'Sets the iOS build configuration to be analyzed.',
|
|
valueHelp: 'configuration',
|
|
hide: !verboseHelp,
|
|
);
|
|
|
|
argParser.addOption('target',
|
|
help: 'Sets the iOS build target to be analyzed.',
|
|
valueHelp: 'target',
|
|
hide: !verboseHelp,
|
|
);
|
|
}
|
|
|
|
/// The working directory for testing analysis using dartanalyzer.
|
|
final Directory? workingDirectory;
|
|
|
|
final Artifacts _artifacts;
|
|
final FileSystem _fileSystem;
|
|
final Logger _logger;
|
|
final Terminal _terminal;
|
|
final ProcessManager _processManager;
|
|
final Platform _platform;
|
|
final List<ProjectValidator> _allProjectValidators;
|
|
final bool _suppressAnalytics;
|
|
|
|
@override
|
|
String get name => 'analyze';
|
|
|
|
@override
|
|
String get description => "Analyze the project's Dart code.";
|
|
|
|
@override
|
|
String get category => FlutterCommandCategory.project;
|
|
|
|
@visibleForTesting
|
|
List<ProjectValidator> allProjectValidators() => _allProjectValidators;
|
|
|
|
@override
|
|
bool get shouldRunPub {
|
|
// If they're not analyzing the current project.
|
|
if (!boolArg('current-package')) {
|
|
return false;
|
|
}
|
|
|
|
// Or we're not in a project directory.
|
|
if (!_fileSystem.file('pubspec.yaml').existsSync()) {
|
|
return false;
|
|
}
|
|
|
|
// Don't run pub if asking for machine output.
|
|
if (boolArg('machine')) {
|
|
return false;
|
|
}
|
|
|
|
// Don't run pub if asking for android analysis.
|
|
if (boolArg('android')) {
|
|
return false;
|
|
}
|
|
|
|
return super.shouldRunPub;
|
|
}
|
|
|
|
@override
|
|
Future<FlutterCommandResult> runCommand() async {
|
|
if (boolArg('android')) {
|
|
final AndroidAnalyzeOption option;
|
|
final String? buildVariant;
|
|
if (argResults!['list-build-variants'] as bool && argResults!['output-app-link-settings'] as bool) {
|
|
throwToolExit('Only one of "--list-build-variants" or "--output-app-link-settings" can be provided');
|
|
}
|
|
if (argResults!['list-build-variants'] as bool) {
|
|
option = AndroidAnalyzeOption.listBuildVariant;
|
|
buildVariant = null;
|
|
} else if (argResults!['output-app-link-settings'] as bool) {
|
|
option = AndroidAnalyzeOption.outputAppLinkSettings;
|
|
buildVariant = argResults!['build-variant'] as String?;
|
|
if (buildVariant == null) {
|
|
throwToolExit('"--build-variant" must be provided');
|
|
}
|
|
} else {
|
|
throwToolExit('No argument is provided to analyze. Use -h to see available commands.');
|
|
}
|
|
final Set<String> items = findDirectories(argResults!, _fileSystem);
|
|
final String directoryPath;
|
|
if (items.isEmpty) { // user did not specify any path
|
|
directoryPath = _fileSystem.currentDirectory.path;
|
|
} else if (items.length > 1) { // if the user sends more than one path
|
|
throwToolExit('The Android analyze can process only one directory path');
|
|
} else {
|
|
directoryPath = items.first;
|
|
}
|
|
await AndroidAnalyze(
|
|
fileSystem: _fileSystem,
|
|
option: option,
|
|
userPath: directoryPath,
|
|
buildVariant: buildVariant,
|
|
logger: _logger,
|
|
).analyze();
|
|
} else if (boolArg('ios')) {
|
|
final IOSAnalyzeOption option;
|
|
final String? configuration;
|
|
final String? target;
|
|
if (argResults!['list-build-options'] as bool && argResults!['output-universal-link-settings'] as bool) {
|
|
throwToolExit('Only one of "--list-build-options" or "--output-universal-link-settings" can be provided');
|
|
}
|
|
if (argResults!['list-build-options'] as bool) {
|
|
option = IOSAnalyzeOption.listBuildOptions;
|
|
configuration = null;
|
|
target = null;
|
|
} else if (argResults!['output-universal-link-settings'] as bool) {
|
|
option = IOSAnalyzeOption.outputUniversalLinkSettings;
|
|
configuration = argResults!['configuration'] as String?;
|
|
if (configuration == null) {
|
|
throwToolExit('"--configuration" must be provided');
|
|
}
|
|
target = argResults!['target'] as String?;
|
|
if (target == null) {
|
|
throwToolExit('"--target" must be provided');
|
|
}
|
|
} else {
|
|
throwToolExit('No argument is provided to analyze. Use -h to see available commands.');
|
|
}
|
|
final Set<String> items = findDirectories(argResults!, _fileSystem);
|
|
final String directoryPath;
|
|
if (items.isEmpty) { // user did not specify any path
|
|
directoryPath = _fileSystem.currentDirectory.path;
|
|
} else if (items.length > 1) { // if the user sends more than one path
|
|
throwToolExit('The iOS analyze can process only one directory path');
|
|
} else {
|
|
directoryPath = items.first;
|
|
}
|
|
await IOSAnalyze(
|
|
project: FlutterProject.fromDirectory(_fileSystem.directory(directoryPath)),
|
|
option: option,
|
|
configuration: configuration,
|
|
target: target,
|
|
logger: _logger,
|
|
).analyze();
|
|
} else if (boolArg('suggestions')) {
|
|
final String directoryPath;
|
|
if (boolArg('watch')) {
|
|
throwToolExit('flag --watch is not compatible with --suggestions');
|
|
}
|
|
if (workingDirectory == null) {
|
|
final Set<String> items = findDirectories(argResults!, _fileSystem);
|
|
if (items.isEmpty) { // user did not specify any path
|
|
directoryPath = _fileSystem.currentDirectory.path;
|
|
_logger.printTrace('Showing suggestions for current directory: $directoryPath');
|
|
} else if (items.length > 1) { // if the user sends more than one path
|
|
throwToolExit('The suggestions flag can process only one directory path');
|
|
} else {
|
|
directoryPath = items.first;
|
|
}
|
|
} else {
|
|
directoryPath = workingDirectory!.path;
|
|
}
|
|
return ValidateProject(
|
|
fileSystem: _fileSystem,
|
|
logger: _logger,
|
|
allProjectValidators: _allProjectValidators,
|
|
userPath: directoryPath,
|
|
processManager: _processManager,
|
|
machine: boolArg('machine'),
|
|
).run();
|
|
} else if (boolArg('watch')) {
|
|
await AnalyzeContinuously(
|
|
argResults!,
|
|
runner!.getRepoPackages(),
|
|
fileSystem: _fileSystem,
|
|
logger: _logger,
|
|
platform: _platform,
|
|
processManager: _processManager,
|
|
terminal: _terminal,
|
|
artifacts: _artifacts,
|
|
suppressAnalytics: _suppressAnalytics,
|
|
).analyze();
|
|
} else {
|
|
await AnalyzeOnce(
|
|
argResults!,
|
|
runner!.getRepoPackages(),
|
|
workingDirectory: workingDirectory,
|
|
fileSystem: _fileSystem,
|
|
logger: _logger,
|
|
platform: _platform,
|
|
processManager: _processManager,
|
|
terminal: _terminal,
|
|
artifacts: _artifacts,
|
|
suppressAnalytics: _suppressAnalytics,
|
|
).analyze();
|
|
}
|
|
return FlutterCommandResult.success();
|
|
}
|
|
}
|