/* 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 <map>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

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

#include "cmGenExContext.h"
#include "cmGenExEvaluation.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionNode.h"
#include "cmLinkItem.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
#include "cmValue.h"

namespace {
using UseTo = cmGeneratorTarget::UseTo;
using TransitiveProperty = cmGeneratorTarget::TransitiveProperty;

bool ComputingLinkLibraries(cmGeneratorExpressionDAGChecker const* dagChecker)
{
  return dagChecker && dagChecker->IsComputingLinkLibraries();
}
}

std::map<cm::string_view, TransitiveProperty> const
  cmGeneratorTarget::BuiltinTransitiveProperties = {
    { "AUTOMOC_MACRO_NAMES"_s,
      { "INTERFACE_AUTOMOC_MACRO_NAMES"_s, UseTo::Compile } },
    { "AUTOUIC_OPTIONS"_s, { "INTERFACE_AUTOUIC_OPTIONS"_s, UseTo::Compile } },
    { "COMPILE_DEFINITIONS"_s,
      { "INTERFACE_COMPILE_DEFINITIONS"_s, UseTo::Compile } },
    { "COMPILE_FEATURES"_s,
      { "INTERFACE_COMPILE_FEATURES"_s, UseTo::Compile } },
    { "COMPILE_OPTIONS"_s, { "INTERFACE_COMPILE_OPTIONS"_s, UseTo::Compile } },
    { "INCLUDE_DIRECTORIES"_s,
      { "INTERFACE_INCLUDE_DIRECTORIES"_s, UseTo::Compile } },
    { "LINK_DEPENDS"_s, { "INTERFACE_LINK_DEPENDS"_s, UseTo::Link } },
    { "LINK_DIRECTORIES"_s, { "INTERFACE_LINK_DIRECTORIES"_s, UseTo::Link } },
    { "LINK_LIBRARIES"_s, { "INTERFACE_LINK_LIBRARIES"_s, UseTo::Link } },
    { "LINK_OPTIONS"_s, { "INTERFACE_LINK_OPTIONS"_s, UseTo::Link } },
    { "PRECOMPILE_HEADERS"_s,
      { "INTERFACE_PRECOMPILE_HEADERS"_s, UseTo::Compile } },
    { "SOURCES"_s, { "INTERFACE_SOURCES"_s, UseTo::Compile } },
    { "SYSTEM_INCLUDE_DIRECTORIES"_s,
      { "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"_s, UseTo::Compile } },
  };

bool cmGeneratorTarget::MaybeHaveInterfaceProperty(std::string const& prop,
                                                   cm::GenEx::Evaluation* eval,
                                                   UseTo usage) const
{
  std::string const key = cmStrCat(prop, '@', eval->Context.Config);
  auto i = this->MaybeInterfacePropertyExists.find(key);
  if (i == this->MaybeInterfacePropertyExists.end()) {
    // Insert an entry now in case there is a cycle.
    i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
    bool& maybeInterfaceProp = i->second;

    // If this target itself has a non-empty property value, we are done.
    maybeInterfaceProp = cmNonempty(this->GetProperty(prop));

    // Otherwise, recurse to interface dependencies.
    if (!maybeInterfaceProp) {
      cmGeneratorTarget const* headTarget =
        eval->HeadTarget ? eval->HeadTarget : this;
      if (cmLinkInterfaceLibraries const* iface =
            this->GetLinkInterfaceLibraries(eval->Context.Config, headTarget,
                                            usage)) {
        if (iface->HadHeadSensitiveCondition) {
          // With a different head target we may get to a library with
          // this interface property.
          maybeInterfaceProp = true;
        } else {
          // The transitive interface libraries do not depend on the
          // head target, so we can follow them.
          for (cmLinkItem const& lib : iface->Libraries) {
            if (lib.Target &&
                lib.Target->MaybeHaveInterfaceProperty(prop, eval, usage)) {
              maybeInterfaceProp = true;
              break;
            }
          }
        }
      }
    }
  }
  return i->second;
}

std::string cmGeneratorTarget::EvaluateInterfaceProperty(
  std::string const& prop, cm::GenEx::Evaluation* eval,
  cmGeneratorExpressionDAGChecker* dagCheckerParent, UseTo usage) const
{
  std::string result;

  // If the property does not appear transitively at all, we are done.
  if (!this->MaybeHaveInterfaceProperty(prop, eval, usage)) {
    return result;
  }

  // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled.  This is
  // a subset of TargetPropertyNode::Evaluate without stringify/parse steps
  // but sufficient for transitive interface properties.
  cmGeneratorExpressionDAGChecker dagChecker{
    this, prop, nullptr, dagCheckerParent, eval->Context, eval->Backtrace,
  };
  switch (dagChecker.Check()) {
    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
      dagChecker.ReportError(
        eval, cmStrCat("$<TARGET_PROPERTY:", this->GetName(), ',', prop, '>'));
      return result;
    case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
      // No error. We just skip cyclic references.
    case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
      // No error. We have already seen this transitive property.
      return result;
    case cmGeneratorExpressionDAGChecker::DAG:
      break;
  }

  cmGeneratorTarget const* headTarget =
    eval->HeadTarget ? eval->HeadTarget : this;

  if (cmValue p = this->GetProperty(prop)) {
    result = cmGeneratorExpressionNode::EvaluateDependentExpression(
      *p, eval, headTarget, &dagChecker, this);
  }

  if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries(
        eval->Context.Config, headTarget, usage)) {
    eval->HadContextSensitiveCondition = eval->HadContextSensitiveCondition ||
      iface->HadContextSensitiveCondition;
    for (cmLinkItem const& lib : iface->Libraries) {
      // Broken code can have a target in its own link interface.
      // Don't follow such link interface entries so as not to create a
      // self-referencing loop.
      if (lib.Target && lib.Target != this) {
        // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in the
        // above property and hand-evaluate it as if it were compiled.
        // Create a context as cmCompiledGeneratorExpression::Evaluate does.
        cm::GenEx::Evaluation libEval(eval->Context, eval->Quiet, headTarget,
                                      this, eval->EvaluateForBuildsystem,
                                      eval->Backtrace);
        std::string libResult = cmGeneratorExpression::StripEmptyListElements(
          lib.Target->EvaluateInterfaceProperty(prop, &libEval, &dagChecker,
                                                usage));
        if (!libResult.empty()) {
          if (result.empty()) {
            result = std::move(libResult);
          } else {
            result.reserve(result.size() + 1 + libResult.size());
            result += ";";
            result += libResult;
          }
        }
        eval->HadContextSensitiveCondition =
          eval->HadContextSensitiveCondition ||
          libEval.HadContextSensitiveCondition;
        eval->HadHeadSensitiveCondition =
          eval->HadHeadSensitiveCondition || libEval.HadHeadSensitiveCondition;
      }
    }
  }

  return result;
}

cm::optional<cmGeneratorTarget::TransitiveProperty>
cmGeneratorTarget::IsTransitiveProperty(
  cm::string_view prop, cm::GenEx::Context const& context,
  cmGeneratorExpressionDAGChecker const* dagChecker) const
{
  cm::optional<TransitiveProperty> result;
  static cm::string_view const kINTERFACE_ = "INTERFACE_"_s;
  PropertyFor const propertyFor = cmHasPrefix(prop, kINTERFACE_)
    ? PropertyFor::Interface
    : PropertyFor::Build;
  if (propertyFor == PropertyFor::Interface) {
    prop = prop.substr(kINTERFACE_.length());
  }
  auto i = BuiltinTransitiveProperties.find(prop);
  if (i != BuiltinTransitiveProperties.end() &&
      // Look up CMP0189 in the context where evaluation occurs,
      // not where the target was created.
      context.GetCMP0189() != cmPolicies::NEW && prop == "LINK_LIBRARIES"_s) {
    i = BuiltinTransitiveProperties.end();
  }
  if (i != BuiltinTransitiveProperties.end()) {
    result = i->second;
    if (result->Usage != cmGeneratorTarget::UseTo::Compile) {
      cmPolicies::PolicyStatus cmp0166 =
        context.LG->GetPolicyStatus(cmPolicies::CMP0166);
      if ((cmp0166 == cmPolicies::WARN || cmp0166 == cmPolicies::OLD) &&
          (prop == "LINK_DIRECTORIES"_s || prop == "LINK_DEPENDS"_s ||
           prop == "LINK_OPTIONS"_s)) {
        result->Usage = cmGeneratorTarget::UseTo::Compile;
      }
    }
  } else if (!ComputingLinkLibraries(dagChecker)) {
    // Honor TRANSITIVE_COMPILE_PROPERTIES and TRANSITIVE_LINK_PROPERTIES
    // from the link closure when we are not evaluating the closure itself.
    CustomTransitiveProperties const& ctp =
      this->GetCustomTransitiveProperties(context.Config, propertyFor);
    auto ci = ctp.find(std::string(prop));
    if (ci != ctp.end()) {
      result = ci->second;
    }
  }
  return result;
}

cmGeneratorTarget::CustomTransitiveProperty::CustomTransitiveProperty(
  std::string interfaceName, UseTo usage)
  : CustomTransitiveProperty(
      cm::make_unique<std::string>(std::move(interfaceName)), usage)
{
}
cmGeneratorTarget::CustomTransitiveProperty::CustomTransitiveProperty(
  std::unique_ptr<std::string> interfaceNameBuf, UseTo usage)
  : TransitiveProperty{ *interfaceNameBuf, usage }
  , InterfaceNameBuf(std::move(interfaceNameBuf))
{
}

void cmGeneratorTarget::CustomTransitiveProperties::Add(cmValue props,
                                                        UseTo usage)
{
  if (props) {
    cmList propsList(*props);
    for (std::string p : propsList) {
      std::string ip;
      static cm::string_view const kINTERFACE_ = "INTERFACE_"_s;
      if (cmHasPrefix(p, kINTERFACE_)) {
        ip = std::move(p);
        p = ip.substr(kINTERFACE_.length());
      } else {
        ip = cmStrCat(kINTERFACE_, p);
      }
      this->emplace(std::move(p),
                    CustomTransitiveProperty(std::move(ip), usage));
    }
  }
}

cmGeneratorTarget::CustomTransitiveProperties const&
cmGeneratorTarget::GetCustomTransitiveProperties(std::string const& config,
                                                 PropertyFor propertyFor) const
{
  std::map<std::string, CustomTransitiveProperties>& ctpm =
    propertyFor == PropertyFor::Build
    ? this->CustomTransitiveBuildPropertiesMap
    : this->CustomTransitiveInterfacePropertiesMap;
  auto i = ctpm.find(config);
  if (i == ctpm.end()) {
    CustomTransitiveProperties ctp;
    auto addTransitiveProperties = [this, &config, propertyFor,
                                    &ctp](std::string const& tp, UseTo usage) {
      // Add transitive properties named by the target itself.
      ctp.Add(this->GetProperty(tp), usage);
      // Add transitive properties named by the target's link dependencies.
      if (propertyFor == PropertyFor::Build) {
        for (cmGeneratorTarget const* gt :
             this->GetLinkImplementationClosure(config, usage)) {
          ctp.Add(gt->GetProperty(tp), usage);
        }
      } else {
        // The set of custom transitive INTERFACE_ properties does not
        // depend on the consumer.  Use the target as its own head.
        cmGeneratorTarget const* headTarget = this;
        for (cmGeneratorTarget const* gt :
             this->GetLinkInterfaceClosure(config, headTarget, usage)) {
          ctp.Add(gt->GetProperty(tp), usage);
        }
      }
    };
    addTransitiveProperties("TRANSITIVE_LINK_PROPERTIES", UseTo::Link);
    addTransitiveProperties("TRANSITIVE_COMPILE_PROPERTIES", UseTo::Compile);
    i = ctpm.emplace(config, std::move(ctp)).first;
  }
  return i->second;
}
