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

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <cm/string_view>
#include <cmext/algorithm>

#include <cm3p/json/value.h>

#include "cmCryptoHash.h"
#include "cmExportSet.h"
#include "cmFileAPI.h"
#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCxxModuleBmiGenerator.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmInstallGetRuntimeDependenciesGenerator.h"
#include "cmInstallImportedRuntimeArtifactsGenerator.h"
#include "cmInstallRuntimeDependencySet.h"
#include "cmInstallRuntimeDependencySetGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallSubdirectoryGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLinkItem.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmTargetExport.h"
#include "cmTargetTypes.h"
#include "cmValue.h"
#include "cmake.h"

namespace {

using TargetIndexMapType =
  std::unordered_map<cmGeneratorTarget const*, Json::ArrayIndex>;

std::string RelativeIfUnder(std::string const& top, std::string const& in)
{
  return cmSystemTools::RelativeIfUnder(top, in);
}

class JBTIndex
{
public:
  JBTIndex() = default;
  explicit operator bool() const { return this->Index != None; }
  Json::ArrayIndex Index = None;
  static Json::ArrayIndex const None = static_cast<Json::ArrayIndex>(-1);
};

template <typename T>
class JBT
{
public:
  JBT(T v = T(), JBTIndex bt = JBTIndex())
    : Value(std::move(v))
    , Backtrace(bt)
  {
  }
  T Value;
  JBTIndex Backtrace;
  friend bool operator==(JBT<T> const& l, JBT<T> const& r)
  {
    return l.Value == r.Value && l.Backtrace.Index == r.Backtrace.Index;
  }
  static bool ValueEq(JBT<T> const& l, JBT<T> const& r)
  {
    return l.Value == r.Value;
  }
  static bool ValueLess(JBT<T> const& l, JBT<T> const& r)
  {
    return l.Value < r.Value;
  }
};

template <typename T>
class JBTs
{
public:
  JBTs(T v = T(), std::vector<JBTIndex> ids = std::vector<JBTIndex>())
    : Value(std::move(v))
    , Backtraces(std::move(ids))
  {
  }
  T Value;
  std::vector<JBTIndex> Backtraces;
  friend bool operator==(JBTs<T> const& l, JBTs<T> const& r)
  {
    if ((l.Value == r.Value) && (l.Backtraces.size() == r.Backtraces.size())) {
      for (size_t i = 0; i < l.Backtraces.size(); i++) {
        if (l.Backtraces[i].Index != r.Backtraces[i].Index) {
          return false;
        }
      }
    }
    return true;
  }
  static bool ValueEq(JBTs<T> const& l, JBTs<T> const& r)
  {
    return l.Value == r.Value;
  }
  static bool ValueLess(JBTs<T> const& l, JBTs<T> const& r)
  {
    return l.Value < r.Value;
  }
};

class BacktraceData
{
  std::string TopSource;
  std::unordered_map<std::string, Json::ArrayIndex> CommandMap;
  std::unordered_map<std::string, Json::ArrayIndex> FileMap;
  std::unordered_map<cmListFileContext const*, Json::ArrayIndex> NodeMap;
  Json::Value Commands = Json::arrayValue;
  Json::Value Files = Json::arrayValue;
  Json::Value Nodes = Json::arrayValue;

  Json::ArrayIndex AddCommand(std::string const& command)
  {
    auto i = this->CommandMap.find(command);
    if (i == this->CommandMap.end()) {
      auto cmdIndex = static_cast<Json::ArrayIndex>(this->Commands.size());
      i = this->CommandMap.emplace(command, cmdIndex).first;
      this->Commands.append(command);
    }
    return i->second;
  }

  Json::ArrayIndex AddFile(std::string const& file)
  {
    auto i = this->FileMap.find(file);
    if (i == this->FileMap.end()) {
      auto fileIndex = static_cast<Json::ArrayIndex>(this->Files.size());
      i = this->FileMap.emplace(file, fileIndex).first;
      this->Files.append(RelativeIfUnder(this->TopSource, file));
    }
    return i->second;
  }

public:
  BacktraceData(std::string topSource);
  JBTIndex Add(cmListFileBacktrace const& bt);
  Json::Value Dump();
};

BacktraceData::BacktraceData(std::string topSource)
  : TopSource(std::move(topSource))
{
}

JBTIndex BacktraceData::Add(cmListFileBacktrace const& bt)
{
  JBTIndex index;
  if (bt.Empty()) {
    return index;
  }
  cmListFileContext const* top = &bt.Top();
  auto found = this->NodeMap.find(top);
  if (found != this->NodeMap.end()) {
    index.Index = found->second;
    return index;
  }
  Json::Value entry = Json::objectValue;
  entry["file"] = this->AddFile(top->FilePath);
  if (top->Line) {
    entry["line"] = static_cast<int>(top->Line);
  }
  if (!top->Name.empty()) {
    entry["command"] = this->AddCommand(top->Name);
  }
  if (JBTIndex parent = this->Add(bt.Pop())) {
    entry["parent"] = parent.Index;
  }
  index.Index = this->NodeMap[top] = this->Nodes.size();
  this->Nodes.append(std::move(entry)); // NOLINT(*)
  return index;
}

Json::Value BacktraceData::Dump()
{
  Json::Value backtraceGraph;
  this->CommandMap.clear();
  this->FileMap.clear();
  this->NodeMap.clear();
  backtraceGraph["commands"] = std::move(this->Commands);
  backtraceGraph["files"] = std::move(this->Files);
  backtraceGraph["nodes"] = std::move(this->Nodes);
  return backtraceGraph;
}

class Codemodel
{
  cmFileAPI& FileAPI;
  unsigned int VersionMajor;
  unsigned int VersionMinor;

  Json::Value DumpPaths();
  Json::Value DumpConfigurations();
  Json::Value DumpConfiguration(std::string const& config);

public:
  Codemodel(cmFileAPI& fileAPI, unsigned int versionMajor,
            unsigned int versionMinor);
  Json::Value Dump();
};

class CodemodelConfig
{
  cmFileAPI& FileAPI;
  unsigned int VersionMajor;
  unsigned int VersionMinor;
  std::string const& Config;
  std::string TopSource;
  std::string TopBuild;

  struct Directory
  {
    cmStateSnapshot Snapshot;
    cmLocalGenerator const* LocalGenerator = nullptr;
    Json::Value BuildSystemTargetIndexes = Json::arrayValue;
    Json::Value AbstractTargetIndexes = Json::arrayValue;
    Json::ArrayIndex ProjectIndex;
    bool HasInstallRule = false;
  };
  std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
    DirectoryMap;
  std::vector<Directory> Directories;

  struct Project
  {
    cmStateSnapshot Snapshot;
    static Json::ArrayIndex const NoParentIndex =
      static_cast<Json::ArrayIndex>(-1);
    Json::ArrayIndex ParentIndex = NoParentIndex;
    Json::Value ChildIndexes = Json::arrayValue;
    Json::Value DirectoryIndexes = Json::arrayValue;
    Json::Value BuildSystemTargetIndexes = Json::arrayValue;
    Json::Value AbstractTargetIndexes = Json::arrayValue;
  };
  std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
    ProjectMap;
  std::vector<Project> Projects;

  TargetIndexMapType TargetIndexMap;

  struct DumpedTargets
  {
    Json::Value BuildSystemTargets = Json::arrayValue;
    Json::Value AbstractTargets = Json::arrayValue;
  };

  void ProcessDirectories();

  Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
  Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);

  Json::ArrayIndex AddProject(cmStateSnapshot s);

  DumpedTargets DumpTargets();
  Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);

  Json::Value DumpDirectories();
  Json::Value DumpDirectory(Directory& d);
  Json::Value DumpDirectoryObject(Directory& d);

  Json::Value DumpProjects();
  Json::Value DumpProject(Project& p);

  Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);

public:
  CodemodelConfig(cmFileAPI& fileAPI, unsigned int versionMajor,
                  unsigned int versionMinor, std::string const& config);
  Json::Value Dump();
};

std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
{
  cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
  std::string path = RelativeIfUnder(
    topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
  std::string hash = hasher.HashString(path);
  hash.resize(20, '0');
  return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
}

struct CompileData
{
  struct IncludeEntry
  {
    JBT<std::string> Path;
    bool IsSystem = false;
    IncludeEntry(JBT<std::string> path, bool isSystem)
      : Path(std::move(path))
      , IsSystem(isSystem)
    {
    }
    friend bool operator==(IncludeEntry const& l, IncludeEntry const& r)
    {
      return l.Path == r.Path && l.IsSystem == r.IsSystem;
    }
  };

  std::string Language;
  std::string Sysroot;
  JBTs<std::string> LanguageStandard;
  std::vector<JBT<std::string>> Flags;
  std::vector<JBT<std::string>> Defines;
  std::vector<JBT<std::string>> PrecompileHeaders;
  std::vector<IncludeEntry> Includes;
  std::vector<IncludeEntry> Frameworks;

  friend bool operator==(CompileData const& l, CompileData const& r)
  {
    return (l.Language == r.Language && l.Sysroot == r.Sysroot &&
            l.Flags == r.Flags && l.Defines == r.Defines &&
            l.PrecompileHeaders == r.PrecompileHeaders &&
            l.LanguageStandard == r.LanguageStandard &&
            l.Includes == r.Includes && l.Frameworks == r.Frameworks);
  }
};
}

namespace std {

template <>
struct hash<CompileData>
{
  std::size_t operator()(CompileData const& in) const
  {
    using std::hash;
    size_t result =
      hash<std::string>()(in.Language) ^ hash<std::string>()(in.Sysroot);
    for (auto const& i : in.Includes) {
      result = result ^
        (hash<std::string>()(i.Path.Value) ^
         hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
         (i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
    }
    for (auto const& i : in.Frameworks) {
      result = result ^
        (hash<std::string>()(i.Path.Value) ^
         hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
         (i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
    }
    for (auto const& i : in.Flags) {
      result = result ^ hash<std::string>()(i.Value) ^
        hash<Json::ArrayIndex>()(i.Backtrace.Index);
    }
    for (auto const& i : in.Defines) {
      result = result ^ hash<std::string>()(i.Value) ^
        hash<Json::ArrayIndex>()(i.Backtrace.Index);
    }
    for (auto const& i : in.PrecompileHeaders) {
      result = result ^ hash<std::string>()(i.Value) ^
        hash<Json::ArrayIndex>()(i.Backtrace.Index);
    }
    if (!in.LanguageStandard.Value.empty()) {
      result = result ^ hash<std::string>()(in.LanguageStandard.Value);
      for (JBTIndex backtrace : in.LanguageStandard.Backtraces) {
        result = result ^ hash<Json::ArrayIndex>()(backtrace.Index);
      }
    }
    return result;
  }
};

} // namespace std

namespace {
class DirectoryObject
{
  cmLocalGenerator const* LG = nullptr;
  unsigned int VersionMajor;
  unsigned int VersionMinor;
  std::string const& Config;
  TargetIndexMapType& TargetIndexMap;
  std::string TopSource;
  std::string TopBuild;
  BacktraceData Backtraces;

  void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);

  Json::Value DumpPaths();
  Json::Value DumpInstallers();
  Json::Value DumpInstaller(cmInstallGenerator* gen);
  Json::Value DumpInstallerExportTargets(cmExportSet* exp);
  Json::Value DumpInstallerPath(std::string const& top,
                                std::string const& fromPathIn,
                                std::string const& toPath);

public:
  DirectoryObject(cmLocalGenerator const* lg, unsigned int versionMajor,
                  unsigned int versionMinor, std::string const& config,
                  TargetIndexMapType& targetIndexMap);
  Json::Value Dump();
};

class Target
{
  cmGeneratorTarget* GT;
  unsigned int VersionMajor;
  unsigned int VersionMinor;
  std::string const& Config;
  std::string TopSource;
  std::string TopBuild;
  BacktraceData Backtraces;

  std::map<std::string, CompileData> CompileDataMap;

  std::unordered_map<cmSourceFile const*, Json::ArrayIndex> SourceMap;
  Json::Value Sources = Json::arrayValue;

  struct SourceGroup
  {
    std::string Name;
    Json::Value SourceIndexes = Json::arrayValue;
    Json::Value InterfaceSourceIndexes = Json::arrayValue;
  };
  std::unordered_map<cmSourceGroup const*, Json::ArrayIndex> SourceGroupsMap;
  std::vector<SourceGroup> SourceGroups;

  struct CompileGroup
  {
    std::unordered_map<CompileData, Json::ArrayIndex>::iterator Entry;
    Json::Value SourceIndexes = Json::arrayValue;
  };
  std::unordered_map<CompileData, Json::ArrayIndex> CompileGroupMap;
  std::vector<CompileGroup> CompileGroups;

  using FileSetDatabase = std::map<std::string, std::vector<Json::ArrayIndex>>;

  using FileSetBacktraceDatabase =
    std::unordered_map<std::string, std::vector<cmListFileBacktrace>>;

  std::vector<cm::FileSetMetadata::Visibility> FileSetVisibilities;
  FileSetBacktraceDatabase FileSetBacktraces;

  template <typename T>
  JBT<T> ToJBT(BT<T> const& bt)
  {
    return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace));
  }

  template <typename T>
  JBTs<T> ToJBTs(BTs<T> const& bts)
  {
    std::vector<JBTIndex> ids;
    ids.reserve(bts.Backtraces.size());
    for (cmListFileBacktrace const& backtrace : bts.Backtraces) {
      ids.emplace_back(this->Backtraces.Add(backtrace));
    }
    return JBTs<T>(bts.Value, ids);
  }

  void ProcessLanguages();
  void ProcessLanguage(std::string const& lang);

  Json::ArrayIndex AddSourceGroup(cmSourceGroup const* sg);
  CompileData BuildCompileData(cmSourceFile* sf);
  CompileData MergeCompileData(CompileData const& fd);
  Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf,
                                         Json::ArrayIndex si);
  void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
  void AddBacktrace(Json::Value& object, JBTIndex bt);
  Json::Value DumpPaths();
  Json::Value DumpCompileData(CompileData const& cd);
  Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
  Json::Value DumpFramework(CompileData::IncludeEntry const& fw);
  Json::Value DumpPrecompileHeader(JBT<std::string> const& header);
  Json::Value DumpLanguageStandard(JBTs<std::string> const& standard);
  Json::Value DumpDefine(JBT<std::string> const& def);
  std::pair<Json::Value, FileSetDatabase> DumpFileSets();
  Json::Value DumpFileSet(cmGeneratorFileSet const* fs,
                          std::vector<std::string> const& directories);
  Json::Value DumpSources(FileSetDatabase const& fsdb);
  Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
                         Json::ArrayIndex si, FileSetDatabase const& fsdb);
  Json::Value DumpInterfaceSources(FileSetDatabase const& fsdb);
  Json::Value DumpInterfaceSource(std::string path, Json::ArrayIndex si,
                                  FileSetDatabase const& fsdb);
  Json::Value DumpSourceGroups();
  Json::Value DumpSourceGroup(SourceGroup& sg);
  Json::Value DumpCompileGroups();
  Json::Value DumpCompileGroup(CompileGroup& cg);
  Json::Value DumpSysroot(std::string const& path);
  Json::Value DumpInstall();
  Json::Value DumpInstallPrefix();
  Json::Value DumpInstallDestinations();
  Json::Value DumpInstallDestination(cmInstallTargetGenerator* itGen);
  Json::Value DumpArtifacts();
  Json::Value DumpLink();
  Json::Value DumpArchive();
  Json::Value DumpLinkCommandFragments();
  Json::Value DumpCommandFragments(std::vector<JBT<std::string>> const& frags);
  Json::Value DumpCommandFragment(JBT<std::string> const& frag,
                                  std::string const& role = std::string());
  Json::Value DumpDependencies();
  Json::Value DumpDependency(cmTargetDepend const& td);

  Json::Value DumpLinkItem(cmLinkItem const& linkItem);
  Json::Value DumpLinkImplementationLibraries(cmGeneratorTarget::UseTo usage);
  Json::Value DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo usage);
  Json::Value DumpObjectDependencies();
  Json::Value DumpOrderDependencies();

  Json::Value DumpFolder();
  Json::Value DumpLauncher(char const* name, char const* type);
  Json::Value DumpLaunchers();

  Json::Value DumpDebugger();

public:
  Target(cmGeneratorTarget* gt, unsigned int versionMajor,
         unsigned int versionMinor, std::string const& config);
  Json::Value Dump();
};

Codemodel::Codemodel(cmFileAPI& fileAPI, unsigned int versionMajor,
                     unsigned int versionMinor)
  : FileAPI(fileAPI)
  , VersionMajor(versionMajor)
  , VersionMinor(versionMinor)
{
}

Json::Value Codemodel::Dump()
{
  Json::Value codemodel = Json::objectValue;

  codemodel["paths"] = this->DumpPaths();
  codemodel["configurations"] = this->DumpConfigurations();

  return codemodel;
}

Json::Value Codemodel::DumpPaths()
{
  Json::Value paths = Json::objectValue;
  paths["source"] = this->FileAPI.GetCMakeInstance()->GetHomeDirectory();
  paths["build"] = this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory();
  return paths;
}

Json::Value Codemodel::DumpConfigurations()
{
  Json::Value configurations = Json::arrayValue;
  cmGlobalGenerator* gg =
    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
  auto const& makefiles = gg->GetMakefiles();
  if (!makefiles.empty()) {
    std::vector<std::string> const& configs =
      makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
    for (std::string const& config : configs) {
      configurations.append(this->DumpConfiguration(config));
    }
  }
  return configurations;
}

Json::Value Codemodel::DumpConfiguration(std::string const& config)
{
  CodemodelConfig configuration(this->FileAPI, this->VersionMajor,
                                this->VersionMinor, config);
  return configuration.Dump();
}

CodemodelConfig::CodemodelConfig(cmFileAPI& fileAPI, unsigned int versionMajor,
                                 unsigned int versionMinor,
                                 std::string const& config)
  : FileAPI(fileAPI)
  , VersionMajor(versionMajor)
  , VersionMinor(versionMinor)
  , Config(config)
  , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
  , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
{
}

Json::Value CodemodelConfig::Dump()
{
  Json::Value configuration = Json::objectValue;
  configuration["name"] = this->Config;
  this->ProcessDirectories();

  DumpedTargets dumpedTargets = this->DumpTargets();
  configuration["targets"] = dumpedTargets.BuildSystemTargets;
  configuration["abstractTargets"] = dumpedTargets.AbstractTargets;

  configuration["directories"] = this->DumpDirectories();
  configuration["projects"] = this->DumpProjects();

  return configuration;
}

void CodemodelConfig::ProcessDirectories()
{
  cmGlobalGenerator* gg =
    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
  auto const& localGens = gg->GetLocalGenerators();

  // Add directories in forward order to process parents before children.
  this->Directories.reserve(localGens.size());
  for (auto const& lg : localGens) {
    auto directoryIndex =
      static_cast<Json::ArrayIndex>(this->Directories.size());
    this->Directories.emplace_back();
    Directory& d = this->Directories[directoryIndex];
    d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory();
    d.LocalGenerator = lg.get();
    this->DirectoryMap[d.Snapshot] = directoryIndex;

    d.ProjectIndex = this->AddProject(d.Snapshot);
    this->Projects[d.ProjectIndex].DirectoryIndexes.append(directoryIndex);
  }

  // Update directories in reverse order to process children before parents.
  for (auto di = this->Directories.rbegin(); di != this->Directories.rend();
       ++di) {
    Directory& d = *di;

    // Accumulate the presence of install rules on the way up.
    for (auto const& gen :
         d.LocalGenerator->GetMakefile()->GetInstallGenerators()) {
      if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen.get())) {
        d.HasInstallRule = true;
        break;
      }
    }
    if (!d.HasInstallRule) {
      for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
        cmStateSnapshot childDir = child.GetBuildsystemDirectory();
        Json::ArrayIndex const childIndex = this->GetDirectoryIndex(childDir);
        if (this->Directories[childIndex].HasInstallRule) {
          d.HasInstallRule = true;
          break;
        }
      }
    }
  }
}

Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmLocalGenerator const* lg)
{
  return this->GetDirectoryIndex(
    lg->GetStateSnapshot().GetBuildsystemDirectory());
}

Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmStateSnapshot s)
{
  auto i = this->DirectoryMap.find(s);
  assert(i != this->DirectoryMap.end());
  return i->second;
}

Json::ArrayIndex CodemodelConfig::AddProject(cmStateSnapshot s)
{
  cmStateSnapshot ps = s.GetBuildsystemDirectoryParent();
  if (ps.IsValid() && ps.GetProjectName() == s.GetProjectName()) {
    // This directory is part of its parent directory project.
    Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
    return this->Directories[parentDirIndex].ProjectIndex;
  }

  // This directory starts a new project.
  auto projectIndex = static_cast<Json::ArrayIndex>(this->Projects.size());
  this->Projects.emplace_back();
  Project& p = this->Projects[projectIndex];
  p.Snapshot = s;
  this->ProjectMap[s] = projectIndex;
  if (ps.IsValid()) {
    Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
    p.ParentIndex = this->Directories[parentDirIndex].ProjectIndex;
    this->Projects[p.ParentIndex].ChildIndexes.append(projectIndex);
  }
  return projectIndex;
}

