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

#include <algorithm>
#include <cassert>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iterator>
#include <sstream>
#include <utility>

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

#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"

#include "cmCryptoHash.h"
#include "cmFileAPICMakeFiles.h"
#include "cmFileAPICache.h"
#include "cmFileAPICodemodel.h"
#include "cmFileAPIConfigureLog.h"
#include "cmFileAPIToolchains.h"
#include "cmGlobalGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmake.h"

#if defined(__clang__) && defined(__has_warning)
#  if __has_warning("-Wrange-loop-analysis")
#    if defined(__apple_build_version__)
#      if __apple_build_version__ < 13000000
#        define CM_CLANG_SUPPRESS_WARN_RANGE_LOOP_ANALYSIS
#      endif
#    else
#      if __clang_major__ < 11
#        define CM_CLANG_SUPPRESS_WARN_RANGE_LOOP_ANALYSIS
#      endif
#    endif
#  endif
#endif

cmFileAPI::cmFileAPI(cmake* cm)
  : CMakeInstance(cm)
{
  this->APIv1 =
    cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/.cmake/api/v1");

  if (cm::optional<std::string> cmakeConfigDir =
        cmSystemTools::GetCMakeConfigDirectory()) {
    this->UserAPIv1 = cmStrCat(std::move(*cmakeConfigDir), "/api/v1"_s);
  }

  Json::CharReaderBuilder rbuilder;
  rbuilder["collectComments"] = false;
  rbuilder["failIfExtra"] = true;
  rbuilder["rejectDupKeys"] = false;
  rbuilder["strictRoot"] = true;
  this->JsonReader =
    std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());

  Json::StreamWriterBuilder wbuilder;
  wbuilder["indentation"] = "\t";
  this->JsonWriter =
    std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter());
}

void cmFileAPI::ReadQueries()
{
  std::string const query_dir = cmStrCat(this->APIv1, "/query");
  std::string const user_query_dir = cmStrCat(this->UserAPIv1, "/query");
  this->QueryExists = cmSystemTools::FileIsDirectory(query_dir);
  if (!this->UserAPIv1.empty()) {
    this->QueryExists =
      this->QueryExists || cmSystemTools::FileIsDirectory(user_query_dir);
  }
  if (!this->QueryExists) {
    return;
  }

  // Load queries at the top level.
  std::vector<std::string> queries = cmFileAPI::LoadDir(query_dir);
  if (!this->UserAPIv1.empty()) {
    std::vector<std::string> user_queries = cmFileAPI::LoadDir(user_query_dir);
    std::move(user_queries.begin(), user_queries.end(),
              std::back_inserter(queries));
  }

  // Read the queries and save for later.
  for (std::string& query : queries) {
    if (cmHasLiteralPrefix(query, "client-")) {
      this->ReadClient(query);
    } else if (!cmFileAPI::ReadQuery(query, this->TopQuery.Known)) {
      this->TopQuery.Unknown.push_back(std::move(query));
    }
  }
}

std::vector<unsigned int> cmFileAPI::GetConfigureLogVersions()
{
  std::vector<unsigned int> versions;
  auto getConfigureLogVersions = [&versions](Query const& q) {
#ifdef CM_CLANG_SUPPRESS_WARN_RANGE_LOOP_ANALYSIS
#  pragma clang diagnostic push
#  pragma clang diagnostic ignored "-Wrange-loop-analysis"
#endif
    for (Object const o : q.Known) {
#ifdef CM_CLANG_SUPPRESS_WARN_RANGE_LOOP_ANALYSIS
#  pragma clang diagnostic pop
#endif
      if (o.Kind == ObjectKind::ConfigureLog) {
        versions.emplace_back(o.Version);
      }
    }
  };
  getConfigureLogVersions(this->TopQuery);
  for (auto const& client : this->ClientQueries) {
    getConfigureLogVersions(client.second.DirQuery);
  }
  std::sort(versions.begin(), versions.end());
  versions.erase(std::unique(versions.begin(), versions.end()),
                 versions.end());
  return versions;
}

void cmFileAPI::WriteReplies(IndexFor indexFor)
{
  bool const success = indexFor == IndexFor::Success;
  this->ReplyIndexFor = indexFor;

  if (this->QueryExists) {
    cmSystemTools::MakeDirectory(this->APIv1 + "/reply");
    this->WriteJsonFile(this->BuildReplyIndex(), success ? "index" : "error",
                        ComputeSuffixTime);
  }

  if (success) {
    this->RemoveOldReplyFiles();
  }
}

