From b7c82b26b03349d1201a24acbe198ee1bd00ee3e Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 18 Jul 2022 16:54:13 -0400 Subject: cmArgumentParser: Capture keyword errors in parse results Since commit f46b2e9142 (cmArgumentParser: Model maybe-missing string with wrapper type, 2022-07-06) we know during parsing whether or not it is an error for a keyword to be missing a value. Record such errors in the parse results structure. Offer clients a helper method to report them. This provides clients with an alternative to manually checking `keywordsMissingValue` and generating their own error message. --- Source/cmArgumentParser.cxx | 20 ++++++++++++++++++++ Source/cmArgumentParser.h | 20 +++++++++++++++++++- Tests/CMakeLib/testArgumentParser.cxx | 18 ++++++++++++++++-- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx index c997933..25d5c68 100644 --- a/Source/cmArgumentParser.cxx +++ b/Source/cmArgumentParser.cxx @@ -5,6 +5,9 @@ #include #include "cmArgumentParserTypes.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" namespace ArgumentParser { @@ -106,10 +109,27 @@ void Instance::FinishKeyword() return; } if (this->ExpectValue) { + if (this->ParseResults != nullptr) { + this->ParseResults->AddKeywordError(this->Keyword, + " missing required value\n"); + } if (this->KeywordsMissingValue != nullptr) { this->KeywordsMissingValue->emplace_back(this->Keyword); } } } +bool ParseResult::MaybeReportError(cmMakefile& mf) const +{ + if (*this) { + return false; + } + std::string e; + for (auto const& ke : this->KeywordErrors) { + e = cmStrCat(e, "Error after keyword \"", ke.first, "\":\n", ke.second); + } + mf.IssueMessage(MessageType::FATAL_ERROR, e); + return true; +} + } // namespace ArgumentParser diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h index 0078c04..8fda8b7 100644 --- a/Source/cmArgumentParser.h +++ b/Source/cmArgumentParser.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -20,12 +21,29 @@ template class cmArgumentParser; // IWYU pragma: keep +class cmMakefile; + namespace ArgumentParser { class ParseResult { + std::map KeywordErrors; + public: - explicit operator bool() const { return true; } + explicit operator bool() const { return this->KeywordErrors.empty(); } + + void AddKeywordError(cm::string_view key, cm::string_view text) + + { + this->KeywordErrors[key] += text; + } + + std::map const& GetKeywordErrors() const + { + return this->KeywordErrors; + } + + bool MaybeReportError(cmMakefile& mf) const; }; template diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx index 054cfd5..f0ace50 100644 --- a/Tests/CMakeLib/testArgumentParser.cxx +++ b/Tests/CMakeLib/testArgumentParser.cxx @@ -3,7 +3,9 @@ #include #include +#include #include +#include #include #include @@ -69,6 +71,11 @@ bool verifyResult(Result const& result, static std::vector const missing = { "STRING_1"_s, "LIST_1"_s, "LIST_4"_s }; + static std::map const keywordErrors = { + { "STRING_1"_s, " missing required value\n" }, + { "LIST_1"_s, " missing required value\n" }, + { "LIST_4"_s, " missing required value\n" } + }; #define ASSERT_TRUE(x) \ do { \ @@ -78,7 +85,7 @@ bool verifyResult(Result const& result, } \ } while (false) - ASSERT_TRUE(result); + ASSERT_TRUE(!result); ASSERT_TRUE(result.Option1); ASSERT_TRUE(!result.Option2); @@ -112,6 +119,13 @@ bool verifyResult(Result const& result, ASSERT_TRUE(unparsedArguments[0] == "bar"); ASSERT_TRUE(keywordsMissingValue == missing); + ASSERT_TRUE(result.GetKeywordErrors().size() == keywordErrors.size()); + for (auto const& ke : result.GetKeywordErrors()) { + auto const ki = keywordErrors.find(ke.first); + ASSERT_TRUE(ki != keywordErrors.end()); + ASSERT_TRUE(ke.second == ki->second); + } + return true; } @@ -179,7 +193,7 @@ bool testArgumentParserStaticBool() std::vector keywordsMissingValue; Result result; ASSERT_TRUE(parserStatic.Parse(result, args, &unparsedArguments, - &keywordsMissingValue) == true); + &keywordsMissingValue) == false); return verifyResult(result, unparsedArguments, keywordsMissingValue); } -- cgit v0.12