CodemodelConfig::DumpedTargets CodemodelConfig::DumpTargets()
{
  DumpedTargets dumpedTargets;

  std::vector<cmGeneratorTarget*> targetList;
  cmGlobalGenerator* gg =
    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
  for (auto const& lg : gg->GetLocalGenerators()) {
    cm::append(targetList, lg->GetGeneratorTargets());
    cm::append(targetList, lg->GetOwnedImportedGeneratorTargets());
  }
  std::sort(targetList.begin(), targetList.end(),
            [](cmGeneratorTarget* l, cmGeneratorTarget* r) {
              return l->GetName() < r->GetName();
            });

  for (cmGeneratorTarget* gt : targetList) {
    if (gt->GetType() == cm::TargetType::GLOBAL_TARGET) {
      continue;
    }

    // Ignore targets starting with `__cmake_` as they are internal.
    if (cmHasLiteralPrefix(gt->GetName(), "__cmake_")) {
      continue;
    }

    Json::Value& targets = gt->IsInBuildSystem()
      ? dumpedTargets.BuildSystemTargets
      : dumpedTargets.AbstractTargets;
    targets.append(this->DumpTarget(gt, targets.size()));
  }

  return dumpedTargets;
}

Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt,
                                        Json::ArrayIndex ti)
{
  Target t(gt, this->VersionMajor, this->VersionMinor, this->Config);
  std::string safeTargetName = gt->GetName();
  std::replace(safeTargetName.begin(), safeTargetName.end(), ':', '_');
  std::string prefix = "target-" + safeTargetName;
  if (!this->Config.empty()) {
    prefix += "-" + this->Config;
  }
  Json::Value target = this->FileAPI.MaybeJsonFile(t.Dump(), prefix);
  target["name"] = gt->GetName();
  target["id"] = TargetId(gt, this->TopBuild);

  // Cross-reference directory containing target.
  Json::ArrayIndex di = this->GetDirectoryIndex(gt->GetLocalGenerator());
  target["directoryIndex"] = di;
  if (gt->IsInBuildSystem()) {
    this->Directories[di].BuildSystemTargetIndexes.append(ti);
  } else {
    this->Directories[di].AbstractTargetIndexes.append(ti);
  }

  // Cross-reference project containing target.
  Json::ArrayIndex pi = this->Directories[di].ProjectIndex;
  target["projectIndex"] = pi;
  if (gt->IsInBuildSystem()) {
    this->Projects[pi].BuildSystemTargetIndexes.append(ti);
  } else {
    this->Projects[pi].AbstractTargetIndexes.append(ti);
  }

  this->TargetIndexMap[gt] = ti;

  return target;
}

Json::Value CodemodelConfig::DumpDirectories()
{
  Json::Value directories = Json::arrayValue;
  for (Directory& d : this->Directories) {
    directories.append(this->DumpDirectory(d));
  }
  return directories;
}

Json::Value CodemodelConfig::DumpDirectory(Directory& d)
{
  Json::Value directory = this->DumpDirectoryObject(d);

  std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource();
  directory["source"] = RelativeIfUnder(this->TopSource, sourceDir);

  std::string buildDir = d.Snapshot.GetDirectory().GetCurrentBinary();
  directory["build"] = RelativeIfUnder(this->TopBuild, buildDir);

  cmStateSnapshot parentDir = d.Snapshot.GetBuildsystemDirectoryParent();
  if (parentDir.IsValid()) {
    directory["parentIndex"] = this->GetDirectoryIndex(parentDir);
  }

  Json::Value childIndexes = Json::arrayValue;
  for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
    childIndexes.append(
      this->GetDirectoryIndex(child.GetBuildsystemDirectory()));
  }
  if (!childIndexes.empty()) {
    directory["childIndexes"] = std::move(childIndexes);
  }

  directory["projectIndex"] = d.ProjectIndex;

  if (!d.BuildSystemTargetIndexes.empty()) {
    directory["targetIndexes"] = std::move(d.BuildSystemTargetIndexes);
  }
  if (!d.AbstractTargetIndexes.empty()) {
    directory["abstractTargetIndexes"] = std::move(d.AbstractTargetIndexes);
  }

  Json::Value minimumCMakeVersion = this->DumpMinimumCMakeVersion(d.Snapshot);
  if (!minimumCMakeVersion.isNull()) {
    directory["minimumCMakeVersion"] = std::move(minimumCMakeVersion);
  }

  if (d.HasInstallRule) {
    directory["hasInstallRule"] = true;
  }

  return directory;
}

Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d)
{
  std::string prefix = "directory";
  std::string sourceDirRel = RelativeIfUnder(
    this->TopSource, d.Snapshot.GetDirectory().GetCurrentSource());
  std::string buildDirRel = RelativeIfUnder(
    this->TopBuild, d.Snapshot.GetDirectory().GetCurrentBinary());
  if (!cmSystemTools::FileIsFullPath(buildDirRel)) {
    prefix = cmStrCat(prefix, '-', buildDirRel);
  } else if (!cmSystemTools::FileIsFullPath(sourceDirRel)) {
    prefix = cmStrCat(prefix, '-', sourceDirRel);
  }
  for (char& c : prefix) {
    if (c == '/' || c == '\\') {
      c = '.';
    }
  }
  if (!this->Config.empty()) {
    prefix += "-" + this->Config;
  }

  DirectoryObject dir(d.LocalGenerator, this->VersionMajor, this->VersionMinor,
                      this->Config, this->TargetIndexMap);
  return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix);
}

Json::Value CodemodelConfig::DumpProjects()
{
  Json::Value projects = Json::arrayValue;
  for (Project& p : this->Projects) {
    projects.append(this->DumpProject(p));
  }
  return projects;
}

Json::Value CodemodelConfig::DumpProject(Project& p)
{
  Json::Value project = Json::objectValue;

  project["name"] = p.Snapshot.GetProjectName();

  if (p.ParentIndex != Project::NoParentIndex) {
    project["parentIndex"] = p.ParentIndex;
  }

  if (!p.ChildIndexes.empty()) {
    project["childIndexes"] = std::move(p.ChildIndexes);
  }

  project["directoryIndexes"] = std::move(p.DirectoryIndexes);

  if (!p.BuildSystemTargetIndexes.empty()) {
    project["targetIndexes"] = std::move(p.BuildSystemTargetIndexes);
  }
  if (!p.AbstractTargetIndexes.empty()) {
    project["abstractTargetIndexes"] = std::move(p.AbstractTargetIndexes);
  }

  return project;
}

Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
{
  Json::Value minimumCMakeVersion;
  if (cmValue def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
    minimumCMakeVersion = Json::objectValue;
    minimumCMakeVersion["string"] = *def;
  }
  return minimumCMakeVersion;
}

DirectoryObject::DirectoryObject(cmLocalGenerator const* lg,
                                 unsigned int versionMajor,
                                 unsigned int versionMinor,
                                 std::string const& config,
                                 TargetIndexMapType& targetIndexMap)
  : LG(lg)
  , VersionMajor(versionMajor)
  , VersionMinor(versionMinor)
  , Config(config)
  , TargetIndexMap(targetIndexMap)
  , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
  , TopBuild(
      lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
  , Backtraces(this->TopSource)
{
}

Json::Value DirectoryObject::Dump()
{
  Json::Value directoryObject = Json::objectValue;
  directoryObject["codemodelVersion"] =
    cmFileAPI::BuildVersion(this->VersionMajor, this->VersionMinor);
  directoryObject["paths"] = this->DumpPaths();
  directoryObject["installers"] = this->DumpInstallers();
  directoryObject["backtraceGraph"] = this->Backtraces.Dump();
  return directoryObject;
}

void DirectoryObject::AddBacktrace(Json::Value& object,
                                   cmListFileBacktrace const& bt)
{
  if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
    object["backtrace"] = backtrace.Index;
  }
}

Json::Value DirectoryObject::DumpPaths()
{
  Json::Value paths = Json::objectValue;

  std::string const& sourceDir = this->LG->GetCurrentSourceDirectory();
  paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);

  std::string const& buildDir = this->LG->GetCurrentBinaryDirectory();
  paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);

  return paths;
}

