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