// 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/format_context.h"

#include <algorithm>
#include <vector>

#include "src/developer/debug/zxdb/client/arch_info.h"
#include "src/developer/debug/zxdb/client/disassembler.h"
#include "src/developer/debug/zxdb/client/memory_dump.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/common/file_util.h"
#include "src/developer/debug/zxdb/common/string_util.h"
#include "src/developer/debug/zxdb/console/command_utils.h"
#include "src/developer/debug/zxdb/console/console.h"
#include "src/developer/debug/zxdb/console/format_location.h"
#include "src/developer/debug/zxdb/console/format_table.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/string_util.h"
#include "src/developer/debug/zxdb/expr/expr_tokenizer.h"
#include "src/developer/debug/zxdb/expr/keywords.h"
#include "src/developer/debug/zxdb/symbols/input_location.h"
#include "src/developer/debug/zxdb/symbols/loaded_module_symbols.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/resolve_options.h"
#include "src/developer/debug/zxdb/symbols/source_file_provider.h"
#include "src/developer/debug/zxdb/symbols/source_util.h"
#include "src/lib/files/file.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

// Lines of source code context to show (before, after) the current line.
using ContextLines = std::pair<int64_t, int64_t>;
using LineInfo = std::pair<int, std::string>;  // Line #, Line contents.
using LineVector = std::vector<LineInfo>;

ContextLines GetContextLinesSettings(const SettingStore& settings) {
  return std::make_pair(settings.GetInt(ClientSettings::System::kContextLinesBefore),
                        settings.GetInt(ClientSettings::System::kContextLinesAfter));
}

OutputBuffer FormatSourceLineNoSyntax(const FormatSourceOpts& opts, bool is_highlight_line,
                                      const std::string& line) {
  if (!is_highlight_line) {
    // Non-highlighted lines just get output in either regular or dim.
    Syntax syntax = opts.dim_others ? Syntax::kComment : Syntax::kNormal;
    return OutputBuffer(syntax, line);
  }

  // Highlighted lines may need part of the line highligted or all of it. Convert the colum to
  // 0-based with clamping (since the offsets come from symbols, they could be invalid).
  int line_size = static_cast<int>(line.size());
  int col_index = std::min(std::max(0, opts.highlight_column - 1), line_size);

  OutputBuffer result;
  if (col_index == 0) {
    result.Append(Syntax::kHeading, line);
  } else {
    result.Append(Syntax::kNormal, line.substr(0, col_index));
    if (col_index < line_size)
      result.Append(Syntax::kHeading, line.substr(col_index));
  }
  return result;
}

struct SyntaxVariants {
  SyntaxVariants(Syntax normal_in, Syntax dim_in, Syntax bold_in)
      : normal(normal_in), dim(dim_in), bold(bold_in) {}
  Syntax normal;
  Syntax dim;
  Syntax bold;
};

SyntaxVariants SyntaxForTokenType(ExprTokenType type) {
  // Normal names and such.
  if (type == ExprTokenType::kInvalid || type == ExprTokenType::kName)
    return SyntaxVariants(Syntax::kNormal, Syntax::kComment, Syntax::kHeading);

  // Numbers. Treat true and false as numbers as well.
  if (type == ExprTokenType::kFloat || type == ExprTokenType::kInteger ||
      type == ExprTokenType::kTrue || type == ExprTokenType::kFalse)
    return SyntaxVariants(Syntax::kNumberNormal, Syntax::kNumberDim, Syntax::kNumberBold);

  // Strings.
  if (type == ExprTokenType::kStringLiteral)
    return SyntaxVariants(Syntax::kStringNormal, Syntax::kStringDim, Syntax::kStringBold);

  // Comments.
  if (type == ExprTokenType::kComment)
    return SyntaxVariants(Syntax::kComment, Syntax::kComment, Syntax::kComment);

  // Assume everything that's an alphanumeric token is a keyword. Count Rust lifetimes as keywords
  // also since they're special language things.
  const ExprTokenRecord& record = RecordForTokenType(type);
  if (record.is_alphanum || type == ExprTokenType::kRustLifetime)
    return SyntaxVariants(Syntax::kKeywordNormal, Syntax::kKeywordDim, Syntax::kKeywordBold);

  // Everything else is an operator.
  return SyntaxVariants(Syntax::kOperatorNormal, Syntax::kOperatorDim, Syntax::kOperatorBold);
}

