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

#include <utility>

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

#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmake.h"

cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name,
                           bool generated, cmSourceFileLocationKind kind)
  : Location(mf, name, (!generated) ? kind : cmSourceFileLocationKind::Known)
{
  if (generated) {
    this->MarkAsGenerated();
  }
}

std::string const& cmSourceFile::GetExtension() const
{
  return this->Extension;
}

const std::string propTRUE = "1";
const std::string propFALSE = "0";
const std::string cmSourceFile::propLANGUAGE = "LANGUAGE";
const std::string cmSourceFile::propLOCATION = "LOCATION";
const std::string cmSourceFile::propGENERATED = "GENERATED";
const std::string cmSourceFile::propCOMPILE_DEFINITIONS =
  "COMPILE_DEFINITIONS";
const std::string cmSourceFile::propCOMPILE_OPTIONS = "COMPILE_OPTIONS";
const std::string cmSourceFile::propINCLUDE_DIRECTORIES =
  "INCLUDE_DIRECTORIES";

void cmSourceFile::SetObjectLibrary(std::string const& objlib)
{
  this->ObjectLibrary = objlib;
}

std::string cmSourceFile::GetObjectLibrary() const
{
  return this->ObjectLibrary;
}

std::string const& cmSourceFile::GetOrDetermineLanguage()
{
  // If the language was set explicitly by the user then use it.
  if (cmValue lang = this->GetProperty(propLANGUAGE)) {
    // Assign to member in order to return a reference.
    this->Language = *lang;
    return this->Language;
  }

  // Perform computation needed to get the language if necessary.
  if (this->Language.empty()) {
    // If a known extension is given or a known full path is given then trust
    // that the current extension is sufficient to determine the language. This
    // will fail only if the user specifies a full path to the source but
    // leaves off the extension, which is kind of weird.
    if (this->FullPath.empty() && this->Location.ExtensionIsAmbiguous() &&
        this->Location.DirectoryIsAmbiguous()) {
      // Finalize the file location to get the extension and set the language.
      this->ResolveFullPath();
    } else {
      // Use the known extension to get the language if possible.
      std::string ext =
        cmSystemTools::GetFilenameLastExtension(this->Location.GetName());
      this->CheckLanguage(ext);
    }
  }

  // Use the language determined from the file extension.
  return this->Language;
}

std::string cmSourceFile::GetLanguage() const
{
  // If the language was set explicitly by the user then use it.
  if (cmValue lang = this->GetProperty(propLANGUAGE)) {
    return *lang;
  }

  // Use the language determined from the file extension.
  return this->Language;
}

cmSourceFileLocation const& cmSourceFile::GetLocation() const
{
  return this->Location;
}

std::string const& cmSourceFile::ResolveFullPath(std::string* error,
                                                 std::string* cmp0115Warning)
{
  if (this->FullPath.empty()) {
    if (this->FindFullPath(error, cmp0115Warning)) {
      this->CheckExtension();
    }
  }
  return this->FullPath;
}

std::string const& cmSourceFile::GetFullPath() const
{
  return this->FullPath;
}

bool cmSourceFile::FindFullPath(std::string* error,
                                std::string* cmp0115Warning)
{
  // If the file is generated compute the location without checking on disk.
  // Note: We also check for a locally set GENERATED property, because
  //       it might have been set before policy CMP0118 (or CMP0163) was set
  //       to NEW.
  if (this->GetIsGenerated(CheckScope::GlobalAndLocal)) {
    // The file is either already a full path or is relative to the
    // build directory for the target.
    this->Location.DirectoryUseBinary();
    this->FullPath = this->Location.GetFullPath();
    this->FindFullPathFailed = false;
    return true;
  }

  // If this method has already failed once do not try again.
  if (this->FindFullPathFailed) {
    return false;
  }

  // The file is not generated.  It must exist on disk.
  cmMakefile const* makefile = this->Location.GetMakefile();
  // Location path
  std::string const& lPath = this->Location.GetFullPath();
  // List of extension lists
  std::vector<std::string> exts =
    makefile->GetCMakeInstance()->GetAllExtensions();
  auto cmp0115 = makefile->GetPolicyStatus(cmPolicies::CMP0115);
  auto cmp0163 = makefile->GetPolicyStatus(cmPolicies::CMP0163);
  auto cmp0118 = makefile->GetPolicyStatus(cmPolicies::CMP0118);
  bool const cmp0163new =
    cmp0163 != cmPolicies::OLD && cmp0163 != cmPolicies::WARN;
  bool const cmp0118new =
    cmp0163new || (cmp0118 != cmPolicies::OLD && cmp0118 != cmPolicies::WARN);

  // Tries to find the file in a given directory
  auto findInDir = [this, &exts, &lPath, cmp0115, cmp0115Warning, cmp0118new,
                    makefile](std::string const& dir) -> bool {
    // Compute full path
    std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir);
    // Try full path
    // Is this file globally marked as generated? Then mark so locally.
    if (cmp0118new &&
        makefile->GetGlobalGenerator()->IsGeneratedFile(fullPath)) {
      this->IsGenerated = true;
    }
    if (this->IsGenerated || cmSystemTools::FileExists(fullPath)) {
      this->FullPath = fullPath;
      return true;
    }
    // This has to be an if statement due to a bug in Oracle Developer Studio.
    // See https://community.oracle.com/tech/developers/discussion/4476246/
    // for details.
    if (cmp0115 == cmPolicies::OLD || cmp0115 == cmPolicies::WARN) {
      // Try full path with extension
      for (std::string const& ext : exts) {
        if (!ext.empty()) {
          std::string extPath = cmStrCat(fullPath, '.', ext);
          // Is this file globally marked as generated? Then mark so locally.
          if (cmp0118new &&
              makefile->GetGlobalGenerator()->IsGeneratedFile(extPath)) {
            this->IsGenerated = true;
          }
          if (this->IsGenerated || cmSystemTools::FileExists(extPath)) {
            this->FullPath = extPath;
            if (cmp0115 == cmPolicies::WARN) {
              std::string warning =
                cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0115),
                         "\nFile:\n  ", extPath);
              if (cmp0115Warning) {
                *cmp0115Warning = std::move(warning);
              } else {
                makefile->GetCMakeInstance()->IssueMessage(
                  MessageType::AUTHOR_WARNING, warning);
              }
            }
            return true;
          }
        }
      }
    }
    // File not found
    return false;
  };

  // Try to find the file in various directories
  if (this->Location.DirectoryIsAmbiguous()) {
    if (findInDir(makefile->GetCurrentSourceDirectory()) ||
        findInDir(makefile->GetCurrentBinaryDirectory())) {
      return true;
    }
  } else {
    if (findInDir({})) {
      return true;
    }
  }

  // Compose error
  std::string err = cmStrCat("Cannot find source file:\n  ", lPath);
  switch (cmp0115) {
    case cmPolicies::OLD:
    case cmPolicies::WARN:
      err = cmStrCat(err, "\nTried extensions");
      for (auto const& ext : exts) {
        err = cmStrCat(err, " .", ext);
      }
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
    case cmPolicies::NEW:
      break;
  }
  if (lPath == "FILE_SET"_s) {
    err += "\nHint: the FILE_SET keyword may only appear after a visibility "
           "specifier or another FILE_SET within the target_sources() "
           "command.";
  }
  if (error != nullptr) {
    *error = std::move(err);
  } else {
    makefile->IssueMessage(MessageType::FATAL_ERROR, err);
  }
  this->FindFullPathFailed = true;

  // File not found
  return false;
}

void cmSourceFile::CheckExtension()
{
  // Compute the extension.
  std::string realExt =
    cmSystemTools::GetFilenameLastExtension(this->FullPath);
  if (!realExt.empty()) {
    // Store the extension without the leading '.'.
    this->Extension = realExt.substr(1);
  }

  // Look for object files.
  if (this->Extension == "obj" || this->Extension == "o" ||
      this->Extension == "lo") {
    this->SetProperty("EXTERNAL_OBJECT", "1");
  }

  // Try to identify the source file language from the extension.
  if (this->Language.empty()) {
    this->CheckLanguage(this->Extension);
  }
}

void cmSourceFile::CheckLanguage(std::string const& ext)
{
  // Try to identify the source file language from the extension.
  cmMakefile const* mf = this->Location.GetMakefile();
  cmGlobalGenerator* gg = mf->GetGlobalGenerator();
  std::string l = gg->GetLanguageFromExtension(ext.c_str());
  if (!l.empty()) {
    this->Language = l;
  }
}

bool cmSourceFile::Matches(cmSourceFileLocation const& loc)
{
  return this->Location.Matches(loc);
}

void cmSourceFile::SetProperty(const std::string& prop, cmValue value)
{
  if (prop == propINCLUDE_DIRECTORIES) {
    this->IncludeDirectories.clear();
    if (value) {
      cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
      this->IncludeDirectories.emplace_back(value, lfbt);
    }
  } else if (prop == propCOMPILE_OPTIONS) {
    this->CompileOptions.clear();
    if (value) {
      cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
      this->CompileOptions.emplace_back(value, lfbt);
    }
  } else if (prop == propCOMPILE_DEFINITIONS) {
    this->CompileDefinitions.clear();
    if (value) {
      cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
      this->CompileDefinitions.emplace_back(value, lfbt);
    }
  } else {
    this->Properties.SetProperty(prop, value);
  }
}

void cmSourceFile::AppendProperty(const std::string& prop,
                                  const std::string& value, bool asString)
{
  if (prop == propINCLUDE_DIRECTORIES) {
    if (!value.empty()) {
      cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
      this->IncludeDirectories.emplace_back(value, lfbt);
    }
  } else if (prop == propCOMPILE_OPTIONS) {
    if (!value.empty()) {
      cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
      this->CompileOptions.emplace_back(value, lfbt);
    }
  } else if (prop == propCOMPILE_DEFINITIONS) {
    if (!value.empty()) {
      cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
      this->CompileDefinitions.emplace_back(value, lfbt);
    }
  } else {
    this->Properties.AppendProperty(prop, value, asString);
  }
}

