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

// C Includes
#include <sys/stat.h>
#if defined(__APPLE__) || defined(__linux__)
#include <pwd.h>
#endif

// C++ Includes
// Other libraries and framework includes
#include "llvm/ADT/SmallString.h"

// Project includes
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/CleanUp.h"

#include "llvm/ADT/SmallString.h"

using namespace lldb_private;

CommandCompletions::CommonCompletionElement
    CommandCompletions::g_common_completions[] = {
        {eCustomCompletion, nullptr},
        {eSourceFileCompletion, CommandCompletions::SourceFiles},
        {eDiskFileCompletion, CommandCompletions::DiskFiles},
        {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
        {eSymbolCompletion, CommandCompletions::Symbols},
        {eModuleCompletion, CommandCompletions::Modules},
        {eSettingsNameCompletion, CommandCompletions::SettingsNames},
        {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
        {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
        {eVariablePathCompletion, CommandCompletions::VariablePath},
        {eNoCompletion, nullptr} // This one has to be last in the list.
};

bool CommandCompletions::InvokeCommonCompletionCallbacks(
    CommandInterpreter &interpreter, uint32_t completion_mask,
    const char *completion_str, int match_start_point, int max_return_elements,
    SearchFilter *searcher, bool &word_complete, StringList &matches) {
  bool handled = false;

  if (completion_mask & eCustomCompletion)
    return false;

  for (int i = 0;; i++) {
    if (g_common_completions[i].type == eNoCompletion)
      break;
    else if ((g_common_completions[i].type & completion_mask) ==
                 g_common_completions[i].type &&
             g_common_completions[i].callback != nullptr) {
      handled = true;
      g_common_completions[i].callback(interpreter, completion_str,
                                       match_start_point, max_return_elements,
                                       searcher, word_complete, matches);
    }
  }
  return handled;
}

int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
                                    const char *partial_file_name,
                                    int match_start_point,
                                    int max_return_elements,
                                    SearchFilter *searcher, bool &word_complete,
                                    StringList &matches) {
  word_complete = true;
  // Find some way to switch "include support files..."
  SourceFileCompleter completer(interpreter, false, partial_file_name,
                                match_start_point, max_return_elements,
                                matches);

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

typedef struct DiskFilesOrDirectoriesBaton {
  const char *remainder;
  char *partial_name_copy;
  bool only_directories;
  bool *saw_directory;
  StringList *matches;
  char *end_ptr;
  size_t baselen;
} DiskFilesOrDirectoriesBaton;

FileSpec::EnumerateDirectoryResult
DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type,
                               const FileSpec &spec) {
  const char *name = spec.GetFilename().AsCString();

  const DiskFilesOrDirectoriesBaton *parameters =
      (DiskFilesOrDirectoriesBaton *)baton;
  char *end_ptr = parameters->end_ptr;
  char *partial_name_copy = parameters->partial_name_copy;
  const char *remainder = parameters->remainder;

  // Omit ".", ".." and any . files if the match string doesn't start with .
  if (name[0] == '.') {
    if (name[1] == '\0')
      return FileSpec::eEnumerateDirectoryResultNext;
    else if (name[1] == '.' && name[2] == '\0')
      return FileSpec::eEnumerateDirectoryResultNext;
    else if (remainder[0] != '.')
      return FileSpec::eEnumerateDirectoryResultNext;
  }

  // If we found a directory, we put a "/" at the end of the name.

  if (remainder[0] == '\0' || strstr(name, remainder) == name) {
    if (strlen(name) + parameters->baselen >= PATH_MAX)
      return FileSpec::eEnumerateDirectoryResultNext;

    strcpy(end_ptr, name);

    bool isa_directory = false;
    if (file_type == FileSpec::eFileTypeDirectory)
      isa_directory = true;
    else if (file_type == FileSpec::eFileTypeSymbolicLink) {
      if (FileSpec(partial_name_copy, false).IsDirectory())
        isa_directory = true;
    }

    if (isa_directory) {
      *parameters->saw_directory = true;
      size_t len = strlen(parameters->partial_name_copy);
      partial_name_copy[len] = '/';
      partial_name_copy[len + 1] = '\0';
    }
    if (parameters->only_directories && !isa_directory)
      return FileSpec::eEnumerateDirectoryResultNext;
    parameters->matches->AppendString(partial_name_copy);
  }

  return FileSpec::eEnumerateDirectoryResultNext;
}

static int DiskFilesOrDirectories(const char *partial_file_name,
                                  bool only_directories, bool &saw_directory,
                                  StringList &matches) {
  // I'm going to  use the "glob" function with GLOB_TILDE for user directory
  // expansion.
  // If it is not defined on your host system, you'll need to implement it
  // yourself...

  size_t partial_name_len = strlen(partial_file_name);

  if (partial_name_len >= PATH_MAX)
    return matches.GetSize();

  // This copy of the string will be cut up into the directory part, and the
  // remainder.  end_ptr
  // below will point to the place of the remainder in this string.  Then when
  // we've resolved the
  // containing directory, and opened it, we'll read the directory contents and
  // overwrite the
  // partial_name_copy starting from end_ptr with each of the matches.  Thus we
  // will preserve
  // the form the user originally typed.

  char partial_name_copy[PATH_MAX];
  memcpy(partial_name_copy, partial_file_name, partial_name_len);
  partial_name_copy[partial_name_len] = '\0';

  // We'll need to save a copy of the remainder for comparison, which we do
  // here.
  char remainder[PATH_MAX];

  // end_ptr will point past the last / in partial_name_copy, or if there is no
  // slash to the beginning of the string.
  char *end_ptr;

  end_ptr = strrchr(partial_name_copy, '/');

  // This will store the resolved form of the containing directory
  llvm::SmallString<64> containing_part;

  if (end_ptr == nullptr) {
    // There's no directory.  If the thing begins with a "~" then this is a bare
    // user name.
    if (*partial_name_copy == '~') {
      // Nothing here but the user name.  We could just put a slash on the end,
      // but for completeness sake we'll resolve the user name and only put a
      // slash
      // on the end if it exists.
      llvm::SmallString<64> resolved_username(partial_name_copy);
      FileSpec::ResolveUsername(resolved_username);

      // Not sure how this would happen, a username longer than PATH_MAX?
      // Still...
      if (resolved_username.size() == 0) {
        // The user name didn't resolve, let's look in the password database for
        // matches.
        // The user name database contains duplicates, and is not in
        // alphabetical order, so
        // we'll use a set to manage that for us.
        FileSpec::ResolvePartialUsername(partial_name_copy, matches);
        if (matches.GetSize() > 0)
          saw_directory = true;
        return matches.GetSize();
      } else {
        // The thing exists, put a '/' on the end, and return it...
        // FIXME: complete user names here:
        partial_name_copy[partial_name_len] = '/';
        partial_name_copy[partial_name_len + 1] = '\0';
        matches.AppendString(partial_name_copy);
        saw_directory = true;
        return matches.GetSize();
      }
    } else {
      // The containing part is the CWD, and the whole string is the remainder.
      containing_part = ".";
      strcpy(remainder, partial_name_copy);
      end_ptr = partial_name_copy;
    }
  } else {
    if (end_ptr == partial_name_copy) {
      // We're completing a file or directory in the root volume.
      containing_part = "/";
    } else {
      containing_part.append(partial_name_copy, end_ptr);
    }
    // Push end_ptr past the final "/" and set remainder.
    end_ptr++;
    strcpy(remainder, end_ptr);
  }

  // Look for a user name in the containing part, and if it's there, resolve it
  // and stick the
  // result back into the containing_part:

  if (*partial_name_copy == '~') {
    FileSpec::ResolveUsername(containing_part);
    // User name doesn't exist, we're not getting any further...
    if (containing_part.empty())
      return matches.GetSize();
  }

  // Okay, containing_part is now the directory we want to open and look for
  // files:

  size_t baselen = end_ptr - partial_name_copy;

  DiskFilesOrDirectoriesBaton parameters;
  parameters.remainder = remainder;
  parameters.partial_name_copy = partial_name_copy;
  parameters.only_directories = only_directories;
  parameters.saw_directory = &saw_directory;
  parameters.matches = &matches;
  parameters.end_ptr = end_ptr;
  parameters.baselen = baselen;

  FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true,
                               DiskFilesOrDirectoriesCallback, &parameters);

  return matches.GetSize();
}

int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
                                  const char *partial_file_name,
                                  int match_start_point,
                                  int max_return_elements,
                                  SearchFilter *searcher, bool &word_complete,
                                  StringList &matches) {
  int ret_val =
      DiskFilesOrDirectories(partial_file_name, false, word_complete, matches);
  word_complete = !word_complete;
  return ret_val;
}