// Assumes a valid nonempty token list.
OutputBuffer FormatSourceLineWithTokens(const FormatSourceOpts& opts, bool is_highlight_line,
                                        const std::string& line,
                                        const std::vector<ExprToken>& tokens) {
  FX_DCHECK(!tokens.empty());
  FX_DCHECK(opts.language);

  // The code here always uses the text from the source file. We always want to show the literal
  // source rather than what the tokenizer interpreted it as (though normally these will be the
  // same).
  OutputBuffer out;

  // Specially handle C preprocessor and Rust attributes. Assume these lines start with a "#" and
  // ignore everything after it. Since this code is line-based anyway, the lack of multiline support
  // for these constructs isn't an additional limitation. This just makes the typical uses look
  // better.
  if (tokens[0].type() == ExprTokenType::kOctothorpe) {
    out.Append(Syntax::kComment, line);
    return out;
  }

  // Construct a list of ranges indicating the syntax type. The last item will reference the end of
  // the list to make end conditions easier to handle.
  using OffsetType = std::pair<size_t, ExprTokenType>;
  std::vector<OffsetType> spans;
  if (tokens[0].byte_offset() > 0)  // Stuff before first token (normally whitespace).
    spans.emplace_back(0, ExprTokenType::kInvalid);

  const std::set<std::string>& keywords = AllKeywordsForLanguage(*opts.language, true);
  for (const auto& token : tokens) {
    // The tokenizer doesn't kave tokens for all keywords. Check the name to see if it's a common
    // builtin to annotate accordingly.
    if (token.type() == ExprTokenType::kName && keywords.find(token.value()) != keywords.end()) {
      // Keyword or quasi-built-in. Since there's no general "keyword" token type, assign these all
      // to the "if" token which will trigger the keyword formatting.
      spans.emplace_back(token.byte_offset(), ExprTokenType::kIf);
    } else if (token.type() == ExprTokenType::kCommentBlockEnd) {
      // We have a "*/" on a line. Assume that everything before it was actually a comment and
      // we just didn't see the opening "/*" on a previous line.
      spans.clear();
      spans.emplace_back(0, ExprTokenType::kComment);
    } else {
      // All other tokens.
      spans.emplace_back(token.byte_offset(), token.type());
    }
  }
  spans.emplace_back(line.size(), ExprTokenType::kInvalid);  // End boundary.

  // Convert spans to formatted text. Skip the last once since that's the dummy span at the end.
  for (size_t i = 0; i < spans.size() - 1; i++) {
    // Since we added a dummy span at the end not covered by the loop, there will always be a next
    // span.
    size_t begin_offset = spans[i].first;
    size_t end_offset = spans[i + 1].first;
    if (begin_offset == end_offset)
      continue;

    SyntaxVariants variants = SyntaxForTokenType(spans[i].second);
    Syntax syntax = variants.normal;
    if (!is_highlight_line) {
      // Non-highlighted lines just get output in either regular or dim.
      if (opts.dim_others)
        syntax = variants.dim;
    } else {
      // Highlighted line, Anything past the (1-based) colum gets bolded, everything else is normal.
      if (static_cast<int>(begin_offset) >= opts.highlight_column - 1)
        syntax = variants.bold;
    }

    out.Append(syntax, line.substr(begin_offset, end_offset - begin_offset));
  }

  return out;
}

// Retrieves the proper MOduleSymbols (or null) for the given location as a weak pointer. This is
// used to compute the right module to ask for out-of-date file warnings.
fxl::WeakPtr<ModuleSymbols> GetWeakModuleForLocation(Process* process, const Location& location) {
  if (LoadedModuleSymbols* loaded_sym =
          process->GetSymbols()->GetModuleForAddress(location.address()))
    return loaded_sym->module_symbols()->GetWeakPtr();
  return fxl::WeakPtr<ModuleSymbols>();
}

