30static StringRef exprToString(
const clang::Expr *E) {
31 clang::LangOptions Opts;
32 clang::PrintingPolicy Policy(Opts);
33 SmallString<16> Result;
34 llvm::raw_svector_ostream OS(Result);
35 E->printPretty(OS,
nullptr, Policy);
41 return llvm::SHA1::hash(arrayRefFromStringRef(USR));
44void Serializer::getTemplateParameters(
45 const TemplateParameterList *TemplateParams, llvm::raw_ostream &Stream) {
46 Stream <<
"template <";
48 for (
unsigned i = 0; i < TemplateParams->size(); ++i) {
52 const NamedDecl *Param = TemplateParams->getParam(i);
53 if (
const auto *TTP = llvm::dyn_cast<TemplateTypeParmDecl>(Param)) {
54 if (TTP->wasDeclaredWithTypename())
58 if (TTP->isParameterPack())
60 Stream <<
" " << TTP->getNameAsString();
65 if (TTP->hasTypeConstraint()) {
67 TTP->getTypeConstraint()->print(
68 Stream, TTP->getASTContext().getPrintingPolicy());
70 }
else if (
const auto *NTTP =
71 llvm::dyn_cast<NonTypeTemplateParmDecl>(Param)) {
72 NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy());
73 if (NTTP->isParameterPack())
75 Stream <<
" " << NTTP->getNameAsString();
76 }
else if (
const auto *TTPD =
77 llvm::dyn_cast<TemplateTemplateParmDecl>(Param)) {
78 Stream <<
"template <";
79 getTemplateParameters(TTPD->getTemplateParameters(), Stream);
80 Stream <<
"> class " << TTPD->getNameAsString();
89StringRef Serializer::getFunctionPrototype(
const FunctionDecl *
FuncDecl) {
90 llvm::SmallString<256> Result;
91 llvm::raw_svector_ostream Stream(Result);
92 const ASTContext &Ctx =
FuncDecl->getASTContext();
95 if (
const auto *TmplDecl =
FuncDecl->getDescribedTemplate())
96 getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
99 if (Method &&
Method->isVirtual())
100 Stream <<
"virtual ";
103 FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy());
106 Stream <<
" " <<
FuncDecl->getNameAsString() <<
"(";
109 for (
unsigned I = 0; I <
FuncDecl->getNumParams(); ++I) {
112 const ParmVarDecl *ParamDecl =
FuncDecl->getParamDecl(I);
113 QualType ParamType = ParamDecl->getType();
114 ParamType.print(Stream, Ctx.getPrintingPolicy());
117 if (!ParamDecl->getName().empty())
118 Stream <<
" " << ParamDecl->getNameAsString();
121 if (ParamDecl->hasDefaultArg() &&
122 !ParamDecl->hasUninstantiatedDefaultArg()) {
123 if (
const Expr *DefaultArg = ParamDecl->getDefaultArg()) {
125 DefaultArg->printPretty(Stream,
nullptr, Ctx.getPrintingPolicy());
142 Stream <<
" = delete";
143 if (
Method->size_overridden_methods())
144 Stream <<
" override";
145 if (
Method->hasAttr<clang::FinalAttr>())
149 if (
Method->isPureVirtual())
153 if (
auto ExceptionSpecType =
FuncDecl->getExceptionSpecType())
154 Stream <<
" " << ExceptionSpecType;
159StringRef Serializer::getTypeAlias(
const TypeAliasDecl *Alias) {
160 llvm::SmallString<16> Result;
161 llvm::raw_svector_ostream Stream(Result);
162 const ASTContext &Ctx =
Alias->getASTContext();
163 if (
const auto *TmplDecl =
Alias->getDescribedTemplate())
164 getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
165 Stream <<
"using " <<
Alias->getNameAsString() <<
" = ";
166 QualType Q =
Alias->getUnderlyingType();
167 Q.print(Stream, Ctx.getPrintingPolicy());
185StringRef Serializer::getInfoRelativePath(
186 const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
187 llvm::SmallString<128>
Path;
188 for (
auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
189 llvm::sys::path::append(Path, R->Name);
193StringRef Serializer::getInfoRelativePath(
const Decl *D) {
194 llvm::SmallVector<Reference, 4> Namespaces;
199 populateParentNamespaces(Namespaces, D, B);
200 return getInfoRelativePath(Namespaces);
222 StringRef getCommandName(
unsigned CommandID)
const;
223 bool isWhitespaceOnly(StringRef S)
const;
232 unsigned NumChildren = C->child_count();
233 if (NumChildren > 0) {
237 for (comments::Comment *Child :
238 llvm::make_range(C->child_begin(), C->child_end())) {
245 llvm::ArrayRef<CommentInfo>(ChildrenArray, NumChildren);
250 if (!isWhitespaceOnly(C->getText()))
251 CurrentCI.Text = C->getText().trim();
255 const InlineCommandComment *C) {
256 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
257 llvm::SmallVector<StringRef> Args;
258 for (
unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
261 StringRef *ArgsMem =
TransientArena.Allocate<StringRef>(Args.size());
262 std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
263 CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
268 const HTMLStartTagComment *C) {
270 CurrentCI.SelfClosing = C->isSelfClosing();
271 llvm::SmallVector<StringRef> AttrKeys;
272 llvm::SmallVector<StringRef> AttrValues;
273 for (
unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
274 const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
278 if (!AttrKeys.empty()) {
279 StringRef *KeysMem =
TransientArena.Allocate<StringRef>(AttrKeys.size());
280 std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem);
281 CurrentCI.AttrKeys = llvm::ArrayRef<StringRef>(KeysMem, AttrKeys.size());
283 if (!AttrValues.empty()) {
284 StringRef *ValuesMem =
286 std::uninitialized_copy(AttrValues.begin(), AttrValues.end(), ValuesMem);
287 CurrentCI.AttrValues =
288 llvm::ArrayRef<StringRef>(ValuesMem, AttrValues.size());
293 const HTMLEndTagComment *C) {
295 CurrentCI.SelfClosing =
true;
299 const BlockCommandComment *C) {
300 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
301 llvm::SmallVector<StringRef> Args;
302 for (
unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
305 StringRef *ArgsMem =
TransientArena.Allocate<StringRef>(Args.size());
306 std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
307 CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
312 const ParamCommandComment *C) {
314 ParamCommandComment::getDirectionAsString(C->getDirection()));
315 CurrentCI.Explicit = C->isDirectionExplicit();
316 if (C->hasParamName())
317 CurrentCI.ParamName =
internString(C->getParamNameAsWritten());
321 const TParamCommandComment *C) {
322 if (C->hasParamName())
323 CurrentCI.ParamName =
internString(C->getParamNameAsWritten());
327 const VerbatimBlockComment *C) {
328 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
333 const VerbatimBlockLineComment *C) {
334 if (!isWhitespaceOnly(C->getText()))
339 const VerbatimLineComment *C) {
340 if (!isWhitespaceOnly(C->getText()))
344bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S)
const {
345 return llvm::all_of(S, isspace);
348StringRef ClangDocCommentVisitor::getCommandName(
unsigned CommandID)
const {
349 const CommandInfo *
Info = CommandTraits::getBuiltinCommandInfo(CommandID);
353 return "<not a builtin command>";
358StringRef Serializer::getSourceCode(
const Decl *D,
const SourceRange &R) {
360 CharSourceRange::getTokenRange(R), D->getASTContext().getSourceManager(),
361 D->getASTContext().getLangOpts()));
365static std::string
serialize(T &I, DiagnosticsEngine &Diags) {
366 SmallString<2048> Buffer;
367 llvm::BitstreamWriter Stream(Buffer);
370 return Buffer.str().str();
392 llvm_unreachable(
"unhandled enumerator");
395void Serializer::parseFullComment(
const FullComment *C,
CommentInfo &CI) {
396 ClangDocCommentVisitor Visitor(CI);
397 Visitor.parseComment(C);
400SymbolID Serializer::getUSRForDecl(
const Decl *D) {
401 llvm::SmallString<128> USR;
402 if (index::generateUSRForDecl(D, USR))
407TagDecl *Serializer::getTagDeclForType(
const QualType &T) {
408 if (
const TagDecl *D = T->getAsTagDecl())
409 return D->getDefinition();
413RecordDecl *Serializer::getRecordDeclForType(
const QualType &T) {
414 if (
const RecordDecl *D =
T->getAsRecordDecl())
415 return D->getDefinition();
419TypeInfo Serializer::getTypeInfoForType(
const QualType &T,
420 const PrintingPolicy &Policy) {
421 const TagDecl *TD = getTagDeclForType(T);
423 TypeInfo TI = TypeInfo(Reference(
SymbolID(),
T.getAsString(Policy)));
424 TI.IsBuiltIn =
T->isBuiltinType();
425 TI.IsTemplate =
T->isTemplateTypeParmType();
429 if (isa<EnumDecl>(TD)) {
431 }
else if (isa<RecordDecl>(TD)) {
436 Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
437 T.getAsString(Policy), getInfoRelativePath(TD));
438 TypeInfo TI = TypeInfo(R);
439 TI.IsBuiltIn =
T->isBuiltinType();
440 TI.IsTemplate =
T->isTemplateTypeParmType();
444bool Serializer::isPublic(
const clang::AccessSpecifier AS,
445 const clang::Linkage Link) {
446 if (AS == clang::AccessSpecifier::AS_private)
448 if ((Link == clang::Linkage::Module) || (Link == clang::Linkage::External))
453bool Serializer::shouldSerializeInfo(
bool PublicOnly,
454 bool IsInAnonymousNamespace,
455 const NamedDecl *D) {
456 bool IsAnonymousNamespace =
false;
457 if (
const auto *N = dyn_cast<NamespaceDecl>(D))
458 IsAnonymousNamespace = N->isAnonymousNamespace();
460 (!IsInAnonymousNamespace && !IsAnonymousNamespace &&
461 isPublic(
D->getAccessUnsafe(),
D->getLinkageInternal()));
470void Serializer::InsertChild(ScopeChildren &Scope,
const NamespaceInfo &Info) {
473 getInfoRelativePath(
Info.Namespace));
474 Scope.Namespaces.push_back(*R);
477void Serializer::InsertChild(ScopeChildren &Scope,
const RecordInfo &Info) {
479 Info.Name, getInfoRelativePath(
Info.Namespace),
483void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo Info) {
484 Scope.Enums.push_back(std::move(Info));
487void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo Info) {
488 Scope.Functions.push_back(std::move(Info));
491void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo Info) {
492 Scope.Typedefs.push_back(std::move(Info));
495void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo Info) {
496 Scope.Concepts.push_back(std::move(Info));
499void Serializer::InsertChild(ScopeChildren &Scope, VarInfo Info) {
500 Scope.Variables.push_back(std::move(Info));
517template <
typename ChildType>
518OwnedPtr<Info> Serializer::makeAndInsertIntoParent(ChildType Child) {
519 if (Child.Namespace.empty()) {
522 InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
526 switch (Child.Namespace[0].RefType) {
529 ParentNS->USR = Child.Namespace[0].USR;
530 InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
535 ParentRec->USR = Child.Namespace[0].USR;
536 InsertChild(ParentRec->Children, std::forward<ChildType>(Child));
548 llvm_unreachable(
"Invalid reference type for parent namespace");
566AccessSpecifier Serializer::getFinalAccessSpecifier(AccessSpecifier FirstAS,
567 AccessSpecifier SecondAS) {
568 if (FirstAS == AccessSpecifier::AS_none ||
569 SecondAS == AccessSpecifier::AS_none)
570 return AccessSpecifier::AS_none;
571 if (FirstAS == AccessSpecifier::AS_private ||
572 SecondAS == AccessSpecifier::AS_private)
573 return AccessSpecifier::AS_private;
574 if (FirstAS == AccessSpecifier::AS_protected ||
575 SecondAS == AccessSpecifier::AS_protected)
576 return AccessSpecifier::AS_protected;
577 return AccessSpecifier::AS_public;
582void Serializer::parseFields(RecordInfo &I,
const RecordDecl *D,
584 for (
const FieldDecl *F :
D->fields()) {
585 if (!shouldSerializeInfo(
PublicOnly,
false, F))
587 populateMemberTypeInfo(I, Access, F);
589 const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
592 for (Decl *CxxDecl : CxxRD->decls()) {
593 auto *VD = dyn_cast<VarDecl>(CxxDecl);
598 if (VD->isStaticDataMember())
599 populateMemberTypeInfo(I, Access, VD,
true);
603void Serializer::parseEnumerators(EnumInfo &I,
const EnumDecl *D) {
604 for (
const EnumConstantDecl *E :
D->enumerators()) {
605 std::string ValueExpr;
606 if (
const Expr *InitExpr = E->getInitExpr())
607 ValueExpr = getSourceCode(D, InitExpr->getSourceRange());
608 SmallString<16> ValueStr;
609 E->getInitVal().toString(ValueStr);
610 I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr);
611 ASTContext &Context = E->getASTContext();
612 if (RawComment *Comment =
613 E->getASTContext().getRawCommentForDeclNoCache(E)) {
614 Comment->setAttached();
615 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, E)) {
616 EnumValueInfo &Member = I.Members.back();
617 Member.Description.emplace_back();
618 parseFullComment(Fc, Member.Description.back());
624void Serializer::parseParameters(FunctionInfo &I,
const FunctionDecl *D) {
625 auto &LO =
D->getLangOpts();
626 for (
const ParmVarDecl *P :
D->parameters()) {
627 FieldTypeInfo &FieldInfo = I.Params.emplace_back(
628 getTypeInfoForType(
P->getOriginalType(), LO),
P->getNameAsString());
629 if (std::optional<StringRef> DefaultValue =
630 getSourceCode(D,
P->getDefaultArgRange()))
631 FieldInfo.DefaultValue = *DefaultValue;
637void Serializer::parseBases(RecordInfo &I,
const CXXRecordDecl *D) {
639 if (!
D->isThisDeclarationADefinition())
642 for (
const CXXBaseSpecifier &B :
D->bases()) {
645 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
646 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
647 I.Parents.emplace_back(getUSRForDecl(D),
B.getType().getAsString(),
649 }
else if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
650 I.Parents.emplace_back(getUSRForDecl(P),
P->getNameAsString(),
654 I.Parents.emplace_back(
SymbolID(),
B.getType().getAsString());
656 for (
const CXXBaseSpecifier &B :
D->vbases()) {
657 if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
658 I.VirtualParents.emplace_back(
660 P->getQualifiedNameAsString(),
internString(getInfoRelativePath(P)));
662 I.VirtualParents.emplace_back(
SymbolID(),
B.getType().getAsString());
667void Serializer::populateParentNamespaces(
668 llvm::SmallVector<Reference, 4> &Namespaces,
const T *D,
669 bool &IsInAnonymousNamespace) {
670 const DeclContext *DC =
D->getDeclContext();
672 if (
const auto *N = dyn_cast<NamespaceDecl>(DC)) {
674 if (N->isAnonymousNamespace()) {
676 IsInAnonymousNamespace =
true;
679 Namespaces.emplace_back(getUSRForDecl(N), Namespace,
681 N->getQualifiedNameAsString());
682 }
else if (
const auto *N = dyn_cast<RecordDecl>(DC))
683 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
685 N->getQualifiedNameAsString());
686 else if (
const auto *N = dyn_cast<FunctionDecl>(DC))
687 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
689 N->getQualifiedNameAsString());
690 else if (
const auto *N = dyn_cast<EnumDecl>(DC))
691 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
693 }
while ((DC = DC->getParent()));
698 if ((Namespaces.empty() && isa<RecordDecl>(D)) ||
700 Namespaces.emplace_back(
SymbolID(),
"GlobalNamespace",
704void Serializer::populateTemplateParameters(
705 std::optional<TemplateInfo> &TemplateInfo,
const clang::Decl *D) {
706 if (
const TemplateParameterList *ParamList =
707 D->getDescribedTemplateParams()) {
709 TemplateInfo.emplace();
711 for (
const NamedDecl *ND : *ParamList) {
712 TemplateInfo->Params.emplace_back(
713 getSourceCode(ND, ND->getSourceRange()));
719Serializer::convertTemplateArgToInfo(
const clang::Decl *D,
720 const TemplateArgument &Arg) {
724 llvm::raw_string_ostream Stream(Str);
725 Arg.print(PrintingPolicy(
D->getLangOpts()), Stream,
false);
726 return TemplateParamInfo(Str);
732bool Serializer::isSupportedContext(Decl::Kind DeclKind) {
734 case Decl::Kind::Record:
735 case Decl::Kind::CXXRecord:
736 case Decl::Kind::ClassTemplateSpecialization:
737 case Decl::Kind::ClassTemplatePartialSpecialization:
738 case Decl::Kind::Namespace:
745void Serializer::findParent(Info &I,
const Decl *D) {
746 assert(D &&
"Invalid Decl");
749 if (!isSupportedContext(
D->getKind()))
752 const DeclContext *ParentCtx = dyn_cast<DeclContext>(D)->getLexicalParent();
754 if (isSupportedContext(ParentCtx->getDeclKind())) {
756 I.ParentUSR = getUSRForDecl(dyn_cast<Decl>(ParentCtx));
759 ParentCtx = ParentCtx->getParent();
764void Serializer::populateInfo(Info &I,
const T *D,
const FullComment *C,
765 bool &IsInAnonymousNamespace) {
766 I.USR = getUSRForDecl(D);
769 if (
auto ConversionDecl = dyn_cast_or_null<CXXConversionDecl>(D);
770 ConversionDecl && ConversionDecl->getConversionType()
772 ->isTemplateTypeParmType())
774 ConversionDecl->getConversionType().getAsString());
777 populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
779 I.Description.emplace_back();
780 parseFullComment(C, I.Description.back());
785void Serializer::populateSymbolInfo(
SymbolInfo &I,
const T *D,
786 const FullComment *C, Location Loc,
787 bool &IsInAnonymousNamespace) {
788 populateInfo(I, D, C, IsInAnonymousNamespace);
789 if (
D->isThisDeclarationADefinition())
792 I.Loc.emplace_back(Loc);
794 auto *Mangler = ItaniumMangleContext::create(
795 D->getASTContext(),
D->getASTContext().getDiagnostics());
796 std::string MangledName;
797 llvm::raw_string_ostream MangledStream(MangledName);
798 if (
auto *CXXD = dyn_cast<CXXRecordDecl>(D))
799 Mangler->mangleCXXVTable(CXXD, MangledStream);
801 MangledStream <<
D->getNameAsString();
804 if (MangledName.size() > 250) {
805 auto SymbolID = llvm::toStringRef(llvm::toHex(I.USR)).str();
813void Serializer::handleCompoundConstraints(
815 if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
816 handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
818 }
else if (Constraint->getStmtClass() == Stmt::BinaryOperatorClass) {
819 auto *BinaryOpExpr = dyn_cast<BinaryOperator>(Constraint);
820 handleCompoundConstraints(BinaryOpExpr->getLHS(), ConstraintInfos);
821 handleCompoundConstraints(BinaryOpExpr->getRHS(), ConstraintInfos);
822 }
else if (Constraint->getStmtClass() ==
823 Stmt::ConceptSpecializationExprClass) {
824 auto *
Concept = dyn_cast<ConceptSpecializationExpr>(Constraint);
825 ConstraintInfo CI(getUSRForDecl(
Concept->getNamedConcept()),
826 Concept->getNamedConcept()->getNameAsString());
827 CI.ConstraintExpr =
internString(exprToString(Concept));
828 ConstraintInfos.push_back(CI);
832void Serializer::populateConstraints(TemplateInfo &I,
const TemplateDecl *D) {
833 if (!D || !
D->hasAssociatedConstraints())
836 SmallVector<AssociatedConstraint> AssociatedConstraints;
837 D->getAssociatedConstraints(AssociatedConstraints);
838 for (
const auto &Constraint : AssociatedConstraints) {
843 if (
const auto *ConstraintExpr =
844 dyn_cast_or_null<ConceptSpecializationExpr>(
845 Constraint.ConstraintExpr)) {
846 ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
847 ConstraintExpr->getNamedConcept()->getNameAsString());
848 CI.ConstraintExpr =
internString(exprToString(ConstraintExpr));
849 I.Constraints.push_back(std::move(CI));
851 handleCompoundConstraints(Constraint.ConstraintExpr, I.Constraints);
856void Serializer::populateFunctionInfo(FunctionInfo &I,
const FunctionDecl *D,
857 const FullComment *FC, Location Loc,
858 bool &IsInAnonymousNamespace) {
859 populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
860 auto &LO =
D->getLangOpts();
861 I.ReturnType = getTypeInfoForType(
D->getReturnType(), LO);
862 I.Prototype = getFunctionPrototype(D);
863 parseParameters(I, D);
864 I.IsStatic =
D->isStatic();
866 populateTemplateParameters(I.Template, D);
868 populateConstraints(I.Template.value(),
D->getDescribedFunctionTemplate());
871 if (
const FunctionTemplateSpecializationInfo *FTSI =
872 D->getTemplateSpecializationInfo()) {
874 I.Template.emplace();
875 I.Template->Specialization.emplace();
876 auto &Specialization = *I.Template->Specialization;
878 Specialization.SpecializationOf = getUSRForDecl(FTSI->getTemplate());
881 if (FTSI->TemplateArguments) {
882 for (
const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
883 Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
892void Serializer::populateMemberTypeInfo(T &I,
const Decl *D) {
893 assert(D &&
"Expect non-null FieldDecl in populateMemberTypeInfo");
895 ASTContext &Context =
D->getASTContext();
898 RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
902 Comment->setAttached();
903 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, D)) {
904 I.Description.emplace_back();
905 parseFullComment(Fc, I.Description.back());
909void Serializer::populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
910 const DeclaratorDecl *D,
914 MemberTypeInfo &NewMember = I.Members.emplace_back(
915 getTypeInfoForType(
D->getTypeSourceInfo()->getType(),
D->getLangOpts()),
916 D->getNameAsString(),
917 getFinalAccessSpecifier(Access,
D->getAccessUnsafe()), IsStatic);
918 populateMemberTypeInfo(NewMember, D);
921void Serializer::parseBases(RecordInfo &I,
const CXXRecordDecl *D,
923 bool IsParent, AccessSpecifier ParentAccess) {
925 if (!
D->isThisDeclarationADefinition())
927 for (
const CXXBaseSpecifier &B :
D->bases()) {
928 if (
const auto *Base =
B.getType()->getAsCXXRecordDecl()) {
929 if (Base->isCompleteDefinition()) {
933 {},
"",
internString(getInfoRelativePath(Base)),
B.isVirtual(),
934 getFinalAccessSpecifier(ParentAccess,
B.getAccessSpecifier()),
936 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
937 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
938 BI.USR = getUSRForDecl(D);
941 BI.USR = getUSRForDecl(Base);
945 for (
const auto &Decl : Base->decls())
946 if (
const auto *
MD = dyn_cast<CXXMethodDecl>(Decl)) {
948 if (
MD->getAccessUnsafe() == AccessSpecifier::AS_private ||
949 !
MD->isUserProvided())
953 FI.IsStatic =
MD->isStatic();
957 bool IsInAnonymousNamespace;
958 populateFunctionInfo(FI,
MD, {}, {},
959 IsInAnonymousNamespace);
961 getFinalAccessSpecifier(BI.Access,
MD->getAccessUnsafe());
962 BI.Children.Functions.emplace_back(std::move(FI));
964 I.Bases.emplace_back(std::move(BI));
968 parseBases(I, Base, IsFileInRootDir,
PublicOnly,
false,
969 I.Bases.back().Access);
979 bool IsInAnonymousNamespace =
false;
980 populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
981 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
984 NSI->Name = D->isAnonymousNamespace() ?
"@nonymous_namespace" : NSI->Name;
985 NSI->Path = getInfoRelativePath(NSI->Namespace);
986 if (NSI->Namespace.empty() && NSI->USR ==
SymbolID())
991 return {std::move(NSI), makeAndInsertIntoParent<const NamespaceInfo &>(*NSI)};
994void Serializer::parseFriends(
RecordInfo &RI,
const CXXRecordDecl *D) {
995 if (!D->hasDefinition() || !D->hasFriends())
998 for (
const FriendDecl *FD : D->friends()) {
999 if (FD->isUnsupportedFriend())
1003 const auto *ActualDecl = FD->getFriendDecl();
1005 const auto *FriendTypeInfo = FD->getFriendType();
1006 if (!FriendTypeInfo)
1008 ActualDecl = FriendTypeInfo->getType()->getAsCXXRecordDecl();
1015 if (
const auto *ActualTD = dyn_cast_or_null<TemplateDecl>(ActualDecl)) {
1016 if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
1018 F.Template.emplace();
1019 for (
const auto *Param : ActualTD->getTemplateParameters()->asArray())
1020 F.Template->Params.emplace_back(
1021 getSourceCode(Param, Param->getSourceRange()));
1022 ActualDecl = ActualTD->getTemplatedDecl();
1025 if (
auto *
FuncDecl = dyn_cast_or_null<FunctionDecl>(ActualDecl)) {
1026 FunctionInfo TempInfo;
1027 parseParameters(TempInfo,
FuncDecl);
1029 F.ReturnType = getTypeInfoForType(
FuncDecl->getReturnType(),
1034 Reference(getUSRForDecl(ActualDecl), ActualDecl->getNameAsString(),
1036 getInfoRelativePath(ActualDecl));
1038 populateMemberTypeInfo(F, ActualDecl);
1039 RI.
Friends.push_back(std::move(F));
1048 bool IsInAnonymousNamespace =
false;
1050 populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
1051 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1054 RI->
TagType = D->getTagKind();
1057 if (
const auto *C = dyn_cast<CXXRecordDecl>(D)) {
1058 if (
const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
1065 parseFriends(*RI, C);
1069 populateTemplateParameters(RI->
Template, D);
1071 populateConstraints(RI->
Template.value(), D->getDescribedTemplate());
1074 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1077 RI->
Template->Specialization.emplace();
1078 auto &Specialization = *RI->
Template->Specialization;
1081 auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
1082 if (
auto *SpecTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
1083 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1084 else if (
auto *SpecTD =
1085 dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
1086 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1093 if (
const ClassTemplatePartialSpecializationDecl *CTPSD =
1094 dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
1095 if (
const ASTTemplateArgumentListInfo *AsWritten =
1096 CTPSD->getTemplateArgsAsWritten()) {
1097 for (
unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
1098 Specialization.Params.emplace_back(
1099 getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
1103 for (
const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
1104 Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
1111 auto Parent = makeAndInsertIntoParent<const RecordInfo &>(*RI);
1112 return {std::move(RI), std::move(Parent)};
1119 bool IsInAnonymousNamespace =
false;
1120 populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
1121 Func.
Access = clang::AccessSpecifier::AS_none;
1122 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1126 return {
nullptr, makeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
1133 bool IsInAnonymousNamespace =
false;
1134 populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
1135 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1141 const NamedDecl *Parent =
nullptr;
1142 if (
const auto *SD =
1143 dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
1144 Parent = SD->getSpecializedTemplate();
1146 Parent = D->getParent();
1148 SymbolID ParentUSR = getUSRForDecl(Parent);
1151 Parent->getQualifiedNameAsString()};
1152 Func.
Access = D->getAccess();
1155 return {
nullptr, makeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
1158void Serializer::extractCommentFromDecl(
const Decl *D,
TypedefInfo &
Info) {
1159 assert(D &&
"Invalid Decl when extracting comment");
1160 ASTContext &
Context = D->getASTContext();
1161 RawComment *Comment =
Context.getRawCommentForDeclNoCache(D);
1165 Comment->setAttached();
1166 if (comments::FullComment *Fc = Comment->parse(
Context,
nullptr, D)) {
1176 bool IsInAnonymousNamespace =
false;
1177 populateInfo(
Info, D, FC, IsInAnonymousNamespace);
1179 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1183 auto &LO = D->getLangOpts();
1184 Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1185 populateTemplateParameters(
Info.Template, D);
1187 populateConstraints(
Info.Template.value(), D->getDescribedTemplate());
1189 if (
Info.Underlying.Type.
Name.empty()) {
1195 Info.IsUsing =
false;
1196 extractCommentFromDecl(D,
Info);
1199 return {
nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(
Info))};
1208 bool IsInAnonymousNamespace =
false;
1209 populateInfo(
Info, D, FC, IsInAnonymousNamespace);
1210 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1214 const LangOptions &LO = D->getLangOpts();
1215 Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1216 Info.TypeDeclaration = getTypeAlias(D);
1217 Info.IsUsing =
true;
1218 populateTemplateParameters(
Info.Template, D);
1220 populateConstraints(
Info.Template.value(), D->getDescribedAliasTemplate());
1222 extractCommentFromDecl(D,
Info);
1225 return {
nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(
Info))};
1232 bool IsInAnonymousNamespace =
false;
1233 populateSymbolInfo(Enum, D, FC, Loc, IsInAnonymousNamespace);
1235 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1238 Enum.Scoped = D->isScoped();
1239 if (
const TypeSourceInfo *TSI = D->getIntegerTypeSourceInfo()) {
1240 auto Name = TSI->getType().getAsString();
1241 Enum.BaseType =
TypeInfo(Name, Name);
1243 parseEnumerators(Enum, D);
1246 return {
nullptr, makeAndInsertIntoParent<EnumInfo &&>(std::move(Enum))};
1254 bool IsInAnonymousNamespace =
false;
1255 populateInfo(Concept, D, FC, IsInAnonymousNamespace);
1256 Concept.IsType = D->isTypeConcept();
1257 Concept.DefLoc = Loc;
1258 Concept.ConstraintExpression = exprToString(D->getConstraintExpr());
1260 if (
auto *ConceptParams = D->getTemplateParameters()) {
1261 for (
const auto *Param : ConceptParams->asArray()) {
1262 Concept.Template.Params.emplace_back(
1263 getSourceCode(Param, Param->getSourceRange()));
1267 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1270 return {
nullptr, makeAndInsertIntoParent<ConceptInfo &&>(std::move(Concept))};
1277 bool IsInAnonymousNamespace =
false;
1278 populateSymbolInfo(Var, D, FC, Loc, IsInAnonymousNamespace);
1279 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1282 if (D->getStorageClass() == StorageClass::SC_Static)
1285 getTypeInfoForType(D->getType(), D->getASTContext().getPrintingPolicy());
1287 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1290 return {
nullptr, makeAndInsertIntoParent<VarInfo &&>(std::move(Var))};