int CommandCompletions::DiskDirectories(
    CommandInterpreter &interpreter, const char *partial_file_name,
    int match_start_point, int max_return_elements, SearchFilter *searcher,
    bool &word_complete, StringList &matches) {
  int ret_val =
      DiskFilesOrDirectories(partial_file_name, true, word_complete, matches);
  word_complete = false;
  return ret_val;
}

int CommandCompletions::Modules(CommandInterpreter &interpreter,
                                const char *partial_file_name,
                                int match_start_point, int max_return_elements,
                                SearchFilter *searcher, bool &word_complete,
                                StringList &matches) {
  word_complete = true;
  ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
                            max_return_elements, matches);

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

int CommandCompletions::Symbols(CommandInterpreter &interpreter,
                                const char *partial_file_name,
                                int match_start_point, int max_return_elements,
                                SearchFilter *searcher, bool &word_complete,
                                StringList &matches) {
  word_complete = true;
  SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
                            max_return_elements, matches);

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

int CommandCompletions::SettingsNames(
    CommandInterpreter &interpreter, const char *partial_setting_name,
    int match_start_point, int max_return_elements, SearchFilter *searcher,
    bool &word_complete, StringList &matches) {
  // 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 = strm.GetString();
      g_property_names.SplitIntoLines(str.c_str(), str.size());
    }
  }

  size_t exact_matches_idx = SIZE_MAX;
  const size_t num_matches = g_property_names.AutoComplete(
      partial_setting_name, matches, exact_matches_idx);
  word_complete = exact_matches_idx != SIZE_MAX;
  return num_matches;
}