std::vector<std::string> cmFileAPI::LoadDir(std::string const& dir)
{
  std::vector<std::string> files;
  cmsys::Directory d;
  d.Load(dir);
  for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) {
    std::string f = d.GetFile(i);
    if (f != "." && f != "..") {
      files.push_back(std::move(f));
    }
  }
  std::sort(files.begin(), files.end());
  return files;
}

void cmFileAPI::RemoveOldReplyFiles()
{
  std::string const reply_dir = this->APIv1 + "/reply";
  std::vector<std::string> files = this->LoadDir(reply_dir);
  for (std::string const& f : files) {
    if (this->ReplyFiles.find(f) == this->ReplyFiles.end()) {
      std::string file = cmStrCat(reply_dir, '/', f);
      cmSystemTools::RemoveFile(file);
    }
  }
}

bool cmFileAPI::ReadJsonFile(std::string const& file, Json::Value& value,
                             std::string& error)
{
  std::vector<char> content;

  cmsys::ifstream fin;
  if (!cmSystemTools::FileIsDirectory(file)) {
    fin.open(file.c_str(), std::ios::binary);
  }
  auto finEnd = fin.rdbuf()->pubseekoff(0, std::ios::end);
  if (finEnd > 0) {
    size_t finSize = finEnd;
    try {
      // Allocate a buffer to read the whole file.
      content.resize(finSize);

      // Now read the file from the beginning.
      fin.seekg(0, std::ios::beg);
      fin.read(content.data(), finSize);
    } catch (...) {
      fin.setstate(std::ios::failbit);
    }
  }
  fin.close();
  if (!fin) {
    value = Json::Value();
    error = "failed to read from file";
    return false;
  }

  // Parse our buffer as json.
  if (!this->JsonReader->parse(content.data(), content.data() + content.size(),
                               &value, &error)) {
    value = Json::Value();
    return false;
  }

  return true;
}

std::string cmFileAPI::WriteJsonFile(
  Json::Value const& value, std::string const& prefix,
  std::string (*computeSuffix)(std::string const&))
{
  std::string fileName;

  // Write the json file with a temporary name.
  std::string const& tmpFile = this->APIv1 + "/tmp.json";
  cmsys::ofstream ftmp(tmpFile.c_str());
  this->JsonWriter->write(value, &ftmp);
  ftmp << "\n";
  ftmp.close();
  if (!ftmp) {
    cmSystemTools::RemoveFile(tmpFile);
    return fileName;
  }

  // Compute the final name for the file.
  std::string suffix = computeSuffix(tmpFile);
  std::string suffixWithExtension = cmStrCat('-', suffix, ".json");
  fileName = cmStrCat(prefix, suffixWithExtension);

  // Truncate the file name length
  // eCryptFS has a maximal file name length recommendation of 140
  size_t const maxFileNameLength = 140;
  size_t const fileNameLength = fileName.size();
  if (fileNameLength > maxFileNameLength) {
    size_t const newHashLength = 20;
    size_t const newSuffixLength =
      suffixWithExtension.size() - suffix.size() + newHashLength;
    size_t const overLength =
      fileNameLength - maxFileNameLength + newSuffixLength;
    size_t const startPos = fileNameLength - overLength;
    std::string const toBeRemoved = fileName.substr(startPos, overLength);
    suffix = cmCryptoHash(cmCryptoHash::AlgoSHA256)
               .HashString(toBeRemoved)
               .substr(0, newHashLength);
    suffixWithExtension = cmStrCat('-', suffix, ".json");
    fileName.replace(startPos, overLength, suffixWithExtension);
  }

  // Create the destination.
  std::string file = this->APIv1 + "/reply";
  cmSystemTools::MakeDirectory(file);
  file += "/";
  file += fileName;

  // If the final name already exists then assume it has proper content.
  // Otherwise, atomically place the reply file at its final name
  if (cmSystemTools::FileExists(file, true) ||
      !cmSystemTools::RenameFile(tmpFile, file)) {
    cmSystemTools::RemoveFile(tmpFile);
  }

  // Record this among files we have just written.
  this->ReplyFiles.insert(fileName);

  return fileName;
}

