// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/console/input_location_parser.h"

#include <inttypes.h>

#include <algorithm>
#include <limits>

#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/command_utils.h"
#include "src/developer/debug/zxdb/console/format_location.h"
#include "src/developer/debug/zxdb/console/string_util.h"
#include "src/developer/debug/zxdb/expr/expr.h"
#include "src/developer/debug/zxdb/expr/expr_parser.h"
#include "src/developer/debug/zxdb/expr/find_name.h"
#include "src/developer/debug/zxdb/expr/permissive_input_location.h"
#include "src/developer/debug/zxdb/symbols/identifier.h"
#include "src/developer/debug/zxdb/symbols/index.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/module_symbols.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/developer/debug/zxdb/symbols/target_symbols.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

// Searches the current object ("this") in the frame for local matches of the given identifier.
// This will not return anything that exactly matches the input because it's assumed that value
// is always handled by the "global" case.
//
// For input locations it is not necessary to do a full lexical search beyond the local class
// because unqualified names will match any namespace in ResolveInputLocations(). That will catch
// all other instances of the symbol.
//
// If there is no current object or there are no matches, returns an empty vector. Otherwise returns
// tall matches with fully-qualified names.
std::vector<InputLocation> GetIdentifierMatchesOnThis(const ProcessSymbols* process_symbols,
                                                      const Location& loc,
                                                      const Identifier& input) {
  if (!loc.symbol())
    return {};
  const CodeBlock* code_block = loc.symbol().Get()->AsCodeBlock();
  if (!code_block)
    return {};

  FindNameContext find_context(process_symbols, loc.symbol_context(), code_block);

  // Currently location matching matches only functions. We may need to broaden this in the
  // future as the needs of callers require.
  FindNameOptions find_options(FindNameOptions::kNoKinds);
  find_options.find_functions = true;
  find_options.max_results = std::numeric_limits<size_t>::max();  // Want everything

  std::vector<FoundName> found_local;
  FindMemberOnThis(find_context, find_options, ToParsedIdentifier(input), &found_local);

  std::vector<InputLocation> result;
  for (const auto& found : found_local) {
    Identifier found_ident = ToIdentifier(found.GetName());
    // The empty name check is paranoid in case the symbols are declaring weird things. Don't
    // duplicate the input which will be appended separately if needed.
    if (!found_ident.empty() && !found_ident.EqualsIgnoringQualification(input))
      result.emplace_back(found_ident);
  }
  return result;
}

}  // namespace

Err ParseGlobalInputLocation(const Location& location, const std::string& input,
                             InputLocation* output) {
  if (input.empty())
    return Err("Passed empty location.");

  // Check for one colon. Two colons is a C++ member function.
  size_t colon = input.find(':');
  const char kMissingFileError[] =
      "There is no current file name to use, you'll have to specify a file.";
  if (colon != std::string::npos && colon < input.size() - 1 && input[colon + 1] != ':') {
    // <file>:<line> format.
    std::string file = input.substr(0, colon);
    if (file.empty()) {
      // Empty file names take the current file name just like bare numbers.
      if (location.file_line().file().empty())
        return Err(kMissingFileError);
      file = location.file_line().file();
    }

    uint64_t line = 0;
    if (Err err = StringToUint64(input.substr(colon + 1), &line); err.has_error())
      return err;
    if (line == 0)
      return Err("Can't have a 0 line number.");

    *output = InputLocation(FileLine(std::move(file), static_cast<int>(line)));
    return Err();
  }

  // Hex numbers are addresses.
  if (CheckHexPrefix(input)) {
    uint64_t address = 0;
    if (Err err = StringToUint64(input, &address); err.has_error())
      return err;
    *output = InputLocation(address);
    return Err();
  }

  // Standalone non-hex numbers are line numbers, assume the current file name.
  uint64_t line = 0;
  Err err = StringToUint64(input, &line);
  if (!err.has_error()) {
    if (location.file_line().file().empty())
      return Err(kMissingFileError);

    *output = InputLocation(FileLine(location.file_line().file(), static_cast<int>(line)));
    return Err();
  }

  // Anything else, assume its an identifier.
  Identifier ident;
  if (err = ExprParser::ParseIdentifier(input, &ident); err.has_error())
    return err;

  *output = InputLocation(ident);
  return Err();
}

