/* 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 "cmFileSetMetadata.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 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(cmStrCat('[', 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(cmStrCat('[', 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(cmStrCat('[', 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 =
    [](cm::FileSetMetadata::Visibility visibility) {
      switch (visibility) {
        case cm::FileSetMetadata::Visibility::Private:
          return "Private";
        case cm::FileSetMetadata::Visibility::Public:
          return "Public";
        case cm::FileSetMetadata::Visibility::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->GetFileSetsEntries(cm::FileSetMetadata::CXX_MODULES)));
    targetVariables->AddSubVariables(
      CreateIfAny(variablesManager, "HeaderSets", supportsVariableType,
                  target->GetFileSetsEntries(cm::FileSetMetadata::HEADERS)));
    targetVariables->AddSubVariables(CreateIfAny(
      variablesManager, "InterfaceHeaderSets", supportsVariableType,
      target->GetInterfaceFileSetsEntries(cm::FileSetMetadata::HEADERS)));
    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,
      cmStrCat(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
