/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
/* clang-format off */
#include "cmGeneratorTarget.h"
/* clang-format on */

#include <algorithm>
#include <array>
#include <initializer_list>
#include <map>
#include <ostream>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <cm/memory>
#include <cm/optional>
#include <cm/string_view>

#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorFileSet.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
#include "cmValue.h"

bool cmGeneratorTarget::AddHeaderSetVerification()
{
  for (bool const isInterface : { false, true }) {
    if (!this->GetPropertyAsBool(isInterface ? "VERIFY_INTERFACE_HEADER_SETS"
                                             : "VERIFY_PRIVATE_HEADER_SETS")) {
      continue;
    }

    if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
        this->GetType() != cmStateEnums::SHARED_LIBRARY &&
        (this->GetType() != cmStateEnums::MODULE_LIBRARY || isInterface) &&
        this->GetType() != cmStateEnums::UNKNOWN_LIBRARY &&
        this->GetType() != cmStateEnums::OBJECT_LIBRARY &&
        this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
        this->GetType() != cmStateEnums::EXECUTABLE) {
      continue;
    }

    char const* headerSetsProperty = isInterface
      ? "INTERFACE_HEADER_SETS_TO_VERIFY"
      : "PRIVATE_HEADER_SETS_TO_VERIFY";

    auto verifyValue = this->GetProperty(headerSetsProperty);
    bool const all = verifyValue.IsEmpty();
    std::set<std::string> verifySet;
    if (!all) {
      cmList verifyList{ verifyValue };
      verifySet.insert(verifyList.begin(), verifyList.end());
    }

    cmTarget* verifyTarget = nullptr;
    std::string const verifyTargetName =
      cmStrCat(this->GetName(),
               isInterface ? "_verify_interface_header_sets"
                           : "_verify_private_header_sets");

    char const* allVerifyTargetName = isInterface
      ? "all_verify_interface_header_sets"
      : "all_verify_private_header_sets";
    cmTarget* allVerifyTarget =
      this->GlobalGenerator->GetMakefiles().front()->FindTargetToUse(
        allVerifyTargetName, { cmStateEnums::TargetDomain::NATIVE });

    auto fileSetEntries = isInterface
      ? this->GetInterfaceFileSets(cm::FileSetMetadata::HEADERS)
      : this->GetFileSets(cm::FileSetMetadata::HEADERS);

    std::set<cmGeneratorFileSet const*> fileSets;
    for (auto const& fileSet : fileSetEntries) {
      if (all || verifySet.count(fileSet->GetName())) {
        fileSets.insert(fileSet);
        verifySet.erase(fileSet->GetName());
      }
    }

    if (isInterface) {
      cmPolicies::PolicyStatus const cmp0209 = this->GetPolicyStatusCMP0209();
      if (cmp0209 != cmPolicies::NEW &&
          this->GetType() == cmStateEnums::EXECUTABLE &&
          !this->GetPropertyAsBool("ENABLE_EXPORTS")) {
        if (cmp0209 == cmPolicies::WARN && !fileSets.empty()) {
          this->Makefile->IssueMessage(
            MessageType::AUTHOR_WARNING,
            cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0209),
                     "\n"
                     "Executable target \"",
                     this->GetName(),
                     "\" has interface header file sets, but it does not "
                     "enable exports. Those headers would be verified under "
                     "CMP0209 NEW behavior.\n"));
        }
        continue;
      }
    }

    if (!verifySet.empty()) {
      this->Makefile->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("Property ", headerSetsProperty, " of target \"",
                 this->GetName(),
                 "\" contained the following header sets that are nonexistent "
                 "or not ",
                 isInterface ? "INTERFACE" : "PRIVATE", ":\n  ",
                 cmJoin(verifySet, "\n  ")));
      return false;
    }

    cm::optional<cm::optional<std::string>> defaultLanguage;

    // First, collect all verification stubs before creating the target,
    // so we know whether to create an OBJECT library or not.
    std::vector<std::string> stubSources;
    for (auto const* fileSet : fileSets) {
      auto const& dirCges = fileSet->CompileDirectoryEntries();
      auto const& fileCges = fileSet->CompileFileEntries();

      static auto const contextSensitive =
        [](std::unique_ptr<cmCompiledGeneratorExpression> const& cge) {
          return cge->GetHadContextSensitiveCondition();
        };
      bool dirCgesContextSensitive = false;
      bool fileCgesContextSensitive = false;

      std::vector<std::string> dirs;
      std::map<std::string, std::vector<std::string>> filesPerDir;
      bool first = true;
      for (auto const& config : this->Makefile->GetGeneratorConfigs(
             cmMakefile::GeneratorConfigQuery::IncludeEmptyConfig)) {
        cm::GenEx::Context context(this->LocalGenerator, config);
        if (first || dirCgesContextSensitive) {
          dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, this);
          dirCgesContextSensitive =
            std::any_of(dirCges.begin(), dirCges.end(), contextSensitive);
        }
        if (first || fileCgesContextSensitive) {
          filesPerDir.clear();
          for (auto const& fileCge : fileCges) {
            fileSet->EvaluateFileEntry(dirs, filesPerDir, fileCge, context,
                                       this);
            if (fileCge->GetHadContextSensitiveCondition()) {
              fileCgesContextSensitive = true;
            }
          }
        }

        for (auto const& files : filesPerDir) {
          for (auto const& file : files.second) {
            cm::optional<std::string> filenameOpt =
              this->GenerateHeaderSetVerificationFile(
                *this->Makefile->GetOrCreateSource(file), files.first,
                verifyTargetName, defaultLanguage);
            if (!filenameOpt) {
              continue;
            }
            std::string filename = *filenameOpt;

            if (fileCgesContextSensitive) {
              filename = cmStrCat("$<$<CONFIG:", config, ">:", filename, '>');
            }
            stubSources.emplace_back(std::move(filename));
          }
        }

        if (!dirCgesContextSensitive && !fileCgesContextSensitive) {
          break;
        }
        first = false;
      }
    }

    if (stubSources.empty()) {
      // No headers to verify. Create a utility target so the target
      // name always exists (e.g. for build system dependencies) without
      // needing a placeholder source. This avoids warnings from tools
      // like Xcode's libtool about empty static libraries.
      verifyTarget =
        this->Makefile->AddNewUtilityTarget(verifyTargetName, true);
    } else {
      // Create an OBJECT library to compile the verification stubs.
      {
        cmMakefile::PolicyPushPop polScope(this->Makefile);
        this->Makefile->SetPolicy(cmPolicies::CMP0119, cmPolicies::NEW);
        verifyTarget = this->Makefile->AddLibrary(
          verifyTargetName, cmStateEnums::OBJECT_LIBRARY, {}, true);
      }

      if (isInterface) {
        // Link to the original target so that we pick up its
        // interface compile options just like a consumer would.
        // This also ensures any generated headers in the original
        // target will be created.
        verifyTarget->AddLinkLibrary(
          *this->Makefile, this->GetName(),
          cmTargetLinkLibraryType::GENERAL_LibraryType);
      } else {
        // For private file sets, we need to simulate compiling the
        // same way as the original target. That includes linking to
        // the same things so we pick up the same transitive
        // properties. For the <LANG>_... properties, we don't care if
        // we set them for languages this target won't eventually use.
        // Copy language-standard properties for all supported
        // languages. We don't care if we set properties for languages
        // this target won't eventually use.
        static std::array<std::string, 19> const propertiesToCopy{ {
          "COMPILE_DEFINITIONS",    "COMPILE_FEATURES",
          "COMPILE_FLAGS",          "COMPILE_OPTIONS",
          "DEFINE_SYMBOL",          "INCLUDE_DIRECTORIES",
          "LINK_LIBRARIES",         "C_STANDARD",
          "C_STANDARD_REQUIRED",    "C_EXTENSIONS",
          "CXX_STANDARD",           "CXX_STANDARD_REQUIRED",
          "CXX_EXTENSIONS",         "OBJC_STANDARD",
          "OBJC_STANDARD_REQUIRED", "OBJC_EXTENSIONS",
          "OBJCXX_STANDARD",        "OBJCXX_STANDARD_REQUIRED",
          "OBJCXX_EXTENSIONS",
        } };
        for (std::string const& prop : propertiesToCopy) {
          cmValue propValue = this->Target->GetProperty(prop);
          if (propValue.IsSet()) {
            verifyTarget->SetProperty(prop, propValue);
          }
        }
        // The original target might have generated headers. Since
        // we only link to the original target for compilation,
        // there's nothing to force such generation to happen yet.
        // Our verify target must depend on the original target to
        // ensure such generated files will be created.
        verifyTarget->AddUtility(this->GetName(), false, this->Makefile);
        verifyTarget->AddCodegenDependency(this->GetName());
      }

      verifyTarget->SetProperty("AUTOMOC", "OFF");
      verifyTarget->SetProperty("AUTORCC", "OFF");
      verifyTarget->SetProperty("AUTOUIC", "OFF");
      verifyTarget->SetProperty("DISABLE_PRECOMPILE_HEADERS", "ON");
      verifyTarget->SetProperty("UNITY_BUILD", "OFF");
      verifyTarget->SetProperty("CXX_SCAN_FOR_MODULES", "OFF");

      if (isInterface) {
        verifyTarget->FinalizeTargetConfiguration(
          this->Makefile->GetCompileDefinitionsEntries());
      } else {
        // Private verification only needs to add the directory scope
        // definitions here
        for (auto const& def :
             this->Makefile->GetCompileDefinitionsEntries()) {
          verifyTarget->InsertCompileDefinition(def);
        }
      }

      for (auto const& source : stubSources) {
        verifyTarget->AddSource(source);
      }
    }
    if (!allVerifyTarget) {
      allVerifyTarget =
        this->GlobalGenerator->GetMakefiles().front()->AddNewUtilityTarget(
          allVerifyTargetName, true);
    }
    allVerifyTarget->AddUtility(verifyTargetName, false);

    this->LocalGenerator->AddGeneratorTarget(
      cm::make_unique<cmGeneratorTarget>(verifyTarget, this->LocalGenerator));
  }
  return true;
}

