2222#include " lib/Lib/Diagnostics.hpp"
2323#include < mrdocs/Metadata.hpp>
2424#include < mrdocs/Support/ScopeExit.hpp>
25+ #include < mrdocs/Support/Algorithm.hpp>
2526#include < clang/AST/AST.h>
2627#include < clang/AST/Attr.h>
2728#include < clang/AST/ODRHash.h>
@@ -180,7 +181,7 @@ traverse(UsingDirectiveDecl const* D)
180181 MRDOCS_ASSERT (res);
181182 MRDOCS_ASSERT (res->isIdentifier ());
182183 if (NameInfo NI = *res;
183- std::ranges::find (PNI->UsingDirectives , NI) == PNI-> UsingDirectives . end ( ))
184+ ! contains (PNI->UsingDirectives , NI))
184185 {
185186 PNI->UsingDirectives .push_back (std::move (NI));
186187 }
@@ -1582,7 +1583,7 @@ populateAttributes(InfoTy& I, Decl const* D)
15821583 {
15831584 continue ;
15841585 }
1585- if (std::ranges::find (I.Attributes , II->getName ()) == I. Attributes . end ( ))
1586+ if (! contains (I.Attributes , II->getName ()))
15861587 {
15871588 I.Attributes .emplace_back (II->getName ());
15881589 }
@@ -1779,7 +1780,7 @@ void
17791780ASTVisitor::
17801781addMember (std::vector<SymbolID>& container, Info const & Member) const
17811782{
1782- if (std::ranges::find (container, Member.id ) == container. end ( ))
1783+ if (! contains (container, Member.id ))
17831784 {
17841785 container.push_back (Member.id );
17851786 }
@@ -2821,45 +2822,48 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
28212822 // Update cache
28222823 auto updateCache = [this , D](ExtractionInfo const result) {
28232824 extraction_.emplace (D, result);
2825+ return result;
28242826 };
28252827
28262828 // If not a NamedDecl, then symbol filters don't apply
28272829 auto const * ND = dyn_cast<NamedDecl>(D);
28282830 if (!ND)
28292831 {
2830- ExtractionInfo const res{ExtractionMode::Regular, ExtractionMatchType::Strict};
2831- updateCache (res);
2832- return res;
2832+ constexpr ExtractionInfo res{ExtractionMode::Regular, ExtractionMatchType::Strict};
2833+ return updateCache (res);
28332834 }
28342835
28352836 // Get the symbol name
28362837 SmallString<256 > const name = qualifiedName (ND);
28372838 auto const symbolName = name.str ();
28382839
2839- // We should check the exclusion filters first. If a symbol is
2840+ // Function to check if parent is of a certain extraction mode
2841+ auto ParentIs = [&](Decl const * D, ExtractionMode expected) {
2842+ if (Decl const * P = getParent (D);
2843+ P &&
2844+ !isa<TranslationUnitDecl>(P))
2845+ {
2846+ auto const [parentMode, kind] = checkSymbolFilters (P);
2847+ return parentMode == expected;
2848+ }
2849+ return false ;
2850+ };
2851+
2852+ // 0) We should check the exclusion filters first. If a symbol is
28402853 // explicitly excluded, there's nothing else to check.
28412854 if (!config_->excludeSymbols .empty ())
28422855 {
28432856 if (checkSymbolFiltersImpl<Strict>(config_->excludeSymbols , symbolName))
28442857 {
28452858 ExtractionInfo const res{ExtractionMode::Dependency, ExtractionMatchType::Strict};
2846- updateCache (res);
2847- return res;
2859+ return updateCache (res);
28482860 }
2849- // If the parent scope is excluded, the symbol should also be excluded
2850- // since it would not be possible to refer to this member.
2851- if (AllowParent)
2861+
2862+ // 0a) Check if the parent is excluded
2863+ if (AllowParent &&
2864+ ParentIs (D, ExtractionMode::Dependency))
28522865 {
2853- if (Decl const * P = getParent (D))
2854- {
2855- if (auto const [mode, kind] = checkSymbolFilters (P);
2856- mode == ExtractionMode::Dependency)
2857- {
2858- ExtractionInfo const res = {mode, ExtractionMatchType::StrictParent};
2859- updateCache (res);
2860- return res;
2861- }
2862- }
2866+ return updateCache ({ExtractionMode::Dependency, ExtractionMatchType::StrictParent});
28632867 }
28642868 }
28652869
@@ -2875,14 +2879,47 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
28752879 };
28762880
28772881 // 1) The symbol strictly matches one of the patterns
2878- for (auto const & [patterns, mode ] : patternsAndModes)
2882+ for (auto const & [patterns, patternsMode ] : patternsAndModes)
28792883 {
2880- if (!patterns->empty () &&
2881- checkSymbolFiltersImpl<Strict>(*patterns, symbolName))
2884+ if (!patterns->empty ())
28822885 {
2883- ExtractionInfo res = {mode, ExtractionMatchType::Strict};
2884- updateCache (res);
2885- return res;
2886+ if (checkSymbolFiltersImpl<Strict>(*patterns, symbolName))
2887+ {
2888+ ExtractionInfo const res = {patternsMode, ExtractionMatchType::Strict};
2889+ return updateCache (res);
2890+ }
2891+
2892+ // 1a) Check if the parent in the same exclusion category
2893+ // (see-below or implementation defined).
2894+ if (AllowParent &&
2895+ patternsMode != ExtractionMode::Regular &&
2896+ ParentIs (D, patternsMode))
2897+ {
2898+ if (patternsMode == ExtractionMode::ImplementationDefined)
2899+ {
2900+ // A child of implementation defined is also
2901+ // implementation defined.
2902+ return updateCache (
2903+ { ExtractionMode::ImplementationDefined,
2904+ ExtractionMatchType::StrictParent });
2905+ }
2906+ if (patternsMode == ExtractionMode::SeeBelow)
2907+ {
2908+ // A child of see-below is also see-below (if namespace)
2909+ // or dependency (if record)
2910+ if (Decl const * P = getParent (D);
2911+ P &&
2912+ isa<NamespaceDecl>(P))
2913+ {
2914+ return updateCache (
2915+ { ExtractionMode::SeeBelow,
2916+ ExtractionMatchType::StrictParent });
2917+ }
2918+ return updateCache (
2919+ { ExtractionMode::Dependency,
2920+ ExtractionMatchType::StrictParent });
2921+ }
2922+ }
28862923 }
28872924 }
28882925
@@ -2922,8 +2959,7 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
29222959 checkSymbolFiltersImpl<Literal>(*patterns, namespaceName.str ()))
29232960 {
29242961 ExtractionInfo const res = {mode, ExtractionMatchType::LiteralParent};
2925- updateCache (res);
2926- return res;
2962+ return updateCache (res);
29272963 }
29282964 }
29292965 }
@@ -2996,9 +3032,8 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
29963032 }
29973033 if (childrenMode != ExtractionMode::Dependency)
29983034 {
2999- ExtractionInfo const res = {mode, ExtractionMatchType::Prefix};
3000- updateCache (res);
3001- return res;
3035+ ExtractionInfo const res = {childrenMode, ExtractionMatchType::Prefix};
3036+ return updateCache (res);
30023037 }
30033038 }
30043039 }
@@ -3028,8 +3063,7 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
30283063 // being extracted so that symbols that match
30293064 // the full pattern are included and not all symbols.
30303065 ExtractionInfo const res = {mode, ExtractionMatchType::StrictParent};
3031- updateCache (res);
3032- return res;
3066+ return updateCache (res);
30333067 }
30343068 }
30353069 }
@@ -3042,14 +3076,12 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
30423076 if (config_->includeSymbols .empty ())
30433077 {
30443078 constexpr ExtractionInfo res = {ExtractionMode::Regular, ExtractionMatchType::Strict};
3045- updateCache (res);
3046- return res;
3079+ return updateCache (res);
30473080 }
30483081 // 4b) Otherwise, we don't extract the symbol
30493082 // because it doesn't match any of `include-symbol` filters
30503083 constexpr ExtractionInfo res = {ExtractionMode::Dependency, ExtractionMatchType::Strict};
3051- updateCache (res);
3052- return res;
3084+ return updateCache (res);
30533085}
30543086
30553087template <ASTVisitor::SymbolCheckType t>
0 commit comments