From ca7f80ada0d3bb905572d5711111bb3ac2fec434 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 9 Aug 2012 00:03:17 +0000 Subject: [PATCH] Comment parsing: extract TableGen'able pieces into new CommandTraits class. llvm-svn: 161548 --- clang/include/clang/AST/CommentBriefParser.h | 4 +- .../include/clang/AST/CommentCommandTraits.h | 145 ++++++++++++++++++ clang/include/clang/AST/CommentLexer.h | 38 +---- clang/include/clang/AST/CommentParser.h | 6 +- clang/include/clang/AST/CommentSema.h | 14 +- clang/lib/AST/ASTContext.cpp | 9 +- clang/lib/AST/CommentBriefParser.cpp | 30 ++-- clang/lib/AST/CommentCommandTraits.cpp | 110 +++++++++++++ clang/lib/AST/CommentLexer.cpp | 98 +----------- clang/lib/AST/CommentParser.cpp | 19 ++- clang/lib/AST/CommentSema.cpp | 62 +------- clang/lib/AST/RawCommentList.cpp | 6 +- clang/unittests/AST/CommentLexer.cpp | 4 +- clang/unittests/AST/CommentParser.cpp | 8 +- 14 files changed, 322 insertions(+), 231 deletions(-) create mode 100644 clang/include/clang/AST/CommentCommandTraits.h create mode 100644 clang/lib/AST/CommentCommandTraits.cpp diff --git a/clang/include/clang/AST/CommentBriefParser.h b/clang/include/clang/AST/CommentBriefParser.h index 62fdf6bdc412..003c33727e35 100644 --- a/clang/include/clang/AST/CommentBriefParser.h +++ b/clang/include/clang/AST/CommentBriefParser.h @@ -30,6 +30,8 @@ namespace comments { class BriefParser { Lexer &L; + const CommandTraits &Traits; + /// Current lookahead token. Token Tok; @@ -40,7 +42,7 @@ class BriefParser { } public: - BriefParser(Lexer &L); + BriefParser(Lexer &L, const CommandTraits &Traits); /// Return \\brief paragraph, if it exists; otherwise return the first /// paragraph. diff --git a/clang/include/clang/AST/CommentCommandTraits.h b/clang/include/clang/AST/CommentCommandTraits.h new file mode 100644 index 000000000000..85f2d82a4cfa --- /dev/null +++ b/clang/include/clang/AST/CommentCommandTraits.h @@ -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 VerbatimBlockCommandVector; + + /// Registered additional verbatim-like block commands. + VerbatimBlockCommandVector VerbatimBlockCommands; + + struct VerbatimLineCommand { + StringRef Name; + }; + + typedef SmallVector 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(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(Name) + .Case("b", true) + .Cases("c", "p", true) + .Cases("a", "e", "em", true) + .Default(false); +} + +} // end namespace comments +} // end namespace clang + +#endif + diff --git a/clang/include/clang/AST/CommentLexer.h b/clang/include/clang/AST/CommentLexer.h index 5b69a95ee060..7a24b1163178 100644 --- a/clang/include/clang/AST/CommentLexer.h +++ b/clang/include/clang/AST/CommentLexer.h @@ -26,6 +26,7 @@ namespace comments { class Lexer; class TextTokenRetokenizer; +class CommandTraits; namespace tok { enum TokenKind { @@ -215,6 +216,8 @@ private: /// computed (for example, resolved decimal character references). llvm::BumpPtrAllocator &Allocator; + const CommandTraits &Traits; + const char *const BufferStart; const char *const BufferEnd; SourceLocation FileLoc; @@ -262,37 +265,10 @@ private: /// Current lexing mode. 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 VerbatimBlockCommandVector; - - /// Registered verbatim-like block commands. - VerbatimBlockCommandVector VerbatimBlockCommands; - /// If State is LS_VerbatimBlock, contains the name of verbatim end /// command, including command marker. 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 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 /// it stands for (e.g., "<"). StringRef resolveHTMLNamedCharacterReference(StringRef Name) const; @@ -359,7 +335,7 @@ private: void lexHTMLEndTag(Token &T); public: - Lexer(llvm::BumpPtrAllocator &Allocator, + Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits, SourceLocation FileLoc, const CommentOptions &CommOpts, const char *BufferStart, const char *BufferEnd); @@ -368,12 +344,6 @@ public: StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr, 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 diff --git a/clang/include/clang/AST/CommentParser.h b/clang/include/clang/AST/CommentParser.h index 9539c9f54e68..039079931c58 100644 --- a/clang/include/clang/AST/CommentParser.h +++ b/clang/include/clang/AST/CommentParser.h @@ -24,6 +24,7 @@ namespace clang { class SourceManager; namespace comments { +class CommandTraits; /// Doxygen comment parser. class Parser { @@ -48,6 +49,8 @@ class Parser { return Diags.Report(Loc, DiagID); } + const CommandTraits &Traits; + /// Current lookahead token. We can safely assume that all tokens are from /// a single source file. Token Tok; @@ -85,7 +88,8 @@ class Parser { public: 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. void parseParamCommandArgs(ParamCommandComment *PC, diff --git a/clang/include/clang/AST/CommentSema.h b/clang/include/clang/AST/CommentSema.h index 2fc741e7d1ce..e1756ca3e2f1 100644 --- a/clang/include/clang/AST/CommentSema.h +++ b/clang/include/clang/AST/CommentSema.h @@ -27,6 +27,7 @@ class Decl; class SourceMgr; namespace comments { +class CommandTraits; class Sema { Sema(const Sema&); // DO NOT IMPLEMENT @@ -40,6 +41,8 @@ class Sema { DiagnosticsEngine &Diags; + const CommandTraits &Traits; + /// Information about the declaration this comment is attached to. DeclInfo *ThisDeclInfo; @@ -72,7 +75,7 @@ class Sema { public: Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, - DiagnosticsEngine &Diags); + DiagnosticsEngine &Diags, const CommandTraits &Traits); void setDecl(const Decl *D); @@ -213,15 +216,6 @@ public: StringRef Typo, 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 getInlineCommandRenderKind(StringRef Name) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0ff0e35a433f..4e8587d19191 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Comment.h" +#include "clang/AST/CommentCommandTraits.h" #include "clang/AST/CommentLexer.h" #include "clang/AST/CommentSema.h" #include "clang/AST/CommentParser.h" @@ -226,14 +227,16 @@ comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const { return NULL; const StringRef RawText = RC->getRawText(SourceMgr); - comments::Lexer L(getAllocator(), + comments::CommandTraits Traits; + comments::Lexer L(getAllocator(), Traits, RC->getSourceRange().getBegin(), comments::CommentOptions(), RawText.begin(), RawText.end()); - comments::Sema S(getAllocator(), getSourceManager(), getDiagnostics()); + comments::Sema S(getAllocator(), getSourceManager(), getDiagnostics(), + Traits); S.setDecl(D); comments::Parser P(L, S, getAllocator(), getSourceManager(), - getDiagnostics()); + getDiagnostics(), Traits); comments::FullComment *FC = P.parseFullComment(); DeclComments[D].second = FC; diff --git a/clang/lib/AST/CommentBriefParser.cpp b/clang/lib/AST/CommentBriefParser.cpp index 22209c097fd3..0aebc1e4e3dd 100644 --- a/clang/lib/AST/CommentBriefParser.cpp +++ b/clang/lib/AST/CommentBriefParser.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/CommentBriefParser.h" +#include "clang/AST/CommentCommandTraits.h" #include "llvm/ADT/StringSwitch.h" namespace clang { @@ -39,20 +40,14 @@ void cleanupBrief(std::string &S) { S.resize(O - S.begin()); } - -bool isBlockCommand(StringRef Name) { - return llvm::StringSwitch(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 +BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) : + L(L), Traits(Traits) { + // Get lookahead token. + ConsumeToken(); +} + std::string BriefParser::Parse() { std::string FirstParagraphOrBrief; std::string ReturnsParagraph; @@ -72,18 +67,18 @@ std::string BriefParser::Parse() { if (Tok.is(tok::command)) { StringRef Name = Tok.getCommandName(); - if (Name == "brief" || Name == "short") { + if (Traits.isBriefCommand(Name)) { FirstParagraphOrBrief.clear(); InBrief = true; ConsumeToken(); continue; } - if (Name == "result" || Name == "return" || Name == "returns") { + if (Traits.isReturnsCommand(Name)) { InReturns = true; ReturnsParagraph += "Returns "; } // Block commands implicitly start a new paragraph. - if (isBlockCommand(Name)) { + if (Traits.isBlockCommand(Name)) { // We found an implicit paragraph end. InFirstParagraph = false; if (InBrief) @@ -121,11 +116,6 @@ std::string BriefParser::Parse() { return ReturnsParagraph; } -BriefParser::BriefParser(Lexer &L) : L(L) { - // Get lookahead token. - ConsumeToken(); -} - } // end namespace comments } // end namespace clang diff --git a/clang/lib/AST/CommentCommandTraits.cpp b/clang/lib/AST/CommentCommandTraits.cpp new file mode 100644 index 000000000000..804f2ae612d3 --- /dev/null +++ b/clang/lib/AST/CommentCommandTraits.cpp @@ -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(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(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 + diff --git a/clang/lib/AST/CommentLexer.cpp b/clang/lib/AST/CommentLexer.cpp index dde484510ff1..b6516ec126f6 100644 --- a/clang/lib/AST/CommentLexer.cpp +++ b/clang/lib/AST/CommentLexer.cpp @@ -1,4 +1,5 @@ #include "clang/AST/CommentLexer.h" +#include "clang/AST/CommentCommandTraits.h" #include "clang/Basic/ConvertUTF.h" #include "llvm/ADT/StringSwitch.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"; } -bool Lexer::isVerbatimBlockCommand(StringRef BeginName, - StringRef &EndName) const { - const char *Result = llvm::StringSwitch(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(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 { bool isHTMLNamedCharacterReferenceCharacter(char C) { return (C >= 'a' && C <= 'z') || @@ -433,11 +358,11 @@ void Lexer::lexCommentText(Token &T) { const StringRef CommandName(BufferPtr + 1, Length); StringRef EndName; - if (isVerbatimBlockCommand(CommandName, EndName)) { + if (Traits.isVerbatimBlockCommand(CommandName, EndName)) { setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, EndName); return; } - if (isVerbatimLineCommand(CommandName)) { + if (Traits.isVerbatimLineCommand(CommandName)) { setupAndLexVerbatimLine(T, TokenPtr); return; } @@ -757,10 +682,10 @@ void Lexer::lexHTMLEndTag(Token &T) { State = LS_Normal; } -Lexer::Lexer(llvm::BumpPtrAllocator &Allocator, +Lexer::Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits, SourceLocation FileLoc, const CommentOptions &CommOpts, const char *BufferStart, const char *BufferEnd): - Allocator(Allocator), + Allocator(Allocator), Traits(Traits), BufferStart(BufferStart), BufferEnd(BufferEnd), FileLoc(FileLoc), CommOpts(CommOpts), BufferPtr(BufferStart), CommentState(LCS_BeforeComment), State(LS_Normal) { @@ -885,19 +810,6 @@ StringRef Lexer::getSpelling(const Token &Tok, 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 clang diff --git a/clang/lib/AST/CommentParser.cpp b/clang/lib/AST/CommentParser.cpp index eb1027a9b639..43abf6a476a8 100644 --- a/clang/lib/AST/CommentParser.cpp +++ b/clang/lib/AST/CommentParser.cpp @@ -10,6 +10,7 @@ #include "clang/AST/CommentParser.h" #include "clang/AST/CommentSema.h" #include "clang/AST/CommentDiagnostic.h" +#include "clang/AST/CommentCommandTraits.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/ErrorHandling.h" @@ -250,8 +251,10 @@ public: }; Parser::Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator, - const SourceManager &SourceMgr, DiagnosticsEngine &Diags): - L(L), S(S), Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags) { + const SourceManager &SourceMgr, DiagnosticsEngine &Diags, + const CommandTraits &Traits): + L(L), S(S), Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), + Traits(Traits) { consumeToken(); } @@ -310,25 +313,25 @@ BlockCommandComment *Parser::parseBlockCommand() { bool IsParam = false; bool IsTParam = false; unsigned NumArgs = 0; - if (S.isParamCommand(Tok.getCommandName())) { + if (Traits.isParamCommand(Tok.getCommandName())) { IsParam = true; PC = S.actOnParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), Tok.getCommandName()); - } if (S.isTParamCommand(Tok.getCommandName())) { + } if (Traits.isTParamCommand(Tok.getCommandName())) { IsTParam = true; TPC = S.actOnTParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), Tok.getCommandName()); } else { - NumArgs = S.getBlockCommandNumArgs(Tok.getCommandName()); + NumArgs = Traits.getBlockCommandNumArgs(Tok.getCommandName()); BC = S.actOnBlockCommandStart(Tok.getLocation(), Tok.getEndLocation(), Tok.getCommandName()); } 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 // command has an empty argument. ParagraphComment *Paragraph = S.actOnParagraphComment( @@ -538,12 +541,12 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() { break; // Block content or EOF ahead, finish this parapgaph. case tok::command: - if (S.isBlockCommand(Tok.getCommandName())) { + if (Traits.isBlockCommand(Tok.getCommandName())) { if (Content.size() == 0) return parseBlockCommand(); break; // Block command ahead, finish this parapgaph. } - if (S.isInlineCommand(Tok.getCommandName())) { + if (Traits.isInlineCommand(Tok.getCommandName())) { Content.push_back(parseInlineCommand()); continue; } diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 978c748b7416..c39ee573ef6f 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -9,6 +9,7 @@ #include "clang/AST/CommentSema.h" #include "clang/AST/CommentDiagnostic.h" +#include "clang/AST/CommentCommandTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/SourceManager.h" @@ -18,8 +19,8 @@ namespace clang { namespace comments { Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, - DiagnosticsEngine &Diags) : - Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), + DiagnosticsEngine &Diags, const CommandTraits &Traits) : + Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) { } @@ -462,7 +463,7 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { } void Sema::checkReturnsCommand(const BlockCommandComment *Command) { - if (!isReturnsCommand(Command->getCommandName())) + if (!Traits.isReturnsCommand(Command->getCommandName())) return; if (isFunctionDecl()) { if (ThisDeclInfo->ResultType->isVoidType()) { @@ -498,13 +499,13 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { StringRef Name = Command->getCommandName(); const BlockCommandComment *PrevCommand = NULL; - if (isBriefCommand(Name)) { + if (Traits.isBriefCommand(Name)) { if (!BriefCommand) { BriefCommand = Command; return; } PrevCommand = BriefCommand; - } else if (isReturnsCommand(Name)) { + } else if (Traits.isReturnsCommand(Name)) { if (!ReturnsCommand) { ReturnsCommand = Command; return; @@ -697,58 +698,9 @@ StringRef Sema::correctTypoInTParamReference( return StringRef(); } -// TODO: tablegen -bool Sema::isBlockCommand(StringRef Name) { - return isBriefCommand(Name) || isReturnsCommand(Name) || - isParamCommand(Name) || isTParamCommand(Name) || - llvm::StringSwitch(Name) - .Case("author", true) - .Case("authors", true) - .Case("pre", true) - .Case("post", true) - .Default(false); -} - -bool Sema::isParamCommand(StringRef Name) { - return llvm::StringSwitch(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(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(Name) - .Case("b", true) - .Cases("c", "p", true) - .Cases("a", "e", "em", true) - .Default(false); -} - InlineCommandComment::RenderKind Sema::getInlineCommandRenderKind(StringRef Name) const { - assert(isInlineCommand(Name)); + assert(Traits.isInlineCommand(Name)); return llvm::StringSwitch(Name) .Case("b", InlineCommandComment::RenderBold) diff --git a/clang/lib/AST/RawCommentList.cpp b/clang/lib/AST/RawCommentList.cpp index 41866cf03f11..4f7165f0e4a9 100644 --- a/clang/lib/AST/RawCommentList.cpp +++ b/clang/lib/AST/RawCommentList.cpp @@ -11,6 +11,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CommentLexer.h" #include "clang/AST/CommentBriefParser.h" +#include "clang/AST/CommentCommandTraits.h" #include "llvm/ADT/STLExtras.h" using namespace clang; @@ -139,10 +140,11 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const { // a separate allocator for all temporary stuff. llvm::BumpPtrAllocator Allocator; - comments::Lexer L(Allocator, + comments::CommandTraits Traits; + comments::Lexer L(Allocator, Traits, Range.getBegin(), comments::CommentOptions(), RawText.begin(), RawText.end()); - comments::BriefParser P(L); + comments::BriefParser P(L, Traits); const std::string Result = P.Parse(); const unsigned BriefTextLength = Result.size(); diff --git a/clang/unittests/AST/CommentLexer.cpp b/clang/unittests/AST/CommentLexer.cpp index 8b5d0c8cf015..cab0fdddbc2f 100644 --- a/clang/unittests/AST/CommentLexer.cpp +++ b/clang/unittests/AST/CommentLexer.cpp @@ -11,6 +11,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/Diagnostic.h" #include "clang/AST/CommentLexer.h" +#include "clang/AST/CommentCommandTraits.h" #include "llvm/ADT/STLExtras.h" #include @@ -48,7 +49,8 @@ void CommentLexerTest::lexString(const char *Source, FileID File = SourceMgr.createFileIDForMemBuffer(Buf); 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)); while (1) { diff --git a/clang/unittests/AST/CommentParser.cpp b/clang/unittests/AST/CommentParser.cpp index 1e106c59f188..7258a7ef576c 100644 --- a/clang/unittests/AST/CommentParser.cpp +++ b/clang/unittests/AST/CommentParser.cpp @@ -14,6 +14,7 @@ #include "clang/AST/CommentLexer.h" #include "clang/AST/CommentParser.h" #include "clang/AST/CommentSema.h" +#include "clang/AST/CommentCommandTraits.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Allocator.h" #include @@ -54,11 +55,12 @@ FullComment *CommentParserTest::parseString(const char *Source) { FileID File = SourceMgr.createFileIDForMemBuffer(Buf); 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)); - comments::Sema S(Allocator, SourceMgr, Diags); - comments::Parser P(L, S, Allocator, SourceMgr, Diags); + comments::Sema S(Allocator, SourceMgr, Diags, Traits); + comments::Parser P(L, S, Allocator, SourceMgr, Diags, Traits); comments::FullComment *FC = P.parseFullComment(); if (DEBUG) {