Use matcher's description in AllOf if matcher has no explanation.

PiperOrigin-RevId: 652798234
Change-Id: I8e92248a2d9faf2a5719fe220145ea563acc14ff
This commit is contained in:
Abseil Team
2024-07-16 05:22:04 -07:00
committed by Copybara-Service
parent 417158b8bc
commit d49a665484
3 changed files with 23 additions and 39 deletions

View File

@@ -1300,48 +1300,34 @@ class AllOfMatcherImpl : public MatcherInterface<const T&> {
bool MatchAndExplain(const T& x,
MatchResultListener* listener) const override {
// This method uses matcher's explanation when explaining the result.
// However, if matcher doesn't provide one, this method uses matcher's
// description.
// If either matcher1_ or matcher2_ doesn't match x, we only need
// to explain why one of them fails.
std::string all_match_result;
for (const Matcher<T>& matcher : matchers_) {
for (size_t i = 0; i < matchers_.size(); ++i) {
StringMatchResultListener slistener;
// Return explanation for first failed matcher.
if (!matcher.MatchAndExplain(x, &slistener)) {
const std::string explanation = slistener.str();
if (!explanation.empty()) {
*listener << explanation;
if (matchers_[i].MatchAndExplain(x, &slistener)) {
if (all_match_result.empty()) {
all_match_result = slistener.str();
} else {
*listener << "which doesn't match (" << Describe(matcher) << ")";
std::string result = slistener.str();
if (!result.empty()) {
all_match_result += ", and ";
all_match_result += result;
}
}
return false;
}
// Keep track of explanations in case all matchers succeed.
std::string explanation = slistener.str();
if (explanation.empty()) {
explanation = Describe(matcher);
}
if (all_match_result.empty()) {
all_match_result = explanation;
} else {
if (!explanation.empty()) {
all_match_result += ", and ";
all_match_result += explanation;
}
*listener << slistener.str();
return false;
}
}
// Otherwise we need to explain why *both* of them match.
*listener << all_match_result;
return true;
}
private:
// Returns matcher description as a string.
std::string Describe(const Matcher<T>& matcher) const {
StringMatchResultListener listener;
matcher.DescribeTo(listener.stream());
return listener.str();
}
const std::vector<Matcher<T>> matchers_;
};