@@ -324,6 +324,13 @@ class CommandLineParser {
324
324
return false ;
325
325
}
326
326
327
+ bool hasNamedSubCommands () const {
328
+ for (const auto *S : RegisteredSubCommands)
329
+ if (!S->getName ().empty ())
330
+ return true ;
331
+ return false ;
332
+ }
333
+
327
334
SubCommand *getActiveSubCommand () { return ActiveSubCommand; }
328
335
329
336
void updateArgStr (Option *O, StringRef NewName, SubCommand *SC) {
@@ -425,7 +432,7 @@ class CommandLineParser {
425
432
return nullptr ;
426
433
return Opt;
427
434
}
428
- SubCommand *LookupSubCommand (StringRef Name);
435
+ SubCommand *LookupSubCommand (StringRef Name, std::string &NearestString );
429
436
};
430
437
431
438
} // namespace
@@ -550,9 +557,12 @@ Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
550
557
return I->second ;
551
558
}
552
559
553
- SubCommand *CommandLineParser::LookupSubCommand (StringRef Name) {
560
+ SubCommand *CommandLineParser::LookupSubCommand (StringRef Name,
561
+ std::string &NearestString) {
554
562
if (Name.empty ())
555
563
return &SubCommand::getTopLevel ();
564
+ // Find a subcommand with the edit distance == 1.
565
+ SubCommand *NearestMatch = nullptr ;
556
566
for (auto *S : RegisteredSubCommands) {
557
567
if (S == &SubCommand::getAll ())
558
568
continue ;
@@ -561,7 +571,14 @@ SubCommand *CommandLineParser::LookupSubCommand(StringRef Name) {
561
571
562
572
if (StringRef (S->getName ()) == StringRef (Name))
563
573
return S;
574
+
575
+ if (!NearestMatch && S->getName ().edit_distance (Name) < 2 )
576
+ NearestMatch = S;
564
577
}
578
+
579
+ if (NearestMatch)
580
+ NearestString = NearestMatch->getName ();
581
+
565
582
return &SubCommand::getTopLevel ();
566
583
}
567
584
@@ -1527,10 +1544,14 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
1527
1544
1528
1545
int FirstArg = 1 ;
1529
1546
SubCommand *ChosenSubCommand = &SubCommand::getTopLevel ();
1530
- if (argc >= 2 && argv[FirstArg][0 ] != ' -' ) {
1547
+ std::string NearestSubCommandString;
1548
+ bool MaybeNamedSubCommand =
1549
+ argc >= 2 && argv[FirstArg][0 ] != ' -' && hasNamedSubCommands ();
1550
+ if (MaybeNamedSubCommand) {
1531
1551
// If the first argument specifies a valid subcommand, start processing
1532
1552
// options from the second argument.
1533
- ChosenSubCommand = LookupSubCommand (StringRef (argv[FirstArg]));
1553
+ ChosenSubCommand =
1554
+ LookupSubCommand (StringRef (argv[FirstArg]), NearestSubCommandString);
1534
1555
if (ChosenSubCommand != &SubCommand::getTopLevel ())
1535
1556
FirstArg = 2 ;
1536
1557
}
@@ -1687,21 +1708,35 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
1687
1708
}
1688
1709
1689
1710
if (!Handler) {
1690
- if (SinkOpts.empty ()) {
1691
- *Errs << ProgramName << " : Unknown command line argument '" << argv[i]
1692
- << " '. Try: '" << argv[0 ] << " --help'\n " ;
1693
-
1694
- if (NearestHandler) {
1695
- // If we know a near match, report it as well.
1696
- *Errs << ProgramName << " : Did you mean '"
1697
- << PrintArg (NearestHandlerString, 0 ) << " '?\n " ;
1698
- }
1699
-
1700
- ErrorParsing = true ;
1701
- } else {
1711
+ if (!SinkOpts.empty ()) {
1702
1712
for (Option *SinkOpt : SinkOpts)
1703
1713
SinkOpt->addOccurrence (i, " " , StringRef (argv[i]));
1714
+ continue ;
1704
1715
}
1716
+
1717
+ auto ReportUnknownArgument = [&](bool IsArg,
1718
+ StringRef NearestArgumentName) {
1719
+ *Errs << ProgramName << " : Unknown "
1720
+ << (IsArg ? " command line argument" : " subcommand" ) << " '"
1721
+ << argv[i] << " '. Try: '" << argv[0 ] << " --help'\n " ;
1722
+
1723
+ if (NearestArgumentName.empty ())
1724
+ return ;
1725
+
1726
+ *Errs << ProgramName << " : Did you mean '" ;
1727
+ if (IsArg)
1728
+ *Errs << PrintArg (NearestArgumentName, 0 );
1729
+ else
1730
+ *Errs << NearestArgumentName;
1731
+ *Errs << " '?\n " ;
1732
+ };
1733
+
1734
+ if (i > 1 || !MaybeNamedSubCommand)
1735
+ ReportUnknownArgument (/* IsArg=*/ true , NearestHandlerString);
1736
+ else
1737
+ ReportUnknownArgument (/* IsArg=*/ false , NearestSubCommandString);
1738
+
1739
+ ErrorParsing = true ;
1705
1740
continue ;
1706
1741
}
1707
1742
0 commit comments