Comment AST: add InlineContentComment::RenderKind to specify a default
rendering mode for clients that don't want to interpret Doxygen commands.

Also add a libclang API to query this information.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160633 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 0c45697..c21dafd 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -3308,6 +3308,33 @@
 };
 
 /**
+ * \brief The most appropriate rendering mode for an inline command, chosen on
+ * command semantics in Doxygen.
+ */
+enum CXCommentInlineCommandRenderKind {
+  /**
+   * \brief Command argument should be rendered in a normal font.
+   */
+  CXCommentInlineCommandRenderKind_Normal,
+
+  /**
+   * \brief Command argument should be rendered in a bold font.
+   */
+  CXCommentInlineCommandRenderKind_Bold,
+
+  /**
+   * \brief Command argument should be rendered in a monospaced font.
+   */
+  CXCommentInlineCommandRenderKind_Monospaced,
+
+  /**
+   * \brief Command argument should be rendered emphasized (typically italic
+   * font).
+   */
+  CXCommentInlineCommandRenderKind_Emphasized
+};
+
+/**
  * \brief Describes parameter passing direction for \\param or \\arg command.
  */
 enum CXCommentParamPassDirection {
@@ -3388,6 +3415,15 @@
 /**
  * \param Comment a \c CXComment_InlineCommand AST node.
  *
+ * \returns the most appropriate rendering mode, chosen on command
+ * semantics in Doxygen.
+ */
+CINDEX_LINKAGE enum CXCommentInlineCommandRenderKind
+clang_InlineCommandComment_getRenderKind(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
  * \returns number of command arguments.
  */
 CINDEX_LINKAGE
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index 544a7e4..55cb081 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -63,6 +63,15 @@
   };
   enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
 
+  class InlineCommandCommentBitfields {
+    friend class InlineCommandComment;
+
+    unsigned : NumInlineContentCommentBits;
+
+    unsigned RenderKind : 2;
+  };
+  enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 1 };
+
   class HTMLStartTagCommentBitfields {
     friend class HTMLStartTagComment;
 
@@ -104,6 +113,7 @@
     CommentBitfields CommentBits;
     InlineContentCommentBitfields InlineContentCommentBits;
     TextCommentBitfields TextCommentBits;
+    InlineCommandCommentBitfields InlineCommandCommentBits;
     HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
     ParagraphCommentBitfields ParagraphCommentBits;
     ParamCommandCommentBitfields ParamCommandCommentBits;
@@ -248,6 +258,15 @@
     Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
   };
 
+  /// The most appropriate rendering mode for this command, chosen on command
+  /// semantics in Doxygen.
+  enum RenderKind {
+    RenderNormal,
+    RenderBold,
+    RenderMonospaced,
+    RenderEmphasized
+  };
+
 protected:
   /// Command name.
   StringRef Name;
@@ -259,10 +278,12 @@
   InlineCommandComment(SourceLocation LocBegin,
                        SourceLocation LocEnd,
                        StringRef Name,
+                       RenderKind RK,
                        llvm::ArrayRef<Argument> Args) :
-    InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
-    Name(Name), Args(Args)
-  { }
+      InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
+      Name(Name), Args(Args) {
+    InlineCommandCommentBits.RenderKind = RK;
+  }
 
   static bool classof(const Comment *C) {
     return C->getCommentKind() == InlineCommandCommentKind;
@@ -283,6 +304,10 @@
                        getLocEnd());
   }
 
+  RenderKind getRenderKind() const {
+    return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
+  }
+
   unsigned getNumArgs() const {
     return Args.size();
   }
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 14be08a..be8179d 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -155,7 +155,10 @@
   bool isParamCommand(StringRef Name);
   unsigned getBlockCommandNumArgs(StringRef Name);
 
-  bool isInlineCommand(StringRef Name);
+  bool isInlineCommand(StringRef Name) const;
+
+  InlineCommandComment::RenderKind
+  getInlineCommandRenderKind(StringRef Name) const;
 
   bool isHTMLEndTagOptional(StringRef Name);
   bool isHTMLEndTagForbidden(StringRef Name);
diff --git a/lib/AST/CommentDumper.cpp b/lib/AST/CommentDumper.cpp
index 7a4ca0c..c930b24 100644
--- a/lib/AST/CommentDumper.cpp
+++ b/lib/AST/CommentDumper.cpp
@@ -107,6 +107,21 @@
   dumpComment(C);
 
   OS << " Name=\"" << C->getCommandName() << "\"";
+  switch (C->getRenderKind()) {
+  case InlineCommandComment::RenderNormal:
+    OS << " RenderNormal";
+    break;
+  case InlineCommandComment::RenderBold:
+    OS << " RenderBold";
+    break;
+  case InlineCommandComment::RenderMonospaced:
+    OS << " RenderMonospaced";
+    break;
+  case InlineCommandComment::RenderEmphasized:
+    OS << " RenderEmphasized";
+    break;
+  }
+
   for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
     OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
 }
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index 3d8635f..6c37452 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -202,10 +202,12 @@
                                                SourceLocation CommandLocEnd,
                                                StringRef CommandName) {
   ArrayRef<InlineCommandComment::Argument> Args;
-  return new (Allocator) InlineCommandComment(CommandLocBegin,
-                                              CommandLocEnd,
-                                              CommandName,
-                                              Args);
+  return new (Allocator) InlineCommandComment(
+                                  CommandLocBegin,
+                                  CommandLocEnd,
+                                  CommandName,
+                                  getInlineCommandRenderKind(CommandName),
+                                  Args);
 }
 
 InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
@@ -219,17 +221,22 @@
                                                      ArgLocEnd),
                                          Arg);
 
-  return new (Allocator) InlineCommandComment(CommandLocBegin,
-                                              CommandLocEnd,
-                                              CommandName,
-                                              llvm::makeArrayRef(A, 1));
+  return new (Allocator) InlineCommandComment(
+                                  CommandLocBegin,
+                                  CommandLocEnd,
+                                  CommandName,
+                                  getInlineCommandRenderKind(CommandName),
+                                  llvm::makeArrayRef(A, 1));
 }
 
 InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
                                                 SourceLocation LocEnd,
                                                 StringRef Name) {
   ArrayRef<InlineCommandComment::Argument> Args;
-  return new (Allocator) InlineCommandComment(LocBegin, LocEnd, Name, Args);
+  return new (Allocator) InlineCommandComment(
+                                  LocBegin, LocEnd, Name,
+                                  InlineCommandComment::RenderNormal,
+                                  Args);
 }
 
 TextComment *Sema::actOnText(SourceLocation LocBegin,
@@ -445,7 +452,7 @@
       .Default(0);
 }
 
-bool Sema::isInlineCommand(StringRef Name) {
+bool Sema::isInlineCommand(StringRef Name) const {
   return llvm::StringSwitch<bool>(Name)
       .Case("b", true)
       .Cases("c", "p", true)
@@ -453,6 +460,17 @@
       .Default(false);
 }
 
+InlineCommandComment::RenderKind
+Sema::getInlineCommandRenderKind(StringRef Name) const {
+  assert(isInlineCommand(Name));
+
+  return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
+      .Case("b", InlineCommandComment::RenderBold)
+      .Cases("c", "p", InlineCommandComment::RenderMonospaced)
+      .Cases("a", "e", "em", InlineCommandComment::RenderEmphasized)
+      .Default(InlineCommandComment::RenderNormal);
+}
+
 bool Sema::isHTMLEndTagOptional(StringRef Name) {
   return llvm::StringSwitch<bool>(Name)
       .Case("p", true)
diff --git a/test/Index/annotate-comments.cpp b/test/Index/annotate-comments.cpp
index 872a9fa..980f30b 100644
--- a/test/Index/annotate-comments.cpp
+++ b/test/Index/annotate-comments.cpp
@@ -572,25 +572,25 @@
 // CHECK-NEXT:    (CXComment_FullComment
 // CHECK-NEXT:       (CXComment_Paragraph
 // CHECK-NEXT:         (CXComment_Text Text=[ ] IsWhitespace)
-// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[b] Arg[0]=Aaa)))]
+// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[b] RenderBold Arg[0]=Aaa)))]
 // CHECK: annotate-comments.cpp:307:6: FunctionDecl=comment_to_html_conversion_19:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <tt>Aaa</tt> <tt>Bbb</tt></p>]
 // CHECK-NEXT:  CommentAST=[
 // CHECK-NEXT:    (CXComment_FullComment
 // CHECK-NEXT:       (CXComment_Paragraph
 // CHECK-NEXT:         (CXComment_Text Text=[ ] IsWhitespace)
-// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[c] Arg[0]=Aaa)
+// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[c] RenderMonospaced Arg[0]=Aaa)
 // CHECK-NEXT:         (CXComment_Text Text=[ ] IsWhitespace)
-// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[p] Arg[0]=Bbb)))]
+// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[p] RenderMonospaced Arg[0]=Bbb)))]
 // CHECK: annotate-comments.cpp:310:6: FunctionDecl=comment_to_html_conversion_20:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>Aaa</em> <em>Bbb</em> <em>Ccc</em></p>]
 // CHECK-NEXT:  CommentAST=[
 // CHECK-NEXT:    (CXComment_FullComment
 // CHECK-NEXT:       (CXComment_Paragraph
 // CHECK-NEXT:         (CXComment_Text Text=[ ] IsWhitespace)
-// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[a] Arg[0]=Aaa)
+// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[a] RenderEmphasized Arg[0]=Aaa)
 // CHECK-NEXT:         (CXComment_Text Text=[ ] IsWhitespace)
-// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[e] Arg[0]=Bbb)
+// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[e] RenderEmphasized Arg[0]=Bbb)
 // CHECK-NEXT:         (CXComment_Text Text=[ ] IsWhitespace)
-// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[em] Arg[0]=Ccc)))]
+// CHECK-NEXT:         (CXComment_InlineCommand CommandName=[em] RenderEmphasized Arg[0]=Ccc)))]
 // CHECK: annotate-comments.cpp:313:6: FunctionDecl=comment_to_html_conversion_21:{{.*}} FullCommentAsHTML=[<p class="para-brief"> \ @ &amp; $ # &lt; &gt; % &quot; . ::</p>]
 // CHECK-NEXT:  CommentAST=[
 // CHECK-NEXT:    (CXComment_FullComment
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 574c9f7..df7c72a 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -283,6 +283,20 @@
     PrintCXStringWithPrefixAndDispose(
         "CommandName",
         clang_InlineCommandComment_getCommandName(Comment));
+    switch (clang_InlineCommandComment_getRenderKind(Comment)) {
+    case CXCommentInlineCommandRenderKind_Normal:
+      printf(" RenderNormal");
+      break;
+    case CXCommentInlineCommandRenderKind_Bold:
+      printf(" RenderBold");
+      break;
+    case CXCommentInlineCommandRenderKind_Monospaced:
+      printf(" RenderMonospaced");
+      break;
+    case CXCommentInlineCommandRenderKind_Emphasized:
+      printf(" RenderEmphasized");
+      break;
+    }
     for (i = 0, e = clang_InlineCommandComment_getNumArgs(Comment);
          i != e; ++i) {
       printf(" Arg[%u]=", i);
diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp
index b0ed9bc..6cd9235 100644
--- a/tools/libclang/CXComment.cpp
+++ b/tools/libclang/CXComment.cpp
@@ -126,6 +126,28 @@
   return createCXString(ICC->getCommandName(), /*DupString=*/ false);
 }
 
+enum CXCommentInlineCommandRenderKind
+clang_InlineCommandComment_getRenderKind(CXComment CXC) {
+  const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+  if (!ICC)
+    return CXCommentInlineCommandRenderKind_Normal;
+
+  switch (ICC->getRenderKind()) {
+  case InlineCommandComment::RenderNormal:
+    return CXCommentInlineCommandRenderKind_Normal;
+
+  case InlineCommandComment::RenderBold:
+    return CXCommentInlineCommandRenderKind_Bold;
+
+  case InlineCommandComment::RenderMonospaced:
+    return CXCommentInlineCommandRenderKind_Monospaced;
+
+  case InlineCommandComment::RenderEmphasized:
+    return CXCommentInlineCommandRenderKind_Emphasized;
+  }
+  llvm_unreachable("unknown InlineCommandComment::RenderKind");
+}
+
 unsigned clang_InlineCommandComment_getNumArgs(CXComment CXC) {
   const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
   if (!ICC)
@@ -344,34 +366,34 @@
 
 void CommentASTToHTMLConverter::visitInlineCommandComment(
                                   const InlineCommandComment *C) {
-  StringRef CommandName = C->getCommandName();
-  bool HasArg0 = C->getNumArgs() > 0 && !C->getArgText(0).empty();
-  StringRef Arg0;
-  if (HasArg0)
-    Arg0 = C->getArgText(0);
+  // Nothing to render if no arguments supplied.
+  if (C->getNumArgs() == 0)
+    return;
 
-  if (CommandName == "b") {
-    if (!HasArg0)
-      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)
+      Result << C->getArgText(i) << " ";
+    return;
+
+  case InlineCommandComment::RenderBold:
+    assert(C->getNumArgs() == 1);
     Result << "<b>" << Arg0 << "</b>";
     return;
-  }
-  if (CommandName == "c" || CommandName == "p") {
-    if (!HasArg0)
-      return;
+  case InlineCommandComment::RenderMonospaced:
+    assert(C->getNumArgs() == 1);
     Result << "<tt>" << Arg0 << "</tt>";
     return;
-  }
-  if (CommandName == "a" || CommandName == "e" || CommandName == "em") {
-    if (!HasArg0)
-      return;
+  case InlineCommandComment::RenderEmphasized:
+    assert(C->getNumArgs() == 1);
     Result << "<em>" << Arg0 << "</em>";
     return;
   }
-
-  // We don't recognize this command, so just print its arguments.
-  for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
-    Result << C->getArgText(i) << " ";
 }
 
 void CommentASTToHTMLConverter::visitHTMLStartTagComment(
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 7d3b2a9..bc8c113 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -25,6 +25,7 @@
 clang_InlineContentComment_hasTrailingNewline
 clang_TextComment_getText
 clang_InlineCommandComment_getCommandName
+clang_InlineCommandComment_getRenderKind
 clang_InlineCommandComment_getNumArgs
 clang_InlineCommandComment_getArgText
 clang_HTMLTagComment_getTagName