Update Doxygen docs for util namespace

This commit is contained in:
Bartek Kryza
2023-06-25 17:53:02 +02:00
parent f1250e5780
commit 46b8c29907
11 changed files with 204 additions and 56 deletions

View File

@@ -6,41 +6,29 @@
<!-- <tab type="pages" visible="yes" title="" intro=""/>--> <!-- <tab type="pages" visible="yes" title="" intro=""/>-->
<!-- <tab type="modules" visible="yes" title="" intro=""/>--> <!-- <tab type="modules" visible="yes" title="" intro=""/>-->
<tab type="user" url="./md_docs_2installation.html" title="Installation"/> <tab type="user" url="./md_docs_2installation.html" title="Installation"/>
<tab type="user" url="./md_docs_2test__cases.html" title="Test cases"/> <tab type="user" url="./md_docs_2test__cases.html" title="Test cases"/>
<tab type="user" visible="yes" url="./index.html" title="Doxygen">
<tab type="namespaces" visible="yes" title=""> <tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/> <tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/> <tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab> </tab>
<!-- <tab type="concepts" visible="yes" title="">--> <tab type="classes" visible="yes" title="">
<!-- </tab>--> <tab type="classlist" visible="yes" title="" intro=""/>
<!-- <tab type="interfaces" visible="yes" title="">--> <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<!-- <tab type="interfacelist" visible="yes" title="" intro=""/>--> <tab type="hierarchy" visible="yes" title="" intro=""/>
<!-- <tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>--> <tab type="classmembers" visible="yes" title="" intro=""/>
<!-- <tab type="interfacehierarchy" visible="yes" title="" intro=""/>--> </tab>
<!-- </tab>--> <tab type="structs" visible="yes" title="">
<tab type="classes" visible="yes" title=""> <tab type="structlist" visible="yes" title="" intro=""/>
<tab type="classlist" visible="yes" title="" intro=""/> <tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> </tab>
<tab type="hierarchy" visible="yes" title="" intro=""/> <tab type="files" visible="yes" title="">
<tab type="classmembers" visible="yes" title="" intro=""/> <tab type="filelist" visible="yes" title="" intro=""/>
</tab> <tab type="globals" visible="yes" title="" intro=""/>
<tab type="structs" visible="yes" title=""> </tab>
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
<!-- <tab type="exceptions" visible="yes" title="">-->
<!-- <tab type="exceptionlist" visible="yes" title="" intro=""/>-->
<!-- <tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>-->
<!-- <tab type="exceptionhierarchy" visible="yes" title="" intro=""/>-->
<!-- </tab>-->
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab> </tab>
<tab type="user" url="https://github.com/bkryza/clang-uml-examples" title="Examples"/>
<tab type="user" url="https://github.com/bkryza/clang-uml" title="GitHub"/> <tab type="user" url="https://github.com/bkryza/clang-uml" title="GitHub"/>
</navindex> </navindex>
<!-- Layout definition for a class page --> <!-- Layout definition for a class page -->

View File

@@ -143,6 +143,7 @@ std::optional<std::string> class_::doxygen_link() const
auto name = name_and_ns(); auto name = name_and_ns();
util::replace_all(name, "_", "__"); util::replace_all(name, "_", "__");
util::replace_all(name, "::", "_1_1"); util::replace_all(name, "::", "_1_1");
util::replace_all(name, "##", "_1_1"); // nested classes
return fmt::format("{}{}.html", type, name); return fmt::format("{}{}.html", type, name);
} }
} // namespace clanguml::class_diagram::model } // namespace clanguml::class_diagram::model

View File

@@ -17,7 +17,7 @@
*/ */
#include "compilation_database.h" #include "compilation_database.h"
#include "util/error.h"
#include "util/query_driver_output_extractor.h" #include "util/query_driver_output_extractor.h"
namespace clanguml::common { namespace clanguml::common {
@@ -31,7 +31,7 @@ compilation_database::auto_detect_from_directory(
cfg.compilation_database_dir(), error_message); cfg.compilation_database_dir(), error_message);
if (!error_message.empty()) if (!error_message.empty())
throw compilation_database_error(error_message); throw error::compilation_database_error(error_message);
return std::make_unique<compilation_database>(std::move(res), cfg); return std::make_unique<compilation_database>(std::move(res), cfg);
} }

