• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ArkScript-lang / Ark / 21488144923

29 Jan 2026 05:26PM UTC coverage: 93.408% (-0.009%) from 93.417%
21488144923

push

github

SuperFola
chore: update credits

8828 of 9451 relevant lines covered (93.41%)

274416.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.72
/src/arkreactor/Error/PrettyPrinting.cpp
1
#include <Ark/Error/PrettyPrinting.hpp>
2

3
#include <Ark/Constants.hpp>
4
#include <Ark/Utils/Files.hpp>
5
#include <Ark/Utils/Utils.hpp>
6

7
#include <array>
8
#include <cassert>
9

10
#include <fmt/color.h>
11
#include <fmt/ostream.h>
12

13
namespace Ark::Diagnostics
14
{
15
    [[nodiscard]] bool isPairableChar(const char c)
22✔
16
    {
22✔
17
        return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}';
22✔
18
    }
19

20
    void colorizeLine(const std::string& line, LineColorContextCounts& ctx, std::ostream& os)
3✔
21
    {
3✔
22
        // clang-format off
23
        constexpr std::array pairing_color {
3✔
24
            fmt::color::light_blue,
25
            fmt::color::light_green,
26
            fmt::color::light_salmon,
27
            fmt::color::light_yellow,
28
            fmt::color::light_cyan,
29
            fmt::color::light_coral
30
        };
31
        // clang-format on
32
        constexpr std::size_t pairing_color_size = pairing_color.size();
3✔
33

34
        for (const char c : line)
25✔
35
        {
36
            if (isPairableChar(c))
22✔
37
            {
38
                int idx = 0;
6✔
39

40
                switch (c)
6✔
41
                {
3✔
42
                    case '(':
43
                        idx = ctx.open_parentheses;
3✔
44
                        ctx.open_parentheses++;
3✔
45
                        break;
6✔
46
                    case ')':
47
                        ctx.open_parentheses--;
3✔
48
                        idx = ctx.open_parentheses;
3✔
49
                        break;
3✔
50
                    case '[':
51
                        idx = ctx.open_square_braces;
×
52
                        ctx.open_square_braces++;
×
53
                        break;
×
54
                    case ']':
55
                        ctx.open_square_braces--;
×
56
                        idx = ctx.open_square_braces;
×
57
                        break;
×
58
                    case '{':
59
                        idx = ctx.open_curly_braces;
×
60
                        ctx.open_curly_braces++;
×
61
                        break;
×
62
                    case '}':
63
                        ctx.open_curly_braces--;
×
64
                        idx = ctx.open_curly_braces;
×
65
                        break;
×
66
                    default:
67
                        break;
×
68
                }
6✔
69

70
                const std::size_t pairing_color_index = static_cast<std::size_t>(std::abs(idx)) % pairing_color_size;
6✔
71
                fmt::print(os, "{}", fmt::styled(c, fmt::fg(pairing_color[pairing_color_index])));
6✔
72
            }
6✔
73
            else
74
                fmt::print(os, "{}", c);
16✔
75
        }
22✔
76
    }
3✔
77

78
    Printer::Printer(
596✔
79
        const std::string& filename, const std::size_t target_line,
80
        const std::optional<std::size_t> end_target_line, const bool colorize,
81
        const std::optional<std::string>& maybe_content) :
82
        m_should_colorize(colorize)
298✔
83
    {
298✔
84
        const std::string code = filename == ARK_NO_NAME_FILE ? maybe_content.value_or("") : Utils::readFile(filename);
298✔
85
        m_source = Utils::splitString(code, '\n');
298✔
86

87
        m_window = Window(target_line, end_target_line.value_or(target_line), m_source.size());
298✔
88
        m_current_line = m_window.start;
298✔
89
    }
298✔
90

91
    std::string Printer::sliceCode(const internal::FilePos start, const std::optional<internal::FilePos>& end) const