int CommandCompletions::PlatformPluginNames(
    CommandInterpreter &interpreter, const char *partial_name,
    int match_start_point, int max_return_elements, SearchFilter *searcher,
    bool &word_complete, lldb_private::StringList &matches) {
  const uint32_t num_matches =
      PluginManager::AutoCompletePlatformName(partial_name, matches);
  word_complete = num_matches == 1;
  return num_matches;
}

int CommandCompletions::ArchitectureNames(
    CommandInterpreter &interpreter, const char *partial_name,
    int match_start_point, int max_return_elements, SearchFilter *searcher,
    bool &word_complete, lldb_private::StringList &matches) {
  const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
  word_complete = num_matches == 1;
  return num_matches;
}

int CommandCompletions::VariablePath(
    CommandInterpreter &interpreter, const char *partial_name,
    int match_start_point, int max_return_elements, SearchFilter *searcher,
    bool &word_complete, lldb_private::StringList &matches) {
  return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
                                matches, word_complete);
}

CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
                                         const char *completion_str,
                                         int match_start_point,
                                         int max_return_elements,
                                         StringList &matches)
    : m_interpreter(interpreter), m_completion_str(completion_str),
      m_match_start_point(match_start_point),
      m_max_return_elements(max_return_elements), m_matches(matches) {}

CommandCompletions::Completer::~Completer() = default;

//----------------------------------------------------------------------
// SourceFileCompleter
//----------------------------------------------------------------------

