summaryrefslogtreecommitdiff
path: root/source/slang/slang-doc-markdown-writer.h
blob: 7a6c0a7e0d1a5ac0ecb1c11ecaecfcc278887d97 (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
// slang-doc-markdown-writer.h
#ifndef SLANG_DOC_MARKDOWN_WRITER_H
#define SLANG_DOC_MARKDOWN_WRITER_H

#include "slang-doc-extractor.h"
#include "slang-ast-print.h"
#include "slang-compiler.h"

namespace Slang {

class ASTBuilder;

struct DocMarkdownWriter
{
    typedef ASTPrinter::Part Part;
    typedef ASTPrinter::PartPair PartPair;

    struct Signature
    {
        struct GenericParam
        {
            Part name;
            Part type;
        };

        Part returnType;
        List<PartPair> params;
        List<GenericParam> genericParams;
        Part name;
    };

    struct Requirement
    {
        typedef Requirement ThisType;

        bool operator<(const ThisType& rhs) const { return Index(target) < Index(rhs.target) || (target == rhs.target && value < rhs.value); } 

        bool operator==(const ThisType& rhs) const { return target == rhs.target && value == rhs.value; }
        SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }

            /// Using CodeGenTarget may not be most appropriate, perhaps it should use a CapabilityAtom
            /// For now use target, and since we always go through Source -> byte code it is fairly straight forward to understand the
            /// meaning.
        CodeGenTarget target;
            /// The 'value' requirement associated with a target. If it's empty it's just the target that is a requirement.
        String value;
    };

        /// Write out all documentation to the output buffer
    void writeAll();

        /// This will write information about *all* of the overridden versions of a function/method
    void writeCallableOverridable(const DocMarkup::Entry& entry, CallableDecl* callable);

    void writeEnum(const DocMarkup::Entry& entry, EnumDecl* enumDecl);
    void writeAggType(const DocMarkup::Entry& entry, AggTypeDeclBase* aggTypeDecl);
    void writeDecl(const DocMarkup::Entry& entry, Decl* decl);
    void writeVar(const DocMarkup::Entry& entry, VarDecl* varDecl);

    void writePreamble(const DocMarkup::Entry& entry);
    void writeDescription(const DocMarkup::Entry& entry);

    void writeSignature(CallableDecl* callableDecl);

    bool isVisible(const DocMarkup::Entry& entry);
    bool isVisible(Decl* decl);
    bool isVisible(const Name* name);

        /// Get the output string
    const StringBuilder& getOutput() const { return m_builder; }

        /// Ctor.
    DocMarkdownWriter(DocMarkup* markup, ASTBuilder* astBuilder) :
        m_markup(markup),
        m_astBuilder(astBuilder)
    {
    }

    struct StringListSet;
    
        /// Given a list of ASTPrinter::Parts, works out the different parts of the sig
    static void getSignature(const List<Part>& parts, Signature& outSig);

    struct NameAndText
    {
        String name;
        String text;
    };

    List<NameAndText> _getUniqueParams(const List<Decl*>& decls);

    String _getName(Decl* decl);
    String _getName(InheritanceDecl* decl);

    NameAndText _getNameAndText(DocMarkup::Entry* entry, Decl* decl);
    NameAndText _getNameAndText(Decl* decl);

    template <typename T>
    List<NameAndText> _getAsNameAndTextList(const FilteredMemberList<T>& in)
    {
        List<NameAndText> out;
        for (auto decl : const_cast<FilteredMemberList<T>&>(in))
        {
            out.add(_getNameAndText(decl));
        }
        return out;
    }
    template <typename T>
    List<String> _getAsStringList(const List<T*>& in)
    {
        List<String> strings;
        for (auto decl : in)
        {
            strings.add(_getName(decl));
        }
        return strings;
    }

    List<NameAndText> _getAsNameAndTextList(const List<Decl*>& in);
    List<String> _getAsStringList(const List<Decl*>& in);

    void _appendAsBullets(const List<NameAndText>& values, char wrapChar);
    void _appendAsBullets(const List<String>& values, char wrapChar);

    void _appendCommaList(const List<String>& strings, char wrapChar);

    void _appendRequirements(const List<DocMarkdownWriter::Requirement>& requirements);
    void _maybeAppendRequirements(const UnownedStringSlice& title, const List<List<DocMarkdownWriter::Requirement>>& uniqueRequirements);
    void _writeTargetRequirements(const Requirement* reqs, Index reqsCount);

        /// Appends prefix and the list of types derived from
    void _appendDerivedFrom(const UnownedStringSlice& prefix, AggTypeDeclBase* aggTypeDecl);
    void _appendEscaped(const UnownedStringSlice& text);

    void _appendAggTypeName(AggTypeDeclBase* aggTypeDecl);

    DocMarkup* m_markup;
    ASTBuilder* m_astBuilder;
    StringBuilder m_builder;
};

} // namespace Slang

#endif