// 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/found_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 {
const char kMissingFileError[] =
    R"(There is no file name to use in the current context. Either specify a
file and line number (e.g. main.cc:23), or ensure the process is stopped (try
`pause`) and the file that you want to stop in is the active stack frame with
`frame` to use line numbers with a contextual file name.

See `help break` for details.)";

// 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()->As<CodeBlock>();
  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(':');
  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()->As<CodeBlock>()) {
      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 (found.type()->As<Collection>())
      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
