Goose  Artifact [aed0684a8c]

Artifact aed0684a8c05eba6b21ca75324f94e2e41498369a9c8bbc53dc1462fc1c083b6:

  • File bs/diagnostics/renderer.h — part of check-in [af650a9e95] at 2019-09-22 14:37:55 on branch trunk — Project renaming. (user: achavasse size: 3936)

#ifndef GOOSE_DIAGNOSTICS_RENDERER_H
#define GOOSE_DIAGNOSTICS_RENDERER_H

namespace goose::diagnostics
{
    class Renderer
    {
        public:
            Renderer( llvm::raw_ostream& output ) :
                m_output( output )
            {}

            ~Renderer()
            {
                flushContext();
            }

            enum Style
            {
                None        = 0,

                Caret       = 1 << 0,
                Squiggles   = 1 << 1,
                Highlight   = 1 << 2
            };

            struct Colors
            {
                static const char* Reset;

                static const char* Location;            // File name, line number gutter
                static const char* Context;             // Squiggles and messages providing contextual informations
                static const char* Trace;               // Squiggles and messages displayed during tracing
                static const char* Error;               // Error highlight and "error" keyword
                static const char* Source;              // Source code
            };

            // Wrapper around fmt::format that defines named arguments for all the possible colors above
            // (in lowercase). If the output isn't a terminal, empty strings will be provided instead of
            // color escape sequences.
            template< typename S, typename... A >
            auto format( S&& str, A&&... args ) const;

            template< typename... A >
            void addMessage( uint32_t location, const string& message, A&&... args );

            template< typename... A >
            void addContext( const string&  message, A&&... args );

            void addContext( uint32_t location, uint8_t styleFlags, const char* color = Colors::Reset );
            void addContext( uint32_t location, uint8_t styleFlags, const string& message, const char* color = Colors::Reset );

        private:
            bool useColors() const;

            void addToPendingContext( const optional< Location >& loc, uint8_t styleFlags, const char* pColor, const string& message );
            void flushContext();
            llvm::raw_ostream& m_output;

            struct Item
            {
                string message;

                uint32_t location = 0;

                // The following values are only relevant if the location is valid.
                bool quoteSource = false;
                uint8_t styleFlags = 0;

                // Color is only relevant if styleFlags != 0
                const char* color = "";
            };

            void addItem( Item&& item );

            void applyColor( const char* pColor );

            string m_lastFilename;
            uint32_t m_lastLineNumber = 0;

            // The pending context line informations.
            string m_pendingContextFilename;
            uint32_t m_pendingContextOffset = 0;
            uint32_t m_pendingContextLineNumber = 0;

            // Describe the starting or ending point of a span to be
            // highlighted. color = nullptr means it's an ending point.
            struct SpanVertex
            {
                uint32_t column = 0;
                uint8_t styleFlags = 0;
                const char* color = nullptr;
            };

            // The pending highlighting vertices.
            llvm::SmallVector< SpanVertex, 8 > m_pendingHighlightSpans;

            // The pending context message.
            string m_pendingContextMessage;

            // The color and position of the pending context message.
            const char* m_pendingContextMessageColor = nullptr;
            uint32_t m_pendingContextMessageXPosStart = 0;
            uint32_t m_pendingContextMessageXPosEnd = 0;

            // True if there is a pending caret highlighting.
            // (we only allow one per displayed context line)
            bool m_pendingCaret = false;
    };
}

#endif