Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 72 additions & 14 deletions media/memory-table.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,44 @@
outline-offset: -1px;
}

.memory-inspector-table tbody .column-address {
position: relative;
}

.memory-inspector-table tbody .address-status {
position: absolute;
left: -1px;
align-items: center;
display: flex;
justify-content: center;
}

.memory-inspector-table tbody .address-status.codicon {
font-size: 12px;
}

.memory-inspector-table tbody .address-status.codicon-debug-breakpoint {
color: var(--vscode-debugIcon-breakpointForeground);
}

.memory-inspector-table tbody .address-status.codicon-debug-stackframe {
color: var(--vscode-debugIcon-breakpointCurrentStackframeForeground);
}

.memory-inspector-table
tbody
.address-status.codicon-debug-breakpoint.codicon-debug-stackframe:after {
content: "\ea71";
position: absolute;
left: 3px;
font-size: 6px;
color: var(--vscode-debugIcon-breakpointForeground);
}

.memory-inspector-table tbody .debug-hit {
outline-color: var(--vscode-debugIcon-breakpointCurrentStackframeForeground);
}

/* == MoreMemorySelect == */

.bytes-select {
Expand Down Expand Up @@ -92,7 +130,7 @@

.memory-inspector-table span.p-column-resizer {
border-right: 2px solid var(--vscode-editor-lineHighlightBorder);
transition: border-right .1s ease-out;
transition: border-right 0.1s ease-out;
}

.memory-inspector-table span.p-column-resizer:hover {
Expand All @@ -113,7 +151,7 @@
/* Basic hover formatting (copied from Monaco hovers) */
.memory-hover {
min-width: fit-content;
max-width: var(--vscode-hover-maxWidth,500px);
max-width: var(--vscode-hover-maxWidth, 500px);
border: 1px solid var(--vscode-editorHoverWidget-border);
border-radius: 3px;

Expand All @@ -129,34 +167,40 @@
border-collapse: collapse;
border-style: hidden;
}

.memory-hover table caption {
padding: 4px;
border-bottom: 1px solid var(--vscode-editorHoverWidget-border);
}

.memory-hover td {
border: 1px solid var(--vscode-editorHoverWidget-border);
padding: 2px 8px;
}

.memory-hover td:first-child {
text-align: right;
}

/* Colors for the hover fields */
.memory-hover .label-value-pair>.label {
color: var(--vscode-debugTokenExpression-string);
white-space: nowrap;
.memory-hover .label-value-pair > .label {
color: var(--vscode-debugTokenExpression-string);
white-space: nowrap;
}
.memory-hover .label-value-pair>.value {

.memory-hover .label-value-pair > .value {
color: var(--vscode-debugTokenExpression-number);
}

/* Colors for specific hover fields */
.memory-hover .address-hover .primary {
background-color: var(--vscode-list-hoverBackground);
}

.memory-hover table caption {
color: var(--vscode-symbolIcon-variableForeground);
}

.memory-hover .address-hover .value.utf8,
.memory-hover .data-hover .value.utf8,
.memory-hover .variable-hover .value.type {
Expand All @@ -171,38 +215,42 @@
}

.p-datatable .p-datatable-tbody > tr > td[data-column="data"][role="cell"],
.p-datatable .p-datatable-tbody > tr > td[data-column="variables"][role="cell"] {
.p-datatable
.p-datatable-tbody
> tr
> td[data-column="variables"][role="cell"] {
padding: 0 12px;
vertical-align: middle;
}

/* Group Styles */

[role='group']:hover {
[role="group"]:hover {
border-bottom: 0px;
outline: 1px solid var(--vscode-list-focusOutline);
}

[role='group'][data-group-selected='true'] {
[role="group"][data-group-selected="true"] {
background: var(--vscode-list-activeSelectionBackground);
color: var(--vscode-list-activeSelectionForeground);
outline: 1px solid var(--vscode-list-activeSelectionBackground);
}

[role='group']:focus-visible,
[role='group']:focus {
[role="group"]:focus-visible,
[role="group"]:focus {
outline: 1px solid var(--vscode-list-focusOutline);
}

[data-column="address"][role="group"],
[data-column="ascii"][role="group"] {
padding: 4px 12px;
display: flex;
align-items: center;
outline-offset: -1px;
}

[data-column="data"][role="group"],
[data-column="variables"][role="group"] {
[data-column="variables"][role="group"] {
padding: 4px 1px;
line-height: 23.5px;
outline-offset: -1px;
Expand Down Expand Up @@ -241,7 +289,17 @@
text-indent: 2px;
}

.p-datatable .p-datatable-tbody > tr > td.p-highlight:has(>.selected) {
.p-datatable .p-datatable-tbody > tr > td.p-highlight:has(> .selected) {
background: transparent;
outline: none;
}
}

/* == Data Breakpoint == */

.memory-inspector-table .data-breakpoint {
outline: 1px solid var(--vscode-debugIcon-breakpointForeground);
}

.memory-inspector-table .data-breakpoint.data-breakpoint-external {
outline-style: dashed;
}
87 changes: 86 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,42 @@
"title": "Go to value in Memory Inspector",
"category": "Memory"
},
{
"command": "memory-inspector.data-breakpoint.set.read",
"title": "Break on Value Read",
"enablement": "memory-inspector.canWrite && memory-inspector.dataBreakpoints",
"category": "Memory"
},
{
"command": "memory-inspector.data-breakpoint.set.readWrite",
"title": "Break on Value Access",
"enablement": "memory-inspector.canWrite && memory-inspector.dataBreakpoints",
"category": "Memory"
},
{
"command": "memory-inspector.data-breakpoint.set.write",
"title": "Break on Value Change",
"enablement": "memory-inspector.canWrite && memory-inspector.dataBreakpoints",
"category": "Memory"
},
{
"command": "memory-inspector.data-breakpoint.remove",
"title": "Remove Breakpoint",
"enablement": "memory-inspector.canWrite && memory-inspector.dataBreakpoints",
"category": "Memory"
},
{
"command": "memory-inspector.data-breakpoint.remove-all",
"title": "Remove All Memory Inspector Breakpoints",
"enablement": "memory-inspector.canWrite && memory-inspector.dataBreakpoints",
"category": "Memory"
},
{
"command": "memory-inspector.data-breakpoint.inspect-breakpoints",
"title": "Inspect Breakpoints",
"enablement": "memory-inspector.canWrite && memory-inspector.dataBreakpoints && (memory-inspector.loggingVerbosity == 'debug' || memory-inspector.loggingVerbosity == 'info')",
"category": "Memory"
},
{
"command": "memory-inspector.toggle-variables-column",
"title": "Toggle Variables Column",
Expand Down Expand Up @@ -156,6 +192,22 @@
},
{
"command": "memory-inspector.apply-file"
},
{
"command": "memory-inspector.data-breakpoint.set.read",
"when": "false"
},
{
"command": "memory-inspector.data-breakpoint.set.readWrite",
"when": "false"
},
{
"command": "memory-inspector.data-breakpoint.set.write",
"when": "false"
},
{
"command": "memory-inspector.data-breakpoint.remove",
"when": "false"
}
],
"debug/variables/context": [
Expand Down Expand Up @@ -237,6 +289,31 @@
"command": "memory-inspector.reset-display-options",
"group": "a_reset@2",
"when": "webviewId === memory-inspector.memory && optionsMenu"
},
{
"command": "memory-inspector.data-breakpoint.set.read",
"group": "breakpoints@1",
"when": "memory-inspector.dataBreakpoints && webviewId === memory-inspector.memory && memory-inspector.breakpoint.isBreakable"
},
{
"command": "memory-inspector.data-breakpoint.set.write",
"group": "breakpoints@2",
"when": "memory-inspector.dataBreakpoints && webviewId === memory-inspector.memory && memory-inspector.breakpoint.isBreakable"
},
{
"command": "memory-inspector.data-breakpoint.set.readWrite",
"group": "breakpoints@3",
"when": "memory-inspector.dataBreakpoints && webviewId === memory-inspector.memory && memory-inspector.breakpoint.isBreakable"
},
{
"command": "memory-inspector.data-breakpoint.remove",
"group": "breakpoints@4",
"when": "memory-inspector.dataBreakpoints && webviewId === memory-inspector.memory && memory-inspector.breakpoint.type === 'internal'"
},
{
"command": "memory-inspector.data-breakpoint.remove-all",
"group": "breakpoints@5",
"when": "memory-inspector.dataBreakpoints && webviewId === memory-inspector.memory && memory-inspector.breakpoint.type === 'internal'"
}
]
},
Expand Down Expand Up @@ -279,6 +356,14 @@
],
"description": "C-based debuggers to activate (requires debug session restart)"
},
"memory-inspector.dataBreakpoints": {
"type": "boolean",
"default:": false,
"description": "Enable data breakpoint support.",
"tags": [
"experimental"
]
},
"memory-inspector.refreshOnStop": {
"type": "string",
"enum": [
Expand Down Expand Up @@ -447,4 +532,4 @@
"workspace",
"ui"
]
}
}
58 changes: 58 additions & 0 deletions src/common/breakpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/********************************************************************************
* Copyright (C) 2024 EclipseSource.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { DebugProtocol } from '@vscode/debugprotocol';
import { DebugRequestTypes } from './debug-requests';

/**
* Temp. workaround till we have a proper API for this within VSCode.
*
* @see {@link https://github.com/microsoft/vscode/pull/226735}
*/
export interface ExperimentalDataBreakpoint {
type: TrackedBreakpointType;
breakpoint: DebugProtocol.DataBreakpoint;
/**
* The respective response for the breakpoint.
*/
response: DebugProtocol.Breakpoint;
}

/**
* Temp. workaround till we have a proper API for this within VSCode.
*
* @see {@link https://github.com/microsoft/vscode/pull/226735}
*/
export interface ExperimentalDataBreakpoints {
/**
* Breakpoints set from external contributors.
*/
external: ExperimentalDataBreakpoint[],
/**
* Breakpoints set from us.
*/
internal: ExperimentalDataBreakpoint[]
}

/**
* Temp. workaround till we have a proper API for this within VSCode.
*/
export type TrackedBreakpointType = 'internal' | 'external';

export type DataBreakpointInfoArguments = DebugRequestTypes['dataBreakpointInfo'][0];
export type DataBreakpointInfoResult = DebugRequestTypes['dataBreakpointInfo'][1];
export type SetDataBreakpointsArguments = DebugRequestTypes['setDataBreakpoints'][0];
export type SetDataBreakpointsResult = DebugRequestTypes['setDataBreakpoints'][1];
24 changes: 19 additions & 5 deletions src/common/debug-requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export interface DebugRequestTypes {
'scopes': [DebugProtocol.ScopesArguments, DebugProtocol.ScopesResponse['body']]
'variables': [DebugProtocol.VariablesArguments, DebugProtocol.VariablesResponse['body']]
'writeMemory': [DebugProtocol.WriteMemoryArguments, DebugProtocol.WriteMemoryResponse['body']]
'dataBreakpointInfo': [DebugProtocol.DataBreakpointInfoArguments, DebugProtocol.DataBreakpointInfoResponse['body']]
'setDataBreakpoints': [DebugProtocol.SetDataBreakpointsArguments, DebugProtocol.SetDataBreakpointsResponse['body']]
}

export interface DebugEvents {
Expand Down Expand Up @@ -59,16 +61,28 @@ export function isDebugEvaluateArguments(args: DebugProtocol.EvaluateArguments |
}

export function isDebugRequest<K extends keyof DebugRequestTypes>(command: K, message: unknown): message is DebugRequest<K, DebugRequestTypes[K][0]> {
const assumed = message ? message as DebugProtocol.Request : undefined;
return !!assumed && assumed.type === 'request' && assumed.command === command;
return isDebugRequestType(message) && message.command === command;
}

export function isDebugResponse<K extends keyof DebugRequestTypes>(command: K, message: unknown): message is DebugResponse<K, DebugRequestTypes[K][1]> {
const assumed = message ? message as DebugProtocol.Response : undefined;
return !!assumed && assumed.type === 'response' && assumed.command === command;
return isDebugResponseType(message) && message.command === command;
}

export function isDebugEvent<K extends keyof DebugEvents>(event: K, message: unknown): message is DebugEvents[K] {
return isDebugEventType(message) && message.event === event;
}

export function isDebugRequestType(message: unknown): message is DebugProtocol.Request {
const assumed = message ? message as DebugProtocol.Request : undefined;
return !!assumed && assumed.type === 'request';
}

export function isDebugResponseType(message: unknown): message is DebugProtocol.Response {
const assumed = message ? message as DebugProtocol.Response : undefined;
return !!assumed && assumed.type === 'response';
}

export function isDebugEventType(message: unknown): message is DebugProtocol.Event {
const assumed = message ? message as DebugProtocol.Event : undefined;
return !!assumed && assumed.type === 'event' && assumed.event === event;
return !!assumed && assumed.type === 'event';
}
Loading