//===-- CommandCompletions.cpp --------------------------------------------===//
//
// 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 "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSet.h"

#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/FileSpecList.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/TildeExpressionResolver.h"

#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

using namespace lldb_private;

// This is the command completion callback that is used to complete the
// argument of the option it is bound to (in the OptionDefinition table
// below).
typedef void (*CompletionCallback)(CommandInterpreter &interpreter,
                                   CompletionRequest &request,
                                   // A search filter to limit the search...
                                   lldb_private::SearchFilter *searcher);

struct CommonCompletionElement {
  uint64_t type;
  CompletionCallback callback;
};

bool CommandCompletions::InvokeCommonCompletionCallbacks(
    CommandInterpreter &interpreter, uint32_t completion_mask,
    CompletionRequest &request, SearchFilter *searcher) {
  bool handled = false;

  const CommonCompletionElement common_completions[] = {
      {lldb::eNoCompletion, nullptr},
      {lldb::eSourceFileCompletion, CommandCompletions::SourceFiles},
      {lldb::eDiskFileCompletion, CommandCompletions::DiskFiles},
      {lldb::eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
      {lldb::eSymbolCompletion, CommandCompletions::Symbols},
      {lldb::eModuleCompletion, CommandCompletions::Modules},
      {lldb::eModuleUUIDCompletion, CommandCompletions::ModuleUUIDs},
      {lldb::eSettingsNameCompletion, CommandCompletions::SettingsNames},
      {lldb::ePlatformPluginCompletion,
       CommandCompletions::PlatformPluginNames},
      {lldb::eArchitectureCompletion, CommandCompletions::ArchitectureNames},
      {lldb::eVariablePathCompletion, CommandCompletions::VariablePath},
      {lldb::eRegisterCompletion, CommandCompletions::Registers},
      {lldb::eBreakpointCompletion, CommandCompletions::Breakpoints},
      {lldb::eProcessPluginCompletion, CommandCompletions::ProcessPluginNames},
      {lldb::eDisassemblyFlavorCompletion,
       CommandCompletions::DisassemblyFlavors},
      {lldb::eTypeLanguageCompletion, CommandCompletions::TypeLanguages},
      {lldb::eFrameIndexCompletion, CommandCompletions::FrameIndexes},
      {lldb::eStopHookIDCompletion, CommandCompletions::StopHookIDs},
      {lldb::eThreadIndexCompletion, CommandCompletions::ThreadIndexes},
      {lldb::eWatchpointIDCompletion, CommandCompletions::WatchPointIDs},
      {lldb::eBreakpointNameCompletion, CommandCompletions::BreakpointNames},
      {lldb::eProcessIDCompletion, CommandCompletions::ProcessIDs},
      {lldb::eProcessNameCompletion, CommandCompletions::ProcessNames},
      {lldb::eRemoteDiskFileCompletion, CommandCompletions::RemoteDiskFiles},
      {lldb::eRemoteDiskDirectoryCompletion,
       CommandCompletions::RemoteDiskDirectories},
      {lldb::eTypeCategoryNameCompletion,
       CommandCompletions::TypeCategoryNames},
      {lldb::eThreadIDCompletion, CommandCompletions::ThreadIDs},
      {lldb::eTerminatorCompletion,
       nullptr} // This one has to be last in the list.
  };

  for (int i = 0;; i++) {
    if (common_completions[i].type == lldb::eTerminatorCompletion)
      break;
    else if ((common_completions[i].type & completion_mask) ==
                 common_completions[i].type &&
             common_completions[i].callback != nullptr) {
      handled = true;
      common_completions[i].callback(interpreter, request, searcher);
    }
  }
  return handled;
}

namespace {
// The Completer class is a convenient base class for building searchers that
// go along with the SearchFilter passed to the standard Completer functions.
class Completer : public Searcher {
public:
  Completer(CommandInterpreter &interpreter, CompletionRequest &request)
      : m_interpreter(interpreter), m_request(request) {}

  ~Completer() override = default;

  CallbackReturn SearchCallback(SearchFilter &filter, SymbolContext &context,
                                Address *addr) override = 0;

  lldb::SearchDepth GetDepth() override = 0;

  virtual void DoCompletion(SearchFilter *filter) = 0;

protected:
  CommandInterpreter &m_interpreter;
  CompletionRequest &m_request;

private:
  Completer(const Completer &) = delete;
  const Completer &operator=(const Completer &) = delete;
};
} // namespace

// SourceFileCompleter implements the source file completer
namespace {
class SourceFileCompleter : public Completer {
public:
  SourceFileCompleter(CommandInterpreter &interpreter,
                      CompletionRequest &request)
      : Completer(interpreter, request) {
    FileSpec partial_spec(m_request.GetCursorArgumentPrefix());
    m_file_name = partial_spec.GetFilename().GetCString();
    m_dir_name = partial_spec.GetDirectory().GetCString();
  }

  lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthCompUnit; }

  Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
                                          SymbolContext &context,
                                          Address *addr) override {
    if (context.comp_unit != nullptr) {
      const char *cur_file_name =
          context.comp_unit->GetPrimaryFile().GetFilename().GetCString();
      const char *cur_dir_name =
          context.comp_unit->GetPrimaryFile().GetDirectory().GetCString();

      bool match = false;
      if (m_file_name && cur_file_name &&
          strstr(cur_file_name, m_file_name) == cur_file_name)
        match = true;

      if (match && m_dir_name && cur_dir_name &&
          strstr(cur_dir_name, m_dir_name) != cur_dir_name)
        match = false;

      if (match) {
        m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile());
      }
    }
    return Searcher::eCallbackReturnContinue;
  }

  void DoCompletion(SearchFilter *filter) override {
    filter->Search(*this);
    // Now convert the filelist to completions:
    for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
      m_request.AddCompletion(
          m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
    }
  }

private:
  FileSpecList m_matching_files;
  const char *m_file_name;
  const char *m_dir_name;

  SourceFileCompleter(const SourceFileCompleter &) = delete;
  const SourceFileCompleter &operator=(const SourceFileCompleter &) = delete;
};
} // namespace

static bool regex_chars(const char comp) {
  return llvm::StringRef("[](){}+.*|^$\\?").contains(comp);
}

namespace {
class SymbolCompleter : public Completer {

public:
  SymbolCompleter(CommandInterpreter &interpreter, CompletionRequest &request)
      : Completer(interpreter, request) {
    std::string regex_str;
    if (!m_request.GetCursorArgumentPrefix().empty()) {
      regex_str.append("^");
      regex_str.append(std::string(m_request.GetCursorArgumentPrefix()));
    } else {
      // Match anything since the completion string is empty
      regex_str.append(".");
    }
    std::string::iterator pos =
        find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
    while (pos < regex_str.end()) {
      pos = regex_str.insert(pos, '\\');
      pos = find_if(pos + 2, regex_str.end(), regex_chars);
    }
    m_regex = RegularExpression(regex_str);
  }

  lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }

  Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
                                          SymbolContext &context,
                                          Address *addr) override {
    if (context.module_sp) {
      SymbolContextList sc_list;
      ModuleFunctionSearchOptions function_options;
      function_options.include_symbols = true;
      function_options.include_inlines = true;
      context.module_sp->FindFunctions(m_regex, function_options, sc_list);

      // Now add the functions & symbols to the list - only add if unique:
      for (const SymbolContext &sc : sc_list) {
        ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
        // Ensure that the function name matches the regex. This is more than
        // a sanity check. It is possible that the demangled function name
        // does not start with the prefix, for example when it's in an
        // anonymous namespace.
        if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef()))
          m_match_set.insert(func_name);
      }
    }
    return Searcher::eCallbackReturnContinue;
  }

  void DoCompletion(SearchFilter *filter) override {
    filter->Search(*this);
    collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
    for (pos = m_match_set.begin(); pos != end; pos++)
      m_request.AddCompletion((*pos).GetCString());
  }

private:
  RegularExpression m_regex;
  typedef std::set<ConstString> collection;
  collection m_match_set;

  SymbolCompleter(const SymbolCompleter &) = delete;
  const SymbolCompleter &operator=(const SymbolCompleter &) = delete;
};
} // namespace

namespace {
class ModuleCompleter : public Completer {
public:
  ModuleCompleter(CommandInterpreter &interpreter, CompletionRequest &request)
      : Completer(interpreter, request) {
    FileSpec partial_spec(m_request.GetCursorArgumentPrefix());
    m_file_name = partial_spec.GetFilename().GetCString();
    m_dir_name = partial_spec.GetDirectory().GetCString();
  }

  lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }

  Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
                                          SymbolContext &context,
                                          Address *addr) override {
    if (context.module_sp) {
      const char *cur_file_name =
          context.module_sp->GetFileSpec().GetFilename().GetCString();
      const char *cur_dir_name =
          context.module_sp->GetFileSpec().GetDirectory().GetCString();

      bool match = false;
      if (m_file_name && cur_file_name &&
          strstr(cur_file_name, m_file_name) == cur_file_name)
        match = true;

      if (match && m_dir_name && cur_dir_name &&
          strstr(cur_dir_name, m_dir_name) != cur_dir_name)
        match = false;

      if (match) {
        m_request.AddCompletion(cur_file_name);
      }
    }
    return Searcher::eCallbackReturnContinue;
  }

  void DoCompletion(SearchFilter *filter) override { filter->Search(*this); }

private:
  const char *m_file_name;
  const char *m_dir_name;

  ModuleCompleter(const ModuleCompleter &) = delete;
  const ModuleCompleter &operator=(const ModuleCompleter &) = delete;
};
} // namespace

void CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
                                     CompletionRequest &request,
                                     SearchFilter *searcher) {
  SourceFileCompleter completer(interpreter, request);

  if (searcher == nullptr) {
    lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
    SearchFilterForUnconstrainedSearches null_searcher(target_sp);
    completer.DoCompletion(&null_searcher);
  } else {
    completer.DoCompletion(searcher);
  }
}

static void DiskFilesOrDirectories(const llvm::Twine &partial_name,
                                   bool only_directories,
                                   CompletionRequest &request,
                                   TildeExpressionResolver &Resolver) {
  llvm::SmallString<256> CompletionBuffer;
  llvm::SmallString<256> Storage;
  partial_name.toVector(CompletionBuffer);

  if (CompletionBuffer.size() >= PATH_MAX)
    return;

  namespace path = llvm::sys::path;

  llvm::StringRef SearchDir;
  llvm::StringRef PartialItem;

  if (CompletionBuffer.starts_with("~")) {
    llvm::StringRef Buffer = CompletionBuffer;
    size_t FirstSep =
        Buffer.find_if([](char c) { return path::is_separator(c); });

    llvm::StringRef Username = Buffer.take_front(FirstSep);
    llvm::StringRef Remainder;
    if (FirstSep != llvm::StringRef::npos)
      Remainder = Buffer.drop_front(FirstSep + 1);

    llvm::SmallString<256> Resolved;
    if (!Resolver.ResolveExact(Username, Resolved)) {
      // We couldn't resolve it as a full username.  If there were no slashes
      // then this might be a partial username.   We try to resolve it as such
      // but after that, we're done regardless of any matches.
      if (FirstSep == llvm::StringRef::npos) {
        llvm::StringSet<> MatchSet;
        Resolver.ResolvePartial(Username, MatchSet);
        for (const auto &S : MatchSet) {
          Resolved = S.getKey();
          path::append(Resolved, path::get_separator());
          request.AddCompletion(Resolved, "", CompletionMode::Partial);
        }
      }
      return;
    }

    // If there was no trailing slash, then we're done as soon as we resolve
    // the expression to the correct directory.  Otherwise we need to continue
    // looking for matches within that directory.
    if (FirstSep == llvm::StringRef::npos) {
      // Make sure it ends with a separator.
      path::append(CompletionBuffer, path::get_separator());
      request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial);
      return;
    }

    // We want to keep the form the user typed, so we special case this to
    // search in the fully resolved directory, but CompletionBuffer keeps the
    // unmodified form that the user typed.
    Storage = Resolved;
    llvm::StringRef RemainderDir = path::parent_path(Remainder);
    if (!RemainderDir.empty()) {
      // Append the remaining path to the resolved directory.
      Storage.append(path::get_separator());
      Storage.append(RemainderDir);
    }
    SearchDir = Storage;
  } else if (CompletionBuffer == path::root_directory(CompletionBuffer)) {
    SearchDir = CompletionBuffer;
  } else {
    SearchDir = path::parent_path(CompletionBuffer);
  }

  size_t FullPrefixLen = CompletionBuffer.size();

  PartialItem = path::filename(CompletionBuffer);

  // path::filename() will return "." when the passed path ends with a
  // directory separator or the separator when passed the disk root directory.
  // We have to filter those out, but only when the "." doesn't come from the
  // completion request itself.
  if ((PartialItem == "." || PartialItem == path::get_separator()) &&
      path::is_separator(CompletionBuffer.back()))
    PartialItem = llvm::StringRef();

  if (SearchDir.empty()) {
    llvm::sys::fs::current_path(Storage);
    SearchDir = Storage;
  }
  assert(!PartialItem.contains(path::get_separator()));

  // SearchDir now contains the directory to search in, and Prefix contains the
  // text we want to match against items in that directory.

  FileSystem &fs = FileSystem::Instance();
  std::error_code EC;
  llvm::vfs::directory_iterator Iter = fs.DirBegin(SearchDir, EC);
  llvm::vfs::directory_iterator End;
  for (; Iter != End && !EC; Iter.increment(EC)) {
    auto &Entry = *Iter;
    llvm::ErrorOr<llvm::vfs::Status> Status = fs.GetStatus(Entry.path());

    if (!Status)
      continue;

    auto Name = path::filename(Entry.path());

    // Omit ".", ".."
    if (Name == "." || Name == ".." || !Name.starts_with(PartialItem))
      continue;

    bool is_dir = Status->isDirectory();

    // If it's a symlink, then we treat it as a directory as long as the target
    // is a directory.
    if (Status->isSymlink()) {
      FileSpec symlink_filespec(Entry.path());
      FileSpec resolved_filespec;
      auto error = fs.ResolveSymbolicLink(symlink_filespec, resolved_filespec);
      if (error.Success())
        is_dir = fs.IsDirectory(symlink_filespec);
    }

    if (only_directories && !is_dir)
      continue;

    // Shrink it back down so that it just has the original prefix the user
    // typed and remove the part of the name which is common to the located
    // item and what the user typed.
    CompletionBuffer.resize(FullPrefixLen);
    Name = Name.drop_front(PartialItem.size());
    CompletionBuffer.append(Name);

    if (is_dir) {
      path::append(CompletionBuffer, path::get_separator());
    }

    CompletionMode mode =
        is_dir ? CompletionMode::Partial : CompletionMode::Normal;
    request.AddCompletion(CompletionBuffer, "", mode);
  }
}

