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

#include <algorithm>
#include <cassert>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <utility>

#include <cm/memory>

#include "cmsys/RegularExpression.hxx"

#include "cmCMakePresetsErrors.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

#define CHECK_EXPAND(out, field, expanders, version)                          \
  do {                                                                        \
    switch (ExpandMacros(field, expanders, version)) {                        \
      case ExpandMacroResult::Error:                                          \
        return false;                                                         \
      case ExpandMacroResult::Ignore:                                         \
        out.reset();                                                          \
        return true;                                                          \
      case ExpandMacroResult::Defer:                                          \
        CM_FALLTHROUGH;                                                       \
      case ExpandMacroResult::Ok:                                             \
        break;                                                                \
    }                                                                         \
  } while (false)

namespace {
enum class CycleStatus
{
  Unvisited,
  InProgress,
  Verified,
};

using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
using PackagePreset = cmCMakePresetsGraph::PackagePreset;
using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
template <typename T>
using PresetPair = cmCMakePresetsGraph::PresetPair<T>;
using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
using MacroExpanderVector = cmCMakePresetsGraphInternal::MacroExpanderVector;
using BaseMacroExpander = cmCMakePresetsGraphInternal::BaseMacroExpander;
template <typename T>
using PresetMacroExpander =
  cmCMakePresetsGraphInternal::PresetMacroExpander<T>;
template <typename T>
using ImmediateMacroExpander =
  cmCMakePresetsGraphInternal::ImmediateMacroExpander<T>;
using cmCMakePresetsGraphInternal::ExpandMacros;

bool gSkipNewLine = true;

void InheritString(std::string& child, std::string const& parent)
{
  if (child.empty()) {
    child = parent;
  }
}

template <typename T>
void InheritOptionalValue(cm::optional<T>& child,
                          cm::optional<T> const& parent)
{
  if (!child) {
    child = parent;
  }
}

template <typename T>
void InheritVector(std::vector<T>& child, std::vector<T> const& parent)
{
  if (child.empty()) {
    child = parent;
  }
}

template <typename K, typename V>
void InheritMap(std::map<K, V>& child, std::map<K, V> const& parent)
{
  for (auto const& item : parent) {
    child.insert(item);
  }
}

/**
 * Check preset inheritance for cycles (using a DAG check algorithm) while
 * also bubbling up fields through the inheritance hierarchy, then verify
 * that each preset has the required fields, either directly or through
 * inheritance.
 */
template <typename T>
bool VisitPreset(
  T& preset,
  std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
  std::map<std::string, CycleStatus> cycleStatus, cmCMakePresetsGraph& graph)
{
  switch (cycleStatus[preset.Name]) {
    case CycleStatus::InProgress:
      cmCMakePresetsErrors::CYCLIC_PRESET_INHERITANCE(
        preset.Name, preset.kind(), &graph.parseState);
      return false;
    case CycleStatus::Verified:
      return true;
    default:
      break;
  }

  cycleStatus[preset.Name] = CycleStatus::InProgress;

  if (preset.Environment.count("") != 0) {
    cmCMakePresetsErrors::INVALID_PRESET_NAMED(
      preset.Name, preset.kind(), &graph.parseState,
      "Empty environment variable names are not allowed");
    return false;
  }

  bool result = preset.VisitPresetBeforeInherit();
  if (!result) {
    cmCMakePresetsErrors::INVALID_PRESET_NAMED(
      preset.Name, preset.kind(), &graph.parseState, preset.ErrorDetail);
    return false;
  }

  for (auto const& i : preset.Inherits) {
    auto parent = presets.find(i);
    if (parent == presets.end()) {
      cmCMakePresetsErrors::INVALID_PRESET_NAMED(
        preset.Name, preset.kind(), &graph.parseState,
        cmStrCat("Could not find inherited preset \"", i, "\""));
      return false;
    }

    auto& parentPreset = parent->second.Unexpanded;
    if (!preset.OriginFile->ReachableFiles.count(parentPreset.OriginFile)) {
      cmCMakePresetsErrors::INHERITED_PRESET_UNREACHABLE_FROM_FILE(
        preset.Name, preset.kind(), &graph.parseState);
      return false;
    }

    if (!VisitPreset(parentPreset, presets, cycleStatus, graph)) {
      return false;
    }

    result = preset.VisitPresetInherit(parentPreset);
    if (!result) {
      cmCMakePresetsErrors::INVALID_PRESET_NAMED(
        preset.Name, preset.kind(), &graph.parseState, preset.ErrorDetail);
      return false;
    }

    InheritMap(preset.Environment, parentPreset.Environment);

    if (!preset.ConditionEvaluator) {
      preset.ConditionEvaluator = parentPreset.ConditionEvaluator;
    }
  }

  if (preset.ConditionEvaluator && preset.ConditionEvaluator->IsNull()) {
    preset.ConditionEvaluator.reset();
  }

  result = preset.VisitPresetAfterInherit(graph.GetVersion(preset),
                                          &graph.parseState);
  if (!result) {
    cmCMakePresetsErrors::INVALID_PRESET_NAMED(
      preset.Name, preset.kind(), &graph.parseState, preset.ErrorDetail);
    return false;
  }

  cycleStatus[preset.Name] = CycleStatus::Verified;
  return true;
}

template <typename T>
bool ComputePresetInheritance(
  std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
  cmCMakePresetsGraph& graph)
{
  std::map<std::string, CycleStatus> cycleStatus;
  for (auto const& it : presets) {
    cycleStatus[it.first] = CycleStatus::Unvisited;
  }

  for (auto& it : presets) {
    auto& preset = it.second.Unexpanded;
    if (!VisitPreset<T>(preset, presets, cycleStatus, graph)) {
      return false;
    }
  }

  return true;
}

constexpr char const* ValidPrefixes[] = {
  "",
  "env",
  "penv",
  "vendor",
};

bool PrefixesValidMacroNamespace(std::string const& str)
{
  return std::any_of(
    std::begin(ValidPrefixes), std::end(ValidPrefixes),
    [&str](char const* prefix) -> bool { return cmHasPrefix(prefix, str); });
}

bool IsValidMacroNamespace(std::string const& str)
{
  return std::any_of(
    std::begin(ValidPrefixes), std::end(ValidPrefixes),
    [&str](char const* prefix) -> bool { return str == prefix; });
}

ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
                           MacroExpanderVector const& macroExpanders,
                           int version);
template <typename T>
class EnvironmentMacroExpander : public MacroExpander
{
  std::map<std::string, CycleStatus>& EnvCycles;
  cm::optional<T>& Out;
  MacroExpanderVector& MacroExpanders;

public:
  EnvironmentMacroExpander(MacroExpanderVector& macroExpanders,
                           cm::optional<T>& out,
                           std::map<std::string, CycleStatus>& envCycles)
    : EnvCycles(envCycles)
    , Out(out)
    , MacroExpanders(macroExpanders)
  {
  }
  ExpandMacroResult operator()(std::string const& macroNamespace,
                               std::string const& macroName,
                               std::string& macroOut,
                               int version) const override
  {
    if (macroNamespace == "env" && !macroName.empty() && Out) {
      auto v = Out->Environment.find(macroName);
      if (v != Out->Environment.end() && v->second) {
        auto e =
          VisitEnv(*v->second, EnvCycles[macroName], MacroExpanders, version);
        if (e != ExpandMacroResult::Ok) {
          return e;
        }
        macroOut += *v->second;
        return ExpandMacroResult::Ok;
      }
    }

    if (macroNamespace == "env" || macroNamespace == "penv") {
      if (macroName.empty()) {
        return ExpandMacroResult::Error;
      }
      if (cm::optional<std::string> value =
            cmSystemTools::GetEnvVar(macroName)) {
        macroOut += *value;
      }
      return ExpandMacroResult::Ok;
    }

    return ExpandMacroResult::Ignore;
  }
};

bool CheckExpandMacros(ConfigurePreset const& preset,
                       cm::optional<ConfigurePreset>& out,
                       MacroExpanderVector const& macroExpanders,
                       cmCMakePresetsGraph const* graph = nullptr)
{
  int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;

  std::string binaryDir = preset.BinaryDir;
  CHECK_EXPAND(out, binaryDir, macroExpanders, version);

  if (!binaryDir.empty()) {
    if (graph) {
      if (!cmSystemTools::FileIsFullPath(binaryDir)) {
        binaryDir = cmStrCat(graph->SourceDir, '/', binaryDir);
      }
      out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
      cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
    } else {
      // Defer path normalization until the graph is merged, but store the
      // intermediate result.
      out->BinaryDir = binaryDir;
    }
  }

  if (!preset.InstallDir.empty()) {
    std::string installDir = preset.InstallDir;
    CHECK_EXPAND(out, installDir, macroExpanders, version);

    if (graph) {
      if (!cmSystemTools::FileIsFullPath(installDir)) {
        installDir = cmStrCat(graph->SourceDir, '/', installDir);
      }
      out->InstallDir = cmSystemTools::CollapseFullPath(installDir);
      cmSystemTools::ConvertToUnixSlashes(out->InstallDir);
    } else {
      // Defer path normalization until the graph is merged, but store the
      // intermediate result.
      out->InstallDir = installDir;
    }
  }

  if (!preset.ToolchainFile.empty()) {
    std::string toolchain = preset.ToolchainFile;
    CHECK_EXPAND(out, toolchain, macroExpanders, version);
    out->ToolchainFile = toolchain;
  }

  if (!preset.GraphVizFile.empty()) {
    std::string graphVizFile = preset.GraphVizFile;
    CHECK_EXPAND(out, graphVizFile, macroExpanders, version);
    out->GraphVizFile = graphVizFile;
  }

  for (auto& variable : out->CacheVariables) {
    if (variable.second) {
      CHECK_EXPAND(out, variable.second->Value, macroExpanders, version);
    }
  }

  return true;
}

bool CheckExpandMacros(BuildPreset const& preset,
                       cm::optional<BuildPreset>& out,
                       MacroExpanderVector const& macroExpanders,
                       cmCMakePresetsGraph const* graph = nullptr)
{
  int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;

  for (auto& target : out->Targets) {
    CHECK_EXPAND(out, target, macroExpanders, version);
  }

  for (auto& nativeToolOption : out->NativeToolOptions) {
    CHECK_EXPAND(out, nativeToolOption, macroExpanders, version);
  }

  return true;
}

bool CheckExpandMacros(TestPreset const& preset, cm::optional<TestPreset>& out,
                       MacroExpanderVector const& macroExpanders,
                       cmCMakePresetsGraph const* graph = nullptr)
{
  int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;

  for (auto& overwrite : out->OverwriteConfigurationFile) {
    CHECK_EXPAND(out, overwrite, macroExpanders, version);
  }

  if (out->Output) {
    CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders, version);
    CHECK_EXPAND(out, out->Output->OutputJUnitFile, macroExpanders, version);
  }

  if (out->Filter) {
    if (out->Filter->Include) {
      CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders, version);
      CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders, version);

      if (out->Filter->Include->Index) {
        CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile,
                     macroExpanders, version);
      }
    }

    if (out->Filter->Exclude) {
      CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders, version);
      CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders, version);

      if (out->Filter->Exclude->Fixtures) {
        CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders,
                     version);
        CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup,
                     macroExpanders, version);
        CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup,
                     macroExpanders, version);
      }
    }
  }

  if (out->Execution) {
    CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders,
                 version);
  }

  return true;
}

bool CheckExpandMacros(PackagePreset const& preset,
                       cm::optional<PackagePreset>& out,
                       MacroExpanderVector const& macroExpanders,
                       cmCMakePresetsGraph const* graph = nullptr)
{
  int version = graph ? graph->GetVersion(preset) : preset.OriginFile->Version;

  for (auto& variable : out->Variables) {
    CHECK_EXPAND(out, variable.second, macroExpanders, version);
  }

  CHECK_EXPAND(out, out->ConfigFile, macroExpanders, version);
  CHECK_EXPAND(out, out->PackageName, macroExpanders, version);
  CHECK_EXPAND(out, out->PackageVersion, macroExpanders, version);
  CHECK_EXPAND(out, out->PackageDirectory, macroExpanders, version);
  CHECK_EXPAND(out, out->VendorName, macroExpanders, version);

  return true;
}

bool CheckExpandMacros(WorkflowPreset const& /*preset*/,
                       cm::optional<WorkflowPreset>& /*out*/,
                       MacroExpanderVector const& /*macroExpanders*/,
                       cmCMakePresetsGraph const* /*graph*/ = nullptr)
{
  return true;
}

template <typename T>
bool ExpandMacros(cmCMakePresetsGraph* graph, T const& preset,
                  cm::optional<T>& out)
{
  out.emplace(preset);

  std::map<std::string, CycleStatus> envCycles;
  for (auto const& v : out->Environment) {
    envCycles[v.first] = CycleStatus::Unvisited;
  }

  MacroExpanderVector macroExpanders{};

  macroExpanders.push_back(cm::make_unique<BaseMacroExpander>(*graph));
  macroExpanders.push_back(
    cm::make_unique<PresetMacroExpander<T>>(*graph, preset));
  macroExpanders.push_back(cm::make_unique<EnvironmentMacroExpander<T>>(
    macroExpanders, out, envCycles));

  for (auto& v : out->Environment) {
    if (v.second) {
      switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders,
                       graph->GetVersion(preset))) {
        case ExpandMacroResult::Error:
          cmCMakePresetsErrors::INVALID_PRESET_NAMED(
            preset.Name, preset.kind(), &graph->parseState,
            "Invalid macro expansion");
          return false;
        case ExpandMacroResult::Ignore:
          out.reset();
          return true;
        case ExpandMacroResult::Defer:
          CM_FALLTHROUGH;
        case ExpandMacroResult::Ok:
          break;
      }
    }
  }

  if (preset.ConditionEvaluator) {
    cm::optional<bool> result;
    if (!preset.ConditionEvaluator->Evaluate(
          macroExpanders, graph->GetVersion(preset), result)) {
      cmCMakePresetsErrors::INVALID_PRESET_NAMED(
        preset.Name, preset.kind(), &graph->parseState, "Invalid condition");
      return false;
    }
    if (!result) {
      out.reset();
      return true;
    }
    out->ConditionResult = *result;
  }

  return CheckExpandMacros(preset, out, macroExpanders, graph);
}

ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
                           MacroExpanderVector const& macroExpanders,
                           int version)
{
  if (status == CycleStatus::Verified) {
    return ExpandMacroResult::Ok;
  }
  if (status == CycleStatus::InProgress) {
    return ExpandMacroResult::Error;
  }

  status = CycleStatus::InProgress;
  auto e = ExpandMacros(value, macroExpanders, version);
  if (e != ExpandMacroResult::Ok) {
    return e;
  }
  status = CycleStatus::Verified;
  return ExpandMacroResult::Ok;
}

void PrintPresets(
  std::vector<cmCMakePresetsGraph::Preset const*> const& presets)
{
  if (presets.empty()) {
    return;
  }

  auto presetWithLongestName =
    std::max_element(presets.begin(), presets.end(),
                     [](cmCMakePresetsGraph::Preset const* a,
                        cmCMakePresetsGraph::Preset const* b) {
                       return a->Name.length() < b->Name.length();
                     });
  auto longestLength = (*presetWithLongestName)->Name.length();

  for (auto const* preset : presets) {
    std::string name = cmStrCat("  \"", preset->Name, '"');
    if (!preset->DisplayName.empty()) {
      int const width = static_cast<int>(longestLength + name.length() -
                                         preset->Name.length());
      std::cout << std::left << std::setw(width) << name << " - "
                << preset->DisplayName << '\n';
    } else {
      std::cout << name << '\n';
    }
  }
}

struct AlwaysTrue
{
  template <typename T>
  constexpr bool operator()(T const&) const noexcept
  {
    return true;
  }
};

template <typename PresetType, typename Filter = AlwaysTrue>
void PrintPresetList(
  cmCMakePresetsGraph const* const graph,
  std::map<std::string, cmCMakePresetsGraph::PresetPair<PresetType>>
    cmCMakePresetsGraph::*data,
  std::vector<std::string> cmCMakePresetsGraph::*index, Filter filter = {})
{
  std::vector<cmCMakePresetsGraph::Preset const*> presets;
  presets.reserve((graph->*index).size());
  for (auto const& p : graph->*index) {
    auto const& preset = (graph->*data).at(p);
    if (!preset.Unexpanded.Hidden && preset.Expanded &&
        preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
      presets.push_back(
        static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
    }
  }

  if (!presets.empty()) {
    std::cout << (gSkipNewLine ? "" : "\n") << "Available "
              << PresetType::kind() << " presets:\n\n";
    gSkipNewLine = false;
    PrintPresets(presets);
  }
}
}

template <typename T>
bool cmCMakePresetsGraphInternal::ExpandImmediateMacros(T& preset)
{
  MacroExpanderVector macroExpanders{};
  macroExpanders.push_back(cm::make_unique<ImmediateMacroExpander<T>>(preset));
  cm::optional<T> out = preset;
  bool result = CheckExpandMacros(preset, out, macroExpanders);
  if (out.has_value()) {
    preset = out.value();
  };
  return result;
}

