brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 2789e4d Raw
130 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "TodoCommentCheck.h"10#include "clang/Frontend/CompilerInstance.h"11#include "clang/Lex/Preprocessor.h"12#include <optional>13 14namespace clang::tidy {15 16namespace google::readability {17 18enum class StyleKind { Parentheses, Hyphen };19 20} // namespace google::readability21 22template <> 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::tidy35 36namespace clang::tidy::google::readability {37class TodoCommentCheck::TodoCommentHandler : public CommentHandler {38public:39  TodoCommentHandler(TodoCommentCheck &Check, std::optional<std::string> User)40      : Check(Check), User(User ? *User : "unknown"),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  }57 58  bool HandleComment(Preprocessor &PP, SourceRange Range) override {59    const StringRef Text =60        Lexer::getSourceText(CharSourceRange::getCharRange(Range),61                             PP.getSourceManager(), PP.getLangOpts());62 63    SmallVector<StringRef, 7> Matches;64    if (!TodoMatch.match(Text, &Matches))65      return false;66 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];72 73    if (!Username.empty() &&74        (ParsedStyle == StyleKind::Parentheses || !Comment.empty())) {75      return false;76    }77 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");87 88    return false;89  }90 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 105private:106  TodoCommentCheck &Check;107  std::string User;108  llvm::Regex TodoMatch;109  StyleKind TodoStyle = StyleKind::Hyphen;110};111 112TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context)113    : ClangTidyCheck(Name, Context),114      Handler(std::make_unique<TodoCommentHandler>(115          *this, Context->getOptions().User)) {}116 117TodoCommentCheck::~TodoCommentCheck() = default;118 119void TodoCommentCheck::registerPPCallbacks(const SourceManager &SM,120                                           Preprocessor *PP,121                                           Preprocessor *ModuleExpanderPP) {122  PP->addCommentHandler(Handler.get());123}124 125void TodoCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {126  Options.store(Opts, "Style", Handler->getTodoStyle());127}128 129} // namespace clang::tidy::google::readability130