Json::Value DirectoryObject::DumpInstallers()
{
  Json::Value installers = Json::arrayValue;
  for (auto const& gen : this->LG->GetMakefile()->GetInstallGenerators()) {
    Json::Value installer = this->DumpInstaller(gen.get());
    if (!installer.empty()) {
      installers.append(std::move(installer)); // NOLINT(*)
    }
  }
  return installers;
}

Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
{
  assert(gen);
  Json::Value installer = Json::objectValue;

  // Exclude subdirectory installers and file(GET_RUNTIME_DEPENDENCIES)
  // installers. They are implementation details.
  if (dynamic_cast<cmInstallSubdirectoryGenerator*>(gen) ||
      dynamic_cast<cmInstallGetRuntimeDependenciesGenerator*>(gen)) {
    return installer;
  }

  // Exclude installers not used in this configuration.
  if (!gen->InstallsForConfig(this->Config)) {
    return installer;
  }

  // Add fields specific to each kind of install generator.
  if (auto* installTarget = dynamic_cast<cmInstallTargetGenerator*>(gen)) {
    cmInstallTargetGenerator::Files const& files =
      installTarget->GetFiles(this->Config);
    if (files.From.empty()) {
      return installer;
    }

    installer["type"] = "target";
    installer["destination"] = installTarget->GetDestination(this->Config);
    installer["targetId"] =
      TargetId(installTarget->GetTarget(), this->TopBuild);
    installer["targetIndex"] =
      this->TargetIndexMap[installTarget->GetTarget()];

    std::string fromDir = files.FromDir;
    if (!fromDir.empty()) {
      fromDir.push_back('/');
    }

    std::string toDir = files.ToDir;
    if (!toDir.empty()) {
      toDir.push_back('/');
    }

    Json::Value paths = Json::arrayValue;
    for (size_t i = 0; i < files.From.size(); ++i) {
      std::string const& fromPath = cmStrCat(fromDir, files.From[i]);
      std::string const& toPath = cmStrCat(toDir, files.To[i]);
      paths.append(this->DumpInstallerPath(this->TopBuild, fromPath, toPath));
    }
    installer["paths"] = std::move(paths);

    if (installTarget->GetOptional()) {
      installer["isOptional"] = true;
    }

    if (installTarget->IsImportLibrary()) {
      installer["targetIsImportLibrary"] = true;
    }

    switch (files.NamelinkMode) {
      case cmInstallTargetGenerator::NamelinkModeNone:
        break;
      case cmInstallTargetGenerator::NamelinkModeOnly:
        installer["targetInstallNamelink"] = "only";
        break;
      case cmInstallTargetGenerator::NamelinkModeSkip:
        installer["targetInstallNamelink"] = "skip";
        break;
    }

    // FIXME: Parse FilePermissions to provide structured information.
    // FIXME: Thread EXPORT name through from install() call.
  } else if (auto* installFiles =
               dynamic_cast<cmInstallFilesGenerator*>(gen)) {
    std::vector<std::string> const& files =
      installFiles->GetFiles(this->Config);
    if (files.empty()) {
      return installer;
    }

    installer["type"] = "file";
    installer["destination"] = installFiles->GetDestination(this->Config);
    Json::Value paths = Json::arrayValue;
    std::string const& rename = installFiles->GetRename(this->Config);
    if (!rename.empty() && files.size() == 1) {
      paths.append(this->DumpInstallerPath(this->TopSource, files[0], rename));
    } else {
      for (std::string const& file : installFiles->GetFiles(this->Config)) {
        paths.append(RelativeIfUnder(this->TopSource, file));
      }
    }
    installer["paths"] = std::move(paths);
    if (installFiles->GetOptional()) {
      installer["isOptional"] = true;
    }
    // FIXME: Parse FilePermissions to provide structured information.
  } else if (auto* installDir =
               dynamic_cast<cmInstallDirectoryGenerator*>(gen)) {
    std::vector<std::string> const& dirs =
      installDir->GetDirectories(this->Config);
    if (dirs.empty()) {
      return installer;
    }

    installer["type"] = "directory";
    installer["destination"] = installDir->GetDestination(this->Config);
    Json::Value paths = Json::arrayValue;
    for (std::string const& dir : dirs) {
      if (cmHasSuffix(dir, '/')) {
        paths.append(this->DumpInstallerPath(
          this->TopSource, dir.substr(0, dir.size() - 1), "."));
      } else {
        paths.append(this->DumpInstallerPath(
          this->TopSource, dir, cmSystemTools::GetFilenameName(dir)));
      }
    }
    installer["paths"] = std::move(paths);
    if (installDir->GetOptional()) {
      installer["isOptional"] = true;
    }
    // FIXME: Parse FilePermissions, DirPermissions, and LiteralArguments.
    // to provide structured information.
  } else if (auto* installExport =
               dynamic_cast<cmInstallExportGenerator*>(gen)) {
    installer["type"] = "export";
    installer["destination"] = installExport->GetDestination();
    cmExportSet* exportSet = installExport->GetExportSet();
    installer["exportName"] = exportSet->GetName();
    installer["exportTargets"] = this->DumpInstallerExportTargets(exportSet);
    Json::Value paths = Json::arrayValue;
    paths.append(
      RelativeIfUnder(this->TopBuild, installExport->GetMainImportFile()));
    installer["paths"] = std::move(paths);
  } else if (auto* installScript =
               dynamic_cast<cmInstallScriptGenerator*>(gen)) {
    if (installScript->IsCode()) {
      installer["type"] = "code";
    } else {
      installer["type"] = "script";
      installer["scriptFile"] = RelativeIfUnder(
        this->TopSource, installScript->GetScript(this->Config));
    }
  } else if (auto* installImportedRuntimeArtifacts =
               dynamic_cast<cmInstallImportedRuntimeArtifactsGenerator*>(
                 gen)) {
    installer["type"] = "importedRuntimeArtifacts";
    installer["destination"] =
      installImportedRuntimeArtifacts->GetDestination(this->Config);
    if (installImportedRuntimeArtifacts->GetOptional()) {
      installer["isOptional"] = true;
    }
  } else if (auto* installRuntimeDependencySet =
               dynamic_cast<cmInstallRuntimeDependencySetGenerator*>(gen)) {
    installer["type"] = "runtimeDependencySet";
    installer["destination"] =
      installRuntimeDependencySet->GetDestination(this->Config);
    std::string name(
      installRuntimeDependencySet->GetRuntimeDependencySet()->GetName());
    if (!name.empty()) {
      installer["runtimeDependencySetName"] = name;
    }
    switch (installRuntimeDependencySet->GetDependencyType()) {
      case cmInstallRuntimeDependencySetGenerator::DependencyType::Framework:
        installer["runtimeDependencySetType"] = "framework";
        break;
      case cmInstallRuntimeDependencySetGenerator::DependencyType::Library:
        installer["runtimeDependencySetType"] = "library";
        break;
    }
  } else if (auto* installFileSet =
               dynamic_cast<cmInstallFileSetGenerator*>(gen)) {
    auto const* fileSet = installFileSet->GetFileSet();

    // No fileSet by that name exists for the associated target
    if (!fileSet) {
      return installer;
    }

    installer["type"] = "fileSet";
    installer["destination"] = installFileSet->GetDestination(this->Config);

    auto* target = installFileSet->GetTarget();

    cm::GenEx::Context context(target->LocalGenerator, this->Config);
    auto dirs = fileSet->GetDirectories(context, target);
    auto entries = fileSet->GetFiles(context, target);

    Json::Value files = Json::arrayValue;
    for (auto const& it : entries.first) {
      auto dir = it.first;
      if (!dir.empty()) {
        dir += '/';
      }
      for (auto const& file : it.second) {
        files.append(this->DumpInstallerPath(
          this->TopSource, file,
          cmStrCat(dir, cmSystemTools::GetFilenameNameView(file))));
      }
    }
    installer["paths"] = std::move(files);
    installer["fileSetName"] = fileSet->GetName();
    installer["fileSetType"] = fileSet->GetType();
    installer["fileSetDirectories"] = Json::arrayValue;
    for (auto const& dir : dirs.first) {
      installer["fileSetDirectories"].append(
        RelativeIfUnder(this->TopSource, dir));
    }
    installer["fileSetTarget"] = Json::objectValue;
    installer["fileSetTarget"]["id"] = TargetId(target, this->TopBuild);
    installer["fileSetTarget"]["index"] = this->TargetIndexMap[target];

    if (installFileSet->GetOptional()) {
      installer["isOptional"] = true;
    }
  } else if (auto* cxxModuleBmi =
               dynamic_cast<cmInstallCxxModuleBmiGenerator*>(gen)) {
    installer["type"] = "cxxModuleBmi";
    installer["destination"] = cxxModuleBmi->GetDestination(this->Config);

    auto const* target = cxxModuleBmi->GetTarget();
    installer["cxxModuleBmiTarget"] = Json::objectValue;
    installer["cxxModuleBmiTarget"]["id"] = TargetId(target, this->TopBuild);
    installer["cxxModuleBmiTarget"]["index"] = this->TargetIndexMap[target];

    // FIXME: Parse FilePermissions.
    // FIXME: Parse MessageLevel.
    if (cxxModuleBmi->GetOptional()) {
      installer["isOptional"] = true;
    }
  }

  // Add fields common to all install generators.
  installer["component"] = gen->GetComponent();
  if (gen->GetExcludeFromAll()) {
    installer["isExcludeFromAll"] = true;
  }

  if (gen->GetAllComponentsFlag()) {
    installer["isForAllComponents"] = true;
  }

  this->AddBacktrace(installer, gen->GetBacktrace());

  return installer;
}

Json::Value DirectoryObject::DumpInstallerExportTargets(cmExportSet* exp)
{
  Json::Value targets = Json::arrayValue;
  for (auto const& targetExport : exp->GetTargetExports()) {
    Json::Value target = Json::objectValue;
    target["id"] = TargetId(targetExport->Target, this->TopBuild);
    target["index"] = this->TargetIndexMap[targetExport->Target];
    targets.append(std::move(target)); // NOLINT(*)
  }
  return targets;
}

Json::Value DirectoryObject::DumpInstallerPath(std::string const& top,
                                               std::string const& fromPathIn,
                                               std::string const& toPath)
{
  Json::Value installPath;

  std::string fromPath = RelativeIfUnder(top, fromPathIn);

  // If toPath is the last component of fromPath, use just fromPath.
  if (toPath.find_first_of('/') == std::string::npos &&
      cmHasSuffix(fromPath, toPath) &&
      (fromPath.size() == toPath.size() ||
       fromPath[fromPath.size() - toPath.size() - 1] == '/')) {
    installPath = fromPath;
  } else {
    installPath = Json::objectValue;
    installPath["from"] = fromPath;
    installPath["to"] = toPath;
  }

  return installPath;
}

Target::Target(cmGeneratorTarget* gt, unsigned int versionMajor,
               unsigned int versionMinor, std::string const& config)
  : GT(gt)
  , VersionMajor(versionMajor)
  , VersionMinor(versionMinor)
  , Config(config)
  , TopSource(gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
  , TopBuild(
      gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
  , Backtraces(this->TopSource)
{
}

Json::Value Target::Dump()
{
  Json::Value target = Json::objectValue;

  cm::TargetType const type = this->GT->GetType();

  target["codemodelVersion"] =
    cmFileAPI::BuildVersion(this->VersionMajor, this->VersionMinor);
  target["name"] = this->GT->GetName();
  target["type"] = cmState::GetTargetTypeName(type);
  target["id"] = TargetId(this->GT, this->TopBuild);
  if (this->GT->IsImported()) {
    target["imported"] = true;
    if (!this->GT->IsImportedGloballyVisible()) {
      target["local"] = true;
    }
  }
  if (this->GT->IsSymbolic()) {
    target["symbolic"] = true;
  }
  if (!this->GT->IsInBuildSystem()) {
    target["abstract"] = true;
  }
  target["paths"] = this->DumpPaths();
  if (this->GT->Target->GetIsGeneratorProvided()) {
    target["isGeneratorProvided"] = true;
  }

  this->AddBacktrace(target, this->GT->GetBacktrace());

  if (this->GT->Target->GetHaveInstallRule()) {
    target["install"] = this->DumpInstall();
  }

  if (this->GT->HaveWellDefinedOutputFiles()) {
    Json::Value artifacts = this->DumpArtifacts();
    if (!artifacts.empty()) {
      target["artifacts"] = std::move(artifacts);
    }
  }

  if (type == cm::TargetType::EXECUTABLE ||
      type == cm::TargetType::SHARED_LIBRARY ||
      type == cm::TargetType::MODULE_LIBRARY) {
    target["nameOnDisk"] = this->GT->GetFullName(this->Config);
    if (!this->GT->IsImported()) {
      target["link"] = this->DumpLink();
    }
  } else if (type == cm::TargetType::STATIC_LIBRARY) {
    target["nameOnDisk"] = this->GT->GetFullName(this->Config);
    if (!this->GT->IsImported()) {
      target["archive"] = this->DumpArchive();
    }
  }

  if (type == cm::TargetType::EXECUTABLE) {
    Json::Value launchers = this->DumpLaunchers();
    if (!launchers.empty()) {
      target["launchers"] = std::move(launchers);
    }
  }

  if (!this->GT->IsImported()) {
    Json::Value dependencies = this->DumpDependencies();
    if (!dependencies.empty()) {
      target["dependencies"] = dependencies;
    }
  }

  {
    Json::Value linkLibraries =
      this->DumpLinkImplementationLibraries(cmGeneratorTarget::UseTo::Link);
    if (!linkLibraries.empty()) {
      target["linkLibraries"] = std::move(linkLibraries);
    }
    Json::Value ifaceLinkLibraries =
      this->DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo::Link);
    if (!ifaceLinkLibraries.empty()) {
      target["interfaceLinkLibraries"] = std::move(ifaceLinkLibraries);
    }
    Json::Value compileDependencies =
      this->DumpLinkImplementationLibraries(cmGeneratorTarget::UseTo::Compile);
    if (!compileDependencies.empty()) {
      target["compileDependencies"] = std::move(compileDependencies);
    }
    Json::Value ifaceCompileDependencies =
      this->DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo::Compile);
    if (!ifaceCompileDependencies.empty()) {
      target["interfaceCompileDependencies"] =
        std::move(ifaceCompileDependencies);
    }
    Json::Value objectDependencies = this->DumpObjectDependencies();
    if (!objectDependencies.empty()) {
      target["objectDependencies"] = std::move(objectDependencies);
    }
    Json::Value orderDependencies = this->DumpOrderDependencies();
    if (!orderDependencies.empty()) {
      target["orderDependencies"] = std::move(orderDependencies);
    }

    if (!this->GT->IsImported()) {
      this->ProcessLanguages();
    }

    auto fileSetInfo = this->DumpFileSets();

    if (!fileSetInfo.first.isNull()) {
      target["fileSets"] = fileSetInfo.first;
    }

    // Even though some types of targets can't have sources, we have to always
    // output a sources array to preserve backward compatibility
    target["sources"] = this->DumpSources(fileSetInfo.second);

    auto interfaceSources = this->DumpInterfaceSources(fileSetInfo.second);
    if (!interfaceSources.empty()) {
      target["interfaceSources"] = std::move(interfaceSources);
    }

    Json::Value folder = this->DumpFolder();
    if (!folder.isNull()) {
      target["folder"] = std::move(folder);
    }

    if (!this->GT->IsImported()) {
      Json::Value sourceGroups = this->DumpSourceGroups();
      if (!sourceGroups.empty()) {
        target["sourceGroups"] = std::move(sourceGroups);
      }

      Json::Value compileGroups = this->DumpCompileGroups();
      if (!compileGroups.empty()) {
        target["compileGroups"] = std::move(compileGroups);
      }
    }
  }

  target["backtraceGraph"] = this->Backtraces.Dump();

  if (!this->GT->IsImported()) {
    Json::Value debugger = this->DumpDebugger();
    if (!debugger.isNull()) {
      target["debugger"] = std::move(debugger);
    }
  }

  return target;
}