cm::optional<std::string> cmGeneratorTarget::GenerateHeaderSetVerificationFile(
  cmSourceFile& source, std::string const& dir,
  std::string const& verifyTargetName,
  cm::optional<cm::optional<std::string>>& defaultLanguage) const
{
  if (source.GetPropertyAsBool("SKIP_LINTING")) {
    return cm::nullopt;
  }

  cm::optional<std::string> language =
    this->ResolveHeaderLanguage(source, defaultLanguage);
  if (!language) {
    return cm::nullopt;
  }

  std::string headerFilename = dir;
  if (!headerFilename.empty()) {
    headerFilename += '/';
  }
  headerFilename += source.GetLocation().GetName();

  return this->GenerateStubForLanguage(*language, headerFilename,
                                       verifyTargetName, source);
}

cm::optional<std::string> cmGeneratorTarget::ResolveHeaderLanguage(
  cmSourceFile& source,
  cm::optional<cm::optional<std::string>>& defaultLanguage) const
{
  static std::array<cm::string_view, 4> const supportedLangs{ {
    "C",
    "CXX",
    "OBJC",
    "OBJCXX",
  } };
  auto isSupported = [](cm::string_view lang) -> bool {
    return std::find(supportedLangs.begin(), supportedLangs.end(), lang) !=
      supportedLangs.end();
  };

  // If the source has an explicit language, validate and return it.
  std::string language = source.GetOrDetermineLanguage();
  if (!language.empty()) {
    if (!isSupported(language)) {
      return cm::nullopt;
    }
    return cm::optional<std::string>(std::move(language));
  }

  /*
    Compute and cache the default language for unlanguaged headers.
    The lattice join is run once per file set, not once per header.
    Lattice:   OBJCXX
              /      \
            CXX      OBJC
              \      /
                 C
  */
  if (!defaultLanguage) {
    std::set<std::string> langs;
    for (AllConfigSource const& tgtSource : this->GetAllConfigSources()) {
      std::string const& lang = tgtSource.Source->GetOrDetermineLanguage();
      if (isSupported(lang)) {
        langs.insert(lang);
      }
    }
    if (langs.empty()) {
      std::vector<std::string> languagesVector;
      this->GlobalGenerator->GetEnabledLanguages(languagesVector);
      for (std::string const& lang : languagesVector) {
        if (isSupported(lang)) {
          langs.insert(lang);
        }
      }
    }

    cm::optional<std::string> resolved;
    if (langs.count("OBJCXX") || (langs.count("CXX") && langs.count("OBJC"))) {
      resolved = "OBJCXX"; // promote
    } else if (langs.count("CXX")) {
      resolved = "CXX";
    } else if (langs.count("OBJC")) {
      resolved = "OBJC";
    } else if (langs.count("C")) {
      resolved = "C";
    }
    defaultLanguage = resolved;
  }

  return *defaultLanguage;
}

