blob: 3648a0186a25798ef2e05f1e6a43bc06567b2929 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "command_line_options.h"
#include <lib/cmdline/args_parser.h>
#include <iostream>
namespace fidl {
namespace linter {
namespace help {
// Appears at the top of the --help output above the switch list.
const char kArgSpec[] = "[--options] file1.fidl [fileN.fidl...]";
const char kIntro[] = R"(
const char kIncludeCheck[] = R"( --include-check=<check-id>
-i A check ID to check, excluding all others not explicitly included. By
default, all checks are performed, if not explicitly excluded (with
the --exclude-check option). Multiple check IDs can be included with:
fidl-lint -i some-check -i another-check)";
const char kExcludeCheck[] = R"( --exclude-check=<check-id>
-e A check ID to exclude from checking. All others will be included unless
an --included-check option is present. --include-check overrides any
--exclude-check. Option order is ignored. Multiple check IDs can be
excluded with:
fidl-lint -e some-check -e another-check)";
const char kMustFindExcludedChecks[] = R"( --must-find-excluded-checks
-m If this flag is set, at least one --exclude-check option is required.
After lint checking all given FIDL files, if an excluded check is
not encountered, output an error message and exit with an error
status code. This can be used to temporarily excluded checks,
resolve them over time, and once resolved, the error will force
the developer to remove the unnecessary exclude, preventing the
same lint error from being reintroduced in the future.)";
const char kFormat[] = R"( --format=[text|json]
-f Lint output format (text or json))";
const char kHelp[] = R"( --help
-h Print this help message.)";
} // namespace help
std::string Usage(std::string argv0) {
return argv0 + " " + help::kArgSpec +
"\n(--help for more details))\n"
"Returns exit status 0 if no lint issues were found, 1 if lint tests were\n"
"successful but some lint issues were found, or 2 for all other errors.";
cmdline::Status ParseCommandLine(int argc, const char* argv[], CommandLineOptions* options,
std::vector<std::string>* params) {
std::stringstream suggestion;
suggestion << "Try: " << argv[0] << " --help";
if (argc == 1) {
return cmdline::Status::Error(suggestion.str());
cmdline::ArgsParser<CommandLineOptions> parser;
parser.AddSwitch("include-check", 'i', help::kIncludeCheck, &CommandLineOptions::included_checks);
parser.AddSwitch("exclude-check", 'e', help::kExcludeCheck, &CommandLineOptions::excluded_checks);
parser.AddSwitch("must-find-excluded-checks", 'm', help::kMustFindExcludedChecks,
parser.AddSwitch("format", 'f', help::kFormat, &CommandLineOptions::format,
[](const std::string& format) -> cmdline::Status {
if (format == "text" || format == "json") {
return cmdline::Status::Ok();
return cmdline::Status::Error("Invalid value for --format: " + format);
// Special --help switch which doesn't exist in the options structure.
bool requested_help = false;
parser.AddGeneralSwitch("help", 'h', help::kHelp, [&requested_help]() { requested_help = true; });
cmdline::Status status = parser.Parse(argc, argv, options, params);
if (status.has_error()) {
return status;
// Handle --help switch since we're the one that knows about the switches.
if (requested_help) {
return cmdline::Status::Error(Usage(argv[0]) + "\n" + help::kIntro + parser.GetHelp());
if (options->must_find_excluded_checks && options->excluded_checks.empty()) {
return cmdline::Status::Error(
"--must-find-excluded-checks (-m) flag is only valid if at least"
"one check is excluded, with --exclude-check.");
if (params->size() > 0) {
if ((*params)[0] == "printcurrentoptions") {
std::stringstream current_options;
for (auto check : options->included_checks) {
current_options << "include-check: " << check << std::endl;
for (auto check : options->excluded_checks) {
current_options << "exclude-check: " << check << std::endl;
current_options << "format: " << options->format << std::endl;
return cmdline::Status::Error(current_options.str());
return cmdline::Status::Ok();
} // namespace linter
} // namespace fidl