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

#include "cmDebuggerVariablesHelper.h"

#include <algorithm>
#include <cstddef>
#include <functional>
#include <iomanip>
#include <iterator>
#include <map>
#include <sstream>

#include "cm_codecvt_Encoding.hxx"

#include "cmDebuggerStackFrame.h"
#include "cmDebuggerVariables.h"
#include "cmFileSet.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmPropertyMap.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTest.h"
#include "cmValue.h"
#include "cmake.h"

namespace cmDebugger {

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::Create(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  cmPolicies::PolicyMap const& policyMap)
{
  static std::map<cmPolicies::PolicyStatus, std::string> policyStatusString = {
    { cmPolicies::PolicyStatus::OLD, "OLD" },
    { cmPolicies::PolicyStatus::WARN, "WARN" },
    { cmPolicies::PolicyStatus::NEW, "NEW" },
  };

  return std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret;
      ret.reserve(cmPolicies::CMPCOUNT);
      for (int i = 0; i < cmPolicies::CMPCOUNT; ++i) {
        if (policyMap.IsDefined(static_cast<cmPolicies::PolicyID>(i))) {
          auto status = policyMap.Get(static_cast<cmPolicies::PolicyID>(i));
          std::ostringstream ss;
          ss << "CMP" << std::setfill('0') << std::setw(4) << i;
          ret.emplace_back(ss.str(), policyStatusString[status]);
        }
      }
      return ret;
    });
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::vector<std::pair<std::string, std::string>> const& list)
{
  if (list.empty()) {
    return {};
  }

  auto listVariables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret;
      ret.reserve(list.size());
      for (auto const& kv : list) {
        ret.emplace_back(kv.first, kv.second);
      }
      return ret;
    });

  listVariables->SetValue(std::to_string(list.size()));
  return listVariables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  cmBTStringRange const& entries)
{
  if (entries.empty()) {
    return {};
  }

  auto sourceEntries = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType);

  for (auto const& entry : entries) {
    auto arrayVariables = std::make_shared<cmDebuggerVariables>(
      variablesManager, entry.Value, supportsVariableType, [=]() {
        cmList items{ entry.Value };
        std::vector<cmDebuggerVariableEntry> ret;
        ret.reserve(items.size());
        int i = 0;
        for (std::string const& item : items) {
          ret.emplace_back(cmStrCat('[', i++, ']'), item);
        }
        return ret;
      });
    arrayVariables->SetEnableSorting(false);
    sourceEntries->AddSubVariables(arrayVariables);
  }

  sourceEntries->SetValue(std::to_string(entries.size()));
  return sourceEntries;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::set<std::string> const& values)
{
  if (values.empty()) {
    return {};
  }

  auto arrayVariables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret;
      ret.reserve(values.size());
      int i = 0;
      for (std::string const& value : values) {
        ret.emplace_back("[" + std::to_string(i++) + "]", value);
      }
      return ret;
    });
  arrayVariables->SetValue(std::to_string(values.size()));
  arrayVariables->SetEnableSorting(false);
  return arrayVariables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::vector<std::string> const& values)
{
  if (values.empty()) {
    return {};
  }

  auto arrayVariables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret;
      ret.reserve(values.size());
      int i = 0;
      for (std::string const& value : values) {
        ret.emplace_back("[" + std::to_string(i++) + "]", value);
      }
      return ret;
    });

  arrayVariables->SetValue(std::to_string(values.size()));
  arrayVariables->SetEnableSorting(false);
  return arrayVariables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::vector<BT<std::string>> const& list)
{
  if (list.empty()) {
    return {};
  }

  auto variables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret;
      ret.reserve(list.size());
      int i = 0;
      for (auto const& item : list) {
        ret.emplace_back("[" + std::to_string(i++) + "]", item.Value);
      }

      return ret;
    });

  variables->SetValue(std::to_string(list.size()));
  variables->SetEnableSorting(false);
  return variables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType, cmFileSet* fileSet)
{
  if (!fileSet) {
    return {};
  }

  static auto visibilityString = [](cmFileSetVisibility visibility) {
    switch (visibility) {
      case cmFileSetVisibility::Private:
        return "Private";
      case cmFileSetVisibility::Public:
        return "Public";
      case cmFileSetVisibility::Interface:
        return "Interface";
      default:
        return "Unknown";
    }
  };

  auto variables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret{
        { "Name", fileSet->GetName() },
        { "Type", fileSet->GetType() },
        { "Visibility", visibilityString(fileSet->GetVisibility()) },
      };

      return ret;
    });

  variables->AddSubVariables(CreateIfAny(variablesManager, "Directories",
                                         supportsVariableType,
                                         fileSet->GetDirectoryEntries()));
  variables->AddSubVariables(CreateIfAny(variablesManager, "Files",
                                         supportsVariableType,
                                         fileSet->GetFileEntries()));
  return variables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::vector<cmFileSet*> const& fileSets)
{
  if (fileSets.empty()) {
    return {};
  }

  auto fileSetsVariables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType);

  for (auto const& fileSet : fileSets) {
    fileSetsVariables->AddSubVariables(CreateIfAny(
      variablesManager, fileSet->GetName(), supportsVariableType, fileSet));
  }

  return fileSetsVariables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::vector<cmTarget*> const& targets)
{
  if (targets.empty()) {
    return {};
  }

  auto targetsVariables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType);

  for (auto const& target : targets) {
    auto targetVariables = std::make_shared<cmDebuggerVariables>(
      variablesManager, target->GetName(), supportsVariableType, [=]() {
        std::vector<cmDebuggerVariableEntry> ret = {
          { "InstallPath", target->GetInstallPath() },
          { "IsAIX", target->IsAIX() },
          { "IsAndroidGuiExecutable", target->IsAndroidGuiExecutable() },
          { "IsAppBundleOnApple", target->IsAppBundleOnApple() },
          { "IsDLLPlatform", target->IsDLLPlatform() },
          { "IsExecutableWithExports", target->IsExecutableWithExports() },
          { "IsFrameworkOnApple", target->IsFrameworkOnApple() },
          { "IsImported", target->IsImported() },
          { "IsImportedGloballyVisible", target->IsImportedGloballyVisible() },
          { "IsPerConfig", target->IsPerConfig() },
          { "Name", target->GetName() },
          { "RuntimeInstallPath", target->GetRuntimeInstallPath() },
          { "Type", cmState::GetTargetTypeName(target->GetType()) },
        };

        return ret;
      });
    targetVariables->SetValue(cmState::GetTargetTypeName(target->GetType()));

    targetVariables->AddSubVariables(Create(variablesManager, "PolicyMap",
                                            supportsVariableType,
                                            target->GetPolicyMap()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "Properties", supportsVariableType,
                  target->GetProperties().GetList()));

    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "IncludeDirectories", supportsVariableType,
                  target->GetIncludeDirectoriesEntries()));
    targetVariables->AddSubVariables(CreateIfAny(variablesManager, "Sources",
                                                 supportsVariableType,
                                                 target->GetSourceEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "CompileDefinitions", supportsVariableType,
                  target->GetCompileDefinitionsEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "CompileFeatures", supportsVariableType,
                  target->GetCompileFeaturesEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "CompileOptions", supportsVariableType,
                  target->GetCompileOptionsEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "CxxModuleSets", supportsVariableType,
                  target->GetCxxModuleSetsEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "HeaderSets", supportsVariableType,
                  target->GetHeaderSetsEntries()));
    targetVariables->AddSubVariables(CreateIfAny(
      variablesManager, "InterfaceHeaderSets", supportsVariableType,
      target->GetInterfaceHeaderSetsEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "LinkDirectories", supportsVariableType,
                  target->GetLinkDirectoriesEntries()));
    targetVariables->AddSubVariables(CreateIfAny(
      variablesManager, "LinkImplementations", supportsVariableType,
      target->GetLinkImplementationEntries()));
    targetVariables->AddSubVariables(CreateIfAny(
      variablesManager, "LinkInterfaceDirects", supportsVariableType,
      target->GetLinkInterfaceDirectEntries()));
    targetVariables->AddSubVariables(CreateIfAny(
      variablesManager, "LinkInterfaceDirectExcludes", supportsVariableType,
      target->GetLinkInterfaceDirectExcludeEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "LinkInterfaces", supportsVariableType,
                  target->GetLinkInterfaceEntries()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "LinkOptions", supportsVariableType,
                  target->GetLinkOptionsEntries()));
    targetVariables->AddSubVariables(CreateIfAny(
      variablesManager, "SystemIncludeDirectories", supportsVariableType,
      target->GetSystemIncludeDirectories()));
    targetVariables->AddSubVariables(CreateIfAny(variablesManager, "Makefile",
                                                 supportsVariableType,
                                                 target->GetMakefile()));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "GlobalGenerator", supportsVariableType,
                  target->GetGlobalGenerator()));

    std::vector<cmFileSet*> allFileSets;
    auto allFileSetNames = target->GetAllFileSetNames();
    allFileSets.reserve(allFileSetNames.size());
    for (auto const& fileSetName : allFileSetNames) {
      allFileSets.emplace_back(target->GetFileSet(fileSetName));
    }
    targetVariables->AddSubVariables(CreateIfAny(
      variablesManager, "AllFileSets", supportsVariableType, allFileSets));

    std::vector<cmFileSet*> allInterfaceFileSets;
    auto allInterfaceFileSetNames = target->GetAllInterfaceFileSets();
    allInterfaceFileSets.reserve(allInterfaceFileSetNames.size());
    for (auto const& interfaceFileSetName : allInterfaceFileSetNames) {
      allInterfaceFileSets.emplace_back(
        target->GetFileSet(interfaceFileSetName));
    }
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "AllInterfaceFileSets",
                  supportsVariableType, allInterfaceFileSets));

    targetVariables->SetIgnoreEmptyStringEntries(true);
    targetsVariables->AddSubVariables(targetVariables);
  }

  targetsVariables->SetValue(std::to_string(targets.size()));
  return targetsVariables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::Create(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::shared_ptr<cmDebuggerStackFrame> const& frame)
{
  auto variables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      return std::vector<cmDebuggerVariableEntry>{ { "CurrentLine",
                                                     frame->GetLine() } };
    });

  auto closureKeys = frame->GetMakefile()->GetStateSnapshot().ClosureKeys();
  auto locals = std::make_shared<cmDebuggerVariables>(
    variablesManager, "Locals", supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret;
      ret.reserve(closureKeys.size());
      for (auto const& key : closureKeys) {
        ret.emplace_back(
          key, frame->GetMakefile()->GetStateSnapshot().GetDefinition(key));
      }
      return ret;
    });
  locals->SetValue(std::to_string(closureKeys.size()));
  variables->AddSubVariables(locals);

  std::function<bool(std::string const&)> isDirectory =
    [](std::string const& key) {
      size_t pos1 = key.rfind("_DIR");
      size_t pos2 = key.rfind("_DIRECTORY");
      return !((pos1 == std::string::npos || pos1 != key.size() - 4) &&
               (pos2 == std::string::npos || pos2 != key.size() - 10));
    };
  auto directorySize =
    std::count_if(closureKeys.begin(), closureKeys.end(), isDirectory);
  auto directories = std::make_shared<cmDebuggerVariables>(
    variablesManager, "Directories", supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret;
      ret.reserve(directorySize);
      for (auto const& key : closureKeys) {
        if (isDirectory(key)) {
          ret.emplace_back(
            key, frame->GetMakefile()->GetStateSnapshot().GetDefinition(key));
        }
      }
      return ret;
    });
  directories->SetValue(std::to_string(directorySize));
  variables->AddSubVariables(directories);

  auto cacheVariables = std::make_shared<cmDebuggerVariables>(
    variablesManager, "CacheVariables", supportsVariableType);
  auto* state = frame->GetMakefile()->GetCMakeInstance()->GetState();
  auto keys = state->GetCacheEntryKeys();
  for (auto const& key : keys) {
    auto entry = std::make_shared<cmDebuggerVariables>(
      variablesManager,
      key + ":" +
        cmState::CacheEntryTypeToString(state->GetCacheEntryType(key)),
      supportsVariableType, [=]() {
        std::vector<cmDebuggerVariableEntry> ret;
        auto properties = state->GetCacheEntryPropertyList(key);
        ret.reserve(properties.size() + 2);
        for (auto const& propertyName : properties) {
          ret.emplace_back(propertyName,
                           state->GetCacheEntryProperty(key, propertyName));
        }

        ret.emplace_back(
          "TYPE",
          cmState::CacheEntryTypeToString(state->GetCacheEntryType(key)));
        ret.emplace_back("VALUE", state->GetCacheEntryValue(key));
        return ret;
      });

    entry->SetValue(state->GetCacheEntryValue(key));
    cacheVariables->AddSubVariables(entry);
  }

  cacheVariables->SetValue(std::to_string(keys.size()));
  variables->AddSubVariables(cacheVariables);

  auto targetVariables =
    CreateIfAny(variablesManager, "Targets", supportsVariableType,
                frame->GetMakefile()->GetOrderedTargets());

  variables->AddSubVariables(targetVariables);
  std::vector<cmTest*> tests;
  frame->GetMakefile()->GetTests(
    frame->GetMakefile()->GetDefaultConfiguration(), tests);
  variables->AddSubVariables(
    CreateIfAny(variablesManager, "Tests", supportsVariableType, tests));

  return variables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType, cmTest* test)
{
  if (!test) {
    return {};
  }

  auto variables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret{
        { "CommandExpandLists", test->GetCommandExpandLists() },
        { "Name", test->GetName() },
        { "OldStyle", test->GetOldStyle() },
      };

      return ret;
    });

  variables->AddSubVariables(CreateIfAny(
    variablesManager, "Command", supportsVariableType, test->GetCommand()));

  variables->AddSubVariables(CreateIfAny(variablesManager, "Properties",
                                         supportsVariableType,
                                         test->GetProperties().GetList()));
  return variables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType,
  std::vector<cmTest*> const& tests)
{
  if (tests.empty()) {
    return {};
  }

  auto variables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType);

  for (auto const& test : tests) {
    variables->AddSubVariables(CreateIfAny(variablesManager, test->GetName(),
                                           supportsVariableType, test));
  }
  variables->SetValue(std::to_string(tests.size()));
  return variables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType, cmMakefile* mf)
{
  if (!mf) {
    return {};
  }

  auto AppleSDKTypeString = [&](cmMakefile::AppleSDK sdk) {
    switch (sdk) {
      case cmMakefile::AppleSDK::MacOS:
        return "MacOS";
      case cmMakefile::AppleSDK::IPhoneOS:
        return "IPhoneOS";
      case cmMakefile::AppleSDK::IPhoneSimulator:
        return "IPhoneSimulator";
      case cmMakefile::AppleSDK::AppleTVOS:
        return "AppleTVOS";
      case cmMakefile::AppleSDK::AppleTVSimulator:
        return "AppleTVSimulator";
      default:
        return "Unknown";
    }
  };

  auto variables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret = {
        { "DefineFlags", mf->GetDefineFlags() },
        { "DirectoryId", mf->GetDirectoryId().String },
        { "IsRootMakefile", mf->IsRootMakefile() },
        { "HomeDirectory", mf->GetHomeDirectory() },
        { "HomeOutputDirectory", mf->GetHomeOutputDirectory() },
        { "CurrentSourceDirectory", mf->GetCurrentSourceDirectory() },
        { "CurrentBinaryDirectory", mf->GetCurrentBinaryDirectory() },
        { "PlatformIs32Bit", mf->PlatformIs32Bit() },
        { "PlatformIs64Bit", mf->PlatformIs64Bit() },
        { "PlatformIsx32", mf->PlatformIsx32() },
        { "AppleSDKType", AppleSDKTypeString(mf->GetAppleSDKType()) },
        { "PlatformIsAppleEmbedded", mf->PlatformIsAppleEmbedded() }
      };

      return ret;
    });

  variables->AddSubVariables(CreateIfAny(
    variablesManager, "ListFiles", supportsVariableType, mf->GetListFiles()));
  variables->AddSubVariables(CreateIfAny(variablesManager, "OutputFiles",
                                         supportsVariableType,
                                         mf->GetOutputFiles()));

  variables->SetIgnoreEmptyStringEntries(true);
  variables->SetValue(mf->GetDirectoryId().String);
  return variables;
}

std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
  std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
  std::string const& name, bool supportsVariableType, cmGlobalGenerator* gen)
{
  if (!gen) {
    return {};
  }

  auto makeFileEncodingString = [](codecvt_Encoding encoding) {
    switch (encoding) {
      case codecvt_Encoding::None:
        return "None";
      case codecvt_Encoding::UTF8:
        return "UTF8";
      case codecvt_Encoding::UTF8_WITH_BOM:
        return "UTF8_WITH_BOM";
      case codecvt_Encoding::ANSI:
        return "ANSI";
      case codecvt_Encoding::ConsoleOutput:
        return "ConsoleOutput";
      default:
        return "Unknown";
    }
  };

  auto variables = std::make_shared<cmDebuggerVariables>(
    variablesManager, name, supportsVariableType, [=]() {
      std::vector<cmDebuggerVariableEntry> ret = {
        { "AllTargetName", gen->GetAllTargetName() },
        { "CleanTargetName", gen->GetCleanTargetName() },
        { "EditCacheCommand", gen->GetEditCacheCommand() },
        { "EditCacheTargetName", gen->GetEditCacheTargetName() },
        { "ExtraGeneratorName", gen->GetExtraGeneratorName() },
        { "ForceUnixPaths", gen->GetForceUnixPaths() },
        { "InstallLocalTargetName", gen->GetInstallLocalTargetName() },
        { "InstallStripTargetName", gen->GetInstallStripTargetName() },
        { "InstallTargetName", gen->GetInstallTargetName() },
        { "IsMultiConfig", gen->IsMultiConfig() },
        { "Name", gen->GetName() },
        { "MakefileEncoding",
          makeFileEncodingString(gen->GetMakefileEncoding()) },
        { "PackageSourceTargetName", gen->GetPackageSourceTargetName() },
        { "PackageTargetName", gen->GetPackageTargetName() },
        { "PreinstallTargetName", gen->GetPreinstallTargetName() },
        { "NeedSymbolicMark", gen->GetNeedSymbolicMark() },
        { "RebuildCacheTargetName", gen->GetRebuildCacheTargetName() },
        { "TestTargetName", gen->GetTestTargetName() },
        { "UseLinkScript", gen->GetUseLinkScript() },
      };

      return ret;
    });

  if (auto const* ic = gen->GetInstallComponents()) {
    variables->AddSubVariables(CreateIfAny(
      variablesManager, "InstallComponents", supportsVariableType, *ic));
  }

  variables->SetIgnoreEmptyStringEntries(true);
  variables->SetValue(gen->GetName());

  return variables;
}

} // namespace cmDebugger
