summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-doc-extractor.h
blob: 45575126fc68847cb2e544260408a96ef88cf2f1 (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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// slang-doc.h
#ifndef SLANG_DOC_EXTRACTOR_H
#define SLANG_DOC_EXTRACTOR_H

#include "../core/slang-basic.h"
#include "slang-lexer.h"
#include "slang-source-loc.h"

namespace Slang
{

enum class MarkupVisibility : uint8_t
{
    Public,   ///< Always available
    Internal, ///< Can be available in more verbose 'internal' documentation
    Hidden,   ///< Not generally available
};

/* Extracts 'markup' from comments in Slang source core. The comments are extracted and associated
in declarations. The association is held in DocMarkup type. The comment style follows the doxygen
style */
class DocMarkupExtractor
{
public:
    typedef uint32_t MarkupFlags;
    struct MarkupFlag
    {
        enum Enum : MarkupFlags
        {
            Before = 0x1,
            After = 0x2,
            IsMultiToken = 0x4, ///< Can use more than one token
            IsBlock = 0x8,      ///<
        };
    };

    // NOTE! Don't change order without fixing isBefore and isAfter
    enum class MarkupType
    {
        None,

        BlockBefore,     /// /**  */ or /*!  */.
        LineBangBefore,  /// //! Can be multiple lines
        LineSlashBefore, /// /// Can be multiple lines
        OrdinaryBlockBefore,
        OrdinaryLineBefore,

        BlockAfter,     /// /*!< */ or /**< */
        LineBangAfter,  /// //!< Can be multiple lines
        LineSlashAfter, /// ///< Can be multiple lines
        OrdinaryLineAfter,
    };

    static bool isBefore(MarkupType type)
    {
        return Index(type) >= Index(MarkupType::BlockBefore) &&
               Index(type) <= Index(MarkupType::OrdinaryLineBefore);
    }
    static bool isAfter(MarkupType type) { return Index(type) >= Index(MarkupType::BlockAfter); }

    struct IndexRange
    {
        SLANG_FORCE_INLINE Index getCount() const { return end - start; }

        Index start;
        Index end;
    };

    enum class Location
    {
        None, ///< No defined location
        Before,
        AfterParam,        ///< Can have trailing , or )
        AfterSemicolon,    ///< Can have a trailing ;
        AfterEnumCase,     ///< Can have a , or before }
        AfterGenericParam, ///< Can have trailing , or >
    };

    static bool isAfter(Location location)
    {
        return Index(location) >= Index(Location::AfterParam);
    }
    static bool isBefore(Location location) { return location == Location::Before; }

    struct FoundMarkup
    {
        void reset()
        {
            location = Location::None;
            type = MarkupType::None;
            range = IndexRange{0, 0};
        }

        Location location = Location::None;
        MarkupType type = MarkupType::None;
        IndexRange range;
    };

    enum SearchStyle
    {
        None,         ///< Cannot be searched for
        EnumCase,     ///< An enum case
        Param,        ///< A parameter in a function/method
        Variable,     ///< A variable-like declaration
        Before,       ///< Only allows before
        Function,     ///< Function/method
        GenericParam, ///< Generic parameter
        Attribute,    ///< Attribute definition
    };

    /// An input search item
    struct SearchItemInput
    {
        SourceLoc sourceLoc;
        SearchStyle searchStyle; ///< The search style when looking for an item
    };

    /// The items will be in source order
    struct SearchItemOutput
    {
        Index viewIndex;            ///< Index into the array of views on the output
        Index inputIndex;           ///< The index to this item in the input
        String text;                ///< The found text
        MarkupVisibility visibilty; ///< Visibility of the item
    };

    struct FindInfo
    {
        SourceView* sourceView; ///< The source view the tokens were generated from
        TokenList* tokenList;   ///< The token list
        Index tokenIndex;       ///< The token index location (where searches start from)
        Index lineIndex;        ///< The line number for the decl
    };

    void setSearchInOrdinaryComments(bool val) { m_searchInOrindaryComments = val; }

    /// Extracts 'markup' doc information for the specified input items
    /// The output is placed in out - with the items now in the source order *not* the order of the
    /// input items The inputIndex on the output holds the input item index The outViews holds the
    /// views specified in viewIndex in the output, which may be useful for determining where the
    /// documentation was placed in source
    SlangResult extract(
        const SearchItemInput* inputItems,
        Index inputCount,
        SourceManager* sourceManager,
        DiagnosticSink* sink,
        List<SourceView*>& outViews,
        List<SearchItemOutput>& out);

    static MarkupFlags getFlags(MarkupType type);
    static MarkupType findMarkupType(const Token& tok);
    static UnownedStringSlice removeStart(MarkupType type, const UnownedStringSlice& comment);

protected:
    /// returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success else an error
    SlangResult _findMarkup(const FindInfo& info, Location location, FoundMarkup& out);

    /// Locations are processed in order, and the first successful used. If found in another
    /// location will issue a warning. returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success
    /// else an error
    SlangResult _findFirstMarkup(
        const FindInfo& info,
        const Location* locs,
        Index locCount,
        FoundMarkup& out,
        Index& outIndex);

    SlangResult _findMarkup(
        const FindInfo& info,
        const Location* locs,
        Index locCount,
        FoundMarkup& out);

    /// Given the decl, the token stream, and the decls tokenIndex, try to find some associated
    /// markup
    SlangResult _findMarkup(const FindInfo& info, SearchStyle searchStyle, FoundMarkup& out);

    /// Given a found markup location extracts the contents of the tokens into out
    SlangResult _extractMarkup(
        const FindInfo& info,
        const FoundMarkup& foundMarkup,
        StringBuilder& out);

    /// Given a location, try to find the first token index that could potentially be markup
    /// Will return -1 if not found
    Index _findStartIndex(const FindInfo& info, Location location);

    /// True if the tok is 'on' lineIndex. Interpretation of 'on' depends on the markup type.
    static bool _isTokenOnLineIndex(
        SourceView* sourceView,
        MarkupType type,
        const Token& tok,
        Index lineIndex);

    DiagnosticSink* m_sink;

    bool m_searchInOrindaryComments = false;
};

} // namespace Slang

#endif