//===-- SearchFilter.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/SearchFilter.h"

#include "lldb/Breakpoint/Breakpoint.h" // for Breakpoint
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h" // for ModuleList
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h" // for ConstString
#include "lldb/Utility/Status.h"      // for Status
#include "lldb/Utility/Stream.h"      // for Stream
#include "lldb/lldb-enumerations.h"   // for SymbolContextItem::eSymbolCo...

#include "llvm/ADT/StringRef.h"         // for StringRef
#include "llvm/Support/ErrorHandling.h" // for llvm_unreachable

#include <memory> // for shared_ptr
#include <mutex>  // for recursive_mutex, lock_guard
#include <string> // for string

#include <inttypes.h> // for PRIu64
#include <string.h>   // for size_t, strcmp

namespace lldb_private {
class Address;
}
namespace lldb_private {
class Function;
}

using namespace lldb;
using namespace lldb_private;

const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception",
                                            "Module",        "Modules",
                                            "ModulesAndCU",  "Unknown"};

const char
    *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = {
        "ModuleList", "CUList"};

const char *SearchFilter::FilterTyToName(enum FilterTy type) {
  if (type > LastKnownFilterType)
    return g_ty_to_name[UnknownFilter];

  return g_ty_to_name[type];
}

SearchFilter::FilterTy SearchFilter::NameToFilterTy(llvm::StringRef name) {
  for (size_t i = 0; i <= LastKnownFilterType; i++) {
    if (name == g_ty_to_name[i])
      return (FilterTy)i;
  }
  return UnknownFilter;
}

Searcher::Searcher() = default;

Searcher::~Searcher() = default;

void Searcher::GetDescription(Stream *s) {}

SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType)
    : m_target_sp(target_sp), SubclassID(filterType) {}

SearchFilter::SearchFilter(const SearchFilter &rhs) = default;

SearchFilter &SearchFilter::operator=(const SearchFilter &rhs) = default;

SearchFilter::~SearchFilter() = default;

SearchFilterSP SearchFilter::CreateFromStructuredData(
    Target &target, const StructuredData::Dictionary &filter_dict,
    Status &error) {
  SearchFilterSP result_sp;
  if (!filter_dict.IsValid()) {
    error.SetErrorString("Can't deserialize from an invalid data object.");
    return result_sp;
  }

  llvm::StringRef subclass_name;

  bool success = filter_dict.GetValueForKeyAsString(
      GetSerializationSubclassKey(), subclass_name);
  if (!success) {
    error.SetErrorStringWithFormat("Filter data missing subclass key");
    return result_sp;
  }

  FilterTy filter_type = NameToFilterTy(subclass_name);
  if (filter_type == UnknownFilter) {
    error.SetErrorStringWithFormatv("Unknown filter type: {0}.", subclass_name);
    return result_sp;
  }

  StructuredData::Dictionary *subclass_options = nullptr;
  success = filter_dict.GetValueForKeyAsDictionary(
      GetSerializationSubclassOptionsKey(), subclass_options);
  if (!success || !subclass_options || !subclass_options->IsValid()) {
    error.SetErrorString("Filter data missing subclass options key.");
    return result_sp;
  }

  switch (filter_type) {
  case Unconstrained:
    result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
        target, *subclass_options, error);
    break;
  case ByModule:
    result_sp = SearchFilterByModule::CreateFromStructuredData(
        target, *subclass_options, error);
    break;
  case ByModules:
    result_sp = SearchFilterByModuleList::CreateFromStructuredData(
        target, *subclass_options, error);
    break;
  case ByModulesAndCU:
    result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData(
        target, *subclass_options, error);
    break;
  case Exception:
    error.SetErrorString("Can't serialize exception breakpoints yet.");
    break;
  default:
    llvm_unreachable("Should never get an uresolvable filter type.");
  }

  return result_sp;
}

bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; }

bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; }

bool SearchFilter::AddressPasses(Address &address) { return true; }

bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }

bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; }

uint32_t SearchFilter::GetFilterRequiredItems() {
  return (lldb::SymbolContextItem)0;
}