// Generates the source listing for source intersperced with assembly code for the source between
// the given two lines. The prev_line is the last one outputted.
//
// This re-opens and line splits the file for each block of source shown. This is very inefficient
// but normally disassembly is not performance sensitive. If needed this could be cached.
//
// The module_for_time_warning is an optional pointer to the module corresponding to this source
// file so we can show warnings if the build is out-of-date.
OutputBuffer FormatAsmSourceForRange(Process* process,
                                     fxl::WeakPtr<ModuleSymbols> module_for_time_warning,
                                     const SourceFileProvider& file_provider,
                                     const FileLine& prev_line, const FileLine& line) {
  // Maximum number of lines of source we'll include.
  constexpr int kMaxContext = 4;

  int first_num = line.line() - kMaxContext + 1;  // Most context we'll show.
  if (prev_line.file() == line.file())            // Same file, try to include since the last line.
    first_num = std::max(prev_line.line() + 1, first_num);
  first_num = std::max(1, first_num);  // Clamp to beginning of file.

  FormatSourceOpts opts;
  opts.first_line = first_num;
  opts.last_line = line.line();
  opts.left_indent = 2;
  opts.dim_others = true;  // Dim everything (we didn't specify an active line).
  opts.module_for_time_warning = std::move(module_for_time_warning);

  FileLine start_line(line.file(), line.comp_dir(), first_num);
  OutputBuffer out;
  if (FormatSourceFileContext(start_line, file_provider, opts, &out).ok()) {
    // The formatted table will end in a newline which will combine with our table's newline and
    // insert a blank below the source code. Trim the embedded newline so we only get one.
    out.TrimTrailingNewlines();
    return out;
  }

  // Some error getting the source code, show the location file/line number instead.
  return FormatFileLine(start_line, process->GetSymbols()->target_symbols());
}

// Describes the destination for the given call destination, formatted as for a disassembly. The
// process may be null which will mean only addresses will be printed, no symbols.
OutputBuffer DescribeAsmCallDest(Process* process, uint64_t call_dest) {
  OutputBuffer result(Syntax::kComment, GetRightArrow() + " ");

  std::vector<Location> resolved;
  if (process) {
    // If there are multiple symbols starting at the given location (like nested inline calls), use
    // the outermost one since this is a jump *to* that location.
    ResolveOptions options;
    options.ambiguous_inline = ResolveOptions::AmbiguousInline::kOuter;

    resolved = process->GetSymbols()->ResolveInputLocation(InputLocation(call_dest), options);
    FX_DCHECK(resolved.size() == 1);  // Addresses should always match one location.
  } else {
    // Can't symbolize, use the address.
    resolved.emplace_back(Location(Location::State::kAddress, call_dest));
  }

  FormatLocationOptions opts;
  if (process)
    opts = FormatLocationOptions(process->GetTarget());
  opts.always_show_addresses = false;
  opts.show_file_line = false;

  result.Append(FormatLocation(resolved[0], opts));
  return result;
}

}  // namespace

void FormatSourceOpts::SetLanguageFromFileName(const std::string& file_name) {
  language = FileNameToLanguage(file_name);
  if (!language) {
    // Default to C for anything still unknown because it should give reasonable highlighting for
    // most languages.
    language = ExprLanguage::kC;
  }
}

