summaryrefslogtreecommitdiff
path: root/source/slang
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-03-09 18:38:00 -0500
committerGitHub <noreply@github.com>2022-03-09 18:38:00 -0500
commitf67d929c24babc302eb2807251fc09b084abac2e (patch)
treef4b3a47d5165e4e890c9d68e846e2aa238dbb1e0 /source/slang
parent727c7d2b824913b3ae263243421ea79ca4940eb8 (diff)
Initial support for documentation extraction in C++ (#2156)
* #include an absolute path didn't work - because paths were taken to always be relative. * Split doc extractor such that can be used in C++ extractor. * Compiles. Update the stdlib docs. * Fix issue on release builds. * Add support for extracting documentation to C++ extractor. * Dump out markup. Make enum value backing type take tokens. * Node::Type -> Node::Kind * More improvements around Node::Type -> Node::Kind
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/slang-ast-print.h2
-rw-r--r--source/slang/slang-doc-ast.cpp139
-rw-r--r--source/slang/slang-doc-ast.h82
-rw-r--r--source/slang/slang-doc-extractor.cpp989
-rw-r--r--source/slang/slang-doc-extractor.h219
-rw-r--r--source/slang/slang-doc-markdown-writer.cpp22
-rw-r--r--source/slang/slang-doc-markdown-writer.h25
-rw-r--r--source/slang/slang.cpp10
8 files changed, 251 insertions, 1237 deletions
diff --git a/source/slang/slang-ast-print.h b/source/slang/slang-ast-print.h
index 1c4c20e28..15ca58acf 100644
--- a/source/slang/slang-ast-print.h
+++ b/source/slang/slang-ast-print.h
@@ -139,7 +139,7 @@ public:
UnownedStringSlice getPartSlice(const Part& part) const { return getPart(getSlice(), part); }
/// Gets the specified part type
- static UnownedStringSlice getPart(const UnownedStringSlice& slice, const Part& part) { return UnownedStringSlice(slice.begin() + part.start, slice.begin() + part.end); }
+ static UnownedStringSlice getPart(const UnownedStringSlice& slice, const Part& part) { return (part.type != Part::Type::None) ? UnownedStringSlice(slice.begin() + part.start, slice.begin() + part.end) : UnownedStringSlice(); }
static UnownedStringSlice getPart(Part::Type partType, const UnownedStringSlice& slice, const List<Part>& parts);
static void appendDeclName(Decl* decl, StringBuilder& out);
diff --git a/source/slang/slang-doc-ast.cpp b/source/slang/slang-doc-ast.cpp
new file mode 100644
index 000000000..8301b1a63
--- /dev/null
+++ b/source/slang/slang-doc-ast.cpp
@@ -0,0 +1,139 @@
+// slang-doc-ast.cpp
+#include "slang-doc-ast.h"
+
+#include "../core/slang-string-util.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 (auto enumCaseDecl = as<EnumCaseDecl>(decl))
+ {
+ return SearchStyle::EnumCase;
+ }
+ if (auto paramDecl = as<ParamDecl>(decl))
+ {
+ return SearchStyle::Param;
+ }
+ else if (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 can't determine just allow before
+ return SearchStyle::Before;
+ }
+}
+
+static void _addDeclRec(Decl* decl, List<Decl*>& outDecls)
+{
+ if (decl == nullptr)
+ {
+ 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);
+ }
+ else
+ {
+ SLANG_ASSERT(!"Decl without a location!");
+ }
+
+ 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->members)
+ {
+ _addDeclRec(childDecl, outDecls);
+ }
+ }
+}
+
+/* static */void ASTMarkupUtil::findDecls(ModuleDecl* moduleDecl, List<Decl*>& outDecls)
+{
+ for (Decl* decl : moduleDecl->members)
+ {
+ _addDeclRec(decl, outDecls);
+ }
+}
+
+SlangResult ASTMarkupUtil::extract(ModuleDecl* moduleDecl, SourceManager* sourceManager, DiagnosticSink* sink, ASTMarkup* outDoc)
+{
+ 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);
+ }
+
+ DocMarkupExtractor extractor;
+
+ 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
diff --git a/source/slang/slang-doc-ast.h b/source/slang/slang-doc-ast.h
new file mode 100644
index 000000000..c5291a31a
--- /dev/null
+++ b/source/slang/slang-doc-ast.h
@@ -0,0 +1,82 @@
+// slang-doc-ast.h
+#ifndef SLANG_DOC_AST_H
+#define SLANG_DOC_AST_H
+
+#include "../core/slang-basic.h"
+
+#include "../compiler-core/slang-doc-extractor.h"
+
+#include "slang-ast-all.h"
+
+namespace Slang {
+
+/* Holds the documentation markup that is associated with each node (typically a decl) from a module */
+class ASTMarkup : public RefObject
+{
+public:
+ struct Entry
+ {
+ NodeBase* m_node; ///< The node this documentation is associated with
+ String m_markup; ///< The raw contents of of markup associated with the decoration
+ MarkupVisibility m_visibility = MarkupVisibility::Public; ///< How visible this decl is
+ };
+
+ /// Adds an entry, returns the reference to pre-existing node if there is one
+ Entry& addEntry(NodeBase* base);
+ /// Gets an entry for a node. Returns nullptr if there is no markup.
+ Entry* getEntry(NodeBase* base);
+
+ /// Get list of all of the entries in source order
+ const List<Entry>& getEntries() const { return m_entries; }
+
+protected:
+
+ /// Map from AST nodes to documentation entries
+ Dictionary<NodeBase*, Index> m_entryMap;
+ /// All of the documentation entries in source order
+ List<Entry> m_entries;
+};
+
+// ---------------------------------------------------------------------------
+SLANG_INLINE ASTMarkup::Entry& ASTMarkup::addEntry(NodeBase* base)
+{
+ const Index count = m_entries.getCount();
+ const Index index = m_entryMap.GetOrAddValue(base, count);
+
+ if (index == count)
+ {
+ Entry entry;
+ entry.m_node = base;
+ m_entries.add(entry);
+ }
+ return m_entries[index];
+}
+
+// ---------------------------------------------------------------------------
+SLANG_INLINE ASTMarkup::Entry* ASTMarkup::getEntry(NodeBase* base)
+{
+ Index* indexPtr = m_entryMap.TryGetValue(base);
+ return (indexPtr) ? &m_entries[*indexPtr] : nullptr;
+}
+
+/* Extracts documentation markup from source.
+The comments are extracted and associated in declarations. The association
+is held in DocMarkup type. The comment style follows the doxygen style */
+struct ASTMarkupUtil
+{
+ typedef DocMarkupExtractor Extractor;
+
+ /// Given a module finds all the decls, and places in outDecls
+ static void findDecls(ModuleDecl* moduleDecl, List<Decl*>& outDecls);
+
+ /// Given a decl determines the search style that is appropriate. Returns None if can't determine a suitable style
+ static Extractor::SearchStyle getSearchStyle(Decl* decl);
+
+ /// Extracts documentation from the nodes held in the module using the source manager. Found documentation is placed
+ /// in outMarkup
+ static SlangResult extract(ModuleDecl* moduleDecl, SourceManager* sourceManager, DiagnosticSink* sink, ASTMarkup* outMarkup);
+};
+
+} // namespace Slang
+
+#endif
diff --git a/source/slang/slang-doc-extractor.cpp b/source/slang/slang-doc-extractor.cpp
deleted file mode 100644
index 0677e2af4..000000000
--- a/source/slang/slang-doc-extractor.cpp
+++ /dev/null
@@ -1,989 +0,0 @@
-// slang-doc.cpp
-#include "slang-doc-extractor.h"
-
-#include "../core/slang-string-util.h"
-
-#include "slang-ast-builder.h"
-#include "slang-ast-print.h"
-
-namespace Slang {
-
-/* TODO(JS):
-
-* If Decls hand SourceRange, then we could use the range to simplify getting the Post markup, as will be trivial to get to the 'end'
-* Need to handle preceeding * in some markup styles
-* If we want to be able to disable markup we need a mechanism to do this. Probably define source ranges.
-
-* Need a way to take the extracted markup and produce suitable markdown
-** This will need to display the decoration appropriately
-*/
-
-/* static */UnownedStringSlice DocMarkupExtractor::removeStart(MarkupType type, const UnownedStringSlice& comment)
-{
- switch (type)
- {
- case MarkupType::BlockBefore:
- {
- if (comment.startsWith(UnownedStringSlice::fromLiteral("/**")) ||
- comment.startsWith(UnownedStringSlice::fromLiteral("/*!")))
- {
- /// /** */ or /*! */.
- return comment.tail(3);
- }
- return comment;
- }
- case MarkupType::BlockAfter:
- {
-
- if (comment.startsWith(UnownedStringSlice::fromLiteral("/**<")) ||
- comment.startsWith(UnownedStringSlice::fromLiteral("/*!<")))
- {
- /// /*!< */ or /**< */
- return comment.tail(4);
- }
- return comment;
- }
-
- case MarkupType::LineBangBefore:
- {
- return comment.startsWith(UnownedStringSlice::fromLiteral("//!")) ? comment.tail(3) : comment;
- }
- case MarkupType::LineSlashBefore:
- {
- return comment.startsWith(UnownedStringSlice::fromLiteral("///")) ? comment.tail(3) : comment;
- }
-
- case MarkupType::LineBangAfter:
- {
- /// //!< Can be multiple lines
- return comment.startsWith(UnownedStringSlice::fromLiteral("//!<")) ? comment.tail(4) : comment;
- }
- case MarkupType::LineSlashAfter:
- {
- return comment.startsWith(UnownedStringSlice::fromLiteral("///<")) ? comment.tail(4) : comment;
- }
- default: break;
- }
- return comment;
-}
-
-static Index _findTokenIndex(SourceLoc loc, const Token* toks, Index numToks)
-{
- // Use a binary search to find the token
- Index lo = 0;
- Index hi = numToks;
-
- while (lo + 1 < hi)
- {
- const Index mid = (hi + lo) >> 1;
- const Token& midToken = toks[mid];
-
- if (midToken.loc == loc)
- {
- return mid;
- }
-
- if (midToken.loc.getRaw() <= loc.getRaw())
- {
- lo = mid;
- }
- else
- {
- hi = mid;
- }
- }
-
- // Not found
- return -1;
-}
-
-/* static */DocMarkupExtractor::MarkupFlags DocMarkupExtractor::getFlags(MarkupType type)
-{
- switch (type)
- {
- default:
- case MarkupType::None: return 0;
- case MarkupType::BlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock;
- case MarkupType::BlockAfter: return MarkupFlag::After | MarkupFlag::IsBlock;
-
- case MarkupType::LineBangBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken;
- case MarkupType::LineSlashBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken;
-
- case MarkupType::LineBangAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken;
- case MarkupType::LineSlashAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken;
- }
-}
-
-/* static */DocMarkupExtractor::MarkupType DocMarkupExtractor::findMarkupType(const Token& tok)
-{
- switch (tok.type)
- {
- case TokenType::BlockComment:
- {
- UnownedStringSlice slice = tok.getContent();
- if (slice.getLength() >= 3 && (slice[2] == '!' || slice[2] == '*'))
- {
- return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::BlockAfter : MarkupType::BlockBefore;
- }
- break;
- }
- case TokenType::LineComment:
- {
- UnownedStringSlice slice = tok.getContent();
- if (slice.getLength() >= 3)
- {
- if (slice[2] == '!')
- {
- return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineBangAfter : MarkupType::LineBangBefore;
- }
- else if (slice[2] == '/')
- {
- return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineSlashAfter : MarkupType::LineSlashBefore;
- }
- }
- break;
- }
- default: break;
- }
- return MarkupType::None;
-}
-
-static Index _calcWhitespaceIndent(const UnownedStringSlice& line)
-{
- // TODO(JS): For now we ignore tabs and just work out indentation based on spaces/assume ASCII
- Index indent = 0;
- const Index count = line.getLength();
- for (; indent < count && line[indent] == ' '; indent++);
- return indent;
-}
-
-static Index _calcIndent(const UnownedStringSlice& line)
-{
- // TODO(JS): For now we just assume no tabs, and that every char is ASCII
- return line.getLength();
-}
-
-static void _appendUnindenttedLine(const UnownedStringSlice& line, Index maxIndent, StringBuilder& out)
-{
- Index indent = _calcWhitespaceIndent(line);
-
- // We want to remove indenting remove no more than maxIndent
- if (maxIndent >= 0)
- {
- indent = (indent > maxIndent) ? maxIndent : indent;
- }
-
- // Remove the indenting, and append to out
- out.append(line.tail(indent));
-}
-
-SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const FoundMarkup& foundMarkup, StringBuilder& out)
-{
- SourceView* sourceView = info.sourceView;
- SourceFile* sourceFile = sourceView->getSourceFile();
-
- // Here we want to produce the text that is implied by the markup tokens.
- // We want to removing surrounding markup, and to also keep appropriate indentation
-
- switch (foundMarkup.type)
- {
- case MarkupType::BlockBefore:
- case MarkupType::BlockAfter:
- {
- // We should only have a single line
- SLANG_ASSERT(foundMarkup.range.getCount() == 1);
-
- const auto& tok = info.tokenList->m_tokens[foundMarkup.range.start];
- uint32_t offset = sourceView->getRange().getOffset(tok.loc);
-
- const UnownedStringSlice startLine = sourceFile->getLineContainingOffset(offset);
-
- UnownedStringSlice content = tok.getContent();
-
- // Split into lines
- List<UnownedStringSlice> lines;
-
- StringUtil::calcLines(content, lines);
-
- Index maxIndent = -1;
-
- StringBuilder unindentedLine;
-
- const Index linesCount = lines.getCount();
- for (Index i = 0; i < linesCount; ++i)
- {
- UnownedStringSlice line = lines[i];
- unindentedLine.Clear();
-
- if (i == 0)
- {
- if (startLine.isMemoryContained(line.begin()))
- {
- // For now we'll ignore tabs, and that the indent amount is, the amount of *byte*
- // NOTE! This is only appropriate for ASCII without tabs.
- maxIndent = _calcIndent(UnownedStringSlice(startLine.begin(), line.begin()));
-
- // Let's strip the start stuff
- line = removeStart(foundMarkup.type, line);
- }
- }
-
- if (i == linesCount - 1)
- {
- SLANG_ASSERT(line.tail(line.getLength() - 2) == UnownedStringSlice::fromLiteral("*/"));
- // Remove the */ at the end of the line
- line = line.head(line.getLength() - 2);
- }
-
- if (i > 0)
- {
- _appendUnindenttedLine(line, maxIndent, unindentedLine);
- }
- else
- {
- unindentedLine.append(line);
- }
-
- // If the first or last line are all white space, just ignore them
- if ((i == linesCount - 1 || i == 0) && unindentedLine.getUnownedSlice().trim().getLength() == 0)
- {
- continue;
- }
-
- out.append(unindentedLine);
- out.appendChar('\n');
- }
-
- break;
- }
- case MarkupType::LineBangBefore:
- case MarkupType::LineSlashBefore:
- case MarkupType::LineBangAfter:
- case MarkupType::LineSlashAfter:
- {
- // Holds the lines extracted, they may have some white space indenting (like the space at the start of //)
- List<UnownedStringSlice> lines;
-
- const auto& range = foundMarkup.range;
- for (Index i = range.start; i < range.end; ++ i)
- {
- const auto& tok = info.tokenList->m_tokens[i];
- UnownedStringSlice line = tok.getContent();
- line = removeStart(foundMarkup.type, line);
-
- // If the first or last line are all white space, just ignore them
- if ((i == range.start || i == range.end - 1) && line.trim().getLength() == 0)
- {
- continue;
- }
- lines.add(line);
- }
-
- if (lines.getCount() == 0)
- {
- // If there are no lines, theres no content
- return SLANG_OK;
- }
-
- Index minIndent = 0x7fffffff;
- for (const auto& line : lines)
- {
- const Index indent = _calcWhitespaceIndent(line);
- minIndent = (indent < minIndent) ? indent : minIndent;
- }
-
- for (const auto& line : lines)
- {
- _appendUnindenttedLine(line, minIndent, out);
- out.appendChar('\n');
- }
-
- break;
- }
- default: return SLANG_FAIL;
- }
-
- return SLANG_OK;
-}
-
-Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location location)
-{
- Index openCount = 0;
-
- const TokenList& toks = *info.tokenList;
- const Index tokIndex = info.tokenIndex;
-
- Index direction = isBefore(location) ? -1 : 1;
-
- const Index count = toks.m_tokens.getCount();
- for (Index i = tokIndex; i >= 0 && i < count; i += direction)
- {
- const Token& tok = toks.m_tokens[i];
-
- switch (tok.type)
- {
- case TokenType::LBrace:
- case TokenType::LBracket:
- case TokenType::LParent:
- case TokenType::OpLess:
- {
- openCount += direction;
- if (openCount < 0) return -1;
- break;
- }
- case TokenType::RBracket:
- {
- openCount -= direction;
- if (openCount < 0) return -1;
- break;
- }
- case TokenType::OpGreater:
- {
- if (location == Location::AfterGenericParam && openCount == 0)
- {
- return i + 1;
- }
-
- openCount -= direction;
- if (openCount < 0) return -1;
-
- break;
- }
- case TokenType::RParent:
- {
- if (openCount == 0 && location == Location::AfterParam)
- {
- return i + 1;
- }
-
- openCount -= direction;
- if (openCount < 0) return -1;
- break;
- }
- case TokenType::RBrace:
- {
- // If we haven't hit a candidate yet before hitting } it's not going to work
- if (location == Location::Before || location == Location::AfterEnumCase)
- {
- return -1;
- }
- break;
- }
- case TokenType::BlockComment:
- case TokenType::LineComment:
- {
- if (openCount == 0)
- {
- // Determine the markup type
- const MarkupType markupType = findMarkupType(tok);
- // If the location wanted is before and the markup is, we'll assume this is it
- if (isBefore(location) && isBefore(markupType))
- {
- return i;
- }
- // If we are looking for enum cases, and the markup is after, we'll assume this is it
- if (isAfter(location) && isAfter(markupType))
- {
- return i;
- }
- }
- break;
- }
- case TokenType::Comma:
- {
- if (openCount == 0)
- {
- if (location == Location::AfterParam || location == Location::AfterEnumCase || location == Location::AfterGenericParam)
- {
- return i + 1;
- }
-
- if (location == Location::Before)
- {
- return -1;
- }
- }
-
- break;
- }
- case TokenType::Semicolon:
- {
- // If we haven't hit a candidate yet it's not going to work
- if (location == Location::Before)
- {
- return -1;
- }
- if (openCount == 0 && location == Location::AfterSemicolon)
- {
- return i + 1;
- }
- break;
- }
- default: break;
- }
- }
-
- return -1;
-}
-
-/* static */bool DocMarkupExtractor::_isTokenOnLineIndex(SourceView* sourceView, MarkupType type, const Token& tok, Index lineIndex)
-{
- SourceFile* sourceFile = sourceView->getSourceFile();
- const int offset = sourceView->getRange().getOffset(tok.loc);
-
- auto const flags = getFlags(type);
-
- if (flags & MarkupFlag::IsBlock)
- {
- // Either the start or the end of the block have to be on the specified line
- return sourceFile->isOffsetOnLine(offset, lineIndex) || sourceFile->isOffsetOnLine(offset + tok.charsCount, lineIndex);
- }
- else
- {
- // Has to be exactly on the specified line
- return sourceFile->isOffsetOnLine(offset, lineIndex);
- }
-}
-
-SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location location, FoundMarkup& out)
-{
- out.reset();
-
- const auto& toks = info.tokenList->m_tokens;
- const Index tokIndex = info.tokenIndex;
-
- // The starting token index
- Index startIndex = _findStartIndex(info, location);
- if (startIndex <= 0)
- {
- return SLANG_E_NOT_FOUND;
- }
-
- SourceView* sourceView = info.sourceView;
- SourceFile* sourceFile = sourceView->getSourceFile();
-
- // Let's lookup the line index where this occurred
- const int startOffset = sourceView->getRange().getOffset(toks[startIndex - 1].loc);
-
- // The line index that the markoff starts from
- Index lineIndex = sourceFile->calcLineIndexFromOffset(startOffset);
- if (lineIndex < 0)
- {
- return SLANG_E_NOT_FOUND;
- }
-
- const Index searchDirection = isBefore(location) ? -1 : 1;
-
- // Get the type and flags
- const MarkupType type = findMarkupType(toks[startIndex]);
- const MarkupFlags flags = getFlags(type);
-
- const MarkupFlag::Enum requiredFlag = isBefore(location) ? MarkupFlag::Before : MarkupFlag::After;
- if ((flags & requiredFlag) == 0)
- {
- return SLANG_E_NOT_FOUND;
- }
-
-#if 0
- // The token still isn't accepted, unless it's on the expected line
- if (_isTokenOnLineIndex(info.sourceView, type, toks[startIndex], expectedLineIndex))
- {
- return SLANG_E_NOT_FOUND;
- }
-#endif
-
- Index endIndex = startIndex;
-
- // If it's multiline, so look for the end index
- if (flags & MarkupFlag::IsMultiToken)
- {
- Index expectedLineIndex = lineIndex;
-
- // TODO(JS):
- // We should probably do the work here to confirm indentation - but that
- // requires knowing something about tabs, so for now we leave.
-
- while (true)
- {
- endIndex += searchDirection;
- expectedLineIndex += searchDirection;
-
- if (endIndex < 0 || endIndex >= toks.getCount())
- {
- break;
- }
-
- // Do we find a token of the right type?
- if (findMarkupType(toks[endIndex]) != type)
- {
- break;
- }
-
- // Is it on the right line?
- if (_isTokenOnLineIndex(info.sourceView, type, toks[startIndex], expectedLineIndex))
- {
- break;
- }
- }
-
- // Fix the end index (it's the last one that worked)
- endIndex -= searchDirection;
- }
-
- // Put start < end order
- if (endIndex < startIndex)
- {
- Swap(endIndex, startIndex);
- }
- // The range excludes end so increase
- endIndex++;
-
- // Okay we've found the markup
- out.type = type;
- out.location = location;
- out.range = IndexRange{ startIndex, endIndex };
-
- SLANG_ASSERT(out.range.getCount() > 0);
-
- return SLANG_OK;
-}
-
-SlangResult DocMarkupExtractor::_findFirstMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out, Index& outIndex)
-{
- Index i = 0;
- for (; i < locCount; ++i)
- {
- SlangResult res = _findMarkup(info, locs[i], out);
- if (SLANG_SUCCEEDED(res) || (SLANG_FAILED(res) && res != SLANG_E_NOT_FOUND))
- {
- outIndex = i;
- return res;
- }
- }
- return SLANG_E_NOT_FOUND;
-}
-
-SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out)
-{
- Index foundIndex;
- SLANG_RETURN_ON_FAIL(_findFirstMarkup(info, locs, locCount, out, foundIndex));
-
- // Lets see if the remaining ones match
- {
- FoundMarkup otherMarkup;
- for (Index i = foundIndex + 1; i < locCount; ++i)
- {
- SlangResult res = _findMarkup(info, locs[i], otherMarkup);
- if (SLANG_SUCCEEDED(res))
- {
- // TODO(JS): Warning found markup in another location
- }
- }
- }
-
- return SLANG_OK;
-}
-
-/* static */DocMarkupExtractor::SearchStyle DocMarkupExtractor::getSearchStyle(Decl* decl)
-{
- if (auto enumCaseDecl = as<EnumCaseDecl>(decl))
- {
- return SearchStyle::EnumCase;
- }
- if (auto paramDecl = as<ParamDecl>(decl))
- {
- return SearchStyle::Param;
- }
- else if (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 can't determine just allow before
- return SearchStyle::Before;
- }
-}
-
-SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, SearchStyle searchStyle, FoundMarkup& out)
-{
- switch (searchStyle)
- {
- default:
- case SearchStyle::None:
- {
- return SLANG_E_NOT_FOUND;
- }
- case SearchStyle::EnumCase:
- {
- Location locs[] = { Location::Before, Location::AfterEnumCase };
- return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out);
- }
- case SearchStyle::Param:
- {
- Location locs[] = { Location::Before, Location::AfterParam };
- return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out);
- }
- case SearchStyle::Before:
- {
- return _findMarkup(info, Location::Before, out);
- }
- case SearchStyle::Function:
- {
- return _findMarkup(info, Location::Before, out);
- }
- case SearchStyle::Variable:
- {
- Location locs[] = { Location::Before, Location::AfterSemicolon };
- return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out);
- }
- case SearchStyle::GenericParam:
- {
- Location locs[] = { Location::Before, Location::AfterGenericParam };
- return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out);
- }
- }
-}
-
-
-static void _calcLineVisibility(SourceView* sourceView, const TokenList& toks, List<MarkupVisibility>& outLineVisibility)
-{
- SourceFile* sourceFile = sourceView->getSourceFile();
- const auto& lineOffsets = sourceFile->getLineBreakOffsets();
-
- outLineVisibility.setCount(lineOffsets.getCount() + 1);
-
- MarkupVisibility lastVisibility = MarkupVisibility::Public;
- Index lastLine = 0;
-
- for (const auto& tok : toks)
- {
- if (tok.type == TokenType::LineComment)
- {
- UnownedStringSlice contents = tok.getContent();
-
- MarkupVisibility newVisibility = lastVisibility;
-
- // Distinct from other markup
- if (contents.startsWith(toSlice("//@")))
- {
- UnownedStringSlice access = contents.tail(3).trim();
- if (access == "hidden:" || access == "private:")
- {
- newVisibility = MarkupVisibility::Hidden;
- }
- else if (access == "internal:")
- {
- newVisibility = MarkupVisibility::Internal;
- }
- else if (access == "public:")
- {
- newVisibility = MarkupVisibility::Public;
- }
- }
-
- if (newVisibility != lastVisibility)
- {
- // Work up the line it's on
- const int offset = sourceView->getRange().getOffset(tok.loc);
- Index line = sourceFile->calcLineIndexFromOffset(offset);
-
- // Fill in the span
- for (Index i = lastLine; i < line; ++i)
- {
- outLineVisibility[i] = lastVisibility;
- }
-
- // Record the new access and where we are up to
- lastLine = line;
- lastVisibility = newVisibility;
- }
- }
- }
-
- // Fill in the remaining
- for (Index i = lastLine; i < outLineVisibility.getCount(); ++ i)
- {
- outLineVisibility[i] = lastVisibility;
- }
-}
-
-
-SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inputCount, SourceManager* sourceManager, DiagnosticSink* sink, List<SourceView*>& outViews, List<SearchItemOutput>& out)
-{
- struct Entry
- {
- typedef Entry ThisType;
-
- Index viewIndex; ///< The view/file index this loc is found in
- SourceLoc::RawValue locOrOffset; ///< Can be a loc or an offset into the file
-
- SearchStyle searchStyle; ///< The search style when looking for an item
- Index inputIndex; ///< The index to this item in the input
- };
-
- List<Entry> entries;
-
- {
- entries.setCount(inputCount);
- for (Index i = 0; i < inputCount; ++i)
- {
- const auto& input = inputs[i];
- Entry& entry = entries[i];
- entry.inputIndex = i;
- entry.viewIndex = -1; //< We don't know what file/view it's in
- entry.locOrOffset = input.sourceLoc.getRaw();
- entry.searchStyle = input.searchStyle;
- }
- }
-
- // Sort them into loc order
- entries.sort([](const Entry& a, const Entry& b) -> bool { return a.locOrOffset < b.locOrOffset; });
-
- {
- SourceView* sourceView = nullptr;
- Index viewIndex = -1;
-
- for (auto& entry : entries)
- {
- const SourceLoc loc = SourceLoc::fromRaw(entry.locOrOffset);
-
- if (sourceView == nullptr || !sourceView->getRange().contains(loc))
- {
- // Find the new view
- sourceView = sourceManager->findSourceView(loc);
- SLANG_ASSERT(sourceView);
-
- // We want only one view per SourceFile
- SourceFile* sourceFile = sourceView->getSourceFile();
-
- // NOTE! The view found might be different than sourceView.
- viewIndex = outViews.findFirstIndex([&](SourceView* currentView) -> bool { return currentView->getSourceFile() == sourceFile; });
-
- if (viewIndex < 0)
- {
- viewIndex = outViews.getCount();
- outViews.add(sourceView);
- }
- }
-
- SLANG_ASSERT(viewIndex >= 0);
- SLANG_ASSERT(sourceView && sourceView->getRange().contains(loc));
-
- // Set the file index
- entry.viewIndex = viewIndex;
- // Set as the offset within the file
- entry.locOrOffset = sourceView->getRange().getOffset(loc);
- }
-
- // Sort into view/file and then offset order
- entries.sort([](const Entry& a, const Entry& b) -> bool { return (a.viewIndex < b.viewIndex) || ((a.viewIndex == b.viewIndex) && a.locOrOffset < b.locOrOffset); });
- }
-
- {
- TokenList tokens;
- List<MarkupVisibility> lineVisibility;
-
- MemoryArena memoryArena(4096);
-
- RootNamePool rootNamePool;
- NamePool namePool;
- namePool.setRootNamePool(&rootNamePool);
-
- Index viewIndex = -1;
- SourceView* sourceView = nullptr;
-
- const Int entryCount = entries.getCount();
-
- out.setCount(entryCount);
-
- for (Index i = 0; i < entryCount; ++i)
- {
- const auto& entry = entries[i];
- auto& dst = out[i];
-
- dst.viewIndex = -1;
- dst.inputIndex = entry.inputIndex;
- dst.visibilty = MarkupVisibility::Public;
-
- // If there isn't a mechanism to search with, just move on
- if (entry.searchStyle == SearchStyle::None)
- {
- continue;
- }
-
- if (viewIndex != entry.viewIndex)
- {
- viewIndex = entry.viewIndex;
- sourceView = outViews[viewIndex];
-
- // Make all memory free again
- memoryArena.reset();
-
- // Run the lexer
- Lexer lexer;
- lexer.initialize(sourceView, sink, &namePool, &memoryArena);
-
- // Lex everything
- tokens = lexer.lexAllMarkupTokens();
-
- // Let's work out the access
-
- _calcLineVisibility(sourceView, tokens, lineVisibility);
- }
-
- dst.viewIndex = viewIndex;
-
- // Get the offset within the source file
- const uint32_t offset = entry.locOrOffset;
-
- // We need to get the loc in the source views space, so we look up appropriately in the list of tokens (which uses the views loc range)
- const SourceLoc loc = sourceView->getRange().getSourceLocFromOffset(offset);
-
- // Work out the line number
- SourceFile* sourceFile = sourceView->getSourceFile();
- const Index lineIndex = sourceFile->calcLineIndexFromOffset(int(offset));
-
- dst.visibilty = lineVisibility[lineIndex];
-
- // Okay, lets find the token index with a binary chop
- Index tokenIndex = _findTokenIndex(loc, tokens.m_tokens.getBuffer(), tokens.m_tokens.getCount());
- if (tokenIndex >= 0 && lineIndex >= 0)
- {
- FindInfo findInfo;
- findInfo.tokenIndex = tokenIndex;
- findInfo.lineIndex = lineIndex;
- findInfo.tokenList = &tokens;
- findInfo.sourceView = sourceView;
-
- // Okay let's see if we extract some documentation then for this.
- FoundMarkup foundMarkup;
- SlangResult res = _findMarkup(findInfo, entry.searchStyle, foundMarkup);
-
- if (SLANG_SUCCEEDED(res))
- {
- // We need to extract
- StringBuilder buf;
- SLANG_RETURN_ON_FAIL(_extractMarkup(findInfo, foundMarkup, buf));
-
- // Save the extracted text in the output
- dst.text = buf;
-
- }
- else if (res != SLANG_E_NOT_FOUND)
- {
- return res;
- }
- }
- }
- }
-
- return SLANG_OK;
-}
-
-static void _addDeclRec(Decl* decl, List<Decl*>& outDecls)
-{
- if (decl == nullptr)
- {
- 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);
- }
- else
- {
- SLANG_ASSERT(!"Decl without a location!");
- }
-
- 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->members)
- {
- _addDeclRec(childDecl, outDecls);
- }
- }
-}
-
-/* static */void DocMarkupExtractor::findDecls(ModuleDecl* moduleDecl, List<Decl*>& outDecls)
-{
- for (Decl* decl : moduleDecl->members)
- {
- _addDeclRec(decl, outDecls);
- }
-}
-
-SlangResult DocMarkupExtractor::extract(ModuleDecl* moduleDecl, SourceManager* sourceManager, DiagnosticSink* sink, DocMarkup* outDoc)
-{
- List<Decl*> decls;
- findDecls(moduleDecl, decls);
-
- const Index declsCount = decls.getCount();
-
- List<SearchItemInput> inputItems;
- List<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);
- }
-
- DocMarkupExtractor extractor;
-
- 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 != SearchStyle::None)
- {
- Decl* decl = decls[outputItem.inputIndex];
-
- // Add to the documentation
- DocMarkup::Entry& docEntry = outDoc->addEntry(decl);
- docEntry.m_markup = outputItem.text;
- docEntry.m_visibility = outputItem.visibilty;
- }
- }
-
- return SLANG_OK;
-}
-
-} // namespace Slang
diff --git a/source/slang/slang-doc-extractor.h b/source/slang/slang-doc-extractor.h
deleted file mode 100644
index 7a33b390a..000000000
--- a/source/slang/slang-doc-extractor.h
+++ /dev/null
@@ -1,219 +0,0 @@
-// slang-doc.h
-#ifndef SLANG_DOC_EXTRACTOR_H
-#define SLANG_DOC_EXTRACTOR_H
-
-#include "../core/slang-basic.h"
-#include "slang-ast-all.h"
-
-namespace Slang {
-
-enum class MarkupVisibility : uint8_t
-{
- Public, ///< Always available
- Internal, ///< Can be available in more verbose 'internal' documentation
- Hidden, ///< Not generally available
-};
-
-/* Holds the documentation markup that is associated with each node (typically a decl) from a module */
-class DocMarkup : public RefObject
-{
-public:
- struct Entry
- {
- NodeBase* m_node; ///< The node this documentation is associated with
- String m_markup; ///< The raw contents of of markup associated with the decoration
- MarkupVisibility m_visibility = MarkupVisibility::Public; ///< How visible this decl is
- };
-
- /// Adds an entry, returns the reference to pre-existing node if there is one
- Entry& addEntry(NodeBase* base);
- /// Gets an entry for a node. Returns nullptr if there is no markup.
- Entry* getEntry(NodeBase* base);
-
- /// Get list of all of the entries in source order
- const List<Entry>& getEntries() const { return m_entries; }
-
-protected:
-
- /// Map from AST nodes to documentation entries
- Dictionary<NodeBase*, Index> m_entryMap;
- /// All of the documentation entries in source order
- List<Entry> m_entries;
-};
-
-// ---------------------------------------------------------------------------
-SLANG_INLINE DocMarkup::Entry& DocMarkup::addEntry(NodeBase* base)
-{
- const Index count = m_entries.getCount();
- const Index index = m_entryMap.GetOrAddValue(base, count);
-
- if (index == count)
- {
- Entry entry;
- entry.m_node = base;
- m_entries.add(entry);
- }
- return m_entries[index];
-}
-
-// ---------------------------------------------------------------------------
-SLANG_INLINE DocMarkup::Entry* DocMarkup::getEntry(NodeBase* base)
-{
- Index* indexPtr = m_entryMap.TryGetValue(base);
- return (indexPtr) ? &m_entries[*indexPtr] : nullptr;
-}
-
-/* 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
-
- BlockAfter, /// /*!< */ or /**< */
- LineBangAfter, /// //!< Can be multiple lines
- LineSlashAfter, /// ///< Can be multiple lines
- };
-
- static bool isBefore(MarkupType type) { return Index(type) >= Index(MarkupType::BlockBefore) && Index(type) <= Index(MarkupType::LineSlashBefore); }
- 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
- };
-
- /// 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
- };
-
- /// Extracts documentation from the nodes held in the module using the source manager. Found documentation is placed
- /// in outMarkup
- static SlangResult extract(ModuleDecl* moduleDecl, SourceManager* sourceManager, DiagnosticSink* sink, DocMarkup* outMarkup);
-
- /// 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);
-
- /// Given a module finds all the decls, and places in outDecls
- static void findDecls(ModuleDecl* moduleDecl, List<Decl*>& outDecls);
-
- /// Given a decl determines the search style that is appropriate. Returns None if can't determine a suitable style
- static SearchStyle getSearchStyle(Decl* decl);
-
- 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;
-};
-
-} // namespace Slang
-
-#endif
diff --git a/source/slang/slang-doc-markdown-writer.cpp b/source/slang/slang-doc-markdown-writer.cpp
index 2a1226bb7..4d8afd763 100644
--- a/source/slang/slang-doc-markdown-writer.cpp
+++ b/source/slang/slang-doc-markdown-writer.cpp
@@ -128,7 +128,7 @@ String DocMarkdownWriter::_getName(InheritanceDecl* decl)
return buf.ProduceString();
}
-DocMarkdownWriter::NameAndText DocMarkdownWriter::_getNameAndText(DocMarkup::Entry* entry, Decl* decl)
+DocMarkdownWriter::NameAndText DocMarkdownWriter::_getNameAndText(ASTMarkup::Entry* entry, Decl* decl)
{
NameAndText nameAndText;
@@ -146,7 +146,7 @@ DocMarkdownWriter::NameAndText DocMarkdownWriter::_getNameAndText(DocMarkup::Ent
DocMarkdownWriter::NameAndText DocMarkdownWriter::_getNameAndText(Decl* decl)
{
- DocMarkup::Entry* entry = m_markup->getEntry(decl);
+ ASTMarkup::Entry* entry = m_markup->getEntry(decl);
return _getNameAndText(entry, decl);
}
@@ -242,7 +242,7 @@ void DocMarkdownWriter::_appendCommaList(const List<String>& strings, char wrapC
}
}
-void DocMarkdownWriter::writeVar(const DocMarkup::Entry& entry, VarDecl* varDecl)
+void DocMarkdownWriter::writeVar(const ASTMarkup::Entry& entry, VarDecl* varDecl)
{
writePreamble(entry);
auto& out = m_builder;
@@ -680,7 +680,7 @@ static bool _isFirstOverridden(Decl* decl)
return false;
}
-void DocMarkdownWriter::writeCallableOverridable(const DocMarkup::Entry& entry, CallableDecl* callableDecl)
+void DocMarkdownWriter::writeCallableOverridable(const ASTMarkup::Entry& entry, CallableDecl* callableDecl)
{
auto& out = m_builder;
@@ -843,7 +843,7 @@ void DocMarkdownWriter::writeCallableOverridable(const DocMarkup::Entry& entry,
}
}
-void DocMarkdownWriter::writeEnum(const DocMarkup::Entry& entry, EnumDecl* enumDecl)
+void DocMarkdownWriter::writeEnum(const ASTMarkup::Entry& entry, EnumDecl* enumDecl)
{
writePreamble(entry);
@@ -963,7 +963,7 @@ void DocMarkdownWriter::_appendAggTypeName(AggTypeDeclBase* aggTypeDecl)
}
}
-void DocMarkdownWriter::writeAggType(const DocMarkup::Entry& entry, AggTypeDeclBase* aggTypeDecl)
+void DocMarkdownWriter::writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclBase* aggTypeDecl)
{
writePreamble(entry);
@@ -1005,7 +1005,7 @@ void DocMarkdownWriter::writeAggType(const DocMarkup::Entry& entry, AggTypeDeclB
out << "* _" << assocTypeDecl->getName()->text << "_ ";
// Look up markup
- DocMarkup::Entry* assocTypeDeclEntry = m_markup->getEntry(assocTypeDecl);
+ ASTMarkup::Entry* assocTypeDeclEntry = m_markup->getEntry(assocTypeDecl);
if (assocTypeDeclEntry)
{
_appendAsSingleLine(assocTypeDeclEntry->m_markup.getUnownedSlice(), out);
@@ -1086,7 +1086,7 @@ void DocMarkdownWriter::writeAggType(const DocMarkup::Entry& entry, AggTypeDeclB
}
}
-void DocMarkdownWriter::writePreamble(const DocMarkup::Entry& entry)
+void DocMarkdownWriter::writePreamble(const ASTMarkup::Entry& entry)
{
SLANG_UNUSED(entry);
auto& out = m_builder;
@@ -1097,7 +1097,7 @@ void DocMarkdownWriter::writePreamble(const DocMarkup::Entry& entry)
out << toSlice("\n");
}
-void DocMarkdownWriter::writeDescription(const DocMarkup::Entry& entry)
+void DocMarkdownWriter::writeDescription(const ASTMarkup::Entry& entry)
{
auto& out = m_builder;
@@ -1117,7 +1117,7 @@ void DocMarkdownWriter::writeDescription(const DocMarkup::Entry& entry)
}
}
-void DocMarkdownWriter::writeDecl(const DocMarkup::Entry& entry, Decl* decl)
+void DocMarkdownWriter::writeDecl(const ASTMarkup::Entry& entry, Decl* decl)
{
// Skip these they will be output as part of their respective 'containers'
if (as<ParamDecl>(decl) || as<EnumCaseDecl>(decl) || as<AssocTypeDecl>(decl) || as<InheritanceDecl>(decl))
@@ -1161,7 +1161,7 @@ bool DocMarkdownWriter::isVisible(const Name* name)
return name == nullptr || !name->text.startsWith(toSlice("__"));
}
-bool DocMarkdownWriter::isVisible(const DocMarkup::Entry& entry)
+bool DocMarkdownWriter::isVisible(const ASTMarkup::Entry& entry)
{
// For now if it's not public it's not visible
if (entry.m_visibility != MarkupVisibility::Public)
diff --git a/source/slang/slang-doc-markdown-writer.h b/source/slang/slang-doc-markdown-writer.h
index 7a6c0a7e0..ff4c50759 100644
--- a/source/slang/slang-doc-markdown-writer.h
+++ b/source/slang/slang-doc-markdown-writer.h
@@ -2,7 +2,8 @@
#ifndef SLANG_DOC_MARKDOWN_WRITER_H
#define SLANG_DOC_MARKDOWN_WRITER_H
-#include "slang-doc-extractor.h"
+#include "slang-doc-ast.h"
+
#include "slang-ast-print.h"
#include "slang-compiler.h"
@@ -50,19 +51,19 @@ struct DocMarkdownWriter
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 writeCallableOverridable(const ASTMarkup::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 writeEnum(const ASTMarkup::Entry& entry, EnumDecl* enumDecl);
+ void writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclBase* aggTypeDecl);
+ void writeDecl(const ASTMarkup::Entry& entry, Decl* decl);
+ void writeVar(const ASTMarkup::Entry& entry, VarDecl* varDecl);
- void writePreamble(const DocMarkup::Entry& entry);
- void writeDescription(const DocMarkup::Entry& entry);
+ void writePreamble(const ASTMarkup::Entry& entry);
+ void writeDescription(const ASTMarkup::Entry& entry);
void writeSignature(CallableDecl* callableDecl);
- bool isVisible(const DocMarkup::Entry& entry);
+ bool isVisible(const ASTMarkup::Entry& entry);
bool isVisible(Decl* decl);
bool isVisible(const Name* name);
@@ -70,7 +71,7 @@ struct DocMarkdownWriter
const StringBuilder& getOutput() const { return m_builder; }
/// Ctor.
- DocMarkdownWriter(DocMarkup* markup, ASTBuilder* astBuilder) :
+ DocMarkdownWriter(ASTMarkup* markup, ASTBuilder* astBuilder) :
m_markup(markup),
m_astBuilder(astBuilder)
{
@@ -92,7 +93,7 @@ struct DocMarkdownWriter
String _getName(Decl* decl);
String _getName(InheritanceDecl* decl);
- NameAndText _getNameAndText(DocMarkup::Entry* entry, Decl* decl);
+ NameAndText _getNameAndText(ASTMarkup::Entry* entry, Decl* decl);
NameAndText _getNameAndText(Decl* decl);
template <typename T>
@@ -134,7 +135,7 @@ struct DocMarkdownWriter
void _appendAggTypeName(AggTypeDeclBase* aggTypeDecl);
- DocMarkup* m_markup;
+ ASTMarkup* m_markup;
ASTBuilder* m_astBuilder;
StringBuilder m_builder;
};
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 67908841f..e0b11604c 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -31,7 +31,7 @@
#include "slang-serialize-ir.h"
#include "slang-serialize-container.h"
-#include "slang-doc-extractor.h"
+#include "slang-doc-ast.h"
#include "slang-doc-markdown-writer.h"
#include "slang-check-impl.h"
@@ -300,8 +300,8 @@ SlangResult Session::compileStdLib(slang::CompileStdLibFlags compileFlags)
// For all the modules add their doc output to docStrings
for (Module* stdlibModule : stdlibModules)
{
- RefPtr<DocMarkup> markup(new DocMarkup);
- DocMarkupExtractor::extract(stdlibModule->getModuleDecl(), sourceManager, &sink, markup);
+ RefPtr<ASTMarkup> markup(new ASTMarkup);
+ ASTMarkupUtil::extract(stdlibModule->getModuleDecl(), sourceManager, &sink, markup);
DocMarkdownWriter writer(markup, astBuilder);
writer.writeAll();
@@ -2150,8 +2150,8 @@ SlangResult FrontEndCompileRequest::executeActionsInner()
{
for (TranslationUnitRequest* translationUnit : translationUnits)
{
- RefPtr<DocMarkup> markup(new DocMarkup);
- DocMarkupExtractor::extract(translationUnit->getModuleDecl(), getSourceManager(), getSink(), markup);
+ RefPtr<ASTMarkup> markup(new ASTMarkup);
+ ASTMarkupUtil::extract(translationUnit->getModuleDecl(), getSourceManager(), getSink(), markup);
// Convert to markdown
DocMarkdownWriter markdownWriter(markup, astBuilder);