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();
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())
796 I.Description.push_back(*NewCI);
797 parseFullComment(C, *NewCI->Ptr);
802void Serializer::populateSymbolInfo(
SymbolInfo &I,
const T *D,
803 const FullComment *C, Location Loc,
804 bool &IsInAnonymousNamespace) {
805 populateInfo(I, D, C, IsInAnonymousNamespace);
806 if (
D->isThisDeclarationADefinition())
812 auto *Mangler = ItaniumMangleContext::create(
813 D->getASTContext(),
D->getASTContext().getDiagnostics());
814 std::string MangledName;
815 llvm::raw_string_ostream MangledStream(MangledName);
816 if (
auto *CXXD = dyn_cast<CXXRecordDecl>(D))
817 Mangler->mangleCXXVTable(CXXD, MangledStream);
819 MangledStream <<
D->getNameAsString();
822 if (MangledName.size() > 250) {
823 auto SymbolID = llvm::toStringRef(llvm::toHex(I.USR)).str();
831void Serializer::handleCompoundConstraints(
832 const Expr *Constraint,
833 llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos) {
834 if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
835 handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
837 }
else if (Constraint->getStmtClass() == Stmt::BinaryOperatorClass) {
838 auto *BinaryOpExpr = dyn_cast<BinaryOperator>(Constraint);
839 handleCompoundConstraints(BinaryOpExpr->getLHS(), ConstraintInfos);
840 handleCompoundConstraints(BinaryOpExpr->getRHS(), ConstraintInfos);
841 }
else if (Constraint->getStmtClass() ==
842 Stmt::ConceptSpecializationExprClass) {
843 auto *
Concept = dyn_cast<ConceptSpecializationExpr>(Constraint);
844 ConstraintInfo CI(getUSRForDecl(
Concept->getNamedConcept()),
845 Concept->getNamedConcept()->getNameAsString());
847 ConstraintInfos.push_back(CI);
851void Serializer::populateConstraints(TemplateInfo &I,
const TemplateDecl *D) {
852 if (!D || !
D->hasAssociatedConstraints())
855 SmallVector<AssociatedConstraint> AssociatedConstraints;
856 D->getAssociatedConstraints(AssociatedConstraints);
857 SmallVector<ConstraintInfo, 4> LocalConstraints;
858 for (
const auto &Constraint : AssociatedConstraints) {
863 if (
const auto *ConstraintExpr =
864 dyn_cast_or_null<ConceptSpecializationExpr>(
865 Constraint.ConstraintExpr)) {
866 ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
867 ConstraintExpr->getNamedConcept()->getNameAsString());
869 LocalConstraints.push_back(std::move(CI));
871 handleCompoundConstraints(Constraint.ConstraintExpr, LocalConstraints);
874 if (!LocalConstraints.empty())
879void Serializer::populateFunctionInfo(FunctionInfo &I,
const FunctionDecl *D,
880 const FullComment *FC, Location Loc,
881 bool &IsInAnonymousNamespace) {
882 populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
883 auto &LO =
D->getLangOpts();
884 I.ReturnType = getTypeInfoForType(
D->getReturnType(), LO);
885 I.Prototype = getFunctionPrototype(D);
886 parseParameters(I, D);
887 I.IsStatic =
D->isStatic();
889 populateTemplateParameters(I.Template, D);
891 populateConstraints(I.Template.value(),
D->getDescribedFunctionTemplate());
894 if (
const FunctionTemplateSpecializationInfo *FTSI =
895 D->getTemplateSpecializationInfo()) {
897 I.Template.emplace();
898 I.Template->Specialization.emplace();
899 auto &Specialization = *I.Template->Specialization;
901 Specialization.SpecializationOf = getUSRForDecl(FTSI->getTemplate());
904 if (FTSI->TemplateArguments) {
905 SmallVector<TemplateParamInfo, 4> LocalParams;
906 for (
const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
907 LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
909 if (!LocalParams.empty())
910 Specialization.Params =
919void Serializer::populateMemberTypeInfo(T &I,
const Decl *D) {
920 assert(D &&
"Expect non-null FieldDecl in populateMemberTypeInfo");
922 ASTContext &Context =
D->getASTContext();
925 RawComment *Comment = Context.getRawCommentNoCache(D);
929 Comment->setAttached();
930 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, D)) {
932 I.Description.push_back(*NewCI);
933 parseFullComment(Fc, *NewCI->Ptr);
937void Serializer::populateMemberTypeInfo(
938 SmallVectorImpl<MemberTypeInfo> &Members, AccessSpecifier &Access,
939 const DeclaratorDecl *D,
bool IsStatic) {
942 MemberTypeInfo &NewMember = Members.emplace_back(
943 getTypeInfoForType(
D->getTypeSourceInfo()->getType(),
D->getLangOpts()),
944 D->getNameAsString(),
945 getFinalAccessSpecifier(Access,
D->getAccessUnsafe()), IsStatic);
946 populateMemberTypeInfo(NewMember, D);
949void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
950 const CXXRecordDecl *D,
bool IsFileInRootDir,
952 AccessSpecifier ParentAccess) {
954 if (!
D->isThisDeclarationADefinition())
956 for (
const CXXBaseSpecifier &B :
D->bases()) {
957 if (
const auto *Base =
B.getType()->getAsCXXRecordDecl()) {
958 if (Base->isCompleteDefinition()) {
962 {},
"",
internString(getInfoRelativePath(Base)),
B.isVirtual(),
963 getFinalAccessSpecifier(ParentAccess,
B.getAccessSpecifier()),
965 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
966 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
967 BI.USR = getUSRForDecl(D);
970 BI.USR = getUSRForDecl(Base);
974 for (
const auto &Decl : Base->decls())
975 if (
const auto *
MD = dyn_cast<CXXMethodDecl>(Decl)) {
977 if (
MD->getAccessUnsafe() == AccessSpecifier::AS_private ||
978 !
MD->isUserProvided())
982 FI.IsStatic =
MD->isStatic();
986 bool IsInAnonymousNamespace;
987 populateFunctionInfo(FI,
MD, {}, {},
988 IsInAnonymousNamespace);
990 getFinalAccessSpecifier(BI.Access,
MD->getAccessUnsafe());
991 BI.Children.Functions.push_back(
994 Bases.emplace_back(std::move(BI));
998 parseBases(Bases, Base, IsFileInRootDir,
PublicOnly,
false,
999 Bases.back().Access);
1006 const FullComment *FC,
1009 bool IsInAnonymousNamespace =
false;
1010 populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
1011 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1014 NSI->Name = D->isAnonymousNamespace() ?
"@nonymous_namespace" : NSI->Name;
1015 NSI->Path = getInfoRelativePath(NSI->Namespace);
1016 if (NSI->Namespace.empty() && NSI->USR ==
SymbolID())
1017 return {NSI,
nullptr};
1021 return {std::move(NSI), makeAndInsertIntoParent<const NamespaceInfo &>(*NSI)};
1024void Serializer::parseFriends(
RecordInfo &RI,
const CXXRecordDecl *D) {
1025 if (!D->hasDefinition() || !D->hasFriends())
1028 llvm::SmallVector<FriendInfo, 4> LocalFriends;
1030 for (
const FriendDecl *FD : D->friends()) {
1031 if (FD->isUnsupportedFriend())
1035 const auto *ActualDecl = FD->getFriendDecl();
1037 const auto *FriendTypeInfo = FD->getFriendType();
1038 if (!FriendTypeInfo)
1040 ActualDecl = FriendTypeInfo->getType()->getAsCXXRecordDecl();
1047 if (
const auto *ActualTD = dyn_cast_or_null<TemplateDecl>(ActualDecl)) {
1048 if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
1050 F.Template.emplace();
1051 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1052 for (
const auto *Param : ActualTD->getTemplateParameters()->asArray())
1053 LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
1054 if (!LocalParams.empty())
1055 F.Template->Params =
1057 ActualDecl = ActualTD->getTemplatedDecl();
1060 if (
auto *
FuncDecl = dyn_cast_or_null<FunctionDecl>(ActualDecl)) {
1061 FunctionInfo TempInfo;
1062 parseParameters(TempInfo,
FuncDecl);
1064 F.ReturnType = getTypeInfoForType(
FuncDecl->getReturnType(),
1069 Reference(getUSRForDecl(ActualDecl), ActualDecl->getNameAsString(),
1071 getInfoRelativePath(ActualDecl));
1073 populateMemberTypeInfo(F, ActualDecl);
1074 LocalFriends.push_back(std::move(F));
1076 if (!LocalFriends.empty())
1081 const FullComment *FC,
1085 bool IsInAnonymousNamespace =
false;
1087 populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
1088 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1091 RI->
TagType = D->getTagKind();
1094 if (
const auto *C = dyn_cast<CXXRecordDecl>(D)) {
1095 if (
const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
1101 llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
1104 if (!LocalBases.empty())
1106 parseFriends(*RI, C);
1110 populateTemplateParameters(RI->
Template, D);
1112 populateConstraints(RI->
Template.value(), D->getDescribedTemplate());
1115 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1118 RI->
Template->Specialization.emplace();
1119 auto &Specialization = *RI->
Template->Specialization;
1122 auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
1123 if (
auto *SpecTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
1124 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1125 else if (
auto *SpecTD =
1126 dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
1127 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1134 if (
const ClassTemplatePartialSpecializationDecl *CTPSD =
1135 dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
1136 if (
const ASTTemplateArgumentListInfo *AsWritten =
1137 CTPSD->getTemplateArgsAsWritten()) {
1138 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1139 for (
unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
1140 LocalParams.emplace_back(
1141 getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
1143 if (!LocalParams.empty())
1144 Specialization.Params =
1148 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1149 for (
const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
1150 LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
1152 if (!LocalParams.empty())
1153 Specialization.Params =
1160 auto *Parent = makeAndInsertIntoParent<const RecordInfo &>(*RI);
1161 return {std::move(RI), std::move(Parent)};
1165 const FullComment *FC,
1168 bool IsInAnonymousNamespace =
false;
1169 populateFunctionInfo(*Func, D, FC, Loc, IsInAnonymousNamespace);
1170 Func->
Access = clang::AccessSpecifier::AS_none;
1171 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1175 return {
nullptr, makeAndInsertIntoParent(*Func)};
1179 const FullComment *FC,
1182 bool IsInAnonymousNamespace =
false;
1183 populateFunctionInfo(*Func, D, FC, Loc, IsInAnonymousNamespace);
1184 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1190 const NamedDecl *Parent =
nullptr;
1191 if (
const auto *SD =
1192 dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
1193 Parent = SD->getSpecializedTemplate();
1195 Parent = D->getParent();
1197 SymbolID ParentUSR = getUSRForDecl(Parent);
1200 Parent->getQualifiedNameAsString()};
1201 Func->
Access = D->getAccess();
1204 return {
nullptr, makeAndInsertIntoParent(*Func)};
1207void Serializer::extractCommentFromDecl(
const Decl *D,
TypedefInfo &
Info) {
1208 assert(D &&
"Invalid Decl when extracting comment");
1209 ASTContext &
Context = D->getASTContext();
1210 RawComment *Comment =
Context.getRawCommentNoCache(D);
1214 Comment->setAttached();
1215 if (comments::FullComment *Fc = Comment->parse(
Context,
nullptr, D)) {
1218 parseFullComment(Fc, *NewCI->Ptr);
1223 const FullComment *FC,
1226 bool IsInAnonymousNamespace =
false;
1227 populateInfo(*
Info, D, FC, IsInAnonymousNamespace);
1229 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1233 auto &LO = D->getLangOpts();
1234 Info->Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1235 populateTemplateParameters(
Info->Template, D);
1237 populateConstraints(
Info->Template.value(), D->getDescribedTemplate());
1239 if (
Info->Underlying.Type.
Name.empty()) {
1245 Info->IsUsing =
false;
1246 extractCommentFromDecl(D, *
Info);
1249 return {
nullptr, makeAndInsertIntoParent(*
Info)};
1255 const FullComment *FC,
1258 bool IsInAnonymousNamespace =
false;
1259 populateInfo(*
Info, D, FC, IsInAnonymousNamespace);
1260 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1264 const LangOptions &LO = D->getLangOpts();
1265 Info->Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1266 Info->TypeDeclaration = getTypeAlias(D);
1267 Info->IsUsing =
true;
1268 populateTemplateParameters(
Info->Template, D);
1270 populateConstraints(
Info->Template.value(), D->getDescribedAliasTemplate());
1272 extractCommentFromDecl(D, *
Info);
1275 return {
nullptr, makeAndInsertIntoParent(*
Info)};
1279 const FullComment *FC,
1282 bool IsInAnonymousNamespace =
false;
1283 populateSymbolInfo(*Enum, D, FC, Loc, IsInAnonymousNamespace);
1285 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1288 Enum->Scoped = D->isScoped();
1289 if (
const TypeSourceInfo *TSI = D->getIntegerTypeSourceInfo()) {
1290 auto Name = TSI->getType().getAsString();
1291 Enum->BaseType =
TypeInfo(Name, Name);
1293 parseEnumerators(*Enum, D);
1296 return {
nullptr, makeAndInsertIntoParent(*Enum)};
1300 const FullComment *FC,
1305 bool IsInAnonymousNamespace =
false;
1306 populateInfo(*Concept, D, FC, IsInAnonymousNamespace);
1307 Concept->IsType = D->isTypeConcept();
1308 Concept->DefLoc = Loc;
1309 Concept->ConstraintExpression =
exprToString(D->getConstraintExpr());
1311 if (
auto *ConceptParams = D->getTemplateParameters()) {
1312 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1313 for (
const auto *Param : ConceptParams->asArray()) {
1314 LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
1316 if (!LocalParams.empty())
1317 Concept->Template.Params =
1321 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1324 return {
nullptr, makeAndInsertIntoParent(*Concept)};
1328 const FullComment *FC,
1332 bool IsInAnonymousNamespace =
false;
1333 populateSymbolInfo(*Var, D, FC, Loc, IsInAnonymousNamespace);
1334 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1337 if (D->getStorageClass() == StorageClass::SC_Static)
1340 getTypeInfoForType(D->getType(), D->getASTContext().getPrintingPolicy());
1342 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1345 return {
nullptr, makeAndInsertIntoParent(*Var)};