×
92
    {
×
93
        std::string code;
×
94
        if (!end)
×
95
        {
96
            code = m_source[start.line];
×
97
            Utils::ltrim(Utils::rtrim(code));
×
98
        }
×
99
        else
100
        {
101
            if (start.line == end->line)
×
102
                code = m_source[start.line].substr(start.column, end->column);
×
103
            else
104
            {
105
                code = m_source[start.line].substr(start.column);
×
106

107
                if (end->line - start.line > 1)
×
108
                {
109
                    for (std::size_t i = start.line + 1; i <= end->line - 1; ++i)
×
110
                    {
111
                        code += "\n";
×
112
                        code += m_source[i];
×
113
                    }
×
114
                }
×
115
                code += "\n" + m_source[end->line].substr(0, end->column);
×
116
            }
117
        }
118

119
        return code;
×
120
    }
×
121

122
    void Printer::extendWindow(const std::size_t line_to_include)
3✔
123
    {
3✔
124
        // showing the context will require an ellipsis, to avoid showing too many lines in the error message
125
        if (line_to_include + 3 < m_window.start)
3✔
126
            m_window.skip_start_at = line_to_include + 3;
3✔
127
        m_window.resume_at = m_window.start;
3✔
128

129
        assert(line_to_include <= m_window.start && "line_to_include has to be before the start of our base context, source of errors are always before our errors");
3✔
130
        // due to how context works, if it points to the same file,
131
        // we are guaranteed it will be before our error
132
        m_window.start = line_to_include >= 3 ? line_to_include - 3 : 0;
3✔
133
        m_current_line = m_window.start;
3✔
134
    }
3✔
135

136
    void Printer::printLine(std::ostream& os)
818✔
137
    {
818✔
138
        if (!hasContent())
818✔
139
            return;
×
140

141
        if (m_window.hasSkip() &&
878✔
142
            m_current_line >= m_window.skip_start_at.value() &&
42✔
143
            m_current_line < m_window.resume_at.value())
30✔
144
        {
145
            // do not print the current line, we want to skip 1 or more lines
146
            ++m_current_line;
14✔
147
            return;
14✔
148
        }
149

150
        // show current line with its number
151
        fmt::print(os, "{: >5} |{}", m_current_line + 1, !m_source[m_current_line].empty() ? " " : "");
804✔
152
        if (m_should_colorize)
804✔
153
            colorizeLine(m_source[m_current_line], m_color_ctx, os);
3✔
154
        else
155
            fmt::print(os, "{}", m_source[m_current_line]);
801✔
156
        fmt::print(os, "\n");
804✔
157

158
        ++m_current_line;
804✔
159

160
        // if skip_start_at is equal to the next line to print, and we have to skip,
161
        // display an ellipsis
162
        if (m_window.skip_start_at &&
832✔
163
            m_current_line == m_window.skip_start_at.value())
28✔
164
            fmt::print(os, "  ... |\n");
3✔
165
    }
818✔
166

167
    bool Printer::isTargetLine() const
814✔
168
    {
814✔
169
        return m_window.target + 1 <= m_current_line && m_current_line <= m_window.target_end + 1;
814✔
170
    }
171

172
    bool Printer::isNextLineTheFirstLineOfTarget() const
4✔
173
    {
4✔
174
        return m_window.target == m_current_line;
4✔
175
    }
176

177
    bool Printer::isLastLineOfTarget() const
4✔
178
    {
4✔
179
        return m_window.target != m_window.target_end &&
4✔
180
            m_current_line == m_window.target_end + 1;
4✔
181
    }
182

183
    bool Printer::hasContent() const
2,231✔
184
    {
2,231✔
185
        return m_current_line < m_window.end && !m_source.empty() && m_window.target < m_window.end;
2,231✔
186
    }
187

188
    bool Printer::coversLine(const std::size_t line_number) const
17✔
189
    {
17✔
190
        return m_window.start <= line_number && line_number < m_window.end;
17✔
191
    }
192

193
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc