//===--- AvoidUnderscoreInGoogletestNameCheck.cpp - clang-tidy --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <string>

#include "AvoidUnderscoreInGoogletestNameCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/MacroArgs.h"

namespace clang {
namespace tidy {
namespace google {
namespace readability {

constexpr llvm::StringLiteral kDisabledTestPrefix = "DISABLED_";

// Determines whether the macro is a Googletest test macro.
static bool isGoogletestTestMacro(StringRef MacroName) {
  static const llvm::StringSet<> MacroNames = {"TEST", "TEST_F", "TEST_P",
                                               "TYPED_TEST", "TYPED_TEST_P"};
  return MacroNames.find(MacroName) != MacroNames.end();
}

namespace {

class AvoidUnderscoreInGoogletestNameCallback : public PPCallbacks {
public:
  AvoidUnderscoreInGoogletestNameCallback(
      Preprocessor *PP, AvoidUnderscoreInGoogletestNameCheck *Check)
      : PP(PP), Check(Check) {}

  // Detects expansions of the TEST, TEST_F, TEST_P, TYPED_TEST, TYPED_TEST_P
  // macros and checks that their arguments do not have any underscores.
  void MacroExpands(const Token &MacroNameToken,
                    const MacroDefinition &MacroDefinition, SourceRange Range,
                    const MacroArgs *Args) override {
    IdentifierInfo *NameIdentifierInfo = MacroNameToken.getIdentifierInfo();
    if (!NameIdentifierInfo)
      return;
    StringRef MacroName = NameIdentifierInfo->getName();
    if (!isGoogletestTestMacro(MacroName) || !Args ||
        Args->getNumMacroArguments() < 2)
      return;
    const Token *TestCaseNameToken = Args->getUnexpArgument(0);
    const Token *TestNameToken = Args->getUnexpArgument(1);
    if (!TestCaseNameToken || !TestNameToken)
      return;
    std::string TestCaseName = PP->getSpelling(*TestCaseNameToken);
    if (TestCaseName.find('_') != std::string::npos)
      Check->diag(TestCaseNameToken->getLocation(),
                  "avoid using \"_\" in test case name \"%0\" according to "
                  "Googletest FAQ")
          << TestCaseName;

    std::string TestNameMaybeDisabled = PP->getSpelling(*TestNameToken);
    StringRef TestName = TestNameMaybeDisabled;
    TestName.consume_front(kDisabledTestPrefix);
    if (TestName.contains('_'))
      Check->diag(TestNameToken->getLocation(),
                  "avoid using \"_\" in test name \"%0\" according to "
                  "Googletest FAQ")
          << TestName;
  }

private:
  Preprocessor *PP;
  AvoidUnderscoreInGoogletestNameCheck *Check;
};

} // namespace

void AvoidUnderscoreInGoogletestNameCheck::registerPPCallbacks(
    const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
  PP->addPPCallbacks(
      std::make_unique<AvoidUnderscoreInGoogletestNameCallback>(PP, this));
}

} // namespace readability
} // namespace google
} // namespace tidy
} // namespace clang
