summaryrefslogtreecommitdiffstats
path: root/tools/slang-test/parse-diagnostic-util.h
blob: 269c9048336ddfbd839f112a540a681180cefe25 (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
// parse-diagnostic-util.h

#ifndef PARSE_DIAGNOSTIC_UTIL_H
#define PARSE_DIAGNOSTIC_UTIL_H

#include "../../source/compiler-core/slang-artifact-diagnostic-util.h"
#include "../../source/compiler-core/slang-downstream-compiler.h"
#include "../../source/core/slang-string-util.h"
#include "../../source/core/slang-string.h"
#include "slang-com-ptr.h"

struct ParseDiagnosticUtil
{
    struct OutputInfo
    {
        int resultCode;
        Slang::String stdError;
        Slang::String stdOut;
    };

    /// We need a way to identify downstream compilers and others - specifically here Slang.
    /// Ideally we'd have an enum that included Slang.
    /// Just adding to SlangPassThrough doesn't seem right. If we had an enumeration with a
    /// more appropriate name, then including downstream and slang compilers wouldn't be a problem.
    /// So for now this is punted, and this type is used to represent possible compiler identities.
    struct CompilerIdentity
    {
        typedef CompilerIdentity ThisType;

        enum Type
        {
            Unknown,
            Slang,
            DownstreamCompiler,
        };

        static CompilerIdentity make(Type type, SlangPassThrough downstreamCompiler)
        {
            CompilerIdentity ident;
            ident.m_type = type;
            ident.m_downstreamCompiler = downstreamCompiler;
            return ident;
        }
        static CompilerIdentity make(SlangPassThrough downstreamCompiler)
        {
            return make(Type::DownstreamCompiler, downstreamCompiler);
        }
        static CompilerIdentity makeSlang() { return make(Type::Slang, SLANG_PASS_THROUGH_NONE); }

        bool operator==(const ThisType& rhs) const
        {
            return m_type == rhs.m_type && m_downstreamCompiler == rhs.m_downstreamCompiler;
        }
        bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }

        Type m_type = Type::Unknown;
        SlangPassThrough m_downstreamCompiler = SLANG_PASS_THROUGH_NONE;
    };

    typedef uint32_t EqualityFlags;
    struct EqualityFlag
    {
        enum Enum : EqualityFlags
        {
            IgnoreLineNos = 0x1,
        };
    };

    typedef SlangResult (*LineParser)(
        Slang::SliceAllocator& allocator,
        const Slang::UnownedStringSlice& line,
        Slang::List<Slang::UnownedStringSlice>& lineSlices,
        Slang::ArtifactDiagnostic& outDiagnostic);

    /// Given a compiler identity returns a line parsing function.
    static LineParser getLineParser(const CompilerIdentity& compilerIdentity);

    /// For a 'generic' (as in uses DownstreamCompiler mechanism) line parsing
    static SlangResult parseGenericLine(
        Slang::SliceAllocator& allocator,
        const Slang::UnownedStringSlice& line,
        Slang::List<Slang::UnownedStringSlice>& lineSlices,
        Slang::ArtifactDiagnostic& outDiagnostic);

    /// For parsing diagnostics from Slang
    static SlangResult parseSlangLine(
        Slang::SliceAllocator& allocator,
        const Slang::UnownedStringSlice& line,
        Slang::List<Slang::UnownedStringSlice>& lineSlices,
        Slang::ArtifactDiagnostic& outDiagnostic);

    /// Parse diagnostics into output text
    static SlangResult parseDiagnostics(
        const Slang::UnownedStringSlice& inText,
        Slang::IArtifactDiagnostics* diagnostics);

    /// Parse diagnostics with known compiler identity.
    /// If the prefix is empty, it is assumed there is no prefix and it won't be checked.
    static SlangResult parseDiagnostics(
        const Slang::UnownedStringSlice& inText,
        const CompilerIdentity& identity,
        const Slang::UnownedStringSlice& prefix,
        Slang::IArtifactDiagnostics* diagnostics);

    /// Given the file output style used by tests, get components of the output into Diagnostic
    static SlangResult parseOutputInfo(const Slang::UnownedStringSlice& in, OutputInfo& out);

    /// Given a line split it into slices - taking into account compiler output, path
    /// considerations, and potentially line prefixing
    static SlangResult splitDiagnosticLine(
        const CompilerIdentity& compilerIdentity,
        const Slang::UnownedStringSlice& line,
        const Slang::UnownedStringSlice& linePrefix,
        Slang::List<Slang::UnownedStringSlice>& outSlices);

    /// Give text of diagnostic determine which compiler the output is from
    static SlangResult identifyCompiler(
        const Slang::UnownedStringSlice& in,
        CompilerIdentity& outIdentity);

    /// Determines if the diagnostics in a and b (they are parsed via parseDiagnostics) are equal,
    /// taking into account flags Note! If the parse of either a or b fails, then equality is
    /// returns as false.
    static bool areEqual(
        const Slang::UnownedStringSlice& a,
        const Slang::UnownedStringSlice& b,
        EqualityFlags flags);
};

#endif // PARSE_DIAGNOSTIC_UTIL_H