Skip to content

Commit

Permalink
feat: tagfiles generation for cross-referencing in doxygen format
Browse files Browse the repository at this point in the history
  • Loading branch information
fpelliccioni committed Oct 29, 2024
1 parent 3f24987 commit 4452a6b
Show file tree
Hide file tree
Showing 22 changed files with 821 additions and 22 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,9 @@ jobs:
for generator in "${generators[@]}"; do
[[ $generator = xml && $variant = multi ]] && continue
[[ $variant = multi ]] && multipage="true" || multipage="false"
echo "Generating demos for $variant/$generator"
mrdocs --config="$(pwd)/boost/libs/url/doc/mrdocs.yml" "../CMakeLists.txt" --output="$(pwd)/demos/boost-url/$variant/$generator" --multipage=$multipage --generate="$generator"
echo "Number of files in demos/boost-url/$variant/$format: $(find demos/boost-url/$variant/$format -type f | wc -l)"
echo "Number of files in demos/boost-url/$variant/$generator: $(find demos/boost-url/$variant/$generator -type f | wc -l)"
done
done
Expand Down
33 changes: 33 additions & 0 deletions include/mrdocs/Corpus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,39 @@ class MRDOCS_VISIBLE
}
}

/** Visit the members of specified Info.
This function iterates the members of the specified
Info `I`. For each member associated with a
function with the same name as the member, the
function object `f` is invoked with the member
as the first argument, followed by `args...`.
When there are more than one member function
with the same name, the function object `f` is
invoked with an @ref OverloadSet as the first
argument, followed by `args...`.
@param I The Info to traverse.
@param pred The predicate to use to determine if the member should be visited.
@param f The function to invoke with the member as the first argument, followed by `args...`.
@param args The arguments to pass to the function.
*/
template <InfoParent T, class Pred, class F, class... Args>
void
traverseIf(
T const& I, Pred&& pred, F&& f, Args&&... args) const
{
for (auto const& id : I.Members)
{
if (std::forward<Pred>(pred)(get(id)))
{
visit(get(id), std::forward<F>(f),
std::forward<Args>(args)...);
}
}
}

/** Visit the function members of specified Info.
This function iterates the members of the specified
Expand Down
37 changes: 36 additions & 1 deletion include/mrdocs/Generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
namespace clang {
namespace mrdocs {

/** Context for the output of a single page.
* Needed to write the tagfile.
*/
struct GenerationContext {
std::ostream& tagFileOs;
std::string tagFileName;
};

/** Base class for documentation generators.
*/
class MRDOCS_VISIBLE
Expand Down Expand Up @@ -100,6 +108,33 @@ class MRDOCS_VISIBLE
std::string_view outputPath,
Corpus const& corpus) const;

/** Build reference documentation for the corpus.
This function invokes the generator to emit
the full documentation to an output stream,
as a single entity.
@par Thread Safety
@li Different `corpus` object: may be called concurrently.
@li Same `corpus` object: may not be called concurrently.
@return The error, if any occurred.
@param os The stream to write to.
@param corpus The metadata to emit.
@param context The context to use for the output.
*/
MRDOCS_DECL
virtual
Error
buildOne(
std::ostream& os,
Corpus const& corpus,
GenerationContext const& context) const = 0;