template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<
  ConfigurePreset>(ConfigurePreset&);
template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<BuildPreset>(
  BuildPreset&);
template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<TestPreset>(
  TestPreset&);
template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<
  PackagePreset>(PackagePreset&);
template bool cmCMakePresetsGraphInternal::ExpandImmediateMacros<
  WorkflowPreset>(WorkflowPreset&);

ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacros(
  std::string& out, MacroExpanderVector const& macroExpanders, int version)
{
  std::string result;
  std::string macroNamespace;
  std::string macroName;

  enum class State
  {
    Default,
    MacroNamespace,
    MacroName,
  } state = State::Default;

  for (auto c : out) {
    switch (state) {
      case State::Default:
        if (c == '$') {
          state = State::MacroNamespace;
        } else {
          result += c;
        }
        break;

      case State::MacroNamespace:
        if (c == '{') {
          if (IsValidMacroNamespace(macroNamespace)) {
            state = State::MacroName;
          } else {
            result += '$';
            result += macroNamespace;
            result += '{';
            macroNamespace.clear();
            state = State::Default;
          }
        } else {
          macroNamespace += c;
          if (!PrefixesValidMacroNamespace(macroNamespace)) {
            result += '$';
            result += macroNamespace;
            macroNamespace.clear();
            state = State::Default;
          }
        }
        break;

      case State::MacroName:
        if (c == '}') {
          auto e = ExpandMacro(result, macroNamespace, macroName,
                               macroExpanders, version);
          if (e != ExpandMacroResult::Ok) {
            return e;
          }
          macroNamespace.clear();
          macroName.clear();
          state = State::Default;
        } else {
          macroName += c;
        }
        break;
    }
  }

  switch (state) {
    case State::Default:
      break;
    case State::MacroNamespace:
      result += '$';
      result += macroNamespace;
      break;
    case State::MacroName:
      return ExpandMacroResult::Error;
  }

  out = std::move(result);
  return ExpandMacroResult::Ok;
}

ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacro(
  std::string& out, std::string const& macroNamespace,
  std::string const& macroName, MacroExpanderVector const& macroExpanders,
  int version)
{
  for (auto const& macroExpander : macroExpanders) {
    auto result = (*macroExpander)(macroNamespace, macroName, out, version);
    if (result != ExpandMacroResult::Ignore) {
      return result;
    }
  }

  if (macroNamespace == "vendor") {
    return ExpandMacroResult::Ignore;
  }

  return ExpandMacroResult::Error;
}

namespace {
template <typename T>
bool SetupWorkflowConfigurePreset(T const& preset,
                                  ConfigurePreset const*& configurePreset,
                                  cmJSONState* state)
{
  if (preset.ConfigurePreset != configurePreset->Name) {
    cmCMakePresetsErrors::INVALID_WORKFLOW_STEPS(configurePreset->Name, state);
    return false;
  }
  return true;
}

template <>
bool SetupWorkflowConfigurePreset<ConfigurePreset>(
  ConfigurePreset const& preset, ConfigurePreset const*& configurePreset,
  cmJSONState*)
{
  configurePreset = &preset;
  return true;
}

template <typename T>
bool TryReachPresetFromWorkflow(
  WorkflowPreset const& origin,
  std::map<std::string, PresetPair<T>> const& presets, std::string const& name,
  ConfigurePreset const*& configurePreset, cmJSONState* state)
{
  auto it = presets.find(name);
  if (it == presets.end()) {
    cmCMakePresetsErrors::INVALID_WORKFLOW_STEPS(name, state);
    return false;
  }
  if (!origin.OriginFile->ReachableFiles.count(
        it->second.Unexpanded.OriginFile)) {
    cmCMakePresetsErrors::WORKFLOW_STEP_UNREACHABLE_FROM_FILE(name, state);
    return false;
  }
  return SetupWorkflowConfigurePreset<T>(it->second.Unexpanded,
                                         configurePreset, state);
}
}

ExpandMacroResult BaseMacroExpander::operator()(
  std::string const& macroNamespace, std::string const& macroName,
  std::string& macroOut, int version) const
{
  if (macroNamespace.empty()) {
    if (macroName == "sourceDir") {
      macroOut += Graph.SourceDir;
      return ExpandMacroResult::Ok;
    }
    if (macroName == "sourceParentDir") {
      macroOut += cmSystemTools::GetParentDirectory(Graph.SourceDir);
      return ExpandMacroResult::Ok;
    }
    if (macroName == "sourceDirName") {
      macroOut += cmSystemTools::GetFilenameName(Graph.SourceDir);
      return ExpandMacroResult::Ok;
    }
    if (macroName == "dollar") {
      macroOut += '$';
      return ExpandMacroResult::Ok;
    }
    if (macroName == "hostSystemName") {
      if (version < 3) {
        return ExpandMacroResult::Error;
      }
      macroOut += cmSystemTools::GetSystemName();
      return ExpandMacroResult::Ok;
    }
    // Enable fileDir macro expansion for non-preset expanders
    if (macroName == "fileDir" && File) {
      if (version < 4) {
        return ExpandMacroResult::Error;
      }
      macroOut += cmSystemTools::GetParentDirectory(File.value());
      return ExpandMacroResult::Ok;
    }
    if (macroName == "pathListSep") {
      if (version < 5) {
        return ExpandMacroResult::Error;
      }
      macroOut += cmSystemTools::GetSystemPathlistSeparator();
      return ExpandMacroResult::Ok;
    }
  }

  return ExpandMacroResult::Ignore;
}

bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate(
  MacroExpanderVector const& expanders, int version,
  cm::optional<bool>& out) const
{
  std::string lhs = this->Lhs;
  CHECK_EXPAND(out, lhs, expanders, version);

  std::string rhs = this->Rhs;
  CHECK_EXPAND(out, rhs, expanders, version);

  out = (lhs == rhs);
  return true;
}

bool cmCMakePresetsGraphInternal::InListCondition::Evaluate(
  MacroExpanderVector const& expanders, int version,
  cm::optional<bool>& out) const
{
  std::string str = this->String;
  CHECK_EXPAND(out, str, expanders, version);

  for (auto item : this->List) {
    CHECK_EXPAND(out, item, expanders, version);
    if (str == item) {
      out = true;
      return true;
    }
  }

  out = false;
  return true;
}

bool cmCMakePresetsGraphInternal::MatchesCondition::Evaluate(
  MacroExpanderVector const& expanders, int version,
  cm::optional<bool>& out) const
{
  std::string str = this->String;
  CHECK_EXPAND(out, str, expanders, version);
  std::string regexStr = this->Regex;
  CHECK_EXPAND(out, regexStr, expanders, version);

  cmsys::RegularExpression regex;
  if (!regex.compile(regexStr)) {
    return false;
  }

  out = regex.find(str);
  return true;
}

bool cmCMakePresetsGraphInternal::AnyAllOfCondition::Evaluate(
  MacroExpanderVector const& expanders, int version,
  cm::optional<bool>& out) const
{
  for (auto const& condition : this->Conditions) {
    cm::optional<bool> result;
    if (!condition->Evaluate(expanders, version, result)) {
      out.reset();
      return false;
    }

    if (!result) {
      out.reset();
      return true;
    }

    if (result == this->StopValue) {
      out = result;
      return true;
    }
  }

  out = !this->StopValue;
  return true;
}

bool cmCMakePresetsGraphInternal::NotCondition::Evaluate(
  MacroExpanderVector const& expanders, int version,
  cm::optional<bool>& out) const
{
  out.reset();
  if (!this->SubCondition->Evaluate(expanders, version, out)) {
    out.reset();
    return false;
  }
  if (out) {
    *out = !*out;
  }
  return true;
}

bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetInherit(
  cmCMakePresetsGraph::Preset const& parentPreset)
{
  auto& preset = *this;
  ConfigurePreset const& parent =
    static_cast<ConfigurePreset const&>(parentPreset);
  InheritString(preset.Generator, parent.Generator);
  InheritString(preset.Architecture, parent.Architecture);
  InheritString(preset.Toolset, parent.Toolset);
  if (!preset.ArchitectureStrategy) {
    preset.ArchitectureStrategy = parent.ArchitectureStrategy;
  }
  if (!preset.ToolsetStrategy) {
    preset.ToolsetStrategy = parent.ToolsetStrategy;
  }
  InheritString(preset.BinaryDir, parent.BinaryDir);
  InheritString(preset.InstallDir, parent.InstallDir);
  InheritString(preset.ToolchainFile, parent.ToolchainFile);
  InheritString(preset.GraphVizFile, parent.GraphVizFile);
  InheritMap(preset.Warnings, parent.Warnings);
  InheritMap(preset.Errors, parent.Errors);
  InheritOptionalValue(preset.WarnSystemVars, parent.WarnSystemVars);
  InheritMap(preset.CacheVariables, parent.CacheVariables);
  InheritOptionalValue(preset.DebugOutput, parent.DebugOutput);
  InheritOptionalValue(preset.DebugTryCompile, parent.DebugTryCompile);
  InheritOptionalValue(preset.DebugFind, parent.DebugFind);
  InheritOptionalValue(preset.TraceMode, parent.TraceMode);
  InheritOptionalValue(preset.TraceFormat, parent.TraceFormat);
  InheritVector(preset.TraceSource, parent.TraceSource);
  InheritString(preset.TraceRedirect, parent.TraceRedirect);

  return true;
}

bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetBeforeInherit()
{
  auto& preset = *this;
  if (preset.Environment.count("") != 0) {
    this->ErrorDetail =
      "Empty environment variable names are not allowed in configure presets";
    return false;
  }

  return true;
}

bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetAfterInherit(
  int version, cmJSONState* state)
{
  auto& preset = *this;
  if (!preset.Hidden) {
    if (version < 3) {
      if (preset.Generator.empty()) {
        cmCMakePresetsErrors::PRESET_MISSING_FIELD(preset.Name, "generator",
                                                   state);
        return false;
      }
      if (preset.BinaryDir.empty()) {
        cmCMakePresetsErrors::PRESET_MISSING_FIELD(preset.Name, "binaryDir",
                                                   state);
        return false;
      }
    }

    for (auto const& w : preset.Warnings) {
      auto const ei = preset.Errors.find(w.first);
      if (ei != preset.Errors.end()) {
        if (w.second == false && ei->second == true) {
          return false;
        }
      }
    }

    if (preset.CacheVariables.count("") != 0) {
      this->ErrorDetail = "Empty cache variable names are not allowed";
      return false;
    }
  }

  return true;
}

bool cmCMakePresetsGraph::BuildPreset::VisitPresetInherit(
  cmCMakePresetsGraph::Preset const& parentPreset)
{
  auto& preset = *this;
  BuildPreset const& parent = static_cast<BuildPreset const&>(parentPreset);

  InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
  InheritOptionalValue(preset.InheritConfigureEnvironment,
                       parent.InheritConfigureEnvironment);
  InheritOptionalValue(preset.Jobs, parent.Jobs);
  InheritVector(preset.Targets, parent.Targets);
  InheritString(preset.Configuration, parent.Configuration);
  InheritOptionalValue(preset.CleanFirst, parent.CleanFirst);
  InheritOptionalValue(preset.Verbose, parent.Verbose);
  InheritVector(preset.NativeToolOptions, parent.NativeToolOptions);
  if (!preset.ResolvePackageReferences) {
    preset.ResolvePackageReferences = parent.ResolvePackageReferences;
  }

  return true;
}

