From: Nico Weber Date: Wed, 1 May 2019 14:46:17 +0000 (+0000) Subject: Fix OptTable::findNearest() adding delimiter for free X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28a57e37b20cedebd1adc5117eebf871c2c81731;p=llvm Fix OptTable::findNearest() adding delimiter for free Prior to this, OptTable::findNearest() thought that the input `--foo` had an editing distance of 0 from an existing flag `--foo=`, which made it suggest flags with delimiters more often than flags without one. After this, it correctly assigns this case an editing distance of 1. Differential Revision: https://reviews.llvm.org/D61373 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359685 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Option/OptTable.cpp b/lib/Option/OptTable.cpp index 944de9f417e..47c5f80c7d7 100644 --- a/lib/Option/OptTable.cpp +++ b/lib/Option/OptTable.cpp @@ -280,23 +280,22 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString, // Now check if the candidate ends with a character commonly used when // delimiting an option from its value, such as '=' or ':'. If it does, // attempt to split the given option based on that delimiter. - std::string Delimiter = ""; - char Last = CandidateName.back(); - if (Last == '=' || Last == ':') - Delimiter = std::string(1, Last); - StringRef LHS, RHS; - if (Delimiter.empty()) - LHS = Option; - else + char Last = CandidateName.back(); + bool CandidateHasDelimiter = Last == '=' || Last == ':'; + std::string NormalizedName = Option; + if (CandidateHasDelimiter) { std::tie(LHS, RHS) = Option.split(Last); + NormalizedName = LHS; + if (Option.find(Last) == LHS.size()) + NormalizedName += Last; + } // Consider each possible prefix for each candidate to find the most // appropriate one. For example, if a user asks for "--helm", suggest // "--help" over "-help". for (int P = 0; const char *const CandidatePrefix = CandidateInfo.Prefixes[P]; P++) { - std::string NormalizedName = (LHS + Delimiter).str(); std::string Candidate = (CandidatePrefix + CandidateName).str(); StringRef CandidateRef = Candidate; unsigned Distance = diff --git a/unittests/Option/OptionParsingTest.cpp b/unittests/Option/OptionParsingTest.cpp index f6b6b95a209..ee741c25d05 100644 --- a/unittests/Option/OptionParsingTest.cpp +++ b/unittests/Option/OptionParsingTest.cpp @@ -298,6 +298,11 @@ TEST(Option, FindNearest) { EXPECT_EQ(1U, T.findNearest("/framb:foo", Nearest)); EXPECT_EQ(Nearest, "/cramb:foo"); + // `--glormp` should have an editing distance of 1 to `--glormp=`. + EXPECT_EQ(1U, T.findNearest("--glormp", Nearest)); + EXPECT_EQ(Nearest, "--glormp="); + EXPECT_EQ(0U, T.findNearest("--glormp=foo", Nearest)); + // Flags should be included and excluded as specified. EXPECT_EQ(1U, T.findNearest("-doopf", Nearest, /*FlagsToInclude=*/OptFlag2)); EXPECT_EQ(Nearest, "-doopf2"); diff --git a/unittests/Option/Opts.td b/unittests/Option/Opts.td index e6151d375ef..231af4914d8 100644 --- a/unittests/Option/Opts.td +++ b/unittests/Option/Opts.td @@ -36,4 +36,7 @@ def Doopf1 : Flag<["-"], "doopf1">, HelpText<"The doopf1 option">, Flags<[OptFla def Doopf2 : Flag<["-"], "doopf2">, HelpText<"The doopf2 option">, Flags<[OptFlag2]>; def Ermgh : Joined<["--"], "ermgh">, HelpText<"The ermgh option">, MetaVarName<"ERMGH">, Flags<[OptFlag1]>; def Fjormp : Flag<["--"], "fjormp">, HelpText<"The fjormp option">, Flags<[OptFlag1]>; + +def Glormp_eq : Flag<["--"], "glormp=">; + def DashDash : Option<["--"], "", KIND_REMAINING_ARGS>;