Json::Value cmFileAPI::MaybeJsonFile(Json::Value in, std::string const& prefix)
{
  Json::Value out;
  if (in.isObject() || in.isArray()) {
    out = Json::objectValue;
    out["jsonFile"] = this->WriteJsonFile(in, prefix);
  } else {
    out = std::move(in);
  }
  return out;
}

std::string cmFileAPI::ComputeSuffixHash(std::string const& file)
{
  cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
  std::string hash = hasher.HashFile(file);
  hash.resize(20, '0');
  return hash;
}

std::string cmFileAPI::ComputeSuffixTime(std::string const&)
{
  std::chrono::milliseconds ms =
    std::chrono::duration_cast<std::chrono::milliseconds>(
      std::chrono::system_clock::now().time_since_epoch());
  std::chrono::seconds s =
    std::chrono::duration_cast<std::chrono::seconds>(ms);

  std::time_t ts = s.count();
  std::size_t tms = ms.count() % 1000;

  cmTimestamp cmts;
  std::ostringstream ss;
  ss << cmts.CreateTimestampFromTimeT(ts, "%Y-%m-%dT%H-%M-%S", true) << '-'
     << std::setfill('0') << std::setw(4) << tms;
  return ss.str();
}

bool cmFileAPI::ReadQuery(std::string const& query,
                          std::vector<Object>& objects)
{
  // Parse the "<kind>-" syntax.
  std::string::size_type sep_pos = query.find('-');
  if (sep_pos == std::string::npos) {
    return false;
  }
  std::string kindName = query.substr(0, sep_pos);
  std::string verStr = query.substr(sep_pos + 1);
  if (kindName == ObjectKindName(ObjectKind::CodeModel)) {
    Object o;
    o.Kind = ObjectKind::CodeModel;
    if (verStr == "v2") {
      o.Version = 2;
    } else {
      return false;
    }
    objects.push_back(o);
    return true;
  }
  if (kindName == ObjectKindName(ObjectKind::ConfigureLog)) {
    Object o;
    o.Kind = ObjectKind::ConfigureLog;
    if (verStr == "v1") {
      o.Version = 1;
    } else {
      return false;
    }
    objects.push_back(o);
    return true;
  }
  if (kindName == ObjectKindName(ObjectKind::Cache)) {
    Object o;
    o.Kind = ObjectKind::Cache;
    if (verStr == "v2") {
      o.Version = 2;
    } else {
      return false;
    }
    objects.push_back(o);
    return true;
  }
  if (kindName == ObjectKindName(ObjectKind::CMakeFiles)) {
    Object o;
    o.Kind = ObjectKind::CMakeFiles;
    if (verStr == "v1") {
      o.Version = 1;
    } else {
      return false;
    }
    objects.push_back(o);
    return true;
  }
  if (kindName == ObjectKindName(ObjectKind::Toolchains)) {
    Object o;
    o.Kind = ObjectKind::Toolchains;
    if (verStr == "v1") {
      o.Version = 1;
    } else {
      return false;
    }
    objects.push_back(o);
    return true;
  }
  if (kindName == ObjectKindName(ObjectKind::InternalTest)) {
    Object o;
    o.Kind = ObjectKind::InternalTest;
    if (verStr == "v1") {
      o.Version = 1;
    } else if (verStr == "v2") {
      o.Version = 2;
    } else {
      return false;
    }
    objects.push_back(o);
    return true;
  }
  return false;
}

void cmFileAPI::ReadClient(std::string const& client)
{
  // Load queries for the client.
  std::string clientDir = cmStrCat(this->APIv1, "/query/", client);
  std::vector<std::string> queries = this->LoadDir(clientDir);

  // Read the queries and save for later.
  ClientQuery& clientQuery = this->ClientQueries[client];
  for (std::string& query : queries) {
    if (query == "query.json") {
      clientQuery.HaveQueryJson = true;
      this->ReadClientQuery(client, clientQuery.QueryJson);
    } else if (!this->ReadQuery(query, clientQuery.DirQuery.Known)) {
      clientQuery.DirQuery.Unknown.push_back(std::move(query));
    }
  }
}

void cmFileAPI::ReadClientQuery(std::string const& client, ClientQueryJson& q)
{
  // Read the query.json file.
  std::string queryFile =
    cmStrCat(this->APIv1, "/query/", client, "/query.json");
  Json::Value query;
  if (!this->ReadJsonFile(queryFile, query, q.Error)) {
    return;
  }
  if (!query.isObject()) {
    q.Error = "query root is not an object";
    return;
  }

  Json::Value const& clientValue = query["client"];
  if (!clientValue.isNull()) {
    q.ClientValue = clientValue;
  }
  q.RequestsValue = std::move(query["requests"]);
  q.Requests = this->BuildClientRequests(q.RequestsValue);
}

Json::Value cmFileAPI::BuildReplyIndex()
{
  Json::Value index(Json::objectValue);

  // Report information about this version of CMake.
  index["cmake"] = this->BuildCMake();

  // Reply to all queries that we loaded.
  Json::Value& reply = index["reply"] = this->BuildReply(this->TopQuery);
  for (auto const& client : this->ClientQueries) {
    std::string const& clientName = client.first;
    ClientQuery const& clientQuery = client.second;
    reply[clientName] = this->BuildClientReply(clientQuery);
  }

  // Move our index of generated objects into its field.
  Json::Value& objects = index["objects"] = Json::arrayValue;
  for (auto& entry : this->ReplyIndexObjects) {
    objects.append(std::move(entry.second)); // NOLINT(*)
  }

  return index;
}

Json::Value cmFileAPI::BuildCMake()
{
  Json::Value cmake = Json::objectValue;
  cmake["version"] = this->CMakeInstance->ReportVersionJson();
  Json::Value& cmake_paths = cmake["paths"] = Json::objectValue;
  cmake_paths["cmake"] = cmSystemTools::GetCMakeCommand();
  cmake_paths["ctest"] = cmSystemTools::GetCTestCommand();
  cmake_paths["cpack"] = cmSystemTools::GetCPackCommand();
  cmake_paths["root"] = cmSystemTools::GetCMakeRoot();
  cmake["generator"] = this->CMakeInstance->GetGlobalGenerator()->GetJson();
  return cmake;
}

Json::Value cmFileAPI::BuildReply(Query const& q)
{
  Json::Value reply = Json::objectValue;
#ifdef CM_CLANG_SUPPRESS_WARN_RANGE_LOOP_ANALYSIS
#  pragma clang diagnostic push
#  pragma clang diagnostic ignored "-Wrange-loop-analysis"
#endif
  for (Object const o : q.Known) {
#ifdef CM_CLANG_SUPPRESS_WARN_RANGE_LOOP_ANALYSIS
#  pragma clang diagnostic pop
#endif
    std::string const& name = ObjectName(o);
    reply[name] = this->BuildReplyEntry(o);
  }

  for (std::string const& name : q.Unknown) {
    reply[name] = cmFileAPI::BuildReplyError("unknown query file");
  }
  return reply;
}

Json::Value cmFileAPI::BuildReplyEntry(Object object)
{
  if (this->ReplyIndexFor != IndexFor::Success) {
    switch (object.Kind) {
      case ObjectKind::ConfigureLog:
        break;
      case ObjectKind::CodeModel:
      case ObjectKind::Cache:
      case ObjectKind::CMakeFiles:
      case ObjectKind::Toolchains:
      case ObjectKind::InternalTest:
        return this->BuildReplyError("no buildsystem generated");
    }
  }
  return this->AddReplyIndexObject(object);
}

Json::Value cmFileAPI::BuildReplyError(std::string const& error)
{
  Json::Value e = Json::objectValue;
  e["error"] = error;
  return e;
}

Json::Value const& cmFileAPI::AddReplyIndexObject(Object o)
{
  Json::Value& indexEntry = this->ReplyIndexObjects[o];
  if (!indexEntry.isNull()) {
    // The reply object has already been generated.
    return indexEntry;
  }

  // Generate this reply object.
  Json::Value const& object = this->BuildObject(o);
  assert(object.isObject());

  // Populate this index entry.
  indexEntry = Json::objectValue;
  indexEntry["kind"] = object["kind"];
  indexEntry["version"] = object["version"];
  indexEntry["jsonFile"] = this->WriteJsonFile(object, ObjectName(o));
  return indexEntry;
}

char const* cmFileAPI::ObjectKindName(ObjectKind kind)
{
  // Keep in sync with ObjectKind enum.
  static char const* objectKindNames[] = {
    "codemodel",    //
    "configureLog", //
    "cache",        //
    "cmakeFiles",   //
    "toolchains",   //
    "__test"        //
  };
  return objectKindNames[static_cast<size_t>(kind)];
}

std::string cmFileAPI::ObjectName(Object o)
{
  std::string name = cmStrCat(ObjectKindName(o.Kind), "-v", o.Version);
  return name;
}

Json::Value cmFileAPI::BuildVersion(unsigned int major, unsigned int minor)
{
  Json::Value version;
  version["major"] = major;
  version["minor"] = minor;
  return version;
}

Json::Value cmFileAPI::BuildObject(Object object)
{
  Json::Value value;

  switch (object.Kind) {
    case ObjectKind::CodeModel:
      value = this->BuildCodeModel(object);
      break;
    case ObjectKind::ConfigureLog:
      value = this->BuildConfigureLog(object);
      break;
    case ObjectKind::Cache:
      value = this->BuildCache(object);
      break;
    case ObjectKind::CMakeFiles:
      value = this->BuildCMakeFiles(object);
      break;
    case ObjectKind::Toolchains:
      value = this->BuildToolchains(object);
      break;
    case ObjectKind::InternalTest:
      value = this->BuildInternalTest(object);
      break;
  }

  return value;
}

cmFileAPI::ClientRequests cmFileAPI::BuildClientRequests(
  Json::Value const& requests)
{
  ClientRequests result;
  if (requests.isNull()) {
    result.Error = "'requests' member missing";
    return result;
  }
  if (!requests.isArray()) {
    result.Error = "'requests' member is not an array";
    return result;
  }

  result.reserve(requests.size());
  for (Json::Value const& request : requests) {
    result.emplace_back(this->BuildClientRequest(request));
  }

  return result;
}

cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
  Json::Value const& request)
{
  ClientRequest r;

  if (!request.isObject()) {
    r.Error = "request is not an object";
    return r;
  }

  Json::Value const& kind = request["kind"];
  if (kind.isNull()) {
    r.Error = "'kind' member missing";
    return r;
  }
  if (!kind.isString()) {
    r.Error = "'kind' member is not a string";
    return r;
  }
  std::string const& kindName = kind.asString();

  if (kindName == this->ObjectKindName(ObjectKind::CodeModel)) {
    r.Kind = ObjectKind::CodeModel;
  } else if (kindName == this->ObjectKindName(ObjectKind::ConfigureLog)) {
    r.Kind = ObjectKind::ConfigureLog;
  } else if (kindName == this->ObjectKindName(ObjectKind::Cache)) {
    r.Kind = ObjectKind::Cache;
  } else if (kindName == this->ObjectKindName(ObjectKind::CMakeFiles)) {
    r.Kind = ObjectKind::CMakeFiles;
  } else if (kindName == this->ObjectKindName(ObjectKind::Toolchains)) {
    r.Kind = ObjectKind::Toolchains;
  } else if (kindName == this->ObjectKindName(ObjectKind::InternalTest)) {
    r.Kind = ObjectKind::InternalTest;
  } else {
    r.Error = cmStrCat("unknown request kind '", kindName, '\'');
    return r;
  }

  Json::Value const& version = request["version"];
  if (version.isNull()) {
    r.Error = "'version' member missing";
    return r;
  }
  std::vector<RequestVersion> versions;
  if (!cmFileAPI::ReadRequestVersions(version, versions, r.Error)) {
    return r;
  }

  switch (r.Kind) {
    case ObjectKind::CodeModel:
      this->BuildClientRequestCodeModel(r, versions);
      break;
    case ObjectKind::ConfigureLog:
      this->BuildClientRequestConfigureLog(r, versions);
      break;
    case ObjectKind::Cache:
      this->BuildClientRequestCache(r, versions);
      break;
    case ObjectKind::CMakeFiles:
      this->BuildClientRequestCMakeFiles(r, versions);
      break;
    case ObjectKind::Toolchains:
      this->BuildClientRequestToolchains(r, versions);
      break;
    case ObjectKind::InternalTest:
      this->BuildClientRequestInternalTest(r, versions);
      break;
  }

  return r;
}

