mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 19:06:33 +00:00
[lldb-dap] Adding a DAPError for showing users error messages. (#132255)
The `DAPError` can be used to craft an error message that is displayed to a user (with showUser=true). Any request handler implementation using subclassing `RequestHandler<>` should be able to use this. I updated SourceRequestHandler to report DAPError's specifically.
This commit is contained in:
parent
ff21b50509
commit
30bb0c443e
@ -18,6 +18,7 @@ add_lldb_tool(lldb-dap
|
||||
Breakpoint.cpp
|
||||
BreakpointBase.cpp
|
||||
DAP.cpp
|
||||
DAPError.cpp
|
||||
DAPLog.cpp
|
||||
EventHelper.cpp
|
||||
ExceptionBreakpoint.cpp
|
||||
|
29
lldb/tools/lldb-dap/DAPError.cpp
Normal file
29
lldb/tools/lldb-dap/DAPError.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
//===-- DAPError.cpp ------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DAPError.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <system_error>
|
||||
|
||||
namespace lldb_dap {
|
||||
|
||||
char DAPError::ID;
|
||||
|
||||
DAPError::DAPError(std::string message, std::error_code EC, bool show_user,
|
||||
std::optional<std::string> url,
|
||||
std::optional<std::string> url_label)
|
||||
: m_message(message), m_ec(EC), m_show_user(show_user), m_url(url),
|
||||
m_url_label(url_label) {}
|
||||
|
||||
void DAPError::log(llvm::raw_ostream &OS) const { OS << m_message; }
|
||||
|
||||
std::error_code DAPError::convertToErrorCode() const {
|
||||
return llvm::inconvertibleErrorCode();
|
||||
}
|
||||
|
||||
} // namespace lldb_dap
|
43
lldb/tools/lldb-dap/DAPError.h
Normal file
43
lldb/tools/lldb-dap/DAPError.h
Normal file
@ -0,0 +1,43 @@
|
||||
//===-- DAPError.h --------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
namespace lldb_dap {
|
||||
|
||||
/// An Error that is reported as a DAP Error Message, which may be presented to
|
||||
/// the user.
|
||||
class DAPError : public llvm::ErrorInfo<DAPError> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
DAPError(std::string message,
|
||||
std::error_code EC = llvm::inconvertibleErrorCode(),
|
||||
bool show_user = true, std::optional<std::string> url = std::nullopt,
|
||||
std::optional<std::string> url_label = std::nullopt);
|
||||
|
||||
void log(llvm::raw_ostream &OS) const override;
|
||||
std::error_code convertToErrorCode() const override;
|
||||
|
||||
const std::string &getMessage() const { return m_message; }
|
||||
bool getShowUser() const { return m_show_user; }
|
||||
const std::optional<std::string> &getURL() const { return m_url; }
|
||||
const std::optional<std::string> &getURLLabel() const { return m_url; }
|
||||
|
||||
private:
|
||||
std::string m_message;
|
||||
std::error_code m_ec;
|
||||
bool m_show_user;
|
||||
std::optional<std::string> m_url;
|
||||
std::optional<std::string> m_url_label;
|
||||
};
|
||||
|
||||
} // namespace lldb_dap
|
@ -10,11 +10,13 @@
|
||||
#define LLDB_TOOLS_LLDB_DAP_HANDLER_HANDLER_H
|
||||
|
||||
#include "DAP.h"
|
||||
#include "DAPError.h"
|
||||
#include "DAPLog.h"
|
||||
#include "Protocol/ProtocolBase.h"
|
||||
#include "Protocol/ProtocolRequests.h"
|
||||
#include "lldb/API/SBError.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/JSON.h"
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
@ -118,20 +120,38 @@ class RequestHandler : public BaseRequestHandler {
|
||||
std::string parse_failure;
|
||||
llvm::raw_string_ostream OS(parse_failure);
|
||||
root.printErrorContext(request.arguments, OS);
|
||||
|
||||
protocol::ErrorMessage error_message;
|
||||
error_message.format = parse_failure;
|
||||
|
||||
protocol::ErrorResponseBody body;
|
||||
body.error = error_message;
|
||||
|
||||
response.success = false;
|
||||
response.message = parse_failure;
|
||||
response.body = std::move(body);
|
||||
|
||||
dap.Send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
auto body = Run(arguments);
|
||||
// FIXME: Add a dedicated DAPError for enhanced errors that are
|
||||
// user-visibile.
|
||||
llvm::Expected<Body> body = Run(arguments);
|
||||
if (auto Err = body.takeError()) {
|
||||
protocol::ErrorMessage error_message;
|
||||
error_message.sendTelemetry = false;
|
||||
if (llvm::Error unhandled = llvm::handleErrors(
|
||||
std::move(Err), [&](const DAPError &E) -> llvm::Error {
|
||||
error_message.format = E.getMessage();
|
||||
error_message.showUser = E.getShowUser();
|
||||
error_message.id = E.convertToErrorCode().value();
|
||||
error_message.url = E.getURL();
|
||||
error_message.urlLabel = E.getURLLabel();
|
||||
return llvm::Error::success();
|
||||
}))
|
||||
error_message.format = llvm::toString(std::move(unhandled));
|
||||
protocol::ErrorResponseBody body;
|
||||
body.error = error_message;
|
||||
response.success = false;
|
||||
// FIXME: Build ErrorMessage based on error details instead of using the
|
||||
// 'message' field.
|
||||
response.message = llvm::toString(std::move(Err));
|
||||
response.body = std::move(body);
|
||||
} else {
|
||||
response.success = true;
|
||||
if constexpr (!std::is_same_v<Body, std::monostate>)
|
||||
|
@ -29,7 +29,7 @@ SourceRequestHandler::Run(const protocol::SourceArguments &args) const {
|
||||
args.source->sourceReference.value_or(args.sourceReference);
|
||||
|
||||
if (!source)
|
||||
return llvm::createStringError(
|
||||
return llvm::make_error<DAPError>(
|
||||
"invalid arguments, expected source.sourceReference to be set");
|
||||
|
||||
lldb::SBProcess process = dap.target.GetProcess();
|
||||
@ -39,7 +39,7 @@ SourceRequestHandler::Run(const protocol::SourceArguments &args) const {
|
||||
// Lower 32 bits is the frame index
|
||||
lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(source));
|
||||
if (!frame.IsValid())
|
||||
return llvm::createStringError("source not found");
|
||||
return llvm::make_error<DAPError>("source not found");
|
||||
|
||||
lldb::SBInstructionList insts = frame.GetSymbol().GetInstructions(dap.target);
|
||||
lldb::SBStream stream;
|
||||
|
@ -286,4 +286,13 @@ json::Value toJSON(const Message &M) {
|
||||
return std::visit([](auto &M) { return toJSON(M); }, M);
|
||||
}
|
||||
|
||||
json::Value toJSON(const ErrorResponseBody &E) {
|
||||
json::Object result{};
|
||||
|
||||
if (E.error)
|
||||
result.insert({"error", *E.error});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace lldb_dap::protocol
|
||||
|
@ -109,7 +109,7 @@ struct ErrorMessage {
|
||||
/// requirement that every user visible error message needs a corresponding
|
||||
/// error number, so that users or customer support can find information about
|
||||
/// the specific error more easily.
|
||||
uint64_t id;
|
||||
uint64_t id = 0;
|
||||
|
||||
/// A format string for the message. Embedded variables have the form
|
||||
/// `{name}`. If variable name starts with an underscore character, the
|
||||
@ -122,10 +122,10 @@ struct ErrorMessage {
|
||||
std::optional<std::map<std::string, std::string>> variables;
|
||||
|
||||
/// If true send to telemetry.
|
||||
bool sendTelemetry;
|
||||
bool sendTelemetry = false;
|
||||
|
||||
/// If true show user.
|
||||
bool showUser;
|
||||
bool showUser = false;
|
||||
|
||||
/// A url where additional information about this message can be found.
|
||||
std::optional<std::string> url;
|
||||
@ -141,6 +141,13 @@ using Message = std::variant<Request, Response, Event>;
|
||||
bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path);
|
||||
llvm::json::Value toJSON(const Message &);
|
||||
|
||||
/// On error (whenever `success` is false), the body can provide more details.
|
||||
struct ErrorResponseBody {
|
||||
/// A structured error message.
|
||||
std::optional<ErrorMessage> error;
|
||||
};
|
||||
llvm::json::Value toJSON(const ErrorResponseBody &);
|
||||
|
||||
/// This is just an acknowledgement, so no body field is required.
|
||||
using VoidResponse = std::monostate;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user