@@ -1561,6 +1561,19 @@ void request_completions(const llvm::json::Object &request) {
1561
1561
// client can use this optional information to
1562
1562
// present the variables in a paged UI and fetch
1563
1563
// them in chunks."
1564
+ // },
1565
+ // "valueLocationReference": {
1566
+ // "type": "integer",
1567
+ // "description": "A reference that allows the client to request
1568
+ // the location where the returned value is
1569
+ // declared. For example, if a function pointer is
1570
+ // returned, the adapter may be able to look up the
1571
+ // function's location. This should be present only
1572
+ // if the adapter is likely to be able to resolve
1573
+ // the location.\n\nThis reference shares the same
1574
+ // lifetime as the `variablesReference`. See
1575
+ // 'Lifetime of Object References' in the
1576
+ // Overview section for details."
1564
1577
// }
1565
1578
// "memoryReference": {
1566
1579
// "type": "string",
@@ -1647,16 +1660,19 @@ void request_evaluate(const llvm::json::Object &request) {
1647
1660
VariableDescription desc (value);
1648
1661
EmplaceSafeString (body, " result" , desc.GetResult (context));
1649
1662
EmplaceSafeString (body, " type" , desc.display_type_name );
1650
- if (value.MightHaveChildren ()) {
1651
- auto variableReference = g_dap.variables .InsertVariable (
1663
+ int64_t var_ref = 0 ;
1664
+ if (value.MightHaveChildren () || ValuePointsToCode (value))
1665
+ var_ref = g_dap.variables .InsertVariable (
1652
1666
value, /* is_permanent=*/ context == " repl" );
1653
- body.try_emplace (" variablesReference" , variableReference);
1654
- } else {
1667
+ if (value.MightHaveChildren ())
1668
+ body.try_emplace (" variablesReference" , var_ref);
1669
+ else
1655
1670
body.try_emplace (" variablesReference" , (int64_t )0 );
1656
- }
1657
1671
if (lldb::addr_t addr = value.GetLoadAddress ();
1658
1672
addr != LLDB_INVALID_ADDRESS)
1659
1673
body.try_emplace (" memoryReference" , EncodeMemoryReference (addr));
1674
+ if (ValuePointsToCode (value))
1675
+ body.try_emplace (" valueLocationReference" , var_ref);
1660
1676
}
1661
1677
}
1662
1678
response.try_emplace (" body" , std::move (body));
@@ -3770,6 +3786,17 @@ void request_threads(const llvm::json::Object &request) {
3770
3786
// "description": "The number of indexed child variables. The client
3771
3787
// can use this optional information to present the variables in a
3772
3788
// paged UI and fetch them in chunks."
3789
+ // },
3790
+ // "valueLocationReference": {
3791
+ // "type": "integer",
3792
+ // "description": "A reference that allows the client to request the
3793
+ // location where the new value is declared. For example, if the new
3794
+ // value is function pointer, the adapter may be able to look up the
3795
+ // function's location. This should be present only if the adapter
3796
+ // is likely to be able to resolve the location.\n\nThis reference
3797
+ // shares the same lifetime as the `variablesReference`. See
3798
+ // 'Lifetime of Object References' in the Overview section for
3799
+ // details."
3773
3800
// }
3774
3801
// },
3775
3802
// "required": [ "value" ]
@@ -3794,7 +3821,6 @@ void request_setVariable(const llvm::json::Object &request) {
3794
3821
response.try_emplace (" success" , false );
3795
3822
3796
3823
lldb::SBValue variable;
3797
- int64_t newVariablesReference = 0 ;
3798
3824
3799
3825
// The "id" is the unique integer ID that is unique within the enclosing
3800
3826
// variablesReference. It is optionally added to any "interface Variable"
@@ -3824,14 +3850,17 @@ void request_setVariable(const llvm::json::Object &request) {
3824
3850
// so always insert a new one to get its variablesReference.
3825
3851
// is_permanent is false because debug console does not support
3826
3852
// setVariable request.
3853
+ int64_t new_var_ref =
3854
+ g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
3827
3855
if (variable.MightHaveChildren ())
3828
- newVariablesReference =
3829
- g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
3830
- body.try_emplace (" variablesReference" , newVariablesReference);
3831
-
3856
+ body.try_emplace (" variablesReference" , new_var_ref);
3857
+ else
3858
+ body.try_emplace (" variablesReference" , 0 );
3832
3859
if (lldb::addr_t addr = variable.GetLoadAddress ();
3833
3860
addr != LLDB_INVALID_ADDRESS)
3834
3861
body.try_emplace (" memoryReference" , EncodeMemoryReference (addr));
3862
+ if (ValuePointsToCode (variable))
3863
+ body.try_emplace (" valueLocationReference" , new_var_ref);
3835
3864
} else {
3836
3865
EmplaceSafeString (body, " message" , std::string (error.GetCString ()));
3837
3866
}
@@ -4122,32 +4151,64 @@ void request_variables(const llvm::json::Object &request) {
4122
4151
void request_locations (const llvm::json::Object &request) {
4123
4152
llvm::json::Object response;
4124
4153
FillResponse (request, response);
4125
- auto arguments = request.getObject (" arguments" );
4154
+ auto * arguments = request.getObject (" arguments" );
4126
4155
4127
- uint64_t reference_id = GetUnsigned (arguments, " locationReference" , 0 );
4128
- lldb::SBValue variable = g_dap.variables .GetVariable (reference_id);
4156
+ uint64_t location_id = GetUnsigned (arguments, " locationReference" , 0 );
4157
+ // We use the lowest bit to distinguish between value location and declaration
4158
+ // location
4159
+ auto [var_ref, is_value_location] = UnpackLocation (location_id);
4160
+ lldb::SBValue variable = g_dap.variables .GetVariable (var_ref);
4129
4161
if (!variable.IsValid ()) {
4130
4162
response[" success" ] = false ;
4131
4163
response[" message" ] = " Invalid variable reference" ;
4132
4164
g_dap.SendJSON (llvm::json::Value (std::move (response)));
4133
4165
return ;
4134
4166
}
4135
4167
4136
- // Get the declaration location
4137
- lldb::SBDeclaration decl = variable.GetDeclaration ();
4138
- if (!decl.IsValid ()) {
4139
- response[" success" ] = false ;
4140
- response[" message" ] = " No declaration location available" ;
4141
- g_dap.SendJSON (llvm::json::Value (std::move (response)));
4142
- return ;
4143
- }
4144
-
4145
4168
llvm::json::Object body;
4146
- body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
4147
- if (int line = decl.GetLine ())
4148
- body.try_emplace (" line" , line);
4149
- if (int column = decl.GetColumn ())
4150
- body.try_emplace (" column" , column);
4169
+ if (is_value_location) {
4170
+ // Get the value location
4171
+ if (!variable.GetType ().IsPointerType () &&
4172
+ !variable.GetType ().IsReferenceType ()) {
4173
+ response[" success" ] = false ;
4174
+ response[" message" ] =
4175
+ " Value locations are only available for pointers and references" ;
4176
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4177
+ return ;
4178
+ }
4179
+
4180
+ lldb::addr_t addr = variable.GetValueAsAddress ();
4181
+ lldb::SBLineEntry line_entry =
4182
+ g_dap.target .ResolveLoadAddress (addr).GetLineEntry ();
4183
+
4184
+ if (!line_entry.IsValid ()) {
4185
+ response[" success" ] = false ;
4186
+ response[" message" ] = " Failed to resolve line entry for location" ;
4187
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4188
+ return ;
4189
+ }
4190
+
4191
+ body.try_emplace (" source" , CreateSource (line_entry.GetFileSpec ()));
4192
+ if (int line = line_entry.GetLine ())
4193
+ body.try_emplace (" line" , line);
4194
+ if (int column = line_entry.GetColumn ())
4195
+ body.try_emplace (" column" , column);
4196
+ } else {
4197
+ // Get the declaration location
4198
+ lldb::SBDeclaration decl = variable.GetDeclaration ();
4199
+ if (!decl.IsValid ()) {
4200
+ response[" success" ] = false ;
4201
+ response[" message" ] = " No declaration location available" ;
4202
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4203
+ return ;
4204
+ }
4205
+
4206
+ body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
4207
+ if (int line = decl.GetLine ())
4208
+ body.try_emplace (" line" , line);
4209
+ if (int column = decl.GetColumn ())
4210
+ body.try_emplace (" column" , column);
4211
+ }
4151
4212
4152
4213
response.try_emplace (" body" , std::move (body));
4153
4214
g_dap.SendJSON (llvm::json::Value (std::move (response)));
0 commit comments