void Target::ProcessLanguages()
{
  std::set<std::string> languages;
  this->GT->GetLanguages(languages, this->Config);
  for (std::string const& lang : languages) {
    this->ProcessLanguage(lang);
  }
}

void Target::ProcessLanguage(std::string const& lang)
{
  CompileData& cd = this->CompileDataMap[lang];
  cd.Language = lang;
  if (cmValue sysrootCompile =
        this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
    cd.Sysroot = *sysrootCompile;
  } else if (cmValue sysroot =
               this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
    cd.Sysroot = *sysroot;
  }
  cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  {
    // FIXME: Add flags from end section of ExpandRuleVariable,
    // which may need to be factored out.
    std::vector<BT<std::string>> flags =
      lg->GetTargetCompileFlags(this->GT, this->Config, lang);

    cd.Flags.reserve(flags.size());
    for (const BT<std::string>& f : flags) {
      cd.Flags.emplace_back(this->ToJBT(f));
    }
  }
  std::set<BT<std::string>> defines =
    lg->GetTargetDefines(this->GT, this->Config, lang);
  cd.Defines.reserve(defines.size());
  for (BT<std::string> const& d : defines) {
    cd.Defines.emplace_back(this->ToJBT(d));
  }
  std::vector<BT<std::string>> includePathList =
    lg->GetIncludeDirectories(this->GT, lang, this->Config);
  for (BT<std::string> const& i : includePathList) {
    if (this->GT->IsApple() && cmSystemTools::IsPathToFramework(i.Value)) {
      cd.Frameworks.emplace_back(
        this->ToJBT(i),
        this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
    } else {
      cd.Includes.emplace_back(
        this->ToJBT(i),
        this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
    }
  }
  std::vector<BT<std::string>> precompileHeaders =
    this->GT->GetPrecompileHeaders(this->Config, lang);
  for (BT<std::string> const& pch : precompileHeaders) {
    cd.PrecompileHeaders.emplace_back(this->ToJBT(pch));
  }
  BTs<std::string> const* languageStandard =
    this->GT->GetLanguageStandardProperty(lang, this->Config);
  if (languageStandard) {
    cd.LanguageStandard = this->ToJBTs(*languageStandard);
  }
}

Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup const* sg)
{
  auto i = this->SourceGroupsMap.find(sg);
  if (i == this->SourceGroupsMap.end()) {
    auto sgIndex = static_cast<Json::ArrayIndex>(this->SourceGroups.size());
    i = this->SourceGroupsMap.emplace(sg, sgIndex).first;
    SourceGroup g;
    g.Name = sg->GetFullName();
    this->SourceGroups.push_back(std::move(g));
  }
  return i->second;
}

CompileData Target::BuildCompileData(cmSourceFile* sf)
{
  CompileData fd;

  fd.Language = sf->GetOrDetermineLanguage();
  if (fd.Language.empty()) {
    return fd;
  }

  cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT,
                                                    fd.Language);

  cmGeneratorFileSet const* fileSet =
    GT->GetFileSetForSource(this->Config, sf);

  std::string const COMPILE_FLAGS("COMPILE_FLAGS");
  if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) {
    std::string flags = genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS);
    fd.Flags.emplace_back(std::move(flags), JBTIndex());
  }
  std::string const COMPILE_OPTIONS("COMPILE_OPTIONS");
  for (BT<std::string> tmpOpt : sf->GetCompileOptions()) {
    tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS);
    // After generator evaluation we need to use the AppendCompileOptions
    // method so we handle situations where backtrace entries have lists
    // and properly escape flags.
    std::string tmp;
    lg->AppendCompileOptions(tmp, tmpOpt.Value);
    BT<std::string> opt(tmp, tmpOpt.Backtrace);
    fd.Flags.emplace_back(this->ToJBT(opt));
  }
  // File set compile options, if any
  if (fileSet) {
    for (BT<std::string> const& tmpOpt : fileSet->BelongsTo(this->GT)
           ? fileSet->GetCompileOptions(this->Config, fd.Language)
           : fileSet->GetInterfaceCompileOptions(this->Config, fd.Language)) {
      // We need to use the AppendCompileOptions method so we handle situations
      // where backtrace entries have list and properly escape flags.
      std::string tmp;
      lg->AppendCompileOptions(tmp, tmpOpt.Value);
      BT<std::string> opt(tmp, tmpOpt.Backtrace);
      fd.Flags.emplace_back(this->ToJBT(opt));
    }
  }

  // Add precompile headers compile options.
  std::vector<std::string> pchArchs =
    this->GT->GetPchArchs(this->Config, fd.Language);

  std::unordered_map<std::string, std::string> pchSources;
  for (std::string const& arch : pchArchs) {
    std::string const pchSource =
      this->GT->GetPchSource(this->Config, fd.Language, arch);
    if (!pchSource.empty()) {
      pchSources.insert(std::make_pair(pchSource, arch));
    }
  }

  if (!pchSources.empty() &&
      !((fileSet && fileSet->GetProperty("SKIP_PRECOMPILE_HEADERS")) ||
        sf->GetProperty("SKIP_PRECOMPILE_HEADERS"))) {
    std::string pchOptions;
    auto pchIt = pchSources.find(sf->ResolveFullPath());
    if (pchIt != pchSources.end()) {
      pchOptions = this->GT->GetPchCreateCompileOptions(
        this->Config, fd.Language, pchIt->second);
    } else {
      pchOptions =
        this->GT->GetPchUseCompileOptions(this->Config, fd.Language);
    }

    BT<std::string> tmpOpt(pchOptions);
    tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS);

    // After generator evaluation we need to use the AppendCompileOptions
    // method so we handle situations where backtrace entries have lists
    // and properly escape flags.
    std::string tmp;
    lg->AppendCompileOptions(tmp, tmpOpt.Value);
    BT<std::string> opt(tmp, tmpOpt.Backtrace);
    fd.Flags.emplace_back(this->ToJBT(opt));
  }

  std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
  // Add include directories from file set properties.
  if (fileSet) {
    for (BT<std::string> const& tmpInclude : fileSet->BelongsTo(this->GT)
           ? fileSet->GetIncludeDirectories(this->Config, fd.Language)
           : fileSet->GetInterfaceIncludeDirectories(this->Config,
                                                     fd.Language)) {
      // We need to use the AppendIncludeDirectories method so we handle
      // situations where backtrace entries have lists.
      std::vector<std::string> tmp;
      lg->AppendIncludeDirectories(tmp, tmpInclude.Value, *sf);
      for (std::string& i : tmp) {
        bool const isSystemInclude =
          this->GT->IsSystemIncludeDirectory(i, this->Config, fd.Language);
        BT<std::string> include(i, tmpInclude.Backtrace);
        if (this->GT->IsApple() && cmSystemTools::IsPathToFramework(i)) {
          fd.Frameworks.emplace_back(this->ToJBT(include), isSystemInclude);
        } else {
          fd.Includes.emplace_back(this->ToJBT(include), isSystemInclude);
        }
      }
    }
  }
  // Add include directories from source file properties.
  {
    for (BT<std::string> tmpInclude : sf->GetIncludeDirectories()) {
      tmpInclude.Value =
        genexInterpreter.Evaluate(tmpInclude.Value, INCLUDE_DIRECTORIES);

      // After generator evaluation we need to use the AppendIncludeDirectories
      // method so we handle situations where backtrace entries have lists.
      std::vector<std::string> tmp;
      lg->AppendIncludeDirectories(tmp, tmpInclude.Value, *sf);
      for (std::string& i : tmp) {
        bool const isSystemInclude =
          this->GT->IsSystemIncludeDirectory(i, this->Config, fd.Language);
        BT<std::string> include(i, tmpInclude.Backtrace);
        if (this->GT->IsApple() && cmSystemTools::IsPathToFramework(i)) {
          fd.Frameworks.emplace_back(this->ToJBT(include), isSystemInclude);
        } else {
          fd.Includes.emplace_back(this->ToJBT(include), isSystemInclude);
        }
      }
    }
  }

  std::string const COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
  std::set<BT<std::string>> fileDefines;
  for (BT<std::string> tmpDef : sf->GetCompileDefinitions()) {
    tmpDef.Value =
      genexInterpreter.Evaluate(tmpDef.Value, COMPILE_DEFINITIONS);

    // After generator evaluation we need to use the AppendDefines method
    // so we handle situations where backtrace entries have lists.
    std::set<std::string> tmp;
    lg->AppendDefines(tmp, tmpDef.Value);
    for (std::string const& i : tmp) {
      BT<std::string> def(i, tmpDef.Backtrace);
      fileDefines.insert(def);
    }
  }

  std::set<std::string> configFileDefines;
  std::string const defPropName =
    "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config);
  if (cmValue config_defs = sf->GetProperty(defPropName)) {
    lg->AppendDefines(
      configFileDefines,
      genexInterpreter.Evaluate(*config_defs, COMPILE_DEFINITIONS));
  }

  std::set<BT<std::string>> fileSetDefines;
  if (fileSet) {
    for (BT<std::string> const& tmpDef : fileSet->BelongsTo(this->GT)
           ? fileSet->GetCompileDefinitions(this->Config, fd.Language)
           : fileSet->GetInterfaceCompileDefinitions(this->Config,
                                                     fd.Language)) {
      // We need to use the AppendDefines method so we handle situations where
      // backtrace entries have lists.
      std::set<std::string> tmp;
      lg->AppendDefines(tmp, tmpDef.Value);
      for (std::string const& i : tmp) {
        BT<std::string> def(i, tmpDef.Backtrace);
        fileSetDefines.insert(def);
      }
    }
  }

  fd.Defines.reserve(fileDefines.size() + configFileDefines.size() +
                     fileSetDefines.size());

  for (BT<std::string> const& def : fileDefines) {
    fd.Defines.emplace_back(this->ToJBT(def));
  }

  for (std::string const& d : configFileDefines) {
    fd.Defines.emplace_back(d, JBTIndex());
  }

  for (BT<std::string> const& def : fileSetDefines) {
    fd.Defines.emplace_back(this->ToJBT(def));
  }

  return fd;
}

