clang-tools  9.0.0
Serialize.cpp
Go to the documentation of this file.
1 //===-- Serialize.cpp - ClangDoc Serializer ---------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Serialize.h"
10 #include "BitcodeWriter.h"
11 #include "clang/AST/Comment.h"
12 #include "clang/Index/USRGeneration.h"
13 #include "llvm/ADT/Hashing.h"
14 #include "llvm/ADT/StringExtras.h"
15 #include "llvm/Support/SHA1.h"
16 
17 using clang::comments::FullComment;
18 
19 namespace clang {
20 namespace doc {
21 namespace serialize {
22 
23 SymbolID hashUSR(llvm::StringRef USR) {
24  return llvm::SHA1::hash(arrayRefFromStringRef(USR));
25 }
26 
27 template <typename T>
28 static void
29 populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
30  const T *D, bool &IsAnonymousNamespace);
31 
32 // A function to extract the appropriate relative path for a given info's
33 // documentation. The path returned is a composite of the parent namespaces.
34 //
35 // Example: Given the below, the diretory path for class C info will be
36 // <root>/A/B
37 //
38 // namespace A {
39 // namesapce B {
40 //
41 // class C {};
42 //
43 // }
44 // }
45 llvm::SmallString<128>
46 getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
47  std::error_code OK;
48  llvm::SmallString<128> Path;
49  for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
50  llvm::sys::path::append(Path, R->Name);
51  return Path;
52 }
53 
54 llvm::SmallString<128> getInfoRelativePath(const Decl *D) {
55  llvm::SmallVector<Reference, 4> Namespaces;
56  // The third arg in populateParentNamespaces is a boolean passed by reference,
57  // its value is not relevant in here so it's not used anywhere besides the
58  // function call
59  bool B = true;
60  populateParentNamespaces(Namespaces, D, B);
61  return getInfoRelativePath(Namespaces);
62 }
63 
65  : public ConstCommentVisitor<ClangDocCommentVisitor> {
66 public:
67  ClangDocCommentVisitor(CommentInfo &CI) : CurrentCI(CI) {}
68 
69  void parseComment(const comments::Comment *C);
70 
71  void visitTextComment(const TextComment *C);
72  void visitInlineCommandComment(const InlineCommandComment *C);
73  void visitHTMLStartTagComment(const HTMLStartTagComment *C);
74  void visitHTMLEndTagComment(const HTMLEndTagComment *C);
75  void visitBlockCommandComment(const BlockCommandComment *C);
76  void visitParamCommandComment(const ParamCommandComment *C);
77  void visitTParamCommandComment(const TParamCommandComment *C);
78  void visitVerbatimBlockComment(const VerbatimBlockComment *C);
79  void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
80  void visitVerbatimLineComment(const VerbatimLineComment *C);
81 
82 private:
83  std::string getCommandName(unsigned CommandID) const;
84  bool isWhitespaceOnly(StringRef S) const;
85 
86  CommentInfo &CurrentCI;
87 };
88 
89 void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
90  CurrentCI.Kind = C->getCommentKindName();
92  for (comments::Comment *Child :
93  llvm::make_range(C->child_begin(), C->child_end())) {
94  CurrentCI.Children.emplace_back(llvm::make_unique<CommentInfo>());
95  ClangDocCommentVisitor Visitor(*CurrentCI.Children.back());
96  Visitor.parseComment(Child);
97  }
98 }
99 
100 void ClangDocCommentVisitor::visitTextComment(const TextComment *C) {
101  if (!isWhitespaceOnly(C->getText()))
102  CurrentCI.Text = C->getText();
103 }
104 
106  const InlineCommandComment *C) {
107  CurrentCI.Name = getCommandName(C->getCommandID());
108  for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
109  CurrentCI.Args.push_back(C->getArgText(I));
110 }
111 
113  const HTMLStartTagComment *C) {
114  CurrentCI.Name = C->getTagName();
115  CurrentCI.SelfClosing = C->isSelfClosing();
116  for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
117  const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
118  CurrentCI.AttrKeys.push_back(Attr.Name);
119  CurrentCI.AttrValues.push_back(Attr.Value);
120  }
121 }
122 
124  const HTMLEndTagComment *C) {
125  CurrentCI.Name = C->getTagName();
126  CurrentCI.SelfClosing = true;
127 }
128 
130  const BlockCommandComment *C) {
131  CurrentCI.Name = getCommandName(C->getCommandID());
132  for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
133  CurrentCI.Args.push_back(C->getArgText(I));
134 }
135 
137  const ParamCommandComment *C) {
138  CurrentCI.Direction =
139  ParamCommandComment::getDirectionAsString(C->getDirection());
140  CurrentCI.Explicit = C->isDirectionExplicit();
141  if (C->hasParamName())
142  CurrentCI.ParamName = C->getParamNameAsWritten();
143 }
144 
146  const TParamCommandComment *C) {
147  if (C->hasParamName())
148  CurrentCI.ParamName = C->getParamNameAsWritten();
149 }
150 
152  const VerbatimBlockComment *C) {
153  CurrentCI.Name = getCommandName(C->getCommandID());
154  CurrentCI.CloseName = C->getCloseName();
155 }
156 
158  const VerbatimBlockLineComment *C) {
159  if (!isWhitespaceOnly(C->getText()))
160  CurrentCI.Text = C->getText();
161 }
162 
164  const VerbatimLineComment *C) {
165  if (!isWhitespaceOnly(C->getText()))
166  CurrentCI.Text = C->getText();
167 }
168 
169 bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S) const {
170  return std::all_of(S.begin(), S.end(), isspace);
171 }
172 
173 std::string ClangDocCommentVisitor::getCommandName(unsigned CommandID) const {
174  const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
175  if (Info)
176  return Info->Name;
177  // TODO: Add parsing for \file command.
178  return "<not a builtin command>";
179 }
180 
181 // Serializing functions.
182 
183 template <typename T> static std::string serialize(T &I) {
184  SmallString<2048> Buffer;
185  llvm::BitstreamWriter Stream(Buffer);
186  ClangDocBitcodeWriter Writer(Stream);
187  Writer.emitBlock(I);
188  return Buffer.str().str();
189 }
190 
191 std::string serialize(std::unique_ptr<Info> &I) {
192  switch (I->IT) {
194  return serialize(*static_cast<NamespaceInfo *>(I.get()));
195  case InfoType::IT_record:
196  return serialize(*static_cast<RecordInfo *>(I.get()));
197  case InfoType::IT_enum:
198  return serialize(*static_cast<EnumInfo *>(I.get()));
200  return serialize(*static_cast<FunctionInfo *>(I.get()));
201  default:
202  return "";
203  }
204 }
205 
206 static void parseFullComment(const FullComment *C, CommentInfo &CI) {
207  ClangDocCommentVisitor Visitor(CI);
208  Visitor.parseComment(C);
209 }
210 
211 static SymbolID getUSRForDecl(const Decl *D) {
212  llvm::SmallString<128> USR;
213  if (index::generateUSRForDecl(D, USR))
214  return SymbolID();
215  return hashUSR(USR);
216 }
217 
218 static RecordDecl *getDeclForType(const QualType &T) {
219  if (const RecordDecl *D = T->getAsRecordDecl())
220  return D->getDefinition();
221  return nullptr;
222 }
223 
224 static bool isPublic(const clang::AccessSpecifier AS,
225  const clang::Linkage Link) {
226  if (AS == clang::AccessSpecifier::AS_private)
227  return false;
228  else if ((Link == clang::Linkage::ModuleLinkage) ||
229  (Link == clang::Linkage::ExternalLinkage))
230  return true;
231  return false; // otherwise, linkage is some form of internal linkage
232 }
233 
234 static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) {
235  for (const FieldDecl *F : D->fields()) {
236  if (PublicOnly && !isPublic(F->getAccessUnsafe(), F->getLinkageInternal()))
237  continue;
238  if (const auto *T = getDeclForType(F->getTypeSourceInfo()->getType())) {
239  // Use getAccessUnsafe so that we just get the default AS_none if it's not
240  // valid, as opposed to an assert.
241  if (const auto *N = dyn_cast<EnumDecl>(T)) {
242  I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
244  F->getNameAsString(), N->getAccessUnsafe());
245  continue;
246  } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
247  I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
249  F->getNameAsString(), N->getAccessUnsafe());
250  continue;
251  }
252  }
253  I.Members.emplace_back(F->getTypeSourceInfo()->getType().getAsString(),
254  F->getNameAsString(), F->getAccessUnsafe());
255  }
256 }
257 
258 static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
259  for (const EnumConstantDecl *E : D->enumerators())
260  I.Members.emplace_back(E->getNameAsString());
261 }
262 
263 static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
264  for (const ParmVarDecl *P : D->parameters()) {
265  if (const auto *T = getDeclForType(P->getOriginalType())) {
266  if (const auto *N = dyn_cast<EnumDecl>(T)) {
267  I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
269  P->getNameAsString());
270  continue;
271  } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
272  I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
274  P->getNameAsString());
275  continue;
276  }
277  }
278  I.Params.emplace_back(P->getOriginalType().getAsString(),
279  P->getNameAsString());
280  }
281 }
282 
283 static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
284  // Don't parse bases if this isn't a definition.
285  if (!D->isThisDeclarationADefinition())
286  return;
287  for (const CXXBaseSpecifier &B : D->bases()) {
288  if (B.isVirtual())
289  continue;
290  if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
291  const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
292  I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
294  } else if (const RecordDecl *P = getDeclForType(B.getType()))
295  I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
297  else
298  I.Parents.emplace_back(B.getType().getAsString());
299  }
300  for (const CXXBaseSpecifier &B : D->vbases()) {
301  if (const auto *P = getDeclForType(B.getType()))
302  I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
305  else
306  I.VirtualParents.emplace_back(B.getType().getAsString());
307  }
308 }
309 
310 template <typename T>
311 static void
312 populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
313  const T *D, bool &IsInAnonymousNamespace) {
314  const auto *DC = dyn_cast<DeclContext>(D);
315  while ((DC = DC->getParent())) {
316  if (const auto *N = dyn_cast<NamespaceDecl>(DC)) {
317  std::string Namespace;
318  if (N->isAnonymousNamespace()) {
319  Namespace = "@nonymous_namespace";
320  IsInAnonymousNamespace = true;
321  } else
322  Namespace = N->getNameAsString();
323  Namespaces.emplace_back(getUSRForDecl(N), Namespace,
325  } else if (const auto *N = dyn_cast<RecordDecl>(DC))
326  Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
328  else if (const auto *N = dyn_cast<FunctionDecl>(DC))
329  Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
331  else if (const auto *N = dyn_cast<EnumDecl>(DC))
332  Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
334  }
335 }
336 
337 template <typename T>
338 static void populateInfo(Info &I, const T *D, const FullComment *C,
339  bool &IsInAnonymousNamespace) {
340  I.USR = getUSRForDecl(D);
341  I.Name = D->getNameAsString();
342  populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
343  if (C) {
344  I.Description.emplace_back();
345  parseFullComment(C, I.Description.back());
346  }
347 }
348 
349 template <typename T>
350 static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
351  int LineNumber, StringRef Filename,
352  bool &IsInAnonymousNamespace) {
353  populateInfo(I, D, C, IsInAnonymousNamespace);
354  if (D->isThisDeclarationADefinition())
355  I.DefLoc.emplace(LineNumber, Filename);
356  else
357  I.Loc.emplace_back(LineNumber, Filename);
358 }
359 
360 static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
361  const FullComment *FC, int LineNumber,
362  StringRef Filename,
363  bool &IsInAnonymousNamespace) {
364  populateSymbolInfo(I, D, FC, LineNumber, Filename, IsInAnonymousNamespace);
365  if (const auto *T = getDeclForType(D->getReturnType())) {
366  if (dyn_cast<EnumDecl>(T))
367  I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
369  else if (dyn_cast<RecordDecl>(T))
370  I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
372  } else {
373  I.ReturnType = TypeInfo(D->getReturnType().getAsString());
374  }
375  parseParameters(I, D);
376 }
377 
378 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
379 emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber,
380  llvm::StringRef File, bool PublicOnly) {
381  auto I = llvm::make_unique<NamespaceInfo>();
382  bool IsInAnonymousNamespace = false;
383  populateInfo(*I, D, FC, IsInAnonymousNamespace);
384  if (PublicOnly && ((IsInAnonymousNamespace || D->isAnonymousNamespace()) ||
385  !isPublic(D->getAccess(), D->getLinkageInternal())))
386  return {};
387  I->Name = D->isAnonymousNamespace()
388  ? llvm::SmallString<16>("@nonymous_namespace")
389  : I->Name;
390  I->Path = getInfoRelativePath(I->Namespace);
391  if (I->Namespace.empty() && I->USR == SymbolID())
392  return {std::unique_ptr<Info>{std::move(I)}, nullptr};
393 
394  auto ParentI = llvm::make_unique<NamespaceInfo>();
395  ParentI->USR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
396  ParentI->ChildNamespaces.emplace_back(I->USR, I->Name,
398  if (I->Namespace.empty())
399  ParentI->Path = getInfoRelativePath(ParentI->Namespace);
400  return {std::unique_ptr<Info>{std::move(I)},
401  std::unique_ptr<Info>{std::move(ParentI)}};
402 }
403 
404 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
405 emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
406  llvm::StringRef File, bool PublicOnly) {
407  auto I = llvm::make_unique<RecordInfo>();
408  bool IsInAnonymousNamespace = false;
409  populateSymbolInfo(*I, D, FC, LineNumber, File, IsInAnonymousNamespace);
410  if (PublicOnly && ((IsInAnonymousNamespace ||
411  !isPublic(D->getAccess(), D->getLinkageInternal()))))
412  return {};
413 
414  I->TagType = D->getTagKind();
415  parseFields(*I, D, PublicOnly);
416  if (const auto *C = dyn_cast<CXXRecordDecl>(D)) {
417  if (const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
418  I->Name = TD->getNameAsString();
419  I->IsTypeDef = true;
420  }
421  parseBases(*I, C);
422  }
423  I->Path = getInfoRelativePath(I->Namespace);
424 
425  if (I->Namespace.empty()) {
426  auto ParentI = llvm::make_unique<NamespaceInfo>();
427  ParentI->USR = SymbolID();
428  ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
429  ParentI->Path = getInfoRelativePath(ParentI->Namespace);
430  return {std::unique_ptr<Info>{std::move(I)},
431  std::unique_ptr<Info>{std::move(ParentI)}};
432  }
433 
434  switch (I->Namespace[0].RefType) {
435  case InfoType::IT_namespace: {
436  auto ParentI = llvm::make_unique<NamespaceInfo>();
437  ParentI->USR = I->Namespace[0].USR;
438  ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
439  return {std::unique_ptr<Info>{std::move(I)},
440  std::unique_ptr<Info>{std::move(ParentI)}};
441  }
442  case InfoType::IT_record: {
443  auto ParentI = llvm::make_unique<RecordInfo>();
444  ParentI->USR = I->Namespace[0].USR;
445  ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
446  return {std::unique_ptr<Info>{std::move(I)},
447  std::unique_ptr<Info>{std::move(ParentI)}};
448  }
449  default:
450  llvm_unreachable("Invalid reference type for parent namespace");
451  }
452 }
453 
454 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
455 emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber,
456  llvm::StringRef File, bool PublicOnly) {
457  FunctionInfo Func;
458  bool IsInAnonymousNamespace = false;
459  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace);
460  if (PublicOnly && ((IsInAnonymousNamespace ||
461  !isPublic(D->getAccess(), D->getLinkageInternal()))))
462  return {};
463 
464  Func.Access = clang::AccessSpecifier::AS_none;
465 
466  // Wrap in enclosing scope
467  auto ParentI = llvm::make_unique<NamespaceInfo>();
468  if (!Func.Namespace.empty())
469  ParentI->USR = Func.Namespace[0].USR;
470  else
471  ParentI->USR = SymbolID();
472  if (Func.Namespace.empty())
473  ParentI->Path = getInfoRelativePath(ParentI->Namespace);
474  ParentI->ChildFunctions.emplace_back(std::move(Func));
475  // Info is wrapped in its parent scope so it's returned in the second position
476  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
477 }
478 
479 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
480 emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
481  llvm::StringRef File, bool PublicOnly) {
482  FunctionInfo Func;
483  bool IsInAnonymousNamespace = false;
484  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace);
485  if (PublicOnly && ((IsInAnonymousNamespace ||
486  !isPublic(D->getAccess(), D->getLinkageInternal()))))
487  return {};
488 
489  Func.IsMethod = true;
490 
491  const NamedDecl *Parent = nullptr;
492  if (const auto *SD =
493  dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
494  Parent = SD->getSpecializedTemplate();
495  else
496  Parent = D->getParent();
497 
498  SymbolID ParentUSR = getUSRForDecl(Parent);
499  Func.Parent =
500  Reference{ParentUSR, Parent->getNameAsString(), InfoType::IT_record};
501  Func.Access = D->getAccess();
502 
503  // Wrap in enclosing scope
504  auto ParentI = llvm::make_unique<RecordInfo>();
505  ParentI->USR = ParentUSR;
506  if (Func.Namespace.empty())
507  ParentI->Path = getInfoRelativePath(ParentI->Namespace);
508  ParentI->ChildFunctions.emplace_back(std::move(Func));
509  // Info is wrapped in its parent scope so it's returned in the second position
510  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
511 }
512 
513 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
514 emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
515  llvm::StringRef File, bool PublicOnly) {
516  EnumInfo Enum;
517  bool IsInAnonymousNamespace = false;
518  populateSymbolInfo(Enum, D, FC, LineNumber, File, IsInAnonymousNamespace);
519  if (PublicOnly && ((IsInAnonymousNamespace ||
520  !isPublic(D->getAccess(), D->getLinkageInternal()))))
521  return {};
522 
523  Enum.Scoped = D->isScoped();
524  parseEnumerators(Enum, D);
525 
526  // Put in global namespace
527  if (Enum.Namespace.empty()) {
528  auto ParentI = llvm::make_unique<NamespaceInfo>();
529  ParentI->USR = SymbolID();
530  ParentI->ChildEnums.emplace_back(std::move(Enum));
531  ParentI->Path = getInfoRelativePath(ParentI->Namespace);
532  // Info is wrapped in its parent scope so it's returned in the second
533  // position
534  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
535  }
536 
537  // Wrap in enclosing scope
538  switch (Enum.Namespace[0].RefType) {
539  case InfoType::IT_namespace: {
540  auto ParentI = llvm::make_unique<NamespaceInfo>();
541  ParentI->USR = Enum.Namespace[0].USR;
542  ParentI->ChildEnums.emplace_back(std::move(Enum));
543  // Info is wrapped in its parent scope so it's returned in the second
544  // position
545  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
546  }
547  case InfoType::IT_record: {
548  auto ParentI = llvm::make_unique<RecordInfo>();
549  ParentI->USR = Enum.Namespace[0].USR;
550  ParentI->ChildEnums.emplace_back(std::move(Enum));
551  // Info is wrapped in its parent scope so it's returned in the second
552  // position
553  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
554  }
555  default:
556  llvm_unreachable("Invalid reference type for parent namespace");
557  }
558 }
559 
560 } // namespace serialize
561 } // namespace doc
562 } // namespace clang
llvm::SmallVector< Reference, 4 > Namespace
static void parseFullComment(const FullComment *C, CommentInfo &CI)
Definition: Serialize.cpp:206
void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C)
Definition: Serialize.cpp:157
static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, const FullComment *FC, int LineNumber, StringRef Filename, bool &IsInAnonymousNamespace)
Definition: Serialize.cpp:360
void visitParamCommandComment(const ParamCommandComment *C)
Definition: Serialize.cpp:136
void emitBlock(const NamespaceInfo &I)
llvm::Optional< Location > DefLoc
void visitVerbatimBlockComment(const VerbatimBlockComment *C)
Definition: Serialize.cpp:151
llvm::SmallVector< Location, 2 > Loc
llvm::SmallString< 128 > getInfoRelativePath(const llvm::SmallVectorImpl< doc::Reference > &Namespaces)
Definition: Serialize.cpp:46
static void parseBases(RecordInfo &I, const CXXRecordDecl *D)
Definition: Serialize.cpp:283
static RecordDecl * getDeclForType(const QualType &T)
Definition: Serialize.cpp:218
std::vector< HeaderHandle > Path
void parseComment(const comments::Comment *C)
Definition: Serialize.cpp:89
std::string serialize(std::unique_ptr< Info > &I)
Definition: Serialize.cpp:191
static llvm::cl::opt< bool > PublicOnly("public", llvm::cl::desc("Document only public declarations."), llvm::cl::init(false), llvm::cl::cat(ClangDocCategory))
static std::string serialize(T &I)
Definition: Serialize.cpp:183
llvm::SmallVector< Reference, 4 > VirtualParents
std::pair< std::unique_ptr< Info >, std::unique_ptr< Info > > emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, llvm::StringRef File, bool PublicOnly)
Definition: Serialize.cpp:379
void visitHTMLStartTagComment(const HTMLStartTagComment *C)
Definition: Serialize.cpp:112
llvm::SmallVector< FieldTypeInfo, 4 > Params
static void parseEnumerators(EnumInfo &I, const EnumDecl *D)
Definition: Serialize.cpp:258
std::string Filename
Filename as a string.
llvm::SmallVector< SmallString< 16 >, 4 > Members
llvm::SmallVector< SmallString< 16 >, 4 > AttrValues
std::vector< CommentInfo > Description
void visitHTMLEndTagComment(const HTMLEndTagComment *C)
Definition: Serialize.cpp:123
void visitTParamCommandComment(const TParamCommandComment *C)
Definition: Serialize.cpp:145
llvm::SmallVector< SmallString< 16 >, 4 > Args
static void populateParentNamespaces(llvm::SmallVector< Reference, 4 > &Namespaces, const T *D, bool &IsAnonymousNamespace)
Definition: Serialize.cpp:312
SmallString< 16 > Name
const Decl * D
Definition: XRefs.cpp:868
A base struct for Infos.
llvm::SmallVector< Reference, 4 > Parents
void visitTextComment(const TextComment *C)
Definition: Serialize.cpp:100
SmallString< 16 > ParamName
static bool isPublic(const clang::AccessSpecifier AS, const clang::Linkage Link)
Definition: Serialize.cpp:224
llvm::SmallVector< SmallString< 16 >, 4 > AttrKeys
static void parseParameters(FunctionInfo &I, const FunctionDecl *D)
Definition: Serialize.cpp:263
SmallString< 16 > Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static SymbolID getUSRForDecl(const Decl *D)
Definition: Serialize.cpp:211
SmallString< 16 > CloseName
void visitBlockCommandComment(const BlockCommandComment *C)
Definition: Serialize.cpp:129
SmallString< 8 > Direction
void visitInlineCommandComment(const InlineCommandComment *C)
Definition: Serialize.cpp:105
llvm::SmallVector< MemberTypeInfo, 4 > Members
SmallString< 16 > Kind
static void populateInfo(Info &I, const T *D, const FullComment *C, bool &IsInAnonymousNamespace)
Definition: Serialize.cpp:338
std::vector< std::unique_ptr< CommentInfo > > Children
SmallString< 64 > Text
std::array< uint8_t, 20 > SymbolID
void visitVerbatimLineComment(const VerbatimLineComment *C)
Definition: Serialize.cpp:163
SymbolID hashUSR(llvm::StringRef USR)
Definition: Serialize.cpp:23
static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, int LineNumber, StringRef Filename, bool &IsInAnonymousNamespace)
Definition: Serialize.cpp:350
static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly)
Definition: Serialize.cpp:234