27
27
#include " llvm/ADT/StringRef.h"
28
28
#include " llvm/Support/FormatVariadic.h"
29
29
30
+ #include < regex>
31
+
30
32
using namespace llvm ;
31
33
using namespace lldb ;
32
34
using namespace lldb_private ;
@@ -109,6 +111,37 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
109
111
language = frame->GuessLanguage ();
110
112
// END SWIFT
111
113
114
+ // Add a hint if object description was requested, but no description
115
+ // function was implemented.
116
+ auto maybe_add_hint = [&](llvm::StringRef output) {
117
+ // Identify the default output of object description for Swift and
118
+ // Objective-C
119
+ // "<Name: 0x...>. The regex is:
120
+ // - Start with "<".
121
+ // - Followed by 1 or more non-whitespace characters.
122
+ // - Followed by ": 0x".
123
+ // - Followed by 5 or more hex digits.
124
+ // - Followed by ">".
125
+ // - End with zero or more whitespace characters.
126
+ const std::regex swift_class_regex (" ^<\\ S+: 0x[[:xdigit:]]{5,}>\\ s*$" );
127
+
128
+ if (GetDebugger ().GetShowDontUsePoHint () && target_ptr &&
129
+ (language == lldb::eLanguageTypeSwift ||
130
+ language == lldb::eLanguageTypeObjC) &&
131
+ std::regex_match (output.data (), swift_class_regex)) {
132
+
133
+ static bool note_shown = false ;
134
+ if (note_shown)
135
+ return ;
136
+
137
+ result.GetOutputStream ()
138
+ << " note: object description requested, but type doesn't implement "
139
+ " a custom object description. Consider using \" p\" instead of "
140
+ " \" po\" (this note will only be shown once per debug session).\n " ;
141
+ note_shown = true ;
142
+ }
143
+ };
144
+
112
145
// First, try `expr` as the name of a frame variable.
113
146
if (frame) {
114
147
auto valobj_sp = frame->FindVariable (ConstString (expr));
@@ -126,7 +159,15 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
126
159
flags, expr);
127
160
}
128
161
129
- valobj_sp->Dump (result.GetOutputStream (), dump_options);
162
+ if (is_po) {
163
+ StreamString temp_result_stream;
164
+ valobj_sp->Dump (temp_result_stream, dump_options);
165
+ llvm::StringRef output = temp_result_stream.GetString ();
166
+ maybe_add_hint (output);
167
+ result.GetOutputStream () << output;
168
+ } else {
169
+ valobj_sp->Dump (result.GetOutputStream (), dump_options);
170
+ }
130
171
result.SetStatus (eReturnStatusSuccessFinishResult);
131
172
return true ;
132
173
}
@@ -184,8 +225,17 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
184
225
expr);
185
226
}
186
227
187
- if (valobj_sp->GetError ().GetError () != UserExpression::kNoResult )
188
- valobj_sp->Dump (result.GetOutputStream (), dump_options);
228
+ if (valobj_sp->GetError ().GetError () != UserExpression::kNoResult ) {
229
+ if (is_po) {
230
+ StreamString temp_result_stream;
231
+ valobj_sp->Dump (temp_result_stream, dump_options);
232
+ llvm::StringRef output = temp_result_stream.GetString ();
233
+ maybe_add_hint (output);
234
+ result.GetOutputStream () << output;
235
+ } else {
236
+ valobj_sp->Dump (result.GetOutputStream (), dump_options);
237
+ }
238
+ }
189
239
190
240
if (suppress_result)
191
241
if (auto result_var_sp =
0 commit comments