cm::optional<std::string> cmGeneratorTarget::GenerateStubForLanguage(
  std::string const& language, std::string const& headerFilename,
  std::string const& verifyTargetName, cmSourceFile& source) const
{
  static std::array<std::pair<cm::string_view, cm::string_view>, 4> const
    langToExt = { {
      { "C", ".c" },
      { "CXX", ".cxx" },
      { "OBJC", ".m" },
      { "OBJCXX", ".mm" },
    } };

  // NOLINTNEXTLINE(readability-qualified-auto)
  auto const it =
    std::find_if(langToExt.begin(), langToExt.end(),
                 [&](std::pair<cm::string_view, cm::string_view> const& p) {
                   return p.first == language;
                 });
  if (it == langToExt.end()) {
    return cm::nullopt;
  }

  std::string filename =
    cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
             verifyTargetName, '/', headerFilename, it->second);

  cmSourceFile* verificationSource =
    this->Makefile->GetOrCreateSource(filename);
  source.SetSpecialSourceType(
    cmSourceFile::SpecialSourceType::HeaderSetVerificationSource);
  verificationSource->SetProperty("LANGUAGE", language);

  cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(filename));

  cmGeneratedFileStream fout(filename);
  fout.SetCopyIfDifferent(true);
  // The IWYU "associated" pragma tells include-what-you-use to
  // consider the headerFile as part of the entire language
  // unit within include-what-you-use and as a result allows
  // one to get IWYU advice for headers.
  // Also suppress clang-tidy include checks in generated code.
  fout
    << "/* NOLINTNEXTLINE(misc-header-include-cycle,misc-include-cleaner) */\n"
    << "#include <" << headerFilename << "> /* IWYU pragma: associated */\n";
  fout.close();

  return cm::optional<std::string>(std::move(filename));
}
