Skip to content

Commit

Permalink
docs: expand build utilities javadoc
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Jan 31, 2024
1 parent 113ecbc commit 91d6742
Show file tree
Hide file tree
Showing 12 changed files with 459 additions and 101 deletions.
9 changes: 9 additions & 0 deletions src/lib/AST/Bitcode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,20 @@ namespace clang {
namespace mrdocs {

/** Return the serialized bitcode for a metadata node.
This function writes an Info variant to the buffer
as bitcode.
*/
llvm::SmallString<0>
writeBitcode(Info const& I);

/** Return an array of Info read from a bitstream.
This function reads a bitstream and returns an array
of Info objects. The bitstream must have been written
by `writeBitcode`.
@note Each bitcode might contain multiple Info objects.
*/
mrdocs::Expected<std::vector<std::unique_ptr<Info>>>
readBitcode(llvm::StringRef bitcode);
Expand Down
4 changes: 1 addition & 3 deletions src/lib/AST/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1247,10 +1247,8 @@ emitBlock(

//------------------------------------------------

/** Write an Info variant to the buffer as bitcode.
*/
llvm::SmallString<0>
writeBitcode(const Info& info)
writeBitcode(Info const& info)
{
llvm::SmallString<0> buffer;
llvm::BitstreamWriter stream(buffer);
Expand Down
31 changes: 30 additions & 1 deletion src/lib/AST/BitcodeWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@
namespace clang {
namespace mrdocs {

/** A writer for serializing the mrdocs' `Info` representation to LLVM bitcode.
This class takes in a llvm::BitstreamWriter stream and
emits the generated bitcode to that stream.
The function `dispatchInfoForWrite` is used to dispatch
the appropriate write function for the given `Info` object.
After calling `dispatchInfoForWrite`, the buffer used to
create the initial llvm::BitstreamWriter will be populated with
the serialized bitcode for the given `Info` object.
*/
class BitcodeWriter
{
public:
Expand All @@ -44,7 +57,23 @@ class BitcodeWriter
explicit
BitcodeWriter(llvm::BitstreamWriter &Stream);

// Write a specific info to a bitcode stream.
/** Write a specific Info to a bitcode stream.
This function takes in an `Info` object and
emits the generated bitcode to the internal
llvm::BitstreamWriter stream.
The function will dispatch the appropriate
write function for the given `Info` object.
After calling `dispatchInfoForWrite`, the
buffer used to create the initial
llvm::BitstreamWriter will be populated with
the serialized bitcode for the given
`Info` object.
@param I The info to write.
*/
bool dispatchInfoForWrite(const Info& I);

void emitHeader();
Expand Down
96 changes: 62 additions & 34 deletions src/lib/Lib/CorpusImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,36 +78,50 @@ find(

//------------------------------------------------

namespace {
template <class Rep, class Period>
std::string
format_duration(
std::chrono::duration<Rep, Period> delta)
{
auto delta_ms = std::chrono::duration_cast<
std::chrono::milliseconds>(delta).count();
if (delta_ms < 1000)
{
return fmt::format("{} ms", delta_ms);
}
else
{
double const delta_s = static_cast<double>(delta_ms) / 1000.0;
return fmt::format("{:.02f} s", delta_s);
}
}
}

mrdocs::Expected<std::unique_ptr<Corpus>>
CorpusImpl::
build(
report::Level reportLevel,
std::shared_ptr<ConfigImpl const> config,
std::shared_ptr<ConfigImpl const> const& config,
tooling::CompilationDatabase const& compilations)
{
using clock_type = std::chrono::steady_clock;
const auto format_duration =
[](clock_type::duration delta)
{
auto delta_ms = std::chrono::duration_cast<
std::chrono::milliseconds>(delta).count();
if(delta_ms < 1000)
return fmt::format("{} ms", delta_ms);
else
return fmt::format("{:.02f} s",
delta_ms / 1000.0);
};
auto start_time = clock_type::now();

auto corpus = std::make_unique<CorpusImpl>(config);

// Traverse the AST for all translation units
// and emit serializd bitcode into tool results.
// This operation happens ona thread pool.
report::print(reportLevel, "Extracting declarations");
// ------------------------------------------
// Create empty corpus
// ------------------------------------------
// The corpus will keep a reference to Config.
std::unique_ptr<CorpusImpl> corpus = std::make_unique<CorpusImpl>(config);

// ------------------------------------------
// Execution context
// ------------------------------------------
// Create an execution context to store the
// results of the AST traversal.
// Any new Info objects will be added to the
// InfoSet in the execution context.
#define USE_BITCODE

#ifdef USE_BITCODE
BitcodeExecutionContext context(*config);
#else
Expand All @@ -117,13 +131,9 @@ build(
makeFrontendActionFactory(context, *config);
MRDOCS_ASSERT(action);

// Get a copy of the filename strings
std::vector<std::string> files =
compilations.getAllFiles();

if(files.empty())
return Unexpected(formatError("Compilations database is empty"));

// ------------------------------------------
// "Process file" task
// ------------------------------------------
auto const processFile =
[&](std::string path)
{
Expand All @@ -144,15 +154,27 @@ build(
formatError("Failed to run action on {}", path).Throw();
};

// Run the action on all files in the database
// ------------------------------------------
// Run the process file task on all files
// ------------------------------------------
// Traverse the AST for all translation units
// and emit serializd bitcode into tool results.
// This operation happens on a thread pool.
report::print(reportLevel, "Extracting declarations");

// Get a copy of the filename strings
std::vector<std::string> files = compilations.getAllFiles();
MRDOCS_CHECK(files, "Compilations database is empty");
std::vector<Error> errors;
if(files.size() == 1)

// Run the action on all files in the database
if (files.size() == 1)
{
try
{
processFile(std::move(files.front()));
}
catch(Exception const& ex)
catch (Exception const& ex)
{
errors.push_back(ex.error());
}
Expand All @@ -169,16 +191,18 @@ build(
report::format(reportLevel,
"[{}/{}] \"{}\"", idx, files.size(), path);

processFile(std::move(path));
processFile(path);
});
}
errors = taskGroup.wait();
}

// Report warning and error totals
// Print diagnostics totals
context.reportEnd(reportLevel);

if(! errors.empty())
// ------------------------------------------
// Report warning and error totals
// ------------------------------------------
if (!errors.empty())
{
Error err(errors);
if(! (*config)->ignoreFailures)
Expand Down Expand Up @@ -207,6 +231,7 @@ build(
"Reduced {} symbols in {}",
corpus->info_.size(),
format_duration(clock_type::now() - start_time));
#undef USE_BITCODE
#else
auto results = context.results();
if(! results)
Expand All @@ -219,9 +244,12 @@ build(
format_duration(clock_type::now() - start_time));
#endif

// ------------------------------------------
// Finalize corpus
// ------------------------------------------
auto lookup = std::make_unique<SymbolLookup>(*corpus);

finalize(corpus->info_, *lookup);

return corpus;
}

Expand Down
36 changes: 33 additions & 3 deletions src/lib/Lib/CorpusImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ namespace clang {
namespace mrdocs {

/** Implements the Corpus.
The CorpusImpl class is the implementation of the Corpus interface.
It is responsible for building the index of all symbols in the
translation units, and providing access to the symbols via the
iterator interface.
The CorpusImpl class is not intended to be used directly. Instead,
the Corpus interface can used by plugins to access the symbols.
*/
class CorpusImpl : public Corpus
{
Expand All @@ -40,15 +49,36 @@ class CorpusImpl : public Corpus
{
}

iterator begin() const noexcept override;
iterator end() const noexcept override;
/** Iterator to the first Info.
*/
iterator
begin() const noexcept override;

/** Iterator to one past the last Info.
*/
iterator
end() const noexcept override;

/** Return the Info with the specified symbol ID.
If the id does not exist, the behavior is undefined.
*/
Info*
find(
SymbolID const& id) noexcept;

/** Build metadata for a set of translation units.
This is the main point of interaction between MrDocs
and the Clang Tooling infrastructure. The compilation
database is used to build the index of all symbols
in the translation units.
Users of the MrDocs library via plugins will
only have access to the Corpus interface whose
instance will be already populated. They will
not need to call this function directly.
@param reportLevel Error reporting level.
@param config A shared pointer to the configuration.
@param compilations A compilations database for the input files.
Expand All @@ -59,7 +89,7 @@ class CorpusImpl : public Corpus
mrdocs::Expected<std::unique_ptr<Corpus>>
build(
report::Level reportLevel,
std::shared_ptr<ConfigImpl const> config,
std::shared_ptr<ConfigImpl const> const& config,
tooling::CompilationDatabase const& compilations);

private:
Expand Down
Loading

0 comments on commit 91d6742

Please sign in to comment.