summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-doc-ast.cpp
blob: e6259167be44af38f2872131bfccf4f5fc16ab64 (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
// slang-doc-ast.cpp
#include "slang-doc-ast.h"

#include "../core/slang-string-util.h"
#include "slang-ast-support-types.h"
// #include "slang-ast-builder.h"
// #include "slang-ast-print.h"

namespace Slang
{

/* static */ DocMarkupExtractor::SearchStyle ASTMarkupUtil::getSearchStyle(Decl* decl)
{
    typedef Extractor::SearchStyle SearchStyle;

    if (const auto enumCaseDecl = as<EnumCaseDecl>(decl))
    {
        return SearchStyle::EnumCase;
    }
    if (const auto paramDecl = as<ParamDecl>(decl))
    {
        return SearchStyle::Param;
    }
    else if (const auto callableDecl = as<CallableDecl>(decl))
    {
        return SearchStyle::Function;
    }
    else if (as<VarDecl>(decl) || as<TypeDefDecl>(decl) || as<AssocTypeDecl>(decl))
    {
        return SearchStyle::Variable;
    }
    else if (auto genericDecl = as<GenericDecl>(decl))
    {
        return getSearchStyle(genericDecl->inner);
    }
    else if (as<GenericTypeParamDecl>(decl) || as<GenericValueParamDecl>(decl))
    {
        return SearchStyle::GenericParam;
    }
    else if (as<AttributeDecl>(decl))
    {
        return SearchStyle::Attribute;
    }
    else
    {
        // If can't determine just allow before
        return SearchStyle::Before;
    }
}

bool shouldDocumentDecl(Decl* decl)
{
    return !getText(decl->getName()).startsWith("$__syn") &&
           !decl->hasModifier<SynthesizedModifier>();
}

static void _addDeclRec(Decl* decl, List<Decl*>& outDecls)
{
    if (decl == nullptr || !shouldDocumentDecl(decl))
    {
        return;
    }

    // If we don't have a loc, we have no way of locating documentation.
    if (decl->loc.isValid() || decl->nameAndLoc.loc.isValid())
    {
        outDecls.add(decl);
    }

    if (GenericDecl* genericDecl = as<GenericDecl>(decl))
    {
        _addDeclRec(genericDecl->inner, outDecls);
    }

    if (ContainerDecl* containerDecl = as<ContainerDecl>(decl))
    {
        // Add the container - which could be a class, struct, enum, namespace, extension, generic
        // etc. Now add what the container contains
        for (Decl* childDecl : containerDecl->getDirectMemberDecls())
        {
            _addDeclRec(childDecl, outDecls);
        }
    }
}

/* static */ void ASTMarkupUtil::findDecls(ModuleDecl* moduleDecl, List<Decl*>& outDecls)
{
    for (Decl* decl : moduleDecl->getDirectMemberDecls())
    {
        _addDeclRec(decl, outDecls);
    }
}

SlangResult ASTMarkupUtil::extract(
    ModuleDecl* moduleDecl,
    SourceManager* sourceManager,
    DiagnosticSink* sink,
    ASTMarkup* outDoc,
    bool searchOrindaryComments)
{
    List<Decl*> decls;
    findDecls(moduleDecl, decls);

    const Index declsCount = decls.getCount();

    List<Extractor::SearchItemInput> inputItems;
    List<Extractor::SearchItemOutput> outItems;

    {
        inputItems.setCount(declsCount);

        for (Index i = 0; i < declsCount; ++i)
        {
            Decl* decl = decls[i];
            auto& item = inputItems[i];

            item.sourceLoc = decl->loc.isValid() ? decl->loc : decl->nameAndLoc.loc;
            // Has to be valid to be lookupable
            SLANG_ASSERT(item.sourceLoc.isValid());

            item.searchStyle = getSearchStyle(decl);

            // Don't generate documentation for synthesized members.
            if (!shouldDocumentDecl(decl))
                item.searchStyle = DocMarkupExtractor::SearchStyle::None;
        }

        DocMarkupExtractor extractor;
        extractor.setSearchInOrdinaryComments(searchOrindaryComments);

        List<SourceView*> views;
        SLANG_RETURN_ON_FAIL(
            extractor
                .extract(inputItems.getBuffer(), declsCount, sourceManager, sink, views, outItems));
    }

    // Set back
    for (Index i = 0; i < declsCount; ++i)
    {
        const auto& outputItem = outItems[i];
        const auto& inputItem = inputItems[outputItem.inputIndex];

        // If we don't know how to search add to the output
        if (inputItem.searchStyle != Extractor::SearchStyle::None)
        {
            Decl* decl = decls[outputItem.inputIndex];

            // Add to the documentation
            ASTMarkup::Entry& docEntry = outDoc->addEntry(decl);
            docEntry.m_markup = outputItem.text;
            docEntry.m_visibility = outputItem.visibilty;
        }
    }

    return SLANG_OK;
}

} // namespace Slang