/** Build reference documentation for the corpus.
This function invokes the generator to emit
Expand All @@ -121,7 +156,7 @@ class MRDOCS_VISIBLE
Error
buildOne(
std::ostream& os,
Corpus const& corpus) const = 0;
Corpus const& corpus) const;

/** Build the reference as a single page to a file.
Expand Down
48 changes: 45 additions & 3 deletions src/lib/Gen/adoc/AdocGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@
#include "MultiPageVisitor.hpp"
#include "SinglePageVisitor.hpp"
#include "lib/Support/LegibleNames.hpp"
#include "lib/Support/RawOstream.hpp"

#include <mrdocs/Metadata/DomCorpus.hpp>
#include <mrdocs/Support/Error.hpp>
#include <mrdocs/Support/Path.hpp>

#include <llvm/Support/Path.h>

#include <fstream>
#include <optional>
#include <vector>

Expand Down Expand Up @@ -69,10 +76,35 @@ build(
if(! ex)
return ex.error();

MultiPageVisitor visitor(*ex, outputPath, corpus);
std::string path = files::appendPath(outputPath, "reference.tag.xml");
if(auto err = files::createDirectory(outputPath))
{
return err;
}

std::ofstream os;
try
{
os.open(path,
std::ios_base::binary |
std::ios_base::out |
std::ios_base::trunc // | std::ios_base::noreplace
);
}
catch(std::exception const& ex)
{
return formatError("std::ofstream(\"{}\") threw \"{}\"", path, ex.what());
}

RawOstream raw_os(os);
auto tagfileWriter = TagfileWriter(raw_os, corpus);
tagfileWriter.initialize();

MultiPageVisitor visitor(*ex, outputPath, corpus, tagfileWriter);
visitor(corpus.globalNamespace());

auto errors = ex->wait();
tagfileWriter.finalize();
if(! errors.empty())
return Error(errors);
return Error::success();
Expand All @@ -82,8 +114,11 @@ Error
AdocGenerator::
buildOne(
std::ostream& os,
Corpus const& corpus) const
Corpus const& corpus,
GenerationContext const& context) const
{
namespace path = llvm::sys::path;

auto options = loadOptions(corpus);
if(! options)
return options.error();
Expand All @@ -105,9 +140,16 @@ buildOne(
if(! errors.empty())
return {errors};

SinglePageVisitor visitor(*ex, corpus, os);

RawOstream raw_os(context.tagFileOs);
auto tagfileWriter = TagfileWriter(raw_os, corpus);
tagfileWriter.initialize();

auto const justFileName = path::filename(context.tagFileName);
SinglePageVisitor visitor(*ex, corpus, os, justFileName, tagfileWriter);
visitor(corpus.globalNamespace());
errors = ex->wait();
tagfileWriter.finalize();
if(! errors.empty())
return {errors};

Expand Down
3 changes: 2 additions & 1 deletion src/lib/Gen/adoc/AdocGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class AdocGenerator
Error
buildOne(
std::ostream& os,
Corpus const& corpus) const override;
Corpus const& corpus,
GenerationContext const& context) const override;
};

} // adoc
Expand Down
8 changes: 6 additions & 2 deletions src/lib/Gen/adoc/MultiPageVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,12 @@ operator()(T const& I)
{
ex_.async([this, &I](Builder& builder)
{
if(const auto r = builder(I))
writePage(*r, builder.domCorpus.getXref(I));
if(const auto r = builder(I))
{
auto const xref = builder.domCorpus.getXref(I);
writePage(*r, xref);
tagfileWriter_(I, xref, 0);
}
else
r.error().Throw();
if constexpr(
Expand Down
6 changes: 5 additions & 1 deletion src/lib/Gen/adoc/MultiPageVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define MRDOCS_LIB_GEN_ADOC_MULTIPAGEVISITOR_HPP

#include "Builder.hpp"
#include <lib/Lib/TagfileWriter.hpp>
#include <mrdocs/Support/ExecutorGroup.hpp>
#include <mutex>
#include <ostream>
Expand All @@ -29,6 +30,7 @@ class MultiPageVisitor
ExecutorGroup<Builder>& ex_;
std::string_view outputPath_;
Corpus const& corpus_;
TagfileWriter& tagfileWriter_;

void
writePage(
Expand All @@ -39,10 +41,12 @@ class MultiPageVisitor
MultiPageVisitor(
ExecutorGroup<Builder>& ex,
std::string_view outputPath,
Corpus const& corpus) noexcept
Corpus const& corpus,
TagfileWriter& tagfileWriter) noexcept
: ex_(ex)
, outputPath_(outputPath)
, corpus_(corpus)
, tagfileWriter_(tagfileWriter)
{
}

Expand Down
5 changes: 4 additions & 1 deletion src/lib/Gen/adoc/SinglePageVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ operator()(T const& I)
{
ex_.async([this, &I, page = numPages_++](Builder& builder)
{
if(auto r = builder(I))
if(auto r = builder(I))
{
writePage(*r, page);
tagfileWriter_(I, fileName_, page);
}
else
r.error().Throw();
});
Expand Down
9 changes: 8 additions & 1 deletion src/lib/Gen/adoc/SinglePageVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "Builder.hpp"
#include <mrdocs/MetadataFwd.hpp>
#include <lib/Lib/TagfileWriter.hpp>
#include <mrdocs/Support/ExecutorGroup.hpp>
#include <mutex>
#include <ostream>
Expand All @@ -35,16 +36,22 @@ class SinglePageVisitor
std::size_t topPage_ = 0;
std::vector<std::optional<
std::string>> pages_;
std::string fileName_;
TagfileWriter& tagfileWriter_;

void writePage(std::string pageText, std::size_t pageNumber);
public:
SinglePageVisitor(
ExecutorGroup<Builder>& ex,
Corpus const& corpus,
std::ostream& os) noexcept
std::ostream& os,
std::string_view fileName,
TagfileWriter& tagfileWriter) noexcept
: ex_(ex)
, corpus_(corpus)
, os_(os)
, fileName_(fileName)
, tagfileWriter_(tagfileWriter)
{
}

Expand Down
44 changes: 40 additions & 4 deletions src/lib/Gen/html/HTMLGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
#include "MultiPageVisitor.hpp"
#include "SinglePageVisitor.hpp"
#include "lib/Support/LegibleNames.hpp"
#include "lib/Support/RawOstream.hpp"

#include <mrdocs/Metadata/DomCorpus.hpp>
#include <mrdocs/Support/Error.hpp>
#include <mrdocs/Support/Path.hpp>

#include <fstream>
#include <optional>
#include <vector>

Expand Down Expand Up @@ -67,9 +71,34 @@ build(
if(! ex)
return ex.error();

MultiPageVisitor visitor(*ex, outputPath, corpus);
std::string path = files::appendPath(outputPath, "reference.tag.xml");
if(auto err = files::createDirectory(outputPath))
{
return err;
}

std::ofstream os;
try
{
os.open(path,
std::ios_base::binary |
std::ios_base::out |
std::ios_base::trunc // | std::ios_base::noreplace
);
}
catch(std::exception const& ex)
{
return formatError("std::ofstream(\"{}\") threw \"{}\"", path, ex.what());
}

RawOstream raw_os(os);
auto tagfileWriter = TagfileWriter(raw_os, corpus);
tagfileWriter.initialize();

MultiPageVisitor visitor(*ex, outputPath, corpus, tagfileWriter);
visitor(corpus.globalNamespace());
auto errors = ex->wait();
tagfileWriter.finalize();
if(! errors.empty())
return Error(errors);
return Error::success();
Expand All @@ -79,8 +108,9 @@ Error
HTMLGenerator::
buildOne(
std::ostream& os,
Corpus const& corpus) const
{
Corpus const& corpus,
GenerationContext const& context) const
{
HTMLCorpus domCorpus(corpus);
auto ex = createExecutors(domCorpus);
if(! ex)
Expand All @@ -98,9 +128,15 @@ buildOne(
if(! errors.empty())
return Error(errors);

SinglePageVisitor visitor(*ex, corpus, os);

RawOstream raw_os(context.tagFileOs);
auto tagfileWriter = TagfileWriter(raw_os, corpus);
tagfileWriter.initialize();

SinglePageVisitor visitor(*ex, corpus, os, context.tagFileName, tagfileWriter);
visitor(corpus.globalNamespace());
errors = ex->wait();
tagfileWriter.finalize();
if(! errors.empty())
return Error(errors);

Expand Down
3 changes: 2 additions & 1 deletion src/lib/Gen/html/HTMLGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class HTMLGenerator
Error
buildOne(
std::ostream& os,
Corpus const& corpus) const override;
Corpus const& corpus,
GenerationContext const& context) const override;
};

} // html
Expand Down
1 change: 1 addition & 0 deletions src/lib/Gen/html/MultiPageVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ renderPage(
std::ios_base::trunc // | std::ios_base::noreplace
);
os.write(pageText.data(), pageText.size());
tagfileWriter_(I, fileName, 0);
}
catch(std::exception const& ex)
{
Expand Down
Loading

0 comments on commit 4452a6b

Please sign in to comment.