While looking at the '[raw]' value of a std::vector I noticed we didn't
handle the anonymous inner struct very well. The 'evaluateName' was
incorrect (e.g. the evaluateName would return `<var>.` for the anonymous
struct).
This improves support for variables with anonymous fields and anonymous
types.
* Changed the name of anonymous fields from `<null>` to `(anonymous)`,
which matches other tooling like clangd's representation and how types
are presented if the field is not defined.
* Adjusts variables to not return an 'evaluateName' for anonymous
fields.
* Adjusted '[raw]' values to be marked as 'internal' which deemphasizes
them in the UI.
While working in this area, I also consolidated some helpers that are
only used within Variables.cpp.
Before my changes:
<img width="513" height="460" alt="before"
src="https://github.com/user-attachments/assets/3da0aada-8ba3-415d-bbec-56b41a9b9415"
/>
After my changes:
<img width="414" height="467" alt="after"
src="https://github.com/user-attachments/assets/66a47108-ee44-4e01-8eab-e89edb348fde"
/>
Adjusting `VariableReferenceStorage` to only need to track permanent vs
temporary storage by making `VariableStore` the common base class.
Moved the subclasses of `VariableStore` into the Variables.cpp file,
since they're no long referenced externally.
Expanding on the tests by adding an updated core dump with variables in
the argument scope we can use to validate variable storage.
This commit refactors the Variables class into a
VariableReferenceStorage with variableReferences of different
ReferenceKinds.
The variablesReference is now a uint32_t.
The most significant byte (bits 24 - 31) holds the reference kind and
the remaining 3 bytes (bits 0 -23) holds the actual reference.
We have (at the moment) 3 reference kinds.
Temporary => 0b0000 => 0x00
Permanent => 0b0001 => 0x01
Scope => 0b0010 => 0x03
The actual variablesReference can be used to get a `VariableStore`.
VariableStore holds variables in a group.
It has two implementations:
- ScopeStore: Holds variables within frame scopes (locals, globals,
registers). This is lazy-loaded and only fetched when variable(s) in the
scope is requested.
- ExpandableValueStore: Holds SBValue and fetches it's variable children
when requested.
ReferenceKindPool:
The variablesReference created starts from 1 with the mask of the
Reference kind applied.
It holds vector of VariableStore of one Referencekind,
This allows constant lookup of a reference
Example:
```md
| maskedVariablesReference | Mask | variablesReference | RefrenceKind | VariableStore |
|--------------------------|------|--------------------|--------------|---------------|
| 20 -> 0x00000014 | 0x00 | 20 -> 0x00000014 | temporary | ValueStore |
| 268435476 -> 0x01000014 | 0x01 | 20 -> 0x00000014 | permanent | ValueStore |
| 536870932 -> 0x01000014 | 0x02 | 20 -> 0x00000014 | scope | ScopeStore |
```
Closes#119784
Probably closes#147105 as well, but I couldn't test due to #156473:
This PR fixes two bugs:
1. It generates unique variable reference IDs per suspended debuggee
state.
2. It stores all created variables in a stopped state instead of
dropping variables in unselected scopes. So it can properly handle all
scope/variable requests
It does this by storing all variables in their respective scopes and
using that mapping in request handlers that relied on the old mapping.
It dynamically creates new variable/scope IDs instead of resetting IDs
whenever a new scope is created.
I also removed some unused code as well.
---------
Co-authored-by: Med Ismail Bennani <ismail@bennani.ma>
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
Co-authored-by: Ebuka Ezike <yerimyah1@gmail.com>
This adds new protocol types for the 'variables' request.
While implementing this, I removed the '$__lldb_extension' field we
returned on the 'variables' request, since I think all the data can be
retrieved from other DAP requests.
---------
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
This moves all the common settings of the launch and attach operations
into the `lldb_dap::protocol::Configuration`. These common settings
can be in both `launch` and `attach` requests and allows us to isolate
the DAP configuration operations into a single common location.
This is split out from #133624.
Replace Get{Signed,Unsigned} with GetInteger<T> and return std::optional
so you can distinguish between the value not being present and it being
explicitly set to the previous fail_value. All existing uses are
replaced by calling value_or(fail_value).
Continuation of #129818
Return a std::optional<bool> from GetBoolean so you can distinguish
between the value not being present and it being explicitly set to true
or false. All existing uses are replaced by calling
`value_or(fail_value`).
Motivated by #129753