annotate clang-tools-extra/clang-doc/Serialize.cpp @ 180:680fa57a2f20

fix compile errors.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 30 May 2020 17:44:06 +0900
parents 0572611fdcc8
children c4bab56944e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===-- Serialize.cpp - ClangDoc Serializer ---------------------*- C++ -*-===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include "Serialize.h"
anatofuz
parents:
diff changeset
10 #include "BitcodeWriter.h"
anatofuz
parents:
diff changeset
11 #include "clang/AST/Comment.h"
anatofuz
parents:
diff changeset
12 #include "clang/Index/USRGeneration.h"
anatofuz
parents:
diff changeset
13 #include "llvm/ADT/Hashing.h"
anatofuz
parents:
diff changeset
14 #include "llvm/ADT/StringExtras.h"
anatofuz
parents:
diff changeset
15 #include "llvm/Support/SHA1.h"
anatofuz
parents:
diff changeset
16
anatofuz
parents:
diff changeset
17 using clang::comments::FullComment;
anatofuz
parents:
diff changeset
18
anatofuz
parents:
diff changeset
19 namespace clang {
anatofuz
parents:
diff changeset
20 namespace doc {
anatofuz
parents:
diff changeset
21 namespace serialize {
anatofuz
parents:
diff changeset
22
anatofuz
parents:
diff changeset
23 SymbolID hashUSR(llvm::StringRef USR) {
anatofuz
parents:
diff changeset
24 return llvm::SHA1::hash(arrayRefFromStringRef(USR));
anatofuz
parents:
diff changeset
25 }
anatofuz
parents:
diff changeset
26
anatofuz
parents:
diff changeset
27 template <typename T>
anatofuz
parents:
diff changeset
28 static void
anatofuz
parents:
diff changeset
29 populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
anatofuz
parents:
diff changeset
30 const T *D, bool &IsAnonymousNamespace);
anatofuz
parents:
diff changeset
31
anatofuz
parents:
diff changeset
32 // A function to extract the appropriate relative path for a given info's
anatofuz
parents:
diff changeset
33 // documentation. The path returned is a composite of the parent namespaces.
anatofuz
parents:
diff changeset
34 //
anatofuz
parents:
diff changeset
35 // Example: Given the below, the directory path for class C info will be
anatofuz
parents:
diff changeset
36 // <root>/A/B
anatofuz
parents:
diff changeset
37 //
anatofuz
parents:
diff changeset
38 // namespace A {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
39 // namespace B {
150
anatofuz
parents:
diff changeset
40 //
anatofuz
parents:
diff changeset
41 // class C {};
anatofuz
parents:
diff changeset
42 //
anatofuz
parents:
diff changeset
43 // }
anatofuz
parents:
diff changeset
44 // }
anatofuz
parents:
diff changeset
45 llvm::SmallString<128>
anatofuz
parents:
diff changeset
46 getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
anatofuz
parents:
diff changeset
47 llvm::SmallString<128> Path;
anatofuz
parents:
diff changeset
48 for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
anatofuz
parents:
diff changeset
49 llvm::sys::path::append(Path, R->Name);
anatofuz
parents:
diff changeset
50 return Path;
anatofuz
parents:
diff changeset
51 }
anatofuz
parents:
diff changeset
52
anatofuz
parents:
diff changeset
53 llvm::SmallString<128> getInfoRelativePath(const Decl *D) {
anatofuz
parents:
diff changeset
54 llvm::SmallVector<Reference, 4> Namespaces;
anatofuz
parents:
diff changeset
55 // The third arg in populateParentNamespaces is a boolean passed by reference,
anatofuz
parents:
diff changeset
56 // its value is not relevant in here so it's not used anywhere besides the
anatofuz
parents:
diff changeset
57 // function call
anatofuz
parents:
diff changeset
58 bool B = true;
anatofuz
parents:
diff changeset
59 populateParentNamespaces(Namespaces, D, B);
anatofuz
parents:
diff changeset
60 return getInfoRelativePath(Namespaces);
anatofuz
parents:
diff changeset
61 }
anatofuz
parents:
diff changeset
62
anatofuz
parents:
diff changeset
63 class ClangDocCommentVisitor
anatofuz
parents:
diff changeset
64 : public ConstCommentVisitor<ClangDocCommentVisitor> {
anatofuz
parents:
diff changeset
65 public:
anatofuz
parents:
diff changeset
66 ClangDocCommentVisitor(CommentInfo &CI) : CurrentCI(CI) {}
anatofuz
parents:
diff changeset
67
anatofuz
parents:
diff changeset
68 void parseComment(const comments::Comment *C);
anatofuz
parents:
diff changeset
69
anatofuz
parents:
diff changeset
70 void visitTextComment(const TextComment *C);
anatofuz
parents:
diff changeset
71 void visitInlineCommandComment(const InlineCommandComment *C);
anatofuz
parents:
diff changeset
72 void visitHTMLStartTagComment(const HTMLStartTagComment *C);
anatofuz
parents:
diff changeset
73 void visitHTMLEndTagComment(const HTMLEndTagComment *C);
anatofuz
parents:
diff changeset
74 void visitBlockCommandComment(const BlockCommandComment *C);
anatofuz
parents:
diff changeset
75 void visitParamCommandComment(const ParamCommandComment *C);
anatofuz
parents:
diff changeset
76 void visitTParamCommandComment(const TParamCommandComment *C);
anatofuz
parents:
diff changeset
77 void visitVerbatimBlockComment(const VerbatimBlockComment *C);
anatofuz
parents:
diff changeset
78 void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
anatofuz
parents:
diff changeset
79 void visitVerbatimLineComment(const VerbatimLineComment *C);
anatofuz
parents:
diff changeset
80
anatofuz
parents:
diff changeset
81 private:
anatofuz
parents:
diff changeset
82 std::string getCommandName(unsigned CommandID) const;
anatofuz
parents:
diff changeset
83 bool isWhitespaceOnly(StringRef S) const;
anatofuz
parents:
diff changeset
84
anatofuz
parents:
diff changeset
85 CommentInfo &CurrentCI;
anatofuz
parents:
diff changeset
86 };
anatofuz
parents:
diff changeset
87
anatofuz
parents:
diff changeset
88 void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
anatofuz
parents:
diff changeset
89 CurrentCI.Kind = C->getCommentKindName();
anatofuz
parents:
diff changeset
90 ConstCommentVisitor<ClangDocCommentVisitor>::visit(C);
anatofuz
parents:
diff changeset
91 for (comments::Comment *Child :
anatofuz
parents:
diff changeset
92 llvm::make_range(C->child_begin(), C->child_end())) {
anatofuz
parents:
diff changeset
93 CurrentCI.Children.emplace_back(std::make_unique<CommentInfo>());
anatofuz
parents:
diff changeset
94 ClangDocCommentVisitor Visitor(*CurrentCI.Children.back());
anatofuz
parents:
diff changeset
95 Visitor.parseComment(Child);
anatofuz
parents:
diff changeset
96 }
anatofuz
parents:
diff changeset
97 }
anatofuz
parents:
diff changeset
98
anatofuz
parents:
diff changeset
99 void ClangDocCommentVisitor::visitTextComment(const TextComment *C) {
anatofuz
parents:
diff changeset
100 if (!isWhitespaceOnly(C->getText()))
anatofuz
parents:
diff changeset
101 CurrentCI.Text = C->getText();
anatofuz
parents:
diff changeset
102 }
anatofuz
parents:
diff changeset
103
anatofuz
parents:
diff changeset
104 void ClangDocCommentVisitor::visitInlineCommandComment(
anatofuz
parents:
diff changeset
105 const InlineCommandComment *C) {
anatofuz
parents:
diff changeset
106 CurrentCI.Name = getCommandName(C->getCommandID());
anatofuz
parents:
diff changeset
107 for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
anatofuz
parents:
diff changeset
108 CurrentCI.Args.push_back(C->getArgText(I));
anatofuz
parents:
diff changeset
109 }
anatofuz
parents:
diff changeset
110
anatofuz
parents:
diff changeset
111 void ClangDocCommentVisitor::visitHTMLStartTagComment(
anatofuz
parents:
diff changeset
112 const HTMLStartTagComment *C) {
anatofuz
parents:
diff changeset
113 CurrentCI.Name = C->getTagName();
anatofuz
parents:
diff changeset
114 CurrentCI.SelfClosing = C->isSelfClosing();
anatofuz
parents:
diff changeset
115 for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
anatofuz
parents:
diff changeset
116 const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
anatofuz
parents:
diff changeset
117 CurrentCI.AttrKeys.push_back(Attr.Name);
anatofuz
parents:
diff changeset
118 CurrentCI.AttrValues.push_back(Attr.Value);
anatofuz
parents:
diff changeset
119 }
anatofuz
parents:
diff changeset
120 }
anatofuz
parents:
diff changeset
121
anatofuz
parents:
diff changeset
122 void ClangDocCommentVisitor::visitHTMLEndTagComment(
anatofuz
parents:
diff changeset
123 const HTMLEndTagComment *C) {
anatofuz
parents:
diff changeset
124 CurrentCI.Name = C->getTagName();
anatofuz
parents:
diff changeset
125 CurrentCI.SelfClosing = true;
anatofuz
parents:
diff changeset
126 }
anatofuz
parents:
diff changeset
127
anatofuz
parents:
diff changeset
128 void ClangDocCommentVisitor::visitBlockCommandComment(
anatofuz
parents:
diff changeset
129 const BlockCommandComment *C) {
anatofuz
parents:
diff changeset
130 CurrentCI.Name = getCommandName(C->getCommandID());
anatofuz
parents:
diff changeset
131 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
anatofuz
parents:
diff changeset
132 CurrentCI.Args.push_back(C->getArgText(I));
anatofuz
parents:
diff changeset
133 }
anatofuz
parents:
diff changeset
134
anatofuz
parents:
diff changeset
135 void ClangDocCommentVisitor::visitParamCommandComment(
anatofuz
parents:
diff changeset
136 const ParamCommandComment *C) {
anatofuz
parents:
diff changeset
137 CurrentCI.Direction =
anatofuz
parents:
diff changeset
138 ParamCommandComment::getDirectionAsString(C->getDirection());
anatofuz
parents:
diff changeset
139 CurrentCI.Explicit = C->isDirectionExplicit();
anatofuz
parents:
diff changeset
140 if (C->hasParamName())
anatofuz
parents:
diff changeset
141 CurrentCI.ParamName = C->getParamNameAsWritten();
anatofuz
parents:
diff changeset
142 }
anatofuz
parents:
diff changeset
143
anatofuz
parents:
diff changeset
144 void ClangDocCommentVisitor::visitTParamCommandComment(
anatofuz
parents:
diff changeset
145 const TParamCommandComment *C) {
anatofuz
parents:
diff changeset
146 if (C->hasParamName())
anatofuz
parents:
diff changeset
147 CurrentCI.ParamName = C->getParamNameAsWritten();
anatofuz
parents:
diff changeset
148 }
anatofuz
parents:
diff changeset
149
anatofuz
parents:
diff changeset
150 void ClangDocCommentVisitor::visitVerbatimBlockComment(
anatofuz
parents:
diff changeset
151 const VerbatimBlockComment *C) {
anatofuz
parents:
diff changeset
152 CurrentCI.Name = getCommandName(C->getCommandID());
anatofuz
parents:
diff changeset
153 CurrentCI.CloseName = C->getCloseName();
anatofuz
parents:
diff changeset
154 }
anatofuz
parents:
diff changeset
155
anatofuz
parents:
diff changeset
156 void ClangDocCommentVisitor::visitVerbatimBlockLineComment(
anatofuz
parents:
diff changeset
157 const VerbatimBlockLineComment *C) {
anatofuz
parents:
diff changeset
158 if (!isWhitespaceOnly(C->getText()))
anatofuz
parents:
diff changeset
159 CurrentCI.Text = C->getText();
anatofuz
parents:
diff changeset
160 }
anatofuz
parents:
diff changeset
161
anatofuz
parents:
diff changeset
162 void ClangDocCommentVisitor::visitVerbatimLineComment(
anatofuz
parents:
diff changeset
163 const VerbatimLineComment *C) {
anatofuz
parents:
diff changeset
164 if (!isWhitespaceOnly(C->getText()))
anatofuz
parents:
diff changeset
165 CurrentCI.Text = C->getText();
anatofuz
parents:
diff changeset
166 }
anatofuz
parents:
diff changeset
167
anatofuz
parents:
diff changeset
168 bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S) const {
anatofuz
parents:
diff changeset
169 return std::all_of(S.begin(), S.end(), isspace);
anatofuz
parents:
diff changeset
170 }
anatofuz
parents:
diff changeset
171
anatofuz
parents:
diff changeset
172 std::string ClangDocCommentVisitor::getCommandName(unsigned CommandID) const {
anatofuz
parents:
diff changeset
173 const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
anatofuz
parents:
diff changeset
174 if (Info)
anatofuz
parents:
diff changeset
175 return Info->Name;
anatofuz
parents:
diff changeset
176 // TODO: Add parsing for \file command.
anatofuz
parents:
diff changeset
177 return "<not a builtin command>";
anatofuz
parents:
diff changeset
178 }
anatofuz
parents:
diff changeset
179
anatofuz
parents:
diff changeset
180 // Serializing functions.
anatofuz
parents:
diff changeset
181
anatofuz
parents:
diff changeset
182 template <typename T> static std::string serialize(T &I) {
anatofuz
parents:
diff changeset
183 SmallString<2048> Buffer;
anatofuz
parents:
diff changeset
184 llvm::BitstreamWriter Stream(Buffer);
anatofuz
parents:
diff changeset
185 ClangDocBitcodeWriter Writer(Stream);
anatofuz
parents:
diff changeset
186 Writer.emitBlock(I);
anatofuz
parents:
diff changeset
187 return Buffer.str().str();
anatofuz
parents:
diff changeset
188 }
anatofuz
parents:
diff changeset
189
anatofuz
parents:
diff changeset
190 std::string serialize(std::unique_ptr<Info> &I) {
anatofuz
parents:
diff changeset
191 switch (I->IT) {
anatofuz
parents:
diff changeset
192 case InfoType::IT_namespace:
anatofuz
parents:
diff changeset
193 return serialize(*static_cast<NamespaceInfo *>(I.get()));
anatofuz
parents:
diff changeset
194 case InfoType::IT_record:
anatofuz
parents:
diff changeset
195 return serialize(*static_cast<RecordInfo *>(I.get()));
anatofuz
parents:
diff changeset
196 case InfoType::IT_enum:
anatofuz
parents:
diff changeset
197 return serialize(*static_cast<EnumInfo *>(I.get()));
anatofuz
parents:
diff changeset
198 case InfoType::IT_function:
anatofuz
parents:
diff changeset
199 return serialize(*static_cast<FunctionInfo *>(I.get()));
anatofuz
parents:
diff changeset
200 default:
anatofuz
parents:
diff changeset
201 return "";
anatofuz
parents:
diff changeset
202 }
anatofuz
parents:
diff changeset
203 }
anatofuz
parents:
diff changeset
204
anatofuz
parents:
diff changeset
205 static void parseFullComment(const FullComment *C, CommentInfo &CI) {
anatofuz
parents:
diff changeset
206 ClangDocCommentVisitor Visitor(CI);
anatofuz
parents:
diff changeset
207 Visitor.parseComment(C);
anatofuz
parents:
diff changeset
208 }
anatofuz
parents:
diff changeset
209
anatofuz
parents:
diff changeset
210 static SymbolID getUSRForDecl(const Decl *D) {
anatofuz
parents:
diff changeset
211 llvm::SmallString<128> USR;
anatofuz
parents:
diff changeset
212 if (index::generateUSRForDecl(D, USR))
anatofuz
parents:
diff changeset
213 return SymbolID();
anatofuz
parents:
diff changeset
214 return hashUSR(USR);
anatofuz
parents:
diff changeset
215 }
anatofuz
parents:
diff changeset
216
anatofuz
parents:
diff changeset
217 static RecordDecl *getDeclForType(const QualType &T) {
anatofuz
parents:
diff changeset
218 if (const RecordDecl *D = T->getAsRecordDecl())
anatofuz
parents:
diff changeset
219 return D->getDefinition();
anatofuz
parents:
diff changeset
220 return nullptr;
anatofuz
parents:
diff changeset
221 }
anatofuz
parents:
diff changeset
222
anatofuz
parents:
diff changeset
223 static bool isPublic(const clang::AccessSpecifier AS,
anatofuz
parents:
diff changeset
224 const clang::Linkage Link) {
anatofuz
parents:
diff changeset
225 if (AS == clang::AccessSpecifier::AS_private)
anatofuz
parents:
diff changeset
226 return false;
anatofuz
parents:
diff changeset
227 else if ((Link == clang::Linkage::ModuleLinkage) ||
anatofuz
parents:
diff changeset
228 (Link == clang::Linkage::ExternalLinkage))
anatofuz
parents:
diff changeset
229 return true;
anatofuz
parents:
diff changeset
230 return false; // otherwise, linkage is some form of internal linkage
anatofuz
parents:
diff changeset
231 }
anatofuz
parents:
diff changeset
232
anatofuz
parents:
diff changeset
233 static bool shouldSerializeInfo(bool PublicOnly, bool IsInAnonymousNamespace,
anatofuz
parents:
diff changeset
234 const NamedDecl *D) {
anatofuz
parents:
diff changeset
235 bool IsAnonymousNamespace = false;
anatofuz
parents:
diff changeset
236 if (const auto *N = dyn_cast<NamespaceDecl>(D))
anatofuz
parents:
diff changeset
237 IsAnonymousNamespace = N->isAnonymousNamespace();
anatofuz
parents:
diff changeset
238 return !PublicOnly ||
anatofuz
parents:
diff changeset
239 (!IsInAnonymousNamespace && !IsAnonymousNamespace &&
anatofuz
parents:
diff changeset
240 isPublic(D->getAccessUnsafe(), D->getLinkageInternal()));
anatofuz
parents:
diff changeset
241 }
anatofuz
parents:
diff changeset
242
anatofuz
parents:
diff changeset
243 // There are two uses for this function.
anatofuz
parents:
diff changeset
244 // 1) Getting the resulting mode of inheritance of a record.
anatofuz
parents:
diff changeset
245 // Example: class A {}; class B : private A {}; class C : public B {};
anatofuz
parents:
diff changeset
246 // It's explicit that C is publicly inherited from C and B is privately
anatofuz
parents:
diff changeset
247 // inherited from A. It's not explicit but C is also privately inherited from
anatofuz
parents:
diff changeset
248 // A. This is the AS that this function calculates. FirstAS is the
anatofuz
parents:
diff changeset
249 // inheritance mode of `class C : B` and SecondAS is the inheritance mode of
anatofuz
parents:
diff changeset
250 // `class B : A`.
anatofuz
parents:
diff changeset
251 // 2) Getting the inheritance mode of an inherited attribute / method.
anatofuz
parents:
diff changeset
252 // Example : class A { public: int M; }; class B : private A {};
anatofuz
parents:
diff changeset
253 // Class B is inherited from class A, which has a public attribute. This
anatofuz
parents:
diff changeset
254 // attribute is now part of the derived class B but it's not public. This
anatofuz
parents:
diff changeset
255 // will be private because the inheritance is private. This is the AS that
anatofuz
parents:
diff changeset
256 // this function calculates. FirstAS is the inheritance mode and SecondAS is
anatofuz
parents:
diff changeset
257 // the AS of the attribute / method.
anatofuz
parents:
diff changeset
258 static AccessSpecifier getFinalAccessSpecifier(AccessSpecifier FirstAS,
anatofuz
parents:
diff changeset
259 AccessSpecifier SecondAS) {
anatofuz
parents:
diff changeset
260 if (FirstAS == AccessSpecifier::AS_none ||
anatofuz
parents:
diff changeset
261 SecondAS == AccessSpecifier::AS_none)
anatofuz
parents:
diff changeset
262 return AccessSpecifier::AS_none;
anatofuz
parents:
diff changeset
263 if (FirstAS == AccessSpecifier::AS_private ||
anatofuz
parents:
diff changeset
264 SecondAS == AccessSpecifier::AS_private)
anatofuz
parents:
diff changeset
265 return AccessSpecifier::AS_private;
anatofuz
parents:
diff changeset
266 if (FirstAS == AccessSpecifier::AS_protected ||
anatofuz
parents:
diff changeset
267 SecondAS == AccessSpecifier::AS_protected)
anatofuz
parents:
diff changeset
268 return AccessSpecifier::AS_protected;
anatofuz
parents:
diff changeset
269 return AccessSpecifier::AS_public;
anatofuz
parents:
diff changeset
270 }
anatofuz
parents:
diff changeset
271
anatofuz
parents:
diff changeset
272 // The Access parameter is only provided when parsing the field of an inherited
anatofuz
parents:
diff changeset
273 // record, the access specification of the field depends on the inheritance mode
anatofuz
parents:
diff changeset
274 static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly,
anatofuz
parents:
diff changeset
275 AccessSpecifier Access = AccessSpecifier::AS_public) {
anatofuz
parents:
diff changeset
276 for (const FieldDecl *F : D->fields()) {
anatofuz
parents:
diff changeset
277 if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F))
anatofuz
parents:
diff changeset
278 continue;
anatofuz
parents:
diff changeset
279 if (const auto *T = getDeclForType(F->getTypeSourceInfo()->getType())) {
anatofuz
parents:
diff changeset
280 // Use getAccessUnsafe so that we just get the default AS_none if it's not
anatofuz
parents:
diff changeset
281 // valid, as opposed to an assert.
anatofuz
parents:
diff changeset
282 if (const auto *N = dyn_cast<EnumDecl>(T)) {
anatofuz
parents:
diff changeset
283 I.Members.emplace_back(
anatofuz
parents:
diff changeset
284 getUSRForDecl(T), N->getNameAsString(), InfoType::IT_enum,
anatofuz
parents:
diff changeset
285 getInfoRelativePath(N), F->getNameAsString(),
anatofuz
parents:
diff changeset
286 getFinalAccessSpecifier(Access, N->getAccessUnsafe()));
anatofuz
parents:
diff changeset
287 continue;
anatofuz
parents:
diff changeset
288 } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
anatofuz
parents:
diff changeset
289 I.Members.emplace_back(
anatofuz
parents:
diff changeset
290 getUSRForDecl(T), N->getNameAsString(), InfoType::IT_record,
anatofuz
parents:
diff changeset
291 getInfoRelativePath(N), F->getNameAsString(),
anatofuz
parents:
diff changeset
292 getFinalAccessSpecifier(Access, N->getAccessUnsafe()));
anatofuz
parents:
diff changeset
293 continue;
anatofuz
parents:
diff changeset
294 }
anatofuz
parents:
diff changeset
295 }
anatofuz
parents:
diff changeset
296 I.Members.emplace_back(
anatofuz
parents:
diff changeset
297 F->getTypeSourceInfo()->getType().getAsString(), F->getNameAsString(),
anatofuz
parents:
diff changeset
298 getFinalAccessSpecifier(Access, F->getAccessUnsafe()));
anatofuz
parents:
diff changeset
299 }
anatofuz
parents:
diff changeset
300 }
anatofuz
parents:
diff changeset
301
anatofuz
parents:
diff changeset
302 static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
anatofuz
parents:
diff changeset
303 for (const EnumConstantDecl *E : D->enumerators())
anatofuz
parents:
diff changeset
304 I.Members.emplace_back(E->getNameAsString());
anatofuz
parents:
diff changeset
305 }
anatofuz
parents:
diff changeset
306
anatofuz
parents:
diff changeset
307 static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
anatofuz
parents:
diff changeset
308 for (const ParmVarDecl *P : D->parameters()) {
anatofuz
parents:
diff changeset
309 if (const auto *T = getDeclForType(P->getOriginalType())) {
anatofuz
parents:
diff changeset
310 if (const auto *N = dyn_cast<EnumDecl>(T)) {
anatofuz
parents:
diff changeset
311 I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
anatofuz
parents:
diff changeset
312 InfoType::IT_enum, getInfoRelativePath(N),
anatofuz
parents:
diff changeset
313 P->getNameAsString());
anatofuz
parents:
diff changeset
314 continue;
anatofuz
parents:
diff changeset
315 } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
anatofuz
parents:
diff changeset
316 I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
anatofuz
parents:
diff changeset
317 InfoType::IT_record, getInfoRelativePath(N),
anatofuz
parents:
diff changeset
318 P->getNameAsString());
anatofuz
parents:
diff changeset
319 continue;
anatofuz
parents:
diff changeset
320 }
anatofuz
parents:
diff changeset
321 }
anatofuz
parents:
diff changeset
322 I.Params.emplace_back(P->getOriginalType().getAsString(),
anatofuz
parents:
diff changeset
323 P->getNameAsString());
anatofuz
parents:
diff changeset
324 }
anatofuz
parents:
diff changeset
325 }
anatofuz
parents:
diff changeset
326
anatofuz
parents:
diff changeset
327 // TODO: Remove the serialization of Parents and VirtualParents, this
anatofuz
parents:
diff changeset
328 // information is also extracted in the other definition of parseBases.
anatofuz
parents:
diff changeset
329 static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
anatofuz
parents:
diff changeset
330 // Don't parse bases if this isn't a definition.
anatofuz
parents:
diff changeset
331 if (!D->isThisDeclarationADefinition())
anatofuz
parents:
diff changeset
332 return;
anatofuz
parents:
diff changeset
333 for (const CXXBaseSpecifier &B : D->bases()) {
anatofuz
parents:
diff changeset
334 if (B.isVirtual())
anatofuz
parents:
diff changeset
335 continue;
anatofuz
parents:
diff changeset
336 if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
anatofuz
parents:
diff changeset
337 const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
anatofuz
parents:
diff changeset
338 I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
anatofuz
parents:
diff changeset
339 InfoType::IT_record);
anatofuz
parents:
diff changeset
340 } else if (const RecordDecl *P = getDeclForType(B.getType()))
anatofuz
parents:
diff changeset
341 I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
anatofuz
parents:
diff changeset
342 InfoType::IT_record, getInfoRelativePath(P));
anatofuz
parents:
diff changeset
343 else
anatofuz
parents:
diff changeset
344 I.Parents.emplace_back(B.getType().getAsString());
anatofuz
parents:
diff changeset
345 }
anatofuz
parents:
diff changeset
346 for (const CXXBaseSpecifier &B : D->vbases()) {
anatofuz
parents:
diff changeset
347 if (const auto *P = getDeclForType(B.getType()))
anatofuz
parents:
diff changeset
348 I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
anatofuz
parents:
diff changeset
349 InfoType::IT_record,
anatofuz
parents:
diff changeset
350 getInfoRelativePath(P));
anatofuz
parents:
diff changeset
351 else
anatofuz
parents:
diff changeset
352 I.VirtualParents.emplace_back(B.getType().getAsString());
anatofuz
parents:
diff changeset
353 }
anatofuz
parents:
diff changeset
354 }
anatofuz
parents:
diff changeset
355
anatofuz
parents:
diff changeset
356 template <typename T>
anatofuz
parents:
diff changeset
357 static void
anatofuz
parents:
diff changeset
358 populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
anatofuz
parents:
diff changeset
359 const T *D, bool &IsInAnonymousNamespace) {
anatofuz
parents:
diff changeset
360 const auto *DC = dyn_cast<DeclContext>(D);
anatofuz
parents:
diff changeset
361 while ((DC = DC->getParent())) {
anatofuz
parents:
diff changeset
362 if (const auto *N = dyn_cast<NamespaceDecl>(DC)) {
anatofuz
parents:
diff changeset
363 std::string Namespace;
anatofuz
parents:
diff changeset
364 if (N->isAnonymousNamespace()) {
anatofuz
parents:
diff changeset
365 Namespace = "@nonymous_namespace";
anatofuz
parents:
diff changeset
366 IsInAnonymousNamespace = true;
anatofuz
parents:
diff changeset
367 } else
anatofuz
parents:
diff changeset
368 Namespace = N->getNameAsString();
anatofuz
parents:
diff changeset
369 Namespaces.emplace_back(getUSRForDecl(N), Namespace,
anatofuz
parents:
diff changeset
370 InfoType::IT_namespace);
anatofuz
parents:
diff changeset
371 } else if (const auto *N = dyn_cast<RecordDecl>(DC))
anatofuz
parents:
diff changeset
372 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
anatofuz
parents:
diff changeset
373 InfoType::IT_record);
anatofuz
parents:
diff changeset
374 else if (const auto *N = dyn_cast<FunctionDecl>(DC))
anatofuz
parents:
diff changeset
375 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
anatofuz
parents:
diff changeset
376 InfoType::IT_function);
anatofuz
parents:
diff changeset
377 else if (const auto *N = dyn_cast<EnumDecl>(DC))
anatofuz
parents:
diff changeset
378 Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
anatofuz
parents:
diff changeset
379 InfoType::IT_enum);
anatofuz
parents:
diff changeset
380 }
anatofuz
parents:
diff changeset
381 // The global namespace should be added to the list of namespaces if the decl
anatofuz
parents:
diff changeset
382 // corresponds to a Record and if it doesn't have any namespace (because this
anatofuz
parents:
diff changeset
383 // means it's in the global namespace). Also if its outermost namespace is a
anatofuz
parents:
diff changeset
384 // record because that record matches the previous condition mentioned.
anatofuz
parents:
diff changeset
385 if ((Namespaces.empty() && dyn_cast<RecordDecl>(D)) ||
anatofuz
parents:
diff changeset
386 (!Namespaces.empty() && Namespaces.back().RefType == InfoType::IT_record))
anatofuz
parents:
diff changeset
387 Namespaces.emplace_back(SymbolID(), "GlobalNamespace",
anatofuz
parents:
diff changeset
388 InfoType::IT_namespace);
anatofuz
parents:
diff changeset
389 }
anatofuz
parents:
diff changeset
390
anatofuz
parents:
diff changeset
391 template <typename T>
anatofuz
parents:
diff changeset
392 static void populateInfo(Info &I, const T *D, const FullComment *C,
anatofuz
parents:
diff changeset
393 bool &IsInAnonymousNamespace) {
anatofuz
parents:
diff changeset
394 I.USR = getUSRForDecl(D);
anatofuz
parents:
diff changeset
395 I.Name = D->getNameAsString();
anatofuz
parents:
diff changeset
396 populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
397 if (C) {
anatofuz
parents:
diff changeset
398 I.Description.emplace_back();
anatofuz
parents:
diff changeset
399 parseFullComment(C, I.Description.back());
anatofuz
parents:
diff changeset
400 }
anatofuz
parents:
diff changeset
401 }
anatofuz
parents:
diff changeset
402
anatofuz
parents:
diff changeset
403 template <typename T>
anatofuz
parents:
diff changeset
404 static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
anatofuz
parents:
diff changeset
405 int LineNumber, StringRef Filename,
anatofuz
parents:
diff changeset
406 bool IsFileInRootDir,
anatofuz
parents:
diff changeset
407 bool &IsInAnonymousNamespace) {
anatofuz
parents:
diff changeset
408 populateInfo(I, D, C, IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
409 if (D->isThisDeclarationADefinition())
anatofuz
parents:
diff changeset
410 I.DefLoc.emplace(LineNumber, Filename, IsFileInRootDir);
anatofuz
parents:
diff changeset
411 else
anatofuz
parents:
diff changeset
412 I.Loc.emplace_back(LineNumber, Filename, IsFileInRootDir);
anatofuz
parents:
diff changeset
413 }
anatofuz
parents:
diff changeset
414
anatofuz
parents:
diff changeset
415 static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
anatofuz
parents:
diff changeset
416 const FullComment *FC, int LineNumber,
anatofuz
parents:
diff changeset
417 StringRef Filename, bool IsFileInRootDir,
anatofuz
parents:
diff changeset
418 bool &IsInAnonymousNamespace) {
anatofuz
parents:
diff changeset
419 populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir,
anatofuz
parents:
diff changeset
420 IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
421 if (const auto *T = getDeclForType(D->getReturnType())) {
anatofuz
parents:
diff changeset
422 if (dyn_cast<EnumDecl>(T))
anatofuz
parents:
diff changeset
423 I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
anatofuz
parents:
diff changeset
424 InfoType::IT_enum, getInfoRelativePath(T));
anatofuz
parents:
diff changeset
425 else if (dyn_cast<RecordDecl>(T))
anatofuz
parents:
diff changeset
426 I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
anatofuz
parents:
diff changeset
427 InfoType::IT_record, getInfoRelativePath(T));
anatofuz
parents:
diff changeset
428 } else {
anatofuz
parents:
diff changeset
429 I.ReturnType = TypeInfo(D->getReturnType().getAsString());
anatofuz
parents:
diff changeset
430 }
anatofuz
parents:
diff changeset
431 parseParameters(I, D);
anatofuz
parents:
diff changeset
432 }
anatofuz
parents:
diff changeset
433
anatofuz
parents:
diff changeset
434 static void
anatofuz
parents:
diff changeset
435 parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
anatofuz
parents:
diff changeset
436 bool PublicOnly, bool IsParent,
anatofuz
parents:
diff changeset
437 AccessSpecifier ParentAccess = AccessSpecifier::AS_public) {
anatofuz
parents:
diff changeset
438 // Don't parse bases if this isn't a definition.
anatofuz
parents:
diff changeset
439 if (!D->isThisDeclarationADefinition())
anatofuz
parents:
diff changeset
440 return;
anatofuz
parents:
diff changeset
441 for (const CXXBaseSpecifier &B : D->bases()) {
anatofuz
parents:
diff changeset
442 if (const RecordType *Ty = B.getType()->getAs<RecordType>()) {
anatofuz
parents:
diff changeset
443 if (const CXXRecordDecl *Base =
anatofuz
parents:
diff changeset
444 cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition())) {
anatofuz
parents:
diff changeset
445 // Initialized without USR and name, this will be set in the following
anatofuz
parents:
diff changeset
446 // if-else stmt.
anatofuz
parents:
diff changeset
447 BaseRecordInfo BI(
anatofuz
parents:
diff changeset
448 {}, "", getInfoRelativePath(Base), B.isVirtual(),
anatofuz
parents:
diff changeset
449 getFinalAccessSpecifier(ParentAccess, B.getAccessSpecifier()),
anatofuz
parents:
diff changeset
450 IsParent);
anatofuz
parents:
diff changeset
451 if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
anatofuz
parents:
diff changeset
452 const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
anatofuz
parents:
diff changeset
453 BI.USR = getUSRForDecl(D);
anatofuz
parents:
diff changeset
454 BI.Name = B.getType().getAsString();
anatofuz
parents:
diff changeset
455 } else {
anatofuz
parents:
diff changeset
456 BI.USR = getUSRForDecl(Base);
anatofuz
parents:
diff changeset
457 BI.Name = Base->getNameAsString();
anatofuz
parents:
diff changeset
458 }
anatofuz
parents:
diff changeset
459 parseFields(BI, Base, PublicOnly, BI.Access);
anatofuz
parents:
diff changeset
460 for (const auto &Decl : Base->decls())
anatofuz
parents:
diff changeset
461 if (const auto *MD = dyn_cast<CXXMethodDecl>(Decl)) {
anatofuz
parents:
diff changeset
462 // Don't serialize private methods
anatofuz
parents:
diff changeset
463 if (MD->getAccessUnsafe() == AccessSpecifier::AS_private ||
anatofuz
parents:
diff changeset
464 !MD->isUserProvided())
anatofuz
parents:
diff changeset
465 continue;
anatofuz
parents:
diff changeset
466 FunctionInfo FI;
anatofuz
parents:
diff changeset
467 FI.IsMethod = true;
anatofuz
parents:
diff changeset
468 // The seventh arg in populateFunctionInfo is a boolean passed by
anatofuz
parents:
diff changeset
469 // reference, its value is not relevant in here so it's not used
anatofuz
parents:
diff changeset
470 // anywhere besides the function call.
anatofuz
parents:
diff changeset
471 bool IsInAnonymousNamespace;
anatofuz
parents:
diff changeset
472 populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*LineNumber=*/{},
anatofuz
parents:
diff changeset
473 /*FileName=*/{}, IsFileInRootDir,
anatofuz
parents:
diff changeset
474 IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
475 FI.Access =
anatofuz
parents:
diff changeset
476 getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe());
anatofuz
parents:
diff changeset
477 BI.ChildFunctions.emplace_back(std::move(FI));
anatofuz
parents:
diff changeset
478 }
anatofuz
parents:
diff changeset
479 I.Bases.emplace_back(std::move(BI));
anatofuz
parents:
diff changeset
480 // Call this function recursively to get the inherited classes of
anatofuz
parents:
diff changeset
481 // this base; these new bases will also get stored in the original
anatofuz
parents:
diff changeset
482 // RecordInfo: I.
anatofuz
parents:
diff changeset
483 parseBases(I, Base, IsFileInRootDir, PublicOnly, false,
anatofuz
parents:
diff changeset
484 I.Bases.back().Access);
anatofuz
parents:
diff changeset
485 }
anatofuz
parents:
diff changeset
486 }
anatofuz
parents:
diff changeset
487 }
anatofuz
parents:
diff changeset
488 }
anatofuz
parents:
diff changeset
489
anatofuz
parents:
diff changeset
490 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
anatofuz
parents:
diff changeset
491 emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber,
anatofuz
parents:
diff changeset
492 llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
anatofuz
parents:
diff changeset
493 auto I = std::make_unique<NamespaceInfo>();
anatofuz
parents:
diff changeset
494 bool IsInAnonymousNamespace = false;
anatofuz
parents:
diff changeset
495 populateInfo(*I, D, FC, IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
496 if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
anatofuz
parents:
diff changeset
497 return {};
anatofuz
parents:
diff changeset
498
anatofuz
parents:
diff changeset
499 I->Name = D->isAnonymousNamespace()
anatofuz
parents:
diff changeset
500 ? llvm::SmallString<16>("@nonymous_namespace")
anatofuz
parents:
diff changeset
501 : I->Name;
anatofuz
parents:
diff changeset
502 I->Path = getInfoRelativePath(I->Namespace);
anatofuz
parents:
diff changeset
503 if (I->Namespace.empty() && I->USR == SymbolID())
anatofuz
parents:
diff changeset
504 return {std::unique_ptr<Info>{std::move(I)}, nullptr};
anatofuz
parents:
diff changeset
505
anatofuz
parents:
diff changeset
506 auto ParentI = std::make_unique<NamespaceInfo>();
anatofuz
parents:
diff changeset
507 ParentI->USR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
anatofuz
parents:
diff changeset
508 ParentI->ChildNamespaces.emplace_back(I->USR, I->Name, InfoType::IT_namespace,
anatofuz
parents:
diff changeset
509 getInfoRelativePath(I->Namespace));
anatofuz
parents:
diff changeset
510 if (I->Namespace.empty())
anatofuz
parents:
diff changeset
511 ParentI->Path = getInfoRelativePath(ParentI->Namespace);
anatofuz
parents:
diff changeset
512 return {std::unique_ptr<Info>{std::move(I)},
anatofuz
parents:
diff changeset
513 std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
514 }
anatofuz
parents:
diff changeset
515
anatofuz
parents:
diff changeset
516 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
anatofuz
parents:
diff changeset
517 emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
anatofuz
parents:
diff changeset
518 llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
anatofuz
parents:
diff changeset
519 auto I = std::make_unique<RecordInfo>();
anatofuz
parents:
diff changeset
520 bool IsInAnonymousNamespace = false;
anatofuz
parents:
diff changeset
521 populateSymbolInfo(*I, D, FC, LineNumber, File, IsFileInRootDir,
anatofuz
parents:
diff changeset
522 IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
523 if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
anatofuz
parents:
diff changeset
524 return {};
anatofuz
parents:
diff changeset
525
anatofuz
parents:
diff changeset
526 I->TagType = D->getTagKind();
anatofuz
parents:
diff changeset
527 parseFields(*I, D, PublicOnly);
anatofuz
parents:
diff changeset
528 if (const auto *C = dyn_cast<CXXRecordDecl>(D)) {
anatofuz
parents:
diff changeset
529 if (const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
anatofuz
parents:
diff changeset
530 I->Name = TD->getNameAsString();
anatofuz
parents:
diff changeset
531 I->IsTypeDef = true;
anatofuz
parents:
diff changeset
532 }
anatofuz
parents:
diff changeset
533 // TODO: remove first call to parseBases, that function should be deleted
anatofuz
parents:
diff changeset
534 parseBases(*I, C);
anatofuz
parents:
diff changeset
535 parseBases(*I, C, IsFileInRootDir, PublicOnly, true);
anatofuz
parents:
diff changeset
536 }
anatofuz
parents:
diff changeset
537 I->Path = getInfoRelativePath(I->Namespace);
anatofuz
parents:
diff changeset
538
anatofuz
parents:
diff changeset
539 switch (I->Namespace[0].RefType) {
anatofuz
parents:
diff changeset
540 case InfoType::IT_namespace: {
anatofuz
parents:
diff changeset
541 auto ParentI = std::make_unique<NamespaceInfo>();
anatofuz
parents:
diff changeset
542 ParentI->USR = I->Namespace[0].USR;
anatofuz
parents:
diff changeset
543 ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record,
anatofuz
parents:
diff changeset
544 getInfoRelativePath(I->Namespace));
anatofuz
parents:
diff changeset
545 return {std::unique_ptr<Info>{std::move(I)},
anatofuz
parents:
diff changeset
546 std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
547 }
anatofuz
parents:
diff changeset
548 case InfoType::IT_record: {
anatofuz
parents:
diff changeset
549 auto ParentI = std::make_unique<RecordInfo>();
anatofuz
parents:
diff changeset
550 ParentI->USR = I->Namespace[0].USR;
anatofuz
parents:
diff changeset
551 ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record,
anatofuz
parents:
diff changeset
552 getInfoRelativePath(I->Namespace));
anatofuz
parents:
diff changeset
553 return {std::unique_ptr<Info>{std::move(I)},
anatofuz
parents:
diff changeset
554 std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
555 }
anatofuz
parents:
diff changeset
556 default:
anatofuz
parents:
diff changeset
557 llvm_unreachable("Invalid reference type for parent namespace");
anatofuz
parents:
diff changeset
558 }
anatofuz
parents:
diff changeset
559 }
anatofuz
parents:
diff changeset
560
anatofuz
parents:
diff changeset
561 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
anatofuz
parents:
diff changeset
562 emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber,
anatofuz
parents:
diff changeset
563 llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
anatofuz
parents:
diff changeset
564 FunctionInfo Func;
anatofuz
parents:
diff changeset
565 bool IsInAnonymousNamespace = false;
anatofuz
parents:
diff changeset
566 populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir,
anatofuz
parents:
diff changeset
567 IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
568 Func.Access = clang::AccessSpecifier::AS_none;
anatofuz
parents:
diff changeset
569 if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
anatofuz
parents:
diff changeset
570 return {};
anatofuz
parents:
diff changeset
571
anatofuz
parents:
diff changeset
572 // Wrap in enclosing scope
anatofuz
parents:
diff changeset
573 auto ParentI = std::make_unique<NamespaceInfo>();
anatofuz
parents:
diff changeset
574 if (!Func.Namespace.empty())
anatofuz
parents:
diff changeset
575 ParentI->USR = Func.Namespace[0].USR;
anatofuz
parents:
diff changeset
576 else
anatofuz
parents:
diff changeset
577 ParentI->USR = SymbolID();
anatofuz
parents:
diff changeset
578 if (Func.Namespace.empty())
anatofuz
parents:
diff changeset
579 ParentI->Path = getInfoRelativePath(ParentI->Namespace);
anatofuz
parents:
diff changeset
580 ParentI->ChildFunctions.emplace_back(std::move(Func));
anatofuz
parents:
diff changeset
581 // Info is wrapped in its parent scope so it's returned in the second position
anatofuz
parents:
diff changeset
582 return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
583 }
anatofuz
parents:
diff changeset
584
anatofuz
parents:
diff changeset
585 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
anatofuz
parents:
diff changeset
586 emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
anatofuz
parents:
diff changeset
587 llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
anatofuz
parents:
diff changeset
588 FunctionInfo Func;
anatofuz
parents:
diff changeset
589 bool IsInAnonymousNamespace = false;
anatofuz
parents:
diff changeset
590 populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir,
anatofuz
parents:
diff changeset
591 IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
592 if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
anatofuz
parents:
diff changeset
593 return {};
anatofuz
parents:
diff changeset
594
anatofuz
parents:
diff changeset
595 Func.IsMethod = true;
anatofuz
parents:
diff changeset
596
anatofuz
parents:
diff changeset
597 const NamedDecl *Parent = nullptr;
anatofuz
parents:
diff changeset
598 if (const auto *SD =
anatofuz
parents:
diff changeset
599 dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
anatofuz
parents:
diff changeset
600 Parent = SD->getSpecializedTemplate();
anatofuz
parents:
diff changeset
601 else
anatofuz
parents:
diff changeset
602 Parent = D->getParent();
anatofuz
parents:
diff changeset
603
anatofuz
parents:
diff changeset
604 SymbolID ParentUSR = getUSRForDecl(Parent);
anatofuz
parents:
diff changeset
605 Func.Parent =
anatofuz
parents:
diff changeset
606 Reference{ParentUSR, Parent->getNameAsString(), InfoType::IT_record};
anatofuz
parents:
diff changeset
607 Func.Access = D->getAccess();
anatofuz
parents:
diff changeset
608
anatofuz
parents:
diff changeset
609 // Wrap in enclosing scope
anatofuz
parents:
diff changeset
610 auto ParentI = std::make_unique<RecordInfo>();
anatofuz
parents:
diff changeset
611 ParentI->USR = ParentUSR;
anatofuz
parents:
diff changeset
612 ParentI->ChildFunctions.emplace_back(std::move(Func));
anatofuz
parents:
diff changeset
613 // Info is wrapped in its parent scope so it's returned in the second position
anatofuz
parents:
diff changeset
614 return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
615 }
anatofuz
parents:
diff changeset
616
anatofuz
parents:
diff changeset
617 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
anatofuz
parents:
diff changeset
618 emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
anatofuz
parents:
diff changeset
619 llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
anatofuz
parents:
diff changeset
620 EnumInfo Enum;
anatofuz
parents:
diff changeset
621 bool IsInAnonymousNamespace = false;
anatofuz
parents:
diff changeset
622 populateSymbolInfo(Enum, D, FC, LineNumber, File, IsFileInRootDir,
anatofuz
parents:
diff changeset
623 IsInAnonymousNamespace);
anatofuz
parents:
diff changeset
624 if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
anatofuz
parents:
diff changeset
625 return {};
anatofuz
parents:
diff changeset
626
anatofuz
parents:
diff changeset
627 Enum.Scoped = D->isScoped();
anatofuz
parents:
diff changeset
628 parseEnumerators(Enum, D);
anatofuz
parents:
diff changeset
629
anatofuz
parents:
diff changeset
630 // Put in global namespace
anatofuz
parents:
diff changeset
631 if (Enum.Namespace.empty()) {
anatofuz
parents:
diff changeset
632 auto ParentI = std::make_unique<NamespaceInfo>();
anatofuz
parents:
diff changeset
633 ParentI->USR = SymbolID();
anatofuz
parents:
diff changeset
634 ParentI->ChildEnums.emplace_back(std::move(Enum));
anatofuz
parents:
diff changeset
635 ParentI->Path = getInfoRelativePath(ParentI->Namespace);
anatofuz
parents:
diff changeset
636 // Info is wrapped in its parent scope so it's returned in the second
anatofuz
parents:
diff changeset
637 // position
anatofuz
parents:
diff changeset
638 return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
639 }
anatofuz
parents:
diff changeset
640
anatofuz
parents:
diff changeset
641 // Wrap in enclosing scope
anatofuz
parents:
diff changeset
642 switch (Enum.Namespace[0].RefType) {
anatofuz
parents:
diff changeset
643 case InfoType::IT_namespace: {
anatofuz
parents:
diff changeset
644 auto ParentI = std::make_unique<NamespaceInfo>();
anatofuz
parents:
diff changeset
645 ParentI->USR = Enum.Namespace[0].USR;
anatofuz
parents:
diff changeset
646 ParentI->ChildEnums.emplace_back(std::move(Enum));
anatofuz
parents:
diff changeset
647 // Info is wrapped in its parent scope so it's returned in the second
anatofuz
parents:
diff changeset
648 // position
anatofuz
parents:
diff changeset
649 return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
650 }
anatofuz
parents:
diff changeset
651 case InfoType::IT_record: {
anatofuz
parents:
diff changeset
652 auto ParentI = std::make_unique<RecordInfo>();
anatofuz
parents:
diff changeset
653 ParentI->USR = Enum.Namespace[0].USR;
anatofuz
parents:
diff changeset
654 ParentI->ChildEnums.emplace_back(std::move(Enum));
anatofuz
parents:
diff changeset
655 // Info is wrapped in its parent scope so it's returned in the second
anatofuz
parents:
diff changeset
656 // position
anatofuz
parents:
diff changeset
657 return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
anatofuz
parents:
diff changeset
658 }
anatofuz
parents:
diff changeset
659 default:
anatofuz
parents:
diff changeset
660 llvm_unreachable("Invalid reference type for parent namespace");
anatofuz
parents:
diff changeset
661 }
anatofuz
parents:
diff changeset
662 }
anatofuz
parents:
diff changeset
663
anatofuz
parents:
diff changeset
664 } // namespace serialize
anatofuz
parents:
diff changeset
665 } // namespace doc
anatofuz
parents:
diff changeset
666 } // namespace clang