30 clang::LangOptions Opts;
31 clang::PrintingPolicy Policy(Opts);
32 SmallString<16> Result;
33 llvm::raw_svector_ostream OS(Result);
34 E->printPretty(OS,
nullptr, Policy);
39 return llvm::SHA1::hash(arrayRefFromStringRef(USR));
42void Serializer::getTemplateParameters(
43 const TemplateParameterList *TemplateParams, llvm::raw_ostream &Stream) {
44 Stream <<
"template <";
46 for (
unsigned i = 0; i < TemplateParams->size(); ++i) {
50 const NamedDecl *Param = TemplateParams->getParam(i);
51 if (
const auto *TTP = llvm::dyn_cast<TemplateTypeParmDecl>(Param)) {
52 if (TTP->wasDeclaredWithTypename())
56 if (TTP->isParameterPack())
58 Stream <<
" " << TTP->getNameAsString();
63 if (TTP->hasTypeConstraint()) {
65 TTP->getTypeConstraint()->print(
66 Stream, TTP->getASTContext().getPrintingPolicy());
68 }
else if (
const auto *NTTP =
69 llvm::dyn_cast<NonTypeTemplateParmDecl>(Param)) {
70 NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy());
71 if (NTTP->isParameterPack())
73 Stream <<
" " << NTTP->getNameAsString();
74 }
else if (
const auto *TTPD =
75 llvm::dyn_cast<TemplateTemplateParmDecl>(Param)) {
76 Stream <<
"template <";
77 getTemplateParameters(TTPD->getTemplateParameters(), Stream);
78 Stream <<
"> class " << TTPD->getNameAsString();
87StringRef Serializer::getFunctionPrototype(
const FunctionDecl *
FuncDecl) {
88 llvm::SmallString<256> Result;
89 llvm::raw_svector_ostream Stream(Result);
90 const ASTContext &Ctx =
FuncDecl->getASTContext();
93 if (
const auto *TmplDecl =
FuncDecl->getDescribedTemplate())
94 getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
97 if (Method &&
Method->isVirtual())
101 FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy());
104 Stream <<
" " <<
FuncDecl->getNameAsString() <<
"(";
107 for (
unsigned I = 0; I <
FuncDecl->getNumParams(); ++I) {
110 const ParmVarDecl *ParamDecl =
FuncDecl->getParamDecl(I);
111 QualType ParamType = ParamDecl->getType();
112 ParamType.print(Stream, Ctx.getPrintingPolicy());
115 if (!ParamDecl->getName().empty())
116 Stream <<
" " << ParamDecl->getNameAsString();
119 if (ParamDecl->hasDefaultArg() &&
120 !ParamDecl->hasUninstantiatedDefaultArg()) {
121 if (
const Expr *DefaultArg = ParamDecl->getDefaultArg()) {
123 DefaultArg->printPretty(Stream,
nullptr, Ctx.getPrintingPolicy());
140 Stream <<
" = delete";
141 if (
Method->size_overridden_methods())
142 Stream <<
" override";
143 if (
Method->hasAttr<clang::FinalAttr>())
147 if (
Method->isPureVirtual())
151 if (
auto ExceptionSpecType =
FuncDecl->getExceptionSpecType())
152 Stream <<
" " << ExceptionSpecType;
157StringRef Serializer::getTypeAlias(
const TypeAliasDecl *Alias) {
158 llvm::SmallString<16> Result;
159 llvm::raw_svector_ostream Stream(Result);
160 const ASTContext &Ctx =
Alias->getASTContext();
161 if (
const auto *TmplDecl =
Alias->getDescribedTemplate())
162 getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
163 Stream <<
"using " <<
Alias->getNameAsString() <<
" = ";
164 QualType Q =
Alias->getUnderlyingType();
165 Q.print(Stream, Ctx.getPrintingPolicy());
184Serializer::getInfoRelativePath(llvm::ArrayRef<doc::Reference> Namespaces) {
185 llvm::SmallString<128>
Path;
186 for (
auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
187 llvm::sys::path::append(Path, R->Name);
191StringRef Serializer::getInfoRelativePath(
const Decl *D) {
192 llvm::SmallVector<Reference, 4> Namespaces;
197 populateParentNamespaces(Namespaces, D, B);
198 return getInfoRelativePath(Namespaces);
220 StringRef getCommandName(
unsigned CommandID)
const;
221 bool isWhitespaceOnly(StringRef S)
const;
230 unsigned NumChildren = C->child_count();
231 if (NumChildren > 0) {
235 for (comments::Comment *Child :
236 llvm::make_range(C->child_begin(), C->child_end())) {
242 assert(Idx == NumChildren &&
243 "Mismatch between child_count and actual children");
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)
266 const HTMLStartTagComment *C) {
268 CurrentCI.SelfClosing = C->isSelfClosing();
269 llvm::SmallVector<StringRef> AttrKeys;
270 llvm::SmallVector<StringRef> AttrValues;
271 for (
unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
272 const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
276 if (!AttrKeys.empty()) {
279 if (!AttrValues.empty()) {
285 const HTMLEndTagComment *C) {
287 CurrentCI.SelfClosing =
true;
291 const BlockCommandComment *C) {
292 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
293 llvm::SmallVector<StringRef> Args;
294 for (
unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
302 const ParamCommandComment *C) {
304 ParamCommandComment::getDirectionAsString(C->getDirection()));
305 CurrentCI.Explicit = C->isDirectionExplicit();
306 if (C->hasParamName())
307 CurrentCI.ParamName =
internString(C->getParamNameAsWritten());
311 const TParamCommandComment *C) {
312 if (C->hasParamName())
313 CurrentCI.ParamName =
internString(C->getParamNameAsWritten());
317 const VerbatimBlockComment *C) {
318 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
323 const VerbatimBlockLineComment *C) {
324 if (!isWhitespaceOnly(C->getText()))
329 const VerbatimLineComment *C) {
330 if (!isWhitespaceOnly(C->getText()))
334bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S)
const {
335 return llvm::all_of(S, isspace);
338StringRef ClangDocCommentVisitor::getCommandName(
unsigned CommandID)
const {
339 const CommandInfo *
Info = CommandTraits::getBuiltinCommandInfo(CommandID);
343 return "<not a builtin command>";
348StringRef Serializer::getSourceCode(
const Decl *D,
const SourceRange &R) {
350 CharSourceRange::getTokenRange(R), D->getASTContext().getSourceManager(),
351 D->getASTContext().getLangOpts()));
355static std::string
serialize(
const T &I, DiagnosticsEngine &Diags) {
356 SmallString<2048> Buffer;
357 llvm::BitstreamWriter Stream(Buffer);
360 return Buffer.str().str();
366 return serialize(cast<NamespaceInfo>(I), Diags);
368 return serialize(cast<RecordInfo>(I), Diags);
370 return serialize(cast<EnumInfo>(I), Diags);
372 return serialize(cast<FunctionInfo>(I), Diags);
374 return serialize(cast<ConceptInfo>(I), Diags);
376 return serialize(cast<VarInfo>(I), Diags);
382 llvm_unreachable(
"unhandled enumerator");
385void Serializer::parseFullComment(
const FullComment *C,
CommentInfo &CI) {
386 ClangDocCommentVisitor Visitor(CI);
387 Visitor.parseComment(C);
390SymbolID Serializer::getUSRForDecl(
const Decl *D) {
391 llvm::SmallString<128> USR;
392 if (index::generateUSRForDecl(D, USR))
397TagDecl *Serializer::getTagDeclForType(
const QualType &T) {
398 if (
const TagDecl *D = T->getAsTagDecl())
399 return D->getDefinition();
403RecordDecl *Serializer::getRecordDeclForType(
const QualType &T) {
404 if (
const RecordDecl *D =
T->getAsRecordDecl())
405 return D->getDefinition();
409TypeInfo Serializer::getTypeInfoForType(
const QualType &T,
410 const PrintingPolicy &Policy) {
411 const TagDecl *TD = getTagDeclForType(T);
413 TypeInfo TI = TypeInfo(Reference(
SymbolID(),
T.getAsString(Policy)));
414 TI.IsBuiltIn =
T->isBuiltinType();
415 TI.IsTemplate =
T->isTemplateTypeParmType();
419 if (isa<EnumDecl>(TD)) {
421 }
else if (isa<RecordDecl>(TD)) {
426 Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
427 T.getAsString(Policy), getInfoRelativePath(TD));
428 TypeInfo TI = TypeInfo(R);
429 TI.IsBuiltIn =
T->isBuiltinType();
430 TI.IsTemplate =
T->isTemplateTypeParmType();
434bool Serializer::isPublic(
const clang::AccessSpecifier AS,
435 const clang::Linkage Link) {
436 if (AS == clang::AccessSpecifier::AS_private)
438 if ((Link == clang::Linkage::Module) || (Link == clang::Linkage::External))
443bool Serializer::shouldSerializeInfo(
bool PublicOnly,
444 bool IsInAnonymousNamespace,
445 const NamedDecl *D) {
446 bool IsAnonymousNamespace =
false;
447 if (
const auto *N = dyn_cast<NamespaceDecl>(D))
448 IsAnonymousNamespace = N->isAnonymousNamespace();
450 (!IsInAnonymousNamespace && !IsAnonymousNamespace &&
451 isPublic(
D->getAccessUnsafe(),
D->getLinkageInternal()));
460void Serializer::InsertChild(ScopeChildren &Scope,
const NamespaceInfo &Info) {
463 getInfoRelativePath(
Info.Namespace)));
466void Serializer::InsertChild(ScopeChildren &Scope,
const RecordInfo &Info) {
469 getInfoRelativePath(
Info.Namespace),
Info.MangledName));
472void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo &Info) {
476void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo &Info) {
480void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo &Info) {
484void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo &Info) {
488void Serializer::InsertChild(ScopeChildren &Scope, VarInfo &Info) {
506template <
typename ChildType>
507Info *Serializer::makeAndInsertIntoParent(ChildType &Child) {
508 if (Child.Namespace.empty()) {
511 InsertChild(ParentNS->Children, Child);
515 switch (Child.Namespace[0].RefType) {
518 ParentNS->USR = Child.Namespace[0].USR;
519 InsertChild(ParentNS->Children, Child);
524 ParentRec->USR = Child.Namespace[0].USR;
525 InsertChild(ParentRec->Children, Child);
537 llvm_unreachable(
"Invalid reference type for parent namespace");
555AccessSpecifier Serializer::getFinalAccessSpecifier(AccessSpecifier FirstAS,
556 AccessSpecifier SecondAS) {
557 if (FirstAS == AccessSpecifier::AS_none ||
558 SecondAS == AccessSpecifier::AS_none)
559 return AccessSpecifier::AS_none;
560 if (FirstAS == AccessSpecifier::AS_private ||
561 SecondAS == AccessSpecifier::AS_private)
562 return AccessSpecifier::AS_private;
563 if (FirstAS == AccessSpecifier::AS_protected ||
564 SecondAS == AccessSpecifier::AS_protected)
565 return AccessSpecifier::AS_protected;
566 return AccessSpecifier::AS_public;
571void Serializer::parseFields(RecordInfo &I,
const RecordDecl *D,
573 SmallVector<MemberTypeInfo, 4> Members;
574 for (
const FieldDecl *F :
D->fields()) {
575 if (!shouldSerializeInfo(
PublicOnly,
false, F))
577 populateMemberTypeInfo(Members, Access, F);
579 const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
581 if (!Members.empty())
585 for (Decl *CxxDecl : CxxRD->decls()) {
586 auto *VD = dyn_cast<VarDecl>(CxxDecl);
591 if (VD->isStaticDataMember())
592 populateMemberTypeInfo(Members, Access, VD,
true);
594 if (!Members.empty())
598void Serializer::parseEnumerators(EnumInfo &I,
const EnumDecl *D) {
599 llvm::SmallVector<EnumValueInfo, 4> LocalMembers;
600 for (
const EnumConstantDecl *E :
D->enumerators()) {
601 std::string ValueExpr;
602 if (
const Expr *InitExpr = E->getInitExpr())
603 ValueExpr = getSourceCode(D, InitExpr->getSourceRange());
604 SmallString<16> ValueStr;
605 E->getInitVal().toString(ValueStr);
606 EnumValueInfo &Member = LocalMembers.emplace_back(
607 E->getNameAsString(), ValueStr.str(), ValueExpr);
608 ASTContext &Context = E->getASTContext();
609 if (RawComment *Comment = E->getASTContext().getRawCommentNoCache(E)) {
610 Comment->setAttached();
611 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, E)) {
613 Member.Description.push_back(*NewCI);
614 parseFullComment(Fc, *NewCI->Ptr);
618 if (!LocalMembers.empty())
622void Serializer::parseParameters(FunctionInfo &I,
const FunctionDecl *D) {
623 llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
624 auto &LO =
D->getLangOpts();
625 for (
const ParmVarDecl *P :
D->parameters()) {
626 FieldTypeInfo &FieldInfo = LocalParams.emplace_back(
627 getTypeInfoForType(
P->getOriginalType(), LO),
P->getNameAsString());
628 if (std::optional<StringRef> DefaultValue =
629 getSourceCode(D,
P->getDefaultArgRange()))
630 FieldInfo.DefaultValue = *DefaultValue;
632 if (!LocalParams.empty())
638void Serializer::parseBases(RecordInfo &I,
const CXXRecordDecl *D) {
640 if (!
D->isThisDeclarationADefinition())
643 llvm::SmallVector<Reference, 4> LocalParents;
644 for (
const CXXBaseSpecifier &B :
D->bases()) {
647 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
648 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
649 LocalParents.emplace_back(getUSRForDecl(D),
B.getType().getAsString(),
651 }
else if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
652 LocalParents.emplace_back(
654 P->getQualifiedNameAsString(),
internString(getInfoRelativePath(P)));
656 LocalParents.emplace_back(
SymbolID(),
B.getType().getAsString());
658 if (!LocalParents.empty())
661 llvm::SmallVector<Reference, 4> LocalVirtualParents;
662 for (
const CXXBaseSpecifier &B :
D->vbases()) {
663 if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
664 LocalVirtualParents.emplace_back(
666 P->getQualifiedNameAsString(),
internString(getInfoRelativePath(P)));
668 LocalVirtualParents.emplace_back(
SymbolID(),
B.getType().getAsString());
670 if (!LocalVirtualParents.empty())
676void Serializer::populateParentNamespaces(
677 llvm::SmallVector<Reference, 4> &Namespaces,
const T *D,
678 bool &IsInAnonymousNamespace) {
679 const DeclContext *DC =
D->getDeclContext();
681 if (
const auto *N = dyn_cast<NamespaceDecl>(DC)) {
683 if (N->isAnonymousNamespace()) {
685 IsInAnonymousNamespace =
true;
688 Namespaces.emplace_back(getUSRForDecl(N), Namespace,
690 N->getQualifiedNameAsString());
691 }
else if (
const auto *N = dyn_cast<RecordDecl>(DC))
692 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
694 N->getQualifiedNameAsString());
695 else if (
const auto *N = dyn_cast<FunctionDecl>(DC))
696 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
698 N->getQualifiedNameAsString());
699 else if (
const auto *N = dyn_cast<EnumDecl>(DC))
700 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
702 }
while ((DC = DC->getParent()));
707 if ((Namespaces.empty() && isa<RecordDecl>(D)) ||
709 Namespaces.emplace_back(
SymbolID(),
"GlobalNamespace",
713void Serializer::populateTemplateParameters(
714 std::optional<TemplateInfo> &TemplateInfo,
const clang::Decl *D) {
715 if (
const TemplateParameterList *ParamList =
716 D->getDescribedTemplateParams()) {
718 TemplateInfo.emplace();
720 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
721 for (
const NamedDecl *ND : *ParamList) {
722 LocalParams.emplace_back(getSourceCode(ND, ND->getSourceRange()));
724 if (!LocalParams.empty())
725 TemplateInfo->Params =
731Serializer::convertTemplateArgToInfo(
const clang::Decl *D,
732 const TemplateArgument &Arg) {
736 llvm::raw_string_ostream Stream(Str);
737 Arg.print(PrintingPolicy(
D->getLangOpts()), Stream,
false);
738 return TemplateParamInfo(Str);
744bool Serializer::isSupportedContext(Decl::Kind DeclKind) {
746 case Decl::Kind::Record:
747 case Decl::Kind::CXXRecord:
748 case Decl::Kind::ClassTemplateSpecialization:
749 case Decl::Kind::ClassTemplatePartialSpecialization:
750 case Decl::Kind::Namespace:
757void Serializer::findParent(Info &I,
const Decl *D) {
758 assert(D &&
"Invalid Decl");
761 if (!isSupportedContext(
D->getKind()))
764 const DeclContext *ParentCtx = dyn_cast<DeclContext>(D)->getLexicalParent();
766 if (isSupportedContext(ParentCtx->getDeclKind())) {
768 I.ParentUSR = getUSRForDecl(dyn_cast<Decl>(ParentCtx));
771 ParentCtx = ParentCtx->getParent();
776void Serializer::populateInfo(Info &I,
const T *D,
const FullComment *C,
777 bool &IsInAnonymousNamespace) {
778 I.USR = getUSRForDecl(D);
781 if (
auto ConversionDecl = dyn_cast_or_null<CXXConversionDecl>(D);
782 ConversionDecl && ConversionDecl->getConversionType()
784 ->isTemplateTypeParmType())
786 ConversionDecl->getConversionType().getAsString());
789 llvm::SmallVector<Reference, 4> LocalNamespaces;
790 populateParentNamespaces(LocalNamespaces, D, IsInAnonymousNamespace);
791 if (!LocalNamespaces.empty())
797 I.Description.push_back(*NewCI);
798 parseFullComment(C, *NewCI->Ptr);
803void Serializer::populateSymbolInfo(
SymbolInfo &I,
const T *D,
804 const FullComment *C, Location Loc,
805 bool &IsInAnonymousNamespace) {
806 populateInfo(I, D, C, IsInAnonymousNamespace);
807 if (
D->isThisDeclarationADefinition())
813 auto *Mangler = ItaniumMangleContext::create(
814 D->getASTContext(),
D->getASTContext().getDiagnostics());
815 std::string MangledName;
816 llvm::raw_string_ostream MangledStream(MangledName);
817 if (
auto *CXXD = dyn_cast<CXXRecordDecl>(D))
818 Mangler->mangleCXXVTable(CXXD, MangledStream);
820 MangledStream <<
D->getNameAsString();
823 if (MangledName.size() > 250) {
824 auto SymbolID = llvm::toStringRef(llvm::toHex(I.USR)).str();
832void Serializer::handleCompoundConstraints(
833 const Expr *Constraint,
834 llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos) {
835 if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
836 handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
838 }
else if (Constraint->getStmtClass() == Stmt::BinaryOperatorClass) {
839 auto *BinaryOpExpr = dyn_cast<BinaryOperator>(Constraint);
840 handleCompoundConstraints(BinaryOpExpr->getLHS(), ConstraintInfos);
841 handleCompoundConstraints(BinaryOpExpr->getRHS(), ConstraintInfos);
842 }
else if (Constraint->getStmtClass() ==
843 Stmt::ConceptSpecializationExprClass) {
844 auto *
Concept = dyn_cast<ConceptSpecializationExpr>(Constraint);
845 ConstraintInfo CI(getUSRForDecl(
Concept->getNamedConcept()),
846 Concept->getNamedConcept()->getNameAsString());
848 ConstraintInfos.push_back(CI);
852void Serializer::populateConstraints(TemplateInfo &I,
const TemplateDecl *D) {
853 if (!D || !
D->hasAssociatedConstraints())
856 SmallVector<AssociatedConstraint> AssociatedConstraints;
857 D->getAssociatedConstraints(AssociatedConstraints);
858 SmallVector<ConstraintInfo, 4> LocalConstraints;
859 for (
const auto &Constraint : AssociatedConstraints) {
864 if (
const auto *ConstraintExpr =
865 dyn_cast_or_null<ConceptSpecializationExpr>(
866 Constraint.ConstraintExpr)) {
867 ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
868 ConstraintExpr->getNamedConcept()->getNameAsString());
870 LocalConstraints.push_back(std::move(CI));
872 handleCompoundConstraints(Constraint.ConstraintExpr, LocalConstraints);
875 if (!LocalConstraints.empty())
880void Serializer::populateFunctionInfo(FunctionInfo &I,
const FunctionDecl *D,
881 const FullComment *FC, Location Loc,
882 bool &IsInAnonymousNamespace) {
883 populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
884 auto &LO =
D->getLangOpts();
885 I.ReturnType = getTypeInfoForType(
D->getReturnType(), LO);
886 I.Prototype = getFunctionPrototype(D);
887 parseParameters(I, D);
888 I.IsStatic =
D->isStatic();
890 populateTemplateParameters(I.Template, D);
892 populateConstraints(I.Template.value(),
D->getDescribedFunctionTemplate());
895 if (
const FunctionTemplateSpecializationInfo *FTSI =
896 D->getTemplateSpecializationInfo()) {
898 I.Template.emplace();
899 I.Template->Specialization.emplace();
900 auto &Specialization = *I.Template->Specialization;
902 Specialization.SpecializationOf = getUSRForDecl(FTSI->getTemplate());
905 if (FTSI->TemplateArguments) {
906 SmallVector<TemplateParamInfo, 4> LocalParams;
907 for (
const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
908 LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
910 if (!LocalParams.empty())
911 Specialization.Params =
920void Serializer::populateMemberTypeInfo(T &I,
const Decl *D) {
921 assert(D &&
"Expect non-null FieldDecl in populateMemberTypeInfo");
923 ASTContext &Context =
D->getASTContext();
926 RawComment *Comment = Context.getRawCommentNoCache(D);
930 Comment->setAttached();
931 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, D)) {
933 I.Description.push_back(*NewCI);
934 parseFullComment(Fc, *NewCI->Ptr);
938void Serializer::populateMemberTypeInfo(
939 SmallVectorImpl<MemberTypeInfo> &Members, AccessSpecifier &Access,
940 const DeclaratorDecl *D,
bool IsStatic) {
943 MemberTypeInfo &NewMember = Members.emplace_back(
944 getTypeInfoForType(
D->getTypeSourceInfo()->getType(),
D->getLangOpts()),
945 D->getNameAsString(),
946 getFinalAccessSpecifier(Access,
D->getAccessUnsafe()), IsStatic);
947 populateMemberTypeInfo(NewMember, D);
950void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
951 const CXXRecordDecl *D,
bool IsFileInRootDir,
953 AccessSpecifier ParentAccess) {
955 if (!
D->isThisDeclarationADefinition())
957 for (
const CXXBaseSpecifier &B :
D->bases()) {
958 if (
const auto *Base =
B.getType()->getAsCXXRecordDecl()) {
959 if (Base->isCompleteDefinition()) {
963 {},
"",
internString(getInfoRelativePath(Base)),
B.isVirtual(),
964 getFinalAccessSpecifier(ParentAccess,
B.getAccessSpecifier()),
966 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
967 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
968 BI.USR = getUSRForDecl(D);
971 BI.USR = getUSRForDecl(Base);
975 for (
const auto &Decl : Base->decls())
976 if (
const auto *
MD = dyn_cast<CXXMethodDecl>(Decl)) {
978 if (
MD->getAccessUnsafe() == AccessSpecifier::AS_private ||
979 !
MD->isUserProvided())
983 FI.IsStatic =
MD->isStatic();
987 bool IsInAnonymousNamespace;
988 populateFunctionInfo(FI,
MD, {}, {},
989 IsInAnonymousNamespace);
991 getFinalAccessSpecifier(BI.Access,
MD->getAccessUnsafe());
992 BI.Children.Functions.push_back(
995 Bases.emplace_back(std::move(BI));
999 parseBases(Bases, Base, IsFileInRootDir,
PublicOnly,
false,
1000 Bases.back().Access);
1007 const FullComment *FC,
1010 bool IsInAnonymousNamespace =
false;
1011 populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
1012 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1015 NSI->Name = D->isAnonymousNamespace() ?
"@nonymous_namespace" : NSI->Name;
1016 NSI->Path = getInfoRelativePath(NSI->Namespace);
1017 if (NSI->Namespace.empty() && NSI->USR ==
SymbolID())
1018 return {NSI,
nullptr};
1022 return {std::move(NSI), makeAndInsertIntoParent<const NamespaceInfo &>(*NSI)};
1025void Serializer::parseFriends(
RecordInfo &RI,
const CXXRecordDecl *D) {
1026 if (!D->hasDefinition() || !D->hasFriends())
1029 llvm::SmallVector<FriendInfo, 4> LocalFriends;
1031 for (
const FriendDecl *FD : D->friends()) {
1032 if (FD->isUnsupportedFriend())
1036 const auto *ActualDecl = FD->getFriendDecl();
1038 const auto *FriendTypeInfo = FD->getFriendType();
1039 if (!FriendTypeInfo)
1041 ActualDecl = FriendTypeInfo->getType()->getAsCXXRecordDecl();
1048 if (
const auto *ActualTD = dyn_cast_or_null<TemplateDecl>(ActualDecl)) {
1049 if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
1051 F.Template.emplace();
1052 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1053 for (
const auto *Param : ActualTD->getTemplateParameters()->asArray())
1054 LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
1055 if (!LocalParams.empty())
1056 F.Template->Params =
1058 ActualDecl = ActualTD->getTemplatedDecl();
1061 if (
auto *
FuncDecl = dyn_cast_or_null<FunctionDecl>(ActualDecl)) {
1062 FunctionInfo TempInfo;
1063 parseParameters(TempInfo,
FuncDecl);
1066 F.ReturnType = getTypeInfoForType(
FuncDecl->getReturnType(),
1071 Reference(getUSRForDecl(ActualDecl), ActualDecl->getNameAsString(),
1073 getInfoRelativePath(ActualDecl));
1075 populateMemberTypeInfo(F, ActualDecl);
1076 LocalFriends.push_back(std::move(F));
1078 if (!LocalFriends.empty())
1083 const FullComment *FC,
1087 bool IsInAnonymousNamespace =
false;
1089 populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
1090 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1093 RI->
TagType = D->getTagKind();
1096 if (
const auto *C = dyn_cast<CXXRecordDecl>(D)) {
1097 if (
const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
1103 llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
1106 if (!LocalBases.empty())
1109 parseFriends(*RI, C);
1113 populateTemplateParameters(RI->
Template, D);
1115 populateConstraints(RI->
Template.value(), D->getDescribedTemplate());
1118 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1121 RI->
Template->Specialization.emplace();
1122 auto &Specialization = *RI->
Template->Specialization;
1125 auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
1126 if (
auto *SpecTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
1127 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1128 else if (
auto *SpecTD =
1129 dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
1130 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1137 if (
const ClassTemplatePartialSpecializationDecl *CTPSD =
1138 dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
1139 if (
const ASTTemplateArgumentListInfo *AsWritten =
1140 CTPSD->getTemplateArgsAsWritten()) {
1141 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1142 for (
unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
1143 LocalParams.emplace_back(
1144 getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
1146 if (!LocalParams.empty())
1151 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1152 for (
const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
1153 LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
1155 if (!LocalParams.empty())
1156 Specialization.Params =
1163 auto *Parent = makeAndInsertIntoParent<const RecordInfo &>(*RI);
1164 return {std::move(RI), std::move(Parent)};
1168 const FullComment *FC,
1171 bool IsInAnonymousNamespace =
false;
1172 populateFunctionInfo(*Func, D, FC, Loc, IsInAnonymousNamespace);
1173 Func->
Access = clang::AccessSpecifier::AS_none;
1174 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1178 return {
nullptr, makeAndInsertIntoParent(*Func)};
1182 const FullComment *FC,
1185 bool IsInAnonymousNamespace =
false;
1186 populateFunctionInfo(*Func, D, FC, Loc, IsInAnonymousNamespace);
1187 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1193 const NamedDecl *Parent =
nullptr;
1194 if (
const auto *SD =
1195 dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
1196 Parent = SD->getSpecializedTemplate();
1198 Parent = D->getParent();
1200 SymbolID ParentUSR = getUSRForDecl(Parent);
1203 Parent->getQualifiedNameAsString()};
1204 Func->
Access = D->getAccess();
1207 return {
nullptr, makeAndInsertIntoParent(*Func)};
1210void Serializer::extractCommentFromDecl(
const Decl *D,
TypedefInfo &
Info) {
1211 assert(D &&
"Invalid Decl when extracting comment");
1212 ASTContext &
Context = D->getASTContext();
1213 RawComment *Comment =
Context.getRawCommentNoCache(D);
1217 Comment->setAttached();
1218 if (comments::FullComment *Fc = Comment->parse(
Context,
nullptr, D)) {
1221 parseFullComment(Fc, *NewCI->Ptr);
1226 const FullComment *FC,
1229 bool IsInAnonymousNamespace =
false;
1230 populateInfo(*
Info, D, FC, IsInAnonymousNamespace);
1232 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1236 auto &LO = D->getLangOpts();
1237 Info->Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1238 populateTemplateParameters(
Info->Template, D);
1240 populateConstraints(
Info->Template.value(), D->getDescribedTemplate());
1242 if (
Info->Underlying.Type.
Name.empty()) {
1248 Info->IsUsing =
false;
1249 extractCommentFromDecl(D, *
Info);
1252 return {
nullptr, makeAndInsertIntoParent(*
Info)};
1258 const FullComment *FC,
1261 bool IsInAnonymousNamespace =
false;
1262 populateInfo(*
Info, D, FC, IsInAnonymousNamespace);
1263 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1267 const LangOptions &LO = D->getLangOpts();
1268 Info->Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1269 Info->TypeDeclaration = getTypeAlias(D);
1270 Info->IsUsing =
true;
1271 populateTemplateParameters(
Info->Template, D);
1273 populateConstraints(
Info->Template.value(), D->getDescribedAliasTemplate());
1275 extractCommentFromDecl(D, *
Info);
1278 return {
nullptr, makeAndInsertIntoParent(*
Info)};
1282 const FullComment *FC,
1285 bool IsInAnonymousNamespace =
false;
1286 populateSymbolInfo(*Enum, D, FC, Loc, IsInAnonymousNamespace);
1288 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1291 Enum->Scoped = D->isScoped();
1292 if (
const TypeSourceInfo *TSI = D->getIntegerTypeSourceInfo()) {
1293 auto Name = TSI->getType().getAsString();
1294 Enum->BaseType =
TypeInfo(Name, Name);
1296 parseEnumerators(*Enum, D);
1299 return {
nullptr, makeAndInsertIntoParent(*Enum)};
1303 const FullComment *FC,
1308 bool IsInAnonymousNamespace =
false;
1309 populateInfo(*Concept, D, FC, IsInAnonymousNamespace);
1310 Concept->IsType = D->isTypeConcept();
1311 Concept->DefLoc = Loc;
1312 Concept->ConstraintExpression =
exprToString(D->getConstraintExpr());
1314 if (
auto *ConceptParams = D->getTemplateParameters()) {
1315 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1316 for (
const auto *Param : ConceptParams->asArray()) {
1317 LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
1319 if (!LocalParams.empty())
1320 Concept->Template.Params =
1324 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1327 return {
nullptr, makeAndInsertIntoParent(*Concept)};
1331 const FullComment *FC,
1335 bool IsInAnonymousNamespace =
false;
1336 populateSymbolInfo(*Var, D, FC, Loc, IsInAnonymousNamespace);
1337 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1340 if (D->getStorageClass() == StorageClass::SC_Static)
1343 getTypeInfoForType(D->getType(), D->getASTContext().getPrintingPolicy());
1345 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1348 return {
nullptr, makeAndInsertIntoParent(*Var)};