void EvalGlobalInputLocation(
    const fxl::RefPtr<EvalContext> eval_context, const Location& location, const std::string& input,
    fit::callback<void(ErrOr<InputLocation>, std::optional<uint32_t> size)> cb) {
  if (input.empty() || input[0] != '*') {
    // Not an expression, forward to the synchronous parser.
    InputLocation sync_result;
    if (Err err = ParseGlobalInputLocation(location, input, &sync_result); err.has_error())
      cb(err, std::nullopt);
    else
      cb(sync_result, std::nullopt);
    return;
  }

  // Everything following the * is the expression.
  std::string expr = input.substr(1);
  EvalExpression(
      expr, eval_context, true, [eval_context, cb = std::move(cb)](ErrOrValue result) mutable {
        if (result.has_error())
          return cb(RewriteCommandExpressionError(std::string(), result.err()), std::nullopt);

        uint64_t address = 0;
        std::optional<uint32_t> size;
        if (Err err = ValueToAddressAndSize(eval_context, result.value(), &address, &size);
            err.has_error()) {
          return cb(err, std::nullopt);
        }

        cb(InputLocation(address), size);
      });
}

Err ParseLocalInputLocation(const ProcessSymbols* optional_process_symbols,
                            const Location& location, const std::string& input,
                            std::vector<InputLocation>* output) {
  output->clear();

  InputLocation global;
  if (Err err = ParseGlobalInputLocation(location, input, &global); err.has_error())
    return err;

  if (optional_process_symbols && global.type == InputLocation::Type::kName)
    *output = GetIdentifierMatchesOnThis(optional_process_symbols, location, global.name);

  // The global one always goes last so the most specific ones come first.
  output->push_back(std::move(global));
  return Err();
}

Err ParseLocalInputLocation(const Frame* optional_frame, const std::string& input,
                            std::vector<InputLocation>* output) {
  const ProcessSymbols* process_symbols = nullptr;
  Location location;
  if (optional_frame) {
    process_symbols = optional_frame->GetThread()->GetProcess()->GetSymbols();
    location = optional_frame->GetLocation();
  }
  return ParseLocalInputLocation(process_symbols, location, input, output);
}

void EvalLocalInputLocation(
    const fxl::RefPtr<EvalContext>& eval_context, const Frame* optional_frame,
    const std::string& input,
    fit::callback<void(ErrOr<std::vector<InputLocation>>, std::optional<uint32_t> size)> cb) {
  Location cur_location;
  if (optional_frame)
    cur_location = optional_frame->GetLocation();
  return EvalLocalInputLocation(eval_context, cur_location, input, std::move(cb));
}

void EvalLocalInputLocation(
    const fxl::RefPtr<EvalContext>& eval_context, const Location& location,
    const std::string& input,
    fit::callback<void(ErrOr<std::vector<InputLocation>>, std::optional<uint32_t> size)> cb) {
  EvalGlobalInputLocation(
      eval_context, location, input,
      [eval_context, location, cb = std::move(cb)](ErrOr<InputLocation> global_location,
                                                   std::optional<uint32_t> size) mutable {
        if (global_location.has_error())
          return cb(global_location.err(), std::nullopt);

        // Possibly null.
        const ProcessSymbols* process_symbols = eval_context->GetProcessSymbols();

        std::vector<InputLocation> result;
        if (process_symbols && global_location.value().type == InputLocation::Type::kName) {
          result =
              GetIdentifierMatchesOnThis(process_symbols, location, global_location.value().name);
        }

        // The global one always goes last so the most specific ones come first.
        result.push_back(global_location.take_value());

        cb(std::move(result), size);
      });
}

Err ResolveInputLocations(const ProcessSymbols* process_symbols, const Location& location,
                          const std::string& input, bool symbolize, std::vector<Location>* output) {
  std::vector<InputLocation> input_locations;
  if (Err err = ParseLocalInputLocation(process_symbols, location, input, &input_locations);
      err.has_error()) {
    return err;
  }
  return ResolveInputLocations(process_symbols, input_locations, symbolize, output);
}