Err OutputSourceContext(Process* process, std::unique_ptr<SourceFileProvider> file_provider,
                        const Location& location, SourceAffinity source_affinity) {
  FX_DCHECK(file_provider);
  if (source_affinity != SourceAffinity::kAssembly && location.file_line().is_valid()) {
    ContextLines context = GetContextLinesSettings(process->session()->system().settings());
    // Synchronous source output.
    FormatSourceOpts source_opts;
    source_opts.active_line = location.file_line().line();
    source_opts.highlight_line = source_opts.active_line;
    source_opts.highlight_column = location.column();
    source_opts.first_line = source_opts.active_line - context.first;
    source_opts.last_line = source_opts.active_line + context.second;
    source_opts.dim_others = true;
    source_opts.module_for_time_warning = GetWeakModuleForLocation(process, location);

    if (const Symbol* sym = location.symbol().Get())
      source_opts.language = DwarfLangToExprLanguage(sym->GetLanguage());

    OutputBuffer out;
    Err err = FormatSourceFileContext(location.file_line(), *file_provider, source_opts, &out);
    if (err.has_error())
      return err;

    Console::get()->Output(out);
  } else {
    // Fall back to disassembly.
    FormatAsmOpts options;
    options.emit_addresses = true;
    options.emit_bytes = false;
    options.include_source = true;
    options.active_address = location.address();

    uint64_t start_address;
    const ArchInfo& arch_info = process->session()->arch_info();
    if (arch_info.is_fixed_instr()) {
      // Fixed instruction length, back up 2 instructions to provide context.
      start_address = location.address() - 2 * arch_info.max_instr_len();
      options.max_instructions = 5;
    } else {
      // Variable length instructions. Since this code path is triggered when
      // there are no symbols, we can't back up reliably. Just disassemble
      // starting from the current location.
      //
      // In the future it might be nice to keep some record of recently stepped
      // instructions since usually this address will be the one after the one
      // that was just stepped.
      start_address = location.address();
      options.max_instructions = 4;
    }

    size_t size = options.max_instructions * arch_info.max_instr_len();

    process->ReadMemory(
        start_address, size,
        [options, weak_process = process->GetWeakPtr(), file_provider = std::move(file_provider)](
            const Err& in_err, MemoryDump dump) {
          if (!weak_process)
            return;  // Give up when the process went away.

          Console* console = Console::get();
          if (in_err.has_error()) {
            console->Output(in_err);
            return;
          }
          OutputBuffer out;
          Err err = FormatAsmContext(weak_process->session()->arch_info(), dump, options,
                                     weak_process.get(), *file_provider, &out);
          if (err.has_error())
            console->Output(err);
          else
            console->Output(out);
        });
  }
  return Err();
}

// This doesn't cache the file contents. We may want to add that for performance, but we should be
// careful to always pick the latest version since it can get updated.
Err FormatSourceFileContext(const FileLine& file_line, const SourceFileProvider& file_provider,
                            const FormatSourceOpts& opts, OutputBuffer* out) {
  auto data_or = file_provider.GetFileData(file_line.file(), file_line.comp_dir());
  if (data_or.has_error())
    return data_or.err();

  // Check modification times for warning about out-of-date builds.
  if (opts.module_for_time_warning) {
    // Either of the times can be 0 if there was an error. Ignore the check in that case.
    std::time_t module_time = opts.module_for_time_warning->GetModificationTime();
    std::time_t file_time = data_or.value().modification_time;
    if (module_time && file_time && file_time > module_time) {
      // File is known out-of-date. Only show warning once for each file per module.
      if (opts.module_for_time_warning->newer_files_warned().insert(file_line.file()).second) {
        out->Append(Syntax::kWarning, GetExclamation() + " Warning:");
        out->Append(" Source file is newer than the binary. The build may be out-of-date.\n");
      }
    }
  }

  return FormatSourceContext(data_or.value().full_path, data_or.value().contents, opts, out);
}