CompileData Target::MergeCompileData(CompileData const& fd)
{
  CompileData cd;
  cd.Language = fd.Language;
  if (cd.Language.empty()) {
    return cd;
  }
  CompileData const& td = this->CompileDataMap.at(cd.Language);

  // All compile groups share the sysroot of the target.
  cd.Sysroot = td.Sysroot;

  // All compile groups share the precompile headers of the target.
  cd.PrecompileHeaders = td.PrecompileHeaders;

  // All compile groups share the language standard of the target.
  cd.LanguageStandard = td.LanguageStandard;

  // Use target-wide flags followed by source-specific flags.
  cd.Flags.reserve(td.Flags.size() + fd.Flags.size());
  cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end());
  cd.Flags.insert(cd.Flags.end(), fd.Flags.begin(), fd.Flags.end());

  // Use source-specific includes followed by target-wide includes.
  cd.Includes.reserve(fd.Includes.size() + td.Includes.size());
  cd.Includes.insert(cd.Includes.end(), fd.Includes.begin(),
                     fd.Includes.end());
  cd.Includes.insert(cd.Includes.end(), td.Includes.begin(),
                     td.Includes.end());

  // Use source-specific frameworks followed by target-wide frameworks.
  cd.Frameworks.reserve(fd.Frameworks.size() + td.Frameworks.size());
  cd.Frameworks.insert(cd.Frameworks.end(), fd.Frameworks.begin(),
                       fd.Frameworks.end());
  cd.Frameworks.insert(cd.Frameworks.end(), td.Frameworks.begin(),
                       td.Frameworks.end());

  // Use target-wide defines followed by source-specific defines.
  cd.Defines.reserve(td.Defines.size() + fd.Defines.size());
  cd.Defines.insert(cd.Defines.end(), td.Defines.begin(), td.Defines.end());
  cd.Defines.insert(cd.Defines.end(), fd.Defines.begin(), fd.Defines.end());

  // De-duplicate defines.
  std::stable_sort(cd.Defines.begin(), cd.Defines.end(),
                   JBT<std::string>::ValueLess);
  auto end = std::unique(cd.Defines.begin(), cd.Defines.end(),
                         JBT<std::string>::ValueEq);
  cd.Defines.erase(end, cd.Defines.end());

  return cd;
}

Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf,
                                               Json::ArrayIndex si)
{
  CompileData compileData = this->BuildCompileData(sf);
  auto i = this->CompileGroupMap.find(compileData);
  if (i == this->CompileGroupMap.end()) {
    Json::ArrayIndex cgIndex =
      static_cast<Json::ArrayIndex>(this->CompileGroups.size());
    i = this->CompileGroupMap.emplace(std::move(compileData), cgIndex).first;
    CompileGroup g;
    g.Entry = i;
    this->CompileGroups.push_back(std::move(g));
  }
  this->CompileGroups[i->second].SourceIndexes.append(si);
  return i->second;
}

void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt)
{
  if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
    object["backtrace"] = backtrace.Index;
  }
}

void Target::AddBacktrace(Json::Value& object, JBTIndex bt)
{
  if (bt) {
    object["backtrace"] = bt.Index;
  }
}

Json::Value Target::DumpPaths()
{
  Json::Value paths = Json::objectValue;
  cmLocalGenerator* lg = this->GT->GetLocalGenerator();

  std::string const& sourceDir = lg->GetCurrentSourceDirectory();
  paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);

  std::string const& buildDir = lg->GetCurrentBinaryDirectory();
  paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);

  return paths;
}

std::pair<Json::Value, Target::FileSetDatabase> Target::DumpFileSets()
{
  Json::Value fsJson = Json::nullValue;
  FileSetDatabase fsdb;

  // We record the visibility of each file set for later use when dumping
  // interface sources, which needs to map files to file set visibility
  // with only an index available. Those indexes match this vector.
  this->FileSetVisibilities.clear();
  this->FileSetBacktraces.clear();

  // Build the fileset database.
  auto const& fileSets = this->GT->GetAllFileSets();

  if (!fileSets.empty()) {
    fsJson = Json::arrayValue;
    size_t fsIndex = 0;
    for (auto const* fs : fileSets) {
      cm::GenEx::Context context(this->GT->LocalGenerator, this->Config);

      auto directories = fs->GetDirectories(context, this->GT);

      fsJson.append(this->DumpFileSet(fs, directories.first));
      this->FileSetVisibilities.push_back(fs->GetVisibility());

      auto files_per_dirs = fs->GetFiles(context, this->GT);

      for (auto const& files_per_dir : files_per_dirs.first) {
        auto const& dir = files_per_dir.first;
        for (auto const& file : files_per_dir.second) {
          std::string sf_path;
          if (dir.empty() || cmSystemTools::FileIsFullPath(file)) {
            sf_path = file;
          } else {
            sf_path = cmStrCat(dir, '/', file);
          }
          fsdb[sf_path].emplace_back(static_cast<Json::ArrayIndex>(fsIndex));
        }
      }

      // Collect backtraces from each original file set FILES entry so that
      // source backtraces preserve line metadata and can include repeated
      // additions from multiple file sets.
      auto const& fileEntries = fs->GetFileEntries();
      for (BT<std::string> const& fileEntry : fileEntries) {
        cmGeneratorExpression ge(
          *this->GT->GetLocalGenerator()->GetCMakeInstance(),
          fileEntry.Backtrace);
        for (std::string const& ex : cmList{ fileEntry.Value }) {
          std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(ex);
          std::map<std::string, std::vector<std::string>> filesForEntry;
          fs->EvaluateFileEntry(directories.first, filesForEntry, cge, context,
                                this->GT);
          for (auto const& filesPerDir : filesForEntry) {
            std::string const& dir = filesPerDir.first;
            for (std::string const& file : filesPerDir.second) {
              std::string sf_path;
              if (dir.empty() || cmSystemTools::FileIsFullPath(file)) {
                sf_path = file;
              } else {
                sf_path = cmStrCat(dir, '/', file);
              }
              this->FileSetBacktraces[sf_path].push_back(fileEntry.Backtrace);
            }
          }
        }
      }

      ++fsIndex;
    }
  }

  return std::make_pair(fsJson, fsdb);
}

Json::Value Target::DumpFileSet(cmGeneratorFileSet const* fs,
                                std::vector<std::string> const& directories)
{
  Json::Value fileSet = Json::objectValue;

  fileSet["name"] = fs->GetName();
  fileSet["type"] = fs->GetType();
  fileSet["visibility"] =
    std::string(cm::FileSetMetadata::VisibilityToName(fs->GetVisibility()));

  Json::Value baseDirs = Json::arrayValue;
  for (auto const& directory : directories) {
    baseDirs.append(RelativeIfUnder(this->TopSource, directory));
  }
  fileSet["baseDirectories"] = baseDirs;

  return fileSet;
}

Json::Value Target::DumpSources(FileSetDatabase const& fsdb)
{
  Json::Value sources = Json::arrayValue;
  cmGeneratorTarget::KindedSources const& kinded =
    this->GT->GetKindedSources(this->Config);
  for (cmGeneratorTarget::SourceAndKind const& sk : kinded.Sources) {
    sources.append(this->DumpSource(sk, sources.size(), fsdb));
  }
  return sources;
}

Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
                               Json::ArrayIndex si,
                               FileSetDatabase const& fsdb)
{
  Json::Value source = Json::objectValue;

  cmSourceFile* sf = sk.Source.Value;
  std::string const path = sf->ResolveFullPath();
  source["path"] = RelativeIfUnder(this->TopSource, path);
  if (sk.Source.Value->GetIsGenerated()) {
    source["isGenerated"] = true;
  }

  JBTIndex sourceBacktrace = this->Backtraces.Add(sk.Source.Backtrace);
  JBTIndex primaryBacktrace = sourceBacktrace;
  Json::Value backtraces = Json::arrayValue;
  auto const fileSetBacktraces = this->FileSetBacktraces.find(path);
  if (fileSetBacktraces != this->FileSetBacktraces.end() &&
      !fileSetBacktraces->second.empty()) {
    for (cmListFileBacktrace const& fsbt : fileSetBacktraces->second) {
      if (JBTIndex bt = this->Backtraces.Add(fsbt)) {
        if (!primaryBacktrace) {
          primaryBacktrace = bt;
        }
        backtraces.append(bt.Index);
      }
    }
  } else {
    if (sourceBacktrace) {
      backtraces.append(sourceBacktrace.Index);
    }
  }

  this->AddBacktrace(source, primaryBacktrace);

  if (!backtraces.empty()) {
    source["backtraces"] = std::move(backtraces);
  }

  auto fsit = fsdb.find(path);
  if (fsit != fsdb.end()) {
    source["fileSetIndex"] = fsit->second.back();
    source["fileSetIndexes"] = Json::arrayValue;
    for (Json::ArrayIndex const& fsIndex : fsit->second) {
      source["fileSetIndexes"].append(fsIndex);
    }
  }

  if (cmSourceGroup const* sg = this->GT->LocalGenerator->FindSourceGroup(
        this->GT, sf, this->Config)) {
    Json::ArrayIndex const groupIndex = this->AddSourceGroup(sg);
    source["sourceGroupIndex"] = groupIndex;
    this->SourceGroups[groupIndex].SourceIndexes.append(si);
  }

  switch (sk.Kind) {
    case cmGeneratorTarget::SourceKindCxxModuleSource:
    case cmGeneratorTarget::SourceKindObjectSource: {
      source["compileGroupIndex"] =
        this->AddSourceCompileGroup(sk.Source.Value, si);
    } break;
    case cmGeneratorTarget::SourceKindAppManifest:
    case cmGeneratorTarget::SourceKindCertificate:
    case cmGeneratorTarget::SourceKindCustomCommand:
    case cmGeneratorTarget::SourceKindExternalObject:
    case cmGeneratorTarget::SourceKindExtra:
    case cmGeneratorTarget::SourceKindHeader:
    case cmGeneratorTarget::SourceKindIDL:
    case cmGeneratorTarget::SourceKindManifest:
    case cmGeneratorTarget::SourceKindModuleDefinition:
    case cmGeneratorTarget::SourceKindResx:
    case cmGeneratorTarget::SourceKindXaml:
    case cmGeneratorTarget::SourceKindUnityBatched:
    case cmGeneratorTarget::SourceKindRustMainCrateRoot:
      break;
  }

  return source;
}

Json::Value Target::DumpInterfaceSources(FileSetDatabase const& fsdb)
{
  Json::Value interfaceSources = Json::arrayValue;
  auto dumpFile = [this, &interfaceSources, &fsdb](std::string const& file) {
    std::string path = file;
    if (!cmSystemTools::FileIsFullPath(path)) {
      path = cmStrCat(
        this->GT->GetLocalGenerator()->GetCurrentSourceDirectory(), '/', file);
    }
    path = cmSystemTools::CollapseFullPath(path);

    interfaceSources.append(
      this->DumpInterfaceSource(path, interfaceSources.size(), fsdb));
  };

  cmValue prop = this->GT->GetProperty("INTERFACE_SOURCES");
  if (prop) {
    cmList files{ cmGeneratorExpression::Evaluate(
      *prop, this->GT->GetLocalGenerator(), this->Config, this->GT) };

    for (std::string const& file : files) {
      dumpFile(file);
    }
  }

  for (auto const& fsIter : fsdb) {
    Json::ArrayIndex const index = fsIter.second.back();
    // FileSetVisibilities was populated by DumpFileSets() and will always
    // have the same size as the file sets array that index is indexing into
    if (this->FileSetVisibilities[index] !=
        cm::FileSetMetadata::Visibility::Private) {
      dumpFile(fsIter.first);
    }
  }

  return interfaceSources;
}

