summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-artifact-diagnostic-util.cpp
blob: 98f8f2245c3a600b5ea9aaa5b3feec30f21d1b5d (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// slang-artifact-diagnostic-util.cpp
#include "slang-artifact-diagnostic-util.h"

#include "../core/slang-char-util.h"
#include "../core/slang-string-util.h"

namespace Slang
{

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnosticsUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */

/* static */ UnownedStringSlice ArtifactDiagnosticUtil::getSeverityText(Severity severity)
{
    switch (severity)
    {
    default:
        return UnownedStringSlice::fromLiteral("Unknown");
    case Severity::Info:
        return UnownedStringSlice::fromLiteral("Info");
    case Severity::Warning:
        return UnownedStringSlice::fromLiteral("Warning");
    case Severity::Error:
        return UnownedStringSlice::fromLiteral("Error");
    }
}

/* static */ SlangResult ArtifactDiagnosticUtil::splitPathLocation(
    SliceAllocator& allocator,
    const UnownedStringSlice& pathLocation,
    ArtifactDiagnostic& outDiagnostic)
{
    const Index lineStartIndex = pathLocation.lastIndexOf('(');
    if (lineStartIndex >= 0)
    {
        outDiagnostic.filePath = allocator.allocate(pathLocation.head(lineStartIndex).trim());

        const UnownedStringSlice tail = pathLocation.tail(lineStartIndex + 1);
        const Index lineEndIndex = tail.indexOf(')');

        if (lineEndIndex >= 0)
        {
            // Extract the location info
            UnownedStringSlice locationSlice(tail.begin(), tail.begin() + lineEndIndex);

            UnownedStringSlice slices[2];
            const Index numSlices = StringUtil::split(locationSlice, ',', 2, slices);

            // NOTE! FXC actually outputs a range of columns in the form of START-END in the column
            // position We don't need to parse here, because we only care about the line number

            Int lineNumber = 0;
            if (numSlices > 0)
            {
                SLANG_RETURN_ON_FAIL(StringUtil::parseInt(slices[0], lineNumber));
            }

            // Store the line
            outDiagnostic.location.line = lineNumber;
        }
    }
    else
    {
        outDiagnostic.filePath = allocator.allocate(pathLocation);
    }
    return SLANG_OK;
}

/* static */ SlangResult ArtifactDiagnosticUtil::splitColonDelimitedLine(
    const UnownedStringSlice& line,
    Int pathIndex,
    List<UnownedStringSlice>& outSlices)
{
    StringUtil::split(line, ':', outSlices);

    // Now we want to fix up a path as might have drive letter, and therefore :
    // If this is the situation then we need to have a slice after the one at the index
    if (outSlices.getCount() > pathIndex + 1)
    {
        const UnownedStringSlice pathStart = outSlices[pathIndex].trim();
        if (pathStart.getLength() == 1 && CharUtil::isAlpha(pathStart[0]))
        {
            // Splice back together
            outSlices[pathIndex] =
                UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end());
            outSlices.removeAt(pathIndex + 1);
        }
    }

    return SLANG_OK;
}

/* static */ SlangResult ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(
    SliceAllocator& allocator,
    const UnownedStringSlice& inText,
    Int pathIndex,
    LineParser lineParser,
    IArtifactDiagnostics* diagnostics)
{
    List<UnownedStringSlice> splitLine;

    UnownedStringSlice text(inText), line;
    while (StringUtil::extractLine(text, line))
    {
        SLANG_RETURN_ON_FAIL(splitColonDelimitedLine(line, pathIndex, splitLine));

        ArtifactDiagnostic diagnostic;
        diagnostic.severity = Severity::Error;
        diagnostic.stage = ArtifactDiagnostic::Stage::Compile;
        diagnostic.location.line = 0;
        diagnostic.location.column = 0;

        if (SLANG_SUCCEEDED(lineParser(allocator, line, splitLine, diagnostic)))
        {
            diagnostics->add(diagnostic);
        }
        else
        {
            // If couldn't parse, just add as a note
            maybeAddNote(line, diagnostics);
        }
    }

    return SLANG_OK;
}

/* static */ void ArtifactDiagnosticUtil::maybeAddNote(
    const UnownedStringSlice& in,
    IArtifactDiagnostics* diagnostics)
{
    // Don't bother adding an empty line
    if (in.trim().getLength() == 0)
    {
        return;
    }

    // If there's nothing previous, we'll ignore too, as note should be in addition to
    // a pre-existing error/warning
    if (diagnostics->getCount() == 0)
    {
        return;
    }

    // Make it a note on the output
    ArtifactDiagnostic diagnostic;

    String text(in);

    diagnostic.severity = ArtifactDiagnostic::Severity::Info;
    diagnostic.text = SliceUtil::asTerminatedCharSlice(text);
    diagnostics->add(diagnostic);
}


} // namespace Slang