CommandCompletions::SourceFileCompleter::SourceFileCompleter(
    CommandInterpreter &interpreter, bool include_support_files,
    const char *completion_str, int match_start_point, int max_return_elements,
    StringList &matches)
    : CommandCompletions::Completer(interpreter, completion_str,
                                    match_start_point, max_return_elements,
                                    matches),
      m_include_support_files(include_support_files), m_matching_files() {
  FileSpec partial_spec(m_completion_str.c_str(), false);
  m_file_name = partial_spec.GetFilename().GetCString();
  m_dir_name = partial_spec.GetDirectory().GetCString();
}

Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
  return eDepthCompUnit;
}

Searcher::CallbackReturn
CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
                                                        SymbolContext &context,
                                                        Address *addr,
                                                        bool complete) {
  if (context.comp_unit != nullptr) {
    if (m_include_support_files) {
      FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
      for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
        const FileSpec &sfile_spec =
            supporting_files.GetFileSpecAtIndex(sfiles);
        const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
        const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
        bool match = false;
        if (m_file_name && sfile_file_name &&
            strstr(sfile_file_name, m_file_name) == sfile_file_name)
          match = true;
        if (match && m_dir_name && sfile_dir_name &&
            strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
          match = false;

        if (match) {
          m_matching_files.AppendIfUnique(sfile_spec);
        }
      }
    } else {
      const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
      const char *cur_dir_name = context.comp_unit->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);
      }
    }
  }
  return Searcher::eCallbackReturnContinue;
}

size_t
CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
  filter->Search(*this);
  // Now convert the filelist to completions:
  for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
    m_matches.AppendString(
        m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
  }
  return m_matches.GetSize();
}

//----------------------------------------------------------------------
// SymbolCompleter
//----------------------------------------------------------------------

static bool regex_chars(const char comp) {
  return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
          comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
          comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
          comp == '\\' || comp == '?');
}

CommandCompletions::SymbolCompleter::SymbolCompleter(
    CommandInterpreter &interpreter, const char *completion_str,
    int match_start_point, int max_return_elements, StringList &matches)
    : CommandCompletions::Completer(interpreter, completion_str,
                                    match_start_point, max_return_elements,
                                    matches) {
  std::string regex_str;
  if (completion_str && completion_str[0]) {
    regex_str.append("^");
    regex_str.append(completion_str);
  } 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.Compile(regex_str.c_str());
}

Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
  return eDepthModule;
}

Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
    SearchFilter &filter, SymbolContext &context, Address *addr,
    bool complete) {
  if (context.module_sp) {
    SymbolContextList sc_list;
    const bool include_symbols = true;
    const bool include_inlines = true;
    const bool append = true;
    context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
                                     append, sc_list);

    SymbolContext sc;
    // Now add the functions & symbols to the list - only add if unique:
    for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
      if (sc_list.GetContextAtIndex(i, sc)) {
        ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
        if (!func_name.IsEmpty())
          m_match_set.insert(func_name);
      }
    }
  }
  return Searcher::eCallbackReturnContinue;
}

size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
  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_matches.AppendString((*pos).GetCString());

  return m_matches.GetSize();
}

//----------------------------------------------------------------------
// ModuleCompleter
//----------------------------------------------------------------------
CommandCompletions::ModuleCompleter::ModuleCompleter(
    CommandInterpreter &interpreter, const char *completion_str,
    int match_start_point, int max_return_elements, StringList &matches)
    : CommandCompletions::Completer(interpreter, completion_str,
                                    match_start_point, max_return_elements,
                                    matches) {
  FileSpec partial_spec(m_completion_str.c_str(), false);
  m_file_name = partial_spec.GetFilename().GetCString();
  m_dir_name = partial_spec.GetDirectory().GetCString();
}

Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
  return eDepthModule;
}

Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
    SearchFilter &filter, SymbolContext &context, Address *addr,
    bool complete) {
  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_matches.AppendString(cur_file_name);
    }
  }
  return Searcher::eCallbackReturnContinue;
}

size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
  filter->Search(*this);
  return m_matches.GetSize();
}
