//===-- 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/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.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::eManagedPluginCompletion, CommandCompletions::ManagedPlugins},
      {lldb::eTerminatorCompletion,
       nullptr} // This one has to be last in the list.
  };

  for (int i = 0; request.ShouldAddCompletions(); 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 m_matching_files.GetSize() >= m_request.GetMaxNumberOfCompletionsToAdd()
               ? Searcher::eCallbackReturnStop
               : 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) {
        if (m_match_set.size() >= m_request.GetMaxNumberOfCompletionsToAdd())
          break;

        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 m_match_set.size() >= m_request.GetMaxNumberOfCompletionsToAdd()
               ? Searcher::eCallbackReturnStop
               : 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) {
    llvm::StringRef request_str = m_request.GetCursorArgumentPrefix();
    // We can match the full path, or the file name only. The full match will be
    // attempted always, the file name match only if the request does not
    // contain a path separator.

    // Preserve both the path as spelled by the user (used for completion) and
    // the canonical version (used for matching).
    m_spelled_path = request_str;
    m_canonical_path = FileSpec(m_spelled_path).GetPath();
    if (!m_spelled_path.empty() &&
        llvm::sys::path::is_separator(m_spelled_path.back()) &&
        !llvm::StringRef(m_canonical_path).ends_with(m_spelled_path.back())) {
      m_canonical_path += m_spelled_path.back();
    }

    if (llvm::find_if(request_str, [](char c) {
          return llvm::sys::path::is_separator(c);
        }) == request_str.end())
      m_file_name = request_str;
  }

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

  Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
                                          SymbolContext &context,
                                          Address *addr) override {
    if (context.module_sp) {
      // Attempt a full path match.
      std::string cur_path = context.module_sp->GetFileSpec().GetPath();
      llvm::StringRef cur_path_view = cur_path;
      if (cur_path_view.consume_front(m_canonical_path))
        m_request.AddCompletion((m_spelled_path + cur_path_view).str());

      // And a file name match.
      if (m_file_name) {
        llvm::StringRef cur_file_name =
            context.module_sp->GetFileSpec().GetFilename().GetStringRef();
        if (cur_file_name.starts_with(*m_file_name))
          m_request.AddCompletion(cur_file_name);
      }
    }
    return m_request.ShouldAddCompletions() ? Searcher::eCallbackReturnContinue
                                            : Searcher::eCallbackReturnStop;
  }

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

private:
  std::optional<llvm::StringRef> m_file_name;
  llvm::StringRef m_spelled_path;
  std::string m_canonical_path;

  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 && request.ShouldAddCompletions();
       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 IterationAction::Continue;
      });
}

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, /*show_hidden*/ 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, /*show_hidden*/ true);
    request.TryCompleteCurrentArg(std::to_string(thread_sp->GetID()),
                                  strm.GetString());
  }
}

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

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