30static SmallString<16> 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();
90Serializer::getFunctionPrototype(
const FunctionDecl *
FuncDecl) {
91 llvm::SmallString<256> Result;
92 llvm::raw_svector_ostream Stream(Result);
93 const ASTContext &Ctx =
FuncDecl->getASTContext();
96 if (
const auto *TmplDecl =
FuncDecl->getDescribedTemplate())
97 getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
100 if (Method &&
Method->isVirtual())
101 Stream <<
"virtual ";
104 FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy());
107 Stream <<
" " <<
FuncDecl->getNameAsString() <<
"(";
110 for (
unsigned I = 0; I <
FuncDecl->getNumParams(); ++I) {
113 const ParmVarDecl *ParamDecl =
FuncDecl->getParamDecl(I);
114 QualType ParamType = ParamDecl->getType();
115 ParamType.print(Stream, Ctx.getPrintingPolicy());
118 if (!ParamDecl->getName().empty())
119 Stream <<
" " << ParamDecl->getNameAsString();
122 if (ParamDecl->hasDefaultArg() &&
123 !ParamDecl->hasUninstantiatedDefaultArg()) {
124 if (
const Expr *DefaultArg = ParamDecl->getDefaultArg()) {
126 DefaultArg->printPretty(Stream,
nullptr, Ctx.getPrintingPolicy());
143 Stream <<
" = delete";
144 if (
Method->size_overridden_methods())
145 Stream <<
" override";
146 if (
Method->hasAttr<clang::FinalAttr>())
150 if (
Method->isPureVirtual())
154 if (
auto ExceptionSpecType =
FuncDecl->getExceptionSpecType())
155 Stream <<
" " << ExceptionSpecType;
160llvm::SmallString<16> Serializer::getTypeAlias(
const TypeAliasDecl *Alias) {
161 llvm::SmallString<16> Result;
162 llvm::raw_svector_ostream Stream(Result);
163 const ASTContext &Ctx =
Alias->getASTContext();
164 if (
const auto *TmplDecl =
Alias->getDescribedTemplate())
165 getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
166 Stream <<
"using " <<
Alias->getNameAsString() <<
" = ";
167 QualType Q =
Alias->getUnderlyingType();
168 Q.print(Stream, Ctx.getPrintingPolicy());
186llvm::SmallString<128> Serializer::getInfoRelativePath(
187 const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
188 llvm::SmallString<128>
Path;
189 for (
auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
190 llvm::sys::path::append(Path, R->Name);
194llvm::SmallString<128> Serializer::getInfoRelativePath(
const Decl *D) {
195 llvm::SmallVector<Reference, 4> Namespaces;
200 populateParentNamespaces(Namespaces, D, B);
201 return getInfoRelativePath(Namespaces);
223 std::string getCommandName(
unsigned CommandID)
const;
224 bool isWhitespaceOnly(StringRef S)
const;
232 for (comments::Comment *Child :
233 llvm::make_range(C->child_begin(), C->child_end())) {
241 if (!isWhitespaceOnly(C->getText()))
242 CurrentCI.Text = C->getText().trim();
246 const InlineCommandComment *C) {
247 CurrentCI.Name = getCommandName(C->getCommandID());
248 for (
unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
249 CurrentCI.Args.push_back(C->getArgText(I).trim());
253 const HTMLStartTagComment *C) {
254 CurrentCI.Name = C->getTagName();
255 CurrentCI.SelfClosing = C->isSelfClosing();
256 for (
unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
257 const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
258 CurrentCI.AttrKeys.push_back(Attr.Name);
259 CurrentCI.AttrValues.push_back(Attr.Value);
264 const HTMLEndTagComment *C) {
265 CurrentCI.Name = C->getTagName();
266 CurrentCI.SelfClosing =
true;
270 const BlockCommandComment *C) {
271 CurrentCI.Name = getCommandName(C->getCommandID());
272 for (
unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
273 CurrentCI.Args.push_back(C->getArgText(I).trim());
277 const ParamCommandComment *C) {
278 CurrentCI.Direction =
279 ParamCommandComment::getDirectionAsString(C->getDirection());
280 CurrentCI.Explicit = C->isDirectionExplicit();
281 if (C->hasParamName())
282 CurrentCI.ParamName = C->getParamNameAsWritten();
286 const TParamCommandComment *C) {
287 if (C->hasParamName())
288 CurrentCI.ParamName = C->getParamNameAsWritten();
292 const VerbatimBlockComment *C) {
293 CurrentCI.Name = getCommandName(C->getCommandID());
294 CurrentCI.CloseName = C->getCloseName();
298 const VerbatimBlockLineComment *C) {
299 if (!isWhitespaceOnly(C->getText()))
300 CurrentCI.Text = C->getText();
304 const VerbatimLineComment *C) {
305 if (!isWhitespaceOnly(C->getText()))
306 CurrentCI.Text = C->getText();
309bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S)
const {
310 return llvm::all_of(S, isspace);
313std::string ClangDocCommentVisitor::getCommandName(
unsigned CommandID)
const {
314 const CommandInfo *
Info = CommandTraits::getBuiltinCommandInfo(CommandID);
318 return "<not a builtin command>";
323std::string Serializer::getSourceCode(
const Decl *D,
const SourceRange &R) {
324 return Lexer::getSourceText(CharSourceRange::getTokenRange(R),
325 D->getASTContext().getSourceManager(),
326 D->getASTContext().getLangOpts())
331static std::string
serialize(T &I, DiagnosticsEngine &Diags) {
332 SmallString<2048> Buffer;
333 llvm::BitstreamWriter Stream(Buffer);
336 return Buffer.str().str();
358 llvm_unreachable(
"unhandled enumerator");
361void Serializer::parseFullComment(
const FullComment *C,
CommentInfo &CI) {
362 ClangDocCommentVisitor Visitor(CI);
363 Visitor.parseComment(C);
366SymbolID Serializer::getUSRForDecl(
const Decl *D) {
367 llvm::SmallString<128> USR;
368 if (index::generateUSRForDecl(D, USR))
373TagDecl *Serializer::getTagDeclForType(
const QualType &T) {
374 if (
const TagDecl *D = T->getAsTagDecl())
375 return D->getDefinition();
379RecordDecl *Serializer::getRecordDeclForType(
const QualType &T) {
380 if (
const RecordDecl *D =
T->getAsRecordDecl())
381 return D->getDefinition();
385TypeInfo Serializer::getTypeInfoForType(
const QualType &T,
386 const PrintingPolicy &Policy) {
387 const TagDecl *TD = getTagDeclForType(T);
389 TypeInfo TI = TypeInfo(Reference(
SymbolID(),
T.getAsString(Policy)));
390 TI.IsBuiltIn =
T->isBuiltinType();
391 TI.IsTemplate =
T->isTemplateTypeParmType();
395 if (isa<EnumDecl>(TD)) {
397 }
else if (isa<RecordDecl>(TD)) {
402 Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
403 T.getAsString(Policy), getInfoRelativePath(TD));
404 TypeInfo TI = TypeInfo(R);
405 TI.IsBuiltIn =
T->isBuiltinType();
406 TI.IsTemplate =
T->isTemplateTypeParmType();
410bool Serializer::isPublic(
const clang::AccessSpecifier AS,
411 const clang::Linkage Link) {
412 if (AS == clang::AccessSpecifier::AS_private)
414 if ((Link == clang::Linkage::Module) || (Link == clang::Linkage::External))
419bool Serializer::shouldSerializeInfo(
bool PublicOnly,
420 bool IsInAnonymousNamespace,
421 const NamedDecl *D) {
422 bool IsAnonymousNamespace =
false;
423 if (
const auto *N = dyn_cast<NamespaceDecl>(D))
424 IsAnonymousNamespace = N->isAnonymousNamespace();
426 (!IsInAnonymousNamespace && !IsAnonymousNamespace &&
427 isPublic(
D->getAccessUnsafe(),
D->getLinkageInternal()));
436void Serializer::InsertChild(ScopeChildren &Scope,
const NamespaceInfo &Info) {
438 Info.Name, getInfoRelativePath(
Info.Namespace));
441void Serializer::InsertChild(ScopeChildren &Scope,
const RecordInfo &Info) {
443 Info.Name, getInfoRelativePath(
Info.Namespace),
447void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo Info) {
448 Scope.Enums.push_back(std::move(Info));
451void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo Info) {
452 Scope.Functions.push_back(std::move(Info));
455void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo Info) {
456 Scope.Typedefs.push_back(std::move(Info));
459void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo Info) {
460 Scope.Concepts.push_back(std::move(Info));
463void Serializer::InsertChild(ScopeChildren &Scope, VarInfo Info) {
464 Scope.Variables.push_back(std::move(Info));
481template <
typename ChildType>
482OwnedPtr<Info> Serializer::makeAndInsertIntoParent(ChildType Child) {
483 if (Child.Namespace.empty()) {
486 InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
490 switch (Child.Namespace[0].RefType) {
493 ParentNS->USR = Child.Namespace[0].USR;
494 InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
499 ParentRec->USR = Child.Namespace[0].USR;
500 InsertChild(ParentRec->Children, std::forward<ChildType>(Child));
512 llvm_unreachable(
"Invalid reference type for parent namespace");
530AccessSpecifier Serializer::getFinalAccessSpecifier(AccessSpecifier FirstAS,
531 AccessSpecifier SecondAS) {
532 if (FirstAS == AccessSpecifier::AS_none ||
533 SecondAS == AccessSpecifier::AS_none)
534 return AccessSpecifier::AS_none;
535 if (FirstAS == AccessSpecifier::AS_private ||
536 SecondAS == AccessSpecifier::AS_private)
537 return AccessSpecifier::AS_private;
538 if (FirstAS == AccessSpecifier::AS_protected ||
539 SecondAS == AccessSpecifier::AS_protected)
540 return AccessSpecifier::AS_protected;
541 return AccessSpecifier::AS_public;
546void Serializer::parseFields(RecordInfo &I,
const RecordDecl *D,
548 for (
const FieldDecl *F :
D->fields()) {
549 if (!shouldSerializeInfo(
PublicOnly,
false, F))
551 populateMemberTypeInfo(I, Access, F);
553 const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
556 for (Decl *CxxDecl : CxxRD->decls()) {
557 auto *VD = dyn_cast<VarDecl>(CxxDecl);
562 if (VD->isStaticDataMember())
563 populateMemberTypeInfo(I, Access, VD,
true);
567void Serializer::parseEnumerators(EnumInfo &I,
const EnumDecl *D) {
568 for (
const EnumConstantDecl *E :
D->enumerators()) {
569 std::string ValueExpr;
570 if (
const Expr *InitExpr = E->getInitExpr())
571 ValueExpr = getSourceCode(D, InitExpr->getSourceRange());
572 SmallString<16> ValueStr;
573 E->getInitVal().toString(ValueStr);
574 I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr);
575 ASTContext &Context = E->getASTContext();
576 if (RawComment *Comment =
577 E->getASTContext().getRawCommentForDeclNoCache(E)) {
578 Comment->setAttached();
579 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, E)) {
580 EnumValueInfo &Member = I.Members.back();
581 Member.Description.emplace_back();
582 parseFullComment(Fc, Member.Description.back());
588void Serializer::parseParameters(FunctionInfo &I,
const FunctionDecl *D) {
589 auto &LO =
D->getLangOpts();
590 for (
const ParmVarDecl *P :
D->parameters()) {
591 FieldTypeInfo &FieldInfo = I.Params.emplace_back(
592 getTypeInfoForType(
P->getOriginalType(), LO),
P->getNameAsString());
593 FieldInfo.DefaultValue = getSourceCode(D,
P->getDefaultArgRange());
599void Serializer::parseBases(RecordInfo &I,
const CXXRecordDecl *D) {
601 if (!
D->isThisDeclarationADefinition())
604 for (
const CXXBaseSpecifier &B :
D->bases()) {
607 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
608 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
609 I.Parents.emplace_back(getUSRForDecl(D),
B.getType().getAsString(),
611 }
else if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
612 I.Parents.emplace_back(getUSRForDecl(P),
P->getNameAsString(),
614 getInfoRelativePath(P));
616 I.Parents.emplace_back(
SymbolID(),
B.getType().getAsString());
618 for (
const CXXBaseSpecifier &B :
D->vbases()) {
619 if (
const RecordDecl *P = getRecordDeclForType(
B.getType()))
620 I.VirtualParents.emplace_back(
622 P->getQualifiedNameAsString(), getInfoRelativePath(P));
624 I.VirtualParents.emplace_back(
SymbolID(),
B.getType().getAsString());
629void Serializer::populateParentNamespaces(
630 llvm::SmallVector<Reference, 4> &Namespaces,
const T *D,
631 bool &IsInAnonymousNamespace) {
632 const DeclContext *DC =
D->getDeclContext();
634 if (
const auto *N = dyn_cast<NamespaceDecl>(DC)) {
636 if (N->isAnonymousNamespace()) {
638 IsInAnonymousNamespace =
true;
641 Namespaces.emplace_back(getUSRForDecl(N), Namespace,
643 N->getQualifiedNameAsString());
644 }
else if (
const auto *N = dyn_cast<RecordDecl>(DC))
645 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
647 N->getQualifiedNameAsString());
648 else if (
const auto *N = dyn_cast<FunctionDecl>(DC))
649 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
651 N->getQualifiedNameAsString());
652 else if (
const auto *N = dyn_cast<EnumDecl>(DC))
653 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
655 }
while ((DC = DC->getParent()));
660 if ((Namespaces.empty() && isa<RecordDecl>(D)) ||
662 Namespaces.emplace_back(
SymbolID(),
"GlobalNamespace",
666void Serializer::populateTemplateParameters(
667 std::optional<TemplateInfo> &TemplateInfo,
const clang::Decl *D) {
668 if (
const TemplateParameterList *ParamList =
669 D->getDescribedTemplateParams()) {
671 TemplateInfo.emplace();
673 for (
const NamedDecl *ND : *ParamList) {
674 TemplateInfo->Params.emplace_back(
675 getSourceCode(ND, ND->getSourceRange()));
681Serializer::convertTemplateArgToInfo(
const clang::Decl *D,
682 const TemplateArgument &Arg) {
686 llvm::raw_string_ostream Stream(Str);
687 Arg.print(PrintingPolicy(
D->getLangOpts()), Stream,
false);
688 return TemplateParamInfo(Str);
694bool Serializer::isSupportedContext(Decl::Kind DeclKind) {
696 case Decl::Kind::Record:
697 case Decl::Kind::CXXRecord:
698 case Decl::Kind::ClassTemplateSpecialization:
699 case Decl::Kind::ClassTemplatePartialSpecialization:
700 case Decl::Kind::Namespace:
707void Serializer::findParent(Info &I,
const Decl *D) {
708 assert(D &&
"Invalid Decl");
711 if (!isSupportedContext(
D->getKind()))
714 const DeclContext *ParentCtx = dyn_cast<DeclContext>(D)->getLexicalParent();
716 if (isSupportedContext(ParentCtx->getDeclKind())) {
718 I.ParentUSR = getUSRForDecl(dyn_cast<Decl>(ParentCtx));
721 ParentCtx = ParentCtx->getParent();
726void Serializer::populateInfo(Info &I,
const T *D,
const FullComment *C,
727 bool &IsInAnonymousNamespace) {
728 I.USR = getUSRForDecl(D);
731 if (
auto ConversionDecl = dyn_cast_or_null<CXXConversionDecl>(D);
732 ConversionDecl && ConversionDecl->getConversionType()
734 ->isTemplateTypeParmType())
735 I.Name =
"operator " + ConversionDecl->getConversionType().getAsString();
737 I.Name =
D->getNameAsString();
738 populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
740 I.Description.emplace_back();
741 parseFullComment(C, I.Description.back());
746void Serializer::populateSymbolInfo(
SymbolInfo &I,
const T *D,
747 const FullComment *C, Location Loc,
748 bool &IsInAnonymousNamespace) {
749 populateInfo(I, D, C, IsInAnonymousNamespace);
750 if (
D->isThisDeclarationADefinition())
753 I.Loc.emplace_back(Loc);
755 auto *Mangler = ItaniumMangleContext::create(
756 D->getASTContext(),
D->getASTContext().getDiagnostics());
757 std::string MangledName;
758 llvm::raw_string_ostream MangledStream(MangledName);
759 if (
auto *CXXD = dyn_cast<CXXRecordDecl>(D))
760 Mangler->mangleCXXVTable(CXXD, MangledStream);
762 MangledStream <<
D->getNameAsString();
765 if (MangledName.size() > 250) {
766 auto SymbolID = llvm::toStringRef(llvm::toHex(I.USR)).str();
769 I.MangledName = MangledName;
773void Serializer::handleCompoundConstraints(
775 if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
776 handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
778 }
else if (Constraint->getStmtClass() == Stmt::BinaryOperatorClass) {
779 auto *BinaryOpExpr = dyn_cast<BinaryOperator>(Constraint);
780 handleCompoundConstraints(BinaryOpExpr->getLHS(), ConstraintInfos);
781 handleCompoundConstraints(BinaryOpExpr->getRHS(), ConstraintInfos);
782 }
else if (Constraint->getStmtClass() ==
783 Stmt::ConceptSpecializationExprClass) {
784 auto *
Concept = dyn_cast<ConceptSpecializationExpr>(Constraint);
785 ConstraintInfo CI(getUSRForDecl(
Concept->getNamedConcept()),
786 Concept->getNamedConcept()->getNameAsString());
787 CI.ConstraintExpr = exprToString(Concept);
788 ConstraintInfos.push_back(CI);
792void Serializer::populateConstraints(TemplateInfo &I,
const TemplateDecl *D) {
793 if (!D || !
D->hasAssociatedConstraints())
796 SmallVector<AssociatedConstraint> AssociatedConstraints;
797 D->getAssociatedConstraints(AssociatedConstraints);
798 for (
const auto &Constraint : AssociatedConstraints) {
803 if (
const auto *ConstraintExpr =
804 dyn_cast_or_null<ConceptSpecializationExpr>(
805 Constraint.ConstraintExpr)) {
806 ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
807 ConstraintExpr->getNamedConcept()->getNameAsString());
808 CI.ConstraintExpr = exprToString(ConstraintExpr);
809 I.Constraints.push_back(std::move(CI));
811 handleCompoundConstraints(Constraint.ConstraintExpr, I.Constraints);
816void Serializer::populateFunctionInfo(FunctionInfo &I,
const FunctionDecl *D,
817 const FullComment *FC, Location Loc,
818 bool &IsInAnonymousNamespace) {
819 populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
820 auto &LO =
D->getLangOpts();
821 I.ReturnType = getTypeInfoForType(
D->getReturnType(), LO);
822 I.Prototype = getFunctionPrototype(D);
823 parseParameters(I, D);
824 I.IsStatic =
D->isStatic();
826 populateTemplateParameters(I.Template, D);
828 populateConstraints(I.Template.value(),
D->getDescribedFunctionTemplate());
831 if (
const FunctionTemplateSpecializationInfo *FTSI =
832 D->getTemplateSpecializationInfo()) {
834 I.Template.emplace();
835 I.Template->Specialization.emplace();
836 auto &Specialization = *I.Template->Specialization;
838 Specialization.SpecializationOf = getUSRForDecl(FTSI->getTemplate());
841 if (FTSI->TemplateArguments) {
842 for (
const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
843 Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
852void Serializer::populateMemberTypeInfo(T &I,
const Decl *D) {
853 assert(D &&
"Expect non-null FieldDecl in populateMemberTypeInfo");
855 ASTContext &Context =
D->getASTContext();
858 RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
862 Comment->setAttached();
863 if (comments::FullComment *Fc = Comment->parse(Context,
nullptr, D)) {
864 I.Description.emplace_back();
865 parseFullComment(Fc, I.Description.back());
869void Serializer::populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
870 const DeclaratorDecl *D,
874 MemberTypeInfo &NewMember = I.Members.emplace_back(
875 getTypeInfoForType(
D->getTypeSourceInfo()->getType(),
D->getLangOpts()),
876 D->getNameAsString(),
877 getFinalAccessSpecifier(Access,
D->getAccessUnsafe()), IsStatic);
878 populateMemberTypeInfo(NewMember, D);
881void Serializer::parseBases(RecordInfo &I,
const CXXRecordDecl *D,
883 bool IsParent, AccessSpecifier ParentAccess) {
885 if (!
D->isThisDeclarationADefinition())
887 for (
const CXXBaseSpecifier &B :
D->bases()) {
888 if (
const auto *Base =
B.getType()->getAsCXXRecordDecl()) {
889 if (Base->isCompleteDefinition()) {
893 {},
"", getInfoRelativePath(Base),
B.isVirtual(),
894 getFinalAccessSpecifier(ParentAccess,
B.getAccessSpecifier()),
896 if (
const auto *Ty =
B.getType()->getAs<TemplateSpecializationType>()) {
897 const TemplateDecl *
D = Ty->getTemplateName().getAsTemplateDecl();
898 BI.USR = getUSRForDecl(D);
899 BI.Name =
B.getType().getAsString();
901 BI.USR = getUSRForDecl(Base);
902 BI.Name = Base->getNameAsString();
905 for (
const auto &Decl : Base->decls())
906 if (
const auto *
MD = dyn_cast<CXXMethodDecl>(Decl)) {
908 if (
MD->getAccessUnsafe() == AccessSpecifier::AS_private ||
909 !
MD->isUserProvided())
913 FI.IsStatic =
MD->isStatic();
917 bool IsInAnonymousNamespace;
918 populateFunctionInfo(FI,
MD, {}, {},
919 IsInAnonymousNamespace);
921 getFinalAccessSpecifier(BI.Access,
MD->getAccessUnsafe());
922 BI.Children.Functions.emplace_back(std::move(FI));
924 I.Bases.emplace_back(std::move(BI));
928 parseBases(I, Base, IsFileInRootDir,
PublicOnly,
false,
929 I.Bases.back().Access);
939 bool IsInAnonymousNamespace =
false;
940 populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
941 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
944 NSI->Name = D->isAnonymousNamespace()
945 ? llvm::SmallString<16>(
"@nonymous_namespace")
947 NSI->Path = getInfoRelativePath(NSI->Namespace);
948 if (NSI->Namespace.empty() && NSI->USR ==
SymbolID())
953 return {std::move(NSI), makeAndInsertIntoParent<const NamespaceInfo &>(*NSI)};
956void Serializer::parseFriends(
RecordInfo &RI,
const CXXRecordDecl *D) {
957 if (!D->hasDefinition() || !D->hasFriends())
960 for (
const FriendDecl *FD : D->friends()) {
961 if (FD->isUnsupportedFriend())
965 const auto *ActualDecl = FD->getFriendDecl();
967 const auto *FriendTypeInfo = FD->getFriendType();
970 ActualDecl = FriendTypeInfo->getType()->getAsCXXRecordDecl();
977 if (
const auto *ActualTD = dyn_cast_or_null<TemplateDecl>(ActualDecl)) {
978 if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
980 F.Template.emplace();
981 for (
const auto *Param : ActualTD->getTemplateParameters()->asArray())
982 F.Template->Params.emplace_back(
983 getSourceCode(Param, Param->getSourceRange()));
984 ActualDecl = ActualTD->getTemplatedDecl();
987 if (
auto *
FuncDecl = dyn_cast_or_null<FunctionDecl>(ActualDecl)) {
988 FunctionInfo TempInfo;
989 parseParameters(TempInfo,
FuncDecl);
991 F.Params = std::move(TempInfo.Params);
992 F.ReturnType = getTypeInfoForType(
FuncDecl->getReturnType(),
997 Reference(getUSRForDecl(ActualDecl), ActualDecl->getNameAsString(),
999 getInfoRelativePath(ActualDecl));
1001 populateMemberTypeInfo(F, ActualDecl);
1002 RI.
Friends.push_back(std::move(F));
1011 bool IsInAnonymousNamespace =
false;
1013 populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
1014 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1017 RI->
TagType = D->getTagKind();
1020 if (
const auto *C = dyn_cast<CXXRecordDecl>(D)) {
1021 if (
const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
1022 RI->
Name = TD->getNameAsString();
1028 parseFriends(*RI, C);
1032 populateTemplateParameters(RI->
Template, D);
1034 populateConstraints(RI->
Template.value(), D->getDescribedTemplate());
1037 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1040 RI->
Template->Specialization.emplace();
1041 auto &Specialization = *RI->
Template->Specialization;
1044 auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
1045 if (
auto *SpecTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
1046 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1047 else if (
auto *SpecTD =
1048 dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
1049 Specialization.SpecializationOf = getUSRForDecl(SpecTD);
1056 if (
const ClassTemplatePartialSpecializationDecl *CTPSD =
1057 dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
1058 if (
const ASTTemplateArgumentListInfo *AsWritten =
1059 CTPSD->getTemplateArgsAsWritten()) {
1060 for (
unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
1061 Specialization.Params.emplace_back(
1062 getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
1066 for (
const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
1067 Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
1074 auto Parent = makeAndInsertIntoParent<const RecordInfo &>(*RI);
1075 return {std::move(RI), std::move(Parent)};
1082 bool IsInAnonymousNamespace =
false;
1083 populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
1084 Func.
Access = clang::AccessSpecifier::AS_none;
1085 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1089 return {
nullptr, makeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
1096 bool IsInAnonymousNamespace =
false;
1097 populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
1098 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1104 const NamedDecl *Parent =
nullptr;
1105 if (
const auto *SD =
1106 dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
1107 Parent = SD->getSpecializedTemplate();
1109 Parent = D->getParent();
1111 SymbolID ParentUSR = getUSRForDecl(Parent);
1114 Parent->getQualifiedNameAsString()};
1115 Func.
Access = D->getAccess();
1118 return {
nullptr, makeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
1121void Serializer::extractCommentFromDecl(
const Decl *D,
TypedefInfo &
Info) {
1122 assert(D &&
"Invalid Decl when extracting comment");
1123 ASTContext &
Context = D->getASTContext();
1124 RawComment *Comment =
Context.getRawCommentForDeclNoCache(D);
1128 Comment->setAttached();
1129 if (comments::FullComment *Fc = Comment->parse(
Context,
nullptr, D)) {
1139 bool IsInAnonymousNamespace =
false;
1140 populateInfo(
Info, D, FC, IsInAnonymousNamespace);
1142 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1146 auto &LO = D->getLangOpts();
1147 Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1148 populateTemplateParameters(
Info.Template, D);
1150 populateConstraints(
Info.Template.value(), D->getDescribedTemplate());
1152 if (
Info.Underlying.Type.
Name.empty()) {
1158 Info.IsUsing =
false;
1159 extractCommentFromDecl(D,
Info);
1162 return {
nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(
Info))};
1171 bool IsInAnonymousNamespace =
false;
1172 populateInfo(
Info, D, FC, IsInAnonymousNamespace);
1173 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1177 const LangOptions &LO = D->getLangOpts();
1178 Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1179 Info.TypeDeclaration = getTypeAlias(D);
1180 Info.IsUsing =
true;
1181 populateTemplateParameters(
Info.Template, D);
1183 populateConstraints(
Info.Template.value(), D->getDescribedAliasTemplate());
1185 extractCommentFromDecl(D,
Info);
1188 return {
nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(
Info))};
1195 bool IsInAnonymousNamespace =
false;
1196 populateSymbolInfo(Enum, D, FC, Loc, IsInAnonymousNamespace);
1198 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1201 Enum.Scoped = D->isScoped();
1202 if (
const TypeSourceInfo *TSI = D->getIntegerTypeSourceInfo()) {
1203 auto Name = TSI->getType().getAsString();
1204 Enum.BaseType =
TypeInfo(Name, Name);
1206 parseEnumerators(Enum, D);
1209 return {
nullptr, makeAndInsertIntoParent<EnumInfo &&>(std::move(Enum))};
1217 bool IsInAnonymousNamespace =
false;
1218 populateInfo(Concept, D, FC, IsInAnonymousNamespace);
1219 Concept.IsType = D->isTypeConcept();
1220 Concept.DefLoc = Loc;
1221 Concept.ConstraintExpression = exprToString(D->getConstraintExpr());
1223 if (
auto *ConceptParams = D->getTemplateParameters()) {
1224 for (
const auto *Param : ConceptParams->asArray()) {
1225 Concept.Template.Params.emplace_back(
1226 getSourceCode(Param, Param->getSourceRange()));
1230 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1233 return {
nullptr, makeAndInsertIntoParent<ConceptInfo &&>(std::move(Concept))};
1240 bool IsInAnonymousNamespace =
false;
1241 populateSymbolInfo(Var, D, FC, Loc, IsInAnonymousNamespace);
1242 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1245 if (D->getStorageClass() == StorageClass::SC_Static)
1248 getTypeInfoForType(D->getType(), D->getASTContext().getPrintingPolicy());
1250 if (!shouldSerializeInfo(
PublicOnly, IsInAnonymousNamespace, D))
1253 return {
nullptr, makeAndInsertIntoParent<VarInfo &&>(std::move(Var))};