Json::Value cmFileAPI::BuildClientReply(ClientQuery const& q)
{
  Json::Value reply = this->BuildReply(q.DirQuery);

  if (!q.HaveQueryJson) {
    return reply;
  }

  Json::Value& reply_query_json = reply["query.json"];
  ClientQueryJson const& qj = q.QueryJson;

  if (!qj.Error.empty()) {
    reply_query_json = this->BuildReplyError(qj.Error);
    return reply;
  }

  if (!qj.ClientValue.isNull()) {
    reply_query_json["client"] = qj.ClientValue;
  }

  if (!qj.RequestsValue.isNull()) {
    reply_query_json["requests"] = qj.RequestsValue;
  }

  reply_query_json["responses"] = this->BuildClientReplyResponses(qj.Requests);

  return reply;
}

Json::Value cmFileAPI::BuildClientReplyResponses(
  ClientRequests const& requests)
{
  Json::Value responses;

  if (!requests.Error.empty()) {
    responses = this->BuildReplyError(requests.Error);
    return responses;
  }

  responses = Json::arrayValue;
  for (ClientRequest const& request : requests) {
    responses.append(this->BuildClientReplyResponse(request));
  }

  return responses;
}

Json::Value cmFileAPI::BuildClientReplyResponse(ClientRequest const& request)
{
  Json::Value response;
  if (!request.Error.empty()) {
    response = this->BuildReplyError(request.Error);
    return response;
  }
  response = this->BuildReplyEntry(request);
  return response;
}

bool cmFileAPI::ReadRequestVersions(Json::Value const& version,
                                    std::vector<RequestVersion>& versions,
                                    std::string& error)
{
  if (version.isArray()) {
    for (Json::Value const& v : version) {
      if (!ReadRequestVersion(v, /*inArray=*/true, versions, error)) {
        return false;
      }
    }
  } else {
    if (!ReadRequestVersion(version, /*inArray=*/false, versions, error)) {
      return false;
    }
  }
  return true;
}

bool cmFileAPI::ReadRequestVersion(Json::Value const& version, bool inArray,
                                   std::vector<RequestVersion>& result,
                                   std::string& error)
{
  if (version.isUInt()) {
    RequestVersion v;
    v.Major = version.asUInt();
    result.push_back(v);
    return true;
  }

  if (!version.isObject()) {
    if (inArray) {
      error = "'version' array entry is not a non-negative integer or object";
    } else {
      error =
        "'version' member is not a non-negative integer, object, or array";
    }
    return false;
  }

  Json::Value const& major = version["major"];
  if (major.isNull()) {
    error = "'version' object 'major' member missing";
    return false;
  }
  if (!major.isUInt()) {
    error = "'version' object 'major' member is not a non-negative integer";
    return false;
  }

  RequestVersion v;
  v.Major = major.asUInt();

  Json::Value const& minor = version["minor"];
  if (minor.isUInt()) {
    v.Minor = minor.asUInt();
  } else if (!minor.isNull()) {
    error = "'version' object 'minor' member is not a non-negative integer";
    return false;
  }

  result.push_back(v);

  return true;
}

std::string cmFileAPI::NoSupportedVersion(
  std::vector<RequestVersion> const& versions)
{
  std::ostringstream msg;
  msg << "no supported version specified";
  if (!versions.empty()) {
    msg << " among:";
    for (RequestVersion const& v : versions) {
      msg << " " << v.Major << "." << v.Minor;
    }
  }
  return msg.str();
}

// The "codemodel" object kind.

// Update the following files as well when updating this constant:
//   Help/manual/cmake-file-api.7.rst
//   Tests/RunCMake/FileAPI/codemodel-v2-check.py (check_objects())
static unsigned int const CodeModelV2Minor = 9;

void cmFileAPI::BuildClientRequestCodeModel(
  ClientRequest& r, std::vector<RequestVersion> const& versions)
{
  // Select a known version from those requested.
  for (RequestVersion const& v : versions) {
    if ((v.Major == 2 && v.Minor <= CodeModelV2Minor)) {
      r.Version = v.Major;
      break;
    }
  }
  if (!r.Version) {
    r.Error = NoSupportedVersion(versions);
  }
}

Json::Value cmFileAPI::BuildCodeModel(Object object)
{
  assert(object.Version == 2);
  Json::Value codemodel =
    cmFileAPICodemodelDump(*this, object.Version, CodeModelV2Minor);
  codemodel["kind"] = this->ObjectKindName(object.Kind);

  Json::Value& version = codemodel["version"];
  if (object.Version == 2) {
    version = BuildVersion(2, CodeModelV2Minor);
  } else {
    return codemodel; // should be unreachable
  }

  return codemodel;
}

// The "configureLog" object kind.

// Update Help/manual/cmake-file-api.7.rst when updating this constant.
static unsigned int const ConfigureLogV1Minor = 0;

void cmFileAPI::BuildClientRequestConfigureLog(
  ClientRequest& r, std::vector<RequestVersion> const& versions)
{
  // Select a known version from those requested.
  for (RequestVersion const& v : versions) {
    if ((v.Major == 1 && v.Minor <= ConfigureLogV1Minor)) {
      r.Version = v.Major;
      break;
    }
  }
  if (!r.Version) {
    r.Error = NoSupportedVersion(versions);
  }
}

Json::Value cmFileAPI::BuildConfigureLog(Object object)
{
  Json::Value configureLog = cmFileAPIConfigureLogDump(*this, object.Version);
  configureLog["kind"] = this->ObjectKindName(object.Kind);

  Json::Value& version = configureLog["version"];
  if (object.Version == 1) {
    version = BuildVersion(1, ConfigureLogV1Minor);
  } else {
    return configureLog; // should be unreachable
  }

  return configureLog;
}

// The "cache" object kind.

static unsigned int const CacheV2Minor = 0;

void cmFileAPI::BuildClientRequestCache(
  ClientRequest& r, std::vector<RequestVersion> const& versions)
{
  // Select a known version from those requested.
  for (RequestVersion const& v : versions) {
    if ((v.Major == 2 && v.Minor <= CacheV2Minor)) {
      r.Version = v.Major;
      break;
    }
  }
  if (!r.Version) {
    r.Error = NoSupportedVersion(versions);
  }
}

Json::Value cmFileAPI::BuildCache(Object object)
{
  Json::Value cache = cmFileAPICacheDump(*this, object.Version);
  cache["kind"] = this->ObjectKindName(object.Kind);

  Json::Value& version = cache["version"];
  if (object.Version == 2) {
    version = BuildVersion(2, CacheV2Minor);
  } else {
    return cache; // should be unreachable
  }

  return cache;
}

// The "cmakeFiles" object kind.

static unsigned int const CMakeFilesV1Minor = 1;

void cmFileAPI::BuildClientRequestCMakeFiles(
  ClientRequest& r, std::vector<RequestVersion> const& versions)
{
  // Select a known version from those requested.
  for (RequestVersion const& v : versions) {
    if ((v.Major == 1 && v.Minor <= CMakeFilesV1Minor)) {
      r.Version = v.Major;
      break;
    }
  }
  if (!r.Version) {
    r.Error = NoSupportedVersion(versions);
  }
}

Json::Value cmFileAPI::BuildCMakeFiles(Object object)
{
  Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version);
  cmakeFiles["kind"] = this->ObjectKindName(object.Kind);

  Json::Value& version = cmakeFiles["version"];
  if (object.Version == 1) {
    version = BuildVersion(1, CMakeFilesV1Minor);
  } else {
    return cmakeFiles; // should be unreachable
  }

  return cmakeFiles;
}

// The "toolchains" object kind.

static unsigned int const ToolchainsV1Minor = 1;

void cmFileAPI::BuildClientRequestToolchains(
  ClientRequest& r, std::vector<RequestVersion> const& versions)
{
  // Select a known version from those requested.
  for (RequestVersion const& v : versions) {
    if ((v.Major == 1 && v.Minor <= ToolchainsV1Minor)) {
      r.Version = v.Major;
      break;
    }
  }
  if (!r.Version) {
    r.Error = NoSupportedVersion(versions);
  }
}

Json::Value cmFileAPI::BuildToolchains(Object object)
{
  Json::Value toolchains = cmFileAPIToolchainsDump(*this, object.Version);
  toolchains["kind"] = this->ObjectKindName(object.Kind);

  Json::Value& version = toolchains["version"];
  if (object.Version == 1) {
    version = BuildVersion(1, ToolchainsV1Minor);
  } else {
    return toolchains; // should be unreachable
  }

  return toolchains;
}

