Skip to content

Commit

Permalink
Allow defining symbols as part of a detail set based on namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterTh committed Feb 15, 2024
1 parent 8e686b9 commit 67e6a0c
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 27 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ We are happy to integrate useful PRs, but we don't currently have the bandwidth
* Support **markdown syntax** in doc comments
* Document **aliases (i.e. usings)**, both at top level namespaces and in records
* Correctly resolve file locations for **symbols defined in macros** (and therefore include them in the docs)
* Allow defining symbols as part of a "detail" set based on a list of namespace (sub-)strings; this set can be styled differently
* Allow ignoring symbols on namespace basis (in addition to file path)
* Include operators in documentation and format them properly
* Various improvements to presentation, especially in the presence of complex member function signatures
Expand Down
8 changes: 8 additions & 0 deletions assets/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ body {
opacity: 1;
}

.hdoc-detail {
opacity: 0.5;
background-color: #f5f5f5;
}
.hdoc-detail:hover {
opacity: 1;
}

.hdoc-overview-template {
font-size: smaller;
}
Expand Down
13 changes: 13 additions & 0 deletions src/frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,19 @@ hdoc::frontend::Frontend::Frontend(int argc, char** argv, hdoc::types::Config* c
}
}

// Get substrings of namespaces that should be considered "detail" namespaces
if (const auto& detailNamespaces = toml["detail"]["namespaces"].as_array()) {
for (const auto& i : *detailNamespaces) {
std::string s = i.value_or(std::string(""));
if (s == "") {
spdlog::warn("A detail namespace directive from .hdoc.toml was malformed, ignoring it.");
continue;
}
spdlog::info("Detail namespaces containing: {}", s);
cfg->detailNamespaces.emplace_back(s);
}
}

if (const toml::value<bool>* ignorePrivateMembers = toml["ignore"]["ignore_private_members"].as_boolean()) {
cfg->ignorePrivateMembers = ignorePrivateMembers->get();
}
Expand Down
3 changes: 2 additions & 1 deletion src/indexer/MatcherUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ const clang::ClassTemplateDecl* getNonSpecializedVersionOfDecl(const clang::TagD
return NULL;
}

void findParentNamespace(hdoc::types::Symbol& s, const clang::NamedDecl* d) {
void fillNamespace(hdoc::types::Symbol& s, const clang::NamedDecl* d, const hdoc::types::Config* cfg) {
const auto* dc = d->getLexicalDeclContext();
if (const auto* n = llvm::dyn_cast_or_null<clang::NamespaceDecl>(dc)) {
s.parentNamespaceID = buildID(n);
} else if (const auto* n = llvm::dyn_cast_or_null<clang::RecordDecl>(dc)) {
s.parentNamespaceID = buildID(n);
}
s.isDetail = hdoc::indexer::matchers::utils::isEnclosingNamespaceInList(d, cfg->detailNamespaces);
}

bool isInIgnoreList(const clang::Decl* d, const hdoc::types::Config* cfg) {
Expand Down
2 changes: 1 addition & 1 deletion src/indexer/MatcherUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void fillOutSymbol(hdoc::types::Symbol& s, const clang::NamedDecl* d, const std:
const clang::ClassTemplateDecl* getNonSpecializedVersionOfDecl(const clang::TagDecl* tagdecl);

/// @brief Find the parent namespace (either record or an actual namespace) of a decl
void findParentNamespace(hdoc::types::Symbol& s, const clang::NamedDecl* d);
void fillNamespace(hdoc::types::Symbol& s, const clang::NamedDecl* d, const hdoc::types::Config* cfg);

/// @brief Check if a decl is defined in a non-existent file or in the set of ignored paths or namespaces
bool isInIgnoreList(const clang::Decl* d, const hdoc::types::Config* cfg);
Expand Down
10 changes: 5 additions & 5 deletions src/indexer/Matchers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ void hdoc::indexer::matchers::FunctionMatcher::run(const clang::ast_matchers::Ma
f.proto = getFunctionSignature(f);
f.isRecordMember = res->isCXXClassMember();

findParentNamespace(f, res);
fillNamespace(f, res, this->cfg);
this->index->functions.update(f.ID, f);
}

Expand Down Expand Up @@ -245,7 +245,7 @@ void hdoc::indexer::matchers::UsingMatcher::run(const clang::ast_matchers::Match
processSymbolComment(a, comment, res->getASTContext());
}

findParentNamespace(a, res);
fillNamespace(a, res, this->cfg);
this->index->aliases.update(a.ID, a);
}

Expand Down Expand Up @@ -531,7 +531,7 @@ void hdoc::indexer::matchers::RecordMatcher::run(const clang::ast_matchers::Matc
processSymbolComment(c, comment, res->getASTContext());
}

findParentNamespace(c, res);
fillNamespace(c, res, this->cfg);
this->index->records.update(c.ID, c);
}

Expand Down Expand Up @@ -593,7 +593,7 @@ void hdoc::indexer::matchers::EnumMatcher::run(const clang::ast_matchers::MatchF
processSymbolComment(e, comment, res->getASTContext());
}

findParentNamespace(e, res);
fillNamespace(e, res, this->cfg);
this->index->enums.update(e.ID, e);
}

Expand All @@ -618,6 +618,6 @@ void hdoc::indexer::matchers::NamespaceMatcher::run(const clang::ast_matchers::M
n.ID = ID;
fillOutSymbol(n, res, this->cfg->rootDir);

findParentNamespace(n, res);
fillNamespace(n, res, this->cfg);
this->index->namespaces.update(n.ID, n);
}
30 changes: 19 additions & 11 deletions src/serde/HTMLWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,11 @@ static void printNewPage(const hdoc::types::Config& cfg,

// Add links to all of the standard sections
menuUL.AddChild(CTML::Node("p.menu-label", "API Documentation"));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Functions").SetAttr("href", "functions.html")));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Namespaces").SetAttr("href", "namespaces.html")));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Records").SetAttr("href", "records.html")));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Aliases").SetAttr("href", "aliases.html")));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Enums").SetAttr("href", "enums.html")));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Namespaces").SetAttr("href", "namespaces.html")));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Functions").SetAttr("href", "functions.html")));
menuUL.AddChild(CTML::Node("li").AddChild(CTML::Node("a", "Aliases").SetAttr("href", "aliases.html")));
aside.AddChild(menuUL);

columnsDiv.AddChild(aside);
Expand Down Expand Up @@ -542,9 +542,11 @@ void hdoc::serde::HTMLWriter::printFunctions() const {
continue;
}
numFunctions += 1;
ul.AddChild(CTML::Node("li")
auto li = CTML::Node("li")
.AddChild(CTML::Node("a.is-family-code", f.name).SetAttr("href", f.url()))
.AppendText(getSymbolBlurb(f)));
.AppendText(getSymbolBlurb(f));
if (f.isDetail) li.ToggleClass("hdoc-detail");
ul.AddChild(li);
CTML::Node page("main");
this->pool.async(
[&](const hdoc::types::FunctionSymbol& func, CTML::Node pg) {
Expand Down Expand Up @@ -619,9 +621,11 @@ void hdoc::serde::HTMLWriter::printAliases() const {
continue;
}
numUsings += 1;
ul.AddChild(CTML::Node("li")
auto li = CTML::Node("li")
.AddChild(CTML::Node("a.is-family-code", u.name).SetAttr("href", u.url()))
.AppendText(getSymbolBlurb(u)));
.AppendText(getSymbolBlurb(u));
if (u.isDetail) li.ToggleClass("hdoc-detail");
ul.AddChild(li);
CTML::Node page("main");
this->pool.async(
[&](const hdoc::types::AliasSymbol& alias, CTML::Node pg) {
Expand Down Expand Up @@ -925,9 +929,11 @@ void hdoc::serde::HTMLWriter::printRecords() const {
CTML::Node ul("ul");
for (const auto& id : getSortedIDs(map2vec(this->index->records), this->index->records)) {
const auto& c = this->index->records.entries.at(id);
ul.AddChild(CTML::Node("li")
auto li = CTML::Node("li")
.AddChild(CTML::Node("a.is-family-code", c.type + " " + c.name).SetAttr("href", c.url()))
.AppendText(getSymbolBlurb(c)));
.AppendText(getSymbolBlurb(c));
if (c.isDetail) li.ToggleClass("hdoc-detail");
ul.AddChild(li);
this->pool.async([&](const hdoc::types::RecordSymbol& cls) { printRecord(cls); }, c);
}
this->pool.wait();
Expand Down Expand Up @@ -1067,9 +1073,11 @@ void hdoc::serde::HTMLWriter::printEnums() const {
CTML::Node ul("ul");
for (const auto& id : getSortedIDs(map2vec(this->index->enums), this->index->enums)) {
const auto& e = this->index->enums.entries.at(id);
ul.AddChild(CTML::Node("li")
auto li = CTML::Node("li")
.AddChild(CTML::Node("a.is-family-code", e.type + " " + e.name).SetAttr("href", e.url()))
.AppendText(getSymbolBlurb(e)));
.AppendText(getSymbolBlurb(e));
if (e.isDetail) li.ToggleClass("hdoc-detail");
ul.AddChild(li);
this->pool.async([&](const hdoc::types::EnumSymbol& en) { printEnum(en); }, e);
}
this->pool.wait();
Expand Down
1 change: 1 addition & 0 deletions src/types/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct Config {
std::vector<std::string> includePaths; ///< Include paths passed on to Clang
std::vector<std::string> ignorePaths; ///< Paths from which matches should be ignored
std::vector<std::string> ignoreNamespaces; ///< Namespaces from which matches should be ignored
std::vector<std::string> detailNamespaces; ///< Namespaces which should be considered "detail" namespaces
bool ignorePrivateMembers = false; ///< Should private members of records be ignored?
std::filesystem::path homepage; ///< Path to "homepage" markdown file
std::vector<std::filesystem::path> mdPaths; ///< Paths to markdown pages
Expand Down
22 changes: 13 additions & 9 deletions src/types/Symbols.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,20 @@ struct SymbolID {

/// @brief Base class for all other types of symbols
struct Symbol {
std::string name; ///< Function name, record name, enum name etc.
std::string briefComment; ///< Text following @brief or \brief command
std::string docComment; ///< All other Doxygen text attached to this symbol's documentation
hdoc::types::SymbolID ID; ///< Unique identifier for this Symbol
std::string file; ///< File where this Symbol is declared, relative to source root
std::uint64_t line; ///< Line number in the file
hdoc::types::SymbolID parentNamespaceID; ///< ID of the parent namespace (or record)

/// @brief Comparison operator sorts alphabetically by symbol name
std::string name = ""; ///< Function name, record name, enum name etc.
std::string briefComment = ""; ///< Text following @brief or \brief command
std::string docComment = ""; ///< All other Doxygen text attached to this symbol's documentation
hdoc::types::SymbolID ID; ///< Unique identifier for this Symbol
std::string file = ""; ///< File where this Symbol is declared, relative to source root
std::uint64_t line = 0; ///< Line number in the file
hdoc::types::SymbolID parentNamespaceID; ///< ID of the parent namespace (or record)
bool isDetail = false; ///< Is this symbol in a "detail" namespace?

/// @brief Comparison operator sorts alphabetically by symbol name, sort detail symbols last
bool operator<(const Symbol& s) const {
if (this->isDetail != s.isDetail) {
return s.isDetail;
}
return this->name < s.name;
}

Expand Down

0 comments on commit 67e6a0c

Please sign in to comment.