bool cmCMakePresetsGraph::BuildPreset::VisitPresetAfterInherit(
  int /* version */, cmJSONState* /*stat*/)
{
  if (!this->Hidden && this->ConfigurePreset.empty()) {
    this->ErrorDetail = "Build presets must either be hidden or have an "
                        "associated configure preset";
    return false;
  }
  return true;
}

bool cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
  cmCMakePresetsGraph::Preset const& parentPreset)
{
  auto& preset = *this;
  TestPreset const& parent = static_cast<TestPreset const&>(parentPreset);

  InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
  InheritOptionalValue(preset.InheritConfigureEnvironment,
                       parent.InheritConfigureEnvironment);
  InheritString(preset.Configuration, parent.Configuration);
  InheritVector(preset.OverwriteConfigurationFile,
                parent.OverwriteConfigurationFile);

  if (parent.Output) {
    if (preset.Output) {
      auto& output = preset.Output.value();
      auto const& parentOutput = parent.Output.value();
      InheritOptionalValue(output.ShortProgress, parentOutput.ShortProgress);
      InheritOptionalValue(output.Verbosity, parentOutput.Verbosity);
      InheritOptionalValue(output.Debug, parentOutput.Debug);
      InheritOptionalValue(output.OutputOnFailure,
                           parentOutput.OutputOnFailure);
      InheritOptionalValue(output.Quiet, parentOutput.Quiet);
      InheritString(output.OutputLogFile, parentOutput.OutputLogFile);
      InheritString(output.OutputJUnitFile, parentOutput.OutputJUnitFile);
      InheritOptionalValue(output.LabelSummary, parentOutput.LabelSummary);
      InheritOptionalValue(output.SubprojectSummary,
                           parentOutput.SubprojectSummary);
      InheritOptionalValue(output.MaxPassedTestOutputSize,
                           parentOutput.MaxPassedTestOutputSize);
      InheritOptionalValue(output.MaxFailedTestOutputSize,
                           parentOutput.MaxFailedTestOutputSize);
      InheritOptionalValue(output.TestOutputTruncation,
                           parentOutput.TestOutputTruncation);
      InheritOptionalValue(output.MaxTestNameWidth,
                           parentOutput.MaxTestNameWidth);
    } else {
      preset.Output = parent.Output;
    }
  }

  if (parent.Filter) {
    if (parent.Filter->Include) {
      if (preset.Filter && preset.Filter->Include) {
        auto& include = *preset.Filter->Include;
        auto const& parentInclude = *parent.Filter->Include;
        InheritString(include.Name, parentInclude.Name);
        InheritString(include.Label, parentInclude.Label);
        InheritOptionalValue(include.Index, parentInclude.Index);
      } else {
        if (!preset.Filter) {
          preset.Filter.emplace();
        }
        preset.Filter->Include = parent.Filter->Include;
      }
    }

    if (parent.Filter->Exclude) {
      if (preset.Filter && preset.Filter->Exclude) {
        auto& exclude = *preset.Filter->Exclude;
        auto const& parentExclude = *parent.Filter->Exclude;
        InheritString(exclude.Name, parentExclude.Name);
        InheritString(exclude.Label, parentExclude.Label);
        InheritOptionalValue(exclude.Fixtures, parentExclude.Fixtures);
      } else {
        if (!preset.Filter) {
          preset.Filter.emplace();
        }
        preset.Filter->Exclude = parent.Filter->Exclude;
      }
    }
  }

  if (parent.Execution) {
    if (preset.Execution) {
      auto& execution = *preset.Execution;
      auto const& parentExecution = *parent.Execution;
      InheritOptionalValue(execution.StopOnFailure,
                           parentExecution.StopOnFailure);
      InheritOptionalValue(execution.EnableFailover,
                           parentExecution.EnableFailover);
      InheritOptionalValue(execution.Jobs, parentExecution.Jobs);
      InheritString(execution.ResourceSpecFile,
                    parentExecution.ResourceSpecFile);
      InheritOptionalValue(execution.TestLoad, parentExecution.TestLoad);
      InheritOptionalValue(execution.ShowOnly, parentExecution.ShowOnly);
      InheritOptionalValue(execution.Repeat, parentExecution.Repeat);
      InheritOptionalValue(execution.InteractiveDebugging,
                           parentExecution.InteractiveDebugging);
      InheritOptionalValue(execution.ScheduleRandom,
                           parentExecution.ScheduleRandom);
      InheritOptionalValue(execution.Timeout, parentExecution.Timeout);
      InheritOptionalValue(execution.NoTestsAction,
                           parentExecution.NoTestsAction);
      InheritVector(execution.TestPassthroughArguments,
                    parentExecution.TestPassthroughArguments);
    } else {
      preset.Execution = parent.Execution;
    }
  }

  return true;
}

bool cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(
  int /* version */, cmJSONState* /*state*/)
{
  if (!this->Hidden && this->ConfigurePreset.empty()) {
    this->ErrorDetail = "Test presets must either be hidden or have an "
                        "associated configure preset";
    return false;
  }
  return true;
}

bool cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
  cmCMakePresetsGraph::Preset const& parentPreset)
{
  auto& preset = *this;
  PackagePreset const& parent =
    static_cast<PackagePreset const&>(parentPreset);

  InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
  InheritOptionalValue(preset.InheritConfigureEnvironment,
                       parent.InheritConfigureEnvironment);
  InheritVector(preset.Generators, parent.Generators);
  InheritVector(preset.Configurations, parent.Configurations);
  InheritMap(preset.Variables, parent.Variables);
  InheritOptionalValue(preset.DebugOutput, parent.DebugOutput);
  InheritOptionalValue(preset.VerboseOutput, parent.VerboseOutput);
  InheritString(preset.PackageName, parent.PackageName);
  InheritString(preset.PackageVersion, parent.PackageVersion);
  InheritString(preset.PackageDirectory, parent.PackageDirectory);
  InheritString(preset.VendorName, parent.VendorName);

  return true;
}