void SearchFilter::GetDescription(Stream *s) {}

void SearchFilter::Dump(Stream *s) const {}

lldb::SearchFilterSP SearchFilter::CopyForBreakpoint(Breakpoint &breakpoint) {
  SearchFilterSP ret_sp = DoCopyForBreakpoint(breakpoint);
  TargetSP target_sp = breakpoint.GetTargetSP();
  ret_sp->SetTarget(target_sp);
  return ret_sp;
}

//----------------------------------------------------------------------
// Helper functions for serialization.
//----------------------------------------------------------------------

StructuredData::DictionarySP
SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) {
  if (!options_dict_sp || !options_dict_sp->IsValid())
    return StructuredData::DictionarySP();

  auto type_dict_sp = std::make_shared<StructuredData::Dictionary>();
  type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName());
  type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);

  return type_dict_sp;
}

void SearchFilter::SerializeFileSpecList(
    StructuredData::DictionarySP &options_dict_sp, OptionNames name,
    FileSpecList &file_list) {
  size_t num_modules = file_list.GetSize();

  // Don't serialize empty lists.
  if (num_modules == 0)
    return;

  auto module_array_sp = std::make_shared<StructuredData::Array>();
  for (size_t i = 0; i < num_modules; i++) {
    module_array_sp->AddItem(std::make_shared<StructuredData::String>(
        file_list.GetFileSpecAtIndex(i).GetPath()));
  }
  options_dict_sp->AddItem(GetKey(name), module_array_sp);
}

//----------------------------------------------------------------------
// UTILITY Functions to help iterate down through the elements of the
// SymbolContext.
//----------------------------------------------------------------------

void SearchFilter::Search(Searcher &searcher) {
  SymbolContext empty_sc;

  if (!m_target_sp)
    return;
  empty_sc.target_sp = m_target_sp;

  if (searcher.GetDepth() == lldb::eSearchDepthTarget)
    searcher.SearchCallback(*this, empty_sc, nullptr, false);
  else
    DoModuleIteration(empty_sc, searcher);
}

void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
  SymbolContext empty_sc;

  if (!m_target_sp)
    return;
  empty_sc.target_sp = m_target_sp;

  if (searcher.GetDepth() == lldb::eSearchDepthTarget)
    searcher.SearchCallback(*this, empty_sc, nullptr, false);
  else {
    std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
    const size_t numModules = modules.GetSize();

    for (size_t i = 0; i < numModules; i++) {
      ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i));
      if (ModulePasses(module_sp)) {
        if (DoModuleIteration(module_sp, searcher) ==
            Searcher::eCallbackReturnStop)
          return;
      }
    }
  }
}

Searcher::CallbackReturn
SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
                                Searcher &searcher) {
  SymbolContext matchingContext(m_target_sp, module_sp);
  return DoModuleIteration(matchingContext, searcher);
}

Searcher::CallbackReturn
SearchFilter::DoModuleIteration(const SymbolContext &context,
                                Searcher &searcher) {
  if (searcher.GetDepth() >= lldb::eSearchDepthModule) {
    if (context.module_sp) {
      if (searcher.GetDepth() == lldb::eSearchDepthModule) {
        SymbolContext matchingContext(context.module_sp.get());
        searcher.SearchCallback(*this, matchingContext, nullptr, false);
      } else {
        return DoCUIteration(context.module_sp, context, searcher);
      }
    } else {
      const ModuleList &target_images = m_target_sp->GetImages();
      std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());

      size_t n_modules = target_images.GetSize();
      for (size_t i = 0; i < n_modules; i++) {
        // If this is the last level supplied, then call the callback directly,
        // otherwise descend.
        ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i));
        if (!ModulePasses(module_sp))
          continue;

        if (searcher.GetDepth() == lldb::eSearchDepthModule) {
          SymbolContext matchingContext(m_target_sp, module_sp);

          Searcher::CallbackReturn shouldContinue =
              searcher.SearchCallback(*this, matchingContext, nullptr, false);
          if (shouldContinue == Searcher::eCallbackReturnStop ||
              shouldContinue == Searcher::eCallbackReturnPop)
            return shouldContinue;
        } else {
          Searcher::CallbackReturn shouldContinue =
              DoCUIteration(module_sp, context, searcher);
          if (shouldContinue == Searcher::eCallbackReturnStop)
            return shouldContinue;
          else if (shouldContinue == Searcher::eCallbackReturnPop)
            continue;
        }
      }
    }
  }
  return Searcher::eCallbackReturnContinue;
}

