]> granicus.if.org Git - llvm/commitdiff
Fix OptTable::findNearest() adding delimiter for free
authorNico Weber <nicolasweber@gmx.de>
Wed, 1 May 2019 14:46:17 +0000 (14:46 +0000)
committerNico Weber <nicolasweber@gmx.de>
Wed, 1 May 2019 14:46:17 +0000 (14:46 +0000)
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

lib/Option/OptTable.cpp
unittests/Option/OptionParsingTest.cpp
unittests/Option/Opts.td

index 944de9f417e50dafb4e0026ab3f6a7a8c825bdd6..47c5f80c7d70fc7a96c01902e6dd74861af7e41c 100644 (file)
@@ -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 =
index f6b6b95a209ba299269fc93f62648b59a554d590..ee741c25d059bdde44fd2e9dbbd3582e70d17328 100644 (file)
@@ -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");
index e6151d375ef4c3c6a434e11793006814072b2a31..231af4914d85bee40615c54d2d50fd821f38bf26 100644 (file)
@@ -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>;