Err ResolveInputLocations(const Frame* optional_frame, const std::string& input, bool symbolize,
                          std::vector<Location>* output) {
  const ProcessSymbols* process_symbols = nullptr;
  Location location;
  if (optional_frame) {
    process_symbols = optional_frame->GetThread()->GetProcess()->GetSymbols();
    location = optional_frame->GetLocation();
  }
  return ResolveInputLocations(process_symbols, location, input, symbolize, output);
}

Err ResolveInputLocations(const ProcessSymbols* process_symbols,
                          const std::vector<InputLocation>& input_locations, bool symbolize,
                          std::vector<Location>* locations) {
  ResolveOptions options;
  options.symbolize = symbolize;

  *locations = ResolvePermissiveInputLocations(process_symbols, options,
                                               FindNameContext(process_symbols), input_locations);

  if (locations->empty()) {
    if (input_locations.size() == 1) {
      return Err("Nothing matching this %s was found.",
                 InputLocation::TypeToString(input_locations[0].type));
    }
    return Err("Nothing matching this location was found.");
  }
  return Err();
}

Err ResolveUniqueInputLocation(const ProcessSymbols* process_symbols,
                               const InputLocation& input_location, bool symbolize,
                               Location* location) {
  return ResolveUniqueInputLocation(process_symbols, std::vector<InputLocation>{input_location},
                                    symbolize, location);
}

// This implementation isn't great, it doesn't always show the best disambiguations for the given
// input.
//
// Also it misses a file name edge case: If there is one file whose full path in the symbols is a
// right-side subset of another (say "foo/bar.cc" and "something/foo/bar.cc"), then "foo/bar.cc" is
// the most unique name of the first file. But if the user types that, they'll get both matches and
// this function will report an ambiguous location.
//
// Instead, if the input is a file name and there is only one result where the file name matches
// exactly, we should pick it.
Err ResolveUniqueInputLocation(const ProcessSymbols* process_symbols,
                               const std::vector<InputLocation>& input_location, bool symbolize,
                               Location* location) {
  std::vector<Location> locations;
  Err err = ResolveInputLocations(process_symbols, input_location, symbolize, &locations);
  if (err.has_error())
    return err;

  FX_DCHECK(!locations.empty());  // Non-empty on success should be guaranteed.

  if (locations.size() == 1u) {
    // Success, got a unique location.
    *location = locations[0];
    return Err();
  }

  // When there is more than one, generate an error that lists the possibilities for disambiguation.
  std::string err_str = "This resolves to more than one location. Could be:\n";
  constexpr size_t kMaxSuggestions = 10u;

  if (!symbolize) {
    // The original call did not request symbolization which will produce very
    // non-helpful suggestions. We're not concerned about performance in this error case so re-query
    // to get the full symbols.
    locations.clear();
    ResolveInputLocations(process_symbols, input_location, true, &locations);
  }

  for (size_t i = 0; i < locations.size() && i < kMaxSuggestions; i++) {
    // Always show the full path (omit TargetSymbols) since we're doing disambiguation and the
    // problem could have been two files with the same name but different paths.
    err_str += fxl::StringPrintf(" %s ", GetBullet().c_str());
    if (locations[i].file_line().is_valid()) {
      err_str += FormatFileLine(locations[i].file_line()).AsString();
      err_str += fxl::StringPrintf(" = 0x%" PRIx64, locations[i].address());
    } else {
      FormatLocationOptions opts;
      opts.always_show_addresses = true;
      err_str += FormatLocation(locations[i], opts).AsString();
    }
    err_str += "\n";
  }
  if (locations.size() > kMaxSuggestions) {
    err_str += fxl::StringPrintf("...%zu more omitted...\n", locations.size() - kMaxSuggestions);
  }
  return Err(err_str);
}

Err ResolveUniqueInputLocation(const ProcessSymbols* process_symbols, const Location& location,
                               const std::string& input, bool symbolize, Location* output) {
  std::vector<InputLocation> input_locations;
  if (Err err = ParseLocalInputLocation(process_symbols, location, input, &input_locations);
      err.has_error()) {
    return err;
  }
  return ResolveUniqueInputLocation(process_symbols, input_locations, symbolize, output);
}

Err ResolveUniqueInputLocation(const Frame* optional_frame, const std::string& input,
                               bool symbolize, Location* output) {
  const ProcessSymbols* process_symbols = nullptr;
  Location location;
  if (optional_frame) {
    process_symbols = optional_frame->GetThread()->GetProcess()->GetSymbols();
    location = optional_frame->GetLocation();
  }

  return ResolveUniqueInputLocation(process_symbols, location, input, symbolize, output);
}

void CompleteInputLocation(const Command& command, const std::string& prefix,
                           std::vector<std::string>* completions) {
  if (!command.target())
    return;

  // Number of items of each category that can be added to the completions.
  constexpr size_t kMaxFileNames = 32;
  constexpr size_t kMaxNamespaces = 8;
  constexpr size_t kMaxClasses = 32;
  constexpr size_t kMaxFunctions = 32;

  // Extract the current code block if possible. This will be used to find local variables and to
  // prioritize symbols from the current module.
  const CodeBlock* code_block = nullptr;
  SymbolContext symbol_context = SymbolContext::ForRelativeAddresses();
  if (const Frame* frame = command.frame()) {
    const Location& location = frame->GetLocation();
    if (const CodeBlock* fn_block = location.symbol().Get()->AsCodeBlock()) {
      symbol_context = location.symbol_context();
      code_block = fn_block->GetMostSpecificChild(symbol_context, location.address());
    }
  }

  // TODO(brettw) prioritize the current module when it's known (when there is a current frame with
  // symbol information). Factor prioritization code from find_name.cc
  for (const ModuleSymbols* mod : command.target()->GetSymbols()->GetModuleSymbols()) {
    const Index& index = mod->GetIndex();
    auto files = index.FindFilePrefixes(prefix);

    // Files get colons at the end for the user to type a line number next.
    for (auto& file : files)
      file.push_back(':');

    completions->insert(completions->end(), files.begin(), files.end());
  }

  std::sort(completions->begin(), completions->end());
  if (completions->size() > kMaxFileNames)
    completions->resize(kMaxFileNames);

  // Now search for functions matching the given input.
  FindNameOptions options(FindNameOptions::kNoKinds);
  options.how = FindNameOptions::kPrefix;

  ParsedIdentifier prefix_identifier;
  Err err = ExprParser::ParseIdentifier(prefix, &prefix_identifier);
  if (err.has_error())
    return;  // Can't match identifier names.

  // When there's a live process there is more context to find stuff.
  std::unique_ptr<FindNameContext> find_context;
  if (Process* process = command.target()->GetProcess()) {
    find_context =
        std::make_unique<FindNameContext>(process->GetSymbols(), symbol_context, code_block);
  } else {
    find_context = std::make_unique<FindNameContext>(command.target()->GetSymbols());
  }

  // First start with namespaces.
  options.find_namespaces = true;
  options.max_results = kMaxNamespaces;
  std::vector<FoundName> found_names;
  FindName(*find_context, options, prefix_identifier, &found_names);
  for (const FoundName& found : found_names)
    completions->push_back(found.GetName().GetFullName() + "::");
  options.find_namespaces = false;

  // Follow with types. Only do structure and class types since we're really looking for function
  // names. In the future it might be nice to check if there are any member functions in the types
  // before adding them.
  options.find_types = true;
  options.max_results = kMaxClasses;
  found_names.clear();
  FindName(*find_context, options, prefix_identifier, &found_names);
  for (const FoundName& found : found_names) {
    FX_DCHECK(found.kind() == zxdb::FoundName::kType);
    if (const Collection* collection = found.type()->AsCollection())
      completions->push_back(found.GetName().GetFullName() + "::");
  }
  options.find_types = false;

  // Finish with functions.
  options.find_functions = true;
  options.max_results = kMaxFunctions;
  found_names.clear();
  FindName(*find_context, options, prefix_identifier, &found_names);
  for (const FoundName& found : found_names) {
    // When completing names, globally qualify the names to prevent ambiguity.
    completions->push_back(found.function()->GetIdentifier().GetFullName());
  }
  options.find_functions = false;
}

}  // namespace zxdb
