#ifndef TESTS_SRDPREPROCLOCATION_H_ #define TESTS_SRDPREPROCLOCATION_H_ #include #include #include #include #include using namespace lw; namespace { inline T_SRDLocationChaining const* NextChain_( T_SRDLocation const* from ) noexcept { return (from && from->isChained( ) ) ? &from->chaining( ) : nullptr; } uint32_t LocationDepth_( const RPC_SRDLocation location ) noexcept { uint32_t depth( 0 ); auto lc( NextChain_( location ) ); while ( lc ) { depth ++; lc = NextChain_( RPC_SRDLocation( lc->location ) ); } return depth; } uint32_t ErrorDepth_( T_SRDErrors const& errors , const size_t index ) noexcept { auto const& error( errors[ index ] ); return LocationDepth_( &error.location( ) ); } uint32_t TokenDepth_( T_SRDList const& tokens , const size_t index ) noexcept { auto const& tok( tokens[ index ] ); assert( tok.hasLocation( ) ); return LocationDepth_( &tok.location( ) ); } T_SRDLocationChaining const& GetChain_( RPC_SRDLocation const& top , uint32_t depth ) noexcept { auto lc( NextChain_( top ) ); assert( lc ); while ( depth ) { depth --; lc = NextChain_( RPC_SRDLocation( lc->location ) ); assert( lc ); } return *lc; } void PrintLoc_( RPC_SRDLocation location ) noexcept { printf( "at %s, l. %d c. %lu\n" , location->source( ).toOSString( ).data( ) , location->line( ) , location->character( ) ); if ( location->isChained( ) ) { auto const& chain( location->chaining( ) ); printf( "\tChain type %d, depth %d, " , int( chain.circumstances ) , chain.depth ); PrintLoc_( RPC_SRDLocation( chain.location ) ); } } } #define M_CKTOKDEPTH_( IDX , DEPTH ) \ CPPUNIT_ASSERT_EQUAL( uint32_t( DEPTH ) , TokenDepth_( output , IDX ) ) #define M_CKTOKLOC_( IDX , NAME , LINE , CHAR ) \ do { \ auto const& loc( output[ IDX ].location( ) ); \ CPPUNIT_ASSERT( T_String{ NAME } == loc.source( ) ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , loc.line( ) ); \ CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , loc.character( ) ); \ } while ( 0 ) #define M_CKTOKFULL_( IDX , NAME , LINE , CHAR , DEPTH ) \ do { \ auto const& loc( output[ IDX ].location( ) ); \ CPPUNIT_ASSERT( T_String{ NAME } == loc.source( ) ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , loc.line( ) ); \ CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , loc.character( ) ); \ M_CKTOKDEPTH_( IDX , DEPTH ); \ } while ( 0 ) #define M_CKTOKCHAIN_( IDX , DEPTH , HOW , NAME , LINE , CHAR , REC ) \ do { \ auto const& chain( GetChain_( &output[ IDX ].location( ) , DEPTH ) ); \ CPPUNIT_ASSERT( E_SRDLocationChaining::HOW == chain.circumstances ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( REC ) , chain.depth ); \ CPPUNIT_ASSERT( T_String{ NAME } == chain.location->source( ) ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , chain.location->line( ) ); \ CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , chain.location->character( ) ); \ } while ( 0 ) #define M_CKERRDEPTH_( IDX , DEPTH ) \ CPPUNIT_ASSERT_EQUAL( uint32_t( DEPTH ) , ErrorDepth_( errors , IDX ) ) #define M_CKERRFULL_( IDX , TEXT , DETAILS , NAME , LINE , CHAR , DEPTH ) \ do { \ CPPUNIT_ASSERT( T_String{ TEXT } == errors[ IDX ].error( ) ); \ CPPUNIT_ASSERT_EQUAL( bool( DETAILS ) , errors[ IDX ].isDetails( ) ); \ auto const& loc( errors[ IDX ].location( ) ); \ CPPUNIT_ASSERT( T_String{ NAME } == loc.source( ) ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , loc.line( ) ); \ CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , loc.character( ) ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( DEPTH ) , ErrorDepth_( errors , IDX ) ); \ } while ( 0 ) #define M_CKERRCHAIN_( IDX , DEPTH , HOW , NAME , LINE , CHAR , REC ) \ do { \ auto const& chain( GetChain_( &errors[ IDX ].location( ) , DEPTH ) ); \ CPPUNIT_ASSERT( E_SRDLocationChaining::HOW == chain.circumstances ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( REC ) , chain.depth ); \ CPPUNIT_ASSERT( T_String{ NAME } == chain.location->source( ) ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( LINE ) , chain.location->line( ) ); \ CPPUNIT_ASSERT_EQUAL( size_t( CHAR ) , chain.location->character( ) ); \ } while ( 0 ) #endif // TESTS_SRDPREPROCLOCATION_H_