1 //===--- TodoCommentCheck.cpp - clang-tidy --------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "TodoCommentCheck.h"
10 #include "clang/Frontend/CompilerInstance.h"
11 #include "clang/Lex/Preprocessor.h"
12 
13 namespace clang {
14 namespace tidy {
15 namespace google {
16 namespace readability {
17 
18 class TodoCommentCheck::TodoCommentHandler : public CommentHandler {
19 public:
TodoCommentHandler(TodoCommentCheck & Check,llvm::Optional<std::string> User)20   TodoCommentHandler(TodoCommentCheck &Check, llvm::Optional<std::string> User)
21       : Check(Check), User(User ? *User : "unknown"),
22         TodoMatch("^// *TODO *(\\(.*\\))?:?( )?(.*)$") {}
23 
HandleComment(Preprocessor & PP,SourceRange Range)24   bool HandleComment(Preprocessor &PP, SourceRange Range) override {
25     StringRef Text =
26         Lexer::getSourceText(CharSourceRange::getCharRange(Range),
27                              PP.getSourceManager(), PP.getLangOpts());
28 
29     SmallVector<StringRef, 4> Matches;
30     if (!TodoMatch.match(Text, &Matches))
31       return false;
32 
33     StringRef Username = Matches[1];
34     StringRef Comment = Matches[3];
35 
36     if (!Username.empty())
37       return false;
38 
39     std::string NewText = ("// TODO(" + Twine(User) + "): " + Comment).str();
40 
41     Check.diag(Range.getBegin(), "missing username/bug in TODO")
42         << FixItHint::CreateReplacement(CharSourceRange::getCharRange(Range),
43                                         NewText);
44     return false;
45   }
46 
47 private:
48   TodoCommentCheck &Check;
49   std::string User;
50   llvm::Regex TodoMatch;
51 };
52 
TodoCommentCheck(StringRef Name,ClangTidyContext * Context)53 TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context)
54     : ClangTidyCheck(Name, Context),
55       Handler(std::make_unique<TodoCommentHandler>(
56           *this, Context->getOptions().User)) {}
57 
58 TodoCommentCheck::~TodoCommentCheck() = default;
59 
registerPPCallbacks(const SourceManager & SM,Preprocessor * PP,Preprocessor * ModuleExpanderPP)60 void TodoCommentCheck::registerPPCallbacks(const SourceManager &SM,
61                                            Preprocessor *PP,
62                                            Preprocessor *ModuleExpanderPP) {
63   PP->addCommentHandler(Handler.get());
64 }
65 
66 } // namespace readability
67 } // namespace google
68 } // namespace tidy
69 } // namespace clang
70