View File

@@ -22,6 +22,7 @@
#include "common/model/template_parameter.h" #include "common/model/template_parameter.h"
#include "config/config.h" #include "config/config.h"
#include "types.h" #include "types.h"
#include "util/error.h"
#include "util/util.h" #include "util/util.h"
#include <clang/Frontend/CompilerInstance.h> #include <clang/Frontend/CompilerInstance.h>
@@ -34,10 +35,6 @@
namespace clanguml::common { namespace clanguml::common {
class compilation_database_error : public std::runtime_error {
using std::runtime_error::runtime_error;
};
/** /**
* @brief Custom compilation database class * @brief Custom compilation database class
* *

View File

@@ -81,12 +81,12 @@ int main(int argc, const char *argv[])
cli.effective_output_directory, db, cli.verbose, cli.thread_count, cli.effective_output_directory, db, cli.verbose, cli.thread_count,
cli.progress, cli.generators, translation_units_map); cli.progress, cli.generators, translation_units_map);
} }
catch (common::compilation_database_error &e) { catch (error::compilation_database_error &e) {
LOG_ERROR("Failed to load compilation database from {} due to: {}", LOG_ERROR("Failed to load compilation database from {} due to: {}",
cli.config.compilation_database_dir(), e.what()); cli.config.compilation_database_dir(), e.what());
return 1; return 1;
} }
catch (util::query_driver_no_paths &e) { catch (error::query_driver_no_paths &e) {
LOG_ERROR("Quering provided compiler driver {} did not provide any " LOG_ERROR("Quering provided compiler driver {} did not provide any "
"paths, please make sure the path is correct and that your " "paths, please make sure the path is correct and that your "
"compiler is GCC-compatible: {}", "compiler is GCC-compatible: {}",

View File

@@ -21,6 +21,10 @@
namespace clanguml::error { namespace clanguml::error {
class query_driver_no_paths : public std::runtime_error {
using std::runtime_error::runtime_error;
};
struct uml_alias_missing : public virtual std::runtime_error { struct uml_alias_missing : public virtual std::runtime_error {
uml_alias_missing(const std::string &message) uml_alias_missing(const std::string &message)
: std::runtime_error(message) : std::runtime_error(message)
@@ -28,4 +32,8 @@ struct uml_alias_missing : public virtual std::runtime_error {
} }
}; };
class compilation_database_error : public std::runtime_error {
using std::runtime_error::runtime_error;
};
} // namespace clanguml::error } // namespace clanguml::error

View File

@@ -18,6 +18,7 @@
#include "query_driver_output_extractor.h" #include "query_driver_output_extractor.h"
#include "error.h"
#include "util.h" #include "util.h"
#include <sstream> #include <sstream>
@@ -46,7 +47,7 @@ void query_driver_output_extractor::execute()
extract_target(driver_output); extract_target(driver_output);
if (system_include_paths_.empty()) { if (system_include_paths_.empty()) {
throw query_driver_no_paths(fmt::format( throw error::query_driver_no_paths(fmt::format(
"Compiler driver {} did not report any system include paths " "Compiler driver {} did not report any system include paths "
"in its output: {}", "in its output: {}",
command_, driver_output)); command_, driver_output));

View File

@@ -23,26 +23,58 @@
namespace clanguml::util { namespace clanguml::util {
class query_driver_no_paths : public std::runtime_error { /**
using std::runtime_error::runtime_error; * @brief Executed compiler frontend and extract default system paths
}; *
* This class - inspired by the `clangd` language server - will invoke the
* provided compiler command and query it for its default system paths,
* which then will be added to each compile command in the database.
*/
class query_driver_output_extractor { class query_driver_output_extractor {
public: public:
/**
* @brief Constructor.
*
* @param command Command to execute the compiler frontend
* @param language Language name to query for (C or C++)
*/
query_driver_output_extractor(std::string command, std::string language); query_driver_output_extractor(std::string command, std::string language);
~query_driver_output_extractor() = default; ~query_driver_output_extractor() = default;
/**
* @brief Execute the command and extract compiler flags and include paths
*/
void execute(); void execute();
/**
* @brief Extract target name from the compiler output
*
* @param output Compiler query driver output
*/
void extract_target(const std::string &output); void extract_target(const std::string &output);
/**
* @brief Extract system include paths from the compiler output
*
* @param output Compiler query driver output
*/
void extract_system_include_paths(const std::string &output); void extract_system_include_paths(const std::string &output);
const std::vector<std::string> &system_include_paths() const; /**
* @brief Name of the target of the compiler command (e.g. x86_64-linux-gnu)
*
* @return Target name
*/
const std::string &target() const; const std::string &target() const;
/**
* @brief Return list of include system paths
*
* @return List of include system paths
*/
const std::vector<std::string> &system_include_paths() const;
private: private:
const std::string command_; const std::string command_;
const std::string language_; const std::string language_;

View File

@@ -23,8 +23,17 @@
#include <vector> #include <vector>
namespace clanguml::util { namespace clanguml::util {
/**
* @brief Simple thread pool executor for parallelizing diagram generation.
*/
class thread_pool_executor { class thread_pool_executor {
public: public:
/**
* @brief Constructor
*
* @param pool_size Number of threads in the pool
*/
explicit thread_pool_executor(unsigned int pool_size); explicit thread_pool_executor(unsigned int pool_size);
thread_pool_executor(const thread_pool_executor &) = delete; thread_pool_executor(const thread_pool_executor &) = delete;
@@ -34,21 +43,31 @@ public:
~thread_pool_executor(); ~thread_pool_executor();
/**
* @brief Add a task to run on the pool.
*
* @param task Function to execute
* @return Future, allowing awaiting the result
*/
std::future<void> add(std::function<void()> &&task); std::future<void> add(std::function<void()> &&task);
/**
* @brief Join all active threads in the pool
*/
void stop(); void stop();
private: private:
/**
* @brief Main worker pool thread method - take task from queue and execute
*/
void worker(); void worker();
std::packaged_task<void()> get(); std::packaged_task<void()> get();
std::atomic_bool done_; std::atomic_bool done_;
std::deque<std::packaged_task<void()>> tasks_; std::deque<std::packaged_task<void()>> tasks_;
std::mutex tasks_mutex_; std::mutex tasks_mutex_;
std::condition_variable tasks_cond_; std::condition_variable tasks_cond_;
std::vector<std::thread> threads_; std::vector<std::thread> threads_;
}; };
} // namespace clanguml::util } // namespace clanguml::util

View File

@@ -54,28 +54,101 @@
namespace clanguml::util { namespace clanguml::util {
std::string ltrim(const std::string &s);
std::string rtrim(const std::string &s);
std::string trim(const std::string &s);
std::string trim_typename(const std::string &s);
#define FILENAME_ \ #define FILENAME_ \
(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
/**
* @brief Left trim a string
*
* @param s Input string
* @return Left trimmed string
*/
std::string ltrim(const std::string &s);
/**
* @brief Right trim a string
*
* @param s Input string
* @return Right trimmed string
*/
std::string rtrim(const std::string &s);
/**
* @brief Trim a string
*
* @param s Input string
* @return Trimmed string
*/
std::string trim(const std::string &s);
/**
* @brief Remove `typename` prefix from a string if exists
* @param s Input string
* @return String without `typename` prefix
*/
std::string trim_typename(const std::string &s);
/**
* @brief Execute a shell `command` and return console output as string
*
* @param command Shell command to execute
* @return Console output of the command
*/
std::string get_process_output(const std::string &command); std::string get_process_output(const std::string &command);
/**
* @brief Get value of an environment variable
*
* @param name Name of the environment variable
* @return Value of the environment variable, or empty if it doesn't exist
*/
std::string get_env(const std::string &name); std::string get_env(const std::string &name);
/**
* @brief Check if `$PWD` is in a Git repository
*
* This can be overridden by exporting `CLANGUML_GIT_COMMIT` environment
* variable.
*
* @return True, if the current directory is in a Git repository
*/
bool is_git_repository(); bool is_git_repository();
/**
* @brief Get current Git branch
*
* @return Name of the current Git branch
*/
std::string get_git_branch(); std::string get_git_branch();
/**
* @brief Get current Git revision
*
* Generates a Git revision tag using `git describe --tags --always` command
*
* @return Current repository Git revision
*/
std::string get_git_revision(); std::string get_git_revision();
/**
* @brief Get current Git commit
*
* @return Latest Git commit hash
*/
std::string get_git_commit(); std::string get_git_commit();
/**
* @brief Get path to the top level Git directory
*
* @return Absolut path to the nearest directory containing `.git` folder
*/
std::string get_git_toplevel_dir(); std::string get_git_toplevel_dir();
/**
* @brief Get descriptive name of the current operating system.
*
* @return Name of the operating system
*/
std::string get_os_name(); std::string get_os_name();
/** /**
@@ -94,14 +167,37 @@ std::string get_os_name();
std::vector<std::string> split( std::vector<std::string> split(
std::string str, std::string_view delimiter, bool skip_empty = true); std::string str, std::string_view delimiter, bool skip_empty = true);
/**
* @brief Remove and erase elements from a vector
*
* @tparam T Element type
* @tparam F Functor type
* @param v Vector to remove elements from
* @param f Functor to decide which elements to remove
*/
template <typename T, typename F> void erase_if(std::vector<T> &v, F &&f) template <typename T, typename F> void erase_if(std::vector<T> &v, F &&f)
{ {
v.erase(std::remove_if(v.begin(), v.end(), std::forward<F>(f)), v.end()); v.erase(std::remove_if(v.begin(), v.end(), std::forward<F>(f)), v.end());
} }
/**
* @brief Join `toks` into string using `delimiter` as separator
*
* @param toks Elements to join into string
* @param delimiter Separator to use to join elements
* @return Concatenated elements into one string
*/
std::string join( std::string join(
const std::vector<std::string> &toks, std::string_view delimiter); const std::vector<std::string> &toks, std::string_view delimiter);
/**
* @brief Join `args` into string using `delimiter` as separator
*
* @tparam Args Element type
* @param delimiter Separator to use to join elements
* @param args Elements to join into string
* @return Arguments concatenated into one string
*/
template <typename... Args> template <typename... Args>
std::string join(std::string_view delimiter, Args... args) std::string join(std::string_view delimiter, Args... args)
{ {
@@ -287,6 +383,12 @@ template <typename F> void _if(const bool condition, F &&func)
_if(condition, std::forward<F>(func), []() {}); _if(condition, std::forward<F>(func), []() {});
} }
/**
* @brief Generate a hash seed.
*
* @param seed Initial seed.
* @return Hash seed.
*/
std::size_t hash_seed(std::size_t seed); std::size_t hash_seed(std::size_t seed);
/** /**

View File

@@ -73,7 +73,7 @@ TEST_CASE("Test compilation_database should work", "[unit-test]")
REQUIRE( REQUIRE(
!contains(ccs.at(0).CommandLine, "-Wno-deprecated-declarations")); !contains(ccs.at(0).CommandLine, "-Wno-deprecated-declarations"));
} }
catch (clanguml::common::compilation_database_error &e) { catch (clanguml::error::compilation_database_error &e) {
REQUIRE(false); REQUIRE(false);
} }
} }
@@ -81,8 +81,8 @@ TEST_CASE("Test compilation_database should work", "[unit-test]")
TEST_CASE("Test compilation_database should throw", "[unit-test]") TEST_CASE("Test compilation_database should throw", "[unit-test]")
{ {
using clanguml::common::compilation_database; using clanguml::common::compilation_database;
using clanguml::common::compilation_database_error;
using clanguml::common::compilation_database_ptr; using clanguml::common::compilation_database_ptr;
using clanguml::error::compilation_database_error;
using clanguml::util::contains; using clanguml::util::contains;
auto cfg = clanguml::config::load( auto cfg = clanguml::config::load(