summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDmitri Gribenko <gribozavr@gmail.com>2013-11-13 22:16:51 +0000
committerDmitri Gribenko <gribozavr@gmail.com>2013-11-13 22:16:51 +0000
commit86cfda2fcccc84e92fb7f27e85b58312440ca8de (patch)
tree413d00f5a47f6de299cfc8882a921ab703ecd9ca /tools
parent1d40d62f137d3831729131e56562fc490b7f9591 (diff)
downloadclang-86cfda2fcccc84e92fb7f27e85b58312440ca8de.tar.gz
clang-86cfda2fcccc84e92fb7f27e85b58312440ca8de.tar.bz2
clang-86cfda2fcccc84e92fb7f27e85b58312440ca8de.tar.xz
Documentation parsing: move comment-to-XML conversion routines to libIndex
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194610 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/libclang/CIndex.cpp7
-rw-r--r--tools/libclang/CMakeLists.txt1
-rw-r--r--tools/libclang/CXComment.cpp1131
-rw-r--r--tools/libclang/CXTranslationUnit.h7
-rw-r--r--tools/libclang/SimpleFormatContext.h75
5 files changed, 28 insertions, 1193 deletions
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 3e741281be..f53e5c1c49 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -22,7 +22,6 @@
#include "CXTranslationUnit.h"
#include "CXType.h"
#include "CursorVisitor.h"
-#include "SimpleFormatContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Diagnostic.h"
@@ -30,6 +29,7 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Index/CommentToXML.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessingRecord.h"
@@ -68,8 +68,7 @@ CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *AU) {
D->StringPool = new cxstring::CXStringPool();
D->Diagnostics = 0;
D->OverridenCursorsPool = createOverridenCXCursorsPool();
- D->FormatContext = 0;
- D->FormatInMemoryUniqueId = 0;
+ D->CommentToXML = 0;
return D;
}
@@ -2904,7 +2903,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
delete CTUnit->StringPool;
delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);
disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool);
- delete CTUnit->FormatContext;
+ delete CTUnit->CommentToXML;
delete CTUnit;
}
}
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index a593dfccd0..f84780e47d 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -39,7 +39,6 @@ set(SOURCES
Indexing.cpp
IndexingContext.cpp
IndexingContext.h
- SimpleFormatContext.h
../../include/clang-c/Index.h
)
diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp
index 1df6e240d9..21057cb66e 100644
--- a/tools/libclang/CXComment.cpp
+++ b/tools/libclang/CXComment.cpp
@@ -15,19 +15,11 @@
#include "CXComment.h"
#include "CXCursor.h"
#include "CXString.h"
-#include "SimpleFormatContext.h"
-#include "clang/AST/Attr.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 "clang/Index/CommentToXML.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
#include <climits>
using namespace clang;
@@ -352,524 +344,23 @@ CXString clang_VerbatimLineComment_getText(CXComment CXC) {
return cxstring::createRef(VLC->getText());
}
-} // end extern "C"
-
//===----------------------------------------------------------------------===//
-// Helpers for converting comment AST to HTML.
+// Converting comments to XML.
//===----------------------------------------------------------------------===//
-namespace {
-
-/// This comparison will sort parameters with valid index by index, then vararg
-/// parameters, and invalid (unresolved) parameters last.
-class ParamCommandCommentCompareIndex {
-public:
- bool operator()(const ParamCommandComment *LHS,
- const ParamCommandComment *RHS) const {
- unsigned LHSIndex = UINT_MAX;
- unsigned RHSIndex = UINT_MAX;
-
- if (LHS->isParamIndexValid()) {
- if (LHS->isVarArgParam())
- LHSIndex = UINT_MAX - 1;
- else
- LHSIndex = LHS->getParamIndex();
- }
- if (RHS->isParamIndexValid()) {
- if (RHS->isVarArgParam())
- RHSIndex = UINT_MAX - 1;
- else
- RHSIndex = RHS->getParamIndex();
- }
- return LHSIndex < RHSIndex;
- }
-};
-
-/// This comparison will sort template parameters in the following order:
-/// \li real template parameters (depth = 1) in index order;
-/// \li all other names (depth > 1);
-/// \li unresolved names.
-class TParamCommandCommentComparePosition {
-public:
- bool operator()(const TParamCommandComment *LHS,
- const TParamCommandComment *RHS) const {
- // Sort unresolved names last.
- if (!LHS->isPositionValid())
- return false;
- if (!RHS->isPositionValid())
- return true;
-
- if (LHS->getDepth() > 1)
- return false;
- if (RHS->getDepth() > 1)
- return true;
-
- // Sort template parameters in index order.
- if (LHS->getDepth() == 1 && RHS->getDepth() == 1)
- return LHS->getIndex(0) < RHS->getIndex(0);
-
- // Leave all other names in source order.
- return true;
- }
-};
-
-/// Separate parts of a FullComment.
-struct FullCommentParts {
- /// Take a full comment apart and initialize members accordingly.
- FullCommentParts(const FullComment *C,
- const CommandTraits &Traits);
-
- const BlockContentComment *Brief;
- const BlockContentComment *Headerfile;
- const ParagraphComment *FirstParagraph;
- SmallVector<const BlockCommandComment *, 4> Returns;
- SmallVector<const ParamCommandComment *, 8> Params;
- SmallVector<const TParamCommandComment *, 4> TParams;
- llvm::TinyPtrVector<const BlockCommandComment *> Exceptions;
- SmallVector<const BlockContentComment *, 8> MiscBlocks;
-};
-
-FullCommentParts::FullCommentParts(const FullComment *C,
- const CommandTraits &Traits) :
- Brief(NULL), Headerfile(NULL), FirstParagraph(NULL) {
- for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
- I != E; ++I) {
- const Comment *Child = *I;
- if (!Child)
- continue;
- switch (Child->getCommentKind()) {
- case Comment::NoCommentKind:
- continue;
-
- case Comment::ParagraphCommentKind: {
- const ParagraphComment *PC = cast<ParagraphComment>(Child);
- if (PC->isWhitespace())
- break;
- if (!FirstParagraph)
- FirstParagraph = PC;
-
- MiscBlocks.push_back(PC);
- break;
- }
-
- case Comment::BlockCommandCommentKind: {
- const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
- const CommandInfo *Info = Traits.getCommandInfo(BCC->getCommandID());
- if (!Brief && Info->IsBriefCommand) {
- Brief = BCC;
- break;
- }
- if (!Headerfile && Info->IsHeaderfileCommand) {
- Headerfile = BCC;
- break;
- }
- if (Info->IsReturnsCommand) {
- Returns.push_back(BCC);
- break;
- }
- if (Info->IsThrowsCommand) {
- Exceptions.push_back(BCC);
- break;
- }
- MiscBlocks.push_back(BCC);
- break;
- }
-
- case Comment::ParamCommandCommentKind: {
- const ParamCommandComment *PCC = cast<ParamCommandComment>(Child);
- if (!PCC->hasParamName())
- break;
-
- if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph())
- break;
-
- Params.push_back(PCC);
- break;
- }
-
- case Comment::TParamCommandCommentKind: {
- const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
- if (!TPCC->hasParamName())
- break;
-
- if (!TPCC->hasNonWhitespaceParagraph())
- break;
-
- TParams.push_back(TPCC);
- break;
- }
-
- case Comment::VerbatimBlockCommentKind:
- MiscBlocks.push_back(cast<BlockCommandComment>(Child));
- break;
-
- case Comment::VerbatimLineCommentKind: {
- const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child);
- const CommandInfo *Info = Traits.getCommandInfo(VLC->getCommandID());
- if (!Info->IsDeclarationCommand)
- MiscBlocks.push_back(VLC);
- break;
- }
-
- case Comment::TextCommentKind:
- case Comment::InlineCommandCommentKind:
- case Comment::HTMLStartTagCommentKind:
- case Comment::HTMLEndTagCommentKind:
- case Comment::VerbatimBlockLineCommentKind:
- case Comment::FullCommentKind:
- llvm_unreachable("AST node of this kind can't be a child of "
- "a FullComment");
- }
- }
-
- // Sort params in order they are declared in the function prototype.
- // Unresolved parameters are put at the end of the list in the same order
- // they were seen in the comment.
- std::stable_sort(Params.begin(), Params.end(),
- ParamCommandCommentCompareIndex());
-
- std::stable_sort(TParams.begin(), TParams.end(),
- TParamCommandCommentComparePosition());
-}
-
-void PrintHTMLStartTagComment(const HTMLStartTagComment *C,
- llvm::raw_svector_ostream &Result) {
- Result << "<" << C->getTagName();
-
- if (C->getNumAttrs() != 0) {
- for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) {
- Result << " ";
- const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
- Result << Attr.Name;
- if (!Attr.Value.empty())
- Result << "=\"" << Attr.Value << "\"";
- }
- }
-
- if (!C->isSelfClosing())
- Result << ">";
- else
- Result << "/>";
-}
-
-class CommentASTToHTMLConverter :
- public ConstCommentVisitor<CommentASTToHTMLConverter> {
-public:
- /// \param Str accumulator for HTML.
- CommentASTToHTMLConverter(const FullComment *FC,
- SmallVectorImpl<char> &Str,
- const CommandTraits &Traits) :
- FC(FC), Result(Str), Traits(Traits)
- { }
-
- // Inline content.
- void visitTextComment(const TextComment *C);
- void visitInlineCommandComment(const InlineCommandComment *C);
- void visitHTMLStartTagComment(const HTMLStartTagComment *C);
- void visitHTMLEndTagComment(const HTMLEndTagComment *C);
-
- // Block content.
- void visitParagraphComment(const ParagraphComment *C);
- void visitBlockCommandComment(const BlockCommandComment *C);
- void visitParamCommandComment(const ParamCommandComment *C);
- void visitTParamCommandComment(const TParamCommandComment *C);
- void visitVerbatimBlockComment(const VerbatimBlockComment *C);
- void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
- void visitVerbatimLineComment(const VerbatimLineComment *C);
-
- void visitFullComment(const FullComment *C);
-
- // Helpers.
-
- /// Convert a paragraph that is not a block by itself (an argument to some
- /// command).
- void visitNonStandaloneParagraphComment(const ParagraphComment *C);
-
- void appendToResultWithHTMLEscaping(StringRef S);
-
-private:
- const FullComment *FC;
- /// Output stream for HTML.
- llvm::raw_svector_ostream Result;
-
- const CommandTraits &Traits;
-};
-} // end unnamed namespace
-
-void CommentASTToHTMLConverter::visitTextComment(const TextComment *C) {
- appendToResultWithHTMLEscaping(C->getText());
-}
-
-void CommentASTToHTMLConverter::visitInlineCommandComment(
- const InlineCommandComment *C) {
- // Nothing to render if no arguments supplied.
- if (C->getNumArgs() == 0)
- return;
-
- // Nothing to render if argument is empty.
- StringRef Arg0 = C->getArgText(0);
- if (Arg0.empty())
- return;
-
- switch (C->getRenderKind()) {
- case InlineCommandComment::RenderNormal:
- for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
- appendToResultWithHTMLEscaping(C->getArgText(i));
- Result << " ";
- }
- return;
-
- case InlineCommandComment::RenderBold:
- assert(C->getNumArgs() == 1);
- Result << "<b>";
- appendToResultWithHTMLEscaping(Arg0);
- Result << "</b>";
- return;
- case InlineCommandComment::RenderMonospaced:
- assert(C->getNumArgs() == 1);
- Result << "<tt>";
- appendToResultWithHTMLEscaping(Arg0);
- Result<< "</tt>";
- return;
- case InlineCommandComment::RenderEmphasized:
- assert(C->getNumArgs() == 1);
- Result << "<em>";
- appendToResultWithHTMLEscaping(Arg0);
- Result << "</em>";
- return;
- }
-}
-
-void CommentASTToHTMLConverter::visitHTMLStartTagComment(
- const HTMLStartTagComment *C) {
- PrintHTMLStartTagComment(C, Result);
-}
-
-void CommentASTToHTMLConverter::visitHTMLEndTagComment(
- const HTMLEndTagComment *C) {
- Result << "</" << C->getTagName() << ">";
-}
-
-void CommentASTToHTMLConverter::visitParagraphComment(
- const ParagraphComment *C) {
- if (C->isWhitespace())
- return;
-
- Result << "<p>";
- for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
- I != E; ++I) {
- visit(*I);
- }
- Result << "</p>";
-}
-
-void CommentASTToHTMLConverter::visitBlockCommandComment(
- const BlockCommandComment *C) {
- const CommandInfo *Info = Traits.getCommandInfo(C->getCommandID());
- if (Info->IsBriefCommand) {
- Result << "<p class=\"para-brief\">";
- visitNonStandaloneParagraphComment(C->getParagraph());
- Result << "</p>";
- return;
- }
- if (Info->IsReturnsCommand) {
- Result << "<p class=\"para-returns\">"
- "<span class=\"word-returns\">Returns</span> ";
- visitNonStandaloneParagraphComment(C->getParagraph());
- Result << "</p>";
- return;
- }
- // We don't know anything about this command. Just render the paragraph.
- visit(C->getParagraph());
-}
-
-void CommentASTToHTMLConverter::visitParamCommandComment(
- const ParamCommandComment *C) {
- if (C->isParamIndexValid()) {
- if (C->isVarArgParam()) {
- Result << "<dt class=\"param-name-index-vararg\">";
- appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
- } else {
- Result << "<dt class=\"param-name-index-"
- << C->getParamIndex()
- << "\">";
- appendToResultWithHTMLEscaping(C->getParamName(FC));
- }
- } else {
- Result << "<dt class=\"param-name-index-invalid\">";
- appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
- }
- Result << "</dt>";
-
- if (C->isParamIndexValid()) {
- if (C->isVarArgParam())
- Result << "<dd class=\"param-descr-index-vararg\">";
- else
- Result << "<dd class=\"param-descr-index-"
- << C->getParamIndex()
- << "\">";
- } else
- Result << "<dd class=\"param-descr-index-invalid\">";
-
- visitNonStandaloneParagraphComment(C->getParagraph());
- Result << "</dd>";
-}
-
-void CommentASTToHTMLConverter::visitTParamCommandComment(
- const TParamCommandComment *C) {
- if (C->isPositionValid()) {
- if (C->getDepth() == 1)
- Result << "<dt class=\"tparam-name-index-"
- << C->getIndex(0)
- << "\">";
- else
- Result << "<dt class=\"tparam-name-index-other\">";
- appendToResultWithHTMLEscaping(C->getParamName(FC));
- } else {
- Result << "<dt class=\"tparam-name-index-invalid\">";
- appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
- }
-
- Result << "</dt>";
-
- if (C->isPositionValid()) {
- if (C->getDepth() == 1)
- Result << "<dd class=\"tparam-descr-index-"
- << C->getIndex(0)
- << "\">";
- else
- Result << "<dd class=\"tparam-descr-index-other\">";
- } else
- Result << "<dd class=\"tparam-descr-index-invalid\">";
-
- visitNonStandaloneParagraphComment(C->getParagraph());
- Result << "</dd>";
-}
-
-void CommentASTToHTMLConverter::visitVerbatimBlockComment(
- const VerbatimBlockComment *C) {
- unsigned NumLines = C->getNumLines();
- if (NumLines == 0)
- return;
-
- Result << "<pre>";
- for (unsigned i = 0; i != NumLines; ++i) {
- appendToResultWithHTMLEscaping(C->getText(i));
- if (i + 1 != NumLines)
- Result << '\n';
- }
- Result << "</pre>";
-}
-
-void CommentASTToHTMLConverter::visitVerbatimBlockLineComment(
- const VerbatimBlockLineComment *C) {
- llvm_unreachable("should not see this AST node");
-}
-
-void CommentASTToHTMLConverter::visitVerbatimLineComment(
- const VerbatimLineComment *C) {
- Result << "<pre>";
- appendToResultWithHTMLEscaping(C->getText());
- Result << "</pre>";
-}
-
-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) {
- Result << "<p class=\"para-brief\">";
- visitNonStandaloneParagraphComment(Parts.FirstParagraph);
- Result << "</p>";
- FirstParagraphIsBrief = true;
- }
-
- for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
- const Comment *C = Parts.MiscBlocks[i];
- if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
- continue;
- visit(C);
- }
-
- if (Parts.TParams.size() != 0) {
- Result << "<dl>";
- for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
- visit(Parts.TParams[i]);
- Result << "</dl>";
- }
-
- if (Parts.Params.size() != 0) {
- Result << "<dl>";
- for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
- visit(Parts.Params[i]);
- Result << "</dl>";
- }
-
- if (Parts.Returns.size() != 0) {
- Result << "<div class=\"result-discussion\">";
- for (unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
- visit(Parts.Returns[i]);
- Result << "</div>";
- }
-
- Result.flush();
-}
-
-void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
- const ParagraphComment *C) {
- if (!C)
- return;
-
- for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
- I != E; ++I) {
- visit(*I);
- }
-}
-
-void CommentASTToHTMLConverter::appendToResultWithHTMLEscaping(StringRef S) {
- for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
- const char C = *I;
- switch (C) {
- case '&':
- Result << "&amp;";
- break;
- case '<':
- Result << "&lt;";
- break;
- case '>':
- Result << "&gt;";
- break;
- case '"':
- Result << "&quot;";
- break;
- case '\'':
- Result << "&#39;";
- break;
- case '/':
- Result << "&#47;";
- break;
- default:
- Result << C;
- break;
- }
- }
-}
-
-extern "C" {
-
CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
if (!HTC)
return cxstring::createNull();
- SmallString<128> HTML;
- CommentASTToHTMLConverter Converter(0, HTML, getCommandTraits(CXC));
- Converter.visit(HTC);
- return cxstring::createDup(HTML.str());
+ CXTranslationUnit TU = CXC.TranslationUnit;
+ if (!TU->CommentToXML)
+ TU->CommentToXML = new index::CommentToXMLConverter();
+
+ SmallString<128> Text;
+ TU->CommentToXML->convertHTMLTagNodeToText(
+ HTC, Text, cxtu::getASTUnit(TU)->getASTContext());
+ return cxstring::createDup(Text.str());
}
CXString clang_FullComment_getAsHTML(CXComment CXC) {
@@ -877,608 +368,28 @@ CXString clang_FullComment_getAsHTML(CXComment CXC) {
if (!FC)
return cxstring::createNull();
+ CXTranslationUnit TU = CXC.TranslationUnit;
+ if (!TU->CommentToXML)
+ TU->CommentToXML = new index::CommentToXMLConverter();
+
SmallString<1024> HTML;
- CommentASTToHTMLConverter Converter(FC, HTML, getCommandTraits(CXC));
- Converter.visit(FC);
+ TU->CommentToXML
+ ->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext());
return cxstring::createDup(HTML.str());
}
-} // end extern "C"
-
-namespace {
-class CommentASTToXMLConverter :
- public ConstCommentVisitor<CommentASTToXMLConverter> {
-public:
- /// \param Str accumulator for XML.
- CommentASTToXMLConverter(const FullComment *FC,
- SmallVectorImpl<char> &Str,
- const CommandTraits &Traits,
- 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);
- void visitInlineCommandComment(const InlineCommandComment *C);
- void visitHTMLStartTagComment(const HTMLStartTagComment *C);
- void visitHTMLEndTagComment(const HTMLEndTagComment *C);
-
- // 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);
- void visitVerbatimBlockComment(const VerbatimBlockComment *C);
- void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
- void visitVerbatimLineComment(const VerbatimLineComment *C);
-
- void visitFullComment(const FullComment *C);
-
- // Helpers.
- void appendToResultWithXMLEscaping(StringRef S);
-
- void formatTextOfDeclaration(const DeclInfo *DI,
- SmallString<128> &Declaration);
-
-private:
- const FullComment *FC;
-
- /// Output stream for XML.
- llvm::raw_svector_ostream Result;
-
- const CommandTraits &Traits;
- const SourceManager &SM;
- SimpleFormatContext &FormatRewriterContext;
- unsigned FormatInMemoryUniqueId;
-};
-
-void getSourceTextOfDeclaration(const DeclInfo *ThisDecl,
- SmallVectorImpl<char> &Str) {
- ASTContext &Context = ThisDecl->CurrentDecl->getASTContext();
- const LangOptions &LangOpts = Context.getLangOpts();
- llvm::raw_svector_ostream OS(Str);
- PrintingPolicy PPolicy(LangOpts);
- PPolicy.PolishForDeclaration = true;
- PPolicy.TerseOutput = true;
- ThisDecl->CurrentDecl->print(OS, PPolicy,
- /*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
-
-void CommentASTToXMLConverter::visitTextComment(const TextComment *C) {
- appendToResultWithXMLEscaping(C->getText());
-}
-
-void CommentASTToXMLConverter::visitInlineCommandComment(const InlineCommandComment *C) {
- // Nothing to render if no arguments supplied.
- if (C->getNumArgs() == 0)
- return;
-
- // Nothing to render if argument is empty.
- StringRef Arg0 = C->getArgText(0);
- if (Arg0.empty())
- return;
-
- switch (C->getRenderKind()) {
- case InlineCommandComment::RenderNormal:
- for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
- appendToResultWithXMLEscaping(C->getArgText(i));
- Result << " ";
- }
- return;
- case InlineCommandComment::RenderBold:
- assert(C->getNumArgs() == 1);
- Result << "<bold>";
- appendToResultWithXMLEscaping(Arg0);
- Result << "</bold>";
- return;
- case InlineCommandComment::RenderMonospaced:
- assert(C->getNumArgs() == 1);
- Result << "<monospaced>";
- appendToResultWithXMLEscaping(Arg0);
- Result << "</monospaced>";
- return;
- case InlineCommandComment::RenderEmphasized:
- assert(C->getNumArgs() == 1);
- Result << "<emphasized>";
- appendToResultWithXMLEscaping(Arg0);
- Result << "</emphasized>";
- return;
- }
-}
-
-void CommentASTToXMLConverter::visitHTMLStartTagComment(const HTMLStartTagComment *C) {
- Result << "<rawHTML><![CDATA[";
- PrintHTMLStartTagComment(C, Result);
- Result << "]]></rawHTML>";
-}
-
-void CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
- Result << "<rawHTML>&lt;/" << C->getTagName() << "&gt;</rawHTML>";
-}
-
-void CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) {
- appendParagraphCommentWithKind(C, StringRef());
-}
-
-void CommentASTToXMLConverter::appendParagraphCommentWithKind(
- const ParagraphComment *C,
- StringRef ParagraphKind) {
- if (C->isWhitespace())
- return;
-
- 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);
- }
- Result << "</Para>";
-}
-
-void CommentASTToXMLConverter::visitBlockCommandComment(const BlockCommandComment *C) {
- 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) {
- Result << "<Parameter><Name>";
- appendToResultWithXMLEscaping(C->isParamIndexValid() ? C->getParamName(FC)
- : C->getParamNameAsWritten());
- Result << "</Name>";
-
- if (C->isParamIndexValid()) {
- if (C->isVarArgParam())
- Result << "<IsVarArg />";
- else
- Result << "<Index>" << C->getParamIndex() << "</Index>";
- }
-
- Result << "<Direction isExplicit=\"" << C->isDirectionExplicit() << "\">";
- switch (C->getDirection()) {
- case ParamCommandComment::In:
- Result << "in";
- break;
- case ParamCommandComment::Out:
- Result << "out";
- break;
- case ParamCommandComment::InOut:
- Result << "in,out";
- break;
- }
- Result << "</Direction><Discussion>";
- visit(C->getParagraph());
- Result << "</Discussion></Parameter>";
-}
-
-void CommentASTToXMLConverter::visitTParamCommandComment(
- const TParamCommandComment *C) {
- Result << "<Parameter><Name>";
- appendToResultWithXMLEscaping(C->isPositionValid() ? C->getParamName(FC)
- : C->getParamNameAsWritten());
- Result << "</Name>";
-
- if (C->isPositionValid() && C->getDepth() == 1) {
- Result << "<Index>" << C->getIndex(0) << "</Index>";
- }
-
- Result << "<Discussion>";
- visit(C->getParagraph());
- Result << "</Discussion></Parameter>";
-}
-
-void CommentASTToXMLConverter::visitVerbatimBlockComment(
- const VerbatimBlockComment *C) {
- unsigned NumLines = C->getNumLines();
- if (NumLines == 0)
- return;
-
- 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)
- Result << '\n';
- }
- Result << "</Verbatim>";
-}
-
-void CommentASTToXMLConverter::visitVerbatimBlockLineComment(
- const VerbatimBlockLineComment *C) {
- llvm_unreachable("should not see this AST node");
-}
-
-void CommentASTToXMLConverter::visitVerbatimLineComment(
- const VerbatimLineComment *C) {
- Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
- appendToResultWithXMLEscaping(C->getText());
- Result << "</Verbatim>";
-}
-
-void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
- FullCommentParts Parts(C, Traits);
-
- const DeclInfo *DI = C->getDeclInfo();
- StringRef RootEndTag;
- if (DI) {
- switch (DI->getKind()) {
- case DeclInfo::OtherKind:
- RootEndTag = "</Other>";
- Result << "<Other";
- break;
- case DeclInfo::FunctionKind:
- RootEndTag = "</Function>";
- Result << "<Function";
- switch (DI->TemplateKind) {
- case DeclInfo::NotTemplate:
- break;
- case DeclInfo::Template:
- Result << " templateKind=\"template\"";
- break;
- case DeclInfo::TemplateSpecialization:
- Result << " templateKind=\"specialization\"";
- break;
- case DeclInfo::TemplatePartialSpecialization:
- llvm_unreachable("partial specializations of functions "
- "are not allowed in C++");
- }
- if (DI->IsInstanceMethod)
- Result << " isInstanceMethod=\"1\"";
- if (DI->IsClassMethod)
- Result << " isClassMethod=\"1\"";
- break;
- case DeclInfo::ClassKind:
- RootEndTag = "</Class>";
- Result << "<Class";
- switch (DI->TemplateKind) {
- case DeclInfo::NotTemplate:
- break;
- case DeclInfo::Template:
- Result << " templateKind=\"template\"";
- break;
- case DeclInfo::TemplateSpecialization:
- Result << " templateKind=\"specialization\"";
- break;
- case DeclInfo::TemplatePartialSpecialization:
- Result << " templateKind=\"partialSpecialization\"";
- break;
- }
- break;
- case DeclInfo::VariableKind:
- RootEndTag = "</Variable>";
- Result << "<Variable";
- break;
- case DeclInfo::NamespaceKind:
- RootEndTag = "</Namespace>";
- Result << "<Namespace";
- break;
- case DeclInfo::TypedefKind:
- RootEndTag = "</Typedef>";
- Result << "<Typedef";
- break;
- case DeclInfo::EnumKind:
- RootEndTag = "</Enum>";
- Result << "<Enum";
- break;
- }
-
- {
- // Print line and column number.
- SourceLocation Loc = DI->CurrentDecl->getLocation();
- std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
- FileID FID = LocInfo.first;
- unsigned FileOffset = LocInfo.second;
-
- if (!FID.isInvalid()) {
- if (const FileEntry *FE = SM.getFileEntryForID(FID)) {
- Result << " file=\"";
- appendToResultWithXMLEscaping(FE->getName());
- Result << "\"";
- }
- Result << " line=\"" << SM.getLineNumber(FID, FileOffset)
- << "\" column=\"" << SM.getColumnNumber(FID, FileOffset)
- << "\"";
- }
- }
-
- // Finish the root tag.
- Result << ">";
-
- bool FoundName = false;
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(DI->CommentDecl)) {
- if (DeclarationName DeclName = ND->getDeclName()) {
- Result << "<Name>";
- std::string Name = DeclName.getAsString();
- appendToResultWithXMLEscaping(Name);
- FoundName = true;
- Result << "</Name>";
- }
- }
- if (!FoundName)
- Result << "<Name>&lt;anonymous&gt;</Name>";
-
- {
- // Print USR.
- SmallString<128> USR;
- cxcursor::getDeclCursorUSR(DI->CommentDecl, USR);
- if (!USR.empty()) {
- Result << "<USR>";
- appendToResultWithXMLEscaping(USR);
- Result << "</USR>";
- }
- }
- } else {
- // No DeclInfo -- just emit some root tag and name tag.
- 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>";
- }
-
- bool FirstParagraphIsBrief = false;
- if (Parts.Brief) {
- Result << "<Abstract>";
- visit(Parts.Brief);
- Result << "</Abstract>";
- } else if (Parts.FirstParagraph) {
- Result << "<Abstract>";
- visit(Parts.FirstParagraph);
- Result << "</Abstract>";
- FirstParagraphIsBrief = true;
- }
-
- if (Parts.TParams.size() != 0) {
- Result << "<TemplateParameters>";
- for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
- visit(Parts.TParams[i]);
- Result << "</TemplateParameters>";
- }
-
- if (Parts.Params.size() != 0) {
- Result << "<Parameters>";
- for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
- visit(Parts.Params[i]);
- Result << "</Parameters>";
- }
-
- if (Parts.Exceptions.size() != 0) {
- Result << "<Exceptions>";
- for (unsigned i = 0, e = Parts.Exceptions.size(); i != e; ++i)
- visit(Parts.Exceptions[i]);
- Result << "</Exceptions>";
- }
-
- if (Parts.Returns.size() != 0) {
- Result << "<ResultDiscussion>";
- for (unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
- visit(Parts.Returns[i]);
- Result << "</ResultDiscussion>";
- }
-
- if (DI->CommentDecl->hasAttrs()) {
- const AttrVec &Attrs = DI->CommentDecl->getAttrs();
- for (unsigned i = 0, e = Attrs.size(); i != e; i++) {
- const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attrs[i]);
- if (!AA) {
- if (const DeprecatedAttr *DA = dyn_cast<DeprecatedAttr>(Attrs[i])) {
- if (DA->getMessage().empty())
- Result << "<Deprecated/>";
- else {
- Result << "<Deprecated>";
- appendToResultWithXMLEscaping(DA->getMessage());
- Result << "</Deprecated>";
- }
- }
- else if (const UnavailableAttr *UA = dyn_cast<UnavailableAttr>(Attrs[i])) {
- if (UA->getMessage().empty())
- Result << "<Unavailable/>";
- else {
- Result << "<Unavailable>";
- appendToResultWithXMLEscaping(UA->getMessage());
- Result << "</Unavailable>";
- }
- }
- continue;
- }
-
- // 'availability' attribute.
- Result << "<Availability";
- StringRef Distribution;
- if (AA->getPlatform()) {
- Distribution = AvailabilityAttr::getPrettyPlatformName(
- AA->getPlatform()->getName());
- if (Distribution.empty())
- Distribution = AA->getPlatform()->getName();
- }
- Result << " distribution=\"" << Distribution << "\">";
- VersionTuple IntroducedInVersion = AA->getIntroduced();
- if (!IntroducedInVersion.empty()) {
- Result << "<IntroducedInVersion>"
- << IntroducedInVersion.getAsString()
- << "</IntroducedInVersion>";
- }
- VersionTuple DeprecatedInVersion = AA->getDeprecated();
- if (!DeprecatedInVersion.empty()) {
- Result << "<DeprecatedInVersion>"
- << DeprecatedInVersion.getAsString()
- << "</DeprecatedInVersion>";
- }
- VersionTuple RemovedAfterVersion = AA->getObsoleted();
- if (!RemovedAfterVersion.empty()) {
- Result << "<RemovedAfterVersion>"
- << RemovedAfterVersion.getAsString()
- << "</RemovedAfterVersion>";
- }
- StringRef DeprecationSummary = AA->getMessage();
- if (!DeprecationSummary.empty()) {
- Result << "<DeprecationSummary>";
- appendToResultWithXMLEscaping(DeprecationSummary);
- Result << "</DeprecationSummary>";
- }
- if (AA->getUnavailable())
- Result << "<Unavailable/>";
- Result << "</Availability>";
- }
- }
-
- {
- bool StartTagEmitted = false;
- for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
- const Comment *C = Parts.MiscBlocks[i];
- if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
- continue;
- if (!StartTagEmitted) {
- Result << "<Discussion>";
- StartTagEmitted = true;
- }
- visit(C);
- }
- if (StartTagEmitted)
- Result << "</Discussion>";
- }
-
- Result << RootEndTag;
-
- Result.flush();
-}
-
-void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) {
- for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
- const char C = *I;
- switch (C) {
- case '&':
- Result << "&amp;";
- break;
- case '<':
- Result << "&lt;";
- break;
- case '>':
- Result << "&gt;";
- break;
- case '"':
- Result << "&quot;";
- break;
- case '\'':
- Result << "&apos;";
- break;
- default:
- Result << C;
- break;
- }
- }
-}
-
-extern "C" {
-
CXString clang_FullComment_getAsXML(CXComment CXC) {
const FullComment *FC = getASTNodeAs<FullComment>(CXC);
if (!FC)
return cxstring::createNull();
- ASTContext &Context = FC->getDeclInfo()->CurrentDecl->getASTContext();
+
CXTranslationUnit TU = CXC.TranslationUnit;
- 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());
- }
+ if (!TU->CommentToXML)
+ TU->CommentToXML = new index::CommentToXMLConverter();
SmallString<1024> XML;
- CommentASTToXMLConverter Converter(FC, XML, getCommandTraits(CXC), SM,
- *TU->FormatContext,
- TU->FormatInMemoryUniqueId++);
- Converter.visit(FC);
+ TU->CommentToXML
+ ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext());
return cxstring::createDup(XML.str());
}
diff --git a/tools/libclang/CXTranslationUnit.h b/tools/libclang/CXTranslationUnit.h
index bdc171cff6..c0014c0c8f 100644
--- a/tools/libclang/CXTranslationUnit.h
+++ b/tools/libclang/CXTranslationUnit.h
@@ -20,7 +20,9 @@
namespace clang {
class ASTUnit;
class CIndexer;
- class SimpleFormatContext;
+namespace index {
+class CommentToXMLConverter;
+} // namespace index
} // namespace clang
struct CXTranslationUnitImpl {
@@ -29,8 +31,7 @@ struct CXTranslationUnitImpl {
clang::cxstring::CXStringPool *StringPool;
void *Diagnostics;
void *OverridenCursorsPool;
- clang::SimpleFormatContext *FormatContext;
- unsigned FormatInMemoryUniqueId;
+ clang::index::CommentToXMLConverter *CommentToXML;
};
namespace clang {
diff --git a/tools/libclang/SimpleFormatContext.h b/tools/libclang/SimpleFormatContext.h
deleted file mode 100644
index 016d0b67d4..0000000000
--- a/tools/libclang/SimpleFormatContext.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//===--- SimpleFormatContext.h ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file
-///
-/// \brief Defines a utility class for use of clang-format in libclang
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SIMPLE_FORM_CONTEXT_H
-#define LLVM_CLANG_SIMPLE_FORM_CONTEXT_H
-
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang {
-
-/// \brief A small class to be used by libclang clients to format
-/// a declaration string in memory. This object is instantiated once
-/// and used each time a formatting is needed.
-class SimpleFormatContext {
-public:
- SimpleFormatContext(LangOptions Options)
- : DiagOpts(new DiagnosticOptions()),
- Diagnostics(new DiagnosticsEngine(new DiagnosticIDs,
- DiagOpts.getPtr())),
- Files((FileSystemOptions())),
- Sources(*Diagnostics, Files),
- Rewrite(Sources, Options) {
- Diagnostics->setClient(new IgnoringDiagConsumer, true);
- }
-
- ~SimpleFormatContext() { }
-
- FileID createInMemoryFile(StringRef Name, StringRef Content) {
- const llvm::MemoryBuffer *Source =
- llvm::MemoryBuffer::getMemBuffer(Content);
- const FileEntry *Entry =
- Files.getVirtualFile(Name, Source->getBufferSize(), 0);
- Sources.overrideFileContents(Entry, Source, true);
- assert(Entry != NULL);
- return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
- }
-
- std::string getRewrittenText(FileID ID) {
- std::string Result;
- llvm::raw_string_ostream OS(Result);
- Rewrite.getEditBuffer(ID).write(OS);
- OS.flush();
- return Result;
- }
-
- IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
- IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
- FileManager Files;
- SourceManager Sources;
- Rewriter Rewrite;
-};
-
-} // end namespace clang
-
-#endif