Err FormatSourceContext(const std::string& file_name_for_display, const std::string& file_contents,
                        const FormatSourceOpts& opts, OutputBuffer* out) {
  FX_DCHECK(opts.active_line == 0 || !opts.require_active_line ||
            (opts.active_line >= opts.first_line && opts.active_line <= opts.last_line));

  // Allow the beginning to be out-of-range. This mirrors the end handling
  // (clamped to end-of-file) so callers can blindly create offsets from
  // a current line without clamping.
  int first_line = std::max(1, opts.first_line);

  std::vector<std::string> context = ExtractSourceLines(file_contents, first_line, opts.last_line);
  if (context.empty()) {
    // No source found for this location. If highlight_line exists, assume
    // it's the one the user cares about.
    int err_line = opts.highlight_line ? opts.highlight_line : first_line;
    return Err(fxl::StringPrintf("There is no line %d in the file %s", err_line,
                                 file_name_for_display.c_str()));
  }
  if (opts.active_line != 0 && opts.require_active_line &&
      first_line + static_cast<int>(context.size()) < opts.active_line) {
    return Err(fxl::StringPrintf("There is no line %d in the file %s", opts.active_line,
                                 file_name_for_display.c_str()));
  }

  // Optional file name.
  if (opts.show_file_name) {
    out->Append("📄 ");
    out->Append(Syntax::kFileName, file_name_for_display);
    out->Append("\n");
  }

  // String to put at the beginning of each line.
  std::string indent(opts.left_indent, ' ');

  std::vector<std::vector<OutputBuffer>> rows;
  for (size_t i = 0; i < context.size(); i++) {
    int line_number = first_line + i;

    rows.emplace_back();
    std::vector<OutputBuffer>& row = rows.back();

    // Compute markers in the left margin.
    OutputBuffer margin;
    if (opts.left_indent)
      margin.Append(indent);

    auto found_bp = opts.bp_lines.find(line_number);
    if (found_bp != opts.bp_lines.end()) {
      std::string breakpoint_marker =
          found_bp->second ? GetBreakpointMarker() : GetDisabledBreakpointMarker();

      if (line_number == opts.active_line) {
        // Active + breakpoint.
        margin.Append(Syntax::kError, breakpoint_marker);
        margin.Append(Syntax::kHeading, GetCurrentRowMarker());
      } else {
        // Breakpoint.
        margin.Append(Syntax::kError, " " + breakpoint_marker);
      }
    } else {
      if (line_number == opts.active_line) {
        // Active line.
        margin.Append(Syntax::kHeading, " " + GetCurrentRowMarker());
      } else {
        // Inactive line with no breakpoint.
        margin.Append("  ");
      }
    }
    row.push_back(std::move(margin));

    std::string number = std::to_string(line_number);
    if (line_number == opts.highlight_line) {
      // This is the line to mark.
      row.emplace_back(Syntax::kHeading, std::move(number));
      row.push_back(FormatSourceLine(opts, true, context[i]));
    } else {
      // Normal context line.
      Syntax syntax = opts.dim_others ? Syntax::kComment : Syntax::kNormal;
      row.emplace_back(syntax, std::move(number));
      row.push_back(FormatSourceLine(opts, false, context[i]));
    }
  }

  FormatTable(
      {ColSpec(Align::kLeft), ColSpec(Align::kRight), ColSpec(Align::kLeft, 0, std::string(), 0)},
      rows, out);
  return Err();
}

