* \brief A comment AST node.
*/
typedef struct {
- const void *Data;
+ const void *ASTNode;
+ CXTranslationUnit TranslationUnit;
} CXComment;
/**
* A Relax NG schema for the XML can be found in comment-xml-schema.rng file
* inside clang source tree.
*
- * \param TU the translation unit \c Comment belongs to.
- *
* \param Comment a \c CXComment_FullComment AST node.
*
* \returns string containing an XML document.
*/
-CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXTranslationUnit TU,
- CXComment Comment);
+CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment);
/**
* @}
#include "clang/AST/Type.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/RawCommentList.h"
+#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
/// Returns NULL if no comment is attached.
comments::FullComment *getCommentForDecl(const Decl *D) const;
+private:
+ mutable comments::CommandTraits CommentCommandTraits;
+
+public:
+ comments::CommandTraits &getCommentCommandTraits() const {
+ return CommentCommandTraits;
+ }
+
/// \brief Retrieve the attributes for the given declaration.
AttrVec& getDeclAttrs(const Decl *D);
SOURCE CommentHTMLTags.td
TARGET ClangCommentHTMLTagsProperties)
+clang_tablegen(CommentCommandInfo.inc -gen-clang-comment-command-info
+ SOURCE CommentCommands.td
+ TARGET ClangCommentCommandInfo)
+
#include "clang/Basic/SourceLocation.h"
#include "clang/AST/Type.h"
+#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
unsigned : NumInlineContentCommentBits;
unsigned RenderKind : 2;
+ unsigned CommandID : 8;
};
- enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 1 };
+ enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 };
class HTMLStartTagCommentBitfields {
friend class HTMLStartTagComment;
};
enum { NumParagraphCommentBits = NumCommentBits + 2 };
+ class BlockCommandCommentBitfields {
+ friend class BlockCommandComment;
+
+ unsigned : NumCommentBits;
+
+ unsigned CommandID : 8;
+ };
+ enum { NumBlockCommandCommentBits = NumCommentBits + 8 };
+
class ParamCommandCommentBitfields {
friend class ParamCommandComment;
- unsigned : NumCommentBits;
+ unsigned : NumBlockCommandCommentBits;
/// Parameter passing direction, see ParamCommandComment::PassDirection.
unsigned Direction : 2;
/// True if direction was specified explicitly in the comment.
unsigned IsDirectionExplicit : 1;
};
- enum { NumParamCommandCommentBits = 11 };
+ enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };
union {
CommentBitfields CommentBits;
InlineCommandCommentBitfields InlineCommandCommentBits;
HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
ParagraphCommentBitfields ParagraphCommentBits;
+ BlockCommandCommentBitfields BlockCommandCommentBits;
ParamCommandCommentBitfields ParamCommandCommentBits;
};
const char *getCommentKindName() const;
LLVM_ATTRIBUTE_USED void dump() const;
- LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const;
- void dump(llvm::raw_ostream &OS, SourceManager *SM) const;
+ LLVM_ATTRIBUTE_USED void dump(const ASTContext &Context) const;
+ void dump(llvm::raw_ostream &OS, const CommandTraits *Traits,
+ const SourceManager *SM) const;
static bool classof(const Comment *) { return true; }
};
protected:
- /// Command name.
- StringRef Name;
-
/// Command arguments.
llvm::ArrayRef<Argument> Args;
public:
InlineCommandComment(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name,
+ unsigned CommandID,
RenderKind RK,
llvm::ArrayRef<Argument> Args) :
InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
- Name(Name), Args(Args) {
+ Args(Args) {
InlineCommandCommentBits.RenderKind = RK;
+ InlineCommandCommentBits.CommandID = CommandID;
}
static bool classof(const Comment *C) {
child_iterator child_end() const { return NULL; }
- StringRef getCommandName() const {
- return Name;
+ unsigned getCommandID() const {
+ return InlineCommandCommentBits.CommandID;
+ }
+
+ StringRef getCommandName(const CommandTraits &Traits) const {
+ return Traits.getCommandInfo(getCommandID())->Name;
}
SourceRange getCommandNameRange() const {
};
protected:
- /// Command name.
- StringRef Name;
-
/// Word-like arguments.
llvm::ArrayRef<Argument> Args;
BlockCommandComment(CommentKind K,
SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) :
+ unsigned CommandID) :
BlockContentComment(K, LocBegin, LocEnd),
- Name(Name),
Paragraph(NULL) {
- setLocation(getCommandNameRange().getBegin());
+ setLocation(getCommandNameBeginLoc());
+ BlockCommandCommentBits.CommandID = CommandID;
}
public:
BlockCommandComment(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) :
+ unsigned CommandID) :
BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
- Name(Name),
Paragraph(NULL) {
- setLocation(getCommandNameRange().getBegin());
+ setLocation(getCommandNameBeginLoc());
+ BlockCommandCommentBits.CommandID = CommandID;
}
static bool classof(const Comment *C) {
return reinterpret_cast<child_iterator>(&Paragraph + 1);
}
- StringRef getCommandName() const {
- return Name;
+ unsigned getCommandID() const {
+ return BlockCommandCommentBits.CommandID;
}
- SourceRange getCommandNameRange() const {
- return SourceRange(getLocStart().getLocWithOffset(1),
+ StringRef getCommandName(const CommandTraits &Traits) const {
+ return Traits.getCommandInfo(getCommandID())->Name;
+ }
+
+ SourceLocation getCommandNameBeginLoc() const {
+ return getLocStart().getLocWithOffset(1);
+ }
+
+ SourceRange getCommandNameRange(const CommandTraits &Traits) const {
+ StringRef Name = getCommandName(Traits);
+ return SourceRange(getCommandNameBeginLoc(),
getLocStart().getLocWithOffset(1 + Name.size()));
}
ParamCommandComment(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) :
- BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name),
+ unsigned CommandID) :
+ BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
+ CommandID),
ParamIndex(InvalidParamIndex) {
ParamCommandCommentBits.Direction = In;
ParamCommandCommentBits.IsDirectionExplicit = false;
public:
TParamCommandComment(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) :
- BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, Name)
+ unsigned CommandID) :
+ BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID)
{ }
static bool classof(const Comment *C) {
public:
VerbatimBlockComment(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) :
+ unsigned CommandID) :
BlockCommandComment(VerbatimBlockCommentKind,
- LocBegin, LocEnd, Name)
+ LocBegin, LocEnd, CommandID)
{ }
static bool classof(const Comment *C) {
public:
VerbatimLineComment(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name,
+ unsigned CommandID,
SourceLocation TextBegin,
StringRef Text) :
BlockCommandComment(VerbatimLineCommentKind,
LocBegin, LocEnd,
- Name),
+ CommandID),
Text(Text),
TextBegin(TextBegin)
{ }
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace comments {
-/// This class provides informaiton about commands that can be used
-/// in comments.
-class CommandTraits {
-public:
- CommandTraits() { }
+/// \brief Information about a single command.
+///
+/// When reordering, adding or removing members please update the corresponding
+/// TableGen backend.
+struct CommandInfo {
+ unsigned getID() const {
+ return ID;
+ }
+
+ const char *Name;
+
+ /// Name of the command that ends the verbatim block.
+ const char *EndCommandName;
+
+ unsigned ID : 8;
+
+ /// Number of word-like arguments for a given block command, except for
+ /// \\param and \\tparam commands -- these have special argument parsers.
+ unsigned NumArgs : 4;
+
+ /// True if this command is a inline command (of any kind).
+ unsigned IsInlineCommand : 1;
+
+ /// True if this command is a block command (of any kind).
+ unsigned IsBlockCommand : 1;
+
+ /// True if this command is introducing a brief documentation
+ /// paragraph (\\brief or an alias).
+ unsigned IsBriefCommand : 1;
+
+ /// True if this command is \\returns or an alias.
+ unsigned IsReturnsCommand : 1;
+
+ /// True if this command is introducing documentation for a function
+ /// parameter (\\param or an alias).
+ unsigned IsParamCommand : 1;
- /// \brief Check if a given command is a verbatim-like block command.
+ /// True if this command is introducing documentation for
+ /// a template parameter (\\tparam or an alias).
+ unsigned IsTParamCommand : 1;
+
+ /// \brief True if this command is a verbatim-like block command.
///
/// A verbatim-like block command eats every character (except line starting
/// decorations) until matching end command is seen or comment end is hit.
- ///
- /// \param StartName name of the command that starts the verbatim block.
- /// \param [out] EndName name of the command that ends the verbatim block.
- ///
- /// \returns true if a given command is a verbatim block command.
- bool isVerbatimBlockCommand(StringRef StartName, StringRef &EndName) const;
+ unsigned IsVerbatimBlockCommand : 1;
- /// \brief Register a new verbatim block command.
- void addVerbatimBlockCommand(StringRef StartName, StringRef EndName);
+ /// \brief True if this command is an end command for a verbatim-like block.
+ unsigned IsVerbatimBlockEndCommand : 1;
- /// \brief Check if a given command is a verbatim line command.
+ /// \brief True if this command is a verbatim line command.
///
/// A verbatim-like line command eats everything until a newline is seen or
/// comment end is hit.
- bool isVerbatimLineCommand(StringRef Name) const;
+ unsigned IsVerbatimLineCommand : 1;
- /// \brief Check if a given command is a command that contains a declaration
- /// for the entity being documented.
+ /// \brief True if this command contains a declaration for the entity being
+ /// documented.
///
/// For example:
/// \code
/// \fn void f(int a);
/// \endcode
- bool isDeclarationCommand(StringRef Name) const;
+ unsigned IsDeclarationCommand : 1;
- /// \brief Register a new verbatim line command.
- void addVerbatimLineCommand(StringRef Name);
+ /// \brief True if this command is unknown. This \c CommandInfo object was
+ /// created during parsing.
+ unsigned IsUnknownCommand : 1;
+};
- /// \brief Check if a given command is a block command (of any kind).
- bool isBlockCommand(StringRef Name) const;
+/// This class provides information about commands that can be used
+/// in comments.
+class CommandTraits {
+public:
+ CommandTraits(llvm::BumpPtrAllocator &Allocator);
- /// \brief Check if a given command is introducing documentation for
- /// a function parameter (\\param or an alias).
- bool isParamCommand(StringRef Name) const;
+ /// \returns a CommandInfo object for a given command name or
+ /// NULL if no CommandInfo object exists for this command.
+ const CommandInfo *getCommandInfoOrNULL(StringRef Name) const;
- /// \brief Check if a given command is introducing documentation for
- /// a template parameter (\\tparam or an alias).
- bool isTParamCommand(StringRef Name) const;
+ const CommandInfo *getCommandInfo(StringRef Name) const {
+ if (const CommandInfo *Info = getCommandInfoOrNULL(Name))
+ return Info;
+ llvm_unreachable("the command should be known");
+ }
- /// \brief Check if a given command is introducing a brief documentation
- /// paragraph (\\brief or an alias).
- bool isBriefCommand(StringRef Name) const;
+ const CommandInfo *getCommandInfo(unsigned CommandID) const;
- /// \brief Check if a given command is \\brief or an alias.
- bool isReturnsCommand(StringRef Name) const;
+ const CommandInfo *registerUnknownCommand(StringRef CommandName);
- /// \returns the number of word-like arguments for a given block command,
- /// except for \\param and \\tparam commands -- these have special argument
- /// parsers.
- unsigned getBlockCommandNumArgs(StringRef Name) const;
+ /// \returns a CommandInfo object for a given command name or
+ /// NULL if \c Name is not a builtin command.
+ static const CommandInfo *getBuiltinCommandInfo(StringRef Name);
- /// \brief Check if a given command is a inline command (of any kind).
- bool isInlineCommand(StringRef Name) const;
+ /// \returns a CommandInfo object for a given command ID or
+ /// NULL if \c CommandID is not a builtin command.
+ static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID);
private:
- struct VerbatimBlockCommand {
- StringRef StartName;
- StringRef EndName;
- };
-
- typedef SmallVector<VerbatimBlockCommand, 4> VerbatimBlockCommandVector;
+ CommandTraits(const CommandTraits &) LLVM_DELETED_FUNCTION;
+ void operator=(const CommandTraits &) LLVM_DELETED_FUNCTION;
- /// Registered additional verbatim-like block commands.
- VerbatimBlockCommandVector VerbatimBlockCommands;
+ const CommandInfo *getRegisteredCommandInfo(StringRef Name) const;
+ const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const;
- struct VerbatimLineCommand {
- StringRef Name;
- };
+ unsigned NextID;
- typedef SmallVector<VerbatimLineCommand, 4> VerbatimLineCommandVector;
+ /// Allocator for CommandInfo objects.
+ llvm::BumpPtrAllocator &Allocator;
- /// Registered verbatim-like line commands.
- VerbatimLineCommandVector VerbatimLineCommands;
+ SmallVector<CommandInfo *, 4> RegisteredCommands;
};
-inline bool CommandTraits::isBlockCommand(StringRef Name) const {
- return isBriefCommand(Name) || isReturnsCommand(Name) ||
- isParamCommand(Name) || isTParamCommand(Name) ||
- llvm::StringSwitch<bool>(Name)
- .Case("author", true)
- .Case("authors", true)
- .Case("pre", true)
- .Case("post", true)
- .Default(false);
-}
-
-inline bool CommandTraits::isParamCommand(StringRef Name) const {
- return Name == "param";
-}
-
-inline bool CommandTraits::isTParamCommand(StringRef Name) const {
- return Name == "tparam" || // Doxygen
- Name == "templatefield"; // HeaderDoc
-}
-
-inline bool CommandTraits::isBriefCommand(StringRef Name) const {
- return Name == "brief" || Name == "short";
-}
-
-inline bool CommandTraits::isReturnsCommand(StringRef Name) const {
- return Name == "returns" || Name == "return" || Name == "result";
-}
-
-inline unsigned CommandTraits::getBlockCommandNumArgs(StringRef Name) const {
- return 0;
-}
-
-inline bool CommandTraits::isInlineCommand(StringRef Name) const {
- return llvm::StringSwitch<bool>(Name)
- .Case("b", true)
- .Cases("c", "p", true)
- .Cases("a", "e", "em", true)
- .Default(false);
-}
-
} // end namespace comments
} // end namespace clang
--- /dev/null
+class Command<string name> {
+ string Name = name;
+ string EndCommandName = "";
+
+ int NumArgs = 0;
+
+ bit IsInlineCommand = 0;
+
+ bit IsBlockCommand = 0;
+ bit IsBriefCommand = 0;
+ bit IsReturnsCommand = 0;
+ bit IsParamCommand = 0;
+ bit IsTParamCommand = 0;
+
+ bit IsVerbatimBlockCommand = 0;
+ bit IsVerbatimBlockEndCommand = 0;
+ bit IsVerbatimLineCommand = 0;
+ bit IsDeclarationCommand = 0;
+}
+
+class InlineCommand<string name> : Command<name> {
+ let IsInlineCommand = 1;
+}
+
+class BlockCommand<string name> : Command<name> {
+ let IsBlockCommand = 1;
+}
+
+class VerbatimBlockCommand<string name> : Command<name> {
+ let EndCommandName = name;
+ let IsVerbatimBlockCommand = 1;
+}
+
+multiclass VerbatimBlockCommand<string name, string endCommandName> {
+ def Begin : Command<name> {
+ let EndCommandName = endCommandName;
+ let IsVerbatimBlockCommand = 1;
+ }
+
+ def End : Command<endCommandName> {
+ let IsVerbatimBlockEndCommand = 1;
+ }
+}
+
+class VerbatimLineCommand<string name> : Command<name> {
+ let IsVerbatimLineCommand = 1;
+}
+
+class DeclarationVerbatimLineCommand<string name> :
+ VerbatimLineCommand<name> {
+ let IsDeclarationCommand = 1;
+}
+
+def B : InlineCommand<"b">;
+def C : InlineCommand<"c">;
+def P : InlineCommand<"p">;
+def A : InlineCommand<"a">;
+def E : InlineCommand<"e">;
+def Em : InlineCommand<"em">;
+
+def Brief : BlockCommand<"brief"> { let IsBriefCommand = 1; }
+def Short : BlockCommand<"short"> { let IsBriefCommand = 1; }
+
+def Returns : BlockCommand<"returns"> { let IsReturnsCommand = 1; }
+def Return : BlockCommand<"return"> { let IsReturnsCommand = 1; }
+def Result : BlockCommand<"result"> { let IsReturnsCommand = 1; }
+
+def Param : BlockCommand<"param"> { let IsParamCommand = 1; }
+
+// Doxygen
+def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; }
+
+// HeaderDoc
+def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; }
+
+def Author : BlockCommand<"author">;
+def Authors : BlockCommand<"authors">;
+def Pre : BlockCommand<"pre">;
+def Post : BlockCommand<"post">;
+
+defm Code : VerbatimBlockCommand<"code", "endcode">;
+defm Verbatim : VerbatimBlockCommand<"verbatim", "endverbatim">;
+defm Htmlonly : VerbatimBlockCommand<"htmlonly", "endhtmlonly">;
+defm Latexonly : VerbatimBlockCommand<"latexonly", "endlatexonly">;
+defm Xmlonly : VerbatimBlockCommand<"xmlonly", "endxmlonly">;
+defm Manonly : VerbatimBlockCommand<"manonly", "endmanonly">;
+defm Rtfonly : VerbatimBlockCommand<"rtfonly", "endrtfonly">;
+
+defm Dot : VerbatimBlockCommand<"dot", "enddot">;
+defm Msc : VerbatimBlockCommand<"msc", "endmsc">;
+
+// These commands have special support in lexer.
+def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula
+defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula
+defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment
+
+def Defgroup : VerbatimLineCommand<"defgroup">;
+def Ingroup : VerbatimLineCommand<"ingroup">;
+def Addtogroup : VerbatimLineCommand<"addtogroup">;
+def Weakgroup : VerbatimLineCommand<"weakgroup">;
+def Name : VerbatimLineCommand<"name">;
+
+def Section : VerbatimLineCommand<"section">;
+def Subsection : VerbatimLineCommand<"subsection">;
+def Subsubsection : VerbatimLineCommand<"subsubsection">;
+def Paragraph : VerbatimLineCommand<"paragraph">;
+
+def Mainpage : VerbatimLineCommand<"mainpage">;
+def Subpage : VerbatimLineCommand<"subpage">;
+def Ref : VerbatimLineCommand<"ref">;
+
+// Doxygen commands.
+def Fn : DeclarationVerbatimLineCommand<"fn">;
+def Var : DeclarationVerbatimLineCommand<"var">;
+def Property : DeclarationVerbatimLineCommand<"property">;
+def Typedef : DeclarationVerbatimLineCommand<"typedef">;
+def Overload : DeclarationVerbatimLineCommand<"overload">;
+
+// HeaderDoc commands.
+def Class : DeclarationVerbatimLineCommand<"class">;
+def Interface : DeclarationVerbatimLineCommand<"interface">;
+def Protocol : DeclarationVerbatimLineCommand<"protocol">;
+def Category : DeclarationVerbatimLineCommand<"category">;
+def Template : DeclarationVerbatimLineCommand<"template">;
+def Function : DeclarationVerbatimLineCommand<"function">;
+def Method : DeclarationVerbatimLineCommand<"method">;
+def Callback : DeclarationVerbatimLineCommand<"callback">;
+def Const : DeclarationVerbatimLineCommand<"const">;
+def Constant : DeclarationVerbatimLineCommand<"constant">;
+def Struct : DeclarationVerbatimLineCommand<"struct">;
+def Union : DeclarationVerbatimLineCommand<"union">;
+def Enum : DeclarationVerbatimLineCommand<"enum">;
+
class Lexer;
class TextTokenRetokenizer;
+struct CommandInfo;
class CommandTraits;
namespace tok {
eof,
newline,
text,
+ unknown_command,
command,
verbatim_block_begin,
verbatim_block_line,
unsigned Length;
/// Contains text value associated with a token.
- const char *TextPtr1;
- unsigned TextLen1;
+ const char *TextPtr;
+
+ /// Integer value associated with a token.
+ ///
+ /// If the token is a konwn command, contains command ID and TextPtr is
+ /// unused (command spelling can be found with CommandTraits). Otherwise,
+ /// contains the length of the string that starts at TextPtr.
+ unsigned IntVal;
public:
SourceLocation getLocation() const LLVM_READONLY { return Loc; }
StringRef getText() const LLVM_READONLY {
assert(is(tok::text));
- return StringRef(TextPtr1, TextLen1);
+ return StringRef(TextPtr, IntVal);
}
void setText(StringRef Text) {
assert(is(tok::text));
- TextPtr1 = Text.data();
- TextLen1 = Text.size();
+ TextPtr = Text.data();
+ IntVal = Text.size();
+ }
+
+ StringRef getUnknownCommandName() const LLVM_READONLY {
+ assert(is(tok::unknown_command));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setUnknownCommandName(StringRef Name) {
+ assert(is(tok::unknown_command));
+ TextPtr = Name.data();
+ IntVal = Name.size();
}
- StringRef getCommandName() const LLVM_READONLY {
+ unsigned getCommandID() const LLVM_READONLY {
assert(is(tok::command));
- return StringRef(TextPtr1, TextLen1);
+ return IntVal;
}
- void setCommandName(StringRef Name) {
+ void setCommandID(unsigned ID) {
assert(is(tok::command));
- TextPtr1 = Name.data();
- TextLen1 = Name.size();
+ IntVal = ID;
}
- StringRef getVerbatimBlockName() const LLVM_READONLY {
+ unsigned getVerbatimBlockID() const LLVM_READONLY {
assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
- return StringRef(TextPtr1, TextLen1);
+ return IntVal;
}
- void setVerbatimBlockName(StringRef Name) {
+ void setVerbatimBlockID(unsigned ID) {
assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
- TextPtr1 = Name.data();
- TextLen1 = Name.size();
+ IntVal = ID;
}
StringRef getVerbatimBlockText() const LLVM_READONLY {
assert(is(tok::verbatim_block_line));
- return StringRef(TextPtr1, TextLen1);
+ return StringRef(TextPtr, IntVal);
}
void setVerbatimBlockText(StringRef Text) {
assert(is(tok::verbatim_block_line));
- TextPtr1 = Text.data();
- TextLen1 = Text.size();
+ TextPtr = Text.data();
+ IntVal = Text.size();
}
- /// Returns the name of verbatim line command.
- StringRef getVerbatimLineName() const LLVM_READONLY {
+ unsigned getVerbatimLineID() const LLVM_READONLY {
assert(is(tok::verbatim_line_name));
- return StringRef(TextPtr1, TextLen1);
+ return IntVal;
}
- void setVerbatimLineName(StringRef Name) {
+ void setVerbatimLineID(unsigned ID) {
assert(is(tok::verbatim_line_name));
- TextPtr1 = Name.data();
- TextLen1 = Name.size();
+ IntVal = ID;
}
StringRef getVerbatimLineText() const LLVM_READONLY {
assert(is(tok::verbatim_line_text));
- return StringRef(TextPtr1, TextLen1);
+ return StringRef(TextPtr, IntVal);
}
void setVerbatimLineText(StringRef Text) {
assert(is(tok::verbatim_line_text));
- TextPtr1 = Text.data();
- TextLen1 = Text.size();
+ TextPtr = Text.data();
+ IntVal = Text.size();
}
StringRef getHTMLTagStartName() const LLVM_READONLY {
assert(is(tok::html_start_tag));
- return StringRef(TextPtr1, TextLen1);
+ return StringRef(TextPtr, IntVal);
}
void setHTMLTagStartName(StringRef Name) {
assert(is(tok::html_start_tag));
- TextPtr1 = Name.data();
- TextLen1 = Name.size();
+ TextPtr = Name.data();
+ IntVal = Name.size();
}
StringRef getHTMLIdent() const LLVM_READONLY {
assert(is(tok::html_ident));
- return StringRef(TextPtr1, TextLen1);
+ return StringRef(TextPtr, IntVal);
}
void setHTMLIdent(StringRef Name) {
assert(is(tok::html_ident));
- TextPtr1 = Name.data();
- TextLen1 = Name.size();
+ TextPtr = Name.data();
+ IntVal = Name.size();
}
StringRef getHTMLQuotedString() const LLVM_READONLY {
assert(is(tok::html_quoted_string));
- return StringRef(TextPtr1, TextLen1);
+ return StringRef(TextPtr, IntVal);
}
void setHTMLQuotedString(StringRef Str) {
assert(is(tok::html_quoted_string));
- TextPtr1 = Str.data();
- TextLen1 = Str.size();
+ TextPtr = Str.data();
+ IntVal = Str.size();
}
StringRef getHTMLTagEndName() const LLVM_READONLY {
assert(is(tok::html_end_tag));
- return StringRef(TextPtr1, TextLen1);
+ return StringRef(TextPtr, IntVal);
}
void setHTMLTagEndName(StringRef Name) {
assert(is(tok::html_end_tag));
- TextPtr1 = Name.data();
- TextLen1 = Name.size();
+ TextPtr = Name.data();
+ IntVal = Name.size();
}
void dump(const Lexer &L, const SourceManager &SM) const;
Result.setKind(Kind);
Result.setLength(TokLen);
#ifndef NDEBUG
- Result.TextPtr1 = "<UNSET>";
- Result.TextLen1 = 7;
+ Result.TextPtr = "<UNSET>";
+ Result.IntVal = 7;
#endif
BufferPtr = TokEnd;
}
void setupAndLexVerbatimBlock(Token &T,
const char *TextBegin,
- char Marker, StringRef EndName);
+ char Marker, const CommandInfo *Info);
void lexVerbatimBlockFirstLine(Token &T);
void lexVerbatimBlockBody(Token &T);
- void setupAndLexVerbatimLine(Token &T, const char *TextBegin);
+ void setupAndLexVerbatimLine(Token &T, const char *TextBegin,
+ const CommandInfo *Info);
void lexVerbatimLineText(Token &T);
DiagnosticsEngine &Diags;
- const CommandTraits &Traits;
+ CommandTraits &Traits;
/// Information about the declaration this comment is attached to.
DeclInfo *ThisDeclInfo;
public:
Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
- DiagnosticsEngine &Diags, const CommandTraits &Traits);
+ DiagnosticsEngine &Diags, CommandTraits &Traits);
void setDecl(const Decl *D);
BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name);
+ unsigned CommandID);
void actOnBlockCommandArgs(BlockCommandComment *Command,
ArrayRef<BlockCommandComment::Argument> Args);
ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name);
+ unsigned CommandID);
void actOnParamCommandDirectionArg(ParamCommandComment *Command,
SourceLocation ArgLocBegin,
TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name);
+ unsigned CommandID);
void actOnTParamCommandParamNameArg(TParamCommandComment *Command,
SourceLocation ArgLocBegin,
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
- StringRef CommandName);
+ unsigned CommandID);
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
- StringRef CommandName,
+ unsigned CommandID,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
StringRef Text);
VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc,
- StringRef Name);
+ unsigned CommandID);
VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc,
StringRef Text);
ArrayRef<VerbatimBlockLineComment *> Lines);
VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin,
- StringRef Name,
+ unsigned CommandID,
SourceLocation TextBegin,
StringRef Text);
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc \
CommentNodes.inc CommentHTMLTags.inc \
- CommentHTMLTagsProperties.inc
+ CommentHTMLTagsProperties.inc CommentCommandInfo.inc
TABLEGEN_INC_FILES_COMMON = 1
$(Echo) "Building Clang comment HTML tag properties with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-comment-html-tags-properties -o $(call SYSPATH, $@) $<
+$(ObjDir)/CommentCommandInfo.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \
+ $(CLANG_TBLGEN) $(ObjDir)/.dir
+ $(Echo) "Building Clang comment command info with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-comment-command-info -o $(call SYSPATH, $@) $<
+
DeclarationNames(*this),
ExternalSource(0), Listener(0),
Comments(SM), CommentsLoaded(false),
+ CommentCommandTraits(BumpAlloc),
LastSDM(0, 0),
UniqueBlockByRefTypeID(0)
{
ClangAttrClasses
ClangAttrList
ClangAttrImpl
+ ClangCommentCommandInfo
ClangCommentNodes
ClangCommentHTMLTags
ClangCommentHTMLTagsProperties
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Comment.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
// in CommentDumper.cpp, that object file would be removed by linker because
// none of its functions are referenced by other object files, despite the
// LLVM_ATTRIBUTE_USED.
- dump(llvm::errs(), NULL);
+ dump(llvm::errs(), NULL, NULL);
}
-void Comment::dump(SourceManager &SM) const {
- dump(llvm::errs(), &SM);
+void Comment::dump(const ASTContext &Context) const {
+ dump(llvm::errs(), &Context.getCommentCommandTraits(),
+ &Context.getSourceManager());
}
namespace {
}
if (Tok.is(tok::command)) {
- StringRef Name = Tok.getCommandName();
- if (Traits.isBriefCommand(Name)) {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
+ if (Info->IsBriefCommand) {
FirstParagraphOrBrief.clear();
InBrief = true;
ConsumeToken();
continue;
}
- if (Traits.isReturnsCommand(Name)) {
+ if (Info->IsReturnsCommand) {
InReturns = true;
InBrief = false;
InFirstParagraph = false;
continue;
}
// Block commands implicitly start a new paragraph.
- if (Traits.isBlockCommand(Name)) {
+ if (Info->IsBlockCommand) {
// We found an implicit paragraph end.
InFirstParagraph = false;
if (InBrief)
//===----------------------------------------------------------------------===//
#include "clang/AST/CommentCommandTraits.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/STLExtras.h"
namespace clang {
namespace comments {
-// TODO: tablegen
+#include "clang/AST/CommentCommandInfo.inc"
-bool CommandTraits::isVerbatimBlockCommand(StringRef StartName,
- StringRef &EndName) const {
- const char *Result = llvm::StringSwitch<const char *>(StartName)
- .Case("code", "endcode")
- .Case("verbatim", "endverbatim")
- .Case("htmlonly", "endhtmlonly")
- .Case("latexonly", "endlatexonly")
- .Case("xmlonly", "endxmlonly")
- .Case("manonly", "endmanonly")
- .Case("rtfonly", "endrtfonly")
+CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator) :
+ NextID(llvm::array_lengthof(Commands)), Allocator(Allocator)
+{ }
- .Case("dot", "enddot")
- .Case("msc", "endmsc")
-
- .Case("f$", "f$") // Inline LaTeX formula
- .Case("f[", "f]") // Displayed LaTeX formula
- .Case("f{", "f}") // LaTeX environment
-
- .Default(NULL);
-
- if (Result) {
- EndName = Result;
- return true;
- }
-
- for (VerbatimBlockCommandVector::const_iterator
- I = VerbatimBlockCommands.begin(),
- E = VerbatimBlockCommands.end();
- I != E; ++I)
- if (I->StartName == StartName) {
- EndName = I->EndName;
- return true;
- }
-
- return false;
+const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const {
+ if (const CommandInfo *Info = getBuiltinCommandInfo(Name))
+ return Info;
+ return getRegisteredCommandInfo(Name);
}
-bool CommandTraits::isVerbatimLineCommand(StringRef Name) const {
- bool Result = isDeclarationCommand(Name) || llvm::StringSwitch<bool>(Name)
- .Case("defgroup", true)
- .Case("ingroup", true)
- .Case("addtogroup", true)
- .Case("weakgroup", true)
- .Case("name", true)
-
- .Case("section", true)
- .Case("subsection", true)
- .Case("subsubsection", true)
- .Case("paragraph", true)
-
- .Case("mainpage", true)
- .Case("subpage", true)
- .Case("ref", true)
+const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {
+ if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID))
+ return Info;
+ return getRegisteredCommandInfo(CommandID);
+}
- .Default(false);
+const CommandInfo *CommandTraits::registerUnknownCommand(StringRef CommandName) {
+ char *Name = Allocator.Allocate<char>(CommandName.size());
+ memcpy(Name, CommandName.data(), CommandName.size());
+ Name[CommandName.size() + 1] = '\0';
- if (Result)
- return true;
+ // Value-initialize (=zero-initialize in this case) a new CommandInfo.
+ CommandInfo *Info = new (Allocator) CommandInfo();
+ Info->Name = Name;
+ Info->ID = NextID++;
- for (VerbatimLineCommandVector::const_iterator
- I = VerbatimLineCommands.begin(),
- E = VerbatimLineCommands.end();
- I != E; ++I)
- if (I->Name == Name)
- return true;
+ RegisteredCommands.push_back(Info);
- return false;
+ return Info;
}
-bool CommandTraits::isDeclarationCommand(StringRef Name) const {
- return llvm::StringSwitch<bool>(Name)
- // Doxygen commands.
- .Case("fn", true)
- .Case("var", true)
- .Case("property", true)
- .Case("typedef", true)
-
- .Case("overload", true)
-
- // HeaderDoc commands.
- .Case("class", true)
- .Case("interface", true)
- .Case("protocol", true)
- .Case("category", true)
- .Case("template", true)
- .Case("function", true)
- .Case("method", true)
- .Case("callback", true)
- .Case("var", true)
- .Case("const", true)
- .Case("constant", true)
- .Case("property", true)
- .Case("struct", true)
- .Case("union", true)
- .Case("typedef", true)
- .Case("enum", true)
-
- .Default(false);
+const CommandInfo *CommandTraits::getBuiltinCommandInfo(
+ unsigned CommandID) {
+ if (CommandID < llvm::array_lengthof(Commands))
+ return &Commands[CommandID];
+ return NULL;
}
-void CommandTraits::addVerbatimBlockCommand(StringRef StartName,
- StringRef EndName) {
- VerbatimBlockCommand VBC;
- VBC.StartName = StartName;
- VBC.EndName = EndName;
- VerbatimBlockCommands.push_back(VBC);
+const CommandInfo *CommandTraits::getRegisteredCommandInfo(
+ StringRef Name) const {
+ for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) {
+ if (RegisteredCommands[i]->Name == Name)
+ return RegisteredCommands[i];
+ }
+ return NULL;
}
-void CommandTraits::addVerbatimLineCommand(StringRef Name) {
- VerbatimLineCommand VLC;
- VLC.Name = Name;
- VerbatimLineCommands.push_back(VLC);
+const CommandInfo *CommandTraits::getRegisteredCommandInfo(
+ unsigned CommandID) const {
+ return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)];
}
} // end namespace comments
namespace {
class CommentDumper: public comments::ConstCommentVisitor<CommentDumper> {
raw_ostream &OS;
- SourceManager *SM;
+ const CommandTraits *Traits;
+ const SourceManager *SM;
unsigned IndentLevel;
public:
- CommentDumper(raw_ostream &OS, SourceManager *SM) :
- OS(OS), SM(SM), IndentLevel(0)
+ CommentDumper(raw_ostream &OS,
+ const CommandTraits *Traits,
+ const SourceManager *SM) :
+ OS(OS), Traits(Traits), SM(SM), IndentLevel(0)
{ }
void dumpIndent() const {
void visitVerbatimLineComment(const VerbatimLineComment *C);
void visitFullComment(const FullComment *C);
+
+ const char *getCommandName(unsigned CommandID) {
+ if (Traits)
+ return Traits->getCommandInfo(CommandID)->Name;
+ const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
+ if (Info)
+ return Info->Name;
+ return "<not a builtin command>";
+ }
};
void CommentDumper::dumpSourceRange(const Comment *C) {
void CommentDumper::visitInlineCommandComment(const InlineCommandComment *C) {
dumpComment(C);
- OS << " Name=\"" << C->getCommandName() << "\"";
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
switch (C->getRenderKind()) {
case InlineCommandComment::RenderNormal:
OS << " RenderNormal";
void CommentDumper::visitBlockCommandComment(const BlockCommandComment *C) {
dumpComment(C);
- OS << " Name=\"" << C->getCommandName() << "\"";
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
}
void CommentDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
dumpComment(C);
- OS << " Name=\"" << C->getCommandName() << "\""
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""
" CloseName=\"" << C->getCloseName() << "\"";
}
} // unnamed namespace
-void Comment::dump(llvm::raw_ostream &OS, SourceManager *SM) const {
- CommentDumper D(llvm::errs(), SM);
+void Comment::dump(llvm::raw_ostream &OS, const CommandTraits *Traits,
+ const SourceManager *SM) const {
+ CommentDumper D(llvm::errs(), Traits, SM);
D.dumpSubtree(this);
llvm::errs() << '\n';
}
}
const StringRef CommandName(BufferPtr + 1, Length);
- StringRef EndName;
- if (Traits.isVerbatimBlockCommand(CommandName, EndName)) {
- setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, EndName);
+ const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName);
+ if (!Info) {
+ formTokenWithChars(T, TokenPtr, tok::unknown_command);
+ T.setUnknownCommandName(CommandName);
return;
}
- if (Traits.isVerbatimLineCommand(CommandName)) {
- setupAndLexVerbatimLine(T, TokenPtr);
+ if (Info->IsVerbatimBlockCommand) {
+ setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info);
+ return;
+ }
+ if (Info->IsVerbatimLineCommand) {
+ setupAndLexVerbatimLine(T, TokenPtr, Info);
return;
}
formTokenWithChars(T, TokenPtr, tok::command);
- T.setCommandName(CommandName);
+ T.setCommandID(Info->getID());
return;
}
void Lexer::setupAndLexVerbatimBlock(Token &T,
const char *TextBegin,
- char Marker, StringRef EndName) {
+ char Marker, const CommandInfo *Info) {
+ assert(Info->IsVerbatimBlockCommand);
+
VerbatimBlockEndCommandName.clear();
VerbatimBlockEndCommandName.append(Marker == '\\' ? "\\" : "@");
- VerbatimBlockEndCommandName.append(EndName);
+ VerbatimBlockEndCommandName.append(Info->EndCommandName);
- StringRef Name(BufferPtr + 1, TextBegin - (BufferPtr + 1));
formTokenWithChars(T, TextBegin, tok::verbatim_block_begin);
- T.setVerbatimBlockName(Name);
+ T.setVerbatimBlockID(Info->getID());
// If there is a newline following the verbatim opening command, skip the
// newline so that we don't create an tok::verbatim_block_line with empty
const char *End = BufferPtr + VerbatimBlockEndCommandName.size();
StringRef Name(BufferPtr + 1, End - (BufferPtr + 1));
formTokenWithChars(T, End, tok::verbatim_block_end);
- T.setVerbatimBlockName(Name);
+ T.setVerbatimBlockID(Traits.getCommandInfo(Name)->getID());
State = LS_Normal;
return;
} else {
lexVerbatimBlockFirstLine(T);
}
-void Lexer::setupAndLexVerbatimLine(Token &T, const char *TextBegin) {
- const StringRef Name(BufferPtr + 1, TextBegin - BufferPtr - 1);
+void Lexer::setupAndLexVerbatimLine(Token &T, const char *TextBegin,
+ const CommandInfo *Info) {
+ assert(Info->IsVerbatimLineCommand);
formTokenWithChars(T, TextBegin, tok::verbatim_line_name);
- T.setVerbatimLineName(Name);
+ T.setVerbatimLineID(Info->getID());
State = LS_VerbatimLineText;
}
Result.setKind(tok::text);
Result.setLength(TokLength);
#ifndef NDEBUG
- Result.TextPtr1 = "<UNSET>";
- Result.TextLen1 = 7;
+ Result.TextPtr = "<UNSET>";
+ Result.IntVal = 7;
#endif
Result.setText(Text);
}
BlockCommandComment *BC;
bool IsParam = false;
bool IsTParam = false;
- unsigned NumArgs = 0;
- if (Traits.isParamCommand(Tok.getCommandName())) {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
+ if (Info->IsParamCommand) {
IsParam = true;
PC = S.actOnParamCommandStart(Tok.getLocation(),
Tok.getEndLocation(),
- Tok.getCommandName());
- } if (Traits.isTParamCommand(Tok.getCommandName())) {
+ Tok.getCommandID());
+ } if (Info->IsTParamCommand) {
IsTParam = true;
TPC = S.actOnTParamCommandStart(Tok.getLocation(),
Tok.getEndLocation(),
- Tok.getCommandName());
+ Tok.getCommandID());
} else {
- NumArgs = Traits.getBlockCommandNumArgs(Tok.getCommandName());
BC = S.actOnBlockCommandStart(Tok.getLocation(),
Tok.getEndLocation(),
- Tok.getCommandName());
+ Tok.getCommandID());
}
consumeToken();
- if (Tok.is(tok::command) && Traits.isBlockCommand(Tok.getCommandName())) {
+ if (Tok.is(tok::command) &&
+ Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand) {
// Block command ahead. We can't nest block commands, so pretend that this
// command has an empty argument.
ParagraphComment *Paragraph = S.actOnParagraphComment(
}
}
- if (IsParam || IsTParam || NumArgs > 0) {
+ if (IsParam || IsTParam || Info->NumArgs > 0) {
// In order to parse command arguments we need to retokenize a few
// following text tokens.
TextTokenRetokenizer Retokenizer(Allocator, *this);
else if (IsTParam)
parseTParamCommandArgs(TPC, Retokenizer);
else
- parseBlockCommandArgs(BC, Retokenizer, NumArgs);
+ parseBlockCommandArgs(BC, Retokenizer, Info->NumArgs);
Retokenizer.putBackLeftoverTokens();
}
if (ArgTokValid) {
IC = S.actOnInlineCommand(CommandTok.getLocation(),
CommandTok.getEndLocation(),
- CommandTok.getCommandName(),
+ CommandTok.getCommandID(),
ArgTok.getLocation(),
ArgTok.getEndLocation(),
ArgTok.getText());
} else {
IC = S.actOnInlineCommand(CommandTok.getLocation(),
CommandTok.getEndLocation(),
- CommandTok.getCommandName());
+ CommandTok.getCommandID());
}
Retokenizer.putBackLeftoverTokens();
assert(Content.size() != 0);
break; // Block content or EOF ahead, finish this parapgaph.
- case tok::command:
- if (Traits.isBlockCommand(Tok.getCommandName())) {
+ case tok::unknown_command:
+ Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
+ Tok.getEndLocation(),
+ Tok.getUnknownCommandName()));
+ consumeToken();
+ continue;
+
+ case tok::command: {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
+ if (Info->IsBlockCommand) {
if (Content.size() == 0)
return parseBlockCommand();
break; // Block command ahead, finish this parapgaph.
}
- if (Traits.isInlineCommand(Tok.getCommandName())) {
- Content.push_back(parseInlineCommand());
- continue;
- }
-
- // Not a block command, not an inline command ==> an unknown command.
- Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
- Tok.getEndLocation(),
- Tok.getCommandName()));
- consumeToken();
+ assert(Info->IsInlineCommand);
+ Content.push_back(parseInlineCommand());
continue;
+ }
case tok::newline: {
consumeToken();
VerbatimBlockComment *VB =
S.actOnVerbatimBlockStart(Tok.getLocation(),
- Tok.getVerbatimBlockName());
+ Tok.getVerbatimBlockID());
consumeToken();
// Don't create an empty line if verbatim opening command is followed
}
if (Tok.is(tok::verbatim_block_end)) {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getVerbatimBlockID());
S.actOnVerbatimBlockFinish(VB, Tok.getLocation(),
- Tok.getVerbatimBlockName(),
+ Info->Name,
S.copyArray(llvm::makeArrayRef(Lines)));
consumeToken();
} else {
}
VerbatimLineComment *VL = S.actOnVerbatimLine(NameTok.getLocation(),
- NameTok.getVerbatimLineName(),
+ NameTok.getVerbatimLineID(),
TextBegin,
Text);
consumeToken();
BlockContentComment *Parser::parseBlockContent() {
switch (Tok.getKind()) {
case tok::text:
+ case tok::unknown_command:
case tok::command:
case tok::html_start_tag:
case tok::html_end_tag:
} // unnamed namespace
Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
- DiagnosticsEngine &Diags, const CommandTraits &Traits) :
+ DiagnosticsEngine &Diags, CommandTraits &Traits) :
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) {
}
BlockCommandComment *Sema::actOnBlockCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) {
- return new (Allocator) BlockCommandComment(LocBegin, LocEnd, Name);
+ unsigned CommandID) {
+ return new (Allocator) BlockCommandComment(LocBegin, LocEnd, CommandID);
}
void Sema::actOnBlockCommandArgs(BlockCommandComment *Command,
ParamCommandComment *Sema::actOnParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) {
+ unsigned CommandID) {
ParamCommandComment *Command =
- new (Allocator) ParamCommandComment(LocBegin, LocEnd, Name);
+ new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID);
if (!isFunctionDecl())
Diag(Command->getLocation(),
diag::warn_doc_param_not_attached_to_a_function_decl)
- << Command->getCommandNameRange();
+ << Command->getCommandNameRange(Traits);
return Command;
}
TParamCommandComment *Sema::actOnTParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) {
+ unsigned CommandID) {
TParamCommandComment *Command =
- new (Allocator) TParamCommandComment(LocBegin, LocEnd, Name);
+ new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID);
if (!isTemplateOrSpecialization())
Diag(Command->getLocation(),
diag::warn_doc_tparam_not_attached_to_a_template_decl)
- << Command->getCommandNameRange();
+ << Command->getCommandNameRange(Traits);
return Command;
}
InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
- StringRef CommandName) {
+ unsigned CommandID) {
ArrayRef<InlineCommandComment::Argument> Args;
+ StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
return new (Allocator) InlineCommandComment(
CommandLocBegin,
CommandLocEnd,
- CommandName,
+ CommandID,
getInlineCommandRenderKind(CommandName),
Args);
}
InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
- StringRef CommandName,
+ unsigned CommandID,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg) {
Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
ArgLocEnd),
Arg);
+ StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
return new (Allocator) InlineCommandComment(
CommandLocBegin,
CommandLocEnd,
- CommandName,
+ CommandID,
getInlineCommandRenderKind(CommandName),
llvm::makeArrayRef(A, 1));
}
SourceLocation LocEnd,
StringRef Name) {
ArrayRef<InlineCommandComment::Argument> Args;
+ unsigned CommandID = Traits.registerUnknownCommand(Name)->getID();
return new (Allocator) InlineCommandComment(
- LocBegin, LocEnd, Name,
+ LocBegin, LocEnd, CommandID,
InlineCommandComment::RenderNormal,
Args);
}
}
VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
- StringRef Name) {
+ unsigned CommandID) {
+ StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
return new (Allocator) VerbatimBlockComment(
Loc,
- Loc.getLocWithOffset(1 + Name.size()),
- Name);
+ Loc.getLocWithOffset(1 + CommandName.size()),
+ CommandID);
}
VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
}
VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
- StringRef Name,
+ unsigned CommandID,
SourceLocation TextBegin,
StringRef Text) {
return new (Allocator) VerbatimLineComment(
LocBegin,
TextBegin.getLocWithOffset(Text.size()),
- Name,
+ CommandID,
TextBegin,
Text);
}
if (Command->getNumArgs() > 0)
DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd();
if (!DiagLoc.isValid())
- DiagLoc = Command->getCommandNameRange().getEnd();
+ DiagLoc = Command->getCommandNameRange(Traits).getEnd();
Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
- << Command->getCommandName()
+ << Command->getCommandName(Traits)
<< Command->getSourceRange();
}
}
void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
- if (!Traits.isReturnsCommand(Command->getCommandName()))
+ if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand)
return;
if (isFunctionDecl()) {
if (ThisDeclInfo->ResultType->isVoidType()) {
}
Diag(Command->getLocation(),
diag::warn_doc_returns_attached_to_a_void_function)
- << Command->getCommandName()
+ << Command->getCommandName(Traits)
<< DiagKind
<< Command->getSourceRange();
}
}
Diag(Command->getLocation(),
diag::warn_doc_returns_not_attached_to_a_function_decl)
- << Command->getCommandName()
+ << Command->getCommandName(Traits)
<< Command->getSourceRange();
}
void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
- StringRef Name = Command->getCommandName();
+ const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
const BlockCommandComment *PrevCommand = NULL;
- if (Traits.isBriefCommand(Name)) {
+ if (Info->IsBriefCommand) {
if (!BriefCommand) {
BriefCommand = Command;
return;
}
PrevCommand = BriefCommand;
- } else if (Traits.isReturnsCommand(Name)) {
+ } else if (Info->IsReturnsCommand) {
if (!ReturnsCommand) {
ReturnsCommand = Command;
return;
// We don't want to check this command for duplicates.
return;
}
+ StringRef CommandName = Command->getCommandName(Traits);
+ StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
- << Name
+ << CommandName
<< Command->getSourceRange();
- if (Name == PrevCommand->getCommandName())
+ if (CommandName == PrevCommandName)
Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
- << PrevCommand->getCommandName()
- << Command->getSourceRange();
+ << PrevCommandName
+ << PrevCommand->getSourceRange();
else
Diag(PrevCommand->getLocation(),
diag::note_doc_block_command_previous_alias)
- << PrevCommand->getCommandName()
- << Name;
+ << PrevCommandName
+ << CommandName;
}
void Sema::resolveParamCommandIndexes(const FullComment *FC) {
InlineCommandComment::RenderKind
Sema::getInlineCommandRenderKind(StringRef Name) const {
- assert(Traits.isInlineCommand(Name));
+ assert(Traits.getCommandInfo(Name)->IsInlineCommand);
return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
.Case("b", InlineCommandComment::RenderBold)
// a separate allocator for all temporary stuff.
llvm::BumpPtrAllocator Allocator;
- comments::CommandTraits Traits;
- comments::Lexer L(Allocator, Traits, Range.getBegin(),
+ comments::Lexer L(Allocator, Context.getCommentCommandTraits(),
+ Range.getBegin(),
RawText.begin(), RawText.end());
- comments::BriefParser P(L, Traits);
+ comments::BriefParser P(L, Context.getCommentCommandTraits());
const std::string Result = P.Parse();
const unsigned BriefTextLength = Result.size();
// Make sure that RawText is valid.
getRawText(Context.getSourceManager());
- comments::CommandTraits Traits;
- comments::Lexer L(Context.getAllocator(), Traits,
+ comments::Lexer L(Context.getAllocator(), Context.getCommentCommandTraits(),
getSourceRange().getBegin(),
RawText.begin(), RawText.end());
comments::Sema S(Context.getAllocator(), Context.getSourceManager(),
- Context.getDiagnostics(), Traits);
+ Context.getDiagnostics(),
+ Context.getCommentCommandTraits());
S.setDecl(D);
comments::Parser P(L, S, Context.getAllocator(), Context.getSourceManager(),
- Context.getDiagnostics(), Traits);
+ Context.getDiagnostics(),
+ Context.getCommentCommandTraits());
return P.parseFullComment();
}
/// Blah blah.
void comment_to_html_conversion_25();
-/// \b Aaa
+/// \unknown
void comment_to_html_conversion_26();
-/// \c Aaa \p Bbb
+/// \b Aaa
void comment_to_html_conversion_27();
-/// \a Aaa \e Bbb \em Ccc
+/// \c Aaa \p Bbb
void comment_to_html_conversion_28();
-/// \a 1<2 \e 3<4 \em 5<6 \param 7<8 aaa \tparam 9<10 bbb
+/// \a Aaa \e Bbb \em Ccc
void comment_to_html_conversion_29();
-/// \\ \@ \& \$ \# \< \> \% \" \. \::
+/// \a 1<2 \e 3<4 \em 5<6 \param 7<8 aaa \tparam 9<10 bbb
void comment_to_html_conversion_30();
-/// & < > "
+/// \\ \@ \& \$ \# \< \> \% \" \. \::
void comment_to_html_conversion_31();
-/// <em>0<i</em>
+/// & < > "
void comment_to_html_conversion_32();
+/// <em>0<i</em>
+void comment_to_html_conversion_33();
+
/// Aaa.
class comment_to_xml_conversion_01 {
/// \param aaa Blah blah.
// CHECK: (CXComment_VerbatimLine Text=[ foo])
// CHECK: (CXComment_Paragraph
// CHECK: (CXComment_Text Text=[ Blah blah.])))]
-// CHECK: annotate-comments.cpp:374:6: FunctionDecl=comment_to_html_conversion_26:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <b>Aaa</b></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="374" column="6"><Name>comment_to_html_conversion_26</Name><USR>c:@F@comment_to_html_conversion_26#</USR><Abstract><Para> <bold>Aaa</bold></Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:374:6: FunctionDecl=comment_to_html_conversion_26:{{.*}} FullCommentAsHTML=[<p class="para-brief"> </p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="374" column="6"><Name>comment_to_html_conversion_26</Name><USR>c:@F@comment_to_html_conversion_26#</USR><Abstract><Para> </Para></Abstract></Function>]
+// CHECK: CommentAST=[
+// CHECK: (CXComment_FullComment
+// CHECK: (CXComment_Paragraph
+// CHECK: (CXComment_Text Text=[ ] IsWhitespace)
+// CHECK: (CXComment_InlineCommand CommandName=[unknown] RenderNormal)))]
+// CHECK: annotate-comments.cpp:377:6: FunctionDecl=comment_to_html_conversion_27:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <b>Aaa</b></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="377" column="6"><Name>comment_to_html_conversion_27</Name><USR>c:@F@comment_to_html_conversion_27#</USR><Abstract><Para> <bold>Aaa</bold></Para></Abstract></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[b] RenderBold Arg[0]=Aaa)))]
-// CHECK: annotate-comments.cpp:377:6: FunctionDecl=comment_to_html_conversion_27:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <tt>Aaa</tt> <tt>Bbb</tt></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="377" column="6"><Name>comment_to_html_conversion_27</Name><USR>c:@F@comment_to_html_conversion_27#</USR><Abstract><Para> <monospaced>Aaa</monospaced> <monospaced>Bbb</monospaced></Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:380:6: FunctionDecl=comment_to_html_conversion_28:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <tt>Aaa</tt> <tt>Bbb</tt></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="380" column="6"><Name>comment_to_html_conversion_28</Name><USR>c:@F@comment_to_html_conversion_28#</USR><Abstract><Para> <monospaced>Aaa</monospaced> <monospaced>Bbb</monospaced></Para></Abstract></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[c] RenderMonospaced Arg[0]=Aaa)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[p] RenderMonospaced Arg[0]=Bbb)))]
-// CHECK: annotate-comments.cpp:380:6: FunctionDecl=comment_to_html_conversion_28:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>Aaa</em> <em>Bbb</em> <em>Ccc</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="380" column="6"><Name>comment_to_html_conversion_28</Name><USR>c:@F@comment_to_html_conversion_28#</USR><Abstract><Para> <emphasized>Aaa</emphasized> <emphasized>Bbb</emphasized> <emphasized>Ccc</emphasized></Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:383:6: FunctionDecl=comment_to_html_conversion_29:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>Aaa</em> <em>Bbb</em> <em>Ccc</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="383" column="6"><Name>comment_to_html_conversion_29</Name><USR>c:@F@comment_to_html_conversion_29#</USR><Abstract><Para> <emphasized>Aaa</emphasized> <emphasized>Bbb</emphasized> <emphasized>Ccc</emphasized></Para></Abstract></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[e] RenderEmphasized Arg[0]=Bbb)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[em] RenderEmphasized Arg[0]=Ccc)))]
-// CHECK: annotate-comments.cpp:383:6: FunctionDecl=comment_to_html_conversion_29:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>1<2</em> <em>3<4</em> <em>5<6</em> </p><dl><dt class="tparam-name-index-invalid">9<10</dt><dd class="tparam-descr-index-invalid"> bbb</dd></dl><dl><dt class="param-name-index-invalid">7<8</dt><dd class="param-descr-index-invalid"> aaa </dd></dl>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="383" column="6"><Name>comment_to_html_conversion_29</Name><USR>c:@F@comment_to_html_conversion_29#</USR><Abstract><Para> <emphasized>1<2</emphasized> <emphasized>3<4</emphasized> <emphasized>5<6</emphasized> </Para></Abstract><TemplateParameters><Parameter><Name>9<10</Name><Discussion><Para> bbb</Para></Discussion></Parameter></TemplateParameters><Parameters><Parameter><Name>7<8</Name><Direction isExplicit="0">in</Direction><Discussion><Para> aaa </Para></Discussion></Parameter></Parameters></Function>]
+// CHECK: annotate-comments.cpp:386:6: FunctionDecl=comment_to_html_conversion_30:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>1<2</em> <em>3<4</em> <em>5<6</em> </p><dl><dt class="tparam-name-index-invalid">9<10</dt><dd class="tparam-descr-index-invalid"> bbb</dd></dl><dl><dt class="param-name-index-invalid">7<8</dt><dd class="param-descr-index-invalid"> aaa </dd></dl>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="386" column="6"><Name>comment_to_html_conversion_30</Name><USR>c:@F@comment_to_html_conversion_30#</USR><Abstract><Para> <emphasized>1<2</emphasized> <emphasized>3<4</emphasized> <emphasized>5<6</emphasized> </Para></Abstract><TemplateParameters><Parameter><Name>9<10</Name><Discussion><Para> bbb</Para></Discussion></Parameter></TemplateParameters><Parameters><Parameter><Name>7<8</Name><Direction isExplicit="0">in</Direction><Discussion><Para> aaa </Para></Discussion></Parameter></Parameters></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_TParamCommand ParamName=[9<10] ParamPosition=Invalid
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ bbb]))))]
-// CHECK: annotate-comments.cpp:386:6: FunctionDecl=comment_to_html_conversion_30:{{.*}} FullCommentAsHTML=[<p class="para-brief"> \ @ & $ # < > % " . ::</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="386" column="6"><Name>comment_to_html_conversion_30</Name><USR>c:@F@comment_to_html_conversion_30#</USR><Abstract><Para> \ @ & $ # < > % " . ::</Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:389:6: FunctionDecl=comment_to_html_conversion_31:{{.*}} FullCommentAsHTML=[<p class="para-brief"> \ @ & $ # < > % " . ::</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="389" column="6"><Name>comment_to_html_conversion_31</Name><USR>c:@F@comment_to_html_conversion_31#</USR><Abstract><Para> \ @ & $ # < > % " . ::</Para></Abstract></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[.])
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_Text Text=[::])))]
-// CHECK: annotate-comments.cpp:389:6: FunctionDecl=comment_to_html_conversion_31:{{.*}} FullCommentAsHTML=[<p class="para-brief"> & < > "</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="389" column="6"><Name>comment_to_html_conversion_31</Name><USR>c:@F@comment_to_html_conversion_31#</USR><Abstract><Para> & < > "</Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:392:6: FunctionDecl=comment_to_html_conversion_32:{{.*}} FullCommentAsHTML=[<p class="para-brief"> & < > "</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="392" column="6"><Name>comment_to_html_conversion_32</Name><USR>c:@F@comment_to_html_conversion_32#</USR><Abstract><Para> & < > "</Para></Abstract></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[>])
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_Text Text=["])))]
-// CHECK: annotate-comments.cpp:392:6: FunctionDecl=comment_to_html_conversion_32:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>0<i</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="392" column="6"><Name>comment_to_html_conversion_32</Name><USR>c:@F@comment_to_html_conversion_32#</USR><Abstract><Para> <rawHTML><![CDATA[<em>]]></rawHTML>0<i<rawHTML></em></rawHTML></Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:395:6: FunctionDecl=comment_to_html_conversion_33:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>0<i</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="395" column="6"><Name>comment_to_html_conversion_33</Name><USR>c:@F@comment_to_html_conversion_33#</USR><Abstract><Para> <rawHTML><![CDATA[<em>]]></rawHTML>0<i<rawHTML></em></rawHTML></Para></Abstract></Function>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[i])
// CHECK-NEXT: (CXComment_HTMLEndTag Name=[em])))]
-// CHECK: annotate-comments.cpp:395:7: ClassDecl=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Class file="{{[^"]+}}annotate-comments.cpp" line="395" column="7"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
-// CHECK: annotate-comments.cpp:397:3: CXXConstructor=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="397" column="3"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_01#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
-// CHECK: annotate-comments.cpp:400:3: CXXDestructor=~comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="400" column="3"><Name>~comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@~comment_to_xml_conversion_01#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
-// CHECK: annotate-comments.cpp:403:7: CXXMethod=comment_to_xml_conversion_02:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="403" column="7"><Name>comment_to_xml_conversion_02</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_02#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
-// CHECK: annotate-comments.cpp:406:14: CXXMethod=comment_to_xml_conversion_03:{{.*}} FullCommentAsXML=[<Function isClassMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="406" column="14"><Name>comment_to_xml_conversion_03</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_03#I#S</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
-// CHECK: annotate-comments.cpp:409:7: FieldDecl=comment_to_xml_conversion_04:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="409" column="7"><Name>comment_to_xml_conversion_04</Name><USR>c:@C@comment_to_xml_conversion_01@FI@comment_to_xml_conversion_04</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
-// CHECK: annotate-comments.cpp:412:14: VarDecl=comment_to_xml_conversion_05:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="412" column="14"><Name>comment_to_xml_conversion_05</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_05</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
-// CHECK: annotate-comments.cpp:415:8: CXXMethod=operator():{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="415" column="8"><Name>operator()</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator()#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
-// CHECK: annotate-comments.cpp:418:3: CXXConversion=operator _Bool:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="418" column="3"><Name>operator _Bool</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator _Bool#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
-// CHECK: annotate-comments.cpp:421:15: TypedefDecl=comment_to_xml_conversion_06:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="421" column="15"><Name>comment_to_xml_conversion_06</Name><USR>c:annotate-comments.cpp@8453@C@comment_to_xml_conversion_01@T@comment_to_xml_conversion_06</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>]
-// CHECK: annotate-comments.cpp:424:9: TypeAliasDecl=comment_to_xml_conversion_07:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="424" column="9"><Name>comment_to_xml_conversion_07</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_07</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>]
-// CHECK: annotate-comments.cpp:431:3: UnexposedDecl=comment_to_xml_conversion_09:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="431" column="3"><Name>comment_to_xml_conversion_09</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_09</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>]
-// CHECK: annotate-comments.cpp:436:6: FunctionTemplate=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="436" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@FT@>2#T#Tcomment_to_xml_conversion_10#t0.0#t0.1#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
-// CHECK: annotate-comments.cpp:440:6: FunctionDecl=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="440" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@F@comment_to_xml_conversion_10<#I#I>#I#I#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
-// CHECK: annotate-comments.cpp:444:7: ClassTemplate=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="444" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CT>2#T#T@comment_to_xml_conversion_11</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
-// CHECK: annotate-comments.cpp:448:7: ClassTemplatePartialSpecialization=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="partialSpecialization" file="{{[^"]+}}annotate-comments.cpp" line="448" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CP>1#T@comment_to_xml_conversion_11>#t0.0#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
-// CHECK: annotate-comments.cpp:452:7: ClassDecl=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="452" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@C@comment_to_xml_conversion_11>#I#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
-// CHECK: annotate-comments.cpp:455:5: VarDecl=comment_to_xml_conversion_12:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="455" column="5"><Name>comment_to_xml_conversion_12</Name><USR>c:@comment_to_xml_conversion_12</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
-// CHECK: annotate-comments.cpp:458:11: Namespace=comment_to_xml_conversion_13:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="458" column="11"><Name>comment_to_xml_conversion_13</Name><USR>c:@N@comment_to_xml_conversion_13</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
-// CHECK: annotate-comments.cpp:460:13: Namespace=comment_to_xml_conversion_14:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="460" column="13"><Name>comment_to_xml_conversion_14</Name><USR>c:@N@comment_to_xml_conversion_13@N@comment_to_xml_conversion_14</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
-// CHECK: annotate-comments.cpp:465:6: EnumDecl=comment_to_xml_conversion_15:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="465" column="6"><Name>comment_to_xml_conversion_15</Name><USR>c:@E@comment_to_xml_conversion_15</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>]
-// CHECK: annotate-comments.cpp:467:3: EnumConstantDecl=comment_to_xml_conversion_16:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="467" column="3"><Name>comment_to_xml_conversion_16</Name><USR>c:@E@comment_to_xml_conversion_15@comment_to_xml_conversion_16</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
-// CHECK: annotate-comments.cpp:471:12: EnumDecl=comment_to_xml_conversion_17:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="471" column="12"><Name>comment_to_xml_conversion_17</Name><USR>c:@E@comment_to_xml_conversion_17</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>]
-// CHECK: annotate-comments.cpp:473:3: EnumConstantDecl=comment_to_xml_conversion_18:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="473" column="3"><Name>comment_to_xml_conversion_18</Name><USR>c:@E@comment_to_xml_conversion_17@comment_to_xml_conversion_18</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
+// CHECK: annotate-comments.cpp:398:7: ClassDecl=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Class file="{{[^"]+}}annotate-comments.cpp" line="398" column="7"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
+// CHECK: annotate-comments.cpp:400:3: CXXConstructor=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="400" column="3"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_01#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
+// CHECK: annotate-comments.cpp:403:3: CXXDestructor=~comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="403" column="3"><Name>~comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@~comment_to_xml_conversion_01#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:406:7: CXXMethod=comment_to_xml_conversion_02:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="406" column="7"><Name>comment_to_xml_conversion_02</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_02#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
+// CHECK: annotate-comments.cpp:409:14: CXXMethod=comment_to_xml_conversion_03:{{.*}} FullCommentAsXML=[<Function isClassMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="409" column="14"><Name>comment_to_xml_conversion_03</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_03#I#S</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
+// CHECK: annotate-comments.cpp:412:7: FieldDecl=comment_to_xml_conversion_04:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="412" column="7"><Name>comment_to_xml_conversion_04</Name><USR>c:@C@comment_to_xml_conversion_01@FI@comment_to_xml_conversion_04</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
+// CHECK: annotate-comments.cpp:415:14: VarDecl=comment_to_xml_conversion_05:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="415" column="14"><Name>comment_to_xml_conversion_05</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_05</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
+// CHECK: annotate-comments.cpp:418:8: CXXMethod=operator():{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="418" column="8"><Name>operator()</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator()#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>]
+// CHECK: annotate-comments.cpp:421:3: CXXConversion=operator _Bool:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="421" column="3"><Name>operator _Bool</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator _Bool#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:424:15: TypedefDecl=comment_to_xml_conversion_06:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="424" column="15"><Name>comment_to_xml_conversion_06</Name><USR>c:annotate-comments.cpp@8505@C@comment_to_xml_conversion_01@T@comment_to_xml_conversion_06</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>]
+// CHECK: annotate-comments.cpp:427:9: TypeAliasDecl=comment_to_xml_conversion_07:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="427" column="9"><Name>comment_to_xml_conversion_07</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_07</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>]
+// CHECK: annotate-comments.cpp:434:3: UnexposedDecl=comment_to_xml_conversion_09:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="434" column="3"><Name>comment_to_xml_conversion_09</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_09</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>]
+// CHECK: annotate-comments.cpp:439:6: FunctionTemplate=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="439" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@FT@>2#T#Tcomment_to_xml_conversion_10#t0.0#t0.1#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:443:6: FunctionDecl=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="443" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@F@comment_to_xml_conversion_10<#I#I>#I#I#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>]
+// CHECK: annotate-comments.cpp:447:7: ClassTemplate=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="447" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CT>2#T#T@comment_to_xml_conversion_11</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
+// CHECK: annotate-comments.cpp:451:7: ClassTemplatePartialSpecialization=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="partialSpecialization" file="{{[^"]+}}annotate-comments.cpp" line="451" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CP>1#T@comment_to_xml_conversion_11>#t0.0#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
+// CHECK: annotate-comments.cpp:455:7: ClassDecl=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="455" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@C@comment_to_xml_conversion_11>#I#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>]
+// CHECK: annotate-comments.cpp:458:5: VarDecl=comment_to_xml_conversion_12:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="458" column="5"><Name>comment_to_xml_conversion_12</Name><USR>c:@comment_to_xml_conversion_12</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
+// CHECK: annotate-comments.cpp:461:11: Namespace=comment_to_xml_conversion_13:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="461" column="11"><Name>comment_to_xml_conversion_13</Name><USR>c:@N@comment_to_xml_conversion_13</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
+// CHECK: annotate-comments.cpp:463:13: Namespace=comment_to_xml_conversion_14:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="463" column="13"><Name>comment_to_xml_conversion_14</Name><USR>c:@N@comment_to_xml_conversion_13@N@comment_to_xml_conversion_14</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>]
+// CHECK: annotate-comments.cpp:468:6: EnumDecl=comment_to_xml_conversion_15:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="468" column="6"><Name>comment_to_xml_conversion_15</Name><USR>c:@E@comment_to_xml_conversion_15</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>]
+// CHECK: annotate-comments.cpp:470:3: EnumConstantDecl=comment_to_xml_conversion_16:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="470" column="3"><Name>comment_to_xml_conversion_16</Name><USR>c:@E@comment_to_xml_conversion_15@comment_to_xml_conversion_16</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
+// CHECK: annotate-comments.cpp:474:12: EnumDecl=comment_to_xml_conversion_17:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="474" column="12"><Name>comment_to_xml_conversion_17</Name><USR>c:@E@comment_to_xml_conversion_17</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>]
+// CHECK: annotate-comments.cpp:476:3: EnumConstantDecl=comment_to_xml_conversion_18:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="476" column="3"><Name>comment_to_xml_conversion_18</Name><USR>c:@E@comment_to_xml_conversion_17@comment_to_xml_conversion_18</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>]
#endif
}
-static void PrintCursorComments(CXTranslationUnit TU,
- CXCursor Cursor,
+static void PrintCursorComments(CXCursor Cursor,
CommentXMLValidationData *ValidationData) {
{
CXString RawComment;
clang_FullComment_getAsHTML(Comment));
{
CXString XML;
- XML = clang_FullComment_getAsXML(TU, Comment);
+ XML = clang_FullComment_getAsXML(Comment);
PrintCXStringWithPrefix("FullCommentAsXML", XML);
ValidateCommentXML(clang_getCString(XML), ValidationData);
clang_disposeString(XML);
PrintRange(RefNameRange, "RefName");
}
- PrintCursorComments(TU, Cursor, ValidationData);
+ PrintCursorComments(Cursor, ValidationData);
}
}
CXComment clang_Cursor_getParsedComment(CXCursor C) {
if (!clang_isDeclaration(C.kind))
- return cxcomment::createCXComment(NULL);
+ return cxcomment::createCXComment(NULL, NULL);
const Decl *D = getCursorDecl(C);
const ASTContext &Context = getCursorContext(C);
const comments::FullComment *FC = Context.getCommentForDecl(D);
- return cxcomment::createCXComment(FC);
+ return cxcomment::createCXComment(FC, getCursorTU(C));
}
} // end: extern "C"
#include "CXString.h"
#include "CXComment.h"
#include "CXCursor.h"
-#include "CXTranslationUnit.h"
#include "clang/AST/CommentVisitor.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/Decl.h"
-#include "clang/Frontend/ASTUnit.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
const Comment *C = getASTNode(CXC);
if (!C || ChildIdx >= C->child_count())
- return createCXComment(NULL);
+ return createCXComment(NULL, NULL);
- return createCXComment(*(C->child_begin() + ChildIdx));
+ return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
}
unsigned clang_Comment_isWhitespace(CXComment CXC) {
if (!ICC)
return createCXString((const char *) 0);
- return createCXString(ICC->getCommandName(), /*DupString=*/ false);
+ const CommandTraits &Traits = getCommandTraits(CXC);
+ return createCXString(ICC->getCommandName(Traits), /*DupString=*/ false);
}
enum CXCommentInlineCommandRenderKind
if (!BCC)
return createCXString((const char *) 0);
- return createCXString(BCC->getCommandName(), /*DupString=*/ false);
+ const CommandTraits &Traits = getCommandTraits(CXC);
+ return createCXString(BCC->getCommandName(Traits), /*DupString=*/ false);
}
unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
if (!BCC)
- return createCXComment(NULL);
+ return createCXComment(NULL, NULL);
- return createCXComment(BCC->getParagraph());
+ return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
}
CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
/// Separate parts of a FullComment.
struct FullCommentParts {
/// Take a full comment apart and initialize members accordingly.
- FullCommentParts(const FullComment *C);
+ FullCommentParts(const FullComment *C,
+ const CommandTraits &Traits);
const BlockContentComment *Brief;
const ParagraphComment *FirstParagraph;
SmallVector<const BlockContentComment *, 8> MiscBlocks;
};
-FullCommentParts::FullCommentParts(const FullComment *C) :
+FullCommentParts::FullCommentParts(const FullComment *C,
+ const CommandTraits &Traits) :
Brief(NULL), FirstParagraph(NULL), Returns(NULL) {
- const CommandTraits Traits;
for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
I != E; ++I) {
const Comment *Child = *I;
case Comment::BlockCommandCommentKind: {
const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
- StringRef CommandName = BCC->getCommandName();
- if (!Brief && Traits.isBriefCommand(CommandName)) {
+ const CommandInfo *Info = Traits.getCommandInfo(BCC->getCommandID());
+ if (!Brief && Info->IsBriefCommand) {
Brief = BCC;
break;
}
- if (!Returns && Traits.isReturnsCommand(CommandName)) {
+ if (!Returns && Info->IsReturnsCommand) {
Returns = BCC;
break;
}
case Comment::VerbatimLineCommentKind: {
const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child);
- if (!Traits.isDeclarationCommand(VLC->getCommandName()))
+ const CommandInfo *Info = Traits.getCommandInfo(VLC->getCommandID());
+ if (!Info->IsDeclarationCommand)
MiscBlocks.push_back(VLC);
break;
}
public ConstCommentVisitor<CommentASTToHTMLConverter> {
public:
/// \param Str accumulator for HTML.
- CommentASTToHTMLConverter(SmallVectorImpl<char> &Str) : Result(Str) { }
+ CommentASTToHTMLConverter(SmallVectorImpl<char> &Str,
+ const CommandTraits &Traits) :
+ Result(Str), Traits(Traits)
+ { }
// Inline content.
void visitTextComment(const TextComment *C);
void appendToResultWithHTMLEscaping(StringRef S);
private:
- const CommandTraits Traits;
-
/// Output stream for HTML.
llvm::raw_svector_ostream Result;
+
+ const CommandTraits &Traits;
};
} // end unnamed namespace
void CommentASTToHTMLConverter::visitBlockCommandComment(
const BlockCommandComment *C) {
- StringRef CommandName = C->getCommandName();
- if (Traits.isBriefCommand(CommandName)) {
+ const CommandInfo *Info = Traits.getCommandInfo(C->getCommandID());
+ if (Info->IsBriefCommand) {
Result << "<p class=\"para-brief\">";
visitNonStandaloneParagraphComment(C->getParagraph());
Result << "</p>";
return;
}
- if (Traits.isReturnsCommand(CommandName)) {
+ if (Info->IsReturnsCommand) {
Result << "<p class=\"para-returns\">"
"<span class=\"word-returns\">Returns</span> ";
visitNonStandaloneParagraphComment(C->getParagraph());
}
void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
- FullCommentParts Parts(C);
+ FullCommentParts Parts(C, Traits);
bool FirstParagraphIsBrief = false;
if (Parts.Brief)
return createCXString((const char *) 0);
SmallString<128> HTML;
- CommentASTToHTMLConverter Converter(HTML);
+ CommentASTToHTMLConverter Converter(HTML, getCommandTraits(CXC));
Converter.visit(HTC);
return createCXString(HTML.str(), /* DupString = */ true);
}
return createCXString((const char *) 0);
SmallString<1024> HTML;
- CommentASTToHTMLConverter Converter(HTML);
+ CommentASTToHTMLConverter Converter(HTML, getCommandTraits(CXC));
Converter.visit(FC);
return createCXString(HTML.str(), /* DupString = */ true);
}
public ConstCommentVisitor<CommentASTToXMLConverter> {
public:
/// \param Str accumulator for XML.
- CommentASTToXMLConverter(const SourceManager &SM,
- SmallVectorImpl<char> &Str) :
- SM(SM), Result(Str) { }
+ CommentASTToXMLConverter(SmallVectorImpl<char> &Str,
+ const CommandTraits &Traits,
+ const SourceManager &SM) :
+ Result(Str), Traits(Traits), SM(SM) { }
// Inline content.
void visitTextComment(const TextComment *C);
void appendToResultWithXMLEscaping(StringRef S);
private:
- const SourceManager &SM;
-
/// Output stream for XML.
llvm::raw_svector_ostream Result;
+
+ const CommandTraits &Traits;
+ const SourceManager &SM;
};
} // end unnamed namespace
if (NumLines == 0)
return;
- Result << llvm::StringSwitch<const char *>(C->getCommandName())
+ Result << llvm::StringSwitch<const char *>(C->getCommandName(Traits))
.Case("code", "<Verbatim xml:space=\"preserve\" kind=\"code\">")
.Default("<Verbatim xml:space=\"preserve\" kind=\"verbatim\">");
for (unsigned i = 0; i != NumLines; ++i) {
}
void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
- FullCommentParts Parts(C);
+ FullCommentParts Parts(C, Traits);
const DeclInfo *DI = C->getDeclInfo();
StringRef RootEndTag;
extern "C" {
-CXString clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) {
+CXString clang_FullComment_getAsXML(CXComment CXC) {
const FullComment *FC = getASTNodeAs<FullComment>(CXC);
if (!FC)
return createCXString((const char *) 0);
+ CXTranslationUnit TU = CXC.TranslationUnit;
SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager();
SmallString<1024> XML;
- CommentASTToXMLConverter Converter(SM, XML);
+ CommentASTToXMLConverter Converter(XML, getCommandTraits(CXC), SM);
Converter.visit(FC);
return createCXString(XML.str(), /* DupString = */ true);
}
#define LLVM_CLANG_CXCOMMENT_H
#include "clang-c/Index.h"
+#include "CXTranslationUnit.h"
#include "clang/AST/Comment.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Frontend/ASTUnit.h"
namespace clang {
+namespace comments {
+ class CommandTraits;
+}
+
namespace cxcomment {
-inline CXComment createCXComment(const comments::Comment *C) {
+inline CXComment createCXComment(const comments::Comment *C,
+ CXTranslationUnit TU) {
CXComment Result;
- Result.Data = C;
+ Result.ASTNode = C;
+ Result.TranslationUnit = TU;
return Result;
}
inline const comments::Comment *getASTNode(CXComment CXC) {
- return static_cast<const comments::Comment *>(CXC.Data);
+ return static_cast<const comments::Comment *>(CXC.ASTNode);
}
template<typename T>
return dyn_cast<T>(C);
}
+inline ASTContext &getASTContext(CXComment CXC) {
+ return static_cast<ASTUnit *>(CXC.TranslationUnit->TUData)->getASTContext();
+}
+
+inline comments::CommandTraits &getCommandTraits(CXComment CXC) {
+ return getASTContext(CXC).getCommentCommandTraits();
+}
+
} // end namespace cxcomment
} // end namespace clang
: FileMgr(FileMgrOpts),
DiagID(new DiagnosticIDs()),
Diags(DiagID, new IgnoringDiagConsumer()),
- SourceMgr(Diags, FileMgr) {
+ SourceMgr(Diags, FileMgr),
+ Traits(Allocator) {
}
FileSystemOptions FileMgrOpts;
DiagnosticsEngine Diags;
SourceManager SourceMgr;
llvm::BumpPtrAllocator Allocator;
+ CommandTraits Traits;
void lexString(const char *Source, std::vector<Token> &Toks);
+
+ StringRef getCommandName(const Token &Tok) {
+ return Traits.getCommandInfo(Tok.getCommandID())->Name;
+ }
+
+ StringRef getVerbatimBlockName(const Token &Tok) {
+ return Traits.getCommandInfo(Tok.getVerbatimBlockID())->Name;
+ }
+
+ StringRef getVerbatimLineName(const Token &Tok) {
+ return Traits.getCommandInfo(Tok.getVerbatimLineID())->Name;
+ }
};
void CommentLexerTest::lexString(const char *Source,
FileID File = SourceMgr.createFileIDForMemBuffer(Buf);
SourceLocation Begin = SourceMgr.getLocForStartOfFile(File);
- comments::CommandTraits Traits;
- comments::Lexer L(Allocator, Traits, Begin,
- Source, Source + strlen(Source));
+ Lexer L(Allocator, Traits, Begin, Source, Source + strlen(Source));
while (1) {
Token Tok;
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::command, Toks[1].getKind());
- ASSERT_EQ(StringRef("brief"), Toks[1].getCommandName());
+ ASSERT_EQ(StringRef("brief"), getCommandName(Toks[1]));
ASSERT_EQ(tok::text, Toks[2].getKind());
ASSERT_EQ(StringRef(" Aaa."), Toks[2].getText());
}
TEST_F(CommentLexerTest, DoxygenCommand6) {
+ const char *Source = "/// \\em\\em \\em\t\\em\n";
+ std::vector<Token> Toks;
+
+ lexString(Source, Toks);
+
+ ASSERT_EQ(8U, Toks.size());
+
+ ASSERT_EQ(tok::text, Toks[0].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[0].getText());
+
+ ASSERT_EQ(tok::command, Toks[1].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[1]));
+
+ ASSERT_EQ(tok::command, Toks[2].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[2]));
+
+ ASSERT_EQ(tok::text, Toks[3].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[3].getText());
+
+ ASSERT_EQ(tok::command, Toks[4].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[4]));
+
+ ASSERT_EQ(tok::text, Toks[5].getKind());
+ ASSERT_EQ(StringRef("\t"), Toks[5].getText());
+
+ ASSERT_EQ(tok::command, Toks[6].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[6]));
+
+ ASSERT_EQ(tok::newline, Toks[7].getKind());
+}
+
+TEST_F(CommentLexerTest, DoxygenCommand7) {
const char *Source = "/// \\aaa\\bbb \\ccc\t\\ddd\n";
std::vector<Token> Toks;
ASSERT_EQ(tok::text, Toks[0].getKind());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
- ASSERT_EQ(tok::command, Toks[1].getKind());
- ASSERT_EQ(StringRef("aaa"), Toks[1].getCommandName());
+ ASSERT_EQ(tok::unknown_command, Toks[1].getKind());
+ ASSERT_EQ(StringRef("aaa"), Toks[1].getUnknownCommandName());
- ASSERT_EQ(tok::command, Toks[2].getKind());
- ASSERT_EQ(StringRef("bbb"), Toks[2].getCommandName());
+ ASSERT_EQ(tok::unknown_command, Toks[2].getKind());
+ ASSERT_EQ(StringRef("bbb"), Toks[2].getUnknownCommandName());
ASSERT_EQ(tok::text, Toks[3].getKind());
ASSERT_EQ(StringRef(" "), Toks[3].getText());
- ASSERT_EQ(tok::command, Toks[4].getKind());
- ASSERT_EQ(StringRef("ccc"), Toks[4].getCommandName());
+ ASSERT_EQ(tok::unknown_command, Toks[4].getKind());
+ ASSERT_EQ(StringRef("ccc"), Toks[4].getUnknownCommandName());
ASSERT_EQ(tok::text, Toks[5].getKind());
ASSERT_EQ(StringRef("\t"), Toks[5].getText());
- ASSERT_EQ(tok::command, Toks[6].getKind());
- ASSERT_EQ(StringRef("ddd"), Toks[6].getCommandName());
+ ASSERT_EQ(tok::unknown_command, Toks[6].getKind());
+ ASSERT_EQ(StringRef("ddd"), Toks[6].getUnknownCommandName());
ASSERT_EQ(tok::newline, Toks[7].getKind());
}
-TEST_F(CommentLexerTest, DoxygenCommand7) {
+TEST_F(CommentLexerTest, DoxygenCommand8) {
const char *Source = "// \\c\n";
std::vector<Token> Toks;
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::command, Toks[1].getKind());
- ASSERT_EQ(StringRef("c"), Toks[1].getCommandName());
+ ASSERT_EQ(StringRef("c"), getCommandName(Toks[1]));
ASSERT_EQ(tok::newline, Toks[2].getKind());
}
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::verbatim_block_end, Toks[2].getKind());
- ASSERT_EQ(StringRef("endverbatim"), Toks[2].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[2]));
ASSERT_EQ(tok::newline, Toks[3].getKind());
ASSERT_EQ(tok::newline, Toks[4].getKind());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::newline, Toks[2].getKind());
}
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::newline, Toks[2].getKind());
ASSERT_EQ(tok::newline, Toks[3].getKind());
ASSERT_EQ(StringRef(" Meow "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
ASSERT_EQ(StringRef(" aaa "), Toks[2].getVerbatimBlockText());
ASSERT_EQ(tok::verbatim_block_end, Toks[3].getKind());
- ASSERT_EQ(StringRef("endverbatim"), Toks[3].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[3]));
ASSERT_EQ(tok::newline, Toks[4].getKind());
ASSERT_EQ(tok::newline, Toks[5].getKind());
ASSERT_EQ(StringRef(" Meow "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
ASSERT_EQ(StringRef(" aaa "), Toks[2].getVerbatimBlockText());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::newline, Toks[2].getKind());
ASSERT_EQ(tok::newline, Toks[7].getKind());
ASSERT_EQ(tok::verbatim_block_end, Toks[8].getKind());
- ASSERT_EQ(StringRef("endverbatim"), Toks[8].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[8]));
ASSERT_EQ(tok::newline, Toks[9].getKind());
}
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
ASSERT_EQ(StringRef(" Aaa"), Toks[2].getVerbatimBlockText());
ASSERT_EQ(StringRef(" Bbb"), Toks[4].getVerbatimBlockText());
ASSERT_EQ(tok::verbatim_block_end, Toks[5].getKind());
- ASSERT_EQ(StringRef("endverbatim"), Toks[5].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[5]));
ASSERT_EQ(tok::newline, Toks[6].getKind());
ASSERT_EQ(StringRef(" Meow "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
ASSERT_EQ(StringRef(" aaa\\$\\@"), Toks[2].getVerbatimBlockText());
ASSERT_EQ(StringRef("ddd "), Toks[5].getVerbatimBlockText());
ASSERT_EQ(tok::verbatim_block_end, Toks[6].getKind());
- ASSERT_EQ(StringRef("endverbatim"), Toks[6].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[6]));
ASSERT_EQ(tok::text, Toks[7].getKind());
ASSERT_EQ(StringRef(" Blah "), Toks[7].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[8].getKind());
- ASSERT_EQ(StringRef("verbatim"), Toks[8].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[8]));
ASSERT_EQ(tok::verbatim_block_line, Toks[9].getKind());
ASSERT_EQ(StringRef(" eee"), Toks[9].getVerbatimBlockText());
ASSERT_EQ(tok::verbatim_block_end, Toks[10].getKind());
- ASSERT_EQ(StringRef("endverbatim"), Toks[10].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[10]));
ASSERT_EQ(tok::text, Toks[11].getKind());
ASSERT_EQ(StringRef(" BlahBlah"), Toks[11].getText());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
- ASSERT_EQ(StringRef("f$"), Toks[1].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("f$"), getVerbatimBlockName(Toks[1]));
ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
ASSERT_EQ(StringRef(" Aaa "), Toks[2].getVerbatimBlockText());
ASSERT_EQ(tok::verbatim_block_end, Toks[3].getKind());
- ASSERT_EQ(StringRef("f$"), Toks[3].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("f$"), getVerbatimBlockName(Toks[3]));
ASSERT_EQ(tok::text, Toks[4].getKind());
ASSERT_EQ(StringRef(" "), Toks[4].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[5].getKind());
- ASSERT_EQ(StringRef("f["), Toks[5].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("f["), getVerbatimBlockName(Toks[5]));
ASSERT_EQ(tok::verbatim_block_line, Toks[6].getKind());
ASSERT_EQ(StringRef(" Bbb "), Toks[6].getVerbatimBlockText());
ASSERT_EQ(tok::verbatim_block_end, Toks[7].getKind());
- ASSERT_EQ(StringRef("f]"), Toks[7].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("f]"), getVerbatimBlockName(Toks[7]));
ASSERT_EQ(tok::text, Toks[8].getKind());
ASSERT_EQ(StringRef(" "), Toks[8].getText());
ASSERT_EQ(tok::verbatim_block_begin, Toks[9].getKind());
- ASSERT_EQ(StringRef("f{"), Toks[9].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("f{"), getVerbatimBlockName(Toks[9]));
ASSERT_EQ(tok::verbatim_block_line, Toks[10].getKind());
ASSERT_EQ(StringRef(" Ccc "), Toks[10].getVerbatimBlockText());
ASSERT_EQ(tok::verbatim_block_end, Toks[11].getKind());
- ASSERT_EQ(StringRef("f}"), Toks[11].getVerbatimBlockName());
+ ASSERT_EQ(StringRef("f}"), getVerbatimBlockName(Toks[11]));
ASSERT_EQ(tok::newline, Toks[12].getKind());
}
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind());
- ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
+ ASSERT_EQ(StringRef("fn"), getVerbatimLineName(Toks[1]));
ASSERT_EQ(tok::newline, Toks[2].getKind());
ASSERT_EQ(tok::newline, Toks[3].getKind());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind());
- ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
+ ASSERT_EQ(StringRef("fn"), getVerbatimLineName(Toks[1]));
ASSERT_EQ(tok::verbatim_line_text, Toks[2].getKind());
ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"),
ASSERT_EQ(StringRef(" "), Toks[0].getText());
ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind());
- ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
+ ASSERT_EQ(StringRef("fn"), getVerbatimLineName(Toks[1]));
ASSERT_EQ(tok::verbatim_line_text, Toks[2].getKind());
ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"),
: FileMgr(FileMgrOpts),
DiagID(new DiagnosticIDs()),
Diags(DiagID, new IgnoringDiagConsumer()),
- SourceMgr(Diags, FileMgr) {
+ SourceMgr(Diags, FileMgr),
+ Traits(Allocator) {
}
FileSystemOptions FileMgrOpts;
DiagnosticsEngine Diags;
SourceManager SourceMgr;
llvm::BumpPtrAllocator Allocator;
+ CommandTraits Traits;
FullComment *parseString(const char *Source);
};
FileID File = SourceMgr.createFileIDForMemBuffer(Buf);
SourceLocation Begin = SourceMgr.getLocForStartOfFile(File);
- comments::CommandTraits Traits;
- comments::Lexer L(Allocator, Traits, Begin,
- Source, Source + strlen(Source));
+ Lexer L(Allocator, Traits, Begin, Source, Source + strlen(Source));
- comments::Sema S(Allocator, SourceMgr, Diags, Traits);
- comments::Parser P(L, S, Allocator, SourceMgr, Diags, Traits);
- comments::FullComment *FC = P.parseFullComment();
+ Sema S(Allocator, SourceMgr, Diags, Traits);
+ Parser P(L, S, Allocator, SourceMgr, Diags, Traits);
+ FullComment *FC = P.parseFullComment();
if (DEBUG) {
llvm::errs() << "=== Source:\n" << Source << "\n=== AST:\n";
- FC->dump(SourceMgr);
+ FC->dump(llvm::errs(), &Traits, &SourceMgr);
}
Token Tok;
}
::testing::AssertionResult HasBlockCommandAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
BlockCommandComment *&BCC,
StringRef Name,
if (!AR)
return AR;
- StringRef ActualName = BCC->getCommandName();
+ StringRef ActualName = BCC->getCommandName(Traits);
if (ActualName != Name)
return ::testing::AssertionFailure()
<< "BlockCommandComment has name \"" << ActualName.str() << "\", "
::testing::AssertionResult HasParamCommandAt(
const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
ParamCommandComment *&PCC,
StringRef CommandName,
if (!AR)
return AR;
- StringRef ActualCommandName = PCC->getCommandName();
+ StringRef ActualCommandName = PCC->getCommandName(Traits);
if (ActualCommandName != CommandName)
return ::testing::AssertionFailure()
<< "ParamCommandComment has name \"" << ActualCommandName.str() << "\", "
::testing::AssertionResult HasTParamCommandAt(
const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
TParamCommandComment *&TPCC,
StringRef CommandName,
if (!AR)
return AR;
- StringRef ActualCommandName = TPCC->getCommandName();
+ StringRef ActualCommandName = TPCC->getCommandName(Traits);
if (ActualCommandName != CommandName)
return ::testing::AssertionFailure()
<< "TParamCommandComment has name \"" << ActualCommandName.str() << "\", "
}
::testing::AssertionResult HasInlineCommandAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
InlineCommandComment *&ICC,
StringRef Name) {
if (!AR)
return AR;
- StringRef ActualName = ICC->getCommandName();
+ StringRef ActualName = ICC->getCommandName(Traits);
if (ActualName != Name)
return ::testing::AssertionFailure()
<< "InlineCommandComment has name \"" << ActualName.str() << "\", "
struct NoArgs {};
::testing::AssertionResult HasInlineCommandAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
InlineCommandComment *&ICC,
StringRef Name,
NoArgs) {
- ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name);
+ ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name);
if (!AR)
return AR;
}
::testing::AssertionResult HasInlineCommandAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
InlineCommandComment *&ICC,
StringRef Name,
StringRef Arg) {
- ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name);
+ ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name);
if (!AR)
return AR;
}
::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
VerbatimBlockComment *&VBC,
StringRef Name,
if (!AR)
return AR;
- StringRef ActualName = VBC->getCommandName();
+ StringRef ActualName = VBC->getCommandName(Traits);
if (ActualName != Name)
return ::testing::AssertionFailure()
<< "VerbatimBlockComment has name \"" << ActualName.str() << "\", "
struct Lines {};
::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
VerbatimBlockComment *&VBC,
StringRef Name,
StringRef CloseName,
NoLines) {
- ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name,
+ ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name,
CloseName);
if (!AR)
return AR;
}
::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
VerbatimBlockComment *&VBC,
StringRef Name,
StringRef CloseName,
Lines,
StringRef Line0) {
- ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name,
+ ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name,
CloseName);
if (!AR)
return AR;
}
::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
VerbatimBlockComment *&VBC,
StringRef Name,
Lines,
StringRef Line0,
StringRef Line1) {
- ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name,
+ ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name,
CloseName);
if (!AR)
return AR;
}
::testing::AssertionResult HasVerbatimLineAt(const Comment *C,
+ const CommandTraits &Traits,
size_t Idx,
VerbatimLineComment *&VLC,
StringRef Name,
if (!AR)
return AR;
- StringRef ActualName = VLC->getCommandName();
+ StringRef ActualName = VLC->getCommandName(Traits);
if (ActualName != Name)
return ::testing::AssertionFailure()
<< "VerbatimLineComment has name \"" << ActualName.str() << "\", "
{
BlockCommandComment *BCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
+ ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC));
ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Aaa"));
}
{
BlockCommandComment *BCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
+ ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC));
ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " "));
}
{
BlockCommandComment *BCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC));
+ ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC));
ASSERT_TRUE(GetChildAt(BCC, 0, PC));
ASSERT_TRUE(HasChildCount(PC, 0));
{
BlockCommandComment *BCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
+ ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC));
ASSERT_TRUE(GetChildAt(BCC, 0, PC));
ASSERT_TRUE(HasChildCount(PC, 2));
{
BlockCommandComment *BCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC));
+ ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC));
ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Ccc"));
}
{
ParamCommandComment *PCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
+ ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param",
ParamCommandComment::In,
/* IsDirectionExplicit = */ false,
"aaa", PC));
{
ParamCommandComment *PCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
+ ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param",
ParamCommandComment::In,
/* IsDirectionExplicit = */ false,
"", PC));
{
BlockCommandComment *BCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "brief", PC));
+ ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC));
ASSERT_TRUE(HasChildCount(PC, 0));
}
}
{
ParamCommandComment *PCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
+ ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param",
ParamCommandComment::In,
/* IsDirectionExplicit = */ false,
"aaa", PC));
{
ParamCommandComment *PCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
+ ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param",
ParamCommandComment::In,
/* IsDirectionExplicit = */ true,
"aaa", PC));
{
ParamCommandComment *PCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
+ ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param",
ParamCommandComment::Out,
/* IsDirectionExplicit = */ true,
"aaa", PC));
{
ParamCommandComment *PCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
+ ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param",
ParamCommandComment::InOut,
/* IsDirectionExplicit = */ true,
"aaa", PC));
{
ParamCommandComment *PCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
+ ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param",
ParamCommandComment::In,
/* IsDirectionExplicit = */ false,
"aaa", PC));
{
TParamCommandComment *TPCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasTParamCommandAt(FC, 1, TPCC, "tparam",
+ ASSERT_TRUE(HasTParamCommandAt(FC, Traits, 1, TPCC, "tparam",
"aaa", PC));
ASSERT_TRUE(HasChildCount(TPCC, 1));
ASSERT_TRUE(HasParagraphCommentAt(TPCC, 0, " Bbb"));
{
TParamCommandComment *TPCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasTParamCommandAt(FC, 1, TPCC, "tparam", "", PC));
+ ASSERT_TRUE(HasTParamCommandAt(FC, Traits, 1, TPCC, "tparam", "", PC));
ASSERT_TRUE(HasChildCount(TPCC, 1));
ASSERT_TRUE(HasChildCount(PC, 0));
}
{
BlockCommandComment *BCC;
ParagraphComment *PC;
- ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "brief", PC));
+ ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC));
ASSERT_TRUE(HasChildCount(PC, 0));
}
}
ASSERT_TRUE(HasChildCount(PC, 2));
ASSERT_TRUE(HasTextAt(PC, 0, " "));
- ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs()));
+ ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", NoArgs()));
}
}
ASSERT_TRUE(HasChildCount(PC, 3));
ASSERT_TRUE(HasTextAt(PC, 0, " "));
- ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs()));
+ ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", NoArgs()));
ASSERT_TRUE(HasTextAt(PC, 2, " "));
}
}
ASSERT_TRUE(HasChildCount(PC, 2));
ASSERT_TRUE(HasTextAt(PC, 0, " "));
- ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa"));
+ ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", "aaa"));
}
}
ASSERT_TRUE(HasChildCount(PC, 3));
ASSERT_TRUE(HasTextAt(PC, 0, " "));
- ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa"));
+ ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", "aaa"));
ASSERT_TRUE(HasTextAt(PC, 2, " bbb"));
}
}
ASSERT_TRUE(HasChildCount(PC, 3));
ASSERT_TRUE(HasTextAt(PC, 0, " "));
- ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "unknown", NoArgs()));
+ ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "unknown", NoArgs()));
ASSERT_TRUE(HasTextAt(PC, 2, " aaa"));
}
}
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimBlockComment *VCC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VCC, "verbatim", "endverbatim",
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VCC,
+ "verbatim", "endverbatim",
NoLines()));
}
}
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimBlockComment *VBC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim",
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC,
+ "verbatim", "endverbatim",
Lines(), " Aaa "));
}
}
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimBlockComment *VBC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "",
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, "verbatim", "",
Lines(), " Aaa"));
}
}
{
VerbatimBlockComment *VBC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", "endverbatim",
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC,
+ "verbatim", "endverbatim",
NoLines()));
}
}
{
VerbatimBlockComment *VBC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", "endverbatim",
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC,
+ "verbatim", "endverbatim",
Lines(), " Aaa"));
}
}
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimBlockComment *VBC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim",
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC,
+ "verbatim", "endverbatim",
Lines(), " Aaa"));
}
}
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimBlockComment *VBC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim",
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC,
+ "verbatim", "endverbatim",
Lines(), " Aaa", " Bbb"));
}
}
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimBlockComment *VBC;
- ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim"));
+ ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC,
+ "verbatim", "endverbatim"));
ASSERT_EQ(3U, VBC->getNumLines());
ASSERT_EQ(" Aaa", VBC->getText(0));
ASSERT_EQ("", VBC->getText(1));
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimLineComment *VLC;
- ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn", ""));
+ ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn", ""));
}
}
}
ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
{
VerbatimLineComment *VLC;
- ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn",
+ ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn",
" void *foo(const char *zzz = \"\\$\");"));
}
}
add_tablegen(clang-tblgen CLANG
ClangASTNodesEmitter.cpp
ClangAttrEmitter.cpp
+ ClangCommentCommandInfoEmitter.cpp
ClangCommentHTMLTagsEmitter.cpp
ClangDiagnosticsEmitter.cpp
ClangSACheckersEmitter.cpp
--- /dev/null
+//===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits command lists and efficient matchers command
+// names that are used in documentation comments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ OS << "namespace {\n"
+ "const CommandInfo Commands[] = {\n";
+ std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
+ for (size_t i = 0, e = Tags.size(); i != e; ++i) {
+ Record &Tag = *Tags[i];
+ OS << " { "
+ << "\"" << Tag.getValueAsString("Name") << "\", "
+ << "\"" << Tag.getValueAsString("EndCommandName") << "\", "
+ << i << ", "
+ << Tag.getValueAsInt("NumArgs") << ", "
+ << Tag.getValueAsBit("IsInlineCommand") << ", "
+ << Tag.getValueAsBit("IsBlockCommand") << ", "
+ << Tag.getValueAsBit("IsBriefCommand") << ", "
+ << Tag.getValueAsBit("IsReturnsCommand") << ", "
+ << Tag.getValueAsBit("IsParamCommand") << ", "
+ << Tag.getValueAsBit("IsTParamCommand") << ", "
+ << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
+ << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
+ << Tag.getValueAsBit("IsVerbatimLineCommand") << ", "
+ << Tag.getValueAsBit("IsDeclarationCommand") << ", "
+ << /* IsUnknownCommand = */ "0"
+ << " }";
+ if (i + 1 != e)
+ OS << ",";
+ OS << "\n";
+ }
+ OS << "};\n"
+ "} // unnamed namespace\n\n";
+
+ std::vector<StringMatcher::StringPair> Matches;
+ for (size_t i = 0, e = Tags.size(); i != e; ++i) {
+ Record &Tag = *Tags[i];
+ std::string Name = Tag.getValueAsString("Name");
+ std::string Return;
+ raw_string_ostream(Return) << "return &Commands[" << i << "];";
+ Matches.push_back(StringMatcher::StringPair(Name, Return));
+ }
+
+ OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
+ << " StringRef Name) {\n";
+ StringMatcher("Name", Matches, OS).Emit();
+ OS << " return NULL;\n"
+ << "}\n\n";
+}
+} // end namespace clang
+
GenClangSACheckers,
GenClangCommentHTMLTags,
GenClangCommentHTMLTagsProperties,
+ GenClangCommentCommandInfo,
GenOptParserDefs, GenOptParserImpl,
GenArmNeon,
GenArmNeonSema,
"gen-clang-comment-html-tags-properties",
"Generate efficient matchers for HTML tag "
"properties"),
+ clEnumValN(GenClangCommentCommandInfo,
+ "gen-clang-comment-command-info",
+ "Generate list of commands that are used in "
+ "documentation comments"),
clEnumValN(GenArmNeon, "gen-arm-neon",
"Generate arm_neon.h for clang"),
clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
case GenClangCommentHTMLTagsProperties:
EmitClangCommentHTMLTagsProperties(Records, OS);
break;
+ case GenClangCommentCommandInfo:
+ EmitClangCommentCommandInfo(Records, OS);
+ break;
case GenOptParserDefs:
EmitOptParser(Records, OS, true);
break;
void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS);
+
void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS);