xref: /llvm-project/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp (revision 7d2ea6c422d3f5712b7253407005e1a465a76946)
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 #include <optional>
13 
14 namespace clang::tidy::google::readability {
15 
16 class TodoCommentCheck::TodoCommentHandler : public CommentHandler {
17 public:
TodoCommentHandler(TodoCommentCheck & Check,std::optional<std::string> User)18   TodoCommentHandler(TodoCommentCheck &Check, std::optional<std::string> User)
19       : Check(Check), User(User ? *User : "unknown"),
20         TodoMatch("^// *TODO *(\\(.*\\))?:?( )?(.*)$") {}
21 
HandleComment(Preprocessor & PP,SourceRange Range)22   bool HandleComment(Preprocessor &PP, SourceRange Range) override {
23     StringRef Text =
24         Lexer::getSourceText(CharSourceRange::getCharRange(Range),
25                              PP.getSourceManager(), PP.getLangOpts());
26 
27     SmallVector<StringRef, 4> Matches;
28     if (!TodoMatch.match(Text, &Matches))
29       return false;
30 
31     StringRef Username = Matches[1];
32     StringRef Comment = Matches[3];
33 
34     if (!Username.empty())
35       return false;
36 
37     std::string NewText = ("// TODO(" + Twine(User) + "): " + Comment).str();
38 
39     Check.diag(Range.getBegin(), "missing username/bug in TODO")
40         << FixItHint::CreateReplacement(CharSourceRange::getCharRange(Range),
41                                         NewText);
42     return false;
43   }
44 
45 private:
46   TodoCommentCheck &Check;
47   std::string User;
48   llvm::Regex TodoMatch;
49 };
50 
TodoCommentCheck(StringRef Name,ClangTidyContext * Context)51 TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context)
52     : ClangTidyCheck(Name, Context),
53       Handler(std::make_unique<TodoCommentHandler>(
54           *this, Context->getOptions().User)) {}
55 
56 TodoCommentCheck::~TodoCommentCheck() = default;
57 
registerPPCallbacks(const SourceManager & SM,Preprocessor * PP,Preprocessor * ModuleExpanderPP)58 void TodoCommentCheck::registerPPCallbacks(const SourceManager &SM,
59                                            Preprocessor *PP,
60                                            Preprocessor *ModuleExpanderPP) {
61   PP->addCommentHandler(Handler.get());
62 }
63 
64 } // namespace clang::tidy::google::readability
65