@@ -211,46 +211,6 @@ static std::optional<std::string> TryCreateAutoSummary(lldb::SBValue value) {
211211 return TryCreateAutoSummaryForContainer (value);
212212}
213213
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-
254214void FillResponse (const llvm::json::Object &request,
255215 llvm::json::Object &response) {
256216 // Fill in all of the needed response fields to a "request" and set "success"
@@ -1045,6 +1005,92 @@ std::string CreateUniqueVariableNameForDisplay(lldb::SBValue v,
10451005 return name_builder.GetData ();
10461006}
10471007
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+
10481094// "Variable": {
10491095// "type": "object",
10501096// "description": "A Variable is a name/value pair. Optionally a variable
@@ -1104,27 +1150,56 @@ std::string CreateUniqueVariableNameForDisplay(lldb::SBValue v,
11041150// can use this optional information to present the
11051151// children in a paged UI and fetch them in chunks."
11061152// }
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",
11121157// "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+ // }
11271179// }
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."
11281203// }
11291204// }
11301205// },
@@ -1134,81 +1209,57 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
11341209 int64_t varID, bool format_hex,
11351210 bool is_name_duplicated,
11361211 std::optional<std::string> custom_name) {
1212+ VariableDescription desc (v, format_hex, is_name_duplicated, custom_name);
11371213 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 );
11421219
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 ();
11481220 // If we have a type with many children, we would like to be able to
11491221 // 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 ();
11631235 const bool is_synthetic = v.IsSynthetic ();
11641236 if (is_array || is_synthetic) {
11651237 const auto num_children = v.GetNumChildren ();
11661238 // 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.
11691241 bool has_raw_child = is_synthetic && g_dap.enable_synthetic_child_debugging ;
11701242 int actual_num_children = num_children + (has_raw_child ? 1 : 0 );
11711243 if (is_array) {
11721244 object.try_emplace (" indexedVariables" , actual_num_children);
11731245 } 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.
11771249 const char *first_child_name = v.GetChildAtIndex (0 ).GetName ();
11781250 if (first_child_name && strcmp (first_child_name, " [0]" ) == 0 )
11791251 object.try_emplace (" indexedVariables" , actual_num_children);
11801252 }
11811253 }
1182- EmplaceSafeString (object, " type" , type_cstr ? type_cstr : NO_TYPENAME );
1254+ EmplaceSafeString (object, " type" , desc. display_type_name );
11831255 if (varID != INT64_MAX)
11841256 object.try_emplace (" id" , varID);
11851257 if (v.MightHaveChildren ())
11861258 object.try_emplace (" variablesReference" , variablesReference);
11871259 else
11881260 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- }
12041261
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 ());
12121263 return llvm::json::Value (std::move (object));
12131264}
12141265
0 commit comments