bool cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(
  int /* version */, cmJSONState* /*state*/)
{
  if (!this->Hidden && this->ConfigurePreset.empty()) {
    this->ErrorDetail = "Package presets must either be hidden or have an "
                        "associated configure preset";
    return false;
  }
  return true;
}

bool cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit(
  cmCMakePresetsGraph::Preset const& /*parentPreset*/)
{
  return true;
}

bool cmCMakePresetsGraph::WorkflowPreset::VisitPresetAfterInherit(
  int /* version */, cmJSONState* /*state*/)
{
  return true;
}

std::string cmCMakePresetsGraph::GetFilename(std::string const& sourceDir)
{
  return cmStrCat(sourceDir, "/CMakePresets.json");
}

std::string cmCMakePresetsGraph::GetUserFilename(std::string const& sourceDir)
{
  return cmStrCat(sourceDir, "/CMakeUserPresets.json");
}

bool cmCMakePresetsGraph::ReadProjectPresets(std::string const& sourceDir,
                                             std::string const& presetsFile,
                                             ReadOption readFilesOption)
{
  this->SourceDir = cmSystemTools::CollapseFullPath(sourceDir);
  this->ClearPresets();

  if (!this->ReadProjectPresetsInternal(presetsFile, readFilesOption)) {
    this->ClearPresets();
    return false;
  }

  return true;
}

std::string cmCMakePresetsGraph::GetGeneratorForPreset(
  std::string const& presetName) const
{
  auto configurePresetName = presetName;

  auto buildPresetIterator = this->BuildPresets.find(presetName);
  if (buildPresetIterator != this->BuildPresets.end()) {
    configurePresetName =
      buildPresetIterator->second.Unexpanded.ConfigurePreset;
  } else {
    auto testPresetIterator = this->TestPresets.find(presetName);
    if (testPresetIterator != this->TestPresets.end()) {
      configurePresetName =
        testPresetIterator->second.Unexpanded.ConfigurePreset;
    }
  }

  auto configurePresetIterator =
    this->ConfigurePresets.find(configurePresetName);
  if (configurePresetIterator != this->ConfigurePresets.end()) {
    return configurePresetIterator->second.Unexpanded.Generator;
  }

  // This should only happen if the preset is hidden
  // or (for build or test presets) if ConfigurePreset is invalid.
  return {};
}

bool cmCMakePresetsGraph::ReadProjectPresetsInternal(
  std::string const& presetsFile, ReadOption readFilesOption)
{
  bool haveOneFile = false;

  File* file;
  std::string filename;
  std::vector<File*> inProgressFiles;
  if (!presetsFile.empty()) {
    filename = presetsFile;
    if (cmSystemTools::FileExists(filename)) {
      if (!this->ReadJSONFile(filename, RootType::Any, ReadReason::Root,
                              inProgressFiles, file, this->errors)) {
        return false;
      }
      haveOneFile = true;
    }
  } else {
    filename = GetUserFilename(this->SourceDir);
    if (cmSystemTools::FileExists(filename)) {
      if (!this->ReadJSONFile(filename, RootType::User, ReadReason::Root,
                              inProgressFiles, file, this->errors)) {
        return false;
      }
      haveOneFile = true;
    } else {
      filename = GetFilename(this->SourceDir);
      if (cmSystemTools::FileExists(filename)) {
        if (!this->ReadJSONFile(filename, RootType::Project, ReadReason::Root,
                                inProgressFiles, file, this->errors)) {
          return false;
        }
        haveOneFile = true;
      }
    }
  }
  assert(inProgressFiles.empty());

  if (!haveOneFile) {
    if (readFilesOption == ReadOption::AllowNoFiles) {
      return true;
    }
    cmCMakePresetsErrors::FILE_NOT_FOUND(filename, &this->parseState);
    return false;
  }

  bool result = ComputePresetInheritance(this->ConfigurePresets, *this) &&
    ComputePresetInheritance(this->BuildPresets, *this) &&
    ComputePresetInheritance(this->TestPresets, *this) &&
    ComputePresetInheritance(this->PackagePresets, *this) &&
    ComputePresetInheritance(this->WorkflowPresets, *this);
  if (!result) {
    return false;
  }

  for (auto& it : this->ConfigurePresets) {
    if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
                                                    &this->parseState);
      return false;
    }
  }

  for (auto& it : this->BuildPresets) {
    if (!it.second.Unexpanded.Hidden) {
      auto const configurePreset =
        this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
      if (configurePreset == this->ConfigurePresets.end()) {
        cmCMakePresetsErrors::INVALID_CONFIGURE_PRESET(it.first,
                                                       &this->parseState);
        return false;
      }
      if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
            configurePreset->second.Unexpanded.OriginFile)) {
        cmCMakePresetsErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
          it.first, &this->parseState);
        return false;
      }

      if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
        it.second.Unexpanded.Environment.insert(
          configurePreset->second.Unexpanded.Environment.begin(),
          configurePreset->second.Unexpanded.Environment.end());
      }
    }

    if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
                                                    &this->parseState);
      return false;
    }
  }

  for (auto& it : this->TestPresets) {
    if (!it.second.Unexpanded.Hidden) {
      auto const configurePreset =
        this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
      if (configurePreset == this->ConfigurePresets.end()) {
        cmCMakePresetsErrors::INVALID_CONFIGURE_PRESET(it.first,
                                                       &this->parseState);
        return false;
      }
      if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
            configurePreset->second.Unexpanded.OriginFile)) {
        cmCMakePresetsErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
          it.first, &this->parseState);
        return false;
      }

      if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
        it.second.Unexpanded.Environment.insert(
          configurePreset->second.Unexpanded.Environment.begin(),
          configurePreset->second.Unexpanded.Environment.end());
      }
    }

    if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
                                                    &this->parseState);
      return false;
    }
  }

  for (auto& it : this->PackagePresets) {
    if (!it.second.Unexpanded.Hidden) {
      auto const configurePreset =
        this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
      if (configurePreset == this->ConfigurePresets.end()) {
        cmCMakePresetsErrors::INVALID_CONFIGURE_PRESET(it.first,
                                                       &this->parseState);
        return false;
      }
      if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
            configurePreset->second.Unexpanded.OriginFile)) {
        cmCMakePresetsErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
          it.first, &this->parseState);
        return false;
      }

      if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
        it.second.Unexpanded.Environment.insert(
          configurePreset->second.Unexpanded.Environment.begin(),
          configurePreset->second.Unexpanded.Environment.end());
      }
    }

    if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
                                                    &this->parseState);
      return false;
    }
  }

  for (auto& it : this->WorkflowPresets) {
    using Type = WorkflowPreset::WorkflowStep::Type;

    ConfigurePreset const* configurePreset = nullptr;
    for (auto const& step : it.second.Unexpanded.Steps) {
      if (!configurePreset && step.PresetType != Type::Configure) {
        cmCMakePresetsErrors::FIRST_WORKFLOW_STEP_NOT_CONFIGURE(
          step.PresetName, &this->parseState);
        return false;
      }
      if (configurePreset && step.PresetType == Type::Configure) {
        cmCMakePresetsErrors::CONFIGURE_WORKFLOW_STEP_NOT_FIRST(
          step.PresetName, &this->parseState);
        return false;
      }

      switch (step.PresetType) {
        case Type::Configure:
          result = TryReachPresetFromWorkflow(
            it.second.Unexpanded, this->ConfigurePresets, step.PresetName,
            configurePreset, &this->parseState);
          break;
        case Type::Build:
          result = TryReachPresetFromWorkflow(
            it.second.Unexpanded, this->BuildPresets, step.PresetName,
            configurePreset, &this->parseState);
          break;
        case Type::Test:
          result = TryReachPresetFromWorkflow(
            it.second.Unexpanded, this->TestPresets, step.PresetName,
            configurePreset, &this->parseState);
          break;
        case Type::Package:
          result = TryReachPresetFromWorkflow(
            it.second.Unexpanded, this->PackagePresets, step.PresetName,
            configurePreset, &this->parseState);
          break;
      }
      if (!result) {
        return false;
      }
    }

    if (!configurePreset) {
      cmCMakePresetsErrors::NO_WORKFLOW_STEPS(it.first, &this->parseState);
      return false;
    }

    if (!ExpandMacros(this, it.second.Unexpanded, it.second.Expanded)) {
      cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
                                                    &this->parseState);
      return false;
    }
  }

  return true;
}

