12 #include "clang/AST/Comment.h" 13 #include "clang/Index/USRGeneration.h" 14 #include "llvm/ADT/Hashing.h" 15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/Support/SHA1.h" 18 using clang::comments::FullComment;
25 return llvm::SHA1::hash(arrayRefFromStringRef(USR));
47 std::string getCommandName(
unsigned CommandID)
const;
48 bool isWhitespaceOnly(StringRef S)
const;
54 CurrentCI.
Kind = C->getCommentKindName();
56 for (comments::Comment *Child :
57 llvm::make_range(C->child_begin(), C->child_end())) {
58 CurrentCI.
Children.emplace_back(llvm::make_unique<CommentInfo>());
65 if (!isWhitespaceOnly(C->getText()))
66 CurrentCI.
Text = C->getText();
70 const InlineCommandComment *C) {
71 CurrentCI.
Name = getCommandName(C->getCommandID());
72 for (
unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
73 CurrentCI.
Args.push_back(C->getArgText(I));
77 const HTMLStartTagComment *C) {
78 CurrentCI.
Name = C->getTagName();
80 for (
unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
81 const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
82 CurrentCI.
AttrKeys.push_back(Attr.Name);
88 const HTMLEndTagComment *C) {
89 CurrentCI.
Name = C->getTagName();
94 const BlockCommandComment *C) {
95 CurrentCI.
Name = getCommandName(C->getCommandID());
96 for (
unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
97 CurrentCI.
Args.push_back(C->getArgText(I));
101 const ParamCommandComment *C) {
103 ParamCommandComment::getDirectionAsString(C->getDirection());
104 CurrentCI.
Explicit = C->isDirectionExplicit();
105 if (C->hasParamName())
106 CurrentCI.
ParamName = C->getParamNameAsWritten();
110 const TParamCommandComment *C) {
111 if (C->hasParamName())
112 CurrentCI.
ParamName = C->getParamNameAsWritten();
116 const VerbatimBlockComment *C) {
117 CurrentCI.
Name = getCommandName(C->getCommandID());
122 const VerbatimBlockLineComment *C) {
123 if (!isWhitespaceOnly(C->getText()))
124 CurrentCI.
Text = C->getText();
128 const VerbatimLineComment *C) {
129 if (!isWhitespaceOnly(C->getText()))
130 CurrentCI.
Text = C->getText();
133 bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S)
const {
134 return std::all_of(S.begin(), S.end(), isspace);
137 std::string ClangDocCommentVisitor::getCommandName(
unsigned CommandID)
const {
138 const CommandInfo *
Info = CommandTraits::getBuiltinCommandInfo(CommandID);
142 return "<not a builtin command>";
147 template <
typename T>
static std::string
serialize(T &I) {
148 SmallString<2048> Buffer;
149 llvm::BitstreamWriter Stream(Buffer);
152 return Buffer.str().str();
158 return serialize(*static_cast<NamespaceInfo *>(I.get()));
160 return serialize(*static_cast<RecordInfo *>(I.get()));
162 return serialize(*static_cast<EnumInfo *>(I.get()));
164 return serialize(*static_cast<FunctionInfo *>(I.get()));
176 llvm::SmallString<128> USR;
177 if (index::generateUSRForDecl(D, USR))
183 auto *Ty = T->getAs<RecordType>();
186 return Ty->getDecl()->getDefinition();
189 static bool isPublic(
const clang::AccessSpecifier AS,
190 const clang::Linkage Link) {
191 if (AS == clang::AccessSpecifier::AS_private)
193 else if ((Link == clang::Linkage::ModuleLinkage) ||
194 (Link == clang::Linkage::ExternalLinkage))
200 for (
const FieldDecl *F : D->fields()) {
201 if (PublicOnly && !
isPublic(F->getAccessUnsafe(), F->getLinkageInternal()))
203 if (
const auto *T =
getDeclForType(F->getTypeSourceInfo()->getType())) {
206 if (
const auto *N = dyn_cast<EnumDecl>(T)) {
209 N->getAccessUnsafe());
211 }
else if (
const auto *N = dyn_cast<RecordDecl>(T)) {
214 N->getAccessUnsafe());
218 I.
Members.emplace_back(F->getTypeSourceInfo()->getType().getAsString(),
219 F->getNameAsString(), F->getAccessUnsafe());
224 for (
const EnumConstantDecl *E : D->enumerators())
225 I.
Members.emplace_back(E->getNameAsString());
229 for (
const ParmVarDecl *P : D->parameters()) {
231 if (
const auto *N = dyn_cast<EnumDecl>(T)) {
235 }
else if (
const auto *N = dyn_cast<RecordDecl>(T)) {
241 I.
Params.emplace_back(P->getOriginalType().getAsString(),
242 P->getNameAsString());
248 if (!D->isThisDeclarationADefinition())
250 for (
const CXXBaseSpecifier &B : D->bases()) {
257 I.
Parents.emplace_back(B.getType().getAsString());
259 for (
const CXXBaseSpecifier &B : D->vbases()) {
268 template <
typename T>
272 const auto *DC = dyn_cast<DeclContext>(
D);
273 while ((DC = DC->getParent())) {
274 if (
const auto *N = dyn_cast<NamespaceDecl>(DC))
275 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
277 else if (
const auto *N = dyn_cast<RecordDecl>(DC))
278 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
280 else if (
const auto *N = dyn_cast<FunctionDecl>(DC))
281 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
283 else if (
const auto *N = dyn_cast<EnumDecl>(DC))
284 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
289 template <
typename T>
292 I.
Name = D->getNameAsString();
300 template <
typename T>
302 int LineNumber, StringRef
Filename) {
304 if (D->isThisDeclarationADefinition())
305 I.
DefLoc.emplace(LineNumber, Filename);
307 I.
Loc.emplace_back(LineNumber, Filename);
311 const FullComment *FC,
int LineNumber,
315 if (dyn_cast<EnumDecl>(T))
318 else if (dyn_cast<RecordDecl>(T))
327 std::unique_ptr<Info>
emitInfo(
const NamespaceDecl *
D,
const FullComment *FC,
328 int LineNumber, llvm::StringRef File,
330 if (PublicOnly && ((D->isAnonymousNamespace()) ||
331 !
isPublic(D->getAccess(), D->getLinkageInternal())))
333 auto I = llvm::make_unique<NamespaceInfo>();
335 return std::unique_ptr<Info>{std::move(I)};
338 std::unique_ptr<Info>
emitInfo(
const RecordDecl *
D,
const FullComment *FC,
339 int LineNumber, llvm::StringRef File,
341 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
343 auto I = llvm::make_unique<RecordInfo>();
345 I->TagType = D->getTagKind();
347 if (
const auto *C = dyn_cast<CXXRecordDecl>(D))
349 return std::unique_ptr<Info>{std::move(I)};
352 std::unique_ptr<Info>
emitInfo(
const FunctionDecl *
D,
const FullComment *FC,
353 int LineNumber, llvm::StringRef File,
355 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
359 Func.
Access = clang::AccessSpecifier::AS_none;
362 auto I = llvm::make_unique<NamespaceInfo>();
367 I->ChildFunctions.emplace_back(std::move(Func));
368 return std::unique_ptr<Info>{std::move(I)};
371 std::unique_ptr<Info>
emitInfo(
const CXXMethodDecl *
D,
const FullComment *FC,
372 int LineNumber, llvm::StringRef File,
374 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
383 Func.
Access = D->getAccess();
386 auto I = llvm::make_unique<RecordInfo>();
388 I->ChildFunctions.emplace_back(std::move(Func));
389 return std::unique_ptr<Info>{std::move(I)};
392 std::unique_ptr<Info>
emitInfo(
const EnumDecl *
D,
const FullComment *FC,
393 int LineNumber, llvm::StringRef File,
395 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
399 Enum.
Scoped = D->isScoped();
406 auto I = llvm::make_unique<NamespaceInfo>();
408 I->ChildEnums.emplace_back(std::move(Enum));
409 return std::unique_ptr<Info>{std::move(I)};
412 auto I = llvm::make_unique<RecordInfo>();
414 I->ChildEnums.emplace_back(std::move(Enum));
415 return std::unique_ptr<Info>{std::move(I)};
423 auto I = llvm::make_unique<NamespaceInfo>();
425 I->ChildEnums.emplace_back(std::move(Enum));
426 return std::unique_ptr<Info>{std::move(I)};
static void populateParentNamespaces(llvm::SmallVector< Reference, 4 > &Namespaces, const T *D)
llvm::SmallVector< Reference, 4 > Namespace
static void parseFullComment(const FullComment *C, CommentInfo &CI)
void emitBlock(const NamespaceInfo &I)
llvm::Optional< Location > DefLoc
llvm::SmallVector< Location, 2 > Loc
static void parseBases(RecordInfo &I, const CXXRecordDecl *D)
static RecordDecl * getDeclForType(const QualType &T)
std::string serialize(std::unique_ptr< Info > &I)
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)
llvm::SmallVector< Reference, 4 > VirtualParents
llvm::SmallVector< FieldTypeInfo, 4 > Params
static void parseEnumerators(EnumInfo &I, const EnumDecl *D)
std::string Filename
Filename as a string.
llvm::SmallVector< SmallString< 16 >, 4 > Members
static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, int LineNumber, StringRef Filename)
std::vector< CommentInfo > Description
llvm::SmallVector< Reference, 4 > Parents
static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, const FullComment *FC, int LineNumber, StringRef Filename)
static bool isPublic(const clang::AccessSpecifier AS, const clang::Linkage Link)
static void parseParameters(FunctionInfo &I, const FunctionDecl *D)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< Info > emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, llvm::StringRef File, bool PublicOnly)
static SymbolID getUSRForDecl(const Decl *D)
llvm::SmallVector< MemberTypeInfo, 4 > Members
static void populateInfo(Info &I, const T *D, const FullComment *C)
std::array< uint8_t, 20 > SymbolID
SymbolID hashUSR(llvm::StringRef USR)
static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly)