/* 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 "cmGlobalGenerator.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 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 cmp0118 = makefile->GetPolicyStatus(cmPolicies::CMP0118);
  bool const cmp0118new =
    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
    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);
          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 (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);
}

template <typename ValueType>
void cmSourceFile::StoreProperty(const std::string& prop, ValueType 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::SetProperty(const std::string& prop, const char* value)
{
  this->StoreProperty(prop, value);
}
void cmSourceFile::SetProperty(const std::string& prop, cmValue value)
{
  this->StoreProperty(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 CMP0118 in order to determine if we need to
    // possibly consider the value of a locally set GENERATED property, too.
    auto policyStatus =
      this->Location.GetMakefile()->GetPolicyStatus(cmPolicies::CMP0118);
    if (this->GetIsGenerated(
          (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)
            ? 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 = cmJoin(this->IncludeDirectories, ";");
    return cmValue(output);
  }

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

    static std::string output;
    output = cmJoin(this->CompileOptions, ";");
    return cmValue(output);
  }

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

    static std::string output;
    output = cmJoin(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 cmIsOn(this->GetProperty(prop));
}

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);
}
