mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-01 12:55:40 +02:00
Fix CAPTURE macro for nontrivial uses
The previous implemetation was just plain broken for most of possible uses, the new one should work (even though it is ugly as all hell, and should be improved ASAP). Fixes #1436
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "catch_uncaught_exceptions.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stack>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -60,19 +61,48 @@ namespace Catch {
|
||||
|
||||
|
||||
Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
|
||||
auto start = std::string::npos;
|
||||
for( size_t pos = 0; pos <= names.size(); ++pos ) {
|
||||
auto trimmed = [&] (size_t start, size_t end) {
|
||||
while (names[start] == ',' || isspace(names[start])) {
|
||||
++start;
|
||||
}
|
||||
while (names[end] == ',' || isspace(names[end])) {
|
||||
--end;
|
||||
}
|
||||
return names.substr(start, end - start + 1);
|
||||
};
|
||||
|
||||
size_t start = 0;
|
||||
std::stack<char> openings;
|
||||
for (size_t pos = 0; pos < names.size(); ++pos) {
|
||||
char c = names[pos];
|
||||
if( pos == names.size() || c == ' ' || c == '\t' || c == ',' || c == ']' ) {
|
||||
if( start != std::string::npos ) {
|
||||
m_messages.push_back( MessageInfo( macroName, lineInfo, resultType ) );
|
||||
m_messages.back().message = names.substr( start, pos-start) + " := ";
|
||||
start = std::string::npos;
|
||||
switch (c) {
|
||||
case '[':
|
||||
case '{':
|
||||
case '(':
|
||||
// It is basically impossible to disambiguate between
|
||||
// comparison and start of template args in this context
|
||||
// case '<':
|
||||
openings.push(c);
|
||||
break;
|
||||
case ']':
|
||||
case '}':
|
||||
case ')':
|
||||
// case '>':
|
||||
openings.pop();
|
||||
break;
|
||||
case ',':
|
||||
if (start != pos && openings.size() == 0) {
|
||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||
m_messages.back().message = trimmed(start, pos);
|
||||
m_messages.back().message += " := ";
|
||||
start = pos;
|
||||
}
|
||||
}
|
||||
else if( c != '[' && c != ']' && start == std::string::npos )
|
||||
start = pos;
|
||||
}
|
||||
assert(openings.size() == 0 && "Mismatched openings");
|
||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||
m_messages.back().message = trimmed(start, names.size() - 1);
|
||||
m_messages.back().message += " := ";
|
||||
}
|
||||
Capturer::~Capturer() {
|
||||
if ( !uncaught_exceptions() ){
|
||||
@@ -82,7 +112,7 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void Capturer::captureValue( size_t index, StringRef value ) {
|
||||
void Capturer::captureValue( size_t index, std::string const& value ) {
|
||||
assert( index < m_messages.size() );
|
||||
m_messages[index].message += value;
|
||||
m_resultCapture.pushScopedMessage( m_messages[index] );
|
||||
|
@@ -77,16 +77,16 @@ namespace Catch {
|
||||
Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
|
||||
~Capturer();
|
||||
|
||||
void captureValue( size_t index, StringRef value );
|
||||
void captureValue( size_t index, std::string const& value );
|
||||
|
||||
template<typename T>
|
||||
void captureValues( size_t index, T&& value ) {
|
||||
void captureValues( size_t index, T const& value ) {
|
||||
captureValue( index, Catch::Detail::stringify( value ) );
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
void captureValues( size_t index, T&& value, Ts&&... values ) {
|
||||
captureValues( index, value );
|
||||
void captureValues( size_t index, T const& value, Ts const&... values ) {
|
||||
captureValue( index, Catch::Detail::stringify(value) );
|
||||
captureValues( index+1, values... );
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user