/* 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 "cmGeneratorExpression.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionNode.h"
#include "cmLinkItem.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
#include "cmValue.h"

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

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, cmGeneratorExpressionContext* context,
  UseTo usage) const
{
  std::string const key = prop + '@' + 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 =
        context->HeadTarget ? context->HeadTarget : this;
      if (cmLinkInterfaceLibraries const* iface =
            this->GetLinkInterfaceLibraries(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, context, usage)) {
              maybeInterfaceProp = true;
              break;
            }
          }
        }
      }
    }
  }
  return i->second;
}

std::string cmGeneratorTarget::EvaluateInterfaceProperty(
  std::string const& prop, cmGeneratorExpressionContext* context,
  cmGeneratorExpressionDAGChecker* dagCheckerParent, UseTo usage) const
{
  std::string result;

  // If the property does not appear transitively at all, we are done.
  if (!this->MaybeHaveInterfaceProperty(prop, context, 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,
    context->LG,
    context->Config,
    context->Backtrace,
  };
  switch (dagChecker.Check()) {
    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
      dagChecker.ReportError(
        context, "$<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 =
    context->HeadTarget ? context->HeadTarget : this;

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

  if (cmLinkInterfaceLibraries const* iface =
        this->GetLinkInterfaceLibraries(context->Config, headTarget, usage)) {
    context->HadContextSensitiveCondition =
      context->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.
        cmGeneratorExpressionContext libContext(
          context->LG, context->Config, context->Quiet, headTarget, this,
          context->EvaluateForBuildsystem, context->Backtrace,
          context->Language);
        std::string libResult = cmGeneratorExpression::StripEmptyListElements(
          lib.Target->EvaluateInterfaceProperty(prop, &libContext, &dagChecker,
                                                usage));
        if (!libResult.empty()) {
          if (result.empty()) {
            result = std::move(libResult);
          } else {
            result.reserve(result.size() + 1 + libResult.size());
            result += ";";
            result += libResult;
          }
        }
        context->HadContextSensitiveCondition =
          context->HadContextSensitiveCondition ||
          libContext.HadContextSensitiveCondition;
        context->HadHeadSensitiveCondition =
          context->HadHeadSensitiveCondition ||
          libContext.HadHeadSensitiveCondition;
      }
    }
  }

  return result;
}

cm::optional<cmGeneratorTarget::TransitiveProperty>
cmGeneratorTarget::IsTransitiveProperty(
  cm::string_view prop, cmLocalGenerator const* lg, std::string const& config,
  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.
      lg->GetPolicyStatus(cmPolicies::CMP0189) != 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 =
        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 (!dagChecker || !dagChecker->IsComputingLinkLibraries()) {
    // 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(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;
}
