Re-push "[Option] Fix PR37006 prefix choice in findNearest"
Summary: Original changeset (https://reviews.llvm.org/D46776) by @modocache. It was reverted after the PS4 bot failed. The issue has been determined to be with the way the PS4 SDK handles this particular option. https://reviews.llvm.org/D50410 removes this test, so we can push this again. Patch by Arnaud Coomans! Reviewers: cfe-commits, modocache Reviewed By: modocache Differential Revision: https://reviews.llvm.org/D50515 llvm-svn: 341329
This commit is contained in:
parent
96c13488ab
commit
f534485387
|
@ -252,38 +252,33 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
|
||||||
unsigned MinimumLength) const {
|
unsigned MinimumLength) const {
|
||||||
assert(!Option.empty());
|
assert(!Option.empty());
|
||||||
|
|
||||||
// Consider each option as a candidate, finding the closest match.
|
// Consider each [option prefix + option name] pair as a candidate, finding
|
||||||
|
// the closest match.
|
||||||
unsigned BestDistance = UINT_MAX;
|
unsigned BestDistance = UINT_MAX;
|
||||||
for (const Info &CandidateInfo :
|
for (const Info &CandidateInfo :
|
||||||
ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
|
ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
|
||||||
StringRef CandidateName = CandidateInfo.Name;
|
StringRef CandidateName = CandidateInfo.Name;
|
||||||
|
|
||||||
// Ignore option candidates with empty names, such as "--", or names
|
// We can eliminate some option prefix/name pairs as candidates right away:
|
||||||
// that do not meet the minimum length.
|
// * Ignore option candidates with empty names, such as "--", or names
|
||||||
|
// that do not meet the minimum length.
|
||||||
if (CandidateName.empty() || CandidateName.size() < MinimumLength)
|
if (CandidateName.empty() || CandidateName.size() < MinimumLength)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If FlagsToInclude were specified, ignore options that don't include
|
// * If FlagsToInclude were specified, ignore options that don't include
|
||||||
// those flags.
|
// those flags.
|
||||||
if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
|
if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
|
||||||
continue;
|
continue;
|
||||||
// Ignore options that contain the FlagsToExclude.
|
// * Ignore options that contain the FlagsToExclude.
|
||||||
if (CandidateInfo.Flags & FlagsToExclude)
|
if (CandidateInfo.Flags & FlagsToExclude)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Ignore positional argument option candidates (which do not
|
// * Ignore positional argument option candidates (which do not
|
||||||
// have prefixes).
|
// have prefixes).
|
||||||
if (!CandidateInfo.Prefixes)
|
if (!CandidateInfo.Prefixes)
|
||||||
continue;
|
continue;
|
||||||
// Find the most appropriate prefix. For example, if a user asks for
|
|
||||||
// "--helm", suggest "--help" over "-help".
|
|
||||||
StringRef Prefix = CandidateInfo.Prefixes[0];
|
|
||||||
for (int P = 1; CandidateInfo.Prefixes[P]; P++) {
|
|
||||||
if (Option.startswith(CandidateInfo.Prefixes[P]))
|
|
||||||
Prefix = CandidateInfo.Prefixes[P];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the candidate ends with a character commonly used when
|
// Now check if the candidate ends with a character commonly used when
|
||||||
// delimiting an option from its value, such as '=' or ':'. If it does,
|
// delimiting an option from its value, such as '=' or ':'. If it does,
|
||||||
// attempt to split the given option based on that delimiter.
|
// attempt to split the given option based on that delimiter.
|
||||||
std::string Delimiter = "";
|
std::string Delimiter = "";
|
||||||
|
@ -297,14 +292,19 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
|
||||||
else
|
else
|
||||||
std::tie(LHS, RHS) = Option.split(Last);
|
std::tie(LHS, RHS) = Option.split(Last);
|
||||||
|
|
||||||
std::string NormalizedName =
|
// Consider each possible prefix for each candidate to find the most
|
||||||
(LHS.drop_front(Prefix.size()) + Delimiter).str();
|
// appropriate one. For example, if a user asks for "--helm", suggest
|
||||||
unsigned Distance =
|
// "--help" over "-help".
|
||||||
CandidateName.edit_distance(NormalizedName, /*AllowReplacements=*/true,
|
for (int P = 0; const char *const CandidatePrefix = CandidateInfo.Prefixes[P]; P++) {
|
||||||
/*MaxEditDistance=*/BestDistance);
|
std::string NormalizedName = (LHS + Delimiter).str();
|
||||||
if (Distance < BestDistance) {
|
StringRef Candidate = (CandidatePrefix + CandidateName).str();
|
||||||
BestDistance = Distance;
|
unsigned Distance =
|
||||||
NearestString = (Prefix + CandidateName + RHS).str();
|
Candidate.edit_distance(NormalizedName, /*AllowReplacements=*/true,
|
||||||
|
/*MaxEditDistance=*/BestDistance);
|
||||||
|
if (Distance < BestDistance) {
|
||||||
|
BestDistance = Distance;
|
||||||
|
NearestString = (Candidate + RHS).str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BestDistance;
|
return BestDistance;
|
||||||
|
|
|
@ -283,6 +283,10 @@ TEST(Option, FindNearest) {
|
||||||
EXPECT_EQ(Nearest, "-blorp");
|
EXPECT_EQ(Nearest, "-blorp");
|
||||||
EXPECT_EQ(1U, T.findNearest("--blorm", Nearest));
|
EXPECT_EQ(1U, T.findNearest("--blorm", Nearest));
|
||||||
EXPECT_EQ(Nearest, "--blorp");
|
EXPECT_EQ(Nearest, "--blorp");
|
||||||
|
EXPECT_EQ(1U, T.findNearest("-blarg", Nearest));
|
||||||
|
EXPECT_EQ(Nearest, "-blarn");
|
||||||
|
EXPECT_EQ(1U, T.findNearest("--blarm", Nearest));
|
||||||
|
EXPECT_EQ(Nearest, "--blarn");
|
||||||
EXPECT_EQ(1U, T.findNearest("-fjormp", Nearest));
|
EXPECT_EQ(1U, T.findNearest("-fjormp", Nearest));
|
||||||
EXPECT_EQ(Nearest, "--fjormp");
|
EXPECT_EQ(Nearest, "--fjormp");
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ def Slurp : Option<["-"], "slurp", KIND_REMAINING_ARGS>;
|
||||||
def SlurpJoined : Option<["-"], "slurpjoined", KIND_REMAINING_ARGS_JOINED>;
|
def SlurpJoined : Option<["-"], "slurpjoined", KIND_REMAINING_ARGS_JOINED>;
|
||||||
|
|
||||||
def Blorp : Flag<["-", "--"], "blorp">, HelpText<"The blorp option">, Flags<[OptFlag1]>;
|
def Blorp : Flag<["-", "--"], "blorp">, HelpText<"The blorp option">, Flags<[OptFlag1]>;
|
||||||
|
def Blarn : Flag<["--", "-"], "blarn">, HelpText<"The blarn option">, Flags<[OptFlag1]>;
|
||||||
def Cramb : Joined<["/"], "cramb:">, HelpText<"The cramb option">, MetaVarName<"CRAMB">, Flags<[OptFlag1]>;
|
def Cramb : Joined<["/"], "cramb:">, HelpText<"The cramb option">, MetaVarName<"CRAMB">, Flags<[OptFlag1]>;
|
||||||
def Doopf1 : Flag<["-"], "doopf1">, HelpText<"The doopf1 option">, Flags<[OptFlag1]>;
|
def Doopf1 : Flag<["-"], "doopf1">, HelpText<"The doopf1 option">, Flags<[OptFlag1]>;
|
||||||
def Doopf2 : Flag<["-"], "doopf2">, HelpText<"The doopf2 option">, Flags<[OptFlag2]>;
|
def Doopf2 : Flag<["-"], "doopf2">, HelpText<"The doopf2 option">, Flags<[OptFlag2]>;
|
||||||
|
|
Loading…
Reference in New Issue