Skip to content

Commit 1d2e2d1

Browse files
Merge pull request swiftlang#9426 from adrian-prantl/cherry-pick-inline-diags
Cherry pick inline diagnostics
2 parents 266bc21 + e103979 commit 1d2e2d1

File tree

61 files changed

+6029
-9371
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+6029
-9371
lines changed

lldb/bindings/python/static-binding/LLDBWrapPython.cpp

Lines changed: 5134 additions & 9113 deletions
Large diffs are not rendered by default.

lldb/bindings/python/static-binding/lldb.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3755,6 +3755,10 @@ def IsValid(self):
37553755
r"""IsValid(SBCommandReturnObject self) -> bool"""
37563756
return _lldb.SBCommandReturnObject_IsValid(self)
37573757

3758+
def GetErrorData(self):
3759+
r"""GetErrorData(SBCommandReturnObject self) -> SBStructuredData"""
3760+
return _lldb.SBCommandReturnObject_GetErrorData(self)
3761+
37583762
def PutOutput(self, *args):
37593763
r"""
37603764
PutOutput(SBCommandReturnObject self, SBFile file) -> size_t
@@ -4968,6 +4972,10 @@ def GetUseColor(self):
49684972
r"""GetUseColor(SBDebugger self) -> bool"""
49694973
return _lldb.SBDebugger_GetUseColor(self)
49704974

4975+
def SetShowInlineDiagnostics(self, arg2):
4976+
r"""SetShowInlineDiagnostics(SBDebugger self, bool arg2) -> bool"""
4977+
return _lldb.SBDebugger_SetShowInlineDiagnostics(self, arg2)
4978+
49714979
def SetUseSourceCache(self, use_source_cache):
49724980
r"""SetUseSourceCache(SBDebugger self, bool use_source_cache) -> bool"""
49734981
return _lldb.SBDebugger_SetUseSourceCache(self, use_source_cache)

lldb/include/lldb/API/SBCommandReturnObject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class LLDB_API SBCommandReturnObject {
4545
const char *GetOutput();
4646

4747
const char *GetError();
48+
SBStructuredData GetErrorData();
4849

4950
#ifndef SWIG
5051
LLDB_DEPRECATED_FIXME("Use PutOutput(SBFile) or PutOutput(FileSP)",

lldb/include/lldb/API/SBDebugger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ class LLDB_API SBDebugger {
304304

305305
bool GetUseColor() const;
306306

307+
bool SetShowInlineDiagnostics(bool);
308+
307309
bool SetUseSourceCache(bool use_source_cache);
308310

309311
bool GetUseSourceCache() const;

lldb/include/lldb/API/SBStructuredData.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLDB_API_SBSTRUCTUREDDATA_H
1010
#define LLDB_API_SBSTRUCTUREDDATA_H
1111

12+
#include "lldb/API/SBCommandReturnObject.h"
1213
#include "lldb/API/SBDefines.h"
1314
#include "lldb/API/SBModule.h"
1415
#include "lldb/API/SBScriptObject.h"
@@ -110,6 +111,7 @@ class SBStructuredData {
110111

111112
protected:
112113
friend class SBAttachInfo;
114+
friend class SBCommandReturnObject;
113115
friend class SBLaunchInfo;
114116
friend class SBDebugger;
115117
friend class SBFrame;

lldb/include/lldb/Core/Debugger.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
368368

369369
const std::string &GetInstanceName() { return m_instance_name; }
370370

371+
bool GetShowInlineDiagnostics() const;
372+
373+
bool SetShowInlineDiagnostics(bool);
374+
371375
bool LoadPlugin(const FileSpec &spec, Status &error);
372376

373377
void RunIOHandlers();

lldb/include/lldb/Expression/DiagnosticManager.h

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "lldb/lldb-defines.h"
1313
#include "lldb/lldb-types.h"
1414

15+
#include "lldb/Utility/DiagnosticsRendering.h"
1516
#include "lldb/Utility/FileSpec.h"
1617
#include "lldb/Utility/Status.h"
1718

@@ -23,48 +24,22 @@
2324

2425
namespace lldb_private {
2526

26-
/// A compiler-independent representation of a Diagnostic. Expression
27-
/// evaluation failures often have more than one diagnostic that a UI
28-
/// layer might want to render differently, for example to colorize
29-
/// it.
30-
///
31-
/// Running example:
32-
/// (lldb) expr 1+foo
33-
/// error: <user expression 0>:1:3: use of undeclared identifier 'foo'
34-
/// 1+foo
35-
/// ^
36-
struct DiagnosticDetail {
37-
struct SourceLocation {
38-
FileSpec file;
39-
unsigned line = 0;
40-
uint16_t column = 0;
41-
uint16_t length = 0;
42-
bool in_user_input = false;
43-
};
44-
/// Contains {{}, 1, 3, 3, true} in the example above.
45-
std::optional<SourceLocation> source_location;
46-
/// Contains eSeverityError in the example above.
47-
lldb::Severity severity = lldb::eSeverityInfo;
48-
/// Contains "use of undeclared identifier 'x'" in the example above.
49-
std::string message;
50-
/// Contains the fully rendered error message.
51-
std::string rendered;
52-
};
53-
5427
/// An llvm::Error used to communicate diagnostics in Status. Multiple
5528
/// diagnostics may be chained in an llvm::ErrorList.
5629
class ExpressionError
57-
: public llvm::ErrorInfo<ExpressionError, ExpressionErrorBase> {
30+
: public llvm::ErrorInfo<ExpressionError, DiagnosticError> {
5831
std::string m_message;
5932
std::vector<DiagnosticDetail> m_details;
6033

6134
public:
6235
static char ID;
63-
using llvm::ErrorInfo<ExpressionError, ExpressionErrorBase>::ErrorInfo;
36+
using llvm::ErrorInfo<ExpressionError, DiagnosticError>::ErrorInfo;
6437
ExpressionError(lldb::ExpressionResults result, std::string msg,
6538
std::vector<DiagnosticDetail> details = {});
6639
std::string message() const override;
67-
llvm::ArrayRef<DiagnosticDetail> GetDetails() const { return m_details; }
40+
llvm::ArrayRef<DiagnosticDetail> GetDetails() const override {
41+
return m_details;
42+
}
6843
std::error_code convertToErrorCode() const override;
6944
void log(llvm::raw_ostream &OS) const override;
7045
std::unique_ptr<CloneableError> Clone() const override;

lldb/include/lldb/Interpreter/CommandObject.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,13 @@ class CommandObject : public std::enable_shared_from_this<CommandObject> {
340340
return false;
341341
}
342342

343+
/// Set the command input as it appeared in the terminal. This
344+
/// is used to have errors refer directly to the original command.
345+
void SetOriginalCommandString(std::string s) { m_original_command = s; }
346+
347+
/// \param offset_in_command is on what column \c args_string
348+
/// appears, if applicable. This enables diagnostics that refer back
349+
/// to the user input.
343350
virtual void Execute(const char *args_string,
344351
CommandReturnObject &result) = 0;
345352

@@ -404,6 +411,7 @@ class CommandObject : public std::enable_shared_from_this<CommandObject> {
404411
std::string m_cmd_help_short;
405412
std::string m_cmd_help_long;
406413
std::string m_cmd_syntax;
414+
std::string m_original_command;
407415
Flags m_flags;
408416
std::vector<CommandArgumentEntry> m_arguments;
409417
lldb::CommandOverrideCallback m_deprecated_command_override_callback;

lldb/include/lldb/Interpreter/CommandReturnObject.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#define LLDB_INTERPRETER_COMMANDRETURNOBJECT_H
1111

1212
#include "lldb/Host/StreamFile.h"
13+
#include "lldb/Utility/DiagnosticsRendering.h"
1314
#include "lldb/Utility/StreamString.h"
1415
#include "lldb/Utility/StreamTee.h"
16+
#include "lldb/Utility/StructuredData.h"
1517
#include "lldb/lldb-private.h"
1618

1719
#include "llvm/ADT/StringRef.h"
@@ -29,19 +31,23 @@ class CommandReturnObject {
2931

3032
~CommandReturnObject() = default;
3133

32-
llvm::StringRef GetOutputData() {
34+
/// Format any inline diagnostics with an indentation of \c indent.
35+
std::string GetInlineDiagnosticString(unsigned indent);
36+
37+
llvm::StringRef GetOutputString() {
3338
lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex));
3439
if (stream_sp)
3540
return std::static_pointer_cast<StreamString>(stream_sp)->GetString();
3641
return llvm::StringRef();
3742
}
3843

39-
llvm::StringRef GetErrorData() {
40-
lldb::StreamSP stream_sp(m_err_stream.GetStreamAtIndex(eStreamStringIndex));
41-
if (stream_sp)
42-
return std::static_pointer_cast<StreamString>(stream_sp)->GetString();
43-
return llvm::StringRef();
44-
}
44+
/// Return the errors as a string.
45+
///
46+
/// If \c with_diagnostics is true, all diagnostics are also
47+
/// rendered into the string. Otherwise the expectation is that they
48+
/// are fetched with \ref GetInlineDiagnosticString().
49+
std::string GetErrorString(bool with_diagnostics = true);
50+
StructuredData::ObjectSP GetErrorData();
4551

4652
Stream &GetOutputStream() {
4753
// Make sure we at least have our normal string stream output stream
@@ -131,10 +137,18 @@ class CommandReturnObject {
131137
AppendError(llvm::formatv(format, std::forward<Args>(args)...).str());
132138
}
133139

134-
void SetError(const Status &error, const char *fallback_error_cstr = nullptr);
140+
void SetError(Status error);
135141

136142
void SetError(llvm::Error error);
137143

144+
void SetDiagnosticIndent(std::optional<uint16_t> indent) {
145+
m_diagnostic_indent = indent;
146+
}
147+
148+
std::optional<uint16_t> GetDiagnosticIndent() const {
149+
return m_diagnostic_indent;
150+
}
151+
138152
lldb::ReturnStatus GetStatus() const;
139153

140154
void SetStatus(lldb::ReturnStatus status);
@@ -160,6 +174,8 @@ class CommandReturnObject {
160174

161175
StreamTee m_out_stream;
162176
StreamTee m_err_stream;
177+
std::vector<DiagnosticDetail> m_diagnostics;
178+
std::optional<uint16_t> m_diagnostic_indent;
163179

164180
lldb::ReturnStatus m_status = lldb::eReturnStatusStarted;
165181

@@ -168,6 +184,7 @@ class CommandReturnObject {
168184

169185
/// If true, then the input handle from the debugger will be hooked up.
170186
bool m_interactive = true;
187+
bool m_colors;
171188
};
172189

173190
} // namespace lldb_private

lldb/include/lldb/Utility/Args.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,23 @@ class Args {
3838

3939
std::unique_ptr<char[]> ptr;
4040
char quote = '\0';
41+
/// The position of the argument in the original argument string.
42+
std::optional<uint16_t> column;
4143

4244
char *data() { return ptr.get(); }
4345

4446
public:
4547
ArgEntry() = default;
46-
ArgEntry(llvm::StringRef str, char quote);
48+
ArgEntry(llvm::StringRef str, char quote, std::optional<uint16_t> column);
4749

4850
llvm::StringRef ref() const { return c_str(); }
4951
const char *c_str() const { return ptr.get(); }
5052

5153
/// Returns true if this argument was quoted in any way.
5254
bool IsQuoted() const { return quote != '\0'; }
5355
char GetQuoteChar() const { return quote; }
56+
std::optional<uint16_t> GetPos() const { return column; }
57+
size_t GetLength() const { return ref().size(); }
5458
};
5559

5660
/// Construct with an option command string.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===-- DiagnosticsRendering.h ----------------------------------*- C++ -*-===//
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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_UTILITY_DIAGNOSTICSRENDERING_H
10+
#define LLDB_UTILITY_DIAGNOSTICSRENDERING_H
11+
12+
#include "lldb/Utility/Status.h"
13+
#include "lldb/Utility/Stream.h"
14+
#include "llvm/Support/WithColor.h"
15+
16+
namespace lldb_private {
17+
18+
/// A compiler-independent representation of an \c
19+
/// lldb_private::Diagnostic. Expression evaluation failures often
20+
/// have more than one diagnostic that a UI layer might want to render
21+
/// differently, for example to colorize it.
22+
///
23+
/// Running example:
24+
/// (lldb) expr 1 + foo
25+
/// error: <user expression 0>:1:3: use of undeclared identifier 'foo'
26+
/// 1 + foo
27+
/// ^~~
28+
struct DiagnosticDetail {
29+
/// A source location consisting of a file name and position.
30+
struct SourceLocation {
31+
/// \c "<user expression 0>" in the example above.
32+
FileSpec file;
33+
/// \c 1 in the example above.
34+
unsigned line = 0;
35+
/// \c 5 in the example above.
36+
uint16_t column = 0;
37+
/// \c 3 in the example above.
38+
uint16_t length = 0;
39+
/// Whether this source location should be surfaced to the
40+
/// user. For example, syntax errors diagnosed in LLDB's
41+
/// expression wrapper code have this set to true.
42+
bool hidden = false;
43+
/// Whether this source location refers to something the user
44+
/// typed as part of the command, i.e., if this qualifies for
45+
/// inline display, or if the source line would need to be echoed
46+
/// again for the message to make sense.
47+
bool in_user_input = false;
48+
};
49+
/// Contains this diagnostic's source location, if applicable.
50+
std::optional<SourceLocation> source_location;
51+
/// Contains \c eSeverityError in the example above.
52+
lldb::Severity severity = lldb::eSeverityInfo;
53+
/// Contains "use of undeclared identifier 'foo'" in the example above.
54+
std::string message;
55+
/// Contains the fully rendered error message, without "error: ",
56+
/// but including the source context.
57+
std::string rendered;
58+
};
59+
60+
class DiagnosticError
61+
: public llvm::ErrorInfo<DiagnosticError, CloneableECError> {
62+
public:
63+
using llvm::ErrorInfo<DiagnosticError, CloneableECError>::ErrorInfo;
64+
DiagnosticError(std::error_code ec) : ErrorInfo(ec) {}
65+
lldb::ErrorType GetErrorType() const override;
66+
virtual llvm::ArrayRef<DiagnosticDetail> GetDetails() const = 0;
67+
static char ID;
68+
};
69+
70+
void RenderDiagnosticDetails(Stream &stream,
71+
std::optional<uint16_t> offset_in_command,
72+
bool show_inline,
73+
llvm::ArrayRef<DiagnosticDetail> details);
74+
} // namespace lldb_private
75+
#endif

lldb/include/lldb/Utility/Status.h

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLDB_UTILITY_STATUS_H
1010
#define LLDB_UTILITY_STATUS_H
1111

12+
#include "lldb/Utility/FileSpec.h"
1213
#include "lldb/lldb-defines.h"
1314
#include "lldb/lldb-enumerations.h"
1415
#include "llvm/ADT/StringRef.h"
@@ -26,8 +27,6 @@ class raw_ostream;
2627

2728
namespace lldb_private {
2829

29-
const char *ExpressionResultAsCString(lldb::ExpressionResults result);
30-
3130
/// Going a bit against the spirit of llvm::Error,
3231
/// lldb_private::Status need to store errors long-term and sometimes
3332
/// copy them. This base class defines an interface for this
@@ -79,16 +78,6 @@ class Win32Error : public llvm::ErrorInfo<Win32Error, CloneableECError> {
7978
static char ID;
8079
};
8180

82-
class ExpressionErrorBase
83-
: public llvm::ErrorInfo<ExpressionErrorBase, CloneableECError> {
84-
public:
85-
using llvm::ErrorInfo<ExpressionErrorBase, CloneableECError>::ErrorInfo;
86-
ExpressionErrorBase(std::error_code ec, std::string msg = {})
87-
: ErrorInfo(ec) {}
88-
lldb::ErrorType GetErrorType() const override;
89-
static char ID;
90-
};
91-
9281
/// \class Status Status.h "lldb/Utility/Status.h" An error handling class.
9382
///
9483
/// This class is designed to be able to hold any error code that can be

0 commit comments

Comments
 (0)