<define name="TextBlockContent">
<choice>
<element name="Para">
+ <optional>
+ <attribute name="kind">
+ <choice>
+ <value>author</value>
+ <value>authors</value>
+ <value>bug</value>
+ <value>copyright</value>
+ <value>date</value>
+ <value>invariant</value>
+ <value>note</value>
+ <value>post</value>
+ <value>pre</value>
+ <value>remark</value>
+ <value>remarks</value>
+ <value>sa</value>
+ <value>see</value>
+ <value>since</value>
+ <value>todo</value>
+ <value>version</value>
+ <value>warning</value>
+ </choice>
+ </attribute>
+ </optional>
<zeroOrMore>
<ref name="TextInlineContent" />
</zeroOrMore>
SOURCE CommentCommands.td
TARGET ClangCommentCommandInfo)
+clang_tablegen(CommentCommandList.inc -gen-clang-comment-command-list
+ SOURCE CommentCommands.td
+ TARGET ClangCommentCommandList)
+
/// in comments.
class CommandTraits {
public:
+ enum KnownCommandIDs {
+#define COMMENT_COMMAND(NAME) KCI_##NAME,
+#include "clang/AST/CommentCommandList.inc"
+#undef COMMENT_COMMAND
+ KCI_Last
+ };
+
CommandTraits(llvm::BumpPtrAllocator &Allocator);
/// \returns a CommandInfo object for a given command name or
def Brief : BlockCommand<"brief"> { let IsBriefCommand = 1; }
def Short : BlockCommand<"short"> { let IsBriefCommand = 1; }
+// Opposite of \brief, it is the default in our implementation.
+def Details : BlockCommand<"details">;
+
def Returns : BlockCommand<"returns"> { let IsReturnsCommand = 1; }
def Return : BlockCommand<"return"> { let IsReturnsCommand = 1; }
def Result : BlockCommand<"result"> { let IsReturnsCommand = 1; }
def Bug : BlockCommand<"bug">;
def Copyright : BlockCommand<"copyright">;
def Date : BlockCommand<"date">;
-def Details : BlockCommand<"details">;
def Invariant : BlockCommand<"invariant">;
def Note : BlockCommand<"note">;
def Post : BlockCommand<"post">;
$(Echo) "Building Clang comment command info with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-comment-command-info -o $(call SYSPATH, $@) $<
+$(ObjDir)/CommentCommandList.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \
+ $(CLANG_TBLGEN) $(ObjDir)/.dir
+ $(Echo) "Building Clang list of comment commands with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-comment-command-list -o $(call SYSPATH, $@) $<
+
ClangAttrImpl
ClangAttrDump
ClangCommentCommandInfo
+ ClangCommentCommandList
ClangCommentNodes
ClangCommentHTMLTags
ClangCommentHTMLTagsProperties
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Function>
+<Name>aaa</Name>
+<Abstract><Para>Aaa.</Para></Abstract>
+<Discussion>
+ <Para kind="">Bbb</Para>
+</Discussion>
+</Function>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Function>
+<Name>aaa</Name>
+<Abstract><Para>Aaa.</Para></Abstract>
+<Discussion>
+ <Para kind="zzz">Bbb</Para>
+</Discussion>
+</Function>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Function>
+<Name>aaa</Name>
+<Abstract><Para>Aaa.</Para></Abstract>
+<Discussion>
+ <Para>Bbb</Para>
+ <Para kind="author">Bbb</Para>
+ <Para kind="authors">Bbb</Para>
+ <Para kind="bug">Bbb</Para>
+ <Para kind="copyright">Bbb</Para>
+ <Para kind="date">Bbb</Para>
+ <Para kind="invariant">Bbb</Para>
+ <Para kind="note">Bbb</Para>
+ <Para kind="post">Bbb</Para>
+ <Para kind="pre">Bbb</Para>
+ <Para kind="remark">Bbb</Para>
+ <Para kind="remarks">Bbb</Para>
+ <Para kind="sa">Bbb</Para>
+ <Para kind="see">Bbb</Para>
+ <Para kind="since">Bbb</Para>
+ <Para kind="todo">Bbb</Para>
+ <Para kind="version">Bbb</Para>
+ <Para kind="warning">Bbb</Para>
+</Discussion>
+</Function>
+
// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:3: EnumConstantDecl=comment_to_xml_conversion_18:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="3"><Name>comment_to_xml_conversion_18</Name><USR>c:@E@comment_to_xml_conversion_17@comment_to_xml_conversion_18</USR><Declaration>comment_to_xml_conversion_18</Declaration><Abstract><Para> Aaa.</Para></Abstract></Variable>]
};
+/// Aaa.
+/// \todo Bbb.
+void comment_to_xml_conversion_todo_1();
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_todo_1:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_todo_1</Name><USR>c:@F@comment_to_xml_conversion_todo_1#</USR><Declaration>void comment_to_xml_conversion_todo_1()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Discussion><Para kind="todo"> Bbb.</Para></Discussion></Function>]
+
+/// Aaa.
+/// \todo Bbb.
+///
+/// Ccc.
+void comment_to_xml_conversion_todo_2();
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_todo_2:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_todo_2</Name><USR>c:@F@comment_to_xml_conversion_todo_2#</USR><Declaration>void comment_to_xml_conversion_todo_2()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Discussion><Para kind="todo"> Bbb.</Para><Para> Ccc.</Para></Discussion></Function>]
+
+/// Aaa.
+/// \todo Bbb.
+///
+/// Ccc.
+/// \todo Ddd.
+void comment_to_xml_conversion_todo_3();
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_todo_3:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_todo_3</Name><USR>c:@F@comment_to_xml_conversion_todo_3#</USR><Declaration>void comment_to_xml_conversion_todo_3()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Discussion><Para kind="todo"> Bbb.</Para><Para> Ccc. </Para><Para kind="todo"> Ddd.</Para></Discussion></Function>]
+
+/// Aaa.
+/// \todo Bbb.
+/// \todo Ccc.
+void comment_to_xml_conversion_todo_4();
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-1]]:6: FunctionDecl=comment_to_xml_conversion_todo_4:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-1]]" column="6"><Name>comment_to_xml_conversion_todo_4</Name><USR>c:@F@comment_to_xml_conversion_todo_4#</USR><Declaration>void comment_to_xml_conversion_todo_4()</Declaration><Abstract><Para> Aaa. </Para></Abstract><Discussion><Para kind="todo"> Bbb. </Para><Para kind="todo"> Ccc.</Para></Discussion></Function>]
+
#endif
// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/valid-typedef-02.xml
//
// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/valid-enum-01.xml
+//
+// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/valid-para-kind-01.xml
// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-01.xml 2>&1 | FileCheck %s -check-prefix=INVALID
// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-02.xml 2>&1 | FileCheck %s -check-prefix=INVALID
// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-10.xml 2>&1 | FileCheck %s -check-prefix=INVALID
// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-11.xml 2>&1 | FileCheck %s -check-prefix=INVALID
// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-12.xml 2>&1 | FileCheck %s -check-prefix=INVALID
+//
+// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-para-kind-01.xml 2>&1 | FileCheck %s -check-prefix=INVALID
+// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-para-kind-02.xml 2>&1 | FileCheck %s -check-prefix=INVALID
// CHECK-INVALID: fails to validate
// 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);
// Helpers.
void appendToResultWithXMLEscaping(StringRef S);
-
+
void formatTextOfDeclaration(const DeclInfo *DI,
SmallString<128> &Declaration);
}
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);
}
void CommentASTToXMLConverter::visitBlockCommandComment(const BlockCommandComment *C) {
- visit(C->getParagraph());
+ StringRef ParagraphKind;
+
+ switch (C->getCommandID()) {
+ 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) {
OS << " return NULL;\n"
<< "}\n\n";
}
+
+static std::string MangleName(StringRef Str) {
+ std::string Mangled;
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ switch (Str[i]) {
+ default:
+ Mangled += Str[i];
+ break;
+ case '[':
+ Mangled += "lsquare";
+ break;
+ case ']':
+ Mangled += "rsquare";
+ break;
+ case '{':
+ Mangled += "lbrace";
+ break;
+ case '}':
+ Mangled += "rbrace";
+ break;
+ case '$':
+ Mangled += "dollar";
+ break;
+ }
+ }
+ return Mangled;
+}
+
+void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
+ emitSourceFileHeader("A list of commands useable in documentation "
+ "comments", OS);
+
+ OS << "#ifndef COMMENT_COMMAND\n"
+ << "# define COMMENT_COMMAND(NAME)\n"
+ << "#endif\n";
+
+ std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
+ for (size_t i = 0, e = Tags.size(); i != e; ++i) {
+ Record &Tag = *Tags[i];
+ std::string MangledName = MangleName(Tag.getValueAsString("Name"));
+
+ OS << "COMMENT_COMMAND(" << MangledName << ")\n";
+ }
+}
} // end namespace clang
GenClangCommentHTMLTagsProperties,
GenClangCommentHTMLNamedCharacterReferences,
GenClangCommentCommandInfo,
+ GenClangCommentCommandList,
GenOptParserDefs, GenOptParserImpl,
GenArmNeon,
GenArmNeonSema,
"references to UTF-8 sequences"),
clEnumValN(GenClangCommentCommandInfo,
"gen-clang-comment-command-info",
+ "Generate command properties for commands that "
+ "are used in documentation comments"),
+ clEnumValN(GenClangCommentCommandList,
+ "gen-clang-comment-command-list",
"Generate list of commands that are used in "
"documentation comments"),
clEnumValN(GenArmNeon, "gen-arm-neon",
case GenClangCommentCommandInfo:
EmitClangCommentCommandInfo(Records, OS);
break;
+ case GenClangCommentCommandList:
+ EmitClangCommentCommandList(Records, OS);
+ break;
case GenOptParserDefs:
EmitOptParser(Records, OS, true);
break;
void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS);
void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);