1111#include " clang/Lex/Preprocessor.h"
1212#include < optional>
1313
14- namespace clang ::tidy::google::readability {
14+ namespace clang ::tidy {
15+
16+ namespace google ::readability {
17+
18+ enum class StyleKind { Parentheses, Hyphen };
19+
20+ } // namespace google::readability
21+
22+ template <> struct OptionEnumMapping <google::readability::StyleKind> {
23+ static ArrayRef<std::pair<google::readability::StyleKind, StringRef>>
24+ getEnumMapping () {
25+ static constexpr std::pair<google::readability::StyleKind, StringRef>
26+ Mapping[] = {
27+ {google::readability::StyleKind::Hyphen, " Hyphen" },
28+ {google::readability::StyleKind::Parentheses, " Parentheses" },
29+ };
30+ return {Mapping};
31+ }
32+ };
33+
34+ } // namespace clang::tidy
1535
36+ namespace clang ::tidy::google::readability {
1637class TodoCommentCheck ::TodoCommentHandler : public CommentHandler {
1738public:
1839 TodoCommentHandler (TodoCommentCheck &Check, std::optional<std::string> User)
1940 : Check(Check), User(User ? *User : " unknown" ),
20- TodoMatch (" ^// *TODO *(\\ (.*\\ ))?:?( )?(.*)$" ) {}
41+ TodoMatch (R"( ^// *TODO *((\((.*)\))?:?( )?|: *(.*) *- *)?(.*)$)" ) {
42+ const llvm::StringRef TodoStyleString =
43+ Check.Options .get (" Style" , " Hyphen" );
44+ for (const auto &[Value, Name] :
45+ OptionEnumMapping<StyleKind>::getEnumMapping ()) {
46+ if (Name == TodoStyleString) {
47+ TodoStyle = Value;
48+ return ;
49+ }
50+ }
51+ Check.configurationDiag (
52+ " invalid value '%0' for "
53+ " google-readability-todo.Style; valid values are "
54+ " 'Parentheses' and 'Hyphen'. Defaulting to 'Hyphen'" )
55+ << TodoStyleString;
56+ }
2157
2258 bool HandleComment (Preprocessor &PP, SourceRange Range) override {
2359 const StringRef Text =
2460 Lexer::getSourceText (CharSourceRange::getCharRange (Range),
2561 PP.getSourceManager (), PP.getLangOpts ());
2662
27- SmallVector<StringRef, 4 > Matches;
63+ SmallVector<StringRef, 7 > Matches;
2864 if (!TodoMatch.match (Text, &Matches))
2965 return false ;
3066
31- const StringRef Username = Matches[1 ];
32- const StringRef Comment = Matches[3 ];
67+ const StyleKind ParsedStyle =
68+ !Matches[3 ].empty () ? StyleKind::Parentheses : StyleKind::Hyphen;
69+ const StringRef Username =
70+ ParsedStyle == StyleKind::Parentheses ? Matches[3 ] : Matches[5 ];
71+ const StringRef Comment = Matches[6 ];
3372
34- if (!Username.empty ())
73+ if (!Username.empty () &&
74+ (ParsedStyle == StyleKind::Parentheses || !Comment.empty ())) {
3575 return false ;
76+ }
3677
37- const std::string NewText =
38- (" // TODO(" + Twine (User) + " ): " + Comment).str ();
78+ if (Username.empty ()) {
79+ Check.diag (Range.getBegin (), " missing username/bug in TODO" )
80+ << FixItHint::CreateReplacement (
81+ CharSourceRange::getCharRange (Range),
82+ createReplacementString (Username, Comment));
83+ }
84+
85+ if (Comment.empty ())
86+ Check.diag (Range.getBegin (), " missing details in TODO" );
3987
40- Check.diag (Range.getBegin (), " missing username/bug in TODO" )
41- << FixItHint::CreateReplacement (CharSourceRange::getCharRange (Range),
42- NewText);
4388 return false ;
4489 }
4590
91+ std::string createReplacementString (const StringRef Username,
92+ const StringRef Comment) const {
93+ if (TodoStyle == StyleKind::Parentheses) {
94+ return (" // TODO(" + Twine (User) +
95+ " ): " + (Comment.empty () ? " some details" : Comment))
96+ .str ();
97+ }
98+ return (" // TODO: " + Twine (User) + " - " +
99+ (Comment.empty () ? " some details" : Comment))
100+ .str ();
101+ }
102+
103+ StyleKind getTodoStyle () const { return TodoStyle; }
104+
46105private:
47106 TodoCommentCheck &Check;
48107 std::string User;
49108 llvm::Regex TodoMatch;
109+ StyleKind TodoStyle = StyleKind::Hyphen;
50110};
51111
52112TodoCommentCheck::TodoCommentCheck (StringRef Name, ClangTidyContext *Context)
@@ -62,4 +122,8 @@ void TodoCommentCheck::registerPPCallbacks(const SourceManager &SM,
62122 PP->addCommentHandler (Handler.get ());
63123}
64124
125+ void TodoCommentCheck::storeOptions (ClangTidyOptions::OptionMap &Opts) {
126+ Options.store (Opts, " Style" , Handler->getTodoStyle ());
127+ }
128+
65129} // namespace clang::tidy::google::readability
0 commit comments