-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integrate Memory Inspector in Theia repository #11394
Integrate Memory Inspector in Theia repository #11394
Conversation
Just out of interest: Did you consider moving this to CDT.cloud instead of the Theia main repo? |
@JonasHelming, I've made this PR for two reasons: I believe that having the code in this repo will make it easier to ensure its compatibility with latest Theia, and I believe that it's advantageous with respect to the features requested in #10841. What would be the benefit of placing it in CDT.cloud? |
ab0ec7f
to
b6db786
Compare
Basically to keep the core Theia project as slim as possible. Most components would benefit from beeing moved to the core project/repo in terms of ensuring compatibility. Are the people maintaining this component the same team that are core Theia developers? Again: I am not opposed to move this to Theia core, I just wanted to raise the question as we had a tendency to try to keep the core repo as small as possible. One example that you could aim at when hosting it at CDT.cloud would be to ensure compatibility for community releases only. |
Thinking about this again: the memory inspector is not necessarily bound to C/C++, correct? This would be an argument in favor to keep it in Theia. |
@JonasHelming, exactly. I've been waiting till I could get it working on at least one non-C(++) debug adapter before trying to move it here, and I was finally able to get it working for Rust. :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a second commit to localize everything I could find, and cleaned up the code slightly.
I still have some comments however.
"@theia/core": "1.27.0", | ||
"@theia/debug": "1.27.0", | ||
"long": "^4.0.0", | ||
"vscode-debugprotocol": "^1.48.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to also update vscode-debugprotocol
in @theia/debug
and @theia/plugin-ext
to follow this version:
theia/packages/debug/package.json
Line 25 in b000f96
"vscode-debugprotocol": "^1.32.0" |
theia/packages/plugin-ext/package.json
Line 45 in b000f96
"vscode-debugprotocol": "^1.32.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because they're both caret versions, we're currently getting a high-enough version (1.51) in our yarn.lock
, but it's probably best to be explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the entries in our various package.json
. They've deprecated this package name, so I've updated that, as well, with the unfortunate consequence that the new package name isn't part of the 3PP baseline, apparently.
packages/memory-inspector/src/browser/memory-inspector-frontend-contribution.ts
Outdated
Show resolved
Hide resolved
render(): React.ReactNode { | ||
return ( | ||
<div className='t-mv-memory-fetch-error'> | ||
Click the | ||
{' '} | ||
<i className='memory-view-icon toolbar' /> | ||
{' '} | ||
icon to add a new memory view or the | ||
{' '} | ||
<i className='register-view-icon toolbar' /> | ||
{' '} | ||
icon to add a register view. | ||
</div> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably clean up this method and localize if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleaned up, but not localized. Not quite sure what to do with the fact that it's broken up by the icons - the pieces in between aren't meaningful enough to pass to an automated translation tool. @msujew, any suggestions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested it yet, but here are my obligatory i18n comments :)
Also please rebase on latest master
to get access to automatic translations for your changes.
packages/memory-inspector/src/browser/diff-widget/memory-diff-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/diff-widget/memory-diff-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/diff-widget/memory-diff-select-widget.tsx
Outdated
Show resolved
Hide resolved
while (currentLevel.parent instanceof DebugVariable) { | ||
currentLevel = currentLevel.parent; | ||
} | ||
return currentLevel.parent instanceof DebugScope && currentLevel.parent['raw'].name === 'Local'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Are Local
or Registers
localized values? I'm feeling queasy about the comparison.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair observation. This class is intended to be tightly coupled to CDT-GDB adapter, and at the moment, it does not localize any of its text, and adapter returns are mapped fairly directly into the display in the Variables widget, so this should work, but it's certainly not as robust as might be ideal. To my knowledge, there aren't hard conventions about the naming of variable scopes - an adapter could return any labels it wants - so I don't see a very good way around this, at the moment. The DAP does specifically mention both that the name of a scope returned by an adapter should be displayed as is, and that that text may be translated (on the adapter's side, presumably).
packages/memory-inspector/src/browser/memory-widget/memory-table-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/register-widget/register-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/register-widget/register-widget-types.ts
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/utils/memory-widget-manager.ts
Outdated
Show resolved
Hide resolved
167ec32
to
d8f1b57
Compare
@colin-grant-work Is this ready for a re-review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @colin-grant-work and everyone, thank you for the great work!
I had a look at this PR for an adopter where we customized the memory view to stick on a particular thread. The design of this component is really thought-out and it was easy to do most of the necessary customizations. Still, I thought I'd share some of my observations with you - mostly about making things a bit easier to override. Please note that my comments are just some minor things that should not prevent this PR from being merged.
async createNewMemoryWidget<T extends MemoryWidget>(kind: 'register' | 'memory' = 'memory'): Promise<T> { | ||
this.widgetDisplayId = this._availableWidgets.size !== 0 ? this.widgetDisplayId + 1 : 1; | ||
const options: MemoryWidgetOptions = { identifier: this.createdWidgetCount += 1, displayId: this.widgetDisplayId }; | ||
const widgetId = kind === 'memory' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand that correctly that the only way to plug in a custom memory or widget view is to re-bind the manager and override this method? At least the README seems to suggest so. If that is true, it would be really create if this mapping from kind to widget id could be in a separate overridable/protected method for easier customization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is reasonable, but doing it right would require a bit of a refactor - I'll leave this one out for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, you can keep the effort as low as possible. I just thought something simple along the lines of:
protected mapKindToWidgetId(kind: 'register' | 'memory' = 'memory') {
return kind === 'memory' ? MemoryWidget.ID : RegisterWidget.ID;
}
So in case you want the editable memory widget you could simply do:
protected override mapKindToWidgetId(kind: 'register' | 'memory' = 'memory') {
return kind === 'memory' ? EditableMemoryWidget.ID : RegisterWidget.ID;
}
But we can also keep it as is for now.
packages/memory-inspector/src/browser/memory-widget/memory-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/memory-widget/memory-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/memory-widget/memory-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/memory-widget/memory-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/editable-widget/memory-editable-table-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/editable-widget/memory-editable-table-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/editable-widget/memory-editable-table-widget.tsx
Outdated
Show resolved
Hide resolved
console.log('Problem writing memory with arguments', edit, '\n', e); | ||
} | ||
} | ||
this.memoryEditsCompleted.resolve(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that when I submit edits there is no update on the view by default. We do resolve the edits which means that the next time the memory is changed it will update accordingly and the pending edits are cleared (handleMemoryChange
). But this requires a specific user action. At the moment, the pending changes just remain in the UI. Should we trigger an explicit update from here or what is the expected flow after the user submits the edits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit tricky because the debug session doesn't emit any events when memory changes - we just get a response. When we implemented this internally, we just had the debug adapter send a StoppedEvent
after successfully updating memory, but that was a bit of a workaround, and I didn't include it when implementing the write memory request upstream in the CDT-GDB adapter. I think your suggestion of triggering a refresh cycle is probably the best way to handle it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've modified the code here so that if a write succeeds we refresh the memory, but we don't clear any pending edits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really, really like this solution! I tested it and it works and looks great! I think it is a great solution to clear the edits one by one if there is no error. Thank you, Colin!
packages/memory-inspector/src/browser/editable-widget/memory-editable-table-widget.tsx
Outdated
Show resolved
Hide resolved
@vince-fugnitto @colin-grant-work: Thanks again for the great work! Is there any chance this PR can make it in the upcoming release? If there is any way I can help out, please let me know. |
@martin-fleck-at, I'll devote some time to this today to address the outstanding comments. |
ae1d582
to
a3785f8
Compare
@vince-fugnitto, @martin-fleck-at, I've addressed most of y'all's comments - since there's some interest in getting this into the release, would you mind taking another look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Colin, I retested our customization with the new commits and everything still works great and I definitely saved a couple of lines of copied code ;-) I really appreciate the time you are taking for this, so thank you very much!
I found a few minors in the new code that again do not a affect the functionality so if you have some time you could fix them but otherwise I'd rather see this change merged than delayed for the next release.
packages/memory-inspector/src/browser/memory-widget/memory-options-widget.tsx
Outdated
Show resolved
Hide resolved
packages/memory-inspector/src/browser/editable-widget/memory-editable-table-widget.tsx
Outdated
Show resolved
Hide resolved
console.log('Problem writing memory with arguments', edit, '\n', e); | ||
} | ||
} | ||
this.memoryEditsCompleted.resolve(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really, really like this solution! I tested it and it works and looks great! I think it is a great solution to clear the edits one by one if there is no error. Thank you, Colin!
async createNewMemoryWidget<T extends MemoryWidget>(kind: 'register' | 'memory' = 'memory'): Promise<T> { | ||
this.widgetDisplayId = this._availableWidgets.size !== 0 ? this.widgetDisplayId + 1 : 1; | ||
const options: MemoryWidgetOptions = { identifier: this.createdWidgetCount += 1, displayId: this.widgetDisplayId }; | ||
const widgetId = kind === 'memory' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, you can keep the effort as low as possible. I just thought something simple along the lines of:
protected mapKindToWidgetId(kind: 'register' | 'memory' = 'memory') {
return kind === 'memory' ? MemoryWidget.ID : RegisterWidget.ID;
}
So in case you want the editable memory widget you could simply do:
protected override mapKindToWidgetId(kind: 'register' | 'memory' = 'memory') {
return kind === 'memory' ? EditableMemoryWidget.ID : RegisterWidget.ID;
}
But we can also keep it as is for now.
packages/memory-inspector/src/browser/editable-widget/memory-editable-table-widget.tsx
Show resolved
Hide resolved
packages/memory-inspector/src/browser/editable-widget/memory-editable-table-widget.tsx
Outdated
Show resolved
Hide resolved
@martin-fleck-at, I've pushed commits that I hope should address your concerns and requests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wow, everything has been done, thank you very much, Colin! I really appreciate it!
I re-tested the latest version with our customizations and everything works and looks great. It is really an awesome feature, thank you to everyone involved.
@vince-fugnitto Do you want to have another look at it or do you think we can merge this? |
b355a0d
to
64c8047
Compare
What it does
This PR transfers the Memory Inspector functionality from the Theia CPP Extensions to the Theia repository. Relative to the current state of that repository, this PR makes some minor changes necessary to operate with [email protected] and transfers some functionality that is not fully determined by the Debug Adapter Protocol into the
MemoryProviderService
, where it can be more easily adjusted for adapters with specific known properties.How to test
lldb.rpcServer
is set tonull
to work around Incorrect conversions fromnull
toundefined
in new RPC #11392Rust Analyzer
andCodeLLDB
main.rs
and put a breakpoint on line 12.Go
. The memory location should load, and it should match the data of the struct whose address you entered.Review checklist
Reminder for reviewers