Skip to content

Commit 7070e30

Browse files
Fix CMake debugger Copy Value copying variable name instead of value (#4672)
* Initial plan * Fix CMake debugger copy value bug by removing evaluateName from variables Co-authored-by: hanniavalera <[email protected]> * Update test to follow repo patterns Co-authored-by: hanniavalera <[email protected]> * Fix test imports to match repository patterns Co-authored-by: hanniavalera <[email protected]> * Remove trailing spaces to fix lint errors Co-authored-by: hanniavalera <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: hanniavalera <[email protected]>
1 parent 48b4729 commit 7070e30

3 files changed

Lines changed: 112 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Features:
88
Bug Fixes:
99

1010
- Fix user-level tasks defined in `~/.config/Code/User/tasks.json` causing infinite spinner. [#4659](https://github.com/microsoft/vscode-cmake-tools/pull/4659)
11+
- Fix "Copy Value" in CMake debugger copying variable name instead of value. [#4551](https://github.com/microsoft/vscode-cmake-tools/issues/4551)
1112
- cmakeDriver: Fixes getCompilerVersion by using compilerPath instead of compilerName. [#4647](https://github.com/microsoft/vscode-cmake-tools/pull/4647) [@lygstate](https://github.com/lygstate)
1213

1314
## 1.22

src/debug/cmakeDebugger/debuggerConfigureDriver.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ export class DebugTrackerFactory implements vscode.DebugAdapterTrackerFactory {
4343
if (message.command === "disconnect") {
4444
await onDisconnected();
4545
}
46+
},
47+
onWillReceiveMessage(message: any) {
48+
// Fix for issue #4551: CMake's debugger sets evaluateName to the variable name,
49+
// which causes "Copy Value" to copy the name instead of the value.
50+
// We remove evaluateName from variables so VSCode falls back to copying the value.
51+
if (message.type === 'response' && message.command === 'variables' && message.body?.variables) {
52+
for (const variable of message.body.variables) {
53+
if (variable.evaluateName) {
54+
delete variable.evaluateName;
55+
}
56+
}
57+
}
4658
}
4759
};
4860
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/* eslint-disable no-unused-expressions */
2+
import { expect } from '@test/util';
3+
import * as vscode from 'vscode';
4+
import { DebugTrackerFactory } from '@cmt/debug/cmakeDebugger/debuggerConfigureDriver';
5+
6+
suite('Debug Tracker tests', () => {
7+
test('Variables response: evaluateName is removed from variables', () => {
8+
const factory = new DebugTrackerFactory();
9+
const tracker = factory.createDebugAdapterTracker({} as vscode.DebugSession);
10+
11+
// Create a mock variables response with evaluateName set
12+
const message = {
13+
type: 'response',
14+
command: 'variables',
15+
body: {
16+
variables: [
17+
{
18+
name: 'VAR1',
19+
value: '99999',
20+
evaluateName: 'VAR1'
21+
},
22+
{
23+
name: 'VAR2',
24+
value: 'test',
25+
evaluateName: 'VAR2'
26+
},
27+
{
28+
name: 'VAR3',
29+
value: 'another',
30+
variablesReference: 1
31+
// No evaluateName
32+
}
33+
]
34+
}
35+
};
36+
37+
// Call onWillReceiveMessage if it exists
38+
if (tracker && 'onWillReceiveMessage' in tracker) {
39+
(tracker as any).onWillReceiveMessage(message);
40+
}
41+
42+
// Verify evaluateName was removed from variables that had it
43+
expect(message.body.variables[0]).to.not.have.property('evaluateName');
44+
expect(message.body.variables[1]).to.not.have.property('evaluateName');
45+
// VAR3 should remain unchanged (it never had evaluateName)
46+
expect(message.body.variables[2]).to.not.have.property('evaluateName');
47+
48+
// Other properties should be preserved
49+
expect(message.body.variables[0].name).to.be.eq('VAR1');
50+
expect(message.body.variables[0].value).to.be.eq('99999');
51+
expect(message.body.variables[2].variablesReference).to.be.eq(1);
52+
});
53+
54+
test('Non-variables messages are not modified', () => {
55+
const factory = new DebugTrackerFactory();
56+
const tracker = factory.createDebugAdapterTracker({} as vscode.DebugSession);
57+
58+
const message = {
59+
type: 'response',
60+
command: 'scopes',
61+
body: {
62+
scopes: [
63+
{
64+
name: 'Local',
65+
variablesReference: 1
66+
}
67+
]
68+
}
69+
};
70+
71+
const originalMessage = JSON.stringify(message);
72+
73+
// Call onWillReceiveMessage if it exists
74+
if (tracker && 'onWillReceiveMessage' in tracker) {
75+
(tracker as any).onWillReceiveMessage(message);
76+
}
77+
78+
// Message should remain unchanged
79+
expect(JSON.stringify(message)).to.be.eq(originalMessage);
80+
});
81+
82+
test('Variables response without body is handled gracefully', () => {
83+
const factory = new DebugTrackerFactory();
84+
const tracker = factory.createDebugAdapterTracker({} as vscode.DebugSession);
85+
86+
const message = {
87+
type: 'response',
88+
command: 'variables'
89+
// No body
90+
};
91+
92+
// Should not throw
93+
expect(() => {
94+
if (tracker && 'onWillReceiveMessage' in tracker) {
95+
(tracker as any).onWillReceiveMessage(message);
96+
}
97+
}).to.not.throw();
98+
});
99+
});

0 commit comments

Comments
 (0)