================
@@ -7,103 +7,157 @@
//===----------------------------------------------------------------------===//
#include "DAP.h"
-#include "JSONUtils.h"
+#include "LLDBUtils.h"
#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
#include "RequestHandler.h"
#include "lldb/API/SBStringList.h"
+#include "llvm/Support/ConvertUTF.h"
using namespace llvm;
using namespace lldb_dap;
+using namespace lldb;
using namespace lldb_dap::protocol;
namespace lldb_dap {
+/// Gets the position in the UTF8 string where the specified line started.
+static size_t GetLineStartPos(llvm::StringRef text, uint32_t line) {
+ if (line == 0) // Invalid line.
+ return llvm::StringRef::npos;
+
+ if (line == 1)
+ return 0;
+
+ uint32_t cur_line = 1;
+ size_t pos = 0;
+
+ while (cur_line < line) {
+ const size_t new_line_pos = text.find('\n', pos);
+
+ if (new_line_pos == llvm::StringRef::npos) {
+ return new_line_pos;
+ }
+
+ pos = new_line_pos + 1;
+ // text may end with a new line
+ if (pos >= text.size())
+ return llvm::StringRef::npos;
+
+ cur_line++;
+ }
+
+ assert(pos < text.size());
+ return pos;
+}
+
+static std::optional<size_t> GetCursorPos(llvm::StringRef text, uint32_t line,
+ uint32_t utf16_codeunits) {
+ if (text.empty())
+ return std::nullopt;
+
+ const size_t line_start_pos = GetLineStartPos(text, line);
+ if (line_start_pos == llvm::StringRef::npos)
+ return std::nullopt;
+
+ const llvm::StringRef completion_line =
+ text.substr(line_start_pos, text.find('\n', line_start_pos));
+ if (completion_line.empty())
+ return std::nullopt;
+
+ const std::optional<size_t> cursor_pos_opt =
+ UTF16CodeunitToBytes(completion_line, utf16_codeunits);
+ if (!cursor_pos_opt)
+ return std::nullopt;
+
+ const size_t cursor_pos = line_start_pos + *cursor_pos_opt;
+ return cursor_pos;
+}
/// Returns a list of possible completions for a given caret position and text.
///
/// Clients should only call this request if the corresponding capability
/// `supportsCompletionsRequest` is true.
Expected<CompletionsResponseBody>
CompletionsRequestHandler::Run(const CompletionsArguments &args) const {
+ std::string text = args.text;
----------------
da-viper wrote:
the column is measured in code unit.
If we convert the string to UTF-16, it does not tell us how many bytes we need
to move the cursor by. so we end up converting from the offset back to UTF-8
and checking if its valid UTF-8.
something like
```cpp
// completion request input
int codeunit = 2;
std::string text = "fƒ";
llvm::SmallVector<UTF16, 10> dest;
llvm::convertUTF8ToUTF16String(text, dest); // convert to UTF-16
llvm::ArrayRef<UTF16> input(dest.begin(), dest.begin() + codeunit); // get
characters until the codeunit.
std::string out_str;
llvm::convertUTF16ToUTF8String(input, out_str); // convert back to UTF-8
llvm::isLegalUTF8String(...) // check it is valid and add it to the cursor
offset.
const auto matches = out_str.size() == 3; // f -> 1 byte and ƒ -> 2 byte
// view it normally
auto view = std::wstring(dest.begin(), dest.end());
```
https://github.com/llvm/llvm-project/pull/176211
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits