diff --git a/CMakeLists.txt b/CMakeLists.txt index 32b8bd9b0..c756346e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,6 @@ else() endif() target_include_directories(mrdox-api SYSTEM PUBLIC ${CLANG_INCLUDE_DIRS}) - # Windows, Win64 if (WIN32) target_compile_definitions( diff --git a/include/mrdox/Config.hpp b/include/mrdox/Config.hpp index ca1ede794..c162f6ac1 100644 --- a/include/mrdox/Config.hpp +++ b/include/mrdox/Config.hpp @@ -22,13 +22,6 @@ #include #include -namespace llvm { -namespace yaml { -template -struct MappingTraits; -} // yaml -} // llvm - namespace clang { namespace mrdox { @@ -53,6 +46,7 @@ class MRDOX_VISIBLE llvm::SmallString<0> outputPath_; std::string sourceRoot_; bool includePrivate_ = false; + bool singlePage_ = false; bool verbose_ = true; explicit @@ -129,6 +123,14 @@ class MRDOX_VISIBLE return includePrivate_; } + /** Return true if the output is single-page output. + */ + bool + singlePage() const noexcept + { + return singlePage_; + } + /** Call a function for each element of a range. The function is invoked with a reference @@ -159,6 +161,13 @@ class MRDOX_VISIBLE verbose_ = verbose; } + void + setSinglePage( + bool singlePage) noexcept + { + singlePage_ = singlePage; + } + /** Set whether or not to include private members. */ void diff --git a/source/api/Config.cpp b/source/api/Config.cpp index 17acd2ef8..4750721ba 100644 --- a/source/api/Config.cpp +++ b/source/api/Config.cpp @@ -37,6 +37,7 @@ class Config::Options bool verbose = true; bool include_private = false; std::string source_root; + bool single_page = false; FileFilter input; }; @@ -64,6 +65,7 @@ struct llvm::yaml::MappingTraits< io.mapOptional("verbose", opt.verbose); io.mapOptional("private", opt.include_private); io.mapOptional("source-root", opt.source_root); + io.mapOptional("single-page", opt.single_page); io.mapOptional("input", opt.input); } }; @@ -258,6 +260,7 @@ loadFromFile( (*config)->setIncludePrivate(opt.include_private); (*config)->setSourceRoot(opt.source_root); (*config)->setInputFileIncludes(opt.input.include); + (*config)->setSinglePage(opt.single_page); return config; } diff --git a/source/api/ConfigImpl.hpp b/source/api/ConfigImpl.hpp index d53593a60..9263a73a6 100644 --- a/source/api/ConfigImpl.hpp +++ b/source/api/ConfigImpl.hpp @@ -17,6 +17,13 @@ #include #include +namespace llvm { +namespace yaml { +template +struct MappingTraits; +} // yaml +} // llvm + namespace clang { namespace mrdox { diff --git a/source/api/_adoc/AdocSinglePageWriter.cpp b/source/api/_adoc/AdocSinglePageWriter.cpp index 228512b2d..509e4403e 100644 --- a/source/api/_adoc/AdocSinglePageWriter.cpp +++ b/source/api/_adoc/AdocSinglePageWriter.cpp @@ -37,33 +37,131 @@ build() "= Reference\n" ":role: mrdox\n"; corpus_.visit(globalNamespaceID, *this); - closeSection(); + endSection(); return llvm::Error::success(); } +//------------------------------------------------ + +template +std::vector +AdocSinglePageWriter:: +buildSortedList( + std::vector const& from) const +{ + std::vector result; + result.reserve(from.size()); + for(auto const& ref : from) + result.push_back(&corpus_.get(ref.id)); + llvm::sort(result, + [&](Info const* I0, Info const* I1) + { + return compareSymbolNames( + I0->Name, I1->Name) < 0; + }); + return result; +} + +/* Write a namespace. + + This will index all individual + symbols except child namespaces, + sorted by group. +*/ bool AdocSinglePageWriter:: visit( NamespaceInfo const& I) { - write(I); - if(! corpus_.visit(I.Children.Namespaces, *this)) - return false; - - // Visit records in alphabetical display order - std::vector list; - list.reserve(I.Children.Records.size()); - for(auto const& ref : I.Children.Records) - list.push_back(&corpus_.get(ref.id)); - std::string s0, s1; - llvm::sort(list, - [&s0, &s1](Info const* I0, Info const* I1) + //if(! corpus_.visit(I.Children.Namespaces, *this)) + //return false; +/* + if( I.Children.Records.empty() && + I.Children.Functions.empty() && + I.Children.Typedefs.empty() && + I.Children.Enums.empty()) + return; +*/ + // build sorted list of namespaces, + // this is for visitation not display. + auto namespaceList = buildSortedList(I.Children.Namespaces); + + // don't emit empty namespaces, + // but still visit child namespaces. + if( ! I.Children.Records.empty() || + ! I.Children.Functions.empty() || + ! I.Children.Typedefs.empty() || + ! I.Children.Enums.empty()) + { + std::string s; + I.getFullyQualifiedName(s); + s = "namespace " + s; + + beginSection(s); + + auto recordList = buildSortedList(I.Children.Records); + auto functionList = buildSortedList(I.Children.Functions); + //auto typeList = ? + //auto enumList = ? + + if(! recordList.empty()) { - return compareSymbolNames( - I0->getFullyQualifiedName(s0), - I1->getFullyQualifiedName(s1)) < 0; - }); - for(auto const I : list) + beginSection("Classes"); + os_ << "\n" + "[cols=1]\n" + "|===\n"; + for(auto const I : recordList) + { + os_ << "\n|" << linkFor(*I) << '\n'; + }; + os_ << "|===\n"; + endSection(); + } + + if(! functionList.empty()) + { + beginSection("Functions"); + os_ << "\n" + "[cols=1]\n" + "|===\n"; + for(auto const I : functionList) + { + os_ << "\n|" << linkFor(*I) << '\n'; + }; + os_ << "|===\n"; + endSection(); + } + + //if(! typeList.empty()) + + //if(! enumList.empty()) + + // now visit each indexed item + for(auto const& I : recordList) + visit(*I); + recordList.clear(); + + for(auto const& I : functionList) + visit(*I); + functionList.clear(); + + /* + for(auto const& I : typeList) + visit(*I); + typeList.clear(); + */ + + /* + for(auto const& I : enumList) + visit(*I); + typeList.clear(); + */ + + endSection(); + } + + // visit child namespaces + for(auto const& I : namespaceList) if(! visit(*I)) return false; diff --git a/source/api/_adoc/AdocSinglePageWriter.hpp b/source/api/_adoc/AdocSinglePageWriter.hpp index f3a0ecfb5..5e4604733 100644 --- a/source/api/_adoc/AdocSinglePageWriter.hpp +++ b/source/api/_adoc/AdocSinglePageWriter.hpp @@ -35,6 +35,13 @@ class AdocSinglePageWriter llvm::Error build(); private: + /** Return an array of info pointers display-sorted by symbol. + */ + template + std::vector + buildSortedList( + std::vector const& from) const; + bool visit(NamespaceInfo const&) override; bool visit(RecordInfo const&) override; bool visit(FunctionInfo const&) override; diff --git a/source/api/_adoc/AdocWriter.cpp b/source/api/_adoc/AdocWriter.cpp index 9733fc0b6..66920526b 100644 --- a/source/api/_adoc/AdocWriter.cpp +++ b/source/api/_adoc/AdocWriter.cpp @@ -115,71 +115,6 @@ AdocWriter:: write( NamespaceInfo const& I) { - if( I.Children.Records.empty() && - I.Children.Functions.empty() && - I.Children.Typedefs.empty() && - I.Children.Enums.empty()) - return; - - std::string s; - I.getFullyQualifiedName(s); - s = "namespace " + s; - - openSection(s); - - if(! I.Children.Records.empty()) - { - openSection("Classes"); - os_ << "\n" - "[cols=1]\n" - "|===\n"; - for(auto const& ref : I.Children.Records) - { - auto const& I = corpus_.get(ref.id); - os_ << "\n|" << linkFor(I) << '\n'; - }; - os_ << - "|===\n"; - closeSection(); - } - - if(! I.Children.Functions.empty()) - { - openSection("Functions"); - os_ << '\n'; - for(auto const& ref : I.Children.Functions) - { - auto const& I = corpus_.get(ref.id); - os_ << linkFor(I) << '\n'; - }; - closeSection(); - } - - if(! I.Children.Typedefs.empty()) - { - openSection("Types"); - os_ << '\n'; - for(auto const& ref : I.Children.Typedefs) - { - auto const& I = corpus_.get(ref.id); - os_ << linkFor(I) << '\n'; - }; - closeSection(); - } - - if(! I.Children.Enums.empty()) - { - openSection("Constants"); - os_ << '\n'; - for(auto const& ref : I.Children.Enums) - { - auto const& I = corpus_.get(ref.id); - os_ << linkFor(I) << '\n'; - }; - closeSection(); - } - - closeSection(); } //------------------------------------------------ @@ -194,13 +129,13 @@ AdocWriter:: write( RecordInfo const& I) { - openSection(I); + beginSection(I); // Brief writeBrief(I.javadoc); // Synopsis - openSection("Synopsis"); + beginSection("Synopsis"); // Location writeLocation(I); @@ -224,7 +159,7 @@ write( os_ << ";\n" "----\n"; - closeSection(); + endSection(); // Description writeDescription(I.javadoc); @@ -271,7 +206,7 @@ write( makeOverloadsSet(corpus_, I.Children, AccessSpecifier::AS_private)); - closeSection(); + endSection(); } void @@ -279,13 +214,13 @@ AdocWriter:: write( FunctionInfo const& I) { - openSection(I.Name); + beginSection(I.Name); // Brief writeBrief(I.javadoc); // Synopsis - openSection("Synopsis"); + beginSection("Synopsis"); writeLocation(I); @@ -314,12 +249,12 @@ write( } os_ << "----\n"; - closeSection(); + endSection(); // Description writeDescription(I.javadoc); - closeSection(); + endSection(); } void @@ -327,7 +262,7 @@ AdocWriter:: write( TypedefInfo const& I) { - openSection(I.Name); + beginSection(I.Name); // Brief writeBrief(I.javadoc); @@ -337,7 +272,7 @@ write( // Description writeDescription(I.javadoc); - closeSection(); + endSection(); } void @@ -345,7 +280,7 @@ AdocWriter:: write( EnumInfo const& I) { - openSection(I.Name); + beginSection(I.Name); // Brief writeBrief(I.javadoc); @@ -355,7 +290,7 @@ write( // Description writeDescription(I.javadoc); - closeSection(); + endSection(); } //------------------------------------------------ @@ -390,7 +325,7 @@ writeFunctionOverloads( { if(set.list.empty()) return; - openSection(sectionName); + beginSection(sectionName); os_ << "\n" "[,cols=2]\n" << @@ -418,7 +353,7 @@ writeFunctionOverloads( os_ << "|===\n" << "\n"; - closeSection(); + endSection(); } void @@ -441,7 +376,7 @@ writeNestedTypes( ++it; } #endif - openSection(sectionName); + beginSection(sectionName); os_ << "\n" "[,cols=2]\n" << @@ -463,7 +398,7 @@ writeNestedTypes( os_ << "|===\n" << "\n"; - closeSection(); + endSection(); } void @@ -485,7 +420,7 @@ writeDataMembers( break; ++it; } - openSection(sectionName); + beginSection(sectionName); os_ << "\n" "[,cols=2]\n" << @@ -505,7 +440,7 @@ writeDataMembers( os_ << "|===\n" << "\n"; - closeSection(); + endSection(); } //------------------------------------------------ @@ -537,10 +472,10 @@ writeDescription( return; //os_ << '\n'; - openSection("Description"); + beginSection("Description"); os_ << '\n'; writeNodes(javadoc->getBlocks()); - closeSection(); + endSection(); } void @@ -737,7 +672,7 @@ typeName( void AdocWriter:: -openSection( +beginSection( Info const& I) { Assert(validAdocSectionID(names_.get(I.id))); @@ -753,7 +688,7 @@ openSection( void AdocWriter:: -openSection( +beginSection( llvm::StringRef name) { sect_.level++; @@ -766,7 +701,7 @@ openSection( void AdocWriter:: -closeSection() +endSection() { Assert(sect_.level > 0); if(sect_.level <= 6) diff --git a/source/api/_adoc/AdocWriter.hpp b/source/api/_adoc/AdocWriter.hpp index f8a4d8bc5..5c7e1b891 100644 --- a/source/api/_adoc/AdocWriter.hpp +++ b/source/api/_adoc/AdocWriter.hpp @@ -100,9 +100,9 @@ class AdocWriter FormalParam formalParam(FieldTypeInfo const& ft); TypeName typeName(TypeInfo const& ti); - void openSection(Info const& I); - void openSection(llvm::StringRef name); - void closeSection(); + void beginSection(Info const& I); + void beginSection(llvm::StringRef name); + void endSection(); static llvm::StringRef toString(TagTypeKind k) noexcept; }; diff --git a/source/tool/ToolMain.cpp b/source/tool/ToolMain.cpp index e2d4047a1..8cc3a60ec 100644 --- a/source/tool/ToolMain.cpp +++ b/source/tool/ToolMain.cpp @@ -29,14 +29,6 @@ #include #include -#if 0 -#if defined(_MSC_VER) && ! defined(NDEBUG) -#define WIN32_LEAN_AND_MEAN -#include -#include -#endif -#endif - namespace clang { namespace mrdox { @@ -138,8 +130,18 @@ toolMain( // Run the generator. if((*config)->verbose()) llvm::outs() << "Generating docs...\n"; - if(! generator->buildPages((*config)->outputPath(), **corpus, R)) - return; + if((*corpus)->config()->singlePage()) + { + if(! generator->buildSinglePageFile( + (*config)->outputPath(), **corpus, R)) + return; + } + else + { + if(! generator->buildPages( + (*config)->outputPath(), **corpus, R)) + return; + } } } // mrdox