//===--- UseDesignatedInitializersCheck.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 "UseDesignatedInitializersCheck.h"
#include "../utils/DesignatedInitializers.h"
#include "clang/AST/APValue.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang::tidy::modernize {

static constexpr char IgnoreSingleElementAggregatesName[] =
    "IgnoreSingleElementAggregates";
static constexpr bool IgnoreSingleElementAggregatesDefault = true;

static constexpr char RestrictToPODTypesName[] = "RestrictToPODTypes";
static constexpr bool RestrictToPODTypesDefault = false;

static constexpr char IgnoreMacrosName[] = "IgnoreMacros";
static constexpr bool IgnoreMacrosDefault = true;

namespace {

struct Designators {

  Designators(const InitListExpr *InitList) : InitList(InitList) {
    assert(InitList->isSyntacticForm());
  };

  unsigned size() { return getCached().size(); }

  std::optional<llvm::StringRef> operator[](const SourceLocation &Location) {
    const auto &Designators = getCached();
    const auto Result = Designators.find(Location);
    if (Result == Designators.end())
      return {};
    const llvm::StringRef Designator = Result->getSecond();
    return (Designator.front() == '.' ? Designator.substr(1) : Designator)
        .trim("\0"); // Trim NULL characters appearing on Windows in the
                     // name.
  }

private:
  using LocationToNameMap = llvm::DenseMap<clang::SourceLocation, std::string>;

  std::optional<LocationToNameMap> CachedDesignators;
  const InitListExpr *InitList;

  LocationToNameMap &getCached() {
    return CachedDesignators ? *CachedDesignators
                             : CachedDesignators.emplace(
                                   utils::getUnwrittenDesignators(InitList));
  }
};

unsigned getNumberOfDesignated(const InitListExpr *SyntacticInitList) {
  return llvm::count_if(*SyntacticInitList, [](auto *InitExpr) {
    return isa<DesignatedInitExpr>(InitExpr);
  });
}

AST_MATCHER(CXXRecordDecl, isAggregate) { return Node.isAggregate(); }

AST_MATCHER(CXXRecordDecl, isPOD) { return Node.isPOD(); }

AST_MATCHER(InitListExpr, isFullyDesignated) {
  if (const InitListExpr *SyntacticForm =
          Node.isSyntacticForm() ? &Node : Node.getSyntacticForm())
    return getNumberOfDesignated(SyntacticForm) == SyntacticForm->getNumInits();
  return true;
}

AST_MATCHER(InitListExpr, hasMoreThanOneElement) {
  return Node.getNumInits() > 1;
}

} // namespace

UseDesignatedInitializersCheck::UseDesignatedInitializersCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context), IgnoreSingleElementAggregates(Options.get(
                                         IgnoreSingleElementAggregatesName,
                                         IgnoreSingleElementAggregatesDefault)),
      RestrictToPODTypes(
          Options.get(RestrictToPODTypesName, RestrictToPODTypesDefault)),
      IgnoreMacros(
          Options.getLocalOrGlobal(IgnoreMacrosName, IgnoreMacrosDefault)) {}

void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) {
  const auto HasBaseWithFields =
      hasAnyBase(hasType(cxxRecordDecl(has(fieldDecl()))));
  Finder->addMatcher(
      initListExpr(
          hasType(cxxRecordDecl(RestrictToPODTypes ? isPOD() : isAggregate(),
                                unless(HasBaseWithFields))
                      .bind("type")),
          IgnoreSingleElementAggregates ? hasMoreThanOneElement() : anything(),
          unless(isFullyDesignated()))
          .bind("init"),
      this);
}

void UseDesignatedInitializersCheck::check(
    const MatchFinder::MatchResult &Result) {
  const auto *InitList = Result.Nodes.getNodeAs<InitListExpr>("init");
  const auto *Type = Result.Nodes.getNodeAs<CXXRecordDecl>("type");
  if (!Type || !InitList)
    return;
  const auto *SyntacticInitList = InitList->getSyntacticForm();
  if (!SyntacticInitList)
    return;
  Designators Designators{SyntacticInitList};
  const unsigned NumberOfDesignated = getNumberOfDesignated(SyntacticInitList);
  if (SyntacticInitList->getNumInits() - NumberOfDesignated >
      Designators.size())
    return;

  // If the whole initializer list is un-designated, issue only one warning and
  // a single fix-it for the whole expression.
  if (0 == NumberOfDesignated) {
    if (IgnoreMacros && InitList->getBeginLoc().isMacroID())
      return;
    {
      DiagnosticBuilder Diag =
          diag(InitList->getLBraceLoc(),
               "use designated initializer list to initialize %0");
      Diag << Type << InitList->getSourceRange();
      for (const Stmt *InitExpr : *SyntacticInitList) {
        const auto Designator = Designators[InitExpr->getBeginLoc()];
        if (Designator && !Designator->empty())
          Diag << FixItHint::CreateInsertion(InitExpr->getBeginLoc(),
                                             ("." + *Designator + "=").str());
      }
    }
    diag(Type->getBeginLoc(), "aggregate type is defined here",
         DiagnosticIDs::Note);
    return;
  }

  // In case that only a few elements are un-designated (not all as before), the
  // check offers dedicated issues and fix-its for each of them.
  for (const auto *InitExpr : *SyntacticInitList) {
    if (isa<DesignatedInitExpr>(InitExpr))
      continue;
    if (IgnoreMacros && InitExpr->getBeginLoc().isMacroID())
      continue;
    const auto Designator = Designators[InitExpr->getBeginLoc()];
    if (!Designator || Designator->empty()) {
      // There should always be a designator. If there's unexpectedly none, we
      // at least report a generic diagnostic.
      diag(InitExpr->getBeginLoc(), "use designated init expression")
          << InitExpr->getSourceRange();
    } else {
      diag(InitExpr->getBeginLoc(),
           "use designated init expression to initialize field '%0'")
          << InitExpr->getSourceRange() << *Designator
          << FixItHint::CreateInsertion(InitExpr->getBeginLoc(),
                                        ("." + *Designator + "=").str());
    }
  }
}

void UseDesignatedInitializersCheck::storeOptions(
    ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, IgnoreSingleElementAggregatesName,
                IgnoreSingleElementAggregates);
  Options.store(Opts, RestrictToPODTypesName, RestrictToPODTypes);
  Options.store(Opts, IgnoreMacrosName, IgnoreMacros);
}

} // namespace clang::tidy::modernize
