brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.8 KiB · de9a15d Raw
110 lines · cpp
1//===-- CompletionsHandler.cpp --------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DAP.h"10#include "JSONUtils.h"11#include "Protocol/ProtocolRequests.h"12#include "Protocol/ProtocolTypes.h"13#include "RequestHandler.h"14#include "lldb/API/SBStringList.h"15 16using namespace llvm;17using namespace lldb_dap;18using namespace lldb_dap::protocol;19 20namespace lldb_dap {21 22/// Returns a list of possible completions for a given caret position and text.23///24/// Clients should only call this request if the corresponding capability25/// `supportsCompletionsRequest` is true.26Expected<CompletionsResponseBody>27CompletionsRequestHandler::Run(const CompletionsArguments &args) const {28  // If we have a frame, try to set the context for variable completions.29  lldb::SBFrame frame = dap.GetLLDBFrame(args.frameId);30  if (frame.IsValid()) {31    frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());32    frame.GetThread().SetSelectedFrame(frame.GetFrameID());33  }34 35  std::string text = args.text;36  auto original_column = args.column;37  auto original_line = args.line;38  auto offset = original_column - 1;39  if (original_line > 1) {40    SmallVector<StringRef, 2> lines;41    StringRef(text).split(lines, '\n');42    for (int i = 0; i < original_line - 1; i++) {43      offset += lines[i].size();44    }45  }46 47  std::vector<CompletionItem> targets;48 49  bool had_escape_prefix =50      StringRef(text).starts_with(dap.configuration.commandEscapePrefix);51  ReplMode completion_mode = dap.DetectReplMode(frame, text, true);52 53  // Handle the offset change introduced by stripping out the54  // `command_escape_prefix`.55  if (had_escape_prefix) {56    if (offset <57        static_cast<int64_t>(dap.configuration.commandEscapePrefix.size())) {58      return CompletionsResponseBody{std::move(targets)};59    }60    offset -= dap.configuration.commandEscapePrefix.size();61  }62 63  // While the user is typing then we likely have an incomplete input and cannot64  // reliably determine the precise intent (command vs variable), try completing65  // the text as both a command and variable expression, if applicable.66  const std::string expr_prefix = "expression -- ";67  std::array<std::tuple<ReplMode, std::string, uint64_t>, 2> exprs = {68      {std::make_tuple(ReplMode::Command, text, offset),69       std::make_tuple(ReplMode::Variable, expr_prefix + text,70                       offset + expr_prefix.size())}};71  for (const auto &[mode, line, cursor] : exprs) {72    if (completion_mode != ReplMode::Auto && completion_mode != mode)73      continue;74 75    lldb::SBStringList matches;76    lldb::SBStringList descriptions;77    if (!dap.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(78            line.c_str(), cursor, 0, 100, matches, descriptions))79      continue;80 81    // The first element is the common substring after the cursor position for82    // all the matches. The rest of the elements are the matches so ignore the83    // first result.84    for (size_t i = 1; i < matches.GetSize(); i++) {85      std::string match = matches.GetStringAtIndex(i);86      std::string description = descriptions.GetStringAtIndex(i);87 88      CompletionItem item;89      StringRef match_ref = match;90      for (StringRef commit_point : {".", "->"}) {91        if (match_ref.contains(commit_point)) {92          match_ref = match_ref.rsplit(commit_point).second;93        }94      }95      item.text = match_ref;96 97      if (description.empty())98        item.label = match;99      else100        item.label = match + " -- " + description;101 102      targets.emplace_back(std::move(item));103    }104  }105 106  return CompletionsResponseBody{std::move(targets)};107}108 109} // namespace lldb_dap110