// The "__test" object kind is for internal testing of CMake.

static unsigned int const InternalTestV1Minor = 3;
static unsigned int const InternalTestV2Minor = 0;

void cmFileAPI::BuildClientRequestInternalTest(
  ClientRequest& r, std::vector<RequestVersion> const& versions)
{
  // Select a known version from those requested.
  for (RequestVersion const& v : versions) {
    if ((v.Major == 1 && v.Minor <= InternalTestV1Minor) || //
        (v.Major == 2 && v.Minor <= InternalTestV2Minor)) {
      r.Version = v.Major;
      break;
    }
  }
  if (!r.Version) {
    r.Error = NoSupportedVersion(versions);
  }
}

Json::Value cmFileAPI::BuildInternalTest(Object object)
{
  Json::Value test = Json::objectValue;
  test["kind"] = this->ObjectKindName(object.Kind);
  Json::Value& version = test["version"];
  if (object.Version == 2) {
    version = BuildVersion(2, InternalTestV2Minor);
  } else {
    version = BuildVersion(1, InternalTestV1Minor);
  }
  return test;
}

Json::Value cmFileAPI::ReportCapabilities()
{
  Json::Value capabilities = Json::objectValue;
  Json::Value& requests = capabilities["requests"] = Json::arrayValue;

  {
    Json::Value request = Json::objectValue;
    request["kind"] = ObjectKindName(ObjectKind::CodeModel);
    Json::Value& versions = request["version"] = Json::arrayValue;
    versions.append(BuildVersion(2, CodeModelV2Minor));
    requests.append(std::move(request)); // NOLINT(*)
  }

  {
    Json::Value request = Json::objectValue;
    request["kind"] = ObjectKindName(ObjectKind::ConfigureLog);
    Json::Value& versions = request["version"] = Json::arrayValue;
    versions.append(BuildVersion(1, ConfigureLogV1Minor));
    requests.append(std::move(request)); // NOLINT(*)
  }

  {
    Json::Value request = Json::objectValue;
    request["kind"] = ObjectKindName(ObjectKind::Cache);
    Json::Value& versions = request["version"] = Json::arrayValue;
    versions.append(BuildVersion(2, CacheV2Minor));
    requests.append(std::move(request)); // NOLINT(*)
  }

  {
    Json::Value request = Json::objectValue;
    request["kind"] = ObjectKindName(ObjectKind::CMakeFiles);
    Json::Value& versions = request["version"] = Json::arrayValue;
    versions.append(BuildVersion(1, CMakeFilesV1Minor));
    requests.append(std::move(request)); // NOLINT(*)
  }

  {
    Json::Value request = Json::objectValue;
    request["kind"] = ObjectKindName(ObjectKind::Toolchains);
    Json::Value& versions = request["version"] = Json::arrayValue;
    versions.append(BuildVersion(1, ToolchainsV1Minor));
    requests.append(std::move(request)); // NOLINT(*)
  }

  return capabilities;
}

bool cmFileAPI::AddProjectQuery(cmFileAPI::ObjectKind kind,
                                unsigned majorVersion, unsigned minorVersion)
{
  switch (kind) {
    case ObjectKind::CodeModel:
      if (majorVersion != 2 || minorVersion > CodeModelV2Minor) {
        return false;
      }
      break;
    case ObjectKind::Cache:
      if (majorVersion != 2 || minorVersion > CacheV2Minor) {
        return false;
      }
      break;
    case ObjectKind::CMakeFiles:
      if (majorVersion != 1 || minorVersion > CMakeFilesV1Minor) {
        return false;
      }
      break;
    case ObjectKind::Toolchains:
      if (majorVersion != 1 || minorVersion > ToolchainsV1Minor) {
        return false;
      }
      break;
    // These cannot be requested by the project
    case ObjectKind::ConfigureLog:
    case ObjectKind::InternalTest:
      return false;
  }

  Object query;
  query.Kind = kind;
  query.Version = majorVersion;
  if (std::find(this->TopQuery.Known.begin(), this->TopQuery.Known.end(),
                query) == this->TopQuery.Known.end()) {
    this->TopQuery.Known.emplace_back(query);
    this->QueryExists = true;
  }

  return true;
}