static void DiskFilesOrDirectories(const llvm::Twine &partial_name,
                                   bool only_directories, StringList &matches,
                                   TildeExpressionResolver &Resolver) {
  CompletionResult result;
  std::string partial_name_str = partial_name.str();
  CompletionRequest request(partial_name_str, partial_name_str.size(), result);
  DiskFilesOrDirectories(partial_name, only_directories, request, Resolver);
  result.GetMatches(matches);
}

static void DiskFilesOrDirectories(CompletionRequest &request,
                                   bool only_directories) {
  StandardTildeExpressionResolver resolver;
  DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories,
                         request, resolver);
}

void CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
                                   CompletionRequest &request,
                                   SearchFilter *searcher) {
  DiskFilesOrDirectories(request, /*only_dirs*/ false);
}

void CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
                                   StringList &matches,
                                   TildeExpressionResolver &Resolver) {
  DiskFilesOrDirectories(partial_file_name, false, matches, Resolver);
}

void CommandCompletions::DiskDirectories(CommandInterpreter &interpreter,
                                         CompletionRequest &request,
                                         SearchFilter *searcher) {
  DiskFilesOrDirectories(request, /*only_dirs*/ true);
}

void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
                                         StringList &matches,
                                         TildeExpressionResolver &Resolver) {
  DiskFilesOrDirectories(partial_file_name, true, matches, Resolver);
}

void CommandCompletions::RemoteDiskFiles(CommandInterpreter &interpreter,
                                         CompletionRequest &request,
                                         SearchFilter *searcher) {
  lldb::PlatformSP platform_sp =
      interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
  if (platform_sp)
    platform_sp->AutoCompleteDiskFileOrDirectory(request, false);
}

