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());
186Serializer::getInfoRelativePath(llvm::ArrayRef<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())) {
244 assert(Idx == NumChildren &&
245 "Mismatch between child_count and actual children");
247 llvm::ArrayRef<CommentInfo>(ChildrenArray, NumChildren);
252 if (!isWhitespaceOnly(C->getText()))
253 CurrentCI.Text = C->getText().trim();
257 const InlineCommandComment *C) {
258 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
259 llvm::SmallVector<StringRef> Args;
260 for (
unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
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()) {
281 if (!AttrValues.empty()) {
287 const HTMLEndTagComment *C) {
289 CurrentCI.SelfClosing =
true;
293 const BlockCommandComment *C) {
294 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
295 llvm::SmallVector<StringRef> Args;
296 for (
unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
304 const ParamCommandComment *C) {
306 ParamCommandComment::getDirectionAsString(C->getDirection()));
307 CurrentCI.Explicit = C->isDirectionExplicit();
308 if (C->hasParamName())
309 CurrentCI.ParamName =
internString(C->getParamNameAsWritten());
313 const TParamCommandComment *C) {
314 if (C->hasParamName())
315 CurrentCI.ParamName =
internString(C->getParamNameAsWritten());
319 const VerbatimBlockComment *C) {
320 CurrentCI.Name =
internString(getCommandName(C->getCommandID()));
325 const VerbatimBlockLineComment *C) {
326 if (!isWhitespaceOnly(C->getText()))
331 const VerbatimLineComment *C) {
332 if (!isWhitespaceOnly(C->getText()))
336bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S)
const {
337 return llvm::all_of(S, isspace);
340StringRef ClangDocCommentVisitor::getCommandName(
unsigned CommandID)
const {
341 const CommandInfo *
Info = CommandTraits::getBuiltinCommandInfo(CommandID);
345 return "<not a builtin command>";
350StringRef Serializer::getSourceCode(
const Decl *D,
const SourceRange &R) {
352 CharSourceRange::getTokenRange(R), D->getASTContext().getSourceManager(),
353 D->getASTContext().getLangOpts()));
357static std::string
serialize(T &I, DiagnosticsEngine &Diags) {
358 SmallString<2048> Buffer;
359 llvm::BitstreamWriter Stream(Buffer);
362 return Buffer.str().str();
384 llvm_unreachable(
"unhandled enumerator");
387void Serializer::parseFullComment(
const FullComment *C,
CommentInfo &CI) {
388 ClangDocCommentVisitor Visitor(CI);
389 Visitor.parseComment(C);
392SymbolID Serializer::getUSRForDecl(
const Decl *D) {
393 llvm::SmallString<128> USR;
394 if (index::generateUSRForDecl(D, USR))
399TagDecl *Serializer::getTagDeclForType(
const QualType &T) {
400 if (
const TagDecl *D = T->getAsTagDecl())
401 return D->getDefinition();
405RecordDecl *Serializer::getRecordDeclForType(
const QualType &T) {
406 if (
const RecordDecl *D =
T->getAsRecordDecl())
407 return D->getDefinition();
411TypeInfo Serializer::getTypeInfoForType(
const QualType &T,
412 const PrintingPolicy &Policy) {
413 const TagDecl *TD = getTagDeclForType(T);
415 TypeInfo TI = TypeInfo(Reference(
SymbolID(),
T.getAsString(Policy)));
416 TI.IsBuiltIn =
T->isBuiltinType();
417 TI.IsTemplate =
T->isTemplateTypeParmType();
421 if (isa<EnumDecl>(TD)) {
423 }
else if (isa<RecordDecl>(TD)) {
428 Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
429 T.getAsString(Policy), getInfoRelativePath(TD));
430 TypeInfo TI = TypeInfo(R);
431 TI.IsBuiltIn =
T->isBuiltinType();
432 TI.IsTemplate =
T->isTemplateTypeParmType();
436bool Serializer::isPublic(
const clang::AccessSpecifier AS,
437 const clang::Linkage Link) {
438 if (AS == clang::AccessSpecifier::AS_private)
440 if ((Link == clang::Linkage::Module) || (Link == clang::Linkage::External))
445bool Serializer::shouldSerializeInfo(
bool PublicOnly,
446 bool IsInAnonymousNamespace,
447 const NamedDecl *D) {
448 bool IsAnonymousNamespace =
false;
449 if (
const auto *N = dyn_cast<NamespaceDecl>(D))
450 IsAnonymousNamespace = N->isAnonymousNamespace();
452 (!IsInAnonymousNamespace && !IsAnonymousNamespace &&
453 isPublic(
D->getAccessUnsafe(),
D->getLinkageInternal()));
462void Serializer::InsertChild(ScopeChildren &Scope,
const NamespaceInfo &Info) {
465 getInfoRelativePath(
Info.Namespace)));
468void Serializer::InsertChild(ScopeChildren &Scope,
const RecordInfo &Info) {
471 getInfoRelativePath(
Info.Namespace),
Info.MangledName));
474void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo &Info) {
478void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo &Info) {
482void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo &Info) {
486void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo &Info) {
490void Serializer::InsertChild(ScopeChildren &Scope, VarInfo &Info) {
508template <
typename ChildType>
509OwnedPtr<Info> Serializer::makeAndInsertIntoParent(ChildType &Child) {
510 if (Child.Namespace.empty()) {
513 InsertChild(ParentNS->Children, Child);
517 switch (Child.Namespace[0].RefType) {
520 ParentNS->USR = Child.Namespace[0].USR;
521 InsertChild(ParentNS->Children, Child);
526 ParentRec->USR = Child.Namespace[0].USR;
527 InsertChild(ParentRec->Children, Child);
539 llvm_unreachable(
"Invalid reference type for parent namespace");
557AccessSpecifier Serializer::getFinalAccessSpecifier(AccessSpecifier FirstAS,
558 AccessSpecifier SecondAS) {
559 if (FirstAS == AccessSpecifier::AS_none ||
560 SecondAS == AccessSpecifier::AS_none)
561 return AccessSpecifier::AS_none;
562 if (FirstAS == AccessSpecifier::AS_private ||
563 SecondAS == AccessSpecifier::AS_private)
564 return AccessSpecifier::AS_private;
565 if (FirstAS == AccessSpecifier::AS_protected ||
566 SecondAS == AccessSpecifier::AS_protected)
567 return AccessSpecifier::AS_protected;
568 return AccessSpecifier::AS_public;
573void Serializer::parseFields(RecordInfo &I,
const RecordDecl *D,
575 SmallVector<MemberTypeInfo, 4> Members;
576 for (
const FieldDecl *F :
D->fields()) {
577 if (!shouldSerializeInfo(
PublicOnly,
false, F))
579 populateMemberTypeInfo(Members, Access, F);
581 const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
583 if (!Members.empty())
587 for (Decl *CxxDecl : CxxRD->decls()) {
588 auto *VD = dyn_cast<VarDecl>(CxxDecl);
593 if (VD->isStaticDataMember())
594 populateMemberTypeInfo(Members, Access, VD,
true);
596 if (!Members.empty())
600void Serializer::parseEnumerators(EnumInfo &I,
const EnumDecl *D) {
601 llvm::SmallVector<EnumValueInfo, 4> LocalMembers;
602 for (
const EnumConstantDecl *E :
D->enumerators()) {
603 std::string ValueExpr;
604 if (
const Expr *InitExpr = E->getInitExpr())
605 ValueExpr = getSourceCode(D, InitExpr->getSourceRange());
606 SmallString<16> ValueStr;
607 E->getInitVal().toString(ValueStr);
608 EnumValueInfo &Member = LocalMembers.emplace_back(
609 E->getNameAsString(), ValueStr.str(), ValueExpr);
610 ASTContext &Context = E->getASTContext();
611 if (RawComment *Comment =
612 E->getASTContext().getRawCommentForDeclNoCache(E)) {
613 Comment->setAttached();
614 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, E)) {
616 Member.Description.push_back(*NewCI);
617 parseFullComment(Fc, *NewCI->Ptr);
621 if (!LocalMembers.empty())
625void Serializer::parseParameters(FunctionInfo &I,
const FunctionDecl *D) {
626 llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
627 auto &LO =
D->getLangOpts();
628 for (
const ParmVarDecl *P :
D->parameters()) {
629 FieldTypeInfo &FieldInfo = LocalParams.emplace_back(
630 getTypeInfoForType(
P->getOriginalType(), LO),
P->getNameAsString());
631 if (std::optional<StringRef> DefaultValue =
632 getSourceCode(D,
P->getDefaultArgRange()))
633 FieldInfo.DefaultValue = *DefaultValue;
635 if (!LocalParams.empty())
641void Serializer::parseBases(RecordInfo &I,
const CXXRecordDecl *D) {
643 if (!
D->isThisDeclarationADefinition())
646 llvm::SmallVector<Reference, 4> LocalParents;
647 for (
const CXXBaseSpecifier &B :
D->bases()) {
650 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
651 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
652 LocalParents.emplace_back(getUSRForDecl(D),
B.getType().getAsString(),
654 }
else if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
655 LocalParents.emplace_back(
657 P->getQualifiedNameAsString(),
internString(getInfoRelativePath(P)));
659 LocalParents.emplace_back(
SymbolID(),
B.getType().getAsString());
661 if (!LocalParents.empty())
664 llvm::SmallVector<Reference, 4> LocalVirtualParents;
665 for (
const CXXBaseSpecifier &B :
D->vbases()) {
666 if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
667 LocalVirtualParents.emplace_back(
669 P->getQualifiedNameAsString(),
internString(getInfoRelativePath(P)));
671 LocalVirtualParents.emplace_back(
SymbolID(),
B.getType().getAsString());
673 if (!LocalVirtualParents.empty())
679void Serializer::populateParentNamespaces(
680 llvm::SmallVector<Reference, 4> &Namespaces,
const T *D,
681 bool &IsInAnonymousNamespace) {
682 const DeclContext *DC =
D->getDeclContext();
684 if (
const auto *N = dyn_cast<NamespaceDecl>(DC)) {
686 if (N->isAnonymousNamespace()) {
688 IsInAnonymousNamespace =
true;
691 Namespaces.emplace_back(getUSRForDecl(N), Namespace,
693 N->getQualifiedNameAsString());
694 }
else if (
const auto *N = dyn_cast<RecordDecl>(DC))
695 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
697 N->getQualifiedNameAsString());
698 else if (
const auto *N = dyn_cast<FunctionDecl>(DC))
699 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
701 N->getQualifiedNameAsString());
702 else if (
const auto *N = dyn_cast<EnumDecl>(DC))
703 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
705 }
while ((DC = DC->getParent()));
710 if ((Namespaces.empty() && isa<RecordDecl>(D)) ||
712 Namespaces.emplace_back(
SymbolID(),
"GlobalNamespace",
716void Serializer::populateTemplateParameters(
717 std::optional<TemplateInfo> &TemplateInfo,
const clang::Decl *D) {
718 if (
const TemplateParameterList *ParamList =
719 D->getDescribedTemplateParams()) {
721 TemplateInfo.emplace();
723 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
724 for (
const NamedDecl *ND : *ParamList) {
725 LocalParams.emplace_back(getSourceCode(ND, ND->getSourceRange()));
727 if (!LocalParams.empty())
728 TemplateInfo->Params =
734Serializer::convertTemplateArgToInfo(
const clang::Decl *D,
735 const TemplateArgument &Arg) {
739 llvm::raw_string_ostream Stream(Str);
740 Arg.print(PrintingPolicy(
D->getLangOpts()), Stream,
false);
741 return TemplateParamInfo(Str);
747bool Serializer::isSupportedContext(Decl::Kind DeclKind) {
749 case Decl::Kind::Record:
750 case Decl::Kind::CXXRecord:
751 case Decl::Kind::ClassTemplateSpecialization:
752 case Decl::Kind::ClassTemplatePartialSpecialization:
753 case Decl::Kind::Namespace:
760void Serializer::findParent(Info &I,
const Decl *D) {
761 assert(D &&
"Invalid Decl");
764 if (!isSupportedContext(
D->getKind()))
767 const DeclContext *ParentCtx = dyn_cast<DeclContext>(D)->getLexicalParent();
769 if (isSupportedContext(ParentCtx->getDeclKind())) {
771 I.ParentUSR = getUSRForDecl(dyn_cast<Decl>(ParentCtx));
774 ParentCtx = ParentCtx->getParent();
779void Serializer::populateInfo(Info &I,
const T *D,
const FullComment *C,
780 bool &IsInAnonymousNamespace) {
781 I.USR = getUSRForDecl(D);
784 if (
auto ConversionDecl = dyn_cast_or_null<CXXConversionDecl>(D);
785 ConversionDecl && ConversionDecl->getConversionType()
787 ->isTemplateTypeParmType())
789 ConversionDecl->getConversionType().getAsString());
792 llvm::SmallVector<Reference, 4> LocalNamespaces;
793 populateParentNamespaces(LocalNamespaces, D, IsInAnonymousNamespace);
794 if (!LocalNamespaces.empty())
799 I.Description.push_back(*NewCI);
800 parseFullComment(C, *NewCI->Ptr);
805void Serializer::populateSymbolInfo(
SymbolInfo &I,
const T *D,
806 const FullComment *C, Location Loc,
807 bool &IsInAnonymousNamespace) {
808 populateInfo(I, D, C, IsInAnonymousNamespace);
809 if (
D->isThisDeclarationADefinition())
815 auto *Mangler = ItaniumMangleContext::create(
816 D->getASTContext(),
D->getASTContext().getDiagnostics());
817 std::string MangledName;
818 llvm::raw_string_ostream MangledStream(MangledName);
819 if (
auto *CXXD = dyn_cast<CXXRecordDecl>(D))
820 Mangler->mangleCXXVTable(CXXD, MangledStream);
822 MangledStream <<
D->getNameAsString();
825 if (MangledName.size() > 250) {
826 auto SymbolID = llvm::toStringRef(llvm::toHex(I.USR)).str();
834void Serializer::handleCompoundConstraints(
835 const Expr *Constraint,
836 llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos) {
837 if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
838 handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
840 }
else if (Constraint->getStmtClass() == Stmt::BinaryOperatorClass) {
841 auto *BinaryOpExpr = dyn_cast<BinaryOperator>(Constraint);
842 handleCompoundConstraints(BinaryOpExpr->getLHS(), ConstraintInfos);
843 handleCompoundConstraints(BinaryOpExpr->getRHS(), ConstraintInfos);
844 }
else if (Constraint->getStmtClass() ==
845 Stmt::ConceptSpecializationExprClass) {
846 auto *
Concept = dyn_cast<ConceptSpecializationExpr>(Constraint);
847 ConstraintInfo CI(getUSRForDecl(
Concept->getNamedConcept()),
848 Concept->getNamedConcept()->getNameAsString());
849 CI.ConstraintExpr =
internString(exprToString(Concept));
850 ConstraintInfos.push_back(CI);
854void Serializer::populateConstraints(TemplateInfo &I,
const TemplateDecl *D) {
855 if (!D || !
D->hasAssociatedConstraints())
858 SmallVector<AssociatedConstraint> AssociatedConstraints;
859 D->getAssociatedConstraints(AssociatedConstraints);
860 SmallVector<ConstraintInfo, 4> LocalConstraints;
861 for (
const auto &Constraint : AssociatedConstraints) {
866 if (
const auto *ConstraintExpr =
867 dyn_cast_or_null<ConceptSpecializationExpr>(
868 Constraint.ConstraintExpr)) {
869 ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
870 ConstraintExpr->getNamedConcept()->getNameAsString());
871 CI.ConstraintExpr =
internString(exprToString(ConstraintExpr));
872 LocalConstraints.push_back(std::move(CI));
874 handleCompoundConstraints(Constraint.ConstraintExpr, LocalConstraints);
877 if (!LocalConstraints.empty())
882void Serializer::populateFunctionInfo(FunctionInfo &I,
const FunctionDecl *D,
883 const FullComment *FC, Location Loc,
884 bool &IsInAnonymousNamespace) {
885 populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
886 auto &LO =
D->getLangOpts();
887 I.ReturnType = getTypeInfoForType(
D->getReturnType(), LO);
888 I.Prototype = getFunctionPrototype(D);
889 parseParameters(I, D);
890 I.IsStatic =
D->isStatic();
892 populateTemplateParameters(I.Template, D);
894 populateConstraints(I.Template.value(),
D->getDescribedFunctionTemplate());
897 if (
const FunctionTemplateSpecializationInfo *FTSI =
898 D->getTemplateSpecializationInfo()) {
900 I.Template.emplace();
901 I.Template->Specialization.emplace();
902 auto &Specialization = *I.Template->Specialization;
904 Specialization.SpecializationOf = getUSRForDecl(FTSI->getTemplate());
907 if (FTSI->TemplateArguments) {
908 SmallVector<TemplateParamInfo, 4> LocalParams;
909 for (
const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
910 LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
912 if (!LocalParams.empty())
913 Specialization.Params =
922void Serializer::populateMemberTypeInfo(T &I,
const Decl *D) {
923 assert(D &&
"Expect non-null FieldDecl in populateMemberTypeInfo");
925 ASTContext &Context =
D->getASTContext();
928 RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
932 Comment->setAttached();
933 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, D)) {
935 I.Description.push_back(*NewCI);
936 parseFullComment(Fc, *NewCI->Ptr);
940void Serializer::populateMemberTypeInfo(
941 SmallVectorImpl<MemberTypeInfo> &Members, AccessSpecifier &Access,
942 const DeclaratorDecl *D,
bool IsStatic) {
945 MemberTypeInfo &NewMember = Members.emplace_back(
946 getTypeInfoForType(
D->getTypeSourceInfo()->getType(),
D->getLangOpts()),
947 D->getNameAsString(),
948 getFinalAccessSpecifier(Access,
D->getAccessUnsafe()), IsStatic);
949 populateMemberTypeInfo(NewMember, D);
952void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
953 const CXXRecordDecl *D,
bool IsFileInRootDir,
955 AccessSpecifier ParentAccess) {
957 if (!
D->isThisDeclarationADefinition())
959 for (
const CXXBaseSpecifier &B :
D->bases()) {
960 if (
const auto *Base =
B.getType()->getAsCXXRecordDecl()) {
961 if (Base->isCompleteDefinition()) {
965 {},
"",
internString(getInfoRelativePath(Base)),
B.isVirtual(),
966 getFinalAccessSpecifier(ParentAccess,
B.getAccessSpecifier()),
968 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
969 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
970 BI.USR = getUSRForDecl(D);
973 BI.USR = getUSRForDecl(Base);
977 for (
const auto &Decl : Base->decls())
978 if (
const auto *
MD = dyn_cast<CXXMethodDecl>(Decl)) {
980 if (
MD->getAccessUnsafe() == AccessSpecifier::AS_private ||
981 !
MD->isUserProvided())
985 FI.IsStatic =
MD->isStatic();
989 bool IsInAnonymousNamespace;
990 populateFunctionInfo(FI,
MD, {}, {},
991 IsInAnonymousNamespace);
993 getFinalAccessSpecifier(BI.Access,
MD->getAccessUnsafe());
995 BI.Children.Functions.push_back(
998 Bases.emplace_back(std::move(BI));
1002 parseBases(Bases, Base, IsFileInRootDir,
PublicOnly,
false,
1003 Bases.back().Access);
1013 bool IsInAnonymousNamespace =
false;
1014 populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
1015 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1018 NSI->Name = D->isAnonymousNamespace() ?
"@nonymous_namespace" : NSI->Name;
1019 NSI->Path = getInfoRelativePath(NSI->Namespace);
1020 if (NSI->Namespace.empty() && NSI->USR ==
SymbolID())
1025 return {std::move(NSI), makeAndInsertIntoParent<const NamespaceInfo &>(*NSI)};
1028void Serializer::parseFriends(
RecordInfo &RI,
const CXXRecordDecl *D) {
1029 if (!D->hasDefinition() || !D->hasFriends())
1032 llvm::SmallVector<FriendInfo, 4> LocalFriends;
1034 for (
const FriendDecl *FD : D->friends()) {
1035 if (FD->isUnsupportedFriend())
1039 const auto *ActualDecl = FD->getFriendDecl();
1041 const auto *FriendTypeInfo = FD->getFriendType();
1042 if (!FriendTypeInfo)
1044 ActualDecl = FriendTypeInfo->getType()->getAsCXXRecordDecl();
1051 if (
const auto *ActualTD = dyn_cast_or_null<TemplateDecl>(ActualDecl)) {
1052 if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
1054 F.Template.emplace();
1055 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1056 for (
const auto *Param : ActualTD->getTemplateParameters()->asArray())
1057 LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
1058 if (!LocalParams.empty())
1059 F.Template->Params =
1061 ActualDecl = ActualTD->getTemplatedDecl();
1064 if (
auto *
FuncDecl = dyn_cast_or_null<FunctionDecl>(ActualDecl)) {
1065 FunctionInfo TempInfo;
1066 parseParameters(TempInfo,
FuncDecl);
1068 F.ReturnType = getTypeInfoForType(
FuncDecl->getReturnType(),
1073 Reference(getUSRForDecl(ActualDecl), ActualDecl->getNameAsString(),
1075 getInfoRelativePath(ActualDecl));
1077 populateMemberTypeInfo(F, ActualDecl);
1078 LocalFriends.push_back(std::move(F));
1080 if (!LocalFriends.empty())
1089 bool IsInAnonymousNamespace =
false;
1091 populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
1092 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1095 RI->
TagType = D->getTagKind();
1098 if (
const auto *C = dyn_cast<CXXRecordDecl>(D)) {
1099 if (
const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
1105 llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
1108 if (!LocalBases.empty())
1110 parseFriends(*RI, C);
1114 populateTemplateParameters(RI->
Template, D);
1116 populateConstraints(RI->
Template.value(), D->getDescribedTemplate());
1119 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1122 RI->
Template->Specialization.emplace();
1123 auto &Specialization = *RI->
Template->Specialization;
1126 auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
1127 if (
auto *SpecTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
1128 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1129 else if (
auto *SpecTD =
1130 dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
1131 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1138 if (
const ClassTemplatePartialSpecializationDecl *CTPSD =
1139 dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
1140 if (
const ASTTemplateArgumentListInfo *AsWritten =
1141 CTPSD->getTemplateArgsAsWritten()) {
1142 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1143 for (
unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
1144 LocalParams.emplace_back(
1145 getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
1147 if (!LocalParams.empty())
1148 Specialization.Params =
1152 llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
1153 for (
const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
1154 LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
1156 if (!LocalParams.empty())
1157 Specialization.Params =
1164 auto Parent = makeAndInsertIntoParent<const RecordInfo &>(*RI);
1165 return {std::move(RI), std::move(Parent)};
1172 bool IsInAnonymousNamespace =
false;
1173 populateFunctionInfo(*Func, D, FC, Loc, IsInAnonymousNamespace);
1174 Func->
Access = clang::AccessSpecifier::AS_none;
1175 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1179 return {
nullptr, makeAndInsertIntoParent(*Func)};
1186 bool IsInAnonymousNamespace =
false;
1187 populateFunctionInfo(*Func, D, FC, Loc, IsInAnonymousNamespace);
1188 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1194 const NamedDecl *Parent =
nullptr;
1195 if (
const auto *SD =
1196 dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
1197 Parent = SD->getSpecializedTemplate();
1199 Parent = D->getParent();
1201 SymbolID ParentUSR = getUSRForDecl(Parent);
1204 Parent->getQualifiedNameAsString()};
1205 Func->
Access = D->getAccess();
1208 return {
nullptr, makeAndInsertIntoParent(*Func)};
1211void Serializer::extractCommentFromDecl(
const Decl *D,
TypedefInfo &
Info) {
1212 assert(D &&
"Invalid Decl when extracting comment");
1213 ASTContext &
Context = D->getASTContext();
1214 RawComment *Comment =
Context.getRawCommentForDeclNoCache(D);
1218 Comment->setAttached();
1219 if (comments::FullComment *Fc = Comment->parse(
Context,
nullptr, D)) {
1222 parseFullComment(Fc, *NewCI->Ptr);
1230 bool IsInAnonymousNamespace =
false;
1231 populateInfo(*
Info, D, FC, IsInAnonymousNamespace);
1233 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1237 auto &LO = D->getLangOpts();
1238 Info->Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1239 populateTemplateParameters(
Info->Template, D);
1241 populateConstraints(
Info->Template.value(), D->getDescribedTemplate());
1243 if (
Info->Underlying.Type.
Name.empty()) {
1249 Info->IsUsing =
false;
1250 extractCommentFromDecl(D, *
Info);
1253 return {
nullptr, makeAndInsertIntoParent(*
Info)};
1262 bool IsInAnonymousNamespace =
false;
1263 populateInfo(*
Info, D, FC, IsInAnonymousNamespace);
1264 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1268 const LangOptions &LO = D->getLangOpts();
1269 Info->Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1270 Info->TypeDeclaration = getTypeAlias(D);
1271 Info->IsUsing =
true;
1272 populateTemplateParameters(
Info->Template, D);
1274 populateConstraints(
Info->Template.value(), D->getDescribedAliasTemplate());
1276 extractCommentFromDecl(D, *
Info);
1279 return {
nullptr, makeAndInsertIntoParent(*
Info)};
1286 bool IsInAnonymousNamespace =
false;
1287 populateSymbolInfo(*Enum, D, FC, Loc, IsInAnonymousNamespace);
1289 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1292 Enum->Scoped = D->isScoped();
1293 if (
const TypeSourceInfo *TSI = D->getIntegerTypeSourceInfo()) {
1294 auto Name = TSI->getType().getAsString();
1295 Enum->BaseType =
TypeInfo(Name, Name);
1297 parseEnumerators(*Enum, D);
1300 return {
nullptr, makeAndInsertIntoParent(*Enum)};
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)};
1334 bool IsInAnonymousNamespace =
false;
1335 populateSymbolInfo(*Var, D, FC, Loc, IsInAnonymousNamespace);
1336 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1339 if (D->getStorageClass() == StorageClass::SC_Static)
1342 getTypeInfoForType(D->getType(), D->getASTContext().getPrintingPolicy());
1344 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1347 return {
nullptr, makeAndInsertIntoParent(*Var)};