Err FormatAsmContext(const ArchInfo& arch_info, const MemoryDump& dump, const FormatAsmOpts& opts,
                     Process* process, const SourceFileProvider& file_provider, OutputBuffer* out) {
  // Make the disassembler.
  Disassembler disassembler;
  Err my_err = disassembler.Init(&arch_info);
  if (my_err.has_error())
    return my_err;

  Disassembler::Options options;

  std::vector<Disassembler::Row> rows;
  disassembler.DisassembleDump(dump, dump.address(), options, opts.max_instructions, &rows);

  FileLine prev_file_line;  // Last source line printed.

  std::vector<std::vector<OutputBuffer>> table;
  for (auto& row : rows) {
    if (opts.include_source) {
      // Output source code if necessary.
      std::vector<Location> loc =
          process->GetSymbols()->ResolveInputLocation(InputLocation(row.address));
      if (!loc.empty() && loc[0].file_line().is_valid() && prev_file_line != loc[0].file_line()) {
        std::vector<OutputBuffer>& out_row = table.emplace_back();
        out_row.push_back(
            FormatAsmSourceForRange(process, GetWeakModuleForLocation(process, loc[0]),
                                    file_provider, prev_file_line, loc[0].file_line()));

        prev_file_line = loc[0].file_line();
      }
    }

    std::vector<OutputBuffer>& out_row = table.emplace_back();

    // Compute markers in the left margin.
    OutputBuffer margin;
    auto found_bp = opts.bp_addrs.find(row.address);
    if (found_bp != opts.bp_addrs.end()) {
      std::string breakpoint_marker =
          found_bp->second ? GetBreakpointMarker() : GetDisabledBreakpointMarker();

      if (row.address == opts.active_address) {
        // Active + breakpoint.
        margin.Append(Syntax::kError, breakpoint_marker);
        margin.Append(Syntax::kHeading, GetCurrentRowMarker());
      } else {
        // Breakpoint.
        margin.Append(Syntax::kError, " " + breakpoint_marker);
      }
    } else {
      if (row.address == opts.active_address) {
        // Active line.
        margin.Append(Syntax::kHeading, " " + GetCurrentRowMarker());
      } else {
        // Inactive line with no breakpoint.
        margin.Append("  ");
      }
    }
    out_row.push_back(std::move(margin));

    if (opts.emit_addresses)
      out_row.emplace_back(Syntax::kComment, to_hex_string(row.address));
    if (opts.emit_bytes) {
      std::string bytes_str;
      for (size_t i = 0; i < row.bytes.size(); i++) {
        if (i > 0)
          bytes_str.push_back(' ');
        bytes_str.append(fxl::StringPrintf("%2.2x", row.bytes[i]));
      }
      out_row.emplace_back(Syntax::kComment, std::move(bytes_str));
    }

    Syntax op_param_syntax =
        row.address == opts.active_address ? Syntax::kHeading : Syntax::kNormal;
    out_row.emplace_back(op_param_syntax, std::move(row.op));
    out_row.emplace_back(op_param_syntax, std::move(row.params));

    // If there's a call destination, include that. Otherwise use the disassembler-generated comment
    // if present.
    if (row.call_dest) {
      out_row.push_back(DescribeAsmCallDest(process, *row.call_dest));
    } else {
      out_row.emplace_back(Syntax::kComment, std::move(row.comment));
    }
  }

  std::vector<ColSpec> spec;
  spec.emplace_back(Align::kLeft);  // Margin.
  if (opts.emit_addresses)
    spec.emplace_back(Align::kRight);
  if (opts.emit_bytes) {
    // Max out the bytes @ 17 cols (holds 6 bytes) to keep it from pushing
    // things too far over in the common case.
    spec.emplace_back(Align::kLeft, 17, std::string(), 1);
  }

  // When there was an address or byte listing, put 1 extra column of space
  // to separate the opcode. Otherwise keep it by the left margin.
  if (spec.size() > 1)
    spec.emplace_back(Align::kLeft, 0, std::string(), 1);  // Instructions.
  else
    spec.emplace_back(Align::kLeft, 0, std::string(), 0);  // Instructions.

  // Params. Some can be very long so provide a max so the comments don't get
  // pushed too far out.
  spec.emplace_back(Align::kLeft, 10, std::string(), 1);
  spec.emplace_back(Align::kLeft);  // Comments.

  FormatTable(spec, table, out);
  return Err();
}

Err FormatBreakpointContext(const Location& location, const SourceFileProvider& file_provider,
                            bool enabled, OutputBuffer* out) {
  if (!location.has_symbols())
    return Err("No symbols for this location.");

  int line = location.file_line().line();
  ContextLines context =
      GetContextLinesSettings(Console::get()->context().session()->system().settings());

  FormatSourceOpts opts;
  opts.SetLanguageFromFileName(location.file_line().file());
  opts.first_line = line - context.first;
  opts.last_line = line + context.second;
  opts.highlight_line = line;
  opts.bp_lines[line] = enabled;
  return FormatSourceFileContext(location.file_line(), file_provider, opts, out);
}

OutputBuffer FormatSourceLine(const FormatSourceOpts& opts, bool is_highlight_line,
                              const std::string& line) {
  if (opts.language) {
    ExprTokenizer tokenizer(line, *opts.language);
    if (tokenizer.Tokenize() && !tokenizer.tokens().empty())
      return FormatSourceLineWithTokens(opts, is_highlight_line, line, tokenizer.tokens());
  }
  return FormatSourceLineNoSyntax(opts, is_highlight_line, line);
}

}  // namespace zxdb