void CommandCompletions::RemoteDiskDirectories(CommandInterpreter &interpreter,
                                               CompletionRequest &request,
                                               SearchFilter *searcher) {
  lldb::PlatformSP platform_sp =
      interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
  if (platform_sp)
    platform_sp->AutoCompleteDiskFileOrDirectory(request, true);
}

void CommandCompletions::Modules(CommandInterpreter &interpreter,
                                 CompletionRequest &request,
                                 SearchFilter *searcher) {
  ModuleCompleter completer(interpreter, request);

  if (searcher == nullptr) {
    lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
    SearchFilterForUnconstrainedSearches null_searcher(target_sp);
    completer.DoCompletion(&null_searcher);
  } else {
    completer.DoCompletion(searcher);
  }
}

void CommandCompletions::ModuleUUIDs(CommandInterpreter &interpreter,
                                     CompletionRequest &request,
                                     SearchFilter *searcher) {
  const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
  if (!exe_ctx.HasTargetScope())
    return;

  exe_ctx.GetTargetPtr()->GetImages().ForEach(
      [&request](const lldb::ModuleSP &module) {
        StreamString strm;
        module->GetDescription(strm.AsRawOstream(),
                               lldb::eDescriptionLevelInitial);
        request.TryCompleteCurrentArg(module->GetUUID().GetAsString(),
                                      strm.GetString());
        return true;
      });
}

void CommandCompletions::Symbols(CommandInterpreter &interpreter,
                                 CompletionRequest &request,
                                 SearchFilter *searcher) {
  SymbolCompleter completer(interpreter, request);

  if (searcher == nullptr) {
    lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
    SearchFilterForUnconstrainedSearches null_searcher(target_sp);
    completer.DoCompletion(&null_searcher);
  } else {
    completer.DoCompletion(searcher);
  }
}

void CommandCompletions::SettingsNames(CommandInterpreter &interpreter,
                                       CompletionRequest &request,
                                       SearchFilter *searcher) {
  // Cache the full setting name list
  static StringList g_property_names;
  if (g_property_names.GetSize() == 0) {
    // Generate the full setting name list on demand
    lldb::OptionValuePropertiesSP properties_sp(
        interpreter.GetDebugger().GetValueProperties());
    if (properties_sp) {
      StreamString strm;
      properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
      const std::string &str = std::string(strm.GetString());
      g_property_names.SplitIntoLines(str.c_str(), str.size());
    }
  }

  for (const std::string &s : g_property_names)
    request.TryCompleteCurrentArg(s);
}

void CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter,
                                             CompletionRequest &request,
                                             SearchFilter *searcher) {
  PluginManager::AutoCompletePlatformName(request.GetCursorArgumentPrefix(),
                                          request);
}

void CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter,
                                           CompletionRequest &request,
                                           SearchFilter *searcher) {
  ArchSpec::AutoComplete(request);
}

void CommandCompletions::VariablePath(CommandInterpreter &interpreter,
                                      CompletionRequest &request,
                                      SearchFilter *searcher) {
  Variable::AutoComplete(interpreter.GetExecutionContext(), request);
}

void CommandCompletions::Registers(CommandInterpreter &interpreter,
                                   CompletionRequest &request,
                                   SearchFilter *searcher) {
  std::string reg_prefix;
  if (request.GetCursorArgumentPrefix().starts_with("$"))
    reg_prefix = "$";

  RegisterContext *reg_ctx =
      interpreter.GetExecutionContext().GetRegisterContext();
  if (!reg_ctx)
    return;

  const size_t reg_num = reg_ctx->GetRegisterCount();
  for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) {
    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
    request.TryCompleteCurrentArg(reg_prefix + reg_info->name,
                                  reg_info->alt_name);
  }
}

void CommandCompletions::Breakpoints(CommandInterpreter &interpreter,
                                     CompletionRequest &request,
                                     SearchFilter *searcher) {
  lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget();
  if (!target)
    return;

  const BreakpointList &breakpoints = target->GetBreakpointList();

  std::unique_lock<std::recursive_mutex> lock;
  target->GetBreakpointList().GetListMutex(lock);

  size_t num_breakpoints = breakpoints.GetSize();
  if (num_breakpoints == 0)
    return;

  for (size_t i = 0; i < num_breakpoints; ++i) {
    lldb::BreakpointSP bp = breakpoints.GetBreakpointAtIndex(i);

    StreamString s;
    bp->GetDescription(&s, lldb::eDescriptionLevelBrief);
    llvm::StringRef bp_info = s.GetString();

    const size_t colon_pos = bp_info.find_first_of(':');
    if (colon_pos != llvm::StringRef::npos)
      bp_info = bp_info.drop_front(colon_pos + 2);

    request.TryCompleteCurrentArg(std::to_string(bp->GetID()), bp_info);
  }
}

void CommandCompletions::BreakpointNames(CommandInterpreter &interpreter,
                                         CompletionRequest &request,
                                         SearchFilter *searcher) {
  lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget();
  if (!target)
    return;

  std::vector<std::string> name_list;
  target->GetBreakpointNames(name_list);

  for (const std::string &name : name_list)
    request.TryCompleteCurrentArg(name);
}

void CommandCompletions::ProcessPluginNames(CommandInterpreter &interpreter,
                                            CompletionRequest &request,
                                            SearchFilter *searcher) {
  PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(),
                                         request);
}
void CommandCompletions::DisassemblyFlavors(CommandInterpreter &interpreter,
                                            CompletionRequest &request,
                                            SearchFilter *searcher) {
  // Currently the only valid options for disassemble -F are default, and for
  // Intel architectures, att and intel.
  static const char *flavors[] = {"default", "att", "intel"};
  for (const char *flavor : flavors) {
    request.TryCompleteCurrentArg(flavor);
  }
}

void CommandCompletions::ProcessIDs(CommandInterpreter &interpreter,
                                    CompletionRequest &request,
                                    SearchFilter *searcher) {
  lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
  if (!platform_sp)
    return;
  ProcessInstanceInfoList process_infos;
  ProcessInstanceInfoMatch match_info;
  platform_sp->FindProcesses(match_info, process_infos);
  for (const ProcessInstanceInfo &info : process_infos)
    request.TryCompleteCurrentArg(std::to_string(info.GetProcessID()),
                                  info.GetNameAsStringRef());
}

void CommandCompletions::ProcessNames(CommandInterpreter &interpreter,
                                      CompletionRequest &request,
                                      SearchFilter *searcher) {
  lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
  if (!platform_sp)
    return;
  ProcessInstanceInfoList process_infos;
  ProcessInstanceInfoMatch match_info;
  platform_sp->FindProcesses(match_info, process_infos);
  for (const ProcessInstanceInfo &info : process_infos)
    request.TryCompleteCurrentArg(info.GetNameAsStringRef());
}

void CommandCompletions::TypeLanguages(CommandInterpreter &interpreter,
                                       CompletionRequest &request,
                                       SearchFilter *searcher) {
  for (int bit :
       Language::GetLanguagesSupportingTypeSystems().bitvector.set_bits()) {
    request.TryCompleteCurrentArg(
        Language::GetNameForLanguageType(static_cast<lldb::LanguageType>(bit)));
  }
}

void CommandCompletions::FrameIndexes(CommandInterpreter &interpreter,
                                      CompletionRequest &request,
                                      SearchFilter *searcher) {
  const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
  if (!exe_ctx.HasProcessScope())
    return;

  lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
  Debugger &dbg = interpreter.GetDebugger();
  const uint32_t frame_num = thread_sp->GetStackFrameCount();
  for (uint32_t i = 0; i < frame_num; ++i) {
    lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i);
    StreamString strm;
    // Dumping frames can be slow, allow interruption.
    if (INTERRUPT_REQUESTED(dbg, "Interrupted in frame completion"))
      break;
    frame_sp->Dump(&strm, false, true);
    request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
  }
}

void CommandCompletions::StopHookIDs(CommandInterpreter &interpreter,
                                     CompletionRequest &request,
                                     SearchFilter *searcher) {
  const lldb::TargetSP target_sp =
      interpreter.GetExecutionContext().GetTargetSP();
  if (!target_sp)
    return;

  const size_t num = target_sp->GetNumStopHooks();
  for (size_t idx = 0; idx < num; ++idx) {
    StreamString strm;
    // The value 11 is an offset to make the completion description looks
    // neater.
    strm.SetIndentLevel(11);
    const Target::StopHookSP stophook_sp = target_sp->GetStopHookAtIndex(idx);
    stophook_sp->GetDescription(strm, lldb::eDescriptionLevelInitial);
    request.TryCompleteCurrentArg(std::to_string(stophook_sp->GetID()),
                                  strm.GetString());
  }
}

void CommandCompletions::ThreadIndexes(CommandInterpreter &interpreter,
                                       CompletionRequest &request,
                                       SearchFilter *searcher) {
  const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
  if (!exe_ctx.HasProcessScope())
    return;

  ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList();
  lldb::ThreadSP thread_sp;
  for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) {
    StreamString strm;
    thread_sp->GetStatus(strm, 0, 1, 1, true);
    request.TryCompleteCurrentArg(std::to_string(thread_sp->GetIndexID()),
                                  strm.GetString());
  }
}

void CommandCompletions::WatchPointIDs(CommandInterpreter &interpreter,
                                       CompletionRequest &request,
                                       SearchFilter *searcher) {
  const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
  if (!exe_ctx.HasTargetScope())
    return;

  const WatchpointList &wp_list = exe_ctx.GetTargetPtr()->GetWatchpointList();
  for (lldb::WatchpointSP wp_sp : wp_list.Watchpoints()) {
    StreamString strm;
    wp_sp->Dump(&strm);
    request.TryCompleteCurrentArg(std::to_string(wp_sp->GetID()),
                                  strm.GetString());
  }
}

void CommandCompletions::TypeCategoryNames(CommandInterpreter &interpreter,
                                           CompletionRequest &request,
                                           SearchFilter *searcher) {
  DataVisualization::Categories::ForEach(
      [&request](const lldb::TypeCategoryImplSP &category_sp) {
        request.TryCompleteCurrentArg(category_sp->GetName(),
                                      category_sp->GetDescription());
        return true;
      });
}

void CommandCompletions::ThreadIDs(CommandInterpreter &interpreter,
                                   CompletionRequest &request,
                                   SearchFilter *searcher) {
  const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
  if (!exe_ctx.HasProcessScope())
    return;

  ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList();
  lldb::ThreadSP thread_sp;
  for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) {
    StreamString strm;
    thread_sp->GetStatus(strm, 0, 1, 1, true);
    request.TryCompleteCurrentArg(std::to_string(thread_sp->GetID()),
                                  strm.GetString());
  }
}

void CommandCompletions::CompleteModifiableCmdPathArgs(
    CommandInterpreter &interpreter, CompletionRequest &request,
    OptionElementVector &opt_element_vector) {
  // The only arguments constitute a command path, however, there might be
  // options interspersed among the arguments, and we need to skip those.  Do that
  // by copying the args vector, and just dropping all the option bits:
  Args args = request.GetParsedLine();
  std::vector<size_t> to_delete;
  for (auto &elem : opt_element_vector) {
    to_delete.push_back(elem.opt_pos);
    if (elem.opt_arg_pos != 0)
      to_delete.push_back(elem.opt_arg_pos);
  }
  sort(to_delete.begin(), to_delete.end(), std::greater<size_t>());
  for (size_t idx : to_delete)
    args.DeleteArgumentAtIndex(idx);

  // At this point, we should only have args, so now lookup the command up to
  // the cursor element.

  // There's nothing here but options.  It doesn't seem very useful here to
  // dump all the commands, so just return.
  size_t num_args = args.GetArgumentCount();
  if (num_args == 0)
    return;

  // There's just one argument, so we should complete its name:
  StringList matches;
  if (num_args == 1) {
    interpreter.GetUserCommandObject(args.GetArgumentAtIndex(0), &matches,
                                     nullptr);
    request.AddCompletions(matches);
    return;
  }

  // There was more than one path element, lets find the containing command:
  Status error;
  CommandObjectMultiword *mwc =
      interpreter.VerifyUserMultiwordCmdPath(args, true, error);

  // Something was wrong somewhere along the path, but I don't think there's
  // a good way to go back and fill in the missing elements:
  if (error.Fail())
    return;

  // This should never happen.  We already handled the case of one argument
  // above, and we can only get Success & nullptr back if there's a one-word
  // leaf.
  assert(mwc != nullptr);

  mwc->GetSubcommandObject(args.GetArgumentAtIndex(num_args - 1), &matches);
  if (matches.GetSize() == 0)
    return;

  request.AddCompletions(matches);
}
