Comment parsing: extract TableGen'able pieces into new CommandTraits class.

llvm-svn: 161548
This commit is contained in:
Dmitri Gribenko 2012-08-09 00:03:17 +00:00
parent 5fbbc5bfe8
commit ca7f80ada0
14 changed files with 322 additions and 231 deletions

View File

@ -30,6 +30,8 @@ namespace comments {
class BriefParser { class BriefParser {
Lexer &L; Lexer &L;
const CommandTraits &Traits;
/// Current lookahead token. /// Current lookahead token.
Token Tok; Token Tok;
@ -40,7 +42,7 @@ class BriefParser {
} }
public: public:
BriefParser(Lexer &L); BriefParser(Lexer &L, const CommandTraits &Traits);
/// Return \\brief paragraph, if it exists; otherwise return the first /// Return \\brief paragraph, if it exists; otherwise return the first
/// paragraph. /// paragraph.

View File

@ -0,0 +1,145 @@
//===--- CommentCommandTraits.h - Comment command properties ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the class that provides information about comment
// commands.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
namespace clang {
namespace comments {
/// This class provides informaiton about commands that can be used
/// in comments.
class CommandTraits {
public:
/// \brief Check if a given 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 BeginName 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;
/// \brief Register a new verbatim block command.
void addVerbatimBlockCommand(StringRef BeginName, StringRef EndName);
/// \brief Check if a given 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;
/// \brief Register a new verbatim line command.
void addVerbatimLineCommand(StringRef Name);
/// \brief Check if a given command is a block command (of any kind).
bool isBlockCommand(StringRef Name) const;
/// \brief Check if a given command is introducing documentation for
/// a function parameter (\\param or an alias).
bool isParamCommand(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;
/// \brief Check if a given command is introducing a brief documentation
/// paragraph (\\brief or an alias).
bool isBriefCommand(StringRef Name) const;
/// \brief Check if a given command is \\brief or an alias.
bool isReturnsCommand(StringRef Name) const;
/// \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;
/// \brief Check if a given command is a inline command (of any kind).
bool isInlineCommand(StringRef Name) const;
private:
struct VerbatimBlockCommand {
StringRef BeginName;
StringRef EndName;
};
typedef SmallVector<VerbatimBlockCommand, 4> VerbatimBlockCommandVector;
/// Registered additional verbatim-like block commands.
VerbatimBlockCommandVector VerbatimBlockCommands;
struct VerbatimLineCommand {
StringRef Name;
};
typedef SmallVector<VerbatimLineCommand, 4> VerbatimLineCommandVector;
/// Registered verbatim-like line commands.
VerbatimLineCommandVector VerbatimLineCommands;
};
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
#endif

View File

@ -26,6 +26,7 @@ namespace comments {
class Lexer; class Lexer;
class TextTokenRetokenizer; class TextTokenRetokenizer;
class CommandTraits;
namespace tok { namespace tok {
enum TokenKind { enum TokenKind {
@ -215,6 +216,8 @@ private:
/// computed (for example, resolved decimal character references). /// computed (for example, resolved decimal character references).
llvm::BumpPtrAllocator &Allocator; llvm::BumpPtrAllocator &Allocator;
const CommandTraits &Traits;
const char *const BufferStart; const char *const BufferStart;
const char *const BufferEnd; const char *const BufferEnd;
SourceLocation FileLoc; SourceLocation FileLoc;
@ -262,37 +265,10 @@ private:
/// Current lexing mode. /// Current lexing mode.
LexerState State; LexerState State;
/// A verbatim-like block command eats every character (except line starting
/// decorations) until matching end command is seen or comment end is hit.
struct VerbatimBlockCommand {
StringRef BeginName;
StringRef EndName;
};
typedef SmallVector<VerbatimBlockCommand, 4> VerbatimBlockCommandVector;
/// Registered verbatim-like block commands.
VerbatimBlockCommandVector VerbatimBlockCommands;
/// If State is LS_VerbatimBlock, contains the name of verbatim end /// If State is LS_VerbatimBlock, contains the name of verbatim end
/// command, including command marker. /// command, including command marker.
SmallString<16> VerbatimBlockEndCommandName; SmallString<16> VerbatimBlockEndCommandName;
bool isVerbatimBlockCommand(StringRef BeginName, StringRef &EndName) const;
/// A verbatim-like line command eats everything until a newline is seen or
/// comment end is hit.
struct VerbatimLineCommand {
StringRef Name;
};
typedef SmallVector<VerbatimLineCommand, 4> VerbatimLineCommandVector;
/// Registered verbatim-like line commands.
VerbatimLineCommandVector VerbatimLineCommands;
bool isVerbatimLineCommand(StringRef Name) const;
/// Given a character reference name (e.g., "lt"), return the character that /// Given a character reference name (e.g., "lt"), return the character that
/// it stands for (e.g., "<"). /// it stands for (e.g., "<").
StringRef resolveHTMLNamedCharacterReference(StringRef Name) const; StringRef resolveHTMLNamedCharacterReference(StringRef Name) const;
@ -359,7 +335,7 @@ private:
void lexHTMLEndTag(Token &T); void lexHTMLEndTag(Token &T);
public: public:
Lexer(llvm::BumpPtrAllocator &Allocator, Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits,
SourceLocation FileLoc, const CommentOptions &CommOpts, SourceLocation FileLoc, const CommentOptions &CommOpts,
const char *BufferStart, const char *BufferEnd); const char *BufferStart, const char *BufferEnd);
@ -368,12 +344,6 @@ public:
StringRef getSpelling(const Token &Tok, StringRef getSpelling(const Token &Tok,
const SourceManager &SourceMgr, const SourceManager &SourceMgr,
bool *Invalid = NULL) const; bool *Invalid = NULL) const;
/// \brief Register a new verbatim block command.
void addVerbatimBlockCommand(StringRef BeginName, StringRef EndName);
/// \brief Register a new verbatim line command.
void addVerbatimLineCommand(StringRef Name);
}; };
} // end namespace comments } // end namespace comments

View File

@ -24,6 +24,7 @@ namespace clang {
class SourceManager; class SourceManager;
namespace comments { namespace comments {
class CommandTraits;
/// Doxygen comment parser. /// Doxygen comment parser.
class Parser { class Parser {
@ -48,6 +49,8 @@ class Parser {
return Diags.Report(Loc, DiagID); return Diags.Report(Loc, DiagID);
} }
const CommandTraits &Traits;
/// Current lookahead token. We can safely assume that all tokens are from /// Current lookahead token. We can safely assume that all tokens are from
/// a single source file. /// a single source file.
Token Tok; Token Tok;
@ -85,7 +88,8 @@ class Parser {
public: public:
Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator, Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
const SourceManager &SourceMgr, DiagnosticsEngine &Diags); const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const CommandTraits &Traits);
/// Parse arguments for \\param command. /// Parse arguments for \\param command.
void parseParamCommandArgs(ParamCommandComment *PC, void parseParamCommandArgs(ParamCommandComment *PC,

View File

@ -27,6 +27,7 @@ class Decl;
class SourceMgr; class SourceMgr;
namespace comments { namespace comments {
class CommandTraits;
class Sema { class Sema {
Sema(const Sema&); // DO NOT IMPLEMENT Sema(const Sema&); // DO NOT IMPLEMENT
@ -40,6 +41,8 @@ class Sema {
DiagnosticsEngine &Diags; DiagnosticsEngine &Diags;
const CommandTraits &Traits;
/// Information about the declaration this comment is attached to. /// Information about the declaration this comment is attached to.
DeclInfo *ThisDeclInfo; DeclInfo *ThisDeclInfo;
@ -72,7 +75,7 @@ class Sema {
public: public:
Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
DiagnosticsEngine &Diags); DiagnosticsEngine &Diags, const CommandTraits &Traits);
void setDecl(const Decl *D); void setDecl(const Decl *D);
@ -213,15 +216,6 @@ public:
StringRef Typo, StringRef Typo,
const TemplateParameterList *TemplateParameters); const TemplateParameterList *TemplateParameters);
bool isBlockCommand(StringRef Name);
bool isParamCommand(StringRef Name);
bool isTParamCommand(StringRef Name);
bool isBriefCommand(StringRef Name);
bool isReturnsCommand(StringRef Name);
unsigned getBlockCommandNumArgs(StringRef Name);
bool isInlineCommand(StringRef Name) const;
InlineCommandComment::RenderKind InlineCommandComment::RenderKind
getInlineCommandRenderKind(StringRef Name) const; getInlineCommandRenderKind(StringRef Name) const;

View File

@ -14,6 +14,7 @@
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h" #include "clang/AST/CharUnits.h"
#include "clang/AST/Comment.h" #include "clang/AST/Comment.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentLexer.h" #include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentSema.h" #include "clang/AST/CommentSema.h"
#include "clang/AST/CommentParser.h" #include "clang/AST/CommentParser.h"
@ -226,14 +227,16 @@ comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const {
return NULL; return NULL;
const StringRef RawText = RC->getRawText(SourceMgr); const StringRef RawText = RC->getRawText(SourceMgr);
comments::Lexer L(getAllocator(), comments::CommandTraits Traits;
comments::Lexer L(getAllocator(), Traits,
RC->getSourceRange().getBegin(), comments::CommentOptions(), RC->getSourceRange().getBegin(), comments::CommentOptions(),
RawText.begin(), RawText.end()); RawText.begin(), RawText.end());
comments::Sema S(getAllocator(), getSourceManager(), getDiagnostics()); comments::Sema S(getAllocator(), getSourceManager(), getDiagnostics(),
Traits);
S.setDecl(D); S.setDecl(D);
comments::Parser P(L, S, getAllocator(), getSourceManager(), comments::Parser P(L, S, getAllocator(), getSourceManager(),
getDiagnostics()); getDiagnostics(), Traits);
comments::FullComment *FC = P.parseFullComment(); comments::FullComment *FC = P.parseFullComment();
DeclComments[D].second = FC; DeclComments[D].second = FC;

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/AST/CommentBriefParser.h" #include "clang/AST/CommentBriefParser.h"
#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
namespace clang { namespace clang {
@ -39,20 +40,14 @@ void cleanupBrief(std::string &S) {
S.resize(O - S.begin()); S.resize(O - S.begin());
} }
bool isBlockCommand(StringRef Name) {
return llvm::StringSwitch<bool>(Name)
.Cases("brief", "short", true)
.Cases("result", "return", "returns", true)
.Cases("author", "authors", true)
.Case("pre", true)
.Case("post", true)
.Cases("param", "arg", true)
.Case("tparam", true)
.Default(false);
}
} // unnamed namespace } // unnamed namespace
BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) :
L(L), Traits(Traits) {
// Get lookahead token.
ConsumeToken();
}
std::string BriefParser::Parse() { std::string BriefParser::Parse() {
std::string FirstParagraphOrBrief; std::string FirstParagraphOrBrief;
std::string ReturnsParagraph; std::string ReturnsParagraph;
@ -72,18 +67,18 @@ std::string BriefParser::Parse() {
if (Tok.is(tok::command)) { if (Tok.is(tok::command)) {
StringRef Name = Tok.getCommandName(); StringRef Name = Tok.getCommandName();
if (Name == "brief" || Name == "short") { if (Traits.isBriefCommand(Name)) {
FirstParagraphOrBrief.clear(); FirstParagraphOrBrief.clear();
InBrief = true; InBrief = true;
ConsumeToken(); ConsumeToken();
continue; continue;
} }
if (Name == "result" || Name == "return" || Name == "returns") { if (Traits.isReturnsCommand(Name)) {
InReturns = true; InReturns = true;
ReturnsParagraph += "Returns "; ReturnsParagraph += "Returns ";
} }
// Block commands implicitly start a new paragraph. // Block commands implicitly start a new paragraph.
if (isBlockCommand(Name)) { if (Traits.isBlockCommand(Name)) {
// We found an implicit paragraph end. // We found an implicit paragraph end.
InFirstParagraph = false; InFirstParagraph = false;
if (InBrief) if (InBrief)
@ -121,11 +116,6 @@ std::string BriefParser::Parse() {
return ReturnsParagraph; return ReturnsParagraph;
} }
BriefParser::BriefParser(Lexer &L) : L(L) {
// Get lookahead token.
ConsumeToken();
}
} // end namespace comments } // end namespace comments
} // end namespace clang } // end namespace clang

View File

@ -0,0 +1,110 @@
//===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/StringSwitch.h"
namespace clang {
namespace comments {
// TODO: tablegen
bool CommandTraits::isVerbatimBlockCommand(StringRef BeginName,
StringRef &EndName) const {
const char *Result = llvm::StringSwitch<const char *>(BeginName)
.Case("code", "endcode")
.Case("verbatim", "endverbatim")
.Case("htmlonly", "endhtmlonly")
.Case("latexonly", "endlatexonly")
.Case("xmlonly", "endxmlonly")
.Case("manonly", "endmanonly")
.Case("rtfonly", "endrtfonly")
.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->BeginName == BeginName) {
EndName = I->EndName;
return true;
}
return false;
}
bool CommandTraits::isVerbatimLineCommand(StringRef Name) const {
bool Result = llvm::StringSwitch<bool>(Name)
.Case("fn", true)
.Case("var", true)
.Case("property", true)
.Case("typedef", true)
.Case("overload", true)
.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)
.Default(false);
if (Result)
return true;
for (VerbatimLineCommandVector::const_iterator
I = VerbatimLineCommands.begin(),
E = VerbatimLineCommands.end();
I != E; ++I)
if (I->Name == Name)
return true;
return false;
}
void CommandTraits::addVerbatimBlockCommand(StringRef BeginName,
StringRef EndName) {
VerbatimBlockCommand VBC;
VBC.BeginName = BeginName;
VBC.EndName = EndName;
VerbatimBlockCommands.push_back(VBC);
}
void CommandTraits::addVerbatimLineCommand(StringRef Name) {
VerbatimLineCommand VLC;
VLC.Name = Name;
VerbatimLineCommands.push_back(VLC);
}
} // end namespace comments
} // end namespace clang

View File

@ -1,4 +1,5 @@
#include "clang/AST/CommentLexer.h" #include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/Basic/ConvertUTF.h" #include "clang/Basic/ConvertUTF.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -12,82 +13,6 @@ void Token::dump(const Lexer &L, const SourceManager &SM) const {
llvm::errs() << " " << Length << " \"" << L.getSpelling(*this, SM) << "\"\n"; llvm::errs() << " " << Length << " \"" << L.getSpelling(*this, SM) << "\"\n";
} }
bool Lexer::isVerbatimBlockCommand(StringRef BeginName,
StringRef &EndName) const {
const char *Result = llvm::StringSwitch<const char *>(BeginName)
.Case("code", "endcode")
.Case("verbatim", "endverbatim")
.Case("htmlonly", "endhtmlonly")
.Case("latexonly", "endlatexonly")
.Case("xmlonly", "endxmlonly")
.Case("manonly", "endmanonly")
.Case("rtfonly", "endrtfonly")
.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->BeginName == BeginName) {
EndName = I->EndName;
return true;
}
return false;
}
bool Lexer::isVerbatimLineCommand(StringRef Name) const {
bool Result = llvm::StringSwitch<bool>(Name)
.Case("fn", true)
.Case("var", true)
.Case("property", true)
.Case("typedef", true)
.Case("overload", true)
.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)
.Default(false);
if (Result)
return true;
for (VerbatimLineCommandVector::const_iterator
I = VerbatimLineCommands.begin(),
E = VerbatimLineCommands.end();
I != E; ++I)
if (I->Name == Name)
return true;
return false;
}
namespace { namespace {
bool isHTMLNamedCharacterReferenceCharacter(char C) { bool isHTMLNamedCharacterReferenceCharacter(char C) {
return (C >= 'a' && C <= 'z') || return (C >= 'a' && C <= 'z') ||
@ -433,11 +358,11 @@ void Lexer::lexCommentText(Token &T) {
const StringRef CommandName(BufferPtr + 1, Length); const StringRef CommandName(BufferPtr + 1, Length);
StringRef EndName; StringRef EndName;
if (isVerbatimBlockCommand(CommandName, EndName)) { if (Traits.isVerbatimBlockCommand(CommandName, EndName)) {
setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, EndName); setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, EndName);
return; return;
} }
if (isVerbatimLineCommand(CommandName)) { if (Traits.isVerbatimLineCommand(CommandName)) {
setupAndLexVerbatimLine(T, TokenPtr); setupAndLexVerbatimLine(T, TokenPtr);
return; return;
} }
@ -757,10 +682,10 @@ void Lexer::lexHTMLEndTag(Token &T) {
State = LS_Normal; State = LS_Normal;
} }
Lexer::Lexer(llvm::BumpPtrAllocator &Allocator, Lexer::Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits,
SourceLocation FileLoc, const CommentOptions &CommOpts, SourceLocation FileLoc, const CommentOptions &CommOpts,
const char *BufferStart, const char *BufferEnd): const char *BufferStart, const char *BufferEnd):
Allocator(Allocator), Allocator(Allocator), Traits(Traits),
BufferStart(BufferStart), BufferEnd(BufferEnd), BufferStart(BufferStart), BufferEnd(BufferEnd),
FileLoc(FileLoc), CommOpts(CommOpts), BufferPtr(BufferStart), FileLoc(FileLoc), CommOpts(CommOpts), BufferPtr(BufferStart),
CommentState(LCS_BeforeComment), State(LS_Normal) { CommentState(LCS_BeforeComment), State(LS_Normal) {
@ -885,19 +810,6 @@ StringRef Lexer::getSpelling(const Token &Tok,
return StringRef(Begin, Tok.getLength()); return StringRef(Begin, Tok.getLength());
} }
void Lexer::addVerbatimBlockCommand(StringRef BeginName, StringRef EndName) {
VerbatimBlockCommand VBC;
VBC.BeginName = BeginName;
VBC.EndName = EndName;
VerbatimBlockCommands.push_back(VBC);
}
void Lexer::addVerbatimLineCommand(StringRef Name) {
VerbatimLineCommand VLC;
VLC.Name = Name;
VerbatimLineCommands.push_back(VLC);
}
} // end namespace comments } // end namespace comments
} // end namespace clang } // end namespace clang

View File

@ -10,6 +10,7 @@
#include "clang/AST/CommentParser.h" #include "clang/AST/CommentParser.h"
#include "clang/AST/CommentSema.h" #include "clang/AST/CommentSema.h"
#include "clang/AST/CommentDiagnostic.h" #include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -250,8 +251,10 @@ public:
}; };
Parser::Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator, Parser::Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
const SourceManager &SourceMgr, DiagnosticsEngine &Diags): const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
L(L), S(S), Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags) { const CommandTraits &Traits):
L(L), S(S), Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags),
Traits(Traits) {
consumeToken(); consumeToken();
} }
@ -310,25 +313,25 @@ BlockCommandComment *Parser::parseBlockCommand() {
bool IsParam = false; bool IsParam = false;
bool IsTParam = false; bool IsTParam = false;
unsigned NumArgs = 0; unsigned NumArgs = 0;
if (S.isParamCommand(Tok.getCommandName())) { if (Traits.isParamCommand(Tok.getCommandName())) {
IsParam = true; IsParam = true;
PC = S.actOnParamCommandStart(Tok.getLocation(), PC = S.actOnParamCommandStart(Tok.getLocation(),
Tok.getEndLocation(), Tok.getEndLocation(),
Tok.getCommandName()); Tok.getCommandName());
} if (S.isTParamCommand(Tok.getCommandName())) { } if (Traits.isTParamCommand(Tok.getCommandName())) {
IsTParam = true; IsTParam = true;
TPC = S.actOnTParamCommandStart(Tok.getLocation(), TPC = S.actOnTParamCommandStart(Tok.getLocation(),
Tok.getEndLocation(), Tok.getEndLocation(),
Tok.getCommandName()); Tok.getCommandName());
} else { } else {
NumArgs = S.getBlockCommandNumArgs(Tok.getCommandName()); NumArgs = Traits.getBlockCommandNumArgs(Tok.getCommandName());
BC = S.actOnBlockCommandStart(Tok.getLocation(), BC = S.actOnBlockCommandStart(Tok.getLocation(),
Tok.getEndLocation(), Tok.getEndLocation(),
Tok.getCommandName()); Tok.getCommandName());
} }
consumeToken(); consumeToken();
if (Tok.is(tok::command) && S.isBlockCommand(Tok.getCommandName())) { if (Tok.is(tok::command) && Traits.isBlockCommand(Tok.getCommandName())) {
// Block command ahead. We can't nest block commands, so pretend that this // Block command ahead. We can't nest block commands, so pretend that this
// command has an empty argument. // command has an empty argument.
ParagraphComment *Paragraph = S.actOnParagraphComment( ParagraphComment *Paragraph = S.actOnParagraphComment(
@ -538,12 +541,12 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() {
break; // Block content or EOF ahead, finish this parapgaph. break; // Block content or EOF ahead, finish this parapgaph.
case tok::command: case tok::command:
if (S.isBlockCommand(Tok.getCommandName())) { if (Traits.isBlockCommand(Tok.getCommandName())) {
if (Content.size() == 0) if (Content.size() == 0)
return parseBlockCommand(); return parseBlockCommand();
break; // Block command ahead, finish this parapgaph. break; // Block command ahead, finish this parapgaph.
} }
if (S.isInlineCommand(Tok.getCommandName())) { if (Traits.isInlineCommand(Tok.getCommandName())) {
Content.push_back(parseInlineCommand()); Content.push_back(parseInlineCommand());
continue; continue;
} }

View File

@ -9,6 +9,7 @@
#include "clang/AST/CommentSema.h" #include "clang/AST/CommentSema.h"
#include "clang/AST/CommentDiagnostic.h" #include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
@ -18,8 +19,8 @@ namespace clang {
namespace comments { namespace comments {
Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
DiagnosticsEngine &Diags) : DiagnosticsEngine &Diags, const CommandTraits &Traits) :
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) { ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) {
} }
@ -462,7 +463,7 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
} }
void Sema::checkReturnsCommand(const BlockCommandComment *Command) { void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
if (!isReturnsCommand(Command->getCommandName())) if (!Traits.isReturnsCommand(Command->getCommandName()))
return; return;
if (isFunctionDecl()) { if (isFunctionDecl()) {
if (ThisDeclInfo->ResultType->isVoidType()) { if (ThisDeclInfo->ResultType->isVoidType()) {
@ -498,13 +499,13 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
StringRef Name = Command->getCommandName(); StringRef Name = Command->getCommandName();
const BlockCommandComment *PrevCommand = NULL; const BlockCommandComment *PrevCommand = NULL;
if (isBriefCommand(Name)) { if (Traits.isBriefCommand(Name)) {
if (!BriefCommand) { if (!BriefCommand) {
BriefCommand = Command; BriefCommand = Command;
return; return;
} }
PrevCommand = BriefCommand; PrevCommand = BriefCommand;
} else if (isReturnsCommand(Name)) { } else if (Traits.isReturnsCommand(Name)) {
if (!ReturnsCommand) { if (!ReturnsCommand) {
ReturnsCommand = Command; ReturnsCommand = Command;
return; return;
@ -697,58 +698,9 @@ StringRef Sema::correctTypoInTParamReference(
return StringRef(); return StringRef();
} }
// TODO: tablegen
bool Sema::isBlockCommand(StringRef Name) {
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);
}
bool Sema::isParamCommand(StringRef Name) {
return llvm::StringSwitch<bool>(Name)
.Case("param", true)
.Case("arg", true)
.Default(false);
}
bool Sema::isTParamCommand(StringRef Name) {
return Name == "tparam";
}
bool Sema::isBriefCommand(StringRef Name) {
return Name == "brief" || Name == "short";
}
bool Sema::isReturnsCommand(StringRef Name) {
return Name == "returns" || Name == "return" || Name == "result";
}
unsigned Sema::getBlockCommandNumArgs(StringRef Name) {
return llvm::StringSwitch<unsigned>(Name)
.Cases("brief", "short", 0)
.Case("pre", 0)
.Case("post", 0)
.Case("author", 0)
.Case("authors", 0)
.Default(0);
}
bool Sema::isInlineCommand(StringRef Name) const {
return llvm::StringSwitch<bool>(Name)
.Case("b", true)
.Cases("c", "p", true)
.Cases("a", "e", "em", true)
.Default(false);
}
InlineCommandComment::RenderKind InlineCommandComment::RenderKind
Sema::getInlineCommandRenderKind(StringRef Name) const { Sema::getInlineCommandRenderKind(StringRef Name) const {
assert(isInlineCommand(Name)); assert(Traits.isInlineCommand(Name));
return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name) return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
.Case("b", InlineCommandComment::RenderBold) .Case("b", InlineCommandComment::RenderBold)

View File

@ -11,6 +11,7 @@
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/CommentLexer.h" #include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentBriefParser.h" #include "clang/AST/CommentBriefParser.h"
#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
using namespace clang; using namespace clang;
@ -139,10 +140,11 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const {
// a separate allocator for all temporary stuff. // a separate allocator for all temporary stuff.
llvm::BumpPtrAllocator Allocator; llvm::BumpPtrAllocator Allocator;
comments::Lexer L(Allocator, comments::CommandTraits Traits;
comments::Lexer L(Allocator, Traits,
Range.getBegin(), comments::CommentOptions(), Range.getBegin(), comments::CommentOptions(),
RawText.begin(), RawText.end()); RawText.begin(), RawText.end());
comments::BriefParser P(L); comments::BriefParser P(L, Traits);
const std::string Result = P.Parse(); const std::string Result = P.Parse();
const unsigned BriefTextLength = Result.size(); const unsigned BriefTextLength = Result.size();

View File

@ -11,6 +11,7 @@
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/Diagnostic.h" #include "clang/Basic/Diagnostic.h"
#include "clang/AST/CommentLexer.h" #include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include <vector> #include <vector>
@ -48,7 +49,8 @@ void CommentLexerTest::lexString(const char *Source,
FileID File = SourceMgr.createFileIDForMemBuffer(Buf); FileID File = SourceMgr.createFileIDForMemBuffer(Buf);
SourceLocation Begin = SourceMgr.getLocForStartOfFile(File); SourceLocation Begin = SourceMgr.getLocForStartOfFile(File);
comments::Lexer L(Allocator, Begin, CommentOptions(), comments::CommandTraits Traits;
comments::Lexer L(Allocator, Traits, Begin, CommentOptions(),
Source, Source + strlen(Source)); Source, Source + strlen(Source));
while (1) { while (1) {

View File

@ -14,6 +14,7 @@
#include "clang/AST/CommentLexer.h" #include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentParser.h" #include "clang/AST/CommentParser.h"
#include "clang/AST/CommentSema.h" #include "clang/AST/CommentSema.h"
#include "clang/AST/CommentCommandTraits.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h" #include "llvm/Support/Allocator.h"
#include <vector> #include <vector>
@ -54,11 +55,12 @@ FullComment *CommentParserTest::parseString(const char *Source) {
FileID File = SourceMgr.createFileIDForMemBuffer(Buf); FileID File = SourceMgr.createFileIDForMemBuffer(Buf);
SourceLocation Begin = SourceMgr.getLocForStartOfFile(File); SourceLocation Begin = SourceMgr.getLocForStartOfFile(File);
comments::Lexer L(Allocator, Begin, CommentOptions(), comments::CommandTraits Traits;
comments::Lexer L(Allocator, Traits, Begin, CommentOptions(),
Source, Source + strlen(Source)); Source, Source + strlen(Source));
comments::Sema S(Allocator, SourceMgr, Diags); comments::Sema S(Allocator, SourceMgr, Diags, Traits);
comments::Parser P(L, S, Allocator, SourceMgr, Diags); comments::Parser P(L, S, Allocator, SourceMgr, Diags, Traits);
comments::FullComment *FC = P.parseFullComment(); comments::FullComment *FC = P.parseFullComment();
if (DEBUG) { if (DEBUG) {