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();
161 llvm::SmallString<128> USR;
162 if (index::generateUSRForDecl(D, USR))
168 auto *Ty = T->getAs<RecordType>();
171 return Ty->getDecl()->getDefinition();
174 static bool isPublic(
const clang::AccessSpecifier AS,
175 const clang::Linkage Link) {
176 if (AS == clang::AccessSpecifier::AS_private)
178 else if ((Link == clang::Linkage::ModuleLinkage) ||
179 (Link == clang::Linkage::ExternalLinkage))
185 for (
const FieldDecl *F : D->fields()) {
186 if (PublicOnly && !
isPublic(F->getAccessUnsafe(), F->getLinkageInternal()))
188 if (
const auto *T =
getDeclForType(F->getTypeSourceInfo()->getType())) {
191 if (
const auto *N = dyn_cast<EnumDecl>(T)) {
194 N->getAccessUnsafe());
196 }
else if (
const auto *N = dyn_cast<RecordDecl>(T)) {
199 N->getAccessUnsafe());
203 I.
Members.emplace_back(F->getTypeSourceInfo()->getType().getAsString(),
204 F->getNameAsString(), F->getAccessUnsafe());
209 for (
const EnumConstantDecl *E : D->enumerators())
210 I.
Members.emplace_back(E->getNameAsString());
214 for (
const ParmVarDecl *P : D->parameters()) {
216 if (
const auto *N = dyn_cast<EnumDecl>(T)) {
220 }
else if (
const auto *N = dyn_cast<RecordDecl>(T)) {
226 I.
Params.emplace_back(P->getOriginalType().getAsString(),
227 P->getNameAsString());
232 for (
const CXXBaseSpecifier &B : D->bases()) {
239 I.
Parents.emplace_back(B.getType().getAsString());
241 for (
const CXXBaseSpecifier &B : D->vbases()) {
250 template <
typename T>
254 const auto *DC = dyn_cast<DeclContext>(D);
255 while ((DC = DC->getParent())) {
256 if (
const auto *N = dyn_cast<NamespaceDecl>(DC))
257 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
259 else if (
const auto *N = dyn_cast<RecordDecl>(DC))
260 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
262 else if (
const auto *N = dyn_cast<FunctionDecl>(DC))
263 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
265 else if (
const auto *N = dyn_cast<EnumDecl>(DC))
266 Namespaces.emplace_back(
getUSRForDecl(N), N->getNameAsString(),
271 template <
typename T>
274 I.
Name = D->getNameAsString();
282 template <
typename T>
284 int LineNumber, StringRef
Filename) {
286 if (D->isThisDeclarationADefinition())
287 I.
DefLoc.emplace(LineNumber, Filename);
289 I.
Loc.emplace_back(LineNumber, Filename);
293 const FullComment *FC,
int LineNumber,
297 if (dyn_cast<EnumDecl>(T))
300 else if (dyn_cast<RecordDecl>(T))
309 std::string
emitInfo(
const NamespaceDecl *D,
const FullComment *FC,
310 int LineNumber, llvm::StringRef File,
bool PublicOnly) {
311 if (PublicOnly && ((D->isAnonymousNamespace()) ||
312 !
isPublic(D->getAccess(), D->getLinkageInternal())))
319 std::string
emitInfo(
const RecordDecl *D,
const FullComment *FC,
int LineNumber,
321 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
327 if (
const auto *C = dyn_cast<CXXRecordDecl>(D))
332 std::string
emitInfo(
const FunctionDecl *D,
const FullComment *FC,
333 int LineNumber, llvm::StringRef File,
bool PublicOnly) {
334 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
338 I.
Access = clang::AccessSpecifier::AS_none;
342 std::string
emitInfo(
const CXXMethodDecl *D,
const FullComment *FC,
343 int LineNumber, llvm::StringRef File,
bool PublicOnly) {
344 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
351 I.
Access = D->getAccess();
355 std::string
emitInfo(
const EnumDecl *D,
const FullComment *FC,
int LineNumber,
357 if (PublicOnly && !
isPublic(D->getAccess(), D->getLinkageInternal()))
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)
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++ -*-===//
static SymbolID getUSRForDecl(const Decl *D)
std::string emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, llvm::StringRef File, bool PublicOnly)
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)