cmValue cmSourceFile::GetPropertyForUser(const std::string& prop)
{
  // This method is a consequence of design history and backwards
  // compatibility.  GetProperty is (and should be) a const method.
  // Computed properties should not be stored back in the property map
  // but instead reference information already known.  If they need to
  // cache information in a mutable ivar to provide the return string
  // safely then so be it.
  //
  // The LOCATION property is particularly problematic.  The CMake
  // language has very loose restrictions on the names that will match
  // a given source file (for historical reasons).  Implementing
  // lookups correctly with such loose naming requires the
  // cmSourceFileLocation class to commit to a particular full path to
  // the source file as late as possible.  If the users requests the
  // LOCATION property we must commit now.
  if (prop == propLOCATION) {
    // Commit to a location.
    this->ResolveFullPath();
  }

  // Similarly, LANGUAGE can be determined by the file extension
  // if it is requested by the user.
  if (prop == propLANGUAGE) {
    // The pointer is valid until `this->Language` is modified.
    return cmValue(this->GetOrDetermineLanguage());
  }

  // Special handling for GENERATED property.
  if (prop == propGENERATED) {
    // We need to check policy CMP0163 and CMP0118 in order to determine if we
    // need to possibly consider the value of a locally set GENERATED property,
    // too.
    auto cmp0163 =
      this->Location.GetMakefile()->GetPolicyStatus(cmPolicies::CMP0163);
    auto cmp0118 =
      this->Location.GetMakefile()->GetPolicyStatus(cmPolicies::CMP0118);
    bool const cmp0163new =
      cmp0163 != cmPolicies::OLD && cmp0163 != cmPolicies::WARN;
    bool const cmp0118new = cmp0163new ||
      (cmp0118 != cmPolicies::OLD && cmp0118 != cmPolicies::WARN);
    if (this->GetIsGenerated((!cmp0118new) ? CheckScope::GlobalAndLocal
                                           : CheckScope::Global)) {
      return cmValue(propTRUE);
    }
    return cmValue(propFALSE);
  }

  // Perform the normal property lookup.
  return this->GetProperty(prop);
}

cmValue cmSourceFile::GetProperty(const std::string& prop) const
{
  // Check for computed properties.
  if (prop == propLOCATION) {
    if (this->FullPath.empty()) {
      return nullptr;
    }
    return cmValue(this->FullPath);
  }

  // Check for the properties with backtraces.
  if (prop == propINCLUDE_DIRECTORIES) {
    if (this->IncludeDirectories.empty()) {
      return nullptr;
    }

    static std::string output;
    output = cmList::to_string(this->IncludeDirectories);
    return cmValue(output);
  }

  if (prop == propCOMPILE_OPTIONS) {
    if (this->CompileOptions.empty()) {
      return nullptr;
    }

    static std::string output;
    output = cmList::to_string(this->CompileOptions);
    return cmValue(output);
  }

  if (prop == propCOMPILE_DEFINITIONS) {
    if (this->CompileDefinitions.empty()) {
      return nullptr;
    }

    static std::string output;
    output = cmList::to_string(this->CompileDefinitions);
    return cmValue(output);
  }

  cmValue retVal = this->Properties.GetPropertyValue(prop);
  if (!retVal) {
    cmMakefile const* mf = this->Location.GetMakefile();
    const bool chain =
      mf->GetState()->IsPropertyChained(prop, cmProperty::SOURCE_FILE);
    if (chain) {
      return mf->GetProperty(prop, chain);
    }
    return nullptr;
  }

  return retVal;
}

const std::string& cmSourceFile::GetSafeProperty(const std::string& prop) const
{
  cmValue ret = this->GetProperty(prop);
  if (ret) {
    return *ret;
  }

  static std::string const s_empty;
  return s_empty;
}

bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const
{
  return this->GetProperty(prop).IsOn();
}

void cmSourceFile::MarkAsGenerated()
{
  this->IsGenerated = true;
  const auto& mf = *this->Location.GetMakefile();
  mf.GetGlobalGenerator()->MarkAsGeneratedFile(this->ResolveFullPath());
}

bool cmSourceFile::GetIsGenerated(CheckScope checkScope) const
{
  if (this->IsGenerated) {
    // Globally marked as generated!
    return true;
  }
  if (checkScope == CheckScope::GlobalAndLocal) {
    // Check locally stored properties.
    return this->GetPropertyAsBool(propGENERATED);
  }
  return false;
}

void cmSourceFile::SetProperties(cmPropertyMap properties)
{
  this->Properties = std::move(properties);
}

cmCustomCommand* cmSourceFile::GetCustomCommand() const
{
  return this->CustomCommand.get();
}

void cmSourceFile::SetCustomCommand(std::unique_ptr<cmCustomCommand> cc)
{
  this->CustomCommand = std::move(cc);
}