Json::Value Target::DumpInterfaceSource(std::string path, Json::ArrayIndex si,
                                        FileSetDatabase const& fsdb)
{
  Json::Value source = Json::objectValue;

  cmSourceFile* sf = this->GT->Makefile->GetOrCreateSource(path);
  path = sf->ResolveFullPath();
  source["path"] = RelativeIfUnder(this->TopSource, path);
  if (sf->GetIsGenerated()) {
    source["isGenerated"] = true;
  }

  auto fsit = fsdb.find(path);
  if (fsit != fsdb.end()) {
    source["fileSetIndex"] = fsit->second.back();
    source["fileSetIndexes"] = Json::arrayValue;
    for (Json::ArrayIndex const& fsIndex : fsit->second) {
      source["fileSetIndexes"].append(fsIndex);
    }
  }

  if (cmSourceGroup const* sg = this->GT->LocalGenerator->FindSourceGroup(
        this->GT, sf, this->Config)) {
    Json::ArrayIndex const groupIndex = this->AddSourceGroup(sg);
    source["sourceGroupIndex"] = groupIndex;
    this->SourceGroups[groupIndex].InterfaceSourceIndexes.append(si);
  }

  return source;
}

Json::Value Target::DumpCompileData(CompileData const& cd)
{
  Json::Value result = Json::objectValue;

  if (!cd.Language.empty()) {
    result["language"] = cd.Language;
  }
  if (!cd.Sysroot.empty()) {
    result["sysroot"] = this->DumpSysroot(cd.Sysroot);
  }
  if (!cd.Flags.empty()) {
    result["compileCommandFragments"] = this->DumpCommandFragments(cd.Flags);
  }
  if (!cd.Includes.empty()) {
    Json::Value includes = Json::arrayValue;
    for (auto const& i : cd.Includes) {
      includes.append(this->DumpInclude(i));
    }
    result["includes"] = includes;
  }
  if (!cd.Frameworks.empty()) {
    Json::Value frameworks = Json::arrayValue;
    for (auto const& i : cd.Frameworks) {
      frameworks.append(this->DumpFramework(i));
    }
    result["frameworks"] = frameworks;
  }
  if (!cd.Defines.empty()) {
    Json::Value defines = Json::arrayValue;
    for (JBT<std::string> const& d : cd.Defines) {
      defines.append(this->DumpDefine(d));
    }
    result["defines"] = std::move(defines);
  }
  if (!cd.PrecompileHeaders.empty()) {
    Json::Value precompileHeaders = Json::arrayValue;
    for (JBT<std::string> const& pch : cd.PrecompileHeaders) {
      precompileHeaders.append(this->DumpPrecompileHeader(pch));
    }
    result["precompileHeaders"] = std::move(precompileHeaders);
  }
  if (!cd.LanguageStandard.Value.empty()) {
    result["languageStandard"] =
      this->DumpLanguageStandard(cd.LanguageStandard);
  }

  return result;
}

Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc)
{
  Json::Value include = Json::objectValue;
  include["path"] = inc.Path.Value;
  if (inc.IsSystem) {
    include["isSystem"] = true;
  }
  this->AddBacktrace(include, inc.Path.Backtrace);
  return include;
}

Json::Value Target::DumpFramework(CompileData::IncludeEntry const& fw)
{
  // for now, idem as include
  return this->DumpInclude(fw);
}

Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header)
{
  Json::Value precompileHeader = Json::objectValue;
  precompileHeader["header"] = header.Value;
  this->AddBacktrace(precompileHeader, header.Backtrace);
  return precompileHeader;
}

Json::Value Target::DumpLanguageStandard(JBTs<std::string> const& standard)
{
  Json::Value languageStandard = Json::objectValue;
  languageStandard["standard"] = standard.Value;
  if (!standard.Backtraces.empty()) {
    Json::Value backtraces = Json::arrayValue;
    for (JBTIndex backtrace : standard.Backtraces) {
      backtraces.append(backtrace.Index);
    }
    languageStandard["backtraces"] = backtraces;
  }
  return languageStandard;
}

Json::Value Target::DumpDefine(JBT<std::string> const& def)
{
  Json::Value define = Json::objectValue;
  define["define"] = def.Value;
  this->AddBacktrace(define, def.Backtrace);
  return define;
}

Json::Value Target::DumpSourceGroups()
{
  Json::Value sourceGroups = Json::arrayValue;
  for (auto& sg : this->SourceGroups) {
    sourceGroups.append(this->DumpSourceGroup(sg));
  }
  return sourceGroups;
}

Json::Value Target::DumpSourceGroup(SourceGroup& sg)
{
  Json::Value group = Json::objectValue;
  group["name"] = sg.Name;
  group["sourceIndexes"] = std::move(sg.SourceIndexes);
  if (!sg.InterfaceSourceIndexes.empty()) {
    group["interfaceSourceIndexes"] = std::move(sg.InterfaceSourceIndexes);
  }
  return group;
}

Json::Value Target::DumpCompileGroups()
{
  Json::Value compileGroups = Json::arrayValue;
  for (auto& cg : this->CompileGroups) {
    compileGroups.append(this->DumpCompileGroup(cg));
  }
  return compileGroups;
}

Json::Value Target::DumpCompileGroup(CompileGroup& cg)
{
  Json::Value group =
    this->DumpCompileData(this->MergeCompileData(cg.Entry->first));
  group["sourceIndexes"] = std::move(cg.SourceIndexes);
  return group;
}

Json::Value Target::DumpSysroot(std::string const& path)
{
  Json::Value sysroot = Json::objectValue;
  sysroot["path"] = path;
  return sysroot;
}

Json::Value Target::DumpInstall()
{
  Json::Value install = Json::objectValue;
  install["prefix"] = this->DumpInstallPrefix();
  install["destinations"] = this->DumpInstallDestinations();
  return install;
}

Json::Value Target::DumpInstallPrefix()
{
  Json::Value prefix = Json::objectValue;
  std::string p =
    this->GT->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
  cmSystemTools::ConvertToUnixSlashes(p);
  prefix["path"] = p;
  return prefix;
}

Json::Value Target::DumpInstallDestinations()
{
  Json::Value destinations = Json::arrayValue;
  auto installGens = this->GT->Target->GetInstallGenerators();
  for (auto* itGen : installGens) {
    destinations.append(this->DumpInstallDestination(itGen));
  }
  return destinations;
}

Json::Value Target::DumpInstallDestination(cmInstallTargetGenerator* itGen)
{
  Json::Value destination = Json::objectValue;
  destination["path"] = itGen->GetDestination(this->Config);
  this->AddBacktrace(destination, itGen->GetBacktrace());
  return destination;
}

Json::Value Target::DumpArtifacts()
{
  Json::Value artifacts = Json::arrayValue;

  // Object libraries have only object files as artifacts.
  if (this->GT->GetType() == cm::TargetType::OBJECT_LIBRARY) {
    if (!this->GT->Target->HasKnownObjectFileLocation(nullptr)) {
      return artifacts;
    }
    std::vector<cmSourceFile const*> objectSources;
    this->GT->GetObjectSources(objectSources, this->Config);
    std::string const obj_dir = this->GT->GetObjectDirectory(this->Config);
    for (cmSourceFile const* sf : objectSources) {
      std::string const& obj = this->GT->GetObjectName(sf);
      Json::Value artifact = Json::objectValue;
      artifact["path"] = RelativeIfUnder(this->TopBuild, obj_dir + obj);
      artifacts.append(std::move(artifact)); // NOLINT(*)
    }
    return artifacts;
  }

  // Other target types always have a "main" artifact.
  {
    Json::Value artifact = Json::objectValue;
    artifact["path"] =
      RelativeIfUnder(this->TopBuild,
                      this->GT->GetFullPath(
                        this->Config, cmStateEnums::RuntimeBinaryArtifact));
    artifacts.append(std::move(artifact)); // NOLINT(*)
  }

  // Add Windows-specific artifacts produced by the linker.
  // NOTE: HasImportLibrary() only checks if the target SHOULD have an import
  //       library, not whether it has one set.
  if (this->GT->HasImportLibrary(this->Config)) {
    std::string fullPath;
    if (this->GT->IsImported()) {
      // This imported target might not be well-formed. For Windows, it should
      // have its IMPORTED_IMPLIB property set, and CMP0111's NEW behavior is
      // intended to catch and report that. But if nothing uses the imported
      // target, there won't have been any opportunity to detect that property
      // being missing before here. Therefore, we tell ImportedGetFullPath()
      // not to raise that CMP0111 error if it sees the problem. We don't want
      // to trigger an error for a target that nothing uses, as that would be a
      // regression compared to CMake 4.1 and earlier behavior.
      fullPath = this->GT->Target->ImportedGetFullPath(
        this->Config, cmStateEnums::ImportLibraryArtifact,
        cmTarget::ImportArtifactMissingOk::Yes);
      if (cmHasLiteralSuffix(fullPath, "-NOTFOUND")) {
        fullPath.clear();
      }
    } else {
      fullPath = this->GT->NormalGetFullPath(
        this->Config, cmStateEnums::ImportLibraryArtifact, false);
    }
    if (!fullPath.empty()) {
      Json::Value artifact = Json::objectValue;
      artifact["path"] = RelativeIfUnder(this->TopBuild, fullPath);
      artifacts.append(std::move(artifact)); // NOLINT(*)
    }
  }
  if (this->GT->IsDLLPlatform() &&
      this->GT->GetType() != cm::TargetType::STATIC_LIBRARY) {
    cmGeneratorTarget::OutputInfo const* output =
      this->GT->GetOutputInfo(this->Config);
    if (output && !output->PdbDir.empty()) {
      Json::Value artifact = Json::objectValue;
      artifact["path"] = RelativeIfUnder(
        this->TopBuild,
        cmStrCat(output->PdbDir, '/', this->GT->GetPDBName(this->Config)));
      artifacts.append(std::move(artifact)); // NOLINT(*)
    }
  }
  return artifacts;
}

Json::Value Target::DumpLink()
{
  Json::Value link = Json::objectValue;
  std::string lang = this->GT->GetLinkerLanguage(this->Config);
  link["language"] = lang;
  {
    Json::Value commandFragments = this->DumpLinkCommandFragments();
    if (!commandFragments.empty()) {
      link["commandFragments"] = std::move(commandFragments);
    }
  }
  if (cmValue sysrootLink =
        this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
    link["sysroot"] = this->DumpSysroot(*sysrootLink);
  } else if (cmValue sysroot =
               this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
    link["sysroot"] = this->DumpSysroot(*sysroot);
  }
  if (this->GT->IsIPOEnabled(lang, this->Config)) {
    link["lto"] = true;
  }
  return link;
}

