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

ArkScript-lang / Ark / 29648685875

18 Jul 2026 02:46PM UTC coverage: 94.384% (+0.004%) from 94.38%
29648685875

Pull #704

github

web-flow
Merge 0f00e4d0d into e703588d4
Pull Request #704: perf: improve fqn lookups in namespaces

12 of 12 new or added lines in 1 file covered. (100.0%)

3 existing lines in 1 file now uncovered.

10320 of 10934 relevant lines covered (94.38%)

1056937.02 hits per line

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

94.0
/src/arkreactor/Compiler/NameResolution/StaticScope.cpp
1
#include <Ark/Compiler/NameResolution/StaticScope.hpp>
2

3
#include <utility>
4
#include <algorithm>
5

6
#include <Ark/Compiler/Common.hpp>
7

8
namespace Ark::internal
9
{
10
    std::string StaticScope::add(const std::string& name, bool is_mutable)
67,919✔
11
    {
67,919✔
12
        m_vars.emplace(name, name, is_mutable);
67,919✔
13
        return name;
67,919✔
14
    }
15

16
    std::optional<Declaration> StaticScope::get(const std::string& name, [[maybe_unused]] const std::string& origin_namespace, [[maybe_unused]] const bool extensive_lookup)
646,725✔
17
    {
646,725✔
18
        if (const auto it = std::ranges::find(m_vars, name, &Declaration::name); it != m_vars.end())
850,008✔
19
            return *it;
203,283✔
20
        return std::nullopt;
443,442✔
21
    }
646,725✔
22

UNCOV
23
    std::string StaticScope::fullyQualifiedName(const std::string& name) const
×
24
    {
×
25
        return name;
×
26
    }
27

UNCOV
28
    bool StaticScope::saveNamespace([[maybe_unused]] std::unique_ptr<StaticScope>&)
×
29
    {
×
30
        // the scope can not be saved on a static scope
UNCOV
31
        return false;
×
32
    }
33

34
    bool StaticScope::isNamespace() const
728,377✔
35
    {
728,377✔
36
        return false;
728,377✔
37
    }
38

39
    NamespaceScope::NamespaceScope(std::string name, const bool with_prefix, const bool is_glob, const std::vector<std::string>& symbols) :
1,764✔
40
        StaticScope(),
882✔
41
        m_namespace(std::move(name)),
882✔
42
        m_with_prefix(with_prefix),
882✔
43
        m_is_glob(is_glob),
882✔
44
        m_symbols(symbols)
882✔
45
    {}
1,764✔
46

47
    std::string NamespaceScope::add(const std::string& name, bool is_mutable)
27,240✔
48
    {
27,240✔
49
        // Since we do multiple passes on namespaces, we need to check if the given name is already hidden,
50
        // so that we can save the name as it was on the first pass
51
        if (name.ends_with(HiddenSymbolSuffix))
27,240✔
52
        {
53
            std::string std_name = name.substr(0, name.find_first_of('#'));
823✔
54
            return m_vars.emplace(name, std_name, is_mutable).first->name;
823✔
55
        }
823✔
56

57
        // Otherwise, we also have to check for the presence of a namespace prefix,
58
        // and remove it when checking against the symbols list, to determine if we
59
        // need to hide the name or not
60
        const bool starts_with_prefix = !m_namespace.empty() && name.starts_with(m_namespace + ":");
26,417✔
61
        const std::string fqn = fullyQualifiedName(name);
26,417✔
62
        const std::string unprefixed_name = starts_with_prefix ? name.substr(name.find_first_of(':') + 1) : name;
26,417✔
63

64
        if (!m_symbols.empty() && !hasSymbol(unprefixed_name) && !m_with_prefix && !m_is_glob)
26,417✔
65
            return m_vars.emplace(fqn + std::string(HiddenSymbolSuffix), fqn, is_mutable).first->name;
793✔
66
        return m_vars.emplace(fqn, fqn, is_mutable).first->name;
25,624✔
67
    }
27,240✔
68

69
    std::optional<Declaration> NamespaceScope::get(const std::string& name, const std::string& origin_namespace, const bool extensive_lookup)
4,481,161✔
70
    {
4,481,161✔
71
        const bool starts_with_prefix = !m_namespace.empty() && name.starts_with(m_namespace + ":");
4,481,161✔
72
        // If the name starts with the namespace, and we imported the namespace with prefix
73
        // search for name in the namespace
74
        if (starts_with_prefix && m_with_prefix)
4,481,161✔
75
        {
76
            if (const auto it = std::ranges::find(m_vars, name, &Declaration::name); it != m_vars.end())
272,137✔
77
                return *it;
133,189✔
78
        }
5,759✔
79
        // If the name does not start with the prefix, and we import through either glob or symbol list
80
        // search for the name in the namespace
81
        // If the name does not start with the prefix, in a namespace with a symbol list but can be resolved,
82
        // modify it to hide it to the end user
83
        // If the name wasn't qualified, in the current prefixed namespace, look up for it but by qualifying the name
84
        else if (!starts_with_prefix)
4,342,213✔
85
        {
86
            const auto fqn = fullyQualifiedName(name);
4,340,637✔
87

88
            auto it = m_vars.end();
4,340,637✔
89
            auto it_original = m_vars.end();
4,340,637✔
90
            for (auto j = m_vars.begin(), end = m_vars.end(); j != end; ++j)
151,156,082✔
91
            {
92
                if (j->name == fqn)
146,815,445✔
93
                    it = j;
8,004✔
94
                if (j->original_name == fqn)
146,815,445✔
95
                    it_original = j;
8,619✔
96

97
                if (it != end && it_original != end)
146,815,445✔
98
                    break;
8,004✔
99
            }
146,807,441✔
100

101
            if ((m_is_glob || hasSymbol(name) || (m_with_prefix && origin_namespace == m_namespace)) && it != m_vars.end())
4,340,637✔
102
                return *it;
6,625✔
103
            if (!m_symbols.empty() && it_original != m_vars.end())
4,334,012✔
104
                return *it_original;
1,364✔
105
        }
4,340,637✔
106
        // lookup in the additional saved namespaces
107
        if (extensive_lookup)
4,339,983✔
108
        {
109
            std::optional<Declaration> decl;
4,325,771✔
110
            for (const auto& scope : m_additional_namespaces)
7,811,320✔
111
            {
112
                if (auto maybe_decl = scope->get(name, origin_namespace, extensive_lookup); maybe_decl.has_value())
3,646,393✔
113
                {
114
                    // prioritize non-hidden declarations
115
                    if ((decl.has_value() && decl->name.ends_with(HiddenSymbolSuffix)) || !decl.has_value())
160,844✔
116
                        decl = maybe_decl;
107,164✔
117
                }
160,844✔
118
            }
3,485,549✔
119
            return decl;
4,325,771✔
120
        }
4,325,771✔
121
        // otherwise we didn't find the name in the namespace
122
        return std::nullopt;
14,212✔
123
    }
4,481,161✔
124

125
    std::string NamespaceScope::fullyQualifiedName(const std::string& name) const
4,367,140✔
126
    {
4,367,140✔
127
        const bool starts_with_prefix = !m_namespace.empty() && name.starts_with(m_namespace + ":");
4,367,140✔
128
        if (!m_namespace.empty() && !starts_with_prefix)
4,367,140✔
129
            return fmt::format("{}:{}", m_namespace, name);
3,987,730✔
130
        return name;
379,410✔
131
    }
4,367,140✔
132

133
    bool NamespaceScope::saveNamespace(std::unique_ptr<StaticScope>& scope)
332✔
134
    {
332✔
135
        m_additional_namespaces.push_back(std::move(scope));
332✔
136
        return true;
332✔
137
    }
138

139
    bool NamespaceScope::isNamespace() const
508,141✔
140
    {
508,141✔
141
        return true;
508,141✔
142
    }
143

144
    bool NamespaceScope::recursiveHasSymbol(const std::string& symbol)
437✔
145
    {
437✔
146
        if (hasSymbol(symbol))
437✔
147
            return true;
129✔
148
        if (isGlob() && std::ranges::find(m_vars, fullyQualifiedName(symbol), &Declaration::name) != m_vars.end())
308✔
149
            return true;
20✔
150

151
        return std::ranges::any_of(
1,458✔
152
            m_additional_namespaces,
288✔
153
            [&symbol](const auto& saved_scope) {
546✔
154
                return saved_scope->recursiveHasSymbol(symbol);
258✔
155
            });
156
    }
437✔
157
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc