Skip to content

symbol filter: small fixes #883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 71 additions & 39 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "lib/Lib/Diagnostics.hpp"
#include <mrdocs/Metadata.hpp>
#include <mrdocs/Support/ScopeExit.hpp>
#include <mrdocs/Support/Algorithm.hpp>
#include <clang/AST/AST.h>
#include <clang/AST/Attr.h>
#include <clang/AST/ODRHash.h>
Expand Down Expand Up @@ -180,7 +181,7 @@ traverse(UsingDirectiveDecl const* D)
MRDOCS_ASSERT(res);
MRDOCS_ASSERT(res->isIdentifier());
if (NameInfo NI = *res;
std::ranges::find(PNI->UsingDirectives, NI) == PNI->UsingDirectives.end())
!contains(PNI->UsingDirectives, NI))
{
PNI->UsingDirectives.push_back(std::move(NI));
}
Expand Down Expand Up @@ -1582,7 +1583,7 @@ populateAttributes(InfoTy& I, Decl const* D)
{
continue;
}
if (std::ranges::find(I.Attributes, II->getName()) == I.Attributes.end())
if (!contains(I.Attributes, II->getName()))
{
I.Attributes.emplace_back(II->getName());
}
Expand Down Expand Up @@ -1779,7 +1780,7 @@ void
ASTVisitor::
addMember(std::vector<SymbolID>& container, Info const& Member) const
{
if (std::ranges::find(container, Member.id) == container.end())
if (!contains(container, Member.id))
{
container.push_back(Member.id);
}
Expand Down Expand Up @@ -2821,45 +2822,48 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
// Update cache
auto updateCache = [this, D](ExtractionInfo const result) {
extraction_.emplace(D, result);
return result;
};

// If not a NamedDecl, then symbol filters don't apply
auto const* ND = dyn_cast<NamedDecl>(D);
if (!ND)
{
ExtractionInfo const res{ExtractionMode::Regular, ExtractionMatchType::Strict};
updateCache(res);
return res;
constexpr ExtractionInfo res{ExtractionMode::Regular, ExtractionMatchType::Strict};
return updateCache(res);
}

// Get the symbol name
SmallString<256> const name = qualifiedName(ND);
auto const symbolName = name.str();

// We should check the exclusion filters first. If a symbol is
// Function to check if parent is of a certain extraction mode
auto ParentIs = [&](Decl const* D, ExtractionMode expected) {
if (Decl const* P = getParent(D);
P &&
!isa<TranslationUnitDecl>(P))
{
auto const [parentMode, kind] = checkSymbolFilters(P);
return parentMode == expected;
}
return false;
};

// 0) We should check the exclusion filters first. If a symbol is
// explicitly excluded, there's nothing else to check.
if (!config_->excludeSymbols.empty())
{
if (checkSymbolFiltersImpl<Strict>(config_->excludeSymbols, symbolName))
{
ExtractionInfo const res{ExtractionMode::Dependency, ExtractionMatchType::Strict};
updateCache(res);
return res;
return updateCache(res);
}
// If the parent scope is excluded, the symbol should also be excluded
// since it would not be possible to refer to this member.
if (AllowParent)

// 0a) Check if the parent is excluded
if (AllowParent &&
ParentIs(D, ExtractionMode::Dependency))
{
if (Decl const* P = getParent(D))
{
if (auto const [mode, kind] = checkSymbolFilters(P);
mode == ExtractionMode::Dependency)
{
ExtractionInfo const res = {mode, ExtractionMatchType::StrictParent};
updateCache(res);
return res;
}
}
return updateCache({ExtractionMode::Dependency, ExtractionMatchType::StrictParent});
}
}

Expand All @@ -2875,14 +2879,47 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
};

// 1) The symbol strictly matches one of the patterns
for (auto const& [patterns, mode] : patternsAndModes)
for (auto const& [patterns, patternsMode] : patternsAndModes)
{
if (!patterns->empty() &&
checkSymbolFiltersImpl<Strict>(*patterns, symbolName))
if (!patterns->empty())
{
ExtractionInfo res = {mode, ExtractionMatchType::Strict};
updateCache(res);
return res;
if (checkSymbolFiltersImpl<Strict>(*patterns, symbolName))
{
ExtractionInfo const res = {patternsMode, ExtractionMatchType::Strict};
return updateCache(res);
}

// 1a) Check if the parent in the same exclusion category
// (see-below or implementation defined).
if (AllowParent &&
patternsMode != ExtractionMode::Regular &&
ParentIs(D, patternsMode))
{
if (patternsMode == ExtractionMode::ImplementationDefined)
{
// A child of implementation defined is also
// implementation defined.
return updateCache(
{ ExtractionMode::ImplementationDefined,
ExtractionMatchType::StrictParent });
}
if (patternsMode == ExtractionMode::SeeBelow)
{
// A child of see-below is also see-below (if namespace)
// or dependency (if record)
if (Decl const* P = getParent(D);
P &&
isa<NamespaceDecl>(P))
{
return updateCache(
{ ExtractionMode::SeeBelow,
ExtractionMatchType::StrictParent });
}
return updateCache(
{ ExtractionMode::Dependency,
ExtractionMatchType::StrictParent });
}
}
}
}

Expand Down Expand Up @@ -2922,8 +2959,7 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
checkSymbolFiltersImpl<Literal>(*patterns, namespaceName.str()))
{
ExtractionInfo const res = {mode, ExtractionMatchType::LiteralParent};
updateCache(res);
return res;
return updateCache(res);
}
}
}
Expand Down Expand Up @@ -2996,9 +3032,8 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
}
if (childrenMode != ExtractionMode::Dependency)
{
ExtractionInfo const res = {mode, ExtractionMatchType::Prefix};
updateCache(res);
return res;
ExtractionInfo const res = {childrenMode, ExtractionMatchType::Prefix};
return updateCache(res);
}
}
}
Expand Down Expand Up @@ -3028,8 +3063,7 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
// being extracted so that symbols that match
// the full pattern are included and not all symbols.
ExtractionInfo const res = {mode, ExtractionMatchType::StrictParent};
updateCache(res);
return res;
return updateCache(res);
}
}
}
Expand All @@ -3042,14 +3076,12 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
if (config_->includeSymbols.empty())
{
constexpr ExtractionInfo res = {ExtractionMode::Regular, ExtractionMatchType::Strict};
updateCache(res);
return res;
return updateCache(res);
}
// 4b) Otherwise, we don't extract the symbol
// because it doesn't match any of `include-symbol` filters
constexpr ExtractionInfo res = {ExtractionMode::Dependency, ExtractionMatchType::Strict};
updateCache(res);
return res;
return updateCache(res);
}

template <ASTVisitor::SymbolCheckType t>
Expand Down
22 changes: 14 additions & 8 deletions src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "BaseMembersFinalizer.hpp"
#include <mrdocs/Support/Report.hpp>
#include <mrdocs/Support/Algorithm.hpp>

namespace clang::mrdocs {

Expand Down Expand Up @@ -101,12 +102,19 @@ inheritBaseMembers(
for (SymbolID const& otherID: base)
{
// Find the info from the base class
auto idIt = std::ranges::find(derived, otherID);
MRDOCS_CHECK_OR_CONTINUE(idIt == derived.end());
MRDOCS_CHECK_OR_CONTINUE(!contains(derived, otherID));
Info* otherInfoPtr = corpus_.find(otherID);
MRDOCS_CHECK_OR_CONTINUE(otherInfoPtr);
Info& otherInfo = *otherInfoPtr;

// Check if we're not attempt to copy a special member function
if (auto const* funcPtr = static_cast<FunctionInfo const*>(otherInfoPtr))
{
MRDOCS_CHECK_OR_CONTINUE(!is_one_of(
funcPtr->Class,
{ FunctionClass::Constructor, FunctionClass::Destructor }));
}

// Check if derived class has a member that shadows the base member
auto shadowIt = std::ranges::find_if(
derived,
Expand All @@ -126,12 +134,9 @@ inheritBaseMembers(
std::tie(func.Name, func.Params, func.Template) ==
std::tie(otherFunc.Name, otherFunc.Params, func.Template);
}
else
{
// For other kinds of members, it's a shadow if the names
// are the same
return info.Name == otherInfo.Name;
}
// For other kinds of members, it's a shadow if the names
// are the same
return info.Name == otherInfo.Name;
});
MRDOCS_CHECK_OR_CONTINUE(shadowIt == derived.end());

Expand Down Expand Up @@ -220,6 +225,7 @@ void
BaseMembersFinalizer::
operator()(RecordInfo& I)
{
MRDOCS_CHECK_OR(I.Extraction == ExtractionMode::Regular);
report::trace(
"Extracting base members for record '{}'",
corpus_.Corpus::qualifiedName(I));
Expand Down
Loading
Loading