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

ArkScript-lang / Ark / 17095454925

20 Aug 2025 10:15AM UTC coverage: 87.175% (-0.3%) from 87.426%
17095454925

Pull #571

github

web-flow
Merge 582ae8a8d into 120045f7e
Pull Request #571: Feat/better parser position tracking

594 of 697 new or added lines in 17 files covered. (85.22%)

5 existing lines in 2 files now uncovered.

7545 of 8655 relevant lines covered (87.18%)

129898.3 hits per line

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

41.58
/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

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

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

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

NEW
33
        for (const char c : line)
×
34
        {
NEW
35
            if (isPairableChar(c))
×
36
            {
NEW
37
                int idx = 0;
×
38

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

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

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

85
        m_window = Window(target_line, end_target_line.value_or(target_line), m_source.size());
238✔
86
        m_current_line = m_window.start;
238✔
87
    }
238✔
88

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

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

NEW
117
        return code;
×
NEW
118
    }
×
119

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

127
        // due to how context works, if it points to the same file,
128
        // we are guaranteed it will be before our error
129
        m_window.start = line_to_include >= 3 ? line_to_include - 3 : 0;
3✔
130
        m_current_line = m_window.start;
3✔
131
    }
3✔
132

133
    void Printer::printLine(std::ostream& os)
612✔
134
    {
612✔
135
        if (!hasContent())
612✔
NEW
136
            return;
×
137

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

147
        // show current line with its number
148
        fmt::print(os, "{: >5} |{}", m_current_line + 1, !m_source[m_current_line].empty() ? " " : "");
599✔
149
        if (m_should_colorize)
599✔
NEW
150
            colorizeLine(m_source[m_current_line], m_color_ctx, os);
×
151
        else
152
            fmt::print(os, "{}", m_source[m_current_line]);
599✔
153
        fmt::print(os, "\n");
599✔
154

155
        ++m_current_line;
599✔
156

157
        // if skip_start_at is equal to the next line to print, and we have to skip,
158
        // display an ellipsis
159
        if (m_window.skip_start_at &&
628✔
160
            m_current_line == m_window.skip_start_at.value())
29✔
161
            fmt::print(os, "  ... |\n");
3✔
162
    }
612✔
163

164
    bool Printer::isTargetLine() const
612✔
165
    {
612✔
166
        return m_window.target + 1 <= m_current_line && m_current_line <= m_window.target_end + 1;
612✔
167
    }
168

169
    bool Printer::hasContent() const
1,700✔
170
    {
1,700✔
171
        return m_current_line < m_window.end && !m_source.empty() && m_window.target < m_window.end;
1,700✔
172
    }
173

174
    bool Printer::coversLine(const std::size_t line_number) const
15✔
175
    {
15✔
176
        return m_window.start <= line_number && line_number < m_window.end;
15✔
177
    }
178

179
}
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