diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -88,21 +88,26 @@ //===----------------------------------------------------------------------===// -static StringRef ArgPrefix = " -"; -static StringRef ArgPrefixLong = " --"; +const static size_t DefaultPad = 2; + +static StringRef ArgPrefix = "-"; +static StringRef ArgPrefixLong = "--"; static StringRef ArgHelpPrefix = " - "; -static size_t argPlusPrefixesSize(StringRef ArgName) { +static size_t argPlusPrefixesSize(StringRef ArgName, size_t Pad = DefaultPad) { size_t Len = ArgName.size(); if (Len == 1) - return Len + ArgPrefix.size() + ArgHelpPrefix.size(); - return Len + ArgPrefixLong.size() + ArgHelpPrefix.size(); + return Len + Pad + ArgPrefix.size() + ArgHelpPrefix.size(); + return Len + Pad + ArgPrefixLong.size() + ArgHelpPrefix.size(); } -static StringRef argPrefix(StringRef ArgName) { - if (ArgName.size() == 1) - return ArgPrefix; - return ArgPrefixLong; +static SmallString<8> argPrefix(StringRef ArgName, size_t Pad = DefaultPad) { + SmallString<8> Prefix; + for (size_t I = 0; I < Pad; ++I) { + Prefix.push_back(' '); + } + Prefix.append(ArgName.size() > 1 ? ArgPrefixLong : ArgPrefix); + return Prefix; } // Option predicates... @@ -119,13 +124,14 @@ class PrintArg { StringRef ArgName; + size_t Pad; public: - PrintArg(StringRef ArgName) : ArgName(ArgName) {} - friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg&); + PrintArg(StringRef ArgName, size_t Pad = DefaultPad) : ArgName(ArgName), Pad(Pad) {} + friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg &); }; raw_ostream &operator<<(raw_ostream &OS, const PrintArg& Arg) { - OS << argPrefix(Arg.ArgName) << Arg.ArgName; + OS << argPrefix(Arg.ArgName, Arg.Pad) << Arg.ArgName; return OS; } @@ -1447,7 +1453,7 @@ if (NearestHandler) { // If we know a near match, report it as well. *Errs << ProgramName << ": Did you mean '" - << PrintArg(NearestHandlerString) << "'?\n"; + << PrintArg(NearestHandlerString, 0) << "'?\n"; } ErrorParsing = true; @@ -1601,7 +1607,7 @@ if (ArgName.empty()) Errs << HelpStr; // Be nice for positional arguments else - Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName); + Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName, 0); Errs << " option: " << Message << "\n"; return true; diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp --- a/llvm/unittests/Support/CommandLineTest.cpp +++ b/llvm/unittests/Support/CommandLineTest.cpp @@ -1653,4 +1653,54 @@ EXPECT_TRUE(Errs.empty()); Errs.clear(); cl::ResetAllOptionOccurrences(); } + +TEST(CommandLineTest, OptionErrorMessage) { + // When there is an error, we expect some error message like: + // prog: for the -a option: [...] + // + // Test whether the "for the -a option"-part is correctly formatted. + cl::ResetCommandLineParser(); + + StackOption OptA("a", cl::desc("Some option")); + StackOption OptLong("long", cl::desc("Some long option")); + + std::string Errs; + raw_string_ostream OS(Errs); + + OptA.error("custom error", OS); + OS.flush(); + EXPECT_FALSE(Errs.find("for the -a option:") == std::string::npos); + Errs.clear(); + + OptLong.error("custom error", OS); + OS.flush(); + EXPECT_FALSE(Errs.find("for the --long option:") == std::string::npos); + Errs.clear(); + + cl::ResetAllOptionOccurrences(); +} + +TEST(CommandLineTest, OptionErrorMessageSuggest) { + // When there is an error, and the edit-distance is not very large, + // we expect some error message like: + // prog: did you mean '--option'? + // + // Test whether this message is well-formatted. + cl::ResetCommandLineParser(); + + StackOption OptLong("aluminium", cl::desc("Some long option")); + + const char *args[] = {"prog", "--aluminum"}; + + std::string Errs; + raw_string_ostream OS(Errs); + + EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS)); + OS.flush(); + EXPECT_FALSE(Errs.find("prog: Did you mean '--aluminium'?\n") == + std::string::npos); + Errs.clear(); + + cl::ResetAllOptionOccurrences(); +} } // anonymous namespace