@@ -211,46 +211,6 @@ static std::optional<std::string> TryCreateAutoSummary(lldb::SBValue value) {
211
211
return TryCreateAutoSummaryForContainer (value);
212
212
}
213
213
214
- std::string ValueToString (lldb::SBValue v) {
215
- std::string result;
216
- llvm::raw_string_ostream strm (result);
217
-
218
- lldb::SBError error = v.GetError ();
219
- if (!error.Success ()) {
220
- strm << " <error: " << error.GetCString () << " >" ;
221
- } else {
222
- llvm::StringRef value = v.GetValue ();
223
- llvm::StringRef nonAutoSummary = v.GetSummary ();
224
- std::optional<std::string> summary = !nonAutoSummary.empty ()
225
- ? nonAutoSummary.str ()
226
- : TryCreateAutoSummary (v);
227
- if (!value.empty ()) {
228
- strm << value;
229
- if (summary)
230
- strm << ' ' << *summary;
231
- } else if (summary) {
232
- strm << *summary;
233
-
234
- // As last resort, we print its type and address if available.
235
- } else {
236
- if (llvm::StringRef type_name = v.GetType ().GetDisplayTypeName ();
237
- !type_name.empty ()) {
238
- strm << type_name;
239
- lldb::addr_t address = v.GetLoadAddress ();
240
- if (address != LLDB_INVALID_ADDRESS)
241
- strm << " @ " << llvm::format_hex (address, 0 );
242
- }
243
- }
244
- }
245
- return result;
246
- }
247
-
248
- void SetValueForKey (lldb::SBValue &v, llvm::json::Object &object,
249
- llvm::StringRef key) {
250
- std::string result = ValueToString (v);
251
- EmplaceSafeString (object, key, result);
252
- }
253
-
254
214
void FillResponse (const llvm::json::Object &request,
255
215
llvm::json::Object &response) {
256
216
// Fill in all of the needed response fields to a "request" and set "success"
@@ -1045,6 +1005,92 @@ std::string CreateUniqueVariableNameForDisplay(lldb::SBValue v,
1045
1005
return name_builder.GetData ();
1046
1006
}
1047
1007
1008
+ VariableDescription::VariableDescription (lldb::SBValue v, bool format_hex,
1009
+ bool is_name_duplicated,
1010
+ std::optional<std::string> custom_name)
1011
+ : v(v) {
1012
+ name = custom_name
1013
+ ? *custom_name
1014
+ : CreateUniqueVariableNameForDisplay (v, is_name_duplicated);
1015
+
1016
+ type_obj = v.GetType ();
1017
+ std::string raw_display_type_name =
1018
+ llvm::StringRef (type_obj.GetDisplayTypeName ()).str ();
1019
+ display_type_name =
1020
+ !raw_display_type_name.empty () ? raw_display_type_name : NO_TYPENAME;
1021
+
1022
+ if (format_hex)
1023
+ v.SetFormat (lldb::eFormatHex);
1024
+
1025
+ llvm::raw_string_ostream os_display_value (display_value);
1026
+
1027
+ if (lldb::SBError sb_error = v.GetError (); sb_error.Fail ()) {
1028
+ error = sb_error.GetCString ();
1029
+ os_display_value << " <error: " << error << " >" ;
1030
+ } else {
1031
+ value = llvm::StringRef (v.GetValue ()).str ();
1032
+ summary = llvm::StringRef (v.GetSummary ()).str ();
1033
+ if (summary.empty ())
1034
+ auto_summary = TryCreateAutoSummary (v);
1035
+
1036
+ std::optional<std::string> effective_summary =
1037
+ !summary.empty () ? summary : auto_summary;
1038
+
1039
+ if (!value.empty ()) {
1040
+ os_display_value << value;
1041
+ if (effective_summary)
1042
+ os_display_value << " " << *effective_summary;
1043
+ } else if (effective_summary) {
1044
+ os_display_value << *effective_summary;
1045
+
1046
+ // As last resort, we print its type and address if available.
1047
+ } else {
1048
+ if (!raw_display_type_name.empty ()) {
1049
+ os_display_value << raw_display_type_name;
1050
+ lldb::addr_t address = v.GetLoadAddress ();
1051
+ if (address != LLDB_INVALID_ADDRESS)
1052
+ os_display_value << " @ " << llvm::format_hex (address, 0 );
1053
+ }
1054
+ }
1055
+ }
1056
+
1057
+ lldb::SBStream evaluateStream;
1058
+ v.GetExpressionPath (evaluateStream);
1059
+ evaluate_name = llvm::StringRef (evaluateStream.GetData ()).str ();
1060
+ }
1061
+
1062
+ llvm::json::Object VariableDescription::GetVariableExtensionsJSON () {
1063
+ llvm::json::Object extensions;
1064
+ if (error)
1065
+ EmplaceSafeString (extensions, " error" , *error);
1066
+ if (!value.empty ())
1067
+ EmplaceSafeString (extensions, " value" , value);
1068
+ if (!summary.empty ())
1069
+ EmplaceSafeString (extensions, " summary" , summary);
1070
+ if (auto_summary)
1071
+ EmplaceSafeString (extensions, " autoSummary" , *auto_summary);
1072
+
1073
+ if (lldb::SBDeclaration decl = v.GetDeclaration (); decl.IsValid ()) {
1074
+ llvm::json::Object decl_obj;
1075
+ if (lldb::SBFileSpec file = decl.GetFileSpec (); file.IsValid ()) {
1076
+ char path[PATH_MAX] = " " ;
1077
+ if (file.GetPath (path, sizeof (path)) &&
1078
+ lldb::SBFileSpec::ResolvePath (path, path, PATH_MAX)) {
1079
+ decl_obj.try_emplace (" path" , std::string (path));
1080
+ }
1081
+ }
1082
+
1083
+ if (int line = decl.GetLine ())
1084
+ decl_obj.try_emplace (" line" , line);
1085
+ if (int column = decl.GetColumn ())
1086
+ decl_obj.try_emplace (" column" , column);
1087
+
1088
+ if (!decl_obj.empty ())
1089
+ extensions.try_emplace (" declaration" , std::move (decl_obj));
1090
+ }
1091
+ return extensions;
1092
+ }
1093
+
1048
1094
// "Variable": {
1049
1095
// "type": "object",
1050
1096
// "description": "A Variable is a name/value pair. Optionally a variable
@@ -1104,27 +1150,56 @@ std::string CreateUniqueVariableNameForDisplay(lldb::SBValue v,
1104
1150
// can use this optional information to present the
1105
1151
// children in a paged UI and fetch them in chunks."
1106
1152
// }
1107
- // "declaration": {
1108
- // "type": "object | undefined",
1109
- // "description": "Extension to the protocol that indicates the source
1110
- // location where the variable was declared. This value
1111
- // might not be present if no declaration is available.",
1153
+ //
1154
+ //
1155
+ // "$__lldb_extensions": {
1156
+ // "description": "Unofficial extensions to the protocol",
1112
1157
// "properties": {
1113
- // "path": {
1114
- // "type": "string | undefined",
1115
- // "description": "The source file path where the variable was
1116
- // declared."
1117
- // },
1118
- // "line": {
1119
- // "type": "number | undefined",
1120
- // "description": "The 1-indexed source line where the variable was
1121
- // declared."
1122
- // },
1123
- // "column": {
1124
- // "type": "number | undefined",
1125
- // "description": "The 1-indexed source column where the variable was
1126
- // declared."
1158
+ // "declaration": {
1159
+ // "type": "object",
1160
+ // "description": "The source location where the variable was declared.
1161
+ // This value won't be present if no declaration is
1162
+ // available.",
1163
+ // "properties": {
1164
+ // "path": {
1165
+ // "type": "string",
1166
+ // "description": "The source file path where the variable was
1167
+ // declared."
1168
+ // },
1169
+ // "line": {
1170
+ // "type": "number",
1171
+ // "description": "The 1-indexed source line where the variable was
1172
+ // declared."
1173
+ // },
1174
+ // "column": {
1175
+ // "type": "number",
1176
+ // "description": "The 1-indexed source column where the variable
1177
+ // was declared."
1178
+ // }
1127
1179
// }
1180
+ // },
1181
+ // "value":
1182
+ // "type": "string",
1183
+ // "description": "The internal value of the variable as returned by
1184
+ // This is effectively SBValue.GetValue(). The other
1185
+ // `value` entry in the top-level variable response is,
1186
+ // on the other hand, just a display string for the
1187
+ // variable."
1188
+ // },
1189
+ // "summary":
1190
+ // "type": "string",
1191
+ // "description": "The summary string of the variable. This is
1192
+ // effectively SBValue.GetSummary()."
1193
+ // },
1194
+ // "autoSummary":
1195
+ // "type": "string",
1196
+ // "description": "The auto generated summary if using
1197
+ // `enableAutoVariableSummaries`."
1198
+ // },
1199
+ // "error":
1200
+ // "type": "string",
1201
+ // "description": "An error message generated if LLDB couldn't inspect
1202
+ // the variable."
1128
1203
// }
1129
1204
// }
1130
1205
// },
@@ -1134,81 +1209,57 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
1134
1209
int64_t varID, bool format_hex,
1135
1210
bool is_name_duplicated,
1136
1211
std::optional<std::string> custom_name) {
1212
+ VariableDescription desc (v, format_hex, is_name_duplicated, custom_name);
1137
1213
llvm::json::Object object;
1138
- EmplaceSafeString (
1139
- object, " name" ,
1140
- custom_name ? *custom_name
1141
- : CreateUniqueVariableNameForDisplay (v, is_name_duplicated));
1214
+ EmplaceSafeString (object, " name" , desc.name );
1215
+ EmplaceSafeString (object, " value" , desc.display_value );
1216
+
1217
+ if (!desc.evaluate_name .empty ())
1218
+ EmplaceSafeString (object, " evaluateName" , desc.evaluate_name );
1142
1219
1143
- if (format_hex)
1144
- v.SetFormat (lldb::eFormatHex);
1145
- SetValueForKey (v, object, " value" );
1146
- auto type_obj = v.GetType ();
1147
- auto type_cstr = type_obj.GetDisplayTypeName ();
1148
1220
// If we have a type with many children, we would like to be able to
1149
1221
// give a hint to the IDE that the type has indexed children so that the
1150
- // request can be broken up in grabbing only a few children at a time. We want
1151
- // to be careful and only call "v.GetNumChildren()" if we have an array type
1152
- // or if we have a synthetic child provider. We don't want to call
1153
- // "v.GetNumChildren()" on all objects as class, struct and union types don't
1154
- // need to be completed if they are never expanded. So we want to avoid
1155
- // calling this to only cases where we it makes sense to keep performance high
1156
- // during normal debugging.
1157
-
1158
- // If we have an array type, say that it is indexed and provide the number of
1159
- // children in case we have a huge array. If we don't do this, then we might
1160
- // take a while to produce all children at onces which can delay your debug
1161
- // session.
1162
- const bool is_array = type_obj.IsArrayType ();
1222
+ // request can be broken up in grabbing only a few children at a time. We
1223
+ // want to be careful and only call "v.GetNumChildren()" if we have an array
1224
+ // type or if we have a synthetic child provider. We don't want to call
1225
+ // "v.GetNumChildren()" on all objects as class, struct and union types
1226
+ // don't need to be completed if they are never expanded. So we want to
1227
+ // avoid calling this to only cases where we it makes sense to keep
1228
+ // performance high during normal debugging.
1229
+
1230
+ // If we have an array type, say that it is indexed and provide the number
1231
+ // of children in case we have a huge array. If we don't do this, then we
1232
+ // might take a while to produce all children at onces which can delay your
1233
+ // debug session.
1234
+ const bool is_array = desc. type_obj .IsArrayType ();
1163
1235
const bool is_synthetic = v.IsSynthetic ();
1164
1236
if (is_array || is_synthetic) {
1165
1237
const auto num_children = v.GetNumChildren ();
1166
1238
// We create a "[raw]" fake child for each synthetic type, so we have to
1167
- // account for it when returning indexed variables. We don't need to do this
1168
- // for non-indexed ones.
1239
+ // account for it when returning indexed variables. We don't need to do
1240
+ // this for non-indexed ones.
1169
1241
bool has_raw_child = is_synthetic && g_dap.enable_synthetic_child_debugging ;
1170
1242
int actual_num_children = num_children + (has_raw_child ? 1 : 0 );
1171
1243
if (is_array) {
1172
1244
object.try_emplace (" indexedVariables" , actual_num_children);
1173
1245
} else if (num_children > 0 ) {
1174
- // If a type has a synthetic child provider, then the SBType of "v" won't
1175
- // tell us anything about what might be displayed. So we can check if the
1176
- // first child's name is "[0]" and then we can say it is indexed.
1246
+ // If a type has a synthetic child provider, then the SBType of "v"
1247
+ // won't tell us anything about what might be displayed. So we can check
1248
+ // if the first child's name is "[0]" and then we can say it is indexed.
1177
1249
const char *first_child_name = v.GetChildAtIndex (0 ).GetName ();
1178
1250
if (first_child_name && strcmp (first_child_name, " [0]" ) == 0 )
1179
1251
object.try_emplace (" indexedVariables" , actual_num_children);
1180
1252
}
1181
1253
}
1182
- EmplaceSafeString (object, " type" , type_cstr ? type_cstr : NO_TYPENAME );
1254
+ EmplaceSafeString (object, " type" , desc. display_type_name );
1183
1255
if (varID != INT64_MAX)
1184
1256
object.try_emplace (" id" , varID);
1185
1257
if (v.MightHaveChildren ())
1186
1258
object.try_emplace (" variablesReference" , variablesReference);
1187
1259
else
1188
1260
object.try_emplace (" variablesReference" , (int64_t )0 );
1189
- lldb::SBStream evaluateStream;
1190
- v.GetExpressionPath (evaluateStream);
1191
- const char *evaluateName = evaluateStream.GetData ();
1192
- if (evaluateName && evaluateName[0 ])
1193
- EmplaceSafeString (object, " evaluateName" , std::string (evaluateName));
1194
-
1195
- if (lldb::SBDeclaration decl = v.GetDeclaration (); decl.IsValid ()) {
1196
- llvm::json::Object decl_obj;
1197
- if (lldb::SBFileSpec file = decl.GetFileSpec (); file.IsValid ()) {
1198
- char path[PATH_MAX] = " " ;
1199
- if (file.GetPath (path, sizeof (path)) &&
1200
- lldb::SBFileSpec::ResolvePath (path, path, PATH_MAX)) {
1201
- decl_obj.try_emplace (" path" , std::string (path));
1202
- }
1203
- }
1204
1261
1205
- if (int line = decl.GetLine ())
1206
- decl_obj.try_emplace (" line" , line);
1207
- if (int column = decl.GetColumn ())
1208
- decl_obj.try_emplace (" column" , column);
1209
-
1210
- object.try_emplace (" declaration" , std::move (decl_obj));
1211
- }
1262
+ object.try_emplace (" $__lldb_extensions" , desc.GetVariableExtensionsJSON ());
1212
1263
return llvm::json::Value (std::move (object));
1213
1264
}
1214
1265
0 commit comments