summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-diagnostics.cpp
blob: 53d5392a23fa3d8f0e2810f8673df3018765e20b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// slang-diagnostics.cpp
#include "slang-diagnostics.h"

#include "../compiler-core/slang-core-diagnostics.h"
#include "../compiler-core/slang-name.h"
#include "../core/slang-char-util.h"
#include "../core/slang-dictionary.h"
#include "../core/slang-memory-arena.h"
#include "../core/slang-string-util.h"
namespace Slang
{

namespace Diagnostics
{
#define DIAGNOSTIC(id, severity, name, messageFormat) \
    const DiagnosticInfo name = {id, Severity::severity, #name, messageFormat};
#include "slang-diagnostic-defs.h"
#undef DIAGNOSTIC
} // namespace Diagnostics

static const DiagnosticInfo* const kCompilerDiagnostics[] = {
#define DIAGNOSTIC(id, severity, name, messageFormat) &Diagnostics::name,
#include "slang-diagnostic-defs.h"
#undef DIAGNOSTIC
};

static DiagnosticsLookup* _newDiagnosticsLookup()
{
    DiagnosticsLookup* lookup =
        new DiagnosticsLookup(kCompilerDiagnostics, SLANG_COUNT_OF(kCompilerDiagnostics));

    // Add all the diagnostics in 'core'
    DiagnosticsLookup* coreLookup = getCoreDiagnosticsLookup();
    if (coreLookup)
    {
        for (auto diagnostic : coreLookup->getDiagnostics())
        {
            lookup->add(diagnostic);
        }
    }

    // Add the alias
    lookup->addAlias("overlappingBindings", "parameterBindingsOverlap");
    return lookup;
}

static DiagnosticsLookup* _getDiagnosticLookupSingleton()
{
    static RefPtr<DiagnosticsLookup> s_lookup = _newDiagnosticsLookup();
    return s_lookup;
}

DiagnosticInfo const* findDiagnosticByName(UnownedStringSlice const& name)
{
    return _getDiagnosticLookupSingleton()->findDiagnosticByName(name);
}

const DiagnosticsLookup* getDiagnosticsLookup()
{
    return _getDiagnosticLookupSingleton();
}


SlangResult overrideDiagnostic(
    DiagnosticSink* sink,
    DiagnosticSink* outDiagnostic,
    const UnownedStringSlice& identifier,
    Severity originalSeverity,
    Severity overrideSeverity)
{
    auto diagnosticsLookup = getDiagnosticsLookup();

    const DiagnosticInfo* diagnostic = nullptr;
    Int diagnosticId = -1;

    // If it starts with a digit we assume it a number
    if (identifier.getLength() > 0 && (CharUtil::isDigit(identifier[0]) || identifier[0] == '-'))
    {
        if (SLANG_FAILED(StringUtil::parseInt(identifier, diagnosticId)))
        {
            outDiagnostic->diagnose(SourceLoc(), Diagnostics::unknownDiagnosticName, identifier);
            return SLANG_FAIL;
        }

        // If we use numbers, we don't worry if we can't find a diagnostic
        // and silently ignore. This was the previous behavior, and perhaps
        // provides a way to safely disable warnings, without worrying about
        // the version of the compiler.
        diagnostic = diagnosticsLookup->getDiagnosticById(diagnosticId);
    }
    else
    {
        diagnostic = diagnosticsLookup->findDiagnosticByName(identifier);
        if (!diagnostic)
        {
            outDiagnostic->diagnose(SourceLoc(), Diagnostics::unknownDiagnosticName, identifier);
            return SLANG_FAIL;
        }
        diagnosticId = diagnostic->id;
    }

    // If we are only allowing certain original severities check it's the right type
    if (diagnostic && originalSeverity != Severity::Disable &&
        diagnostic->severity != originalSeverity)
    {
        // Strictly speaking the diagnostic name is known, but it's not the right severity
        // to be converted from, so it is an 'unknown name' in the context of severity...
        // Or perhaps we want another diagnostic
        outDiagnostic->diagnose(SourceLoc(), Diagnostics::unknownDiagnosticName, identifier);
        return SLANG_FAIL;
    }

    // Override the diagnostic severity in the sink
    sink->overrideDiagnosticSeverity(int(diagnosticId), overrideSeverity, diagnostic);

    return SLANG_OK;
}

SlangResult overrideDiagnostics(
    DiagnosticSink* sink,
    DiagnosticSink* outDiagnostic,
    const UnownedStringSlice& identifierList,
    Severity originalSeverity,
    Severity overrideSeverity)
{
    List<UnownedStringSlice> slices;
    StringUtil::split(identifierList, ',', slices);

    for (const auto& slice : slices)
    {
        SLANG_RETURN_ON_FAIL(
            overrideDiagnostic(sink, outDiagnostic, slice, originalSeverity, overrideSeverity));
    }
    return SLANG_OK;
}

} // namespace Slang