void cmCMakePresetsGraph::ClearPresets()
{
  this->ConfigurePresets.clear();
  this->BuildPresets.clear();
  this->TestPresets.clear();
  this->PackagePresets.clear();
  this->WorkflowPresets.clear();

  this->ConfigurePresetOrder.clear();
  this->BuildPresetOrder.clear();
  this->TestPresetOrder.clear();
  this->PackagePresetOrder.clear();
  this->WorkflowPresetOrder.clear();

  this->Files.clear();
}

void cmCMakePresetsGraph::PrintConfigurePresetList() const
{
  PrintPresetList<ConfigurePreset>(this,
                                   &cmCMakePresetsGraph::ConfigurePresets,
                                   &cmCMakePresetsGraph::ConfigurePresetOrder);
}

void cmCMakePresetsGraph::PrintConfigurePresetList(
  std::function<bool(ConfigurePreset const&)> const& filter) const
{
  PrintPresetList<ConfigurePreset>(
    this, &cmCMakePresetsGraph::ConfigurePresets,
    &cmCMakePresetsGraph::ConfigurePresetOrder, filter);
}

void cmCMakePresetsGraph::PrintBuildPresetList() const
{
  PrintPresetList<BuildPreset>(this, &cmCMakePresetsGraph::BuildPresets,
                               &cmCMakePresetsGraph::BuildPresetOrder);
}

void cmCMakePresetsGraph::PrintTestPresetList() const
{
  PrintPresetList<TestPreset>(this, &cmCMakePresetsGraph::TestPresets,
                              &cmCMakePresetsGraph::TestPresetOrder);
}

void cmCMakePresetsGraph::PrintPackagePresetList() const
{
  PrintPresetList<PackagePreset>(this, &cmCMakePresetsGraph::PackagePresets,
                                 &cmCMakePresetsGraph::PackagePresetOrder);
}

void cmCMakePresetsGraph::PrintPackagePresetList(
  std::function<bool(PackagePreset const&)> const& filter) const
{
  PrintPresetList<PackagePreset>(this, &cmCMakePresetsGraph::PackagePresets,
                                 &cmCMakePresetsGraph::PackagePresetOrder,
                                 filter);
}

void cmCMakePresetsGraph::PrintWorkflowPresetList() const
{
  PrintPresetList<WorkflowPreset>(this, &cmCMakePresetsGraph::WorkflowPresets,
                                  &cmCMakePresetsGraph::WorkflowPresetOrder);
}

void cmCMakePresetsGraph::PrintAllPresets() const
{
  this->PrintConfigurePresetList();
  this->PrintBuildPresetList();
  this->PrintTestPresetList();
  this->PrintPackagePresetList();
  this->PrintWorkflowPresetList();
}
