diff options
Diffstat (limited to 'tools/libclang/CXComment.cpp')
-rw-r--r-- | tools/libclang/CXComment.cpp | 212 |
1 files changed, 161 insertions, 51 deletions
diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp index fa149a0..1c127e1 100644 --- a/tools/libclang/CXComment.cpp +++ b/tools/libclang/CXComment.cpp @@ -12,23 +12,23 @@ //===----------------------------------------------------------------------===// #include "clang-c/Index.h" -#include "CXString.h" #include "CXComment.h" #include "CXCursor.h" - -#include "clang/AST/PrettyPrinter.h" -#include "clang/AST/CommentVisitor.h" +#include "CXString.h" +#include "SimpleFormatContext.h" #include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/CommentVisitor.h" #include "clang/AST/Decl.h" - +#include "clang/AST/PrettyPrinter.h" +#include "clang/Format/Format.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" - #include <climits> using namespace clang; -using namespace clang::cxstring; using namespace clang::comments; using namespace clang::cxcomment; @@ -123,18 +123,18 @@ unsigned clang_InlineContentComment_hasTrailingNewline(CXComment CXC) { CXString clang_TextComment_getText(CXComment CXC) { const TextComment *TC = getASTNodeAs<TextComment>(CXC); if (!TC) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(TC->getText(), /*DupString=*/ false); + return cxstring::createRef(TC->getText()); } CXString clang_InlineCommandComment_getCommandName(CXComment CXC) { const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC); if (!ICC) - return createCXString((const char *) 0); + return cxstring::createNull(); const CommandTraits &Traits = getCommandTraits(CXC); - return createCXString(ICC->getCommandName(Traits), /*DupString=*/ false); + return cxstring::createRef(ICC->getCommandName(Traits)); } enum CXCommentInlineCommandRenderKind @@ -171,17 +171,17 @@ CXString clang_InlineCommandComment_getArgText(CXComment CXC, unsigned ArgIdx) { const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC); if (!ICC || ArgIdx >= ICC->getNumArgs()) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(ICC->getArgText(ArgIdx), /*DupString=*/ false); + return cxstring::createRef(ICC->getArgText(ArgIdx)); } CXString clang_HTMLTagComment_getTagName(CXComment CXC) { const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC); if (!HTC) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(HTC->getTagName(), /*DupString=*/ false); + return cxstring::createRef(HTC->getTagName()); } unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) { @@ -203,26 +203,26 @@ unsigned clang_HTMLStartTag_getNumAttrs(CXComment CXC) { CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) { const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC); if (!HST || AttrIdx >= HST->getNumAttrs()) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(HST->getAttr(AttrIdx).Name, /*DupString=*/ false); + return cxstring::createRef(HST->getAttr(AttrIdx).Name); } CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) { const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC); if (!HST || AttrIdx >= HST->getNumAttrs()) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(HST->getAttr(AttrIdx).Value, /*DupString=*/ false); + return cxstring::createRef(HST->getAttr(AttrIdx).Value); } CXString clang_BlockCommandComment_getCommandName(CXComment CXC) { const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC); if (!BCC) - return createCXString((const char *) 0); + return cxstring::createNull(); const CommandTraits &Traits = getCommandTraits(CXC); - return createCXString(BCC->getCommandName(Traits), /*DupString=*/ false); + return cxstring::createRef(BCC->getCommandName(Traits)); } unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) { @@ -237,9 +237,9 @@ CXString clang_BlockCommandComment_getArgText(CXComment CXC, unsigned ArgIdx) { const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC); if (!BCC || ArgIdx >= BCC->getNumArgs()) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(BCC->getArgText(ArgIdx), /*DupString=*/ false); + return cxstring::createRef(BCC->getArgText(ArgIdx)); } CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) { @@ -253,9 +253,9 @@ CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) { CXString clang_ParamCommandComment_getParamName(CXComment CXC) { const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC); if (!PCC || !PCC->hasParamName()) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(PCC->getParamNameAsWritten(), /*DupString=*/ false); + return cxstring::createRef(PCC->getParamNameAsWritten()); } unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) { @@ -304,9 +304,9 @@ enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection( CXString clang_TParamCommandComment_getParamName(CXComment CXC) { const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC); if (!TPCC || !TPCC->hasParamName()) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(TPCC->getParamNameAsWritten(), /*DupString=*/ false); + return cxstring::createRef(TPCC->getParamNameAsWritten()); } unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) { @@ -337,17 +337,17 @@ CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) { const VerbatimBlockLineComment *VBL = getASTNodeAs<VerbatimBlockLineComment>(CXC); if (!VBL) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(VBL->getText(), /*DupString=*/ false); + return cxstring::createRef(VBL->getText()); } CXString clang_VerbatimLineComment_getText(CXComment CXC) { const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC); if (!VLC) - return createCXString((const char *) 0); + return cxstring::createNull(); - return createCXString(VLC->getText(), /*DupString=*/ false); + return cxstring::createRef(VLC->getText()); } } // end extern "C" @@ -410,6 +410,7 @@ struct FullCommentParts { const CommandTraits &Traits); const BlockContentComment *Brief; + const BlockContentComment *Headerfile; const ParagraphComment *FirstParagraph; const BlockCommandComment *Returns; SmallVector<const ParamCommandComment *, 8> Params; @@ -419,7 +420,7 @@ struct FullCommentParts { FullCommentParts::FullCommentParts(const FullComment *C, const CommandTraits &Traits) : - Brief(NULL), FirstParagraph(NULL), Returns(NULL) { + Brief(NULL), Headerfile(NULL), FirstParagraph(NULL), Returns(NULL) { for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); I != E; ++I) { const Comment *Child = *I; @@ -447,6 +448,10 @@ FullCommentParts::FullCommentParts(const FullComment *C, Brief = BCC; break; } + if (!Headerfile && Info->IsHeaderfileCommand) { + Headerfile = BCC; + break; + } if (!Returns && Info->IsReturnsCommand) { Returns = BCC; break; @@ -749,6 +754,8 @@ void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) { FullCommentParts Parts(C, Traits); bool FirstParagraphIsBrief = false; + if (Parts.Headerfile) + visit(Parts.Headerfile); if (Parts.Brief) visit(Parts.Brief); else if (Parts.FirstParagraph) { @@ -830,23 +837,23 @@ extern "C" { CXString clang_HTMLTagComment_getAsString(CXComment CXC) { const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC); if (!HTC) - return createCXString((const char *) 0); + return cxstring::createNull(); SmallString<128> HTML; CommentASTToHTMLConverter Converter(0, HTML, getCommandTraits(CXC)); Converter.visit(HTC); - return createCXString(HTML.str(), /* DupString = */ true); + return cxstring::createDup(HTML.str()); } CXString clang_FullComment_getAsHTML(CXComment CXC) { const FullComment *FC = getASTNodeAs<FullComment>(CXC); if (!FC) - return createCXString((const char *) 0); + return cxstring::createNull(); SmallString<1024> HTML; CommentASTToHTMLConverter Converter(FC, HTML, getCommandTraits(CXC)); Converter.visit(FC); - return createCXString(HTML.str(), /* DupString = */ true); + return cxstring::createDup(HTML.str()); } } // end extern "C" @@ -859,8 +866,12 @@ public: CommentASTToXMLConverter(const FullComment *FC, SmallVectorImpl<char> &Str, const CommandTraits &Traits, - const SourceManager &SM) : - FC(FC), Result(Str), Traits(Traits), SM(SM) { } + const SourceManager &SM, + SimpleFormatContext &SFC, + unsigned FUID) : + FC(FC), Result(Str), Traits(Traits), SM(SM), + FormatRewriterContext(SFC), + FormatInMemoryUniqueId(FUID) { } // Inline content. void visitTextComment(const TextComment *C); @@ -870,6 +881,10 @@ public: // Block content. void visitParagraphComment(const ParagraphComment *C); + + void appendParagraphCommentWithKind(const ParagraphComment *C, + StringRef Kind); + void visitBlockCommandComment(const BlockCommandComment *C); void visitParamCommandComment(const ParamCommandComment *C); void visitTParamCommandComment(const TParamCommandComment *C); @@ -882,6 +897,9 @@ public: // Helpers. void appendToResultWithXMLEscaping(StringRef S); + void formatTextOfDeclaration(const DeclInfo *DI, + SmallString<128> &Declaration); + private: const FullComment *FC; @@ -890,6 +908,8 @@ private: const CommandTraits &Traits; const SourceManager &SM; + SimpleFormatContext &FormatRewriterContext; + unsigned FormatInMemoryUniqueId; }; void getSourceTextOfDeclaration(const DeclInfo *ThisDecl, @@ -898,10 +918,40 @@ void getSourceTextOfDeclaration(const DeclInfo *ThisDecl, const LangOptions &LangOpts = Context.getLangOpts(); llvm::raw_svector_ostream OS(Str); PrintingPolicy PPolicy(LangOpts); - PPolicy.SuppressAttributes = true; + PPolicy.PolishForDeclaration = true; PPolicy.TerseOutput = true; ThisDecl->CurrentDecl->print(OS, PPolicy, - /*Indentation*/0, /*PrintInstantiation*/true); + /*Indentation*/0, /*PrintInstantiation*/false); +} + +void CommentASTToXMLConverter::formatTextOfDeclaration( + const DeclInfo *DI, + SmallString<128> &Declaration) { + // FIXME. formatting API expects null terminated input string. + // There might be more efficient way of doing this. + std::string StringDecl = Declaration.str(); + + // Formatter specific code. + // Form a unique in memory buffer name. + SmallString<128> filename; + filename += "xmldecl"; + filename += llvm::utostr(FormatInMemoryUniqueId); + filename += ".xd"; + FileID ID = FormatRewriterContext.createInMemoryFile(filename, StringDecl); + SourceLocation Start = + FormatRewriterContext.Sources.getLocForStartOfFile(ID).getLocWithOffset(0); + unsigned Length = Declaration.size(); + + std::vector<CharSourceRange> + Ranges(1, CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length))); + ASTContext &Context = DI->CurrentDecl->getASTContext(); + const LangOptions &LangOpts = Context.getLangOpts(); + Lexer Lex(ID, FormatRewriterContext.Sources.getBuffer(ID), + FormatRewriterContext.Sources, LangOpts); + tooling::Replacements Replace = + reformat(format::getLLVMStyle(), Lex, FormatRewriterContext.Sources, Ranges); + applyAllReplacements(Replace, FormatRewriterContext.Rewrite); + Declaration = FormatRewriterContext.getRewrittenText(ID); } } // end unnamed namespace @@ -959,10 +1009,20 @@ void CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C } void CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) { + appendParagraphCommentWithKind(C, StringRef()); +} + +void CommentASTToXMLConverter::appendParagraphCommentWithKind( + const ParagraphComment *C, + StringRef ParagraphKind) { if (C->isWhitespace()) return; - Result << "<Para>"; + if (ParagraphKind.empty()) + Result << "<Para>"; + else + Result << "<Para kind=\"" << ParagraphKind << "\">"; + for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); I != E; ++I) { visit(*I); @@ -971,7 +1031,33 @@ void CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) } void CommentASTToXMLConverter::visitBlockCommandComment(const BlockCommandComment *C) { - visit(C->getParagraph()); + StringRef ParagraphKind; + + switch (C->getCommandID()) { + case CommandTraits::KCI_attention: + case CommandTraits::KCI_author: + case CommandTraits::KCI_authors: + case CommandTraits::KCI_bug: + case CommandTraits::KCI_copyright: + case CommandTraits::KCI_date: + case CommandTraits::KCI_invariant: + case CommandTraits::KCI_note: + case CommandTraits::KCI_post: + case CommandTraits::KCI_pre: + case CommandTraits::KCI_remark: + case CommandTraits::KCI_remarks: + case CommandTraits::KCI_sa: + case CommandTraits::KCI_see: + case CommandTraits::KCI_since: + case CommandTraits::KCI_todo: + case CommandTraits::KCI_version: + case CommandTraits::KCI_warning: + ParagraphKind = C->getCommandName(Traits); + default: + break; + } + + appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind); } void CommentASTToXMLConverter::visitParamCommandComment(const ParamCommandComment *C) { @@ -1022,9 +1108,14 @@ void CommentASTToXMLConverter::visitVerbatimBlockComment( if (NumLines == 0) return; - Result << llvm::StringSwitch<const char *>(C->getCommandName(Traits)) - .Case("code", "<Verbatim xml:space=\"preserve\" kind=\"code\">") - .Default("<Verbatim xml:space=\"preserve\" kind=\"verbatim\">"); + switch (C->getCommandID()) { + case CommandTraits::KCI_code: + Result << "<Verbatim xml:space=\"preserve\" kind=\"code\">"; + break; + default: + Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">"; + break; + } for (unsigned i = 0; i != NumLines; ++i) { appendToResultWithXMLEscaping(C->getText(i)); if (i + 1 != NumLines) @@ -1162,13 +1253,21 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { RootEndTag = "</Other>"; Result << "<Other><Name>unknown</Name>"; } + + if (Parts.Headerfile) { + Result << "<Headerfile>"; + visit(Parts.Headerfile); + Result << "</Headerfile>"; + } { // Pretty-print the declaration. Result << "<Declaration>"; SmallString<128> Declaration; getSourceTextOfDeclaration(DI, Declaration); + formatTextOfDeclaration(DI, Declaration); appendToResultWithXMLEscaping(Declaration); + Result << "</Declaration>"; } @@ -1183,7 +1282,7 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { Result << "</Abstract>"; FirstParagraphIsBrief = true; } - + if (Parts.TParams.size() != 0) { Result << "<TemplateParameters>"; for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i) @@ -1322,15 +1421,26 @@ extern "C" { CXString clang_FullComment_getAsXML(CXComment CXC) { const FullComment *FC = getASTNodeAs<FullComment>(CXC); if (!FC) - return createCXString((const char *) 0); - + return cxstring::createNull(); + ASTContext &Context = FC->getDeclInfo()->CurrentDecl->getASTContext(); CXTranslationUnit TU = CXC.TranslationUnit; - SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager(); + SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager(); + + if (!TU->FormatContext) { + TU->FormatContext = new SimpleFormatContext(Context.getLangOpts()); + } else if ((TU->FormatInMemoryUniqueId % 1000) == 0) { + // Delete after some number of iterators, so the buffers don't grow + // too large. + delete TU->FormatContext; + TU->FormatContext = new SimpleFormatContext(Context.getLangOpts()); + } SmallString<1024> XML; - CommentASTToXMLConverter Converter(FC, XML, getCommandTraits(CXC), SM); + CommentASTToXMLConverter Converter(FC, XML, getCommandTraits(CXC), SM, + *TU->FormatContext, + TU->FormatInMemoryUniqueId++); Converter.visit(FC); - return createCXString(XML.str(), /* DupString = */ true); + return cxstring::createDup(XML.str()); } } // end extern "C" |