//===-- ValueObjectSyntheticFilter.cpp --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/ValueObjectSyntheticFilter.h"

#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/SharingPtr.h"
#include "lldb/Utility/Status.h"

#include "llvm/ADT/STLExtras.h"

namespace lldb_private {
class Declaration;
}

using namespace lldb_private;

class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
  DummySyntheticFrontEnd(ValueObject &backend)
      : SyntheticChildrenFrontEnd(backend) {}

  size_t CalculateNumChildren() override { return m_backend.GetNumChildren(); }

  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
    return m_backend.GetChildAtIndex(idx, true);
  }

  size_t GetIndexOfChildWithName(ConstString name) override {
    return m_backend.GetIndexOfChildWithName(name);
  }

  bool MightHaveChildren() override { return true; }

  bool Update() override { return false; }
};

ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
                                           lldb::SyntheticChildrenSP filter)
    : ValueObject(parent), m_synth_sp(filter), m_children_byindex(),
      m_name_toindex(), m_synthetic_children_cache(),
      m_synthetic_children_count(UINT32_MAX),
      m_parent_type_name(parent.GetTypeName()),
      m_might_have_children(eLazyBoolCalculate),
      m_provides_value(eLazyBoolCalculate) {
  SetName(parent.GetName());
  CopyValueData(m_parent);
  CreateSynthFilter();
}

ValueObjectSynthetic::~ValueObjectSynthetic() = default;

CompilerType ValueObjectSynthetic::GetCompilerTypeImpl() {
  return m_parent->GetCompilerType();
}

ConstString ValueObjectSynthetic::GetTypeName() {
  return m_parent->GetTypeName();
}

ConstString ValueObjectSynthetic::GetQualifiedTypeName() {
  return m_parent->GetQualifiedTypeName();
}

ConstString ValueObjectSynthetic::GetDisplayTypeName() {
  if (ConstString synth_name = m_synth_filter_up->GetSyntheticTypeName())
    return synth_name;

  return m_parent->GetDisplayTypeName();
}

size_t ValueObjectSynthetic::CalculateNumChildren(uint32_t max) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);

  UpdateValueIfNeeded();
  if (m_synthetic_children_count < UINT32_MAX)
    return m_synthetic_children_count <= max ? m_synthetic_children_count : max;

  if (max < UINT32_MAX) {
    size_t num_children = m_synth_filter_up->CalculateNumChildren(max);
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
              "%s and type %s, the filter returned %zu child values",
              GetName().AsCString(), GetTypeName().AsCString(), num_children);
    return num_children;
  } else {
    size_t num_children = (m_synthetic_children_count =
                               m_synth_filter_up->CalculateNumChildren(max));
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
              "%s and type %s, the filter returned %zu child values",
              GetName().AsCString(), GetTypeName().AsCString(), num_children);
    return num_children;
  }
}

lldb::ValueObjectSP
ValueObjectSynthetic::GetDynamicValue(lldb::DynamicValueType valueType) {
  if (!m_parent)
    return lldb::ValueObjectSP();
  if (IsDynamic() && GetDynamicValueType() == valueType)
    return GetSP();
  return m_parent->GetDynamicValue(valueType);
}

bool ValueObjectSynthetic::MightHaveChildren() {
  if (m_might_have_children == eLazyBoolCalculate)
    m_might_have_children =
        (m_synth_filter_up->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
  return (m_might_have_children != eLazyBoolNo);
}

uint64_t ValueObjectSynthetic::GetByteSize() { return m_parent->GetByteSize(); }

lldb::ValueType ValueObjectSynthetic::GetValueType() const {
  return m_parent->GetValueType();
}

void ValueObjectSynthetic::CreateSynthFilter() {
  ValueObject *valobj_for_frontend = m_parent;
  if (m_synth_sp->WantsDereference())
  {
    CompilerType type = m_parent->GetCompilerType();
    if (type.IsValid() && type.IsPointerOrReferenceType())
    {
      Status error;
      lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
      if (error.Success())
        valobj_for_frontend = deref_sp.get();
    }
  }
  m_synth_filter_up = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
  if (!m_synth_filter_up)
    m_synth_filter_up = std::make_unique<DummySyntheticFrontEnd>(*m_parent);
}

bool ValueObjectSynthetic::UpdateValue() {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);

  SetValueIsValid(false);
  m_error.Clear();

  if (!m_parent->UpdateValueIfNeeded(false)) {
    // our parent could not update.. as we are meaningless without a parent,
    // just stop
    if (m_parent->GetError().Fail())
      m_error = m_parent->GetError();
    return false;
  }

  // regenerate the synthetic filter if our typename changes
  // <rdar://problem/12424824>
  ConstString new_parent_type_name = m_parent->GetTypeName();
  if (new_parent_type_name != m_parent_type_name) {
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::UpdateValue] name=%s, type changed "
              "from %s to %s, recomputing synthetic filter",
              GetName().AsCString(), m_parent_type_name.AsCString(),
              new_parent_type_name.AsCString());
    m_parent_type_name = new_parent_type_name;
    CreateSynthFilter();
  }

  // let our backend do its update
  if (!m_synth_filter_up->Update()) {
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
              "filter said caches are stale - clearing",
              GetName().AsCString());
    // filter said that cached values are stale
    {
      std::lock_guard<std::mutex> guard(m_child_mutex);
      m_children_byindex.clear();
      m_name_toindex.clear();
    }
    // usually, an object's value can change but this does not alter its
    // children count for a synthetic VO that might indeed happen, so we need
    // to tell the upper echelons that they need to come back to us asking for
    // children
    m_children_count_valid = false;
    {
      std::lock_guard<std::mutex> guard(m_child_mutex);
      m_synthetic_children_cache.clear();
    }
    m_synthetic_children_count = UINT32_MAX;
    m_might_have_children = eLazyBoolCalculate;
  } else {
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
              "filter said caches are still valid",
              GetName().AsCString());
  }

  m_provides_value = eLazyBoolCalculate;

  lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue());

  if (synth_val && synth_val->CanProvideValue()) {
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
              "filter said it can provide a value",
              GetName().AsCString());

    m_provides_value = eLazyBoolYes;
    CopyValueData(synth_val.get());
  } else {
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
              "filter said it will not provide a value",
              GetName().AsCString());

    m_provides_value = eLazyBoolNo;
    CopyValueData(m_parent);
  }

  SetValueIsValid(true);
  return true;
}

lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
                                                          bool can_create) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);

  LLDB_LOGF(log,
            "[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving "
            "child at index %zu",
            GetName().AsCString(), idx);

  UpdateValueIfNeeded();

  ValueObject *valobj;
  bool child_is_cached;
  {
    std::lock_guard<std::mutex> guard(m_child_mutex);
    auto cached_child_it = m_children_byindex.find(idx);
    child_is_cached = cached_child_it != m_children_byindex.end();
    if (child_is_cached)
      valobj = cached_child_it->second;
  }

  if (!child_is_cached) {
    if (can_create && m_synth_filter_up != nullptr) {
      LLDB_LOGF(log,
                "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
                "index %zu not cached and will be created",
                GetName().AsCString(), idx);

      lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx);

      LLDB_LOGF(
          log,
          "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index "
          "%zu created as %p (is "
          "synthetic: %s)",
          GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()),
          synth_guy.get()
              ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no")
              : "no");

      if (!synth_guy)
        return synth_guy;

      {
        std::lock_guard<std::mutex> guard(m_child_mutex);
        if (synth_guy->IsSyntheticChildrenGenerated())
          m_synthetic_children_cache.push_back(synth_guy);
        m_children_byindex[idx] = synth_guy.get();
      }
      synth_guy->SetPreferredDisplayLanguageIfNeeded(
          GetPreferredDisplayLanguage());
      return synth_guy;
    } else {
      LLDB_LOGF(log,
                "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
                "index %zu not cached and cannot "
                "be created (can_create = %s, synth_filter = %p)",
                GetName().AsCString(), idx, can_create ? "yes" : "no",
                static_cast<void *>(m_synth_filter_up.get()));

      return lldb::ValueObjectSP();
    }
  } else {
    LLDB_LOGF(log,
              "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
              "index %zu cached as %p",
              GetName().AsCString(), idx, static_cast<void *>(valobj));

    return valobj->GetSP();
  }
}

lldb::ValueObjectSP
ValueObjectSynthetic::GetChildMemberWithName(ConstString name,
                                             bool can_create) {
  UpdateValueIfNeeded();

  uint32_t index = GetIndexOfChildWithName(name);

  if (index == UINT32_MAX)
    return lldb::ValueObjectSP();

  return GetChildAtIndex(index, can_create);
}

size_t ValueObjectSynthetic::GetIndexOfChildWithName(ConstString name) {
  UpdateValueIfNeeded();

  uint32_t found_index = UINT32_MAX;
  bool did_find;
  {
    std::lock_guard<std::mutex> guard(m_child_mutex);
    auto name_to_index = m_name_toindex.find(name.GetCString());
    did_find = name_to_index != m_name_toindex.end();
    if (did_find)
      found_index = name_to_index->second;
  }

  if (!did_find && m_synth_filter_up != nullptr) {
    uint32_t index = m_synth_filter_up->GetIndexOfChildWithName(name);
    if (index == UINT32_MAX)
      return index;
    std::lock_guard<std::mutex> guard(m_child_mutex);
    m_name_toindex[name.GetCString()] = index;
    return index;
  } else if (!did_find && m_synth_filter_up == nullptr)
    return UINT32_MAX;
  else /*if (iter != m_name_toindex.end())*/
    return found_index;
}

bool ValueObjectSynthetic::IsInScope() { return m_parent->IsInScope(); }

lldb::ValueObjectSP ValueObjectSynthetic::GetNonSyntheticValue() {
  return m_parent->GetSP();
}

void ValueObjectSynthetic::CopyValueData(ValueObject *source) {
  m_value = (source->UpdateValueIfNeeded(), source->GetValue());
  ExecutionContext exe_ctx(GetExecutionContextRef());
  m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
}

bool ValueObjectSynthetic::CanProvideValue() {
  if (!UpdateValueIfNeeded())
    return false;
  if (m_provides_value == eLazyBoolYes)
    return true;
  return m_parent->CanProvideValue();
}

bool ValueObjectSynthetic::SetValueFromCString(const char *value_str,
                                               Status &error) {
  return m_parent->SetValueFromCString(value_str, error);
}

void ValueObjectSynthetic::SetFormat(lldb::Format format) {
  if (m_parent) {
    m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
    m_parent->SetFormat(format);
  }
  this->ValueObject::SetFormat(format);
  this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
}

void ValueObjectSynthetic::SetPreferredDisplayLanguage(
    lldb::LanguageType lang) {
  this->ValueObject::SetPreferredDisplayLanguage(lang);
  if (m_parent)
    m_parent->SetPreferredDisplayLanguage(lang);
}

lldb::LanguageType ValueObjectSynthetic::GetPreferredDisplayLanguage() {
  if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
    if (m_parent)
      return m_parent->GetPreferredDisplayLanguage();
    return lldb::eLanguageTypeUnknown;
  } else
    return m_preferred_display_language;
}

bool ValueObjectSynthetic::IsSyntheticChildrenGenerated() {
  if (m_parent)
    return m_parent->IsSyntheticChildrenGenerated();
  return false;
}

void ValueObjectSynthetic::SetSyntheticChildrenGenerated(bool b) {
  if (m_parent)
    m_parent->SetSyntheticChildrenGenerated(b);
  this->ValueObject::SetSyntheticChildrenGenerated(b);
}

bool ValueObjectSynthetic::GetDeclaration(Declaration &decl) {
  if (m_parent)
    return m_parent->GetDeclaration(decl);

  return ValueObject::GetDeclaration(decl);
}

uint64_t ValueObjectSynthetic::GetLanguageFlags() {
  if (m_parent)
    return m_parent->GetLanguageFlags();
  return this->ValueObject::GetLanguageFlags();
}

void ValueObjectSynthetic::SetLanguageFlags(uint64_t flags) {
  if (m_parent)
    m_parent->SetLanguageFlags(flags);
  else
    this->ValueObject::SetLanguageFlags(flags);
}
