@@ -1542,6 +1542,19 @@ void request_completions(const llvm::json::Object &request) {
1542
1542
// client can use this optional information to
1543
1543
// present the variables in a paged UI and fetch
1544
1544
// them in chunks."
1545
+ // },
1546
+ // "valueLocationReference": {
1547
+ // "type": "integer",
1548
+ // "description": "A reference that allows the client to request
1549
+ // the location where the returned value is
1550
+ // declared. For example, if a function pointer is
1551
+ // returned, the adapter may be able to look up the
1552
+ // function's location. This should be present only
1553
+ // if the adapter is likely to be able to resolve
1554
+ // the location.\n\nThis reference shares the same
1555
+ // lifetime as the `variablesReference`. See
1556
+ // 'Lifetime of Object References' in the
1557
+ // Overview section for details."
1545
1558
// }
1546
1559
// "memoryReference": {
1547
1560
// "type": "string",
@@ -1611,16 +1624,17 @@ void request_evaluate(const llvm::json::Object &request) {
1611
1624
VariableDescription desc (value);
1612
1625
EmplaceSafeString (body, " result" , desc.GetResult (context));
1613
1626
EmplaceSafeString (body, " type" , desc.display_type_name );
1614
- if (value. MightHaveChildren ()) {
1615
- auto variableReference = g_dap. variables . InsertVariable (
1616
- value, /* is_permanent= */ context == " repl " );
1617
- body.try_emplace (" variablesReference" , variableReference );
1618
- } else {
1627
+ auto var_ref = g_dap. variables . InsertVariable (
1628
+ value, /* is_permanent= */ context == " repl " );
1629
+ if ( value. MightHaveChildren ())
1630
+ body.try_emplace (" variablesReference" , var_ref );
1631
+ else
1619
1632
body.try_emplace (" variablesReference" , (int64_t )0 );
1620
- }
1621
1633
if (lldb::addr_t addr = value.GetLoadAddress ();
1622
1634
addr != LLDB_INVALID_ADDRESS)
1623
1635
body.try_emplace (" memoryReference" , EncodeMemoryReference (addr));
1636
+ if (HasValueLocation (value))
1637
+ body.try_emplace (" valueLocationReference" , var_ref);
1624
1638
}
1625
1639
}
1626
1640
response.try_emplace (" body" , std::move (body));
@@ -3735,6 +3749,17 @@ void request_threads(const llvm::json::Object &request) {
3735
3749
// "description": "The number of indexed child variables. The client
3736
3750
// can use this optional information to present the variables in a
3737
3751
// paged UI and fetch them in chunks."
3752
+ // },
3753
+ // "valueLocationReference": {
3754
+ // "type": "integer",
3755
+ // "description": "A reference that allows the client to request the
3756
+ // location where the new value is declared. For example, if the new
3757
+ // value is function pointer, the adapter may be able to look up the
3758
+ // function's location. This should be present only if the adapter
3759
+ // is likely to be able to resolve the location.\n\nThis reference
3760
+ // shares the same lifetime as the `variablesReference`. See
3761
+ // 'Lifetime of Object References' in the Overview section for
3762
+ // details."
3738
3763
// }
3739
3764
// },
3740
3765
// "required": [ "value" ]
@@ -3759,7 +3784,6 @@ void request_setVariable(const llvm::json::Object &request) {
3759
3784
response.try_emplace (" success" , false );
3760
3785
3761
3786
lldb::SBValue variable;
3762
- int64_t newVariablesReference = 0 ;
3763
3787
3764
3788
// The "id" is the unique integer ID that is unique within the enclosing
3765
3789
// variablesReference. It is optionally added to any "interface Variable"
@@ -3789,14 +3813,17 @@ void request_setVariable(const llvm::json::Object &request) {
3789
3813
// so always insert a new one to get its variablesReference.
3790
3814
// is_permanent is false because debug console does not support
3791
3815
// setVariable request.
3816
+ int64_t new_var_ref =
3817
+ g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
3792
3818
if (variable.MightHaveChildren ())
3793
- newVariablesReference =
3794
- g_dap.variables .InsertVariable (variable, /* is_permanent=*/ false );
3795
- body.try_emplace (" variablesReference" , newVariablesReference);
3796
-
3819
+ body.try_emplace (" variablesReference" , new_var_ref);
3820
+ else
3821
+ body.try_emplace (" variablesReference" , 0 );
3797
3822
if (lldb::addr_t addr = variable.GetLoadAddress ();
3798
3823
addr != LLDB_INVALID_ADDRESS)
3799
3824
body.try_emplace (" memoryReference" , EncodeMemoryReference (addr));
3825
+ if (HasValueLocation (variable))
3826
+ body.try_emplace (" valueLocationReference" , new_var_ref);
3800
3827
} else {
3801
3828
EmplaceSafeString (body, " message" , std::string (error.GetCString ()));
3802
3829
}
@@ -4087,32 +4114,64 @@ void request_variables(const llvm::json::Object &request) {
4087
4114
void request_locations (const llvm::json::Object &request) {
4088
4115
llvm::json::Object response;
4089
4116
FillResponse (request, response);
4090
- auto arguments = request.getObject (" arguments" );
4117
+ auto * arguments = request.getObject (" arguments" );
4091
4118
4092
4119
uint64_t reference_id = GetUnsigned (arguments, " locationReference" , 0 );
4093
- lldb::SBValue variable = g_dap.variables .GetVariable (reference_id);
4120
+ // We use the lowest bit to distinguish between value location and declaration
4121
+ // location
4122
+ bool isValueLocation = reference_id & 1 ;
4123
+ lldb::SBValue variable = g_dap.variables .GetVariable (reference_id >> 1 );
4094
4124
if (!variable.IsValid ()) {
4095
4125
response[" success" ] = false ;
4096
4126
response[" message" ] = " Invalid variable reference" ;
4097
4127
g_dap.SendJSON (llvm::json::Value (std::move (response)));
4098
4128
return ;
4099
4129
}
4100
4130
4101
- // Get the declaration location
4102
- lldb::SBDeclaration decl = variable.GetDeclaration ();
4103
- if (!decl.IsValid ()) {
4104
- response[" success" ] = false ;
4105
- response[" message" ] = " No declaration location available" ;
4106
- g_dap.SendJSON (llvm::json::Value (std::move (response)));
4107
- return ;
4108
- }
4109
-
4110
4131
llvm::json::Object body;
4111
- body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
4112
- if (int line = decl.GetLine ())
4113
- body.try_emplace (" line" , line);
4114
- if (int column = decl.GetColumn ())
4115
- body.try_emplace (" column" , column);
4132
+ if (isValueLocation) {
4133
+ // Get the value location
4134
+ if (!variable.GetType ().IsPointerType () &&
4135
+ !variable.GetType ().IsReferenceType ()) {
4136
+ response[" success" ] = false ;
4137
+ response[" message" ] =
4138
+ " Value locations are only available for pointers and references" ;
4139
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4140
+ return ;
4141
+ }
4142
+
4143
+ lldb::addr_t addr = variable.GetValueAsAddress ();
4144
+ lldb::SBLineEntry line_entry =
4145
+ g_dap.target .ResolveLoadAddress (addr).GetLineEntry ();
4146
+
4147
+ if (!line_entry.IsValid ()) {
4148
+ response[" success" ] = false ;
4149
+ response[" message" ] = " Failed to resolve line entry for location" ;
4150
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4151
+ return ;
4152
+ }
4153
+
4154
+ body.try_emplace (" source" , CreateSource (line_entry.GetFileSpec ()));
4155
+ if (int line = line_entry.GetLine ())
4156
+ body.try_emplace (" line" , line);
4157
+ if (int column = line_entry.GetColumn ())
4158
+ body.try_emplace (" column" , column);
4159
+ } else {
4160
+ // Get the declaration location
4161
+ lldb::SBDeclaration decl = variable.GetDeclaration ();
4162
+ if (!decl.IsValid ()) {
4163
+ response[" success" ] = false ;
4164
+ response[" message" ] = " No declaration location available" ;
4165
+ g_dap.SendJSON (llvm::json::Value (std::move (response)));
4166
+ return ;
4167
+ }
4168
+
4169
+ body.try_emplace (" source" , CreateSource (decl.GetFileSpec ()));
4170
+ if (int line = decl.GetLine ())
4171
+ body.try_emplace (" line" , line);
4172
+ if (int column = decl.GetColumn ())
4173
+ body.try_emplace (" column" , column);
4174
+ }
4116
4175
4117
4176
response.try_emplace (" body" , std::move (body));
4118
4177
g_dap.SendJSON (llvm::json::Value (std::move (response)));
0 commit comments