/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt 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