Searcher::CallbackReturn
SearchFilter::DoCUIteration(const ModuleSP &module_sp,
                            const SymbolContext &context, Searcher &searcher) {
  Searcher::CallbackReturn shouldContinue;
  if (context.comp_unit == nullptr) {
    const size_t num_comp_units = module_sp->GetNumCompileUnits();
    for (size_t i = 0; i < num_comp_units; i++) {
      CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
      if (cu_sp) {
        if (!CompUnitPasses(*(cu_sp.get())))
          continue;

        if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
          SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());

          shouldContinue =
              searcher.SearchCallback(*this, matchingContext, nullptr, false);

          if (shouldContinue == Searcher::eCallbackReturnPop)
            return Searcher::eCallbackReturnContinue;
          else if (shouldContinue == Searcher::eCallbackReturnStop)
            return shouldContinue;
        } else {
          // FIXME Descend to block.
        }
      }
    }
  } else {
    if (CompUnitPasses(*context.comp_unit)) {
      SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit);
      return searcher.SearchCallback(*this, matchingContext, nullptr, false);
    }
  }
  return Searcher::eCallbackReturnContinue;
}

Searcher::CallbackReturn SearchFilter::DoFunctionIteration(
    Function *function, const SymbolContext &context, Searcher &searcher) {
  // FIXME: Implement...
  return Searcher::eCallbackReturnContinue;
}

//----------------------------------------------------------------------
//  SearchFilterForUnconstrainedSearches:
//  Selects a shared library matching a given file spec, consulting the targets
//  "black list".
//----------------------------------------------------------------------
SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
    Target &target, const StructuredData::Dictionary &data_dict,
    Status &error) {
  // No options for an unconstrained search.
  return std::make_shared<SearchFilterForUnconstrainedSearches>(
      target.shared_from_this());
}

StructuredData::ObjectSP
SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
  // The options dictionary is an empty dictionary:
  auto result_sp = std::make_shared<StructuredData::Dictionary>();
  return WrapOptionsDict(result_sp);
}

bool SearchFilterForUnconstrainedSearches::ModulePasses(
    const FileSpec &module_spec) {
  if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec))
    return false;
  else
    return true;
}

bool SearchFilterForUnconstrainedSearches::ModulePasses(
    const lldb::ModuleSP &module_sp) {
  if (!module_sp)
    return true;
  else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp))
    return false;
  else
    return true;
}

lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint(
    Breakpoint &breakpoint) {
  return std::make_shared<SearchFilterForUnconstrainedSearches>(*this);
}

//----------------------------------------------------------------------
//  SearchFilterByModule:
//  Selects a shared library matching a given file spec
//----------------------------------------------------------------------

SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp,
                                           const FileSpec &module)
    : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {}

SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule &rhs) =
    default;

SearchFilterByModule &SearchFilterByModule::
operator=(const SearchFilterByModule &rhs) {
  m_target_sp = rhs.m_target_sp;
  m_module_spec = rhs.m_module_spec;
  return *this;
}

SearchFilterByModule::~SearchFilterByModule() = default;

bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
  return (module_sp &&
          FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false));
}

bool SearchFilterByModule::ModulePasses(const FileSpec &spec) {
  // Do a full match only if "spec" has a directory
  const bool full_match = (bool)spec.GetDirectory();
  return FileSpec::Equal(spec, m_module_spec, full_match);
}

bool SearchFilterByModule::AddressPasses(Address &address) {
  // FIXME: Not yet implemented
  return true;
}

bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; }

bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) {
  return true;
}

void SearchFilterByModule::Search(Searcher &searcher) {
  if (!m_target_sp)
    return;

  if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
    SymbolContext empty_sc;
    empty_sc.target_sp = m_target_sp;
    searcher.SearchCallback(*this, empty_sc, nullptr, false);
  }

  // If the module file spec is a full path, then we can just find the one
  // filespec that passes.  Otherwise, we need to go through all modules and
  // find the ones that match the file name.

  const ModuleList &target_modules = m_target_sp->GetImages();
  std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());

  const size_t num_modules = target_modules.GetSize();
  for (size_t i = 0; i < num_modules; i++) {
    Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
    const bool full_match = (bool)m_module_spec.GetDirectory();
    if (FileSpec::Equal(m_module_spec, module->GetFileSpec(), full_match)) {
      SymbolContext matchingContext(m_target_sp, module->shared_from_this());
      Searcher::CallbackReturn shouldContinue;

      shouldContinue = DoModuleIteration(matchingContext, searcher);
      if (shouldContinue == Searcher::eCallbackReturnStop)
        return;
    }
  }
}

void SearchFilterByModule::GetDescription(Stream *s) {
  s->PutCString(", module = ");
  s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>"));
}

uint32_t SearchFilterByModule::GetFilterRequiredItems() {
  return eSymbolContextModule;
}

void SearchFilterByModule::Dump(Stream *s) const {}

lldb::SearchFilterSP
SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) {
  return std::make_shared<SearchFilterByModule>(*this);
}

SearchFilterSP SearchFilterByModule::CreateFromStructuredData(
    Target &target, const StructuredData::Dictionary &data_dict,
    Status &error) {
  StructuredData::Array *modules_array;
  bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
                                                 modules_array);
  if (!success) {
    error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
    return nullptr;
  }

  size_t num_modules = modules_array->GetSize();
  if (num_modules > 1) {
    error.SetErrorString(
        "SFBM::CFSD: Only one modules allowed for SearchFilterByModule.");
    return nullptr;
  }

  llvm::StringRef module;
  success = modules_array->GetItemAtIndexAsString(0, module);
  if (!success) {
    error.SetErrorString("SFBM::CFSD: filter module item not a string.");
    return nullptr;
  }
  FileSpec module_spec(module, false);

  return std::make_shared<SearchFilterByModule>(target.shared_from_this(),
                                                module_spec);
}

StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() {
  auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
  auto module_array_sp = std::make_shared<StructuredData::Array>();
  module_array_sp->AddItem(
      std::make_shared<StructuredData::String>(m_module_spec.GetPath()));
  options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp);
  return WrapOptionsDict(options_dict_sp);
}

//----------------------------------------------------------------------
//  SearchFilterByModuleList:
//  Selects a shared library matching a given file spec
//----------------------------------------------------------------------

SearchFilterByModuleList::SearchFilterByModuleList(
    const lldb::TargetSP &target_sp, const FileSpecList &module_list)
    : SearchFilter(target_sp, FilterTy::ByModules),
      m_module_spec_list(module_list) {}

SearchFilterByModuleList::SearchFilterByModuleList(
    const lldb::TargetSP &target_sp, const FileSpecList &module_list,
    enum FilterTy filter_ty)
    : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}

SearchFilterByModuleList::SearchFilterByModuleList(
    const SearchFilterByModuleList &rhs) = default;

SearchFilterByModuleList &SearchFilterByModuleList::
operator=(const SearchFilterByModuleList &rhs) {
  m_target_sp = rhs.m_target_sp;
  m_module_spec_list = rhs.m_module_spec_list;
  return *this;
}

SearchFilterByModuleList::~SearchFilterByModuleList() = default;

bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
  if (m_module_spec_list.GetSize() == 0)
    return true;

  if (module_sp &&
      m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) !=
          UINT32_MAX)
    return true;
  else
    return false;
}

bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) {
  if (m_module_spec_list.GetSize() == 0)
    return true;

  if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX)
    return true;
  else
    return false;
}

bool SearchFilterByModuleList::AddressPasses(Address &address) {
  // FIXME: Not yet implemented
  return true;
}

bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) {
  return true;
}

bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) {
  return true;
}

