//===--- EnumInitialValueCheck.cpp - clang-tidy ---------------------------===//
//
// 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 "EnumInitialValueCheck.h"
#include "../utils/LexerUtils.h"
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"

using namespace clang::ast_matchers;

namespace clang::tidy::readability {

static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
    return ECD->getInitExpr() == nullptr;
  });
}

static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
  bool IsFirst = true;
  for (const EnumConstantDecl *ECD : Node.enumerators()) {
    if ((IsFirst && ECD->getInitExpr() == nullptr) ||
        (!IsFirst && ECD->getInitExpr() != nullptr))
      return false;
    IsFirst = false;
  }
  return !IsFirst;
}

static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
    return ECD->getInitExpr() != nullptr;
  });
}

/// Check if \p Enumerator is initialized with a (potentially negated) \c
/// IntegerLiteral.
static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
  const Expr *const Init = Enumerator->getInitExpr();
  if (!Init)
    return false;
  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
}

static void cleanInitialValue(DiagnosticBuilder &Diag,
                              const EnumConstantDecl *ECD,
                              const SourceManager &SM,
                              const LangOptions &LangOpts) {
  const SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
      InitExprRange.getEnd().isMacroID())
    return;
  std::optional<Token> EqualToken = utils::lexer::findNextTokenSkippingComments(
      ECD->getLocation(), SM, LangOpts);
  if (!EqualToken.has_value() ||
      EqualToken.value().getKind() != tok::TokenKind::equal)
    return;
  const SourceLocation EqualLoc{EqualToken->getLocation()};
  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
    return;
  Diag << FixItHint::CreateRemoval(EqualLoc)
       << FixItHint::CreateRemoval(InitExprRange);
  return;
}

namespace {

AST_MATCHER(EnumDecl, isMacro) {
  SourceLocation Loc = Node.getBeginLoc();
  return Loc.isMacroID();
}

AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
  return isNoneEnumeratorsInitialized(Node) ||
         isOnlyFirstEnumeratorInitialized(Node) ||
         areAllEnumeratorsInitialized(Node);
}

AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
  const EnumDecl::enumerator_range Enumerators = Node.enumerators();
  if (Enumerators.empty())
    return false;
  const EnumConstantDecl *ECD = *Enumerators.begin();
  return isOnlyFirstEnumeratorInitialized(Node) &&
         isInitializedByLiteral(ECD) && ECD->getInitVal().isZero();
}

/// Excludes bitfields because enumerators initialized with the result of a
/// bitwise operator on enumeration values or any other expr that is not a
/// potentially negative integer literal.
/// Enumerations where it is not directly clear if they are used with
/// bitmask, evident when enumerators are only initialized with (potentially
/// negative) integer literals, are ignored. This is also the case when all
/// enumerators are powers of two (e.g., 0, 1, 2).
AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
  const EnumDecl::enumerator_range Enumerators = Node.enumerators();
  if (Enumerators.empty())
    return false;
  const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin();
  llvm::APSInt PrevValue = FirstEnumerator->getInitVal();
  if (!isInitializedByLiteral(FirstEnumerator))
    return false;
  bool AllEnumeratorsArePowersOfTwo = true;
  for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) {
    const llvm::APSInt NewValue = Enumerator->getInitVal();
    if (NewValue != ++PrevValue)
      return false;
    if (!isInitializedByLiteral(Enumerator))
      return false;
    PrevValue = NewValue;
    AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2();
  }
  return !AllEnumeratorsArePowersOfTwo;
}

std::string getName(const EnumDecl *Decl) {
  if (!Decl->getDeclName())
    return "<unnamed>";

  return Decl->getQualifiedNameAsString();
}

} // namespace

EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
                                             ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      AllowExplicitZeroFirstInitialValue(
          Options.get("AllowExplicitZeroFirstInitialValue", true)),
      AllowExplicitSequentialInitialValues(
          Options.get("AllowExplicitSequentialInitialValues", true)) {}

void EnumInitialValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "AllowExplicitZeroFirstInitialValue",
                AllowExplicitZeroFirstInitialValue);
  Options.store(Opts, "AllowExplicitSequentialInitialValues",
                AllowExplicitSequentialInitialValues);
}

void EnumInitialValueCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(enumDecl(isDefinition(), unless(isMacro()),
                              unless(hasConsistentInitialValues()))
                         .bind("inconsistent"),
                     this);
  if (!AllowExplicitZeroFirstInitialValue)
    Finder->addMatcher(
        enumDecl(isDefinition(), hasZeroInitialValueForFirstEnumerator())
            .bind("zero_first"),
        this);
  if (!AllowExplicitSequentialInitialValues)
    Finder->addMatcher(enumDecl(isDefinition(), unless(isMacro()),
                                hasSequentialInitialValues())
                           .bind("sequential"),
                       this);
}

void EnumInitialValueCheck::check(const MatchFinder::MatchResult &Result) {
  if (const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>("inconsistent")) {
    DiagnosticBuilder Diag =
        diag(
            Enum->getBeginLoc(),
            "initial values in enum '%0' are not consistent, consider explicit "
            "initialization of all, none or only the first enumerator")
        << getName(Enum);
    for (const EnumConstantDecl *ECD : Enum->enumerators())
      if (ECD->getInitExpr() == nullptr) {
        const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
            ECD->getLocation(), 0, *Result.SourceManager, getLangOpts());
        if (EndLoc.isMacroID())
          continue;
        llvm::SmallString<8> Str{" = "};
        ECD->getInitVal().toString(Str);
        Diag << FixItHint::CreateInsertion(EndLoc, Str);
      }
    return;
  }

  if (const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>("zero_first")) {
    const EnumConstantDecl *ECD = *Enum->enumerator_begin();
    const SourceLocation Loc = ECD->getLocation();
    if (Loc.isInvalid() || Loc.isMacroID())
      return;
    DiagnosticBuilder Diag = diag(Loc, "zero initial value for the first "
                                       "enumerator in '%0' can be disregarded")
                             << getName(Enum);
    cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts());
    return;
  }
  if (const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>("sequential")) {
    DiagnosticBuilder Diag =
        diag(Enum->getBeginLoc(),
             "sequential initial value in '%0' can be ignored")
        << getName(Enum);
    for (const EnumConstantDecl *ECD : llvm::drop_begin(Enum->enumerators()))
      cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts());
    return;
  }
}

} // namespace clang::tidy::readability
