From 859a40b291580b0d7e5a6405f63331bb49d4a80a Mon Sep 17 00:00:00 2001 From: Tyler Yankee Date: Sun, 1 Nov 2026 13:30:48 -0500 Subject: [PATCH] cmSubcommandTable: Implement closest string for invalid subcommand --- .codespellrc | 1 + Source/cmSubcommandTable.cxx | 13 ++++++++++++- .../list/InvalidSubcommandDidYouMean-result.txt | 1 + .../list/InvalidSubcommandDidYouMean-stderr.txt | 4 ++++ .../RunCMake/list/InvalidSubcommandDidYouMean.cmake | 1 + Tests/RunCMake/list/RunCMakeTest.cmake | 1 + 6 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/list/InvalidSubcommandDidYouMean-result.txt create mode 100644 Tests/RunCMake/list/InvalidSubcommandDidYouMean-stderr.txt create mode 100644 Tests/RunCMake/list/InvalidSubcommandDidYouMean.cmake diff --git a/.codespellrc b/.codespellrc index 94fa8e84ad..01ea2152b7 100644 --- a/.codespellrc +++ b/.codespellrc @@ -17,6 +17,7 @@ skip = Source/kwsys/*, Tests/RunCMake/CPack/tests/DMG_SLA/German.*, Tests/RunCMake/CommandLine/RunCMakeTest.cmake, + Tests/RunCMake/list/InvalidSubcommandDidYouMean*, Tests/RunCMake/ParseImplicitData/*.input, Tests/RunCMake/cmake_language/call_typo_function.cmake, Tests/StringFileTest/test.utf8, diff --git a/Source/cmSubcommandTable.cxx b/Source/cmSubcommandTable.cxx index d1d35d5ad2..4fa82fc54a 100644 --- a/Source/cmSubcommandTable.cxx +++ b/Source/cmSubcommandTable.cxx @@ -26,6 +26,17 @@ bool cmSubcommandTable::operator()(cm::string_view key, if (it != this->Impl.end() && it->first == key) { return it->second(args, status); } - status.SetError(cmStrCat("does not recognize sub-command ", key)); + std::string error = cmStrCat("does not recognize sub-command ", key); + std::vector candidates; + candidates.reserve(this->Impl.size()); + for (Elem const& elem : this->Impl) { + candidates.emplace_back(elem.first); + } + std::string const suggestion = cmFindClosestString(key, candidates); + if (!suggestion.empty()) { + error = + cmStrCat(std::move(error), ". Did you mean: \"", suggestion, "\"?"); + } + status.SetError(error); return false; } diff --git a/Tests/RunCMake/list/InvalidSubcommandDidYouMean-result.txt b/Tests/RunCMake/list/InvalidSubcommandDidYouMean-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/list/InvalidSubcommandDidYouMean-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/list/InvalidSubcommandDidYouMean-stderr.txt b/Tests/RunCMake/list/InvalidSubcommandDidYouMean-stderr.txt new file mode 100644 index 0000000000..29c9767d0a --- /dev/null +++ b/Tests/RunCMake/list/InvalidSubcommandDidYouMean-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at InvalidSubcommandDidYouMean\.cmake:1 \(list\): + list does not recognize sub-command APEND\. Did you mean: "APPEND"\? +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\)$ diff --git a/Tests/RunCMake/list/InvalidSubcommandDidYouMean.cmake b/Tests/RunCMake/list/InvalidSubcommandDidYouMean.cmake new file mode 100644 index 0000000000..7913e1c9b0 --- /dev/null +++ b/Tests/RunCMake/list/InvalidSubcommandDidYouMean.cmake @@ -0,0 +1 @@ +list(APEND mylist a) diff --git a/Tests/RunCMake/list/RunCMakeTest.cmake b/Tests/RunCMake/list/RunCMakeTest.cmake index a3b48c8978..29432cb7f0 100644 --- a/Tests/RunCMake/list/RunCMakeTest.cmake +++ b/Tests/RunCMake/list/RunCMakeTest.cmake @@ -7,6 +7,7 @@ run_cmake(EmptyInsert-1) run_cmake(NoArguments) run_cmake(InvalidSubcommand) +run_cmake(InvalidSubcommandDidYouMean) run_cmake(FILTER-REGEX-InvalidRegex) run_cmake(GET-InvalidIndex)