void SearchFilterByModuleList::Search(Searcher &searcher) {
  if (!m_target_sp)
    return;

  if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
    SymbolContext empty_sc;
    empty_sc.target_sp = m_target_sp;
    searcher.SearchCallback(*this, empty_sc, nullptr, false);
  }

  // If the module file spec is a full path, then we can just find the one
  // filespec that passes.  Otherwise, we need to go through all modules and
  // find the ones that match the file name.

  const ModuleList &target_modules = m_target_sp->GetImages();
  std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());

  const size_t num_modules = target_modules.GetSize();
  for (size_t i = 0; i < num_modules; i++) {
    Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
    if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) !=
        UINT32_MAX) {
      SymbolContext matchingContext(m_target_sp, module->shared_from_this());
      Searcher::CallbackReturn shouldContinue;

      shouldContinue = DoModuleIteration(matchingContext, searcher);
      if (shouldContinue == Searcher::eCallbackReturnStop)
        return;
    }
  }
}

void SearchFilterByModuleList::GetDescription(Stream *s) {
  size_t num_modules = m_module_spec_list.GetSize();
  if (num_modules == 1) {
    s->Printf(", module = ");
    s->PutCString(
        m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
            "<Unknown>"));
  } else {
    s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
    for (size_t i = 0; i < num_modules; i++) {
      s->PutCString(
          m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
              "<Unknown>"));
      if (i != num_modules - 1)
        s->PutCString(", ");
    }
  }
}

uint32_t SearchFilterByModuleList::GetFilterRequiredItems() {
  return eSymbolContextModule;
}

void SearchFilterByModuleList::Dump(Stream *s) const {}

lldb::SearchFilterSP
SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) {
  return std::make_shared<SearchFilterByModuleList>(*this);
}

SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
    Target &target, const StructuredData::Dictionary &data_dict,
    Status &error) {
  StructuredData::Array *modules_array;
  bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
                                                 modules_array);
  FileSpecList modules;
  if (success) {
    size_t num_modules = modules_array->GetSize();
    for (size_t i = 0; i < num_modules; i++) {
      llvm::StringRef module;
      success = modules_array->GetItemAtIndexAsString(i, module);
      if (!success) {
        error.SetErrorStringWithFormat(
            "SFBM::CFSD: filter module item %zu not a string.", i);
        return nullptr;
      }
      modules.Append(FileSpec(module, false));
    }
  }

  return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(),
                                                    modules);
}

void SearchFilterByModuleList::SerializeUnwrapped(
    StructuredData::DictionarySP &options_dict_sp) {
  SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
                        m_module_spec_list);
}

StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() {
  auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
  SerializeUnwrapped(options_dict_sp);
  return WrapOptionsDict(options_dict_sp);
}

//----------------------------------------------------------------------
//  SearchFilterByModuleListAndCU:
//  Selects a shared library matching a given file spec
//----------------------------------------------------------------------

SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
    const lldb::TargetSP &target_sp, const FileSpecList &module_list,
    const FileSpecList &cu_list)
    : SearchFilterByModuleList(target_sp, module_list,
                               FilterTy::ByModulesAndCU),
      m_cu_spec_list(cu_list) {}

SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
    const SearchFilterByModuleListAndCU &rhs) = default;

SearchFilterByModuleListAndCU &SearchFilterByModuleListAndCU::
operator=(const SearchFilterByModuleListAndCU &rhs) {
  if (&rhs != this) {
    m_target_sp = rhs.m_target_sp;
    m_module_spec_list = rhs.m_module_spec_list;
    m_cu_spec_list = rhs.m_cu_spec_list;
  }
  return *this;
}

SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;

lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
    Target &target, const StructuredData::Dictionary &data_dict,
    Status &error) {
  StructuredData::Array *modules_array = nullptr;
  SearchFilterSP result_sp;
  bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
                                                 modules_array);
  FileSpecList modules;
  if (success) {
    size_t num_modules = modules_array->GetSize();
    for (size_t i = 0; i < num_modules; i++) {
      llvm::StringRef module;
      success = modules_array->GetItemAtIndexAsString(i, module);
      if (!success) {
        error.SetErrorStringWithFormat(
            "SFBM::CFSD: filter module item %zu not a string.", i);
        return result_sp;
      }
      modules.Append(FileSpec(module, false));
    }
  }

  StructuredData::Array *cus_array = nullptr;
  success =
      data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array);
  if (!success) {
    error.SetErrorString("SFBM::CFSD: Could not find the CU list key.");
    return result_sp;
  }

  size_t num_cus = cus_array->GetSize();
  FileSpecList cus;
  for (size_t i = 0; i < num_cus; i++) {
    llvm::StringRef cu;
    success = cus_array->GetItemAtIndexAsString(i, cu);
    if (!success) {
      error.SetErrorStringWithFormat(
          "SFBM::CFSD: filter cu item %zu not a string.", i);
      return nullptr;
    }
    cus.Append(FileSpec(cu, false));
  }

  return std::make_shared<SearchFilterByModuleListAndCU>(
      target.shared_from_this(), modules, cus);
}

StructuredData::ObjectSP
SearchFilterByModuleListAndCU::SerializeToStructuredData() {
  auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
  SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp);
  SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list);
  return WrapOptionsDict(options_dict_sp);
}

bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
  return true;
}

bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
  return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX;
}

bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) {
  bool in_cu_list =
      m_cu_spec_list.FindFileIndex(0, compUnit, false) != UINT32_MAX;
  if (in_cu_list) {
    ModuleSP module_sp(compUnit.GetModule());
    if (module_sp) {
      bool module_passes = SearchFilterByModuleList::ModulePasses(module_sp);
      return module_passes;
    } else
      return true;
  } else
    return false;
}

void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
  if (!m_target_sp)
    return;

  if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
    SymbolContext empty_sc;
    empty_sc.target_sp = m_target_sp;
    searcher.SearchCallback(*this, empty_sc, nullptr, false);
  }

  // If the module file spec is a full path, then we can just find the one
  // filespec that passes.  Otherwise, we need to go through all modules and
  // find the ones that match the file name.

  ModuleList matching_modules;
  const ModuleList &target_images = m_target_sp->GetImages();
  std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());

  const size_t num_modules = target_images.GetSize();
  bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
  for (size_t i = 0; i < num_modules; i++) {
    lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i);
    if (no_modules_in_filter ||
        m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) !=
            UINT32_MAX) {
      SymbolContext matchingContext(m_target_sp, module_sp);
      Searcher::CallbackReturn shouldContinue;

      if (searcher.GetDepth() == lldb::eSearchDepthModule) {
        shouldContinue = DoModuleIteration(matchingContext, searcher);
        if (shouldContinue == Searcher::eCallbackReturnStop)
          return;
      } else {
        const size_t num_cu = module_sp->GetNumCompileUnits();
        for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) {
          CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
          matchingContext.comp_unit = cu_sp.get();
          if (matchingContext.comp_unit) {
            if (m_cu_spec_list.FindFileIndex(0, *matchingContext.comp_unit,
                                             false) != UINT32_MAX) {
              shouldContinue =
                  DoCUIteration(module_sp, matchingContext, searcher);
              if (shouldContinue == Searcher::eCallbackReturnStop)
                return;
            }
          }
        }
      }
    }
  }
}

void SearchFilterByModuleListAndCU::GetDescription(Stream *s) {
  size_t num_modules = m_module_spec_list.GetSize();
  if (num_modules == 1) {
    s->Printf(", module = ");
    s->PutCString(
        m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
            "<Unknown>"));
  } else if (num_modules > 0) {
    s->Printf(", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules));
    for (size_t i = 0; i < num_modules; i++) {
      s->PutCString(
          m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
              "<Unknown>"));
      if (i != num_modules - 1)
        s->PutCString(", ");
    }
  }
}

uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() {
  return eSymbolContextModule | eSymbolContextCompUnit;
}

void SearchFilterByModuleListAndCU::Dump(Stream *s) const {}

lldb::SearchFilterSP
SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) {
  return std::make_shared<SearchFilterByModuleListAndCU>(*this);
}
