// 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(decl)) { return SearchStyle::EnumCase; } if (const auto paramDecl = as(decl)) { return SearchStyle::Param; } else if (const auto callableDecl = as(decl)) { return SearchStyle::Function; } else if (as(decl) || as(decl) || as(decl)) { return SearchStyle::Variable; } else if (auto genericDecl = as(decl)) { return getSearchStyle(genericDecl->inner); } else if (as(decl) || as(decl)) { return SearchStyle::GenericParam; } else if (as(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(); } static void _addDeclRec(Decl* decl, List& 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(decl)) { _addDeclRec(genericDecl->inner, outDecls); } if (ContainerDecl* containerDecl = as(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& outDecls) { for (Decl* decl : moduleDecl->getDirectMemberDecls()) { _addDeclRec(decl, outDecls); } } SlangResult ASTMarkupUtil::extract( ModuleDecl* moduleDecl, SourceManager* sourceManager, DiagnosticSink* sink, ASTMarkup* outDoc, bool searchOrindaryComments) { List decls; findDecls(moduleDecl, decls); const Index declsCount = decls.getCount(); List inputItems; List 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 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