Json::Value Target::DumpArchive()
{
  Json::Value archive = Json::objectValue;
  {
    // The "link" fragments not relevant to static libraries are empty.
    Json::Value commandFragments = this->DumpLinkCommandFragments();
    if (!commandFragments.empty()) {
      archive["commandFragments"] = std::move(commandFragments);
    }
  }
  std::string lang = this->GT->GetLinkerLanguage(this->Config);
  if (this->GT->IsIPOEnabled(lang, this->Config)) {
    archive["lto"] = true;
  }
  return archive;
}

Json::Value Target::DumpLinkCommandFragments()
{
  Json::Value linkFragments = Json::arrayValue;

  std::string linkLanguageFlags;
  std::vector<BT<std::string>> linkFlags;
  std::string frameworkPath;
  std::vector<BT<std::string>> linkPath;
  std::vector<BT<std::string>> linkLibs;
  cmLocalGenerator* lg = this->GT->GetLocalGenerator();
  cmGlobalGenerator* gg = this->GT->GetGlobalGenerator();
  std::unique_ptr<cmLinkLineComputer> linkLineComputer =
    gg->CreateLinkLineComputer(lg, lg->GetStateSnapshot().GetDirectory());
  lg->GetTargetFlags(linkLineComputer.get(), this->Config, linkLibs,
                     linkLanguageFlags, linkFlags, frameworkPath, linkPath,
                     this->GT);
  linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
  frameworkPath = cmTrimWhitespace(frameworkPath);

  if (!linkLanguageFlags.empty()) {
    linkFragments.append(
      this->DumpCommandFragment(std::move(linkLanguageFlags), "flags"));
  }

  if (!linkFlags.empty()) {
    for (BT<std::string> frag : linkFlags) {
      frag.Value = cmTrimWhitespace(frag.Value);
      linkFragments.append(
        this->DumpCommandFragment(this->ToJBT(frag), "flags"));
    }
  }

  if (!frameworkPath.empty()) {
    linkFragments.append(
      this->DumpCommandFragment(std::move(frameworkPath), "frameworkPath"));
  }

  if (!linkPath.empty()) {
    for (BT<std::string> frag : linkPath) {
      frag.Value = cmTrimWhitespace(frag.Value);
      linkFragments.append(
        this->DumpCommandFragment(this->ToJBT(frag), "libraryPath"));
    }
  }

  if (!linkLibs.empty()) {
    for (BT<std::string> frag : linkLibs) {
      frag.Value = cmTrimWhitespace(frag.Value);
      linkFragments.append(
        this->DumpCommandFragment(this->ToJBT(frag), "libraries"));
    }
  }

  return linkFragments;
}

Json::Value Target::DumpCommandFragments(
  std::vector<JBT<std::string>> const& frags)
{
  Json::Value commandFragments = Json::arrayValue;
  for (JBT<std::string> const& f : frags) {
    commandFragments.append(this->DumpCommandFragment(f));
  }
  return commandFragments;
}

Json::Value Target::DumpCommandFragment(JBT<std::string> const& frag,
                                        std::string const& role)
{
  Json::Value fragment = Json::objectValue;
  fragment["fragment"] = frag.Value;
  if (!role.empty()) {
    fragment["role"] = role;
  }
  this->AddBacktrace(fragment, frag.Backtrace);
  return fragment;
}

Json::Value Target::DumpDependencies()
{
  Json::Value dependencies = Json::arrayValue;
  cmGlobalGenerator* gg = this->GT->GetGlobalGenerator();
  for (cmTargetDepend const& td : gg->GetTargetDirectDepends(this->GT)) {
    dependencies.append(this->DumpDependency(td));
  }
  return dependencies;
}

Json::Value Target::DumpDependency(cmTargetDepend const& td)
{
  Json::Value dependency = Json::objectValue;
  dependency["id"] = TargetId(td, this->TopBuild);
  this->AddBacktrace(dependency, td.GetBacktrace());
  return dependency;
}

Json::Value Target::DumpLinkItem(cmLinkItem const& linkItem)
{
  Json::Value itemJson = Json::objectValue;
  if (linkItem.Target) {
    itemJson["id"] = TargetId(linkItem.Target, this->TopBuild);
  } else {
    itemJson["fragment"] = linkItem.AsStr();
  }
  if (linkItem.InterfaceDirectFrom) {
    Json::Value jsonDirectFrom = Json::objectValue;
    jsonDirectFrom["id"] =
      TargetId(linkItem.InterfaceDirectFrom, this->TopBuild);
    itemJson["fromDependency"] = jsonDirectFrom;
  }
  this->AddBacktrace(itemJson, linkItem.Backtrace);
  return itemJson;
}

Json::Value Target::DumpLinkImplementationLibraries(
  cmGeneratorTarget::UseTo usage)
{
  Json::Value jsonLibs = Json::arrayValue;

  cmLinkImplementationLibraries const* implLibs =
    this->GT->GetLinkImplementationLibraries(this->Config, usage);
  if (implLibs) {
    for (cmLinkItem const& linkItem : implLibs->Libraries) {
      // Non-target compile items are never used, so we drop them here too
      if (usage == cmGeneratorTarget::UseTo::Link || linkItem.Target) {
        jsonLibs.append(this->DumpLinkItem(linkItem));
      }
    }
  }
  return jsonLibs;
}

Json::Value Target::DumpLinkInterfaceLibraries(cmGeneratorTarget::UseTo usage)
{
  Json::Value jsonLibs = Json::arrayValue;

  cmLinkInterfaceLibraries const* ifaceLibs =
    this->GT->GetLinkInterfaceLibraries(this->Config, this->GT, usage);
  if (ifaceLibs) {
    for (cmLinkItem const& linkItem : ifaceLibs->Libraries) {
      // Non-target compile items are never used, so we drop them here too
      if (usage == cmGeneratorTarget::UseTo::Link || linkItem.Target) {
        jsonLibs.append(this->DumpLinkItem(linkItem));
      }
    }
  }
  return jsonLibs;
}

Json::Value Target::DumpObjectDependencies()
{
  // Object dependencies are a special case. They cannot be config-specific
  // because they are obtained by matching the pattern $<TARGET_OBJECTS:xxx>
  // against the SOURCES property, and the matcher rejects any cases where
  // "xxx" contains a generator expression. We can't use
  // GetSourceObjectLibraries() either because that also returns object
  // libraries added via LINK_LIBRARIES rather than $<TARGET_OBJECTS:xxx>,
  // and the whole point of orderDependencies is to capture those that are
  // not listed in LINK_LIBRARIES.
  std::vector<BT<cmGeneratorTarget*>> objectLibraries;
  this->GT->GetObjectLibrariesInSources(objectLibraries);

  // We don't want to repeat the same target in the list. We will only
  // retain one backtrace for cases where the same target is added multiple
  // times from different commands. We also need a deterministic ordering,
  // so we can't use cmGeneratorTarget* pointers in a std::set here.
  using TargetIdMap = std::map<std::string, BT<cmGeneratorTarget*>>;
  TargetIdMap uniqueObjectLibraries;
  for (BT<cmGeneratorTarget*> const& target : objectLibraries) {
    uniqueObjectLibraries[TargetId(target.Value, this->TopBuild)] = target;
  }

  Json::Value jsonDependencies = Json::arrayValue;
  for (TargetIdMap::value_type const& idTargetPair : uniqueObjectLibraries) {
    Json::Value jsonDependency = Json::objectValue;
    jsonDependency["id"] = idTargetPair.first;
    this->AddBacktrace(jsonDependency, idTargetPair.second.Backtrace);
    jsonDependencies.append(jsonDependency);
  }
  return jsonDependencies;
}

Json::Value Target::DumpOrderDependencies()
{
  // The generated build systems don't account for per-config dependencies.
  // This is due to limitations of Xcode and/or Visual Studio, which have
  // (or at least once had) no way to express a per-config inter-target
  // dependency.
  Json::Value jsonDependencies = Json::arrayValue;
  for (cmLinkItem const& linkItem : this->GT->GetUtilityItems()) {
    // We don't want to dump dependencies on reserved targets like ZERO_CHECK.
    // We shouldn't see link items that are not targets, but for backward
    // compatibility reasons, they are currently allowed but silently ignored.
    if (!linkItem.Target ||
        cmGlobalGenerator::IsReservedTarget(linkItem.Target->GetName())) {
      continue;
    }
    Json::Value jsonDependency = Json::objectValue;
    jsonDependency["id"] = TargetId(linkItem.Target, this->TopBuild);
    this->AddBacktrace(jsonDependency, linkItem.Backtrace);
    jsonDependencies.append(jsonDependency);
  }
  return jsonDependencies;
}

Json::Value Target::DumpFolder()
{
  Json::Value folder;
  if (cmValue f = this->GT->GetProperty("FOLDER")) {
    folder = Json::objectValue;
    folder["name"] = *f;
  }
  return folder;
}

Json::Value Target::DumpLauncher(char const* name, char const* type)
{
  cmValue property = this->GT->GetProperty(name);
  Json::Value launcher;
  if (property) {
    cmLocalGenerator* lg = this->GT->GetLocalGenerator();
    cmGeneratorExpression ge(*lg->GetCMakeInstance());
    cmList commandWithArgs{ ge.Parse(*property)->Evaluate(lg, this->Config) };
    if (!commandWithArgs.empty() && !commandWithArgs[0].empty()) {
      std::string command(commandWithArgs[0]);
      cmSystemTools::ConvertToUnixSlashes(command);
      launcher = Json::objectValue;
      launcher["command"] = RelativeIfUnder(this->TopSource, command);
      launcher["type"] = type;
      Json::Value args;
      for (std::string const& arg : cmMakeRange(commandWithArgs).advance(1)) {
        args.append(arg);
      }
      if (!args.empty()) {
        launcher["arguments"] = std::move(args);
      }
    }
  }
  return launcher;
}

Json::Value Target::DumpLaunchers()
{
  Json::Value launchers;
  {
    Json::Value launcher = DumpLauncher("TEST_LAUNCHER", "test");
    if (!launcher.empty()) {
      launchers.append(std::move(launcher));
    }
  }
  if (this->GT->Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
    Json::Value emulator = DumpLauncher("CROSSCOMPILING_EMULATOR", "emulator");
    if (!emulator.empty()) {
      launchers.append(std::move(emulator));
    }
  }
  return launchers;
}
}

Json::Value Target::DumpDebugger()
{
  Json::Value debuggerInformation;
  if (cmValue debuggerWorkingDirectory =
        this->GT->GetGlobalGenerator()->GetDebuggerWorkingDirectory(
          this->GT)) {
    debuggerInformation = Json::objectValue;
    debuggerInformation["workingDirectory"] = *debuggerWorkingDirectory;
  }

  return debuggerInformation;
}

Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI,
                                   unsigned int versionMajor,
                                   unsigned int versionMinor)
{
  Codemodel codemodel(fileAPI, versionMajor, versionMinor);
  return codemodel.Dump();
}
